implement work with services

This commit is contained in:
2025-12-18 19:57:38 +02:00
parent 438bed8f13
commit ad980ee600

View File

@@ -13,16 +13,23 @@ import (
"git.oblat.lv/alex/triggerssmith/api" "git.oblat.lv/alex/triggerssmith/api"
application "git.oblat.lv/alex/triggerssmith/internal/app" application "git.oblat.lv/alex/triggerssmith/internal/app"
"git.oblat.lv/alex/triggerssmith/internal/auth"
"git.oblat.lv/alex/triggerssmith/internal/config" "git.oblat.lv/alex/triggerssmith/internal/config"
"git.oblat.lv/alex/triggerssmith/internal/jwt"
"git.oblat.lv/alex/triggerssmith/internal/server" "git.oblat.lv/alex/triggerssmith/internal/server"
"git.oblat.lv/alex/triggerssmith/internal/token"
"git.oblat.lv/alex/triggerssmith/internal/user"
"git.oblat.lv/alex/triggerssmith/internal/vars" "git.oblat.lv/alex/triggerssmith/internal/vars"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
) )
var optsServeCmd = struct { var optsServeCmd = struct {
ConfigPath *string ConfigPath *string
Debug *bool Debug *bool
HideGreetings *bool HideGreetings *bool
NoPIDFile *bool
}{} }{}
// // simple middleware for request logging // // simple middleware for request logging
@@ -99,10 +106,8 @@ var serveCmd = &cobra.Command{
fmt.Fprintf(f, "Panic: %v\n", r) fmt.Fprintf(f, "Panic: %v\n", r)
f.Write(stack) f.Write(stack)
f.WriteString("\n\n") f.WriteString("\n\n")
}
slog.Error("Application panicked: the stack is flushed to disk", slog.Any("error", r)) slog.Error("Application panicked: the stack is flushed to disk", slog.Any("error", r))
}
os.Exit(-1) os.Exit(-1)
} }
}() }()
@@ -114,6 +119,7 @@ var serveCmd = &cobra.Command{
slog.SetDefault(slog.New(slog.NewTextHandler(cmd.OutOrStdout(), &slog.HandlerOptions{Level: slog.LevelInfo}))) slog.SetDefault(slog.New(slog.NewTextHandler(cmd.OutOrStdout(), &slog.HandlerOptions{Level: slog.LevelInfo})))
} }
if !*optsServeCmd.NoPIDFile {
pid := os.Getpid() pid := os.Getpid()
slog.Debug("Starting server", slog.Int("pid", pid)) slog.Debug("Starting server", slog.Int("pid", pid))
if err := writePID(vars.PID_PATH); err != nil { if err := writePID(vars.PID_PATH); err != nil {
@@ -121,6 +127,9 @@ var serveCmd = &cobra.Command{
} }
slog.Debug("created pid file", slog.String("path", vars.PID_PATH)) slog.Debug("created pid file", slog.String("path", vars.PID_PATH))
defer os.Remove(vars.PID_PATH) defer os.Remove(vars.PID_PATH)
} else {
slog.Warn("Starting server without PID file as requested by --no-pidfile flag: this may complicate process management")
}
// load config // load config
slog.Debug("Reading configuration", slog.String("path", *optsServeCmd.ConfigPath)) slog.Debug("Reading configuration", slog.String("path", *optsServeCmd.ConfigPath))
@@ -141,8 +150,80 @@ var serveCmd = &cobra.Command{
srv := app.Server() srv := app.Server()
// Services initialization
var jwtSigner jwt.Signer
// TODO: support more signing algorithms
// : support hot config reload for signing alg and secret
switch cfg.Auth.SignAlg {
case "HS256":
secretBytes, err := os.ReadFile(cfg.Auth.HMACSecretPath)
if err != nil {
slog.Error("Failed to read HMAC secret file", slog.String("path", cfg.Auth.HMACSecretPath), slog.String("error", err.Error()))
return
}
jwtSigner = jwt.NewHMACSigner(secretBytes)
default:
slog.Error("Unsupported JWT signing algorithm", slog.String("alg", cfg.Auth.SignAlg))
return
}
jwtService := jwt.NewService(jwtSigner)
router := api.NewRouter(cfg) err = os.MkdirAll(cfg.Data.DataPath, 0755)
if err != nil {
slog.Error("Failed to create data directory", slog.String("path", cfg.Data.DataPath), slog.String("error", err.Error()))
return
}
tokenDb, err := gorm.Open(sqlite.Open(filepath.Join(cfg.Data.DataPath, "tokens.sqlite3")), &gorm.Config{})
if err != nil {
slog.Error("Failed to open token database", slog.String("error", err.Error()))
return
}
err = tokenDb.AutoMigrate(&token.Token{})
if err != nil {
slog.Error("Failed to migrate token database", slog.String("error", err.Error()))
return
}
tokenStore, err := token.NewSQLiteTokenStore(tokenDb)
if err != nil {
slog.Error("Failed to create token store", slog.String("error", err.Error()))
return
}
tokenService, err := token.NewTokenService(&cfg.Auth, tokenStore)
userDb, err := gorm.Open(sqlite.Open(filepath.Join(cfg.Data.DataPath, "users.sqlite3")), &gorm.Config{})
if err != nil {
slog.Error("Failed to open user database", slog.String("error", err.Error()))
return
}
err = userDb.AutoMigrate(&user.User{})
if err != nil {
slog.Error("Failed to migrate user database", slog.String("error", err.Error()))
return
}
userStore, err := user.NewGormUserStore(userDb)
if err != nil {
slog.Error("Failed to create user store", slog.String("error", err.Error()))
return
}
userService, err := user.NewService(userStore)
authService, err := auth.NewAuthService(auth.AuthServiceDependencies{
Configuration: cfg,
JWTService: jwtService,
UserService: userService,
TokenService: tokenService,
})
if err != nil {
slog.Error("Failed to create auth service", slog.String("error", err.Error()))
return
}
router := api.NewRouter(api.RouterDependencies{
AuthService: authService,
Configuration: cfg,
})
srv.SetHandler(router.MustRoute()) srv.SetHandler(router.MustRoute())
srv.Init() srv.Init()
@@ -204,5 +285,6 @@ func init() {
optsServeCmd.Debug = serveCmd.Flags().BoolP("debug", "d", false, "Enable debug logs") optsServeCmd.Debug = serveCmd.Flags().BoolP("debug", "d", false, "Enable debug logs")
optsServeCmd.ConfigPath = serveCmd.Flags().StringP("config", "c", "config.yaml", "Path to configuration file") optsServeCmd.ConfigPath = serveCmd.Flags().StringP("config", "c", "config.yaml", "Path to configuration file")
optsServeCmd.HideGreetings = serveCmd.Flags().BoolP("hide-greetings", "g", false, "Hide the welcome message and version when starting the server") optsServeCmd.HideGreetings = serveCmd.Flags().BoolP("hide-greetings", "g", false, "Hide the welcome message and version when starting the server")
optsServeCmd.NoPIDFile = serveCmd.Flags().BoolP("no-pidfile", "p", false, "Do not write a PID file")
rootCmd.AddCommand(serveCmd) rootCmd.AddCommand(serveCmd)
} }