1diff --git a/main.go b/main.go
2index ab4aee90d096f54cc9235ea4b5e48c27a206774b..797ebea41f73cc63fed21d9fdd12a7cd2bbe4f78 100644
3--- a/main.go
4+++ b/main.go
5@@ -74,8 +74,7 @@ if err != nil {
6 return err
7 }
8
9- // checking chroma configurationo
10-
11+ // checking chroma configuration
12 if _, ok := styles.Registry[configRepo.GetSyntaxHighlight()]; !ok {
13 slog.Warn(
14 "Invalid Syntax highlight selected",
15@@ -87,8 +86,13 @@ }
16
17 // services
18 gitService := service.NewGitService(configRepo)
19+ authService := service.NewAuthService(configRepo)
20
21- handler, err := handler.MountHandler(gitService, configRepo)
22+ handler, err := handler.MountHandler(
23+ gitService,
24+ authService,
25+ configRepo,
26+ )
27 if err != nil {
28 return err
29 }
30diff --git a/pkg/config/config.go b/pkg/config/config.go
31index 812a06ef7ead3d270cd1b2d7d5d31a3033aabc5e..da6e0e7044745edf7ef9a5b3e720f97b2ce62df0 100644
32--- a/pkg/config/config.go
33+++ b/pkg/config/config.go
34@@ -55,8 +55,8 @@ // information.
35 ConfigurationRepository struct {
36 rootReadme string
37 listenAddr string
38- passphrase string
39- aesKey string
40+ passphrase []byte
41+ aesKey []byte
42 syntaxHighlight string
43 repositories []*GitRepositoryConfiguration
44 }
45@@ -74,9 +74,9 @@ return nil, err
46 }
47
48 repo := &ConfigurationRepository{
49- aesKey: config.AESKey,
50+ aesKey: []byte(config.AESKey),
51 listenAddr: config.ListenAddr,
52- passphrase: config.Passphrase,
53+ passphrase: []byte(config.Passphrase),
54 repositories: config.Repositories,
55 rootReadme: config.RootReadme,
56 syntaxHighlight: config.SyntaxHighlight,
57@@ -103,6 +103,14 @@ }
58
59 func (c *ConfigurationRepository) GetListenAddr() string {
60 return c.listenAddr
61+}
62+
63+func (c *ConfigurationRepository) GetPassphrase() []byte {
64+ return c.passphrase
65+}
66+
67+func (c *ConfigurationRepository) GetBase64AesKey() []byte {
68+ return c.aesKey
69 }
70
71 // GetByName returns configuration of repository for a given name.
72diff --git a/pkg/ext/auth.go b/pkg/ext/auth.go
73new file mode 100644
74index 0000000000000000000000000000000000000000..bb6c0a2c07f23394ead3809aa54390326fd0fcd0
75--- /dev/null
76+++ b/pkg/ext/auth.go
77@@ -0,0 +1,45 @@
78+package ext
79+
80+import (
81+ "context"
82+ "encoding/base64"
83+ "log/slog"
84+ "net/http"
85+)
86+
87+type authService interface {
88+ ValidateToken(token []byte) (bool, error)
89+}
90+
91+func Authenticate(auth authService) func(next http.HandlerFunc) http.HandlerFunc {
92+ return func(next http.HandlerFunc) http.HandlerFunc {
93+ return func(w http.ResponseWriter, r *http.Request) {
94+ cookie, err := r.Cookie("auth")
95+ if err != nil {
96+ slog.Error("Error loading cookie", "error", err)
97+ next(w, r)
98+ return
99+ }
100+
101+ value, err := base64.StdEncoding.DecodeString(cookie.Value)
102+ if err != nil {
103+ slog.Error("Error decoding", "error", err)
104+ next(w, r)
105+ return
106+ }
107+
108+ valid, err := auth.ValidateToken(value)
109+ if err != nil {
110+ slog.Error("Error validating token", "error", err, "cookie", cookie.Value)
111+ next(w, r)
112+ return
113+ }
114+
115+ ctx := r.Context()
116+ ctx = context.WithValue(ctx, "logged", true)
117+
118+ slog.Info("Validated token", "valid?", valid)
119+ next(w, r.WithContext(ctx))
120+ }
121+ }
122+}
123diff --git a/pkg/ext/router.go b/pkg/ext/router.go
124index 96da1c9399992e589bbd4fefdb0bfc78b5e59b80..956254d06334a443ea3e66b37bded75847120230 100644
125--- a/pkg/ext/router.go
126+++ b/pkg/ext/router.go
127@@ -23,6 +23,7 @@ return &Router{
128 router: http.NewServeMux(),
129 }
130 }
131+
132 func (r *Router) Handler() http.Handler {
133 return r.router
134 }
135@@ -35,9 +36,9 @@ func wrapError(next ErrorRequestHandler) http.HandlerFunc {
136 return func(w http.ResponseWriter, r *http.Request) {
137 if err := next(w, r); err != nil {
138 if errors.Is(err, service.ErrRepositoryNotFound) {
139- NotFound(w)
140+ NotFound(w, r)
141 } else {
142- InternalServerError(w, err)
143+ InternalServerError(r, w, err)
144 }
145 }
146 }
147@@ -57,16 +58,21 @@ func (r *Router) HandleFunc(path string, handler ErrorRequestHandler) {
148 r.router.HandleFunc(path, r.run(handler))
149 }
150
151-func NotFound(w http.ResponseWriter) {
152+func NotFound(w http.ResponseWriter, r *http.Request) {
153 w.WriteHeader(http.StatusNotFound)
154 templates.WritePageTemplate(w, &templates.ErrorPage{
155 Message: "Not Found",
156- })
157+ }, r.Context())
158 }
159
160-func InternalServerError(w http.ResponseWriter, err error) {
161+func Redirect(w http.ResponseWriter, location string) {
162+ w.Header().Add("location", location)
163+ w.WriteHeader(http.StatusTemporaryRedirect)
164+}
165+
166+func InternalServerError(r *http.Request, w http.ResponseWriter, err error) {
167 w.WriteHeader(http.StatusInternalServerError)
168 templates.WritePageTemplate(w, &templates.ErrorPage{
169 Message: fmt.Sprintf("Internal Server Error:\n%s", err.Error()),
170- })
171+ }, r.Context())
172 }
173diff --git a/pkg/handler/about/handler.go b/pkg/handler/about/handler.go
174index ac3d31417836e98121bd03807b2993fa2dbf27cb..ee084cd38dc3bf6124cd8e7462005446cfb0222c 100644
175--- a/pkg/handler/about/handler.go
176+++ b/pkg/handler/about/handler.go
177@@ -26,7 +26,7 @@ func NewAboutHandler(configRepo configurationRepository) *AboutHandler {
178 return &AboutHandler{configRepo.GetRootReadme()}
179 }
180
181-func (g *AboutHandler) About(w http.ResponseWriter, _ *http.Request) error {
182+func (g *AboutHandler) About(w http.ResponseWriter, r *http.Request) error {
183 f, err := os.Open(g.readmePath)
184 if err != nil {
185 return err
186@@ -50,6 +50,6 @@
187 gitList := &templates.AboutPage{
188 Body: bs,
189 }
190- templates.WritePageTemplate(w, gitList)
191+ templates.WritePageTemplate(w, gitList, r.Context())
192 return nil
193 }
194diff --git a/pkg/handler/auth/login.go b/pkg/handler/auth/login.go
195index 7e77a67ba295d77bb0b742eb3ccefea98d9fd411..7014548c0965def2eba242a03ae269b8c27f7a00 100644
196--- a/pkg/handler/auth/login.go
197+++ b/pkg/handler/auth/login.go
198@@ -1,20 +1,87 @@
199 package auth
200
201 import (
202+ "encoding/base64"
203 "net/http"
204+ "time"
205
206 "git.gabrielgio.me/cerrado/pkg/ext"
207 "git.gabrielgio.me/cerrado/templates"
208 )
209
210 type (
211- LoginHandler struct{}
212+ LoginHandler struct {
213+ auth authService
214+ }
215+
216+ authService interface {
217+ CheckAuth(username, password string) bool
218+ IssueToken() ([]byte, error)
219+ }
220 )
221
222+func NewLoginHandler(auth authService) *LoginHandler {
223+ return &LoginHandler{
224+ auth: auth,
225+ }
226+}
227+
228+func (g *LoginHandler) Logout(w http.ResponseWriter, r *http.Request) error {
229+ cookie := &http.Cookie{
230+ Name: "auth",
231+ Value: "",
232+ Path: "/",
233+ Expires: time.Unix(0, 0),
234+ }
235+
236+ referer := r.Header.Get("Referer")
237+ if referer == "" {
238+ referer = "/"
239+ }
240+
241+ http.SetCookie(w, cookie)
242+ ext.Redirect(w, referer)
243+ return nil
244+}
245+
246 func (g *LoginHandler) Login(w http.ResponseWriter, r *http.Request) error {
247- ext.SetHTML(w)
248+ if r.Method == "GET" {
249+ ext.SetHTML(w)
250+
251+ login := &templates.LoginPage{}
252+ templates.WritePageTemplate(w, login, r.Context())
253+ } else if r.Method == "POST" {
254+
255+ username := r.FormValue("username")
256+ password := r.FormValue("password")
257+
258+ if !g.auth.CheckAuth(username, password) {
259+ login := &templates.LoginPage{
260+ ErrorMessage: "Invalid login",
261+ }
262+ templates.WritePageTemplate(w, login, r.Context())
263+ } else {
264+
265+ bytes, err := g.auth.IssueToken()
266+ if err != nil {
267+ return err
268+ }
269+
270+ cookie := &http.Cookie{
271+ Name: "auth",
272+ Value: base64.StdEncoding.EncodeToString(bytes),
273+ Path: "/",
274+ MaxAge: 3600,
275+ HttpOnly: true,
276+ Secure: true,
277+ SameSite: http.SameSiteStrictMode,
278+ }
279+
280+ http.SetCookie(w, cookie)
281+ ext.Redirect(w, "/")
282+ }
283
284- login := &templates.LoginPage{}
285- templates.WritePageTemplate(w, login)
286+ }
287+
288 return nil
289 }
290diff --git a/pkg/handler/git/handler.go b/pkg/handler/git/handler.go
291index 5739c8e9dbca0c7b015224ed3af26f53118eb72c..42761595323c97d0ea49dc3fe69d618446284bcc 100644
292--- a/pkg/handler/git/handler.go
293+++ b/pkg/handler/git/handler.go
294@@ -43,7 +43,7 @@ config: confRepo,
295 }
296 }
297
298-func (g *GitHandler) List(w http.ResponseWriter, _ *http.Request) error {
299+func (g *GitHandler) List(w http.ResponseWriter, r *http.Request) error {
300 repos, err := g.gitService.ListRepositories()
301 if err != nil {
302 return err
303@@ -73,7 +73,7 @@ gitList := &templates.GitListPage{
304 Respositories: repos,
305 About: bs,
306 }
307- templates.WritePageTemplate(w, gitList)
308+ templates.WritePageTemplate(w, gitList, r.Context())
309 return nil
310 }
311
312@@ -85,7 +85,7 @@ ref := strings.TrimSuffix(file, ".tar.gz")
313
314 // TODO: remove it once we can support more than gzip
315 if !strings.HasSuffix(file, ".tar.gz") {
316- ext.NotFound(w)
317+ ext.NotFound(w, r)
318 return nil
319 }
320
321@@ -135,7 +135,7 @@ Branches: branches,
322 Commits: commits,
323 },
324 }
325- templates.WritePageTemplate(w, gitList)
326+ templates.WritePageTemplate(w, gitList, r.Context())
327 return nil
328 }
329
330@@ -155,7 +155,7 @@ Ref: ref.Name().Short(),
331 GitItemBase: &templates.GitItemAboutPage{
332 About: []byte("About file not configured properly"),
333 },
334- })
335+ }, r.Context())
336 return nil
337 }
338 if err != nil {
339@@ -179,7 +179,7 @@ GitItemBase: &templates.GitItemAboutPage{
340 About: bs,
341 },
342 }
343- templates.WritePageTemplate(w, gitList)
344+ templates.WritePageTemplate(w, gitList, r.Context())
345 return nil
346 }
347
348@@ -210,7 +210,7 @@ Tags: tags,
349 Branches: branches,
350 },
351 }
352- templates.WritePageTemplate(w, gitList)
353+ templates.WritePageTemplate(w, gitList, r.Context())
354 return nil
355 }
356
357@@ -239,7 +239,7 @@ Path: paths,
358 Tree: tree,
359 },
360 }
361- templates.WritePageTemplate(w, gitList)
362+ templates.WritePageTemplate(w, gitList, r.Context())
363 return nil
364 }
365
366@@ -270,7 +270,7 @@ Path: paths,
367 Content: []byte("Binary file"),
368 },
369 }
370- templates.WritePageTemplate(w, gitList)
371+ templates.WritePageTemplate(w, gitList, r.Context())
372 return nil
373 }
374
375@@ -307,7 +307,7 @@ Path: paths,
376 Content: code.Bytes(),
377 },
378 }
379- templates.WritePageTemplate(w, gitList)
380+ templates.WritePageTemplate(w, gitList, r.Context())
381 return nil
382 }
383
384@@ -328,7 +328,7 @@ GitItemBase: &templates.GitItemLogPage{
385 Commits: commits,
386 },
387 }
388- templates.WritePageTemplate(w, gitList)
389+ templates.WritePageTemplate(w, gitList, r.Context())
390 return nil
391 }
392
393@@ -355,7 +355,7 @@ Commit: commit,
394 Diff: diff,
395 },
396 }
397- templates.WritePageTemplate(w, gitList)
398+ templates.WritePageTemplate(w, gitList, r.Context())
399 return nil
400 }
401
402diff --git a/pkg/handler/router.go b/pkg/handler/router.go
403index 32bd78adff98f82bca843aba96d2ddb85d7c79f7..ee4081b504b8291e24926062dfb9bc1765119874 100644
404--- a/pkg/handler/router.go
405+++ b/pkg/handler/router.go
406@@ -17,12 +17,13 @@ // This functons wraps the whole handler package and wraps it into one part so
407 // its sub package don't leak in other places.
408 func MountHandler(
409 gitService *service.GitService,
410+ authService *service.AuthService,
411 configRepo *serverconfig.ConfigurationRepository,
412 ) (http.Handler, error) {
413 var (
414 gitHandler = git.NewGitHandler(gitService, configRepo)
415 aboutHandler = about.NewAboutHandler(configRepo)
416- loginHandler = &auth.LoginHandler{}
417+ loginHandler = auth.NewLoginHandler(authService)
418 )
419
420 staticHandler, err := static.ServeStaticHandler()
421@@ -32,10 +33,12 @@ }
422
423 mux := ext.NewRouter()
424 mux.AddMiddleware(ext.Compress)
425+ mux.AddMiddleware(ext.Authenticate(authService))
426 mux.AddMiddleware(ext.Log)
427
428 mux.HandleFunc("/static/{file}", staticHandler)
429 mux.HandleFunc("/login/{$}", loginHandler.Login)
430+ mux.HandleFunc("/logout/{$}", loginHandler.Logout)
431 mux.HandleFunc("/{name}/about/{$}", gitHandler.About)
432 mux.HandleFunc("/{name}/", gitHandler.Summary)
433 mux.HandleFunc("/{name}/refs/{$}", gitHandler.Refs)
434diff --git a/pkg/service/auth.go b/pkg/service/auth.go
435index 1fbf4b61724c079a9557bc675846ba94d1ad370e..0dbd960ff2a49368f531da1b5ceb58719c8537fe 100644
436--- a/pkg/service/auth.go
437+++ b/pkg/service/auth.go
438@@ -23,7 +23,13 @@ GetBase64AesKey() []byte
439 }
440 )
441
442-var tokenSeed = []byte("cerrado")
443+var tokenSeed = []byte("this is a token for cerrado")
444+
445+func NewAuthService(repostiory authRepository) *AuthService {
446+ return &AuthService{
447+ authRepository: repostiory,
448+ }
449+}
450
451 func (a *AuthService) CheckAuth(username, password string) bool {
452 passphrase := a.authRepository.GetPassphrase()
453diff --git a/pkg/service/git.go b/pkg/service/git.go
454index f03ba426f3933a7bf8f1a9f1ff15e6b88613954a..6c3912fae3c57a3500849ef2e15d2616b838f144 100644
455--- a/pkg/service/git.go
456+++ b/pkg/service/git.go
457@@ -30,9 +30,7 @@ GetByName(name string) *config.GitRepositoryConfiguration
458 }
459 )
460
461-var (
462- ErrRepositoryNotFound = errors.New("Repository not found")
463-)
464+var ErrRepositoryNotFound = errors.New("Repository not found")
465
466 // TODO: make it configurable
467 const timeFormat = "2006.01.02 15:04:05"
468diff --git a/templates/about.qtpl b/templates/about.qtpl
469index faee50e18821c54e739efd5611c0b548cf94cc15..cfbf0d9001e0dea884eb1096834169bc2d620496 100644
470--- a/templates/about.qtpl
471+++ b/templates/about.qtpl
472@@ -1,16 +1,19 @@
473+{% import "context" %}
474+
475 {% code
476 type AboutPage struct {
477+ LoggedIn bool
478 Body []byte
479 }
480 %}
481
482-{% func (p *AboutPage) Title() %}Hello{% endfunc %}
483+{% func (p *AboutPage) Title(ctx context.Context) %}Hello{% endfunc %}
484
485-{% func (p *AboutPage) Navbar() %}{%= Navbar(About) %}{% endfunc %}
486+{% func (p *AboutPage) Navbar(ctx context.Context) %}{%= Navbar(ctx, About) %}{% endfunc %}
487
488-{% func (p *AboutPage) Content() %}
489+{% func (p *AboutPage) Content(ctx context.Context) %}
490 {%z= p.Body %}
491 {% endfunc %}
492
493-{% func (p *AboutPage) Script() %}
494+{% func (p *AboutPage) Script(ctx context.Context) %}
495 {% endfunc %}
496diff --git a/templates/about.qtpl.go b/templates/about.qtpl.go
497index 2c07ceb1818619df56672b4bea08b8b1af0bcb62..a640f7eddc849adab11651d44c5644ad367240d4 100644
498--- a/templates/about.qtpl.go
499+++ b/templates/about.qtpl.go
500@@ -5,130 +5,100 @@ //line templates/about.qtpl:1
501 package templates
502
503 //line templates/about.qtpl:1
504+import "context"
505+
506+//line templates/about.qtpl:3
507 import (
508 qtio422016 "io"
509
510 qt422016 "github.com/valyala/quicktemplate"
511 )
512
513-//line templates/about.qtpl:1
514+//line templates/about.qtpl:3
515 var (
516 _ = qtio422016.Copy
517 _ = qt422016.AcquireByteBuffer
518 )
519
520-//line templates/about.qtpl:2
521+//line templates/about.qtpl:4
522 type AboutPage struct {
523- Body []byte
524+ LoggedIn bool
525+ Body []byte
526 }
527
528-//line templates/about.qtpl:7
529-func (p *AboutPage) StreamTitle(qw422016 *qt422016.Writer) {
530-//line templates/about.qtpl:7
531+//line templates/about.qtpl:10
532+func (p *AboutPage) StreamTitle(qw422016 *qt422016.Writer, ctx context.Context) {
533+//line templates/about.qtpl:10
534 qw422016.N().S(`Hello`)
535-//line templates/about.qtpl:7
536-}
537-
538-//line templates/about.qtpl:7
539-func (p *AboutPage) WriteTitle(qq422016 qtio422016.Writer) {
540-//line templates/about.qtpl:7
541- qw422016 := qt422016.AcquireWriter(qq422016)
542-//line templates/about.qtpl:7
543- p.StreamTitle(qw422016)
544-//line templates/about.qtpl:7
545- qt422016.ReleaseWriter(qw422016)
546-//line templates/about.qtpl:7
547-}
548-
549-//line templates/about.qtpl:7
550-func (p *AboutPage) Title() string {
551-//line templates/about.qtpl:7
552- qb422016 := qt422016.AcquireByteBuffer()
553-//line templates/about.qtpl:7
554- p.WriteTitle(qb422016)
555-//line templates/about.qtpl:7
556- qs422016 := string(qb422016.B)
557-//line templates/about.qtpl:7
558- qt422016.ReleaseByteBuffer(qb422016)
559-//line templates/about.qtpl:7
560- return qs422016
561-//line templates/about.qtpl:7
562-}
563-
564-//line templates/about.qtpl:9
565-func (p *AboutPage) StreamNavbar(qw422016 *qt422016.Writer) {
566-//line templates/about.qtpl:9
567- StreamNavbar(qw422016, About)
568-//line templates/about.qtpl:9
569+//line templates/about.qtpl:10
570 }
571
572-//line templates/about.qtpl:9
573-func (p *AboutPage) WriteNavbar(qq422016 qtio422016.Writer) {
574-//line templates/about.qtpl:9
575+//line templates/about.qtpl:10
576+func (p *AboutPage) WriteTitle(qq422016 qtio422016.Writer, ctx context.Context) {
577+//line templates/about.qtpl:10
578 qw422016 := qt422016.AcquireWriter(qq422016)
579-//line templates/about.qtpl:9
580- p.StreamNavbar(qw422016)
581-//line templates/about.qtpl:9
582+//line templates/about.qtpl:10
583+ p.StreamTitle(qw422016, ctx)
584+//line templates/about.qtpl:10
585 qt422016.ReleaseWriter(qw422016)
586-//line templates/about.qtpl:9
587+//line templates/about.qtpl:10
588 }
589
590-//line templates/about.qtpl:9
591-func (p *AboutPage) Navbar() string {
592-//line templates/about.qtpl:9
593+//line templates/about.qtpl:10
594+func (p *AboutPage) Title(ctx context.Context) string {
595+//line templates/about.qtpl:10
596 qb422016 := qt422016.AcquireByteBuffer()
597-//line templates/about.qtpl:9
598- p.WriteNavbar(qb422016)
599-//line templates/about.qtpl:9
600+//line templates/about.qtpl:10
601+ p.WriteTitle(qb422016, ctx)
602+//line templates/about.qtpl:10
603 qs422016 := string(qb422016.B)
604-//line templates/about.qtpl:9
605+//line templates/about.qtpl:10
606 qt422016.ReleaseByteBuffer(qb422016)
607-//line templates/about.qtpl:9
608+//line templates/about.qtpl:10
609 return qs422016
610-//line templates/about.qtpl:9
611+//line templates/about.qtpl:10
612 }
613
614-//line templates/about.qtpl:11
615-func (p *AboutPage) StreamContent(qw422016 *qt422016.Writer) {
616-//line templates/about.qtpl:11
617- qw422016.N().S(`
618-`)
619 //line templates/about.qtpl:12
620- qw422016.N().Z(p.Body)
621+func (p *AboutPage) StreamNavbar(qw422016 *qt422016.Writer, ctx context.Context) {
622 //line templates/about.qtpl:12
623- qw422016.N().S(`
624-`)
625-//line templates/about.qtpl:13
626+ StreamNavbar(qw422016, ctx, About)
627+//line templates/about.qtpl:12
628 }
629
630-//line templates/about.qtpl:13
631-func (p *AboutPage) WriteContent(qq422016 qtio422016.Writer) {
632-//line templates/about.qtpl:13
633+//line templates/about.qtpl:12
634+func (p *AboutPage) WriteNavbar(qq422016 qtio422016.Writer, ctx context.Context) {
635+//line templates/about.qtpl:12
636 qw422016 := qt422016.AcquireWriter(qq422016)
637-//line templates/about.qtpl:13
638- p.StreamContent(qw422016)
639-//line templates/about.qtpl:13
640+//line templates/about.qtpl:12
641+ p.StreamNavbar(qw422016, ctx)
642+//line templates/about.qtpl:12
643 qt422016.ReleaseWriter(qw422016)
644-//line templates/about.qtpl:13
645+//line templates/about.qtpl:12
646 }
647
648-//line templates/about.qtpl:13
649-func (p *AboutPage) Content() string {
650-//line templates/about.qtpl:13
651+//line templates/about.qtpl:12
652+func (p *AboutPage) Navbar(ctx context.Context) string {
653+//line templates/about.qtpl:12
654 qb422016 := qt422016.AcquireByteBuffer()
655-//line templates/about.qtpl:13
656- p.WriteContent(qb422016)
657-//line templates/about.qtpl:13
658+//line templates/about.qtpl:12
659+ p.WriteNavbar(qb422016, ctx)
660+//line templates/about.qtpl:12
661 qs422016 := string(qb422016.B)
662-//line templates/about.qtpl:13
663+//line templates/about.qtpl:12
664 qt422016.ReleaseByteBuffer(qb422016)
665-//line templates/about.qtpl:13
666+//line templates/about.qtpl:12
667 return qs422016
668-//line templates/about.qtpl:13
669+//line templates/about.qtpl:12
670 }
671
672+//line templates/about.qtpl:14
673+func (p *AboutPage) StreamContent(qw422016 *qt422016.Writer, ctx context.Context) {
674+//line templates/about.qtpl:14
675+ qw422016.N().S(`
676+`)
677 //line templates/about.qtpl:15
678-func (p *AboutPage) StreamScript(qw422016 *qt422016.Writer) {
679+ qw422016.N().Z(p.Body)
680 //line templates/about.qtpl:15
681 qw422016.N().S(`
682 `)
683@@ -136,22 +106,22 @@ //line templates/about.qtpl:16
684 }
685
686 //line templates/about.qtpl:16
687-func (p *AboutPage) WriteScript(qq422016 qtio422016.Writer) {
688+func (p *AboutPage) WriteContent(qq422016 qtio422016.Writer, ctx context.Context) {
689 //line templates/about.qtpl:16
690 qw422016 := qt422016.AcquireWriter(qq422016)
691 //line templates/about.qtpl:16
692- p.StreamScript(qw422016)
693+ p.StreamContent(qw422016, ctx)
694 //line templates/about.qtpl:16
695 qt422016.ReleaseWriter(qw422016)
696 //line templates/about.qtpl:16
697 }
698
699 //line templates/about.qtpl:16
700-func (p *AboutPage) Script() string {
701+func (p *AboutPage) Content(ctx context.Context) string {
702 //line templates/about.qtpl:16
703 qb422016 := qt422016.AcquireByteBuffer()
704 //line templates/about.qtpl:16
705- p.WriteScript(qb422016)
706+ p.WriteContent(qb422016, ctx)
707 //line templates/about.qtpl:16
708 qs422016 := string(qb422016.B)
709 //line templates/about.qtpl:16
710@@ -160,3 +130,37 @@ //line templates/about.qtpl:16
711 return qs422016
712 //line templates/about.qtpl:16
713 }
714+
715+//line templates/about.qtpl:18
716+func (p *AboutPage) StreamScript(qw422016 *qt422016.Writer, ctx context.Context) {
717+//line templates/about.qtpl:18
718+ qw422016.N().S(`
719+`)
720+//line templates/about.qtpl:19
721+}
722+
723+//line templates/about.qtpl:19
724+func (p *AboutPage) WriteScript(qq422016 qtio422016.Writer, ctx context.Context) {
725+//line templates/about.qtpl:19
726+ qw422016 := qt422016.AcquireWriter(qq422016)
727+//line templates/about.qtpl:19
728+ p.StreamScript(qw422016, ctx)
729+//line templates/about.qtpl:19
730+ qt422016.ReleaseWriter(qw422016)
731+//line templates/about.qtpl:19
732+}
733+
734+//line templates/about.qtpl:19
735+func (p *AboutPage) Script(ctx context.Context) string {
736+//line templates/about.qtpl:19
737+ qb422016 := qt422016.AcquireByteBuffer()
738+//line templates/about.qtpl:19
739+ p.WriteScript(qb422016, ctx)
740+//line templates/about.qtpl:19
741+ qs422016 := string(qb422016.B)
742+//line templates/about.qtpl:19
743+ qt422016.ReleaseByteBuffer(qb422016)
744+//line templates/about.qtpl:19
745+ return qs422016
746+//line templates/about.qtpl:19
747+}
748diff --git a/templates/base.qtpl b/templates/base.qtpl
749index 566308f9c13c670c3106c8ba2c51230e533e00d8..2a42cb889be45ffeb308c0aae56cd37666f9e2f8 100644
750--- a/templates/base.qtpl
751+++ b/templates/base.qtpl
752@@ -1,5 +1,6 @@
753 This is a base page template. All the other template pages implement this interface.
754
755+{% import "context" %}
756 {% import "strconv" %}
757 {% import "time" %}
758
759@@ -9,10 +10,10 @@ %}
760
761 {% interface
762 Page {
763- Title()
764- Content()
765- Script()
766- Navbar()
767+ Title(ctx context.Context)
768+ Content(ctx context.Context)
769+ Script(ctx context.Context)
770+ Navbar(ctx context.Context)
771 }
772 %}
773
774@@ -24,6 +25,8 @@ }
775 return ""
776 }
777 %}
778+
779+
780
781 {% code func TimeFormat(t time.Time) string {
782 return t.Format("02.01.2006")
783@@ -35,24 +38,30 @@ return v
784 }
785 %}
786
787+{% code func IsLoggedIn(ctx context.Context) bool {
788+ t, ok := ctx.Value("logged").(bool)
789+ return ok && t
790+ }
791+%}
792+
793 Page prints a page implementing Page interface.
794-{% func PageTemplate(p Page) %}
795+{% func PageTemplate(p Page, ctx context.Context) %}
796 <!DOCTYPE html>
797 <html lang="en">
798 <head>
799 <meta charset="utf-8">
800 <link rel="icon" href="data:,">
801- <title>{%= p.Title() %}</title>
802+ <title>{%= p.Title(ctx) %}</title>
803 <link rel="stylesheet" href="/static/main{%s Slug %}.css">
804 <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
805 <meta name="viewport" content="width=device-width, initial-scale=1" />
806 </head>
807 <body>
808- {%= p.Navbar() %}
809+ {%= p.Navbar(ctx) %}
810 <div class="container">
811- {%= p.Content() %}
812+ {%= p.Content(ctx) %}
813 </div>
814 </body>
815- {%= p.Script() %}
816+ {%= p.Script(ctx) %}
817 </html>
818 {% endfunc %}
819diff --git a/templates/base.qtpl.go b/templates/base.qtpl.go
820index f8ff91f23386053a256a62cf482aaaaa4f68d5f7..5bb45323a0d55b6106c12d8370671c6e3e909553 100644
821--- a/templates/base.qtpl.go
822+++ b/templates/base.qtpl.go
823@@ -8,57 +8,60 @@ //line templates/base.qtpl:3
824 package templates
825
826 //line templates/base.qtpl:3
827+import "context"
828+
829+//line templates/base.qtpl:4
830 import "strconv"
831
832-//line templates/base.qtpl:4
833+//line templates/base.qtpl:5
834 import "time"
835
836-//line templates/base.qtpl:6
837+//line templates/base.qtpl:7
838 import (
839 qtio422016 "io"
840
841 qt422016 "github.com/valyala/quicktemplate"
842 )
843
844-//line templates/base.qtpl:6
845+//line templates/base.qtpl:7
846 var (
847 _ = qtio422016.Copy
848 _ = qt422016.AcquireByteBuffer
849 )
850
851-//line templates/base.qtpl:7
852+//line templates/base.qtpl:8
853 var Slug = ""
854
855-//line templates/base.qtpl:11
856+//line templates/base.qtpl:12
857 type Page interface {
858-//line templates/base.qtpl:11
859- Title() string
860-//line templates/base.qtpl:11
861- StreamTitle(qw422016 *qt422016.Writer)
862-//line templates/base.qtpl:11
863- WriteTitle(qq422016 qtio422016.Writer)
864-//line templates/base.qtpl:11
865- Content() string
866-//line templates/base.qtpl:11
867- StreamContent(qw422016 *qt422016.Writer)
868-//line templates/base.qtpl:11
869- WriteContent(qq422016 qtio422016.Writer)
870-//line templates/base.qtpl:11
871- Script() string
872-//line templates/base.qtpl:11
873- StreamScript(qw422016 *qt422016.Writer)
874-//line templates/base.qtpl:11
875- WriteScript(qq422016 qtio422016.Writer)
876-//line templates/base.qtpl:11
877- Navbar() string
878-//line templates/base.qtpl:11
879- StreamNavbar(qw422016 *qt422016.Writer)
880-//line templates/base.qtpl:11
881- WriteNavbar(qq422016 qtio422016.Writer)
882-//line templates/base.qtpl:11
883+//line templates/base.qtpl:12
884+ Title(ctx context.Context) string
885+//line templates/base.qtpl:12
886+ StreamTitle(qw422016 *qt422016.Writer, ctx context.Context)
887+//line templates/base.qtpl:12
888+ WriteTitle(qq422016 qtio422016.Writer, ctx context.Context)
889+//line templates/base.qtpl:12
890+ Content(ctx context.Context) string
891+//line templates/base.qtpl:12
892+ StreamContent(qw422016 *qt422016.Writer, ctx context.Context)
893+//line templates/base.qtpl:12
894+ WriteContent(qq422016 qtio422016.Writer, ctx context.Context)
895+//line templates/base.qtpl:12
896+ Script(ctx context.Context) string
897+//line templates/base.qtpl:12
898+ StreamScript(qw422016 *qt422016.Writer, ctx context.Context)
899+//line templates/base.qtpl:12
900+ WriteScript(qq422016 qtio422016.Writer, ctx context.Context)
901+//line templates/base.qtpl:12
902+ Navbar(ctx context.Context) string
903+//line templates/base.qtpl:12
904+ StreamNavbar(qw422016 *qt422016.Writer, ctx context.Context)
905+//line templates/base.qtpl:12
906+ WriteNavbar(qq422016 qtio422016.Writer, ctx context.Context)
907+//line templates/base.qtpl:12
908 }
909
910-//line templates/base.qtpl:20
911+//line templates/base.qtpl:21
912 func FromUInttoString(u *uint) string {
913 if u != nil {
914 return strconv.FormatUint(uint64(*u), 10)
915@@ -66,21 +69,27 @@ }
916 return ""
917 }
918
919-//line templates/base.qtpl:28
920+//line templates/base.qtpl:31
921 func TimeFormat(t time.Time) string {
922 return t.Format("02.01.2006")
923 }
924
925-//line templates/base.qtpl:33
926+//line templates/base.qtpl:36
927 func Ignore[T any](v T, _ error) T {
928 return v
929 }
930
931+//line templates/base.qtpl:41
932+func IsLoggedIn(ctx context.Context) bool {
933+ t, ok := ctx.Value("logged").(bool)
934+ return ok && t
935+}
936+
937 // Page prints a page implementing Page interface.
938
939-//line templates/base.qtpl:39
940-func StreamPageTemplate(qw422016 *qt422016.Writer, p Page) {
941-//line templates/base.qtpl:39
942+//line templates/base.qtpl:48
943+func StreamPageTemplate(qw422016 *qt422016.Writer, p Page, ctx context.Context) {
944+//line templates/base.qtpl:48
945 qw422016.N().S(`
946 <!DOCTYPE html>
947 <html lang="en">
948@@ -88,64 +97,64 @@ <head>
949 <meta charset="utf-8">
950 <link rel="icon" href="data:,">
951 <title>`)
952-//line templates/base.qtpl:45
953- p.StreamTitle(qw422016)
954-//line templates/base.qtpl:45
955+//line templates/base.qtpl:54
956+ p.StreamTitle(qw422016, ctx)
957+//line templates/base.qtpl:54
958 qw422016.N().S(`</title>
959 <link rel="stylesheet" href="/static/main`)
960-//line templates/base.qtpl:46
961+//line templates/base.qtpl:55
962 qw422016.E().S(Slug)
963-//line templates/base.qtpl:46
964+//line templates/base.qtpl:55
965 qw422016.N().S(`.css">
966 <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
967 <meta name="viewport" content="width=device-width, initial-scale=1" />
968 </head>
969 <body>
970 `)
971-//line templates/base.qtpl:51
972- p.StreamNavbar(qw422016)
973-//line templates/base.qtpl:51
974+//line templates/base.qtpl:60
975+ p.StreamNavbar(qw422016, ctx)
976+//line templates/base.qtpl:60
977 qw422016.N().S(`
978 <div class="container">
979 `)
980-//line templates/base.qtpl:53
981- p.StreamContent(qw422016)
982-//line templates/base.qtpl:53
983+//line templates/base.qtpl:62
984+ p.StreamContent(qw422016, ctx)
985+//line templates/base.qtpl:62
986 qw422016.N().S(`
987 </div>
988 </body>
989 `)
990-//line templates/base.qtpl:56
991- p.StreamScript(qw422016)
992-//line templates/base.qtpl:56
993+//line templates/base.qtpl:65
994+ p.StreamScript(qw422016, ctx)
995+//line templates/base.qtpl:65
996 qw422016.N().S(`
997 </html>
998 `)
999-//line templates/base.qtpl:58
1000+//line templates/base.qtpl:67
1001 }
1002
1003-//line templates/base.qtpl:58
1004-func WritePageTemplate(qq422016 qtio422016.Writer, p Page) {
1005-//line templates/base.qtpl:58
1006+//line templates/base.qtpl:67
1007+func WritePageTemplate(qq422016 qtio422016.Writer, p Page, ctx context.Context) {
1008+//line templates/base.qtpl:67
1009 qw422016 := qt422016.AcquireWriter(qq422016)
1010-//line templates/base.qtpl:58
1011- StreamPageTemplate(qw422016, p)
1012-//line templates/base.qtpl:58
1013+//line templates/base.qtpl:67
1014+ StreamPageTemplate(qw422016, p, ctx)
1015+//line templates/base.qtpl:67
1016 qt422016.ReleaseWriter(qw422016)
1017-//line templates/base.qtpl:58
1018+//line templates/base.qtpl:67
1019 }
1020
1021-//line templates/base.qtpl:58
1022-func PageTemplate(p Page) string {
1023-//line templates/base.qtpl:58
1024+//line templates/base.qtpl:67
1025+func PageTemplate(p Page, ctx context.Context) string {
1026+//line templates/base.qtpl:67
1027 qb422016 := qt422016.AcquireByteBuffer()
1028-//line templates/base.qtpl:58
1029- WritePageTemplate(qb422016, p)
1030-//line templates/base.qtpl:58
1031+//line templates/base.qtpl:67
1032+ WritePageTemplate(qb422016, p, ctx)
1033+//line templates/base.qtpl:67
1034 qs422016 := string(qb422016.B)
1035-//line templates/base.qtpl:58
1036+//line templates/base.qtpl:67
1037 qt422016.ReleaseByteBuffer(qb422016)
1038-//line templates/base.qtpl:58
1039+//line templates/base.qtpl:67
1040 return qs422016
1041-//line templates/base.qtpl:58
1042+//line templates/base.qtpl:67
1043 }
1044diff --git a/templates/error.qtpl b/templates/error.qtpl
1045index 771d5333f95ee509b2e1680de168003bf24b2b32..65e1321d87ff4dbe30790880e238fc7f5ce5dd14 100644
1046--- a/templates/error.qtpl
1047+++ b/templates/error.qtpl
1048@@ -1,16 +1,18 @@
1049+{% import "context" %}
1050+
1051 {% code
1052 type ErrorPage struct {
1053 Message string
1054 }
1055 %}
1056
1057-{% func (p *ErrorPage) Title() %}Error{% endfunc %}
1058+{% func (p *ErrorPage) Title(ctx context.Context) %}Error{% endfunc %}
1059
1060-{% func (p *ErrorPage) Navbar() %}{%= Navbar(Git) %}{% endfunc %}
1061+{% func (p *ErrorPage) Navbar(ctx context.Context) %}{%= Navbar(ctx, Git) %}{% endfunc %}
1062
1063-{% func (p *ErrorPage) Content() %}
1064+{% func (p *ErrorPage) Content(ctx context.Context) %}
1065 {%s p.Message %}
1066 {% endfunc %}
1067
1068-{% func (p *ErrorPage) Script() %}
1069+{% func (p *ErrorPage) Script(ctx context.Context) %}
1070 {% endfunc %}
1071diff --git a/templates/error.qtpl.go b/templates/error.qtpl.go
1072index f415968c0d258de095a65790f09956cbf2976396..d4732c525cc879e2ac39ad7b46b481fa35edd748 100644
1073--- a/templates/error.qtpl.go
1074+++ b/templates/error.qtpl.go
1075@@ -5,80 +5,50 @@ //line templates/error.qtpl:1
1076 package templates
1077
1078 //line templates/error.qtpl:1
1079+import "context"
1080+
1081+//line templates/error.qtpl:3
1082 import (
1083 qtio422016 "io"
1084
1085 qt422016 "github.com/valyala/quicktemplate"
1086 )
1087
1088-//line templates/error.qtpl:1
1089+//line templates/error.qtpl:3
1090 var (
1091 _ = qtio422016.Copy
1092 _ = qt422016.AcquireByteBuffer
1093 )
1094
1095-//line templates/error.qtpl:2
1096+//line templates/error.qtpl:4
1097 type ErrorPage struct {
1098 Message string
1099 }
1100
1101-//line templates/error.qtpl:7
1102-func (p *ErrorPage) StreamTitle(qw422016 *qt422016.Writer) {
1103-//line templates/error.qtpl:7
1104- qw422016.N().S(`Error`)
1105-//line templates/error.qtpl:7
1106-}
1107-
1108-//line templates/error.qtpl:7
1109-func (p *ErrorPage) WriteTitle(qq422016 qtio422016.Writer) {
1110-//line templates/error.qtpl:7
1111- qw422016 := qt422016.AcquireWriter(qq422016)
1112-//line templates/error.qtpl:7
1113- p.StreamTitle(qw422016)
1114-//line templates/error.qtpl:7
1115- qt422016.ReleaseWriter(qw422016)
1116-//line templates/error.qtpl:7
1117-}
1118-
1119-//line templates/error.qtpl:7
1120-func (p *ErrorPage) Title() string {
1121-//line templates/error.qtpl:7
1122- qb422016 := qt422016.AcquireByteBuffer()
1123-//line templates/error.qtpl:7
1124- p.WriteTitle(qb422016)
1125-//line templates/error.qtpl:7
1126- qs422016 := string(qb422016.B)
1127-//line templates/error.qtpl:7
1128- qt422016.ReleaseByteBuffer(qb422016)
1129-//line templates/error.qtpl:7
1130- return qs422016
1131-//line templates/error.qtpl:7
1132-}
1133-
1134 //line templates/error.qtpl:9
1135-func (p *ErrorPage) StreamNavbar(qw422016 *qt422016.Writer) {
1136+func (p *ErrorPage) StreamTitle(qw422016 *qt422016.Writer, ctx context.Context) {
1137 //line templates/error.qtpl:9
1138- StreamNavbar(qw422016, Git)
1139+ qw422016.N().S(`Error`)
1140 //line templates/error.qtpl:9
1141 }
1142
1143 //line templates/error.qtpl:9
1144-func (p *ErrorPage) WriteNavbar(qq422016 qtio422016.Writer) {
1145+func (p *ErrorPage) WriteTitle(qq422016 qtio422016.Writer, ctx context.Context) {
1146 //line templates/error.qtpl:9
1147 qw422016 := qt422016.AcquireWriter(qq422016)
1148 //line templates/error.qtpl:9
1149- p.StreamNavbar(qw422016)
1150+ p.StreamTitle(qw422016, ctx)
1151 //line templates/error.qtpl:9
1152 qt422016.ReleaseWriter(qw422016)
1153 //line templates/error.qtpl:9
1154 }
1155
1156 //line templates/error.qtpl:9
1157-func (p *ErrorPage) Navbar() string {
1158+func (p *ErrorPage) Title(ctx context.Context) string {
1159 //line templates/error.qtpl:9
1160 qb422016 := qt422016.AcquireByteBuffer()
1161 //line templates/error.qtpl:9
1162- p.WriteNavbar(qb422016)
1163+ p.WriteTitle(qb422016, ctx)
1164 //line templates/error.qtpl:9
1165 qs422016 := string(qb422016.B)
1166 //line templates/error.qtpl:9
1167@@ -89,74 +59,107 @@ //line templates/error.qtpl:9
1168 }
1169
1170 //line templates/error.qtpl:11
1171-func (p *ErrorPage) StreamContent(qw422016 *qt422016.Writer) {
1172+func (p *ErrorPage) StreamNavbar(qw422016 *qt422016.Writer, ctx context.Context) {
1173+//line templates/error.qtpl:11
1174+ StreamNavbar(qw422016, ctx, Git)
1175+//line templates/error.qtpl:11
1176+}
1177+
1178+//line templates/error.qtpl:11
1179+func (p *ErrorPage) WriteNavbar(qq422016 qtio422016.Writer, ctx context.Context) {
1180+//line templates/error.qtpl:11
1181+ qw422016 := qt422016.AcquireWriter(qq422016)
1182+//line templates/error.qtpl:11
1183+ p.StreamNavbar(qw422016, ctx)
1184+//line templates/error.qtpl:11
1185+ qt422016.ReleaseWriter(qw422016)
1186 //line templates/error.qtpl:11
1187+}
1188+
1189+//line templates/error.qtpl:11
1190+func (p *ErrorPage) Navbar(ctx context.Context) string {
1191+//line templates/error.qtpl:11
1192+ qb422016 := qt422016.AcquireByteBuffer()
1193+//line templates/error.qtpl:11
1194+ p.WriteNavbar(qb422016, ctx)
1195+//line templates/error.qtpl:11
1196+ qs422016 := string(qb422016.B)
1197+//line templates/error.qtpl:11
1198+ qt422016.ReleaseByteBuffer(qb422016)
1199+//line templates/error.qtpl:11
1200+ return qs422016
1201+//line templates/error.qtpl:11
1202+}
1203+
1204+//line templates/error.qtpl:13
1205+func (p *ErrorPage) StreamContent(qw422016 *qt422016.Writer, ctx context.Context) {
1206+//line templates/error.qtpl:13
1207 qw422016.N().S(`
1208 `)
1209-//line templates/error.qtpl:12
1210+//line templates/error.qtpl:14
1211 qw422016.E().S(p.Message)
1212-//line templates/error.qtpl:12
1213+//line templates/error.qtpl:14
1214 qw422016.N().S(`
1215 `)
1216-//line templates/error.qtpl:13
1217+//line templates/error.qtpl:15
1218 }
1219
1220-//line templates/error.qtpl:13
1221-func (p *ErrorPage) WriteContent(qq422016 qtio422016.Writer) {
1222-//line templates/error.qtpl:13
1223+//line templates/error.qtpl:15
1224+func (p *ErrorPage) WriteContent(qq422016 qtio422016.Writer, ctx context.Context) {
1225+//line templates/error.qtpl:15
1226 qw422016 := qt422016.AcquireWriter(qq422016)
1227-//line templates/error.qtpl:13
1228- p.StreamContent(qw422016)
1229-//line templates/error.qtpl:13
1230+//line templates/error.qtpl:15
1231+ p.StreamContent(qw422016, ctx)
1232+//line templates/error.qtpl:15
1233 qt422016.ReleaseWriter(qw422016)
1234-//line templates/error.qtpl:13
1235+//line templates/error.qtpl:15
1236 }
1237
1238-//line templates/error.qtpl:13
1239-func (p *ErrorPage) Content() string {
1240-//line templates/error.qtpl:13
1241+//line templates/error.qtpl:15
1242+func (p *ErrorPage) Content(ctx context.Context) string {
1243+//line templates/error.qtpl:15
1244 qb422016 := qt422016.AcquireByteBuffer()
1245-//line templates/error.qtpl:13
1246- p.WriteContent(qb422016)
1247-//line templates/error.qtpl:13
1248+//line templates/error.qtpl:15
1249+ p.WriteContent(qb422016, ctx)
1250+//line templates/error.qtpl:15
1251 qs422016 := string(qb422016.B)
1252-//line templates/error.qtpl:13
1253+//line templates/error.qtpl:15
1254 qt422016.ReleaseByteBuffer(qb422016)
1255-//line templates/error.qtpl:13
1256+//line templates/error.qtpl:15
1257 return qs422016
1258-//line templates/error.qtpl:13
1259+//line templates/error.qtpl:15
1260 }
1261
1262-//line templates/error.qtpl:15
1263-func (p *ErrorPage) StreamScript(qw422016 *qt422016.Writer) {
1264-//line templates/error.qtpl:15
1265+//line templates/error.qtpl:17
1266+func (p *ErrorPage) StreamScript(qw422016 *qt422016.Writer, ctx context.Context) {
1267+//line templates/error.qtpl:17
1268 qw422016.N().S(`
1269 `)
1270-//line templates/error.qtpl:16
1271+//line templates/error.qtpl:18
1272 }
1273
1274-//line templates/error.qtpl:16
1275-func (p *ErrorPage) WriteScript(qq422016 qtio422016.Writer) {
1276-//line templates/error.qtpl:16
1277+//line templates/error.qtpl:18
1278+func (p *ErrorPage) WriteScript(qq422016 qtio422016.Writer, ctx context.Context) {
1279+//line templates/error.qtpl:18
1280 qw422016 := qt422016.AcquireWriter(qq422016)
1281-//line templates/error.qtpl:16
1282- p.StreamScript(qw422016)
1283-//line templates/error.qtpl:16
1284+//line templates/error.qtpl:18
1285+ p.StreamScript(qw422016, ctx)
1286+//line templates/error.qtpl:18
1287 qt422016.ReleaseWriter(qw422016)
1288-//line templates/error.qtpl:16
1289+//line templates/error.qtpl:18
1290 }
1291
1292-//line templates/error.qtpl:16
1293-func (p *ErrorPage) Script() string {
1294-//line templates/error.qtpl:16
1295+//line templates/error.qtpl:18
1296+func (p *ErrorPage) Script(ctx context.Context) string {
1297+//line templates/error.qtpl:18
1298 qb422016 := qt422016.AcquireByteBuffer()
1299-//line templates/error.qtpl:16
1300- p.WriteScript(qb422016)
1301-//line templates/error.qtpl:16
1302+//line templates/error.qtpl:18
1303+ p.WriteScript(qb422016, ctx)
1304+//line templates/error.qtpl:18
1305 qs422016 := string(qb422016.B)
1306-//line templates/error.qtpl:16
1307+//line templates/error.qtpl:18
1308 qt422016.ReleaseByteBuffer(qb422016)
1309-//line templates/error.qtpl:16
1310+//line templates/error.qtpl:18
1311 return qs422016
1312-//line templates/error.qtpl:16
1313+//line templates/error.qtpl:18
1314 }
1315diff --git a/templates/gititem.qtpl b/templates/gititem.qtpl
1316index a6a312d333e2e4942004073ed33494454f1eeeea..c43bbfdf906e81797b9bbbc00e8dab843f960be0 100644
1317--- a/templates/gititem.qtpl
1318+++ b/templates/gititem.qtpl
1319@@ -1,3 +1,5 @@
1320+{% import "context" %}
1321+
1322 {% interface
1323 GitItemBase {
1324 Nav(name, ref string)
1325@@ -13,16 +15,16 @@ GitItemBase
1326 }
1327 %}
1328
1329-{% func (p *GitItemPage) Title() %}Git | {%s p.Name %}{% endfunc %}
1330+{% func (p *GitItemPage) Title(ctx context.Context) %}Git | {%s p.Name %}{% endfunc %}
1331
1332-{% func (p *GitItemPage) Navbar() %}{%= Navbar(Git) %}{% endfunc %}
1333+{% func (p *GitItemPage) Navbar(ctx context.Context) %}{%= Navbar(ctx, Git) %}{% endfunc %}
1334
1335-{% func (p *GitItemPage) Content() %}
1336+{% func (p *GitItemPage) Content(ctx context.Context) %}
1337 {%= p.Nav(p.Name, p.Ref) %}
1338 <div class="container">
1339 {%= p.GitContent(p.Name, p.Ref) %}
1340 </div>
1341 {% endfunc %}
1342
1343-{% func (p *GitItemPage) Script() %}
1344+{% func (p *GitItemPage) Script(ctx context.Context) %}
1345 {% endfunc %}
1346diff --git a/templates/gititem.qtpl.go b/templates/gititem.qtpl.go
1347index c9a00b29d0fd28cd514db8e97d63f5dcff9b172b..5292e44812ac71d251a8678380da7c80b40e48e8 100644
1348--- a/templates/gititem.qtpl.go
1349+++ b/templates/gititem.qtpl.go
1350@@ -5,101 +5,71 @@ //line templates/gititem.qtpl:1
1351 package templates
1352
1353 //line templates/gititem.qtpl:1
1354+import "context"
1355+
1356+//line templates/gititem.qtpl:3
1357 import (
1358 qtio422016 "io"
1359
1360 qt422016 "github.com/valyala/quicktemplate"
1361 )
1362
1363-//line templates/gititem.qtpl:1
1364+//line templates/gititem.qtpl:3
1365 var (
1366 _ = qtio422016.Copy
1367 _ = qt422016.AcquireByteBuffer
1368 )
1369
1370-//line templates/gititem.qtpl:2
1371+//line templates/gititem.qtpl:4
1372 type GitItemBase interface {
1373-//line templates/gititem.qtpl:2
1374+//line templates/gititem.qtpl:4
1375 Nav(name, ref string) string
1376-//line templates/gititem.qtpl:2
1377+//line templates/gititem.qtpl:4
1378 StreamNav(qw422016 *qt422016.Writer, name, ref string)
1379-//line templates/gititem.qtpl:2
1380+//line templates/gititem.qtpl:4
1381 WriteNav(qq422016 qtio422016.Writer, name, ref string)
1382-//line templates/gititem.qtpl:2
1383+//line templates/gititem.qtpl:4
1384 GitContent(name, ref string) string
1385-//line templates/gititem.qtpl:2
1386+//line templates/gititem.qtpl:4
1387 StreamGitContent(qw422016 *qt422016.Writer, name, ref string)
1388-//line templates/gititem.qtpl:2
1389+//line templates/gititem.qtpl:4
1390 WriteGitContent(qq422016 qtio422016.Writer, name, ref string)
1391-//line templates/gititem.qtpl:2
1392+//line templates/gititem.qtpl:4
1393 }
1394
1395-//line templates/gititem.qtpl:9
1396+//line templates/gititem.qtpl:11
1397 type GitItemPage struct {
1398 Name string
1399 Ref string
1400 GitItemBase
1401 }
1402
1403-//line templates/gititem.qtpl:16
1404-func (p *GitItemPage) StreamTitle(qw422016 *qt422016.Writer) {
1405-//line templates/gititem.qtpl:16
1406+//line templates/gititem.qtpl:18
1407+func (p *GitItemPage) StreamTitle(qw422016 *qt422016.Writer, ctx context.Context) {
1408+//line templates/gititem.qtpl:18
1409 qw422016.N().S(`Git | `)
1410-//line templates/gititem.qtpl:16
1411+//line templates/gititem.qtpl:18
1412 qw422016.E().S(p.Name)
1413-//line templates/gititem.qtpl:16
1414-}
1415-
1416-//line templates/gititem.qtpl:16
1417-func (p *GitItemPage) WriteTitle(qq422016 qtio422016.Writer) {
1418-//line templates/gititem.qtpl:16
1419- qw422016 := qt422016.AcquireWriter(qq422016)
1420-//line templates/gititem.qtpl:16
1421- p.StreamTitle(qw422016)
1422-//line templates/gititem.qtpl:16
1423- qt422016.ReleaseWriter(qw422016)
1424-//line templates/gititem.qtpl:16
1425-}
1426-
1427-//line templates/gititem.qtpl:16
1428-func (p *GitItemPage) Title() string {
1429-//line templates/gititem.qtpl:16
1430- qb422016 := qt422016.AcquireByteBuffer()
1431-//line templates/gititem.qtpl:16
1432- p.WriteTitle(qb422016)
1433-//line templates/gititem.qtpl:16
1434- qs422016 := string(qb422016.B)
1435-//line templates/gititem.qtpl:16
1436- qt422016.ReleaseByteBuffer(qb422016)
1437-//line templates/gititem.qtpl:16
1438- return qs422016
1439-//line templates/gititem.qtpl:16
1440-}
1441-
1442-//line templates/gititem.qtpl:18
1443-func (p *GitItemPage) StreamNavbar(qw422016 *qt422016.Writer) {
1444-//line templates/gititem.qtpl:18
1445- StreamNavbar(qw422016, Git)
1446 //line templates/gititem.qtpl:18
1447 }
1448
1449 //line templates/gititem.qtpl:18
1450-func (p *GitItemPage) WriteNavbar(qq422016 qtio422016.Writer) {
1451+func (p *GitItemPage) WriteTitle(qq422016 qtio422016.Writer, ctx context.Context) {
1452 //line templates/gititem.qtpl:18
1453 qw422016 := qt422016.AcquireWriter(qq422016)
1454 //line templates/gititem.qtpl:18
1455- p.StreamNavbar(qw422016)
1456+ p.StreamTitle(qw422016, ctx)
1457 //line templates/gititem.qtpl:18
1458 qt422016.ReleaseWriter(qw422016)
1459 //line templates/gititem.qtpl:18
1460 }
1461
1462 //line templates/gititem.qtpl:18
1463-func (p *GitItemPage) Navbar() string {
1464+func (p *GitItemPage) Title(ctx context.Context) string {
1465 //line templates/gititem.qtpl:18
1466 qb422016 := qt422016.AcquireByteBuffer()
1467 //line templates/gititem.qtpl:18
1468- p.WriteNavbar(qb422016)
1469+ p.WriteTitle(qb422016, ctx)
1470 //line templates/gititem.qtpl:18
1471 qs422016 := string(qb422016.B)
1472 //line templates/gititem.qtpl:18
1473@@ -110,81 +80,114 @@ //line templates/gititem.qtpl:18
1474 }
1475
1476 //line templates/gititem.qtpl:20
1477-func (p *GitItemPage) StreamContent(qw422016 *qt422016.Writer) {
1478+func (p *GitItemPage) StreamNavbar(qw422016 *qt422016.Writer, ctx context.Context) {
1479+//line templates/gititem.qtpl:20
1480+ StreamNavbar(qw422016, ctx, Git)
1481+//line templates/gititem.qtpl:20
1482+}
1483+
1484+//line templates/gititem.qtpl:20
1485+func (p *GitItemPage) WriteNavbar(qq422016 qtio422016.Writer, ctx context.Context) {
1486+//line templates/gititem.qtpl:20
1487+ qw422016 := qt422016.AcquireWriter(qq422016)
1488+//line templates/gititem.qtpl:20
1489+ p.StreamNavbar(qw422016, ctx)
1490+//line templates/gititem.qtpl:20
1491+ qt422016.ReleaseWriter(qw422016)
1492+//line templates/gititem.qtpl:20
1493+}
1494+
1495+//line templates/gititem.qtpl:20
1496+func (p *GitItemPage) Navbar(ctx context.Context) string {
1497+//line templates/gititem.qtpl:20
1498+ qb422016 := qt422016.AcquireByteBuffer()
1499+//line templates/gititem.qtpl:20
1500+ p.WriteNavbar(qb422016, ctx)
1501+//line templates/gititem.qtpl:20
1502+ qs422016 := string(qb422016.B)
1503 //line templates/gititem.qtpl:20
1504+ qt422016.ReleaseByteBuffer(qb422016)
1505+//line templates/gititem.qtpl:20
1506+ return qs422016
1507+//line templates/gititem.qtpl:20
1508+}
1509+
1510+//line templates/gititem.qtpl:22
1511+func (p *GitItemPage) StreamContent(qw422016 *qt422016.Writer, ctx context.Context) {
1512+//line templates/gititem.qtpl:22
1513 qw422016.N().S(`
1514 `)
1515-//line templates/gititem.qtpl:21
1516+//line templates/gititem.qtpl:23
1517 p.StreamNav(qw422016, p.Name, p.Ref)
1518-//line templates/gititem.qtpl:21
1519+//line templates/gititem.qtpl:23
1520 qw422016.N().S(`
1521 <div class="container">
1522 `)
1523-//line templates/gititem.qtpl:23
1524+//line templates/gititem.qtpl:25
1525 p.StreamGitContent(qw422016, p.Name, p.Ref)
1526-//line templates/gititem.qtpl:23
1527+//line templates/gititem.qtpl:25
1528 qw422016.N().S(`
1529 </div>
1530 `)
1531-//line templates/gititem.qtpl:25
1532+//line templates/gititem.qtpl:27
1533 }
1534
1535-//line templates/gititem.qtpl:25
1536-func (p *GitItemPage) WriteContent(qq422016 qtio422016.Writer) {
1537-//line templates/gititem.qtpl:25
1538+//line templates/gititem.qtpl:27
1539+func (p *GitItemPage) WriteContent(qq422016 qtio422016.Writer, ctx context.Context) {
1540+//line templates/gititem.qtpl:27
1541 qw422016 := qt422016.AcquireWriter(qq422016)
1542-//line templates/gititem.qtpl:25
1543- p.StreamContent(qw422016)
1544-//line templates/gititem.qtpl:25
1545+//line templates/gititem.qtpl:27
1546+ p.StreamContent(qw422016, ctx)
1547+//line templates/gititem.qtpl:27
1548 qt422016.ReleaseWriter(qw422016)
1549-//line templates/gititem.qtpl:25
1550+//line templates/gititem.qtpl:27
1551 }
1552
1553-//line templates/gititem.qtpl:25
1554-func (p *GitItemPage) Content() string {
1555-//line templates/gititem.qtpl:25
1556+//line templates/gititem.qtpl:27
1557+func (p *GitItemPage) Content(ctx context.Context) string {
1558+//line templates/gititem.qtpl:27
1559 qb422016 := qt422016.AcquireByteBuffer()
1560-//line templates/gititem.qtpl:25
1561- p.WriteContent(qb422016)
1562-//line templates/gititem.qtpl:25
1563+//line templates/gititem.qtpl:27
1564+ p.WriteContent(qb422016, ctx)
1565+//line templates/gititem.qtpl:27
1566 qs422016 := string(qb422016.B)
1567-//line templates/gititem.qtpl:25
1568+//line templates/gititem.qtpl:27
1569 qt422016.ReleaseByteBuffer(qb422016)
1570-//line templates/gititem.qtpl:25
1571+//line templates/gititem.qtpl:27
1572 return qs422016
1573-//line templates/gititem.qtpl:25
1574+//line templates/gititem.qtpl:27
1575 }
1576
1577-//line templates/gititem.qtpl:27
1578-func (p *GitItemPage) StreamScript(qw422016 *qt422016.Writer) {
1579-//line templates/gititem.qtpl:27
1580+//line templates/gititem.qtpl:29
1581+func (p *GitItemPage) StreamScript(qw422016 *qt422016.Writer, ctx context.Context) {
1582+//line templates/gititem.qtpl:29
1583 qw422016.N().S(`
1584 `)
1585-//line templates/gititem.qtpl:28
1586+//line templates/gititem.qtpl:30
1587 }
1588
1589-//line templates/gititem.qtpl:28
1590-func (p *GitItemPage) WriteScript(qq422016 qtio422016.Writer) {
1591-//line templates/gititem.qtpl:28
1592+//line templates/gititem.qtpl:30
1593+func (p *GitItemPage) WriteScript(qq422016 qtio422016.Writer, ctx context.Context) {
1594+//line templates/gititem.qtpl:30
1595 qw422016 := qt422016.AcquireWriter(qq422016)
1596-//line templates/gititem.qtpl:28
1597- p.StreamScript(qw422016)
1598-//line templates/gititem.qtpl:28
1599+//line templates/gititem.qtpl:30
1600+ p.StreamScript(qw422016, ctx)
1601+//line templates/gititem.qtpl:30
1602 qt422016.ReleaseWriter(qw422016)
1603-//line templates/gititem.qtpl:28
1604+//line templates/gititem.qtpl:30
1605 }
1606
1607-//line templates/gititem.qtpl:28
1608-func (p *GitItemPage) Script() string {
1609-//line templates/gititem.qtpl:28
1610+//line templates/gititem.qtpl:30
1611+func (p *GitItemPage) Script(ctx context.Context) string {
1612+//line templates/gititem.qtpl:30
1613 qb422016 := qt422016.AcquireByteBuffer()
1614-//line templates/gititem.qtpl:28
1615- p.WriteScript(qb422016)
1616-//line templates/gititem.qtpl:28
1617+//line templates/gititem.qtpl:30
1618+ p.WriteScript(qb422016, ctx)
1619+//line templates/gititem.qtpl:30
1620 qs422016 := string(qb422016.B)
1621-//line templates/gititem.qtpl:28
1622+//line templates/gititem.qtpl:30
1623 qt422016.ReleaseByteBuffer(qb422016)
1624-//line templates/gititem.qtpl:28
1625+//line templates/gititem.qtpl:30
1626 return qs422016
1627-//line templates/gititem.qtpl:28
1628+//line templates/gititem.qtpl:30
1629 }
1630diff --git a/templates/gitlist.qtpl b/templates/gitlist.qtpl
1631index 7c104ca5b394315b2657d598ddd79f797af27de7..fa470089e9f4fd64c066822ec1c849628ddd4f1e 100644
1632--- a/templates/gitlist.qtpl
1633+++ b/templates/gitlist.qtpl
1634@@ -1,4 +1,5 @@
1635 {% import "git.gabrielgio.me/cerrado/pkg/service" %}
1636+{% import "context" %}
1637
1638 {% code
1639 type GitListPage struct {
1640@@ -7,11 +8,11 @@ About []byte
1641 }
1642 %}
1643
1644-{% func (p *GitListPage) Title() %}Git | List{% endfunc %}
1645+{% func (p *GitListPage) Title(ctx context.Context) %}Git | List{% endfunc %}
1646
1647-{% func (p *GitListPage) Navbar() %}{%= Navbar(Git) %}{% endfunc %}
1648+{% func (p *GitListPage) Navbar(ctx context.Context) %}{%= Navbar(ctx, Git) %}{% endfunc %}
1649
1650-{% func (p *GitListPage) Content() %}
1651+{% func (p *GitListPage) Content(ctx context.Context) %}
1652 <div class="row">
1653 <div class="col-md-6 order-last order-md-first">
1654 <div class="event-list">
1655@@ -40,5 +41,5 @@ </div>
1656 </div>
1657 {% endfunc %}
1658
1659-{% func (p *GitListPage) Script() %}
1660+{% func (p *GitListPage) Script(ctx context.Context) %}
1661 {% endfunc %}
1662diff --git a/templates/gitlist.qtpl.go b/templates/gitlist.qtpl.go
1663index 29adbc6d54b1d1bc78b24b34043d756ee96e5d81..601dbb2fa8c947e791800ebded6aabbd64005919 100644
1664--- a/templates/gitlist.qtpl.go
1665+++ b/templates/gitlist.qtpl.go
1666@@ -7,159 +7,162 @@
1667 //line templates/gitlist.qtpl:1
1668 import "git.gabrielgio.me/cerrado/pkg/service"
1669
1670-//line templates/gitlist.qtpl:3
1671+//line templates/gitlist.qtpl:2
1672+import "context"
1673+
1674+//line templates/gitlist.qtpl:4
1675 import (
1676 qtio422016 "io"
1677
1678 qt422016 "github.com/valyala/quicktemplate"
1679 )
1680
1681-//line templates/gitlist.qtpl:3
1682+//line templates/gitlist.qtpl:4
1683 var (
1684 _ = qtio422016.Copy
1685 _ = qt422016.AcquireByteBuffer
1686 )
1687
1688-//line templates/gitlist.qtpl:4
1689+//line templates/gitlist.qtpl:5
1690 type GitListPage struct {
1691 Respositories []*service.Repository
1692 About []byte
1693 }
1694
1695-//line templates/gitlist.qtpl:10
1696-func (p *GitListPage) StreamTitle(qw422016 *qt422016.Writer) {
1697-//line templates/gitlist.qtpl:10
1698+//line templates/gitlist.qtpl:11
1699+func (p *GitListPage) StreamTitle(qw422016 *qt422016.Writer, ctx context.Context) {
1700+//line templates/gitlist.qtpl:11
1701 qw422016.N().S(`Git | List`)
1702-//line templates/gitlist.qtpl:10
1703+//line templates/gitlist.qtpl:11
1704 }
1705
1706-//line templates/gitlist.qtpl:10
1707-func (p *GitListPage) WriteTitle(qq422016 qtio422016.Writer) {
1708-//line templates/gitlist.qtpl:10
1709+//line templates/gitlist.qtpl:11
1710+func (p *GitListPage) WriteTitle(qq422016 qtio422016.Writer, ctx context.Context) {
1711+//line templates/gitlist.qtpl:11
1712 qw422016 := qt422016.AcquireWriter(qq422016)
1713-//line templates/gitlist.qtpl:10
1714- p.StreamTitle(qw422016)
1715-//line templates/gitlist.qtpl:10
1716+//line templates/gitlist.qtpl:11
1717+ p.StreamTitle(qw422016, ctx)
1718+//line templates/gitlist.qtpl:11
1719 qt422016.ReleaseWriter(qw422016)
1720-//line templates/gitlist.qtpl:10
1721+//line templates/gitlist.qtpl:11
1722 }
1723
1724-//line templates/gitlist.qtpl:10
1725-func (p *GitListPage) Title() string {
1726-//line templates/gitlist.qtpl:10
1727+//line templates/gitlist.qtpl:11
1728+func (p *GitListPage) Title(ctx context.Context) string {
1729+//line templates/gitlist.qtpl:11
1730 qb422016 := qt422016.AcquireByteBuffer()
1731-//line templates/gitlist.qtpl:10
1732- p.WriteTitle(qb422016)
1733-//line templates/gitlist.qtpl:10
1734+//line templates/gitlist.qtpl:11
1735+ p.WriteTitle(qb422016, ctx)
1736+//line templates/gitlist.qtpl:11
1737 qs422016 := string(qb422016.B)
1738-//line templates/gitlist.qtpl:10
1739+//line templates/gitlist.qtpl:11
1740 qt422016.ReleaseByteBuffer(qb422016)
1741-//line templates/gitlist.qtpl:10
1742+//line templates/gitlist.qtpl:11
1743 return qs422016
1744-//line templates/gitlist.qtpl:10
1745+//line templates/gitlist.qtpl:11
1746 }
1747
1748-//line templates/gitlist.qtpl:12
1749-func (p *GitListPage) StreamNavbar(qw422016 *qt422016.Writer) {
1750-//line templates/gitlist.qtpl:12
1751- StreamNavbar(qw422016, Git)
1752-//line templates/gitlist.qtpl:12
1753+//line templates/gitlist.qtpl:13
1754+func (p *GitListPage) StreamNavbar(qw422016 *qt422016.Writer, ctx context.Context) {
1755+//line templates/gitlist.qtpl:13
1756+ StreamNavbar(qw422016, ctx, Git)
1757+//line templates/gitlist.qtpl:13
1758 }
1759
1760-//line templates/gitlist.qtpl:12
1761-func (p *GitListPage) WriteNavbar(qq422016 qtio422016.Writer) {
1762-//line templates/gitlist.qtpl:12
1763+//line templates/gitlist.qtpl:13
1764+func (p *GitListPage) WriteNavbar(qq422016 qtio422016.Writer, ctx context.Context) {
1765+//line templates/gitlist.qtpl:13
1766 qw422016 := qt422016.AcquireWriter(qq422016)
1767-//line templates/gitlist.qtpl:12
1768- p.StreamNavbar(qw422016)
1769-//line templates/gitlist.qtpl:12
1770+//line templates/gitlist.qtpl:13
1771+ p.StreamNavbar(qw422016, ctx)
1772+//line templates/gitlist.qtpl:13
1773 qt422016.ReleaseWriter(qw422016)
1774-//line templates/gitlist.qtpl:12
1775+//line templates/gitlist.qtpl:13
1776 }
1777
1778-//line templates/gitlist.qtpl:12
1779-func (p *GitListPage) Navbar() string {
1780-//line templates/gitlist.qtpl:12
1781+//line templates/gitlist.qtpl:13
1782+func (p *GitListPage) Navbar(ctx context.Context) string {
1783+//line templates/gitlist.qtpl:13
1784 qb422016 := qt422016.AcquireByteBuffer()
1785-//line templates/gitlist.qtpl:12
1786- p.WriteNavbar(qb422016)
1787-//line templates/gitlist.qtpl:12
1788+//line templates/gitlist.qtpl:13
1789+ p.WriteNavbar(qb422016, ctx)
1790+//line templates/gitlist.qtpl:13
1791 qs422016 := string(qb422016.B)
1792-//line templates/gitlist.qtpl:12
1793+//line templates/gitlist.qtpl:13
1794 qt422016.ReleaseByteBuffer(qb422016)
1795-//line templates/gitlist.qtpl:12
1796+//line templates/gitlist.qtpl:13
1797 return qs422016
1798-//line templates/gitlist.qtpl:12
1799+//line templates/gitlist.qtpl:13
1800 }
1801
1802-//line templates/gitlist.qtpl:14
1803-func (p *GitListPage) StreamContent(qw422016 *qt422016.Writer) {
1804-//line templates/gitlist.qtpl:14
1805+//line templates/gitlist.qtpl:15
1806+func (p *GitListPage) StreamContent(qw422016 *qt422016.Writer, ctx context.Context) {
1807+//line templates/gitlist.qtpl:15
1808 qw422016.N().S(`
1809 <div class="row">
1810 <div class="col-md-6 order-last order-md-first">
1811 <div class="event-list">
1812 `)
1813-//line templates/gitlist.qtpl:18
1814+//line templates/gitlist.qtpl:19
1815 for _, r := range p.Respositories {
1816-//line templates/gitlist.qtpl:18
1817+//line templates/gitlist.qtpl:19
1818 qw422016.N().S(`
1819 <div class="event">
1820 <h4>
1821 <a href="/`)
1822-//line templates/gitlist.qtpl:21
1823+//line templates/gitlist.qtpl:22
1824 qw422016.E().S(r.Name)
1825-//line templates/gitlist.qtpl:21
1826+//line templates/gitlist.qtpl:22
1827 qw422016.N().S(`/">`)
1828-//line templates/gitlist.qtpl:21
1829+//line templates/gitlist.qtpl:22
1830 qw422016.E().S(r.Name)
1831-//line templates/gitlist.qtpl:21
1832+//line templates/gitlist.qtpl:22
1833 qw422016.N().S(`</a>
1834 </h4>
1835 </hr>
1836 <p>`)
1837-//line templates/gitlist.qtpl:24
1838+//line templates/gitlist.qtpl:25
1839 qw422016.E().S(r.Description)
1840-//line templates/gitlist.qtpl:24
1841+//line templates/gitlist.qtpl:25
1842 qw422016.N().S(`</p>
1843 <p>
1844 <a href="/`)
1845-//line templates/gitlist.qtpl:26
1846+//line templates/gitlist.qtpl:27
1847 qw422016.E().S(r.Name)
1848-//line templates/gitlist.qtpl:26
1849+//line templates/gitlist.qtpl:27
1850 qw422016.N().S(`/log/`)
1851-//line templates/gitlist.qtpl:26
1852+//line templates/gitlist.qtpl:27
1853 qw422016.E().S(r.Ref)
1854-//line templates/gitlist.qtpl:26
1855+//line templates/gitlist.qtpl:27
1856 qw422016.N().S(`/">log</a>
1857 <a href="/`)
1858-//line templates/gitlist.qtpl:27
1859+//line templates/gitlist.qtpl:28
1860 qw422016.E().S(r.Name)
1861-//line templates/gitlist.qtpl:27
1862+//line templates/gitlist.qtpl:28
1863 qw422016.N().S(`/tree/`)
1864-//line templates/gitlist.qtpl:27
1865+//line templates/gitlist.qtpl:28
1866 qw422016.E().S(r.Ref)
1867-//line templates/gitlist.qtpl:27
1868+//line templates/gitlist.qtpl:28
1869 qw422016.N().S(`/">tree</a>
1870 <a href="/`)
1871-//line templates/gitlist.qtpl:28
1872+//line templates/gitlist.qtpl:29
1873 qw422016.E().S(r.Name)
1874-//line templates/gitlist.qtpl:28
1875+//line templates/gitlist.qtpl:29
1876 qw422016.N().S(`/refs/">refs</a>
1877 </p>
1878 </div>
1879 `)
1880-//line templates/gitlist.qtpl:31
1881+//line templates/gitlist.qtpl:32
1882 }
1883-//line templates/gitlist.qtpl:31
1884+//line templates/gitlist.qtpl:32
1885 qw422016.N().S(`
1886 </div>
1887 </div>
1888 <div id="about" class="col-md-4 order-first order-md-last">
1889 `)
1890-//line templates/gitlist.qtpl:35
1891+//line templates/gitlist.qtpl:36
1892 qw422016.N().Z(p.About)
1893-//line templates/gitlist.qtpl:35
1894+//line templates/gitlist.qtpl:36
1895 qw422016.N().S(`
1896 <div class="alert alert-warning text-center" role="alert">
1897 This project is under development, things may be broken or incomplete.
1898@@ -167,65 +170,65 @@ </div>
1899 </div>
1900 </div>
1901 `)
1902-//line templates/gitlist.qtpl:41
1903+//line templates/gitlist.qtpl:42
1904 }
1905
1906-//line templates/gitlist.qtpl:41
1907-func (p *GitListPage) WriteContent(qq422016 qtio422016.Writer) {
1908-//line templates/gitlist.qtpl:41
1909+//line templates/gitlist.qtpl:42
1910+func (p *GitListPage) WriteContent(qq422016 qtio422016.Writer, ctx context.Context) {
1911+//line templates/gitlist.qtpl:42
1912 qw422016 := qt422016.AcquireWriter(qq422016)
1913-//line templates/gitlist.qtpl:41
1914- p.StreamContent(qw422016)
1915-//line templates/gitlist.qtpl:41
1916+//line templates/gitlist.qtpl:42
1917+ p.StreamContent(qw422016, ctx)
1918+//line templates/gitlist.qtpl:42
1919 qt422016.ReleaseWriter(qw422016)
1920-//line templates/gitlist.qtpl:41
1921+//line templates/gitlist.qtpl:42
1922 }
1923
1924-//line templates/gitlist.qtpl:41
1925-func (p *GitListPage) Content() string {
1926-//line templates/gitlist.qtpl:41
1927+//line templates/gitlist.qtpl:42
1928+func (p *GitListPage) Content(ctx context.Context) string {
1929+//line templates/gitlist.qtpl:42
1930 qb422016 := qt422016.AcquireByteBuffer()
1931-//line templates/gitlist.qtpl:41
1932- p.WriteContent(qb422016)
1933-//line templates/gitlist.qtpl:41
1934+//line templates/gitlist.qtpl:42
1935+ p.WriteContent(qb422016, ctx)
1936+//line templates/gitlist.qtpl:42
1937 qs422016 := string(qb422016.B)
1938-//line templates/gitlist.qtpl:41
1939+//line templates/gitlist.qtpl:42
1940 qt422016.ReleaseByteBuffer(qb422016)
1941-//line templates/gitlist.qtpl:41
1942+//line templates/gitlist.qtpl:42
1943 return qs422016
1944-//line templates/gitlist.qtpl:41
1945+//line templates/gitlist.qtpl:42
1946 }
1947
1948-//line templates/gitlist.qtpl:43
1949-func (p *GitListPage) StreamScript(qw422016 *qt422016.Writer) {
1950-//line templates/gitlist.qtpl:43
1951+//line templates/gitlist.qtpl:44
1952+func (p *GitListPage) StreamScript(qw422016 *qt422016.Writer, ctx context.Context) {
1953+//line templates/gitlist.qtpl:44
1954 qw422016.N().S(`
1955 `)
1956-//line templates/gitlist.qtpl:44
1957+//line templates/gitlist.qtpl:45
1958 }
1959
1960-//line templates/gitlist.qtpl:44
1961-func (p *GitListPage) WriteScript(qq422016 qtio422016.Writer) {
1962-//line templates/gitlist.qtpl:44
1963+//line templates/gitlist.qtpl:45
1964+func (p *GitListPage) WriteScript(qq422016 qtio422016.Writer, ctx context.Context) {
1965+//line templates/gitlist.qtpl:45
1966 qw422016 := qt422016.AcquireWriter(qq422016)
1967-//line templates/gitlist.qtpl:44
1968- p.StreamScript(qw422016)
1969-//line templates/gitlist.qtpl:44
1970+//line templates/gitlist.qtpl:45
1971+ p.StreamScript(qw422016, ctx)
1972+//line templates/gitlist.qtpl:45
1973 qt422016.ReleaseWriter(qw422016)
1974-//line templates/gitlist.qtpl:44
1975+//line templates/gitlist.qtpl:45
1976 }
1977
1978-//line templates/gitlist.qtpl:44
1979-func (p *GitListPage) Script() string {
1980-//line templates/gitlist.qtpl:44
1981+//line templates/gitlist.qtpl:45
1982+func (p *GitListPage) Script(ctx context.Context) string {
1983+//line templates/gitlist.qtpl:45
1984 qb422016 := qt422016.AcquireByteBuffer()
1985-//line templates/gitlist.qtpl:44
1986- p.WriteScript(qb422016)
1987-//line templates/gitlist.qtpl:44
1988+//line templates/gitlist.qtpl:45
1989+ p.WriteScript(qb422016, ctx)
1990+//line templates/gitlist.qtpl:45
1991 qs422016 := string(qb422016.B)
1992-//line templates/gitlist.qtpl:44
1993+//line templates/gitlist.qtpl:45
1994 qt422016.ReleaseByteBuffer(qb422016)
1995-//line templates/gitlist.qtpl:44
1996+//line templates/gitlist.qtpl:45
1997 return qs422016
1998-//line templates/gitlist.qtpl:44
1999+//line templates/gitlist.qtpl:45
2000 }
2001diff --git a/templates/login.qtpl b/templates/login.qtpl
2002index eee57117106360c2f0d9bbf104e0b820bf051e92..7815bd7401ff8cdee199144ac88b61421f253eb7 100644
2003--- a/templates/login.qtpl
2004+++ b/templates/login.qtpl
2005@@ -1,31 +1,41 @@
2006+{% import "context" %}
2007+
2008 {% code
2009 type LoginPage struct {
2010+ ErrorMessage string
2011 }
2012 %}
2013
2014-{% func (p *LoginPage) Title() %}Hello{% endfunc %}
2015+{% func (p *LoginPage) Title(ctx context.Context) %}Hello{% endfunc %}
2016
2017-{% func (p *LoginPage) Navbar() %}{%= Navbar(Login) %}{% endfunc %}
2018+{% func (p *LoginPage) Navbar(ctx context.Context) %}{%= Navbar(ctx, Login) %}{% endfunc %}
2019
2020-{% func (p *LoginPage) Content() %}
2021+{% func (p *LoginPage) Content(ctx context.Context) %}
2022 <div class="row">
2023 <div class="col-md-6 offset-md-3">
2024- <form>
2025+ <form action="/login/" method="POST">
2026 <div class="form-group m-3">
2027 <label for="username" class="form-label">Username</label>
2028- <input type="text" class="form-control" id="username" aria-describedby="emailHelp">
2029+ <input type="text" class="form-control" name="username" id="username">
2030 </div>
2031 <div class="form-group m-3">
2032 <label for="password" class="form-label">Password</label>
2033- <input type="password" class="form-control" id="password">
2034+ <input type="password" class="form-control" name="password" id="password">
2035 </div>
2036 <div class="form-group m-3">
2037 <button type="submit" class="btn btn-primary">Login</button>
2038 </div>
2039 </form>
2040 </div>
2041+ {% if p.ErrorMessage != "" %}
2042+ <div class="col-md-6 offset-md-3">
2043+ <div class="alert alert-warning text-center" >
2044+ {%s p.ErrorMessage %}
2045+ </div>
2046+ </div>
2047+ {% endif %}
2048 </div>
2049 {% endfunc %}
2050
2051-{% func (p *LoginPage) Script() %}
2052+{% func (p *LoginPage) Script(ctx context.Context) %}
2053 {% endfunc %}
2054diff --git a/templates/login.qtpl.go b/templates/login.qtpl.go
2055index 0d3d2b0c41d592cf030a0806131d1057e8726786..5c07a44eea42027c0c04ab1e56ec192c187964cb 100644
2056--- a/templates/login.qtpl.go
2057+++ b/templates/login.qtpl.go
2058@@ -5,169 +5,192 @@ //line templates/login.qtpl:1
2059 package templates
2060
2061 //line templates/login.qtpl:1
2062+import "context"
2063+
2064+//line templates/login.qtpl:3
2065 import (
2066 qtio422016 "io"
2067
2068 qt422016 "github.com/valyala/quicktemplate"
2069 )
2070
2071-//line templates/login.qtpl:1
2072+//line templates/login.qtpl:3
2073 var (
2074 _ = qtio422016.Copy
2075 _ = qt422016.AcquireByteBuffer
2076 )
2077
2078-//line templates/login.qtpl:2
2079+//line templates/login.qtpl:4
2080 type LoginPage struct {
2081+ ErrorMessage string
2082 }
2083
2084-//line templates/login.qtpl:6
2085-func (p *LoginPage) StreamTitle(qw422016 *qt422016.Writer) {
2086-//line templates/login.qtpl:6
2087+//line templates/login.qtpl:9
2088+func (p *LoginPage) StreamTitle(qw422016 *qt422016.Writer, ctx context.Context) {
2089+//line templates/login.qtpl:9
2090 qw422016.N().S(`Hello`)
2091-//line templates/login.qtpl:6
2092+//line templates/login.qtpl:9
2093 }
2094
2095-//line templates/login.qtpl:6
2096-func (p *LoginPage) WriteTitle(qq422016 qtio422016.Writer) {
2097-//line templates/login.qtpl:6
2098+//line templates/login.qtpl:9
2099+func (p *LoginPage) WriteTitle(qq422016 qtio422016.Writer, ctx context.Context) {
2100+//line templates/login.qtpl:9
2101 qw422016 := qt422016.AcquireWriter(qq422016)
2102-//line templates/login.qtpl:6
2103- p.StreamTitle(qw422016)
2104-//line templates/login.qtpl:6
2105+//line templates/login.qtpl:9
2106+ p.StreamTitle(qw422016, ctx)
2107+//line templates/login.qtpl:9
2108 qt422016.ReleaseWriter(qw422016)
2109-//line templates/login.qtpl:6
2110+//line templates/login.qtpl:9
2111 }
2112
2113-//line templates/login.qtpl:6
2114-func (p *LoginPage) Title() string {
2115-//line templates/login.qtpl:6
2116+//line templates/login.qtpl:9
2117+func (p *LoginPage) Title(ctx context.Context) string {
2118+//line templates/login.qtpl:9
2119 qb422016 := qt422016.AcquireByteBuffer()
2120-//line templates/login.qtpl:6
2121- p.WriteTitle(qb422016)
2122-//line templates/login.qtpl:6
2123+//line templates/login.qtpl:9
2124+ p.WriteTitle(qb422016, ctx)
2125+//line templates/login.qtpl:9
2126 qs422016 := string(qb422016.B)
2127-//line templates/login.qtpl:6
2128+//line templates/login.qtpl:9
2129 qt422016.ReleaseByteBuffer(qb422016)
2130-//line templates/login.qtpl:6
2131+//line templates/login.qtpl:9
2132 return qs422016
2133-//line templates/login.qtpl:6
2134+//line templates/login.qtpl:9
2135 }
2136
2137-//line templates/login.qtpl:8
2138-func (p *LoginPage) StreamNavbar(qw422016 *qt422016.Writer) {
2139-//line templates/login.qtpl:8
2140- StreamNavbar(qw422016, Login)
2141-//line templates/login.qtpl:8
2142+//line templates/login.qtpl:11
2143+func (p *LoginPage) StreamNavbar(qw422016 *qt422016.Writer, ctx context.Context) {
2144+//line templates/login.qtpl:11
2145+ StreamNavbar(qw422016, ctx, Login)
2146+//line templates/login.qtpl:11
2147 }
2148
2149-//line templates/login.qtpl:8
2150-func (p *LoginPage) WriteNavbar(qq422016 qtio422016.Writer) {
2151-//line templates/login.qtpl:8
2152+//line templates/login.qtpl:11
2153+func (p *LoginPage) WriteNavbar(qq422016 qtio422016.Writer, ctx context.Context) {
2154+//line templates/login.qtpl:11
2155 qw422016 := qt422016.AcquireWriter(qq422016)
2156-//line templates/login.qtpl:8
2157- p.StreamNavbar(qw422016)
2158-//line templates/login.qtpl:8
2159+//line templates/login.qtpl:11
2160+ p.StreamNavbar(qw422016, ctx)
2161+//line templates/login.qtpl:11
2162 qt422016.ReleaseWriter(qw422016)
2163-//line templates/login.qtpl:8
2164+//line templates/login.qtpl:11
2165 }
2166
2167-//line templates/login.qtpl:8
2168-func (p *LoginPage) Navbar() string {
2169-//line templates/login.qtpl:8
2170+//line templates/login.qtpl:11
2171+func (p *LoginPage) Navbar(ctx context.Context) string {
2172+//line templates/login.qtpl:11
2173 qb422016 := qt422016.AcquireByteBuffer()
2174-//line templates/login.qtpl:8
2175- p.WriteNavbar(qb422016)
2176-//line templates/login.qtpl:8
2177+//line templates/login.qtpl:11
2178+ p.WriteNavbar(qb422016, ctx)
2179+//line templates/login.qtpl:11
2180 qs422016 := string(qb422016.B)
2181-//line templates/login.qtpl:8
2182+//line templates/login.qtpl:11
2183 qt422016.ReleaseByteBuffer(qb422016)
2184-//line templates/login.qtpl:8
2185+//line templates/login.qtpl:11
2186 return qs422016
2187-//line templates/login.qtpl:8
2188+//line templates/login.qtpl:11
2189 }
2190
2191-//line templates/login.qtpl:10
2192-func (p *LoginPage) StreamContent(qw422016 *qt422016.Writer) {
2193-//line templates/login.qtpl:10
2194+//line templates/login.qtpl:13
2195+func (p *LoginPage) StreamContent(qw422016 *qt422016.Writer, ctx context.Context) {
2196+//line templates/login.qtpl:13
2197 qw422016.N().S(`
2198 <div class="row">
2199 <div class="col-md-6 offset-md-3">
2200- <form>
2201+ <form action="/login/" method="POST">
2202 <div class="form-group m-3">
2203 <label for="username" class="form-label">Username</label>
2204- <input type="text" class="form-control" id="username" aria-describedby="emailHelp">
2205+ <input type="text" class="form-control" name="username" id="username">
2206 </div>
2207 <div class="form-group m-3">
2208 <label for="password" class="form-label">Password</label>
2209- <input type="password" class="form-control" id="password">
2210+ <input type="password" class="form-control" name="password" id="password">
2211 </div>
2212 <div class="form-group m-3">
2213 <button type="submit" class="btn btn-primary">Login</button>
2214 </div>
2215 </form>
2216 </div>
2217+ `)
2218+//line templates/login.qtpl:30
2219+ if p.ErrorMessage != "" {
2220+//line templates/login.qtpl:30
2221+ qw422016.N().S(`
2222+ <div class="col-md-6 offset-md-3">
2223+ <div class="alert alert-warning text-center" >
2224+ `)
2225+//line templates/login.qtpl:33
2226+ qw422016.E().S(p.ErrorMessage)
2227+//line templates/login.qtpl:33
2228+ qw422016.N().S(`
2229+ </div>
2230+ </div>
2231+ `)
2232+//line templates/login.qtpl:36
2233+ }
2234+//line templates/login.qtpl:36
2235+ qw422016.N().S(`
2236 </div>
2237 `)
2238-//line templates/login.qtpl:28
2239+//line templates/login.qtpl:38
2240 }
2241
2242-//line templates/login.qtpl:28
2243-func (p *LoginPage) WriteContent(qq422016 qtio422016.Writer) {
2244-//line templates/login.qtpl:28
2245+//line templates/login.qtpl:38
2246+func (p *LoginPage) WriteContent(qq422016 qtio422016.Writer, ctx context.Context) {
2247+//line templates/login.qtpl:38
2248 qw422016 := qt422016.AcquireWriter(qq422016)
2249-//line templates/login.qtpl:28
2250- p.StreamContent(qw422016)
2251-//line templates/login.qtpl:28
2252+//line templates/login.qtpl:38
2253+ p.StreamContent(qw422016, ctx)
2254+//line templates/login.qtpl:38
2255 qt422016.ReleaseWriter(qw422016)
2256-//line templates/login.qtpl:28
2257+//line templates/login.qtpl:38
2258 }
2259
2260-//line templates/login.qtpl:28
2261-func (p *LoginPage) Content() string {
2262-//line templates/login.qtpl:28
2263+//line templates/login.qtpl:38
2264+func (p *LoginPage) Content(ctx context.Context) string {
2265+//line templates/login.qtpl:38
2266 qb422016 := qt422016.AcquireByteBuffer()
2267-//line templates/login.qtpl:28
2268- p.WriteContent(qb422016)
2269-//line templates/login.qtpl:28
2270+//line templates/login.qtpl:38
2271+ p.WriteContent(qb422016, ctx)
2272+//line templates/login.qtpl:38
2273 qs422016 := string(qb422016.B)
2274-//line templates/login.qtpl:28
2275+//line templates/login.qtpl:38
2276 qt422016.ReleaseByteBuffer(qb422016)
2277-//line templates/login.qtpl:28
2278+//line templates/login.qtpl:38
2279 return qs422016
2280-//line templates/login.qtpl:28
2281+//line templates/login.qtpl:38
2282 }
2283
2284-//line templates/login.qtpl:30
2285-func (p *LoginPage) StreamScript(qw422016 *qt422016.Writer) {
2286-//line templates/login.qtpl:30
2287+//line templates/login.qtpl:40
2288+func (p *LoginPage) StreamScript(qw422016 *qt422016.Writer, ctx context.Context) {
2289+//line templates/login.qtpl:40
2290 qw422016.N().S(`
2291 `)
2292-//line templates/login.qtpl:31
2293+//line templates/login.qtpl:41
2294 }
2295
2296-//line templates/login.qtpl:31
2297-func (p *LoginPage) WriteScript(qq422016 qtio422016.Writer) {
2298-//line templates/login.qtpl:31
2299+//line templates/login.qtpl:41
2300+func (p *LoginPage) WriteScript(qq422016 qtio422016.Writer, ctx context.Context) {
2301+//line templates/login.qtpl:41
2302 qw422016 := qt422016.AcquireWriter(qq422016)
2303-//line templates/login.qtpl:31
2304- p.StreamScript(qw422016)
2305-//line templates/login.qtpl:31
2306+//line templates/login.qtpl:41
2307+ p.StreamScript(qw422016, ctx)
2308+//line templates/login.qtpl:41
2309 qt422016.ReleaseWriter(qw422016)
2310-//line templates/login.qtpl:31
2311+//line templates/login.qtpl:41
2312 }
2313
2314-//line templates/login.qtpl:31
2315-func (p *LoginPage) Script() string {
2316-//line templates/login.qtpl:31
2317+//line templates/login.qtpl:41
2318+func (p *LoginPage) Script(ctx context.Context) string {
2319+//line templates/login.qtpl:41
2320 qb422016 := qt422016.AcquireByteBuffer()
2321-//line templates/login.qtpl:31
2322- p.WriteScript(qb422016)
2323-//line templates/login.qtpl:31
2324+//line templates/login.qtpl:41
2325+ p.WriteScript(qb422016, ctx)
2326+//line templates/login.qtpl:41
2327 qs422016 := string(qb422016.B)
2328-//line templates/login.qtpl:31
2329+//line templates/login.qtpl:41
2330 qt422016.ReleaseByteBuffer(qb422016)
2331-//line templates/login.qtpl:31
2332+//line templates/login.qtpl:41
2333 return qs422016
2334-//line templates/login.qtpl:31
2335+//line templates/login.qtpl:41
2336 }
2337diff --git a/templates/navbar.qtpl b/templates/navbar.qtpl
2338index 18400b19faa99a904eecd35b103dce288b378cfb..3cd1b39dd764a9754891be72beb340c74bcae476 100644
2339--- a/templates/navbar.qtpl
2340+++ b/templates/navbar.qtpl
2341@@ -1,3 +1,5 @@
2342+{% import "context" %}
2343+
2344 {% code
2345 type Selection int
2346 const (
2347@@ -22,13 +24,17 @@ %}
2348
2349 {% func insertIfEqual(s, d any) %}{% if s == d %} selected{% endif %}{% endfunc %}
2350
2351-{% func Navbar (s Selection) %}
2352+{% func Navbar (ctx context.Context, s Selection) %}
2353 <nav class="container navbar navbar-expand">
2354 <div class="navbar-nav">
2355 <a class="nav-link{%= insertIfEqual(s, Git) %}" href="/">git</a>
2356 </div>
2357 <div class="navbar-nav ms-auto">
2358+ {% if IsLoggedIn(ctx) %}
2359+ <a class="nav-link{%= insertIfEqual(s, Login) %}" href="/logout">logout</a>
2360+ {% else %}
2361 <a class="nav-link{%= insertIfEqual(s, Login) %}" href="/login">login</a>
2362+ {% endif %}
2363 {% comment %}
2364 Add this back once needed
2365 <a class="nav-link{%= insertIfEqual(s, List) %}" href="/list/">list</a>
2366diff --git a/templates/navbar.qtpl.go b/templates/navbar.qtpl.go
2367index e080785da7c19c0dee4de95c1e329e319d293957..d900c9cfe6bf59b13261796d539952e453cec6d0 100644
2368--- a/templates/navbar.qtpl.go
2369+++ b/templates/navbar.qtpl.go
2370@@ -5,19 +5,22 @@ //line templates/navbar.qtpl:1
2371 package templates
2372
2373 //line templates/navbar.qtpl:1
2374+import "context"
2375+
2376+//line templates/navbar.qtpl:3
2377 import (
2378 qtio422016 "io"
2379
2380 qt422016 "github.com/valyala/quicktemplate"
2381 )
2382
2383-//line templates/navbar.qtpl:1
2384+//line templates/navbar.qtpl:3
2385 var (
2386 _ = qtio422016.Copy
2387 _ = qt422016.AcquireByteBuffer
2388 )
2389
2390-//line templates/navbar.qtpl:2
2391+//line templates/navbar.qtpl:4
2392 type Selection int
2393
2394 const (
2395@@ -28,7 +31,7 @@ Config
2396 Login
2397 )
2398
2399-//line templates/navbar.qtpl:13
2400+//line templates/navbar.qtpl:15
2401 type GitSelection int
2402
2403 const (
2404@@ -39,213 +42,233 @@ Refs
2405 Tree
2406 )
2407
2408-//line templates/navbar.qtpl:23
2409+//line templates/navbar.qtpl:25
2410 func streaminsertIfEqual(qw422016 *qt422016.Writer, s, d any) {
2411-//line templates/navbar.qtpl:23
2412+//line templates/navbar.qtpl:25
2413 if s == d {
2414-//line templates/navbar.qtpl:23
2415+//line templates/navbar.qtpl:25
2416 qw422016.N().S(` selected`)
2417-//line templates/navbar.qtpl:23
2418+//line templates/navbar.qtpl:25
2419 }
2420-//line templates/navbar.qtpl:23
2421+//line templates/navbar.qtpl:25
2422 }
2423
2424-//line templates/navbar.qtpl:23
2425+//line templates/navbar.qtpl:25
2426 func writeinsertIfEqual(qq422016 qtio422016.Writer, s, d any) {
2427-//line templates/navbar.qtpl:23
2428+//line templates/navbar.qtpl:25
2429 qw422016 := qt422016.AcquireWriter(qq422016)
2430-//line templates/navbar.qtpl:23
2431+//line templates/navbar.qtpl:25
2432 streaminsertIfEqual(qw422016, s, d)
2433-//line templates/navbar.qtpl:23
2434+//line templates/navbar.qtpl:25
2435 qt422016.ReleaseWriter(qw422016)
2436-//line templates/navbar.qtpl:23
2437+//line templates/navbar.qtpl:25
2438 }
2439
2440-//line templates/navbar.qtpl:23
2441+//line templates/navbar.qtpl:25
2442 func insertIfEqual(s, d any) string {
2443-//line templates/navbar.qtpl:23
2444+//line templates/navbar.qtpl:25
2445 qb422016 := qt422016.AcquireByteBuffer()
2446-//line templates/navbar.qtpl:23
2447+//line templates/navbar.qtpl:25
2448 writeinsertIfEqual(qb422016, s, d)
2449-//line templates/navbar.qtpl:23
2450+//line templates/navbar.qtpl:25
2451 qs422016 := string(qb422016.B)
2452-//line templates/navbar.qtpl:23
2453+//line templates/navbar.qtpl:25
2454 qt422016.ReleaseByteBuffer(qb422016)
2455-//line templates/navbar.qtpl:23
2456+//line templates/navbar.qtpl:25
2457 return qs422016
2458-//line templates/navbar.qtpl:23
2459+//line templates/navbar.qtpl:25
2460 }
2461
2462-//line templates/navbar.qtpl:25
2463-func StreamNavbar(qw422016 *qt422016.Writer, s Selection) {
2464-//line templates/navbar.qtpl:25
2465+//line templates/navbar.qtpl:27
2466+func StreamNavbar(qw422016 *qt422016.Writer, ctx context.Context, s Selection) {
2467+//line templates/navbar.qtpl:27
2468 qw422016.N().S(`
2469 <nav class="container navbar navbar-expand">
2470 <div class="navbar-nav">
2471 <a class="nav-link`)
2472-//line templates/navbar.qtpl:28
2473+//line templates/navbar.qtpl:30
2474 streaminsertIfEqual(qw422016, s, Git)
2475-//line templates/navbar.qtpl:28
2476+//line templates/navbar.qtpl:30
2477 qw422016.N().S(`" href="/">git</a>
2478 </div>
2479 <div class="navbar-nav ms-auto">
2480+ `)
2481+//line templates/navbar.qtpl:33
2482+ if IsLoggedIn(ctx) {
2483+//line templates/navbar.qtpl:33
2484+ qw422016.N().S(`
2485 <a class="nav-link`)
2486-//line templates/navbar.qtpl:31
2487- streaminsertIfEqual(qw422016, s, Login)
2488-//line templates/navbar.qtpl:31
2489- qw422016.N().S(`" href="/login">login</a>
2490+//line templates/navbar.qtpl:34
2491+ streaminsertIfEqual(qw422016, s, Login)
2492+//line templates/navbar.qtpl:34
2493+ qw422016.N().S(`" href="/logout">logout</a>
2494+ `)
2495+//line templates/navbar.qtpl:35
2496+ } else {
2497+//line templates/navbar.qtpl:35
2498+ qw422016.N().S(`
2499+ <a class="nav-link`)
2500+//line templates/navbar.qtpl:36
2501+ streaminsertIfEqual(qw422016, s, Login)
2502+//line templates/navbar.qtpl:36
2503+ qw422016.N().S(`" href="/login">login</a>
2504+ `)
2505+//line templates/navbar.qtpl:37
2506+ }
2507+//line templates/navbar.qtpl:37
2508+ qw422016.N().S(`
2509 `)
2510-//line templates/navbar.qtpl:35
2511+//line templates/navbar.qtpl:41
2512 qw422016.N().S(`
2513 `)
2514-//line templates/navbar.qtpl:39
2515+//line templates/navbar.qtpl:45
2516 qw422016.N().S(`
2517 </div>
2518 </nav>
2519 `)
2520-//line templates/navbar.qtpl:42
2521+//line templates/navbar.qtpl:48
2522 }
2523
2524-//line templates/navbar.qtpl:42
2525-func WriteNavbar(qq422016 qtio422016.Writer, s Selection) {
2526-//line templates/navbar.qtpl:42
2527+//line templates/navbar.qtpl:48
2528+func WriteNavbar(qq422016 qtio422016.Writer, ctx context.Context, s Selection) {
2529+//line templates/navbar.qtpl:48
2530 qw422016 := qt422016.AcquireWriter(qq422016)
2531-//line templates/navbar.qtpl:42
2532- StreamNavbar(qw422016, s)
2533-//line templates/navbar.qtpl:42
2534+//line templates/navbar.qtpl:48
2535+ StreamNavbar(qw422016, ctx, s)
2536+//line templates/navbar.qtpl:48
2537 qt422016.ReleaseWriter(qw422016)
2538-//line templates/navbar.qtpl:42
2539+//line templates/navbar.qtpl:48
2540 }
2541
2542-//line templates/navbar.qtpl:42
2543-func Navbar(s Selection) string {
2544-//line templates/navbar.qtpl:42
2545+//line templates/navbar.qtpl:48
2546+func Navbar(ctx context.Context, s Selection) string {
2547+//line templates/navbar.qtpl:48
2548 qb422016 := qt422016.AcquireByteBuffer()
2549-//line templates/navbar.qtpl:42
2550- WriteNavbar(qb422016, s)
2551-//line templates/navbar.qtpl:42
2552+//line templates/navbar.qtpl:48
2553+ WriteNavbar(qb422016, ctx, s)
2554+//line templates/navbar.qtpl:48
2555 qs422016 := string(qb422016.B)
2556-//line templates/navbar.qtpl:42
2557+//line templates/navbar.qtpl:48
2558 qt422016.ReleaseByteBuffer(qb422016)
2559-//line templates/navbar.qtpl:42
2560+//line templates/navbar.qtpl:48
2561 return qs422016
2562-//line templates/navbar.qtpl:42
2563+//line templates/navbar.qtpl:48
2564 }
2565
2566-//line templates/navbar.qtpl:44
2567+//line templates/navbar.qtpl:50
2568 func StreamGitItemNav(qw422016 *qt422016.Writer, name, ref string, s GitSelection) {
2569-//line templates/navbar.qtpl:44
2570+//line templates/navbar.qtpl:50
2571 qw422016.N().S(`
2572 <div class="row">
2573 <h3 id="name">`)
2574-//line templates/navbar.qtpl:46
2575+//line templates/navbar.qtpl:52
2576 qw422016.E().S(name)
2577-//line templates/navbar.qtpl:46
2578+//line templates/navbar.qtpl:52
2579 qw422016.N().S(` `)
2580-//line templates/navbar.qtpl:46
2581+//line templates/navbar.qtpl:52
2582 if ref != "" && (s == Log || s == Tree) {
2583-//line templates/navbar.qtpl:46
2584+//line templates/navbar.qtpl:52
2585 qw422016.N().S(`@ `)
2586-//line templates/navbar.qtpl:46
2587+//line templates/navbar.qtpl:52
2588 qw422016.E().S(ref)
2589-//line templates/navbar.qtpl:46
2590+//line templates/navbar.qtpl:52
2591 }
2592-//line templates/navbar.qtpl:46
2593+//line templates/navbar.qtpl:52
2594 qw422016.N().S(`</h3>
2595 </div>
2596 <div class="row">
2597 <ul class="nav">
2598 <li class="nav-item">
2599 <a class="nav-link`)
2600-//line templates/navbar.qtpl:51
2601+//line templates/navbar.qtpl:57
2602 streaminsertIfEqual(qw422016, s, Readme)
2603-//line templates/navbar.qtpl:51
2604+//line templates/navbar.qtpl:57
2605 qw422016.N().S(`" aria-current="page" href="/`)
2606-//line templates/navbar.qtpl:51
2607+//line templates/navbar.qtpl:57
2608 qw422016.E().S(name)
2609-//line templates/navbar.qtpl:51
2610+//line templates/navbar.qtpl:57
2611 qw422016.N().S(`/about/">about</a>
2612 </li>
2613 <li class="nav-item">
2614 <a class="nav-link`)
2615-//line templates/navbar.qtpl:54
2616+//line templates/navbar.qtpl:60
2617 streaminsertIfEqual(qw422016, s, Summary)
2618-//line templates/navbar.qtpl:54
2619+//line templates/navbar.qtpl:60
2620 qw422016.N().S(`" aria-current="page" href="/`)
2621-//line templates/navbar.qtpl:54
2622+//line templates/navbar.qtpl:60
2623 qw422016.E().S(name)
2624-//line templates/navbar.qtpl:54
2625+//line templates/navbar.qtpl:60
2626 qw422016.N().S(`/">summary</a>
2627 </li>
2628 <li class="nav-item">
2629 <a class="nav-link`)
2630-//line templates/navbar.qtpl:57
2631+//line templates/navbar.qtpl:63
2632 streaminsertIfEqual(qw422016, s, Refs)
2633-//line templates/navbar.qtpl:57
2634+//line templates/navbar.qtpl:63
2635 qw422016.N().S(`" aria-current="page" href="/`)
2636-//line templates/navbar.qtpl:57
2637+//line templates/navbar.qtpl:63
2638 qw422016.E().S(name)
2639-//line templates/navbar.qtpl:57
2640+//line templates/navbar.qtpl:63
2641 qw422016.N().S(`/refs/">refs</a>
2642 </li>
2643 <li class="nav-item">
2644 <a class="nav-link`)
2645-//line templates/navbar.qtpl:60
2646+//line templates/navbar.qtpl:66
2647 streaminsertIfEqual(qw422016, s, Log)
2648-//line templates/navbar.qtpl:60
2649+//line templates/navbar.qtpl:66
2650 qw422016.N().S(`" aria-current="page" href="/`)
2651-//line templates/navbar.qtpl:60
2652+//line templates/navbar.qtpl:66
2653 qw422016.E().S(name)
2654-//line templates/navbar.qtpl:60
2655+//line templates/navbar.qtpl:66
2656 qw422016.N().S(`/log/`)
2657-//line templates/navbar.qtpl:60
2658+//line templates/navbar.qtpl:66
2659 qw422016.E().S(ref)
2660-//line templates/navbar.qtpl:60
2661+//line templates/navbar.qtpl:66
2662 qw422016.N().S(`/">log</a>
2663 </li>
2664 <li class="nav-item">
2665 <a class="nav-link`)
2666-//line templates/navbar.qtpl:63
2667+//line templates/navbar.qtpl:69
2668 streaminsertIfEqual(qw422016, s, Tree)
2669-//line templates/navbar.qtpl:63
2670+//line templates/navbar.qtpl:69
2671 qw422016.N().S(`" aria-current="page" href="/`)
2672-//line templates/navbar.qtpl:63
2673+//line templates/navbar.qtpl:69
2674 qw422016.E().S(name)
2675-//line templates/navbar.qtpl:63
2676+//line templates/navbar.qtpl:69
2677 qw422016.N().S(`/tree/`)
2678-//line templates/navbar.qtpl:63
2679+//line templates/navbar.qtpl:69
2680 qw422016.E().S(ref)
2681-//line templates/navbar.qtpl:63
2682+//line templates/navbar.qtpl:69
2683 qw422016.N().S(`/">tree</a>
2684 </li>
2685 </ul>
2686 </div>
2687 `)
2688-//line templates/navbar.qtpl:67
2689+//line templates/navbar.qtpl:73
2690 }
2691
2692-//line templates/navbar.qtpl:67
2693+//line templates/navbar.qtpl:73
2694 func WriteGitItemNav(qq422016 qtio422016.Writer, name, ref string, s GitSelection) {
2695-//line templates/navbar.qtpl:67
2696+//line templates/navbar.qtpl:73
2697 qw422016 := qt422016.AcquireWriter(qq422016)
2698-//line templates/navbar.qtpl:67
2699+//line templates/navbar.qtpl:73
2700 StreamGitItemNav(qw422016, name, ref, s)
2701-//line templates/navbar.qtpl:67
2702+//line templates/navbar.qtpl:73
2703 qt422016.ReleaseWriter(qw422016)
2704-//line templates/navbar.qtpl:67
2705+//line templates/navbar.qtpl:73
2706 }
2707
2708-//line templates/navbar.qtpl:67
2709+//line templates/navbar.qtpl:73
2710 func GitItemNav(name, ref string, s GitSelection) string {
2711-//line templates/navbar.qtpl:67
2712+//line templates/navbar.qtpl:73
2713 qb422016 := qt422016.AcquireByteBuffer()
2714-//line templates/navbar.qtpl:67
2715+//line templates/navbar.qtpl:73
2716 WriteGitItemNav(qb422016, name, ref, s)
2717-//line templates/navbar.qtpl:67
2718+//line templates/navbar.qtpl:73
2719 qs422016 := string(qb422016.B)
2720-//line templates/navbar.qtpl:67
2721+//line templates/navbar.qtpl:73
2722 qt422016.ReleaseByteBuffer(qb422016)
2723-//line templates/navbar.qtpl:67
2724+//line templates/navbar.qtpl:73
2725 return qs422016
2726-//line templates/navbar.qtpl:67
2727+//line templates/navbar.qtpl:73
2728 }