S2S: Project: Accept: Switch from basic to full OCAP verification

This commit is contained in:
Pere Lev 2024-02-01 20:26:49 +02:00
parent bce8079cb5
commit ff2c5659af
No known key found for this signature in database
GPG key ID: 5252C5C863E5E57D

View file

@ -94,6 +94,24 @@ import Vervis.Web.Collab
-- * Otherwise, i.e. sender isn't the component: -- * Otherwise, i.e. sender isn't the component:
-- * Verify I've seen the component-Accept for this Add -- * Verify I've seen the component-Accept for this Add
-- * Verify the new Accept is authorized -- * Verify the new Accept is authorized
--
-- * Give me a new child active SourceOriginUs
-- * Verify we haven't yet seen child's Accept
-- * Give me a new child passive SourceOriginThem
-- * Option 1: We haven't seen child's Accept yet
-- * Verify sender is the child
-- * Option 2: We saw it, but not my collaborator's Accept
-- * Verify the Accept is authorized
-- * Otherwise respond with error, no Accept is needed
-- * Give me a new parent active DestOriginUs
-- * Respond with error, we aren't supposed to get any Accept
-- * Give me a new parent passive DestOriginThem
-- * Option 1: I haven't yet seen parent's Accept
-- * Verify sender is the parent
-- * Option 2: I saw it, but not my collaborator's Accept
-- * Verify the accept is authorized
-- * Otherwise respond with error, no Accept is needed
--
-- * If it's none of these, respond with error -- * If it's none of these, respond with error
-- --
-- * In collab mode, verify the Collab isn't enabled yet -- * In collab mode, verify the Collab isn't enabled yet
@ -112,9 +130,22 @@ import Vervis.Web.Collab
-- * Otherwise, i.e. sender isn't the component, record the Accept and -- * Otherwise, i.e. sender isn't the component, record the Accept and
-- enable the Component in DB -- enable the Component in DB
-- --
-- * In child-active mode,
-- * If sender is the child, record the Accept into the Source record
-- * Prepare to send degelator-Grant
-- * Otherwise nothing to do
-- * In child-passive mode,
-- * Option 1: Record child's Accept in Source record
-- * Option 2: Record my collaborator's Accept
-- * Prepare to send delegator-Grant
-- * In parent-passive mode,
-- * Option 1: Record parent's Accept in the Dest record
-- * Option 2: Record my collaborator's Accept in the Dest record
-- * Prepare to send my own Accept
--
-- * Forward the Accept to my followers -- * Forward the Accept to my followers
-- --
-- * Possibly send a Grant: -- * Possibly send a Grant/Accept:
-- * For Invite-collab mode: -- * For Invite-collab mode:
-- * Regular collaborator-Grant -- * Regular collaborator-Grant
-- * To: Accepter (i.e. Invite target) -- * To: Accepter (i.e. Invite target)
@ -138,6 +169,32 @@ import Vervis.Web.Collab
-- - Component's followers -- - Component's followers
-- - My followers -- - My followers
-- - The Accept's sender -- - The Accept's sender
--
-- * Child-active
-- * If sender is the child
-- * delegator-Grant
-- * To: Child
-- * CC:
-- - Child's followers
-- - My followers
-- * Child-passive
-- * In option 2
-- * delegator-Grant
-- * To: Child
-- * CC:
-- - Child's followers
-- - My followers
-- - The Accept sender (my collaborator)
-- * Parent-passive
-- * In option 2
-- * Accept
-- * Object: The Add
-- * Fulfills: My collaborator's Accept
-- * To: Parent
-- * CC:
-- - Parent's followers
-- - My followers
-- - The Accept sender (my collaborator)
projectAccept projectAccept
:: UTCTime :: UTCTime
-> ProjectId -> ProjectId
@ -148,22 +205,9 @@ projectAccept now projectID (Verse authorIdMsig body) accept = do
-- Check input -- Check input
acceptee <- parseAccept accept acceptee <- parseAccept accept
let muCap = AP.activityCapability $ actbActivity body
-- Verify that the capability URI, if specified, is one of: collabOrComp <- withDBExcept $ do
-- * Outbox item URI of a local actor, i.e. a local activity
-- * A remote URI
maybeCap <-
traverse
(nameExceptT "Accept capability" . parseActivityURI')
(AP.activityCapability $ actbActivity body)
maybeNew <- withDBExcept $ do
-- Grab me from DB
(recipActorID, recipActor) <- lift $ do
recip <- getJust projectID
let actorID = projectActor recip
(actorID,) <$> getJust actorID
-- Find the accepted activity in our DB -- Find the accepted activity in our DB
accepteeDB <- do accepteeDB <- do
@ -174,104 +218,103 @@ projectAccept now projectID (Verse authorIdMsig body) accept = do
-- URI is the resource, grabbing the Collab record from our DB, -- URI is the resource, grabbing the Collab record from our DB,
-- Or if the accepted activity is an Invite or Add where my components -- Or if the accepted activity is an Invite or Add where my components
-- URI is the resource, grabbing the Component record from our DB -- URI is the resource, grabbing the Component record from our DB
collabOrComp <- do let adapt = maybe (Right Nothing) (either Left (Right . Just))
let adapt = maybe (Right Nothing) (either Left (Right . Just)) maybeCollab <-
maybeCollab <- ExceptT $ fmap adapt $ runMaybeT $
ExceptT $ fmap adapt $ runMaybeT $ runExceptT (Left <$> tryInviteCollab accepteeDB) <|>
runExceptT (Left <$> tryInviteCollab accepteeDB) <|> runExceptT (Left <$> tryJoinCollab accepteeDB) <|>
runExceptT (Left <$> tryJoinCollab accepteeDB) <|> runExceptT (Right <$> tryInviteComp accepteeDB) <|>
runExceptT (Right <$> tryInviteComp accepteeDB) <|> runExceptT (Right <$> tryAddComp accepteeDB)
runExceptT (Right <$> tryAddComp accepteeDB) fromMaybeE
fromMaybeE maybeCollab
maybeCollab "Accepted activity isn't an Invite/Join/Add I'm aware of"
"Accepted activity isn't an Invite/Join/Add I'm aware of"
idsForAccept <- bitraverse idsForAccept <- bitraverse
(\ (collabID, fulfills, inviterOrJoiner) -> (collabID,inviterOrJoiner,) <$> bitraverse (\ (collabID, fulfills, inviterOrJoiner) -> (collabID,inviterOrJoiner,) <$> bitraverse
-- If accepting an Invite, find the Collab recipient and verify -- If accepting an Invite, find the Collab recipient and verify
-- it's the sender of the Accept -- it's the sender of the Accept
(\ fulfillsID -> do (\ fulfillsID -> withDBExcept $ do
recip <- recip <-
lift $ lift $
requireEitherAlt requireEitherAlt
(getBy $ UniqueCollabRecipLocal collabID) (getBy $ UniqueCollabRecipLocal collabID)
(getBy $ UniqueCollabRecipRemote collabID) (getBy $ UniqueCollabRecipRemote collabID)
"Found Collab with no recip" "Found Collab with no recip"
"Found Collab with multiple recips" "Found Collab with multiple recips"
case (recip, authorIdMsig) of case (recip, authorIdMsig) of
(Left (Entity crlid crl), Left (LocalActorPerson personID, _, _)) (Left (Entity crlid crl), Left (LocalActorPerson personID, _, _))
| collabRecipLocalPerson crl == personID -> | collabRecipLocalPerson crl == personID ->
return (fulfillsID, Left crlid) return (fulfillsID, Left crlid)
(Right (Entity crrid crr), Right (author, _, _)) (Right (Entity crrid crr), Right (author, _, _))
| collabRecipRemoteActor crr == remoteAuthorId author -> | collabRecipRemoteActor crr == remoteAuthorId author ->
return (fulfillsID, Right crrid) return (fulfillsID, Right crrid)
_ -> throwE "Accepting an Invite whose recipient is someone else" _ -> throwE "Accepting an Invite whose recipient is someone else"
)
-- If accepting a Join, verify accepter has permission
(\ fulfillsID -> do
capID <- fromMaybeE maybeCap "No capability provided"
capability <-
case capID of
Left (capActor, _, capItem) -> return (capActor, capItem)
Right _ -> throwE "Capability is a remote URI, i.e. not authored by the local resource"
verifyCapability'
capability
authorIdMsig
(LocalActorProject projectID)
AP.RoleAdmin
return fulfillsID
)
fulfills
) )
(\ (componentID, ident, inviteOrAdd) -> (componentID, ident,) <$> bitraverse -- If accepting a Join, verify accepter has permission
(\ fulfillsID -> do
-- If accepting an Invite-component, there's nothing to check uCap <- fromMaybeE muCap "No capability provided"
-- at this point verifyCapability''
pure uCap
authorIdMsig
-- If accepting an Add-component: (LocalActorProject projectID)
-- * If the sender is the component, verify I haven't seen AP.RoleAdmin
-- a component-Accept on this Add return fulfillsID
-- * Otherwise, verify I've seen the component-Accept for
-- this Add and that the new Accept is authorized
(\ () -> do
maybeComponentAccept <-
lift $
case bimap fst fst ident of
Left localID -> (() <$) <$> getBy (UniqueComponentAcceptLocal localID)
Right remoteID -> (() <$) <$> getBy (UniqueComponentAcceptRemote remoteID)
if componentIsAuthor ident
then
verifyNothingE
maybeComponentAccept
"I've already seen a ComponentAccept* on \
\that Add"
else do
fromMaybeE
maybeComponentAccept
"I haven't yet seen the Component's Accept on \
\the Add"
capID <- fromMaybeE maybeCap "No capability provided"
capability <-
case capID of
Left (capActor, _, capItem) -> return (capActor, capItem)
Right _ -> throwE "Capability is a remote URI, i.e. not authored by me"
verifyCapability'
capability
authorIdMsig
(LocalActorProject projectID)
AP.RoleAdmin
)
inviteOrAdd
) )
collabOrComp fulfills
)
(\ (componentID, ident, inviteOrAdd) -> (componentID, ident,) <$> bitraverse
-- If accepting an Invite-component, there's nothing to check
-- at this point
pure
-- If accepting an Add-component:
-- * If the sender is the component, verify I haven't seen
-- a component-Accept on this Add
-- * Otherwise, verify I've seen the component-Accept for
-- this Add and that the new Accept is authorized
(\ () -> do
maybeComponentAccept <-
lift $ withDB $
case bimap fst fst ident of
Left localID -> (() <$) <$> getBy (UniqueComponentAcceptLocal localID)
Right remoteID -> (() <$) <$> getBy (UniqueComponentAcceptRemote remoteID)
if componentIsAuthor ident
then
verifyNothingE
maybeComponentAccept
"I've already seen a ComponentAccept* on \
\that Add"
else do
fromMaybeE
maybeComponentAccept
"I haven't yet seen the Component's Accept on \
\the Add"
uCap <- fromMaybeE muCap "No capability provided"
verifyCapability''
uCap
authorIdMsig
(LocalActorProject projectID)
AP.RoleAdmin
)
inviteOrAdd
)
collabOrComp
maybeNew <- withDBExcept $ do
-- Grab me from DB
(recipActorID, recipActor) <- lift $ do
recip <- getJust projectID
let actorID = projectActor recip
(actorID,) <$> getJust actorID
-- In collab mode, verify the Collab isn't already validated -- In collab mode, verify the Collab isn't already validated
-- In component mode, verify the Component isn't already validated -- In component mode, verify the Component isn't already validated