mirror of
https://github.com/rjNemo/auth
synced 2026-06-06 08:26:39 +00:00
95 lines
1.9 KiB
Go
95 lines
1.9 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"crypto/rand"
|
|
"fmt"
|
|
"html/template"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/go-chi/chi/v5/middleware"
|
|
|
|
"github.com/rjnemo/auth/internal/auth"
|
|
"github.com/rjnemo/auth/web"
|
|
)
|
|
|
|
const (
|
|
seedEmail = "user@example.com"
|
|
seedPassword = "password123"
|
|
)
|
|
|
|
// Server holds HTTP dependencies for the application.
|
|
type Server struct {
|
|
templates *template.Template
|
|
authService *auth.Service
|
|
sessions *SessionStore
|
|
}
|
|
|
|
// New constructs a Server with parsed templates and default state.
|
|
func New() (*Server, error) {
|
|
tmpl, err := template.ParseFS(
|
|
web.Templates,
|
|
"templates/index.html",
|
|
"templates/in.html",
|
|
"templates/unauthorized.html",
|
|
)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("parse templates: %w", err)
|
|
}
|
|
|
|
store := auth.NewMemoryStore()
|
|
if err := seedUser(store); err != nil {
|
|
return nil, fmt.Errorf("seed user: %w", err)
|
|
}
|
|
|
|
secret := make([]byte, 32)
|
|
if _, err := rand.Read(secret); err != nil {
|
|
return nil, fmt.Errorf("session secret: %w", err)
|
|
}
|
|
|
|
sessionStore, err := NewSessionStore(secret)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("session store: %w", err)
|
|
}
|
|
|
|
return &Server{
|
|
templates: tmpl,
|
|
authService: auth.NewService(store),
|
|
sessions: sessionStore,
|
|
}, nil
|
|
}
|
|
|
|
// Router returns the configured HTTP router.
|
|
func (s *Server) Router() http.Handler {
|
|
r := chi.NewRouter()
|
|
r.Use(
|
|
middleware.RequestID,
|
|
middleware.RealIP,
|
|
middleware.Logger,
|
|
middleware.Recoverer,
|
|
s.sessionMiddleware,
|
|
s.csrfMiddleware,
|
|
)
|
|
s.registerRoutes(r)
|
|
return r
|
|
}
|
|
|
|
func seedUser(store auth.UserStore) error {
|
|
salt, hash, err := auth.HashPassword(seedPassword)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
email := auth.MustUserEmail(seedEmail)
|
|
|
|
ctx := context.Background()
|
|
return store.Create(ctx, auth.User{
|
|
ID: "seed-user",
|
|
Email: email,
|
|
PasswordSalt: salt,
|
|
PasswordHash: hash,
|
|
CreatedAt: time.Now().UTC(),
|
|
})
|
|
}
|