Files

155 lines
4.5 KiB
Go

package auth
import (
"testing"
"time"
jwt "github.com/golang-jwt/jwt/v4"
)
func TestTokenUsesConfiguredSecretAndTimeout(t *testing.T) {
const secret = "test-secret"
before := time.Now().Add(2 * time.Minute).Unix()
raw, err := NewToken("alice", 2, secret)
if err != nil {
t.Fatal(err)
}
var claims jwtClaims
token, err := jwt.ParseWithClaims(raw, &claims, func(t *jwt.Token) (interface{}, error) {
return []byte(secret), nil
})
if err != nil || !token.Valid {
t.Fatalf("token should validate with configured secret: %v", err)
}
if claims.ExpiresAt < before-1 || claims.ExpiresAt > before+1 {
t.Fatalf("unexpected expiration: %v", claims.ExpiresAt)
}
if _, err := GetAccFromToken(raw, "wrong-secret"); err == nil {
t.Fatal("token validated with wrong secret")
}
}
func TestMatchPath(t *testing.T) {
cases := []struct {
pattern, path string
want bool
}{
{"test", "test", true},
{"test", "test/sub", true},
{"test", "testing", false},
{"test*", "test2", true},
{"test*", "test/sub", true},
{"te?t", "test", true},
{"te?t", "teat", true},
{"te?t", "te", false},
{"test/sub", "test/sub/file", true},
{"test/sub", "test/other/file", false},
}
for _, tc := range cases {
if got := MatchPath(tc.pattern, tc.path); got != tc.want {
t.Errorf("MatchPath(%q,%q)=%v want %v", tc.pattern, tc.path, got, tc.want)
}
}
}
func TestMaskForLongestRule(t *testing.T) {
a := &Account{Mask: Read, Rules: []PathRule{
{Dir: "team", Mask: Write},
{Dir: "team/private", Mask: None},
}}
if got := a.MaskFor("team/file"); got != Write {
t.Fatalf("team/file mask=%d", got)
}
if got := a.MaskFor("team/private/file"); got != None {
t.Fatalf("team/private/file mask=%d", got)
}
if got := a.MaskFor("other/file"); got != Read {
t.Fatalf("other/file mask=%d", got)
}
}
func TestParseRulesGuestDefaultAndOverride(t *testing.T) {
m, err := ParseRules(nil)
if err != nil || m.Guest.Mask != (Read|Write|Delete) {
t.Fatalf("unexpected guest default: %#v err=%v", m.Guest, err)
}
m, err = ParseRules([]string{"::r|demo:pw:rw"})
if err != nil || m.Guest.Mask != Read || m.Accounts["demo"].Mask != (Read|Write) {
t.Fatalf("unexpected parsed masks: %#v %#v err=%v", m.Guest, m.Accounts["demo"], err)
}
}
func TestParseRulesAdminAccount(t *testing.T) {
m, err := ParseRules([]string{"::r|admin:secret:rw"})
if err != nil {
t.Fatal(err)
}
if !m.Accounts["admin"].Admin {
t.Fatal("admin account should be marked admin")
}
}
func TestSectionRuleSemantics(t *testing.T) {
a := &Account{Mask: Delete, Rules: []PathRule{
{Dir: "private", Mask: None, Deny: true},
{Dir: "readonly", Mask: ParseMask("r"), ChildrenOnly: true},
{Dir: "writable", Mask: ParseMask("w"), ChildrenOnly: true},
{Dir: "full", Mask: ParseMask("d"), ChildrenOnly: true},
}}
if got := a.MaskFor("private"); got != None {
t.Fatalf("private=%v", got)
}
if got := a.MaskFor("private/file"); got != None {
t.Fatalf("private/file=%v", got)
}
if got := a.MaskForEntry("readonly"); got != Delete {
t.Fatalf("readonly entry=%v", got)
}
if got := a.MaskFor("readonly/file"); got != Read {
t.Fatalf("readonly/file=%v", got)
}
if got := a.MaskForEntry("writable"); got != Delete {
t.Fatalf("writable entry=%v", got)
}
if got := a.MaskFor("writable/file"); got != ParseMask("w") {
t.Fatalf("writable/file=%v", got)
}
if got := a.MaskForEntry("full"); got != Delete {
t.Fatalf("full entry=%v", got)
}
if got := a.MaskFor("full/file"); got != (Read | Write | Delete) {
t.Fatalf("full/file=%v", got)
}
if got := a.MaskForEntry("readonly"); got != Delete {
t.Fatalf("readonly entry mask=%v", got)
}
if got := a.MaskForEntry("private"); got != None {
t.Fatalf("private entry mask=%v", got)
}
}
func TestSectionRuleSamePathPriority(t *testing.T) {
a := &Account{Mask: Delete, Rules: []PathRule{
{Dir: "secret", Mask: None, Deny: true},
{Dir: "secret", Mask: ParseMask("r"), ChildrenOnly: true},
{Dir: "secret", Mask: ParseMask("w"), ChildrenOnly: true},
{Dir: "secret", Mask: ParseMask("d"), ChildrenOnly: true},
}}
if got := a.MaskFor("secret/file"); got != ParseMask("d") {
t.Fatalf("same-path rule priority=%v", got)
}
}
func TestWildcardSectionRules(t *testing.T) {
a := &Account{Mask: Read, Rules: []PathRule{{Dir: "project-*", Mask: Write, ChildrenOnly: true}}}
if got := a.MaskFor("project-one/file"); got != Write {
t.Fatalf("project-one/file=%v", got)
}
if got := a.MaskFor("project-two/file"); got != Write {
t.Fatalf("project-two/file=%v", got)
}
if got := a.MaskFor("project/file"); got != Read {
t.Fatalf("project/file=%v", got)
}
}