2 Module : Gargantext.Database.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.
13 {-# OPTIONS_GHC -fno-warn-name-shadowing #-}
14 {-# OPTIONS_GHC -fno-warn-orphans #-}
16 {-# LANGUAGE TemplateHaskell #-}
17 {-# LANGUAGE FlexibleInstances #-}
18 {-# LANGUAGE MultiParamTypeClasses #-}
19 {-# LANGUAGE FunctionalDependencies #-}
20 {-# LANGUAGE Arrows #-}
21 {-# LANGUAGE NoImplicitPrelude #-}
22 {-# LANGUAGE OverloadedStrings #-}
23 {-# LANGUAGE RankNTypes #-}
25 module Gargantext.Database.Schema.User where
27 import Control.Arrow (returnA)
28 import Control.Lens.TH (makeLensesWith, abbreviatedFields)
29 import Data.Eq(Eq(..))
30 import Data.List (find)
31 import Data.Maybe (Maybe)
32 import Data.Profunctor.Product.TH (makeAdaptorAndInstance)
33 import Data.Text (Text)
34 import Data.Time (UTCTime)
35 import GHC.Show(Show(..))
36 import Gargantext.Core.Types.Individu (Username, arbitraryUsername)
37 import Gargantext.Database.Utils
38 import Gargantext.Prelude
41 ------------------------------------------------------------------------
43 ------------------------------------------------------------------------
46 data UserLight = UserLight { userLight_id :: Int
47 , userLight_username :: Text
48 , userLight_email :: Text
51 toUserLight :: User -> UserLight
52 toUserLight (User id _ _ _ u _ _ e _ _ _ ) = UserLight id u e
54 data UserPoly id pass llogin suser
56 mail staff active djoined = User { user_id :: id
57 , user_password :: pass
58 , user_lastLogin :: llogin
59 , user_isSuperUser :: suser
61 , user_username :: uname
62 , user_firstName :: fname
63 , user_lastName :: lname
66 , user_isStaff :: staff
67 , user_isActive :: active
68 , user_dateJoined :: djoined
71 type UserWrite = UserPoly (Maybe (Column PGInt4)) (Column PGText)
72 (Maybe (Column PGTimestamptz)) (Column PGBool)
73 (Column PGText) (Column PGText)
74 (Column PGText) (Column PGText)
75 (Column PGBool) (Column PGBool)
76 (Maybe (Column PGTimestamptz))
78 type UserRead = UserPoly (Column PGInt4) (Column PGText)
79 (Column PGTimestamptz) (Column PGBool)
80 (Column PGText) (Column PGText)
81 (Column PGText) (Column PGText)
82 (Column PGBool) (Column PGBool)
83 (Column PGTimestamptz)
85 type UserReadNull = UserPoly (Column (Nullable PGInt4)) (Column (Nullable PGText))
86 (Column (Nullable PGTimestamptz)) (Column (Nullable PGBool))
87 (Column (Nullable PGText)) (Column (Nullable PGText))
88 (Column (Nullable PGText)) (Column (Nullable PGText))
89 (Column (Nullable PGBool)) (Column (Nullable PGBool))
90 (Column (Nullable PGTimestamptz))
95 type User = UserPoly Int Text (Maybe UTCTime) Bool Text Text Text Text Bool Bool UTCTime
97 $(makeAdaptorAndInstance "pUser" ''UserPoly)
98 $(makeLensesWith abbreviatedFields ''UserPoly)
101 userTable :: Table UserWrite UserRead
102 userTable = Table "auth_user" (pUser User { user_id = optional "id"
103 , user_password = required "password"
104 , user_lastLogin = optional "last_login"
105 , user_isSuperUser = required "is_superuser"
106 , user_username = required "username"
107 , user_firstName = required "first_name"
108 , user_lastName = required "last_name"
109 , user_email = required "email"
110 , user_isStaff = required "is_staff"
111 , user_isActive = required "is_active"
112 , user_dateJoined = optional "date_joined"
116 -- TODO: on conflict, nice message
117 insertUsers :: [UserWrite] -> Cmd err Int64
118 insertUsers us = mkCmd $ \c -> runInsert_ c insert
120 insert = Insert userTable us rCount Nothing
123 gargantextUser :: Username -> UserWrite
124 gargantextUser u = User (Nothing) (pgStrictText "password")
125 (Nothing) (pgBool True) (pgStrictText u)
126 (pgStrictText "first_name")
127 (pgStrictText "last_name")
128 (pgStrictText "e@mail")
129 (pgBool True) (pgBool True) (Nothing)
131 insertUsersDemo :: Cmd err Int64
132 insertUsersDemo = insertUsers $ map (\u -> gargantextUser u) arbitraryUsername
135 ------------------------------------------------------------------
136 queryUserTable :: Query UserRead
137 queryUserTable = queryTable userTable
139 selectUsersLight :: Query UserRead
140 selectUsersLight = proc () -> do
141 row@(User i _p _ll _is _un _fn _ln _m _iff _ive _dj) <- queryUserTable -< ()
143 --returnA -< User i p ll is un fn ln m iff ive dj
145 ------------------------------------------------------------------
146 -- | Select User with some parameters
147 -- Not optimized version
148 userWith :: (Eq a1, Foldable t) => (a -> a1) -> a1 -> t a -> Maybe a
149 userWith f t xs = find (\x -> f x == t) xs
151 -- | Select User with Username
152 userWithUsername :: Text -> [User] -> Maybe User
153 userWithUsername t xs = userWith user_username t xs
155 userWithId :: Int -> [User] -> Maybe User
156 userWithId t xs = userWith user_id t xs
158 userLightWithUsername :: Text -> [UserLight] -> Maybe UserLight
159 userLightWithUsername t xs = userWith userLight_username t xs
161 userLightWithId :: Int -> [UserLight] -> Maybe UserLight
162 userLightWithId t xs = userWith userLight_id t xs
165 instance QueryRunnerColumnDefault PGTimestamptz (Maybe UTCTime) where
166 queryRunnerColumnDefault = fieldQueryRunnerColumn
169 users :: Cmd err [User]
170 users = runOpaQuery queryUserTable
172 usersLight :: Cmd err [UserLight]
173 usersLight = map toUserLight <$> users
175 getUser :: Username -> Cmd err (Maybe UserLight)
176 getUser u = userLightWithUsername u <$> usersLight