Add patch version route and GET handler, serving a specific patch file

This commit is contained in:
fr33domlover 2020-05-25 09:40:48 +00:00
parent 55c87b8a54
commit c63479470e
6 changed files with 98 additions and 2 deletions

View file

@ -445,6 +445,7 @@ TicketUnderProject
Patch Patch
ticket TicketId ticket TicketId
created UTCTime
content Text content Text
TicketDependency TicketDependency

View file

@ -201,4 +201,6 @@
/s/#ShrIdent/pt/#TicketAuthorLocalKeyHashid/followers SharerPatchFollowersR GET /s/#ShrIdent/pt/#TicketAuthorLocalKeyHashid/followers SharerPatchFollowersR GET
/s/#ShrIdent/pt/#TicketAuthorLocalKeyHashid/events SharerPatchEventsR GET /s/#ShrIdent/pt/#TicketAuthorLocalKeyHashid/events SharerPatchEventsR GET
/s/#ShrIdent/pt/#TicketAuthorLocalKeyHashid/v/#PatchKeyHashid SharerPatchVersionR GET
/s/#ShrIdent/p/#PrjIdent/w/+Texts WikiPageR GET /s/#ShrIdent/p/#PrjIdent/w/+Texts WikiPageR GET

View file

@ -70,7 +70,7 @@ import qualified Network.HTTP.Signature as S (Algorithm (..))
import Crypto.PublicVerifKey import Crypto.PublicVerifKey
import Network.FedURI import Network.FedURI
import Web.ActivityAccess import Web.ActivityAccess
import Web.ActivityPub hiding (Ticket, TicketDependency) import Web.ActivityPub hiding (Ticket, TicketDependency, Patch)
import Yesod.ActivityPub import Yesod.ActivityPub
import Yesod.FedURI import Yesod.FedURI
import Yesod.Hashids import Yesod.Hashids
@ -131,6 +131,7 @@ type LocalMessageKeyHashid = KeyHashid LocalMessage
type LocalTicketKeyHashid = KeyHashid LocalTicket type LocalTicketKeyHashid = KeyHashid LocalTicket
type TicketAuthorLocalKeyHashid = KeyHashid TicketAuthorLocal type TicketAuthorLocalKeyHashid = KeyHashid TicketAuthorLocal
type TicketDepKeyHashid = KeyHashid TicketDependency type TicketDepKeyHashid = KeyHashid TicketDependency
type PatchKeyHashid = KeyHashid Patch
-- This is where we define all of the routes in our application. For a full -- This is where we define all of the routes in our application. For a full
-- explanation of the syntax, please see: -- explanation of the syntax, please see:

View file

@ -21,9 +21,12 @@ module Vervis.Handler.Patch
, getSharerPatchReverseDepsR , getSharerPatchReverseDepsR
, getSharerPatchFollowersR , getSharerPatchFollowersR
, getSharerPatchEventsR , getSharerPatchEventsR
, getSharerPatchVersionR
) )
where where
import Control.Monad
import Data.Bitraversable import Data.Bitraversable
import Data.Text (Text) import Data.Text (Text)
import Data.Traversable import Data.Traversable
@ -34,7 +37,7 @@ import Yesod.Persist.Core
import qualified Database.Esqueleto as E import qualified Database.Esqueleto as E
import Network.FedURI import Network.FedURI
import Web.ActivityPub hiding (Ticket (..)) import Web.ActivityPub hiding (Ticket (..), Patch (..))
import Yesod.ActivityPub import Yesod.ActivityPub
import Yesod.FedURI import Yesod.FedURI
import Yesod.Hashids import Yesod.Hashids
@ -51,6 +54,7 @@ import Vervis.FedURI
import Vervis.Foundation import Vervis.Foundation
import Vervis.Model import Vervis.Model
import Vervis.Model.Ident import Vervis.Model.Ident
import Vervis.Model.Repo
import Vervis.Model.Ticket import Vervis.Model.Ticket
import Vervis.Paginate import Vervis.Paginate
import Vervis.Patch import Vervis.Patch
@ -208,3 +212,37 @@ getSharerPatchEventsR shr talkhid = do
provideEmptyCollection provideEmptyCollection
CollectionTypeOrdered CollectionTypeOrdered
(SharerPatchEventsR shr talkhid) (SharerPatchEventsR shr talkhid)
getSharerPatchVersionR
:: ShrIdent
-> KeyHashid TicketAuthorLocal
-> KeyHashid Patch
-> Handler TypedContent
getSharerPatchVersionR shr talkhid ptkhid = do
(vcs, patch) <- runDB $ do
(_, _, Entity tid _, repo) <- getSharerPatch404 shr talkhid
(,) <$> case repo of
Left (_, Entity _ trl) ->
repoVcs <$> getJust (ticketRepoLocalRepo trl)
Right _ ->
error "TODO determine mediaType of patch of remote repo"
<*> do ptid <- decodeKeyHashid404 ptkhid
pt <- get404 ptid
unless (patchTicket pt == tid) notFound
return pt
encodeRouteLocal <- getEncodeRouteLocal
encodeRouteHome <- getEncodeRouteHome
let versionAP = AP.Patch
{ AP.patchId = encodeRouteLocal here
, AP.patchAttributedTo = encodeRouteHome $ SharerR shr
, AP.patchPublished = patchCreated patch
, AP.patchContext = encodeRouteLocal $ SharerPatchR shr talkhid
, AP.patchType =
case vcs of
VCSDarcs -> PatchTypeDarcs
VCSGit -> error "TODO add PatchType for git patches"
, AP.patchContent = patchContent patch
}
provideHtmlAndAP versionAP $ redirectToPrettyJSON here
where
here = SharerPatchVersionR shr talkhid ptkhid

View file

@ -1580,6 +1580,8 @@ changes hLocal ctx =
, removeField "TicketContextLocal" "project" , removeField "TicketContextLocal" "project"
-- 249 -- 249
, addEntities model_2020_05_17 , addEntities model_2020_05_17
-- 250
, addFieldPrimRequired "Patch" defaultTime "created"
] ]
migrateDB migrateDB

View file

@ -46,6 +46,8 @@ module Web.ActivityPub
, TicketDependency (..) , TicketDependency (..)
, TextHtml (..) , TextHtml (..)
, TextPandocMarkdown (..) , TextPandocMarkdown (..)
, PatchType (..)
, Patch (..)
, TicketLocal (..) , TicketLocal (..)
, Ticket (..) , Ticket (..)
, Author (..) , Author (..)
@ -823,6 +825,56 @@ newtype TextPandocMarkdown = TextPandocMarkdown
} }
deriving (FromJSON, ToJSON) deriving (FromJSON, ToJSON)
data PatchType = PatchTypeDarcs
instance FromJSON PatchType where
parseJSON = withText "PatchType" parse
where
parse "application/x-darcs-patch" = pure PatchTypeDarcs
parse t = fail $ "Unknown patch mediaType: " ++ T.unpack t
instance ToJSON PatchType where
toJSON = error "toJSON PatchType"
toEncoding = toEncoding . render
where
render PatchTypeDarcs = "application/x-darcs-patch" :: Text
data Patch u = Patch
{ patchId :: LocalURI
, patchAttributedTo :: ObjURI u
, patchPublished :: UTCTime
, patchContext :: LocalURI
, patchType :: PatchType
, patchContent :: Text
}
instance ActivityPub Patch where
jsonldContext _ = [as2Context, forgeContext]
parseObject o = do
typ <- o .: "type"
unless (typ == ("Patch" :: Text)) $
fail "type isn't Patch"
ObjURI a id_ <- o .: "id"
fmap (a,) $
Patch id_
<$> o .: "attributedTo"
<*> o .: "published"
<*> withAuthorityO a (o .: "context")
<*> o .: "mediaType"
<*> o .: "content"
toSeries a (Patch id_ attrib published context typ content)
= "id" .= ObjURI a id_
<> "type" .= ("Patch" :: Text)
<> "attributedTo" .= attrib
<> "context" .= ObjURI a context
<> "published" .= published
<> "mediaType" .= typ
<> "content" .= content
data TicketLocal = TicketLocal data TicketLocal = TicketLocal
{ ticketId :: LocalURI { ticketId :: LocalURI
, ticketReplies :: LocalURI , ticketReplies :: LocalURI