2 Module : Gargantext.Database.Query.Table.User
3 Description : User Database management tools
4 Copyright : (c) CNRS, 2017-Present
5 License : AGPL + CECILL v3
6 Maintainer : team@gargantext.org
7 Stability : experimental
10 Functions to deal with users, database side.
14 {-# OPTIONS_GHC -fno-warn-orphans #-}
16 {-# LANGUAGE TemplateHaskell #-}
17 {-# LANGUAGE FunctionalDependencies #-}
18 {-# LANGUAGE Arrows #-}
20 module Gargantext.Database.Query.Table.User
27 , getUsersWithHyperdata
28 , getUsersWithNodeHyperdata
31 , updateUserForgotPasswordUUID
34 , selectUsersLightWith
40 , getUsersWithForgotPasswordUUID
42 , module Gargantext.Database.Schema.User
46 import Control.Arrow (returnA)
47 import Control.Lens ((^.))
48 import Data.Maybe (fromMaybe)
49 import Data.List (find)
50 import Data.Text (Text)
51 import Data.Time (UTCTime)
52 import qualified Data.UUID as UUID
53 import Gargantext.Core.Types.Individu
54 import qualified Gargantext.Prelude.Crypto.Auth as Auth
55 import Gargantext.Database.Admin.Config (nodeTypeId)
56 import Gargantext.Database.Admin.Types.Hyperdata (HyperdataUser)
57 import Gargantext.Database.Admin.Types.Node (NodeType(NodeUser), Node)
58 import Gargantext.Database.Prelude
59 import Gargantext.Database.Schema.Node (NodeRead, node_hyperdata, queryNodeTable, node_user_id, node_typename)
60 import Gargantext.Database.Schema.User
61 import Gargantext.Prelude
64 ------------------------------------------------------------------------
65 -- TODO: on conflict, nice message
66 insertUsers :: [UserWrite] -> Cmd err Int64
67 insertUsers us = mkCmd $ \c -> runInsert_ c insert
69 insert = Insert userTable us rCount Nothing
71 deleteUsers :: [Username] -> Cmd err Int64
72 deleteUsers us = mkCmd $ \c -> runDelete_ c
74 (\user -> in_ (map sqlStrictText us) (user_username user))
77 -- Updates email or password only (for now)
78 updateUserDB :: UserWrite -> Cmd err Int64
79 updateUserDB us = mkCmd $ \c -> runUpdate_ c (updateUserQuery us)
81 updateUserQuery :: UserWrite -> Update Int64
82 updateUserQuery us' = Update
84 , uUpdateWith = updateEasy (\ (UserDB { .. })
85 -> UserDB { user_password = p'
89 , uWhere = (\row -> user_username row .== un')
93 UserDB { user_password = p'
95 , user_email = em' } = us'
97 -----------------------------------------------------------------------
98 toUserWrite :: NewUser HashPassword -> UserWrite
99 toUserWrite (NewUser u m (Auth.PasswordHash p)) =
100 UserDB { user_id = Nothing
101 , user_password = sqlStrictText p
102 , user_lastLogin = Nothing
103 , user_isSuperUser = sqlBool True
104 , user_username = sqlStrictText u
105 , user_firstName = sqlStrictText "first_name"
106 , user_lastName = sqlStrictText "last_name"
107 , user_email = sqlStrictText m
108 , user_isStaff = sqlBool True
109 , user_isActive = sqlBool True
110 , user_dateJoined = Nothing
111 , user_forgot_password_uuid = Nothing }
113 ------------------------------------------------------------------
114 getUsersWith :: Username -> Cmd err [UserLight]
115 getUsersWith u = map toUserLight <$> runOpaQuery (selectUsersLightWith u)
117 selectUsersLightWith :: Username -> Select UserRead
118 selectUsersLightWith u = proc () -> do
119 row <- queryUserTable -< ()
120 restrict -< user_username row .== sqlStrictText u
123 getUsersWithEmail :: Text -> Cmd err [UserLight]
124 getUsersWithEmail e = map toUserLight <$> runOpaQuery (selectUsersLightWithEmail e)
126 selectUsersLightWithEmail :: Text -> Select UserRead
127 selectUsersLightWithEmail e = proc () -> do
128 row <- queryUserTable -< ()
129 restrict -< user_email row .== sqlStrictText e
132 getUsersWithForgotPasswordUUID :: UUID.UUID -> Cmd err [UserLight]
133 getUsersWithForgotPasswordUUID uuid = map toUserLight <$> runOpaQuery (selectUsersLightWithForgotPasswordUUID uuid)
135 selectUsersLightWithForgotPasswordUUID :: UUID.UUID -> Select UserRead
136 selectUsersLightWithForgotPasswordUUID uuid = proc () -> do
137 row <- queryUserTable -< ()
138 restrict -< user_forgot_password_uuid row .== sqlStrictText (UUID.toText uuid)
141 ----------------------------------------------------------
142 getUsersWithId :: Int -> Cmd err [UserLight]
143 getUsersWithId i = map toUserLight <$> runOpaQuery (selectUsersLightWithId i)
145 selectUsersLightWithId :: Int -> Select UserRead
146 selectUsersLightWithId i' = proc () -> do
147 row <- queryUserTable -< ()
148 restrict -< user_id row .== sqlInt4 i'
152 queryUserTable :: Select UserRead
153 queryUserTable = selectTable userTable
155 ----------------------------------------------------------------------
156 getUserHyperdata :: Int -> Cmd err [HyperdataUser]
157 getUserHyperdata i = do
158 runOpaQuery (selectUserHyperdataWithId i)
160 selectUserHyperdataWithId :: Int -> Select (Column SqlJsonb)
161 selectUserHyperdataWithId i' = proc () -> do
162 row <- queryNodeTable -< ()
163 restrict -< row^.node_user_id .== (sqlInt4 i')
164 restrict -< row^.node_typename .== (sqlInt4 $ nodeTypeId NodeUser)
165 returnA -< row^.node_hyperdata
167 getUserNodeHyperdata :: Int -> Cmd err [Node HyperdataUser]
168 getUserNodeHyperdata i = do
169 runOpaQuery (selectUserHyperdataWithId i)
171 selectUserHyperdataWithId :: Int -> Select NodeRead
172 selectUserHyperdataWithId i' = proc () -> do
173 row <- queryNodeTable -< ()
174 restrict -< row^.node_user_id .== (sqlInt4 i')
175 restrict -< row^.node_typename .== (sqlInt4 $ nodeTypeId NodeUser)
180 getUsersWithHyperdata :: Int -> Cmd err [(UserLight, HyperdataUser)]
181 getUsersWithHyperdata i = do
182 u <- getUsersWithId i
183 h <- getUserHyperdata i
184 -- printDebug "[getUsersWithHyperdata]" (u,h)
187 getUsersWithNodeHyperdata :: Int -> Cmd err [(UserLight, Node HyperdataUser)]
188 getUsersWithNodeHyperdata i = do
189 u <- getUsersWithId i
190 h <- getUserNodeHyperdata i
191 -- printDebug "[getUsersWithHyperdata]" (u,h)
195 updateUserEmail :: UserLight -> Cmd err Int64
196 updateUserEmail (UserLight { .. }) = mkCmd $ \c -> runUpdate_ c updateUserQuery
198 updateUserQuery :: Update Int64
199 updateUserQuery = Update
201 , uUpdateWith = updateEasy (\ (UserDB { .. }) -> UserDB { user_email = sqlStrictText userLight_email, .. } )
202 , uWhere = (\row -> user_id row .== (sqlInt4 userLight_id))
203 , uReturning = rCount }
205 updateUserPassword :: UserLight -> Cmd err Int64
206 updateUserPassword (UserLight { userLight_password = GargPassword password, .. }) = mkCmd $ \c -> runUpdate_ c updateUserQuery
208 updateUserQuery :: Update Int64
209 updateUserQuery = Update
211 , uUpdateWith = updateEasy (\ (UserDB { .. }) -> UserDB { user_password = sqlStrictText password, .. } )
212 , uWhere = (\row -> user_id row .== (sqlInt4 userLight_id))
213 , uReturning = rCount }
215 updateUserForgotPasswordUUID :: UserLight -> Cmd err Int64
216 updateUserForgotPasswordUUID (UserLight { .. }) = mkCmd $ \c -> runUpdate_ c updateUserQuery
218 pass = sqlStrictText $ fromMaybe "" userLight_forgot_password_uuid
219 updateUserQuery :: Update Int64
220 updateUserQuery = Update
222 , uUpdateWith = updateEasy (\ (UserDB { .. }) -> UserDB { user_forgot_password_uuid = pass, .. })
223 , uWhere = (\row -> user_id row .== (sqlInt4 userLight_id))
224 , uReturning = rCount }
225 ------------------------------------------------------------------
226 -- | Select User with some parameters
227 -- Not optimized version
228 userWith :: (Eq a1, Foldable t) => (a -> a1) -> a1 -> t a -> Maybe a
229 userWith f t xs = find (\x -> f x == t) xs
231 -- | Select User with Username
232 userWithUsername :: Text -> [UserDB] -> Maybe UserDB
233 userWithUsername t xs = userWith user_username t xs
235 userWithId :: Int -> [UserDB] -> Maybe UserDB
236 userWithId t xs = userWith user_id t xs
238 userLightWithUsername :: Text -> [UserLight] -> Maybe UserLight
239 userLightWithUsername t xs = userWith userLight_username t xs
241 userLightWithId :: Int -> [UserLight] -> Maybe UserLight
242 userLightWithId t xs = userWith userLight_id t xs
243 ----------------------------------------------------------------------
244 users :: Cmd err [UserDB]
245 users = runOpaQuery queryUserTable
247 usersLight :: Cmd err [UserLight]
248 usersLight = map toUserLight <$> users
250 getUser :: Username -> Cmd err (Maybe UserLight)
251 getUser u = userLightWithUsername u <$> usersLight
253 ----------------------------------------------------------------------
254 insertNewUsers :: [NewUser GargPassword] -> Cmd err Int64
255 insertNewUsers newUsers = do
256 users' <- liftBase $ mapM toUserHash newUsers
257 insertUsers $ map toUserWrite users'
259 ----------------------------------------------------------------------
260 instance DefaultFromField SqlTimestamptz (Maybe UTCTime) where
261 defaultFromField = fromPGSFromField