thentos-core-0.0.1.1: The swiss army knife of privacy-preserving identity management

Safe HaskellNone
LanguageHaskell2010

Thentos.Transaction

Contents

Synopsis

user

lookupAnyUser :: UserId -> ThentosQuery e (UserId, User)

Lookup any user (whether confirmed or not) by their ID.

lookupAnyUserByEmail :: UserEmail -> ThentosQuery e (UserId, User)

Lookup any user (whether confirmed or not) by their email address.

addUserPrim :: Maybe UserId -> User -> Bool -> ThentosQuery e UserId

Actually add a new user. The user may already have an ID, otherwise the DB will automatically create one (auto-increment). NOTE that mixing calls with Just an ID with those without is a very bad idea and will quickly lead to errors!

addUser :: (Show e, Typeable e) => User -> ThentosQuery e UserId

Add a new user and return the new user's UserId. Ensures that user name and email address are unique.

addUnconfirmedUser :: (Show e, Typeable e) => ConfirmationToken -> User -> ThentosQuery e UserId

Add a new unconfirmed user (i.e. one whose email address we haven't confirmed yet). Ensures that user name and email address are unique.

addPasswordResetToken :: UserEmail -> PasswordResetToken -> ThentosQuery e User

Add a password reset token. Return the user whose password this token can change.

resetPassword :: Timeout -> PasswordResetToken -> HashedSecret UserPass -> ThentosQuery e ()

Change a password with a given password reset token and remove the token. Throw an error if the token does not exist or has expired.

confirmUserEmailChange :: Timeout -> ConfirmationToken -> ThentosQuery e ()

Change email with a given token and remove the token. Throw an error if the token does not exist or has expired.

changePassword :: UserId -> HashedSecret UserPass -> ThentosQuery e ()

Change password. Should only be called once the old password has been verified.

deleteUser :: UserId -> ThentosQuery e ()

Delete user with given UserId. Throw an error if user does not exist.

service

deleteService :: ServiceId -> ThentosQuery e ()

Delete service with given ServiceId. Throw an error if service does not exist.

personas, contexts, and groups

addPersona :: PersonaName -> UserId -> Maybe Uri -> ThentosQuery e Persona

Add a new persona to the DB. A persona has a unique name and a user to which it belongs. The PersonaId is assigned by the DB. May throw NoSuchUser or PersonaNameAlreadyExists.

deletePersona :: PersonaId -> ThentosQuery e ()

Delete a persona. Throw NoSuchPersona if the persona does not exist in the DB.

addContext :: ServiceId -> ContextName -> ContextDescription -> Maybe ProxyUri -> ThentosQuery e Context

Add a new context. The first argument identifies the service to which the context belongs. May throw NoSuchService or ContextNameAlreadyExists.

deleteContext :: ServiceId -> ContextName -> ThentosQuery e ()

Delete a context. Throw an error if the context does not exist in the DB.

addPersonaToGroup :: PersonaId -> Group -> ThentosQuery e ()

Add a persona to a group. If the persona is already a member of the group, do nothing.

removePersonaFromGroup :: PersonaId -> Group -> ThentosQuery e ()

Remove a persona from a group. If the persona is not a member of the group, do nothing.

addGroupToGroup :: Group -> Group -> ThentosQuery e ()

Add a group (subgroup) to another group (supergroup) so that all members of subgroup will also be considered members of supergroup. If subgroup is already a direct member of supergroup, do nothing. Throws GroupMembershipLoop if adding the relation would cause a loop.

removeGroupFromGroup :: Group -> Group -> ThentosQuery e ()

Remove a group (subgroup) from another group (supergroup). If subgroup is not a direct member of supergroup, do nothing.

personaGroups :: PersonaId -> ThentosQuery e [Group]

List all groups a persona belongs to, directly or indirectly. If p is a member of g1, g1 is a member of g2, and g2 is a member of g3, [g1, g2, g3] will be returned.

thentos and service session

lookupThentosSession :: ThentosSessionToken -> ThentosQuery e (ThentosSessionToken, ThentosSession)

Lookup session. If session does not exist or has expired, throw an error. If it does exist, bump the expiry time and return session with bumped expiry time.

startThentosSession :: ThentosSessionToken -> Agent -> Timeout -> ThentosQuery e ()

Start a new thentos session. Start time is set to now, end time is calculated based on the specified Timeout. If the agent is a user, this new session is added to their existing sessions. Only confirmed users are allowed to log in; a NoSuchUser error is thrown otherwise. FIXME not implemented: If the agent is a service with an existing session, its session is replaced.

endThentosSession :: ThentosSessionToken -> ThentosQuery e ()

End thentos session and all associated service sessions. If thentos session does not exist or has expired, remove it just the same.

Always call this transaction if you want to clean up a session (e.g., from a garbage collection transaction). This way in the future, you can replace this transaction easily by one that does not actually destroy the session, but move it to an archive.

serviceNamesFromThentosSession :: ThentosSessionToken -> ThentosQuery e [ServiceName]

Get the names of all services that a given thentos session is signed into

lookupServiceSession :: ServiceSessionToken -> ThentosQuery e (ServiceSessionToken, ServiceSession)

Like lookupThentosSession, but for ServiceSession. Bump both service and associated thentos session. If the service session is still active, but the associated thentos session has expired, update service sessions expiry time to now and throw NoSuchThentosSession.

startServiceSession :: ThentosSessionToken -> ServiceSessionToken -> ServiceId -> Timeout -> ThentosQuery e ()

Like startThentosSession for service sessions. Bump associated thentos session. Throw an error if thentos session lookup fails. If a service session already exists for the given ServiceId, return its token.

endServiceSession :: ServiceSessionToken -> ThentosQuery e ()

Like endThentosSession for service sessions (see there). If thentos session or service session do not exist or have expired, remove the service session just the same, but never thentos session.

agents and roles

assignRole :: Agent -> Role -> ThentosQuery e ()

Add a new role to the roles defined for an Agent. If Role is already assigned to Agent, do nothing.

unassignRole :: Agent -> Role -> ThentosQuery e ()

Remove a Role from the roles defined for an Agent. If Role is not assigned to Agent, do nothing.

agentRoles :: Agent -> ThentosQuery e [Role]

All Roles of an Agent. If Agent does not exist or has no roles, return an empty list.

Sybil attack prevention

storeCaptcha :: CaptchaId -> ST -> ThentosQuery e ()

Store the solution to a captcha in the DB. May throw CaptchaIdAlreadyExists.

solveCaptcha :: CaptchaId -> ST -> ThentosQuery e Bool

Submit a solution to a captcha, returning whether or not the solution is correct. Calling this action deletes the referenced captcha from the DB, so every captcha must be solved (or not) at first attempt. Throws NoSuchCaptchaId if the given CaptchaId doesn't exist in the DB (either because it never did or because it was deleted due to garbage collection or a prior call to this action).

garbage collection

garbageCollectThentosSessions :: ThentosQuery e ()

Go through "thentos_sessions" table and find all expired sessions.

garbageCollectUnconfirmedUsers :: Timeout -> ThentosQuery e ()

Remove all expired unconfirmed users from db.

garbageCollectPasswordResetTokens :: Timeout -> ThentosQuery e ()

Remove all expired password reset requests from db.

garbageCollectEmailChangeTokens :: Timeout -> ThentosQuery e ()

Remove all expired email change requests from db.

garbageCollectCaptchas :: Timeout -> ThentosQuery e ()

Remove all expired captchas from db.

helpers

impossible :: String -> a

Throw an error from a situation which (we believe) will never arise.

makeAgent :: Maybe UserId -> Maybe ServiceId -> Agent

Given either a UserId or a ServiceId, return an Agent. Throws an error if not exactly one of the arguments is Just (totality enforced by constraint on `services.owner_{user,service}`). Useful for getting an Agent from the database.