Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Federated following, starring, issues, forks, and pull requests #20391

Closed
wants to merge 94 commits into from
Closed
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
d12fd43
Add Person and Repository ActivityPub endpoints
Jun 19, 2022
a7f32d3
Finish initial ForgeFed implementation
Jun 20, 2022
e090c95
Write a FEDERATION.md describing future Gitea federation features
Jun 21, 2022
24a462a
Delete the old example from FEDERATION.md
Jun 21, 2022
30a703c
Fix minor wording issue
Jun 22, 2022
e348477
Add some additional info about migrations to FEDERATION.md
Jun 26, 2022
786ee03
Merge remote-tracking branch 'upstream/main'
Jun 26, 2022
721b734
Merge remote-tracking branch 'upstream/main'
Jul 7, 2022
fa72294
Fix build errors and start working on constructing outbox activities …
Jul 7, 2022
18b4cd3
Don't track go.work files
Jul 7, 2022
8b354fe
Merge remote-tracking branch 'upstream/main'
Jul 10, 2022
d016dbb
Switch to using gitea.com/Ta180m/activitypub fork of the go-ap/activi…
Jul 11, 2022
79a59bd
Use a replace in go.mod to point to Ta180m/activitypub fork instead o…
Jul 11, 2022
1b39e39
Add basic implementation of federated commenting
Jul 11, 2022
63aa270
Initial implementation of federated pull requests
Jul 13, 2022
a63b2be
Merge remote-tracking branch 'upstream/main'
Jul 13, 2022
5671739
Big refactor: Improve inbox handling logic, move some IRI stuff to ir…
Jul 14, 2022
0609d71
Add more TODO notes
Jul 14, 2022
1b4cd98
Merge remote-tracking branch 'upstream/main'
Jul 14, 2022
b491a2e
Update FEDERATION.md with a more accurate description of federated is…
Jul 17, 2022
705706b
Generate person outbox for only repo creates and stars
Jul 17, 2022
f1577c2
Merge remote-tracking branch 'upstream/main'
Jul 17, 2022
48deb8e
Fix repo AP outbox path typo
Jul 17, 2022
08cb2d6
Fix typos in FEDERATION.md
Jul 17, 2022
c100b8e
Apply suggestions from code review
Jul 17, 2022
0925235
Fix federated following/unfollowing regression
Jul 20, 2022
6e10030
Merge remote-tracking branch 'upstream/main'
Jul 20, 2022
c8a8e1e
Check err in Follow() to avoid crash and don't check FederatedUserNew…
Jul 20, 2022
5196dcd
Check if httpsig keyID matches actor and attributedTo
Jul 20, 2022
85abd9c
Fix typo in follow.go
Jul 22, 2022
763f98b
Create user at /authorize_interaction?uri= endpoint
Jul 23, 2022
5da6b4f
Disable authorize_endpoint if federation is disabled
Jul 24, 2022
ab540d0
Create new federated users in reqsignature.go
Jul 24, 2022
bffb682
Fix a bunch of lint errors (still 10 more to fix 🙁)
Jul 24, 2022
30b431d
Set ap.ItemTyperFunc to correctly unmarshal JSON
Jul 25, 2022
38a687c
Replace GetID() with GetLink()
Jul 25, 2022
f0cded8
Start cleaning up fork.go
Jul 27, 2022
d909c97
Move models/forgefed to modules/forgefed
Jul 27, 2022
8e5621c
Merge remote-tracking branch 'upstream/main'
Jul 27, 2022
c94a891
Process Like activities for starring repos
Jul 27, 2022
71b2b4d
Implement FederatedRepoNew
Jul 27, 2022
fe8ef28
Merge remote-tracking branch 'upstream/main'
Aug 4, 2022
ecefb6a
Merge remote-tracking branch 'upstream/main'
Aug 10, 2022
0b97c6a
Cache remote user public keys
Aug 15, 2022
d945e6a
Start working on Ticket object endpoint implementation
Aug 15, 2022
6b73c09
Download avatar from URL and set it with user_service.UploadAvatar
Aug 15, 2022
6a6c6b3
Merge remote-tracking branch 'upstream/main'
Aug 19, 2022
27cda2f
Implement JSONLoad, To, and On functions for ForgeFed types
Aug 21, 2022
b3c065c
Refactor RepoInbox to use On functions instead of type assertions
Aug 21, 2022
18809f8
Make the frontend linter happy
Aug 22, 2022
b9dd4a2
Make revive linter happy
Aug 22, 2022
819e495
Make gofmt happy
Aug 22, 2022
1bc8e67
Fix linting errors (errcheck)
Aug 22, 2022
f1e61af
Fix another linting error
Aug 22, 2022
ee85f7d
Use the Repository AttributedTo to get owner IRI
Aug 22, 2022
c0efded
Fix typo for JSONUnmarshalerFn description comment
Aug 22, 2022
73284db
Add authorize_interaction case for Tickets
Aug 22, 2022
5ad0387
Add copyright to test file
Aug 22, 2022
2373b41
Add paginition to Person's outbox
Aug 22, 2022
45324e1
Add todo
Aug 22, 2022
2e957e7
Fix repository tests
Aug 22, 2022
ec1ffd6
Merge remote-tracking branch 'upstream/main'
anthowan Sep 5, 2022
f026988
Fix build errors
anthowan Sep 5, 2022
42b1bac
Merge remote-tracking branch 'upstream/main'
anthowan Sep 12, 2022
47229ea
Merge remote-tracking branch 'upstream/main'
anthowan Sep 15, 2022
f7dbbf7
Remove /integrations directory
anthowan Sep 15, 2022
117463b
Change Ta180m/activitypub to xy/activitypub
anthowan Sep 16, 2022
26f57be
Merge remote-tracking branch 'upstream/main'
anthowan Sep 22, 2022
379b9a7
Serve issues as ForgeFed tickets
anthowan Sep 23, 2022
f9d9019
Fix Comment permission checking
anthowan Sep 23, 2022
cbc2a97
Set isResolved to true for closed issues
anthowan Sep 29, 2022
e78dd69
Merge remote-tracking branch 'upstream/main'
anthowan Oct 18, 2022
f133e9c
Implement sending follow activities
anthowan Oct 21, 2022
5612130
Merge remote-tracking branch 'upstream/main'
anthowan Oct 27, 2022
69c1bdd
Merge remote-tracking branch 'upstream/main'
anthowan Nov 8, 2022
0cacdc3
More Ticket IRI processing to iri.go
anthowan Nov 11, 2022
f75ab80
make fmt
anthowan Nov 11, 2022
ca50224
Send out undo follow activity in UnfollowUser
anthowan Nov 12, 2022
20e8c64
Fix UnfollowUser addressing
anthowan Nov 12, 2022
19af0c9
Implement loading remote tickets
anthowan Nov 25, 2022
d22dab7
Add custom NotEmpty function to handle ForgeFed types
anthowan Nov 26, 2022
447650f
Remove @ from regex because idk what it was doing there in the first …
anthowan Nov 26, 2022
41e9a10
make fmt
anthowan Nov 26, 2022
fd4d0e7
Move AS object processing to routers/api/v1/activitypub, move AP tran…
anthowan Nov 27, 2022
2d74e4f
Delete fork code and move createPullRequest to create.go
anthowan Nov 27, 2022
c982b67
Set issue Index, not ID, when creating issues from an AS object
anthowan Nov 27, 2022
a666eef
Rewrite createPullRequest and add createPersonFromIRI
anthowan Nov 27, 2022
3f5f626
Fix AppSubURL -> AppURL typo
anthowan Nov 27, 2022
1066cfe
Implement commenting and fix lint errors
anthowan Nov 27, 2022
77896f1
Save issue IRIs when creating them from AS objects
anthowan Nov 27, 2022
3e690fb
Federated issue creation
anthowan Nov 27, 2022
f5a50ce
Add Note object endpoint
anthowan Nov 27, 2022
c64d3fa
Implement commenting on issues from Mastodon
anthowan Nov 27, 2022
439f675
Don't send emails to federated users
anthowan Nov 27, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions FEDERATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Federation

*This describes Gitea's future federation capabilities, not what it can do currently.*

Gitea is federated using [ActivityPub](https://www.w3.org/TR/activitypub/) and the [ForgeFed extension](https://forgefed.org/) so you can interact with users and repositories from other instances as if they were on your own instance. By using the standardized ActivityPub protocol, users on any fediverse software such as [Mastodon](https://joinmastodon.org/) can follow Gitea users, stars repos, receive activity updates, and comment on issues.

Currently, C2S ActivityPub is not supported.

## Following

You can use any fediverse software to follow a Gitea user. Gitea will automatically accept follow requests. The usernames of remote users are displayed as `username@instance.com`. To follow a remote user, click follow on their profile page, and a pop-up box will appear for you to type in your instance. You are redirected to your own instance, where the remote user is fetched and rendered, and you can now follow them.

When following a Gitea user, you will receive updates when they star a repo, create, fork, or make a private repo public, or follow a user. If you are using Mastodon or Pleroma, these will show up in your feed.

## Starring

You can star repositories on another instance. The full name of a remote repository is `username@instance.com/reponame`. Similar to following, a pop-up box appears for you to type in your instance, and you are redirected to your own instance, where the remote repository is fetched and rendered.

## Organizations

You can add users from other instances to organizations. An organization has a name and an instance, so its full name would look like `orgname@instance.com`. This indicates that the organization data resides on `instance.com`. To prevent syncronization errors, this data is only synchronized one-way to other instances.

## Collaborators

You can add users from other instances as collaborators. As mentioned previously, a repository has full name `username@instance.com/reponame`, which indicates that the repository data resides on `instance.com`. Each collaborator's instance has a copy of the repository, but to prevent synchronization errors, the copy at `instance.com` is the main copy and it is synchronized one-way to all other instances. When a collaborator tries to modify their copy of the repository, the modification is first sent to the main copy at `instance.com` and then synchronized back to their instance.

## Issues

You can create an issue on a remote repository. Your instance can also render a remote issue that you created so you can edit it or comment on it.

## Forks

When forking a remote repository, the fork is created on your instance, not the remote instance.

## Pull requests

When opening a pull request to a remote repository, the pull request can be rendered on your instance. Federated pull requests use the AGit-flow.

## Comments

You can comment on an issue or pull request using any fediverse software. The entire issue thread is rendered on your instance.

## Migrations

If you change your username or the name of repository, Gitea handles this similarly to how Mastodon does. Gitea will send a `Move` activity to your followers and update your actor to point to the new actor and the new actor to point to the old actor.

Changing your instance or a repository's instance is handled in a similar way, but additionally, the data to be migrated between instances.
10 changes: 6 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ require (
github.com/ethantkoenig/rupture v1.0.1
github.com/felixge/fgprof v0.9.2
github.com/gliderlabs/ssh v0.3.4
github.com/go-ap/activitypub v0.0.0-20220615144428-48208c70483b
github.com/go-ap/activitypub v0.0.0-20220706134811-0c84d76ce535
github.com/go-ap/jsonld v0.0.0-20220615144122-1d862b15410d
github.com/go-chi/chi/v5 v5.0.7
github.com/go-chi/cors v1.2.1
Expand Down Expand Up @@ -85,6 +85,7 @@ require (
github.com/tstranex/u2f v1.0.0
github.com/unrolled/render v1.4.1
github.com/urfave/cli v1.22.9
github.com/valyala/fastjson v1.6.3
github.com/xanzy/go-gitlab v0.64.0
github.com/yohcop/openid-go v1.0.0
github.com/yuin/goldmark v1.4.13
Expand All @@ -109,7 +110,7 @@ require (

require (
cloud.google.com/go v0.99.0 // indirect
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20200411073322-f0bcc40f0bf2 // indirect
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 // indirect
github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e // indirect
github.com/Microsoft/go-winio v0.5.2 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20220407094043-a94812496cf5 // indirect
Expand Down Expand Up @@ -163,7 +164,7 @@ require (
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/fullstorydev/grpcurl v1.8.1 // indirect
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
github.com/go-ap/errors v0.0.0-20220615144307-e8bc4a40ae9f // indirect
github.com/go-ap/errors v0.0.0-20220618122732-319f41ac54e1 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
github.com/go-enry/go-oniguruma v1.2.1 // indirect
github.com/go-git/gcfg v1.5.0 // indirect
Expand Down Expand Up @@ -256,7 +257,6 @@ require (
github.com/toqueteos/webbrowser v1.2.0 // indirect
github.com/ulikunitz/xz v0.5.10 // indirect
github.com/unknwon/com v1.0.1 // indirect
github.com/valyala/fastjson v1.6.3 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xanzy/ssh-agent v0.3.1 // indirect
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
Expand Down Expand Up @@ -298,6 +298,8 @@ replace github.com/shurcooL/vfsgen => github.com/lunny/vfsgen v0.0.0-20220105142

replace github.com/satori/go.uuid v1.2.0 => github.com/gofrs/uuid v4.2.0+incompatible

replace github.com/go-ap/activitypub => gitea.com/Ta180m/activitypub v0.0.0-20220711172827-b05423b54985

exclude github.com/gofrs/uuid v3.2.0+incompatible

exclude github.com/gofrs/uuid v4.0.0+incompatible
Expand Down
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,10 @@ contrib.go.opencensus.io/exporter/stackdriver v0.13.5/go.mod h1:aXENhDJ1Y4lIg4EU
contrib.go.opencensus.io/integrations/ocsql v0.1.4/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE=
contrib.go.opencensus.io/resource v0.1.1/go.mod h1:F361eGI91LCmW1I/Saf+rX0+OFcigGlFvXwEGEnkRLA=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20200411073322-f0bcc40f0bf2 h1:2OrsyJYZp7J6nyAsKi2q1SELYRaIc0aQmcQ/EQqPfk8=
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20200411073322-f0bcc40f0bf2/go.mod h1:g/V2Hjas6Z1UHUp4yIx6bATpNzJ7DYtD0FG3+xARWxs=
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:cliQ4HHsCo6xi2oWZYKWW4bly/Ory9FuTpFPRxj/mAg=
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078/go.mod h1:g/V2Hjas6Z1UHUp4yIx6bATpNzJ7DYtD0FG3+xARWxs=
gitea.com/Ta180m/activitypub v0.0.0-20220711172827-b05423b54985 h1:mFjFQxAsUdcvtM3klWtTbkhGnsRVF+DPhZPofsKmPlk=
gitea.com/Ta180m/activitypub v0.0.0-20220711172827-b05423b54985/go.mod h1:KDY/LAOthmTlRA4ft9TKrvPKVe+AZaSaU+3HS/UITvU=
gitea.com/go-chi/binding v0.0.0-20220309004920-114340dabecb h1:Yy0Bxzc8R2wxiwXoG/rECGplJUSpXqCsog9PuJFgiHs=
gitea.com/go-chi/binding v0.0.0-20220309004920-114340dabecb/go.mod h1:77TZu701zMXWJFvB8gvTbQ92zQ3DQq/H7l5wAEjQRKc=
gitea.com/go-chi/cache v0.0.0-20210110083709-82c4c9ce2d5e/go.mod h1:k2V/gPDEtXGjjMGuBJiapffAXTv76H4snSmlJRLUhH0=
Expand Down Expand Up @@ -462,10 +464,8 @@ github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
github.com/go-ap/activitypub v0.0.0-20220615144428-48208c70483b h1:+RjYfEfoZdM3wHFs752dlOpGaoRhwRRyQxjajg08LcQ=
github.com/go-ap/activitypub v0.0.0-20220615144428-48208c70483b/go.mod h1:DE3vvc6Didgfd3k7M1Mos6qMDFNmMrxJmYVMHG9h9Io=
github.com/go-ap/errors v0.0.0-20220615144307-e8bc4a40ae9f h1:kJhGo4NApJP0Lt9lkJnfmuTnRWVFbCynY0kiTxpPUR4=
github.com/go-ap/errors v0.0.0-20220615144307-e8bc4a40ae9f/go.mod h1:KHkKFKZvc05lr79+RGoq/zG8YjWi3+FK60Bxd+mpCew=
github.com/go-ap/errors v0.0.0-20220618122732-319f41ac54e1 h1:PkPVIQGt76HHFWSeUINXCfYpEnzlSS+AQyuXi7oJ/gM=
github.com/go-ap/errors v0.0.0-20220618122732-319f41ac54e1/go.mod h1:KHkKFKZvc05lr79+RGoq/zG8YjWi3+FK60Bxd+mpCew=
github.com/go-ap/jsonld v0.0.0-20220615144122-1d862b15410d h1:Z/oRXMlZHjvjIqDma1FrIGL3iE5YL7MUI0bwYEZ6qbA=
github.com/go-ap/jsonld v0.0.0-20220615144122-1d862b15410d/go.mod h1:jyveZeGw5LaADntW+UEsMjl3IlIwk+DxlYNsbofQkGA=
github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A=
Expand Down
22 changes: 14 additions & 8 deletions models/auth/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,15 @@ type Type int

// Note: new type must append to the end of list to maintain compatibility.
const (
NoType Type = iota
Plain // 1
LDAP // 2
SMTP // 3
PAM // 4
DLDAP // 5
OAuth2 // 6
SSPI // 7
NoType Type = iota
Plain // 1
LDAP // 2
SMTP // 3
PAM // 4
DLDAP // 5
OAuth2 // 6
SSPI // 7
Federated // 8
)

// String returns the string name of the LoginType
Expand Down Expand Up @@ -178,6 +179,11 @@ func (source *Source) IsSSPI() bool {
return source.Type == SSPI
}

// IsFederated returns true of this source is of the Federated type.
func (source *Source) IsFederated() bool {
return source.Type == Federated
}

// HasTLS returns true of this source supports TLS.
func (source *Source) HasTLS() bool {
hasTLSer, ok := source.Cfg.(HasTLSer)
Expand Down
2 changes: 1 addition & 1 deletion models/db/name.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ var (
ErrNameEmpty = errors.New("Name is empty")

// AlphaDashDotPattern characters prohibited in a user name (anything except A-Za-z0-9_.-)
AlphaDashDotPattern = regexp.MustCompile(`[^\w-\.]`)
AlphaDashDotPattern = regexp.MustCompile(`[^\w-\.@]`) // Ugly hack to allow remote usernames to contain @
)

// ErrNameReserved represents a "reserved name" error.
Expand Down
55 changes: 55 additions & 0 deletions models/forgefed/branch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package forgefed

import (
ap "github.com/go-ap/activitypub"
"github.com/valyala/fastjson"
)

const (
BranchType ap.ActivityVocabularyType = "Branch"
)

type Branch struct {
ap.Object
// Ref the unique identifier of the branch within the repo
Ref ap.Item `jsonld:"ref,omitempty"`
}

// BranchNew initializes a Branch type Object
func BranchNew() *Branch {
a := ap.ObjectNew(BranchType)
o := Branch{Object: *a}
return &o
}

func (br Branch) MarshalJSON() ([]byte, error) {
b, err := br.Object.MarshalJSON()
if len(b) == 0 || err != nil {
return make([]byte, 0), err
}

b = b[:len(b)-1]
if br.Ref != nil {
ap.WriteItemJSONProp(&b, "ref", br.Ref)
}
ap.Write(&b, '}')
return b, nil
}

func (br *Branch) UnmarshalJSON(data []byte) error {
p := fastjson.Parser{}
val, err := p.ParseBytes(data)
if err != nil {
return err
}

br.Ref = ap.JSONGetItem(val, "ref")

return ap.OnObject(&br.Object, func(a *ap.Object) error {
return ap.LoadObject(val, a)
})
}
63 changes: 63 additions & 0 deletions models/forgefed/commit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package forgefed

import (
"time"

ap "github.com/go-ap/activitypub"
"github.com/valyala/fastjson"
)

const (
CommitType ap.ActivityVocabularyType = "Commit"
)

type Commit struct {
ap.Object
// Created time at which the commit was written by its author
Created time.Time `jsonld:"created,omitempty"`
// Committed time at which the commit was committed by its committer
Committed time.Time `jsonld:"committed,omitempty"`
}

// CommitNew initializes a Commit type Object
func CommitNew() *Commit {
a := ap.ObjectNew(CommitType)
o := Commit{Object: *a}
return &o
}

func (c Commit) MarshalJSON() ([]byte, error) {
b, err := c.Object.MarshalJSON()
if len(b) == 0 || err != nil {
return make([]byte, 0), err
}

b = b[:len(b)-1]
if !c.Created.IsZero() {
ap.WriteTimeJSONProp(&b, "created", c.Created)
}
if !c.Committed.IsZero() {
ap.WriteTimeJSONProp(&b, "committed", c.Committed)
}
ap.Write(&b, '}')
return b, nil
}

func (c *Commit) UnmarshalJSON(data []byte) error {
p := fastjson.Parser{}
val, err := p.ParseBytes(data)
if err != nil {
return err
}

c.Created = ap.JSONGetTime(val, "created")
c.Committed = ap.JSONGetTime(val, "committed")

return ap.OnObject(&c.Object, func(a *ap.Object) error {
return ap.LoadObject(val, a)
})
}
28 changes: 28 additions & 0 deletions models/forgefed/forgefed.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package forgefed

import (
ap "github.com/go-ap/activitypub"
)

const ForgeFedNamespaceURI = "https://forgefed.org/ns"

// GetItemByType instantiates a new ForgeFed object if the type matches
// otherwise it defaults to existing activitypub package typer function.
func GetItemByType(typ ap.ActivityVocabularyType) (ap.Item, error) {
if typ == CommitType {
return CommitNew(), nil
} else if typ == BranchType {
return BranchNew(), nil
} else if typ == RepositoryType {
return RepositoryNew(""), nil
} else if typ == PushType {
return PushNew(), nil
} else if typ == TicketType {
return TicketNew(), nil
}
return ap.GetItemByType(typ)
}
67 changes: 67 additions & 0 deletions models/forgefed/push.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package forgefed

import (
ap "github.com/go-ap/activitypub"
"github.com/valyala/fastjson"
)

const (
PushType ap.ActivityVocabularyType = "Push"
)

type Push struct {
ap.Object
// Target the specific repo history tip onto which the commits were added
Target ap.Item `jsonld:"target,omitempty"`
// HashBefore hash before adding the new commits
HashBefore ap.Item `jsonld:"hashBefore,omitempty"`
// HashAfter hash before adding the new commits
HashAfter ap.Item `jsonld:"hashAfter,omitempty"`
}

// PushNew initializes a Push type Object
func PushNew() *Push {
a := ap.ObjectNew(PushType)
o := Push{Object: *a}
return &o
}

func (p Push) MarshalJSON() ([]byte, error) {
b, err := p.Object.MarshalJSON()
if len(b) == 0 || err != nil {
return make([]byte, 0), err
}

b = b[:len(b)-1]
if p.Target != nil {
ap.WriteItemJSONProp(&b, "target", p.Target)
}
if p.HashBefore != nil {
ap.WriteItemJSONProp(&b, "hashBefore", p.HashBefore)
}
if p.HashAfter != nil {
ap.WriteItemJSONProp(&b, "hashAfter", p.HashAfter)
}
ap.Write(&b, '}')
return b, nil
}

func (c *Push) UnmarshalJSON(data []byte) error {
p := fastjson.Parser{}
val, err := p.ParseBytes(data)
if err != nil {
return err
}

c.Target = ap.JSONGetItem(val, "target")
c.HashBefore = ap.JSONGetItem(val, "hashBefore")
c.HashAfter = ap.JSONGetItem(val, "hashAfter")

return ap.OnObject(&c.Object, func(a *ap.Object) error {
return ap.LoadObject(val, a)
})
}
Loading