S2S: Deck: Resolve: Use the full OCAP-authorization algorithm

deckResolve now supports Resolve requests that use extension-Grants. It
iterates the verifies the Grant-chain using the process described in the
ForgeFed specification.
This commit is contained in:
Pere Lev 2023-11-12 17:43:11 +02:00
parent 1a3a46b6b2
commit 34386bcf52
No known key found for this signature in database
GPG key ID: 5252C5C863E5E57D
2 changed files with 64 additions and 21 deletions

View file

@ -74,6 +74,7 @@ import Vervis.Persist.Collab
import Vervis.Persist.Discussion
import Vervis.RemoteActorStore
import Vervis.Ticket
import Vervis.Web.Collab
-- Meaning: An actor is adding some object to some target
-- Behavior:
@ -518,6 +519,19 @@ deckResolve now deckID (Verse authorIdMsig body) (AP.Resolve uObject) = do
_ -> throwE "Local route but not a ticket of mine"
taskID <- decodeKeyHashidE taskHash "Invalid TicketDeck keyhashid"
-- Verify that a capability is provided
uCap <- do
let muCap = AP.activityCapability $ actbActivity body
fromMaybeE muCap "No capability provided"
-- Verify the sender is authorized by the tracker to resolve a ticket
verifyCapability''
uCap
authorIdMsig
(GrantResourceDeck deckID)
AP.RoleTriage
{-
-- Check capability
capability <- do
@ -536,6 +550,7 @@ deckResolve now deckID (Verse authorIdMsig body) (AP.Resolve uObject) = do
Left (actorByKey, _, outboxItemID) ->
return (actorByKey, outboxItemID)
_ -> throwE "Capability is remote i.e. definitely not by me"
-}
maybeNew <- withDBExcept $ do
@ -557,12 +572,14 @@ deckResolve now deckID (Verse authorIdMsig body) (AP.Resolve uObject) = do
mractid <- lift $ insertToInbox now authorIdMsig body (actorInbox actorRecip) False
for mractid $ \ resolveDB -> do
{-
-- Verify the sender is authorized by the tracker to resolve a ticket
verifyCapability'
capability
authorIdMsig
(GrantResourceDeck deckID)
AP.RoleTriage
-}
-- Prepare forwarding the Resolve to my followers & ticket
-- followers

View file

@ -198,27 +198,53 @@ verifyCapability'' uCap recipientActor resource requiredRole = do
Left (actor, _, itemID) -> return (actor, itemID)
Right _ -> throwE "Remote, so definitely not by me"
-- We already checked that the activity exists in DB
-- So proceed to find the Collab record
collabID <- do
maybeEnable <- lift $ getValBy $ UniqueCollabEnableGrant capItem
collabEnableCollab <$>
fromMaybeE maybeEnable "No CollabEnable for this activity"
-- Find the recipient of that Collab
recipID <-
lift $ bimap collabRecipLocalPerson collabRecipRemoteActor <$>
requireEitherAlt
(getValBy $ UniqueCollabRecipLocal collabID)
(getValBy $ UniqueCollabRecipRemote collabID)
"No collab recip"
"Both local and remote recips for collab"
-- Find the local topic, on which this Collab gives access
topic <- lift $ getCollabTopic collabID
-- Verify that topic is indeed the sender of the Grant
unless (grantResourceLocalActor topic == capActor) $
error "Grant sender isn't the topic"
-- Verify the topic matches the resource specified
unless (topic == resource) $
throwE "Capability topic is some other local resource"
-- So proceed to find the Collab or Stem record
if null l
-- This is thr only Grant in the chain, so we're
-- looking for a Collab record
then nameExceptT "Collab" $ do
-- Find the Collab record
collabID <- do
maybeEnable <- lift $ getValBy $ UniqueCollabEnableGrant capItem
collabEnableCollab <$>
fromMaybeE maybeEnable "No CollabEnable for this activity"
-- Find the recipient of that Collab
recipID <-
lift $ bimap collabRecipLocalPerson collabRecipRemoteActor <$>
requireEitherAlt
(getValBy $ UniqueCollabRecipLocal collabID)
(getValBy $ UniqueCollabRecipRemote collabID)
"No collab recip"
"Both local and remote recips for collab"
-- Find the local topic, on which this Collab gives access
topic <- lift $ getCollabTopic collabID
-- Verify that topic is indeed the sender of the Grant
unless (grantResourceLocalActor topic == capActor) $
error "Grant sender isn't the topic"
-- Verify the topic matches the resource specified
unless (topic == resource) $
throwE "Capability topic is some other local resource"
-- There are more Grants in the chain, so we're
-- looking for a Stem record
else nameExceptT "Stem" $ do
-- Find the Stem record
stemID <- do
scaID <- do
maybeSCA <- lift $ getValBy $ UniqueStemDelegateLocalGrant capItem
stemDelegateLocalStem <$>
fromMaybeE maybeSCA "No StemDelegateLocal for this activity"
lift $ stemComponentAcceptStem <$> getJust scaID
-- Find the local topic, on which this Stem gives access
topic <- lift $ getStemIdent stemID
-- Verify that topic is indeed the sender of the Grant
unless (componentActor topic == capActor) $
error "Grant sender isn't the Stem ident"
-- Verify the topic matches the resource specified
unless (componentActor topic == grantResourceLocalActor resource) $
throwE "Capability topic is some other local resource"
return $ (u, activity, grant, role, targetIsProject, targetIsTeam) : l
Just uParent -> nameExceptT "Extension-Grant" $ do