S2S: Person: Accept: If topic is approving an Invite, update Permit record
This commit is contained in:
parent
442e36dcc1
commit
39dc2089b2
3 changed files with 123 additions and 5 deletions
|
@ -1,6 +1,6 @@
|
||||||
{- This file is part of Vervis.
|
{- This file is part of Vervis.
|
||||||
-
|
-
|
||||||
- Written in 2016, 2019 by fr33domlover <fr33domlover@riseup.net>.
|
- Written in 2016, 2019, 2023 by fr33domlover <fr33domlover@riseup.net>.
|
||||||
-
|
-
|
||||||
- ♡ Copying is an act of love. Please copy, reuse and share.
|
- ♡ Copying is an act of love. Please copy, reuse and share.
|
||||||
-
|
-
|
||||||
|
@ -16,9 +16,12 @@
|
||||||
module Data.Maybe.Local
|
module Data.Maybe.Local
|
||||||
( partitionMaybes
|
( partitionMaybes
|
||||||
, partitionMaybePairs
|
, partitionMaybePairs
|
||||||
|
, exactlyOneJust
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
|
import Data.Maybe
|
||||||
|
|
||||||
partitionMaybes :: [(Maybe a, b)] -> ([(a, b)], [b])
|
partitionMaybes :: [(Maybe a, b)] -> ([(a, b)], [b])
|
||||||
partitionMaybes = foldr f ([], [])
|
partitionMaybes = foldr f ([], [])
|
||||||
where
|
where
|
||||||
|
@ -32,3 +35,10 @@ partitionMaybePairs = foldr f ([], [], [])
|
||||||
f (Just x, Nothing) (xs, ys, ps) = (x : xs, ys, ps)
|
f (Just x, Nothing) (xs, ys, ps) = (x : xs, ys, ps)
|
||||||
f (Nothing, Just y) (xs, ys, ps) = (xs, y : ys, ps)
|
f (Nothing, Just y) (xs, ys, ps) = (xs, y : ys, ps)
|
||||||
f (Just x, Just y) (xs, ys, ps) = (xs, ys, (x, y) : ps)
|
f (Just x, Just y) (xs, ys, ps) = (xs, ys, (x, y) : ps)
|
||||||
|
|
||||||
|
exactlyOneJust :: Monad m => [Maybe a] -> String -> String -> m a
|
||||||
|
exactlyOneJust l none multiple =
|
||||||
|
case catMaybes l of
|
||||||
|
[] -> error none
|
||||||
|
[x] -> pure x
|
||||||
|
_ -> error multiple
|
||||||
|
|
|
@ -19,6 +19,7 @@ module Vervis.Actor.Person
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
|
import Control.Applicative
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
import Control.Monad.IO.Class
|
import Control.Monad.IO.Class
|
||||||
import Control.Monad.Logger.CallStack
|
import Control.Monad.Logger.CallStack
|
||||||
|
@ -274,7 +275,13 @@ personUndo now recipPersonID (Verse authorIdMsig body) (AP.Undo uObject) = do
|
||||||
-- Meaning: An actor accepted something
|
-- Meaning: An actor accepted something
|
||||||
-- Behavior:
|
-- Behavior:
|
||||||
-- * Insert to my inbox
|
-- * Insert to my inbox
|
||||||
-- * If it's a Follow I sent to them, add to my following list in DB
|
-- * If it's on a Follow I sent to them:
|
||||||
|
-- * Add to my following list in DB
|
||||||
|
-- * If it's on an Invite-for-me to collaborate on a resource:
|
||||||
|
-- * Verify I haven't yet seen the resource's accept
|
||||||
|
-- * Verify the Accept author is the resource
|
||||||
|
-- * Store it in the Permit record in DB
|
||||||
|
-- * Forward to my followers
|
||||||
personAccept
|
personAccept
|
||||||
:: UTCTime
|
:: UTCTime
|
||||||
-> PersonId
|
-> PersonId
|
||||||
|
@ -299,13 +306,22 @@ personAccept now recipPersonID (Verse authorIdMsig body) accept = do
|
||||||
-- Find the accepted activity in our DB
|
-- Find the accepted activity in our DB
|
||||||
accepteeDB <- MaybeT $ getActivity acceptee
|
accepteeDB <- MaybeT $ getActivity acceptee
|
||||||
|
|
||||||
tryFollow (personActor personRecip) accepteeDB acceptDB
|
let recipActorID = personActor personRecip
|
||||||
|
Left <$> tryFollow recipActorID accepteeDB acceptDB <|>
|
||||||
|
Right <$> tryInvite recipActorID accepteeDB acceptDB
|
||||||
|
|
||||||
case maybeNew of
|
case maybeNew of
|
||||||
Nothing -> done "I already have this activity in my inbox"
|
Nothing -> done "I already have this activity in my inbox"
|
||||||
Just Nothing -> done "Not my Follow; Just inserted to my inbox"
|
Just Nothing -> done "Not my Follow/Invite; Just inserted to my inbox"
|
||||||
Just (Just ()) ->
|
Just (Just (Left ())) ->
|
||||||
done "Recorded this Accept on the Follow request I sent"
|
done "Recorded this Accept on the Follow request I sent"
|
||||||
|
Just (Just (Right (actorID, sieve))) -> do
|
||||||
|
forwardActivity
|
||||||
|
authorIdMsig body (LocalActorPerson recipPersonID)
|
||||||
|
actorID sieve
|
||||||
|
done
|
||||||
|
"Recorded this Accept on the Invite I've had & \
|
||||||
|
\forwarded to my followers"
|
||||||
|
|
||||||
where
|
where
|
||||||
|
|
||||||
|
@ -360,6 +376,56 @@ personAccept now recipPersonID (Verse authorIdMsig body) accept = do
|
||||||
-}
|
-}
|
||||||
tryFollow _ (Right _) _ = mzero
|
tryFollow _ (Right _) _ = mzero
|
||||||
|
|
||||||
|
tryInvite recipActorID accepteeDB acceptDB = do
|
||||||
|
|
||||||
|
-- Find a PermitFulfillsInvite
|
||||||
|
(permitID, fulfillsID) <-
|
||||||
|
case accepteeDB of
|
||||||
|
Left (actorByKey, _actorEntity, itemID) -> do
|
||||||
|
PermitTopicGestureLocal fulfillsID _ <-
|
||||||
|
MaybeT $ lift $ getValBy $ UniquePermitTopicGestureLocalInvite itemID
|
||||||
|
PermitFulfillsInvite permitID <- lift . lift $ getJust fulfillsID
|
||||||
|
return (permitID, fulfillsID)
|
||||||
|
Right remoteActivityID -> do
|
||||||
|
PermitTopicGestureRemote fulfillsID _ _ <-
|
||||||
|
MaybeT $ lift $ getValBy $ UniquePermitTopicGestureRemoteInvite remoteActivityID
|
||||||
|
PermitFulfillsInvite permitID <- lift . lift $ getJust fulfillsID
|
||||||
|
return (permitID, fulfillsID)
|
||||||
|
|
||||||
|
-- Find the local person and verify it's me
|
||||||
|
Permit p _role <- lift . lift $ getJust permitID
|
||||||
|
guard $ p == recipPersonID
|
||||||
|
|
||||||
|
lift $ do
|
||||||
|
-- Find the topic
|
||||||
|
topic <- lift $ getPermitTopic permitID
|
||||||
|
|
||||||
|
-- Verify I haven't seen the topic's accept yet
|
||||||
|
maybeTopicAccept <-
|
||||||
|
lift $ case bimap fst fst topic of
|
||||||
|
Left localID -> void <$> getBy (UniquePermitTopicAcceptLocalTopic localID)
|
||||||
|
Right remoteID -> void <$> getBy (UniquePermitTopicAcceptRemoteTopic remoteID)
|
||||||
|
unless (isNothing maybeTopicAccept) $
|
||||||
|
throwE "I've already seen the topic's Accept"
|
||||||
|
|
||||||
|
-- Verify topic is the Accept sender
|
||||||
|
case (bimap snd snd topic, bimap (view _1) (view _1) acceptDB) of
|
||||||
|
(Left la, Left la') | la == la' -> pure ()
|
||||||
|
(Right raID, Right ra) | raID == remoteAuthorId ra -> pure ()
|
||||||
|
_ -> throwE "Accept sender isn't the Invite topic"
|
||||||
|
|
||||||
|
-- Update the Permit record
|
||||||
|
lift $ case (bimap fst fst topic, bimap (view _3) (view _3) acceptDB) of
|
||||||
|
(Left localID, Left acceptID) -> insert_ $ PermitTopicAcceptLocal fulfillsID localID acceptID
|
||||||
|
(Right remoteID, Right acceptID) -> insert_ $ PermitTopicAcceptRemote fulfillsID remoteID acceptID
|
||||||
|
_ -> error "personAccept impossible"
|
||||||
|
|
||||||
|
-- Prepare forwarding Accept to my followers
|
||||||
|
recipPersonHash <- encodeKeyHashid recipPersonID
|
||||||
|
let sieve = makeRecipientSet [] [LocalStagePersonFollowers recipPersonHash]
|
||||||
|
|
||||||
|
return (recipActorID, sieve)
|
||||||
|
|
||||||
-- Meaning: An actor rejected something
|
-- Meaning: An actor rejected something
|
||||||
-- Behavior:
|
-- Behavior:
|
||||||
-- * Insert to my inbox
|
-- * Insert to my inbox
|
||||||
|
|
|
@ -17,6 +17,7 @@ module Vervis.Persist.Collab
|
||||||
( getCollabTopic
|
( getCollabTopic
|
||||||
, getCollabTopic'
|
, getCollabTopic'
|
||||||
, getCollabRecip
|
, getCollabRecip
|
||||||
|
, getPermitTopic
|
||||||
, getStemIdent
|
, getStemIdent
|
||||||
, getStemProject
|
, getStemProject
|
||||||
, getGrantRecip
|
, getGrantRecip
|
||||||
|
@ -64,6 +65,7 @@ import qualified Web.ActivityPub as AP
|
||||||
|
|
||||||
import Control.Monad.Trans.Except.Local
|
import Control.Monad.Trans.Except.Local
|
||||||
import Data.Either.Local
|
import Data.Either.Local
|
||||||
|
import Data.Maybe.Local
|
||||||
import Database.Persist.Local
|
import Database.Persist.Local
|
||||||
|
|
||||||
import Vervis.Actor
|
import Vervis.Actor
|
||||||
|
@ -110,6 +112,46 @@ getCollabRecip collabID =
|
||||||
"Collab without recip"
|
"Collab without recip"
|
||||||
"Collab with both local and remote recip"
|
"Collab with both local and remote recip"
|
||||||
|
|
||||||
|
getPermitTopic
|
||||||
|
:: MonadIO m
|
||||||
|
=> PermitId
|
||||||
|
-> ReaderT SqlBackend m
|
||||||
|
(Either
|
||||||
|
(PermitTopicLocalId, LocalActorBy Key)
|
||||||
|
(PermitTopicRemoteId, RemoteActorId)
|
||||||
|
)
|
||||||
|
getPermitTopic permitID = do
|
||||||
|
topic <-
|
||||||
|
requireEitherAlt
|
||||||
|
(getKeyBy $ UniquePermitTopicLocal permitID)
|
||||||
|
(getBy $ UniquePermitTopicRemote permitID)
|
||||||
|
"Permit without topic"
|
||||||
|
"Permit with both local and remote topic"
|
||||||
|
bitraverse
|
||||||
|
(\ localID -> (localID,) <$> do
|
||||||
|
options <-
|
||||||
|
sequence
|
||||||
|
[ fmap (LocalActorRepo . permitTopicRepoRepo) <$>
|
||||||
|
getValBy (UniquePermitTopicRepo localID)
|
||||||
|
, fmap (LocalActorDeck . permitTopicDeckDeck) <$>
|
||||||
|
getValBy (UniquePermitTopicDeck localID)
|
||||||
|
, fmap (LocalActorLoom . permitTopicLoomLoom) <$>
|
||||||
|
getValBy (UniquePermitTopicLoom localID)
|
||||||
|
, fmap (LocalActorProject . permitTopicProjectProject) <$>
|
||||||
|
getValBy (UniquePermitTopicProject localID)
|
||||||
|
, fmap (LocalActorGroup . permitTopicGroupGroup) <$>
|
||||||
|
getValBy (UniquePermitTopicGroup localID)
|
||||||
|
]
|
||||||
|
exactlyOneJust
|
||||||
|
options
|
||||||
|
"Found Permit without topic"
|
||||||
|
"Found Permit with multiple topics"
|
||||||
|
)
|
||||||
|
(\ (Entity topicID (PermitTopicRemote _ actorID)) ->
|
||||||
|
return (topicID, actorID)
|
||||||
|
)
|
||||||
|
topic
|
||||||
|
|
||||||
getStemIdent :: MonadIO m => StemId -> ReaderT SqlBackend m (ComponentBy Key)
|
getStemIdent :: MonadIO m => StemId -> ReaderT SqlBackend m (ComponentBy Key)
|
||||||
getStemIdent stemID = do
|
getStemIdent stemID = do
|
||||||
maybeRepo <- getValBy $ UniqueStemIdentRepo stemID
|
maybeRepo <- getValBy $ UniqueStemIdentRepo stemID
|
||||||
|
|
Loading…
Reference in a new issue