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.Text (Text)
21 import Gargantext.Core.Types.Individu (User(..))
22 import Gargantext.Database
23 import Gargantext.Database.Action.User (getUserId)
24 import Gargantext.Database.Admin.Config (hasNodeType, isInNodeTypes)
25 import Gargantext.Database.Admin.Types.Hyperdata (HyperdataAny(..))
26 import Gargantext.Database.Admin.Types.Node
27 import Gargantext.Database.Query.Join (leftJoin3')
28 import Gargantext.Database.Query.Table.Node (getNode, getNodesWith)
29 import Gargantext.Database.Query.Table.Node.Error (HasNodeError, errorWith)
30 import Gargantext.Database.Query.Table.NodeNode (deleteNodeNode, queryNodeNodeTable)
31 import Gargantext.Database.Query.Table.User
32 import Gargantext.Database.Query.Tree.Root (getRootId)
33 import Gargantext.Database.Schema.Node
34 import Gargantext.Prelude
35 import Opaleye hiding (not)
36 import qualified Opaleye as O
38 -- | TODO move in PhyloConfig of Gargantext
39 publicNodeTypes :: [NodeType]
40 publicNodeTypes = [NodeDashboard, NodeGraph, NodePhylo, NodeFile]
42 ------------------------------------------------------------------------
43 data ShareNodeWith = ShareNodeWith_User { snwu_nodetype :: NodeType
46 | ShareNodeWith_Node { snwn_nodetype :: NodeType
47 , snwn_node_id :: NodeId
49 ------------------------------------------------------------------------
50 deleteMemberShip :: HasNodeError err => [(SharedFolderId, TeamNodeId)] -> Cmd err [Int]
51 deleteMemberShip xs = mapM (\(s,t) -> deleteNodeNode s t) xs
53 ------------------------------------------------------------------------
55 type SharedFolderId = NodeId
56 type TeamNodeId = NodeId
58 -- List members of a Team
59 -- Result gives the username and its SharedFolderId that has to be eventually
60 -- used for the membership
61 membersOf :: HasNodeError err
62 => TeamNodeId -> Cmd err [(Text, SharedFolderId)]
63 membersOf nId = runOpaQuery (membersOfQuery nId)
66 membersOfQuery :: TeamNodeId
67 -> SelectArr () (Column (Nullable SqlText), Column (Nullable SqlInt4))
68 membersOfQuery (NodeId teamId) = proc () -> do
69 (nn, (n, u)) <- nodeNode_node_User -< ()
70 restrict -< nn^.nn_node2_id .== sqlInt4 teamId
71 returnA -< (user_username u, n^.node_id)
74 nodeNode_node_User :: O.Select (NodeNodeRead, (NodeReadNull, UserReadNull))
75 nodeNode_node_User = leftJoin3' queryNodeNodeTable
81 cond12 :: (NodeNodeRead, (NodeRead, UserReadNull)) -> Column SqlBool
82 cond12 (nn, (n, _u)) = (nn^.nn_node1_id .== n^.node_id)
83 cond23 :: (NodeRead, UserRead) -> Column SqlBool
84 cond23 (n, u) = (n^.node_user_id .== user_id u)
88 ------------------------------------------------------------------------
89 -- To Share a Node Team with a user, use this function
90 -- basically used with the invitation to a team
91 shareNodeWith :: HasNodeError err
95 shareNodeWith (ShareNodeWith_User NodeFolderShared u) n = do
96 nodeToCheck <- getNode n
97 userIdCheck <- getUserId u
98 if not (hasNodeType nodeToCheck NodeTeam)
99 then errorWith "[G.D.A.S.shareNodeWith] Can share node Team only"
101 if (view node_user_id nodeToCheck == userIdCheck)
102 then errorWith "[G.D.A.S.shareNodeWith] Can share to others only"
104 folderSharedId <- getFolderId u NodeFolderShared
105 insertDB ([NodeNode { _nn_node1_id = folderSharedId
107 , _nn_score = Nothing
108 , _nn_category = Nothing }]:: [NodeNode])
110 shareNodeWith (ShareNodeWith_Node NodeFolderPublic nId) n = do
111 nodeToCheck <- getNode n
112 if not (isInNodeTypes nodeToCheck publicNodeTypes)
113 then errorWith $ "[G.D.A.S.shareNodeWith] Can share this nodesTypes only: "
114 <> (cs $ show publicNodeTypes)
116 folderToCheck <- getNode nId
117 if hasNodeType folderToCheck NodeFolderPublic
118 then insertDB ([NodeNode { _nn_node1_id = nId
120 , _nn_score = Nothing
121 , _nn_category = Nothing }] :: [NodeNode])
122 else errorWith "[G.D.A.S.shareNodeWith] Can share NodeWith NodeFolderPublic only"
124 shareNodeWith _ _ = errorWith "[G.D.A.S.shareNodeWith] Not implemented for this NodeType"
126 ------------------------------------------------------------------------
127 getFolderId :: HasNodeError err => User -> NodeType -> Cmd err NodeId
128 getFolderId u nt = do
129 rootId <- getRootId u
130 s <- getNodesWith rootId HyperdataAny (Just nt) Nothing Nothing
132 Nothing -> errorWith "[G.D.A.S.getFolderId] No folder shared found"
133 Just f -> pure (_node_id f)
135 ------------------------------------------------------------------------
138 delFolderTeam :: HasNodeError err => User -> TeamId -> Cmd err Int
139 delFolderTeam u nId = do
140 folderSharedId <- getFolderId u NodeFolderShared
141 deleteNodeNode folderSharedId nId
143 unPublish :: HasNodeError err
144 => ParentId -> NodeId
146 unPublish p n = deleteNodeNode p n