- commit
- ac244f8
- parent
- 837fe8a
- author
- Eric Bower
- date
- 2024-11-06 10:01:23 -0500 EST
fix: repo owners have full perms
6 files changed,
+92,
-45
+10,
-9
1@@ -9,16 +9,16 @@ ID RepoID Name Status Patchsets User Date
2 PR submitted! Use the ID for interacting with this PR.
3 Info
4 ====
5-URL: https://localhost/prs/8
6+URL: https://localhost/prs/9
7 Repo: contributor/bin
8
9 ID Name Status Date
10-8 feat: lets build an rnn [open]
11+9 feat: lets build an rnn [open]
12
13 Patchsets
14 ====
15 ID Type User Date
16-ps-12 contributor
17+ps-13 contributor
18
19 Patches from latest patchset
20 ====
21@@ -29,21 +29,22 @@ Idx Title Commit Author Date
22
23 [TestE2E - 3]
24 ID RepoID Name Status Patchsets User Date
25-8 contributor/bin feat: lets build an rnn [open] 1 contributor
26-7 admin/ai feat: lets build an rnn [accepted] 2 contributor
27+9 contributor/bin feat: lets build an rnn [open] 1 contributor
28+8 admin/ai feat: lets build an rnn [accepted] 2 contributor
29+7 contributor/ai feat: lets build an rnn [accepted] 1 admin
30 6 contributor/test Closed patch with review [closed] 2 contributor
31 5 contributor/test Accepted patch with review [accepted] 2 contributor
32 4 contributor/test Reviewed patch [reviewed] 2 contributor
33 3 contributor/test Closed patch (contributor) [closed] 1 contributor
34 2 contributor/test Closed patch (admin) [closed] 1 contributor
35-1 contributor/test Accepted patch [accepted] 1 contributor
36+1 admin/test Accepted patch [accepted] 1 contributor
37
38 ---
39
40 [TestE2E - 4]
41 RepoID PrID PatchsetID Event Created Data
42-admin/ai 7 ps-10 pr_created
43-admin/ai 7 ps-11 pr_patchset_added
44-admin/ai 7 pr_status_changed {"status":"accepted"}
45+admin/ai 8 ps-11 pr_created
46+admin/ai 8 ps-12 pr_patchset_added
47+admin/ai 8 pr_status_changed {"status":"accepted"}
48
49 ---
+15,
-2
1@@ -110,8 +110,12 @@ type PrAcl struct {
2 CanDelete bool
3 }
4
5-func (be *Backend) GetPatchRequestAcl(prq *PatchRequest, requester *User) *PrAcl {
6+func (be *Backend) GetPatchRequestAcl(repo *Repo, prq *PatchRequest, requester *User) *PrAcl {
7 acl := &PrAcl{}
8+ if requester == nil {
9+ return acl
10+ }
11+
12 pubkey, err := be.PubkeyToPublicKey(requester.Pubkey)
13 if err != nil {
14 return acl
15@@ -126,14 +130,23 @@ func (be *Backend) GetPatchRequestAcl(prq *PatchRequest, requester *User) *PrAcl
16 return acl
17 }
18
19+ // repo owner can do it all
20+ if repo.UserID == requester.ID {
21+ acl.CanModify = true
22+ acl.CanReview = true
23+ acl.CanDelete = true
24+ return acl
25+ }
26+
27 // pr creator have special priv
28- if requester != nil && be.IsPrOwner(prq.UserID, requester.ID) {
29+ if be.IsPrOwner(prq.UserID, requester.ID) {
30 acl.CanModify = true
31 acl.CanReview = false
32 acl.CanDelete = true
33 return acl
34 }
35
36+ // otherwise no perms
37 acl.CanModify = false
38 acl.CanReview = false
39 acl.CanDelete = false
M
cli.go
+39,
-14
1@@ -212,7 +212,6 @@ Here's how it works:
2 isPubkey := cCtx.Bool("pubkey")
3 prID := cCtx.Int64("pr")
4 repoNs := cCtx.String("repo")
5- fmt.Println("ZZZZ", repoNs)
6 var eventLogs []*EventLog
7 if isPubkey {
8 eventLogs, err = pr.GetEventLogsByUserID(user.ID)
9@@ -650,7 +649,13 @@ Here's how it works:
10 return err
11 }
12
13- acl := be.GetPatchRequestAcl(prq, user)
14+ repo, err := pr.GetRepoByID(prq.RepoID)
15+ if err != nil {
16+ return err
17+ }
18+
19+ acl := be.GetPatchRequestAcl(repo, prq, user)
20+ fmt.Println(repo.UserID, user.ID)
21 if !acl.CanReview {
22 return fmt.Errorf("you are not authorized to accept a PR")
23 }
24@@ -683,22 +688,27 @@ Here's how it works:
25 return err
26 }
27
28- patchReq, err := pr.GetPatchRequestByID(prID)
29+ prq, err := pr.GetPatchRequestByID(prID)
30 if err != nil {
31 return err
32 }
33
34- patchUser, err := pr.GetUserByID(patchReq.UserID)
35+ patchUser, err := pr.GetUserByID(prq.UserID)
36 if err != nil {
37 return err
38 }
39
40- acl := be.GetPatchRequestAcl(patchReq, patchUser)
41+ repo, err := pr.GetRepoByID(prq.RepoID)
42+ if err != nil {
43+ return err
44+ }
45+
46+ acl := be.GetPatchRequestAcl(repo, prq, patchUser)
47 if !acl.CanModify {
48 return fmt.Errorf("you are not authorized to change PR status")
49 }
50
51- if patchReq.Status == "closed" {
52+ if prq.Status == "closed" {
53 return fmt.Errorf("PR has already been closed")
54 }
55
56@@ -711,7 +721,7 @@ Here's how it works:
57 if err != nil {
58 return err
59 }
60- wish.Printf(sesh, "Closed PR %s (#%d)\n", patchReq.Name, patchReq.ID)
61+ wish.Printf(sesh, "Closed PR %s (#%d)\n", prq.Name, prq.ID)
62 return prSummary(be, pr, sesh, prID)
63 },
64 },
65@@ -731,22 +741,27 @@ Here's how it works:
66 return err
67 }
68
69- patchReq, err := pr.GetPatchRequestByID(prID)
70+ prq, err := pr.GetPatchRequestByID(prID)
71+ if err != nil {
72+ return err
73+ }
74+
75+ patchUser, err := pr.GetUserByID(prq.UserID)
76 if err != nil {
77 return err
78 }
79
80- patchUser, err := pr.GetUserByID(patchReq.UserID)
81+ repo, err := pr.GetRepoByID(prq.RepoID)
82 if err != nil {
83 return err
84 }
85
86- acl := be.GetPatchRequestAcl(patchReq, patchUser)
87+ acl := be.GetPatchRequestAcl(repo, prq, patchUser)
88 if !acl.CanModify {
89 return fmt.Errorf("you are not authorized to change PR status")
90 }
91
92- if patchReq.Status == "open" {
93+ if prq.Status == "open" {
94 return fmt.Errorf("PR is already open")
95 }
96
97@@ -757,7 +772,7 @@ Here's how it works:
98
99 err = pr.UpdatePatchRequestStatus(prID, user.ID, "open")
100 if err == nil {
101- wish.Printf(sesh, "Reopened PR %s (#%d)\n", patchReq.Name, patchReq.ID)
102+ wish.Printf(sesh, "Reopened PR %s (#%d)\n", prq.Name, prq.ID)
103 }
104 return prSummary(be, pr, sesh, prID)
105 },
106@@ -787,7 +802,12 @@ Here's how it works:
107 return err
108 }
109
110- acl := be.GetPatchRequestAcl(prq, user)
111+ repo, err := pr.GetRepoByID(prq.RepoID)
112+ if err != nil {
113+ return err
114+ }
115+
116+ acl := be.GetPatchRequestAcl(repo, prq, user)
117 if !acl.CanModify {
118 return fmt.Errorf("you are not authorized to change PR")
119 }
120@@ -853,7 +873,12 @@ Here's how it works:
121 isAccept := cCtx.Bool("accept")
122 isClose := cCtx.Bool("close")
123
124- acl := be.GetPatchRequestAcl(prq, user)
125+ repo, err := pr.GetRepoByID(prq.RepoID)
126+ if err != nil {
127+ return err
128+ }
129+
130+ acl := be.GetPatchRequestAcl(repo, prq, user)
131 if !acl.CanModify {
132 return fmt.Errorf("you are not authorized to add patchsets to pr")
133 }
+23,
-15
1@@ -29,11 +29,11 @@ func testSingleTenantE2E(t *testing.T) {
2 time.Sleep(time.Millisecond * 100)
3 _, err := suite.userKey.Cmd(suite.patch, "pr create test")
4 if err == nil {
5- t.Error("user should not be able to create a PR")
6+ t.Fatal("user should not be able to create a PR")
7 }
8 suite.adminKey.MustCmd(suite.patch, "pr create test")
9
10- // Snapshot test ls command
11+ t.Log("Snapshot test ls command")
12 actual, err := suite.userKey.Cmd(nil, "pr ls")
13 bail(err)
14 snaps.MatchSnapshot(t, actual)
15@@ -53,56 +53,64 @@ func testMultiTenantE2E(t *testing.T) {
16
17 time.Sleep(time.Millisecond * 100)
18
19- // Accepted pr
20- suite.userKey.MustCmd(suite.patch, "pr create test")
21+ t.Log("Admin should be able to create a repo")
22+ suite.adminKey.MustCmd(nil, "repo create test")
23+
24+ t.Log("Accepted pr")
25+ suite.userKey.MustCmd(suite.patch, "pr create admin/test")
26 suite.userKey.MustCmd(nil, "pr edit 1 Accepted patch")
27 _, err := suite.userKey.Cmd(nil, "pr accept 1")
28 if err == nil {
29- t.Error("contrib should not be able to accept their own PR")
30+ t.Fatal("contrib should not be able to accept their own PR")
31 }
32 suite.adminKey.MustCmd(nil, "pr accept 1")
33
34- // Closed pr (admin)
35+ t.Log("Closed pr (admin)")
36 suite.userKey.MustCmd(suite.patch, "pr create test")
37 suite.userKey.MustCmd(nil, "pr edit 2 Closed patch (admin)")
38 suite.adminKey.MustCmd(nil, "pr close 2")
39
40- // Closed pr (contributor)
41+ t.Log("Closed pr (contributor)")
42 suite.userKey.MustCmd(suite.patch, "pr create test")
43 suite.userKey.MustCmd(nil, "pr edit 3 Closed patch (contributor)")
44 suite.userKey.MustCmd(nil, "pr close 3")
45
46- // Reviewed pr
47+ t.Log("Reviewed pr")
48 suite.userKey.MustCmd(suite.patch, "pr create test")
49 suite.userKey.MustCmd(nil, "pr edit 4 Reviewed patch")
50 suite.adminKey.MustCmd(suite.otherPatch, "pr add --review 4")
51
52- // Accepted pr with review
53+ t.Log("Accepted pr with review")
54 suite.userKey.MustCmd(suite.patch, "pr create test")
55 suite.userKey.MustCmd(nil, "pr edit 5 Accepted patch with review")
56 suite.adminKey.MustCmd(suite.otherPatch, "pr add --accept 5")
57
58- // Closed pr with review
59+ t.Log("Closed pr with review")
60 suite.userKey.MustCmd(suite.patch, "pr create test")
61 suite.userKey.MustCmd(nil, "pr edit 6 Closed patch with review")
62 suite.adminKey.MustCmd(suite.otherPatch, "pr add --close 6")
63
64- // Create pr with user namespace
65+ t.Log("Create pr with user repo and user can accept")
66+ suite.userKey.MustCmd(nil, "repo create ai")
67+ suite.adminKey.MustCmd(suite.patch, "pr create contributor/ai")
68+ suite.userKey.MustCmd(suite.otherPatch, "pr accept 7")
69+
70+ t.Log("Create pr with user repo and admin can accept")
71 suite.adminKey.MustCmd(nil, "repo create ai")
72 suite.userKey.MustCmd(suite.patch, "pr create admin/ai")
73- suite.adminKey.MustCmd(suite.otherPatch, "pr add --accept 7")
74+ suite.adminKey.MustCmd(suite.otherPatch, "pr add --accept 8")
75
76- // Create pr with default `bin` repo
77+ t.Log("Create pr with default `bin` repo")
78 actual, err := suite.userKey.Cmd(suite.patch, "pr create")
79 bail(err)
80 snaps.MatchSnapshot(t, actual)
81
82- // Snapshot test ls command
83+ t.Log("Snapshot test ls command")
84 actual, err = suite.userKey.Cmd(nil, "pr ls")
85 bail(err)
86 snaps.MatchSnapshot(t, actual)
87
88- // Snapshot test logs command
89+ t.Log("Snapshot test logs command")
90 actual, err = suite.userKey.Cmd(nil, "logs --repo admin/ai")
91 bail(err)
92 snaps.MatchSnapshot(t, actual)
M
pr.go
+0,
-1
1@@ -147,7 +147,6 @@ func (pr PrCmd) GetRepos() (repos []*Repo, err error) {
2
3 func (pr PrCmd) GetRepoByName(user *User, repoName string) (*Repo, error) {
4 var repo Repo
5- fmt.Println(user.ID, repoName)
6 err := pr.Backend.DB.Get(&repo, "SELECT * FROM repos WHERE user_id=? AND name=?", user.ID, repoName)
7 if err != nil {
8 return nil, fmt.Errorf("repo not found: %s/%s", user.Name, repoName)
+5,
-4
1@@ -19,13 +19,14 @@ CREATE TABLE IF NOT EXISTS app_users (
2 CREATE TABLE IF NOT EXISTS repos (
3 id INTEGER PRIMARY KEY AUTOINCREMENT,
4 user_id INTEGER NOT NULL,
5- name TEXT NOT NULL UNIQUE,
6+ name TEXT NOT NULL,
7 created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
8 updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
9+ UNIQUE (user_id, name),
10 CONSTRAINT repo_user_id_fk
11- FOREIGN KEY(user_id) REFERENCES app_users(id)
12- ON DELETE CASCADE
13- ON UPDATE CASCADE
14+ FOREIGN KEY(user_id) REFERENCES app_users(id)
15+ ON DELETE CASCADE
16+ ON UPDATE CASCADE
17 );
18
19 CREATE TABLE IF NOT EXISTS acl (