internal/httpd/searchweb.go
73 lines · 1966 bytes
3 symbols in this file
1package httpd
2
3import (
4 "net/http"
5 "strconv"
6 "strings"
7
8 "gitbay.org/gitbay/internal/control"
9 "gitbay.org/gitbay/internal/store"
10)
11
12// searchResult is one hit as the template renders it: the link is built
13// here so the template does not have to know each kind's URL shape.
14type searchResult struct {
15 control.SearchResult
16 Marker string
17 Href string
18}
19
20// globalSearch is /search: repositories, issues and merge requests across
21// the instance. It is readable without a session — a visitor sees exactly
22// the public rows — so it runs control.Search directly rather than
23// dispatching a command as a user who may not exist.
24func (s *Server) globalSearch(w http.ResponseWriter, r *http.Request) {
25 var viewer store.User
26 if s.cfg.Web.Mode == "accounts" {
27 viewer = s.viewer(r)
28 }
29 q := strings.TrimSpace(r.URL.Query().Get("q"))
30 kind := r.URL.Query().Get("kind")
31 if kind != "repo" && kind != "issue" && kind != "mr" {
32 kind = ""
33 }
34 var kinds []string
35 if kind != "" {
36 kinds = []string{kind}
37 }
38 var results []searchResult
39 var queryErr string
40 if q != "" {
41 if len(q) < 2 || len(q) > 200 {
42 queryErr = "query must be 2 to 200 characters"
43 } else {
44 hits, err := control.Search(s.st, s.cfg.Server.Root, viewer.ID, q, kinds)
45 if err != nil {
46 http.Error(w, "internal error", http.StatusInternalServerError)
47 return
48 }
49 for _, h := range hits {
50 results = append(results, searchResult{h, control.SearchMarker(h.Kind), searchHref(h)})
51 }
52 }
53 }
54 s.render(w, "globalsearch.html", struct {
55 basePage
56 Tab string
57 Query string
58 Kind string
59 QueryErr string
60 Results []searchResult
61 }{s.baseFor(viewer), "sitesearch", q, kind, queryErr, results})
62}
63
64func searchHref(h control.SearchResult) string {
65 switch h.Kind {
66 case "issue":
67 return "/" + h.Repo + "/issues/" + strconv.FormatInt(h.Number, 10)
68 case "mr":
69 return "/" + h.Repo + "/mrs/" + strconv.FormatInt(h.Number, 10)
70 default:
71 return "/" + h.Repo
72 }
73}