2 Module : Gargantext.Database.Action.Share
4 Copyright : (c) CNRS, 2017-Present
5 License : AGPL + CECILL v3
6 Maintainer : team@gargantext.org
7 Stability : experimental
13 {-# LANGUAGE Arrows #-}
15 module Gargantext.Database.Action.Share
18 import Control.Arrow (returnA)
19 import Control.Lens (view, (^.))
20 import Data.Maybe (catMaybes)
21 import Data.Text (Text)
22 import Gargantext.Core.Types.Individu (User(..))
23 import Gargantext.Database
24 import Gargantext.Database.Action.User (getUserId)
25 import Gargantext.Database.Admin.Config (hasNodeType, isInNodeTypes)
26 import Gargantext.Database.Admin.Types.Hyperdata (HyperdataAny(..))
27 import Gargantext.Database.Admin.Types.Node
28 -- import Gargantext.Database.Query.Join (leftJoin3')
29 import Gargantext.Database.Query.Table.Node (getNode, getNodesWith)
30 import Gargantext.Database.Query.Table.Node.Error (HasNodeError, errorWith)
31 import Gargantext.Database.Query.Table.NodeNode (deleteNodeNode, queryNodeNodeTable)
32 import Gargantext.Database.Query.Table.User
33 import Gargantext.Database.Query.Tree.Root (getRootId)
34 import Gargantext.Database.Schema.Node
35 import Gargantext.Prelude
36 import Gargantext.Utils.Tuple (uncurryMaybe)
37 import Opaleye hiding (not)
38 import qualified Opaleye as O
40 -- | TODO move in PhyloConfig of Gargantext
41 publicNodeTypes :: [NodeType]
42 publicNodeTypes = [NodeDashboard, NodeGraph, NodePhylo, NodeFile]
44 ------------------------------------------------------------------------
45 data ShareNodeWith = ShareNodeWith_User { snwu_nodetype :: NodeType
48 | ShareNodeWith_Node { snwn_nodetype :: NodeType
49 , snwn_node_id :: NodeId
51 ------------------------------------------------------------------------
52 deleteMemberShip :: HasNodeError err => [(SharedFolderId, TeamNodeId)] -> Cmd err [Int]
53 deleteMemberShip xs = mapM (\(s,t) -> deleteNodeNode s t) xs
55 ------------------------------------------------------------------------
57 type SharedFolderId = NodeId
58 type TeamNodeId = NodeId
60 -- List members of a Team
61 -- Result gives the username and its SharedFolderId that has to be eventually
62 -- used for the membership
63 membersOf :: HasNodeError err
64 => TeamNodeId -> Cmd err [(Text, SharedFolderId)]
66 res <- runOpaQuery $ membersOfQuery nId
67 pure $ catMaybes (uncurryMaybe <$> res)
70 membersOfQuery :: TeamNodeId
71 -> SelectArr () (MaybeFields (Field SqlText), MaybeFields (Field SqlInt4))
72 membersOfQuery (NodeId teamId) = proc () -> do
73 (nn, n, u) <- nodeNode_node_User -< ()
74 restrict -< (nn ^. nn_node2_id) .== sqlInt4 teamId
75 returnA -< ( user_username <$> u
79 nodeNode_node_User :: O.Select ( NodeNodeRead
80 , MaybeFields NodeRead
81 , MaybeFields UserRead )
82 nodeNode_node_User = proc () -> do
83 nn <- queryNodeNodeTable -< ()
84 n <- optionalRestrict queryNodeTable -<
85 \n' -> (n' ^. node_id) .== (nn ^. nn_node1_id)
86 u <- optionalRestrict queryUserTable -<
87 \u' -> (view node_user_id <$> n) .=== justFields (user_id u')
91 ------------------------------------------------------------------------
92 -- To Share a Node Team with a user, use this function
93 -- basically used with the invitation to a team
94 shareNodeWith :: HasNodeError err
98 shareNodeWith (ShareNodeWith_User NodeFolderShared u) n = do
99 nodeToCheck <- getNode n
100 userIdCheck <- getUserId u
101 if not (hasNodeType nodeToCheck NodeTeam)
102 then errorWith "[G.D.A.S.shareNodeWith] Can share node Team only"
104 if (view node_user_id nodeToCheck == userIdCheck)
105 then errorWith "[G.D.A.S.shareNodeWith] Can share to others only"
107 folderSharedId <- getFolderId u NodeFolderShared
108 insertDB ([NodeNode { _nn_node1_id = folderSharedId
110 , _nn_score = Nothing
111 , _nn_category = Nothing }]:: [NodeNode])
113 shareNodeWith (ShareNodeWith_Node NodeFolderPublic nId) n = do
114 nodeToCheck <- getNode n
115 if not (isInNodeTypes nodeToCheck publicNodeTypes)
116 then errorWith $ "[G.D.A.S.shareNodeWith] Can share this nodesTypes only: "
117 <> (cs $ show publicNodeTypes)
119 folderToCheck <- getNode nId
120 if hasNodeType folderToCheck NodeFolderPublic
121 then insertDB ([NodeNode { _nn_node1_id = nId
123 , _nn_score = Nothing
124 , _nn_category = Nothing }] :: [NodeNode])
125 else errorWith "[G.D.A.S.shareNodeWith] Can share NodeWith NodeFolderPublic only"
127 shareNodeWith _ _ = errorWith "[G.D.A.S.shareNodeWith] Not implemented for this NodeType"
129 ------------------------------------------------------------------------
130 getFolderId :: HasNodeError err => User -> NodeType -> Cmd err NodeId
131 getFolderId u nt = do
132 rootId <- getRootId u
133 s <- getNodesWith rootId HyperdataAny (Just nt) Nothing Nothing
135 Nothing -> errorWith "[G.D.A.S.getFolderId] No folder shared found"
136 Just f -> pure (_node_id f)
138 ------------------------------------------------------------------------
141 delFolderTeam :: HasNodeError err => User -> TeamId -> Cmd err Int
142 delFolderTeam u nId = do
143 folderSharedId <- getFolderId u NodeFolderShared
144 deleteNodeNode folderSharedId nId
146 unPublish :: HasNodeError err
147 => ParentId -> NodeId
149 unPublish p n = deleteNodeNode p n