summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/dashboard/main.go106
1 files changed, 77 insertions, 29 deletions
diff --git a/cmd/dashboard/main.go b/cmd/dashboard/main.go
index 6e013e8..14664fc 100644
--- a/cmd/dashboard/main.go
+++ b/cmd/dashboard/main.go
@@ -2,18 +2,23 @@ package main
import (
"context"
+ "html/template"
"log"
"net/http"
"os"
"os/signal"
+ "path/filepath"
"syscall"
"time"
+ "github.com/alexedwards/scs/sqlite3store"
+ "github.com/alexedwards/scs/v2"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"github.com/joho/godotenv"
"task-dashboard/internal/api"
+ "task-dashboard/internal/auth"
"task-dashboard/internal/config"
"task-dashboard/internal/handlers"
"task-dashboard/internal/store"
@@ -36,6 +41,38 @@ func main() {
}
defer db.Close()
+ // Initialize session manager
+ sessionManager := scs.New()
+ sessionManager.Store = sqlite3store.New(db.DB())
+ sessionManager.Lifetime = 24 * time.Hour
+ sessionManager.Cookie.Secure = false // Set to true in production with HTTPS
+ sessionManager.Cookie.SameSite = http.SameSiteLaxMode
+
+ // Initialize auth service
+ authService := auth.NewService(db.DB())
+
+ // Ensure default admin user exists (use env vars for credentials)
+ defaultUser := os.Getenv("DEFAULT_USER")
+ defaultPass := os.Getenv("DEFAULT_PASS")
+ if defaultUser == "" {
+ defaultUser = "admin"
+ }
+ if defaultPass == "" {
+ defaultPass = "changeme"
+ }
+ if err := authService.EnsureDefaultUser(defaultUser, defaultPass); err != nil {
+ log.Printf("Warning: failed to ensure default user: %v", err)
+ }
+
+ // Parse templates for auth handlers
+ authTemplates, err := template.ParseGlob(filepath.Join(cfg.TemplateDir, "*.html"))
+ if err != nil {
+ log.Printf("Warning: failed to parse auth templates: %v", err)
+ }
+
+ // Initialize auth handlers
+ authHandlers := auth.NewHandlers(authService, sessionManager, authTemplates)
+
// Initialize API clients
todoistClient := api.NewTodoistClient(cfg.TodoistAPIKey)
trelloClient := api.NewTrelloClient(cfg.TrelloAPIKey, cfg.TrelloToken)
@@ -52,43 +89,54 @@ func main() {
// Set up router
r := chi.NewRouter()
- // Middleware
+ // Global middleware
r.Use(middleware.Logger)
r.Use(middleware.Recoverer)
r.Use(middleware.Timeout(60 * time.Second))
+ r.Use(sessionManager.LoadAndSave) // Session middleware must be applied globally
- // Routes
- r.Get("/", h.HandleDashboard)
- r.Post("/api/refresh", h.HandleRefresh)
- r.Get("/api/tasks", h.HandleGetTasks)
- r.Get("/api/meals", h.HandleGetMeals)
- r.Get("/api/boards", h.HandleGetBoards)
-
- // Tab routes for HTMX (using new TabsHandler)
- r.Get("/tabs/tasks", tabsHandler.HandleTasks)
- r.Get("/tabs/planning", tabsHandler.HandlePlanning)
- r.Get("/tabs/meals", tabsHandler.HandleMeals)
- r.Post("/tabs/refresh", h.HandleRefreshTab)
-
- // Trello card operations
- r.Post("/cards", h.HandleCreateCard)
- r.Post("/cards/complete", h.HandleCompleteCard)
-
- // Todoist task operations
- r.Post("/tasks", h.HandleCreateTask)
- r.Post("/tasks/complete", h.HandleCompleteTask)
+ // Public routes (no auth required)
+ r.Get("/login", authHandlers.HandleLoginPage)
+ r.Post("/login", authHandlers.HandleLogin)
+ r.Post("/logout", authHandlers.HandleLogout)
- // Unified task completion (for Tasks tab Atoms)
- r.Post("/complete-atom", h.HandleCompleteAtom)
-
- // Unified Quick Add (for Tasks tab)
- r.Post("/unified-add", h.HandleUnifiedAdd)
- r.Get("/partials/lists", h.HandleGetListsOptions)
-
- // Serve static files
+ // Serve static files (public)
fileServer := http.FileServer(http.Dir("web/static"))
r.Handle("/static/*", http.StripPrefix("/static/", fileServer))
+ // Protected routes (auth required)
+ r.Group(func(r chi.Router) {
+ r.Use(authHandlers.Middleware().RequireAuth)
+
+ // Dashboard
+ r.Get("/", h.HandleDashboard)
+ r.Post("/api/refresh", h.HandleRefresh)
+ r.Get("/api/tasks", h.HandleGetTasks)
+ r.Get("/api/meals", h.HandleGetMeals)
+ r.Get("/api/boards", h.HandleGetBoards)
+
+ // Tab routes for HTMX
+ r.Get("/tabs/tasks", tabsHandler.HandleTasks)
+ r.Get("/tabs/planning", tabsHandler.HandlePlanning)
+ r.Get("/tabs/meals", tabsHandler.HandleMeals)
+ r.Post("/tabs/refresh", h.HandleRefreshTab)
+
+ // Trello card operations
+ r.Post("/cards", h.HandleCreateCard)
+ r.Post("/cards/complete", h.HandleCompleteCard)
+
+ // Todoist task operations
+ r.Post("/tasks", h.HandleCreateTask)
+ r.Post("/tasks/complete", h.HandleCompleteTask)
+
+ // Unified task completion (for Tasks tab Atoms)
+ r.Post("/complete-atom", h.HandleCompleteAtom)
+
+ // Unified Quick Add (for Tasks tab)
+ r.Post("/unified-add", h.HandleUnifiedAdd)
+ r.Get("/partials/lists", h.HandleGetListsOptions)
+ })
+
// Start server
addr := ":" + cfg.Port
srv := &http.Server{