mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-12-23 14:53:34 +01:00
introduce RepositoryId
This commit is contained in:
parent
1fe35e14a5
commit
3172eb69d2
2 changed files with 174 additions and 101 deletions
|
@ -8,17 +8,26 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/validation"
|
"code.gitea.io/gitea/modules/validation"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ActorId struct {
|
||||||
|
Id string
|
||||||
|
Source string
|
||||||
|
Schema string
|
||||||
|
Path string
|
||||||
|
Host string
|
||||||
|
Port string
|
||||||
|
UnvalidatedInput string
|
||||||
|
}
|
||||||
|
|
||||||
type PersonId struct {
|
type PersonId struct {
|
||||||
userId string
|
ActorId
|
||||||
source string
|
}
|
||||||
schema string
|
|
||||||
path string
|
type RepositoryId struct {
|
||||||
host string
|
ActorId
|
||||||
port string
|
|
||||||
unvalidatedInput string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPersonId(uri string, source string) (PersonId, error) {
|
func NewPersonId(uri string, source string) (PersonId, error) {
|
||||||
|
@ -27,44 +36,71 @@ func NewPersonId(uri string, source string) (PersonId, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
validatedUri, _ := url.Parse(uri)
|
validatedUri, _ := url.Parse(uri)
|
||||||
pathWithUserID := strings.Split(validatedUri.Path, "/")
|
pathWithActorID := strings.Split(validatedUri.Path, "/")
|
||||||
|
if containsEmptyString(pathWithActorID) {
|
||||||
if containsEmptyString(pathWithUserID) {
|
pathWithActorID = removeEmptyStrings(pathWithActorID)
|
||||||
pathWithUserID = removeEmptyStrings(pathWithUserID)
|
|
||||||
}
|
}
|
||||||
|
length := len(pathWithActorID)
|
||||||
|
pathWithoutActorID := strings.Join(pathWithActorID[0:length-1], "/")
|
||||||
|
id := pathWithActorID[length-1]
|
||||||
|
|
||||||
length := len(pathWithUserID)
|
result := PersonId{}
|
||||||
pathWithoutUserID := strings.Join(pathWithUserID[0:length-1], "/")
|
result.Id = id
|
||||||
userId := pathWithUserID[length-1]
|
result.Source = source
|
||||||
|
result.Schema = validatedUri.Scheme
|
||||||
actorId := PersonId{
|
result.Host = validatedUri.Hostname()
|
||||||
userId: userId,
|
result.Path = pathWithoutActorID
|
||||||
source: source,
|
result.Port = validatedUri.Port()
|
||||||
schema: validatedUri.Scheme,
|
result.UnvalidatedInput = uri
|
||||||
host: validatedUri.Hostname(),
|
if valid, err := result.IsValid(); !valid {
|
||||||
path: pathWithoutUserID,
|
|
||||||
port: validatedUri.Port(),
|
|
||||||
unvalidatedInput: uri,
|
|
||||||
}
|
|
||||||
if valid, err := actorId.IsValid(); !valid {
|
|
||||||
return PersonId{}, err
|
return PersonId{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return actorId, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (id PersonId) AsUri() string {
|
// TODO: tbd how an which parts can be generalized
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
|
||||||
|
validatedUri, _ := url.Parse(uri)
|
||||||
|
pathWithActorID := strings.Split(validatedUri.Path, "/")
|
||||||
|
if containsEmptyString(pathWithActorID) {
|
||||||
|
pathWithActorID = removeEmptyStrings(pathWithActorID)
|
||||||
|
}
|
||||||
|
length := len(pathWithActorID)
|
||||||
|
pathWithoutActorID := strings.Join(pathWithActorID[0:length-1], "/")
|
||||||
|
id := pathWithActorID[length-1]
|
||||||
|
|
||||||
|
result := RepositoryId{}
|
||||||
|
result.Id = id
|
||||||
|
result.Source = source
|
||||||
|
result.Schema = validatedUri.Scheme
|
||||||
|
result.Host = validatedUri.Hostname()
|
||||||
|
result.Path = pathWithoutActorID
|
||||||
|
result.Port = validatedUri.Port()
|
||||||
|
result.UnvalidatedInput = uri
|
||||||
|
if valid, err := result.IsValid(); !valid {
|
||||||
|
return RepositoryId{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (id ActorId) AsUri() string {
|
||||||
result := ""
|
result := ""
|
||||||
if id.port == "" {
|
if id.Port == "" {
|
||||||
result = fmt.Sprintf("%s://%s/%s/%s", id.schema, id.host, id.path, id.userId)
|
result = fmt.Sprintf("%s://%s/%s/%s", id.Schema, id.Host, id.Path, id.Id)
|
||||||
} else {
|
} else {
|
||||||
result = fmt.Sprintf("%s://%s:%s/%s/%s", id.schema, id.host, id.port, id.path, id.userId)
|
result = fmt.Sprintf("%s://%s:%s/%s/%s", id.Schema, id.Host, id.Port, id.Path, id.Id)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (id PersonId) AsWebfinger() string {
|
func (id ActorId) AsWebfinger() string {
|
||||||
result := fmt.Sprintf("@%s@%s", strings.ToLower(id.userId), strings.ToLower(id.host))
|
result := fmt.Sprintf("@%s@%s", strings.ToLower(id.Id), strings.ToLower(id.Host))
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,22 +109,45 @@ Validate collects error strings in a slice and returns this
|
||||||
*/
|
*/
|
||||||
func (value PersonId) Validate() []string {
|
func (value PersonId) Validate() []string {
|
||||||
var result = []string{}
|
var result = []string{}
|
||||||
result = append(result, validation.ValidateNotEmpty(value.userId, "userId")...)
|
result = append(result, validation.ValidateNotEmpty(value.Id, "userId")...)
|
||||||
result = append(result, validation.ValidateNotEmpty(value.source, "source")...)
|
result = append(result, validation.ValidateNotEmpty(value.Source, "source")...)
|
||||||
result = append(result, validation.ValidateNotEmpty(value.schema, "schema")...)
|
result = append(result, validation.ValidateNotEmpty(value.Schema, "schema")...)
|
||||||
result = append(result, validation.ValidateNotEmpty(value.path, "path")...)
|
result = append(result, validation.ValidateNotEmpty(value.Path, "path")...)
|
||||||
result = append(result, validation.ValidateNotEmpty(value.host, "host")...)
|
result = append(result, validation.ValidateNotEmpty(value.Host, "host")...)
|
||||||
result = append(result, validation.ValidateNotEmpty(value.unvalidatedInput, "unvalidatedInput")...)
|
result = append(result, validation.ValidateNotEmpty(value.UnvalidatedInput, "unvalidatedInput")...)
|
||||||
|
|
||||||
result = append(result, validation.ValidateOneOf(value.source, []string{"forgejo", "gitea"})...)
|
result = append(result, validation.ValidateOneOf(value.Source, []string{"forgejo", "gitea"})...)
|
||||||
switch value.source {
|
switch value.Source {
|
||||||
case "forgejo", "gitea":
|
case "forgejo", "gitea":
|
||||||
if strings.ToLower(value.path) != "api/v1/activitypub/user-id" {
|
if strings.ToLower(value.Path) != "api/v1/activitypub/user-id" && strings.ToLower(value.Path) != "api/activitypub/user-id" {
|
||||||
result = append(result, fmt.Sprintf("path has to be a api path"))
|
result = append(result, fmt.Sprintf("path: %q has to be a api path", value.Path))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if value.unvalidatedInput != value.AsUri() {
|
if value.UnvalidatedInput != value.AsUri() {
|
||||||
result = append(result, fmt.Sprintf("not all input: %q was parsed: %q", value.unvalidatedInput, value.AsUri()))
|
result = append(result, fmt.Sprintf("not all input: %q was parsed: %q", value.UnvalidatedInput, value.AsUri()))
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (value RepositoryId) 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"})...)
|
||||||
|
switch value.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 api path", value.Path))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if value.UnvalidatedInput != value.AsUri() {
|
||||||
|
result = append(result, fmt.Sprintf("not all input: %q was parsed: %q", value.UnvalidatedInput, value.AsUri()))
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
@ -106,10 +165,12 @@ func (a PersonId) IsValid() (bool, error) {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a PersonId) PanicIfInvalid() {
|
func (a RepositoryId) IsValid() (bool, error) {
|
||||||
if valid, err := a.IsValid(); !valid {
|
if err := a.Validate(); len(err) > 0 {
|
||||||
panic(err)
|
errString := strings.Join(err, "\n")
|
||||||
|
return false, fmt.Errorf(errString)
|
||||||
}
|
}
|
||||||
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func containsEmptyString(ar []string) bool {
|
func containsEmptyString(ar []string) bool {
|
||||||
|
|
|
@ -5,86 +5,98 @@ package forgefed
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNewPersonId(t *testing.T) {
|
func TestNewPersonId(t *testing.T) {
|
||||||
expected := PersonId{
|
expected := PersonId{}
|
||||||
userId: "1",
|
expected.Id = "1"
|
||||||
source: "forgejo",
|
expected.Source = "forgejo"
|
||||||
schema: "https",
|
expected.Schema = "https"
|
||||||
path: "api/v1/activitypub/user-id",
|
expected.Path = "api/v1/activitypub/user-id"
|
||||||
host: "an.other.host",
|
expected.Host = "an.other.host"
|
||||||
port: "",
|
expected.Port = ""
|
||||||
unvalidatedInput: "https://an.other.host/api/v1/activitypub/user-id/1",
|
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 {
|
if sut != expected {
|
||||||
t.Errorf("expected: %v\n but was: %v\n", expected, sut)
|
t.Errorf("expected: %v\n but was: %v\n", expected, sut)
|
||||||
}
|
}
|
||||||
|
|
||||||
expected = PersonId{
|
expected = PersonId{}
|
||||||
userId: "1",
|
expected.Id = "1"
|
||||||
source: "forgejo",
|
expected.Source = "forgejo"
|
||||||
schema: "https",
|
expected.Schema = "https"
|
||||||
path: "api/v1/activitypub/user-id",
|
expected.Path = "api/v1/activitypub/user-id"
|
||||||
host: "an.other.host",
|
expected.Host = "an.other.host"
|
||||||
port: "443",
|
expected.Port = "443"
|
||||||
unvalidatedInput: "https://an.other.host:443/api/v1/activitypub/user-id/1",
|
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 {
|
if sut != expected {
|
||||||
t.Errorf("expected: %v\n but was: %v\n", expected, sut)
|
t.Errorf("expected: %v\n but was: %v\n", expected, sut)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPersonIdValidation(t *testing.T) {
|
func TestNewRepositoryId(t *testing.T) {
|
||||||
sut := PersonId{
|
setting.AppURL = "http://localhost:3000/"
|
||||||
source: "forgejo",
|
expected := RepositoryId{}
|
||||||
schema: "https",
|
expected.Id = "1"
|
||||||
path: "api/v1/activitypub/user-id",
|
expected.Source = "forgejo"
|
||||||
host: "an.other.host",
|
expected.Schema = "http"
|
||||||
port: "",
|
expected.Path = "api/activitypub/repository-id"
|
||||||
unvalidatedInput: "https://an.other.host/api/v1/activitypub/user-id/",
|
expected.Host = "localhost"
|
||||||
|
expected.Port = "3000"
|
||||||
|
expected.UnvalidatedInput = "http://localhost:3000/api/activitypub/repository-id/1"
|
||||||
|
sut, _ := NewRepositoryId("http://localhost:3000/api/activitypub/repository-id/1", "forgejo")
|
||||||
|
if sut != expected {
|
||||||
|
t.Errorf("expected: %v\n but was: %v\n", expected, sut)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPersonIdValidation(t *testing.T) {
|
||||||
|
sut := PersonId{}
|
||||||
|
sut.Source = "forgejo"
|
||||||
|
sut.Schema = "https"
|
||||||
|
sut.Path = "api/v1/activitypub/user-id"
|
||||||
|
sut.Host = "an.other.host"
|
||||||
|
sut.Port = ""
|
||||||
|
sut.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/"
|
||||||
if sut.Validate()[0] != "Field userId may not be empty" {
|
if sut.Validate()[0] != "Field userId may not be empty" {
|
||||||
t.Errorf("validation error expected but was: %v\n", sut.Validate())
|
t.Errorf("validation error expected but was: %v\n", sut.Validate())
|
||||||
}
|
}
|
||||||
|
|
||||||
sut = PersonId{
|
sut = PersonId{}
|
||||||
userId: "1",
|
sut.Id = "1"
|
||||||
source: "forgejox",
|
sut.Source = "forgejox"
|
||||||
schema: "https",
|
sut.Schema = "https"
|
||||||
path: "api/v1/activitypub/user-id",
|
sut.Path = "api/v1/activitypub/user-id"
|
||||||
host: "an.other.host",
|
sut.Host = "an.other.host"
|
||||||
port: "",
|
sut.Port = ""
|
||||||
unvalidatedInput: "https://an.other.host/api/v1/activitypub/user-id/1",
|
sut.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/1"
|
||||||
}
|
|
||||||
if sut.Validate()[0] != "Value forgejox is not contained in allowed values [[forgejo gitea]]" {
|
if sut.Validate()[0] != "Value forgejox is not contained in allowed values [[forgejo gitea]]" {
|
||||||
t.Errorf("validation error expected but was: %v\n", sut.Validate())
|
t.Errorf("validation error expected but was: %v\n", sut.Validate())
|
||||||
}
|
}
|
||||||
|
|
||||||
sut = PersonId{
|
sut = PersonId{}
|
||||||
userId: "1",
|
sut.Id = "1"
|
||||||
source: "forgejo",
|
sut.Source = "forgejo"
|
||||||
schema: "https",
|
sut.Schema = "https"
|
||||||
path: "api/v1/activitypub/user-idx",
|
sut.Path = "path"
|
||||||
host: "an.other.host",
|
sut.Host = "an.other.host"
|
||||||
port: "",
|
sut.Port = ""
|
||||||
unvalidatedInput: "https://an.other.host/api/v1/activitypub/user-id/1",
|
sut.UnvalidatedInput = "https://an.other.host/path/1"
|
||||||
}
|
if sut.Validate()[0] != "path: \"path\" has to be a api path" {
|
||||||
if sut.Validate()[0] != "path has to be a api path" {
|
|
||||||
t.Errorf("validation error expected but was: %v\n", sut.Validate())
|
t.Errorf("validation error expected but was: %v\n", sut.Validate())
|
||||||
}
|
}
|
||||||
|
|
||||||
sut = PersonId{
|
sut = PersonId{}
|
||||||
userId: "1",
|
sut.Id = "1"
|
||||||
source: "forgejo",
|
sut.Source = "forgejo"
|
||||||
schema: "https",
|
sut.Schema = "https"
|
||||||
path: "api/v1/activitypub/user-id",
|
sut.Path = "api/v1/activitypub/user-id"
|
||||||
host: "an.other.host",
|
sut.Host = "an.other.host"
|
||||||
port: "",
|
sut.Port = ""
|
||||||
unvalidatedInput: "https://an.other.host/api/v1/activitypub/user-id/1?illegal=action",
|
sut.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/1?illegal=action"
|
||||||
}
|
|
||||||
if sut.Validate()[0] != "not all input: \"https://an.other.host/api/v1/activitypub/user-id/1?illegal=action\" was parsed: \"https://an.other.host/api/v1/activitypub/user-id/1\"" {
|
if sut.Validate()[0] != "not all input: \"https://an.other.host/api/v1/activitypub/user-id/1?illegal=action\" was parsed: \"https://an.other.host/api/v1/activitypub/user-id/1\"" {
|
||||||
t.Errorf("validation error expected but was: %v\n", sut.Validate())
|
t.Errorf("validation error expected but was: %v\n", sut.Validate())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue