implement work with services
This commit is contained in:
90
cmd/serve.go
90
cmd/serve.go
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user