Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

A free and open-source forge that lives in your Git repo.

Expand the admin status page into an operational dashboard

4506a4d3d279556435fdd414265e7499c3dada16 · Keenan Nemetz · 14d ago · parent 2e024cc9

server/web/auth.go +32−1

@@ -101,15 +101,22 @@ func (w *Web) principal(r *http.Request) *principal {
101 101 type statusWriter struct {
102 102 http.ResponseWriter
103 103 wroteHeader bool
104 status int
104 105 }
105 106
106 107 func (s *statusWriter) WriteHeader(code int) {
108 if !s.wroteHeader {
109 s.status = code
110 }
107 111 s.wroteHeader = true
108 112 s.ResponseWriter.WriteHeader(code)
109 113 }
110 114
111 115 func (s *statusWriter) Write(b []byte) (int, error) {
112 s.wroteHeader = true
116 if !s.wroteHeader {
117 s.wroteHeader = true
118 s.status = http.StatusOK
119 }
113 120 return s.ResponseWriter.Write(b)
114 121 }
115 122
@@ -168,9 +175,33 @@ func (w *Web) Middleware(next http.Handler) http.Handler {
168 175 w.serverError(sw, r, "")
169 176 }()
170 177 next.ServeHTTP(sw, r)
178 w.recordPageView(r, sw)
171 179 })
172 180 }
173 181
182 // recordPageView counts a successfully rendered HTML page. Static files, Git
183 // traffic, redirects, HTMX fragments and the status page itself are excluded, so
184 // the metric follows reading rather than polling or asset loads. It is
185 // best-effort: analytics must never turn a page into an error.
186 func (w *Web) recordPageView(r *http.Request, sw *statusWriter) {
187 if w.PageViews == nil || r.Method != http.MethodGet || sw.status != http.StatusOK {
188 return
189 }
190 if r.Header.Get("HX-Request") == "true" || r.URL.Path == "/status" {
191 return
192 }
193 if !strings.HasPrefix(sw.Header().Get("Content-Type"), "text/html") {
194 return
195 }
196 account := ""
197 if pr := w.principal(r); pr != nil {
198 account = pr.account.Name
199 }
200 if err := w.PageViews.Record(account, time.Now().UTC()); err != nil && w.Logger != nil {
201 w.Logger("page view: %v", err)
202 }
203 }
204
174 205 // sessionFromCookie returns the first valid session cookie and the name it came
175 206 // from. The dev cookie is only considered when dev login is enabled, so a stray
176 207 // cookie on a normal instance is never a credential.