1package ext
2
3import (
4 "context"
5 "encoding/base64"
6 "errors"
7 "log/slog"
8 "net/http"
9
10 serverconfig "git.gabrielgio.me/cerrado/pkg/config"
11)
12
13type authService interface {
14 ValidateToken(token []byte) (bool, error)
15}
16
17func DisableAuthentication(next http.HandlerFunc) http.HandlerFunc {
18 return func(w http.ResponseWriter, r *http.Request) {
19 ctx := r.Context()
20 ctx = context.WithValue(ctx, "disableAuthentication", true)
21 next(w, r.WithContext(ctx))
22 }
23}
24
25func VerifyRespository(
26 config *serverconfig.ConfigurationRepository,
27) func(next http.HandlerFunc) http.HandlerFunc {
28 return func(next http.HandlerFunc) http.HandlerFunc {
29 return func(w http.ResponseWriter, r *http.Request) {
30 name := r.PathValue("name")
31 if name != "" {
32 repo := config.GetByName(name)
33 if repo != nil && !repo.Public && !IsLoggedIn(r.Context()) {
34 NotFound(w, r)
35 return
36 }
37 }
38
39 next(w, r)
40 }
41 }
42}
43
44func Authenticate(auth authService) func(next http.HandlerFunc) http.HandlerFunc {
45 return func(next http.HandlerFunc) http.HandlerFunc {
46 return func(w http.ResponseWriter, r *http.Request) {
47 cookie, err := r.Cookie("auth")
48 if err != nil {
49 if !errors.Is(err, http.ErrNoCookie) {
50 slog.Error("Error loading cookie", "error", err)
51 }
52
53 next(w, r)
54 return
55 }
56
57 value, err := base64.StdEncoding.DecodeString(cookie.Value)
58 if err != nil {
59 slog.Error("Error decoding", "error", err)
60 next(w, r)
61 return
62 }
63
64 valid, err := auth.ValidateToken(value)
65 if err != nil {
66 slog.Error("Error validating token", "error", err, "cookie", cookie.Value)
67 next(w, r)
68 return
69 }
70
71 ctx := r.Context()
72 ctx = context.WithValue(ctx, "logged", valid)
73
74 slog.Info("Validated token", "valid?", valid)
75 next(w, r.WithContext(ctx))
76 }
77 }
78}
79
80func IsLoggedIn(ctx context.Context) bool {
81 t, ok := ctx.Value("logged").(bool)
82 return ok && t
83}