make validate more compact

This commit is contained in:
Michael Jerger 2023-12-08 19:41:22 +01:00
parent be4d3544ae
commit 3151c8fe81
3 changed files with 73 additions and 32 deletions

View file

@ -19,12 +19,13 @@ type Validatable interface { // ToDo: What is the right package for this interfa
} }
type ActorId struct { type ActorId struct {
userId string userId string
source string source string
schema string schema string
path string path string
host string host string
port string // optional port string
unvalidatedInput string
} }
func validate_is_not_empty(str string) error { func validate_is_not_empty(str string) error {
@ -37,30 +38,24 @@ func validate_is_not_empty(str string) error {
/* /*
Validate collects error strings in a slice and returns this Validate collects error strings in a slice and returns this
*/ */
func (a ActorId) Validate() []string { func (value ActorId) Validate() []string {
var result = []string{}
result = append(result, validation.ValidateNotEmpty(value.userId, "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")...)
var err = []string{} result = append(result, validation.ValidateOneOf(value.source, []string{"forgejo", "gitea"})...)
switch value.source {
if res := validation.ValidateNotEmpty(a.schema, "schema"); res != nil {
err = append(err, res.Error())
}
if res := validate_is_not_empty(a.host); res != nil {
err = append(err, strings.Join([]string{res.Error(), "for host field"}, " "))
}
switch a.source {
case "forgejo", "gitea": case "forgejo", "gitea":
if !strings.Contains(a.path, "api/v1/activitypub/user-id") && if !strings.Contains(value.path, "api/v1/activitypub/user-id") {
!strings.Contains(a.path, "api/v1/activitypub/repository-id") { result = append(result, fmt.Sprintf("path has to be a api path"))
err = append(err, fmt.Errorf("the Path to the API was invalid: ---%v---", a.path).Error())
} }
default:
err = append(err, fmt.Errorf("currently only forgeo and gitea sources are allowed from actor id").Error())
} }
return err return result
} }
/* /*
@ -173,5 +168,30 @@ func NewActorId(uri string, source string) (ActorId, error) {
if !validation.IsValidExternalURL(uri) { if !validation.IsValidExternalURL(uri) {
return ActorId{}, fmt.Errorf("uri %s is not a valid external url", uri) return ActorId{}, fmt.Errorf("uri %s is not a valid external url", uri)
} }
return ActorId{}, nil
validatedUri, _ := url.Parse(uri)
pathWithUserID := strings.Split(validatedUri.Path, "/")
if containsEmptyString(pathWithUserID) {
pathWithUserID = removeEmptyStrings(pathWithUserID)
}
length := len(pathWithUserID)
pathWithoutUserID := strings.Join(pathWithUserID[0:length-1], "/")
userId := pathWithUserID[length-1]
actorId := ActorId{
userId: userId,
source: source,
schema: validatedUri.Scheme,
host: validatedUri.Hostname(),
path: pathWithoutUserID,
port: validatedUri.Port(),
unvalidatedInput: uri,
}
if valid, err := actorId.IsValid(); !valid {
return ActorId{}, err
}
return actorId, nil
} }

View file

@ -130,11 +130,23 @@ func TestShouldThrowErrorOnInvalidInput(t *testing.T) {
} }
_, err = NewActorId("./api/v1/something", "forgejo") _, err = NewActorId("./api/v1/something", "forgejo")
if err == nil { if err == nil {
t.Errorf("relative uris are not alowed.") t.Errorf("relative uris are not alowed")
}
_, err = NewActorId("http://1.2.3.4/api/v1/something", "forgejo")
if err == nil {
t.Errorf("uri may not be ip-4 based")
}
_, err = NewActorId("http:///[fe80::1ff:fe23:4567:890a%25eth0]/api/v1/something", "forgejo")
if err == nil {
t.Errorf("uri may not be ip-6 based")
}
_, err = NewActorId("https://codeberg.org/api/v1/activitypub/../activitypub/user-id/12345", "forgejo")
if err == nil {
t.Errorf("uri may not contain relative path elements")
} }
_, err = NewActorId("https://an.other.host/api/v1/activitypub/person-id/1", "forgejo") _, err = NewActorId("https://an.other.host/api/v1/activitypub/user-id/1", "forgejo")
if err != nil { if err != nil {
t.Errorf("this uri should be valid") t.Errorf("this uri should be valid but was: %v", err)
} }
} }

View file

@ -136,9 +136,18 @@ func IsValidUsername(name string) bool {
return validUsernamePatternWithoutDots.MatchString(name) && !invalidUsernamePattern.MatchString(name) return validUsernamePatternWithoutDots.MatchString(name) && !invalidUsernamePattern.MatchString(name)
} }
func ValidateNotEmpty(value string, fieldName string) error { func ValidateNotEmpty(value string, fieldName string) []string {
if value == "" { if value == "" {
return fmt.Errorf("Field %v may not be empty.", fieldName) return []string{fmt.Sprintf("Field %v may not be empty.", fieldName)}
} }
return nil return []string{}
}
func ValidateOneOf(value string, allowed []string) []string {
for _, allowedElem := range allowed {
if value == allowedElem {
return []string{}
}
}
return []string{fmt.Sprintf("Value %v is not contained in allowed values [%v]", value, allowed)}
} }