+36
-12
appview/issues/issues.go
+36
-12
appview/issues/issues.go
···
78
78
issue, ok := r.Context().Value("issue").(*models.Issue)
79
79
if !ok {
80
80
l.Error("failed to get issue")
81
-
rp.pages.Error404(w)
81
+
rp.pages.Error404(w, pages.ErrorPageParams{
82
+
LoggedInUser: user,
83
+
})
82
84
return
83
85
}
84
86
···
99
101
)
100
102
if err != nil {
101
103
l.Error("failed to fetch labels", "err", err)
102
-
rp.pages.Error503(w)
104
+
rp.pages.Error503(w, pages.ErrorPageParams{
105
+
LoggedInUser: user,
106
+
})
103
107
return
104
108
}
105
109
···
132
136
issue, ok := r.Context().Value("issue").(*models.Issue)
133
137
if !ok {
134
138
l.Error("failed to get issue")
135
-
rp.pages.Error404(w)
139
+
rp.pages.Error404(w, pages.ErrorPageParams{
140
+
LoggedInUser: user,
141
+
})
136
142
return
137
143
}
138
144
···
275
281
issue, ok := r.Context().Value("issue").(*models.Issue)
276
282
if !ok {
277
283
l.Error("failed to get issue")
278
-
rp.pages.Error404(w)
284
+
rp.pages.Error404(w, pages.ErrorPageParams{
285
+
LoggedInUser: user,
286
+
})
279
287
return
280
288
}
281
289
···
324
332
issue, ok := r.Context().Value("issue").(*models.Issue)
325
333
if !ok {
326
334
l.Error("failed to get issue")
327
-
rp.pages.Error404(w)
335
+
rp.pages.Error404(w, pages.ErrorPageParams{
336
+
LoggedInUser: user,
337
+
})
328
338
return
329
339
}
330
340
···
368
378
issue, ok := r.Context().Value("issue").(*models.Issue)
369
379
if !ok {
370
380
l.Error("failed to get issue")
371
-
rp.pages.Error404(w)
381
+
rp.pages.Error404(w, pages.ErrorPageParams{
382
+
LoggedInUser: user,
383
+
})
372
384
return
373
385
}
374
386
···
456
468
issue, ok := r.Context().Value("issue").(*models.Issue)
457
469
if !ok {
458
470
l.Error("failed to get issue")
459
-
rp.pages.Error404(w)
471
+
rp.pages.Error404(w, pages.ErrorPageParams{
472
+
LoggedInUser: user,
473
+
})
460
474
return
461
475
}
462
476
···
497
511
issue, ok := r.Context().Value("issue").(*models.Issue)
498
512
if !ok {
499
513
l.Error("failed to get issue")
500
-
rp.pages.Error404(w)
514
+
rp.pages.Error404(w, pages.ErrorPageParams{
515
+
LoggedInUser: user,
516
+
})
501
517
return
502
518
}
503
519
···
601
617
issue, ok := r.Context().Value("issue").(*models.Issue)
602
618
if !ok {
603
619
l.Error("failed to get issue")
604
-
rp.pages.Error404(w)
620
+
rp.pages.Error404(w, pages.ErrorPageParams{
621
+
LoggedInUser: user,
622
+
})
605
623
return
606
624
}
607
625
···
642
660
issue, ok := r.Context().Value("issue").(*models.Issue)
643
661
if !ok {
644
662
l.Error("failed to get issue")
645
-
rp.pages.Error404(w)
663
+
rp.pages.Error404(w, pages.ErrorPageParams{
664
+
LoggedInUser: user,
665
+
})
646
666
return
647
667
}
648
668
···
683
703
issue, ok := r.Context().Value("issue").(*models.Issue)
684
704
if !ok {
685
705
l.Error("failed to get issue")
686
-
rp.pages.Error404(w)
706
+
rp.pages.Error404(w, pages.ErrorPageParams{
707
+
LoggedInUser: user,
708
+
})
687
709
return
688
710
}
689
711
···
806
828
)
807
829
if err != nil {
808
830
l.Error("failed to fetch labels", "err", err)
809
-
rp.pages.Error503(w)
831
+
rp.pages.Error503(w, pages.ErrorPageParams{
832
+
LoggedInUser: user,
833
+
})
810
834
return
811
835
}
812
836
+20
-6
appview/middleware/middleware.go
+20
-6
appview/middleware/middleware.go
···
191
191
if err != nil {
192
192
// invalid did or handle
193
193
log.Printf("failed to resolve did/handle '%s': %s\n", didOrHandle, err)
194
-
mw.pages.Error404(w)
194
+
mw.pages.Error404(w, pages.ErrorPageParams{})
195
195
return
196
196
}
197
197
···
206
206
return func(next http.Handler) http.Handler {
207
207
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
208
208
repoName := chi.URLParam(req, "repo")
209
+
user := mw.oauth.GetUser(req)
209
210
id, ok := req.Context().Value("resolvedId").(identity.Identity)
210
211
if !ok {
211
212
log.Println("malformed middleware")
···
220
221
)
221
222
if err != nil {
222
223
log.Println("failed to resolve repo", "err", err)
223
-
mw.pages.ErrorKnot404(w)
224
+
mw.pages.ErrorKnot404(w, pages.ErrorPageParams{
225
+
LoggedInUser: user,
226
+
})
224
227
return
225
228
}
226
229
···
235
238
return func(next http.Handler) http.Handler {
236
239
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
237
240
f, err := mw.repoResolver.Resolve(r)
241
+
user := mw.oauth.GetUser(r)
238
242
if err != nil {
239
243
log.Println("failed to fully resolve repo", err)
240
-
mw.pages.ErrorKnot404(w)
244
+
mw.pages.ErrorKnot404(w, pages.ErrorPageParams{
245
+
LoggedInUser: user,
246
+
})
241
247
return
242
248
}
243
249
···
282
288
func (mw Middleware) ResolveIssue(next http.Handler) http.Handler {
283
289
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
284
290
f, err := mw.repoResolver.Resolve(r)
291
+
user := mw.oauth.GetUser(r)
285
292
if err != nil {
286
293
log.Println("failed to fully resolve repo", err)
287
-
mw.pages.ErrorKnot404(w)
294
+
mw.pages.ErrorKnot404(w, pages.ErrorPageParams{
295
+
LoggedInUser: user,
296
+
})
288
297
return
289
298
}
290
299
···
292
301
issueId, err := strconv.Atoi(issueIdStr)
293
302
if err != nil {
294
303
log.Println("failed to fully resolve issue ID", err)
295
-
mw.pages.ErrorKnot404(w)
304
+
mw.pages.ErrorKnot404(w, pages.ErrorPageParams{
305
+
LoggedInUser: user,
306
+
})
296
307
return
297
308
}
298
309
···
326
337
return func(next http.Handler) http.Handler {
327
338
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
328
339
f, err := mw.repoResolver.Resolve(r)
340
+
user := mw.oauth.GetUser(r)
329
341
if err != nil {
330
342
log.Println("failed to fully resolve repo", err)
331
-
mw.pages.ErrorKnot404(w)
343
+
mw.pages.ErrorKnot404(w, pages.ErrorPageParams{
344
+
LoggedInUser: user,
345
+
})
332
346
return
333
347
}
334
348
+6
-2
appview/notifications/notifications.go
+6
-2
appview/notifications/notifications.go
···
61
61
)
62
62
if err != nil {
63
63
l.Error("failed to get total notifications", "err", err)
64
-
n.pages.Error500(w)
64
+
n.pages.Error500(w, pages.ErrorPageParams{
65
+
LoggedInUser: user,
66
+
})
65
67
return
66
68
}
67
69
···
72
74
)
73
75
if err != nil {
74
76
l.Error("failed to get notifications", "err", err)
75
-
n.pages.Error500(w)
77
+
n.pages.Error500(w, pages.ErrorPageParams{
78
+
LoggedInUser: user,
79
+
})
76
80
return
77
81
}
78
82
+42
-50
appview/notify/merged_notifier.go
+42
-50
appview/notify/merged_notifier.go
···
2
2
3
3
import (
4
4
"context"
5
+
"reflect"
6
+
"sync"
5
7
6
8
"tangled.org/core/appview/models"
7
9
)
···
16
18
17
19
var _ Notifier = &mergedNotifier{}
18
20
19
-
func (m *mergedNotifier) NewRepo(ctx context.Context, repo *models.Repo) {
20
-
for _, notifier := range m.notifiers {
21
-
notifier.NewRepo(ctx, repo)
21
+
// fanout calls the same method on all notifiers concurrently
22
+
func (m *mergedNotifier) fanout(method string, args ...any) {
23
+
var wg sync.WaitGroup
24
+
for _, n := range m.notifiers {
25
+
wg.Add(1)
26
+
go func(notifier Notifier) {
27
+
defer wg.Done()
28
+
v := reflect.ValueOf(notifier).MethodByName(method)
29
+
in := make([]reflect.Value, len(args))
30
+
for i, arg := range args {
31
+
in[i] = reflect.ValueOf(arg)
32
+
}
33
+
v.Call(in)
34
+
}(n)
22
35
}
36
+
wg.Wait()
37
+
}
38
+
39
+
func (m *mergedNotifier) NewRepo(ctx context.Context, repo *models.Repo) {
40
+
m.fanout("NewRepo", ctx, repo)
23
41
}
24
42
25
43
func (m *mergedNotifier) NewStar(ctx context.Context, star *models.Star) {
26
-
for _, notifier := range m.notifiers {
27
-
notifier.NewStar(ctx, star)
28
-
}
44
+
m.fanout("NewStar", ctx, star)
29
45
}
46
+
30
47
func (m *mergedNotifier) DeleteStar(ctx context.Context, star *models.Star) {
31
-
for _, notifier := range m.notifiers {
32
-
notifier.DeleteStar(ctx, star)
33
-
}
48
+
m.fanout("DeleteStar", ctx, star)
34
49
}
35
50
36
51
func (m *mergedNotifier) NewIssue(ctx context.Context, issue *models.Issue) {
37
-
for _, notifier := range m.notifiers {
38
-
notifier.NewIssue(ctx, issue)
39
-
}
52
+
m.fanout("NewIssue", ctx, issue)
40
53
}
54
+
41
55
func (m *mergedNotifier) NewIssueComment(ctx context.Context, comment *models.IssueComment) {
42
-
for _, notifier := range m.notifiers {
43
-
notifier.NewIssueComment(ctx, comment)
44
-
}
56
+
m.fanout("NewIssueComment", ctx, comment)
45
57
}
46
58
47
59
func (m *mergedNotifier) NewIssueClosed(ctx context.Context, issue *models.Issue) {
48
-
for _, notifier := range m.notifiers {
49
-
notifier.NewIssueClosed(ctx, issue)
50
-
}
60
+
m.fanout("NewIssueClosed", ctx, issue)
51
61
}
52
62
53
63
func (m *mergedNotifier) NewFollow(ctx context.Context, follow *models.Follow) {
54
-
for _, notifier := range m.notifiers {
55
-
notifier.NewFollow(ctx, follow)
56
-
}
64
+
m.fanout("NewFollow", ctx, follow)
57
65
}
66
+
58
67
func (m *mergedNotifier) DeleteFollow(ctx context.Context, follow *models.Follow) {
59
-
for _, notifier := range m.notifiers {
60
-
notifier.DeleteFollow(ctx, follow)
61
-
}
68
+
m.fanout("DeleteFollow", ctx, follow)
62
69
}
63
70
64
71
func (m *mergedNotifier) NewPull(ctx context.Context, pull *models.Pull) {
65
-
for _, notifier := range m.notifiers {
66
-
notifier.NewPull(ctx, pull)
67
-
}
72
+
m.fanout("NewPull", ctx, pull)
68
73
}
74
+
69
75
func (m *mergedNotifier) NewPullComment(ctx context.Context, comment *models.PullComment) {
70
-
for _, notifier := range m.notifiers {
71
-
notifier.NewPullComment(ctx, comment)
72
-
}
76
+
m.fanout("NewPullComment", ctx, comment)
73
77
}
74
78
75
79
func (m *mergedNotifier) NewPullMerged(ctx context.Context, pull *models.Pull) {
76
-
for _, notifier := range m.notifiers {
77
-
notifier.NewPullMerged(ctx, pull)
78
-
}
80
+
m.fanout("NewPullMerged", ctx, pull)
79
81
}
80
82
81
83
func (m *mergedNotifier) NewPullClosed(ctx context.Context, pull *models.Pull) {
82
-
for _, notifier := range m.notifiers {
83
-
notifier.NewPullClosed(ctx, pull)
84
-
}
84
+
m.fanout("NewPullClosed", ctx, pull)
85
85
}
86
86
87
87
func (m *mergedNotifier) UpdateProfile(ctx context.Context, profile *models.Profile) {
88
-
for _, notifier := range m.notifiers {
89
-
notifier.UpdateProfile(ctx, profile)
90
-
}
88
+
m.fanout("UpdateProfile", ctx, profile)
91
89
}
92
90
93
-
func (m *mergedNotifier) NewString(ctx context.Context, string *models.String) {
94
-
for _, notifier := range m.notifiers {
95
-
notifier.NewString(ctx, string)
96
-
}
91
+
func (m *mergedNotifier) NewString(ctx context.Context, s *models.String) {
92
+
m.fanout("NewString", ctx, s)
97
93
}
98
94
99
-
func (m *mergedNotifier) EditString(ctx context.Context, string *models.String) {
100
-
for _, notifier := range m.notifiers {
101
-
notifier.EditString(ctx, string)
102
-
}
95
+
func (m *mergedNotifier) EditString(ctx context.Context, s *models.String) {
96
+
m.fanout("EditString", ctx, s)
103
97
}
104
98
105
99
func (m *mergedNotifier) DeleteString(ctx context.Context, did, rkey string) {
106
-
for _, notifier := range m.notifiers {
107
-
notifier.DeleteString(ctx, did, rkey)
108
-
}
100
+
m.fanout("DeleteString", ctx, did, rkey)
109
101
}
+12
-8
appview/pages/pages.go
+12
-8
appview/pages/pages.go
···
1381
1381
Active string
1382
1382
}
1383
1383
1384
+
type ErrorPageParams struct {
1385
+
LoggedInUser *oauth.User
1386
+
}
1387
+
1384
1388
func (p *Pages) Workflow(w io.Writer, params WorkflowParams) error {
1385
1389
params.Active = "pipelines"
1386
1390
return p.executeRepo("repo/pipelines/workflow", w, params)
···
1518
1522
return hex.EncodeToString(hasher.Sum(nil))[:8] // Use first 8 chars of hash
1519
1523
}
1520
1524
1521
-
func (p *Pages) Error500(w io.Writer) error {
1522
-
return p.execute("errors/500", w, nil)
1525
+
func (p *Pages) Error500(w io.Writer, params ErrorPageParams) error {
1526
+
return p.execute("errors/500", w, params)
1523
1527
}
1524
1528
1525
-
func (p *Pages) Error404(w io.Writer) error {
1526
-
return p.execute("errors/404", w, nil)
1529
+
func (p *Pages) Error404(w io.Writer, params ErrorPageParams) error {
1530
+
return p.execute("errors/404", w, params)
1527
1531
}
1528
1532
1529
-
func (p *Pages) ErrorKnot404(w io.Writer) error {
1530
-
return p.execute("errors/knot404", w, nil)
1533
+
func (p *Pages) ErrorKnot404(w io.Writer, params ErrorPageParams) error {
1534
+
return p.execute("errors/knot404", w, params)
1531
1535
}
1532
1536
1533
-
func (p *Pages) Error503(w io.Writer) error {
1534
-
return p.execute("errors/503", w, nil)
1537
+
func (p *Pages) Error503(w io.Writer, params ErrorPageParams) error {
1538
+
return p.execute("errors/503", w, params)
1535
1539
}
+2
-2
appview/pages/templates/repo/issues/fragments/issueCommentHeader.html
+2
-2
appview/pages/templates/repo/issues/fragments/issueCommentHeader.html
···
34
34
35
35
{{ define "editIssueComment" }}
36
36
<a
37
-
class="text-gray-500 dark:text-gray-400 flex gap-1 items-center group"
37
+
class="text-gray-500 dark:text-gray-400 flex gap-1 items-center group cursor-pointer"
38
38
hx-get="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/comment/{{ .Comment.Id }}/edit"
39
39
hx-swap="outerHTML"
40
40
hx-target="#comment-body-{{.Comment.Id}}">
···
44
44
45
45
{{ define "deleteIssueComment" }}
46
46
<a
47
-
class="text-gray-500 dark:text-gray-400 flex gap-1 items-center group"
47
+
class="text-gray-500 dark:text-gray-400 flex gap-1 items-center group cursor-pointer"
48
48
hx-delete="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/comment/{{ .Comment.Id }}/"
49
49
hx-confirm="Are you sure you want to delete your comment?"
50
50
hx-swap="outerHTML"
+2
-2
appview/pages/templates/repo/issues/issue.html
+2
-2
appview/pages/templates/repo/issues/issue.html
···
84
84
85
85
{{ define "editIssue" }}
86
86
<a
87
-
class="text-gray-500 dark:text-gray-400 flex gap-1 items-center group"
87
+
class="text-gray-500 dark:text-gray-400 flex gap-1 items-center group cursor-pointer"
88
88
hx-get="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/edit"
89
89
hx-swap="innerHTML"
90
90
hx-target="#issue-{{.Issue.IssueId}}">
···
94
94
95
95
{{ define "deleteIssue" }}
96
96
<a
97
-
class="text-gray-500 dark:text-gray-400 flex gap-1 items-center group"
97
+
class="text-gray-500 dark:text-gray-400 flex gap-1 items-center group cursor-pointer"
98
98
hx-delete="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/"
99
99
hx-confirm="Are you sure you want to delete your issue?"
100
100
hx-swap="none">
+2
appview/pages/templates/repo/settings/access.html
+2
appview/pages/templates/repo/settings/access.html
+2
appview/pages/templates/spindles/fragments/addMemberModal.html
+2
appview/pages/templates/spindles/fragments/addMemberModal.html
+3
appview/pages/templates/user/login.html
+3
appview/pages/templates/user/login.html
+30
-10
appview/pulls/pulls.go
+30
-10
appview/pulls/pulls.go
···
205
205
)
206
206
if err != nil {
207
207
log.Println("failed to fetch labels", err)
208
-
s.pages.Error503(w)
208
+
s.pages.Error503(w, pages.ErrorPageParams{
209
+
LoggedInUser: user,
210
+
})
209
211
return
210
212
}
211
213
···
636
638
)
637
639
if err != nil {
638
640
log.Println("failed to fetch labels", err)
639
-
s.pages.Error503(w)
641
+
s.pages.Error503(w, pages.ErrorPageParams{
642
+
LoggedInUser: user,
643
+
})
640
644
return
641
645
}
642
646
···
785
789
if err != nil {
786
790
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
787
791
log.Println("failed to call XRPC repo.branches", xrpcerr)
788
-
s.pages.Error503(w)
792
+
s.pages.Error503(w, pages.ErrorPageParams{
793
+
LoggedInUser: user,
794
+
})
789
795
return
790
796
}
791
797
log.Println("failed to fetch branches", err)
···
795
801
var result types.RepoBranchesResponse
796
802
if err := json.Unmarshal(xrpcBytes, &result); err != nil {
797
803
log.Println("failed to decode XRPC response", err)
798
-
s.pages.Error503(w)
804
+
s.pages.Error503(w, pages.ErrorPageParams{
805
+
LoggedInUser: user,
806
+
})
799
807
return
800
808
}
801
809
···
1392
1400
if err != nil {
1393
1401
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
1394
1402
log.Println("failed to call XRPC repo.branches", xrpcerr)
1395
-
s.pages.Error503(w)
1403
+
s.pages.Error503(w, pages.ErrorPageParams{
1404
+
LoggedInUser: user,
1405
+
})
1396
1406
return
1397
1407
}
1398
1408
log.Println("failed to fetch branches", err)
···
1402
1412
var result types.RepoBranchesResponse
1403
1413
if err := json.Unmarshal(xrpcBytes, &result); err != nil {
1404
1414
log.Println("failed to decode XRPC response", err)
1405
-
s.pages.Error503(w)
1415
+
s.pages.Error503(w, pages.ErrorPageParams{
1416
+
LoggedInUser: user,
1417
+
})
1406
1418
return
1407
1419
}
1408
1420
···
1484
1496
if err != nil {
1485
1497
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
1486
1498
log.Println("failed to call XRPC repo.branches for source", xrpcerr)
1487
-
s.pages.Error503(w)
1499
+
s.pages.Error503(w, pages.ErrorPageParams{
1500
+
LoggedInUser: user,
1501
+
})
1488
1502
return
1489
1503
}
1490
1504
log.Println("failed to fetch source branches", err)
···
1495
1509
var sourceBranches types.RepoBranchesResponse
1496
1510
if err := json.Unmarshal(sourceXrpcBytes, &sourceBranches); err != nil {
1497
1511
log.Println("failed to decode source branches XRPC response", err)
1498
-
s.pages.Error503(w)
1512
+
s.pages.Error503(w, pages.ErrorPageParams{
1513
+
LoggedInUser: user,
1514
+
})
1499
1515
return
1500
1516
}
1501
1517
···
1513
1529
if err != nil {
1514
1530
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
1515
1531
log.Println("failed to call XRPC repo.branches for target", xrpcerr)
1516
-
s.pages.Error503(w)
1532
+
s.pages.Error503(w, pages.ErrorPageParams{
1533
+
LoggedInUser: user,
1534
+
})
1517
1535
return
1518
1536
}
1519
1537
log.Println("failed to fetch target branches", err)
···
1524
1542
var targetBranches types.RepoBranchesResponse
1525
1543
if err := json.Unmarshal(targetXrpcBytes, &targetBranches); err != nil {
1526
1544
log.Println("failed to decode target branches XRPC response", err)
1527
-
s.pages.Error503(w)
1545
+
s.pages.Error503(w, pages.ErrorPageParams{
1546
+
LoggedInUser: user,
1547
+
})
1528
1548
return
1529
1549
}
1530
1550
+8
-2
appview/repo/feed.go
+8
-2
appview/repo/feed.go
···
10
10
11
11
"tangled.org/core/appview/db"
12
12
"tangled.org/core/appview/models"
13
+
"tangled.org/core/appview/pages"
13
14
"tangled.org/core/appview/pagination"
14
15
"tangled.org/core/appview/reporesolver"
15
16
···
152
153
log.Println("failed to fully resolve repo:", err)
153
154
return
154
155
}
156
+
user := rp.oauth.GetUser(r)
155
157
156
158
feed, err := rp.getRepoFeed(r.Context(), f)
157
159
if err != nil {
158
160
log.Println("failed to get repo feed:", err)
159
-
rp.pages.Error500(w)
161
+
rp.pages.Error500(w, pages.ErrorPageParams{
162
+
LoggedInUser: user,
163
+
})
160
164
return
161
165
}
162
166
163
167
atom, err := feed.ToAtom()
164
168
if err != nil {
165
-
rp.pages.Error500(w)
169
+
rp.pages.Error500(w, pages.ErrorPageParams{
170
+
LoggedInUser: user,
171
+
})
166
172
return
167
173
}
168
174
+3
-1
appview/repo/index.go
+3
-1
appview/repo/index.go
+83
-34
appview/repo/repo.go
+83
-34
appview/repo/repo.go
···
90
90
91
91
func (rp *Repo) DownloadArchive(w http.ResponseWriter, r *http.Request) {
92
92
l := rp.logger.With("handler", "DownloadArchive")
93
+
user := rp.oauth.GetUser(r)
93
94
94
95
ref := chi.URLParam(r, "ref")
95
96
ref, _ = url.PathUnescape(ref)
···
113
114
archiveBytes, err := tangled.RepoArchive(r.Context(), xrpcc, "tar.gz", "", ref, repo)
114
115
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
115
116
l.Error("failed to call XRPC repo.archive", "err", xrpcerr)
116
-
rp.pages.Error503(w)
117
+
rp.pages.Error503(w, pages.ErrorPageParams{
118
+
LoggedInUser: user,
119
+
})
117
120
return
118
121
}
119
122
···
130
133
131
134
func (rp *Repo) RepoLog(w http.ResponseWriter, r *http.Request) {
132
135
l := rp.logger.With("handler", "RepoLog")
136
+
user := rp.oauth.GetUser(r)
133
137
134
138
f, err := rp.repoResolver.Resolve(r)
135
139
if err != nil {
···
169
173
xrpcBytes, err := tangled.RepoLog(r.Context(), xrpcc, cursor, limit, "", ref, repo)
170
174
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
171
175
l.Error("failed to call XRPC repo.log", "err", xrpcerr)
172
-
rp.pages.Error503(w)
176
+
rp.pages.Error503(w, pages.ErrorPageParams{
177
+
LoggedInUser: user,
178
+
})
173
179
return
174
180
}
175
181
176
182
var xrpcResp types.RepoLogResponse
177
183
if err := json.Unmarshal(xrpcBytes, &xrpcResp); err != nil {
178
184
l.Error("failed to decode XRPC response", "err", err)
179
-
rp.pages.Error503(w)
185
+
rp.pages.Error503(w, pages.ErrorPageParams{
186
+
LoggedInUser: user,
187
+
})
180
188
return
181
189
}
182
190
183
191
tagBytes, err := tangled.RepoTags(r.Context(), xrpcc, "", 0, repo)
184
192
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
185
193
l.Error("failed to call XRPC repo.tags", "err", xrpcerr)
186
-
rp.pages.Error503(w)
194
+
rp.pages.Error503(w, pages.ErrorPageParams{
195
+
LoggedInUser: user,
196
+
})
187
197
return
188
198
}
189
199
···
204
214
branchBytes, err := tangled.RepoBranches(r.Context(), xrpcc, "", 0, repo)
205
215
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
206
216
l.Error("failed to call XRPC repo.branches", "err", xrpcerr)
207
-
rp.pages.Error503(w)
217
+
rp.pages.Error503(w, pages.ErrorPageParams{
218
+
LoggedInUser: user,
219
+
})
208
220
return
209
221
}
210
222
···
216
228
}
217
229
}
218
230
}
219
-
220
-
user := rp.oauth.GetUser(r)
221
231
222
232
emailToDidMap, err := db.GetEmailToDid(rp.db, uniqueEmails(xrpcResp.Commits), true)
223
233
if err != nil {
···
353
363
354
364
func (rp *Repo) RepoCommit(w http.ResponseWriter, r *http.Request) {
355
365
l := rp.logger.With("handler", "RepoCommit")
366
+
user := rp.oauth.GetUser(r)
356
367
357
368
f, err := rp.repoResolver.Resolve(r)
358
369
if err != nil {
···
368
379
}
369
380
370
381
if !plumbing.IsHash(ref) {
371
-
rp.pages.Error404(w)
382
+
rp.pages.Error404(w, pages.ErrorPageParams{
383
+
LoggedInUser: user,
384
+
})
372
385
return
373
386
}
374
387
···
385
398
xrpcBytes, err := tangled.RepoDiff(r.Context(), xrpcc, ref, repo)
386
399
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
387
400
l.Error("failed to call XRPC repo.diff", "err", xrpcerr)
388
-
rp.pages.Error503(w)
401
+
rp.pages.Error503(w, pages.ErrorPageParams{
402
+
LoggedInUser: user,
403
+
})
389
404
return
390
405
}
391
406
392
407
var result types.RepoCommitResponse
393
408
if err := json.Unmarshal(xrpcBytes, &result); err != nil {
394
409
l.Error("failed to decode XRPC response", "err", err)
395
-
rp.pages.Error503(w)
410
+
rp.pages.Error503(w, pages.ErrorPageParams{
411
+
LoggedInUser: user,
412
+
})
396
413
return
397
414
}
398
415
···
406
423
l.Error("failed to GetVerifiedCommits", "err", err)
407
424
}
408
425
409
-
user := rp.oauth.GetUser(r)
410
426
repoInfo := f.RepoInfo(user)
411
427
pipelines, err := getPipelineStatuses(rp.db, repoInfo, []string{result.Diff.Commit.This})
412
428
if err != nil {
···
431
447
432
448
func (rp *Repo) RepoTree(w http.ResponseWriter, r *http.Request) {
433
449
l := rp.logger.With("handler", "RepoTree")
450
+
user := rp.oauth.GetUser(r)
434
451
435
452
f, err := rp.repoResolver.Resolve(r)
436
453
if err != nil {
···
460
477
xrpcResp, err := tangled.RepoTree(r.Context(), xrpcc, treePath, ref, repo)
461
478
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
462
479
l.Error("failed to call XRPC repo.tree", "err", xrpcerr)
463
-
rp.pages.Error503(w)
480
+
rp.pages.Error503(w, pages.ErrorPageParams{
481
+
LoggedInUser: user,
482
+
})
464
483
return
465
484
}
466
485
···
511
530
http.Redirect(w, r, redirectTo, http.StatusFound)
512
531
return
513
532
}
514
-
515
-
user := rp.oauth.GetUser(r)
516
533
517
534
var breadcrumbs [][]string
518
535
breadcrumbs = append(breadcrumbs, []string{f.Name, fmt.Sprintf("/%s/tree/%s", f.OwnerSlashRepo(), url.PathEscape(ref))})
···
535
552
536
553
func (rp *Repo) RepoTags(w http.ResponseWriter, r *http.Request) {
537
554
l := rp.logger.With("handler", "RepoTags")
555
+
user := rp.oauth.GetUser(r)
538
556
539
557
f, err := rp.repoResolver.Resolve(r)
540
558
if err != nil {
···
555
573
xrpcBytes, err := tangled.RepoTags(r.Context(), xrpcc, "", 0, repo)
556
574
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
557
575
l.Error("failed to call XRPC repo.tags", "err", xrpcerr)
558
-
rp.pages.Error503(w)
576
+
rp.pages.Error503(w, pages.ErrorPageParams{
577
+
LoggedInUser: user,
578
+
})
559
579
return
560
580
}
561
581
562
582
var result types.RepoTagsResponse
563
583
if err := json.Unmarshal(xrpcBytes, &result); err != nil {
564
584
l.Error("failed to decode XRPC response", "err", err)
565
-
rp.pages.Error503(w)
585
+
rp.pages.Error503(w, pages.ErrorPageParams{
586
+
LoggedInUser: user,
587
+
})
566
588
return
567
589
}
568
590
···
594
616
}
595
617
}
596
618
597
-
user := rp.oauth.GetUser(r)
598
619
rp.pages.RepoTags(w, pages.RepoTagsParams{
599
620
LoggedInUser: user,
600
621
RepoInfo: f.RepoInfo(user),
···
606
627
607
628
func (rp *Repo) RepoBranches(w http.ResponseWriter, r *http.Request) {
608
629
l := rp.logger.With("handler", "RepoBranches")
630
+
user := rp.oauth.GetUser(r)
609
631
610
632
f, err := rp.repoResolver.Resolve(r)
611
633
if err != nil {
···
626
648
xrpcBytes, err := tangled.RepoBranches(r.Context(), xrpcc, "", 0, repo)
627
649
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
628
650
l.Error("failed to call XRPC repo.branches", "err", xrpcerr)
629
-
rp.pages.Error503(w)
651
+
rp.pages.Error503(w, pages.ErrorPageParams{
652
+
LoggedInUser: user,
653
+
})
630
654
return
631
655
}
632
656
633
657
var result types.RepoBranchesResponse
634
658
if err := json.Unmarshal(xrpcBytes, &result); err != nil {
635
659
l.Error("failed to decode XRPC response", "err", err)
636
-
rp.pages.Error503(w)
660
+
rp.pages.Error503(w, pages.ErrorPageParams{
661
+
LoggedInUser: user,
662
+
})
637
663
return
638
664
}
639
665
640
666
sortBranches(result.Branches)
641
667
642
-
user := rp.oauth.GetUser(r)
643
668
rp.pages.RepoBranches(w, pages.RepoBranchesParams{
644
669
LoggedInUser: user,
645
670
RepoInfo: f.RepoInfo(user),
···
698
723
699
724
func (rp *Repo) RepoBlob(w http.ResponseWriter, r *http.Request) {
700
725
l := rp.logger.With("handler", "RepoBlob")
726
+
user := rp.oauth.GetUser(r)
701
727
702
728
f, err := rp.repoResolver.Resolve(r)
703
729
if err != nil {
···
724
750
resp, err := tangled.RepoBlob(r.Context(), xrpcc, filePath, false, ref, repo)
725
751
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
726
752
l.Error("failed to call XRPC repo.blob", "err", xrpcerr)
727
-
rp.pages.Error503(w)
753
+
rp.pages.Error503(w, pages.ErrorPageParams{
754
+
LoggedInUser: user,
755
+
})
728
756
return
729
757
}
730
758
···
796
824
sizeHint = uint64(len(resp.Content))
797
825
}
798
826
799
-
user := rp.oauth.GetUser(r)
800
-
801
827
// Determine if content is binary (dereference pointer)
802
828
isBinary := false
803
829
if resp.IsBinary != nil {
···
824
850
825
851
func (rp *Repo) RepoBlobRaw(w http.ResponseWriter, r *http.Request) {
826
852
l := rp.logger.With("handler", "RepoBlobRaw")
853
+
user := rp.oauth.GetUser(r)
827
854
828
855
f, err := rp.repoResolver.Resolve(r)
829
856
if err != nil {
···
872
899
resp, err := client.Do(req)
873
900
if err != nil {
874
901
l.Error("failed to reach knotserver", "err", err)
875
-
rp.pages.Error503(w)
902
+
rp.pages.Error503(w, pages.ErrorPageParams{
903
+
LoggedInUser: user,
904
+
})
876
905
return
877
906
}
878
907
defer resp.Body.Close()
···
1963
1992
xrpcBytes, err := tangled.RepoBranches(r.Context(), xrpcc, "", 0, repo)
1964
1993
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
1965
1994
l.Error("failed to call XRPC repo.branches", "err", xrpcerr)
1966
-
rp.pages.Error503(w)
1995
+
rp.pages.Error503(w, pages.ErrorPageParams{
1996
+
LoggedInUser: user,
1997
+
})
1967
1998
return
1968
1999
}
1969
2000
1970
2001
var result types.RepoBranchesResponse
1971
2002
if err := json.Unmarshal(xrpcBytes, &result); err != nil {
1972
2003
l.Error("failed to decode XRPC response", "err", err)
1973
-
rp.pages.Error503(w)
2004
+
rp.pages.Error503(w, pages.ErrorPageParams{
2005
+
LoggedInUser: user,
2006
+
})
1974
2007
return
1975
2008
}
1976
2009
1977
2010
defaultLabels, err := db.GetLabelDefinitions(rp.db, db.FilterIn("at_uri", models.DefaultLabelDefs()))
1978
2011
if err != nil {
1979
2012
l.Error("failed to fetch labels", "err", err)
1980
-
rp.pages.Error503(w)
2013
+
rp.pages.Error503(w, pages.ErrorPageParams{
2014
+
LoggedInUser: user,
2015
+
})
1981
2016
return
1982
2017
}
1983
2018
1984
2019
labels, err := db.GetLabelDefinitions(rp.db, db.FilterIn("at_uri", f.Repo.Labels))
1985
2020
if err != nil {
1986
2021
l.Error("failed to fetch labels", "err", err)
1987
-
rp.pages.Error503(w)
2022
+
rp.pages.Error503(w, pages.ErrorPageParams{
2023
+
LoggedInUser: user,
2024
+
})
1988
2025
return
1989
2026
}
1990
2027
// remove default labels from the labels list, if present
···
2418
2455
branchBytes, err := tangled.RepoBranches(r.Context(), xrpcc, "", 0, repo)
2419
2456
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
2420
2457
l.Error("failed to call XRPC repo.branches", "err", xrpcerr)
2421
-
rp.pages.Error503(w)
2458
+
rp.pages.Error503(w, pages.ErrorPageParams{
2459
+
LoggedInUser: user,
2460
+
})
2422
2461
return
2423
2462
}
2424
2463
···
2455
2494
tagBytes, err := tangled.RepoTags(r.Context(), xrpcc, "", 0, repo)
2456
2495
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
2457
2496
l.Error("failed to call XRPC repo.tags", "err", xrpcerr)
2458
-
rp.pages.Error503(w)
2497
+
rp.pages.Error503(w, pages.ErrorPageParams{
2498
+
LoggedInUser: user,
2499
+
})
2459
2500
return
2460
2501
}
2461
2502
···
2512
2553
2513
2554
if base == "" || head == "" {
2514
2555
l.Error("invalid comparison")
2515
-
rp.pages.Error404(w)
2556
+
rp.pages.Error404(w, pages.ErrorPageParams{
2557
+
LoggedInUser: user,
2558
+
})
2516
2559
return
2517
2560
}
2518
2561
···
2530
2573
branchBytes, err := tangled.RepoBranches(r.Context(), xrpcc, "", 0, repo)
2531
2574
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
2532
2575
l.Error("failed to call XRPC repo.branches", "err", xrpcerr)
2533
-
rp.pages.Error503(w)
2576
+
rp.pages.Error503(w, pages.ErrorPageParams{
2577
+
LoggedInUser: user,
2578
+
})
2534
2579
return
2535
2580
}
2536
2581
···
2544
2589
tagBytes, err := tangled.RepoTags(r.Context(), xrpcc, "", 0, repo)
2545
2590
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
2546
2591
l.Error("failed to call XRPC repo.tags", "err", xrpcerr)
2547
-
rp.pages.Error503(w)
2592
+
rp.pages.Error503(w, pages.ErrorPageParams{
2593
+
LoggedInUser: user,
2594
+
})
2548
2595
return
2549
2596
}
2550
2597
···
2558
2605
compareBytes, err := tangled.RepoCompare(r.Context(), xrpcc, repo, base, head)
2559
2606
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
2560
2607
l.Error("failed to call XRPC repo.compare", "err", xrpcerr)
2561
-
rp.pages.Error503(w)
2608
+
rp.pages.Error503(w, pages.ErrorPageParams{
2609
+
LoggedInUser: user,
2610
+
})
2562
2611
return
2563
2612
}
2564
2613
+6
-2
appview/state/gfi.go
+6
-2
appview/state/gfi.go
···
28
28
repoLabels, err := db.GetRepoLabels(s.db, db.FilterEq("label_at", goodFirstIssueLabel))
29
29
if err != nil {
30
30
log.Println("failed to get repo labels", err)
31
-
s.pages.Error503(w)
31
+
s.pages.Error503(w, pages.ErrorPageParams{
32
+
LoggedInUser: user,
33
+
})
32
34
return
33
35
}
34
36
···
57
59
)
58
60
if err != nil {
59
61
log.Println("failed to get issues", err)
60
-
s.pages.Error503(w)
62
+
s.pages.Error503(w, pages.ErrorPageParams{
63
+
LoggedInUser: user,
64
+
})
61
65
return
62
66
}
63
67
+36
-10
appview/state/profile.go
+36
-10
appview/state/profile.go
···
112
112
113
113
func (s *State) profileOverview(w http.ResponseWriter, r *http.Request) {
114
114
l := s.logger.With("handler", "profileHomePage")
115
+
user := s.oauth.GetUser(r)
115
116
116
117
profile, err := s.profile(r)
117
118
if err != nil {
118
119
l.Error("failed to build profile card", "err", err)
119
-
s.pages.Error500(w)
120
+
s.pages.Error500(w, pages.ErrorPageParams{
121
+
LoggedInUser: user,
122
+
})
120
123
return
121
124
}
122
125
l = l.With("profileDid", profile.UserDid, "profileHandle", profile.UserHandle)
···
173
176
174
177
func (s *State) reposPage(w http.ResponseWriter, r *http.Request) {
175
178
l := s.logger.With("handler", "reposPage")
179
+
user := s.oauth.GetUser(r)
176
180
177
181
profile, err := s.profile(r)
178
182
if err != nil {
179
183
l.Error("failed to build profile card", "err", err)
180
-
s.pages.Error500(w)
184
+
s.pages.Error500(w, pages.ErrorPageParams{
185
+
LoggedInUser: user,
186
+
})
181
187
return
182
188
}
183
189
l = l.With("profileDid", profile.UserDid, "profileHandle", profile.UserHandle)
···
189
195
)
190
196
if err != nil {
191
197
l.Error("failed to get repos", "err", err)
192
-
s.pages.Error500(w)
198
+
s.pages.Error500(w, pages.ErrorPageParams{
199
+
LoggedInUser: user,
200
+
})
193
201
return
194
202
}
195
203
···
202
210
203
211
func (s *State) starredPage(w http.ResponseWriter, r *http.Request) {
204
212
l := s.logger.With("handler", "starredPage")
213
+
user := s.oauth.GetUser(r)
205
214
206
215
profile, err := s.profile(r)
207
216
if err != nil {
208
217
l.Error("failed to build profile card", "err", err)
209
-
s.pages.Error500(w)
218
+
s.pages.Error500(w, pages.ErrorPageParams{
219
+
LoggedInUser: user,
220
+
})
210
221
return
211
222
}
212
223
l = l.With("profileDid", profile.UserDid, "profileHandle", profile.UserHandle)
···
214
225
stars, err := db.GetStars(s.db, 0, db.FilterEq("starred_by_did", profile.UserDid))
215
226
if err != nil {
216
227
l.Error("failed to get stars", "err", err)
217
-
s.pages.Error500(w)
228
+
s.pages.Error500(w, pages.ErrorPageParams{
229
+
LoggedInUser: user,
230
+
})
218
231
return
219
232
}
220
233
var repos []models.Repo
···
233
246
234
247
func (s *State) stringsPage(w http.ResponseWriter, r *http.Request) {
235
248
l := s.logger.With("handler", "stringsPage")
249
+
user := s.oauth.GetUser(r)
236
250
237
251
profile, err := s.profile(r)
238
252
if err != nil {
239
253
l.Error("failed to build profile card", "err", err)
240
-
s.pages.Error500(w)
254
+
s.pages.Error500(w, pages.ErrorPageParams{
255
+
LoggedInUser: user,
256
+
})
241
257
return
242
258
}
243
259
l = l.With("profileDid", profile.UserDid, "profileHandle", profile.UserHandle)
···
245
261
strings, err := db.GetStrings(s.db, 0, db.FilterEq("did", profile.UserDid))
246
262
if err != nil {
247
263
l.Error("failed to get strings", "err", err)
248
-
s.pages.Error500(w)
264
+
s.pages.Error500(w, pages.ErrorPageParams{
265
+
LoggedInUser: user,
266
+
})
249
267
return
250
268
}
251
269
···
380
398
381
399
func (s *State) AtomFeedPage(w http.ResponseWriter, r *http.Request) {
382
400
ident, ok := r.Context().Value("resolvedId").(identity.Identity)
401
+
user := s.oauth.GetUser(r)
402
+
383
403
if !ok {
384
-
s.pages.Error404(w)
404
+
s.pages.Error404(w, pages.ErrorPageParams{
405
+
LoggedInUser: user,
406
+
})
385
407
return
386
408
}
387
409
388
410
feed, err := s.getProfileFeed(r.Context(), &ident)
389
411
if err != nil {
390
-
s.pages.Error500(w)
412
+
s.pages.Error500(w, pages.ErrorPageParams{
413
+
LoggedInUser: user,
414
+
})
391
415
return
392
416
}
393
417
···
397
421
398
422
atom, err := feed.ToAtom()
399
423
if err != nil {
400
-
s.pages.Error500(w)
424
+
s.pages.Error500(w, pages.ErrorPageParams{
425
+
LoggedInUser: user,
426
+
})
401
427
return
402
428
}
403
429
+3
-2
appview/state/router.go
+3
-2
appview/state/router.go
···
10
10
"tangled.org/core/appview/labels"
11
11
"tangled.org/core/appview/middleware"
12
12
"tangled.org/core/appview/notifications"
13
+
"tangled.org/core/appview/pages"
13
14
"tangled.org/core/appview/pipelines"
14
15
"tangled.org/core/appview/pulls"
15
16
"tangled.org/core/appview/repo"
···
103
104
})
104
105
105
106
r.NotFound(func(w http.ResponseWriter, r *http.Request) {
106
-
s.pages.Error404(w)
107
+
s.pages.Error404(w, pages.ErrorPageParams{})
107
108
})
108
109
109
110
return r
···
174
175
r.Get("/brand", s.Brand)
175
176
176
177
r.NotFound(func(w http.ResponseWriter, r *http.Request) {
177
-
s.pages.Error404(w)
178
+
s.pages.Error404(w, pages.ErrorPageParams{})
178
179
})
179
180
return r
180
181
}
+4
-1
appview/strings/strings.go
+4
-1
appview/strings/strings.go
···
88
88
89
89
func (s *Strings) contents(w http.ResponseWriter, r *http.Request) {
90
90
l := s.Logger.With("handler", "contents")
91
+
user := s.OAuth.GetUser(r)
91
92
92
93
id, ok := r.Context().Value("resolvedId").(identity.Identity)
93
94
if !ok {
···
118
119
}
119
120
if len(strings) < 1 {
120
121
l.Error("string not found")
121
-
s.Pages.Error404(w)
122
+
s.Pages.Error404(w, pages.ErrorPageParams{
123
+
LoggedInUser: user,
124
+
})
122
125
return
123
126
}
124
127
if len(strings) != 1 {