mirror of
https://code.sup39.dev/repos/Wqawg
synced 2024-12-27 19:24:52 +09:00
Person: Port Undo{Follow} handler
This commit is contained in:
parent
552ef760e6
commit
b4ebd08c5a
2 changed files with 100 additions and 146 deletions
|
@ -29,6 +29,7 @@ import Control.Monad.Trans.Class
|
|||
import Control.Monad.Trans.Except
|
||||
import Control.Monad.Trans.Maybe
|
||||
import Control.Monad.Trans.Reader
|
||||
import Data.Bifunctor
|
||||
import Data.Bitraversable
|
||||
import Data.ByteString (ByteString)
|
||||
import Data.Foldable
|
||||
|
@ -217,6 +218,101 @@ personFollow now recipPersonID author body mfwd luFollow follow = do
|
|||
(\ () -> pure [])
|
||||
now recipPersonID author body mfwd luFollow follow
|
||||
|
||||
-- Meaning: A remote actor is undoing some previous action
|
||||
-- Behavior:
|
||||
-- * Insert to my inbox
|
||||
-- * If they're undoing their Following of me:
|
||||
-- * Record it in my DB
|
||||
-- * Publish and send an Accept only to the sender
|
||||
personUndo
|
||||
:: UTCTime
|
||||
-> PersonId
|
||||
-> RemoteAuthor
|
||||
-> ActivityBody
|
||||
-> Maybe (RecipientRoutes, ByteString)
|
||||
-> LocalURI
|
||||
-> AP.Undo URIMode
|
||||
-> ActE (Text, Act (), Next)
|
||||
personUndo now recipPersonID author body _mfwd luUndo (AP.Undo uObject) = do
|
||||
|
||||
-- Check input
|
||||
undone <-
|
||||
first (\ (actor, _, item) -> (actor, item)) <$>
|
||||
parseActivityURI' uObject
|
||||
|
||||
maybeUndo <- withDBExcept $ do
|
||||
|
||||
-- Grab recipient person from DB
|
||||
(personRecip, actorRecip) <- lift $ do
|
||||
p <- getJust recipPersonID
|
||||
(p,) <$> getJust (personActor p)
|
||||
|
||||
-- Insert the Undo to person's inbox
|
||||
mractid <- lift $ insertToInbox now author body (actorInbox actorRecip) luUndo False
|
||||
for mractid $ \ undoID -> do
|
||||
|
||||
maybeUndo <- runMaybeT $ do
|
||||
|
||||
-- Find the undone activity in our DB
|
||||
undoneDB <- MaybeT $ getActivity undone
|
||||
|
||||
let followers = actorFollowers actorRecip
|
||||
tryUnfollow followers undoneDB
|
||||
|
||||
for maybeUndo $ \ () -> do
|
||||
|
||||
-- Prepare an Accept activity and insert to person's outbox
|
||||
acceptID <- lift $ insertEmptyOutboxItem' (actorOutbox actorRecip) now
|
||||
accept@(actionAccept, _, _, _) <- lift $ lift prepareAccept
|
||||
_luAccept <- lift $ updateOutboxItem' (LocalActorPerson recipPersonID) acceptID actionAccept
|
||||
|
||||
return (personActor personRecip, acceptID, accept)
|
||||
|
||||
case maybeUndo of
|
||||
Nothing -> done "I already have this activity in my inbox"
|
||||
Just Nothing -> done "Unrelated to me, just inserted to inbox"
|
||||
Just (Just (actorID, acceptID, (actionAccept, localRecipsAccept, remoteRecipsAccept, fwdHostsAccept))) -> do
|
||||
lift $ sendActivity
|
||||
(LocalActorPerson recipPersonID) actorID localRecipsAccept
|
||||
remoteRecipsAccept fwdHostsAccept acceptID
|
||||
EventAcceptRemoteFollow actionAccept
|
||||
done "Undid the Follow and published Accept"
|
||||
|
||||
where
|
||||
|
||||
tryUnfollow _ (Left _) = mzero
|
||||
tryUnfollow personFollowersID (Right remoteActivityID) = do
|
||||
Entity remoteFollowID remoteFollow <-
|
||||
MaybeT $ lift $ getBy $ UniqueRemoteFollowFollow remoteActivityID
|
||||
let followerID = remoteFollowActor remoteFollow
|
||||
followerSetID = remoteFollowTarget remoteFollow
|
||||
guard $ followerSetID == personFollowersID
|
||||
unless (followerID == remoteAuthorId author) $
|
||||
lift $ throwE "You're trying to Undo someone else's Follow"
|
||||
lift $ lift $ delete remoteFollowID
|
||||
|
||||
prepareAccept = do
|
||||
encodeRouteHome <- getEncodeRouteHome
|
||||
|
||||
let ObjURI hAuthor luAuthor = remoteAuthorURI author
|
||||
audSender = AudRemote hAuthor [luAuthor] []
|
||||
(recipientSet, remoteActors, fwdHosts, audLocal, audRemote) =
|
||||
collectAudience [audSender]
|
||||
|
||||
recips = map encodeRouteHome audLocal ++ audRemote
|
||||
action = AP.Action
|
||||
{ AP.actionCapability = Nothing
|
||||
, AP.actionSummary = Nothing
|
||||
, AP.actionAudience = AP.Audience recips [] [] [] [] []
|
||||
, AP.actionFulfills = []
|
||||
, AP.actionSpecific = AP.AcceptActivity AP.Accept
|
||||
{ AP.acceptObject = ObjURI hAuthor luUndo
|
||||
, AP.acceptResult = Nothing
|
||||
}
|
||||
}
|
||||
|
||||
return (action, recipientSet, remoteActors, fwdHosts)
|
||||
|
||||
-- Meaning: A remote actor accepted something
|
||||
-- Behavior:
|
||||
-- * Insert to my inbox
|
||||
|
@ -620,10 +716,8 @@ personBehavior now personID (Right (VerseRemote author body mfwd luActivity)) =
|
|||
personInvite now personID author body mfwd luActivity invite
|
||||
AP.JoinActivity join ->
|
||||
personJoin now personID author body mfwd luActivity join
|
||||
{-
|
||||
AP.UndoActivity undo ->
|
||||
(,Nothing) <$> personUndoA now personID author body mfwd luActivity undo
|
||||
-}
|
||||
AP.RejectActivity reject ->
|
||||
personReject now personID author body mfwd luActivity reject
|
||||
AP.UndoActivity undo ->
|
||||
personUndo now personID author body mfwd luActivity undo
|
||||
_ -> throwE "Unsupported activity type for Person"
|
||||
|
|
|
@ -25,8 +25,8 @@ module Vervis.Federation.Offer
|
|||
--, loomFollowF
|
||||
--, repoFollowF
|
||||
|
||||
personUndoF
|
||||
, deckUndoF
|
||||
--personUndoF
|
||||
deckUndoF
|
||||
, loomUndoF
|
||||
, repoUndoF
|
||||
)
|
||||
|
@ -550,146 +550,6 @@ repoFollowF now recipRepoHash =
|
|||
recipRepoHash
|
||||
-}
|
||||
|
||||
personUndoF
|
||||
:: UTCTime
|
||||
-> KeyHashid Person
|
||||
-> RemoteAuthor
|
||||
-> ActivityBody
|
||||
-> Maybe (RecipientRoutes, ByteString)
|
||||
-> LocalURI
|
||||
-> AP.Undo URIMode
|
||||
-> ExceptT Text Handler Text
|
||||
personUndoF now recipPersonHash author body mfwd luUndo (AP.Undo uObject) = do
|
||||
|
||||
-- Check input
|
||||
recipPersonID <- decodeKeyHashid404 recipPersonHash
|
||||
undone <-
|
||||
first (\ (actor, _, item) -> (actor, item)) <$>
|
||||
parseActivityURI uObject
|
||||
|
||||
-- Verify the capability URI, if provided, is one of:
|
||||
-- * Outbox item URI of a local actor, i.e. a local activity
|
||||
-- * A remote URI
|
||||
maybeCapability <-
|
||||
for (AP.activityCapability $ actbActivity body) $ \ uCap ->
|
||||
nameExceptT "Undo capability" $
|
||||
first (\ (actor, _, item) -> (actor, item)) <$>
|
||||
parseActivityURI uCap
|
||||
|
||||
maybeHttp <- runDBExcept $ do
|
||||
|
||||
-- Find recipient person in DB, returning 404 if doesn't exist because we're
|
||||
-- in the person's inbox post handler
|
||||
(recipPersonActorID, recipPersonActor) <- lift $ do
|
||||
person <- get404 recipPersonID
|
||||
let actorID = personActor person
|
||||
(actorID,) <$> getJust actorID
|
||||
|
||||
-- Insert the Undo to person's inbox
|
||||
mractid <- lift $ insertToInbox now author body (actorInbox recipPersonActor) luUndo False
|
||||
for mractid $ \ undoID -> do
|
||||
|
||||
maybeUndo <- runMaybeT $ do
|
||||
|
||||
-- Find the undone activity in our DB
|
||||
undoneDB <- MaybeT $ getActivity undone
|
||||
|
||||
let followers = actorFollowers recipPersonActor
|
||||
MaybeT $ lift $ runMaybeT $ tryUnfollow followers undoneDB
|
||||
|
||||
for maybeUndo $ \ (remoteFollowID, followerID) -> do
|
||||
|
||||
(sieve, acceptAudience) <- do
|
||||
(audSenderOnly, _audSenderAndFollowers) <- do
|
||||
ra <- lift $ getJust $ remoteAuthorId author
|
||||
let ObjURI hAuthor luAuthor = remoteAuthorURI author
|
||||
return
|
||||
( AudRemote hAuthor [luAuthor] []
|
||||
, AudRemote hAuthor
|
||||
[luAuthor]
|
||||
(maybeToList $ remoteActorFollowers ra)
|
||||
)
|
||||
unless (followerID == remoteAuthorId author) $
|
||||
throwE "Trying to undo someone else's Follow"
|
||||
lift $ delete remoteFollowID
|
||||
return
|
||||
( makeRecipientSet [] []
|
||||
, [audSenderOnly]
|
||||
)
|
||||
|
||||
-- Forward the Undo activity to relevant local stages, and
|
||||
-- schedule delivery for unavailable remote members of them
|
||||
maybeHttpFwdUndo <- lift $ for mfwd $ \ (localRecips, sig) ->
|
||||
forwardActivityDB
|
||||
(actbBL body) localRecips sig recipPersonActorID
|
||||
(LocalActorPerson recipPersonHash) sieve undoID
|
||||
|
||||
|
||||
-- Prepare an Accept activity and insert to person's outbox
|
||||
acceptID <- lift $ insertEmptyOutboxItem (actorOutbox recipPersonActor) now
|
||||
(actionAccept, localRecipsAccept, remoteRecipsAccept, fwdHostsAccept) <-
|
||||
lift . lift $ prepareAccept acceptAudience
|
||||
_luAccept <- lift $ updateOutboxItem (LocalActorPerson recipPersonID) acceptID actionAccept
|
||||
|
||||
-- Deliver the Accept to local recipients, and schedule delivery
|
||||
-- for unavailable remote recipients
|
||||
deliverHttpAccept <-
|
||||
deliverActivityDB
|
||||
(LocalActorPerson recipPersonHash) recipPersonActorID
|
||||
localRecipsAccept remoteRecipsAccept fwdHostsAccept
|
||||
acceptID actionAccept
|
||||
|
||||
-- Return instructions for HTTP inbox-forwarding of the Undo
|
||||
-- activity, and for HTTP delivery of the Accept activity to
|
||||
-- remote recipients
|
||||
return (maybeHttpFwdUndo, deliverHttpAccept)
|
||||
|
||||
-- Launch asynchronous HTTP forwarding of the Undo activity and HTTP
|
||||
-- delivery of the Accept activity
|
||||
case maybeHttp of
|
||||
Nothing -> return "I already have this activity in my inbox, doing nothing"
|
||||
Just Nothing -> return "Unrelated to me, just inserted to inbox"
|
||||
Just (Just (maybeHttpFwdUndo, deliverHttpAccept)) -> do
|
||||
forkWorker "personUndoF Accept HTTP delivery" deliverHttpAccept
|
||||
case maybeHttpFwdUndo of
|
||||
Nothing -> return "Undid, no inbox-forwarding to do"
|
||||
Just forwardHttpUndo -> do
|
||||
forkWorker "personUndoF inbox-forwarding" forwardHttpUndo
|
||||
return "Undid and ran inbox-forwarding of the Undo"
|
||||
|
||||
where
|
||||
|
||||
tryUnfollow _ (Left _) = mzero
|
||||
tryUnfollow personFollowersID (Right remoteActivityID) = do
|
||||
Entity remoteFollowID remoteFollow <-
|
||||
MaybeT $ getBy $ UniqueRemoteFollowFollow remoteActivityID
|
||||
let followerID = remoteFollowActor remoteFollow
|
||||
followerSetID = remoteFollowTarget remoteFollow
|
||||
guard $ followerSetID == personFollowersID
|
||||
return (remoteFollowID, followerID)
|
||||
|
||||
prepareAccept audience = do
|
||||
encodeRouteHome <- getEncodeRouteHome
|
||||
|
||||
let ObjURI hAuthor _ = remoteAuthorURI author
|
||||
|
||||
(recipientSet, remoteActors, fwdHosts, audLocal, audRemote) =
|
||||
collectAudience audience
|
||||
|
||||
recips = map encodeRouteHome audLocal ++ audRemote
|
||||
action = AP.Action
|
||||
{ AP.actionCapability = Nothing
|
||||
, AP.actionSummary = Nothing
|
||||
, AP.actionAudience = AP.Audience recips [] [] [] [] []
|
||||
, AP.actionFulfills = []
|
||||
, AP.actionSpecific = AP.AcceptActivity AP.Accept
|
||||
{ AP.acceptObject = ObjURI hAuthor luUndo
|
||||
, AP.acceptResult = Nothing
|
||||
}
|
||||
}
|
||||
|
||||
return (action, recipientSet, remoteActors, fwdHosts)
|
||||
|
||||
deckUndoF
|
||||
:: UTCTime
|
||||
-> KeyHashid Deck
|
||||
|
|
Loading…
Reference in a new issue