internal/policy/access_test.go

e4fa4034379ae93e3cf6f1084ed577a7e02b530c
gitbay/internal/policy/access_test.go history · blame · raw

112 lines · 3691 bytes

  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:7:ro", "a/b", false, false}, // deploy keys never pass the account path
 59		{"", "a/b", false, false},
 60	}
 61	for _, tc := range cases {
 62		if got := ScopeAllowsGit(tc.scope, tc.repo, tc.write); got != tc.want {
 63			t.Errorf("ScopeAllowsGit(%q, %q, write=%v) = %v, want %v", tc.scope, tc.repo, tc.write, got, tc.want)
 64		}
 65	}
 66}
 67
 68func TestDeployScopeAllows(t *testing.T) {
 69	cases := []struct {
 70		scope  string
 71		repoID int64
 72		write  bool
 73		want   bool
 74	}{
 75		{"deploy:7:ro", 7, false, true},
 76		{"deploy:7:ro", 7, true, false},
 77		{"deploy:7:rw", 7, true, true},
 78		{"deploy:7:rw", 8, false, false}, // wrong repo
 79		{"deploy:7", 7, false, false},    // malformed
 80		{"full", 7, false, false},        // not a deploy scope
 81	}
 82	for _, tc := range cases {
 83		if got := DeployScopeAllows(tc.scope, tc.repoID, tc.write); got != tc.want {
 84			t.Errorf("DeployScopeAllows(%q, %d, write=%v) = %v, want %v", tc.scope, tc.repoID, tc.write, got, tc.want)
 85		}
 86	}
 87}
 88
 89func TestCheckPush(t *testing.T) {
 90	repo := store.Repo{Settings: store.RepoSettings{ProtectedBranches: []string{"main"}}}
 91	cases := []struct {
 92		name    string
 93		updates []RefUpdate
 94		denied  bool
 95	}{
 96		{"normal push to protected", []RefUpdate{{Ref: "refs/heads/main"}}, false},
 97		{"force to protected", []RefUpdate{{Ref: "refs/heads/main", IsForce: true}}, true},
 98		{"delete protected", []RefUpdate{{Ref: "refs/heads/main", IsDelete: true}}, true},
 99		{"force to unprotected", []RefUpdate{{Ref: "refs/heads/dev", IsForce: true}}, false},
100		{"delete unprotected", []RefUpdate{{Ref: "refs/heads/dev", IsDelete: true}}, false},
101		{"mr namespace", []RefUpdate{{Ref: "refs/merge-requests/1/head"}}, true},
102		{"tag alongside protected", []RefUpdate{{Ref: "refs/tags/v1"}, {Ref: "refs/heads/main"}}, false},
103	}
104	for _, tc := range cases {
105		t.Run(tc.name, func(t *testing.T) {
106			msg := CheckPush(repo, tc.updates)
107			if (msg != "") != tc.denied {
108				t.Errorf("CheckPush = %q, denied should be %v", msg, tc.denied)
109			}
110		})
111	}
112}