internal/httpd/searchweb.go

v1.30.0
gitbay/internal/httpd/searchweb.go history · blame · raw

73 lines · 1966 bytes

 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}