S2S: Project Add handler: Rearrange code in preparation for Component mode

Also add Component mode details into the behavior comment (but haven't
yet implemented the newly described Component-mode behavior)
This commit is contained in:
Pere Lev 2023-06-29 20:56:03 +03:00
parent 2920deb900
commit aec2235fdc
No known key found for this signature in database
GPG key ID: 5252C5C863E5E57D

View file

@ -82,59 +82,60 @@ import Vervis.Ticket
-- * Check if I know the activity that's being Accepted:
-- * Is it an Invite to be a collaborator in me?
-- * Verify the Accept is by the Invite target
-- * If it's on a Join to be a collaborator in me?
-- * Is it a Join to be a collaborator in me?
-- * Verify the Accept is authorized
-- * Is it an Invite to be a component of me?
-- * Nothing to check at this point
-- * Is it an Add to be a component of me?
-- * If the sender is the component:
-- * Verify I haven't seen a component-Accept on this Add
-- * Otherwise, i.e. sender isn't the component:
-- * Verify I've seen the component-Accept for this Add
-- * Verify the Accept is authorized
-- * If it's none of these, respond with error
-- * Verify the Collab isn't enabled yet
--
-- * In collab mode, verify the Collab isn't enabled yet
-- * In component mode, verify the Component isn't enabled yet
--
-- * Insert the Accept to my inbox
-- * Record the Accept and enable the Collab in DB
--
-- * In collab mode, record the Accept and enable the Collab in DB
-- * In Invite-component mode,
-- * If sender is component, record the Accept and enable the Component
-- in DB
-- * Otherwise, nothing at this point
-- * In Add-component mode,
-- * If the sender is the component, record the Accept into the
-- Component record in DB
-- * Otherwise, i.e. sender isn't the component, record the Accept and
-- enable the Component in DB
--
-- * Forward the Accept to my followers
-- * Send a regular collaborator-Grant:
-- * For Invite mode:
--
-- * Possibly send a Grant:
-- * For Invite-collab mode:
-- * Regular collaborator-Grant
-- * To: Accepter (i.e. Invite target)
-- * CC: Invite sender, Accepter's followers, my followers
-- * For Join mode:
-- * For Join-as-collab mode:
-- * Regular collaborator-Grant
-- * To: Join sender
-- * CC: Accept sender, Join sender's followers, my followers
--
--
--
-- Stuff I'm about to implement for Component mode:
--
--
-- * If it's on an Invite to be a component of me:
-- * Verify the Component isn't enabled yet (same as checking if I've
-- recorded the component's Accept)
-- * If the sender isn't the component, just forward the Accept to my
-- followers and done
-- * If the sender is the component:
-- * Enable the Component in DB
-- * Forward the Accept to my followers
-- * Send a delegator Grant to the component
-- * To: Component
-- * CC:
-- - Component's followers
-- - My followers
--
--
-- * If it's on an Add to be a component of me:
-- * Verify the Component isn't enabled yet (same as checking if I've
-- recorded an Accept from a collaborator of mine)
-- * If the sender is the component:
-- * Verify I haven't seen a component-Accept on this Add
-- * Record the Accept into the Component record in DB
-- * Forward the Accept to my followers
-- * Otherwise, i.e. sender isn't the component:
-- * Verify I've seen the component-Accept for this Add
-- * Verify the Accept is authorized
-- * Record the Accept and enable the Component in DB
-- * Forward the Accept to my followers
-- * Send a delegator Grant to the component
-- * To: Component
-- * CC:
-- - Component's followers
-- - My followers
-- - The Accept's sender
-- * For Invite-component mode:
-- * Only if sender is the component
-- * delegator-Grant with a result URI
-- * To: Component
-- * CC:
-- - Component's followers
-- - My followers
-- * For Add-component mode:
-- * Only if sender isn't the component
-- * delegator-Grant with a result URI
-- * To: Component
-- * CC:
-- - Component's followers
-- - My followers
-- - The Accept's sender
projectAccept
:: UTCTime
-> ProjectId
@ -146,7 +147,7 @@ projectAccept now projectID (Verse authorIdMsig body) accept = do
-- Check input
acceptee <- parseAccept accept
-- Verify the capability URI is one of:
-- Verify that the capability URI, if specified, is one of:
-- * Outbox item URI of a local actor, i.e. a local activity
-- * A remote URI
maybeCap <-
@ -167,32 +168,22 @@ projectAccept now projectID (Verse authorIdMsig body) accept = do
a <- getActivity acceptee
fromMaybeE a "Can't find acceptee in DB"
-- See if the accepted activity is an Invite or Join to a local
-- resource, grabbing the Collab record from our DB
collab <- do
-- See if the accepted activity is an Invite or Join where my collabs
-- URI is the resource, grabbing the Collab record from our DB
(collabID, fulfills, inviterOrJoiner) <- do
let adapt = maybe (Right Nothing) (either Left (Right . Just))
maybeCollab <-
lift $ runMaybeT $
Left <$> tryInvite accepteeDB <|>
Right <$> tryJoin accepteeDB
ExceptT $ fmap adapt $ runMaybeT $
runExceptT (tryInviteCollab accepteeDB) <|>
runExceptT (tryJoinCollab accepteeDB)
fromMaybeE maybeCollab "Accepted activity isn't an Invite or Join I'm aware of"
-- Find the local resource and verify it's me
collabID <-
lift $ case collab of
Left (fulfillsID, _) ->
collabFulfillsInviteCollab <$> getJust fulfillsID
Right (fulfillsID, _) ->
collabFulfillsJoinCollab <$> getJust fulfillsID
topic <- lift $ getCollabTopic collabID
unless (GrantResourceProject projectID == topic) $
throwE "Accept object is an Invite/Join for some other resource"
idsForAccept <-
case collab of
bitraverse
-- If accepting an Invite, find the Collab recipient and verify
-- it's the sender of the Accept
Left (fulfillsID, _) -> Left <$> do
(\ fulfillsID -> do
recip <-
lift $
requireEitherAlt
@ -208,9 +199,10 @@ projectAccept now projectID (Verse authorIdMsig body) accept = do
| collabRecipRemoteActor crr == remoteAuthorId author ->
return (fulfillsID, Right crrid)
_ -> throwE "Accepting an Invite whose recipient is someone else"
)
-- If accepting a Join, verify accepter has permission
Right (fulfillsID, _) -> Right <$> do
(\ fulfillsID -> do
capID <- fromMaybeE maybeCap "No capability provided"
capability <-
case capID of
@ -222,6 +214,9 @@ projectAccept now projectID (Verse authorIdMsig body) accept = do
(GrantResourceProject projectID)
AP.RoleAdmin
return fulfillsID
)
fulfills
-- Verify the Collab isn't already validated
maybeEnabled <- lift $ getBy $ UniqueCollabEnable collabID
@ -262,8 +257,7 @@ projectAccept now projectID (Verse authorIdMsig body) accept = do
lift $ insert_ $ CollabEnable collabID grantID
-- Prepare a Grant activity and insert to my outbox
let inviterOrJoiner = either snd snd collab
isInvite = isLeft collab
let isInvite = isLeft fulfills
grant@(actionGrant, _, _, _) <- do
Collab role <- lift $ getJust collabID
lift $ prepareGrant isInvite inviterOrJoiner role
@ -285,30 +279,66 @@ projectAccept now projectID (Verse authorIdMsig body) accept = do
where
tryInvite (Left (actorByKey, _actorEntity, itemID)) =
(,Left actorByKey) . collabInviterLocalCollab <$>
MaybeT (getValBy $ UniqueCollabInviterLocalInvite itemID)
tryInvite (Right remoteActivityID) = do
CollabInviterRemote collab actorID _ <-
MaybeT $ getValBy $
UniqueCollabInviterRemoteInvite remoteActivityID
actor <- lift $ getJust actorID
sender <-
lift $ (,remoteActorFollowers actor) <$> getRemoteActorURI actor
return (collab, Right sender)
verifyCollabTopic collabID = do
topic <- lift $ getCollabTopic collabID
unless (GrantResourceProject projectID == topic) $
throwE "Accept object is an Invite/Join for some other resource"
tryJoin (Left (actorByKey, _actorEntity, itemID)) =
(,Left actorByKey) . collabRecipLocalJoinFulfills <$>
MaybeT (getValBy $ UniqueCollabRecipLocalJoinJoin itemID)
tryJoin (Right remoteActivityID) = do
verifyInviteCollabTopic fulfillsID = do
collabID <- lift $ collabFulfillsInviteCollab <$> getJust fulfillsID
verifyCollabTopic collabID
return collabID
verifyJoinCollabTopic fulfillsID = do
collabID <- lift $ collabFulfillsJoinCollab <$> getJust fulfillsID
verifyCollabTopic collabID
return collabID
tryInviteCollab (Left (actorByKey, _actorEntity, itemID)) = do
fulfillsID <-
lift $ collabInviterLocalCollab <$>
MaybeT (getValBy $ UniqueCollabInviterLocalInvite itemID)
collabID <-
ExceptT $ lift $ runExceptT $ verifyInviteCollabTopic fulfillsID
return (collabID, Left fulfillsID, Left actorByKey)
tryInviteCollab (Right remoteActivityID) = do
CollabInviterRemote fulfillsID actorID _ <-
lift $ MaybeT $ getValBy $
UniqueCollabInviterRemoteInvite remoteActivityID
collabID <-
ExceptT $ lift $ runExceptT $ verifyInviteCollabTopic fulfillsID
sender <- lift $ lift $ do
actor <- getJust actorID
(,remoteActorFollowers actor) <$> getRemoteActorURI actor
return (collabID, Left fulfillsID, Right sender)
tryJoinCollab (Left (actorByKey, _actorEntity, itemID)) = do
fulfillsID <-
lift $ collabRecipLocalJoinFulfills <$>
MaybeT (getValBy $ UniqueCollabRecipLocalJoinJoin itemID)
collabID <-
ExceptT $ lift $ runExceptT $ verifyJoinCollabTopic fulfillsID
return (collabID, Right fulfillsID, Left actorByKey)
tryJoinCollab (Right remoteActivityID) = do
CollabRecipRemoteJoin recipID fulfillsID _ <-
MaybeT $ getValBy $
lift $ MaybeT $ getValBy $
UniqueCollabRecipRemoteJoinJoin remoteActivityID
remoteActorID <- lift $ collabRecipRemoteActor <$> getJust recipID
actor <- lift $ getJust remoteActorID
joiner <-
lift $ (,remoteActorFollowers actor) <$> getRemoteActorURI actor
return (fulfillsID, Right joiner)
collabID <-
ExceptT $ lift $ runExceptT $ verifyJoinCollabTopic fulfillsID
joiner <- lift $ lift $ do
remoteActorID <- collabRecipRemoteActor <$> getJust recipID
actor <- getJust remoteActorID
(,remoteActorFollowers actor) <$> getRemoteActorURI actor
return (collabID, Right fulfillsID, Right joiner)
{-
tryInviteComp (Left (actorByKey, _actorEntity, itemID)) = do
ComponentOriginInvite
ComponentProjectGestureLocal
tryInviteCollab (Right remoteActivityID) = do
ComponentOriginInvite
ComponentProjectGestureRemote
-}
prepareGrant isInvite sender role = do
encodeRouteHome <- getEncodeRouteHome