1
0
Fork 0

S2S: Component: Remove: Implement component mode, updated process

This commit is contained in:
Pere Lev 2024-05-27 18:40:20 +03:00
parent 4838a131b4
commit 185047ecb4
No known key found for this signature in database
GPG key ID: 5252C5C863E5E57D
2 changed files with 444 additions and 197 deletions
src/Vervis/Actor

View file

@ -22,7 +22,7 @@ module Vervis.Actor.Common
, topicAccept , topicAccept
, topicReject , topicReject
, componentInvite , componentInvite
, topicRemove , componentRemove
, topicJoin , topicJoin
, topicCreateMe , topicCreateMe
, componentGrant , componentGrant
@ -89,6 +89,7 @@ import Vervis.Persist.Discussion
import Vervis.Recipient (makeRecipientSet, LocalStageBy (..), Aud (..), collectAudience, localActorFollowers, renderLocalActor) import Vervis.Recipient (makeRecipientSet, LocalStageBy (..), Aud (..), collectAudience, localActorFollowers, renderLocalActor)
import Vervis.RemoteActorStore import Vervis.RemoteActorStore
import Vervis.Ticket import Vervis.Ticket
import Vervis.Web.Collab
actorFollow actorFollow
:: (PersistRecordBackend r SqlBackend, ToBackendKey SqlBackend r) :: (PersistRecordBackend r SqlBackend, ToBackendKey SqlBackend r)
@ -1235,228 +1236,485 @@ componentInvite grabKomponent topicComponent now topicKey (Verse authorIdMsig bo
return (action, recipientSet, remoteActors, fwdHosts) return (action, recipientSet, remoteActors, fwdHosts)
topicRemove -- Meaning: An actor A is removing actor B from a collection C
:: (PersistRecordBackend topic SqlBackend, ToBackendKey SqlBackend topic) -- Behavior:
=> (topic -> ResourceId) -- * If C is my collaborators collection
-> (forall f. f topic -> LocalResourceBy f) -- * Verify A isn't removing themselves
-- * Verify A is authorized by me to remove actors from me
-- * Verify B already has a Grant for me
-- * Remove the whole Collab record from DB
-- * Forward the Remove to my followers
-- * Send a Revoke:
-- * To: Actor B
-- * CC: Actor A, B's followers, my followers
--
-- * If C is my projects collection
-- * Verify A's request is authorized
-- * Verify B is an enabled project of mine
-- * Remove the whole Stem record from DB
-- * Forward to followers
-- * Publish a Revoke on the start-Grant I'd sent to B
-- * To: Actor B
-- * CC: Actor A, B's followers, my followers
--
-- * If I'm B, and C is some project's components collection
-- * Just forward to my followers
componentRemove
:: forall topic.
(PersistRecordBackend topic SqlBackend, ToBackendKey SqlBackend topic)
=> (topic -> KomponentId)
-> (forall f. f topic -> ComponentBy f)
-> UTCTime -> UTCTime
-> Key topic -> Key topic
-> Verse -> Verse
-> AP.Remove URIMode -> AP.Remove URIMode
-> ActE (Text, Act (), Next) -> ActE (Text, Act (), Next)
topicRemove grabResource topicResource now topicKey (Verse authorIdMsig body) remove = do componentRemove grabKomponent topicComponent now topicKey (Verse authorIdMsig body) remove = do
-- Check capability let author = bimap (view _1) (remoteAuthorURI . view _1) authorIdMsig
capability <- do (collection, item) <- parseRemove author remove
case (collection, item) of
(Left (Left lr), _)
| lr == topicResource topicKey ->
removeCollab item
(Left (Right target), _)
| addTargetComponentProjects target == Just (topicComponent topicKey) ->
removeProjectActive item
(_, Left la) | la == resourceToActor (topicResource topicKey) ->
case collection of
Left (Right (ATProjectComponents j)) ->
removeProjectPassive $ Left j
Right (ObjURI h luColl) -> do
-- NOTE this is HTTP GET done synchronously in the activity
-- handler
manager <- asksEnv envHttpManager
c <- AP.fetchAPID_T manager (AP.collectionId :: AP.Collection FedURI URIMode -> LocalURI) h luColl
lu <- fromMaybeE (AP.collectionContext c) "No context"
rwc <- AP.fetchRWC_T manager h lu
AP.Actor l d <-
case AP.rwcResource rwc of
AP.ResourceActor a -> pure a
AP.ResourceChild _ _ -> throwE "Remove.target remote ResourceChild"
let typ = AP.actorType d
if typ == AP.ActorTypeProject && Just luColl == AP.rwcComponents rwc
then removeProjectPassive $ Right $ ObjURI h lu
else throwE "Weird collection situation"
_ -> throwE "I'm being removed from somewhere irrelevant"
_ -> throwE "This Remove isn't for me"
-- Verify that a capability is provided where
topicResource :: forall f. f topic -> LocalResourceBy f
topicResource = componentResource . topicComponent
removeCollab item = do
memberByKey <-
bitraverse
(\case
LocalActorPerson p -> pure p
_ -> throwE "Not accepting non-person actors as collabs"
)
pure
item
-- Check capability
uCap <- do uCap <- do
let muCap = AP.activityCapability $ actbActivity body let muCap = AP.activityCapability $ actbActivity body
fromMaybeE muCap "No capability provided" fromMaybeE muCap "No capability provided"
-- Verify the capability URI is one of: -- Verify the specified capability gives relevant access
-- * Outbox item URI of a local actor, i.e. a local activity verifyCapability'' uCap authorIdMsig (topicResource topicKey) AP.RoleAdmin
-- * A remote URI
cap <- nameExceptT "Remove.capability" $ parseActivityURI' uCap
-- Verify the capability is local maybeNew <- withDBExcept $ do
case cap of
Left (actorByKey, _, outboxItemID) ->
return (actorByKey, outboxItemID)
_ -> throwE "Capability is remote i.e. definitely not by me"
-- Check remove -- Find member in our DB
memberByKey <- do memberDB <-
let author = bimap (view _1) (remoteAuthorURI . view _1) authorIdMsig bitraverse
(resource, memberOrComp) <- parseRemove author remove (flip getEntityE "Member not found in DB")
unless (Left (Left $ topicResource topicKey) == resource) $ (\ u@(ObjURI h lu) -> (,u) <$> do
throwE "Remove topic isn't my collabs URI" maybeActor <- lift $ runMaybeT $ do
bitraverse iid <- MaybeT $ getKeyBy $ UniqueInstance h
(\case roid <- MaybeT $ getKeyBy $ UniqueRemoteObject iid lu
LocalActorPerson p -> pure p MaybeT $ getBy $ UniqueRemoteActor roid
_ -> throwE "Not accepting non-person actors as collabs" fromMaybeE maybeActor "Remote removee not found in DB"
) )
pure memberByKey
memberOrComp
maybeNew <- withDBExcept $ do -- Grab me from DB
komponentID <- lift $ grabKomponent <$> getJust topicKey
Komponent resourceID <- lift $ getJust komponentID
Resource topicActorID <- lift $ getJust resourceID
topicActor <- lift $ getJust topicActorID
-- Find member in our DB -- Find the collab that the member already has for me
memberDB <- existingCollabIDs <-
lift $ case memberDB of
Left (Entity personID _) ->
fmap (map $ over _1 Left) $
E.select $ E.from $ \ (collab `E.InnerJoin` recipl) -> do
E.on $
collab E.^. CollabId E.==.
recipl E.^. CollabRecipLocalCollab
E.where_ $
collab E.^. CollabTopic E.==. E.val resourceID E.&&.
recipl E.^. CollabRecipLocalPerson E.==. E.val personID
return
( recipl E.^. persistIdField
, recipl E.^. CollabRecipLocalCollab
)
Right (Entity remoteActorID _, _) ->
fmap (map $ over _1 Right) $
E.select $ E.from $ \ (collab `E.InnerJoin` recipr) -> do
E.on $
collab E.^. CollabId E.==.
recipr E.^. CollabRecipRemoteCollab
E.where_ $
collab E.^. CollabTopic E.==. E.val resourceID E.&&.
recipr E.^. CollabRecipRemoteActor E.==. E.val remoteActorID
return
( recipr E.^. persistIdField
, recipr E.^. CollabRecipRemoteCollab
)
(recipID, E.Value collabID) <-
case existingCollabIDs of
[] -> throwE "Remove object isn't a member of me"
[collab] -> return collab
_ -> error "Multiple collabs found for removee"
-- Verify the Collab is enabled
maybeEnabled <- lift $ getBy $ UniqueCollabEnable collabID
Entity enableID (CollabEnable _ grantID) <-
fromMaybeE maybeEnabled "Remove object isn't a member of me yet"
-- Verify that at least 1 more enabled Admin collab for me exists
otherCollabIDs <-
lift $ E.select $ E.from $ \ (collab `E.InnerJoin` enable) -> do
E.on $
collab E.^. CollabId E.==.
enable E.^. CollabEnableCollab
E.where_ $
collab E.^. CollabTopic E.==. E.val resourceID E.&&.
collab E.^. CollabId E.!=. E.val collabID
return $ collab E.^. CollabId
when (null otherCollabIDs) $
throwE "No other admins exist, can't remove"
maybeRemoveDB <- lift $ insertToInbox now authorIdMsig body (actorInbox topicActor) False
lift $ for maybeRemoveDB $ \ (inboxItemID, _removeDB) -> do
-- Delete the whole Collab record
deleteBy $ UniqueCollabDelegLocal enableID
deleteBy $ UniqueCollabDelegRemote enableID
delete enableID
case recipID of
Left (E.Value l) -> do
deleteBy $ UniqueCollabRecipLocalJoinCollab l
deleteBy $ UniqueCollabRecipLocalAcceptCollab l
delete l
Right (E.Value r) -> do
deleteBy $ UniqueCollabRecipRemoteJoinCollab r
deleteBy $ UniqueCollabRecipRemoteAcceptCollab r
delete r
fulfills <- do
mf <- runMaybeT $ asum
[ Left <$> MaybeT (getKeyBy $ UniqueCollabFulfillsLocalTopicCreation collabID)
, Right . Left <$> MaybeT (getKeyBy $ UniqueCollabFulfillsInvite collabID)
, Right . Right <$> MaybeT (getKeyBy $ UniqueCollabFulfillsJoin collabID)
]
maybe (error $ "No fulfills for collabID#" ++ show collabID) pure mf
case fulfills of
Left fc -> delete fc
Right (Left fi) -> do
deleteBy $ UniqueCollabInviterLocal fi
deleteBy $ UniqueCollabInviterRemote fi
delete fi
Right (Right fj) -> do
deleteBy $ UniqueCollabApproverLocal fj
deleteBy $ UniqueCollabApproverRemote fj
delete fj
delete collabID
-- Prepare forwarding Remove to my followers
sieve <- lift $ do
topicHash <- encodeKeyHashid topicKey
let topicByHash = resourceToActor $ topicResource topicHash
return $ makeRecipientSet [] [localActorFollowers topicByHash]
-- Prepare a Revoke activity and insert to my outbox
revoke@(actionRevoke, _, _, _) <-
lift $ prepareRevoke memberDB grantID
let recipByKey = resourceToActor $ topicResource topicKey
revokeID <- insertEmptyOutboxItem' (actorOutbox topicActor) now
_luRevoke <- updateOutboxItem' recipByKey revokeID actionRevoke
return (topicActorID, sieve, revokeID, revoke, inboxItemID)
case maybeNew of
Nothing -> done "I already have this activity in my inbox"
Just (topicActorID, sieve, revokeID, (actionRevoke, localRecipsRevoke, remoteRecipsRevoke, fwdHostsRevoke), inboxItemID) -> do
let topicByID = resourceToActor $ topicResource topicKey
forwardActivity authorIdMsig body topicByID topicActorID sieve
lift $ sendActivity
topicByID topicActorID localRecipsRevoke
remoteRecipsRevoke fwdHostsRevoke revokeID actionRevoke
doneDB inboxItemID "[Collab] Deleted the Grant/Collab, forwarded Remove, sent Revoke"
where
prepareRevoke member grantID = do
encodeRouteHome <- getEncodeRouteHome
encodeRouteLocal <- getEncodeRouteLocal
recipHash <- encodeKeyHashid topicKey
let topicByHash = resourceToActor $ topicResource recipHash
memberHash <- bitraverse (encodeKeyHashid . entityKey) pure member
audRemover <- makeAudSenderOnly authorIdMsig
let audience =
let audMember =
case memberHash of
Left p ->
AudLocal [LocalActorPerson p] [LocalStagePersonFollowers p]
Right (Entity _ actor, ObjURI h lu) ->
AudRemote h [lu] (maybeToList $ remoteActorFollowers actor)
audTopic = AudLocal [] [localActorFollowers topicByHash]
in [audRemover, audMember, audTopic]
(recipientSet, remoteActors, fwdHosts, audLocal, audRemote) =
collectAudience audience
recips = map encodeRouteHome audLocal ++ audRemote
uRemove <- getActivityURI authorIdMsig
luGrant <- do
grantHash <- encodeKeyHashid grantID
return $ encodeRouteLocal $ activityRoute topicByHash grantHash
let action = AP.Action
{ AP.actionCapability = Nothing
, AP.actionSummary = Nothing
, AP.actionAudience = AP.Audience recips [] [] [] [] []
, AP.actionFulfills = [uRemove]
, AP.actionSpecific = AP.RevokeActivity AP.Revoke
{ AP.revokeObject = luGrant :| []
}
}
return (action, recipientSet, remoteActors, fwdHosts)
removeProjectActive item = do
project <-
bitraverse bitraverse
(flip getEntityE "Member not found in DB") (\case
(\ u@(ObjURI h lu) -> (,u) <$> do LocalActorProject j -> pure j
maybeActor <- lift $ runMaybeT $ do _ -> throwE "Local object isn't a Project"
iid <- MaybeT $ getKeyBy $ UniqueInstance h
roid <- MaybeT $ getKeyBy $ UniqueRemoteObject iid lu
MaybeT $ getBy $ UniqueRemoteActor roid
fromMaybeE maybeActor "Remote removee not found in DB"
) )
memberByKey pure
item
-- Grab me from DB -- Check capability
resourceID <- lift $ grabResource <$> getJust topicKey uCap <- do
Resource topicActorID <- lift $ getJust resourceID let muCap = AP.activityCapability $ actbActivity body
topicActor <- lift $ getJust topicActorID fromMaybeE muCap "No capability provided"
-- Verify the specified capability gives relevant access -- Verify the specified capability gives relevant access
verifyCapability' verifyCapability'' uCap authorIdMsig (topicResource topicKey) AP.RoleAdmin
capability authorIdMsig (topicResource topicKey) AP.RoleAdmin
-- Find the collab that the member already has for me maybeNew <- withDBExcept $ do
existingCollabIDs <-
lift $ case memberDB of
Left (Entity personID _) ->
fmap (map $ over _1 Left) $
E.select $ E.from $ \ (collab `E.InnerJoin` recipl) -> do
E.on $
collab E.^. CollabId E.==.
recipl E.^. CollabRecipLocalCollab
E.where_ $
collab E.^. CollabTopic E.==. E.val resourceID E.&&.
recipl E.^. CollabRecipLocalPerson E.==. E.val personID
return
( recipl E.^. persistIdField
, recipl E.^. CollabRecipLocalCollab
)
Right (Entity remoteActorID _, _) ->
fmap (map $ over _1 Right) $
E.select $ E.from $ \ (collab `E.InnerJoin` recipr) -> do
E.on $
collab E.^. CollabId E.==.
recipr E.^. CollabRecipRemoteCollab
E.where_ $
collab E.^. CollabTopic E.==. E.val resourceID E.&&.
recipr E.^. CollabRecipRemoteActor E.==. E.val remoteActorID
return
( recipr E.^. persistIdField
, recipr E.^. CollabRecipRemoteCollab
)
(recipID, E.Value collabID) <-
case existingCollabIDs of
[] -> throwE "Remove object isn't a member of me"
[collab] -> return collab
_ -> error "Multiple collabs found for removee"
-- Verify the Collab is enabled -- Find project in our DB
maybeEnabled <- lift $ getBy $ UniqueCollabEnable collabID projectDB <-
Entity enableID (CollabEnable _ grantID) <- bitraverse
fromMaybeE maybeEnabled "Remove object isn't a member of me yet" (flip getEntityE "Member not found in DB")
(\ u@(ObjURI h lu) -> (,u) <$> do
maybeActor <- lift $ runMaybeT $ do
iid <- MaybeT $ getKeyBy $ UniqueInstance h
roid <- MaybeT $ getKeyBy $ UniqueRemoteObject iid lu
MaybeT $ getBy $ UniqueRemoteActor roid
fromMaybeE maybeActor "Remote removee not found in DB"
)
project
-- Verify that at least 1 more enabled Admin collab for me exists -- Grab me from DB
otherCollabIDs <- komponentID <- lift $ grabKomponent <$> getJust topicKey
lift $ E.select $ E.from $ \ (collab `E.InnerJoin` enable) -> do Komponent resourceID <- lift $ getJust komponentID
E.on $ Resource topicActorID <- lift $ getJust resourceID
collab E.^. CollabId E.==. topicActor <- lift $ getJust topicActorID
enable E.^. CollabEnableCollab
E.where_ $
collab E.^. CollabTopic E.==. E.val resourceID E.&&.
collab E.^. CollabId E.!=. E.val collabID
return $ collab E.^. CollabId
when (null otherCollabIDs) $
throwE "No other admins exist, can't remove"
maybeRemoveDB <- lift $ insertToInbox now authorIdMsig body (actorInbox topicActor) False -- Find my Stem record for this project
lift $ for maybeRemoveDB $ \ (inboxItemID, _removeDB) -> do existingStemIDs <-
lift $ case projectDB of
Left (Entity projectID _) ->
fmap (map $ over _1 Left) $
E.select $ E.from $ \ (stem `E.InnerJoin` project) -> do
E.on $ stem E.^. StemId E.==. project E.^. StemProjectLocalStem
E.where_ $
project E.^. StemProjectLocalProject E.==. E.val projectID E.&&.
stem E.^. StemHolder E.==. E.val komponentID
return
( project E.^. StemProjectLocalId
, project E.^. StemProjectLocalStem
)
Right (Entity remoteActorID _, _) ->
fmap (map $ over _1 Right) $
E.select $ E.from $ \ (stem `E.InnerJoin` project) -> do
E.on $ stem E.^. StemId E.==. project E.^. StemProjectRemoteStem
E.where_ $
project E.^. StemProjectRemoteProject E.==. E.val remoteActorID E.&&.
stem E.^. StemHolder E.==. E.val komponentID
return
( project E.^. StemProjectRemoteId
, project E.^. StemProjectRemoteStem
)
(recipID, E.Value stemID) <-
case existingStemIDs of
[] -> throwE "Remove object isn't a project of mine"
[stem] -> return stem
_ -> error "Multiple Stems found for removee"
-- Delete the whole Collab record -- Verify the Stem is enabled
deleteBy $ UniqueCollabDelegLocal enableID maybeDelegatorGrant <-
deleteBy $ UniqueCollabDelegRemote enableID lift $
delete enableID case recipID of
case recipID of Left (E.Value localID) -> fmap Left <$> getBy (UniqueStemProjectGrantLocalProject localID)
Left (E.Value l) -> do Right (E.Value remoteID) -> fmap Right <$> getBy (UniqueStemProjectGrantRemoteProject remoteID)
deleteBy $ UniqueCollabRecipLocalJoinCollab l delegatorGrant <- fromMaybeE maybeDelegatorGrant "Stem not enabled yet"
deleteBy $ UniqueCollabRecipLocalAcceptCollab l
delete l
Right (E.Value r) -> do
deleteBy $ UniqueCollabRecipRemoteJoinCollab r
deleteBy $ UniqueCollabRecipRemoteAcceptCollab r
delete r
fulfills <- do
mf <- runMaybeT $ asum
[ Left <$> MaybeT (getKeyBy $ UniqueCollabFulfillsLocalTopicCreation collabID)
, Right . Left <$> MaybeT (getKeyBy $ UniqueCollabFulfillsInvite collabID)
, Right . Right <$> MaybeT (getKeyBy $ UniqueCollabFulfillsJoin collabID)
]
maybe (error $ "No fulfills for collabID#" ++ show collabID) pure mf
case fulfills of
Left fc -> delete fc
Right (Left fi) -> do
deleteBy $ UniqueCollabInviterLocal fi
deleteBy $ UniqueCollabInviterRemote fi
delete fi
Right (Right fj) -> do
deleteBy $ UniqueCollabApproverLocal fj
deleteBy $ UniqueCollabApproverRemote fj
delete fj
delete collabID
-- Prepare forwarding Remove to my followers -- Grab start-Grant that I'm going to revoke
sieve <- lift $ do let componentAcceptID =
topicHash <- encodeKeyHashid topicKey case delegatorGrant of
let topicByHash = resourceToActor $ topicResource topicHash Left (Entity _ (StemProjectGrantLocal ca _ _)) -> ca
return $ makeRecipientSet [] [localActorFollowers topicByHash] Right (Entity _ (StemProjectGrantRemote ca _ _)) -> ca
Entity startID (StemDelegateLocal _ grantID) <- do
maybeStart <-
lift $ getBy $ UniqueStemDelegateLocal componentAcceptID
fromMaybeE maybeStart "Start-Grant not sent yet"
-- Prepare a Revoke activity and insert to my outbox maybeRemoveDB <- lift $ insertToInbox now authorIdMsig body (actorInbox topicActor) False
revoke@(actionRevoke, _, _, _) <- lift $ for maybeRemoveDB $ \ (inboxItemID, _removeDB) -> do
lift $ prepareRevoke memberDB grantID
let recipByKey = resourceToActor $ topicResource topicKey
revokeID <- insertEmptyOutboxItem' (actorOutbox topicActor) now
_luRevoke <- updateOutboxItem' recipByKey revokeID actionRevoke
return (topicActorID, sieve, revokeID, revoke, inboxItemID) -- Delete the whole Stem record
usOrThem <-
requireEitherAlt
(getKeyBy $ UniqueStemOriginAdd stemID)
(getKeyBy $ UniqueStemOriginInvite stemID)
"Neither us nor them"
"Both us and them"
case maybeNew of delete startID
Nothing -> done "I already have this activity in my inbox" case delegatorGrant of
Just (topicActorID, sieve, revokeID, (actionRevoke, localRecipsRevoke, remoteRecipsRevoke, fwdHostsRevoke), inboxItemID) -> do Left (Entity localID _) -> delete localID
let topicByID = resourceToActor $ topicResource topicKey Right (Entity remoteID _) -> delete remoteID
forwardActivity authorIdMsig body topicByID topicActorID sieve case usOrThem of
lift $ sendActivity Left usID -> delete usID
topicByID topicActorID localRecipsRevoke Right themID -> do
remoteRecipsRevoke fwdHostsRevoke revokeID actionRevoke deleteBy $ UniqueStemProjectAcceptLocal themID
doneDB inboxItemID "Deleted the Grant/Collab, forwarded Remove, sent Revoke" deleteBy $ UniqueStemProjectGestureRemote themID
deleteBy $ UniqueStemProjectGestureLocal themID
delete themID
delete componentAcceptID
deleteBy $ UniqueStemComponentGestureLocal stemID
deleteBy $ UniqueStemComponentGestureRemote stemID
case recipID of
Left (E.Value localID) -> delete localID
Right (E.Value remoteID) -> delete remoteID
delete stemID
where -- Prepare forwarding Remove to my followers
sieve <- lift $ do
topicHash <- encodeKeyHashid topicKey
let topicByHash = resourceToActor $ topicResource topicHash
return $ makeRecipientSet [] [localActorFollowers topicByHash]
prepareRevoke member grantID = do -- Prepare a Revoke activity and insert to my outbox
encodeRouteHome <- getEncodeRouteHome revoke@(actionRevoke, _, _, _) <-
encodeRouteLocal <- getEncodeRouteLocal lift $ prepareRevoke projectDB grantID
let recipByKey = resourceToActor $ topicResource topicKey
revokeID <- insertEmptyOutboxItem' (actorOutbox topicActor) now
_luRevoke <- updateOutboxItem' recipByKey revokeID actionRevoke
recipHash <- encodeKeyHashid topicKey return (topicActorID, sieve, revokeID, revoke, inboxItemID)
let topicByHash = resourceToActor $ topicResource recipHash
memberHash <- bitraverse (encodeKeyHashid . entityKey) pure member case maybeNew of
Nothing -> done "I already have this activity in my inbox"
Just (topicActorID, sieve, revokeID, (actionRevoke, localRecipsRevoke, remoteRecipsRevoke, fwdHostsRevoke), inboxItemID) -> do
let topicByID = resourceToActor $ topicResource topicKey
forwardActivity authorIdMsig body topicByID topicActorID sieve
lift $ sendActivity
topicByID topicActorID localRecipsRevoke
remoteRecipsRevoke fwdHostsRevoke revokeID actionRevoke
doneDB inboxItemID "[Project-active] Deleted the Stem, forwarded Remove, sent Revoke"
audRemover <- makeAudSenderOnly authorIdMsig where
let audience =
let audMember =
case memberHash of
Left p ->
AudLocal [LocalActorPerson p] [LocalStagePersonFollowers p]
Right (Entity _ actor, ObjURI h lu) ->
AudRemote h [lu] (maybeToList $ remoteActorFollowers actor)
audTopic = AudLocal [] [localActorFollowers topicByHash]
in [audRemover, audMember, audTopic]
(recipientSet, remoteActors, fwdHosts, audLocal, audRemote) = prepareRevoke project grantID = do
collectAudience audience encodeRouteHome <- getEncodeRouteHome
encodeRouteLocal <- getEncodeRouteLocal
recips = map encodeRouteHome audLocal ++ audRemote recipHash <- encodeKeyHashid topicKey
uRemove <- getActivityURI authorIdMsig let topicByHash = resourceToActor $ topicResource recipHash
luGrant <- do
grantHash <- encodeKeyHashid grantID projectHash <- bitraverse (encodeKeyHashid . entityKey) pure project
return $ encodeRouteLocal $ activityRoute topicByHash grantHash
let action = AP.Action audRemover <- makeAudSenderOnly authorIdMsig
{ AP.actionCapability = Nothing let audience =
, AP.actionSummary = Nothing let audProject =
, AP.actionAudience = AP.Audience recips [] [] [] [] [] case projectHash of
, AP.actionFulfills = [uRemove] Left j ->
, AP.actionSpecific = AP.RevokeActivity AP.Revoke AudLocal [LocalActorProject j] [LocalStageProjectFollowers j]
{ AP.revokeObject = luGrant :| [] Right (Entity _ actor, ObjURI h lu) ->
AudRemote h [lu] (maybeToList $ remoteActorFollowers actor)
audMe = AudLocal [] [localActorFollowers topicByHash]
in [audRemover, audProject, audMe]
(recipientSet, remoteActors, fwdHosts, audLocal, audRemote) =
collectAudience audience
recips = map encodeRouteHome audLocal ++ audRemote
uRemove <- getActivityURI authorIdMsig
luGrant <- do
grantHash <- encodeKeyHashid grantID
return $ encodeRouteLocal $ activityRoute topicByHash grantHash
let action = AP.Action
{ AP.actionCapability = Nothing
, AP.actionSummary = Nothing
, AP.actionAudience = AP.Audience recips [] [] [] [] []
, AP.actionFulfills = [uRemove]
, AP.actionSpecific = AP.RevokeActivity AP.Revoke
{ AP.revokeObject = luGrant :| []
}
} }
}
return (action, recipientSet, remoteActors, fwdHosts) return (action, recipientSet, remoteActors, fwdHosts)
removeProjectPassive _project = do
maybeNew <- withDBExcept $ do
-- Grab me from DB
komponentID <- lift $ grabKomponent <$> getJust topicKey
Komponent resourceID <- lift $ getJust komponentID
Resource topicActorID <- lift $ getJust resourceID
topicActor <- lift $ getJust topicActorID
maybeRemoveDB <- lift $ insertToInbox now authorIdMsig body (actorInbox topicActor) False
lift $ for maybeRemoveDB $ \ (inboxItemID, _removeDB) -> do
-- Prepare forwarding Remove to my followers
sieve <- lift $ do
topicHash <- encodeKeyHashid topicKey
let topicByHash = resourceToActor $ topicResource topicHash
return $ makeRecipientSet [] [localActorFollowers topicByHash]
return (topicActorID, sieve, inboxItemID)
case maybeNew of
Nothing -> done "I already have this activity in my inbox"
Just (topicActorID, sieve, inboxItemID) -> do
let topicByID = resourceToActor $ topicResource topicKey
forwardActivity authorIdMsig body topicByID topicActorID sieve
doneDB inboxItemID "[Project-passive] Just forwarded Remove"
topicJoin topicJoin
:: (PersistRecordBackend topic SqlBackend, ToBackendKey SqlBackend topic) :: (PersistRecordBackend topic SqlBackend, ToBackendKey SqlBackend topic)

View file

@ -627,24 +627,13 @@ deckInvite
-> ActE (Text, Act (), Next) -> ActE (Text, Act (), Next)
deckInvite = componentInvite deckKomponent ComponentDeck deckInvite = componentInvite deckKomponent ComponentDeck
-- Meaning: An actor A is removing actor B from a resource
-- Behavior:
-- * Verify the resource is me
-- * Verify A isn't removing themselves
-- * Verify A is authorized by me to remove actors from me
-- * Verify B already has a Grant for me
-- * Remove the whole Collab record from DB
-- * Forward the Remove to my followers
-- * Send a Revoke:
-- * To: Actor B
-- * CC: Actor A, B's followers, my followers
deckRemove deckRemove
:: UTCTime :: UTCTime
-> DeckId -> DeckId
-> Verse -> Verse
-> AP.Remove URIMode -> AP.Remove URIMode
-> ActE (Text, Act (), Next) -> ActE (Text, Act (), Next)
deckRemove = topicRemove deckResource LocalResourceDeck deckRemove = componentRemove deckKomponent ComponentDeck
-- Meaning: An actor A asked to join a resource -- Meaning: An actor A asked to join a resource
-- Behavior: -- Behavior: