From d2b4b924d3d068923a5a15bec2173d31af5547f5 Mon Sep 17 00:00:00 2001 From: zam Date: Mon, 31 Mar 2025 19:43:30 +0200 Subject: [PATCH] further steps --- models/forgefed/federationhost.go | 4 +- modules/forgefed/actor.go | 70 +++++++++----------- modules/forgefed/actor_test.go | 79 ++++++++++++----------- modules/forgefed/nodeinfo.go | 4 +- modules/validation/validatable.go | 4 -- services/federation/federation_service.go | 2 +- 6 files changed, 74 insertions(+), 89 deletions(-) diff --git a/models/forgefed/federationhost.go b/models/forgefed/federationhost.go index c24e0938f9..c089f83ae3 100644 --- a/models/forgefed/federationhost.go +++ b/models/forgefed/federationhost.go @@ -18,7 +18,7 @@ type FederationHost struct { ID int64 `xorm:"pk autoincr"` HostFqdn string `xorm:"host_fqdn UNIQUE INDEX VARCHAR(255) NOT NULL"` NodeInfo NodeInfo `xorm:"extends NOT NULL"` - HostPort uint16 `xorm:"NOT NULL"` + HostPort string `xorm:"NOT NULL"` HostSchema string `xorm:"NOT NULL"` LatestActivity time.Time `xorm:"NOT NULL"` Created timeutil.TimeStamp `xorm:"created"` @@ -26,7 +26,7 @@ type FederationHost struct { } // Factory function for FederationHost. Created struct is asserted to be valid. -func NewFederationHost(hostFqdn string, nodeInfo NodeInfo, port uint16, schema string) (FederationHost, error) { +func NewFederationHost(hostFqdn string, nodeInfo NodeInfo, port string, schema string) (FederationHost, error) { result := FederationHost{ HostFqdn: strings.ToLower(hostFqdn), NodeInfo: nodeInfo, diff --git a/modules/forgefed/actor.go b/modules/forgefed/actor.go index 63fb911d8b..fc43b90653 100644 --- a/modules/forgefed/actor.go +++ b/modules/forgefed/actor.go @@ -6,7 +6,6 @@ package forgefed import ( "fmt" "net/url" - "strconv" "strings" "code.gitea.io/gitea/modules/validation" @@ -21,7 +20,7 @@ type ActorID struct { HostSchema string Path string Host string - HostPort uint16 + HostPort string UnvalidatedInput string } @@ -39,14 +38,9 @@ func NewActorID(uri string) (ActorID, error) { return result, nil } +//Todo: add id.HostPort in case of given https://an.other.host:443/api/v1/activitypub/user-id/1 func (id ActorID) AsURI() string { - var result string - if id.HostPort == 0 { - result = fmt.Sprintf("%s://%s/%s/%s", id.HostSchema, id.Host, id.Path, id.ID) - } else { - result = fmt.Sprintf("%s://%s:%d/%s/%s", id.HostSchema, id.Host, id.HostPort, id.Path, id.ID) - } - return result + return fmt.Sprintf("%s://%s/%s/%s", id.HostSchema, id.Host, id.Path, id.ID) } func (id ActorID) Validate() []string { @@ -55,14 +49,16 @@ func (id ActorID) Validate() []string { result = append(result, validation.ValidateNotEmpty(id.HostSchema, "schema")...) result = append(result, validation.ValidateNotEmpty(id.Path, "path")...) result = append(result, validation.ValidateNotEmpty(id.Host, "host")...) - //ToDo Port should be >0 result = append(result, validation.ValidateNotEmpty(id.HostPort, "HostPort")...) result = append(result, validation.ValidateNotEmpty(id.UnvalidatedInput, "unvalidatedInput")...) - if id.UnvalidatedInput != id.AsURI() { + fmt.Println("id.UnvalidatedInput: ", id.UnvalidatedInput) + fmt.Println("id.AsURI: ", id.AsURI()) + + //add or + if id.UnvalidatedInput != id.AsURI() || id.HostPort != "443" { result = append(result, fmt.Sprintf("not all input was parsed, \nUnvalidated Input:%q \nParsed URI: %q", id.UnvalidatedInput, id.AsURI())) } - return result } @@ -107,12 +103,22 @@ func (id PersonID) Validate() []string { result := id.ActorID.Validate() result = append(result, validation.ValidateNotEmpty(id.Source, "source")...) result = append(result, validation.ValidateOneOf(id.Source, []any{"forgejo", "gitea"}, "Source")...) + result = append(result, validation.ValidateOneOf(id.HostSchema, []any{"https", "http", "HTTPS", "HTTP"}, "Source")...) + switch id.Source { case "forgejo", "gitea": 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)) } } + switch id.HostSchema { + case "HTTPS", "HTTP": + if strings.ToLower(id.HostSchema) == "https" { + result = append(result, fmt.Sprintf("-%s", strings.ToLower(id.HostSchema))) + } else if strings.ToLower(id.HostSchema) == "http" { + result = append(result, fmt.Sprintf("-%s", strings.ToLower(id.HostSchema))) + } + } return result } @@ -173,6 +179,7 @@ func removeEmptyStrings(ls []string) []string { func newActorID(uri string) (ActorID, error) { validatedURI, err := url.ParseRequestURI(uri) + if err != nil { return ActorID{}, err } @@ -183,43 +190,24 @@ func newActorID(uri string) (ActorID, error) { length := len(pathWithActorID) pathWithoutActorID := strings.Join(pathWithActorID[0:length-1], "/") id := pathWithActorID[length-1] - + result := ActorID{} result.ID = id result.HostSchema = validatedURI.Scheme result.Host = validatedURI.Hostname() result.Path = pathWithoutActorID - //Todo correct type & cond 443|80 - numPort, err := strconv.ParseUint(validatedURI.Port(), 10, 16) - //error - //fmt.Printf("\nerror\n numPort= %v\n datatype: %T\n", numPort, numPort) - //fmt.Printf("\nerror\n err= %v\n err: %T\n", err, err) - - if err != nil { - } else if result.HostSchema == "https" { - numPort = 443 - } else if result.HostSchema == "http" { - numPort = 80 - } -/* if numPort == 0 then set no value like result = fmt.Sprintf("%s://%s/%s/%s", id.HostSchema, id.Host, id.Path, id.ID) - if numPort == 0 && result.HostSchema == "https" { - numPort = 443 - } - if numPort == 0 && result.HostSchema == "http" { - numPort = 80 - } - */ - if numPort == 0 && result.HostSchema == "https" { - numPort = 443 - result.HostPort = uint16(numPort) - //result = fmt.Sprintf("%s://%s/%s/%s", id.HostSchema, id.Host, id.Path, id.ID) - result.UnvalidatedInput = uri - fmt.Printf("\ninside numPort = 0: %v\n datatype: %T\n", result, result) + + if validatedURI.Port() == "" && result.HostSchema == "https" { + result.HostPort = "443" + result.UnvalidatedInput = fmt.Sprintf("%s://%s/%s/%s", result.HostSchema, result.Host, result.Path, result.ID) + return result, nil + } else if validatedURI.Port() == "" && result.HostSchema == "http" { + result.HostPort = "80" + result.UnvalidatedInput = fmt.Sprintf("%s://%s/%s/%s", result.HostSchema, result.Host, result.Path, result.ID) return result, nil } - result.HostPort = uint16(numPort) - fmt.Printf("\nresult.HostPort: %v\n datatype: %T\n", result.HostPort, result.HostPort) + result.HostPort = validatedURI.Port() result.UnvalidatedInput = uri return result, nil } diff --git a/modules/forgefed/actor_test.go b/modules/forgefed/actor_test.go index 4bf246d692..61ee58702a 100644 --- a/modules/forgefed/actor_test.go +++ b/modules/forgefed/actor_test.go @@ -21,58 +21,59 @@ func TestNewPersonId(t *testing.T) { expected.HostSchema = "https" expected.Path = "api/v1/activitypub/user-id" expected.Host = "an.other.host" - expected.HostPort = 443 + expected.HostPort = "443" expected.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/1" - t.Log("end at expected 443, but missing") + 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.Source = "forgejo" expected.HostSchema = "https" expected.Path = "api/v1/activitypub/user-id" expected.Host = "an.other.host" - expected.HostPort = 443 + expected.HostPort = "443" expected.UnvalidatedInput = "https://an.other.host:443/api/v1/activitypub/user-id/1" - t.Log("end at expected 443, given") + 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) - } + } + //Todo doit with http:80 + expected = PersonID{} + expected.ID = "1" + expected.Source = "forgejo" + expected.HostSchema = "http" + expected.Path = "api/v1/activitypub/user-id" + expected.Host = "an.other.host" + expected.HostPort = "80" + expected.UnvalidatedInput = "http://an.other.host:80/api/v1/activitypub/user-id/1" - //Todo doit with http:80 - expected = PersonID{} - expected.ID = "1" - expected.Source = "forgejo" - expected.HostSchema = "http" - expected.Path = "api/v1/activitypub/user-id" - expected.Host = "an.other.host" - expected.HostPort = 80 - expected.UnvalidatedInput = "http://an.other.host:80/api/v1/activitypub/user-id/1" - t.Log("end at expected 80, given") - sut, _ = NewPersonID("http://an.other.host:80/api/v1/activitypub/user-id/1", "forgejo") - if sut != expected { - t.Errorf("expected: %v\n but was: %v\n", expected, sut) - } + sut, _ = NewPersonID("http://an.other.host:80/api/v1/activitypub/user-id/1", "forgejo") + if sut != expected { + t.Errorf("expected: %v\n but was: %v\n", expected, sut) + } - //Todo HTTPS - expected = PersonID{} - expected.ID = "1" - expected.Source = "forgejo" - expected.HostSchema = "HTTPS" - expected.Path = "api/v1/activitypub/user-id" - expected.Host = "an.other.host" - expected.HostPort = 443 - expected.UnvalidatedInput = "https://an.other.host:443/api/v1/activitypub/user-id/1" - t.Log("end at expected HTTPS, given") - 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) + //Todo HTTPS + expected = PersonID{} + expected.ID = "1" + expected.Source = "forgejo" + expected.HostSchema = "HTTPS" + expected.Path = "api/v1/activitypub/user-id" + expected.Host = "an.other.host" + expected.HostPort = "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") + if sut != expected { + t.Errorf("expected: %v\n but was: %v\n", expected, sut) + } + */ } -} func TestNewRepositoryId(t *testing.T) { setting.AppURL = "http://localhost:3000/" @@ -82,7 +83,7 @@ func TestNewRepositoryId(t *testing.T) { expected.HostSchema = "http" expected.Path = "api/activitypub/repository-id" expected.Host = "localhost" - expected.HostPort = 3000 + expected.HostPort = "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 { @@ -96,7 +97,7 @@ func TestActorIdValidation(t *testing.T) { sut.HostSchema = "https" sut.Path = "api/v1/activitypub/user-id" sut.Host = "an.other.host" - sut.HostPort = 0 + sut.HostPort = "0" sut.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/" if sut.Validate()[0] != "userId should not be empty" { t.Errorf("validation error expected but was: %v\n", sut.Validate()) @@ -108,7 +109,7 @@ func TestActorIdValidation(t *testing.T) { sut.HostSchema = "https" sut.Path = "api/v1/activitypub/user-id" sut.Host = "an.other.host" - sut.HostPort = 0 + sut.HostPort = "0" sut.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/1?illegal=action" if sut.Validate()[0] != "not all input was parsed, \nUnvalidated Input:\"https://an.other.host/api/v1/activitypub/user-id/1?illegal=action\" \nParsed URI: \"https://an.other.host/api/v1/activitypub/user-id/1\"" { t.Errorf("validation error expected but was: %v\n", sut.Validate()[0]) @@ -122,7 +123,7 @@ func TestPersonIdValidation(t *testing.T) { sut.HostSchema = "https" sut.Path = "path" sut.Host = "an.other.host" - sut.HostPort = 0 + sut.HostPort = "0" sut.UnvalidatedInput = "https://an.other.host/path/1" _, err := validation.IsValid(sut) @@ -136,7 +137,7 @@ func TestPersonIdValidation(t *testing.T) { sut.HostSchema = "https" sut.Path = "api/v1/activitypub/user-id" sut.Host = "an.other.host" - sut.HostPort = 0 + sut.HostPort = "0" 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]" { t.Errorf("validation error expected but was: %v\n", sut.Validate()[0]) diff --git a/modules/forgefed/nodeinfo.go b/modules/forgefed/nodeinfo.go index 9bd142e3f3..09a9b33c6c 100644 --- a/modules/forgefed/nodeinfo.go +++ b/modules/forgefed/nodeinfo.go @@ -10,10 +10,10 @@ import ( func (id ActorID) AsWellKnownNodeInfoURI() string { wellKnownPath := ".well-known/nodeinfo" var result string - if id.HostPort == 0 { + if id.HostPort == "0" { result = fmt.Sprintf("%s://%s/%s", id.HostSchema, id.Host, wellKnownPath) } else { - result = fmt.Sprintf("%s://%s:%d/%s", id.HostSchema, id.Host, id.HostPort, wellKnownPath) + result = fmt.Sprintf("%s://%s:%s/%s", id.HostSchema, id.Host, id.HostPort, wellKnownPath) } return result } diff --git a/modules/validation/validatable.go b/modules/validation/validatable.go index 6a52edc4f6..94b5cc135c 100644 --- a/modules/validation/validatable.go +++ b/modules/validation/validatable.go @@ -53,10 +53,6 @@ func ValidateNotEmpty(value any, name string) []string { if v.IsZero() { isValid = false } - case uint16: - if v == 0 { - isValid = false - } case int64: if v == 0 { isValid = false diff --git a/services/federation/federation_service.go b/services/federation/federation_service.go index 774815cbef..4980ede90e 100644 --- a/services/federation/federation_service.go +++ b/services/federation/federation_service.go @@ -124,7 +124,7 @@ func CreateFederationHostFromAP(ctx context.Context, actorID fm.ActorID) (*forge if err != nil { return nil, err } - result, err := forgefed.NewFederationHost(actorID.Host, nodeInfo, actorID.Port, actorID.Schema) + result, err := forgefed.NewFederationHost(actorID.Host, nodeInfo, actorID.HostPort, actorID.HostSchema) if err != nil { return nil, err }