1
0
Fork 0
mirror of https://code.naskya.net/repos/ndqEd synced 2025-01-10 11:26:45 +09:00

S2S: Support commenting on sharer-patch and repo-patch

This commit is contained in:
fr33domlover 2020-05-27 14:07:02 +00:00
parent cf946e0326
commit 3fb529325d
4 changed files with 221 additions and 20 deletions

View file

@ -37,6 +37,7 @@ import Control.Monad.Trans.Reader
import Crypto.Hash
import Data.Aeson
import Data.Bifunctor
import Data.Bitraversable
import Data.ByteString (ByteString)
import Data.Either
import Data.Foldable
@ -111,6 +112,7 @@ import Vervis.Model.Ident
import Vervis.Model.Ticket
import Vervis.RemoteActorStore
import Vervis.Settings
import Vervis.Patch
import Vervis.Ticket
verifyIsLoggedInUser
@ -201,29 +203,44 @@ createNoteC (Entity pidUser personUser) sharerUser summary audience note = runEx
let actors =
case mproject of
Nothing -> []
Just (shr, prj) -> [LocalActorProject shr prj]
Just (Left (shr, prj)) -> [LocalActorProject shr prj]
Just (Right (shr, rp)) -> [LocalActorRepo shr rp]
collections =
let project =
case mproject of
Nothing -> []
Just (shr, prj) ->
Just (Left (shr, prj)) ->
[ LocalPersonCollectionProjectTeam shr prj
, LocalPersonCollectionProjectFollowers shr prj
]
Just (Right (shr, rp)) ->
[ LocalPersonCollectionRepoTeam shr rp
, LocalPersonCollectionRepoFollowers shr rp
]
ticket =
case context of
Left nc ->
case nc of
NoteContextSharerTicket shr talid ->
NoteContextSharerTicket shr talid False ->
let talkhid = hashTAL talid
in [ -- LocalPersonCollectionSharerTicketTeam shr talkhid
LocalPersonCollectionSharerTicketFollowers shr talkhid
]
NoteContextSharerTicket shr talid True ->
let talkhid = hashTAL talid
in [ -- LocalPersonCollectionSharerPatchTeam shr talkhid
LocalPersonCollectionSharerPatchFollowers shr talkhid
]
NoteContextProjectTicket shr prj ltid ->
let ltkhid = hashLT ltid
in [ -- LocalPersonCollectionProjectTicketTeam shr prj ltkhid
LocalPersonCollectionProjectTicketFollowers shr prj ltkhid
]
NoteContextRepoPatch shr rp ltid ->
let ltkhid = hashLT ltid
in [ -- LocalPersonCollectionRepoPatchTeam shr rp ltkhid
LocalPersonCollectionRepoPatchFollowers shr rp ltkhid
]
Right _ -> []
commenter = [LocalPersonCollectionSharerFollowers shrUser]
in project ++ ticket ++ commenter
@ -251,15 +268,25 @@ createNoteC (Entity pidUser personUser) sharerUser summary audience note = runEx
parseTopic name route =
case route of
SharerTicketR shr talkhid ->
NoteContextSharerTicket shr <$>
flip (NoteContextSharerTicket shr) False <$>
decodeKeyHashidE
talkhid
(name <> " sharer ticket invalid talkhid")
SharerPatchR shr talkhid ->
flip (NoteContextSharerTicket shr) True <$>
decodeKeyHashidE
talkhid
(name <> " sharer patch invalid talkhid")
ProjectTicketR shr prj ltkhid ->
NoteContextProjectTicket shr prj <$>
decodeKeyHashidE
ltkhid
(name <> " project ticket invalid ltkhid")
RepoPatchR shr rp ltkhid ->
NoteContextRepoPatch shr rp <$>
decodeKeyHashidE
ltkhid
(name <> " repo patch invalid ltkhid")
_ -> throwE $ name <> " isn't a discussion topic route"
parseNoteContext u@(ObjURI h lu) = do
hl <- hostIsLocal h
@ -306,7 +333,7 @@ createNoteC (Entity pidUser personUser) sharerUser summary audience note = runEx
unless (any ((== h) . fst) remoteRecips) $
throwE
"Context is remote but no recipients of that host are listed"
verifyContextRecip (Left (NoteContextSharerTicket shr _)) localRecips _ =
verifyContextRecip (Left (NoteContextSharerTicket shr _ _)) localRecips _ =
fromMaybeE
verify
"Local context ticket's hosting sharer isn't listed as a recipient"
@ -323,6 +350,15 @@ createNoteC (Entity pidUser personUser) sharerUser summary audience note = runEx
sharerSet <- lookup shr localRecips
projectSet <- lookup prj $ localRecipProjectRelated sharerSet
guard $ localRecipProject $ localRecipProjectDirect projectSet
verifyContextRecip (Left (NoteContextRepoPatch shr rp _)) localRecips _ =
fromMaybeE
verify
"Local context patch's hosting repo isn't listed as a recipient"
where
verify = do
sharerSet <- lookup shr localRecips
repoSet <- lookup rp $ localRecipRepoRelated sharerSet
guard $ localRecipRepo $ localRecipRepoDirect repoSet
insertEmptyOutboxItem obid now = do
h <- asksSite siteInstanceHost
insert OutboxItem
@ -334,23 +370,41 @@ createNoteC (Entity pidUser personUser) sharerUser summary audience note = runEx
j <- getJust $ ticketProjectLocalProject tpl
s <- getJust $ projectSharer j
return (sharerIdent s, projectIdent j)
getRepo trl = do
r <- getJust $ ticketRepoLocalRepo trl
s <- getJust $ repoSharer r
return (sharerIdent s, repoIdent r)
getTopicAndParent (Left context) mparent = do
(mproject, did) <-
case context of
NoteContextSharerTicket shr talid -> do
NoteContextSharerTicket shr talid False -> do
(_, Entity _ lt, _, project) <- do
mticket <- lift $ getSharerTicket shr talid
fromMaybeE mticket "Note context no such local sharer-hosted ticket"
mproj <-
case project of
Left (_, Entity _ tpl) -> lift $ Just <$> getProject tpl
Left (_, Entity _ tpl) -> lift $ Just . Left <$> getProject tpl
Right _ -> return Nothing
return (mproj, localTicketDiscuss lt)
NoteContextSharerTicket shr talid True -> do
(_, Entity _ lt, _, repo, _) <- do
mticket <- lift $ getSharerPatch shr talid
fromMaybeE mticket "Note context no such local sharer-hosted patch"
mproj <-
case repo of
Left (_, Entity _ trl) -> lift $ Just . Right <$> getRepo trl
Right _ -> return Nothing
return (mproj, localTicketDiscuss lt)
NoteContextProjectTicket shr prj ltid -> do
(_, _, _, Entity _ lt, _, _, _) <- do
mticket <- lift $ getProjectTicket shr prj ltid
fromMaybeE mticket "Note context no such local project-hosted ticket"
return (Just (shr, prj), localTicketDiscuss lt)
return (Just $ Left (shr, prj), localTicketDiscuss lt)
NoteContextRepoPatch shr rp ltid -> do
(_, _, _, Entity _ lt, _, _, _, _) <- do
mticket <- lift $ getRepoPatch shr rp ltid
fromMaybeE mticket "Note context no such local project-hosted ticket"
return (Just $ Right (shr, rp), localTicketDiscuss lt)
mmidParent <- for mparent $ \ parent ->
case parent of
Left (shrParent, lmidParent) -> getLocalParentMessageId did shrParent lmidParent
@ -377,9 +431,14 @@ createNoteC (Entity pidUser personUser) sharerUser summary audience note = runEx
rt <- MaybeT $ getValBy $ UniqueRemoteTicketDiscuss rdid
tar <- lift $ getJust $ remoteTicketTicket rt
let tclid = ticketAuthorRemoteTicket tar
tpl <-
MaybeT $ getValBy $ UniqueTicketProjectLocal tclid
lift $ getProject tpl
txl <-
lift $
requireEitherAlt
(getValBy $ UniqueTicketProjectLocal tclid)
(getValBy $ UniqueTicketRepoLocal tclid)
"No specific TCL"
"Both TPL and TRL"
lift $ bitraverse getProject getRepo txl
return (mproj, rd, False)
Nothing -> do
did <- insert Discussion

View file

@ -130,8 +130,9 @@ import Vervis.Widget.Repo
import Vervis.Widget.Sharer
data NoteContext
= NoteContextSharerTicket ShrIdent TicketAuthorLocalId
= NoteContextSharerTicket ShrIdent TicketAuthorLocalId Bool
| NoteContextProjectTicket ShrIdent PrjIdent LocalTicketId
| NoteContextRepoPatch ShrIdent RpIdent LocalTicketId
deriving Eq
hostIsLocal :: (MonadSite m, SiteEnv m ~ App) => Host -> m Bool
@ -158,12 +159,18 @@ parseContext uContext = do
Just r -> return r
case route of
SharerTicketR shr talkhid ->
NoteContextSharerTicket shr <$>
flip (NoteContextSharerTicket shr) False <$>
decodeKeyHashidE talkhid "Note context invalid talkhid"
SharerPatchR shr talkhid ->
flip (NoteContextSharerTicket shr) True <$>
decodeKeyHashidE talkhid "Note context invalid talkhid"
ProjectTicketR shr prj ltkhid ->
NoteContextProjectTicket shr prj <$>
decodeKeyHashidE ltkhid "Note context invalid ltkhid"
_ -> throwE "Local context isn't a ticket route"
RepoPatchR shr rp ltkhid ->
NoteContextRepoPatch shr rp <$>
decodeKeyHashidE ltkhid "Note context invalid ltkhid"
_ -> throwE "Local context isn't a ticket/patch route"
else return $ Right uContext
parseParent

View file

@ -336,6 +336,11 @@ handleRepoInbox now shrRecip rpRecip auth body = do
ActivityAuthLocal local -> throwE $ errorLocalForwarded local
ActivityAuthRemote ra -> return ra
case activitySpecific $ actbActivity body of
CreateActivity (Create obj mtarget) ->
case obj of
CreateNote note ->
repoCreateNoteF now shrRecip rpRecip remoteAuthor body note
_ -> error "Unsupported create object type for repos"
FollowActivity follow ->
repoFollowF shrRecip rpRecip now remoteAuthor body follow
UndoActivity undo->

View file

@ -16,6 +16,7 @@
module Vervis.Federation.Discussion
( sharerCreateNoteF
, projectCreateNoteF
, repoCreateNoteF
)
where
@ -72,6 +73,7 @@ import Vervis.Model
import Vervis.Model.Ident
import Vervis.Settings
import Vervis.Ticket
import Vervis.Patch
-- | Check the note in the remote Create Note activity delivered to us.
checkNote
@ -256,12 +258,21 @@ sharerCreateNoteF now shrRecip author body note = do
case mractid of
Nothing -> "I already have this activity in my inbox, doing nothing"
Just _ -> "Context is remote, so just inserting to my inbox"
Left (NoteContextSharerTicket shr talid) -> do
Left (NoteContextSharerTicket shr talid patch) -> do
mremotesHttp <- runDBExcept $ do
(sid, pid, ibid) <- lift getRecip404
(Entity _ tal, Entity _ lt, _, _) <- do
mticket <- lift $ getSharerTicket shr talid
fromMaybeE mticket "Context: No such sharer-ticket"
(tal, lt, followers) <-
if patch
then do
(Entity _ tal, Entity _ lt, _, _, _) <- do
mticket <- lift $ getSharerPatch shr talid
fromMaybeE mticket "Context: No such sharer-patch"
return (tal, lt, LocalPersonCollectionSharerPatchFollowers)
else do
(Entity _ tal, Entity _ lt, _, _) <- do
mticket <- lift $ getSharerTicket shr talid
fromMaybeE mticket "Context: No such sharer-ticket"
return (tal, lt, LocalPersonCollectionSharerTicketFollowers)
if ticketAuthorLocalAuthor tal == pid
then do
mractid <- lift $ insertToInbox now author body ibid luCreate True
@ -283,7 +294,7 @@ sharerCreateNoteF now shrRecip author body note = do
let sieve =
makeRecipientSet
[]
[ LocalPersonCollectionSharerTicketFollowers shrRecip talkhid
[ followers shrRecip talkhid
--, LocalPersonCollectionSharerTicketTeam shrRecip talkhid
]
remoteRecips <- insertRemoteActivityToLocalInboxes False ractid $ localRecipSieve' sieve False False localRecips
@ -315,6 +326,20 @@ sharerCreateNoteF now shrRecip author body note = do
case mractid of
Nothing -> "I already have this activity in my inbox, doing nothing"
Just _ -> "Context is a project-ticket, so just inserting to my inbox"
Left (NoteContextRepoPatch shr rp ltid) -> runDBExcept $ do
personRecip <- lift $ do
sid <- getKeyBy404 $ UniqueSharer shrRecip
getValBy404 $ UniquePersonIdent sid
(_, _, _, Entity _ lt, _, _, _, _) <- do
mticket <- lift $ getRepoPatch shr rp ltid
fromMaybeE mticket "Context: No such repo-patch"
let did = localTicketDiscuss lt
_ <- traverse (getParent did) mparent
mractid <- lift $ insertToInbox now author body (personInbox personRecip) luCreate True
return $
case mractid of
Nothing -> "I already have this activity in my inbox, doing nothing"
Just _ -> "Context is a repo-patch, so just inserting to my inbox"
where
getRecip404 = do
sid <- getKeyBy404 $ UniqueSharer shrRecip
@ -361,7 +386,7 @@ projectCreateNoteF now shrRecip prjRecip author body note = do
msig <- checkForward $ LocalActorProject shrRecip prjRecip
case context of
Right _ -> return "Not using; context isn't local"
Left (NoteContextSharerTicket shr talid) -> do
Left (NoteContextSharerTicket shr talid False) -> do
mremotesHttp <- runDBExcept $ do
(jid, ibid) <- lift getProjectRecip404
(_, _, _, project) <- do
@ -396,6 +421,7 @@ projectCreateNoteF now shrRecip prjRecip author body note = do
Right (sig, remotesHttp) -> do
forkWorker "projectCreateNoteF inbox forwarding by http" $ deliverRemoteHTTP_J now shrRecip prjRecip (actbBL body) sig remotesHttp
return "Stored to inbox and did inbox forwarding"
Left (NoteContextSharerTicket _ _ True) -> return "Context is a sharer-patch, ignoring activity"
Left (NoteContextProjectTicket shr prj ltid) -> do
mremotesHttp <- runDBExcept $ do
(jid, ibid) <- lift getProjectRecip404
@ -436,8 +462,112 @@ projectCreateNoteF now shrRecip prjRecip author body note = do
Right (sig, remotesHttp) -> do
forkWorker "projectCreateNoteF inbox forwarding by http" $ deliverRemoteHTTP_J now shrRecip prjRecip (actbBL body) sig remotesHttp
return "Stored to inbox, cached comment, and did inbox forwarding"
Left (NoteContextRepoPatch _ _ _) -> return "Context is a repo-patch, ignoring activity"
where
getProjectRecip404 = do
sid <- getKeyBy404 $ UniqueSharer shrRecip
Entity jid j <- getBy404 $ UniqueProject prjRecip sid
return (jid, projectInbox j)
repoCreateNoteF
:: UTCTime
-> ShrIdent
-> RpIdent
-> RemoteAuthor
-> ActivityBody
-> Note URIMode
-> ExceptT Text Handler Text
repoCreateNoteF now shrRecip rpRecip author body note = do
luCreate <-
fromMaybeE (activityId $ actbActivity body) "Create without 'id'"
(luNote, published, context, mparent, source, content) <- checkNote note
(localRecips, _remoteRecips) <- do
mrecips <- parseAudience $ activityAudience $ actbActivity body
fromMaybeE mrecips "Create Note with no recipients"
msig <- checkForward $ LocalActorRepo shrRecip rpRecip
case context of
Right _ -> return "Not using; context isn't local"
Left (NoteContextSharerTicket _ _ False) ->
return "Context is a sharer-ticket, ignoring activity"
Left (NoteContextSharerTicket shr talid True) -> do
mremotesHttp <- runDBExcept $ do
(rid, ibid) <- lift getRepoRecip404
(_, _, _, repo, _) <- do
mticket <- lift $ getSharerPatch shr talid
fromMaybeE mticket "Context: No such sharer-ticket"
case repo of
Left (_, Entity _ trl)
| ticketRepoLocalRepo trl == rid -> do
mractid <- lift $ insertToInbox now author body ibid luCreate False
case mractid of
Nothing -> return $ Left "Activity already in my inbox"
Just ractid ->
case msig of
Nothing ->
return $ Left
"Context is a sharer-patch, \
\but no inbox forwarding \
\header for me, so doing \
\nothing, just storing in inbox"
Just sig -> lift $ Right <$> do
let sieve =
makeRecipientSet
[]
[ LocalPersonCollectionRepoFollowers shrRecip rpRecip
, LocalPersonCollectionRepoTeam shrRecip rpRecip
]
remoteRecips <- insertRemoteActivityToLocalInboxes False ractid $ localRecipSieve' sieve False False localRecips
(sig,) <$> deliverRemoteDB_R (actbBL body) ractid rid sig remoteRecips
_ -> return $ Left "Context is a sharer-patch of another repo"
case mremotesHttp of
Left msg -> return msg
Right (sig, remotesHttp) -> do
forkWorker "repoCreateNoteF inbox forwarding by http" $ deliverRemoteHTTP_R now shrRecip rpRecip (actbBL body) sig remotesHttp
return "Stored to inbox and did inbox forwarding"
Left (NoteContextProjectTicket _ _ _) ->
return "Context is a project-ticket, ignoring activity"
Left (NoteContextRepoPatch shr rp ltid) -> do
mremotesHttp <- runDBExcept $ do
(rid, ibid) <- lift getRepoRecip404
(_, _, _, Entity _ lt, _, Entity _ trl, _, _) <- do
mticket <- lift $ getRepoPatch shr rp ltid
fromMaybeE mticket "Context: No such repo-patch"
if ticketRepoLocalRepo trl == rid
then do
mractid <- lift $ insertToInbox now author body ibid luCreate False
case mractid of
Nothing -> return $ Left "Activity already in my inbox"
Just ractid -> do
let did = localTicketDiscuss lt
meparent <- traverse (getParent did) mparent
mmid <- lift $ insertToDiscussion author luNote published source content did meparent ractid
case mmid of
Nothing -> return $ Left "I already have this comment, just storing in inbox"
Just mid -> lift $ do
updateOrphans author luNote did mid
case msig of
Nothing ->
return $ Left "Storing in inbox, caching comment, no inbox forwarding header"
Just sig -> Right <$> do
ltkhid <- encodeKeyHashid ltid
let sieve =
makeRecipientSet
[]
[ LocalPersonCollectionRepoFollowers shrRecip rpRecip
, LocalPersonCollectionRepoTeam shrRecip rpRecip
, LocalPersonCollectionRepoPatchFollowers shrRecip rpRecip ltkhid
--, LocalPersonCollectionProjectTicketTeam shrRecip prjRecip ltkhid
]
remoteRecips <- insertRemoteActivityToLocalInboxes False ractid $ localRecipSieve' sieve False False localRecips
(sig,) <$> deliverRemoteDB_R (actbBL body) ractid rid sig remoteRecips
else return $ Left "Context is a repo-patch of another repo"
case mremotesHttp of
Left msg -> return msg
Right (sig, remotesHttp) -> do
forkWorker "repoCreateNoteF inbox forwarding by http" $ deliverRemoteHTTP_R now shrRecip rpRecip (actbBL body) sig remotesHttp
return "Stored to inbox, cached comment, and did inbox forwarding"
where
getRepoRecip404 = do
sid <- getKeyBy404 $ UniqueSharer shrRecip
Entity rid r <- getBy404 $ UniqueRepo rpRecip sid
return (rid, repoInbox r)