arche / internal/archesrv/handlers_wiki.go

commit 154431fd
  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}