git@cosmocr.at/gitweb.git @ main · summary refs log
main / internal / auth / authz_test.go /
internal/auth/authz_test.go · 3.3 KiB · raw
view: SourceMarkdown ☑ force

package auth

import ( "os" "path/filepath" "testing"

"gitweb/internal/store"

)

// writeTree writes files (path -> content) under a fresh temp root and returns a // LocalStore over it. func writeTree(t *testing.T, files map[string]string) *store.LocalStore { t.Helper() root := t.TempDir() for p, content := range files { full := filepath.Join(root, filepath.FromSlash(p)) if err := os.MkdirAll(filepath.Dir(full), 0o755); err != nil { t.Fatal(err) } if err := os.WriteFile(full, []byte(content), 0o644); err != nil { t.Fatal(err) } } return store.NewLocalStore(root) }

// checker reduces the boilerplate of asserting CanRead/CanWrite outcomes. type checker struct { t *testing.T a *Authorizer }

func (c checker) read(name, user, p string, want bool) { c.t.Helper() got, err := c.a.CanRead(user, p) if err != nil { c.t.Fatalf("%s: CanRead error: %v", name, err) } if got != want { c.t.Errorf("%s: CanRead(%q) = %v, want %v", name, user, got, want) } }

func (c checker) write(name, user, p string, want bool) { c.t.Helper() got, err := c.a.CanWrite(user, p) if err != nil { c.t.Fatalf("%s: CanWrite error: %v", name, err) } if got != want { c.t.Errorf("%s: CanWrite(%q) = %v, want %v", name, user, got, want) } }

func TestAuthorizerPublicRepo(t testing.T) { const owner = "u@d.com" repo := owner + "/public.git" st := writeTree(t, map[string]string{ repo + "/HEAD": "ref: refs/heads/main\n", repo + "/Access": "read,list: all\n: " + owner + "\n", }) c := checker{t, NewAuthorizer(st)}

c.read("anon", "", repo, true)
c.read("stranger", "x@other.com", repo, true)
c.read("owner", owner, repo, true)
c.write("anon", "", repo, false)
c.write("owner", owner, repo, true)
c.write("stranger", "x@other.com", repo, false)

}

func TestAuthorizerPrivateRepo(t testing.T) { const owner = "u@d.com" repo := owner + "/private.git" st := writeTree(t, map[string]string{ repo + "/HEAD": "ref: refs/heads/main\n", repo + "/Access": ": " + owner + "\nread,write: w@d.com\n", }) c := checker{t, NewAuthorizer(st)}

c.read("anon", "", repo, false)
c.read("collaborator", "w@d.com", repo, true)
c.read("stranger", "x@other.com", repo, false)
c.write("collaborator", "w@d.com", repo, true)
c.write("stranger", "x@other.com", repo, false)
c.write("owner", owner, repo, true)

}

// A private Access file inside the repo overrides a public one on the parent // directory (nearest ancestor wins). func TestAuthorizerNearestAccessWins(t testing.T) { const owner = "u@d.com" repo := owner + "/proj/secret.git" st := writeTree(t, map[string]string{ owner + "/proj/Access": "read,list: all\n: " + owner + "\n", repo + "/HEAD": "ref: refs/heads/main\n", repo + "/Access": "*: " + owner + "\n", }) c := checker{t, NewAuthorizer(st)}

c.read("anon", "", repo, false)
c.read("owner", owner, repo, true)

}

// With no Access file anywhere, only the owner has any rights. func TestAuthorizerNoAccessOwnerOnly(t *testing.T) { const owner = "u@d.com" repo := owner + "/bare.git" st := writeTree(t, map[string]string{ repo + "/HEAD": "ref: refs/heads/main\n", }) c := checker{t, NewAuthorizer(st)}

c.read("owner", owner, repo, true)
c.read("anon", "", repo, false)
c.read("stranger", "x@other.com", repo, false)
c.write("owner", owner, repo, true)

}