{-# LANGUAGE TupleSections #-}
module Docs.Hasql.Transactions
( now
, getTreeRevision
, existsTreeRevision
, getTree
, createDocument
, createTextElement
, getTextElementRevision
, existsTextRevision
, updateTextRevision
, createTextRevision
, putTree
, createTreeRevision
, existsDocument
, existsTextElement
, getLatestTextRevisionID
, isTextElementInDocument
, hasPermission
, isGroupAdmin
, createComment
, existsComment
, resolveComment
, createReply
, logMessage
, updateLatestTitle
, getTextElement
, createDraftTextRevision
, getDraftTextRevision
, deleteDraftTextRevision
, getRevisionKey
, getDocument
, getDocuments
, getDocumentsBy
) where
import qualified Crypto.Hash.SHA1 as SHA1
import Hasql.Transaction (Transaction, statement)
import Control.Monad (guard)
import Data.Functor ((<&>))
import qualified Data.Set as Set
import Data.Text (Text)
import Data.Time (UTCTime)
import Data.Vector (Vector)
import qualified Data.Vector as Vector
import UserManagement.DocumentPermission (Permission)
import UserManagement.Group (GroupID)
import UserManagement.User (UserID)
import Data.Aeson (ToJSON)
import Docs.Comment (Comment, CommentAnchor, CommentID, CommentRef, Message)
import qualified Docs.Comment as Comment
import Docs.Document (Document, DocumentID)
import Docs.Hash
( Hash (Hash)
, Hashable (..)
)
import qualified Docs.Hasql.Statements as Statements
import Docs.Hasql.TreeEdge
( TreeEdge (TreeEdge)
, TreeEdgeChild (TreeEdgeToNode, TreeEdgeToTextElement)
, TreeEdgeChildRef (..)
)
import qualified Docs.Hasql.TreeEdge as TreeEdge
import Docs.Revision (RevisionKey, RevisionRef (RevisionRef))
import Docs.TextElement
( TextElement
, TextElementID
, TextElementKind
, TextElementRef (..)
, TextElementType
)
import Docs.TextRevision
( DraftRevision
, TextElementRevision
, TextRevision
, TextRevisionID
, TextRevisionRef
)
import Docs.Tree (Node (Node), NodeHeader, Tree (Leaf, Tree))
import qualified Docs.Tree as Tree
import Docs.TreeRevision (TreeRevision, TreeRevisionRef (TreeRevisionRef))
import qualified Docs.TreeRevision as TreeRevision
import Logging.Logs (LogMessage, Scope, Severity)
now :: Transaction UTCTime
now :: Transaction UTCTime
now = () -> Statement () UTCTime -> Transaction UTCTime
forall a b. a -> Statement a b -> Transaction b
statement () Statement () UTCTime
Statements.now
getTextElementRevision
:: TextRevisionRef
-> Transaction (Maybe TextElementRevision)
getTextElementRevision :: TextRevisionRef -> Transaction (Maybe TextElementRevision)
getTextElementRevision TextRevisionRef
ref = do
(TextRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction (Maybe TextElementRevision)
textElementRevision <- TextRevisionRef
-> Statement
TextRevisionRef
((TextRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction (Maybe TextElementRevision))
-> Transaction
((TextRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction (Maybe TextElementRevision))
forall a b. a -> Statement a b -> Transaction b
statement TextRevisionRef
ref Statement
TextRevisionRef
((TextRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction (Maybe TextElementRevision))
forall (m :: * -> *).
Monad m =>
Statement
TextRevisionRef
((TextRevisionID -> m (Vector CommentAnchor))
-> m (Maybe TextElementRevision))
Statements.getTextElementRevision
(TextRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction (Maybe TextElementRevision)
textElementRevision ((TextRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction (Maybe TextElementRevision))
-> (TextRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction (Maybe TextElementRevision)
forall a b. (a -> b) -> a -> b
$ (TextRevisionID
-> Statement TextRevisionID (Vector CommentAnchor)
-> Transaction (Vector CommentAnchor))
-> Statement TextRevisionID (Vector CommentAnchor)
-> TextRevisionID
-> Transaction (Vector CommentAnchor)
forall a b c. (a -> b -> c) -> b -> a -> c
flip TextRevisionID
-> Statement TextRevisionID (Vector CommentAnchor)
-> Transaction (Vector CommentAnchor)
forall a b. a -> Statement a b -> Transaction b
statement Statement TextRevisionID (Vector CommentAnchor)
Statements.getCommentAnchors
createDocument :: Text -> GroupID -> UserID -> Transaction Document
createDocument :: Text -> GroupID -> UserID -> Transaction Document
createDocument Text
name GroupID
group UserID
user =
(Text, GroupID, UserID)
-> Statement (Text, GroupID, UserID) Document
-> Transaction Document
forall a b. a -> Statement a b -> Transaction b
statement (Text
name, GroupID
group, UserID
user) Statement (Text, GroupID, UserID) Document
Statements.createDocument
createTextElement
:: DocumentID
-> TextElementKind
-> TextElementType
-> Transaction TextElement
createTextElement :: DocumentID -> Text -> Text -> Transaction TextElement
createTextElement DocumentID
docID Text
kind Text
type_ = (DocumentID, Text, Text)
-> Statement (DocumentID, Text, Text) TextElement
-> Transaction TextElement
forall a b. a -> Statement a b -> Transaction b
statement (DocumentID
docID, Text
kind, Text
type_) Statement (DocumentID, Text, Text) TextElement
Statements.createTextElement
existsTextRevision :: TextRevisionRef -> Transaction Bool
existsTextRevision :: TextRevisionRef -> Transaction Bool
existsTextRevision = (TextRevisionRef
-> Statement TextRevisionRef Bool -> Transaction Bool)
-> Statement TextRevisionRef Bool
-> TextRevisionRef
-> Transaction Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip TextRevisionRef
-> Statement TextRevisionRef Bool -> Transaction Bool
forall a b. a -> Statement a b -> Transaction b
statement Statement TextRevisionRef Bool
Statements.existsTextRevision
existsDocument :: DocumentID -> Transaction Bool
existsDocument :: DocumentID -> Transaction Bool
existsDocument = (DocumentID -> Statement DocumentID Bool -> Transaction Bool)
-> Statement DocumentID Bool -> DocumentID -> Transaction Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip DocumentID -> Statement DocumentID Bool -> Transaction Bool
forall a b. a -> Statement a b -> Transaction b
statement Statement DocumentID Bool
Statements.existsDocument
existsTextElement :: TextElementRef -> Transaction Bool
existsTextElement :: TextElementRef -> Transaction Bool
existsTextElement = (TextElementRef
-> Statement TextElementRef Bool -> Transaction Bool)
-> Statement TextElementRef Bool
-> TextElementRef
-> Transaction Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip TextElementRef -> Statement TextElementRef Bool -> Transaction Bool
forall a b. a -> Statement a b -> Transaction b
statement Statement TextElementRef Bool
Statements.existsTextElement
getLatestTextRevisionID :: TextElementRef -> Transaction (Maybe TextRevisionID)
getLatestTextRevisionID :: TextElementRef -> Transaction (Maybe TextRevisionID)
getLatestTextRevisionID = (TextElementRef
-> Statement TextElementRef (Maybe TextRevisionID)
-> Transaction (Maybe TextRevisionID)
forall a b. a -> Statement a b -> Transaction b
`statement` Statement TextElementRef (Maybe TextRevisionID)
Statements.getLatestTextRevisionID)
updateTextRevision
:: TextRevisionID
-> Text
-> Vector CommentAnchor
-> Transaction TextRevision
updateTextRevision :: TextRevisionID
-> Text -> Vector CommentAnchor -> Transaction TextRevision
updateTextRevision TextRevisionID
rev Text
text Vector CommentAnchor
commentAnchors = do
(TextRevisionID, Vector CommentID)
-> Statement (TextRevisionID, Vector CommentID) ()
-> Transaction ()
forall a b. a -> Statement a b -> Transaction b
statement
(TextRevisionID
rev, CommentAnchor -> CommentID
Comment.comment (CommentAnchor -> CommentID)
-> Vector CommentAnchor -> Vector CommentID
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Vector CommentAnchor
commentAnchors)
Statement (TextRevisionID, Vector CommentID) ()
Statements.deleteCommentAnchorsExcept
(TextRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction TextRevision
textRevision <- (TextRevisionID, Text)
-> Statement
(TextRevisionID, Text)
((TextRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction TextRevision)
-> Transaction
((TextRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction TextRevision)
forall a b. a -> Statement a b -> Transaction b
statement (TextRevisionID
rev, Text
text) Statement
(TextRevisionID, Text)
((TextRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction TextRevision)
forall (m :: * -> *).
Monad m =>
Statement
(TextRevisionID, Text)
((TextRevisionID -> m (Vector CommentAnchor)) -> m TextRevision)
Statements.updateTextRevision
(TextRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction TextRevision
textRevision ((TextRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction TextRevision)
-> (TextRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction TextRevision
forall a b. (a -> b) -> a -> b
$
\TextRevisionID
newRev ->
((TextRevisionID, CommentAnchor) -> Transaction CommentAnchor)
-> Vector (TextRevisionID, CommentAnchor)
-> Transaction (Vector CommentAnchor)
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> Vector a -> m (Vector b)
mapM ((TextRevisionID, CommentAnchor)
-> Statement (TextRevisionID, CommentAnchor) CommentAnchor
-> Transaction CommentAnchor
forall a b. a -> Statement a b -> Transaction b
`statement` Statement (TextRevisionID, CommentAnchor) CommentAnchor
Statements.putCommentAnchor) ((TextRevisionID
newRev,) (CommentAnchor -> (TextRevisionID, CommentAnchor))
-> Vector CommentAnchor -> Vector (TextRevisionID, CommentAnchor)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Vector CommentAnchor
commentAnchors)
createTextRevision
:: UserID
-> TextElementRef
-> Text
-> Vector CommentAnchor
-> Transaction TextRevision
createTextRevision :: UserID
-> TextElementRef
-> Text
-> Vector CommentAnchor
-> Transaction TextRevision
createTextRevision UserID
userID (TextElementRef DocumentID
_ TextElementID
textID) Text
content Vector CommentAnchor
commentAnchors = do
(TextRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction TextRevision
textRevision <-
(TextElementID, UserID, Text)
-> Statement
(TextElementID, UserID, Text)
((TextRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction TextRevision)
-> Transaction
((TextRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction TextRevision)
forall a b. a -> Statement a b -> Transaction b
statement (TextElementID
textID, UserID
userID, Text
content) Statement
(TextElementID, UserID, Text)
((TextRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction TextRevision)
forall (m :: * -> *).
Monad m =>
Statement
(TextElementID, UserID, Text)
((TextRevisionID -> m (Vector CommentAnchor)) -> m TextRevision)
Statements.createTextRevision
(TextRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction TextRevision
textRevision ((TextRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction TextRevision)
-> (TextRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction TextRevision
forall a b. (a -> b) -> a -> b
$
\TextRevisionID
rev ->
((TextRevisionID, CommentAnchor) -> Transaction CommentAnchor)
-> Vector (TextRevisionID, CommentAnchor)
-> Transaction (Vector CommentAnchor)
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> Vector a -> m (Vector b)
mapM ((TextRevisionID, CommentAnchor)
-> Statement (TextRevisionID, CommentAnchor) CommentAnchor
-> Transaction CommentAnchor
forall a b. a -> Statement a b -> Transaction b
`statement` Statement (TextRevisionID, CommentAnchor) CommentAnchor
Statements.putCommentAnchor) ((TextRevisionID
rev,) (CommentAnchor -> (TextRevisionID, CommentAnchor))
-> Vector CommentAnchor -> Vector (TextRevisionID, CommentAnchor)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Vector CommentAnchor
commentAnchors)
isTextElementInDocument :: DocumentID -> Transaction (TextElementID -> Bool)
isTextElementInDocument :: DocumentID -> Transaction (TextElementID -> Bool)
isTextElementInDocument DocumentID
docID =
DocumentID
-> Statement DocumentID (Vector TextElementID)
-> Transaction (Vector TextElementID)
forall a b. a -> Statement a b -> Transaction b
statement DocumentID
docID Statement DocumentID (Vector TextElementID)
Statements.getTextElementIDsForDocument
Transaction (Vector TextElementID)
-> (Vector TextElementID -> TextElementID -> Bool)
-> Transaction (TextElementID -> Bool)
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> (TextElementID -> Set TextElementID -> Bool)
-> Set TextElementID -> TextElementID -> Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip TextElementID -> Set TextElementID -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member (Set TextElementID -> TextElementID -> Bool)
-> (Vector TextElementID -> Set TextElementID)
-> Vector TextElementID
-> TextElementID
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [TextElementID] -> Set TextElementID
forall a. Ord a => [a] -> Set a
Set.fromList ([TextElementID] -> Set TextElementID)
-> (Vector TextElementID -> [TextElementID])
-> Vector TextElementID
-> Set TextElementID
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector TextElementID -> [TextElementID]
forall a. Vector a -> [a]
Vector.toList
createTreeRevision
:: UserID
-> DocumentID
-> Node TextElementID
-> Transaction (TreeRevision TextElementID)
createTreeRevision :: UserID
-> DocumentID
-> Node TextElementID
-> Transaction (TreeRevision TextElementID)
createTreeRevision UserID
authorID DocumentID
docID Node TextElementID
rootNode = do
Hash
rootHash <- Node TextElementID -> Transaction Hash
putTree Node TextElementID
rootNode
Maybe (Hash, Node TextElementID -> TreeRevision TextElementID)
current <-
TreeRevisionRef
-> Statement
TreeRevisionRef
(Maybe (Hash, Node TextElementID -> TreeRevision TextElementID))
-> Transaction
(Maybe (Hash, Node TextElementID -> TreeRevision TextElementID))
forall a b. a -> Statement a b -> Transaction b
statement
(DocumentID -> TreeRevisionSelector -> TreeRevisionRef
TreeRevisionRef DocumentID
docID TreeRevisionSelector
TreeRevision.Latest)
Statement
TreeRevisionRef
(Maybe (Hash, Node TextElementID -> TreeRevision TextElementID))
forall a.
Statement TreeRevisionRef (Maybe (Hash, Node a -> TreeRevision a))
Statements.getTreeRevision
let keepCurrent :: Maybe (Node TextElementID -> TreeRevision TextElementID)
keepCurrent = Maybe (Hash, Node TextElementID -> TreeRevision TextElementID)
current Maybe (Hash, Node TextElementID -> TreeRevision TextElementID)
-> ((Hash, Node TextElementID -> TreeRevision TextElementID)
-> Maybe ())
-> Maybe ()
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> Maybe ())
-> ((Hash, Node TextElementID -> TreeRevision TextElementID)
-> Bool)
-> (Hash, Node TextElementID -> TreeRevision TextElementID)
-> Maybe ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Hash -> Hash -> Bool
forall a. Eq a => a -> a -> Bool
== Hash
rootHash) (Hash -> Bool)
-> ((Hash, Node TextElementID -> TreeRevision TextElementID)
-> Hash)
-> (Hash, Node TextElementID -> TreeRevision TextElementID)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Hash, Node TextElementID -> TreeRevision TextElementID) -> Hash
forall a b. (a, b) -> a
fst) Maybe ()
-> Maybe (Hash, Node TextElementID -> TreeRevision TextElementID)
-> Maybe (Hash, Node TextElementID -> TreeRevision TextElementID)
forall a b. Maybe a -> Maybe b -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Maybe (Hash, Node TextElementID -> TreeRevision TextElementID)
current Maybe (Hash, Node TextElementID -> TreeRevision TextElementID)
-> ((Hash, Node TextElementID -> TreeRevision TextElementID)
-> Node TextElementID -> TreeRevision TextElementID)
-> Maybe (Node TextElementID -> TreeRevision TextElementID)
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> (Hash, Node TextElementID -> TreeRevision TextElementID)
-> Node TextElementID -> TreeRevision TextElementID
forall a b. (a, b) -> b
snd
case Maybe (Node TextElementID -> TreeRevision TextElementID)
keepCurrent of
Just Node TextElementID -> TreeRevision TextElementID
currentRevision ->
TreeRevision TextElementID
-> Transaction (TreeRevision TextElementID)
forall a. a -> Transaction a
forall (m :: * -> *) a. Monad m => a -> m a
return (TreeRevision TextElementID
-> Transaction (TreeRevision TextElementID))
-> TreeRevision TextElementID
-> Transaction (TreeRevision TextElementID)
forall a b. (a -> b) -> a -> b
$ Node TextElementID -> TreeRevision TextElementID
currentRevision Node TextElementID
rootNode
Maybe (Node TextElementID -> TreeRevision TextElementID)
Nothing -> do
Node TextElementID -> TreeRevision TextElementID
revision <-
(DocumentID, UserID, Hash)
-> Statement
(DocumentID, UserID, Hash)
(Node TextElementID -> TreeRevision TextElementID)
-> Transaction (Node TextElementID -> TreeRevision TextElementID)
forall a b. a -> Statement a b -> Transaction b
statement
(DocumentID
docID, UserID
authorID, Hash
rootHash)
Statement
(DocumentID, UserID, Hash)
(Node TextElementID -> TreeRevision TextElementID)
forall a.
Statement (DocumentID, UserID, Hash) (Node a -> TreeRevision a)
Statements.putTreeRevision
TreeRevision TextElementID
-> Transaction (TreeRevision TextElementID)
forall a. a -> Transaction a
forall (m :: * -> *) a. Monad m => a -> m a
return (TreeRevision TextElementID
-> Transaction (TreeRevision TextElementID))
-> TreeRevision TextElementID
-> Transaction (TreeRevision TextElementID)
forall a b. (a -> b) -> a -> b
$ Node TextElementID -> TreeRevision TextElementID
revision Node TextElementID
rootNode
putTree :: Node TextElementID -> Transaction Hash
putTree :: Node TextElementID -> Transaction Hash
putTree (Node NodeHeader
metaData [Tree TextElementID]
children) = do
[TreeEdgeChildRef]
childRefs <- (Tree TextElementID -> Transaction TreeEdgeChildRef)
-> [Tree TextElementID] -> Transaction [TreeEdgeChildRef]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM Tree TextElementID -> Transaction TreeEdgeChildRef
putSubTree [Tree TextElementID]
children
let ownHash :: Hash
ownHash =
ByteString -> Hash
Hash (ByteString -> Hash) -> ByteString -> Hash
forall a b. (a -> b) -> a -> b
$
Ctx -> ByteString
SHA1.finalize (Ctx -> ByteString) -> Ctx -> ByteString
forall a b. (a -> b) -> a -> b
$
((TreeEdgeChildRef, Int) -> Ctx -> Ctx)
-> Ctx -> [(TreeEdgeChildRef, Int)] -> Ctx
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr
(\(TreeEdgeChildRef
child, Int
idx) -> (Ctx -> Int -> Ctx
forall a. Hashable a => Ctx -> a -> Ctx
`updateHash` Int
idx) (Ctx -> Ctx) -> (Ctx -> Ctx) -> Ctx -> Ctx
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Ctx -> TreeEdgeChildRef -> Ctx) -> TreeEdgeChildRef -> Ctx -> Ctx
forall a b c. (a -> b -> c) -> b -> a -> c
flip Ctx -> TreeEdgeChildRef -> Ctx
forall a. Hashable a => Ctx -> a -> Ctx
updateHash TreeEdgeChildRef
child)
(Ctx -> NodeHeader -> Ctx
forall a. Hashable a => Ctx -> a -> Ctx
updateHash Ctx
SHA1.init NodeHeader
metaData)
([TreeEdgeChildRef] -> [Int] -> [(TreeEdgeChildRef, Int)]
forall a b. [a] -> [b] -> [(a, b)]
zip [TreeEdgeChildRef]
childRefs [Int
0 :: Int ..])
(Hash, NodeHeader)
-> Statement (Hash, NodeHeader) () -> Transaction ()
forall a b. a -> Statement a b -> Transaction b
statement (Hash
ownHash, NodeHeader
metaData) Statement (Hash, NodeHeader) ()
Statements.putTreeNode
let toEdge :: TreeEdgeChildRef -> GroupID -> TreeEdge
toEdge TreeEdgeChildRef
ref GroupID
idx =
TreeEdge
{ parentHash :: Hash
TreeEdge.parentHash = Hash
ownHash
, position :: GroupID
TreeEdge.position = GroupID
idx
, child :: TreeEdgeChildRef
TreeEdge.child = TreeEdgeChildRef
ref
}
let edges :: [TreeEdge]
edges = (TreeEdgeChildRef -> GroupID -> TreeEdge)
-> [TreeEdgeChildRef] -> [GroupID] -> [TreeEdge]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith TreeEdgeChildRef -> GroupID -> TreeEdge
toEdge [TreeEdgeChildRef]
childRefs [GroupID
0 ..]
(TreeEdge -> Transaction ()) -> [TreeEdge] -> Transaction ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (TreeEdge -> Statement TreeEdge () -> Transaction ()
forall a b. a -> Statement a b -> Transaction b
`statement` Statement TreeEdge ()
Statements.putTreeEdge) [TreeEdge]
edges
Hash -> Transaction Hash
forall a. a -> Transaction a
forall (m :: * -> *) a. Monad m => a -> m a
return Hash
ownHash
where
putSubTree :: Tree TextElementID -> Transaction TreeEdgeChildRef
putSubTree :: Tree TextElementID -> Transaction TreeEdgeChildRef
putSubTree (Leaf TextElementID
id_) = TreeEdgeChildRef -> Transaction TreeEdgeChildRef
forall a. a -> Transaction a
forall (m :: * -> *) a. Monad m => a -> m a
return (TreeEdgeChildRef -> Transaction TreeEdgeChildRef)
-> TreeEdgeChildRef -> Transaction TreeEdgeChildRef
forall a b. (a -> b) -> a -> b
$ TextElementID -> TreeEdgeChildRef
TreeEdgeRefToTextElement TextElementID
id_
putSubTree (Tree Node TextElementID
node) = Node TextElementID -> Transaction Hash
putTree Node TextElementID
node Transaction Hash
-> (Hash -> TreeEdgeChildRef) -> Transaction TreeEdgeChildRef
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> Hash -> TreeEdgeChildRef
TreeEdgeRefToNode
hasPermission :: UserID -> DocumentID -> Permission -> Transaction Bool
hasPermission :: UserID -> DocumentID -> Permission -> Transaction Bool
hasPermission UserID
userID DocumentID
docID Permission
perms =
(UserID, DocumentID, Permission)
-> Statement (UserID, DocumentID, Permission) Bool
-> Transaction Bool
forall a b. a -> Statement a b -> Transaction b
statement (UserID
userID, DocumentID
docID, Permission
perms) Statement (UserID, DocumentID, Permission) Bool
Statements.hasPermission
isGroupAdmin :: UserID -> GroupID -> Transaction Bool
isGroupAdmin :: UserID -> GroupID -> Transaction Bool
isGroupAdmin UserID
userID GroupID
groupID =
(UserID, GroupID)
-> Statement (UserID, GroupID) Bool -> Transaction Bool
forall a b. a -> Statement a b -> Transaction b
statement (UserID
userID, GroupID
groupID) Statement (UserID, GroupID) Bool
Statements.isGroupAdmin
createComment :: UserID -> TextElementID -> Text -> Transaction Comment
UserID
userID TextElementID
textElemID Text
text =
(UserID, TextElementID, Text)
-> Statement (UserID, TextElementID, Text) Comment
-> Transaction Comment
forall a b. a -> Statement a b -> Transaction b
statement (UserID
userID, TextElementID
textElemID, Text
text) Statement (UserID, TextElementID, Text) Comment
Statements.createComment
existsComment :: CommentRef -> Transaction Bool
=
(CommentRef -> Statement CommentRef Bool -> Transaction Bool)
-> Statement CommentRef Bool -> CommentRef -> Transaction Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip CommentRef -> Statement CommentRef Bool -> Transaction Bool
forall a b. a -> Statement a b -> Transaction b
statement Statement CommentRef Bool
Statements.existsComment
resolveComment :: CommentID -> Transaction ()
=
(CommentID -> Statement CommentID () -> Transaction ())
-> Statement CommentID () -> CommentID -> Transaction ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip CommentID -> Statement CommentID () -> Transaction ()
forall a b. a -> Statement a b -> Transaction b
statement Statement CommentID ()
Statements.resolveComment
createReply :: UserID -> CommentID -> Text -> Transaction Message
createReply :: UserID -> CommentID -> Text -> Transaction Message
createReply UserID
userID CommentID
commentID = ((UserID, CommentID, Text)
-> Statement (UserID, CommentID, Text) Message
-> Transaction Message
forall a b. a -> Statement a b -> Transaction b
`statement` Statement (UserID, CommentID, Text) Message
Statements.createReply) ((UserID, CommentID, Text) -> Transaction Message)
-> (Text -> (UserID, CommentID, Text))
-> Text
-> Transaction Message
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UserID
userID,CommentID
commentID,)
logMessage
:: (ToJSON v)
=> Severity
-> Maybe UserID
-> Scope
-> v
-> Transaction LogMessage
logMessage :: forall v.
ToJSON v =>
Severity -> Maybe UserID -> Scope -> v -> Transaction LogMessage
logMessage Severity
severity Maybe UserID
source Scope
scope v
content =
(Severity, Maybe UserID, Scope, v)
-> Statement (Severity, Maybe UserID, Scope, v) LogMessage
-> Transaction LogMessage
forall a b. a -> Statement a b -> Transaction b
statement (Severity
severity, Maybe UserID
source, Scope
scope, v
content) Statement (Severity, Maybe UserID, Scope, v) LogMessage
forall v.
ToJSON v =>
Statement (Severity, Maybe UserID, Scope, v) LogMessage
Statements.logMessage
updateLatestTitle :: TextElementID -> Text -> Transaction ()
updateLatestTitle :: TextElementID -> Text -> Transaction ()
updateLatestTitle = ((TextElementID, Text) -> Transaction ())
-> TextElementID -> Text -> Transaction ()
forall a b c. ((a, b) -> c) -> a -> b -> c
curry ((TextElementID, Text)
-> Statement (TextElementID, Text) () -> Transaction ()
forall a b. a -> Statement a b -> Transaction b
`statement` Statement (TextElementID, Text) ()
Statements.updateLatestTitle)
getTextElement :: TextElementID -> Transaction (Maybe TextElement)
getTextElement :: TextElementID -> Transaction (Maybe TextElement)
getTextElement = (TextElementID
-> Statement TextElementID (Maybe TextElement)
-> Transaction (Maybe TextElement))
-> Statement TextElementID (Maybe TextElement)
-> TextElementID
-> Transaction (Maybe TextElement)
forall a b c. (a -> b -> c) -> b -> a -> c
flip TextElementID
-> Statement TextElementID (Maybe TextElement)
-> Transaction (Maybe TextElement)
forall a b. a -> Statement a b -> Transaction b
statement Statement TextElementID (Maybe TextElement)
Statements.getTextElement
createDraftTextRevision
:: UserID
-> TextElementRef
-> TextRevisionID
-> Text
-> Vector CommentAnchor
-> Transaction DraftRevision
createDraftTextRevision :: UserID
-> TextElementRef
-> TextRevisionID
-> Text
-> Vector CommentAnchor
-> Transaction DraftRevision
createDraftTextRevision UserID
userID (TextElementRef DocumentID
_ TextElementID
textID) TextRevisionID
basedOnRevision Text
content Vector CommentAnchor
commentAnchors = do
(DraftRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction DraftRevision
draftRevision <-
(TextElementID, TextRevisionID, UserID, Text)
-> Statement
(TextElementID, TextRevisionID, UserID, Text)
((DraftRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction DraftRevision)
-> Transaction
((DraftRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction DraftRevision)
forall a b. a -> Statement a b -> Transaction b
statement
(TextElementID
textID, TextRevisionID
basedOnRevision, UserID
userID, Text
content)
Statement
(TextElementID, TextRevisionID, UserID, Text)
((DraftRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction DraftRevision)
forall (m :: * -> *).
Monad m =>
Statement
(TextElementID, TextRevisionID, UserID, Text)
((DraftRevisionID -> m (Vector CommentAnchor)) -> m DraftRevision)
Statements.createDraftTextRevision
(DraftRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction DraftRevision
draftRevision ((DraftRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction DraftRevision)
-> (DraftRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction DraftRevision
forall a b. (a -> b) -> a -> b
$ \DraftRevisionID
draftId ->
((DraftRevisionID, Vector CommentAnchor) -> Transaction ())
-> [(DraftRevisionID, Vector CommentAnchor)] -> Transaction ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_
((DraftRevisionID, Vector CommentAnchor)
-> Statement (DraftRevisionID, Vector CommentAnchor) ()
-> Transaction ()
forall a b. a -> Statement a b -> Transaction b
`statement` Statement (DraftRevisionID, Vector CommentAnchor) ()
Statements.putDraftCommentAnchors)
[(DraftRevisionID
draftId, Vector CommentAnchor
commentAnchors)]
Transaction ()
-> Transaction (Vector CommentAnchor)
-> Transaction (Vector CommentAnchor)
forall a b. Transaction a -> Transaction b -> Transaction b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> DraftRevisionID
-> Statement DraftRevisionID (Vector CommentAnchor)
-> Transaction (Vector CommentAnchor)
forall a b. a -> Statement a b -> Transaction b
statement DraftRevisionID
draftId Statement DraftRevisionID (Vector CommentAnchor)
Statements.getDraftCommentAnchors
getDraftTextRevision
:: UserID -> TextElementRef -> Transaction (Maybe DraftRevision)
getDraftTextRevision :: UserID -> TextElementRef -> Transaction (Maybe DraftRevision)
getDraftTextRevision UserID
userID (TextElementRef DocumentID
_ TextElementID
textID) = do
(DraftRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction (Maybe DraftRevision)
draftGetter <- (TextElementID, UserID)
-> Statement
(TextElementID, UserID)
((DraftRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction (Maybe DraftRevision))
-> Transaction
((DraftRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction (Maybe DraftRevision))
forall a b. a -> Statement a b -> Transaction b
statement (TextElementID
textID, UserID
userID) Statement
(TextElementID, UserID)
((DraftRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction (Maybe DraftRevision))
forall (m :: * -> *).
Monad m =>
Statement
(TextElementID, UserID)
((DraftRevisionID -> m (Vector CommentAnchor))
-> m (Maybe DraftRevision))
Statements.getDraftTextRevision
(DraftRevisionID -> Transaction (Vector CommentAnchor))
-> Transaction (Maybe DraftRevision)
draftGetter (DraftRevisionID
-> Statement DraftRevisionID (Vector CommentAnchor)
-> Transaction (Vector CommentAnchor)
forall a b. a -> Statement a b -> Transaction b
`statement` Statement DraftRevisionID (Vector CommentAnchor)
Statements.getDraftCommentAnchors)
deleteDraftTextRevision :: UserID -> TextElementRef -> Transaction ()
deleteDraftTextRevision :: UserID -> TextElementRef -> Transaction ()
deleteDraftTextRevision UserID
userID (TextElementRef DocumentID
_ TextElementID
textID) =
(TextElementID, UserID)
-> Statement (TextElementID, UserID) () -> Transaction ()
forall a b. a -> Statement a b -> Transaction b
statement (TextElementID
textID, UserID
userID) Statement (TextElementID, UserID) ()
Statements.deleteDraftTextRevision
getTreeRevision
:: TreeRevisionRef
-> Transaction (Maybe (TreeRevision TextElement))
getTreeRevision :: TreeRevisionRef -> Transaction (Maybe (TreeRevision TextElement))
getTreeRevision TreeRevisionRef
ref = do
Maybe (Hash, Node TextElement -> TreeRevision TextElement)
revision <- Transaction
(Maybe (Hash, Node TextElement -> TreeRevision TextElement))
forall {a}. Transaction (Maybe (Hash, Node a -> TreeRevision a))
getRevision
case Maybe (Hash, Node TextElement -> TreeRevision TextElement)
revision of
Just (Hash
rootHash, Node TextElement -> TreeRevision TextElement
treeRevision) -> do
Node TextElement
root <- Hash -> Transaction (Node TextElement)
getTree Hash
rootHash
Maybe (TreeRevision TextElement)
-> Transaction (Maybe (TreeRevision TextElement))
forall a. a -> Transaction a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (TreeRevision TextElement)
-> Transaction (Maybe (TreeRevision TextElement)))
-> Maybe (TreeRevision TextElement)
-> Transaction (Maybe (TreeRevision TextElement))
forall a b. (a -> b) -> a -> b
$ TreeRevision TextElement -> Maybe (TreeRevision TextElement)
forall a. a -> Maybe a
Just (TreeRevision TextElement -> Maybe (TreeRevision TextElement))
-> TreeRevision TextElement -> Maybe (TreeRevision TextElement)
forall a b. (a -> b) -> a -> b
$ Node TextElement -> TreeRevision TextElement
treeRevision Node TextElement
root
Maybe (Hash, Node TextElement -> TreeRevision TextElement)
Nothing -> Maybe (TreeRevision TextElement)
-> Transaction (Maybe (TreeRevision TextElement))
forall a. a -> Transaction a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (TreeRevision TextElement)
forall a. Maybe a
Nothing
where
getRevision :: Transaction (Maybe (Hash, Node a -> TreeRevision a))
getRevision = TreeRevisionRef
-> Statement
TreeRevisionRef (Maybe (Hash, Node a -> TreeRevision a))
-> Transaction (Maybe (Hash, Node a -> TreeRevision a))
forall a b. a -> Statement a b -> Transaction b
statement TreeRevisionRef
ref Statement TreeRevisionRef (Maybe (Hash, Node a -> TreeRevision a))
forall a.
Statement TreeRevisionRef (Maybe (Hash, Node a -> TreeRevision a))
Statements.getTreeRevision
getTree :: Hash -> Transaction (Node TextElement)
getTree :: Hash -> Transaction (Node TextElement)
getTree Hash
rootHash = do
NodeHeader
rootHeader <- Hash -> Statement Hash NodeHeader -> Transaction NodeHeader
forall a b. a -> Statement a b -> Transaction b
statement Hash
rootHash Statement Hash NodeHeader
Statements.getTreeNode
Hash -> NodeHeader -> Transaction (Node TextElement)
fromHeader Hash
rootHash NodeHeader
rootHeader
where
fromHeader :: Hash -> NodeHeader -> Transaction (Node TextElement)
fromHeader :: Hash -> NodeHeader -> Transaction (Node TextElement)
fromHeader Hash
hash' NodeHeader
header = do
Vector TreeEdgeChild
children <- Hash
-> Statement Hash (Vector TreeEdgeChild)
-> Transaction (Vector TreeEdgeChild)
forall a b. a -> Statement a b -> Transaction b
statement Hash
hash' Statement Hash (Vector TreeEdgeChild)
Statements.getTreeEdgesByParent
Vector (Tree TextElement)
edges <- (TreeEdgeChild -> Transaction (Tree TextElement))
-> Vector TreeEdgeChild -> Transaction (Vector (Tree TextElement))
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> Vector a -> m (Vector b)
mapM TreeEdgeChild -> Transaction (Tree TextElement)
edgeSelector Vector TreeEdgeChild
children
Node TextElement -> Transaction (Node TextElement)
forall a. a -> Transaction a
forall (m :: * -> *) a. Monad m => a -> m a
return (Node TextElement -> Transaction (Node TextElement))
-> Node TextElement -> Transaction (Node TextElement)
forall a b. (a -> b) -> a -> b
$ NodeHeader -> [Tree TextElement] -> Node TextElement
forall a. NodeHeader -> [Tree a] -> Node a
Node NodeHeader
header ([Tree TextElement] -> Node TextElement)
-> [Tree TextElement] -> Node TextElement
forall a b. (a -> b) -> a -> b
$ Vector (Tree TextElement) -> [Tree TextElement]
forall a. Vector a -> [a]
Vector.toList Vector (Tree TextElement)
edges
edgeSelector :: TreeEdgeChild -> Transaction (Tree TextElement)
edgeSelector :: TreeEdgeChild -> Transaction (Tree TextElement)
edgeSelector TreeEdgeChild
edge =
case TreeEdgeChild
edge of
(TreeEdgeToTextElement TextElement
textElement) -> Tree TextElement -> Transaction (Tree TextElement)
forall a. a -> Transaction a
forall (m :: * -> *) a. Monad m => a -> m a
return (Tree TextElement -> Transaction (Tree TextElement))
-> Tree TextElement -> Transaction (Tree TextElement)
forall a b. (a -> b) -> a -> b
$ TextElement -> Tree TextElement
forall a. a -> Tree a
Tree.Leaf TextElement
textElement
(TreeEdgeToNode Hash
hash' NodeHeader
header) -> Hash -> NodeHeader -> Transaction (Node TextElement)
fromHeader Hash
hash' NodeHeader
header Transaction (Node TextElement)
-> (Node TextElement -> Tree TextElement)
-> Transaction (Tree TextElement)
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> Node TextElement -> Tree TextElement
forall a. Node a -> Tree a
Tree.Tree
existsTreeRevision :: TreeRevisionRef -> Transaction Bool
existsTreeRevision :: TreeRevisionRef -> Transaction Bool
existsTreeRevision = (TreeRevisionRef
-> Statement TreeRevisionRef Bool -> Transaction Bool)
-> Statement TreeRevisionRef Bool
-> TreeRevisionRef
-> Transaction Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip TreeRevisionRef
-> Statement TreeRevisionRef Bool -> Transaction Bool
forall a b. a -> Statement a b -> Transaction b
statement Statement TreeRevisionRef Bool
Statements.existsTreeRevision
getRevisionKey :: RevisionRef -> Transaction (Maybe RevisionKey)
getRevisionKey :: RevisionRef -> Transaction (Maybe RevisionKey)
getRevisionKey (RevisionRef DocumentID
docID RevisionSelector
revID) =
(DocumentID, RevisionSelector)
-> Statement (DocumentID, RevisionSelector) (Maybe RevisionKey)
-> Transaction (Maybe RevisionKey)
forall a b. a -> Statement a b -> Transaction b
statement (DocumentID
docID, RevisionSelector
revID) Statement (DocumentID, RevisionSelector) (Maybe RevisionKey)
Statements.getRevisionKey
getDocument :: DocumentID -> Transaction (Maybe Document)
getDocument :: DocumentID -> Transaction (Maybe Document)
getDocument = (DocumentID
-> Statement DocumentID (Maybe Document)
-> Transaction (Maybe Document)
forall a b. a -> Statement a b -> Transaction b
`statement` Statement DocumentID (Maybe Document)
Statements.getDocument)
getDocuments :: UserID -> Transaction (Vector Document)
getDocuments :: UserID -> Transaction (Vector Document)
getDocuments = (UserID
-> Statement UserID (Vector Document)
-> Transaction (Vector Document)
forall a b. a -> Statement a b -> Transaction b
`statement` Statement UserID (Vector Document)
Statements.getDocuments)
getDocumentsBy :: Maybe UserID -> Maybe GroupID -> Transaction (Vector Document)
getDocumentsBy :: Maybe UserID -> Maybe GroupID -> Transaction (Vector Document)
getDocumentsBy = ((Maybe UserID, Maybe GroupID) -> Transaction (Vector Document))
-> Maybe UserID -> Maybe GroupID -> Transaction (Vector Document)
forall a b c. ((a, b) -> c) -> a -> b -> c
curry ((Maybe UserID, Maybe GroupID)
-> Statement (Maybe UserID, Maybe GroupID) (Vector Document)
-> Transaction (Vector Document)
forall a b. a -> Statement a b -> Transaction b
`statement` Statement (Maybe UserID, Maybe GroupID) (Vector Document)
Statements.getDocumentsBy)