Files
wg-portal/internal/app/app.go
T

163 lines
3.9 KiB
Go
Raw Normal View History

2023-08-04 13:34:18 +02:00
package app
import (
"context"
"errors"
"fmt"
"log/slog"
"time"
2025-02-28 08:29:40 +01:00
"github.com/h44z/wg-portal/internal/config"
"github.com/h44z/wg-portal/internal/domain"
2023-08-04 13:34:18 +02:00
)
// region dependencies
2023-08-04 13:34:18 +02:00
type WireGuardManager interface {
ImportNewInterfaces(ctx context.Context, filter ...domain.InterfaceIdentifier) (int, error)
RestoreInterfaceState(ctx context.Context, updateDbOnError bool, filter ...domain.InterfaceIdentifier) error
2023-08-04 13:34:18 +02:00
}
type UserManager interface {
GetUser(ctx context.Context, id domain.UserIdentifier) (*domain.User, error)
CreateUser(ctx context.Context, user *domain.User) (*domain.User, error)
}
// endregion dependencies
// App is the main application struct.
type App struct {
cfg *config.Config
wg WireGuardManager
users UserManager
}
// Initialize creates a new App instance and initializes it.
func Initialize(
ctx context.Context,
cfg *config.Config,
wg WireGuardManager,
users UserManager,
) error {
2023-08-04 13:34:18 +02:00
a := &App{
cfg: cfg,
2023-08-04 13:34:18 +02:00
wg: wg,
users: users,
2023-08-04 13:34:18 +02:00
}
startupContext, cancel := context.WithTimeout(ctx, cfg.Advanced.StartupTimeout)
2023-08-04 13:34:18 +02:00
defer cancel()
// Switch to admin user context
startupContext = domain.SetUserInfo(startupContext, domain.SystemAdminContextUserInfo())
2025-09-08 10:39:10 +02:00
if !cfg.Core.AdminUserDisabled {
if err := a.createDefaultUser(startupContext); err != nil {
return fmt.Errorf("failed to create default user: %w", err)
}
} else {
slog.Info("Local Admin user disabled!")
2023-08-04 13:34:18 +02:00
}
if err := a.importNewInterfaces(startupContext); err != nil {
return fmt.Errorf("failed to import new interfaces: %w", err)
2023-08-04 13:34:18 +02:00
}
if err := a.restoreInterfaceState(startupContext); err != nil {
return fmt.Errorf("failed to restore interface state: %w", err)
2023-08-04 13:34:18 +02:00
}
return nil
}
func (a *App) importNewInterfaces(ctx context.Context) error {
if !a.cfg.Core.ImportExisting {
slog.Debug("skipping interface import - feature disabled")
2023-08-04 13:34:18 +02:00
return nil // feature disabled
}
importedCount, err := a.wg.ImportNewInterfaces(ctx)
2023-08-04 13:34:18 +02:00
if err != nil {
return err
}
if importedCount > 0 {
slog.Info("new interfaces imported", "count", importedCount)
2023-08-04 13:34:18 +02:00
}
return nil
}
func (a *App) restoreInterfaceState(ctx context.Context) error {
if !a.cfg.Core.RestoreState {
slog.Debug("skipping interface state restore - feature disabled")
2023-08-04 13:34:18 +02:00
return nil // feature disabled
}
err := a.wg.RestoreInterfaceState(ctx, true)
2023-08-04 13:34:18 +02:00
if err != nil {
return err
}
slog.Info("interface state restored")
2023-08-04 13:34:18 +02:00
return nil
}
func (a *App) createDefaultUser(ctx context.Context) error {
adminUserId := domain.UserIdentifier(a.cfg.Core.AdminUser)
2023-08-04 13:34:18 +02:00
if adminUserId == "" {
slog.Debug("skipping default user creation - admin user is blank")
2023-08-04 13:34:18 +02:00
return nil // empty admin user - do not create
}
_, err := a.users.GetUser(ctx, adminUserId)
2023-08-04 13:34:18 +02:00
if err != nil && !errors.Is(err, domain.ErrNotFound) {
return err
}
if err == nil {
slog.Debug("skipping default user creation - admin user already exists")
2023-08-04 13:34:18 +02:00
return nil // admin user already exists
}
now := time.Now()
defaultAdmin := &domain.User{
2023-08-04 13:34:18 +02:00
BaseModel: domain.BaseModel{
2025-01-11 22:56:25 +01:00
CreatedBy: domain.CtxSystemAdminId,
UpdatedBy: domain.CtxSystemAdminId,
2023-08-04 13:34:18 +02:00
CreatedAt: now,
UpdatedAt: now,
},
Identifier: adminUserId,
Email: "admin@wgportal.local",
IsAdmin: true,
Firstname: "WireGuard Portal",
Lastname: "Admin",
Phone: "",
Department: "",
Notes: "default administrator user",
Password: domain.PrivateString(a.cfg.Core.AdminPassword),
2023-08-04 13:34:18 +02:00
Disabled: nil,
DisabledReason: "",
Locked: nil,
LockedReason: "",
LinkedPeerCount: 0,
}
if a.cfg.Core.AdminApiToken != "" {
if len(a.cfg.Core.AdminApiToken) < 18 {
slog.Warn("admin API token is too short, should be at least 18 characters long")
}
defaultAdmin.ApiToken = a.cfg.Core.AdminApiToken
defaultAdmin.ApiTokenCreated = &now
}
admin, err := a.users.CreateUser(ctx, defaultAdmin)
2023-08-04 13:34:18 +02:00
if err != nil {
return err
}
slog.Info("admin user created", "identifier", admin.Identifier)
2023-08-04 13:34:18 +02:00
return nil
}