on master help sign in
Added users/update
c96dd55iko
denis/src/Data/Query.hs+27−1
@@ -57,7 +57,8 @@ module Data.Query (
57 tryActivateToken,
57 tryActivateToken,
58 deactivateToken,
58 deactivateToken,
59 searchUsers,
59 searchUsers,
60− searchTags
60+ searchTags,
61+ updateUser
61 ) where
62 ) where
62
63
63import Squeal.PostgreSQL
64import Squeal.PostgreSQL
@@ -286,6 +287,18 @@ getChannelForUserQ = selectStar $
286 from (table #channels) &
287 from (table #channels) &
287 where_ (#namedChannelFullOwner .== param @1 .&& #namedChannelFullId .== param @2)
288 where_ (#namedChannelFullOwner .== param @1 .&& #namedChannelFullId .== param @2)
288
289
290+updateUserQ :: Manipulation Schema (TuplePG (User FacultyUrl)) (RowPG (Only UserId))
291+updateUserQ = update #users (
292+ Same `as` #userRowId :*
293+ Set (param @2) `as` #userRowFirstName :*
294+ Set (param @3) `as` #userRowMiddleName :*
295+ Set (param @4) `as` #userRowLastName :*
296+ Set (param @5) `as` #userRowFacultyUrl :*
297+ Same `as` #userRowEmail :*
298+ Same `as` #userRowIsValidated)
299+ (#userRowId .== param @1 .&& #userRowEmail .== param @6)
300+ (Returning $ #userRowId `as` #fromOnly)
301+
289getAllChannelsForUserQ :: Query Schema (TuplePG (Only UserId)) (RowPG NamedChannelFull)
302getAllChannelsForUserQ :: Query Schema (TuplePG (Only UserId)) (RowPG NamedChannelFull)
290getAllChannelsForUserQ = selectStar $
303getAllChannelsForUserQ = selectStar $
291 from (table #channels) &
304 from (table #channels) &
@@ -1041,8 +1054,21 @@ deactivateToken uId dData = fmap fromOnly <$> (manipulateParams deactivateTokenQ
1041getVerifiedToken :: UserId -> ByteString -> StaticPQ (Maybe Token)
1054getVerifiedToken :: UserId -> ByteString -> StaticPQ (Maybe Token)
1042getVerifiedToken uId tokenData = runQueryParams getVerifiedTokenQ (uId, hash tokenData) >>= firstRow
1055getVerifiedToken uId tokenData = runQueryParams getVerifiedTokenQ (uId, hash tokenData) >>= firstRow
1043
1056
1057+updateUser :: (User FacultyUrl) -> StaticPQ (Maybe UserId)
1058+updateUser user = fmap fromOnly <$> (manipulateParams updateUserQ (normalizeUser user) >>= firstRow)
1059+
1044-- MARK: Utils
1060-- MARK: Utils
1045
1061
1062+normalizeUser :: User FacultyUrl -> User FacultyUrl
1063+normalizeUser User{..} = User {
1064+ userId = userId,
1065+ firstName = T.strip $ firstName,
1066+ middleName = T.strip $ middleName,
1067+ lastName = T.strip $ lastName,
1068+ userFaculty = T.toLower . T.strip $ userFaculty,
1069+ userEmail = T.toLower . T.strip $ userEmail
1070+}
1071+
1046data UserRow = UserRow {
1072data UserRow = UserRow {
1047 userRowId :: UserId,
1073 userRowId :: UserId,
1048 userRowFirstName :: Text,
1074 userRowFirstName :: Text,
denis/src/Server/API.hs+23−2
@@ -3,7 +3,8 @@
3 DataKinds,
3 DataKinds,
4 TypeOperators,
4 TypeOperators,
5 OverloadedStrings,
5 OverloadedStrings,
6− ScopedTypeVariables #-}
6+ ScopedTypeVariables,
7+ RecordWildCards #-}
7{-# OPTIONS_GHC -Wno-orphans #-}
8{-# OPTIONS_GHC -Wno-orphans #-}
8
9
9module Server.API (
10module Server.API (
@@ -32,6 +33,8 @@ import Server.API.Messages
32import Data.Faculty
33import Data.Faculty
33import Server.API.Faculty
34import Server.API.Faculty
34import Data.Text (Text)
35import Data.Text (Text)
36+import Data.Maybe (isJust)
37+import Control.Monad.Except
35
38
36-- MARK: Documentation
39-- MARK: Documentation
37
40
@@ -41,6 +44,8 @@ instance HasDocs api => HasDocs (Authentication :> api) where
41
44
42type UserSearchDescription = Description "Searches for users with the given string.\n\nFeed in the raw user input string."
45type UserSearchDescription = Description "Searches for users with the given string.\n\nFeed in the raw user input string."
43
46
47+type UpdateUserDescription = Description "Updates the current user.\n\nThrow 401 if you try to change email or something like that."
48+
44-- MARK: Implementation
49-- MARK: Implementation
45
50
46type Authentication = AuthProtect "basicAuth"
51type Authentication = AuthProtect "basicAuth"
@@ -53,6 +58,7 @@ type API =
53 "users" :> ReqBody '[JSON] [UserId] :> Post '[JSON] [User Faculty] :<|>
58 "users" :> ReqBody '[JSON] [UserId] :> Post '[JSON] [User Faculty] :<|>
54 "users" :> "all" :> Post '[JSON] [User Faculty] :<|>
59 "users" :> "all" :> Post '[JSON] [User Faculty] :<|>
55 "users" :> "search" :> UserSearchDescription :> ReqBody '[JSON, PlainText] Text :> Post '[JSON] [User Faculty] :<|>
60 "users" :> "search" :> UserSearchDescription :> ReqBody '[JSON, PlainText] Text :> Post '[JSON] [User Faculty] :<|>
61+ "users" :> "update" :> UpdateUserDescription :> ReqBody '[JSON] UserCreation :> PostNoContent '[JSON, PlainText] NoContent :<|>
56 "posts" :> PostApi :<|>
62 "posts" :> PostApi :<|>
57 "channels" :> ChannelsApi :<|>
63 "channels" :> ChannelsApi :<|>
58 MessagesApi
64 MessagesApi
@@ -71,9 +77,24 @@ mkServerAPI l =
71 maybeNotFound . runQnotFound . getUsers :<|>
77 maybeNotFound . runQnotFound . getUsers :<|>
72 runQerror getAllUsers :<|>
78 runQerror getAllUsers :<|>
73 runQerror . searchUsers :<|>
79 runQerror . searchUsers :<|>
80+ updateUserApi uId :<|>
74 postApi uId :<|>
81 postApi uId :<|>
75 channelsApi uId :<|>
82 channelsApi uId :<|>
76 messagesServer uId
83 messagesServer uId
77 ) :<|>
84 ) :<|>
78 tagsServer :<|>
85 tagsServer :<|>
79− facultyServer
86+ facultyServer
87+
88+updateUserApi :: UserId -> UserCreation -> App NoContent
89+updateUserApi uId UserCreation{..} = do
90+ res <- runQerror $ updateUser User {
91+ userId = uId,
92+ firstName = userCreationFirstName,
93+ middleName = userCreationMiddleName,
94+ lastName = userCreationLastName,
95+ userFaculty = userCreationUserFaculty,
96+ userEmail = userCreationUserEmail
97+ }
98+ if isJust res
99+ then return NoContent
100+ else throwError err401
denis/src/Server/API/Completions.hs+1−1
@@ -59,7 +59,7 @@ type CompletionsDescription = Description "\
59 \}\n\
59 \}\n\
60 \```"
60 \```"
61
61
62−type SearchDescription = Description "Returns tag completions for given user input."
62+type SearchDescription = Description "Returns top 1000 tag completions for given user input."
63
63
64type TagsAPI = "completions" :> CompletionsDescription :> Get '[JSON] CompletionTree :<|>
64type TagsAPI = "completions" :> CompletionsDescription :> Get '[JSON] CompletionTree :<|>
65 "search" :> SearchDescription :> ReqBody '[JSON, PlainText] Text :> Post '[JSON] [Text]
65 "search" :> SearchDescription :> ReqBody '[JSON, PlainText] Text :> Post '[JSON] [Text]