@@ -15,7 +15,59 @@
1515{-# OPTIONS_GHC -Wno-partial-type-signatures #-}
1616
1717
18−module Data.Query where
18+module Data.Query (
19+ Schema,
20+ createTables,
21+ getPosts,
22+ -- getUser,
23+ getUsers,
24+ getAllUsers,
25+ getLastPosts,
26+ getPostsForUser,
27+ Limit,
28+ publishPost,
29+ getChannelPosts,
30+ updateChannel,
31+ createNewChannel,
32+ getAllChannels,
33+ getAnonymousChannelPosts,
34+ deleteNamedChannel,
35+ HasUsers(..),
36+ wrapIntoUsers,
37+ ResponseWithUsers(..),
38+ getTags,
39+ getDialogs,
40+ getMessagesInUserChat,
41+ getMessagesInGroupChat,
42+ sendMessage,
43+ createGroupChat,
44+ updateGroupChat,
45+ leaveGroupChat,
46+ getGroupChatForUser,
47+ getFaculty,
48+ updateFaculty,
49+ getFacultyFromQuery,
50+ getUserWithEmail,
51+ createToken,
52+ validateToken,
53+ invalidateToken,
54+ tryVerifyToken,
55+ getVerifiedToken,
56+ UserCreation(..),
57+ createUser,
58+ tryActivateToken,
59+ deactivateToken,
60+ searchUsers,
61+ searchTags,
62+ updateUser,
63+ UserUpdateRow(..),
64+ killAllTokens,
65+ channelCountForUser,
66+ pruneAuth,
67+ searchChannels,
68+ isValidFaculty,
69+ groupChatIsValidForUser
70+ ) where
1971
2072import Squeal.PostgreSQL
2173import Data.User
@@ -58,9 +110,6 @@ import qualified Data.Vector as V
58110import Server.Auth.Token
59111import Server.Error
60112import Data.Text.Validator
61−import Control.Monad.Except
62−import Control.Monad.IO.Class
63−import Crypto.Hash.SHA512 (hash)
64113
65114-- MARK: Documentation
66115
@@ -73,17 +122,14 @@ instance (ToSample r) => ToSample (ResponseWithUsers r) where
73122type TableEndo schema params from grouping = TableExpression schema params from grouping ->
74123 TableExpression schema params from grouping
75124
76−-- |Функция, возвращаяющая запрос на посты, прменяя к нему данный ндоморфизм.
77125postsQ :: TableEndo Schema params _ 'Ungrouped -> Query Schema params _
78126postsQ te = selectStar $ te (from $ table #posts)
79127
80−-- |Функция, возвращающая посты
81128postViewT :: TableEndo Schema params _ 'Ungrouped -> TableExpression Schema params _ 'Ungrouped
82129postViewT te = from $ subquery (postsQ te `As` #posts) &
83130 innerJoin (table #postElements)
84131 (#posts ! #postRowId .== #postElements ! #rowElementId)
85132
86−-- |Функция, возвращающая запрос на поста, примення два промежуточных эндоморфизма к таблице.
87133getPostQ
88134 :: TableEndo Schema params _ 'Ungrouped
89135 -- ^ PostRowResponse endo
@@ -126,7 +172,6 @@ getPostQ oTe te = select (
126172-- let rows = M.fromList $ map (tupleBy $ quoteRowId . head) . groupBy ((==) `on` quoteRowId) . sortBy (compare `on` quoteRowId) $ rows'
127173-- return $ M.lookup qId rows >>= rowsToQuote rows
128174
129−-- |Запрос, возвращающий пользователя по адресу почты.
130175getUserWithEmailQ :: Query Schema (TuplePG (Only UserEmail)) (RowPG (User FacultyUrl))
131176getUserWithEmailQ = select (
132177 #userRowId `as` #userId :*
@@ -139,7 +184,6 @@ getUserWithEmailQ = select (
139184 where_ (#userRowEmail .== param @1) &
140185 where_ (notNull #userRowIsValidated))
141186
142−-- |Запрос, возвращающий подтвержденных пользователей.
143187verifiedUserIdsQ :: [UserId] -> Maybe (Query Schema '[] (RowPG (Only UserId)))
144188verifiedUserIdsQ uIds = case idsToColumn uIds of
145189 Just idQ -> Just $ select (#users ! #userRowId `as` #fromOnly) $ from (subquery (idQ `As` #ids) &
@@ -147,7 +191,6 @@ verifiedUserIdsQ uIds = case idsToColumn uIds of
147191 (#ids ! #id .== #users ! #userRowId))
148192 Nothing -> Nothing
149193
150−-- |Запрос, возвращающий пользователей с данными идентификаторами.
151194getUsersQ :: [UserId] -> Maybe (Query Schema '[] (RowPG UserRow))
152195getUsersQ uIds = case idsToColumn uIds of
153196 Just idQ -> Just $ select (
@@ -173,7 +216,6 @@ getUsersQ uIds = case idsToColumn uIds of
173216 where_ (notNull $ #users ! #userRowIsValidated))
174217 Nothing -> Nothing
175218
176−-- |Запорс, возвращающий всех пользователей.
177219getAllUsersQ :: Query Schema '[] (RowPG UserRow)
178220getAllUsersQ = select (
179221 #users ! #userRowId :*
@@ -195,7 +237,6 @@ getAllUsersQ = select (
195237 (#users ! #userRowFacultyUrl .== #faculties ! #facultyUrl))&
196238 where_ (notNull $ #users ! #userRowIsValidated))
197239
198−-- |Запрос, возвращающий все посты по идентификатору.
199240getPostsByIdQ :: [PostId] -> Maybe (Query Schema '[] (RowPG PostRowResponse))
200241getPostsByIdQ pIds = case idsToColumn pIds of
201242 Just idQ -> Just $ selectDotStar #posts $ from (subquery (idQ `As` #ids) &
@@ -204,17 +245,14 @@ getPostsByIdQ pIds = case idsToColumn pIds of
204245 (#ids ! #id .== #posts ! #postRowId))
205246 Nothing -> Nothing
206247
207−-- |Ограничение
208248type Limit = Word64
209249
210−-- |SQL оператор IS NOT FALSE
211250isNotFalse
212251 :: Expression schema from grouping params ('Null ty)
213252 -- ^ possibly @NULL@
214253 -> Condition schema from grouping params
215254isNotFalse x = UnsafeExpression $ renderExpression x <+> "IS NOT FALSE"
216255
217−-- |Запрос, возвращающий последние посты.
218256getLastPostsQ
219257 :: TableEndo _ _ _ _
220258 -> Limit
@@ -229,14 +267,12 @@ getLastPostsQ te lim dir = getPostQ
229267 where
230268 ((.^), order) = directionToOperator dir
231269
232−-- |Запрос, возвращающий последние посты для данного пользователя.
233270getLastNPostsForUserQ
234271 :: Limit
235272 -> P.PaginationDirection
236273 -> Query Schema (TuplePG (Maybe PostId, UserId)) (RowPG PostRowResponse)
237274getLastNPostsForUserQ = getLastPostsQ $ where_ (#posts ! #postRowAuthorId .== param @2)
238275
239−-- |Запрос на создание поста.
240276createPostRowQ :: Manipulation Schema (TuplePG (UserId, Vector Text)) (RowPG (Only PostId))
241277createPostRowQ = insertRow #posts
242278 (Default `as` #postRowId :*
@@ -246,7 +282,6 @@ createPostRowQ = insertRow #posts
246282 OnConflictDoRaise
247283 (Returning $ #postRowId `as` #fromOnly)
248284
249−-- |Запрос на создание элементов постов.
250285createPostElementRowsQ :: Manipulation Schema (TuplePG (PostElementRow Post)) '[]
251286createPostElementRowsQ = insertRow_ #postElements
252287 (Set (param @1) `as` #rowElementId :*
@@ -257,13 +292,11 @@ createPostElementRowsQ = insertRow_ #postElements
257292 Set (param @6) `as` #rowElementQuote :*
258293 Set (param @7) `as` #rowElementAttachment)
259294
260−-- |Запрос, возвращающий канал для данного пользователя.
261295getChannelForUserQ :: Query Schema (TuplePG (UserId, NamedChannelId)) (RowPG NamedChannelFull)
262296getChannelForUserQ = selectStar $
263297 from (table #channels) &
264298 where_ (#namedChannelFullOwner .== param @1 .&& #namedChannelFullId .== param @2)
265299
266−-- |Запрос, обновляющий данные о пользователе.
267300updateUserQ :: Manipulation Schema (TuplePG (UserUpdateRow)) (RowPG (Only UserId))
268301updateUserQ = update #users (
269302 Same `as` #userRowId :*
@@ -276,14 +309,12 @@ updateUserQ = update #users (
276309 (#userRowId .== param @1)
277310 (Returning $ #userRowId `as` #fromOnly)
278311
279−-- |Запрос, возвращающий каналы пользователя.
280312getAllChannelsForUserQ :: Query Schema (TuplePG (Only UserId)) (RowPG NamedChannelFull)
281313getAllChannelsForUserQ = selectStar $
282314 from (table #channels) &
283315 where_ (#namedChannelFullOwner .== param @1) &
284316 orderBy [#namedChannelFullId & Desc]
285317
286−-- |Запрос, осуществляющий поиск по каналам данного пользователя.
287318searchChannelsForUserQ :: Query Schema (TuplePG (UserId, Text)) (RowPG NamedChannelFull)
288319searchChannelsForUserQ = selectStar $
289320 from (table #channels) &
@@ -300,7 +331,6 @@ searchChannelsForUserQ = selectStar $
300331 vector1 = tsVector' #namedChannelFullName
301332 query = tsQuery' (param @2)
302333
303−-- |Запрос, обновляющий факультет.
304334updateFacultyQ :: Manipulation Schema (TuplePG Faculty) '[]
305335updateFacultyQ = insertRow #faculties
306336 (
@@ -315,12 +345,10 @@ updateFacultyQ = insertRow #faculties
315345 (OnConflictDoNothing)
316346 (Returning Nil)
317347
318−-- |Запрос, возвращающий факультет.
319348getFacultyQ :: Query Schema (TuplePG (Only Text)) (RowPG Faculty)
320349getFacultyQ = selectStar (from (table #faculties) &
321350 where_ (#facultyUrl .== param @1))
322351
323−-- |Запрос на создание нового именованного канала.
324352createNamedChannelQ :: Manipulation Schema (TuplePG NamedChannelCreation) (RowPG (Only NamedChannelId))
325353createNamedChannelQ = insertRow #channels
326354 (
@@ -333,17 +361,14 @@ createNamedChannelQ = insertRow #channels
333361 OnConflictDoRaise
334362 (Returning $ #namedChannelFullId `as` #fromOnly)
335363
336−-- |Запрос, возвращающий количество каналов у данного пользователя.
337364countChannelsQ :: Query Schema (TuplePG (Only UserId)) (RowPG (Only Int64))
338365countChannelsQ = select (countStar `as` #fromOnly) (from (table #channels) &
339366 where_ (#namedChannelFullOwner .== param @1) &
340367 groupBy #namedChannelFullOwner)
341368
342−-- |Запрос, удаляющий канал у данного пользователя.
343369deleteNamedChannelQ :: Manipulation Schema (TuplePG (Only NamedChannelId)) '[]
344370deleteNamedChannelQ = deleteFrom_ #channels (#namedChannelFullId .== param @1)
345371
346−-- |Запрос, обновляющий именованный канал.
347372updateNamedChannelQ :: Manipulation Schema (TuplePG NamedChannelFull) '[]
348373updateNamedChannelQ = update_ #channels
349374 (
@@ -355,7 +380,6 @@ updateNamedChannelQ = update_ #channels
355380 )
356381 (#namedChannelFullOwner .== param @2 .&& #namedChannelFullId .== param @1)
357382
358−-- |Запрос на каналы пользователя.
359383getChannelPostsQ
360384 :: Limit
361385 -> P.PaginationDirection
@@ -374,12 +398,10 @@ getChannelPostsQ lim dir uIds tags = getLastPostsQ
374398 Just uIdsQ -> (`in_` uIdsQ)
375399 Nothing -> const $ false
376400
377−-- |Запрос на все хэштеги.
378401getTagsQ :: Query Schema params (RowPG (Only String))
379402getTagsQ = selectDistinct (unsafeFunction "unnest" #postRowTags `as` #fromOnly) $
380403 from (table #posts)
381404
382−-- |Запорс на создание сообщения.
383405createMessageQ :: Manipulation
384406 Schema
385407 (TuplePG (UserId, Maybe GroupChatId, Maybe UserId, Jsonb (PostElement (MessageCreation))))
@@ -396,7 +418,6 @@ createMessageQ = insertRow #messages
396418 OnConflictDoRaise
397419 (Returning $ #messageStorageId `as` #fromOnly)
398420
399−-- |Запрос на создание фантомного сообщения.
400421createPhantomMessageQ :: Manipulation Schema (TuplePG (Only GroupChatId)) '[]
401422createPhantomMessageQ = insertRow_ #messages
402423 (
@@ -408,7 +429,6 @@ createPhantomMessageQ = insertRow_ #messages
408429 Set currentTimestamp `as` #messageStorageTime
409430 )
410431
411−-- |Запрос на создание групповой беседы.
412432createGroupChatQ :: Manipulation Schema (TuplePG GroupChatCreation) (RowPG (Only GroupChatId))
413433createGroupChatQ = insertRow #groupChats
414434 (
@@ -419,7 +439,6 @@ createGroupChatQ = insertRow #groupChats
419439 OnConflictDoRaise
420440 (Returning $ #groupChatId `as` #fromOnly)
421441
422−-- |Запрос на обновление групповой беседы.
423442updateGroupChatQ :: Manipulation Schema (TuplePG GroupChat) '[]
424443updateGroupChatQ = update_ #groupChats
425444 (
@@ -429,27 +448,23 @@ updateGroupChatQ = update_ #groupChats
429448 )
430449 (#groupChatId .== param @1)
431450
432−-- |Тип строки, воозвращаемой в промежуточном запросе на все диалоги.
433451type ChatsQueryResponse = '[
434452 "messageId" ::: 'NotNull (PG UserId),
435453 "messageGroupId" ::: 'Null (PG UserId),
436454 "messageUserId" ::: 'Null (PG UserId)
437455 ]
438456
439−-- |Тип оператора сравнения.
440457type ConditionOp schema from grouping params nullity0 nullity1 (ty :: PGType)
441458 = Expression schema from grouping params (nullity0 ty)
442459 -> Expression schema from grouping params (nullity1 ty)
443460 -> Condition schema from grouping params
444461
445−-- |Тип параметров на запрос диалогов.
446462type ChatQueryParams = TuplePG
447463 ( UserId
448464 , Maybe String -- Just UserId as String
449465 , Maybe MessageId
450466 )
451467
452−-- |Запрос на все диалоги.
453468getChatsQ
454469 :: Limit
455470 -> P.PaginationDirection
@@ -510,7 +525,6 @@ getChatsQ lim dir = select (
510525 where_ (isNotNull #messageStorageDestinationGroupId) &
511526 groupBy #messageStorageDestinationGroupId
512527
513−-- |Запрос на сообщения.
514528getMessagesQ
515529 :: Limit
516530 -> P.PaginationDirection
@@ -530,7 +544,6 @@ getMessagesQ lim dir = selectStar (from (table #messages) &
530544 where
531545 ((.^), order) = directionToOperator dir
532546
533−-- |Запрос на сообщения в групповой беседе.
534547getGroupMessagesQ
535548 :: Limit
536549 -> P.PaginationDirection
@@ -549,14 +562,12 @@ getGroupMessagesQ lim dir = selectStar (from (table #messages) &
549562 ((.^), order) = directionToOperator dir
550563
551564-- String -- user id as String
552−-- |Запрос на групповую беседу для данного пользователя.
553565getGroupChatForUserQ :: Query Schema (TuplePG (String, GroupChatId)) (RowPG GroupChat)
554566getGroupChatForUserQ = selectStar $
555567 (from (table #groupChats)) &
556568 where_ (#groupChatId .== param @2) &
557569 where_ (#groupChatUsers .? param @1)
558570
559−-- |Запрос на поиск факультета.
560571getFacultySearchResultQ :: Query Schema (TuplePG (Only Text)) (RowPG Faculty)
561572getFacultySearchResultQ = selectStar (from (table #faculties) &
562573 where_ (vector @@ query) &
@@ -577,7 +588,6 @@ getFacultySearchResultQ = selectStar (from (table #faculties) &
577588 #facultyPath])
578589 query = tsQuery "russian" (param @1)
579590
580−-- |Запрос на поиск пользователя.
581591searchUsersQ :: Query Schema (TuplePG (Only Text)) (RowPG UserRow)
582592searchUsersQ = select (
583593 #users ! #userRowId :*
@@ -609,21 +619,19 @@ searchUsersQ = select (
609619 ])
610620 query = tsQuery' (param @1)
611621
612−-- |Запрос на теги по популярности.
613622tagsByFrquencyQ :: Query Schema params '["tag" ::: 'NotNull (PG Text), "count" ::: 'NotNull 'PGint8]
614623tagsByFrquencyQ = select
615624 (#fromOnly `as` #tag :* count #fromOnly `as` #count)
616625 (from (subquery $ getTagsQ `As` #tt) &
617626 groupBy #fromOnly)
618627
619−-- |Запрос на данной количество самых популярных тегов.
620628getNpopularTagsQ :: Limit -> Query Schema param (RowPG (Only Text))
621629getNpopularTagsQ lim = select (#tag `as` #fromOnly)
622630 (from (subquery $ tagsByFrquencyQ `As` #tt) &
623631 orderBy [#count & Desc] &
624632 limit lim)
625633
626−-- |Запрос на поиск по тегам.
634+
627635searchTagsQ :: Query Schema (TuplePG (Only Text)) (RowPG (Only Text))
628636searchTagsQ = select (#tag `as` #fromOnly) $
629637 from (subquery (tagsByFrquencyQ `As` #tt)) &
@@ -634,7 +642,6 @@ searchTagsQ = select (#tag `as` #fromOnly) $
634642 query = tsQuery' (param @1)
635643 vector = tsVector' #tag
636644
637−-- |PostgreSQL функция ts_rank_cd
638645tsRankCd
639646 :: Expression schema from grouping params ('NotNull 'PGtext)
640647 -> Expression schema from grouping params ('NotNull 'PGtext)
@@ -642,7 +649,6 @@ tsRankCd
642649tsRankCd vector query = UnsafeExpression $
643650 "ts_rank_cd" <> parenthesized (commaSeparated ["ARRAY[1,1,1,1]", renderExpression vector, renderExpression query, "2|4|8|16|32"])
644651
645−-- |PostgreSQL функция ts_vector
646652tsVector
647653 :: ByteString -- ^ Language
648654 -> Expression schema from grouping params ('NotNull 'PGtext)
@@ -650,14 +656,12 @@ tsVector
650656tsVector lang x = UnsafeExpression $
651657 "to_tsvector" <> parenthesized (commaSeparated [singleQuotedUtf8 lang, renderExpression x])
652658
653−-- |PostgreSQL функция ts_vector без языка.
654659tsVector'
655660 :: Expression schema from grouping params ('NotNull 'PGtext)
656661 -> Expression schema from grouping params ('NotNull 'PGtext)
657662tsVector' x = UnsafeExpression $
658663 "to_tsvector" <> parenthesized (renderExpression x)
659664
660−-- |PostgreSQL функция ts_query.
661665tsQuery
662666 :: ByteString -- ^ Language
663667 -> Expression schema from grouping params ('NotNull 'PGtext)
@@ -665,38 +669,32 @@ tsQuery
665669tsQuery lang x = UnsafeExpression $
666670 "to_tsquery" <> parenthesized (commaSeparated [singleQuotedUtf8 lang, renderExpression x])
667671
668−-- |PostgreSQL функция ts_query без языка.
669672tsQuery'
670673 :: Expression schema from grouping params ('NotNull 'PGtext)
671674 -> Expression schema from grouping params ('NotNull 'PGtext)
672675tsQuery' x = UnsafeExpression $
673676 "to_tsquery" <> parenthesized (renderExpression x)
674677
675−-- |PostgreSQL функция array_to_string
676678arrayToText
677679 :: Expression schema from grouping params ('NotNull ('PGvararray ('NotNull 'PGtext)))
678680 -> Expression schema from grouping params ('NotNull 'PGtext)
679681arrayToText x = UnsafeExpression $
680682 "array_to_string" <> parenthesized (commaSeparated [renderExpression x, "' '"])
681683
682−-- |PostgreSQL оператор @@
683684(@@)
684685 :: Expression schema from grouping params (nullity0 'PGtext)
685686 -> Expression schema from grouping params (nullity1 'PGtext)
686687 -> Expression schema from grouping params (nullity2 'PGbool)
687688(@@) = unsafeBinaryOp "@@"
688689
689−-- |Пробел.
690690space :: Expression schema from grouping params ('NotNull 'PGtext)
691691space = UnsafeExpression "' '"
692692
693−-- |Функция, переводящая список варажений текста в одно выражение текста через пробел.
694693textArrayToText
695694 :: [Expression schema from grouping params ('NotNull 'PGtext)]
696695 -> Expression schema from grouping params ('NotNull 'PGtext)
697696textArrayToText = fold . L.intersperse space
698697
699−-- |Запрос, создающий пользователя.
700698createUserQ :: Manipulation Schema (TuplePG UserCreation) (RowPG (Only UserId))
701699createUserQ = insertRow #users (
702700 Default `as` #userRowId :*
@@ -709,13 +707,12 @@ createUserQ = insertRow #users (
709707 OnConflictDoRaise
710708 (Returning (#userRowId `as` #fromOnly))
711709
712−-- |Запрос, удалющий пользователей, которые не подтвердили свой профиль.
713710removeUnverifiedUserQ :: Manipulation Schema (TuplePG (Only UserEmail)) '[]
714711removeUnverifiedUserQ = deleteFrom_ #users
715712 (#userRowEmail .== param @1 .&&
716713 (not_ . notNull $ #userRowIsValidated))
717714
718−-- |Запрос, создающий токен.
715+
719716createTokenQ :: Manipulation Schema (TuplePG Token) '[]
720717createTokenQ = insertRow_ #tokens (
721718 Set (param @1) `as` #tokenUserId :*
@@ -728,7 +725,6 @@ createTokenQ = insertRow_ #tokens (
728725 Set (param @8) `as` #tokenDeactivationCode
729726 )
730727
731−-- |Запрос, обновляющий токен.
732728updateTokenQ :: Manipulation Schema (TuplePG Token) '[]
733729updateTokenQ = update_ #tokens (
734730 Same `as` #tokenUserId :*
@@ -741,12 +737,10 @@ updateTokenQ = update_ #tokens (
741737 Set (param @8) `as` #tokenDeactivationCode)
742738 (#tokenUserId .== param @1 .&& #tokenValue .== param @2)
743739
744−-- |Запрос, удалющий токен.
745740deleteTokenQ :: Manipulation Schema (TuplePG (UserId, ByteString)) '[]
746741deleteTokenQ = deleteFrom_ #tokens
747742 (#tokenUserId .== param @1 .&& #tokenValue .== param @2)
748743
749−-- |Запрос, подтверждающий профиль пользователя.
750744validateUserQ :: Manipulation Schema (TuplePG (Only UserId)) '[]
751745validateUserQ = update_ #users (
752746 Same `as` #userRowId :*
@@ -758,26 +752,22 @@ validateUserQ = update_ #users (
758752 Set true `as` #userRowIsValidated)
759753 (#userRowId .== param @1)
760754
761−-- |Запрос, возвращающий токен.
762755getTokenQ :: Query Schema (TuplePG (UserId, ByteString)) (RowPG Token)
763756getTokenQ = selectStar (from (table #tokens) &
764757 where_ (#tokenUserId .== param @1 .&&
765758 #tokenValue .== param @2))
766759
767−-- |Запрос, возвращающий токен по хэшу кода активации.
768760getTokenActivationQ :: Query Schema (TuplePG (UserId, ByteString)) (RowPG Token)
769761getTokenActivationQ = selectStar (from (table #tokens) &
770762 where_ (#tokenUserId .== param @1 .&&
771763 #tokenActivationCode .== param @2))
772764
773−-- |Запрос, даективирующий токен.
774765deactivateTokenQ :: Manipulation Schema (TuplePG (UserId, ByteString)) (RowPG (Only Text))
775766deactivateTokenQ = deleteFrom #tokens
776767 (#tokenUserId .== param @1 .&&
777768 #tokenDeactivationCode .== param @2)
778769 (Returning (#tokenUserAgent `as` #fromOnly))
779770
780−-- |Запрос, возвращающий подтвержденный токен.
781771getVerifiedTokenQ :: Query Schema (TuplePG (UserId, ByteString)) (RowPG Token)
782772getVerifiedTokenQ = selectStar (from (table #tokens) &
783773 where_ (#tokenUserId .== param @1 .&&
@@ -785,17 +775,14 @@ getVerifiedTokenQ = selectStar (from (table #tokens) &
785775 isNull #tokenVerificationCode .&&
786776 currentTimestamp .< #tokenExpiryDate))
787777
788−-- |Запрос, даективирующий все токены для данного пользователя.
789778killAllTokensQ :: Manipulation Schema (TuplePG (Only UserId)) '[]
790779killAllTokensQ = deleteFrom_ #tokens
791780 (#tokenUserId .== param @1)
792781
793−-- |Запрос, удаляющий недействительные токены.
794782pruneDeadTokensQ :: Manipulation Schema '[] '[]
795783pruneDeadTokensQ = deleteFrom_ #tokens
796784 (#tokenExpiryDate .< currentTimestamp)
797785
798−-- |Запрос, удаляющий неактивированных пользователей.
799786pruneGhostUsersQ :: Manipulation Schema '[] '[]
800787pruneGhostUsersQ = deleteFrom_ #users
801788 ((not_ . in_ #userRowId $ select (#tokens ! #tokenUserId `as` #id) (from $ table #tokens)) .&&
@@ -811,17 +798,11 @@ instance HasValidatableText UserCreation where
811798 userCreationUserFaculty,
812799 userCreationUserEmail]
813800
814−-- |Объект для создания пользователя.
815801data UserCreation = UserCreation {
816− -- |Имя.
817802 userCreationFirstName :: Text,
818− -- |Отчество.
819803 userCreationMiddleName :: Text,
820− -- |Фамилия.
821804 userCreationLastName :: Text,
822− -- |Факультет.
823805 userCreationUserFaculty :: FacultyUrl,
824− -- |Адрес почты.
825806 userCreationUserEmail :: Text
826807} deriving (GHC.Generic, SOP.Generic, SOP.HasDatatypeInfo)
827808
@@ -838,62 +819,42 @@ instance FromJSON UserCreation where
838819 parseJSON = withObject "user creation" $ \e ->
839820 UserCreation <$> e .: "firstName" <*> e .: "middleName" <*> e .: "lastName" <*> e .: "faculty" <*> e .: "email"
840821
841−-- |Объект для обновления пользователя.
842822data UserUpdateRow = UserUpdateRow {
843− -- |Идентификатор пользователя.
844823 userUpdateRowId :: UserId,
845− -- |Имя.
846824 userUpdateRowFirstName :: Text,
847− -- |Отчество.
848825 userUpdateRowMiddleName :: Text,
849− -- |Фамилия.
850826 userUpdateRowLastName :: Text,
851− -- |Факультет.
852827 userUpdateRowUserFaculty :: FacultyUrl
853828} deriving (GHC.Generic, SOP.Generic, SOP.HasDatatypeInfo)
854829
855−-- |Объект для создания канала.
830+
856831data NamedChannelCreation = NamedChannelCreation {
857− -- |Владелец канала.
858832 namedChannelCreationOwner :: UserId,
859− -- |Название канала.
860833 namedChannelCreationName :: Text,
861− -- |Теги в канале.
862834 namedChannelCreationTags :: Vector Text,
863− -- |Люди в канале.
864835 namedChannelCreationPeopleIds :: Vector UserId
865836} deriving (GHC.Generic, SOP.Generic, SOP.HasDatatypeInfo)
866837
867−-- |Функция, добавлющая в структуру пользователя.
868838addUserToChannelCreate :: UserId -> NamedChannelCreationRequest -> NamedChannelCreation
869839addUserToChannelCreate uId (NamedChannelCreationRequest cName cTags cPeople) = NamedChannelCreation uId cName cTags cPeople
870840
871−-- |Полный объект канала.
872841data NamedChannelFull = NamedChannelFull {
873− -- |Идентификатор.
874842 namedChannelFullId :: NamedChannelId,
875− -- |Владелец.
876843 namedChannelFullOwner :: UserId,
877− -- |Название.
878844 namedChannelFullName :: Text,
879− -- |Теги.
880845 namedChannelFullTags :: Vector Text,
881− -- |пользователи.
882846 namedChannelFullPeopleIds :: Vector UserId
883847} deriving GHC.Generic
884848
885849instance SOP.Generic NamedChannelFull
886850instance SOP.HasDatatypeInfo NamedChannelFull
887851
888−-- |Добавляет в структуру пользователя.
889852addUserToChannelUpdate :: UserId -> NamedChannel UserId -> NamedChannelFull
890853addUserToChannelUpdate uId (NamedChannel cId cName cTags cPeople) = NamedChannelFull cId uId cName cTags cPeople
891854
892−-- |Убирает пользователя из структуры.
893855removeUserFromChannel :: NamedChannelFull -> NamedChannel UserId
894856removeUserFromChannel (NamedChannelFull cId _ cName cTags cPeople) = NamedChannel cId cName cTags cPeople
895857
896−-- |Возвращаает канал для данного человека.
897858getChannelForUser :: UserId -> NamedChannelId -> StaticPQ NamedChannelFull
898859getChannelForUser uId cId = do
899860 channel <- runQueryParams getChannelForUserQ (uId, cId) >>= firstRow
@@ -901,7 +862,7 @@ getChannelForUser uId cId = do
901862 (Just c) -> return c
902863 Nothing -> lift $ S.throwError S.err404
903864
904−-- |Проверяет, существует ли пользователь.
865+-- TODO: Reject bad requests. Should be binary.
905866verifyUsers :: [UserId] -> StaticPQ ()
906867verifyUsers uIds =
907868 case verifiedUserIdsQ uIds of
@@ -910,7 +871,6 @@ verifyUsers uIds =
910871 when (length us /= length uIds) $ lift $ S.throwError impossibleContent
911872 Nothing -> return ()
912873
913−-- |Удаляет групповую беседу.
914874deleteGroupChat :: GroupChatId -> StaticPQ ()
915875deleteGroupChat gId = do
916876 _ <- manipulateParams deleteGroupChatQ (Only gId)
@@ -925,7 +885,6 @@ deleteGroupChat gId = do
925885 (#messageStorageDestinationGroupId .== param @1)
926886
927887-- NOTE: Not transactional
928−-- |Создает пользователя.
929888createUser :: UserCreation -> StaticPQ UserId
930889createUser creation = do
931890 _ <- manipulateParams removeUnverifiedUserQ (Only $ userCreationUserEmail creation)
@@ -935,7 +894,6 @@ createUser creation = do
935894-- MARK: FrontEnd functions
936895
937896-- Nothing <=> no user
938−-- |Возвращаает посты от данного пользователя.
939897getPostsForUser
940898 :: Maybe PostId
941899 -> Limit
@@ -946,7 +904,6 @@ getPostsForUser pId lim dir uId = do
946904 postRows <- runQueryParams (getLastNPostsForUserQ lim dir) (pId, uId) >>= getRows
947905 wrapIntoResponse (fromMaybe [] . rowsToPosts $ postRows)
948906
949−-- |Возвращаает посты по идентификатором.
950907getPosts :: [PostId] -> StaticPQ (Maybe (ResponseWithUsers [Post]))
951908getPosts pId =
952909 case getPostsByIdQ pId of
@@ -955,7 +912,6 @@ getPosts pId =
955912 rowsToPosts postRows `liftMaybe` wrapIntoResponse
956913 Nothing -> return Nothing
957914
958−-- |Возвращает последние посты.
959915getLastPosts
960916 :: Maybe PostId
961917 -> Limit
@@ -965,29 +921,24 @@ getLastPosts pId lim dir = do
965921 postRows <- runQueryParams (getLastPostsQ id lim dir) (Only pId) >>= getRows
966922 rowsToPosts postRows `liftMaybe` wrapIntoResponse
967923
968−-- |Возвращает пользователя по адресу почты.
969924getUserWithEmail :: UserEmail -> StaticPQ (Maybe (User FacultyUrl))
970925getUserWithEmail email = runQueryParams getUserWithEmailQ (Only email) >>= firstRow
971926
972−-- |возвращает пользователей по идентификаторам.
973927getUsers :: [UserId] -> StaticPQ (Maybe [User Faculty])
974928getUsers ids = getUsersQ ids `liftMaybe` (fmap (Just . map rowToUser) . (runQuery >=> getRows))
975929
976−-- |Возвращает всех пользователей.
977930getAllUsers :: StaticPQ [User Faculty]
978931getAllUsers = fmap rowToUser <$> (runQuery getAllUsersQ >>= getRows)
979932
980−-- |Публичует пост.
981933publishPost :: UserId -> PostCreation -> StaticPQ PostId
982934publishPost uId pc = commitedTransactionallyUpdate $ do
983935 pId' <- manipulateParams createPostRowQ (uId, postCreationTags pc) >>= firstRow
984936 case pId' of
985937 (Just (Only pId)) -> do
986− traversePrepared_ createPostElementRowsQ $ elementsToRows pId (postCreationBody pc)
938+ traversePrepared_ createPostElementRowsQ $ elementsToRows pId (map stripPostElement $ postCreationBody pc)
987939 return pId
988940 _ -> lift $ S.throwError S.err404
989941
990−-- |Создает канал.
991942createNewChannel :: UserId -> NamedChannelCreationRequest -> StaticPQ (Maybe NamedChannelId)
992943createNewChannel uId req = commitedTransactionallyUpdate $ do
993944 let uIds = toList $ namedChannelCreationRequestPeopleIds req
@@ -995,11 +946,9 @@ createNewChannel uId req = commitedTransactionallyUpdate $ do
995946 cId <- manipulateParams createNamedChannelQ (addUserToChannelCreate uId (req {namedChannelCreationRequestPeopleIds = fromList uIds})) >>= firstRow
996947 return $ fmap fromOnly cId
997948
998−-- |Возвращает канал для данного пользователя.
999949channelCountForUser :: UserId -> StaticPQ Int64
1000950channelCountForUser uId = (fromMaybe 0 . fmap fromOnly) <$> (runQueryParams countChannelsQ (Only uId) >>= firstRow)
1001951
1002−-- |Обновляет канал.
1003952updateChannel :: UserId -> NamedChannel UserId -> StaticPQ ()
1004953updateChannel uId req = do
1005954 let uIds = namedChannelPeopleIds req
@@ -1008,21 +957,17 @@ updateChannel uId req = do
1008957 _ <- commitedTransactionallyUpdate $ manipulateParams updateNamedChannelQ $ addUserToChannelUpdate uId (req {namedChannelPeopleIds = uIds})
1009958 return ()
1010959
1011−-- |Возвращает факультет.
1012960getFaculty :: Text -> StaticPQ Faculty
1013961getFaculty t = runQueryParams getFacultyQ (Only t) >>= firstRow >>= fromMaybe404
1014962
1015−-- |Проверяет, является ли данный факультет валидным.
1016963isValidFaculty :: FacultyUrl -> StaticPQ Bool
1017964isValidFaculty url = do
1018965 (faculty :: Maybe Faculty) <- runQueryParams getFacultyQ (Only url) >>= firstRow
1019966 return $ isJust faculty
1020967
1021−-- |Обновляет факультет.
1022968updateFaculty :: Faculty -> StaticPQ ()
1023969updateFaculty fac = void $ manipulateParams updateFacultyQ fac
1024970
1025−-- |Возвращает посты в канале.
1026971getChannelPosts
1027972 :: UserId
1028973 -> Maybe PostId
@@ -1041,7 +986,6 @@ getChannelPosts uId pId lim dir cId = do
1041986 >>= getRows
1042987 fmap (fromMaybe $ ResponseWithUsers mempty mempty) $ rowsToPosts postRows `liftMaybe` wrapIntoResponse
1043988
1044−-- |Возвращает почты в анонимном кнаале.
1045989getAnonymousChannelPosts
1046990 :: Maybe PostId
1047991 -> Limit
@@ -1052,23 +996,19 @@ getAnonymousChannelPosts pId lim dir (AnonymousChannel tags people) = do
1052996 postRows <- runQueryParams (getChannelPostsQ lim dir people tags) (Only pId) >>= getRows
1053997 fmap (fromMaybe $ ResponseWithUsers mempty mempty) $ rowsToPosts postRows `liftMaybe` wrapIntoResponse
1054998
1055−-- |Возвращает все каналы.
1056999getAllChannels :: UserId -> StaticPQ [NamedChannel UserId]
10571000getAllChannels uId = fmap (map removeUserFromChannel) $
10581001 runQueryParams getAllChannelsForUserQ (Only uId) >>= getRows
10591002
1060−-- |Удаляет именованный канал.
10611003deleteNamedChannel :: UserId -> NamedChannelId -> StaticPQ ()
10621004deleteNamedChannel uId cId = do
10631005 _ <- getChannelForUser uId cId
10641006 _ <- commitedTransactionallyUpdate $ manipulateParams deleteNamedChannelQ (Only cId)
10651007 return ()
10661008
1067−-- |Возвращает теги.
10681009getTags :: Limit -> StaticPQ [String]
10691010getTags lim = map fromOnly <$> (runQuery (getNpopularTagsQ lim) >>= getRows)
10701011
1071−-- |Возвращает диалоги.
10721012getDialogs
10731013 :: UserId
10741014 -> Maybe MessageId
@@ -1079,7 +1019,6 @@ getDialogs uId mId lim dir = do
10791019 resp <- runQueryParams (getChatsQ lim dir) (uId, Just $ show uId, mId) >>= getRows
10801020 (>>= fromMaybe500) $ (responseToDialogs uId resp `liftMaybe` wrapIntoResponse)
10811021
1082−-- |Возвращает сообщения в диалоге.
10831022getMessagesInUserChat
10841023 :: UserId
10851024 -> UserId
@@ -1091,7 +1030,6 @@ getMessagesInUserChat selfId uId mId lim dir = do
10911030 resp <- runQueryParams (getMessagesQ lim dir) (selfId, uId, mId) >>= getRows
10921031 fromMaybe500 . sequence . map restoreMessage $ resp
10931032
1094−-- |Возвращает сообщения в групповой беседе.
10951033getMessagesInGroupChat
10961034 :: UserId
10971035 -> GroupChatId
@@ -1104,21 +1042,19 @@ getMessagesInGroupChat selfId gId mId lim dir = do
11041042 resp <- runQueryParams (getGroupMessagesQ lim dir) (gId, mId) >>= getRows
11051043 return . catMaybes . map restoreMessage $ resp
11061044
1107−-- |Отправляет сообщение.
11081045sendMessage :: UserId -> MessageCreation -> StaticPQ MessageId
1109−sendMessage selfId (MessageCreation (Just gId) uId@Nothing body) = do
1046+sendMessage selfId (MessageCreation (Just gId) uId@Nothing (Jsonb body)) = do
11101047 _ <- getGroupChatForUser selfId gId
1111− (Only mId) <- manipulateParams createMessageQ (selfId, Just gId, uId, body)
1048+ (Only mId) <- manipulateParams createMessageQ (selfId, Just gId, uId, Jsonb $ stripPostElement body)
11121049 >>= firstRow >>= fromMaybe500
11131050 return mId
1114−sendMessage selfId (MessageCreation gId@Nothing (Just uId) body) = do
1051+sendMessage selfId (MessageCreation gId@Nothing (Just uId) (Jsonb body)) = do
11151052 verifyUsers [uId]
1116− (Only mId) <- manipulateParams createMessageQ (selfId, gId, Just uId, body)
1053+ (Only mId) <- manipulateParams createMessageQ (selfId, gId, Just uId, Jsonb $ stripPostElement body)
11171054 >>= firstRow >>= fromMaybe500
11181055 return mId
11191056sendMessage _ _ = lift $ S.throwError S.err400
11201057
1121−-- |Создает групповую беседу.
11221058createGroupChat :: UserId -> GroupChatCreation -> StaticPQ GroupChatId
11231059createGroupChat uId (GroupChatCreation (Jsonb chatUsers) name) = do
11241060 verifyUsers . M.keys $ chatUsers
@@ -1129,7 +1065,6 @@ createGroupChat uId (GroupChatCreation (Jsonb chatUsers) name) = do
11291065 _ <- manipulateParams createPhantomMessageQ (Only chatId)
11301066 return chatId
11311067
1132−-- |Обновляет групповую беседу.
11331068updateGroupChat :: UserId -> GroupChat -> StaticPQ ()
11341069updateGroupChat uId (GroupChat gId (Jsonb perms) name) = do
11351070 verifyUsers . M.keys $ perms
@@ -1140,7 +1075,6 @@ updateGroupChat uId (GroupChat gId (Jsonb perms) name) = do
11401075 let newPerms = M.insert uId userPerm perms
11411076 void $ manipulateParams updateGroupChatQ (GroupChat gId (Jsonb newPerms) name)
11421077
1143−-- |Удаляет пользователя из беседы.
11441078leaveGroupChat :: UserId -> GroupChatId -> StaticPQ ()
11451079leaveGroupChat uId gId = commitedTransactionallyUpdate $ do
11461080 gChat@(GroupChat _ (Jsonb perms) _) <- getGroupChatForUser uId gId
@@ -1149,7 +1083,6 @@ leaveGroupChat uId gId = commitedTransactionallyUpdate $ do
11491083 then deleteGroupChat gId
11501084 else void $ manipulateParams updateGroupChatQ gChat{groupChatUsers = Jsonb newPerms}
11511085
1152−-- |Возвращает беседу для пользователя.
11531086getGroupChatForUser :: UserId -> GroupChatId -> StaticPQ GroupChat
11541087getGroupChatForUser uId gId = do
11551088 chat <- runQueryParams getGroupChatForUserQ (show uId, gId) >>= firstRow
@@ -1157,18 +1090,15 @@ getGroupChatForUser uId gId = do
11571090 (Just c) -> return c
11581091 Nothing -> lift $ S.throwError S.err404
11591092
1160−-- |Проверяет, является ли данная беседа валидной для данного пользователя.
11611093groupChatIsValidForUser :: UserId -> GroupChatId -> StaticPQ Bool
11621094groupChatIsValidForUser uId gId = do
11631095 (chat :: Maybe GroupChat) <- runQueryParams getGroupChatForUserQ (show uId, gId) >>= firstRow
11641096 return $ isJust chat
11651097
1166−-- |Возвращает каналы по поисковой строке.
11671098getFacultyFromQuery :: T.Text -> StaticPQ [Faculty]
11681099getFacultyFromQuery query =
11691100 runQueryParams getFacultySearchResultQ (Only . queryFromTextAbbr $ query) >>= getRows
11701101
1171−-- |Ищет пользователей по строке.
11721102searchUsers :: T.Text -> StaticPQ [User Faculty]
11731103searchUsers query = do
11741104 unless (validateText query) $ lift $ throwError lengthExceeded
@@ -1176,45 +1106,37 @@ searchUsers query = do
11761106 then return []
11771107 else map rowToUser <$> (runQueryParams searchUsersQ (Only . queryFromText $ query) >>= getRows)
11781108
1179−-- |Ищет теги по запосу.
11801109searchTags :: T.Text -> StaticPQ [Text]
11811110searchTags "" = return []
11821111searchTags query = map fromOnly <$>
11831112 (runQueryParams searchTagsQ
11841113 (Only . (<> ":*") . T.strip $ query) >>= getRows)
11851114
1186−-- |Создает токен.
11871115createToken :: Token -> StaticPQ ()
11881116createToken token = void $ manipulateParams createTokenQ token
11891117
1190−-- |Деактивирует все токены для пользователя.
11911118killAllTokens :: UserId -> StaticPQ ()
11921119killAllTokens = void . manipulateParams killAllTokensQ . Only
11931120
1194−-- |Удаляет устаревшую информацию про авторизацию.
11951121pruneAuth :: StaticPQ ()
11961122pruneAuth = do
11971123 _ <- commitedTransactionallyUpdate . manipulate $ pruneDeadTokensQ
11981124 _ <- commitedTransactionallyUpdate . manipulate $ pruneGhostUsersQ
11991125 return ()
12001126
1201−-- |Осуществляет поиск по каналам.
12021127searchChannels :: UserId -> Text -> StaticPQ [NamedChannel UserId]
12031128searchChannels uId query = fmap (map removeUserFromChannel) $
12041129 runQueryParams searchChannelsForUserQ (uId, queryFromText query) >>= getRows
12051130
12061131-- NOTE: Not transactional
1207−-- |Проверяет, является ли токен валидным.
12081132validateToken :: Token -> StaticPQ ()
12091133validateToken token = do
12101134 void $ manipulateParams updateTokenQ token{tokenVerificationCode = Nothing, tokenActivationCode = Nothing}
12111135 void $ manipulateParams validateUserQ $ Only $ tokenUserId token
12121136
1213−-- |Даективирует токен.
12141137invalidateToken :: UserId -> ByteString -> StaticPQ ()
12151138invalidateToken uId bs = void . manipulateParams deleteTokenQ $ (uId, bs)
12161139
1217−-- |Пытается активировать токен с помощью кода.
12181140tryVerifyToken :: UserId -> ByteString -> Int -> StaticPQ (Maybe Token)
12191141tryVerifyToken uId tokenData code = commitedTransactionallyUpdate $ do
12201142 token' <- runQueryParams getTokenQ (uId, hash tokenData) >>= firstRow
@@ -1232,7 +1154,6 @@ tryVerifyToken uId tokenData code = commitedTransactionallyUpdate $ do
12321154 _ <- manipulateParams updateTokenQ newToken
12331155 return Nothing
12341156
1235−-- |Пытается активировать с помощью ключа активации.
12361157tryActivateToken :: UserId -> ByteString -> StaticPQ (Maybe Token)
12371158tryActivateToken uId activationData = do
12381159 let hData = hash activationData
@@ -1244,21 +1165,17 @@ tryActivateToken uId activationData = do
12441165 then commitedTransactionallyUpdate (validateToken token) >> (return $ Just token)
12451166 else return Nothing
12461167
1247−-- |Деактивирует токен.
12481168deactivateToken :: UserId -> ByteString -> StaticPQ (Maybe Text)
12491169deactivateToken uId dData = fmap fromOnly <$> (manipulateParams deactivateTokenQ (uId, hash dData) >>= firstRow)
12501170
1251−-- |Возвращает активированный токен.
12521171getVerifiedToken :: UserId -> ByteString -> StaticPQ (Maybe Token)
12531172getVerifiedToken uId tokenData = runQueryParams getVerifiedTokenQ (uId, hash tokenData) >>= firstRow
12541173
1255−-- |Обновляет пользователя.
12561174updateUser :: (UserUpdateRow) -> StaticPQ (Maybe UserId)
12571175updateUser user = fmap fromOnly <$> (manipulateParams updateUserQ (normalizeUser user) >>= firstRow)
12581176
12591177-- MARK: Utils
12601178
1261−-- |Нормализует поля пользователя.
12621179normalizeUser :: UserUpdateRow -> UserUpdateRow
12631180normalizeUser UserUpdateRow{..} = UserUpdateRow {
12641181 userUpdateRowId = userUpdateRowId,
@@ -1268,39 +1185,23 @@ normalizeUser UserUpdateRow{..} = UserUpdateRow {
12681185 userUpdateRowUserFaculty = T.toLower . T.strip $ userUpdateRowUserFaculty
12691186}
12701187
1271−-- |Объект пользователя для ответов с базы данных.
12721188data UserRow = UserRow {
1273− -- |Идентификатор пользователя.
12741189 userRowId :: UserId,
1275− -- |Имя.
12761190 userRowFirstName :: Text,
1277− -- |Отчество.
12781191 userRowMiddleName :: Text,
1279− -- |Фамилия.
12801192 userRowLastName :: Text,
1281− -- |Факультет.
12821193 userRowFacultyUrl :: FacultyUrl,
1283− -- |Почта.
12841194 userRowEmail :: Text,
1285− -- |Был ли профиль подтвержден через почту.
12861195 userRowIsValidated :: Bool,
1287− -- |Название факультета.
12881196 userRowFacultyName :: T.Text,
1289− -- |Адрес сайта факультета.
12901197 userRowFacultyURL :: FacultyUrl,
1291− -- |Вспомогательная информация о факультете.
12921198 userRowFacultyPath :: T.Text,
1293− -- |Кампус.
12941199 userRowFacultyCampusName :: T.Text,
1295− -- |Код Кампуса.
12961200 userRowFacultyCampusCode :: T.Text,
1297− -- |Теги департамента.
12981201 userRowFacultyTags :: V.Vector T.Text,
1299− -- |АДрес департамента.
13001202 userRowFacultyAddress :: T.Text
13011203} deriving (GHC.Generic, SOP.Generic, SOP.HasDatatypeInfo)
13021204
1303−-- |Функция, переводящая ответ с базы данных в пользователя.
13041205rowToUser :: UserRow -> User Faculty
13051206rowToUser UserRow{..} = User {
13061207 userId = userRowId,
@@ -1319,7 +1220,6 @@ rowToUser UserRow{..} = User {
13191220 userEmail = userRowEmail
13201221 }
13211222
1322−-- |Переводит строку в запрос с учетом аббревиатур.
13231223queryFromTextAbbr :: Text -> Text
13241224queryFromTextAbbr = T.unwords . L.intersperse "&" . map processTerm . filter (not . T.null) . T.split (not . isAlphaNum)
13251225 where
@@ -1330,14 +1230,12 @@ queryFromTextAbbr = T.unwords . L.intersperse "&" . map processTerm . filter (no
13301230 else mempty
13311231 ) <> ")"
13321232
1333−-- |Переводит строку в запорс.
13341233queryFromText :: Text -> Text
13351234queryFromText = T.unwords . L.intersperse "&" . map processTerm . filter (not . T.null) . T.split (not . isPrint)
13361235 where
13371236 processTerm :: Text -> Text
13381237 processTerm t = t <> ":*"
13391238
1340−-- |Перевод направление в оператор.
13411239directionToOperator
13421240 :: P.PaginationDirection
13431241 -> (ConditionOp schema0 from0 grouping0 params0 nullity0 nullity1 (ty :: PGType),
@@ -1350,7 +1248,6 @@ foldMaybe [] = Just []
13501248foldMaybe (Nothing : _) = Nothing
13511249foldMaybe (Just x : xs) = (x :) <$> foldMaybe xs
13521250
1353−-- |переводит элементы поста с базы данных в объект поста.
13541251rowsToPosts :: [PostRowResponse] -> Maybe [Post]
13551252rowsToPosts = foldMaybe . map rowsToPost . L.groupBy ((==) `on` postRowId)
13561253
@@ -1364,15 +1261,11 @@ idsToColumn :: [Int64] -> Maybe (Query schema params '["id" ::: 'NotNull 'PGint8
13641261idsToColumn [] = Nothing
13651262idsToColumn (i:ii) = Just $ values (unsafeIntToExpr i `as` #id) $ map ((`as` #id) . unsafeIntToExpr) ii
13661263
1367−-- |Небезопасное переведение числа в SQL выражение.
13681264unsafeIntToExpr :: Int64 -> Expression schema from grouping params ty
13691265unsafeIntToExpr = UnsafeExpression . pack . show
13701266
1371−-- |Ответ сервера с пользователями.
13721267data ResponseWithUsers r = ResponseWithUsers {
1373− -- |Тело ответа.
13741268 response :: r,
1375− -- |Пользователи.
13761269 users :: M.Map UserId (User Faculty)
13771270} deriving (Generic)
13781271
@@ -1403,7 +1296,6 @@ instance (Foldable t, HasUsers r) => HasUsers (t r) where
14031296instance HasUsers Post where
14041297 userSet = Set.singleton . postAuthorId
14051298
1406−-- |Оборачивает ответ в пользователей.
14071299wrapIntoUsers :: r -> Set.Set UserId -> StaticPQ (Maybe (ResponseWithUsers r))
14081300wrapIntoUsers r us
14091301 | Set.null us = return . Just $ ResponseWithUsers r M.empty