1package archesrv
2
3import (
4 "fmt"
5 "net/http"
6 "testing"
7)
8
9func TestForgeServer_Collaborator_AddAndRemove(t *testing.T) {
10 s, ts := newTestServer(t)
11 _, adminClient := loginAsAdmin(t, s, ts)
12 setupRepoWithDisk(t, s, "myrepo", "private")
13
14 s.db.CreateUser("bob", "pass", false) //nolint:errcheck
15
16 resp, err := adminClient.PostForm(ts.URL+"/myrepo/settings/collaborators", map[string][]string{
17 "username": {"bob"},
18 "role": {"read"},
19 })
20 if err != nil {
21 t.Fatalf("POST collaborator: %v", err)
22 }
23 resp.Body.Close()
24 if resp.StatusCode >= 400 {
25 t.Errorf("add collaborator: got %d", resp.StatusCode)
26 }
27
28 rec, _ := s.db.GetRepo("myrepo")
29 u, _, _ := s.db.GetUserByName("bob")
30 if !s.db.CanRead(rec, u) {
31 t.Error("bob should have read access after being added as collaborator")
32 }
33
34 collabs, err := s.db.ListCollaborators(rec.ID)
35 if err != nil {
36 t.Fatalf("ListCollaborators: %v", err)
37 }
38 found := false
39 for _, c := range collabs {
40 if c.Username == "bob" {
41 found = true
42 }
43 }
44 if !found {
45 t.Error("bob should appear in collaborator list")
46 }
47
48 req, _ := http.NewRequest(http.MethodDelete,
49 fmt.Sprintf("%s/myrepo/settings/collaborators/%d", ts.URL, u.ID), nil)
50 resp2, err := adminClient.Do(req)
51 if err != nil {
52 t.Fatalf("DELETE collaborator: %v", err)
53 }
54 resp2.Body.Close()
55 if resp2.StatusCode >= 400 {
56 t.Errorf("remove collaborator: got %d", resp2.StatusCode)
57 }
58
59 rec2, _ := s.db.GetRepo("myrepo")
60 if s.db.CanRead(rec2, u) {
61 t.Error("bob should lose read access after removal")
62 }
63}
64
65func TestForgeServer_Collaborator_NonAdminCannotAdd(t *testing.T) {
66 s, ts := newTestServer(t)
67 s.db.CreateUser("admin", "adminpass", true) //nolint:errcheck
68 setupRepoWithDisk(t, s, "myrepo", "private")
69
70 alice, _ := s.db.CreateUser("alice", "pass", false)
71 rec, _ := s.db.GetRepo("myrepo")
72 s.db.SetPermission(rec.ID, alice.ID, "write") //nolint:errcheck
73
74 aliceClient := loginAs(t, ts, "alice", "pass")
75 s.db.CreateUser("bob", "pass", false) //nolint:errcheck
76
77 resp, err := aliceClient.PostForm(ts.URL+"/myrepo/settings/collaborators", map[string][]string{
78 "username": {"bob"},
79 "role": {"read"},
80 })
81 if err != nil {
82 t.Fatalf("POST collaborator: %v", err)
83 }
84 resp.Body.Close()
85 if resp.StatusCode < 400 {
86 t.Errorf("non-admin should not add collaborators, got %d", resp.StatusCode)
87 }
88}
89
90func TestForgeServer_Collaborator_WriteRoleGrantsWrite(t *testing.T) {
91 s, ts := newTestServer(t)
92 _, adminClient := loginAsAdmin(t, s, ts)
93 setupRepoWithDisk(t, s, "myrepo", "private")
94 s.db.CreateUser("writer", "pass", false) //nolint:errcheck
95
96 resp, err := adminClient.PostForm(ts.URL+"/myrepo/settings/collaborators", map[string][]string{
97 "username": {"writer"},
98 "role": {"write"},
99 })
100 if err != nil {
101 t.Fatalf("POST collaborator: %v", err)
102 }
103 resp.Body.Close()
104
105 rec, _ := s.db.GetRepo("myrepo")
106 u, _, _ := s.db.GetUserByName("writer")
107 if !s.db.CanWrite(rec, u) {
108 t.Error("writer should have write access")
109 }
110}
111
112func TestForgeServer_Collaborator_AdminRoleAllowsManagement(t *testing.T) {
113 s, ts := newTestServer(t)
114 s.db.CreateUser("siteadmin", "adminpass", true) //nolint:errcheck
115 setupRepoWithDisk(t, s, "myrepo", "private")
116
117 repoAdmin, _ := s.db.CreateUser("repoadmin", "pass", false)
118 rec, _ := s.db.GetRepo("myrepo")
119 s.db.SetPermission(rec.ID, repoAdmin.ID, "admin") //nolint:errcheck
120
121 repoAdminClient := loginAs(t, ts, "repoadmin", "pass")
122 s.db.CreateUser("target", "pass", false) //nolint:errcheck
123
124 resp, err := repoAdminClient.PostForm(ts.URL+"/myrepo/settings/collaborators", map[string][]string{
125 "username": {"target"},
126 "role": {"read"},
127 })
128 if err != nil {
129 t.Fatalf("POST collaborator: %v", err)
130 }
131 resp.Body.Close()
132 if resp.StatusCode >= 400 {
133 t.Errorf("repo admin should be able to add collaborators, got %d", resp.StatusCode)
134 }
135}