krz/gitbay

A CLI-first git forge.

clone: git clone https://gitbay.org/krz/gitbay.git

repo-descriptions: internal/policy/access_test.go · raw

 1package policy
 2
 3import (
 4	"testing"
 5
 6	"gitbay.org/gitbay/internal/store"
 7)
 8
 9var (
10	owner    = store.User{ID: 1, Username: "alice"}
11	stranger = store.User{ID: 2, Username: "bob"}
12	priv     = store.Repo{ID: 10, OwnerKind: "user", OwnerID: 1, OwnerName: "alice", Name: "p", Visibility: "private"}
13	pub      = store.Repo{ID: 11, OwnerKind: "user", OwnerID: 1, OwnerName: "alice", Name: "q", Visibility: "public"}
14)
15
16func TestAccessMatrix(t *testing.T) {
17	cases := []struct {
18		name  string
19		user  store.User
20		repo  store.Repo
21		grant string
22		read  bool
23		write bool
24		admin bool
25	}{
26		{"owner private", owner, priv, "", true, true, true},
27		{"stranger private no grant", stranger, priv, "", false, false, false},
28		{"stranger private read", stranger, priv, "read", true, false, false},
29		{"stranger private write", stranger, priv, "write", true, true, false},
30		{"stranger private admin", stranger, priv, "admin", true, true, true},
31		{"stranger public no grant", stranger, pub, "", true, false, false},
32		{"stranger public write", stranger, pub, "write", true, true, false},
33	}
34	for _, tc := range cases {
35		t.Run(tc.name, func(t *testing.T) {
36			if got := CanRead(tc.user, tc.repo, tc.grant); got != tc.read {
37				t.Errorf("CanRead = %v, want %v", got, tc.read)
38			}
39			if got := CanWrite(tc.user, tc.repo, tc.grant); got != tc.write {
40				t.Errorf("CanWrite = %v, want %v", got, tc.write)
41			}
42			if got := CanAdmin(tc.user, tc.repo, tc.grant); got != tc.admin {
43				t.Errorf("CanAdmin = %v, want %v", got, tc.admin)
44			}
45		})
46	}
47}
48
49func TestScopeAllowsGit(t *testing.T) {
50	cases := []struct {
51		scope string
52		repo  string
53		write bool
54		want  bool
55	}{
56		{"full", "a/b", true, true},
57		{"git", "a/b", true, true},
58		{"deploy:a/b:ro", "a/b", false, true},
59		{"deploy:a/b:ro", "a/b", true, false},
60		{"deploy:a/b:rw", "a/b", true, true},
61		{"deploy:a/b:rw", "a/c", false, false}, // wrong repo
62		{"deploy:a/b", "a/b", false, false},    // malformed
63		{"", "a/b", false, false},
64	}
65	for _, tc := range cases {
66		if got := ScopeAllowsGit(tc.scope, tc.repo, tc.write); got != tc.want {
67			t.Errorf("ScopeAllowsGit(%q, %q, write=%v) = %v, want %v", tc.scope, tc.repo, tc.write, got, tc.want)
68		}
69	}
70}
71
72func TestCheckPush(t *testing.T) {
73	repo := store.Repo{Settings: store.RepoSettings{ProtectedBranches: []string{"main"}}}
74	cases := []struct {
75		name    string
76		updates []RefUpdate
77		denied  bool
78	}{
79		{"normal push to protected", []RefUpdate{{Ref: "refs/heads/main"}}, false},
80		{"force to protected", []RefUpdate{{Ref: "refs/heads/main", IsForce: true}}, true},
81		{"delete protected", []RefUpdate{{Ref: "refs/heads/main", IsDelete: true}}, true},
82		{"force to unprotected", []RefUpdate{{Ref: "refs/heads/dev", IsForce: true}}, false},
83		{"delete unprotected", []RefUpdate{{Ref: "refs/heads/dev", IsDelete: true}}, false},
84		{"mr namespace", []RefUpdate{{Ref: "refs/merge-requests/1/head"}}, true},
85		{"tag alongside protected", []RefUpdate{{Ref: "refs/tags/v1"}, {Ref: "refs/heads/main"}}, false},
86	}
87	for _, tc := range cases {
88		t.Run(tc.name, func(t *testing.T) {
89			msg := CheckPush(repo, tc.updates)
90			if (msg != "") != tc.denied {
91				t.Errorf("CheckPush = %q, denied should be %v", msg, tc.denied)
92			}
93		})
94	}
95}