diff --git a/src/App/Messages/AuthenticationDaemon.purs b/src/App/Messages/AuthenticationDaemon.purs index 6bec26e..3f57755 100644 --- a/src/App/Messages/AuthenticationDaemon.purs +++ b/src/App/Messages/AuthenticationDaemon.purs @@ -31,7 +31,6 @@ import App.IPC as IPC Maybe this could be changed in the future to match the actual possibilities of the API. Possible requests: - - 14 type EditProfile = { token :: String, new_profile :: Hash(String, JSON::Any) } - 15 type EditProfileContent = { token :: Maybe String, shared_key :: Maybe String, user :: Int | String | Nil, new_profile :: Hash(String, JSON::Any) } -- Deletion can be triggered by either an admin or the user. @@ -53,80 +52,133 @@ type PasswordRecovered = { user :: UserPublic.UserPublic } type Contacts = { user :: Int, email :: Maybe Email.Email, phone :: Maybe Phone.Phone } type MatchingUsers = { users :: Array UserPublic.UserPublic } + type Password = String + +{- UserID should be in a separate module with a dedicated codec. -} +type UserID = Int -- UserID is either a login or an uid number + +{- 0 -} type Login = { login :: String, password :: String } -type AddUser = { shared_key :: String, login :: String, password :: String, email :: Maybe Email.Email, phone :: Maybe Phone.Phone } -- profile :: Maybe Hash(String, JSON::Any) -type ValidateUser = { login :: String, activation_key :: String } +codecLogin ∷ CA.JsonCodec Login +codecLogin = CA.object "Login" (CAR.record { login: CA.string, password: CA.string }) + +{- 1 -} +type Register = { login :: String + , password :: Password + , email :: Maybe Email.Email + {-, profile :: Maybe Hash(String, JSON::Any) -} } +codecRegister ∷ CA.JsonCodec Register +codecRegister + = CA.object "Register" (CAR.record + { login: CA.string + , password: CA.string + , email: CAR.optional Email.codec }) + +{- 2 -} +type ValidateUser = { user :: UserID, activation_key :: String } +codecValidateUser ∷ CA.JsonCodec ValidateUser +codecValidateUser + = CA.object "ValidateUser" (CAR.record + { user: CA.int + , activation_key: CA.string }) + +{- NOTE: "user" attribute for both PasswordRecovery and AskPasswordRecovery could be UserID, + but they'll be used as login since the user has to type it. -} +{- 3 -} +type AskPasswordRecovery = { user :: String } +codecAskPasswordRecovery ∷ CA.JsonCodec AskPasswordRecovery +codecAskPasswordRecovery = CA.object "AskPasswordRecovery" (CAR.record { user: CA.string }) + +{- 4 -} +type PasswordRecovery = { user :: String + , password_renew_key :: String + , new_password :: Password } +codecPasswordRecovery ∷ CA.JsonCodec PasswordRecovery +codecPasswordRecovery + = CA.object "PasswordRecovery" (CAR.record + { user: CA.string + , password_renew_key: CA.string + , new_password: CA.string }) + +{- 5 -} -- I'll split a message in two: either get a user by UID or by name. -- TODO: change it for an Either Int String type. type GetUserByUID = { user :: Int } type GetUserByName = { user :: String } -type GetUserByCredentials = { login :: String, password :: String } -type Register = { login :: String, password :: String, email :: Maybe Email.Email, phone :: Maybe Phone.Phone } -- profile :: Maybe Hash(String, JSON::Any) -type UpdatePassword = { login :: String, old_password :: String, new_password :: String } -type ListUsers = { token :: Maybe String, key :: Maybe String } -type CheckPermission = { shared_key :: Maybe String, token :: Maybe String, user :: String, service :: String, resource :: String } -type SetPermission = { shared_key :: String, user :: String, service :: String, resource :: String, permission :: PermissionLevel.PermissionLevel } -type PasswordRecovery = { user :: String, password_renew_key :: String, new_password :: String } -type AskPasswordRecovery = { user :: String, email :: Email.Email } -type SearchUser = { user :: String } -type EditContacts = { token :: String, email :: Maybe Email.Email, phone :: Maybe Phone.Phone } -type Delete = { shared_key :: Maybe String, login :: Maybe String, password :: Maybe String, user :: String } -type GetContacts = { token :: String } - --- Related JSON codecs. -codecLogin ∷ CA.JsonCodec Login -codecLogin = CA.object "Login" (CAR.record { login: CA.string, password: CA.string }) -codecAddUser ∷ CA.JsonCodec AddUser -codecAddUser = CA.object "AddUser" (CAR.record { shared_key: CA.string - , login: CA.string - , password: CA.string - , email: CAR.optional Email.codec - , phone: CAR.optional Phone.codec }) -codecValidateUser ∷ CA.JsonCodec ValidateUser -codecValidateUser = CA.object "ValidateUser" (CAR.record { login: CA.string, activation_key: CA.string }) codecGetUserByUID ∷ CA.JsonCodec GetUserByUID codecGetUserByUID = CA.object "GetUserByUID" (CAR.record { user: CA.int }) codecGetUserByName ∷ CA.JsonCodec GetUserByName codecGetUserByName = CA.object "GetUserByName" (CAR.record { user: CA.string }) -codecGetUserByCredentials ∷ CA.JsonCodec GetUserByCredentials -codecGetUserByCredentials = CA.object "GetUserByCredentials" (CAR.record { login: CA.string, password: CA.string }) -codecRegister ∷ CA.JsonCodec Register -codecRegister = CA.object "Register" (CAR.record { login: CA.string - , password: CA.string - , email: CAR.optional Email.codec - , phone: CAR.optional Phone.codec }) -codecUpdatePassword ∷ CA.JsonCodec UpdatePassword -codecUpdatePassword = CA.object "UpdatePassword" (CAR.record { login: CA.string - , old_password: CA.string - , new_password: CA.string }) -codecListUsers ∷ CA.JsonCodec ListUsers -codecListUsers = CA.object "ListUsers" (CAR.record { token: CAR.optional CA.string, key: CAR.optional CA.string }) -codecCheckPermission ∷ CA.JsonCodec CheckPermission -codecCheckPermission = CA.object "CheckPermission" (CAR.record { shared_key: CAR.optional CA.string - , token: CAR.optional CA.string - , user: CA.string - , service: CA.string - , resource: CA.string }) -codecSetPermission ∷ CA.JsonCodec SetPermission -codecSetPermission = CA.object "SetPermission" (CAR.record { shared_key: CA.string - , user: CA.string - , service: CA.string - , resource: CA.string - , permission: PermissionLevel.codec }) -codecPasswordRecovery ∷ CA.JsonCodec PasswordRecovery -codecPasswordRecovery = CA.object "PasswordRecovery" (CAR.record { user: CA.string, password_renew_key: CA.string, new_password: CA.string }) -codecAskPasswordRecovery ∷ CA.JsonCodec AskPasswordRecovery -codecAskPasswordRecovery = CA.object "AskPasswordRecovery" (CAR.record { user: CA.string, email: Email.codec }) -codecSearchUser ∷ CA.JsonCodec SearchUser -codecSearchUser = CA.object "SearchUser" (CAR.record { user: CA.string }) -codecEditContacts ∷ CA.JsonCodec EditContacts -codecEditContacts = CA.object "EditContacts" (CAR.record { token: CA.string, email: CAR.optional Email.codec, phone: CAR.optional Phone.codec }) -codecDelete ∷ CA.JsonCodec Delete -codecDelete = CA.object "Delete" (CAR.record { shared_key: CAR.optional CA.string, login: CAR.optional CA.string, password: CAR.optional CA.string, user: CA.string }) -codecGetContacts ∷ CA.JsonCodec GetContacts -codecGetContacts = CA.object "GetContacts" (CAR.record { token: CA.string }) +{- 6 -} +type ModUser = { user :: Maybe UserID + , admin :: Maybe Boolean + , password :: Maybe Password + , email :: Maybe Email.Email } +codecModUser ∷ CA.JsonCodec ModUser +codecModUser + = CA.object "ModUser" (CAR.record + { user: CAR.optional CA.int + , admin: CAR.optional CA.boolean + , password: CAR.optional CA.string + , email: CAR.optional Email.codec }) + +{- 7 -} +{- type EditProfileEntries = { user :: Maybe UserID + , new_profile_entries :: Hash(String, JSON::Any) } -} + +{- 8 -} +type DeleteUser = { user :: Maybe UserID } +codecDeleteUser ∷ CA.JsonCodec DeleteUser +codecDeleteUser = CA.object "DeleteUser" (CAR.record { user: CAR.optional CA.int }) + +{- 9 -} +type AddUser = { login :: String + , password :: Password + , admin :: Boolean + , email :: Maybe Email.Email + {-, profile :: Maybe Hash(String, JSON::Any) -} } +codecAddUser ∷ CA.JsonCodec AddUser +codecAddUser + = CA.object "AddUser" (CAR.record + { login: CA.string + , password: CA.string + , admin: CA.boolean + , email: CAR.optional Email.codec + {-, profile :: Maybe Hash(String, JSON::Any) -} }) + +{- 10 -} +type CheckPermission = { user :: UserID, service :: String, resource :: String } +codecCheckPermission ∷ CA.JsonCodec CheckPermission +codecCheckPermission + = CA.object "CheckPermission" (CAR.record + { user: CA.int + , service: CA.string + , resource: CA.string }) + +{- 11 -} +type SetPermission = { user :: UserID + , service :: String + , resource :: String + , permission :: PermissionLevel.PermissionLevel } +codecSetPermission ∷ CA.JsonCodec SetPermission +codecSetPermission + = CA.object "SetPermission" (CAR.record + { user: CA.int + , service: CA.string + , resource: CA.string + , permission: PermissionLevel.codec }) + +{- 12 -} +type SearchUser = { regex :: Maybe String, offset :: Maybe Int } +codecSearchUser ∷ CA.JsonCodec SearchUser +codecSearchUser + = CA.object "SearchUser" (CAR.record + { regex: CAR.optional CA.string + , offset: CAR.optional CA.int }) + +-- Related JSON codecs. codecGotError ∷ CA.JsonCodec Error codecGotError = CA.object "Error" (CAR.record { reason: CAR.optional CA.string }) codecGotToken ∷ CA.JsonCodec Token @@ -165,24 +217,19 @@ codecGotMatchingUsers = CA.object "MatchingUsers" (CAR.record { users: CA.array -- All possible requests. data RequestMessage = MkLogin Login -- 0 - | MkAddUser AddUser -- 1 + | MkRegister Register -- 1 | MkValidateUser ValidateUser -- 2 - | MkGetUserByUID GetUserByUID -- 3 - | MkGetUserByName GetUserByName -- 3 (bis) - | MkGetUserByCredentials GetUserByCredentials -- 4 - | MkRegister Register -- 6 - | MkUpdatePassword UpdatePassword -- 7 - | MkListUsers ListUsers -- 8 - | MkCheckPermission CheckPermission -- 9 - | MkSetPermission SetPermission -- 10 - | MkPasswordRecovery PasswordRecovery -- 11 - | MkAskPasswordRecovery AskPasswordRecovery -- 12 - | MkSearchUser SearchUser -- 13 - --| MkEditProfile EditProfile -- 14 - --| MkEditProfileContent EditProfileContent -- 15 - | MkEditContacts EditContacts -- 16 - | MkDelete Delete -- 17 - | MkGetContacts GetContacts -- 18 + | MkAskPasswordRecovery AskPasswordRecovery -- 3 + | MkPasswordRecovery PasswordRecovery -- 4 + | MkGetUserByUID GetUserByUID -- 5 + | MkGetUserByName GetUserByName -- 5 (bis) + | MkModUser ModUser -- 6 + --| MkEditProfileContent EditProfileContent -- 7 + | MkDeleteUser DeleteUser -- 8 + | MkAddUser AddUser -- 9 + | MkCheckPermission CheckPermission -- 10 + | MkSetPermission SetPermission -- 11 + | MkSearchUser SearchUser -- 12 -- All possible answers from the authentication daemon (authd). data AnswerMessage @@ -203,26 +250,21 @@ data AnswerMessage encode ∷ RequestMessage -> Tuple UInt String encode m = case m of (MkLogin request) -> get_tuple 0 codecLogin request - (MkAddUser request) -> get_tuple 1 codecAddUser request + (MkRegister request) -> get_tuple 1 codecRegister request (MkValidateUser request) -> get_tuple 2 codecValidateUser request + (MkAskPasswordRecovery request) -> get_tuple 3 codecAskPasswordRecovery request + (MkPasswordRecovery request) -> get_tuple 4 codecPasswordRecovery request -- Both messages are actually a single message type, so they have the same number. -- TODO: change the message codec for an Either Int String. - (MkGetUserByUID request) -> get_tuple 3 codecGetUserByUID request - (MkGetUserByName request) -> get_tuple 3 codecGetUserByName request - (MkGetUserByCredentials request) -> get_tuple 4 codecGetUserByCredentials request - (MkRegister request) -> get_tuple 6 codecRegister request - (MkUpdatePassword request) -> get_tuple 7 codecUpdatePassword request - (MkListUsers request) -> get_tuple 8 codecListUsers request - (MkCheckPermission request) -> get_tuple 9 codecCheckPermission request - (MkSetPermission request) -> get_tuple 10 codecSetPermission request - (MkPasswordRecovery request) -> get_tuple 11 codecPasswordRecovery request - (MkAskPasswordRecovery request) -> get_tuple 12 codecAskPasswordRecovery request - (MkSearchUser request) -> get_tuple 13 codecSearchUser request - -- 14 MkEditProfile - -- 15 MkEditProfileContent - (MkEditContacts request) -> get_tuple 16 codecEditContacts request - (MkDelete request) -> get_tuple 17 codecDelete request - (MkGetContacts request) -> get_tuple 18 codecGetContacts request + (MkGetUserByUID request) -> get_tuple 5 codecGetUserByUID request + (MkGetUserByName request) -> get_tuple 5 codecGetUserByName request + (MkModUser request) -> get_tuple 6 codecModUser request + -- 7 MkEditProfileContent + (MkDeleteUser request) -> get_tuple 8 codecDeleteUser request + (MkAddUser request) -> get_tuple 9 codecAddUser request + (MkCheckPermission request) -> get_tuple 10 codecCheckPermission request + (MkSetPermission request) -> get_tuple 11 codecSetPermission request + (MkSearchUser request) -> get_tuple 12 codecSearchUser request where get_tuple :: forall a. Int -> CA.JsonCodec a -> a -> Tuple UInt String get_tuple num codec request = Tuple (fromInt num) (J.stringify $ CA.encode codec request) @@ -262,7 +304,6 @@ parseDecodeJSON codec str = do json <- JSONParser.jsonParser str lmap CA.printJsonDecodeError (CA.decode codec json) - serialize :: RequestMessage -> Effect ArrayBuffer serialize request = case (encode request) of