internal/httpd/page.go
71 lines · 2017 bytes
1package httpd
2
3import (
4 "net/http"
5
6 "gitbay.org/gitbay/internal/policy"
7 "gitbay.org/gitbay/internal/store"
8)
9
10// railRepo is one pinned repository in the rail.
11type railRepo struct {
12 Owner string
13 Name string
14}
15
16// rail is the viewer's cross-repo state the layout needs. The rail itself
17// is icons only, so what is left is the unread count on its bell; the
18// pinned repositories it used to list are rendered by the dashboard.
19type rail struct {
20 Pinned []railRepo
21 Unread int
22}
23
24// basePage is what the layout needs on every page, repo or not. Page
25// structs embed it so the rail and the site name are always in scope.
26type basePage struct {
27 // Site is the instance's display name; Host is the name a command or
28 // URL must use. Anything copy-pasteable takes Host.
29 Site string
30 Host string
31 Viewer string
32 Admin bool // the viewer is an instance admin: the rail shows /admin
33 Rail rail
34}
35
36// base builds the layout-wide data for a request that has not already
37// resolved a viewer.
38func (s *Server) base(r *http.Request) basePage {
39 if s.cfg.Web.Mode != "accounts" {
40 return basePage{Site: s.siteName(), Host: s.cfg.SiteHost()}
41 }
42 return s.baseFor(s.viewer(r))
43}
44
45// baseFor is base for a handler that already holds the viewer, so the
46// session lookup is not repeated.
47func (s *Server) baseFor(viewer store.User) basePage {
48 b := basePage{Site: s.siteName(), Host: s.cfg.SiteHost()}
49 if viewer.ID == 0 {
50 return b
51 }
52 b.Viewer = viewer.Username
53 b.Admin = viewer.IsAdmin
54 b.Rail = s.railFor(viewer)
55 return b
56}
57
58// railFor collects the viewer's pinned repositories and unread count,
59// dropping anything they may no longer read.
60func (s *Server) railFor(viewer store.User) rail {
61 var rl rail
62 pinned, _ := s.st.PinnedRepos(viewer.ID)
63 for _, rp := range pinned {
64 grant, _ := s.st.AccessRole(rp.ID, viewer.ID)
65 if policy.CanRead(viewer, rp, grant) {
66 rl.Pinned = append(rl.Pinned, railRepo{Owner: rp.OwnerName, Name: rp.Name})
67 }
68 }
69 rl.Unread = s.st.UnreadNotices(viewer.ID)
70 return rl
71}