forked from tangled.org/core
Monorepo for Tangled — https://tangled.org

Compare changes

Choose any two refs to compare.

Changed files
+281 -179
appview
spindle
engines
nixery
+5 -8
appview/db/issues.go
··· 101 101 pLower := FilterGte("row_num", page.Offset+1) 102 102 pUpper := FilterLte("row_num", page.Offset+page.Limit) 103 103 104 - pageClause := "" 105 - if page.Limit > 0 { 106 - args = append(args, pLower.Arg()...) 107 - args = append(args, pUpper.Arg()...) 108 - pageClause = " where " + pLower.Condition() + " and " + pUpper.Condition() 109 - } 104 + args = append(args, pLower.Arg()...) 105 + args = append(args, pUpper.Arg()...) 106 + pagination := " where " + pLower.Condition() + " and " + pUpper.Condition() 110 107 111 108 query := fmt.Sprintf( 112 109 ` ··· 131 128 %s 132 129 `, 133 130 whereClause, 134 - pageClause, 131 + pagination, 135 132 ) 136 133 137 134 rows, err := e.Query(query, args...) ··· 247 244 } 248 245 249 246 func GetIssues(e Execer, filters ...filter) ([]models.Issue, error) { 250 - return GetIssuesPaginated(e, pagination.Page{}, filters...) 247 + return GetIssuesPaginated(e, pagination.FirstPage(), filters...) 251 248 } 252 249 253 250 func AddIssueComment(e Execer, c models.IssueComment) (int64, error) {
+4 -7
appview/db/notifications.go
··· 60 60 whereClause += " AND " + condition 61 61 } 62 62 } 63 - pageClause := "" 64 - if page.Limit > 0 { 65 - pageClause = " limit ? offset ? " 66 - args = append(args, page.Limit, page.Offset) 67 - } 68 63 69 64 query := fmt.Sprintf(` 70 65 select id, recipient_did, actor_did, type, entity_type, entity_id, read, created, repo_id, issue_id, pull_id 71 66 from notifications 72 67 %s 73 68 order by created desc 74 - %s 75 - `, whereClause, pageClause) 69 + limit ? offset ? 70 + `, whereClause) 71 + 72 + args = append(args, page.Limit, page.Offset) 76 73 77 74 rows, err := e.QueryContext(context.Background(), query, args...) 78 75 if err != nil {
+41 -13
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 ··· 770 792 isOpen = true 771 793 } 772 794 773 - page := pagination.FromContext(r.Context()) 795 + page, ok := r.Context().Value("page").(pagination.Page) 796 + if !ok { 797 + l.Error("failed to get page") 798 + page = pagination.FirstPage() 799 + } 774 800 775 801 user := rp.oauth.GetUser(r) 776 802 f, err := rp.repoResolver.Resolve(r) ··· 802 828 ) 803 829 if err != nil { 804 830 l.Error("failed to fetch labels", "err", err) 805 - rp.pages.Error503(w) 831 + rp.pages.Error503(w, pages.ErrorPageParams{ 832 + LoggedInUser: user, 833 + }) 806 834 return 807 835 } 808 836
+21 -7
appview/middleware/middleware.go
··· 105 105 } 106 106 } 107 107 108 - ctx := pagination.IntoContext(r.Context(), page) 108 + ctx := context.WithValue(r.Context(), "page", page) 109 109 next.ServeHTTP(w, r.WithContext(ctx)) 110 110 }) 111 111 } ··· 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
+11 -3
appview/notifications/notifications.go
··· 49 49 l := n.logger.With("handler", "notificationsPage") 50 50 user := n.oauth.GetUser(r) 51 51 52 - page := pagination.FromContext(r.Context()) 52 + page, ok := r.Context().Value("page").(pagination.Page) 53 + if !ok { 54 + l.Error("failed to get page") 55 + page = pagination.FirstPage() 56 + } 53 57 54 58 total, err := db.CountNotifications( 55 59 n.db, ··· 57 61 ) 58 62 if err != nil { 59 63 l.Error("failed to get total notifications", "err", err) 60 - n.pages.Error500(w) 64 + n.pages.Error500(w, pages.ErrorPageParams{ 65 + LoggedInUser: user, 66 + }) 61 67 return 62 68 } 63 69 ··· 68 74 ) 69 75 if err != nil { 70 76 l.Error("failed to get notifications", "err", err) 71 - n.pages.Error500(w) 77 + n.pages.Error500(w, pages.ErrorPageParams{ 78 + LoggedInUser: user, 79 + }) 72 80 return 73 81 } 74 82
+2 -13
appview/oauth/handler.go
··· 4 4 "bytes" 5 5 "context" 6 6 "encoding/json" 7 - "errors" 8 7 "fmt" 9 8 "net/http" 10 9 "slices" 11 10 "time" 12 11 13 - "github.com/bluesky-social/indigo/atproto/auth/oauth" 14 12 "github.com/go-chi/chi/v5" 15 13 "github.com/lestrrat-go/jwx/v2/jwk" 16 14 "github.com/posthog/posthog-go" ··· 60 58 61 59 func (o *OAuth) callback(w http.ResponseWriter, r *http.Request) { 62 60 ctx := r.Context() 63 - l := o.Logger.With("query", r.URL.Query()) 64 61 65 62 sessData, err := o.ClientApp.ProcessCallback(ctx, r.URL.Query()) 66 63 if err != nil { 67 - var callbackErr *oauth.AuthRequestCallbackError 68 - if errors.As(err, &callbackErr) { 69 - l.Debug("callback error", "err", callbackErr) 70 - http.Redirect(w, r, fmt.Sprintf("/login?error=%s", callbackErr.ErrorCode), http.StatusFound) 71 - return 72 - } 73 - l.Error("failed to process callback", "err", err) 74 - http.Redirect(w, r, "/login?error=oauth", http.StatusFound) 64 + http.Error(w, err.Error(), http.StatusInternalServerError) 75 65 return 76 66 } 77 67 78 68 if err := o.SaveSession(w, r, sessData); err != nil { 79 - l.Error("failed to save session", "data", sessData, "err", err) 80 - http.Redirect(w, r, "/login?error=session", http.StatusFound) 69 + http.Error(w, err.Error(), http.StatusInternalServerError) 81 70 return 82 71 } 83 72
+1 -4
appview/oauth/oauth.go
··· 58 58 59 59 sessStore := sessions.NewCookieStore([]byte(config.Core.CookieSecret)) 60 60 61 - clientApp := oauth.NewClientApp(&oauthConfig, authStore) 62 - clientApp.Dir = res.Directory() 63 - 64 61 return &OAuth{ 65 - ClientApp: clientApp, 62 + ClientApp: oauth.NewClientApp(&oauthConfig, authStore), 66 63 Config: config, 67 64 SessStore: sessStore, 68 65 JwksUri: jwksUri,
+2 -3
appview/pages/funcmap.go
··· 297 297 }, 298 298 299 299 "normalizeForHtmlId": func(s string) string { 300 - normalized := strings.ReplaceAll(s, ":", "_") 301 - normalized = strings.ReplaceAll(normalized, ".", "_") 302 - return normalized 300 + // TODO: extend this to handle other cases? 301 + return strings.ReplaceAll(s, ":", "_") 303 302 }, 304 303 "sshFingerprint": func(pubKey string) string { 305 304 fp, err := crypto.SSHFingerprint(pubKey)
+12 -9
appview/pages/pages.go
··· 221 221 222 222 type LoginParams struct { 223 223 ReturnUrl string 224 - ErrorCode string 225 224 } 226 225 227 226 func (p *Pages) Login(w io.Writer, params LoginParams) error { ··· 1382 1381 Active string 1383 1382 } 1384 1383 1384 + type ErrorPageParams struct { 1385 + LoggedInUser *oauth.User 1386 + } 1387 + 1385 1388 func (p *Pages) Workflow(w io.Writer, params WorkflowParams) error { 1386 1389 params.Active = "pipelines" 1387 1390 return p.executeRepo("repo/pipelines/workflow", w, params) ··· 1519 1522 return hex.EncodeToString(hasher.Sum(nil))[:8] // Use first 8 chars of hash 1520 1523 } 1521 1524 1522 - func (p *Pages) Error500(w io.Writer) error { 1523 - 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) 1524 1527 } 1525 1528 1526 - func (p *Pages) Error404(w io.Writer) error { 1527 - 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) 1528 1531 } 1529 1532 1530 - func (p *Pages) ErrorKnot404(w io.Writer) error { 1531 - 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) 1532 1535 } 1533 1536 1534 - func (p *Pages) Error503(w io.Writer) error { 1535 - 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) 1536 1539 }
+1 -1
appview/pages/templates/strings/string.html
··· 47 47 </span> 48 48 </section> 49 49 <section class="bg-white dark:bg-gray-800 px-6 py-4 rounded relative w-full dark:text-white"> 50 - <div class="flex flex-col md:flex-row md:justify-between md:items-center text-gray-500 dark:text-gray-400 text-sm md:text-base pb-2 mb-3 text-base border-b border-gray-200 dark:border-gray-700"> 50 + <div class="flex justify-between items-center text-gray-500 dark:text-gray-400 text-sm md:text-base pb-2 mb-3 text-base border-b border-gray-200 dark:border-gray-700"> 51 51 <span> 52 52 {{ .String.Filename }} 53 53 <span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
+1 -1
appview/pages/templates/user/fragments/followCard.html
··· 3 3 <div class="flex flex-col divide-y divide-gray-200 dark:divide-gray-700 rounded-sm"> 4 4 <div class="py-4 px-6 drop-shadow-sm rounded bg-white dark:bg-gray-800 flex items-center gap-4"> 5 5 <div class="flex-shrink-0 max-h-full w-24 h-24"> 6 - <img class="object-cover rounded-full p-2" src="{{ fullAvatar $userIdent }}" alt="{{ $userIdent }}" /> 6 + <img class="object-cover rounded-full p-2" src="{{ fullAvatar $userIdent }}" /> 7 7 </div> 8 8 9 9 <div class="flex flex-col md:flex-row md:items-center md:justify-between gap-2 w-full">
+2 -20
appview/pages/templates/user/login.html
··· 13 13 <title>login &middot; tangled</title> 14 14 </head> 15 15 <body class="flex items-center justify-center min-h-screen"> 16 - <main class="max-w-md px-7 mt-4"> 16 + <main class="max-w-md px-6 -mt-4"> 17 17 <h1 class="flex place-content-center text-3xl font-semibold italic dark:text-white" > 18 18 {{ template "fragments/logotype" }} 19 19 </h1> ··· 21 21 tightly-knit social coding. 22 22 </h2> 23 23 <form 24 - class="mt-4" 24 + class="mt-4 max-w-sm mx-auto" 25 25 hx-post="/login" 26 26 hx-swap="none" 27 27 hx-disabled-elt="#login-button" ··· 56 56 <span>login</span> 57 57 </button> 58 58 </form> 59 - {{ if .ErrorCode }} 60 - <div class="flex gap-2 my-2 bg-red-50 dark:bg-red-900 border border-red-500 rounded drop-shadow-sm px-3 py-2 text-red-500 dark:text-red-300"> 61 - <span class="py-1">{{ i "circle-alert" "w-4 h-4" }}</span> 62 - <div> 63 - <h5 class="font-medium">Login error</h5> 64 - <p class="text-sm"> 65 - {{ if eq .ErrorCode "access_denied" }} 66 - You have not authorized the app. 67 - {{ else if eq .ErrorCode "session" }} 68 - Server failed to create user session. 69 - {{ else }} 70 - Internal Server error. 71 - {{ end }} 72 - Please try again. 73 - </p> 74 - </div> 75 - </div> 76 - {{ end }} 77 59 <p class="text-sm text-gray-500"> 78 60 Don't have an account? <a href="/signup" class="underline">Create an account</a> on Tangled now! 79 61 </p>
-23
appview/pagination/page.go
··· 1 1 package pagination 2 2 3 - import "context" 4 - 5 3 type Page struct { 6 4 Offset int // where to start from 7 5 Limit int // number of items in a page ··· 12 10 Offset: 0, 13 11 Limit: 30, 14 12 } 15 - } 16 - 17 - type ctxKey struct{} 18 - 19 - func IntoContext(ctx context.Context, page Page) context.Context { 20 - return context.WithValue(ctx, ctxKey{}, page) 21 - } 22 - 23 - func FromContext(ctx context.Context) Page { 24 - if ctx == nil { 25 - return FirstPage() 26 - } 27 - v := ctx.Value(ctxKey{}) 28 - if v == nil { 29 - return FirstPage() 30 - } 31 - page, ok := v.(Page) 32 - if !ok { 33 - return FirstPage() 34 - } 35 - return page 36 13 } 37 14 38 15 func (p Page) Previous() Page {
+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
··· 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
··· 67 67 return 68 68 } 69 69 70 - rp.pages.Error503(w) 70 + rp.pages.Error503(w, pages.ErrorPageParams{ 71 + LoggedInUser: user, 72 + }) 71 73 l.Error("failed to build index response", "err", err) 72 74 return 73 75 }
+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
-1
appview/state/follow.go
··· 26 26 subjectIdent, err := s.idResolver.ResolveIdent(r.Context(), subject) 27 27 if err != nil { 28 28 log.Println("failed to follow, invalid did") 29 - return 30 29 } 31 30 32 31 if currentUser.Did == subjectIdent.DID.String() {
+10 -3
appview/state/gfi.go
··· 18 18 func (s *State) GoodFirstIssues(w http.ResponseWriter, r *http.Request) { 19 19 user := s.oauth.GetUser(r) 20 20 21 - page := pagination.FromContext(r.Context()) 21 + page, ok := r.Context().Value("page").(pagination.Page) 22 + if !ok { 23 + page = pagination.FirstPage() 24 + } 22 25 23 26 goodFirstIssueLabel := fmt.Sprintf("at://%s/%s/%s", consts.TangledDid, tangled.LabelDefinitionNSID, "good-first-issue") 24 27 25 28 repoLabels, err := db.GetRepoLabels(s.db, db.FilterEq("label_at", goodFirstIssueLabel)) 26 29 if err != nil { 27 30 log.Println("failed to get repo labels", err) 28 - s.pages.Error503(w) 31 + s.pages.Error503(w, pages.ErrorPageParams{ 32 + LoggedInUser: user, 33 + }) 29 34 return 30 35 } 31 36 ··· 54 59 ) 55 60 if err != nil { 56 61 log.Println("failed to get issues", err) 57 - s.pages.Error503(w) 62 + s.pages.Error503(w, pages.ErrorPageParams{ 63 + LoggedInUser: user, 64 + }) 58 65 return 59 66 } 60 67
-2
appview/state/login.go
··· 14 14 switch r.Method { 15 15 case http.MethodGet: 16 16 returnURL := r.URL.Query().Get("return_url") 17 - errorCode := r.URL.Query().Get("error") 18 17 s.pages.Login(w, pages.LoginParams{ 19 18 ReturnUrl: returnURL, 20 - ErrorCode: errorCode, 21 19 }) 22 20 case http.MethodPost: 23 21 handle := r.FormValue("handle")
+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
··· 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
··· 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 {
+1 -1
spindle/engines/nixery/engine.go
··· 222 222 }, 223 223 ReadonlyRootfs: false, 224 224 CapDrop: []string{"ALL"}, 225 - CapAdd: []string{"CAP_DAC_OVERRIDE", "CAP_CHOWN", "CAP_FOWNER", "CAP_SETUID", "CAP_SETGID"}, 225 + CapAdd: []string{"CAP_DAC_OVERRIDE"}, 226 226 SecurityOpt: []string{"no-new-privileges"}, 227 227 ExtraHosts: []string{"host.docker.internal:host-gateway"}, 228 228 }, nil, nil, "")