prepare frontend for different WireGuard backends (#426)

This commit is contained in:
Christoph Haas
2025-05-18 19:49:31 +02:00
parent 7fd2bbad02
commit 33dcc80078
17 changed files with 154 additions and 27 deletions

View File

@@ -96,10 +96,29 @@ func (e ConfigEndpoint) handleSettingsGet() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
sessionUser := domain.GetUserInfo(r.Context())
nameFn := func(backend config.Backend) []model.SettingsBackendNames {
names := make([]model.SettingsBackendNames, 0, len(backend.Mikrotik)+1)
names = append(names, model.SettingsBackendNames{
Id: backend.Default,
Name: "modals.interface-edit.backend.local",
})
for _, b := range backend.Mikrotik {
names = append(names, model.SettingsBackendNames{
Id: b.Id,
Name: b.DisplayName,
})
}
return names
}
// For anonymous users, we return the settings object with minimal information
if sessionUser.Id == domain.CtxUnknownUserId || sessionUser.Id == "" {
respond.JSON(w, http.StatusOK, model.Settings{
WebAuthnEnabled: e.cfg.Auth.WebAuthn.Enabled,
WebAuthnEnabled: e.cfg.Auth.WebAuthn.Enabled,
AvailableBackends: []model.SettingsBackendNames{}, // return an empty list instead of null
})
} else {
respond.JSON(w, http.StatusOK, model.Settings{
@@ -109,6 +128,7 @@ func (e ConfigEndpoint) handleSettingsGet() http.HandlerFunc {
ApiAdminOnly: e.cfg.Advanced.ApiAdminOnly,
WebAuthnEnabled: e.cfg.Auth.WebAuthn.Enabled,
MinPasswordLength: e.cfg.Auth.MinPasswordLength,
AvailableBackends: nameFn(e.cfg.Backend),
})
}
}

View File

@@ -6,10 +6,16 @@ type Error struct {
}
type Settings struct {
MailLinkOnly bool `json:"MailLinkOnly"`
PersistentConfigSupported bool `json:"PersistentConfigSupported"`
SelfProvisioning bool `json:"SelfProvisioning"`
ApiAdminOnly bool `json:"ApiAdminOnly"`
WebAuthnEnabled bool `json:"WebAuthnEnabled"`
MinPasswordLength int `json:"MinPasswordLength"`
MailLinkOnly bool `json:"MailLinkOnly"`
PersistentConfigSupported bool `json:"PersistentConfigSupported"`
SelfProvisioning bool `json:"SelfProvisioning"`
ApiAdminOnly bool `json:"ApiAdminOnly"`
WebAuthnEnabled bool `json:"WebAuthnEnabled"`
MinPasswordLength int `json:"MinPasswordLength"`
AvailableBackends []SettingsBackendNames `json:"AvailableBackends"`
}
type SettingsBackendNames struct {
Id string `json:"Id"`
Name string `json:"Name"`
}

View File

@@ -4,6 +4,7 @@ import (
"time"
"github.com/h44z/wg-portal/internal"
"github.com/h44z/wg-portal/internal/config"
"github.com/h44z/wg-portal/internal/domain"
)
@@ -11,6 +12,7 @@ type Interface struct {
Identifier string `json:"Identifier" example:"wg0"` // device name, for example: wg0
DisplayName string `json:"DisplayName"` // a nice display name/ description for the interface
Mode string `json:"Mode" example:"server"` // the interface type, either 'server', 'client' or 'any'
Backend string `json:"Backend" example:"local"` // the backend used for this interface e.g., local, mikrotik, ...
PrivateKey string `json:"PrivateKey" example:"abcdef=="` // private Key of the server interface
PublicKey string `json:"PublicKey" example:"abcdef=="` // public Key of the server interface
Disabled bool `json:"Disabled"` // flag that specifies if the interface is enabled (up) or not (down)
@@ -57,6 +59,7 @@ func NewInterface(src *domain.Interface, peers []domain.Peer) *Interface {
Identifier: string(src.Identifier),
DisplayName: src.DisplayName,
Mode: string(src.Type),
Backend: config.LocalBackendName, // TODO: add backend support
PrivateKey: src.PrivateKey,
PublicKey: src.PublicKey,
Disabled: src.IsDisabled(),

View File

@@ -0,0 +1,48 @@
package config
import (
"fmt"
)
const LocalBackendName = "local"
type Backend struct {
Default string `yaml:"default"` // The default backend to use (defaults to the internal backend)
Mikrotik []BackendMikrotik `yaml:"mikrotik"`
}
// Validate checks the backend configuration for errors.
func (b *Backend) Validate() error {
if b.Default == "" {
b.Default = LocalBackendName
}
uniqueMap := make(map[string]struct{})
for _, backend := range b.Mikrotik {
if backend.Id == LocalBackendName {
return fmt.Errorf("backend ID %q is a reserved keyword", LocalBackendName)
}
if _, exists := uniqueMap[backend.Id]; exists {
return fmt.Errorf("backend ID %q is not unique", backend.Id)
}
uniqueMap[backend.Id] = struct{}{}
}
if b.Default != LocalBackendName {
if _, ok := uniqueMap[b.Default]; !ok {
return fmt.Errorf("default backend %q is not defined in the configuration", b.Default)
}
}
return nil
}
type BackendMikrotik struct {
Id string `yaml:"id"` // A unique id for the Mikrotik backend
DisplayName string `yaml:"display_name"` // A display name for the Mikrotik backend
ApiUrl string `yaml:"api_url"` // The base URL of the Mikrotik API (e.g., "https://10.10.10.10:8729/rest")
ApiUser string `yaml:"api_user"`
ApiPassword string `yaml:"api_password"`
}

View File

@@ -43,6 +43,8 @@ type Config struct {
ApiAdminOnly bool `yaml:"api_admin_only"` // if true, only admin users can access the API
} `yaml:"advanced"`
Backend Backend `yaml:"backend"`
Statistics struct {
UsePingChecks bool `yaml:"use_ping_checks"`
PingCheckWorkers int `yaml:"ping_check_workers"`
@@ -94,6 +96,12 @@ func (c *Config) LogStartupValues() {
"oauthProviders", len(c.Auth.OAuth),
"ldapProviders", len(c.Auth.Ldap),
)
slog.Debug("Config Backend",
"defaultBackend", c.Backend.Default,
"extraBackends", len(c.Backend.Mikrotik),
)
}
// defaultConfig returns the default configuration
@@ -117,6 +125,10 @@ func defaultConfig() *Config {
DSN: "data/sqlite.db",
}
cfg.Backend = Backend{
Default: LocalBackendName, // local backend is the default (using wgcrtl)
}
cfg.Web = WebConfig{
RequestLogging: false,
ExternalUrl: "http://localhost:8888",
@@ -194,6 +206,10 @@ func GetConfig() (*Config, error) {
}
cfg.Web.Sanitize()
err := cfg.Backend.Validate()
if err != nil {
return nil, err
}
return cfg, nil
}