package main import ( "context" "fmt" "log/slog" "net/http" "os" "time" "atlas9.dev/c/core/dbi" "atlas9.dev/c/core/iam" "atlas9.dev/c/core/routes" "atlas9.dev/c/iam/scs_session" "github.com/alexedwards/scs/v2" ) func main() { err := run() if err != nil { slog.Error(err.Error()) os.Exit(1) } } func run() error { // Load config config, err := loadConfig("config.toml") if err != nil { return err } // DB connection and migration db, err := initDB(config) if err != nil { return err } defer db.Close() // Data stores users := func(tx dbi.DBI) iam.UserStore { return NewSqliteUserStore(tx) } passwords := func(tx dbi.DBI) iam.PasswordStore { return NewSqlitePasswordHashStore(tx) } profiles := func(tx dbi.DBI) *ProfileStore { return NewProfileStore(tx) } sessions := sessionStore(config) // OAuth links for login page var oauthLinks []OAuthLink if config.OAuth.Google.ClientID != "" { oauthLinks = append(oauthLinks, OAuthLink{Name: "Google", URL: "/auth/google"}) } if config.OAuth.Apple.ClientID != "" { oauthLinks = append(oauthLinks, OAuthLink{Name: "Apple", URL: "/auth/apple"}) } if config.OAuth.GitHub.ClientID != "" { oauthLinks = append(oauthLinks, OAuthLink{Name: "GitHub", URL: "/auth/github"}) } // Pages pages := NewPages(db, users, passwords, profiles, sessions, oauthLinks) // Routes mux := http.NewServeMux() routes.Register(mux, PageRoutes(pages)) routes.Register(mux, routes.SimpleHealth()) // OIDC providers err = initOauth(context.Background(), config, db, mux, users, sessions) if err != nil { return err } // Wrap with session middleware handler := scs_session.Middleware(sessions, mux) // Serve addr := fmt.Sprintf(":%d", config.Server.Port) slog.Info("Server starting", "addr", addr) return http.ListenAndServe(addr, handler) } func sessionStore(config *Config) *scs_session.Store { sessionManager := scs.New() sessionManager.Lifetime = time.Duration(config.Session.LifetimeHours) * time.Hour sessionManager.Cookie.Name = "atlas9_demo_session" sessionManager.Cookie.HttpOnly = true sessionManager.Cookie.Secure = true // Lax is required for OAuth flows: Strict cookies are not sent on // redirects from external identity providers (e.g. Google). sessionManager.Cookie.SameSite = http.SameSiteLaxMode return scs_session.New(sessionManager) }