@@ -9,7 +9,8 @@
99 FlexibleInstances,
1010 KindSignatures,
1111 DeriveAnyClass,
12− RecordWildCards #-}
12+ RecordWildCards,
13+ ScopedTypeVariables #-}
1314
1415{-# OPTIONS_GHC -Wno-partial-type-signatures #-}
1516
@@ -63,7 +64,9 @@ module Data.Query (
6364 killAllTokens,
6465 channelCountForUser,
6566 pruneAuth,
66− searchChannels
67+ searchChannels,
68+ isValidFaculty,
69+ groupChatIsValidForUser
6770 ) where
6871
6972import Squeal.PostgreSQL
@@ -93,7 +96,7 @@ import Data.Text (Text)
9396import qualified Data.Text as T
9497import Data.Channel.NamedChannel
9598import Data.Channel.AnonymousChannel
96−import Data.Maybe (fromMaybe, catMaybes)
99+import Data.Maybe (fromMaybe, catMaybes, isJust)
97100import Squeal.PostgreSQL.Render
98101import Data.GroupChat
99102import Data.Message
@@ -105,6 +108,8 @@ import Data.Foldable (fold)
105108import Data.Char
106109import qualified Data.Vector as V
107110import Server.Auth.Token
111+import Server.Error
112+import Data.Text.Validator
108113
109114-- MARK: Documentation
110115
@@ -313,8 +318,7 @@ getAllChannelsForUserQ = selectStar $
313318searchChannelsForUserQ :: Query Schema (TuplePG (UserId, Text)) (RowPG NamedChannelFull)
314319searchChannelsForUserQ = selectStar $
315320 from (table #channels) &
316− where_ (#namedChannelFullOwner .== param @1 .&&
317− vector @@ query) &
321+ where_ (#namedChannelFullOwner .== param @1) &
318322 orderBy [
319323 tsRankCd vector1 query & Desc,
320324 tsRankCd vector query & Desc
@@ -786,6 +790,14 @@ pruneGhostUsersQ = deleteFrom_ #users
786790
787791-- MARK: FrontEnd Data Structures
788792
793+instance HasValidatableText UserCreation where
794+ validateText UserCreation{..} = all validateText [
795+ userCreationFirstName,
796+ userCreationMiddleName,
797+ userCreationLastName,
798+ userCreationUserFaculty,
799+ userCreationUserEmail]
800+
789801data UserCreation = UserCreation {
790802 userCreationFirstName :: Text,
791803 userCreationMiddleName :: Text,
@@ -851,11 +863,13 @@ getChannelForUser uId cId = do
851863 Nothing -> lift $ S.throwError S.err404
852864
853865-- TODO: Reject bad requests. Should be binary.
854−verifiedUsers :: [UserId] -> StaticPQ [UserId]
855−verifiedUsers uIds =
866+verifyUsers :: [UserId] -> StaticPQ ()
867+verifyUsers uIds =
856868 case verifiedUserIdsQ uIds of
857− Just uIdsQ -> fmap fromOnly <$> (runQuery uIdsQ >>= getRows)
858− Nothing -> return []
869+ Just uIdsQ -> do
870+ (us :: [UserId]) <- fmap fromOnly <$> (runQuery uIdsQ >>= getRows)
871+ when (length us /= length uIds) $ lift $ S.throwError impossibleContent
872+ Nothing -> return ()
859873
860874deleteGroupChat :: GroupChatId -> StaticPQ ()
861875deleteGroupChat gId = do
@@ -917,7 +931,7 @@ getAllUsers :: StaticPQ [User Faculty]
917931getAllUsers = fmap rowToUser <$> (runQuery getAllUsersQ >>= getRows)
918932
919933publishPost :: UserId -> PostCreation -> StaticPQ PostId
920−publishPost uId pc = commitedTransactionallyUpdate $ do
934+publishPost uId pc = commitedTransactionallyUpdate $ do
921935 pId' <- manipulateParams createPostRowQ (uId, postCreationTags pc) >>= firstRow
922936 case pId' of
923937 (Just (Only pId)) -> do
@@ -927,7 +941,8 @@ publishPost uId pc = commitedTransactionallyUpdate $ do
927941
928942createNewChannel :: UserId -> NamedChannelCreationRequest -> StaticPQ (Maybe NamedChannelId)
929943createNewChannel uId req = commitedTransactionallyUpdate $ do
930− uIds <- verifiedUsers . toList $ namedChannelCreationRequestPeopleIds req
944+ let uIds = toList $ namedChannelCreationRequestPeopleIds req
945+ verifyUsers uIds
931946 cId <- manipulateParams createNamedChannelQ (addUserToChannelCreate uId (req {namedChannelCreationRequestPeopleIds = fromList uIds})) >>= firstRow
932947 return $ fmap fromOnly cId
933948
@@ -935,15 +950,21 @@ channelCountForUser :: UserId -> StaticPQ Int64
935950channelCountForUser uId = (fromMaybe 0 . fmap fromOnly) <$> (runQueryParams countChannelsQ (Only uId) >>= firstRow)
936951
937952updateChannel :: UserId -> NamedChannel UserId -> StaticPQ ()
938−updateChannel uId req = commitedTransactionallyUpdate $ do
939− uIds <- fmap fromList . verifiedUsers . toList $ namedChannelPeopleIds req
953+updateChannel uId req = do
954+ let uIds = namedChannelPeopleIds req
955+ verifyUsers (toList uIds)
940956 _ <- getChannelForUser uId $ namedChannelId req
941− _ <- manipulateParams updateNamedChannelQ $ addUserToChannelUpdate uId (req {namedChannelPeopleIds = uIds})
957+ _ <- commitedTransactionallyUpdate $ manipulateParams updateNamedChannelQ $ addUserToChannelUpdate uId (req {namedChannelPeopleIds = uIds})
942958 return ()
943959
944960getFaculty :: Text -> StaticPQ Faculty
945961getFaculty t = runQueryParams getFacultyQ (Only t) >>= firstRow >>= fromMaybe404
946962
963+isValidFaculty :: FacultyUrl -> StaticPQ Bool
964+isValidFaculty url = do
965+ (faculty :: Maybe Faculty) <- runQueryParams getFacultyQ (Only url) >>= firstRow
966+ return $ isJust faculty
967+
947968updateFaculty :: Faculty -> StaticPQ ()
948969updateFaculty fac = void $ manipulateParams updateFacultyQ fac
949970
@@ -980,9 +1001,9 @@ getAllChannels uId = fmap (map removeUserFromChannel) $
9801001 runQueryParams getAllChannelsForUserQ (Only uId) >>= getRows
9811002
9821003deleteNamedChannel :: UserId -> NamedChannelId -> StaticPQ ()
983−deleteNamedChannel uId cId = commitedTransactionallyUpdate $ do
1004+deleteNamedChannel uId cId = do
9841005 _ <- getChannelForUser uId cId
985− _ <- manipulateParams deleteNamedChannelQ (Only cId)
1006+ _ <- commitedTransactionallyUpdate $ manipulateParams deleteNamedChannelQ (Only cId)
9861007 return ()
9871008
9881009-- Returns n most popular
@@ -1029,6 +1050,7 @@ sendMessage selfId (MessageCreation (Just gId) uId@Nothing body) = do
10291050 >>= firstRow >>= fromMaybe500
10301051 return mId
10311052sendMessage selfId (MessageCreation gId@Nothing (Just uId) body) = do
1053+ verifyUsers [uId]
10321054 (Only mId) <- manipulateParams createMessageQ (selfId, gId, Just uId, body)
10331055 >>= firstRow >>= fromMaybe500
10341056 return mId
@@ -1065,15 +1087,24 @@ getGroupChatForUser uId gId = do
10651087 (Just c) -> return c
10661088 Nothing -> lift $ S.throwError S.err404
10671089
1090+groupChatIsValidForUser :: UserId -> GroupChatId -> StaticPQ Bool
1091+groupChatIsValidForUser uId gId = do
1092+ (chat :: Maybe GroupChat) <- runQueryParams getGroupChatForUserQ (show uId, gId) >>= firstRow
1093+ return $ isJust chat
1094+
10681095getFacultyFromQuery :: T.Text -> StaticPQ [Faculty]
10691096getFacultyFromQuery query =
10701097 runQueryParams getFacultySearchResultQ (Only . queryFromTextAbbr $ query) >>= getRows
10711098
10721099searchUsers :: T.Text -> StaticPQ [User Faculty]
1073−searchUsers query =
1074− map rowToUser <$> (runQueryParams searchUsersQ (Only . queryFromText $ query) >>= getRows)
1100+searchUsers query = do
1101+ unless (validateText query) $ lift $ throwError lengthExceeded
1102+ if (T.null . T.strip $ query)
1103+ then return []
1104+ else map rowToUser <$> (runQueryParams searchUsersQ (Only . queryFromText $ query) >>= getRows)
10751105
10761106searchTags :: T.Text -> StaticPQ [Text]
1107+searchTags "" = return []
10771108searchTags query = map fromOnly <$>
10781109 (runQueryParams searchTagsQ
10791110 (Only . (<> ":*") . T.strip $ query) >>= getRows)