- commit
- 088df6f
- parent
- e76ab98
- author
- Eric Bower
- date
- 2024-06-24 22:55:45 -0400 EDT
code passes
5 files changed,
+222,
-72
+2,
-2
1@@ -44,6 +44,6 @@ func (be *Backend) IsAdmin(pk ssh.PublicKey) bool {
2 return false
3 }
4
5-func (be *Backend) IsPrOwner(pka, pkb string) bool {
6- return be.KeysEqual(pka, pkb)
7+func (be *Backend) IsPrOwner(pka, pkb int64) bool {
8+ return pka == pkb
9 }
M
cli.go
+69,
-13
1@@ -42,6 +42,7 @@ Here's how it works:
2 - Owner marks PR as accepted and pushes code to main (git-push)`
3
4 pubkey := be.Pubkey(sesh.PublicKey())
5+ userName := sesh.User()
6 app := &cli.App{
7 Name: "ssh",
8 Description: desc,
9@@ -108,13 +109,16 @@ Here's how it works:
10 },
11 Action: func(cCtx *cli.Context) error {
12 pubkey := be.Pubkey(sesh.PublicKey())
13+ user, err := pr.GetUserByPubkey(pubkey)
14+ if err != nil {
15+ return err
16+ }
17 isPubkey := cCtx.Bool("pubkey")
18 prID := cCtx.Int64("pr")
19 repoID := cCtx.String("repo")
20 var eventLogs []*EventLog
21- var err error
22 if isPubkey {
23- eventLogs, err = pr.GetEventLogsByPubkey(pubkey)
24+ eventLogs, err = pr.GetEventLogsByUserID(user.ID)
25 } else if prID != 0 {
26 eventLogs, err = pr.GetEventLogsByPrID(prID)
27 } else if repoID != "" {
28@@ -212,8 +216,16 @@ Here's how it works:
29 Args: true,
30 ArgsUsage: "[repoID]",
31 Action: func(cCtx *cli.Context) error {
32+ user, err := pr.UpsertUser(&User{
33+ Pubkey: pubkey,
34+ Name: userName,
35+ })
36+ if err != nil {
37+ return err
38+ }
39+
40 repoID := cCtx.Args().First()
41- request, err := pr.SubmitPatchRequest(repoID, pubkey, sesh)
42+ request, err := pr.SubmitPatchRequest(repoID, user.ID, sesh)
43 if err != nil {
44 return err
45 }
46@@ -440,7 +452,15 @@ Here's how it works:
47 return fmt.Errorf("PR has already been accepted")
48 }
49
50- err = pr.UpdatePatchRequestStatus(prID, pubkey, "accepted")
51+ user, err := pr.UpsertUser(&User{
52+ Pubkey: pubkey,
53+ Name: userName,
54+ })
55+ if err != nil {
56+ return err
57+ }
58+
59+ err = pr.UpdatePatchRequestStatus(prID, user.ID, "accepted")
60 if err == nil {
61 wish.Printf(sesh, "Accepted PR %s (#%d)\n", patchReq.Name, patchReq.ID)
62 }
63@@ -457,12 +477,21 @@ Here's how it works:
64 if err != nil {
65 return err
66 }
67+
68+ user, err := pr.UpsertUser(&User{
69+ Pubkey: pubkey,
70+ Name: userName,
71+ })
72+ if err != nil {
73+ return err
74+ }
75+
76 patchReq, err := pr.GetPatchRequestByID(prID)
77 if err != nil {
78 return err
79 }
80 pk := sesh.PublicKey()
81- isContrib := be.Pubkey(pk) == patchReq.Pubkey
82+ isContrib := be.Pubkey(pk) == user.Pubkey
83 isAdmin := be.IsAdmin(pk)
84 if !isAdmin && !isContrib {
85 return fmt.Errorf("you are not authorized to change PR status")
86@@ -472,7 +501,7 @@ Here's how it works:
87 return fmt.Errorf("PR has already been closed")
88 }
89
90- err = pr.UpdatePatchRequestStatus(prID, pubkey, "closed")
91+ err = pr.UpdatePatchRequestStatus(prID, user.ID, "closed")
92 if err == nil {
93 wish.Printf(sesh, "Closed PR %s (#%d)\n", patchReq.Name, patchReq.ID)
94 }
95@@ -489,12 +518,22 @@ Here's how it works:
96 if err != nil {
97 return err
98 }
99+
100 patchReq, err := pr.GetPatchRequestByID(prID)
101 if err != nil {
102 return err
103 }
104+
105+ user, err := pr.UpsertUser(&User{
106+ Pubkey: pubkey,
107+ Name: userName,
108+ })
109+ if err != nil {
110+ return err
111+ }
112+
113 pk := sesh.PublicKey()
114- isContrib := be.Pubkey(pk) == patchReq.Pubkey
115+ isContrib := be.Pubkey(pk) == user.Pubkey
116 isAdmin := be.IsAdmin(pk)
117 if !isAdmin && !isContrib {
118 return fmt.Errorf("you are not authorized to change PR status")
119@@ -504,7 +543,7 @@ Here's how it works:
120 return fmt.Errorf("PR is already open")
121 }
122
123- err = pr.UpdatePatchRequestStatus(prID, pubkey, "open")
124+ err = pr.UpdatePatchRequestStatus(prID, user.ID, "open")
125 if err == nil {
126 wish.Printf(sesh, "Reopened PR %s (#%d)\n", patchReq.Name, patchReq.ID)
127 }
128@@ -525,8 +564,17 @@ Here's how it works:
129 if err != nil {
130 return err
131 }
132+
133+ user, err := pr.UpsertUser(&User{
134+ Pubkey: pubkey,
135+ Name: userName,
136+ })
137+ if err != nil {
138+ return err
139+ }
140+
141 isAdmin := be.IsAdmin(sesh.PublicKey())
142- isPrOwner := be.IsPrOwner(prq.Pubkey, be.Pubkey(sesh.PublicKey()))
143+ isPrOwner := be.IsPrOwner(prq.UserID, user.ID)
144 if !isAdmin && !isPrOwner {
145 return fmt.Errorf("unauthorized, you are not the owner of this PR")
146 }
147@@ -539,7 +587,7 @@ Here's how it works:
148
149 err = pr.UpdatePatchRequestName(
150 prID,
151- be.Pubkey(sesh.PublicKey()),
152+ user.ID,
153 title,
154 )
155 if err == nil {
156@@ -574,10 +622,18 @@ Here's how it works:
157 return err
158 }
159
160+ user, err := pr.UpsertUser(&User{
161+ Pubkey: pubkey,
162+ Name: userName,
163+ })
164+ if err != nil {
165+ return err
166+ }
167+
168 isAdmin := be.IsAdmin(sesh.PublicKey())
169 isReview := cCtx.Bool("review")
170 isReplace := cCtx.Bool("force")
171- isPrOwner := be.IsPrOwner(prq.Pubkey, be.Pubkey(sesh.PublicKey()))
172+ isPrOwner := be.IsPrOwner(prq.UserID, user.ID)
173 if !isAdmin && !isPrOwner {
174 return fmt.Errorf("unauthorized, you are not the owner of this PR")
175 }
176@@ -591,7 +647,7 @@ Here's how it works:
177 op = OpReplace
178 }
179
180- patches, err := pr.SubmitPatchSet(prID, pubkey, op, sesh)
181+ patches, err := pr.SubmitPatchSet(prID, user.ID, op, sesh)
182 if err != nil {
183 return err
184 }
185@@ -603,7 +659,7 @@ Here's how it works:
186
187 reviewTxt := ""
188 if isReview {
189- err = pr.UpdatePatchRequestStatus(prID, pubkey, "reviewed")
190+ err = pr.UpdatePatchRequestStatus(prID, user.ID, "reviewed")
191 if err != nil {
192 return err
193 }
M
db.go
+39,
-11
1@@ -8,10 +8,18 @@ import (
2 _ "modernc.org/sqlite"
3 )
4
5+type User struct {
6+ ID int64 `db:"id"`
7+ Pubkey string `db:"pubkey"`
8+ Name string `db:"name"`
9+ CreatedAt time.Time `db:"created_at"`
10+ UpdatedAt time.Time `db:"updated_at"`
11+}
12+
13 // PatchRequest is a database model for patches submitted to a Repo.
14 type PatchRequest struct {
15 ID int64 `db:"id"`
16- Pubkey string `db:"pubkey"`
17+ UserID int64 `db:"user_id"`
18 RepoID string `db:"repo_id"`
19 Name string `db:"name"`
20 Text string `db:"text"`
21@@ -24,7 +32,7 @@ type PatchRequest struct {
22 // This usually corresponds to a git commit.
23 type Patch struct {
24 ID int64 `db:"id"`
25- Pubkey string `db:"pubkey"`
26+ UserID int64 `db:"user_id"`
27 PatchRequestID int64 `db:"patch_request_id"`
28 AuthorName string `db:"author_name"`
29 AuthorEmail string `db:"author_email"`
30@@ -42,7 +50,7 @@ type Patch struct {
31 // EventLog is a event log for RSS or other notification systems.
32 type EventLog struct {
33 ID int64 `db:"id"`
34- Pubkey string `db:"pubkey"`
35+ UserID int64 `db:"user_id"`
36 RepoID string `db:"repo_id"`
37 PatchRequestID int64 `db:"patch_request_id"`
38 Event string `db:"event"`
39@@ -57,20 +65,32 @@ type DB struct {
40 }
41
42 var schema = `
43-CREATE TABLE IF NOT EXISTS patch_requests (
44+CREATE TABLE IF NOT EXISTS app_users (
45 id INTEGER PRIMARY KEY AUTOINCREMENT,
46 pubkey TEXT NOT NULL,
47+ name TEXT NOT NULL,
48+ created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
49+ updated_at DATETIME NOT NULL
50+);
51+
52+CREATE TABLE IF NOT EXISTS patch_requests (
53+ id INTEGER PRIMARY KEY AUTOINCREMENT,
54+ user_id INTEGER NOT NULL,
55 repo_id TEXT NOT NULL,
56 name TEXT NOT NULL,
57 text TEXT NOT NULL,
58 status TEXT NOT NULL,
59 created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
60- updated_at DATETIME NOT NULL
61+ updated_at DATETIME NOT NULL,
62+ CONSTRAINT pr_user_id_fk
63+ FOREIGN KEY(user_id) REFERENCES app_users(id)
64+ ON DELETE CASCADE
65+ ON UPDATE CASCADE
66 );
67
68 CREATE TABLE IF NOT EXISTS patches (
69 id INTEGER PRIMARY KEY AUTOINCREMENT,
70- pubkey TEXT NOT NULL,
71+ user_id INTEGER NOT NULL,
72 patch_request_id INTEGER NOT NULL,
73 author_name TEXT NOT NULL,
74 author_email TEXT NOT NULL,
75@@ -84,14 +104,18 @@ CREATE TABLE IF NOT EXISTS patches (
76 raw_text TEXT NOT NULL,
77 created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
78 CONSTRAINT pr_id_fk
79- FOREIGN KEY(patch_request_id) REFERENCES patch_requests(id)
80- ON DELETE CASCADE
81- ON UPDATE CASCADE
82+ FOREIGN KEY(patch_request_id) REFERENCES patch_requests(id)
83+ ON DELETE CASCADE
84+ ON UPDATE CASCADE,
85+ CONSTRAINT patches_user_id_fk
86+ FOREIGN KEY(user_id) REFERENCES app_users(id)
87+ ON DELETE CASCADE
88+ ON UPDATE CASCADE
89 );
90
91 CREATE TABLE IF NOT EXISTS event_logs (
92 id INTEGER PRIMARY KEY AUTOINCREMENT,
93- pubkey TEXT NOT NULL,
94+ user_id INTEGER NOT NULL,
95 repo_id TEXT,
96 patch_request_id INTEGER,
97 event TEXT NOT NULL,
98@@ -100,7 +124,11 @@ CREATE TABLE IF NOT EXISTS event_logs (
99 CONSTRAINT event_logs_pr_id_fk
100 FOREIGN KEY(patch_request_id) REFERENCES patch_requests(id)
101 ON DELETE CASCADE
102- ON UPDATE CASCADE
103+ ON UPDATE CASCADE,
104+ CONSTRAINT event_logs_user_id_fk
105+ FOREIGN KEY(user_id) REFERENCES app_users(id)
106+ ON DELETE CASCADE
107+ ON UPDATE CASCADE
108 );
109 `
110
M
pr.go
+65,
-26
1@@ -24,23 +24,28 @@ const (
2 )
3
4 type GitPatchRequest interface {
5+ GetUsers() ([]*User, error)
6+ GetUserByID(userID int64) (*User, error)
7+ GetUserByPubkey(pubkey string) (*User, error)
8+ CreateUser(user *User) (*User, error)
9+ UpsertUser(user *User) (*User, error)
10 GetRepos() ([]*Repo, error)
11 GetReposWithLatestPr() ([]RepoWithLatestPr, error)
12 GetRepoByID(repoID string) (*Repo, error)
13- SubmitPatchRequest(repoID string, pubkey string, patchset io.Reader) (*PatchRequest, error)
14- SubmitPatchSet(prID int64, pubkey string, op PatchsetOp, patchset io.Reader) ([]*Patch, error)
15+ SubmitPatchRequest(repoID string, userID int64, patchset io.Reader) (*PatchRequest, error)
16+ SubmitPatchSet(prID, userID int64, op PatchsetOp, patchset io.Reader) ([]*Patch, error)
17 GetPatchRequestByID(prID int64) (*PatchRequest, error)
18 GetPatchRequests() ([]*PatchRequest, error)
19 GetPatchRequestsByRepoID(repoID string) ([]*PatchRequest, error)
20 GetPatchesByPrID(prID int64) ([]*Patch, error)
21- UpdatePatchRequestStatus(prID int64, pubkey, status string) error
22- UpdatePatchRequestName(prID int64, pubkey, name string) error
23+ UpdatePatchRequestStatus(prID, userID int64, status string) error
24+ UpdatePatchRequestName(prID, userID int64, name string) error
25 DeletePatchesByPrID(prID int64) error
26 CreateEventLog(eventLog EventLog) error
27 GetEventLogs() ([]*EventLog, error)
28 GetEventLogsByRepoID(repoID string) ([]*EventLog, error)
29 GetEventLogsByPrID(prID int64) ([]*EventLog, error)
30- GetEventLogsByPubkey(pubkey string) ([]*EventLog, error)
31+ GetEventLogsByUserID(userID int64) ([]*EventLog, error)
32 }
33
34 type PrCmd struct {
35@@ -50,6 +55,26 @@ type PrCmd struct {
36 var _ GitPatchRequest = PrCmd{}
37 var _ GitPatchRequest = (*PrCmd)(nil)
38
39+func (pr PrCmd) GetUsers() ([]*User, error) {
40+ return []*User{}, nil
41+}
42+
43+func (pr PrCmd) GetUserByID(id int64) (*User, error) {
44+ return nil, nil
45+}
46+
47+func (pr PrCmd) GetUserByPubkey(pubkey string) (*User, error) {
48+ return nil, nil
49+}
50+
51+func (pr PrCmd) CreateUser(user *User) (*User, error) {
52+ return nil, nil
53+}
54+
55+func (pr PrCmd) UpsertUser(user *User) (*User, error) {
56+ return nil, nil
57+}
58+
59 type PrWithRepo struct {
60 LastUpdatedPrID int64
61 RepoID string
62@@ -57,6 +82,7 @@ type PrWithRepo struct {
63
64 type RepoWithLatestPr struct {
65 *Repo
66+ User *User
67 PatchRequest *PatchRequest
68 }
69
70@@ -72,11 +98,24 @@ func (pr PrCmd) GetReposWithLatestPr() ([]RepoWithLatestPr, error) {
71 return repos, err
72 }
73
74+ users, err := pr.GetUsers()
75+ if err != nil {
76+ return repos, err
77+ }
78+
79 // we want recently modified repos to be on top
80 for _, prq := range prs {
81 for _, repo := range pr.Backend.Cfg.Repos {
82 if prq.RepoID == repo.ID {
83+ var user *User
84+ for _, usr := range users {
85+ if prq.UserID == usr.ID {
86+ user = usr
87+ break
88+ }
89+ }
90 repos = append(repos, RepoWithLatestPr{
91+ User: user,
92 Repo: repo,
93 PatchRequest: &prq,
94 })
95@@ -162,14 +201,14 @@ func (cmd PrCmd) GetPatchRequestByID(prID int64) (*PatchRequest, error) {
96 }
97
98 // Status types: open, closed, accepted, reviewed.
99-func (cmd PrCmd) UpdatePatchRequestStatus(prID int64, pubkey string, status string) error {
100+func (cmd PrCmd) UpdatePatchRequestStatus(prID int64, userID int64, status string) error {
101 _, err := cmd.Backend.DB.Exec(
102 "UPDATE patch_requests SET status=? WHERE id=?",
103 status,
104 prID,
105 )
106 _ = cmd.CreateEventLog(EventLog{
107- Pubkey: pubkey,
108+ UserID: userID,
109 PatchRequestID: prID,
110 Event: "pr_status_changed",
111 Data: fmt.Sprintf(`{"status":"%s"}`, status),
112@@ -177,7 +216,7 @@ func (cmd PrCmd) UpdatePatchRequestStatus(prID int64, pubkey string, status stri
113 return err
114 }
115
116-func (cmd PrCmd) UpdatePatchRequestName(prID int64, pubkey string, name string) error {
117+func (cmd PrCmd) UpdatePatchRequestName(prID int64, userID int64, name string) error {
118 if name == "" {
119 return fmt.Errorf("must provide name or text in order to update patch request")
120 }
121@@ -188,7 +227,7 @@ func (cmd PrCmd) UpdatePatchRequestName(prID int64, pubkey string, name string)
122 prID,
123 )
124 _ = cmd.CreateEventLog(EventLog{
125- Pubkey: pubkey,
126+ UserID: userID,
127 PatchRequestID: prID,
128 Event: "pr_name_changed",
129 Data: fmt.Sprintf(`{"name":"%s"}`, name),
130@@ -215,8 +254,8 @@ func (cmd PrCmd) CreateEventLog(eventLog EventLog) error {
131 }
132
133 _, err := cmd.Backend.DB.Exec(
134- "INSERT INTO event_logs (pubkey, repo_id, patch_request_id, event, data) VALUES (?, ?, ?, ?, ?)",
135- eventLog.Pubkey,
136+ "INSERT INTO event_logs (user_id, repo_id, patch_request_id, event, data) VALUES (?, ?, ?, ?, ?)",
137+ eventLog.UserID,
138 eventLog.RepoID,
139 eventLog.PatchRequestID,
140 eventLog.Event,
141@@ -322,8 +361,8 @@ func (cmd PrCmd) createPatch(tx *sqlx.Tx, review bool, patch *Patch) (int64, err
142
143 var patchID int64
144 row := tx.QueryRow(
145- "INSERT INTO patches (pubkey, patch_request_id, author_name, author_email, author_date, title, body, body_appendix, commit_sha, content_sha, review, raw_text) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING id",
146- patch.Pubkey,
147+ "INSERT INTO patches (user_id, patch_request_id, author_name, author_email, author_date, title, body, body_appendix, commit_sha, content_sha, review, raw_text) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING id",
148+ patch.UserID,
149 patch.PatchRequestID,
150 patch.AuthorName,
151 patch.AuthorEmail,
152@@ -346,7 +385,7 @@ func (cmd PrCmd) createPatch(tx *sqlx.Tx, review bool, patch *Patch) (int64, err
153 return patchID, err
154 }
155
156-func (cmd PrCmd) SubmitPatchRequest(repoID string, pubkey string, patchset io.Reader) (*PatchRequest, error) {
157+func (cmd PrCmd) SubmitPatchRequest(repoID string, userID int64, patchset io.Reader) (*PatchRequest, error) {
158 tx, err := cmd.Backend.DB.Beginx()
159 if err != nil {
160 return nil, err
161@@ -369,8 +408,8 @@ func (cmd PrCmd) SubmitPatchRequest(repoID string, pubkey string, patchset io.Re
162
163 var prID int64
164 row := tx.QueryRow(
165- "INSERT INTO patch_requests (pubkey, repo_id, name, text, status, updated_at) VALUES(?, ?, ?, ?, ?, ?) RETURNING id",
166- pubkey,
167+ "INSERT INTO patch_requests (user_id, repo_id, name, text, status, updated_at) VALUES(?, ?, ?, ?, ?, ?) RETURNING id",
168+ userID,
169 repoID,
170 prName,
171 prText,
172@@ -386,7 +425,7 @@ func (cmd PrCmd) SubmitPatchRequest(repoID string, pubkey string, patchset io.Re
173 }
174
175 for _, patch := range patches {
176- patch.Pubkey = pubkey
177+ patch.UserID = userID
178 patch.PatchRequestID = prID
179 _, err = cmd.createPatch(tx, false, patch)
180 if err != nil {
181@@ -400,7 +439,7 @@ func (cmd PrCmd) SubmitPatchRequest(repoID string, pubkey string, patchset io.Re
182 }
183
184 _ = cmd.CreateEventLog(EventLog{
185- Pubkey: pubkey,
186+ UserID: userID,
187 PatchRequestID: prID,
188 Event: "pr_created",
189 })
190@@ -410,7 +449,7 @@ func (cmd PrCmd) SubmitPatchRequest(repoID string, pubkey string, patchset io.Re
191 return &pr, err
192 }
193
194-func (cmd PrCmd) SubmitPatchSet(prID int64, pubkey string, op PatchsetOp, patchset io.Reader) ([]*Patch, error) {
195+func (cmd PrCmd) SubmitPatchSet(prID int64, userID int64, op PatchsetOp, patchset io.Reader) ([]*Patch, error) {
196 fin := []*Patch{}
197 tx, err := cmd.Backend.DB.Beginx()
198 if err != nil {
199@@ -434,7 +473,7 @@ func (cmd PrCmd) SubmitPatchSet(prID int64, pubkey string, op PatchsetOp, patchs
200 }
201
202 for _, patch := range patches {
203- patch.Pubkey = pubkey
204+ patch.UserID = userID
205 patch.PatchRequestID = prID
206 patchID, err := cmd.createPatch(tx, op == OpReview, patch)
207 if err == nil {
208@@ -461,7 +500,7 @@ func (cmd PrCmd) SubmitPatchSet(prID int64, pubkey string, op PatchsetOp, patchs
209 }
210
211 _ = cmd.CreateEventLog(EventLog{
212- Pubkey: pubkey,
213+ UserID: userID,
214 PatchRequestID: prID,
215 Event: event,
216 })
217@@ -506,19 +545,19 @@ func (cmd PrCmd) GetEventLogsByPrID(prID int64) ([]*EventLog, error) {
218 return eventLogs, err
219 }
220
221-func (cmd PrCmd) GetEventLogsByPubkey(pubkey string) ([]*EventLog, error) {
222+func (cmd PrCmd) GetEventLogsByUserID(userID int64) ([]*EventLog, error) {
223 eventLogs := []*EventLog{}
224 query := `SELECT * FROM event_logs
225- WHERE pubkey=?
226+ WHERE user_id=?
227 OR patch_request_id IN (
228- SELECT id FROM patch_requests WHERE pubkey=?
229+ SELECT id FROM patch_requests WHERE user_id=?
230 )
231 ORDER BY created_at DESC`
232 err := cmd.Backend.DB.Select(
233 &eventLogs,
234 query,
235- pubkey,
236- pubkey,
237+ userID,
238+ userID,
239 )
240 return eventLogs, err
241 }
M
web.go
+47,
-20
1@@ -112,8 +112,9 @@ func repoListHandler(w http.ResponseWriter, r *http.Request) {
2 if repo.PatchRequest != nil {
3 curpr := repo.PatchRequest
4 ls = &PrListData{
5- ID: curpr.ID,
6- Pubkey: curpr.Pubkey,
7+ ID: curpr.ID,
8+ UserName: repo.User.Name,
9+ Pubkey: repo.User.Pubkey,
10 LinkData: LinkData{
11 Url: template.URL(fmt.Sprintf("/prs/%d", curpr.ID)),
12 Text: curpr.Name,
13@@ -146,10 +147,11 @@ func repoListHandler(w http.ResponseWriter, r *http.Request) {
14
15 type PrListData struct {
16 LinkData
17- ID int64
18- Pubkey string
19- Date string
20- Status string
21+ ID int64
22+ UserName string
23+ Pubkey string
24+ Date string
25+ Status string
26 }
27
28 type RepoDetailData struct {
29@@ -191,9 +193,14 @@ func repoDetailHandler(w http.ResponseWriter, r *http.Request) {
30 acceptedList := []PrListData{}
31 closedList := []PrListData{}
32 for _, curpr := range prs {
33+ user, err := web.Pr.GetUserByID(curpr.UserID)
34+ if err != nil {
35+ continue
36+ }
37 ls := PrListData{
38- ID: curpr.ID,
39- Pubkey: curpr.Pubkey,
40+ ID: curpr.ID,
41+ UserName: user.Name,
42+ Pubkey: user.Pubkey,
43 LinkData: LinkData{
44 Url: template.URL(fmt.Sprintf("/prs/%d", curpr.ID)),
45 Text: curpr.Name,
46@@ -221,6 +228,7 @@ func repoDetailHandler(w http.ResponseWriter, r *http.Request) {
47 OpenPrs: openList,
48 AcceptedPrs: acceptedList,
49 ClosedPrs: closedList,
50+ ReviewedPrs: reviewedList,
51 })
52 if err != nil {
53 fmt.Println(err)
54@@ -228,11 +236,12 @@ func repoDetailHandler(w http.ResponseWriter, r *http.Request) {
55 }
56
57 type PrData struct {
58- ID int64
59- Title string
60- Date string
61- Pubkey string
62- Status string
63+ ID int64
64+ Title string
65+ Date string
66+ UserName string
67+ Pubkey string
68+ Status string
69 }
70
71 type PatchData struct {
72@@ -299,6 +308,12 @@ func prDetailHandler(w http.ResponseWriter, r *http.Request) {
73 })
74 }
75
76+ user, err := web.Pr.GetUserByID(pr.UserID)
77+ if err != nil {
78+ w.WriteHeader(http.StatusNotFound)
79+ return
80+ }
81+
82 w.Header().Set("content-type", "text/html")
83 tmpl := getTemplate("pr-detail.html")
84 err = tmpl.Execute(w, PrHeaderData{
85@@ -310,11 +325,12 @@ func prDetailHandler(w http.ResponseWriter, r *http.Request) {
86 Branch: repo.DefaultBranch,
87 Patches: patchesData,
88 Pr: PrData{
89- ID: pr.ID,
90- Title: pr.Name,
91- Pubkey: pr.Pubkey,
92- Date: pr.CreatedAt.Format(time.RFC3339),
93- Status: pr.Status,
94+ ID: pr.ID,
95+ Title: pr.Name,
96+ UserName: user.Name,
97+ Pubkey: user.Pubkey,
98+ Date: pr.CreatedAt.Format(time.RFC3339),
99+ Status: pr.Status,
100 },
101 })
102 if err != nil {
103@@ -345,6 +361,11 @@ func rssHandler(w http.ResponseWriter, r *http.Request) {
104 id := r.PathValue("id")
105 repoID := r.PathValue("repoid")
106 pubkey := r.URL.Query().Get("pubkey")
107+ user, err := web.Pr.GetUserByPubkey(pubkey)
108+ if err != nil {
109+ w.WriteHeader(http.StatusNotFound)
110+ return
111+ }
112 if id != "" {
113 var prID int64
114 prID, err = getPrID(id)
115@@ -354,7 +375,7 @@ func rssHandler(w http.ResponseWriter, r *http.Request) {
116 }
117 eventLogs, err = web.Pr.GetEventLogsByPrID(prID)
118 } else if pubkey != "" {
119- eventLogs, err = web.Pr.GetEventLogsByPubkey(pubkey)
120+ eventLogs, err = web.Pr.GetEventLogsByUserID(user.ID)
121 } else if repoID != "" {
122 eventLogs, err = web.Pr.GetEventLogsByRepoID(repoID)
123 } else {
124@@ -382,6 +403,12 @@ func rssHandler(w http.ResponseWriter, r *http.Request) {
125 if err != nil {
126 continue
127 }
128+
129+ user, err := web.Pr.GetUserByID(pr.UserID)
130+ if err != nil {
131+ continue
132+ }
133+
134 title := fmt.Sprintf(
135 `%s in %s for PR "%s" (#%d)`,
136 eventLog.Event,
137@@ -396,7 +423,7 @@ func rssHandler(w http.ResponseWriter, r *http.Request) {
138 Content: content,
139 Created: eventLog.CreatedAt,
140 Description: title,
141- Author: &feeds.Author{Name: eventLog.Pubkey},
142+ Author: &feeds.Author{Name: user.Name},
143 }
144
145 feedItems = append(feedItems, item)