internal/validate: relocate from app
All checks were successful
Test / Create distribution (push) Successful in 37s
Test / Sandbox (push) Successful in 2m23s
Test / Hakurei (push) Successful in 3m9s
Test / Hpkg (push) Successful in 4m7s
Test / Sandbox (race detector) (push) Successful in 4m11s
Test / Hakurei (race detector) (push) Successful in 5m1s
Test / Flake checks (push) Successful in 1m30s
All checks were successful
Test / Create distribution (push) Successful in 37s
Test / Sandbox (push) Successful in 2m23s
Test / Hakurei (push) Successful in 3m9s
Test / Hpkg (push) Successful in 4m7s
Test / Sandbox (race detector) (push) Successful in 4m11s
Test / Hakurei (race detector) (push) Successful in 5m1s
Test / Flake checks (push) Successful in 1m30s
These are free of the dispatcher from internal/app. This change relocates them into their own package. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
8
internal/validate/sysconf.go
Normal file
8
internal/validate/sysconf.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package validate
|
||||
|
||||
//#include <unistd.h>
|
||||
import "C"
|
||||
|
||||
const SC_LOGIN_NAME_MAX = C._SC_LOGIN_NAME_MAX
|
||||
|
||||
func Sysconf(name C.int) int { return int(C.sysconf(name)) }
|
||||
21
internal/validate/sysconf_test.go
Normal file
21
internal/validate/sysconf_test.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package validate_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"hakurei.app/internal/validate"
|
||||
)
|
||||
|
||||
const (
|
||||
_POSIX_LOGIN_NAME_MAX = 9
|
||||
)
|
||||
|
||||
func TestSysconf(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("LOGIN_NAME_MAX", func(t *testing.T) {
|
||||
if got := validate.Sysconf(validate.SC_LOGIN_NAME_MAX); got < _POSIX_LOGIN_NAME_MAX {
|
||||
t.Errorf("sysconf(_SC_LOGIN_NAME_MAX): %d < _POSIX_LOGIN_NAME_MAX", got)
|
||||
}
|
||||
})
|
||||
}
|
||||
12
internal/validate/username.go
Normal file
12
internal/validate/username.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package validate
|
||||
|
||||
import "regexp"
|
||||
|
||||
// nameRegex is the default NAME_REGEX value from adduser.
|
||||
var nameRegex = regexp.MustCompilePOSIX(`^[a-zA-Z][a-zA-Z0-9_-]*\$?$`)
|
||||
|
||||
// IsValidUsername returns whether the argument is a valid username.
|
||||
func IsValidUsername(username string) bool {
|
||||
return len(username) < Sysconf(SC_LOGIN_NAME_MAX) &&
|
||||
nameRegex.MatchString(username)
|
||||
}
|
||||
30
internal/validate/username_test.go
Normal file
30
internal/validate/username_test.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package validate_test
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"hakurei.app/internal/validate"
|
||||
)
|
||||
|
||||
func TestIsValidUsername(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("long", func(t *testing.T) {
|
||||
if validate.IsValidUsername(strings.Repeat("a", validate.Sysconf(validate.SC_LOGIN_NAME_MAX))) {
|
||||
t.Errorf("IsValidUsername unexpected true")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("regexp", func(t *testing.T) {
|
||||
if validate.IsValidUsername("0") {
|
||||
t.Errorf("IsValidUsername unexpected true")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("valid", func(t *testing.T) {
|
||||
if !validate.IsValidUsername("alice") {
|
||||
t.Errorf("IsValidUsername unexpected false")
|
||||
}
|
||||
})
|
||||
}
|
||||
20
internal/validate/validate.go
Normal file
20
internal/validate/validate.go
Normal file
@@ -0,0 +1,20 @@
|
||||
// Package validate provides functions for validating string values of various types.
|
||||
package validate
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// DeepContainsH returns whether basepath is equivalent to or is the parent of targpath.
|
||||
//
|
||||
// This is used for path hiding warning behaviour, the purpose of which is to improve
|
||||
// user experience and is *not* a security feature and must not be treated as such.
|
||||
func DeepContainsH(basepath, targpath string) (bool, error) {
|
||||
const upper = ".." + string(filepath.Separator)
|
||||
|
||||
rel, err := filepath.Rel(basepath, targpath)
|
||||
return err == nil &&
|
||||
rel != ".." &&
|
||||
!strings.HasPrefix(rel, upper), err
|
||||
}
|
||||
90
internal/validate/validate_test.go
Normal file
90
internal/validate/validate_test.go
Normal file
@@ -0,0 +1,90 @@
|
||||
package validate_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"hakurei.app/internal/validate"
|
||||
)
|
||||
|
||||
func TestDeepContainsH(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
basepath string
|
||||
targpath string
|
||||
want bool
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "equal abs",
|
||||
basepath: "/run",
|
||||
targpath: "/run",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "equal rel",
|
||||
basepath: "./run",
|
||||
targpath: "run",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "contains abs",
|
||||
basepath: "/run",
|
||||
targpath: "/run/dbus",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "inverse contains abs",
|
||||
basepath: "/run/dbus",
|
||||
targpath: "/run",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "contains rel",
|
||||
basepath: "../run",
|
||||
targpath: "../run/dbus",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "inverse contains rel",
|
||||
basepath: "../run/dbus",
|
||||
targpath: "../run",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "weird abs",
|
||||
basepath: "/run/dbus",
|
||||
targpath: "/run/dbus/../current-system",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "weird rel",
|
||||
basepath: "../run/dbus",
|
||||
targpath: "../run/dbus/../current-system",
|
||||
want: false,
|
||||
},
|
||||
|
||||
{
|
||||
name: "invalid mix",
|
||||
basepath: "/run",
|
||||
targpath: "./run",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
if got, err := validate.DeepContainsH(tc.basepath, tc.targpath); (err != nil) != tc.wantErr {
|
||||
t.Errorf("DeepContainsH: error = %v, wantErr %v", err, tc.wantErr)
|
||||
} else if got != tc.want {
|
||||
t.Errorf("DeepContainsH: = %v, want %v", got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user