C2S: Implement real C2S access via outbox POSTing and OAuth2
This commit is contained in:
parent
a0325da028
commit
5d25aba239
6 changed files with 164 additions and 97 deletions
|
@ -155,7 +155,7 @@ noteC
|
||||||
:: Entity Person
|
:: Entity Person
|
||||||
-> Sharer
|
-> Sharer
|
||||||
-> Note URIMode
|
-> Note URIMode
|
||||||
-> Handler (Either Text LocalMessageId)
|
-> ExceptT Text Handler OutboxItemId
|
||||||
noteC person sharer note = do
|
noteC person sharer note = do
|
||||||
let shrUser = sharerIdent sharer
|
let shrUser = sharerIdent sharer
|
||||||
summary <-
|
summary <-
|
||||||
|
@ -170,7 +170,7 @@ noteC person sharer note = do
|
||||||
$nothing
|
$nothing
|
||||||
\ commented.
|
\ commented.
|
||||||
|]
|
|]
|
||||||
createNoteC person sharer summary (noteAudience note) note
|
createNoteC person sharer (Just summary) (noteAudience note) note Nothing
|
||||||
|
|
||||||
-- | Handle a Note submitted by a local user to their outbox. It can be either
|
-- | Handle a Note submitted by a local user to their outbox. It can be either
|
||||||
-- a comment on a local ticket, or a comment on some remote context. Return an
|
-- a comment on a local ticket, or a comment on some remote context. Return an
|
||||||
|
@ -178,20 +178,22 @@ noteC person sharer note = do
|
||||||
createNoteC
|
createNoteC
|
||||||
:: Entity Person
|
:: Entity Person
|
||||||
-> Sharer
|
-> Sharer
|
||||||
-> TextHtml
|
-> Maybe TextHtml
|
||||||
-> Audience URIMode
|
-> Audience URIMode
|
||||||
-> Note URIMode
|
-> Note URIMode
|
||||||
-> Handler (Either Text LocalMessageId)
|
-> Maybe FedURI
|
||||||
createNoteC (Entity pidUser personUser) sharerUser summary audience note = runExceptT $ do
|
-> ExceptT Text Handler OutboxItemId
|
||||||
|
createNoteC (Entity pidUser personUser) sharerUser summary audience note muTarget = do
|
||||||
let shrUser = sharerIdent sharerUser
|
let shrUser = sharerIdent sharerUser
|
||||||
noteData@(muParent, mparent, uContext, context, source, content) <- checkNote shrUser note
|
noteData@(muParent, mparent, uContext, context, source, content) <- checkNote shrUser note
|
||||||
|
verifyNothingE muTarget "Create Note has 'target'"
|
||||||
(localRecips, remoteRecips) <- do
|
(localRecips, remoteRecips) <- do
|
||||||
mrecips <- parseAudience audience
|
mrecips <- parseAudience audience
|
||||||
fromMaybeE mrecips "Create Note with no recipients"
|
fromMaybeE mrecips "Create Note with no recipients"
|
||||||
checkFederation remoteRecips
|
checkFederation remoteRecips
|
||||||
verifyContextRecip context localRecips remoteRecips
|
verifyContextRecip context localRecips remoteRecips
|
||||||
now <- liftIO getCurrentTime
|
now <- liftIO getCurrentTime
|
||||||
(lmid, obiid, doc, remotesHttp) <- runDBExcept $ do
|
(_lmid, obiid, doc, remotesHttp) <- runDBExcept $ do
|
||||||
obiidCreate <- lift $ insertEmptyOutboxItem (personOutbox personUser) now
|
obiidCreate <- lift $ insertEmptyOutboxItem (personOutbox personUser) now
|
||||||
(mproject, did, meparent) <- getTopicAndParent context mparent
|
(mproject, did, meparent) <- getTopicAndParent context mparent
|
||||||
lmid <- lift $ insertMessage now content source obiidCreate did meparent
|
lmid <- lift $ insertMessage now content source obiidCreate did meparent
|
||||||
|
@ -252,7 +254,7 @@ createNoteC (Entity pidUser personUser) sharerUser summary audience note = runEx
|
||||||
lift $ deliverRemoteDB' (objUriAuthority uContext) obiidCreate remoteRecips moreRemoteRecips
|
lift $ deliverRemoteDB' (objUriAuthority uContext) obiidCreate remoteRecips moreRemoteRecips
|
||||||
return (lmid, obiidCreate, docCreate, remoteRecipsHttpCreate)
|
return (lmid, obiidCreate, docCreate, remoteRecipsHttpCreate)
|
||||||
lift $ forkWorker "createNoteC: async HTTP delivery" $ deliverRemoteHttp (objUriAuthority uContext) obiid doc remotesHttp
|
lift $ forkWorker "createNoteC: async HTTP delivery" $ deliverRemoteHttp (objUriAuthority uContext) obiid doc remotesHttp
|
||||||
return lmid
|
return obiid
|
||||||
where
|
where
|
||||||
checkNote shrUser (Note mluNote luAttrib _aud muParent muContext mpublished source content) = do
|
checkNote shrUser (Note mluNote luAttrib _aud muParent muContext mpublished source content) = do
|
||||||
verifyNothingE mluNote "Note specifies an id"
|
verifyNothingE mluNote "Note specifies an id"
|
||||||
|
@ -487,7 +489,7 @@ createNoteC (Entity pidUser personUser) sharerUser summary audience note = runEx
|
||||||
create = Doc hLocal Activity
|
create = Doc hLocal Activity
|
||||||
{ activityId = Just $ encodeRouteLocal $ SharerOutboxItemR shrUser obikhid
|
{ activityId = Just $ encodeRouteLocal $ SharerOutboxItemR shrUser obikhid
|
||||||
, activityActor = luAttrib
|
, activityActor = luAttrib
|
||||||
, activitySummary = Just summary
|
, activitySummary = summary
|
||||||
, activityAudience = audience
|
, activityAudience = audience
|
||||||
, activitySpecific = CreateActivity Create
|
, activitySpecific = CreateActivity Create
|
||||||
{ createObject = CreateNote Note
|
{ createObject = CreateNote Note
|
||||||
|
@ -512,12 +514,12 @@ createNoteC (Entity pidUser personUser) sharerUser summary audience note = runEx
|
||||||
createTicketC
|
createTicketC
|
||||||
:: Entity Person
|
:: Entity Person
|
||||||
-> Sharer
|
-> Sharer
|
||||||
-> TextHtml
|
-> Maybe TextHtml
|
||||||
-> Audience URIMode
|
-> Audience URIMode
|
||||||
-> AP.Ticket URIMode
|
-> AP.Ticket URIMode
|
||||||
-> Maybe FedURI
|
-> Maybe FedURI
|
||||||
-> Handler (Either Text TicketAuthorLocalId)
|
-> ExceptT Text Handler OutboxItemId
|
||||||
createTicketC (Entity pidUser personUser) sharerUser summary audience ticket muTarget = runExceptT $ do
|
createTicketC (Entity pidUser personUser) sharerUser summary audience ticket muTarget = do
|
||||||
let shrUser = sharerIdent sharerUser
|
let shrUser = sharerIdent sharerUser
|
||||||
ticketData@(uContext, title, desc, source, uTarget) <- checkTicket shrUser ticket muTarget
|
ticketData@(uContext, title, desc, source, uTarget) <- checkTicket shrUser ticket muTarget
|
||||||
context <- parseTicketContext uContext
|
context <- parseTicketContext uContext
|
||||||
|
@ -528,7 +530,7 @@ createTicketC (Entity pidUser personUser) sharerUser summary audience ticket muT
|
||||||
verifyProjectRecip context localRecips
|
verifyProjectRecip context localRecips
|
||||||
tracker <- fetchTracker context uTarget
|
tracker <- fetchTracker context uTarget
|
||||||
now <- liftIO getCurrentTime
|
now <- liftIO getCurrentTime
|
||||||
(talid, obiidCreate, docCreate, remotesHttpCreate, maybeAccept) <- runDBExcept $ do
|
(_talid, obiidCreate, docCreate, remotesHttpCreate, maybeAccept) <- runDBExcept $ do
|
||||||
obiidCreate <- lift $ insertEmptyOutboxItem (personOutbox personUser) now
|
obiidCreate <- lift $ insertEmptyOutboxItem (personOutbox personUser) now
|
||||||
project <- prepareProject now tracker
|
project <- prepareProject now tracker
|
||||||
talid <- lift $ insertTicket now pidUser title desc source obiidCreate project
|
talid <- lift $ insertTicket now pidUser title desc source obiidCreate project
|
||||||
|
@ -573,7 +575,7 @@ createTicketC (Entity pidUser personUser) sharerUser summary audience ticket muT
|
||||||
forkWorker "createTicketC: async HTTP Create delivery" $ deliverRemoteHttp (objUriAuthority uTarget) obiidCreate docCreate remotesHttpCreate
|
forkWorker "createTicketC: async HTTP Create delivery" $ deliverRemoteHttp (objUriAuthority uTarget) obiidCreate docCreate remotesHttpCreate
|
||||||
for_ maybeAccept $ \ (obiidAccept, docAccept, remotesHttpAccept) ->
|
for_ maybeAccept $ \ (obiidAccept, docAccept, remotesHttpAccept) ->
|
||||||
forkWorker "createTicketC: async HTTP Accept delivery" $ deliverRemoteHttp dont obiidAccept docAccept remotesHttpAccept
|
forkWorker "createTicketC: async HTTP Accept delivery" $ deliverRemoteHttp dont obiidAccept docAccept remotesHttpAccept
|
||||||
return talid
|
return obiidCreate
|
||||||
where
|
where
|
||||||
checkTicket shr (AP.Ticket mlocal luAttrib mpublished mupdated mcontext summary content source massigned resolved mmr) mtarget = do
|
checkTicket shr (AP.Ticket mlocal luAttrib mpublished mupdated mcontext summary content source massigned resolved mmr) mtarget = do
|
||||||
verifyNothingE mlocal "Ticket with 'id'"
|
verifyNothingE mlocal "Ticket with 'id'"
|
||||||
|
@ -716,7 +718,7 @@ createTicketC (Entity pidUser personUser) sharerUser summary audience ticket muT
|
||||||
create = Doc hLocal Activity
|
create = Doc hLocal Activity
|
||||||
{ activityId = Just $ encodeRouteLocal $ SharerOutboxItemR shrUser obikhid
|
{ activityId = Just $ encodeRouteLocal $ SharerOutboxItemR shrUser obikhid
|
||||||
, activityActor = luAttrib
|
, activityActor = luAttrib
|
||||||
, activitySummary = Just summary
|
, activitySummary = summary
|
||||||
, activityAudience = audience
|
, activityAudience = audience
|
||||||
, activitySpecific = CreateActivity Create
|
, activitySpecific = CreateActivity Create
|
||||||
{ createObject = CreateTicket AP.Ticket
|
{ createObject = CreateTicket AP.Ticket
|
||||||
|
@ -788,11 +790,11 @@ data Followee
|
||||||
|
|
||||||
followC
|
followC
|
||||||
:: ShrIdent
|
:: ShrIdent
|
||||||
-> TextHtml
|
-> Maybe TextHtml
|
||||||
-> Audience URIMode
|
-> Audience URIMode
|
||||||
-> AP.Follow URIMode
|
-> AP.Follow URIMode
|
||||||
-> Handler (Either Text OutboxItemId)
|
-> ExceptT Text Handler OutboxItemId
|
||||||
followC shrUser summary audience follow@(AP.Follow uObject muContext hide) = runExceptT $ do
|
followC shrUser summary audience follow@(AP.Follow uObject muContext hide) = do
|
||||||
(localRecips, remoteRecips) <- do
|
(localRecips, remoteRecips) <- do
|
||||||
mrecips <- parseAudience audience
|
mrecips <- parseAudience audience
|
||||||
fromMaybeE mrecips "Follow with no recipients"
|
fromMaybeE mrecips "Follow with no recipients"
|
||||||
|
@ -924,7 +926,7 @@ followC shrUser summary audience follow@(AP.Follow uObject muContext hide) = run
|
||||||
let activity mluAct = Doc hLocal Activity
|
let activity mluAct = Doc hLocal Activity
|
||||||
{ activityId = mluAct
|
{ activityId = mluAct
|
||||||
, activityActor = encodeRouteLocal $ SharerR shrUser
|
, activityActor = encodeRouteLocal $ SharerR shrUser
|
||||||
, activitySummary = Just summary
|
, activitySummary = summary
|
||||||
, activityAudience = audience
|
, activityAudience = audience
|
||||||
, activitySpecific = FollowActivity follow
|
, activitySpecific = FollowActivity follow
|
||||||
}
|
}
|
||||||
|
@ -996,12 +998,12 @@ followC shrUser summary audience follow@(AP.Follow uObject muContext hide) = run
|
||||||
|
|
||||||
offerTicketC
|
offerTicketC
|
||||||
:: ShrIdent
|
:: ShrIdent
|
||||||
-> TextHtml
|
-> Maybe TextHtml
|
||||||
-> Audience URIMode
|
-> Audience URIMode
|
||||||
-> AP.Ticket URIMode
|
-> AP.Ticket URIMode
|
||||||
-> FedURI
|
-> FedURI
|
||||||
-> Handler (Either Text OutboxItemId)
|
-> ExceptT Text Handler OutboxItemId
|
||||||
offerTicketC shrUser summary audience ticket uTarget = runExceptT $ do
|
offerTicketC shrUser summary audience ticket uTarget = do
|
||||||
(hProject, shrProject, prjProject) <- parseTarget uTarget
|
(hProject, shrProject, prjProject) <- parseTarget uTarget
|
||||||
{-deps <- -}
|
{-deps <- -}
|
||||||
checkOffer hProject shrProject prjProject
|
checkOffer hProject shrProject prjProject
|
||||||
|
@ -1271,11 +1273,11 @@ offerTicketC shrUser summary audience ticket uTarget = runExceptT $ do
|
||||||
|
|
||||||
undoC
|
undoC
|
||||||
:: ShrIdent
|
:: ShrIdent
|
||||||
-> TextHtml
|
-> Maybe TextHtml
|
||||||
-> Audience URIMode
|
-> Audience URIMode
|
||||||
-> Undo URIMode
|
-> Undo URIMode
|
||||||
-> Handler (Either Text OutboxItemId)
|
-> ExceptT Text Handler OutboxItemId
|
||||||
undoC shrUser summary audience undo@(Undo luObject) = runExceptT $ do
|
undoC shrUser summary audience undo@(Undo luObject) = do
|
||||||
(localRecips, remoteRecips) <- do
|
(localRecips, remoteRecips) <- do
|
||||||
mrecips <- parseAudience audience
|
mrecips <- parseAudience audience
|
||||||
fromMaybeE mrecips "Follow with no recipients"
|
fromMaybeE mrecips "Follow with no recipients"
|
||||||
|
@ -1331,7 +1333,7 @@ undoC shrUser summary audience undo@(Undo luObject) = runExceptT $ do
|
||||||
let activity mluAct = Doc hLocal Activity
|
let activity mluAct = Doc hLocal Activity
|
||||||
{ activityId = mluAct
|
{ activityId = mluAct
|
||||||
, activityActor = encodeRouteLocal $ SharerR shrUser
|
, activityActor = encodeRouteLocal $ SharerR shrUser
|
||||||
, activitySummary = Just summary
|
, activitySummary = summary
|
||||||
, activityAudience = audience
|
, activityAudience = audience
|
||||||
, activitySpecific = UndoActivity undo
|
, activitySpecific = UndoActivity undo
|
||||||
}
|
}
|
||||||
|
@ -1354,8 +1356,8 @@ pushCommitsC
|
||||||
-> Push URIMode
|
-> Push URIMode
|
||||||
-> ShrIdent
|
-> ShrIdent
|
||||||
-> RpIdent
|
-> RpIdent
|
||||||
-> Handler (Either Text OutboxItemId)
|
-> ExceptT Text Handler OutboxItemId
|
||||||
pushCommitsC (eperson, sharer) summary push shrRepo rpRepo = runExceptT $ do
|
pushCommitsC (eperson, sharer) summary push shrRepo rpRepo = do
|
||||||
let dont = Authority "dont-do.any-forwarding" Nothing
|
let dont = Authority "dont-do.any-forwarding" Nothing
|
||||||
(obiid, doc, remotesHttp) <- runDBExcept $ do
|
(obiid, doc, remotesHttp) <- runDBExcept $ do
|
||||||
(obiid, doc) <- lift $ insertToOutbox
|
(obiid, doc) <- lift $ insertToOutbox
|
||||||
|
|
|
@ -50,6 +50,8 @@ module Vervis.ActivityPub
|
||||||
, insertRemoteActivityToLocalInboxes
|
, insertRemoteActivityToLocalInboxes
|
||||||
, provideEmptyCollection
|
, provideEmptyCollection
|
||||||
, insertEmptyOutboxItem
|
, insertEmptyOutboxItem
|
||||||
|
, verifyContentTypeAP
|
||||||
|
, verifyContentTypeAP_E
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
|
@ -1180,3 +1182,29 @@ insertEmptyOutboxItem obid now = do
|
||||||
, outboxItemActivity = persistJSONObjectFromDoc $ Doc h emptyActivity
|
, outboxItemActivity = persistJSONObjectFromDoc $ Doc h emptyActivity
|
||||||
, outboxItemPublished = now
|
, outboxItemPublished = now
|
||||||
}
|
}
|
||||||
|
|
||||||
|
verifyContentTypeAP :: MonadHandler m => m ()
|
||||||
|
verifyContentTypeAP = do
|
||||||
|
result <- runExceptT verifyContentTypeAP_E
|
||||||
|
case result of
|
||||||
|
Left e -> invalidArgs ["Content type error: " <> e]
|
||||||
|
Right () -> return ()
|
||||||
|
|
||||||
|
verifyContentTypeAP_E :: MonadHandler m => ExceptT Text m ()
|
||||||
|
verifyContentTypeAP_E = do
|
||||||
|
ctypes <- lookupHeaders "Content-Type"
|
||||||
|
case ctypes of
|
||||||
|
[] -> throwE "Content-Type not specified"
|
||||||
|
[x] | x == typeAS -> return ()
|
||||||
|
| x == typeAS2 -> return ()
|
||||||
|
| otherwise ->
|
||||||
|
throwE $ "Not a recognized AP Content-Type: " <>
|
||||||
|
case decodeUtf8' x of
|
||||||
|
Left _ -> T.pack (show x)
|
||||||
|
Right t -> t
|
||||||
|
_ -> throwE "More than one Content-Type specified"
|
||||||
|
where
|
||||||
|
typeAS = "application/activity+json"
|
||||||
|
typeAS2 =
|
||||||
|
"application/ld+json; \
|
||||||
|
\profile=\"https://www.w3.org/ns/activitystreams\""
|
||||||
|
|
|
@ -330,32 +330,6 @@ verifyForwardedSig hAuthor luAuthor (Verification malgo keyid input signature) =
|
||||||
then ActivityAuthLocal <$> verifySelfSig luAuthor luKey input signature
|
then ActivityAuthLocal <$> verifySelfSig luAuthor luKey input signature
|
||||||
else ActivityAuthRemote <$> verifyActorSig' malgo input signature hKey luKey (Just luAuthor)
|
else ActivityAuthRemote <$> verifyActorSig' malgo input signature hKey luKey (Just luAuthor)
|
||||||
|
|
||||||
verifyContentTypeAP :: MonadHandler m => m ()
|
|
||||||
verifyContentTypeAP = do
|
|
||||||
result <- runExceptT verifyContentTypeAP_E
|
|
||||||
case result of
|
|
||||||
Left e -> invalidArgs ["Content type error: " <> e]
|
|
||||||
Right () -> return ()
|
|
||||||
|
|
||||||
verifyContentTypeAP_E :: MonadHandler m => ExceptT Text m ()
|
|
||||||
verifyContentTypeAP_E = do
|
|
||||||
ctypes <- lookupHeaders "Content-Type"
|
|
||||||
case ctypes of
|
|
||||||
[] -> throwE "Content-Type not specified"
|
|
||||||
[x] | x == typeAS -> return ()
|
|
||||||
| x == typeAS2 -> return ()
|
|
||||||
| otherwise ->
|
|
||||||
throwE $ "Not a recognized AP Content-Type: " <>
|
|
||||||
case decodeUtf8' x of
|
|
||||||
Left _ -> T.pack (show x)
|
|
||||||
Right t -> t
|
|
||||||
_ -> throwE "More than one Content-Type specified"
|
|
||||||
where
|
|
||||||
typeAS = "application/activity+json"
|
|
||||||
typeAS2 =
|
|
||||||
"application/ld+json; \
|
|
||||||
\profile=\"https://www.w3.org/ns/activitystreams\""
|
|
||||||
|
|
||||||
authenticateActivity
|
authenticateActivity
|
||||||
:: UTCTime
|
:: UTCTime
|
||||||
-- -> ExceptT Text Handler (Either PersonId ActivityDetail, BL.ByteString, Object, Activity)
|
-- -> ExceptT Text Handler (Either PersonId ActivityDetail, BL.ByteString, Object, Activity)
|
||||||
|
|
|
@ -60,6 +60,8 @@ import qualified Data.Text as T
|
||||||
import qualified Data.Text.Lazy as TL
|
import qualified Data.Text.Lazy as TL
|
||||||
import qualified Database.Esqueleto as E
|
import qualified Database.Esqueleto as E
|
||||||
|
|
||||||
|
import Dvara
|
||||||
|
|
||||||
import Database.Persist.JSON
|
import Database.Persist.JSON
|
||||||
import Network.FedURI
|
import Network.FedURI
|
||||||
import Web.ActivityPub hiding (Ticket)
|
import Web.ActivityPub hiding (Ticket)
|
||||||
|
@ -259,14 +261,51 @@ getPublishR = do
|
||||||
activityWidget
|
activityWidget
|
||||||
widget1 enctype1 widget2 enctype2 widget3 enctype3 widget4 enctype4
|
widget1 enctype1 widget2 enctype2 widget3 enctype3 widget4 enctype4
|
||||||
|
|
||||||
postSharerOutboxR :: ShrIdent -> Handler Html
|
postSharerOutboxR :: ShrIdent -> Handler Text
|
||||||
postSharerOutboxR _shrAuthor = do
|
postSharerOutboxR shr = do
|
||||||
federation <- getsYesod $ appFederation . appSettings
|
federation <- getsYesod $ appFederation . appSettings
|
||||||
unless federation badMethod
|
unless federation badMethod
|
||||||
|
(ep@(Entity pid person), sharer) <- runDB $ do
|
||||||
error
|
Entity sid s <- getBy404 $ UniqueSharer shr
|
||||||
"ActivityPub C2S outbox POST not implemented yet, but you can post \
|
(,s) <$> getBy404 (UniquePersonIdent sid)
|
||||||
\public activities via the /publish page"
|
(_app, mpid, _scopes) <- maybe notAuthenticated return =<< getDvaraAuth
|
||||||
|
pid' <-
|
||||||
|
maybe (permissionDenied "Not authorized to post as a user") return mpid
|
||||||
|
unless (pid == pid') $
|
||||||
|
permissionDenied "Can't post as other users"
|
||||||
|
verifyContentTypeAP
|
||||||
|
Doc h activity <- requireInsecureJsonBody
|
||||||
|
hl <- hostIsLocal h
|
||||||
|
unless hl $ invalidArgs ["Activity host isn't the instance host"]
|
||||||
|
result <- runExceptT $ handle ep sharer activity
|
||||||
|
case result of
|
||||||
|
Left err -> invalidArgs [err]
|
||||||
|
Right obiid -> do
|
||||||
|
obikhid <- encodeKeyHashid obiid
|
||||||
|
sendResponseCreated $ SharerOutboxItemR shr obikhid
|
||||||
|
where
|
||||||
|
handle eperson sharer (Activity _mid actor summary audience specific) = do
|
||||||
|
case decodeRouteLocal actor of
|
||||||
|
Just (SharerR shr') | shr' == shr -> return ()
|
||||||
|
_ -> throwE "Can't post activity sttributed to someone else"
|
||||||
|
case specific of
|
||||||
|
CreateActivity (Create obj mtarget) ->
|
||||||
|
case obj of
|
||||||
|
CreateNote note ->
|
||||||
|
createNoteC eperson sharer summary audience note mtarget
|
||||||
|
CreateTicket ticket ->
|
||||||
|
createTicketC eperson sharer summary audience ticket mtarget
|
||||||
|
_ -> throwE "Unsupported Create 'object' type"
|
||||||
|
FollowActivity follow ->
|
||||||
|
followC shr summary audience follow
|
||||||
|
OfferActivity (Offer obj target) ->
|
||||||
|
case obj of
|
||||||
|
OfferTicket ticket ->
|
||||||
|
offerTicketC shr summary audience ticket target
|
||||||
|
_ -> throwE "Unsupported Offer 'object' type"
|
||||||
|
UndoActivity undo ->
|
||||||
|
undoC shr summary audience undo
|
||||||
|
_ -> throwE "Unsupported activity type"
|
||||||
|
|
||||||
postPublishR :: Handler Html
|
postPublishR :: Handler Html
|
||||||
postPublishR = do
|
postPublishR = do
|
||||||
|
@ -302,12 +341,20 @@ postPublishR = do
|
||||||
Left err -> setMessage $ toHtml err
|
Left err -> setMessage $ toHtml err
|
||||||
Right id_ ->
|
Right id_ ->
|
||||||
case id_ of
|
case id_ of
|
||||||
Left (Left lmid) -> do
|
Left (Left obiid) -> do
|
||||||
|
mlmid <- runDB $ getKeyBy $ UniqueLocalMessageCreate obiid
|
||||||
|
case mlmid of
|
||||||
|
Nothing -> error "noteC succeeded but no lmid found for obiid"
|
||||||
|
Just lmid -> do
|
||||||
lmkhid <- encodeKeyHashid lmid
|
lmkhid <- encodeKeyHashid lmid
|
||||||
renderUrl <- getUrlRender
|
renderUrl <- getUrlRender
|
||||||
let u = renderUrl $ MessageR shrAuthor lmkhid
|
let u = renderUrl $ MessageR shrAuthor lmkhid
|
||||||
setMessage $ toHtml $ "Message created! ID: " <> u
|
setMessage $ toHtml $ "Message created! ID: " <> u
|
||||||
Left (Right talid) -> do
|
Left (Right obiid) -> do
|
||||||
|
mtalid <- runDB $ getKeyBy $ UniqueTicketAuthorLocalOpen obiid
|
||||||
|
case mtalid of
|
||||||
|
Nothing -> error "createTicketC succeeded but no talid found for obiid"
|
||||||
|
Just talid -> do
|
||||||
talkhid <- encodeKeyHashid talid
|
talkhid <- encodeKeyHashid talid
|
||||||
renderUrl <- getUrlRender
|
renderUrl <- getUrlRender
|
||||||
let u = renderUrl $ SharerTicketR shrAuthor talkhid
|
let u = renderUrl $ SharerTicketR shrAuthor talkhid
|
||||||
|
@ -355,7 +402,7 @@ postPublishR = do
|
||||||
, noteSource = msg'
|
, noteSource = msg'
|
||||||
, noteContent = contentHtml
|
, noteContent = contentHtml
|
||||||
}
|
}
|
||||||
ExceptT $ noteC eperson sharer note
|
noteC eperson sharer note
|
||||||
publishTicket eperson sharer (target, context, title, desc) = do
|
publishTicket eperson sharer (target, context, title, desc) = do
|
||||||
(summary, audience, create) <-
|
(summary, audience, create) <-
|
||||||
ExceptT $ C.createTicket (sharerIdent sharer) title desc target context
|
ExceptT $ C.createTicket (sharerIdent sharer) title desc target context
|
||||||
|
@ -364,7 +411,7 @@ postPublishR = do
|
||||||
CreateTicket t -> t
|
CreateTicket t -> t
|
||||||
_ -> error "Create object isn't a ticket"
|
_ -> error "Create object isn't a ticket"
|
||||||
target = createTarget create
|
target = createTarget create
|
||||||
ExceptT $ createTicketC eperson sharer summary audience ticket target
|
createTicketC eperson sharer (Just summary) audience ticket target
|
||||||
openTicket shrAuthor ((h, shr, prj), TextHtml title, TextPandocMarkdown desc) = do
|
openTicket shrAuthor ((h, shr, prj), TextHtml title, TextPandocMarkdown desc) = do
|
||||||
encodeRouteLocal <- getEncodeRouteLocal
|
encodeRouteLocal <- getEncodeRouteLocal
|
||||||
encodeRouteFed <- getEncodeRouteFed
|
encodeRouteFed <- getEncodeRouteFed
|
||||||
|
@ -412,11 +459,11 @@ postPublishR = do
|
||||||
, audienceGeneral = []
|
, audienceGeneral = []
|
||||||
, audienceNonActors = map (encodeRouteFed h) recipsC
|
, audienceNonActors = map (encodeRouteFed h) recipsC
|
||||||
}
|
}
|
||||||
ExceptT $ offerTicketC shrAuthor summary audience ticketAP target
|
offerTicketC shrAuthor (Just summary) audience ticketAP target
|
||||||
follow shrAuthor (uObject@(ObjURI hObject luObject), uRecip) = do
|
follow shrAuthor (uObject@(ObjURI hObject luObject), uRecip) = do
|
||||||
(summary, audience, followAP) <-
|
(summary, audience, followAP) <-
|
||||||
C.follow shrAuthor uObject uRecip False
|
C.follow shrAuthor uObject uRecip False
|
||||||
ExceptT $ followC shrAuthor summary audience followAP
|
followC shrAuthor (Just summary) audience followAP
|
||||||
|
|
||||||
getBrowseR :: Handler Html
|
getBrowseR :: Handler Html
|
||||||
getBrowseR = do
|
getBrowseR = do
|
||||||
|
@ -481,7 +528,7 @@ postSharerFollowR :: ShrIdent -> Handler ()
|
||||||
postSharerFollowR shrObject = do
|
postSharerFollowR shrObject = do
|
||||||
shrAuthor <- getUserShrIdent
|
shrAuthor <- getUserShrIdent
|
||||||
(summary, audience, follow) <- followSharer shrAuthor shrObject False
|
(summary, audience, follow) <- followSharer shrAuthor shrObject False
|
||||||
eid <- followC shrAuthor summary audience follow
|
eid <- runExceptT $ followC shrAuthor (Just summary) audience follow
|
||||||
setFollowMessage shrAuthor eid
|
setFollowMessage shrAuthor eid
|
||||||
redirect $ SharerR shrObject
|
redirect $ SharerR shrObject
|
||||||
|
|
||||||
|
@ -489,7 +536,7 @@ postProjectFollowR :: ShrIdent -> PrjIdent -> Handler ()
|
||||||
postProjectFollowR shrObject prjObject = do
|
postProjectFollowR shrObject prjObject = do
|
||||||
shrAuthor <- getUserShrIdent
|
shrAuthor <- getUserShrIdent
|
||||||
(summary, audience, follow) <- followProject shrAuthor shrObject prjObject False
|
(summary, audience, follow) <- followProject shrAuthor shrObject prjObject False
|
||||||
eid <- followC shrAuthor summary audience follow
|
eid <- runExceptT $ followC shrAuthor (Just summary) audience follow
|
||||||
setFollowMessage shrAuthor eid
|
setFollowMessage shrAuthor eid
|
||||||
redirect $ ProjectR shrObject prjObject
|
redirect $ ProjectR shrObject prjObject
|
||||||
|
|
||||||
|
@ -497,7 +544,7 @@ postProjectTicketFollowR :: ShrIdent -> PrjIdent -> KeyHashid LocalTicket -> Han
|
||||||
postProjectTicketFollowR shrObject prjObject tkhidObject = do
|
postProjectTicketFollowR shrObject prjObject tkhidObject = do
|
||||||
shrAuthor <- getUserShrIdent
|
shrAuthor <- getUserShrIdent
|
||||||
(summary, audience, follow) <- followTicket shrAuthor shrObject prjObject tkhidObject False
|
(summary, audience, follow) <- followTicket shrAuthor shrObject prjObject tkhidObject False
|
||||||
eid <- followC shrAuthor summary audience follow
|
eid <- runExceptT $ followC shrAuthor (Just summary) audience follow
|
||||||
setFollowMessage shrAuthor eid
|
setFollowMessage shrAuthor eid
|
||||||
redirect $ ProjectTicketR shrObject prjObject tkhidObject
|
redirect $ ProjectTicketR shrObject prjObject tkhidObject
|
||||||
|
|
||||||
|
@ -505,7 +552,7 @@ postRepoFollowR :: ShrIdent -> RpIdent -> Handler ()
|
||||||
postRepoFollowR shrObject rpObject = do
|
postRepoFollowR shrObject rpObject = do
|
||||||
shrAuthor <- getUserShrIdent
|
shrAuthor <- getUserShrIdent
|
||||||
(summary, audience, follow) <- followRepo shrAuthor shrObject rpObject False
|
(summary, audience, follow) <- followRepo shrAuthor shrObject rpObject False
|
||||||
eid <- followC shrAuthor summary audience follow
|
eid <- runExceptT $ followC shrAuthor (Just summary) audience follow
|
||||||
setFollowMessage shrAuthor eid
|
setFollowMessage shrAuthor eid
|
||||||
redirect $ RepoR shrObject rpObject
|
redirect $ RepoR shrObject rpObject
|
||||||
|
|
||||||
|
@ -526,7 +573,7 @@ postSharerUnfollowR shrFollowee = do
|
||||||
eid <- runExceptT $ do
|
eid <- runExceptT $ do
|
||||||
(summary, audience, undo) <-
|
(summary, audience, undo) <-
|
||||||
ExceptT $ undoFollowSharer shrAuthor pidAuthor shrFollowee
|
ExceptT $ undoFollowSharer shrAuthor pidAuthor shrFollowee
|
||||||
ExceptT $ undoC shrAuthor summary audience undo
|
undoC shrAuthor (Just summary) audience undo
|
||||||
setUnfollowMessage shrAuthor eid
|
setUnfollowMessage shrAuthor eid
|
||||||
redirect $ SharerR shrFollowee
|
redirect $ SharerR shrFollowee
|
||||||
|
|
||||||
|
@ -536,7 +583,7 @@ postProjectUnfollowR shrFollowee prjFollowee = do
|
||||||
eid <- runExceptT $ do
|
eid <- runExceptT $ do
|
||||||
(summary, audience, undo) <-
|
(summary, audience, undo) <-
|
||||||
ExceptT $ undoFollowProject shrAuthor pidAuthor shrFollowee prjFollowee
|
ExceptT $ undoFollowProject shrAuthor pidAuthor shrFollowee prjFollowee
|
||||||
ExceptT $ undoC shrAuthor summary audience undo
|
undoC shrAuthor (Just summary) audience undo
|
||||||
setUnfollowMessage shrAuthor eid
|
setUnfollowMessage shrAuthor eid
|
||||||
redirect $ ProjectR shrFollowee prjFollowee
|
redirect $ ProjectR shrFollowee prjFollowee
|
||||||
|
|
||||||
|
@ -546,7 +593,7 @@ postProjectTicketUnfollowR shrFollowee prjFollowee tkhidFollowee = do
|
||||||
eid <- runExceptT $ do
|
eid <- runExceptT $ do
|
||||||
(summary, audience, undo) <-
|
(summary, audience, undo) <-
|
||||||
ExceptT $ undoFollowTicket shrAuthor pidAuthor shrFollowee prjFollowee tkhidFollowee
|
ExceptT $ undoFollowTicket shrAuthor pidAuthor shrFollowee prjFollowee tkhidFollowee
|
||||||
ExceptT $ undoC shrAuthor summary audience undo
|
undoC shrAuthor (Just summary) audience undo
|
||||||
setUnfollowMessage shrAuthor eid
|
setUnfollowMessage shrAuthor eid
|
||||||
redirect $ ProjectTicketR shrFollowee prjFollowee tkhidFollowee
|
redirect $ ProjectTicketR shrFollowee prjFollowee tkhidFollowee
|
||||||
|
|
||||||
|
@ -556,7 +603,7 @@ postRepoUnfollowR shrFollowee rpFollowee = do
|
||||||
eid <- runExceptT $ do
|
eid <- runExceptT $ do
|
||||||
(summary, audience, undo) <-
|
(summary, audience, undo) <-
|
||||||
ExceptT $ undoFollowRepo shrAuthor pidAuthor shrFollowee rpFollowee
|
ExceptT $ undoFollowRepo shrAuthor pidAuthor shrFollowee rpFollowee
|
||||||
ExceptT $ undoC shrAuthor summary audience undo
|
undoC shrAuthor (Just summary) audience undo
|
||||||
setUnfollowMessage shrAuthor eid
|
setUnfollowMessage shrAuthor eid
|
||||||
redirect $ RepoR shrFollowee rpFollowee
|
redirect $ RepoR shrFollowee rpFollowee
|
||||||
|
|
||||||
|
@ -741,7 +788,7 @@ postProjectTicketsR shr prj = do
|
||||||
then Right <$> do
|
then Right <$> do
|
||||||
(summary, audience, ticket, target) <-
|
(summary, audience, ticket, target) <-
|
||||||
ExceptT $ offerTicket shrAuthor (TextHtml title) (TextPandocMarkdown desc) shr prj
|
ExceptT $ offerTicket shrAuthor (TextHtml title) (TextPandocMarkdown desc) shr prj
|
||||||
obiid <- ExceptT $ offerTicketC shrAuthor summary audience ticket target
|
obiid <- offerTicketC shrAuthor (Just summary) audience ticket target
|
||||||
ExceptT $ runDB $ do
|
ExceptT $ runDB $ do
|
||||||
mtal <- getValBy $ UniqueTicketAuthorLocalOpen obiid
|
mtal <- getValBy $ UniqueTicketAuthorLocalOpen obiid
|
||||||
return $
|
return $
|
||||||
|
@ -760,7 +807,16 @@ postProjectTicketsR shr prj = do
|
||||||
case obj of
|
case obj of
|
||||||
CreateTicket t -> t
|
CreateTicket t -> t
|
||||||
_ -> error "Create object isn't a ticket"
|
_ -> error "Create object isn't a ticket"
|
||||||
ExceptT $ createTicketC eperson sharer summary audience ticket mtarget
|
obiid <- createTicketC eperson sharer (Just summary) audience ticket mtarget
|
||||||
|
ExceptT $ runDB $ do
|
||||||
|
mtalid <- getKeyBy $ UniqueTicketAuthorLocalOpen obiid
|
||||||
|
return $
|
||||||
|
case mtalid of
|
||||||
|
Nothing ->
|
||||||
|
Left
|
||||||
|
"Create processed successfully but no ticket \
|
||||||
|
\created"
|
||||||
|
Just v -> Right v
|
||||||
case eid of
|
case eid of
|
||||||
Left e -> do
|
Left e -> do
|
||||||
setMessage $ toHtml e
|
setMessage $ toHtml e
|
||||||
|
@ -772,7 +828,7 @@ postProjectTicketsR shr prj = do
|
||||||
ltkhid <- encodeKeyHashid ltid
|
ltkhid <- encodeKeyHashid ltid
|
||||||
eobiidFollow <- runExceptT $ do
|
eobiidFollow <- runExceptT $ do
|
||||||
(summary, audience, follow) <- followTicket shrAuthor shr prj ltkhid False
|
(summary, audience, follow) <- followTicket shrAuthor shr prj ltkhid False
|
||||||
ExceptT $ followC shrAuthor summary audience follow
|
followC shrAuthor (Just summary) audience follow
|
||||||
case eobiidFollow of
|
case eobiidFollow of
|
||||||
Left e -> setMessage $ toHtml $ "Ticket created, but following it failed: " <> e
|
Left e -> setMessage $ toHtml $ "Ticket created, but following it failed: " <> e
|
||||||
Right _ -> setMessage "Ticket created."
|
Right _ -> setMessage "Ticket created."
|
||||||
|
|
|
@ -217,30 +217,33 @@ postTopReply hDest recipsA recipsC context recipF replyP after = do
|
||||||
s <- runDB $ get404 (personIdent p)
|
s <- runDB $ get404 (personIdent p)
|
||||||
return (ep, s)
|
return (ep, s)
|
||||||
let shrAuthor = sharerIdent sharer
|
let shrAuthor = sharerIdent sharer
|
||||||
elmid <- runExceptT $ do
|
eobiid <- runExceptT $ do
|
||||||
msg <- case result of
|
msg <- case result of
|
||||||
FormMissing -> throwE "Field(s) missing."
|
FormMissing -> throwE "Field(s) missing."
|
||||||
FormFailure _l -> throwE "Message submission failed, see errors below."
|
FormFailure _l -> throwE "Message submission failed, see errors below."
|
||||||
FormSuccess nm ->
|
FormSuccess nm ->
|
||||||
return $ TextPandocMarkdown $ T.filter (/= '\r') $ nmContent nm
|
return $ TextPandocMarkdown $ T.filter (/= '\r') $ nmContent nm
|
||||||
note <- ExceptT $ createThread shrAuthor msg hDest recipsA recipsC context
|
note <- ExceptT $ createThread shrAuthor msg hDest recipsA recipsC context
|
||||||
ExceptT $ noteC eperson sharer note
|
noteC eperson sharer note
|
||||||
case elmid of
|
case eobiid of
|
||||||
Left e -> do
|
Left e -> do
|
||||||
setMessage $ toHtml e
|
setMessage $ toHtml e
|
||||||
defaultLayout $(widgetFile "discussion/top-reply")
|
defaultLayout $(widgetFile "discussion/top-reply")
|
||||||
Right lmid -> do
|
Right obiid -> do
|
||||||
setMessage "Message submitted."
|
setMessage "Message submitted."
|
||||||
|
|
||||||
encodeRouteFed <- getEncodeRouteFed
|
encodeRouteFed <- getEncodeRouteFed
|
||||||
let encodeRecipRoute = encodeRouteFed hDest
|
let encodeRecipRoute = encodeRouteFed hDest
|
||||||
(summary, audience, follow) <- C.follow shrAuthor (encodeRecipRoute context) (encodeRecipRoute recipF) False
|
(summary, audience, follow) <- C.follow shrAuthor (encodeRecipRoute context) (encodeRecipRoute recipF) False
|
||||||
eobiidFollow <- followC shrAuthor summary audience follow
|
eobiidFollow <- runExceptT $ followC shrAuthor (Just summary) audience follow
|
||||||
case eobiidFollow of
|
case eobiidFollow of
|
||||||
Left e -> setMessage $ toHtml $ "Following failed: " <> e
|
Left e -> setMessage $ toHtml $ "Following failed: " <> e
|
||||||
Right _ -> return ()
|
Right _ -> return ()
|
||||||
|
|
||||||
redirect $ after lmid
|
mlmid <- runDB $ getKeyBy $ UniqueLocalMessageCreate obiid
|
||||||
|
case mlmid of
|
||||||
|
Nothing -> error "noteC succeeded but no lmid found for obiid"
|
||||||
|
Just lmid -> redirect $ after lmid
|
||||||
|
|
||||||
getReply
|
getReply
|
||||||
:: (MessageId -> Route App)
|
:: (MessageId -> Route App)
|
||||||
|
@ -273,29 +276,32 @@ postReply hDest recipsA recipsC context recipF replyG replyP after getdid midPar
|
||||||
s <- runDB $ get404 (personIdent p)
|
s <- runDB $ get404 (personIdent p)
|
||||||
return (ep, s)
|
return (ep, s)
|
||||||
let shrAuthor = sharerIdent sharer
|
let shrAuthor = sharerIdent sharer
|
||||||
elmid <- runExceptT $ do
|
eobiid <- runExceptT $ do
|
||||||
msg <- case result of
|
msg <- case result of
|
||||||
FormMissing -> throwE "Field(s) missing."
|
FormMissing -> throwE "Field(s) missing."
|
||||||
FormFailure _l -> throwE "Message submission failed, see errors below."
|
FormFailure _l -> throwE "Message submission failed, see errors below."
|
||||||
FormSuccess nm ->
|
FormSuccess nm ->
|
||||||
return $ TextPandocMarkdown $ T.filter (/= '\r') $ nmContent nm
|
return $ TextPandocMarkdown $ T.filter (/= '\r') $ nmContent nm
|
||||||
note <- ExceptT $ createReply shrAuthor msg hDest recipsA recipsC context midParent
|
note <- ExceptT $ createReply shrAuthor msg hDest recipsA recipsC context midParent
|
||||||
ExceptT $ noteC eperson sharer note
|
noteC eperson sharer note
|
||||||
case elmid of
|
case eobiid of
|
||||||
Left e -> do
|
Left e -> do
|
||||||
setMessage $ toHtml e
|
setMessage $ toHtml e
|
||||||
mtn <- runDB $ getNode getdid midParent
|
mtn <- runDB $ getNode getdid midParent
|
||||||
now <- liftIO getCurrentTime
|
now <- liftIO getCurrentTime
|
||||||
defaultLayout $(widgetFile "discussion/reply")
|
defaultLayout $(widgetFile "discussion/reply")
|
||||||
Right lmid -> do
|
Right obiid -> do
|
||||||
setMessage "Message submitted."
|
setMessage "Message submitted."
|
||||||
|
|
||||||
encodeRouteFed <- getEncodeRouteFed
|
encodeRouteFed <- getEncodeRouteFed
|
||||||
let encodeRecipRoute = encodeRouteFed hDest
|
let encodeRecipRoute = encodeRouteFed hDest
|
||||||
(summary, audience, follow) <- C.follow shrAuthor (encodeRecipRoute context) (encodeRecipRoute recipF) False
|
(summary, audience, follow) <- C.follow shrAuthor (encodeRecipRoute context) (encodeRecipRoute recipF) False
|
||||||
eobiidFollow <- followC shrAuthor summary audience follow
|
eobiidFollow <- runExceptT $ followC shrAuthor (Just summary) audience follow
|
||||||
case eobiidFollow of
|
case eobiidFollow of
|
||||||
Left e -> setMessage $ toHtml $ "Following failed: " <> e
|
Left e -> setMessage $ toHtml $ "Following failed: " <> e
|
||||||
Right _ -> return ()
|
Right _ -> return ()
|
||||||
|
|
||||||
redirect $ after lmid
|
mlmid <- runDB $ getKeyBy $ UniqueLocalMessageCreate obiid
|
||||||
|
case mlmid of
|
||||||
|
Nothing -> error "noteC succeeded but no lmid found for obiid"
|
||||||
|
Just lmid -> redirect $ after lmid
|
||||||
|
|
|
@ -45,6 +45,7 @@ where
|
||||||
import Control.Exception hiding (Handler)
|
import Control.Exception hiding (Handler)
|
||||||
import Control.Monad.IO.Class (liftIO)
|
import Control.Monad.IO.Class (liftIO)
|
||||||
import Control.Monad.Logger (logWarn)
|
import Control.Monad.Logger (logWarn)
|
||||||
|
import Control.Monad.Trans.Except
|
||||||
import Data.Bifunctor
|
import Data.Bifunctor
|
||||||
import Data.Git.Graph
|
import Data.Git.Graph
|
||||||
import Data.Git.Harder
|
import Data.Git.Harder
|
||||||
|
@ -533,7 +534,7 @@ postPostReceiveR = do
|
||||||
$forall c <- lasts
|
$forall c <- lasts
|
||||||
<li>^{commitW c}
|
<li>^{commitW c}
|
||||||
|]
|
|]
|
||||||
eid <- pushCommitsC user summary pushAP shr rp
|
eid <- runExceptT $ pushCommitsC user summary pushAP shr rp
|
||||||
case eid of
|
case eid of
|
||||||
Left e -> liftIO $ throwIO $ userError $ T.unpack e
|
Left e -> liftIO $ throwIO $ userError $ T.unpack e
|
||||||
Right obiid -> do
|
Right obiid -> do
|
||||||
|
|
Loading…
Reference in a new issue