1package archesrv
2
3import (
4 "html/template"
5 "net/http"
6 "strings"
7
8 "arche/internal/markdown"
9 "arche/internal/wiki"
10)
11
12type srvWikiListData struct {
13 Repo string
14 User *User
15 Pages []wiki.Page
16}
17
18type srvWikiPageData struct {
19 Repo string
20 User *User
21 Title string
22 RawContent string
23 RenderedContent template.HTML
24 Editing bool
25}
26
27func (s *forgeServer) handleRepoWikiList(w http.ResponseWriter, r *http.Request) {
28 repoName := r.PathValue("repo")
29 rec, err := s.db.GetRepo(repoName)
30 if err != nil || rec == nil {
31 http.NotFound(w, r)
32 return
33 }
34 user := s.db.currentUser(r)
35 if !s.db.CanRead(rec, user) {
36 http.Error(w, "Unauthorized", http.StatusUnauthorized)
37 return
38 }
39 idb, err := s.openIssueDB(repoName)
40 if err != nil {
41 http.Error(w, "open wikidb: "+err.Error(), http.StatusInternalServerError)
42 return
43 }
44 defer idb.Close()
45 pages, err := idb.Wiki.List()
46 if err != nil {
47 http.Error(w, "list pages: "+err.Error(), http.StatusInternalServerError)
48 return
49 }
50 s.render(w, "srv_repo_wiki_list.html", srvWikiListData{Repo: repoName, User: user, Pages: pages})
51}
52
53func (s *forgeServer) handleRepoWikiPage(w http.ResponseWriter, r *http.Request) {
54 repoName := r.PathValue("repo")
55 rec, err := s.db.GetRepo(repoName)
56 if err != nil || rec == nil {
57 http.NotFound(w, r)
58 return
59 }
60 user := s.db.currentUser(r)
61 if !s.db.CanRead(rec, user) {
62 http.Error(w, "Unauthorized", http.StatusUnauthorized)
63 return
64 }
65
66 title := r.PathValue("title")
67 if title == "" {
68 title = "Home"
69 }
70
71 idb, err := s.openIssueDB(repoName)
72 if err != nil {
73 http.Error(w, "open wikidb: "+err.Error(), http.StatusInternalServerError)
74 return
75 }
76 defer idb.Close()
77
78 editing := r.URL.Query().Get("edit") == "1" && user != nil
79
80 page, err := idb.Wiki.Get(title)
81 if err != nil {
82 s.render(w, "srv_repo_wiki_page.html", srvWikiPageData{
83 Repo: repoName,
84 User: user,
85 Title: title,
86 Editing: user != nil,
87 })
88 return
89 }
90
91 data := srvWikiPageData{
92 Repo: repoName,
93 User: user,
94 Title: title,
95 RawContent: page.Content,
96 Editing: editing,
97 }
98 if !editing && page.Content != "" {
99 data.RenderedContent = markdown.Render(page.Content)
100 }
101 s.render(w, "srv_repo_wiki_page.html", data)
102}
103
104func (s *forgeServer) handleRepoWikiSave(w http.ResponseWriter, r *http.Request) {
105 repoName := r.PathValue("repo")
106 rec, err := s.db.GetRepo(repoName)
107 if err != nil || rec == nil {
108 http.NotFound(w, r)
109 return
110 }
111 user := s.db.currentUser(r)
112 if user == nil {
113 http.Error(w, "login required", http.StatusUnauthorized)
114 return
115 }
116 if !s.db.CanRead(rec, user) {
117 http.Error(w, "Unauthorized", http.StatusUnauthorized)
118 return
119 }
120
121 title := r.PathValue("title")
122 if title == "" {
123 title = "Home"
124 }
125
126 r.ParseForm() //nolint:errcheck
127 content := strings.TrimRight(r.FormValue("content"), "\r\n")
128
129 idb, err := s.openIssueDB(repoName)
130 if err != nil {
131 http.Error(w, "open wikidb: "+err.Error(), http.StatusInternalServerError)
132 return
133 }
134 defer idb.Close()
135
136 if err := idb.Wiki.Set(title, content, user.Username); err != nil {
137 http.Error(w, "save page: "+err.Error(), http.StatusInternalServerError)
138 return
139 }
140 http.Redirect(w, r, "/"+repoName+"/wiki/"+title, http.StatusFound)
141}