An OIDC-protected index page for your homeserver.
at main 2.1 kB view raw
1//go:generate go tool templ generate 2//go:generate go tool go-tw -i tailwind.css -o static/styles.css 3 4package main 5 6import ( 7 "embed" 8 "errors" 9 "log" 10 "log/slog" 11 "net/http" 12 "os" 13 14 _ "github.com/joho/godotenv/autoload" 15 gonanoid "github.com/matoous/go-nanoid/v2" 16 "github.com/sblinch/kdl-go" 17 "github.com/zitadel/logging" 18 19 "github.com/a-h/templ" 20 21 "ladon/auth" 22 "ladon/views" 23) 24 25//go:embed static 26var content embed.FS 27 28func ServeRoot(am *auth.AuthManager) http.Handler { 29 f, err := os.Open("./data/links.kdl") 30 if err != nil { 31 am.Log.Error("ladon: failed to open KDL config") 32 panic(err) 33 } 34 35 doc, err := kdl.Parse(f) 36 if err != nil { 37 am.Log.Error("ladon: failed to pase KDL config") 38 panic(err) 39 } 40 41 return http.HandlerFunc( 42 func(w http.ResponseWriter, r *http.Request) { 43 claims, err := am.GetSession(r) 44 45 if errors.Is(err, auth.ErrNoSession) { 46 templ.Handler(views.Authenticate()).ServeHTTP(w, r) 47 return 48 } else if errors.Is(err, auth.ErrSessionExpired) { 49 am.DeleteSession(w) 50 am.HandleLogin().ServeHTTP(w, r) 51 return 52 } else if err != nil { 53 http.Error(w, err.Error(), http.StatusInternalServerError) 54 return 55 } 56 57 templ.Handler(views.Links(claims.PreferredUsername, doc)).ServeHTTP(w, r) 58 }, 59 ) 60} 61 62func main() { 63 logger := slog.New( 64 slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{ 65 AddSource: true, 66 Level: slog.LevelDebug, 67 }), 68 ) 69 70 am := auth.NewAuthManager(logger) 71 72 // Handle static assets 73 fs := http.FileServer(http.FS(content)) 74 http.Handle("/static/", fs) 75 76 // Serve pages 77 http.Handle("/", ServeRoot(am)) 78 79 // Handle authentication 80 http.Handle("/login", am.HandleLogin()) 81 http.Handle("/logout", am.HandleLogout()) 82 http.Handle("/callback", am.HandleCallback()) 83 84 mw := logging.Middleware( 85 logging.WithLogger(logger), 86 logging.WithGroup("server"), 87 logging.WithIDFunc(func() slog.Attr { 88 return slog.String("id", gonanoid.Must()) 89 }), 90 ) 91 92 log.Println("Listening on port 4000") 93 if err := http.ListenAndServe(":4000", mw(http.DefaultServeMux)); err != nil { 94 panic(err) 95 } 96}