all repos — weimar @ 3ab9da929b53350b9e5a860642317e5a8f5b3750

Unnamed repository; edit this file 'description' to name the repository.

cmd/weimar/serve.go (view raw)

 1package main
 2
 3import (
 4	"embed"
 5	"fmt"
 6	"io/fs"
 7	"log/slog"
 8	"os/signal"
 9	"syscall"
10
11	"github.com/mjensen/weimar/internal/auth"
12	"github.com/mjensen/weimar/internal/config"
13	"github.com/mjensen/weimar/internal/db"
14	"github.com/mjensen/weimar/internal/server"
15	"github.com/spf13/cobra"
16	"github.com/spf13/viper"
17)
18
19//go:embed web/build/*
20var webFS embed.FS
21
22var adminEmail string
23var adminPassword string
24
25var serveCmd = &cobra.Command{
26	Use:   "serve",
27	Short: "Start the HTTP server",
28	RunE: func(cmd *cobra.Command, args []string) error {
29		cfg := config.FromViper()
30
31		webSub, err := fs.Sub(webFS, "web/build")
32		if err != nil {
33			return fmt.Errorf("reading embedded web build: %w", err)
34		}
35
36		database, err := db.Open(cfg.Database.Path)
37		if err != nil {
38			return fmt.Errorf("opening database: %w", err)
39		}
40		defer database.Close()
41
42		if err := database.Migrate(cmd.Context()); err != nil {
43			return fmt.Errorf("running migrations: %w", err)
44		}
45
46		// Create admin user on first run if no users exist and credentials are provided.
47		if adminEmail != "" && adminPassword != "" {
48			users, err := database.ListUsers(cmd.Context())
49			if err != nil {
50				return fmt.Errorf("checking for existing users: %w", err)
51			}
52			if len(users) == 0 {
53				if _, err := auth.Register(cmd.Context(), database, adminEmail, adminPassword, true); err != nil {
54					return fmt.Errorf("creating admin user: %w", err)
55				}
56				slog.Info("created initial admin user", "username", adminEmail)
57			}
58		}
59
60		srv, err := server.New(cfg, webSub, database)
61		if err != nil {
62			return fmt.Errorf("creating server: %w", err)
63		}
64
65		ctx, stop := signal.NotifyContext(cmd.Context(), syscall.SIGINT, syscall.SIGTERM)
66		defer stop()
67
68		slog.Info("starting weimar", "host", cfg.Server.Host, "port", cfg.Server.Port)
69		if err := srv.Start(ctx); err != nil {
70			return fmt.Errorf("server error: %w", err)
71		}
72
73		return nil
74	},
75}
76
77func init() {
78	rootCmd.AddCommand(serveCmd)
79	serveCmd.Flags().StringVar(&adminEmail, "admin-email", "", "admin email for first-run setup")
80	serveCmd.Flags().StringVar(&adminPassword, "admin-password", "", "admin password for first-run setup")
81	viper.BindPFlag("server.host", serveCmd.Flags().Lookup("host"))
82	viper.BindPFlag("server.port", serveCmd.Flags().Lookup("port"))
83}