further steps

This commit is contained in:
zam 2025-03-31 19:43:30 +02:00
parent c86d436261
commit d2b4b924d3
6 changed files with 74 additions and 89 deletions

View file

@ -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,

View file

@ -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
}

View file

@ -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])

View file

@ -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
}

View file

@ -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

View file

@ -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
}