auth/internal/server/server.go

99 lines
2.4 KiB
Go

package server
import (
"context"
"errors"
"fmt"
"html/template"
"io"
"log/slog"
"github.com/rjnemo/auth/internal/config"
"github.com/rjnemo/auth/internal/driver/logging"
"github.com/rjnemo/auth/internal/service/auth"
"github.com/rjnemo/auth/web"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
)
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
logger *slog.Logger
configuration config.Config
googleOAuth *oauth2.Config
}
// New constructs a Server with parsed templates and default state using the provided service.
func New(cfg config.Config, authService *auth.Service, logger *slog.Logger) (*Server, error) {
if authService == nil {
return nil, fmt.Errorf("auth service must be provided")
}
if err := seedUser(context.Background(), authService); err != nil {
return nil, fmt.Errorf("seed user: %w", err)
}
tmpl, err := template.ParseFS(
web.Templates,
"templates/auth_base.html",
"templates/login.html",
"templates/dashboard.html",
"templates/signup.html",
"templates/unauthorized.html",
)
if err != nil {
return nil, fmt.Errorf("parse templates: %w", err)
}
sessionStore, err := NewSessionStore(cfg.SessionSecret)
if err != nil {
return nil, fmt.Errorf("session store: %w", err)
}
if logger == nil {
logger = logging.New(io.Discard, logging.ModeText, nil)
}
logger = logger.With(slog.String("service", "http"))
var googleOAuthConfig *oauth2.Config
if cfg.GoogleOAuth.Enabled() {
googleOAuthConfig = &oauth2.Config{
ClientID: cfg.GoogleOAuth.ClientID,
ClientSecret: cfg.GoogleOAuth.ClientSecret,
RedirectURL: cfg.GoogleOAuth.RedirectURL,
Scopes: []string{
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile",
},
Endpoint: google.Endpoint,
}
}
return &Server{
templates: tmpl,
authService: authService,
sessions: sessionStore,
logger: logger,
configuration: cfg,
googleOAuth: googleOAuthConfig,
}, nil
}
func seedUser(ctx context.Context, service *auth.Service) error {
email := auth.MustUserEmail(seedEmail)
if _, err := service.Register(ctx, email, seedPassword); err != nil {
if errors.Is(err, auth.ErrEmailExists) {
return nil
}
return err
}
return nil
}