Compare commits

...

18 Commits

@ -11,11 +11,11 @@
}
# json notation
{"id": "https://repo.prod.meissa.de/api/activitypub/user-id/1/outbox/12345",
{"id": "https://repo.prod.meissa.de/api/v1/activitypub/user-id/1/outbox/12345",
"type": "Star",
"source": "forgejo",
"actor": "https://repo.prod.meissa.de/api/activitypub/user-id/1",
"object": "https://codeberg.org/api/activitypub/repository-id/1"
"actor": "https://repo.prod.meissa.de/api/v1/activitypub/user-id/1",
"object": "https://codeberg.org/api/v1/activitypub/repository-id/1"
}
```

@ -63,3 +63,8 @@ git push --force
# continue local development after rebase & force-push has happened
git reset --hard origin/forgejo-federated-star
```
# generate swagger api client
go run github.com/go-swagger/go-swagger/cmd/swagger@v0.30.5 generate client -f './templates/swagger/v1_json.tmpl' -c "code.gitea.io/sdk"

@ -0,0 +1,49 @@
package activitypub
import (
"fmt"
"net/url"
"strings"
)
type ActorData struct {
schema string
userId string
path string
host string
port string // optional
}
func (a ActorData) ValidateActorData() error {
if a.schema == "" || a.host == "" {
return fmt.Errorf("the actor ID was not valid: Invalid Schema or Host")
}
if !strings.Contains(a.path, "api/v1/activitypub/user-id") {
return fmt.Errorf("the Path to the API was invalid: %v", a.path)
}
return nil
}
func ParseActorData(actor string) (ActorData, error) {
u, err := url.Parse(actor)
// check if userID IRI is well formed url
if err != nil {
return ActorData{}, fmt.Errorf("the actor ID was not a valid IRI: %v", err)
}
pathWithUserID := strings.Split(u.Path, "/")
userId := pathWithUserID[len(pathWithUserID)-1]
return ActorData{
schema: u.Scheme,
userId: userId,
host: u.Host,
path: u.Path,
port: u.Port(),
}, nil
}

@ -0,0 +1,54 @@
// Copyright 2023 The forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package activitypub
import (
"testing"
)
func Test_ActorParser(t *testing.T) {
type testPair struct {
item string
want ActorData
}
tests := map[string]testPair{
"empty": {
item: "",
want: ActorData{},
},
"withValidActorID": {
item: "https://repo.prod.meissa.de/api/v1/activitypub/user-id/1",
want: ActorData{
schema: "https",
userId: "1",
path: "/api/v1/activitypub/user-id/1",
host: "repo.prod.meissa.de",
port: "",
},
},
"withInvalidActorID": {
item: "https://repo.prod.meissa.de/api/activitypub/user-id/1",
want: ActorData{
schema: "https",
userId: "1",
path: "/api/v1/activitypub/user-id/1",
host: "repo.prod.meissa.de",
port: "",
},
},
}
for name, _ := range tests {
t.Run(name, func(t *testing.T) {
_, err := ParseActorData(tests[name].item)
if err != nil {
t.Errorf("parseActor() error = \"%v\"", err)
return
}
})
}
}

@ -4,6 +4,8 @@
package forgefed
import (
"fmt"
ap "github.com/go-ap/activitypub"
"github.com/valyala/fastjson"
)
@ -42,6 +44,16 @@ func StarNew(id ap.ID, ob ap.ID) *Star { // ToDo: May be used later in creating
return &o
}
func (a Star) ValidateStar() error {
if a.Source != "forgejo" {
return fmt.Errorf("currently, only a forgejo source is supported")
}
return nil
}
func (a Star) MarshalJSON() ([]byte, error) {
b := make([]byte, 0)
ap.JSONWrite(&b, '{')

@ -8,6 +8,7 @@ import (
"net/http"
"strings"
"code.gitea.io/gitea/models/activitypub"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/forgefed"
"code.gitea.io/gitea/modules/log"
@ -35,7 +36,7 @@ func Repository(ctx *context.APIContext) {
// "200":
// "$ref": "#/responses/ActivityPub"
link := fmt.Sprintf("%s/api/v1/activitypub/repoistory-id/%d", strings.TrimSuffix(setting.AppURL, "/"), ctx.Repo.Repository.ID)
link := fmt.Sprintf("%s/api/v1/activitypub/repository-id/%d", strings.TrimSuffix(setting.AppURL, "/"), ctx.Repo.Repository.ID)
repo := forgefed.RepositoryNew(ap.IRI(link))
repo.Name = ap.NaturalLanguageValuesNew()
@ -72,10 +73,37 @@ func RepositoryInbox(ctx *context.APIContext) {
log.Info("RepositoryInbox: repo %v, %v", ctx.Repo.Repository.OwnerName, ctx.Repo.Repository.Name)
opt := web.GetForm(ctx).(*forgefed.Star)
err := opt.ValidateStar()
if err != nil {
panic(err)
}
log.Info("RepositoryInbox: Activity.Source %v", opt.Source)
log.Info("RepositoryInbox: Activity.Actor %v", opt.Activity)
log.Info("RepositoryInbox: Activity.Actor %v", opt.Actor)
// assume actor is: "actor": "https://codeberg.org/api/v1/activitypub/user-id/12345" - NB: This might be actually the ID? Maybe check vocabulary.
// parse actor
actor, err := activitypub.ParseActorData(opt.Actor.GetID().String())
// Is the actor IRI well formed?
if err != nil {
panic(err)
}
// Is the ActorData Struct valid?
err = actor.ValidateActorData()
if err != nil {
panic(err)
}
log.Info("RepositoryInbox: Actor parsed. %v", actor)
// get_person_by_rest
// create_user_from_person (if not alreaydy present)
// assume actor is: "actor": "https://codeberg.org/api/activitypub/user-id/12345"
// wait 15 sec.
ctx.Status(http.StatusNoContent)

Loading…
Cancel
Save