UI, C2S, S2S: Factory: Make allowed types editable

I added a new activity type, Patch. There's already a ForgeFed type with
the same name, used for representing patches of course. Perhaps the
duplication will work, since these types are used in different
situations. I'd happily change to Edit, but Patch may become the
standard name in Fediverse software. So let's go with that.
This commit is contained in:
Pere Lev 2024-08-07 13:16:25 +03:00
parent b74d0d46c4
commit 94762ca76c
No known key found for this signature in database
GPG key ID: 5252C5C863E5E57D
9 changed files with 306 additions and 24 deletions

View file

@ -1149,7 +1149,7 @@ factoryCreate now factoryID verse (AP.Create obj muOrigin) = do
throwE "This Create-Team isn't for me" throwE "This Create-Team isn't for me"
factoryCreateNew NATeam now factoryID verse detail factoryCreateNew NATeam now factoryID verse detail
AP.CreateFactory _ mlocal -> do AP.CreateFactory _ mlocal _ -> do
(h, local) <- fromMaybeE mlocal "No factory id provided" (h, local) <- fromMaybeE mlocal "No factory id provided"
let luFactory = AP.actorId local let luFactory = AP.actorId local
unless (uMe == ObjURI h luFactory) $ unless (uMe == ObjURI h luFactory) $
@ -1823,6 +1823,107 @@ factoryJoin
-> ActE (Text, Act (), Next) -> ActE (Text, Act (), Next)
factoryJoin = topicJoin factoryResource LocalResourceFactory factoryJoin = topicJoin factoryResource LocalResourceFactory
-- Meaning: An actor is asking to update an object
-- Behavior:
-- * Verify I'm the object being patched
-- * Verify sender is authorized
-- * Insert the Patch to my inbox
-- * Update my available types in DB
-- * Forward the Patch to my followers
-- * Send Accept to sender & to my followers
factoryPatch
:: UTCTime
-> FactoryId
-> Verse
-> AP.Patch' URIMode
-> ActE (Text, Act (), Next)
factoryPatch now factoryMeID (Verse authorIdMsig body) patch = do
-- Verify that a capability is provided
uCap <- do
let muCap = AP.activityCapability $ actbActivity body
fromMaybeE muCap "No capability provided"
-- Check patch activity
types <- do
routeOrRemote <- parseFedURI $ AP.patchObject patch
actorOrRemote <- bitraverse parseLocalActorE' pure routeOrRemote
case actorOrRemote of
Left (LocalActorFactory f) | f == factoryMeID ->
return $ AP.patchAvailableActorTypes patch
_ -> throwE "Patch.object isn't me"
-- Verify the specified capability gives relevant access
verifyCapability''
uCap authorIdMsig (LocalResourceFactory factoryMeID) AP.RoleAdmin
maybeNew <- withDBExcept $ do
-- Grab me from DB
resourceID <- lift $ factoryResource <$> getJust factoryMeID
Resource actorMeID <- lift $ getJust resourceID
actorMe <- lift $ getJust actorMeID
maybePatchDB <- lift $ insertToInbox now authorIdMsig body (actorInbox actorMe) False
lift $ for maybePatchDB $ \ (inboxItemID, _patchDB) -> do
-- Update my fields in DB
update factoryMeID
[ FactoryAllowDeck =. (AP.ActorTypeTicketTracker `elem` types)
, FactoryAllowProject =. (AP.ActorTypeProject `elem` types)
, FactoryAllowTeam =. (AP.ActorTypeTeam `elem` types)
]
-- Prepare forwarding Invite to my followers
sieve <- do
factoryHash <- encodeKeyHashid factoryMeID
return $ makeRecipientSet [] [LocalStageFactoryFollowers factoryHash]
-- Prepare an Accept activity and insert to my outbox
accept@(actionAccept, _, _, _) <- prepareAccept
acceptID <- insertEmptyOutboxItem' (actorOutbox actorMe) now
_luAccept <- updateOutboxItem' (LocalActorFactory factoryMeID) acceptID actionAccept
return (actorMeID, sieve, acceptID, accept, inboxItemID)
case maybeNew of
Nothing -> done "I already have this activity in my inbox"
Just (actorMeID, sieve, acceptID, (actionAccept, localRecipsAccept, remoteRecipsAccept, fwdHostsAccept), inboxItemID) -> do
forwardActivity
authorIdMsig body (LocalActorFactory factoryMeID) actorMeID sieve
lift $ sendActivity
(LocalActorFactory factoryMeID) actorMeID localRecipsAccept
remoteRecipsAccept fwdHostsAccept acceptID actionAccept
doneDB inboxItemID "Recorded and forwarded the Patch, updated fields, sent an Accept"
where
prepareAccept = do
encodeRouteHome <- getEncodeRouteHome
audSender <- lift $ makeAudSenderOnly authorIdMsig
audMe <-
AudLocal [] . pure . LocalStageFactoryFollowers <$>
encodeKeyHashid factoryMeID
uPatch <- lift $ getActivityURI authorIdMsig
let (recipientSet, remoteActors, fwdHosts, audLocal, audRemote) =
collectAudience [audSender, audMe]
recips = map encodeRouteHome audLocal ++ audRemote
action = AP.Action
{ AP.actionCapability = Nothing
, AP.actionSummary = Nothing
, AP.actionAudience = AP.Audience recips [] [] [] [] []
, AP.actionFulfills = [uPatch]
, AP.actionSpecific = AP.AcceptActivity AP.Accept
{ AP.acceptObject = uPatch
, AP.acceptResult = Nothing
}
}
return (action, recipientSet, remoteActors, fwdHosts)
-- Meaning: An actor A is removing actor B from collection C -- Meaning: An actor A is removing actor B from collection C
-- Behavior: -- Behavior:
-- * If C is my collaborators collection: -- * If C is my collaborators collection:
@ -2542,6 +2643,7 @@ factoryBehavior now factoryID (FactoryMsgVerse verse@(Verse _authorIdMsig body))
AP.GrantActivity grant -> factoryGrant now factoryID verse grant AP.GrantActivity grant -> factoryGrant now factoryID verse grant
AP.InviteActivity invite -> factoryInvite now factoryID verse invite AP.InviteActivity invite -> factoryInvite now factoryID verse invite
AP.JoinActivity join -> factoryJoin now factoryID verse join AP.JoinActivity join -> factoryJoin now factoryID verse join
AP.PatchActivity patch -> factoryPatch now factoryID verse patch
AP.RemoveActivity remove -> factoryRemove now factoryID verse remove AP.RemoveActivity remove -> factoryRemove now factoryID verse remove
AP.RevokeActivity revoke -> factoryRevoke now factoryID verse revoke AP.RevokeActivity revoke -> factoryRevoke now factoryID verse revoke
_ -> throwE "Unsupported activity type for Factory" _ -> throwE "Unsupported activity type for Factory"

View file

@ -436,8 +436,9 @@ clientCreateFactory
-> PersonId -> PersonId
-> ClientMsg -> ClientMsg
-> AP.ActorDetail -> AP.ActorDetail
-> [AP.ActorType]
-> ActE OutboxItemId -> ActE OutboxItemId
clientCreateFactory now personMeID (ClientMsg maybeCap localRecips remoteRecips fwdHosts action) detail = do clientCreateFactory now personMeID (ClientMsg maybeCap localRecips remoteRecips fwdHosts action) detail types = do
-- Check input -- Check input
verifyNothingE maybeCap "Capability not needed" verifyNothingE maybeCap "Capability not needed"
@ -532,9 +533,9 @@ clientCreateFactory now personMeID (ClientMsg maybeCap localRecips remoteRecips
rid <- insert $ Resource aid rid <- insert $ Resource aid
fid <- insert Factory fid <- insert Factory
{ factoryResource = rid { factoryResource = rid
, factoryAllowDeck = True , factoryAllowDeck = AP.ActorTypeTicketTracker `elem` types
, factoryAllowProject = True , factoryAllowProject = AP.ActorTypeProject `elem` types
, factoryAllowTeam = True , factoryAllowTeam = AP.ActorTypeTeam `elem` types
} }
return (fid, rid, actorFollowers a) return (fid, rid, actorFollowers a)
@ -556,8 +557,19 @@ clientCreateFactory now personMeID (ClientMsg maybeCap localRecips remoteRecips
, AP.actorPublicKeys = [] , AP.actorPublicKeys = []
, AP.actorSshKeys = [] , AP.actorSshKeys = []
} }
types' =
mapMaybe
(\ typ ->
if typ `elem` types
then Just typ
else Nothing
)
[ AP.ActorTypeTicketTracker
, AP.ActorTypeProject
, AP.ActorTypeTeam
]
specific = AP.CreateActivity AP.Create specific = AP.CreateActivity AP.Create
{ AP.createObject = AP.CreateFactory ttdetail (Just (hLocal, ttlocal)) { AP.createObject = AP.CreateFactory ttdetail (Just (hLocal, ttlocal)) types'
, AP.createOrigin = Nothing , AP.createOrigin = Nothing
} }
return action { AP.actionSpecific = specific } return action { AP.actionSpecific = specific }
@ -609,10 +621,10 @@ clientCreate now personMeID msg (AP.Create object muOrigin) =
uOrigin <- fromMaybeE muOrigin "'origin' required for Create TicketTracker" uOrigin <- fromMaybeE muOrigin "'origin' required for Create TicketTracker"
clientCreateActor now personMeID msg detail uOrigin clientCreateActor now personMeID msg detail uOrigin
AP.CreateFactory detail mlocal -> do AP.CreateFactory detail mlocal types -> do
verifyNothingE mlocal "Factory id must not be provided" verifyNothingE mlocal "Factory id must not be provided"
verifyNothingE muOrigin "'target' not supported in Create Factory" verifyNothingE muOrigin "'target' not supported in Create Factory"
clientCreateFactory now personMeID msg detail clientCreateFactory now personMeID msg detail types
_ -> throwE "Unsupported Create object for C2S" _ -> throwE "Unsupported Create object for C2S"
@ -975,6 +987,52 @@ clientOffer now personMeID (ClientMsg maybeCap localRecips remoteRecips fwdHosts
fwdHosts offerID action fwdHosts offerID action
return offerID return offerID
-- Meaning: The human is asking to edit a factory
-- Behavior:
-- * Make sure factory is addressed
-- * Insert to my inbox
-- * Deliver without filtering
clientPatch
:: UTCTime
-> PersonId
-> ClientMsg
-> AP.Patch' URIMode
-> ActE OutboxItemId
clientPatch now personMeID (ClientMsg maybeCap localRecips remoteRecips fwdHosts action) patch = do
-- Parse input
object <- do
routeOrRemote <- parseFedURI $ AP.patchObject patch
bitraverse parseLocalActorE' pure routeOrRemote
-- Verify object is addressed
bitraverse_
(verifyActorAddressed localRecips)
(verifyRemoteAddressed remoteRecips)
object
(actorMeID, localRecipsFinal, patchID) <- withDBExcept $ do
-- Grab me from DB
(personMe, actorMe) <- lift $ do
p <- getJust personMeID
(p,) <$> getJust (personActor p)
-- Insert the Patch activity to my outbox
patchID <- lift $ insertEmptyOutboxItem' (actorOutbox actorMe) now
_luPatch <- lift $ updateOutboxItem' (LocalActorPerson personMeID) patchID action
return
( personActor personMe
, localRecips
, patchID
)
lift $ sendActivity
(LocalActorPerson personMeID) actorMeID localRecipsFinal remoteRecips
fwdHosts patchID action
return patchID
-- Meaning: The human wants to remove someone A from a resource R -- Meaning: The human wants to remove someone A from a resource R
-- Behavior: -- Behavior:
-- * Some basic sanity checks -- * Some basic sanity checks
@ -1162,6 +1220,7 @@ clientBehavior now personID msg =
AP.InviteActivity invite -> clientInvite now personID msg invite AP.InviteActivity invite -> clientInvite now personID msg invite
AP.JoinActivity join -> clientJoin now personID msg join AP.JoinActivity join -> clientJoin now personID msg join
AP.OfferActivity offer -> clientOffer now personID msg offer AP.OfferActivity offer -> clientOffer now personID msg offer
AP.PatchActivity patch -> clientPatch now personID msg patch
AP.RemoveActivity remove -> clientRemove now personID msg remove AP.RemoveActivity remove -> clientRemove now personID msg remove
AP.ResolveActivity resolve -> clientResolve now personID msg resolve AP.ResolveActivity resolve -> clientResolve now personID msg resolve
AP.UndoActivity undo -> clientUndo now personID msg undo AP.UndoActivity undo -> clientUndo now personID msg undo

View file

@ -48,6 +48,7 @@ module Vervis.Client
, acceptProjectInvite , acceptProjectInvite
, acceptPersonalInvite , acceptPersonalInvite
, acceptParentChild , acceptParentChild
, editFactory
) )
where where
@ -75,7 +76,7 @@ import qualified Data.Text.Lazy as TL
import Development.PatchMediaType import Development.PatchMediaType
import Network.FedURI import Network.FedURI
import Web.ActivityPub hiding (Follow, Ticket, Project (..), Repo, ActorLocal (..)) import Web.ActivityPub hiding (Follow, Ticket, Project (..), Repo, ActorLocal (..), Factory)
import Web.Text import Web.Text
import Yesod.ActivityPub import Yesod.ActivityPub
import Yesod.FedURI import Yesod.FedURI
@ -1624,3 +1625,23 @@ acceptParentChild personID uAdd uParent uChild = do
audience = [audParent, audChild, audAuthor] audience = [audParent, audChild, audAuthor]
return (Nothing, audience, activity) return (Nothing, audience, activity)
editFactory
:: (MonadHandler m, HandlerSite m ~ App, MonadSite m, SiteEnv m ~ App)
=> KeyHashid Person
-> KeyHashid Factory
-> [AP.ActorType]
-> m (Maybe HTML, [Aud URIMode], AP.Patch' URIMode)
editFactory senderHash factoryHash types = do
encodeRouteHome <- getEncodeRouteHome
let audAuthor =
AudLocal [] [LocalStagePersonFollowers senderHash]
audFactory =
AudLocal [LocalActorFactory factoryHash] [LocalStageFactoryFollowers factoryHash]
audience = [audAuthor, audFactory]
uFactory = encodeRouteHome $ FactoryR factoryHash
patch = AP.Patch' uFactory types
return (Nothing, audience, patch)

View file

@ -1148,6 +1148,7 @@ instance YesodBreadcrumbs App where
FactoryMessageR f m -> ("Message #" <> keyHashidText m, Just $ FactoryR f) FactoryMessageR f m -> ("Message #" <> keyHashidText m, Just $ FactoryR f)
FactoryNewR -> ("New Factory", Just HomeR) FactoryNewR -> ("New Factory", Just HomeR)
FactoryEditR f -> ("Edit", Just $ FactoryR f)
FactoryStampR f k -> ("Stamp #" <> keyHashidText k, Just $ FactoryR f) FactoryStampR f k -> ("Stamp #" <> keyHashidText k, Just $ FactoryR f)

View file

@ -27,6 +27,7 @@ module Vervis.Handler.Factory
, getFactoryNewR , getFactoryNewR
, postFactoryNewR , postFactoryNewR
, postFactoryEditR
, getFactoryStampR , getFactoryStampR
@ -54,7 +55,7 @@ import Data.Bitraversable
import Data.ByteString (ByteString) import Data.ByteString (ByteString)
import Data.Default.Class import Data.Default.Class
import Data.Foldable import Data.Foldable
import Data.Maybe (fromMaybe, isJust) import Data.Maybe
import Data.Text (Text) import Data.Text (Text)
import Data.Time.Clock import Data.Time.Clock
import Data.Traversable import Data.Traversable
@ -138,6 +139,20 @@ getFactoryR factoryHash = do
Just personID -> getPermitsForResource personID (Left $ factoryResource f) Just personID -> getPermitsForResource personID (Left $ factoryResource f)
return (f, aid, a, sigKeys, permits) return (f, aid, a, sigKeys, permits)
let defTypes =
mapMaybe
(\ (allow, typ) ->
if allow factory
then Just typ
else Nothing
)
[ (factoryAllowDeck , AP.ActorTypeTicketTracker)
, (factoryAllowProject, AP.ActorTypeProject)
, (factoryAllowTeam , AP.ActorTypeTeam)
]
((_result, widget), enctype) <-
runFormPost $ renderDivs $ areq typeField "Allowed types" (Just defTypes)
encodeRouteLocal <- getEncodeRouteLocal encodeRouteLocal <- getEncodeRouteLocal
hashSigKey <- getEncodeKeyHashid hashSigKey <- getEncodeKeyHashid
perActor <- asksSite $ appPerActorKeys . appSettings perActor <- asksSite $ appPerActorKeys . appSettings
@ -169,6 +184,17 @@ getFactoryR factoryHash = do
encodeRouteLocal $ FactoryCollabsR factoryHash encodeRouteLocal $ FactoryCollabsR factoryHash
, AP.factoryTeams = , AP.factoryTeams =
encodeRouteLocal $ FactoryTeamsR factoryHash encodeRouteLocal $ FactoryTeamsR factoryHash
, AP.factoryTypes =
mapMaybe
(\ (allow, typ) ->
if allow factory
then Just typ
else Nothing
)
[ (factoryAllowDeck , AP.ActorTypeTicketTracker)
, (factoryAllowProject, AP.ActorTypeProject)
, (factoryAllowTeam , AP.ActorTypeTeam)
]
} }
provideHtmlAndAP factoryAP $(widgetFile "factory/one") provideHtmlAndAP factoryAP $(widgetFile "factory/one")
@ -199,9 +225,20 @@ getFactoryFollowersR = getActorFollowersCollection' FactoryFollowersR grabActorI
getFactoryMessageR :: KeyHashid Factory -> KeyHashid LocalMessage -> Handler Html getFactoryMessageR :: KeyHashid Factory -> KeyHashid LocalMessage -> Handler Html
getFactoryMessageR _ _ = notFound getFactoryMessageR _ _ = notFound
newFactoryForm = renderDivs $ (,) typeField =
<$> areq textField "Name*" Nothing checkboxesFieldList
<*> areq textField "Description" Nothing [ ("Ticket Tracker", AP.ActorTypeTicketTracker)
:: (Text, AP.ActorType)
, ("Project", AP.ActorTypeProject)
, ("Team", AP.ActorTypeTeam)
]
allTypes = [AP.ActorTypeTicketTracker, AP.ActorTypeProject, AP.ActorTypeTeam]
newFactoryForm = renderDivs $ (,,)
<$> areq textField "Name*" Nothing
<*> areq textField "Description*" Nothing
<*> areq typeField "Allowed types*" (Just allTypes)
getFactoryNewR :: Handler Html getFactoryNewR :: Handler Html
getFactoryNewR = do getFactoryNewR = do
@ -210,13 +247,13 @@ getFactoryNewR = do
postFactoryNewR :: Handler Html postFactoryNewR :: Handler Html
postFactoryNewR = do postFactoryNewR = do
(name, desc) <- runFormPostRedirect FactoryNewR newFactoryForm (name, desc, types) <- runFormPostRedirect FactoryNewR newFactoryForm
personEntity@(Entity personID person) <- requireAuth personEntity@(Entity personID person) <- requireAuth
personHash <- encodeKeyHashid personID personHash <- encodeKeyHashid personID
(maybeSummary, audience, detail) <- C.createFactory personHash name desc (maybeSummary, audience, detail) <- C.createFactory personHash name desc
(localRecips, remoteRecips, fwdHosts, action) <- (localRecips, remoteRecips, fwdHosts, action) <-
C.makeServerInput Nothing maybeSummary audience $ AP.CreateActivity $ AP.Create (AP.CreateFactory detail Nothing) Nothing C.makeServerInput Nothing maybeSummary audience $ AP.CreateActivity $ AP.Create (AP.CreateFactory detail Nothing types) Nothing
result <- result <-
runExceptT $ runExceptT $
handleViaActor personID Nothing localRecips remoteRecips fwdHosts action handleViaActor personID Nothing localRecips remoteRecips fwdHosts action
@ -238,6 +275,37 @@ postFactoryNewR = do
setMessage "New factory created" setMessage "New factory created"
redirect $ FactoryR factoryHash redirect $ FactoryR factoryHash
postFactoryEditR :: KeyHashid Factory -> Handler Html
postFactoryEditR factoryHash = do
factoryID <- decodeKeyHashid404 factoryHash
types <-
runFormPostRedirect (FactoryR factoryHash) $
renderDivs $ areq typeField "Allowed types" (Just allTypes)
personEntity@(Entity personID person) <- requireAuth
personHash <- encodeKeyHashid personID
(maybeSummary, audience, patch) <- C.editFactory personHash factoryHash types
result <- runExceptT $ do
cap <- do
maybeItem <- lift $ runDB $ do
resourceID <- factoryResource <$> get404 factoryID
getCapability personID (Left resourceID) AP.RoleAdmin
fromMaybeE maybeItem "You need to be have Admin access to the Factory to edit settings"
uCap <- lift $ renderActivityURI cap
(localRecips, remoteRecips, fwdHosts, action) <-
lift $
C.makeServerInput (Just uCap) maybeSummary audience $ AP.PatchActivity patch
let cap' = first (\ (la, i) -> (la, error "lah", i)) cap
handleViaActor
personID (Just cap') localRecips remoteRecips fwdHosts action
case result of
Left e -> do
setMessage $ toHtml e
redirect $ FactoryR factoryHash
Right _itemID -> do
setMessage "Patch activity sent"
redirect $ FactoryR factoryHash
getFactoryStampR :: KeyHashid Factory -> KeyHashid SigKey -> Handler TypedContent getFactoryStampR :: KeyHashid Factory -> KeyHashid SigKey -> Handler TypedContent
getFactoryStampR = servePerActorKey'' grabActorID LocalActorFactory getFactoryStampR = servePerActorKey'' grabActorID LocalActorFactory

View file

@ -1340,7 +1340,7 @@ getCapability personID actor role = do
E.where_ $ E.where_ $
permit E.^. PermitPerson E.==. E.val personID E.&&. permit E.^. PermitPerson E.==. E.val personID E.&&.
topic E.^. PermitTopicLocalTopic E.==. E.val resourceID E.&&. topic E.^. PermitTopicLocalTopic E.==. E.val resourceID E.&&.
permit E.^. PermitRole E.>=. E.val role permit E.^. PermitRole `E.in_` E.valList [role .. maxBound]
E.orderBy [E.desc $ enable E.^. PermitTopicEnableLocalId] E.orderBy [E.desc $ enable E.^. PermitTopicEnableLocalId]
E.limit 1 E.limit 1
return $ enable E.^. PermitTopicEnableLocalGrant return $ enable E.^. PermitTopicEnableLocalGrant

View file

@ -93,6 +93,7 @@ module Web.ActivityPub
, Join (..) , Join (..)
, OfferObject (..) , OfferObject (..)
, Offer (..) , Offer (..)
, Patch' (..)
, Push (..) , Push (..)
, Reject (..) , Reject (..)
, Remove (..) , Remove (..)
@ -1102,6 +1103,7 @@ data Factory u = Factory
{ factoryActor :: Actor u { factoryActor :: Actor u
, factoryCollabs :: LocalURI , factoryCollabs :: LocalURI
, factoryTeams :: LocalURI , factoryTeams :: LocalURI
, factoryTypes :: [ActorType]
} }
instance ActivityPub Factory where instance ActivityPub Factory where
@ -1114,10 +1116,12 @@ instance ActivityPub Factory where
Factory a Factory a
<$> withAuthorityO h (o .: "collaborators") <$> withAuthorityO h (o .: "collaborators")
<*> withAuthorityO h (o .: "teams") <*> withAuthorityO h (o .: "teams")
toSeries h (Factory actor collabs teams) <*> (o .: "availableActorTypes")
toSeries h (Factory actor collabs teams types)
= toSeries h actor = toSeries h actor
<> "collaborators" .= ObjURI h collabs <> "collaborators" .= ObjURI h collabs
<> "teams" .= ObjURI h teams <> "teams" .= ObjURI h teams
<> "availableActorTypes" .= types
data Audience u = Audience data Audience u = Audience
{ audienceTo :: [ObjURI u] { audienceTo :: [ObjURI u]
@ -2004,7 +2008,7 @@ data CreateObject u
| CreatePatchTracker ActorDetail (NonEmpty (ObjURI u)) (Maybe (Authority u, ActorLocal u)) | CreatePatchTracker ActorDetail (NonEmpty (ObjURI u)) (Maybe (Authority u, ActorLocal u))
| CreateProject ActorDetail (Maybe (Authority u, ActorLocal u)) | CreateProject ActorDetail (Maybe (Authority u, ActorLocal u))
| CreateTeam ActorDetail (Maybe (Authority u, ActorLocal u)) | CreateTeam ActorDetail (Maybe (Authority u, ActorLocal u))
| CreateFactory ActorDetail (Maybe (Authority u, ActorLocal u)) | CreateFactory ActorDetail (Maybe (Authority u, ActorLocal u)) [ActorType]
| CreatePerson ActorDetail (Maybe (Authority u, ActorLocal u)) | CreatePerson ActorDetail (Maybe (Authority u, ActorLocal u))
parseCreateObject :: UriMode u => Object -> Parser (CreateObject u) parseCreateObject :: UriMode u => Object -> Parser (CreateObject u)
@ -2042,7 +2046,8 @@ parseCreateObject o
unless (actorType f == ActorTypeFactory) $ unless (actorType f == ActorTypeFactory) $
fail "type isn't Factory" fail "type isn't Factory"
ml <- parseActorLocal o ml <- parseActorLocal o
return $ CreateFactory f ml types <- o .: "availableActorTypes"
return $ CreateFactory f ml types
<|> do f <- parseActorDetail o <|> do f <- parseActorDetail o
unless (actorType f == ActorTypePerson) $ unless (actorType f == ActorTypePerson) $
fail "type isn't Person" fail "type isn't Person"
@ -2066,8 +2071,9 @@ encodeCreateObject (CreateProject d ml) =
encodeActorDetail d <> maybe mempty (uncurry encodeActorLocal) ml encodeActorDetail d <> maybe mempty (uncurry encodeActorLocal) ml
encodeCreateObject (CreateTeam d ml) = encodeCreateObject (CreateTeam d ml) =
encodeActorDetail d <> maybe mempty (uncurry encodeActorLocal) ml encodeActorDetail d <> maybe mempty (uncurry encodeActorLocal) ml
encodeCreateObject (CreateFactory d ml) = encodeCreateObject (CreateFactory d ml types) =
encodeActorDetail d <> maybe mempty (uncurry encodeActorLocal) ml encodeActorDetail d <> maybe mempty (uncurry encodeActorLocal) ml <>
"availableActorTypes" .= types
encodeCreateObject (CreatePerson d ml) = encodeCreateObject (CreatePerson d ml) =
encodeActorDetail d <> maybe mempty (uncurry encodeActorLocal) ml encodeActorDetail d <> maybe mempty (uncurry encodeActorLocal) ml
@ -2091,7 +2097,7 @@ parseCreate o a luActor = do
CreatePatchTracker _ _ _ -> return () CreatePatchTracker _ _ _ -> return ()
CreateProject _ _ -> return () CreateProject _ _ -> return ()
CreateTeam _ _ -> return () CreateTeam _ _ -> return ()
CreateFactory _ _ -> return () CreateFactory _ _ _ -> return ()
CreatePerson _ _ -> return () CreatePerson _ _ -> return ()
Create obj <$> o .:? "origin" Create obj <$> o .:? "origin"
@ -2238,6 +2244,21 @@ encodeOffer authority actor (Offer obj target)
= "object" `pair` pairs (toSeries authority obj) = "object" `pair` pairs (toSeries authority obj)
<> "target" .= target <> "target" .= target
data Patch' u = Patch'
{ patchObject :: ObjURI u
, patchAvailableActorTypes :: [ActorType]
}
parsePatch' :: UriMode u => Object-> Parser (Patch' u)
parsePatch' o = Patch'
<$> o .: "object"
<*> o .: "availableActorTypes"
encodePatch' :: UriMode u => Patch' u -> Series
encodePatch' (Patch' obj types)
= "object" .= obj
<> "availableActorTypes" .= types
data Push u = Push data Push u = Push
{ pushCommitsLast :: NonEmpty (Commit u) { pushCommitsLast :: NonEmpty (Commit u)
, pushCommitsFirst :: Maybe (NonEmpty (Commit u)) , pushCommitsFirst :: Maybe (NonEmpty (Commit u))
@ -2401,6 +2422,7 @@ data SpecificActivity u
| InviteActivity (Invite u) | InviteActivity (Invite u)
| JoinActivity (Join u) | JoinActivity (Join u)
| OfferActivity (Offer u) | OfferActivity (Offer u)
| PatchActivity (Patch' u)
| PushActivity (Push u) | PushActivity (Push u)
| RejectActivity (Reject u) | RejectActivity (Reject u)
| RemoveActivity (Remove u) | RemoveActivity (Remove u)
@ -2418,6 +2440,7 @@ activityType (GrantActivity _) = "Grant"
activityType (InviteActivity _) = "Invite" activityType (InviteActivity _) = "Invite"
activityType (JoinActivity _) = "Join" activityType (JoinActivity _) = "Join"
activityType (OfferActivity _) = "Offer" activityType (OfferActivity _) = "Offer"
activityType (PatchActivity _) = "Patch"
activityType (PushActivity _) = "Push" activityType (PushActivity _) = "Push"
activityType (RejectActivity _) = "Reject" activityType (RejectActivity _) = "Reject"
activityType (RemoveActivity _) = "Remove" activityType (RemoveActivity _) = "Remove"
@ -2483,6 +2506,7 @@ instance ActivityPub Activity where
"Invite" -> InviteActivity <$> parseInvite o "Invite" -> InviteActivity <$> parseInvite o
"Join" -> JoinActivity <$> parseJoin o "Join" -> JoinActivity <$> parseJoin o
"Offer" -> OfferActivity <$> parseOffer o a actor "Offer" -> OfferActivity <$> parseOffer o a actor
"Patch" -> PatchActivity <$> parsePatch' o
"Push" -> PushActivity <$> parsePush a o "Push" -> PushActivity <$> parsePush a o
"Reject" -> RejectActivity <$> parseReject o "Reject" -> RejectActivity <$> parseReject o
"Remove" -> RemoveActivity <$> parseRemove o "Remove" -> RemoveActivity <$> parseRemove o
@ -2512,6 +2536,7 @@ instance ActivityPub Activity where
encodeSpecific _ _ (InviteActivity a) = encodeInvite a encodeSpecific _ _ (InviteActivity a) = encodeInvite a
encodeSpecific _ _ (JoinActivity a) = encodeJoin a encodeSpecific _ _ (JoinActivity a) = encodeJoin a
encodeSpecific h u (OfferActivity a) = encodeOffer h u a encodeSpecific h u (OfferActivity a) = encodeOffer h u a
encodeSpecific _ _ (PatchActivity a) = encodePatch' a
encodeSpecific h _ (PushActivity a) = encodePush h a encodeSpecific h _ (PushActivity a) = encodePush h a
encodeSpecific _ _ (RejectActivity a) = encodeReject a encodeSpecific _ _ (RejectActivity a) = encodeReject a
encodeSpecific _ _ (RemoveActivity a) = encodeRemove a encodeSpecific _ _ (RemoveActivity a) = encodeRemove a

View file

@ -17,3 +17,8 @@ $# <http://creativecommons.org/publicdomain/zero/1.0/>.
^{followW' $ Left actorID} ^{followW' $ Left actorID}
^{personPermitsForResourceW permits} ^{personPermitsForResourceW permits}
<form method=POST action=@{FactoryEditR factoryHash} enctype=#{enctype}>
^{widget}
<div class="submit">
<input type="submit">

View file

@ -449,6 +449,7 @@
/factories/#FactoryKeyHashid/messages/#LocalMessageKeyHashid FactoryMessageR GET /factories/#FactoryKeyHashid/messages/#LocalMessageKeyHashid FactoryMessageR GET
/new-factory FactoryNewR GET POST /new-factory FactoryNewR GET POST
/factories/#FactoryKeyHashid/edit FactoryEditR POST
/factories/#FactoryKeyHashid/stamps/#SigKeyKeyHashid FactoryStampR GET /factories/#FactoryKeyHashid/stamps/#SigKeyKeyHashid FactoryStampR GET