1
0
Fork 0
mirror of https://code.sup39.dev/repos/Wqawg synced 2024-12-29 03:44:50 +09:00

Provide ActivityPub representation of tickets in getTicketR

This commit is contained in:
fr33domlover 2019-06-03 21:52:34 +00:00
parent eedbf1d193
commit 708f626294
5 changed files with 171 additions and 4 deletions

View file

@ -145,5 +145,6 @@
/s/#ShrIdent/p/#PrjIdent/t/#Int/rdeps TicketReverseDepsR GET /s/#ShrIdent/p/#PrjIdent/t/#Int/rdeps TicketReverseDepsR GET
/s/#ShrIdent/p/#PrjIdent/t/#Int/participants TicketParticipantsR GET /s/#ShrIdent/p/#PrjIdent/t/#Int/participants TicketParticipantsR GET
/s/#ShrIdent/p/#PrjIdent/t/#Int/team TicketTeamR GET /s/#ShrIdent/p/#PrjIdent/t/#Int/team TicketTeamR GET
/s/#ShrIdent/p/#PrjIdent/t/#Int/events TicketEventsR GET
/s/#ShrIdent/p/#PrjIdent/w/+Texts WikiPageR GET /s/#ShrIdent/p/#PrjIdent/w/+Texts WikiPageR GET

View file

@ -681,6 +681,7 @@ instance YesodRemoteActorStore App where
siteActorFetchShare = appActorFetchShare siteActorFetchShare = appActorFetchShare
instance YesodActivityPub App where instance YesodActivityPub App where
siteInstanceHost = appInstanceHost . appSettings
sitePostSignedHeaders _ = sitePostSignedHeaders _ =
hRequestTarget :| [hHost, hDate, hDigest, hActivityPubActor] hRequestTarget :| [hHost, hDate, hDigest, hActivityPubActor]
siteGetHttpSign = do siteGetHttpSign = do
@ -904,5 +905,8 @@ instance YesodBreadcrumbs App where
TicketTeamR shr prj num -> ( "Team" TicketTeamR shr prj num -> ( "Team"
, Just $ TicketR shr prj num , Just $ TicketR shr prj num
) )
TicketEventsR shr prj num -> ( "Events"
, Just $ TicketR shr prj num
)
WikiPageR shr prj _page -> ("Wiki", Just $ ProjectR shr prj) WikiPageR shr prj _page -> ("Wiki", Just $ ProjectR shr prj)

View file

@ -50,6 +50,7 @@ module Vervis.Handler.Ticket
, getTicketReverseDepsR , getTicketReverseDepsR
, getTicketParticipantsR , getTicketParticipantsR
, getTicketTeamR , getTicketTeamR
, getTicketEventsR
) )
where where
@ -72,6 +73,7 @@ import Data.Traversable (for)
import Database.Persist import Database.Persist
import Network.HTTP.Types (StdMethod (DELETE, POST)) import Network.HTTP.Types (StdMethod (DELETE, POST))
import Text.Blaze.Html (Html, toHtml) import Text.Blaze.Html (Html, toHtml)
import Text.Blaze.Html.Renderer.Text
import Yesod.Auth (requireAuthId, maybeAuthId) import Yesod.Auth (requireAuthId, maybeAuthId)
import Yesod.Core import Yesod.Core
import Yesod.Core.Handler import Yesod.Core.Handler
@ -80,16 +82,20 @@ import Yesod.Form.Types (FormResult (..))
import Yesod.Persist.Core (runDB, get404, getBy404) import Yesod.Persist.Core (runDB, get404, getBy404)
import qualified Data.Text as T (filter, intercalate, pack) import qualified Data.Text as T (filter, intercalate, pack)
import qualified Data.Text.Lazy as TL
import qualified Database.Esqueleto as E import qualified Database.Esqueleto as E
import Database.Persist.Sql.Graph.TransitiveReduction (trrFix) import Database.Persist.Sql.Graph.TransitiveReduction (trrFix)
import Data.Aeson.Encode.Pretty.ToEncoding import Data.Aeson.Encode.Pretty.ToEncoding
import Network.FedURI import Network.FedURI
import Web.ActivityPub import Web.ActivityPub hiding (Ticket (..))
import Yesod.ActivityPub
import Yesod.FedURI import Yesod.FedURI
import Yesod.Hashids import Yesod.Hashids
import qualified Web.ActivityPub as AP
import Data.Maybe.Local (partitionMaybePairs) import Data.Maybe.Local (partitionMaybePairs)
import Database.Persist.Local import Database.Persist.Local
import Yesod.Persist.Local import Yesod.Persist.Local
@ -211,7 +217,7 @@ getTicketNewR shar proj = do
((_result, widget), enctype) <- runFormPost $ newTicketForm wid ((_result, widget), enctype) <- runFormPost $ newTicketForm wid
defaultLayout $(widgetFile "ticket/new") defaultLayout $(widgetFile "ticket/new")
getTicketR :: ShrIdent -> PrjIdent -> Int -> Handler Html getTicketR :: ShrIdent -> PrjIdent -> Int -> Handler TypedContent
getTicketR shar proj num = do getTicketR shar proj num = do
mpid <- maybeAuthId mpid <- maybeAuthId
( wshr, wfl, ( wshr, wfl,
@ -276,7 +282,39 @@ getTicketR shar proj num = do
TSNew -> wffNew filt TSNew -> wffNew filt
TSTodo -> wffTodo filt TSTodo -> wffTodo filt
TSClosed -> wffClosed filt TSClosed -> wffClosed filt
defaultLayout $(widgetFile "ticket/one") encodeRouteLocal <- getEncodeRouteLocal
encodeRouteHome <- getEncodeRouteHome
let siblingUri =
encodeRouteHome . TicketR shar proj . ticketNumber . entityVal
ticketAP = AP.Ticket
{ AP.ticketId =
Just $ encodeRouteLocal $ TicketR shar proj num
, AP.ticketAttributedTo =
encodeRouteHome $ SharerR $ sharerIdent author
, AP.ticketPublished = Just $ ticketCreated ticket
, AP.ticketUpdated = Nothing
, AP.ticketContext = encodeRouteLocal $ ProjectR shar proj
, AP.ticketName = Just $ "#" <> T.pack (show num)
, AP.ticketSummary =
TextHtml $ TL.toStrict $ renderHtml $ toHtml $
ticketTitle ticket
, AP.ticketContent = TextHtml $ ticketDescription ticket
, AP.ticketSource = TextPandocMarkdown $ ticketSource ticket
, AP.ticketReplies =
encodeRouteLocal $ TicketDiscussionR shar proj num
, AP.ticketAssignedTo =
encodeRouteHome . SharerR . sharerIdent . fst <$> massignee
, AP.ticketIsResolved = ticketStatus ticket == TSClosed
, AP.ticketParticipants =
encodeRouteLocal $ TicketParticipantsR shar proj num
, AP.ticketTeam =
encodeRouteLocal $ TicketTeamR shar proj num
, AP.ticketDependsOn = map siblingUri deps
, AP.ticketDependedBy = map siblingUri rdeps
, AP.ticketEvents =
encodeRouteLocal $ TicketEventsR shar proj num
}
provideHtmlAndAP ticketAP $(widgetFile "ticket/one")
putTicketR :: ShrIdent -> PrjIdent -> Int -> Handler Html putTicketR :: ShrIdent -> PrjIdent -> Int -> Handler Html
putTicketR shar proj num = do putTicketR shar proj num = do
@ -898,3 +936,6 @@ getTicketTeamR shr prj num = do
mk (Just _) (Just _) = error errBoth mk (Just _) (Just _) = error errBoth
mk (Just x) Nothing = Left x mk (Just x) Nothing = Left x
mk Nothing (Just y) = Right y mk Nothing (Just y) = Right y
getTicketEventsR :: ShrIdent -> PrjIdent -> Int -> Handler TypedContent
getTicketEventsR shr prj num = error "TODO not implemented"

View file

@ -37,8 +37,13 @@ module Web.ActivityPub
, CollectionPage (..) , CollectionPage (..)
, Recipient (..) , Recipient (..)
-- * Activity -- * Content objects
, Note (..) , Note (..)
, TextHtml (..)
, TextPandocMarkdown (..)
, Ticket (..)
-- * Activity
, Accept (..) , Accept (..)
, Create (..) , Create (..)
, Follow (..) , Follow (..)
@ -600,6 +605,101 @@ encodeNote host (Note id_ mreply mcontext mpublished content) attrib =
<> "content" .= content <> "content" .= content
-} -}
newtype TextHtml = TextHtml
{ unTextHtml :: Text
}
deriving (FromJSON, ToJSON)
newtype TextPandocMarkdown = TextPandocMarkdown
{ unTextPandocMarkdown :: Text
}
deriving (FromJSON, ToJSON)
data Ticket = Ticket
{ ticketId :: Maybe LocalURI
, ticketAttributedTo :: FedURI
, ticketPublished :: Maybe UTCTime
, ticketUpdated :: Maybe UTCTime
, ticketContext :: LocalURI
, ticketName :: Maybe Text
, ticketSummary :: TextHtml
, ticketContent :: TextHtml
, ticketSource :: TextPandocMarkdown
, ticketReplies :: LocalURI
, ticketAssignedTo :: Maybe FedURI
, ticketIsResolved :: Bool
, ticketParticipants :: LocalURI
, ticketTeam :: LocalURI
, ticketDependsOn :: [FedURI]
, ticketDependedBy :: [FedURI]
, ticketEvents :: LocalURI
}
instance ActivityPub Ticket where
jsonldContext _ = ContextAS2
parseObject o = do
typ <- o .: "type"
unless (typ == ("Ticket" :: Text)) $
fail "type isn't Ticket"
mediaType <- o .: "mediaType"
unless (mediaType == ("text/html" :: Text)) $
fail "mediaType isn't HTML"
source <- o .: "source"
sourceType <- source .: "mediaType"
unless (sourceType == ("text/markdown; variant=Pandoc" :: Text)) $
fail "source mediaType isn't Pandoc Markdown"
(h, context) <- f2l <$> o .: "context"
fmap (h,) $
Ticket
<$> withHostMaybe h (fmap f2l <$> o .:? "id")
<*> o .: "attributedTo"
<*> o .:? "published"
<*> o .:? "updated"
<*> pure context
<*> o .:? "name"
<*> (TextHtml . sanitizeBalance <$> o .: "summary")
<*> (TextHtml . sanitizeBalance <$> o .: "content")
<*> source .: "content"
<*> withHost h (f2l <$> o .: "replies")
<*> o .:? (frg <> "assignedTo")
<*> o .: (frg <> "isResolved")
<*> withHost h (f2l <$> o .: (frg <> "participants"))
<*> withHost h (f2l <$> o .: (frg <> "team"))
<*> o .:? (frg <> "dependsOn") .!= []
<*> o .:? (frg <> "dependedBy") .!= []
<*> withHost h (f2l <$> o .: (frg <> "events"))
toSeries host
(Ticket id_ attributedTo published updated context name summary content
source replies assignedTo isResolved participants team
dependsOn dependedBy events)
= "type" .= ("Ticket" :: Text)
<> "id" .=? (l2f host <$> id_)
<> "attributedTo" .= attributedTo
<> "published" .=? published
<> "updated" .=? updated
<> "context" .= l2f host context
<> "name" .=? name
<> "summary" .= summary
<> "content" .= content
<> "mediaType" .= ("text/html" :: Text)
<> "source" .= object
[ "content" .= source
, "mediaType" .= ("text/markdown; variant=Pandoc" :: Text)
]
<> "replies" .= l2f host replies
<> (frg <> "assignedTo") .=? assignedTo
<> (frg <> "isResolved") .= isResolved
<> (frg <> "participants") .= l2f host participants
<> (frg <> "team") .= l2f host team
<> (frg <> "dependsOn") .=% dependsOn
<> (frg <> "dependedBy") .=% dependedBy
<> (frg <> "events") .= l2f host events
data Accept = Accept data Accept = Accept
{ acceptObject :: FedURI { acceptObject :: FedURI
} }

View file

@ -17,6 +17,7 @@ module Yesod.ActivityPub
( YesodActivityPub (..) ( YesodActivityPub (..)
, deliverActivity , deliverActivity
, forwardActivity , forwardActivity
, provideHtmlAndAP
) )
where where
@ -36,11 +37,13 @@ import qualified Data.Text as T
import Network.HTTP.Signature import Network.HTTP.Signature
import Data.Aeson.Encode.Pretty.ToEncoding
import Network.FedURI import Network.FedURI
import Web.ActivityPub import Web.ActivityPub
import Yesod.MonadSite import Yesod.MonadSite
class Yesod site => YesodActivityPub site where class Yesod site => YesodActivityPub site where
siteInstanceHost :: site -> Text
sitePostSignedHeaders :: site -> NonEmpty HeaderName sitePostSignedHeaders :: site -> NonEmpty HeaderName
siteGetHttpSign :: (MonadSite m, SiteEnv m ~ site) siteGetHttpSign :: (MonadSite m, SiteEnv m ~ site)
=> m (KeyId, ByteString -> Signature) => m (KeyId, ByteString -> Signature)
@ -111,3 +114,21 @@ forwardActivity inbox sig rSender body = do
, "> success: ", T.pack $ show $ responseStatus resp , "> success: ", T.pack $ show $ responseStatus resp
] ]
return result return result
provideHtmlAndAP
:: (YesodActivityPub site, ActivityPub a)
=> a -> WidgetFor site () -> HandlerFor site TypedContent
provideHtmlAndAP object widget = do
host <- getsYesod siteInstanceHost
let doc = Doc host object
selectRep $ do
provideAP $ pure doc
provideRep $ do
mval <- lookupGetParam "prettyjson"
defaultLayout $
case mval of
Just "true" ->
[whamlet|
<div><pre>#{encodePrettyToLazyText doc}
|]
_ -> widget