Commit 6a1ce6c2c8
6a1ce6c2c89ba7f547d1932096877e84359b1527
parent: 85ec9f4218
Verified · cmc
cmc <hello@cleberg.net> · 2026-09-12 05:01 UTC
web: the editor explains a refusal before the textarea
Ref #182
e2e/accounts_test.go
+7
| @@ -189,6 +189,13 @@ func TestWebAccounts(t *testing.T) { |
| 189 | 189 | t.Fatalf("require-signed web edit not refused:\n%s", body) |
| 190 | 190 | } |
| 191 | 191 | |
| 192 | // With signed commits required the editor cannot succeed, so the GET |
| 193 | // form says so instead of offering a textarea. |
| 194 | status, body = browserGet(t, browser, inst.base()+"/alice/site/edit/main/notes.txt") |
| 195 | if status != 200 || !strings.Contains(body, "requires signed commits") || strings.Contains(body, "<textarea") { |
| 196 | t.Fatalf("edit page under require-signed: %d\n%s", status, body) |
| 197 | } |
| 198 | |
| 192 | 199 | // Issue participation through the web. |
| 193 | 200 | if _, _, code := inst.ssh(t, aliceKey, "", "issue", "create", "alice/site", "--title", "'from ssh'"); code != 0 { |
| 194 | 201 | t.Fatal("issue create failed") |
internal/httpd/accounts.go
+11 −1
| @@ -479,6 +479,7 @@ type editPage struct { |
| 479 | 479 | Path string |
| 480 | 480 | Content string |
| 481 | 481 | Error string |
| 482 | Blocked string |
| 482 | 483 | } |
| 483 | 484 | |
| 484 | 485 | func (s *Server) editForm(w http.ResponseWriter, r *http.Request, u store.User) { |
| @@ -488,6 +489,15 @@ func (s *Server) editForm(w http.ResponseWriter, r *http.Request, u store.User) |
| 488 | 489 | } |
| 489 | 490 | ref := r.PathValue("ref") |
| 490 | 491 | filePath := strings.Trim(r.PathValue("path"), "/") |
| 492 | |
| 493 | blocked := "" |
| 494 | switch { |
| 495 | case repo.Settings.RequireSignedCommits: |
| 496 | blocked = repo.Path() + " requires signed commits and the web editor cannot sign; edit locally and push a signed commit." |
| 497 | case repo.Settings.RequireMR && slices.Contains(repo.Settings.ProtectedBranches, ref): |
| 498 | blocked = "branch " + ref + " accepts changes through merge requests only; edit on another branch and open one." |
| 499 | } |
| 500 | |
| 491 | 501 | dir := control.RepoDir(s.cfg.Server.Root, repo.OwnerName, repo.Name) |
| 492 | 502 | content, err := gitutil.ReadBlob(dir, "refs/heads/"+ref, filePath, maxRenderBytes) |
| 493 | 503 | if err != nil { |
| @@ -499,7 +509,7 @@ func (s *Server) editForm(w http.ResponseWriter, r *http.Request, u store.User) |
| 499 | 509 | } |
| 500 | 510 | s.render(w, "edit.html", editPage{ |
| 501 | 511 | basePage: s.baseFor(u), Repo: repo, |
| 502 | | Ref: ref, Path: filePath, Content: string(content), |
| 512 | Ref: ref, Path: filePath, Content: string(content), Blocked: blocked, |
| 503 | 513 | }) |
| 504 | 514 | } |
| 505 | 515 | |
internal/web/templates/edit.html
+2
| @@ -2,6 +2,7 @@ |
| 2 | 2 | {{define "content"}} |
| 3 | 3 | <h1>edit {{.Repo.OwnerName}}/{{.Repo.Name}} : {{.Path}} @ {{.Ref}}</h1> |
| 4 | 4 | {{if .Error}}<p class="error" role="alert">{{.Error}}</p>{{end}} |
| 5 | {{if .Blocked}}<p class="empty-note">{{.Blocked}}</p>{{else}} |
| 5 | 6 | <form method="post" action="/{{.Repo.OwnerName}}/{{.Repo.Name}}/edit/{{.Ref}}/{{.Path}}" class="editform"> |
| 6 | 7 | <p><textarea name="content" aria-label="File contents" rows="24" spellcheck="false">{{.Content}}</textarea></p> |
| 7 | 8 | <p><input name="message" aria-label="Commit message" placeholder="commit message"> |
| @@ -9,3 +10,4 @@ |
| 9 | 10 | <p class="crumbs">this commit will be unsigned and authored as {{.Viewer}}</p> |
| 10 | 11 | </form> |
| 11 | 12 | {{end}} |
| 13 | {{end}} |