{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
module UserManagement.Statements
( getAllUsers
, getUserByEmail
, getUserByID
, putUser
, deleteUser
, getUserID
, getLoginRequirements
, checkGroupMembership
, getUserRoleInGroup
, getAllUserRoles
, updateUserName
, updateUserEmail
, updateUserPWHash
, addGroup
, getGroupInfo
, getAllGroupsOverview
, deleteGroup
, updateGroupName
, updateGroupDescription
, addRole
, updateUserRoleInGroup
, removeUserFromGroup
, getMembersOfGroup
, addSuperadmin
, removeSuperadmin
, checkSuperadmin
, checkGroupPermission
, checkGroupNameExistence
, getExternalPermission
, getDocumentGroupID
, getAllExternalUsersOfDocument
, addExternalPermission
, updateExternalPermission
, deleteExternalPermission
, createPasswordResetToken
, getPasswordResetToken
, markPasswordResetTokenUsed
, cleanupExpiredTokens
)
where
import Data.Bifunctor (Bifunctor (second))
import Data.Maybe (listToMaybe)
import Data.Profunctor (lmap, rmap)
import Data.Text
import Data.Time (UTCTime)
import Data.Tuple.Curry (uncurryN)
import Data.UUID (UUID)
import Data.Vector
import qualified Docs.Document as Document
import GHC.Int
import Hasql.Statement
import Hasql.TH
import qualified UserManagement.DocumentPermission as Permission
import qualified UserManagement.Group as Group
import qualified UserManagement.User as User
import Prelude hiding (id)
getUserID :: Statement Text User.UserID
getUserID :: Statement Text UUID
getUserID =
[singletonStatement|
select
id :: uuid
from
users
where
email = $1 :: text
|]
getLoginRequirements :: Statement Text (Maybe (User.UserID, Text))
getLoginRequirements :: Statement Text (Maybe (UUID, Text))
getLoginRequirements =
(Vector (UUID, Text) -> Maybe (UUID, Text))
-> Statement Text (Vector (UUID, Text))
-> Statement Text (Maybe (UUID, Text))
forall b c a. (b -> c) -> Statement a b -> Statement a c
forall (p :: * -> * -> *) b c a.
Profunctor p =>
(b -> c) -> p a b -> p a c
rmap
([(UUID, Text)] -> Maybe (UUID, Text)
forall a. [a] -> Maybe a
listToMaybe ([(UUID, Text)] -> Maybe (UUID, Text))
-> (Vector (UUID, Text) -> [(UUID, Text)])
-> Vector (UUID, Text)
-> Maybe (UUID, Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector (UUID, Text) -> [(UUID, Text)]
forall a. Vector a -> [a]
toList)
[vectorStatement|
select
id :: uuid, pwhash :: text
from
users
where
email = $1 :: text
|]
getUserByEmail :: Statement Text (Maybe User.User)
getUserByEmail :: Statement Text (Maybe User)
getUserByEmail =
(Maybe (UUID, Text, Text) -> Maybe User)
-> Statement Text (Maybe (UUID, Text, Text))
-> Statement Text (Maybe User)
forall b c a. (b -> c) -> Statement a b -> Statement a c
forall (p :: * -> * -> *) b c a.
Profunctor p =>
(b -> c) -> p a b -> p a c
rmap
(((UUID, Text, Text) -> User)
-> Maybe (UUID, Text, Text) -> Maybe User
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((UUID -> Text -> Text -> User) -> (UUID, Text, Text) -> User
forall a b. Curry a b => b -> a
uncurryN UUID -> Text -> Text -> User
User.User))
[maybeStatement|
select id :: uuid, name :: text, email :: text
from users
where email = $1 :: text
|]
getUserByID :: Statement User.UserID (Maybe User.User)
getUserByID :: Statement UUID (Maybe User)
getUserByID =
(Maybe (UUID, Text, Text) -> Maybe User)
-> Statement UUID (Maybe (UUID, Text, Text))
-> Statement UUID (Maybe User)
forall b c a. (b -> c) -> Statement a b -> Statement a c
forall (p :: * -> * -> *) b c a.
Profunctor p =>
(b -> c) -> p a b -> p a c
rmap
(((UUID, Text, Text) -> User)
-> Maybe (UUID, Text, Text) -> Maybe User
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((UUID -> Text -> Text -> User) -> (UUID, Text, Text) -> User
forall a b. Curry a b => b -> a
uncurryN UUID -> Text -> Text -> User
User.User))
[maybeStatement|
select id :: uuid, name :: text, email :: text
from users
where id = $1 :: uuid
|]
checkGroupMembership :: Statement (User.UserID, Group.GroupID) Bool
checkGroupMembership :: Statement (UUID, GroupID) Bool
checkGroupMembership =
[singletonStatement|
select exists (
select 1
from roles
where user_id = $1 :: uuid and group_id = $2 :: int8
) :: bool
|]
getUserRoleInGroup :: Statement (User.UserID, Group.GroupID) (Maybe Text)
getUserRoleInGroup :: Statement (UUID, GroupID) (Maybe Text)
getUserRoleInGroup =
(Vector Text -> Maybe Text)
-> Statement (UUID, GroupID) (Vector Text)
-> Statement (UUID, GroupID) (Maybe Text)
forall b c a. (b -> c) -> Statement a b -> Statement a c
forall (p :: * -> * -> *) b c a.
Profunctor p =>
(b -> c) -> p a b -> p a c
rmap
([Text] -> Maybe Text
forall a. [a] -> Maybe a
listToMaybe ([Text] -> Maybe Text)
-> (Vector Text -> [Text]) -> Vector Text -> Maybe Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector Text -> [Text]
forall a. Vector a -> [a]
toList)
[vectorStatement|
select
r.role :: text
from users u
join roles r on u.id = r.user_id
join groups g on g.id = r.group_id
where u.id = $1 :: uuid and g.id = $2 :: int8
|]
getAllUsers :: Statement () [User.User]
getAllUsers :: Statement () [User]
getAllUsers =
((UUID, Text, Text) -> User) -> [(UUID, Text, Text)] -> [User]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(UUID
id, Text
name, Text
email) -> UUID -> Text -> Text -> User
User.User (UUID
id :: User.UserID) Text
name Text
email)
([(UUID, Text, Text)] -> [User])
-> Statement () [(UUID, Text, Text)] -> Statement () [User]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Vector (UUID, Text, Text) -> [(UUID, Text, Text)])
-> Statement () (Vector (UUID, Text, Text))
-> Statement () [(UUID, Text, Text)]
forall b c a. (b -> c) -> Statement a b -> Statement a c
forall (p :: * -> * -> *) b c a.
Profunctor p =>
(b -> c) -> p a b -> p a c
rmap
Vector (UUID, Text, Text) -> [(UUID, Text, Text)]
forall a. Vector a -> [a]
toList
[vectorStatement|
select id :: uuid, name :: text, email :: text
from users
|]
getAllUserRoles :: Statement User.UserID [(Group.GroupID, Text, Text)]
getAllUserRoles :: Statement UUID [(GroupID, Text, Text)]
getAllUserRoles =
(Vector (GroupID, Text, Text) -> [(GroupID, Text, Text)])
-> Statement UUID (Vector (GroupID, Text, Text))
-> Statement UUID [(GroupID, Text, Text)]
forall b c a. (b -> c) -> Statement a b -> Statement a c
forall (p :: * -> * -> *) b c a.
Profunctor p =>
(b -> c) -> p a b -> p a c
rmap
Vector (GroupID, Text, Text) -> [(GroupID, Text, Text)]
forall a. Vector a -> [a]
toList
[vectorStatement|
select g.id :: int8, g.name :: text, r.role :: text
from users u
join roles r on u.id = r.user_id
join groups g on g.id = r.group_id
where u.id = $1 :: uuid
|]
putUser :: Statement User.UserCreate User.UserID
putUser :: Statement UserCreate UUID
putUser =
(UserCreate -> (Text, Text, Text))
-> Statement (Text, Text, Text) UUID -> Statement UserCreate UUID
forall a b c. (a -> b) -> Statement b c -> Statement a c
forall (p :: * -> * -> *) a b c.
Profunctor p =>
(a -> b) -> p b c -> p a c
lmap
(\(User.UserCreate Text
name Text
email Text
pwhash) -> (Text
name, Text
email, Text
pwhash))
[singletonStatement|
insert into users (name, email, pwhash)
values ($1 :: text, $2 :: text, $3 :: text)
returning id :: uuid
|]
deleteUser :: Statement User.UserID ()
deleteUser :: Statement UUID ()
deleteUser =
[resultlessStatement|
delete from users where id = $1 :: uuid
|]
updateUserName :: Statement (Text, User.UserID) ()
updateUserName :: Statement (Text, UUID) ()
updateUserName =
[resultlessStatement|
update users
set name = $1 :: text
where id = $2 :: uuid
|]
updateUserEmail :: Statement (Text, User.UserID) ()
updateUserEmail :: Statement (Text, UUID) ()
updateUserEmail =
[resultlessStatement|
update users
set email = $1 :: text
where id = $2 :: uuid
|]
updateUserPWHash :: Statement (Text, User.UserID) ()
updateUserPWHash :: Statement (Text, UUID) ()
updateUserPWHash =
[resultlessStatement|
update users
set pwhash = $1 :: text
where id = $2 :: uuid
|]
addGroup :: Statement (Text, Maybe Text) Group.GroupID
addGroup :: Statement (Text, Maybe Text) GroupID
addGroup =
[singletonStatement|
insert into groups (name, description)
values ($1 :: text, $2 :: text?)
returning id :: int8
|]
getGroupInfo :: Statement Group.GroupID (Text, Maybe Text)
getGroupInfo :: Statement GroupID (Text, Maybe Text)
getGroupInfo =
[singletonStatement|
select name :: text, description :: text?
from groups
where id = $1 :: int8
|]
getAllGroupsOverview :: Statement () [Group.GroupOverview]
getAllGroupsOverview :: Statement () [GroupOverview]
getAllGroupsOverview =
((GroupID, Text, Maybe Text) -> GroupOverview)
-> [(GroupID, Text, Maybe Text)] -> [GroupOverview]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap
( \(GroupID
id, Text
name, Maybe Text
mDescription) -> GroupID -> Text -> Maybe Text -> GroupOverview
Group.GroupOverview (GroupID
id :: Group.GroupID) Text
name Maybe Text
mDescription
)
([(GroupID, Text, Maybe Text)] -> [GroupOverview])
-> Statement () [(GroupID, Text, Maybe Text)]
-> Statement () [GroupOverview]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Vector (GroupID, Text, Maybe Text)
-> [(GroupID, Text, Maybe Text)])
-> Statement () (Vector (GroupID, Text, Maybe Text))
-> Statement () [(GroupID, Text, Maybe Text)]
forall b c a. (b -> c) -> Statement a b -> Statement a c
forall (p :: * -> * -> *) b c a.
Profunctor p =>
(b -> c) -> p a b -> p a c
rmap
Vector (GroupID, Text, Maybe Text) -> [(GroupID, Text, Maybe Text)]
forall a. Vector a -> [a]
toList
[vectorStatement|
select id :: int8, name :: text, description :: text?
from groups
|]
deleteGroup :: Statement Group.GroupID ()
deleteGroup :: Statement GroupID ()
deleteGroup =
[resultlessStatement|
delete from groups
where id = $1 :: int8
|]
updateGroupName :: Statement (Text, Group.GroupID) ()
updateGroupName :: Statement (Text, GroupID) ()
updateGroupName =
[resultlessStatement|
update groups
set name = $1 :: text
where id = $2 :: int8
|]
updateGroupDescription :: Statement (Maybe Text, Group.GroupID) ()
updateGroupDescription :: Statement (Maybe Text, GroupID) ()
updateGroupDescription =
[resultlessStatement|
update groups
set description = $1 :: text?
where id = $2 :: int8
|]
addRole :: Statement (User.UserID, Group.GroupID, Text) ()
addRole :: Statement (UUID, GroupID, Text) ()
addRole =
[resultlessStatement|
insert into roles (user_id, group_id, role)
values ($1 :: uuid, $2 :: int8, $3 :: text :: role)
|]
updateUserRoleInGroup :: Statement (User.UserID, Group.GroupID, Text) ()
updateUserRoleInGroup :: Statement (UUID, GroupID, Text) ()
updateUserRoleInGroup =
[resultlessStatement|
update roles
set role = $3 :: text :: role
where user_id = $1 :: uuid and group_id = $2 :: int8
|]
removeUserFromGroup :: Statement (User.UserID, Group.GroupID) ()
removeUserFromGroup :: Statement (UUID, GroupID) ()
removeUserFromGroup =
[resultlessStatement|
delete from roles
where user_id = $1 :: uuid and group_id = $2 :: int8
|]
getMembersOfGroup :: Statement Int64 [User.UserInfo]
getMembersOfGroup :: Statement GroupID [UserInfo]
getMembersOfGroup =
(Vector (UUID, Text, Text, Text) -> [UserInfo])
-> Statement GroupID (Vector (UUID, Text, Text, Text))
-> Statement GroupID [UserInfo]
forall b c a. (b -> c) -> Statement a b -> Statement a c
forall (p :: * -> * -> *) b c a.
Profunctor p =>
(b -> c) -> p a b -> p a c
rmap
( ((UUID, Text, Text, Text) -> UserInfo)
-> [(UUID, Text, Text, Text)] -> [UserInfo]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap
( \(UUID
id, Text
name, Text
email, Text
role) ->
UUID -> Text -> Text -> Role -> UserInfo
User.UserInfo UUID
id Text
name Text
email (String -> Role
forall a. Read a => String -> a
read (String -> Role) -> String -> Role
forall a b. (a -> b) -> a -> b
$ Text -> String
unpack Text
role)
)
([(UUID, Text, Text, Text)] -> [UserInfo])
-> (Vector (UUID, Text, Text, Text) -> [(UUID, Text, Text, Text)])
-> Vector (UUID, Text, Text, Text)
-> [UserInfo]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector (UUID, Text, Text, Text) -> [(UUID, Text, Text, Text)]
forall a. Vector a -> [a]
toList
)
[vectorStatement|
select u.id :: uuid, u.name :: text, u.email :: text, r.role :: text
from users u
join roles r on u.id = r.user_id
join groups g on g.id = r.group_id
where g.id = $1 :: int8
|]
addSuperadmin :: Statement User.UserID ()
addSuperadmin :: Statement UUID ()
addSuperadmin =
[resultlessStatement|
insert into superadmins (user_id)
values ($1 :: uuid)
|]
removeSuperadmin :: Statement User.UserID ()
removeSuperadmin :: Statement UUID ()
removeSuperadmin =
[resultlessStatement|
delete from superadmins
where user_id = $1 :: uuid
|]
checkSuperadmin :: Statement User.UserID Bool
checkSuperadmin :: Statement UUID Bool
checkSuperadmin =
[singletonStatement|
select exists (
select 1
from superadmins
where user_id = $1 :: uuid
) :: bool
|]
checkGroupPermission :: Statement (User.UserID, Document.DocumentID) Bool
checkGroupPermission :: Statement (UUID, DocumentID) Bool
checkGroupPermission =
((UUID, DocumentID) -> (UUID, GroupID))
-> Statement (UUID, GroupID) Bool
-> Statement (UUID, DocumentID) Bool
forall a b c. (a -> b) -> Statement b c -> Statement a c
forall (p :: * -> * -> *) a b c.
Profunctor p =>
(a -> b) -> p b c -> p a c
lmap
((DocumentID -> GroupID) -> (UUID, DocumentID) -> (UUID, GroupID)
forall b c a. (b -> c) -> (a, b) -> (a, c)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second DocumentID -> GroupID
Document.unDocumentID)
[singletonStatement|
select exists (
select 1
from roles r
join documents d on d.group_id = r.group_id
where r.user_id = $1 :: uuid and d.id = $2 :: int8
) :: bool
|]
checkGroupNameExistence :: Statement Text Bool
checkGroupNameExistence :: Statement Text Bool
checkGroupNameExistence =
[singletonStatement|
select exists (
select 1
from groups
where name = $1 :: text
) :: bool
|]
getExternalPermission
:: Statement (User.UserID, Document.DocumentID) (Maybe Permission.Permission)
getExternalPermission :: Statement (UUID, DocumentID) (Maybe Permission)
getExternalPermission =
(Maybe Text -> Maybe Permission)
-> Statement (UUID, DocumentID) (Maybe Text)
-> Statement (UUID, DocumentID) (Maybe Permission)
forall b c a. (b -> c) -> Statement a b -> Statement a c
forall (p :: * -> * -> *) b c a.
Profunctor p =>
(b -> c) -> p a b -> p a c
rmap
(Maybe Text -> (Text -> Maybe Permission) -> Maybe Permission
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Text -> Maybe Permission
Permission.textToPermission)
(Statement (UUID, DocumentID) (Maybe Text)
-> Statement (UUID, DocumentID) (Maybe Permission))
-> Statement (UUID, DocumentID) (Maybe Text)
-> Statement (UUID, DocumentID) (Maybe Permission)
forall a b. (a -> b) -> a -> b
$ ((UUID, DocumentID) -> (UUID, GroupID))
-> Statement (UUID, GroupID) (Maybe Text)
-> Statement (UUID, DocumentID) (Maybe Text)
forall a b c. (a -> b) -> Statement b c -> Statement a c
forall (p :: * -> * -> *) a b c.
Profunctor p =>
(a -> b) -> p b c -> p a c
lmap
((DocumentID -> GroupID) -> (UUID, DocumentID) -> (UUID, GroupID)
forall b c a. (b -> c) -> (a, b) -> (a, c)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second DocumentID -> GroupID
Document.unDocumentID)
[maybeStatement|
select permission :: text
from external_document_rights
where user_id = $1 :: uuid and document_id = $2 :: int8
|]
getDocumentGroupID :: Statement Document.DocumentID (Maybe Group.GroupID)
getDocumentGroupID :: Statement DocumentID (Maybe GroupID)
getDocumentGroupID =
(DocumentID -> GroupID)
-> Statement GroupID (Maybe GroupID)
-> Statement DocumentID (Maybe GroupID)
forall a b c. (a -> b) -> Statement b c -> Statement a c
forall (p :: * -> * -> *) a b c.
Profunctor p =>
(a -> b) -> p b c -> p a c
lmap
DocumentID -> GroupID
Document.unDocumentID
[maybeStatement|
select group_id :: int8
from documents
where id = $1 :: int8
|]
addExternalPermission
:: Statement (User.UserID, Document.DocumentID, Text) ()
addExternalPermission :: Statement (UUID, DocumentID, Text) ()
addExternalPermission =
((UUID, DocumentID, Text) -> (UUID, GroupID, Text))
-> Statement (UUID, GroupID, Text) ()
-> Statement (UUID, DocumentID, Text) ()
forall a b c. (a -> b) -> Statement b c -> Statement a c
forall (p :: * -> * -> *) a b c.
Profunctor p =>
(a -> b) -> p b c -> p a c
lmap
( \(UUID
user, DocumentID
document, Text
permission) -> (UUID
user, DocumentID -> GroupID
Document.unDocumentID DocumentID
document, Text
permission)
)
[resultlessStatement|
insert into external_document_rights (user_id, document_id, permission)
values ($1 :: uuid, $2 :: int8, $3 :: text :: permission)
|]
updateExternalPermission
:: Statement (User.UserID, Document.DocumentID, Text) ()
updateExternalPermission :: Statement (UUID, DocumentID, Text) ()
updateExternalPermission =
((UUID, DocumentID, Text) -> (UUID, GroupID, Text))
-> Statement (UUID, GroupID, Text) ()
-> Statement (UUID, DocumentID, Text) ()
forall a b c. (a -> b) -> Statement b c -> Statement a c
forall (p :: * -> * -> *) a b c.
Profunctor p =>
(a -> b) -> p b c -> p a c
lmap
( \(UUID
user, DocumentID
document, Text
permission) -> (UUID
user, DocumentID -> GroupID
Document.unDocumentID DocumentID
document, Text
permission)
)
[resultlessStatement|
update external_document_rights
set permission = $3 :: text :: permission
where user_id = $1 :: uuid and document_id = $2 :: int8
|]
deleteExternalPermission :: Statement (User.UserID, Document.DocumentID) ()
deleteExternalPermission :: Statement (UUID, DocumentID) ()
deleteExternalPermission =
((UUID, DocumentID) -> (UUID, GroupID))
-> Statement (UUID, GroupID) () -> Statement (UUID, DocumentID) ()
forall a b c. (a -> b) -> Statement b c -> Statement a c
forall (p :: * -> * -> *) a b c.
Profunctor p =>
(a -> b) -> p b c -> p a c
lmap
((DocumentID -> GroupID) -> (UUID, DocumentID) -> (UUID, GroupID)
forall b c a. (b -> c) -> (a, b) -> (a, c)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second DocumentID -> GroupID
Document.unDocumentID)
[resultlessStatement|
delete from external_document_rights
where user_id = $1 :: uuid and document_id = $2 :: int8
|]
createPasswordResetToken :: Statement (User.UserID, Text, UTCTime) UUID
createPasswordResetToken :: Statement (UUID, Text, UTCTime) UUID
createPasswordResetToken =
[singletonStatement|
insert into password_reset_tokens (user_id, token_hash, expires_at)
values ($1 :: uuid, $2 :: text, $3 :: timestamptz)
returning id :: uuid
|]
getPasswordResetToken
:: Statement
Text
(Maybe (UUID, User.UserID, Text, UTCTime, UTCTime, Maybe UTCTime))
getPasswordResetToken :: Statement
Text (Maybe (UUID, UUID, Text, UTCTime, UTCTime, Maybe UTCTime))
getPasswordResetToken =
[maybeStatement|
select
id :: uuid,
user_id :: uuid,
token_hash :: text,
expires_at :: timestamptz,
created_at :: timestamptz,
used_at :: timestamptz?
from password_reset_tokens
where token_hash = $1 :: text
and expires_at > now()
and used_at is null
|]
markPasswordResetTokenUsed :: Statement Text ()
markPasswordResetTokenUsed :: Statement Text ()
markPasswordResetTokenUsed =
[resultlessStatement|
update password_reset_tokens
set used_at = now()
where token_hash = $1 :: text
|]
cleanupExpiredTokens :: Statement () ()
cleanupExpiredTokens :: Statement () ()
cleanupExpiredTokens =
[resultlessStatement|
delete from password_reset_tokens
where expires_at < now() - interval '24 hours'
|]
getAllExternalUsersOfDocument
:: Statement Document.DocumentID [(User.UserID, Maybe Permission.Permission)]
getAllExternalUsersOfDocument :: Statement DocumentID [(UUID, Maybe Permission)]
getAllExternalUsersOfDocument =
(Vector (UUID, Text) -> [(UUID, Maybe Permission)])
-> Statement DocumentID (Vector (UUID, Text))
-> Statement DocumentID [(UUID, Maybe Permission)]
forall b c a. (b -> c) -> Statement a b -> Statement a c
forall (p :: * -> * -> *) b c a.
Profunctor p =>
(b -> c) -> p a b -> p a c
rmap
(((UUID, Text) -> (UUID, Maybe Permission))
-> [(UUID, Text)] -> [(UUID, Maybe Permission)]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Text -> Maybe Permission)
-> (UUID, Text) -> (UUID, Maybe Permission)
forall b c a. (b -> c) -> (a, b) -> (a, c)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
Data.Bifunctor.second Text -> Maybe Permission
Permission.textToPermission) ([(UUID, Text)] -> [(UUID, Maybe Permission)])
-> (Vector (UUID, Text) -> [(UUID, Text)])
-> Vector (UUID, Text)
-> [(UUID, Maybe Permission)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector (UUID, Text) -> [(UUID, Text)]
forall a. Vector a -> [a]
toList)
(Statement DocumentID (Vector (UUID, Text))
-> Statement DocumentID [(UUID, Maybe Permission)])
-> Statement DocumentID (Vector (UUID, Text))
-> Statement DocumentID [(UUID, Maybe Permission)]
forall a b. (a -> b) -> a -> b
$ (DocumentID -> GroupID)
-> Statement GroupID (Vector (UUID, Text))
-> Statement DocumentID (Vector (UUID, Text))
forall a b c. (a -> b) -> Statement b c -> Statement a c
forall (p :: * -> * -> *) a b c.
Profunctor p =>
(a -> b) -> p b c -> p a c
lmap
DocumentID -> GroupID
Document.unDocumentID
[vectorStatement|
select user_id :: uuid, permission :: text
from external_document_rights
where document_id = $1 :: int8
|]