Decouple OutboxItem from Person via a new table named Outbox

This commit is contained in:
fr33domlover 2019-06-15 18:51:26 +00:00
parent 6452d239f2
commit 499479b662
8 changed files with 113 additions and 34 deletions

View file

@ -35,14 +35,18 @@ Person
resetPassKeyCreated UTCTime resetPassKeyCreated UTCTime
about Text about Text
inbox InboxId inbox InboxId
outbox OutboxId
UniquePersonIdent ident UniquePersonIdent ident
UniquePersonLogin login UniquePersonLogin login
UniquePersonEmail email UniquePersonEmail email
UniquePersonInbox inbox UniquePersonInbox inbox
UniquePersonOutbox outbox
Outbox
OutboxItem OutboxItem
person PersonId outbox OutboxId
activity PersistActivity activity PersistActivity
published UTCTime published UTCTime

View file

@ -0,0 +1,26 @@
Person
ident Int64
login Text
passphraseHash ByteString
email Text
verified Bool
verifiedKey Text
verifiedKeyCreated UTCTime
resetPassKey Text
resetPassKeyCreated UTCTime
about Text
inbox Int64
outbox OutboxId
UniquePersonIdent ident
UniquePersonLogin login
UniquePersonEmail email
UniquePersonInbox inbox
Outbox
OutboxItem
person PersonId
outbox OutboxId
activity PersistJSONObject
published UTCTime

View file

@ -162,8 +162,8 @@ createNoteC host (Note mluNote luAttrib aud muParent muContext mpublished source
federation <- getsYesod $ appFederation . appSettings federation <- getsYesod $ appFederation . appSettings
unless (federation || null remoteRecips) $ unless (federation || null remoteRecips) $
throwE "Federation disabled, but remote recipients specified" throwE "Federation disabled, but remote recipients specified"
(lmid, obid, doc, remotesHttp) <- runDBExcept $ do (lmid, obiid, doc, remotesHttp) <- runDBExcept $ do
(pid, shrUser) <- verifyIsLoggedInUser luAttrib "Note attributed to different actor" (pid, obid, shrUser) <- verifyIsLoggedInUser luAttrib "Note attributed to different actor"
(did, meparent, mcollections) <- case mticket of (did, meparent, mcollections) <- case mticket of
Just (shr, prj, num) -> do Just (shr, prj, num) -> do
mt <- lift $ runMaybeT $ do mt <- lift $ runMaybeT $ do
@ -231,13 +231,13 @@ createNoteC host (Note mluNote luAttrib aud muParent muContext mpublished source
\ commented on a # \ commented on a #
<a href=#{renderFedURI uContext}>ticket</a>. <a href=#{renderFedURI uContext}>ticket</a>.
|] |]
(lmid, obid, doc) <- lift $ insertMessage luAttrib shrUser pid uContext did muParent meparent source content summary (lmid, obiid, doc) <- lift $ insertMessage luAttrib shrUser pid obid uContext did muParent meparent source content summary
moreRemotes <- deliverLocal pid obid localRecips mcollections moreRemotes <- deliverLocal pid obiid localRecips mcollections
unless (federation || null moreRemotes) $ unless (federation || null moreRemotes) $
throwE "Federation disabled but remote collection members found" throwE "Federation disabled but remote collection members found"
remotesHttp <- lift $ deliverRemoteDB (furiHost uContext) obid remoteRecips moreRemotes remotesHttp <- lift $ deliverRemoteDB (furiHost uContext) obiid remoteRecips moreRemotes
return (lmid, obid, doc, remotesHttp) return (lmid, obiid, doc, remotesHttp)
lift $ forkWorker "Outbox POST handler: async HTTP delivery" $ deliverRemoteHttp (furiHost uContext) obid doc remotesHttp lift $ forkWorker "Outbox POST handler: async HTTP delivery" $ deliverRemoteHttp (furiHost uContext) obiid doc remotesHttp
return lmid return lmid
where where
nonEmptyE :: Monad m => [a] -> e -> ExceptT e m (NonEmpty a) nonEmptyE :: Monad m => [a] -> e -> ExceptT e m (NonEmpty a)
@ -401,20 +401,24 @@ createNoteC host (Note mluNote luAttrib aud muParent muContext mpublished source
verifyOnlySharers :: LocalRecipientSet -> ExceptT Text Handler [ShrIdent] verifyOnlySharers :: LocalRecipientSet -> ExceptT Text Handler [ShrIdent]
verifyOnlySharers lrs = catMaybes <$> traverse (atMostSharer "Note with remote context but local project-related recipients") lrs verifyOnlySharers lrs = catMaybes <$> traverse (atMostSharer "Note with remote context but local project-related recipients") lrs
verifyIsLoggedInUser :: LocalURI -> Text -> ExceptT Text AppDB (PersonId, ShrIdent) verifyIsLoggedInUser
:: LocalURI
-> Text
-> ExceptT Text AppDB (PersonId, OutboxId, ShrIdent)
verifyIsLoggedInUser lu t = do verifyIsLoggedInUser lu t = do
Entity pid p <- requireVerifiedAuth Entity pid p <- requireVerifiedAuth
s <- lift $ getJust $ personIdent p s <- lift $ getJust $ personIdent p
route2local <- getEncodeRouteLocal route2local <- getEncodeRouteLocal
let shr = sharerIdent s let shr = sharerIdent s
if route2local (SharerR shr) == lu if route2local (SharerR shr) == lu
then return (pid, shr) then return (pid, personOutbox p, shr)
else throwE t else throwE t
insertMessage insertMessage
:: LocalURI :: LocalURI
-> ShrIdent -> ShrIdent
-> PersonId -> PersonId
-> OutboxId
-> FedURI -> FedURI
-> DiscussionId -> DiscussionId
-> Maybe FedURI -> Maybe FedURI
@ -423,7 +427,7 @@ createNoteC host (Note mluNote luAttrib aud muParent muContext mpublished source
-> Text -> Text
-> Html -> Html
-> AppDB (LocalMessageId, OutboxItemId, Doc Activity) -> AppDB (LocalMessageId, OutboxItemId, Doc Activity)
insertMessage luAttrib shrUser pid uContext did muParent meparent source content summary = do insertMessage luAttrib shrUser pid obid uContext did muParent meparent source content summary = do
now <- liftIO getCurrentTime now <- liftIO getCurrentTime
mid <- insert Message mid <- insert Message
{ messageCreated = now { messageCreated = now
@ -454,28 +458,28 @@ createNoteC host (Note mluNote luAttrib aud muParent muContext mpublished source
} }
} }
tempUri = LocalURI "" "" tempUri = LocalURI "" ""
obid <- insert OutboxItem obiid <- insert OutboxItem
{ outboxItemPerson = pid { outboxItemOutbox = obid
, outboxItemActivity = PersistJSON $ activity tempUri tempUri , outboxItemActivity = PersistJSON $ activity tempUri tempUri
, outboxItemPublished = now , outboxItemPublished = now
} }
lmid <- insert LocalMessage lmid <- insert LocalMessage
{ localMessageAuthor = pid { localMessageAuthor = pid
, localMessageRest = mid , localMessageRest = mid
, localMessageCreate = obid , localMessageCreate = obiid
, localMessageUnlinkedParent = , localMessageUnlinkedParent =
case meparent of case meparent of
Just (Right uParent) -> Just uParent Just (Right uParent) -> Just uParent
_ -> Nothing _ -> Nothing
} }
route2local <- getEncodeRouteLocal route2local <- getEncodeRouteLocal
obhid <- encodeKeyHashid obid obihid <- encodeKeyHashid obiid
lmhid <- encodeKeyHashid lmid lmhid <- encodeKeyHashid lmid
let luAct = route2local $ OutboxItemR shrUser obhid let luAct = route2local $ OutboxItemR shrUser obihid
luNote = route2local $ MessageR shrUser lmhid luNote = route2local $ MessageR shrUser lmhid
doc = activity luAct luNote doc = activity luAct luNote
update obid [OutboxItemActivity =. PersistJSON doc] update obiid [OutboxItemActivity =. PersistJSON doc]
return (lmid, obid, doc) return (lmid, obiid, doc)
-- Deliver to local recipients. For local users, find in DB and deliver. -- Deliver to local recipients. For local users, find in DB and deliver.
-- For local collections, expand them, deliver to local users, and return a -- For local collections, expand them, deliver to local users, and return a

View file

@ -410,22 +410,25 @@ handleSharerInbox
-> Activity -> Activity
-> ExceptT Text Handler Text -> ExceptT Text Handler Text
handleSharerInbox _now shrRecip (Left pidAuthor) _raw activity = do handleSharerInbox _now shrRecip (Left pidAuthor) _raw activity = do
(shrActivity, obid) <- do (shrActivity, obiid) <- do
route <- route <-
case decodeRouteLocal $ activityId activity of case decodeRouteLocal $ activityId activity of
Nothing -> throwE "Local activity: Not a valid route" Nothing -> throwE "Local activity: Not a valid route"
Just r -> return r Just r -> return r
case route of case route of
OutboxItemR shr obkhid -> OutboxItemR shr obikhid ->
(shr,) <$> decodeKeyHashidE obkhid "Local activity: ID is invalid hashid" (shr,) <$> decodeKeyHashidE obikhid "Local activity: ID is invalid hashid"
_ -> throwE "Local activity: Not an activity route" _ -> throwE "Local activity: Not an activity route"
runDBExcept $ do runDBExcept $ do
Entity pidRecip personRecip <- lift $ do Entity pidRecip personRecip <- lift $ do
sid <- getKeyBy404 $ UniqueSharer shrRecip sid <- getKeyBy404 $ UniqueSharer shrRecip
getBy404 $ UniquePersonIdent sid getBy404 $ UniquePersonIdent sid
mob <- lift $ get obid mobi <- lift $ get obiid
ob <- fromMaybeE mob "Local activity: No such ID in DB" obi <- fromMaybeE mobi "Local activity: No such ID in DB"
let pidOutbox = outboxItemPerson ob mpidOutbox <-
lift $ getKeyBy $ UniquePersonOutbox $ outboxItemOutbox obi
pidOutbox <-
fromMaybeE mpidOutbox "Local activity not in a user outbox"
p <- lift $ getJust pidOutbox p <- lift $ getJust pidOutbox
s <- lift $ getJust $ personIdent p s <- lift $ getJust $ personIdent p
unless (sharerIdent s == shrActivity) $ unless (sharerIdent s == shrActivity) $
@ -437,7 +440,7 @@ handleSharerInbox _now shrRecip (Left pidAuthor) _raw activity = do
else lift $ do else lift $ do
ibiid <- insert $ InboxItem True ibiid <- insert $ InboxItem True
let ibid = personInbox personRecip let ibid = personInbox personRecip
miblid <- insertUnique $ InboxItemLocal ibid obid ibiid miblid <- insertUnique $ InboxItemLocal ibid obiid ibiid
let recip = shr2text shrRecip let recip = shr2text shrRecip
case miblid of case miblid of
Nothing -> do Nothing -> do

View file

@ -589,6 +589,7 @@ instance AccountDB AccountPersistDB' where
return $ Left $ mr $ MsgUsernameExists name return $ Left $ mr $ MsgUsernameExists name
Right sid -> do Right sid -> do
ibid <- insert Inbox ibid <- insert Inbox
obid <- insert Outbox
let defTime = UTCTime (ModifiedJulianDay 0) 0 let defTime = UTCTime (ModifiedJulianDay 0) 0
person = Person person = Person
{ personIdent = sid { personIdent = sid
@ -602,6 +603,7 @@ instance AccountDB AccountPersistDB' where
, personResetPassKeyCreated = defTime , personResetPassKeyCreated = defTime
, personAbout = "" , personAbout = ""
, personInbox = ibid , personInbox = ibid
, personOutbox = obid
} }
pid <- insert person pid <- insert person
return $ Right $ Entity pid person return $ Right $ Entity pid person

View file

@ -369,9 +369,10 @@ getOutboxR :: ShrIdent -> Handler TypedContent
getOutboxR shr = do getOutboxR shr = do
(total, pages, mpage) <- runDB $ do (total, pages, mpage) <- runDB $ do
sid <- getKeyBy404 $ UniqueSharer shr sid <- getKeyBy404 $ UniqueSharer shr
pid <- getKeyBy404 $ UniquePersonIdent sid p <- getValBy404 $ UniquePersonIdent sid
let countAllItems = count [OutboxItemPerson ==. pid] let obid = personOutbox p
selectItems off lim = selectList [OutboxItemPerson ==. pid] [Desc OutboxItemId, OffsetBy off, LimitTo lim] countAllItems = count [OutboxItemOutbox ==. obid]
selectItems off lim = selectList [OutboxItemOutbox ==. obid] [Desc OutboxItemId, OffsetBy off, LimitTo lim]
getPageAndNavCount countAllItems selectItems getPageAndNavCount countAllItems selectItems
let here = OutboxR shr let here = OutboxR shr
encodeRouteLocal <- getEncodeRouteLocal encodeRouteLocal <- getEncodeRouteLocal
@ -423,14 +424,14 @@ getOutboxR shr = do
defaultLayout $(widgetFile "person/outbox") defaultLayout $(widgetFile "person/outbox")
getOutboxItemR :: ShrIdent -> KeyHashid OutboxItem -> Handler TypedContent getOutboxItemR :: ShrIdent -> KeyHashid OutboxItem -> Handler TypedContent
getOutboxItemR shr obkhid = do getOutboxItemR shr obikhid = do
obid <- decodeKeyHashid404 obkhid obiid <- decodeKeyHashid404 obikhid
doc <- runDB $ do doc <- runDB $ do
sid <- getKeyBy404 $ UniqueSharer shr sid <- getKeyBy404 $ UniqueSharer shr
pid <- getKeyBy404 $ UniquePersonIdent sid p <- getValBy404 $ UniquePersonIdent sid
ob <- get404 obid obi <- get404 obiid
unless (outboxItemPerson ob == pid) notFound unless (outboxItemOutbox obi == personOutbox p) notFound
return $ persistJSONValue $ outboxItemActivity ob return $ persistJSONValue $ outboxItemActivity obi
selectRep $ do selectRep $ do
provideAP $ pure doc provideAP $ pure doc
provideRep $ defaultLayout $ provideRep $ defaultLayout $

View file

@ -788,6 +788,37 @@ changes hLocal ctx =
-- 115 -- 115
, addUnique "TicketAuthorLocal" $ , addUnique "TicketAuthorLocal" $
Unique "UniqueTicketAuthorLocaleOffer" ["offer"] Unique "UniqueTicketAuthorLocaleOffer" ["offer"]
-- 116
, addEntity $ ST.Entity "Outbox" [] []
-- 117
, addFieldRefRequired'
"Person"
Outbox20190615
(Just $ do
pids <- selectKeysList ([] :: [Filter Person20190615]) []
for_ pids $ \ pid -> do
obid <- insert Outbox20190615
update pid [Person20190615Outbox =. obid]
)
"outbox"
"Outbox"
-- 118
, addUnique "Person" $ Unique "UniquePersonOutbox" ["outbox"]
-- 119
, addFieldRefRequired'
"OutboxItem"
Outbox20190615
(Just $ do
obiids <- selectList ([] :: [Filter OutboxItem20190615]) []
for_ obiids $ \ (Entity obiid obi) -> do
person <- getJust $ outboxItem20190615Person obi
let obid = person20190615Outbox person
update obiid [OutboxItem20190615Outbox =. obid]
)
"outbox"
"Outbox"
-- 120
, removeField "OutboxItem" "person"
] ]
migrateDB migrateDB

View file

@ -91,6 +91,11 @@ module Vervis.Migration.Model
, Ticket20190612Generic (..) , Ticket20190612Generic (..)
, Ticket20190612 , Ticket20190612
, TicketAuthorLocal20190612Generic (..) , TicketAuthorLocal20190612Generic (..)
, Person20190615Generic (..)
, Person20190615
, Outbox20190615Generic (..)
, OutboxItem20190615Generic (..)
, OutboxItem20190615
) )
where where
@ -199,3 +204,6 @@ makeEntitiesMigration "20190610"
makeEntitiesMigration "20190612" makeEntitiesMigration "20190612"
$(modelFile "migrations/2019_06_12.model") $(modelFile "migrations/2019_06_12.model")
makeEntitiesMigration "20190615"
$(modelFile "migrations/2019_06_15.model")