diff --git a/models/forgefed/actor.go b/models/forgefed/actor.go index 14804b3123..9c409ae9b1 100644 --- a/models/forgefed/actor.go +++ b/models/forgefed/actor.go @@ -14,12 +14,11 @@ import ( type Validateables interface { validation.Validateable - ActorId | PersonId | RepositoryId + ActorID | PersonID | RepositoryID } -type ActorId struct { - validation.Validateable - Id string +type ActorID struct { + ID string Source string Schema string Path string @@ -28,18 +27,17 @@ type ActorId struct { UnvalidatedInput string } -type PersonId struct { - ActorId +type PersonID struct { + ActorID } -type RepositoryId struct { - ActorId +type RepositoryID struct { + ActorID } -// newActorId receives already validated inputs -func newActorId(validatedUri *url.URL, source string) (ActorId, error) { - - pathWithActorID := strings.Split(validatedUri.Path, "/") +// newActorID receives already validated inputs +func newActorID(validatedURI *url.URL, source string) (ActorID, error) { + pathWithActorID := strings.Split(validatedURI.Path, "/") if containsEmptyString(pathWithActorID) { pathWithActorID = removeEmptyStrings(pathWithActorID) } @@ -47,14 +45,14 @@ func newActorId(validatedUri *url.URL, source string) (ActorId, error) { pathWithoutActorID := strings.Join(pathWithActorID[0:length-1], "/") id := pathWithActorID[length-1] - result := ActorId{} - result.Id = id + result := ActorID{} + result.ID = id result.Source = source - result.Schema = validatedUri.Scheme - result.Host = validatedUri.Hostname() + result.Schema = validatedURI.Scheme + result.Host = validatedURI.Hostname() result.Path = pathWithoutActorID - result.Port = validatedUri.Port() - result.UnvalidatedInput = validatedUri.String() + result.Port = validatedURI.Port() + result.UnvalidatedInput = validatedURI.String() if valid, err := IsValid(result); !valid { return ActorId{}, err @@ -63,114 +61,115 @@ func newActorId(validatedUri *url.URL, source string) (ActorId, error) { return result, nil } -func NewPersonId(uri string, source string) (PersonId, error) { +func NewPersonID(uri string, source string) (PersonID, error) { // TODO: remove after test //if !validation.IsValidExternalURL(uri) { // return PersonId{}, fmt.Errorf("uri %s is not a valid external url", uri) //} - validatedUri, err := url.ParseRequestURI(uri) + validatedURI, err := url.ParseRequestURI(uri) if err != nil { - return PersonId{}, err + return PersonID{}, err } - actorId, err := newActorId(validatedUri, source) + actorID, err := newActorID(validatedURI, source) if err != nil { - return PersonId{}, err + return PersonID{}, err } // validate Person specific path - personId := PersonId{actorId} - if valid, outcome := IsValid(personId); !valid { - return PersonId{}, outcome + personID := PersonID{actorID} + if valid, outcome := validation.IsValid(personID); !valid { + return PersonID{}, outcome } - return personId, nil + return personID, nil } -func NewRepositoryId(uri string, source string) (RepositoryId, error) { +func NewRepositoryId(uri string, source string) (RepositoryID, error) { + if !validation.IsAPIURL(uri) { - return RepositoryId{}, fmt.Errorf("uri %s is not a valid repo url on this host %s", uri, setting.AppURL+"api") + return RepositoryID{}, fmt.Errorf("uri %s is not a valid repo url on this host %s", uri, setting.AppURL+"api") } - validatedUri, err := url.ParseRequestURI(uri) + validatedURI, err := url.ParseRequestURI(uri) if err != nil { - return RepositoryId{}, err + return RepositoryID{}, err } - actorId, err := newActorId(validatedUri, source) + actorID, err := newActorID(validatedURI, source) if err != nil { - return RepositoryId{}, err + return RepositoryID{}, err } // validate Person specific path - repoId := RepositoryId{actorId} - if valid, outcome := IsValid(repoId); !valid { - return RepositoryId{}, outcome + repoID := RepositoryID{actorID} + if valid, outcome := validation.IsValid(repoID); !valid { + return RepositoryID{}, outcome } - return repoId, nil + return repoID, nil } -func (id ActorId) AsUri() string { - result := "" +func (id ActorID) AsURI() string { + var result string if id.Port == "" { - result = fmt.Sprintf("%s://%s/%s/%s", id.Schema, id.Host, id.Path, id.Id) + result = fmt.Sprintf("%s://%s/%s/%s", id.Schema, id.Host, id.Path, id.ID) } else { - result = fmt.Sprintf("%s://%s:%s/%s/%s", id.Schema, id.Host, id.Port, id.Path, id.Id) + result = fmt.Sprintf("%s://%s:%s/%s/%s", id.Schema, id.Host, id.Port, id.Path, id.ID) } return result } -func (id PersonId) AsWebfinger() string { - result := fmt.Sprintf("@%s@%s", strings.ToLower(id.Id), strings.ToLower(id.Host)) +func (id PersonID) AsWebfinger() string { + result := fmt.Sprintf("@%s@%s", strings.ToLower(id.ID), strings.ToLower(id.Host)) return result } -func (id PersonId) AsLoginName() string { - result := fmt.Sprintf("%s%s", strings.ToLower(id.Id), id.HostSuffix()) +func (id PersonID) AsLoginName() string { + result := fmt.Sprintf("%s%s", strings.ToLower(id.ID), id.HostSuffix()) return result } -func (id PersonId) HostSuffix() string { +func (id PersonID) HostSuffix() string { result := fmt.Sprintf("-%s", strings.ToLower(id.Host)) return result } // Validate collects error strings in a slice and returns this -func (value ActorId) Validate() []string { +func (id ActorID) Validate() []string { var result = []string{} - result = append(result, validation.ValidateNotEmpty(value.Id, "userId")...) - result = append(result, validation.ValidateNotEmpty(value.Source, "source")...) - result = append(result, validation.ValidateNotEmpty(value.Schema, "schema")...) - result = append(result, validation.ValidateNotEmpty(value.Path, "path")...) - result = append(result, validation.ValidateNotEmpty(value.Host, "host")...) - result = append(result, validation.ValidateNotEmpty(value.UnvalidatedInput, "unvalidatedInput")...) - result = append(result, validation.ValidateOneOf(value.Source, []string{"forgejo", "gitea"})...) + result = append(result, validation.ValidateNotEmpty(id.ID, "userId")...) + result = append(result, validation.ValidateNotEmpty(id.Source, "source")...) + result = append(result, validation.ValidateNotEmpty(id.Schema, "schema")...) + result = append(result, validation.ValidateNotEmpty(id.Path, "path")...) + result = append(result, validation.ValidateNotEmpty(id.Host, "host")...) + result = append(result, validation.ValidateNotEmpty(id.UnvalidatedInput, "unvalidatedInput")...) + result = append(result, validation.ValidateOneOf(id.Source, []string{"forgejo", "gitea"})...) - if value.UnvalidatedInput != value.AsUri() { - result = append(result, fmt.Sprintf("not all input: %q was parsed: %q", value.UnvalidatedInput, value.AsUri())) + if id.UnvalidatedInput != id.AsURI() { + result = append(result, fmt.Sprintf("not all input: %q was parsed: %q", id.UnvalidatedInput, id.AsURI())) } return result } -func (value PersonId) Validate() []string { - var result = value.ActorId.Validate() - switch value.Source { +func (id PersonID) Validate() []string { + var result = id.ActorID.Validate() + switch id.Source { case "forgejo", "gitea": - if strings.ToLower(value.Path) != "api/v1/activitypub/user-id" && strings.ToLower(value.Path) != "api/activitypub/user-id" { - result = append(result, fmt.Sprintf("path: %q has to be a person specific api path", value.Path)) + if strings.ToLower(id.Path) != "api/v1/activitypub/user-id" && strings.ToLower(id.Path) != "api/activitypub/user-id" { + result = append(result, fmt.Sprintf("path: %q has to be a person specific api path", id.Path)) } } return result } -func (value RepositoryId) Validate() []string { - var result = value.ActorId.Validate() - switch value.Source { +func (id RepositoryID) Validate() []string { + var result = id.ActorID.Validate() + switch id.Source { case "forgejo", "gitea": - if strings.ToLower(value.Path) != "api/v1/activitypub/repository-id" && strings.ToLower(value.Path) != "api/activitypub/repository-id" { - result = append(result, fmt.Sprintf("path: %q has to be a repo specific api path", value.Path)) + if strings.ToLower(id.Path) != "api/v1/activitypub/repository-id" && strings.ToLower(id.Path) != "api/activitypub/repository-id" { + result = append(result, fmt.Sprintf("path: %q has to be a repo specific api path", id.Path)) } } return result diff --git a/models/forgefed/actor_test.go b/models/forgefed/actor_test.go index 1733d3fd1f..d316d60aa5 100644 --- a/models/forgefed/actor_test.go +++ b/models/forgefed/actor_test.go @@ -10,28 +10,28 @@ import ( ) func TestNewPersonId(t *testing.T) { - expected := PersonId{} - expected.Id = "1" + expected := PersonID{} + expected.ID = "1" expected.Source = "forgejo" expected.Schema = "https" expected.Path = "api/v1/activitypub/user-id" expected.Host = "an.other.host" expected.Port = "" expected.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/1" - sut, _ := NewPersonId("https://an.other.host/api/v1/activitypub/user-id/1", "forgejo") + sut, _ := NewPersonID("https://an.other.host/api/v1/activitypub/user-id/1", "forgejo") if sut != expected { t.Errorf("expected: %v\n but was: %v\n", expected, sut) } - expected = PersonId{} - expected.Id = "1" + expected = PersonID{} + expected.ID = "1" expected.Source = "forgejo" expected.Schema = "https" expected.Path = "api/v1/activitypub/user-id" expected.Host = "an.other.host" expected.Port = "443" expected.UnvalidatedInput = "https://an.other.host:443/api/v1/activitypub/user-id/1" - sut, _ = NewPersonId("https://an.other.host:443/api/v1/activitypub/user-id/1", "forgejo") + sut, _ = NewPersonID("https://an.other.host:443/api/v1/activitypub/user-id/1", "forgejo") if sut != expected { t.Errorf("expected: %v\n but was: %v\n", expected, sut) } @@ -39,8 +39,8 @@ func TestNewPersonId(t *testing.T) { func TestNewRepositoryId(t *testing.T) { setting.AppURL = "http://localhost:3000/" - expected := RepositoryId{} - expected.Id = "1" + expected := RepositoryID{} + expected.ID = "1" expected.Source = "forgejo" expected.Schema = "http" expected.Path = "api/activitypub/repository-id" @@ -54,7 +54,7 @@ func TestNewRepositoryId(t *testing.T) { } func TestActorIdValidation(t *testing.T) { - sut := ActorId{} + sut := ActorID{} sut.Source = "forgejo" sut.Schema = "https" sut.Path = "api/v1/activitypub/user-id" @@ -65,8 +65,8 @@ func TestActorIdValidation(t *testing.T) { t.Errorf("validation error expected but was: %v\n", sut.Validate()) } - sut = ActorId{} - sut.Id = "1" + sut = ActorID{} + sut.ID = "1" sut.Source = "forgejox" sut.Schema = "https" sut.Path = "api/v1/activitypub/user-id" @@ -77,8 +77,8 @@ func TestActorIdValidation(t *testing.T) { t.Errorf("validation error expected but was: %v\n", sut.Validate()) } - sut = ActorId{} - sut.Id = "1" + sut = ActorID{} + sut.ID = "1" sut.Source = "forgejo" sut.Schema = "https" sut.Path = "api/v1/activitypub/user-id" @@ -91,8 +91,8 @@ func TestActorIdValidation(t *testing.T) { } func TestPersonIdValidation(t *testing.T) { - sut := PersonId{} - sut.Id = "1" + sut := PersonID{} + sut.ID = "1" sut.Source = "forgejo" sut.Schema = "https" sut.Path = "path" @@ -105,12 +105,12 @@ func TestPersonIdValidation(t *testing.T) { } func TestWebfingerId(t *testing.T) { - sut, _ := NewPersonId("https://codeberg.org/api/v1/activitypub/user-id/12345", "forgejo") + sut, _ := NewPersonID("https://codeberg.org/api/v1/activitypub/user-id/12345", "forgejo") if sut.AsWebfinger() != "@12345@codeberg.org" { t.Errorf("wrong webfinger: %v", sut.AsWebfinger()) } - sut, _ = NewPersonId("https://Codeberg.org/api/v1/activitypub/user-id/12345", "forgejo") + sut, _ = NewPersonID("https://Codeberg.org/api/v1/activitypub/user-id/12345", "forgejo") if sut.AsWebfinger() != "@12345@codeberg.org" { t.Errorf("wrong webfinger: %v", sut.AsWebfinger()) } @@ -122,32 +122,32 @@ func TestShouldThrowErrorOnInvalidInput(t *testing.T) { t.Errorf("empty input should be invalid.") } - _, err = NewPersonId("http://localhost:3000/api/v1/something", "forgejo") + _, err = NewPersonID("http://localhost:3000/api/v1/something", "forgejo") if err == nil { t.Errorf("localhost uris are not external") } - _, err = NewPersonId("./api/v1/something", "forgejo") + _, err = NewPersonID("./api/v1/something", "forgejo") if err == nil { t.Errorf("relative uris are not alowed") } - _, err = NewPersonId("http://1.2.3.4/api/v1/something", "forgejo") + _, err = NewPersonID("http://1.2.3.4/api/v1/something", "forgejo") if err == nil { t.Errorf("uri may not be ip-4 based") } - _, err = NewPersonId("http:///[fe80::1ff:fe23:4567:890a%25eth0]/api/v1/something", "forgejo") + _, err = NewPersonID("http:///[fe80::1ff:fe23:4567:890a%25eth0]/api/v1/something", "forgejo") if err == nil { t.Errorf("uri may not be ip-6 based") } - _, err = NewPersonId("https://codeberg.org/api/v1/activitypub/../activitypub/user-id/12345", "forgejo") + _, err = NewPersonID("https://codeberg.org/api/v1/activitypub/../activitypub/user-id/12345", "forgejo") if err == nil { t.Errorf("uri may not contain relative path elements") } - _, err = NewPersonId("https://myuser@an.other.host/api/v1/activitypub/user-id/1", "forgejo") + _, err = NewPersonID("https://myuser@an.other.host/api/v1/activitypub/user-id/1", "forgejo") if err == nil { t.Errorf("uri may not contain unparsed elements") } - _, err = NewPersonId("https://an.other.host/api/v1/activitypub/user-id/1", "forgejo") + _, err = NewPersonID("https://an.other.host/api/v1/activitypub/user-id/1", "forgejo") if err != nil { t.Errorf("this uri should be valid but was: %v", err) } diff --git a/models/forgefed/star.go b/models/forgefed/star.go index 3e6843e0f9..681adb8cbe 100644 --- a/models/forgefed/star.go +++ b/models/forgefed/star.go @@ -42,12 +42,12 @@ func StarNew(id ap.ID, ob ap.ID) *Star { // ToDo: May be used later in creating return &o } -func (a Star) MarshalJSON() ([]byte, error) { +func (s Star) MarshalJSON() ([]byte, error) { b := make([]byte, 0) ap.JSONWrite(&b, '{') - ap.JSONWriteStringProp(&b, "source", string(a.Source)) - if !ap.JSONWriteActivityValue(&b, a.Activity) { + ap.JSONWriteStringProp(&b, "source", string(s.Source)) + if !ap.JSONWriteActivityValue(&b, s.Activity) { return nil, nil } ap.JSONWrite(&b, '}') diff --git a/routers/api/v1/activitypub/repository.go b/routers/api/v1/activitypub/repository.go index 31b6b844c8..9d26dec0b3 100644 --- a/routers/api/v1/activitypub/repository.go +++ b/routers/api/v1/activitypub/repository.go @@ -89,30 +89,30 @@ func RepositoryInbox(ctx *context.APIContext) { activity := web.GetForm(ctx).(*forgefed.Star) log.Info("RepositoryInbox: activity:%v", activity) - // parse actorId (person) - actorId, err := forgefed.NewPersonId(activity.Actor.GetID().String(), string(activity.Source)) + // parse actorID (person) + actorID, err := forgefed.NewPersonID(activity.Actor.GetID().String(), string(activity.Source)) if err != nil { ctx.ServerError("Validate actorId", err) return } - log.Info("RepositoryInbox: actorId validated: %v", actorId) - // parse objectId (repository) - objectId, err := forgefed.NewRepositoryId(activity.Object.GetID().String(), string(activity.Source)) + log.Info("RepositoryInbox: actorId validated: %v", actorID) + // parse objectID (repository) + objectID, err := forgefed.NewRepositoryId(activity.Object.GetID().String(), string(activity.Source)) if err != nil { ctx.ServerError("Validate objectId", err) return } - if objectId.Id != fmt.Sprint(repository.ID) { + if objectID.ID != fmt.Sprint(repository.ID) { ctx.ServerError("Validate objectId", err) return } - log.Info("RepositoryInbox: objectId validated: %v", objectId) + log.Info("RepositoryInbox: objectId validated: %v", objectID) - actorAsLoginId := actorId.AsLoginName() // used as LoginName in newly created user - log.Info("RepositoryInbox: remoteStargazer: %v", actorAsLoginId) + actorAsLoginID := actorID.AsLoginName() // used as LoginName in newly created user + log.Info("RepositoryInbox: remoteStargazer: %v", actorAsLoginID) // Check if user already exists - users, err := SearchUsersByLoginName(actorAsLoginId) + users, err := SearchUsersByLoginName(actorAsLoginID) if err != nil { ctx.ServerError("Searching for user failed", err) return @@ -122,7 +122,7 @@ func RepositoryInbox(ctx *context.APIContext) { switch len(users) { case 0: { - user, err = createUserFromAP(ctx, actorId) + user, err = createUserFromAP(ctx, actorID) if err != nil { ctx.ServerError("Creating user failed", err) return @@ -182,7 +182,7 @@ func SearchUsersByLoginName(loginName string) ([]*user_model.User, error) { } // ToDo: Maybe use externalLoginUser -func createUserFromAP(ctx *context.APIContext, personId forgefed.PersonId) (*user_model.User, error) { +func createUserFromAP(ctx *context.APIContext, personID forgefed.PersonID) (*user_model.User, error) { // ToDo: Do we get a publicKeyId from server, repo or owner or repo? var actionsUser = user_model.NewActionsUser() client, err := api.NewClient(ctx, actionsUser, "no idea where to get key material.") @@ -190,7 +190,7 @@ func createUserFromAP(ctx *context.APIContext, personId forgefed.PersonId) (*use return &user_model.User{}, err } - response, err := client.Get(personId.AsUri()) + response, err := client.Get(personID.AsURI()) if err != nil { return &user_model.User{}, err } @@ -198,7 +198,7 @@ func createUserFromAP(ctx *context.APIContext, personId forgefed.PersonId) (*use // validate response; ToDo: Should we widen the restrictions here? if response.StatusCode != 200 { - err = fmt.Errorf("got non 200 status code for id: %v", personId.Id) + err = fmt.Errorf("got non 200 status code for id: %v", personID.ID) return &user_model.User{}, err } @@ -216,9 +216,9 @@ func createUserFromAP(ctx *context.APIContext, personId forgefed.PersonId) (*use } log.Info("RepositoryInbox: got person by ap: %v", person) - email := fmt.Sprintf("%v@%v", uuid.New().String(), personId.Host) - loginName := personId.AsLoginName() - name := fmt.Sprintf("%v%v", person.PreferredUsername.String(), personId.HostSuffix()) + email := fmt.Sprintf("%v@%v", uuid.New().String(), personID.Host) + loginName := personID.AsLoginName() + name := fmt.Sprintf("%v%v", person.PreferredUsername.String(), personID.HostSuffix()) log.Info("RepositoryInbox: person.Name: %v", person.Name) fullName := person.Name.String() if len(person.Name) == 0 {