From fc965fcb73986de9c9a527e6351c490a36526317 Mon Sep 17 00:00:00 2001 From: Christoph Date: Thu, 10 Sep 2026 23:10:35 +0200 Subject: [PATCH] go fix changes --- internal/adapters/database.go | 40 +++++------ internal/adapters/database_created_at_test.go | 6 +- internal/adapters/wgcontroller/local.go | 33 +++------ internal/adapters/wgcontroller/mikrotik.go | 30 +++----- internal/adapters/wgcontroller/opnsense.go | 28 ++++---- internal/adapters/wgcontroller/pfsense.go | 22 +++--- internal/adapters/wireguard.go | 34 +++------- .../app/api/core/middleware/cors/wildcard.go | 6 +- .../app/api/core/middleware/csrf/token.go | 4 +- .../core/middleware/recovery/middleware.go | 5 +- internal/app/api/v0/handlers/base.go | 2 +- .../app/api/v0/handlers/web_authentication.go | 7 +- internal/app/api/v0/model/models_interface.go | 10 ++- internal/app/api/v0/model/models_peer.go | 2 +- internal/app/api/v1/handlers/base.go | 2 +- .../app/api/v1/handlers/web_authentication.go | 9 +-- .../app/api/v1/models/models_interface.go | 10 ++- internal/app/app.go | 10 ++- internal/app/audit/recorder.go | 2 +- internal/app/auth/auth.go | 20 +++--- internal/app/auth/oauth_common.go | 26 +++---- .../app/auth/oauth_common_sanitize_test.go | 14 ++-- internal/app/auth/oauth_common_test.go | 50 ++++++-------- internal/app/migrate_v1.go | 68 ++++++++----------- internal/app/route/routes.go | 2 +- internal/app/users/ldap_helper.go | 10 ++- .../app/users/ldap_helper_sanitize_test.go | 14 ++-- internal/app/users/user_manager.go | 12 ++-- internal/app/webhooks/manager.go | 2 +- .../controller_manager_opnsense_test.go | 11 +-- internal/app/wireguard/statistics.go | 2 +- internal/app/wireguard/wireguard.go | 2 +- .../app/wireguard/wireguard_interfaces.go | 10 ++- .../wireguard/wireguard_interfaces_test.go | 2 +- internal/app/wireguard/wireguard_peers.go | 10 ++- .../app/wireguard/wireguard_peers_test.go | 4 +- internal/config/auth.go | 14 ++-- internal/config/backend_test.go | 16 ++--- internal/domain/interface.go | 11 ++- internal/domain/peer_test.go | 8 +-- 40 files changed, 229 insertions(+), 341 deletions(-) diff --git a/internal/adapters/database.go b/internal/adapters/database.go index de3cf507..2a368860 100644 --- a/internal/adapters/database.go +++ b/internal/adapters/database.go @@ -279,12 +279,10 @@ func (r *SqlRepo) migrate() error { now := time.Now() for _, user := range users { auth := domain.UserAuthentication{ - BaseModel: domain.BaseModel{ - CreatedBy: domain.CtxSystemDBMigrator, - UpdatedBy: domain.CtxSystemDBMigrator, - CreatedAt: now, - UpdatedAt: now, - }, + CreatedBy: domain.CtxSystemDBMigrator, + UpdatedBy: domain.CtxSystemDBMigrator, + CreatedAt: now, + UpdatedAt: now, UserIdentifier: user.Identifier, Source: user.Source, ProviderName: user.ProviderName, @@ -493,12 +491,10 @@ func (r *SqlRepo) getOrCreateInterface( // interfaceDefaults will be applied to newly created interface records interfaceDefaults := domain.Interface{ - BaseModel: domain.BaseModel{ - CreatedBy: ui.UserId(), - UpdatedBy: ui.UserId(), - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - }, + CreatedBy: ui.UserId(), + UpdatedBy: ui.UserId(), + CreatedAt: time.Now(), + UpdatedAt: time.Now(), Identifier: id, } @@ -702,12 +698,10 @@ func (r *SqlRepo) getOrCreatePeer(ui *domain.ContextUserInfo, tx *gorm.DB, id do // interfaceDefaults will be applied to newly created interface records interfaceDefaults := domain.Peer{ - BaseModel: domain.BaseModel{ - CreatedBy: ui.UserId(), - UpdatedBy: ui.UserId(), - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - }, + CreatedBy: ui.UserId(), + UpdatedBy: ui.UserId(), + CreatedAt: time.Now(), + UpdatedAt: time.Now(), Identifier: id, } @@ -995,12 +989,10 @@ func (r *SqlRepo) getOrCreateUser(ui *domain.ContextUserInfo, tx *gorm.DB, id do // create a new user record if no user record exists yet userDefaults := domain.User{ - BaseModel: domain.BaseModel{ - CreatedBy: ui.UserId(), - UpdatedBy: ui.UserId(), - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - }, + CreatedBy: ui.UserId(), + UpdatedBy: ui.UserId(), + CreatedAt: time.Now(), + UpdatedAt: time.Now(), Identifier: id, IsAdmin: false, } diff --git a/internal/adapters/database_created_at_test.go b/internal/adapters/database_created_at_test.go index 2a2761b2..1bcfb6c9 100644 --- a/internal/adapters/database_created_at_test.go +++ b/internal/adapters/database_created_at_test.go @@ -54,10 +54,8 @@ func TestUpsertUser_PreservesExistingCreatedAt(t *testing.T) { user := &domain.User{ Identifier: "test-user", Email: "test@example.com", - BaseModel: domain.BaseModel{ - CreatedAt: originalTime, - CreatedBy: "original-creator", - }, + CreatedAt: originalTime, + CreatedBy: "original-creator", } err := repo.upsertUser(ui, db, user) diff --git a/internal/adapters/wgcontroller/local.go b/internal/adapters/wgcontroller/local.go index 141917f3..38da58b7 100644 --- a/internal/adapters/wgcontroller/local.go +++ b/internal/adapters/wgcontroller/local.go @@ -127,11 +127,9 @@ func (c LocalController) convertWireGuardInterface(device *wgtypes.Device) (doma // read data from wgctrl interface iface := domain.PhysicalInterface{ - Identifier: domain.InterfaceIdentifier(device.Name), - KeyPair: domain.KeyPair{ - PrivateKey: device.PrivateKey.String(), - PublicKey: device.PublicKey.String(), - }, + Identifier: domain.InterfaceIdentifier(device.Name), + PrivateKey: device.PrivateKey.String(), + PublicKey: device.PublicKey.String(), ListenPort: device.ListenPort, Addresses: nil, Mtu: 0, @@ -190,12 +188,10 @@ func (c LocalController) GetPeers(_ context.Context, deviceId domain.InterfaceId func (c LocalController) convertWireGuardPeer(peer *wgtypes.Peer) (domain.PhysicalPeer, error) { peerModel := domain.PhysicalPeer{ - Identifier: domain.PeerIdentifier(peer.PublicKey.String()), - Endpoint: "", - AllowedIPs: nil, - KeyPair: domain.KeyPair{ - PublicKey: peer.PublicKey.String(), - }, + Identifier: domain.PeerIdentifier(peer.PublicKey.String()), + Endpoint: "", + AllowedIPs: nil, + PublicKey: peer.PublicKey.String(), PresharedKey: "", PersistentKeepalive: int(peer.PersistentKeepaliveInterval.Seconds()), LastHandshake: peer.LastHandshakeTime, @@ -280,9 +276,7 @@ func (c LocalController) getInterface(id domain.InterfaceIdentifier) (*domain.Ph func (c LocalController) createLowLevelInterface(id domain.InterfaceIdentifier) error { link := &netlink.GenericLink{ - LinkAttrs: netlink.LinkAttrs{ - Name: string(id), - }, + Name: string(id), LinkType: "wireguard", } err := c.nl.LinkAdd(link) @@ -318,13 +312,7 @@ func (c LocalController) updateLowLevelInterface(pi *domain.PhysicalInterface) e } for _, rawAddr := range rawAddresses { netlinkAddr := domain.CidrFromNetlinkAddr(rawAddr) - remove := true - for _, addr := range pi.Addresses { - if addr == netlinkAddr { - remove = false - break - } - } + remove := !slices.Contains(pi.Addresses, netlinkAddr) if !remove { continue @@ -385,8 +373,7 @@ func (c LocalController) DeleteInterface(_ context.Context, id domain.InterfaceI func (c LocalController) deleteLowLevelInterface(id domain.InterfaceIdentifier) error { link, err := c.nl.LinkByName(string(id)) if err != nil { - var linkNotFoundError netlink.LinkNotFoundError - if errors.As(err, &linkNotFoundError) { + if _, ok := errors.AsType[netlink.LinkNotFoundError](err); ok { return nil // ignore not found error } return fmt.Errorf("unable to find low level interface: %w", err) diff --git a/internal/adapters/wgcontroller/mikrotik.go b/internal/adapters/wgcontroller/mikrotik.go index 70d429c3..1914a93f 100644 --- a/internal/adapters/wgcontroller/mikrotik.go +++ b/internal/adapters/wgcontroller/mikrotik.go @@ -263,11 +263,9 @@ func (c *MikrotikController) convertWireGuardInterface( error, ) { pi := domain.PhysicalInterface{ - Identifier: domain.InterfaceIdentifier(wg.GetString("name")), - KeyPair: domain.KeyPair{ - PrivateKey: wg.GetString("private-key"), - PublicKey: wg.GetString("public-key"), - }, + Identifier: domain.InterfaceIdentifier(wg.GetString("name")), + PrivateKey: wg.GetString("private-key"), + PublicKey: wg.GetString("public-key"), ListenPort: wg.GetInt("listen-port"), Addresses: addresses, Mtu: wg.GetInt("mtu"), @@ -354,13 +352,11 @@ func (c *MikrotikController) convertWireGuardPeer(peer lowlevel.GenericJsonObjec } peerModel := domain.PhysicalPeer{ - Identifier: domain.PeerIdentifier(peer.GetString("public-key")), - Endpoint: currentEndpoint, - AllowedIPs: allowedAddresses, - KeyPair: domain.KeyPair{ - PublicKey: peer.GetString("public-key"), - PrivateKey: peer.GetString("private-key"), - }, + Identifier: domain.PeerIdentifier(peer.GetString("public-key")), + Endpoint: currentEndpoint, + AllowedIPs: allowedAddresses, + PublicKey: peer.GetString("public-key"), + PrivateKey: peer.GetString("private-key"), PresharedKey: domain.PreSharedKey(peer.GetString("preshared-key")), PersistentKeepalive: keepAliveSeconds, LastHandshake: lastHandshakeTime, @@ -792,7 +788,7 @@ func (c *MikrotikController) ExecuteInterfaceHook( } scriptName := fmt.Sprintf("wg-portal-hook-%s-%d", id, time.Now().UnixNano()) - + // Replace %i with the interface ID to mimic wg-quick behavior scriptSource := strings.ReplaceAll(hookCmd, "%i", string(id)) // Inject the interface ID as a local variable for convenience in RouterOS scripts @@ -1076,13 +1072,7 @@ func (c *MikrotikController) setRoutesForFamily( continue } - valid := false - for _, cidr := range cidrs { - if existingRoute.EqualPrefix(cidr) { - valid = true - break - } - } + valid := slices.ContainsFunc(cidrs, existingRoute.EqualPrefix) if valid { continue // route is still valid, nothing to do } diff --git a/internal/adapters/wgcontroller/opnsense.go b/internal/adapters/wgcontroller/opnsense.go index 84988c7b..712ea2c6 100644 --- a/internal/adapters/wgcontroller/opnsense.go +++ b/internal/adapters/wgcontroller/opnsense.go @@ -168,7 +168,7 @@ func parseCidrsTolerant(value, what, owner string) []domain.Cidr { } parsed := make([]domain.Cidr, 0, 1) - for _, part := range strings.Split(value, ",") { + for part := range strings.SplitSeq(value, ",") { part = strings.TrimSpace(part) if part == "" { continue @@ -424,11 +424,9 @@ func (c *OpnsenseController) convertServer( stats := interfaceStats[string(identifier)] physicalInterface := &domain.PhysicalInterface{ - Identifier: identifier, - KeyPair: domain.KeyPair{ - PrivateKey: row.GetString("privkey"), - PublicKey: row.GetString("pubkey"), - }, + Identifier: identifier, + PrivateKey: row.GetString("privkey"), + PublicKey: row.GetString("pubkey"), ListenPort: row.GetInt("port"), Addresses: addresses, Mtu: row.GetInt("mtu"), @@ -494,7 +492,7 @@ func clientBelongsToServer(row lowlevel.GenericJsonObject, serverUuid string) bo if serverUuid == "" { return false } - for _, uuid := range strings.Split(row.GetString("servers"), ",") { + for uuid := range strings.SplitSeq(row.GetString("servers"), ",") { if strings.TrimSpace(uuid) == serverUuid { return true } @@ -522,12 +520,10 @@ func (c *OpnsenseController) convertClient( Identifier: domain.PeerIdentifier(publicKey), Endpoint: endpoint, AllowedIPs: allowedIPs, - KeyPair: domain.KeyPair{ - PublicKey: publicKey, - // OPNsense stores only the public key for a peer; the private key - // stays with the client device. - PrivateKey: "", - }, + PublicKey: publicKey, + // OPNsense stores only the public key for a peer; the private key + // stays with the client device. + PrivateKey: "", PresharedKey: domain.PreSharedKey(row.GetString("psk")), PersistentKeepalive: row.GetInt("keepalive"), LastHandshake: stats.lastHandshake, @@ -726,7 +722,7 @@ func (c *OpnsenseController) SavePeer( } else { physicalPeer = &domain.PhysicalPeer{ Identifier: id, - KeyPair: domain.KeyPair{PublicKey: string(id)}, + PublicKey: string(id), ImportSource: domain.ControllerTypeOpnsense, } physicalPeer.SetExtras(domain.OpnsensePeerExtras{}) @@ -781,7 +777,7 @@ func (c *OpnsenseController) createOrUpdatePeer( // from them. servers := map[string]struct{}{serverUuid: {}} if existingRow != nil { - for _, uuid := range strings.Split(existingRow.GetString("servers"), ",") { + for uuid := range strings.SplitSeq(existingRow.GetString("servers"), ",") { if uuid = strings.TrimSpace(uuid); uuid != "" { servers[uuid] = struct{}{} } @@ -912,7 +908,7 @@ func (c *OpnsenseController) DeletePeer( remaining := make([]string, 0) if serverRow != nil { serverUuid := serverRow.GetString("uuid") - for _, attached := range strings.Split(row.GetString("servers"), ",") { + for attached := range strings.SplitSeq(row.GetString("servers"), ",") { if attached = strings.TrimSpace(attached); attached != "" && attached != serverUuid { remaining = append(remaining, attached) } diff --git a/internal/adapters/wgcontroller/pfsense.go b/internal/adapters/wgcontroller/pfsense.go index 872baefa..29d06bf6 100644 --- a/internal/adapters/wgcontroller/pfsense.go +++ b/internal/adapters/wgcontroller/pfsense.go @@ -340,11 +340,9 @@ func (c *PfsenseController) convertWireGuardInterface( var rxBytes, txBytes uint64 pi := domain.PhysicalInterface{ - Identifier: domain.InterfaceIdentifier(wg.GetString("name")), - KeyPair: domain.KeyPair{ - PrivateKey: privateKey, - PublicKey: publicKey, - }, + Identifier: domain.InterfaceIdentifier(wg.GetString("name")), + PrivateKey: privateKey, + PublicKey: publicKey, ListenPort: listenPort, Addresses: addresses, Mtu: mtu, @@ -559,13 +557,11 @@ func (c *PfsenseController) convertWireGuardPeer(peer lowlevel.GenericJsonObject txBytes := uint64(0) peerModel := domain.PhysicalPeer{ - Identifier: domain.PeerIdentifier(publicKey), - Endpoint: endpoint, - AllowedIPs: allowedAddresses, - KeyPair: domain.KeyPair{ - PublicKey: publicKey, - PrivateKey: privateKey, - }, + Identifier: domain.PeerIdentifier(publicKey), + Endpoint: endpoint, + AllowedIPs: allowedAddresses, + PublicKey: publicKey, + PrivateKey: privateKey, PresharedKey: domain.PreSharedKey(presharedKey), PersistentKeepalive: keepAliveSeconds, LastHandshake: lastHandshakeTime, @@ -794,7 +790,7 @@ func (c *PfsenseController) SavePeer( if physicalPeer == nil { physicalPeer = &domain.PhysicalPeer{ Identifier: id, - KeyPair: domain.KeyPair{PublicKey: string(id)}, + PublicKey: string(id), ImportSource: domain.ControllerTypePfsense, } physicalPeer.SetExtras(domain.PfsensePeerExtras{}) diff --git a/internal/adapters/wireguard.go b/internal/adapters/wireguard.go index 327d54a8..2467fd0b 100644 --- a/internal/adapters/wireguard.go +++ b/internal/adapters/wireguard.go @@ -6,6 +6,7 @@ import ( "fmt" "log/slog" "os" + "slices" "github.com/vishvananda/netlink" "golang.zx2c4.com/wireguard/wgctrl" @@ -106,11 +107,9 @@ func (r *WgRepo) convertWireGuardInterface(device *wgtypes.Device) (domain.Physi // read data from wgctrl interface iface := domain.PhysicalInterface{ - Identifier: domain.InterfaceIdentifier(device.Name), - KeyPair: domain.KeyPair{ - PrivateKey: device.PrivateKey.String(), - PublicKey: device.PublicKey.String(), - }, + Identifier: domain.InterfaceIdentifier(device.Name), + PrivateKey: device.PrivateKey.String(), + PublicKey: device.PublicKey.String(), ListenPort: device.ListenPort, Addresses: nil, Mtu: 0, @@ -148,12 +147,10 @@ func (r *WgRepo) convertWireGuardInterface(device *wgtypes.Device) (domain.Physi func (r *WgRepo) convertWireGuardPeer(peer *wgtypes.Peer) (domain.PhysicalPeer, error) { peerModel := domain.PhysicalPeer{ - Identifier: domain.PeerIdentifier(peer.PublicKey.String()), - Endpoint: "", - AllowedIPs: nil, - KeyPair: domain.KeyPair{ - PublicKey: peer.PublicKey.String(), - }, + Identifier: domain.PeerIdentifier(peer.PublicKey.String()), + Endpoint: "", + AllowedIPs: nil, + PublicKey: peer.PublicKey.String(), PresharedKey: "", PersistentKeepalive: int(peer.PersistentKeepaliveInterval.Seconds()), LastHandshake: peer.LastHandshakeTime, @@ -241,9 +238,7 @@ func (r *WgRepo) getInterface(id domain.InterfaceIdentifier) (*domain.PhysicalIn func (r *WgRepo) createLowLevelInterface(id domain.InterfaceIdentifier) error { link := &netlink.GenericLink{ - LinkAttrs: netlink.LinkAttrs{ - Name: string(id), - }, + Name: string(id), LinkType: "wireguard", } err := r.nl.LinkAdd(link) @@ -279,13 +274,7 @@ func (r *WgRepo) updateLowLevelInterface(pi *domain.PhysicalInterface) error { } for _, rawAddr := range rawAddresses { netlinkAddr := domain.CidrFromNetlinkAddr(rawAddr) - remove := true - for _, addr := range pi.Addresses { - if addr == netlinkAddr { - remove = false - break - } - } + remove := !slices.Contains(pi.Addresses, netlinkAddr) if !remove { continue @@ -351,8 +340,7 @@ func (r *WgRepo) DeleteInterface(_ context.Context, id domain.InterfaceIdentifie func (r *WgRepo) deleteLowLevelInterface(id domain.InterfaceIdentifier) error { link, err := r.nl.LinkByName(string(id)) if err != nil { - var linkNotFoundError netlink.LinkNotFoundError - if errors.As(err, &linkNotFoundError) { + if _, ok := errors.AsType[netlink.LinkNotFoundError](err); ok { return nil // ignore not found error } return fmt.Errorf("unable to find low level interface: %w", err) diff --git a/internal/app/api/core/middleware/cors/wildcard.go b/internal/app/api/core/middleware/cors/wildcard.go index 01d352d4..104c186f 100644 --- a/internal/app/api/core/middleware/cors/wildcard.go +++ b/internal/app/api/core/middleware/cors/wildcard.go @@ -18,10 +18,10 @@ func (w wildcard) match(s string) bool { } func newWildcard(s string) wildcard { - if i := strings.IndexByte(s, '*'); i >= 0 { + if before, after, ok := strings.Cut(s, "*"); ok { return wildcard{ - prefix: s[:i], - suffix: s[i+1:], + prefix: before, + suffix: after, } } diff --git a/internal/app/api/core/middleware/csrf/token.go b/internal/app/api/core/middleware/csrf/token.go index fa47deec..713467c1 100644 --- a/internal/app/api/core/middleware/csrf/token.go +++ b/internal/app/api/core/middleware/csrf/token.go @@ -52,7 +52,7 @@ func maskToken(token, key []byte) []byte { // masked contains the key in the first half and the XOR masked token in the second half tokenLength := len(token) masked := make([]byte, tokenLength*2) - for i := 0; i < len(token); i++ { + for i := range token { masked[i] = key[i] masked[i+tokenLength] = token[i] ^ key[i] // XOR mask } @@ -65,7 +65,7 @@ func maskToken(token, key []byte) []byte { func unmaskToken(masked []byte) []byte { tokenLength := len(masked) / 2 token := make([]byte, tokenLength) - for i := 0; i < tokenLength; i++ { + for i := range tokenLength { token[i] = masked[i] ^ masked[i+tokenLength] // XOR unmask } diff --git a/internal/app/api/core/middleware/recovery/middleware.go b/internal/app/api/core/middleware/recovery/middleware.go index f4b6c466..ab54fda9 100644 --- a/internal/app/api/core/middleware/recovery/middleware.go +++ b/internal/app/api/core/middleware/recovery/middleware.go @@ -85,7 +85,7 @@ func addPrefix(o options, message string) string { // enabled, the stack trace is included in the response. func getDefaultErrCallback(o options) func(err error, stack []byte, w http.ResponseWriter, r *http.Request) { return func(err error, stack []byte, w http.ResponseWriter, r *http.Request) { - responseBody := map[string]interface{}{ + responseBody := map[string]any{ "error": "Internal Server Error", } if o.exposeStackTrace && len(stack) > 0 { @@ -120,8 +120,7 @@ func getDefaultLogCallback(o options) func(error, []byte, bool) { } func isBrokenPipeError(err error) bool { - var syscallErr *os.SyscallError - if errors.As(err, &syscallErr) { + if syscallErr, ok := errors.AsType[*os.SyscallError](err); ok { errMsg := strings.ToLower(syscallErr.Err.Error()) if strings.Contains(errMsg, "broken pipe") || strings.Contains(errMsg, "connection reset by peer") { diff --git a/internal/app/api/v0/handlers/base.go b/internal/app/api/v0/handlers/base.go index bee1d051..9df68cfe 100644 --- a/internal/app/api/v0/handlers/base.go +++ b/internal/app/api/v0/handlers/base.go @@ -114,7 +114,7 @@ type Session interface { type Validator interface { // Struct validates the given struct. - Struct(s interface{}) error + Struct(s any) error } // endregion handler-interfaces diff --git a/internal/app/api/v0/handlers/web_authentication.go b/internal/app/api/v0/handlers/web_authentication.go index f847cb87..71ebcedc 100644 --- a/internal/app/api/v0/handlers/web_authentication.go +++ b/internal/app/api/v0/handlers/web_authentication.go @@ -3,6 +3,7 @@ package handlers import ( "context" "net/http" + "slices" "github.com/h44z/wg-portal/internal/app/api/core/request" "github.com/h44z/wg-portal/internal/app/api/core/respond" @@ -137,10 +138,8 @@ func UserHasScopes(session SessionData, scopes ...Scope) bool { } // Check if admin scope is required - for _, scope := range scopes { - if scope == ScopeAdmin { - return false - } + if slices.Contains(scopes, ScopeAdmin) { + return false } // For all other scopes, a logged-in user is sufficient (for now) diff --git a/internal/app/api/v0/model/models_interface.go b/internal/app/api/v0/model/models_interface.go index 9994e655..05462391 100644 --- a/internal/app/api/v0/model/models_interface.go +++ b/internal/app/api/v0/model/models_interface.go @@ -137,12 +137,10 @@ func NewDomainInterface(src *Interface) *domain.Interface { cidrs, _ := domain.CidrsFromArray(src.Addresses) res := &domain.Interface{ - BaseModel: domain.BaseModel{}, - Identifier: domain.InterfaceIdentifier(src.Identifier), - KeyPair: domain.KeyPair{ - PrivateKey: src.PrivateKey, - PublicKey: src.PublicKey, - }, + BaseModel: domain.BaseModel{}, + Identifier: domain.InterfaceIdentifier(src.Identifier), + PrivateKey: src.PrivateKey, + PublicKey: src.PublicKey, ListenPort: src.ListenPort, Addresses: cidrs, DnsStr: internal.SliceToString(src.Dns), diff --git a/internal/app/api/v0/model/models_peer.go b/internal/app/api/v0/model/models_peer.go index 998a5ada..4b574cf4 100644 --- a/internal/app/api/v0/model/models_peer.go +++ b/internal/app/api/v0/model/models_peer.go @@ -47,7 +47,7 @@ type Peer struct { InterfaceIdentifier string `json:"InterfaceIdentifier"` // the interface id Disabled bool `json:"Disabled"` // flag that specifies if the peer is enabled (up) or not (down) DisabledReason string `json:"DisabledReason"` // the reason why the peer has been disabled - ExpiresAt ExpiryDate `json:"ExpiresAt,omitempty"` // expiry dates for peers + ExpiresAt ExpiryDate `json:"ExpiresAt"` // expiry dates for peers Notes string `json:"Notes"` // a note field for peers IsDynamic bool `json:"IsDynamic"` // specifies if the peer is dynamically created by mikrotik diff --git a/internal/app/api/v1/handlers/base.go b/internal/app/api/v1/handlers/base.go index 760e4b5f..352cc8e2 100644 --- a/internal/app/api/v1/handlers/base.go +++ b/internal/app/api/v1/handlers/base.go @@ -88,7 +88,7 @@ type Authenticator interface { type Validator interface { // Struct validates the given struct. - Struct(s interface{}) error + Struct(s any) error } // endregion handler-interfaces diff --git a/internal/app/api/v1/handlers/web_authentication.go b/internal/app/api/v1/handlers/web_authentication.go index 9365eab2..06a8fac6 100644 --- a/internal/app/api/v1/handlers/web_authentication.go +++ b/internal/app/api/v1/handlers/web_authentication.go @@ -3,6 +3,7 @@ package handlers import ( "context" "net/http" + "slices" "github.com/h44z/wg-portal/internal/app/api/core/respond" "github.com/h44z/wg-portal/internal/app/api/v0/model" @@ -104,11 +105,5 @@ func UserHasScopes(user *domain.User, scopes ...Scope) bool { } // Check if admin scope is required - for _, scope := range scopes { - if scope == ScopeAdmin { - return false - } - } - - return true + return !slices.Contains(scopes, ScopeAdmin) } diff --git a/internal/app/api/v1/models/models_interface.go b/internal/app/api/v1/models/models_interface.go index ed14c2c4..4bd94ca7 100644 --- a/internal/app/api/v1/models/models_interface.go +++ b/internal/app/api/v1/models/models_interface.go @@ -159,12 +159,10 @@ func NewDomainInterface(src *Interface) *domain.Interface { cidrs, _ := domain.CidrsFromArray(src.Addresses) res := &domain.Interface{ - BaseModel: domain.BaseModel{}, - Identifier: domain.InterfaceIdentifier(src.Identifier), - KeyPair: domain.KeyPair{ - PrivateKey: src.PrivateKey, - PublicKey: src.PublicKey, - }, + BaseModel: domain.BaseModel{}, + Identifier: domain.InterfaceIdentifier(src.Identifier), + PrivateKey: src.PrivateKey, + PublicKey: src.PublicKey, ListenPort: src.ListenPort, Addresses: cidrs, DnsStr: internal.SliceToString(src.Dns), diff --git a/internal/app/app.go b/internal/app/app.go index 5f6a9655..8d1a16e9 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -122,12 +122,10 @@ func (a *App) createDefaultUser(ctx context.Context) error { now := time.Now() defaultAdmin := &domain.User{ - BaseModel: domain.BaseModel{ - CreatedBy: domain.CtxSystemAdminId, - UpdatedBy: domain.CtxSystemAdminId, - CreatedAt: now, - UpdatedAt: now, - }, + CreatedBy: domain.CtxSystemAdminId, + UpdatedBy: domain.CtxSystemAdminId, + CreatedAt: now, + UpdatedAt: now, Identifier: adminUserId, Email: "admin@wgportal.local", IsAdmin: true, diff --git a/internal/app/audit/recorder.go b/internal/app/audit/recorder.go index e9c5a255..abe6b205 100644 --- a/internal/app/audit/recorder.go +++ b/internal/app/audit/recorder.go @@ -20,7 +20,7 @@ type DatabaseRepo interface { type EventBus interface { // Subscribe subscribes to a topic - Subscribe(topic string, fn interface{}) error + Subscribe(topic string, fn any) error } // endregion dependencies diff --git a/internal/app/auth/auth.go b/internal/app/auth/auth.go index 1f4f9db2..37657a05 100644 --- a/internal/app/auth/auth.go +++ b/internal/app/auth/auth.go @@ -673,12 +673,10 @@ func (a *Authenticator) registerNewUser( Department: userInfo.Department, Authentications: []domain.UserAuthentication{ { - BaseModel: domain.BaseModel{ - CreatedBy: ctxUserInfo.UserId(), - UpdatedBy: ctxUserInfo.UserId(), - CreatedAt: now, - UpdatedAt: now, - }, + CreatedBy: ctxUserInfo.UserId(), + UpdatedBy: ctxUserInfo.UserId(), + CreatedAt: now, + UpdatedAt: now, UserIdentifier: userInfo.Identifier, Source: source, ProviderName: provider, @@ -742,12 +740,10 @@ func (a *Authenticator) updateExternalUser( ctxUserInfo := domain.GetUserInfo(ctx) now := time.Now() existingUser.Authentications = append(existingUser.Authentications, domain.UserAuthentication{ - BaseModel: domain.BaseModel{ - CreatedBy: ctxUserInfo.UserId(), - UpdatedBy: ctxUserInfo.UserId(), - CreatedAt: now, - UpdatedAt: now, - }, + CreatedBy: ctxUserInfo.UserId(), + UpdatedBy: ctxUserInfo.UserId(), + CreatedAt: now, + UpdatedAt: now, UserIdentifier: existingUser.Identifier, Source: source, ProviderName: provider, diff --git a/internal/app/auth/oauth_common.go b/internal/app/auth/oauth_common.go index 586be156..3c1c4c2f 100644 --- a/internal/app/auth/oauth_common.go +++ b/internal/app/auth/oauth_common.go @@ -1,6 +1,7 @@ package auth import ( + "slices" "strings" "github.com/h44z/wg-portal/internal" @@ -49,11 +50,8 @@ func parseOauthUserInfo( if !isAdmin && mapping.UserGroups != "" && adminMapping.AdminGroupRegex != "" { adminInfoAvailable = true re := adminMapping.GetAdminGroupRegex() - for _, group := range userInfo.UserGroups { - if re.MatchString(group) { - isAdmin = true - break - } + if slices.ContainsFunc(userInfo.UserGroups, re.MatchString) { + isAdmin = true } userInfo.IsAdmin = isAdmin userInfo.AdminInfoAvailable = adminInfoAvailable @@ -65,16 +63,14 @@ func parseOauthUserInfo( // getOauthFieldMapping returns the default field mapping for the oauth provider func getOauthFieldMapping(f config.OauthFields) config.OauthFields { defaultMap := config.OauthFields{ - BaseFields: config.BaseFields{ - UserIdentifier: "sub", - Email: "email", - Firstname: "given_name", - Lastname: "family_name", - Phone: "phone", - Department: "department", - }, - IsAdmin: "admin_flag", - UserGroups: "", // by default, do not use user groups + UserIdentifier: "sub", + Email: "email", + Firstname: "given_name", + Lastname: "family_name", + Phone: "phone", + Department: "department", + IsAdmin: "admin_flag", + UserGroups: "", // by default, do not use user groups } if f.UserIdentifier != "" { defaultMap.UserIdentifier = f.UserIdentifier diff --git a/internal/app/auth/oauth_common_sanitize_test.go b/internal/app/auth/oauth_common_sanitize_test.go index bb7a48ba..f538a572 100644 --- a/internal/app/auth/oauth_common_sanitize_test.go +++ b/internal/app/auth/oauth_common_sanitize_test.go @@ -16,14 +16,12 @@ import ( // makeOauthFieldMapping returns a minimal OauthFields mapping for testing. func makeOauthFieldMapping() config.OauthFields { return config.OauthFields{ - BaseFields: config.BaseFields{ - UserIdentifier: "sub", - Email: "email", - Firstname: "given_name", - Lastname: "family_name", - Phone: "phone", - Department: "department", - }, + UserIdentifier: "sub", + Email: "email", + Firstname: "given_name", + Lastname: "family_name", + Phone: "phone", + Department: "department", } } diff --git a/internal/app/auth/oauth_common_test.go b/internal/app/auth/oauth_common_test.go index d3992e32..bc210c8d 100644 --- a/internal/app/auth/oauth_common_test.go +++ b/internal/app/auth/oauth_common_test.go @@ -32,14 +32,12 @@ func Test_parseOauthUserInfo_no_admin(t *testing.T) { require.NoError(t, err) fieldMapping := getOauthFieldMapping(config.OauthFields{ - BaseFields: config.BaseFields{ - UserIdentifier: "email", - Email: "email", - Firstname: "name", - Lastname: "family_name", - }, - IsAdmin: "is_admin", - UserGroups: "groups", + UserIdentifier: "email", + Email: "email", + Firstname: "name", + Lastname: "family_name", + IsAdmin: "is_admin", + UserGroups: "groups", }) adminMapping := &config.OauthAdminMapping{} @@ -78,13 +76,11 @@ func Test_parseOauthUserInfo_admin_group(t *testing.T) { require.NoError(t, err) fieldMapping := getOauthFieldMapping(config.OauthFields{ - BaseFields: config.BaseFields{ - UserIdentifier: "email", - Email: "email", - Firstname: "name", - Lastname: "family_name", - }, - UserGroups: "groups", + UserIdentifier: "email", + Email: "email", + Firstname: "name", + Lastname: "family_name", + UserGroups: "groups", }) adminMapping := &config.OauthAdminMapping{ AdminGroupRegex: "^wgportal-admins@mydomain.net$", @@ -122,13 +118,11 @@ func Test_parseOauthUserInfo_admin_value(t *testing.T) { require.NoError(t, err) fieldMapping := getOauthFieldMapping(config.OauthFields{ - BaseFields: config.BaseFields{ - UserIdentifier: "email", - Email: "email", - Firstname: "name", - Lastname: "family_name", - }, - IsAdmin: "is_admin", + UserIdentifier: "email", + Email: "email", + Firstname: "name", + Lastname: "family_name", + IsAdmin: "is_admin", }) adminMapping := &config.OauthAdminMapping{} // test with default regex @@ -163,13 +157,11 @@ func Test_parseOauthUserInfo_admin_value_custom(t *testing.T) { require.NoError(t, err) fieldMapping := getOauthFieldMapping(config.OauthFields{ - BaseFields: config.BaseFields{ - UserIdentifier: "email", - Email: "email", - Firstname: "name", - Lastname: "family_name", - }, - IsAdmin: "is_admin", + UserIdentifier: "email", + Email: "email", + Firstname: "name", + Lastname: "family_name", + IsAdmin: "is_admin", }) adminMapping := &config.OauthAdminMapping{ AdminValueRegex: "^1$", diff --git a/internal/app/migrate_v1.go b/internal/app/migrate_v1.go index e7f2bad8..37a57ff8 100644 --- a/internal/app/migrate_v1.go +++ b/internal/app/migrate_v1.go @@ -136,12 +136,10 @@ func migrateV1Users(oldDb, newDb *gorm.DB) error { deletionReason = "disabled prior to migration" } newUser := domain.User{ - BaseModel: domain.BaseModel{ - CreatedBy: domain.CtxSystemV1Migrator, - UpdatedBy: domain.CtxSystemV1Migrator, - CreatedAt: oldUser.CreatedAt, - UpdatedAt: oldUser.UpdatedAt, - }, + CreatedBy: domain.CtxSystemV1Migrator, + UpdatedBy: domain.CtxSystemV1Migrator, + CreatedAt: oldUser.CreatedAt, + UpdatedAt: oldUser.UpdatedAt, Identifier: domain.UserIdentifier(oldUser.Email), Email: oldUser.Email, IsAdmin: oldUser.IsAdmin, @@ -162,12 +160,10 @@ func migrateV1Users(oldDb, newDb *gorm.DB) error { } authentication := domain.UserAuthentication{ - BaseModel: domain.BaseModel{ - CreatedBy: domain.CtxSystemV1Migrator, - UpdatedBy: domain.CtxSystemV1Migrator, - CreatedAt: oldUser.CreatedAt, - UpdatedAt: oldUser.UpdatedAt, - }, + CreatedBy: domain.CtxSystemV1Migrator, + UpdatedBy: domain.CtxSystemV1Migrator, + CreatedAt: oldUser.CreatedAt, + UpdatedAt: oldUser.UpdatedAt, UserIdentifier: domain.UserIdentifier(oldUser.Email), Source: domain.UserSource(oldUser.Source), ProviderName: "", // unknown @@ -223,17 +219,13 @@ func migrateV1Interfaces(oldDb, newDb *gorm.DB) error { networks[i] = domain.CidrFromIpNet(*ip.IpNet()) } newInterface := domain.Interface{ - BaseModel: domain.BaseModel{ - CreatedBy: domain.CtxSystemV1Migrator, - UpdatedBy: domain.CtxSystemV1Migrator, - CreatedAt: oldDevice.CreatedAt, - UpdatedAt: oldDevice.UpdatedAt, - }, - Identifier: domain.InterfaceIdentifier(oldDevice.DeviceName), - KeyPair: domain.KeyPair{ - PrivateKey: oldDevice.PrivateKey, - PublicKey: oldDevice.PublicKey, - }, + CreatedBy: domain.CtxSystemV1Migrator, + UpdatedBy: domain.CtxSystemV1Migrator, + CreatedAt: oldDevice.CreatedAt, + UpdatedAt: oldDevice.UpdatedAt, + Identifier: domain.InterfaceIdentifier(oldDevice.DeviceName), + PrivateKey: oldDevice.PrivateKey, + PublicKey: oldDevice.PublicKey, ListenPort: oldDevice.ListenPort, Addresses: ips, DnsStr: "", @@ -350,12 +342,10 @@ func migrateV1Peers(oldDb, newDb *gorm.DB) error { // create dummy user now := time.Now() user = domain.User{ - BaseModel: domain.BaseModel{ - CreatedBy: domain.CtxSystemV1Migrator, - UpdatedBy: domain.CtxSystemV1Migrator, - CreatedAt: now, - UpdatedAt: now, - }, + CreatedBy: domain.CtxSystemV1Migrator, + UpdatedBy: domain.CtxSystemV1Migrator, + CreatedAt: now, + UpdatedAt: now, Identifier: domain.UserIdentifier(oldPeer.Email), Email: oldPeer.Email, IsAdmin: false, @@ -369,12 +359,10 @@ func migrateV1Peers(oldDb, newDb *gorm.DB) error { } authentication := domain.UserAuthentication{ - BaseModel: domain.BaseModel{ - CreatedBy: domain.CtxSystemV1Migrator, - UpdatedBy: domain.CtxSystemV1Migrator, - CreatedAt: now, - UpdatedAt: now, - }, + CreatedBy: domain.CtxSystemV1Migrator, + UpdatedBy: domain.CtxSystemV1Migrator, + CreatedAt: now, + UpdatedAt: now, UserIdentifier: domain.UserIdentifier(oldPeer.Email), Source: domain.UserSourceDatabase, ProviderName: "", // unknown @@ -386,12 +374,10 @@ func migrateV1Peers(oldDb, newDb *gorm.DB) error { slog.Debug("dummy user migrated successfully", "identifier", user.Identifier) } newPeer := domain.Peer{ - BaseModel: domain.BaseModel{ - CreatedBy: domain.CtxSystemV1Migrator, - UpdatedBy: domain.CtxSystemV1Migrator, - CreatedAt: oldPeer.CreatedAt, - UpdatedAt: oldPeer.UpdatedAt, - }, + CreatedBy: domain.CtxSystemV1Migrator, + UpdatedBy: domain.CtxSystemV1Migrator, + CreatedAt: oldPeer.CreatedAt, + UpdatedAt: oldPeer.UpdatedAt, Endpoint: domain.NewConfigOption(oldPeer.Endpoint, !oldPeer.IgnoreGlobalSettings), EndpointPublicKey: domain.NewConfigOption(iface.PublicKey, !oldPeer.IgnoreGlobalSettings), AllowedIPsStr: domain.NewConfigOption(oldPeer.AllowedIPsStr, !oldPeer.IgnoreGlobalSettings), diff --git a/internal/app/route/routes.go b/internal/app/route/routes.go index 62cd67e7..b2a60c1e 100644 --- a/internal/app/route/routes.go +++ b/internal/app/route/routes.go @@ -25,7 +25,7 @@ type InterfaceAndPeerDatabaseRepo interface { type EventBus interface { // Subscribe subscribes to a topic - Subscribe(topic string, fn interface{}) error + Subscribe(topic string, fn any) error } type RoutesController interface { diff --git a/internal/app/users/ldap_helper.go b/internal/app/users/ldap_helper.go index 51430cbe..28a7587a 100644 --- a/internal/app/users/ldap_helper.go +++ b/internal/app/users/ldap_helper.go @@ -29,12 +29,10 @@ func convertRawLdapUser( uid := domain.UserIdentifier(internal.MapDefaultString(rawUser, fields.UserIdentifier, "")) user := &domain.User{ - BaseModel: domain.BaseModel{ - CreatedBy: domain.CtxSystemLdapSyncer, - UpdatedBy: domain.CtxSystemLdapSyncer, - CreatedAt: now, - UpdatedAt: now, - }, + CreatedBy: domain.CtxSystemLdapSyncer, + UpdatedBy: domain.CtxSystemLdapSyncer, + CreatedAt: now, + UpdatedAt: now, Identifier: uid, Email: strings.ToLower(internal.MapDefaultString(rawUser, fields.Email, "")), IsAdmin: isAdmin, diff --git a/internal/app/users/ldap_helper_sanitize_test.go b/internal/app/users/ldap_helper_sanitize_test.go index 8333992f..25203fbc 100644 --- a/internal/app/users/ldap_helper_sanitize_test.go +++ b/internal/app/users/ldap_helper_sanitize_test.go @@ -16,14 +16,12 @@ import ( // makeTestLdapFields returns a minimal LdapFields config for testing. func makeTestLdapFields() *config.LdapFields { return &config.LdapFields{ - BaseFields: config.BaseFields{ - UserIdentifier: "uid", - Email: "mail", - Firstname: "givenName", - Lastname: "sn", - Phone: "telephoneNumber", - Department: "department", - }, + UserIdentifier: "uid", + Email: "mail", + Firstname: "givenName", + Lastname: "sn", + Phone: "telephoneNumber", + Department: "department", GroupMembership: "memberOf", } } diff --git a/internal/app/users/user_manager.go b/internal/app/users/user_manager.go index 77437657..73723a1f 100644 --- a/internal/app/users/user_manager.go +++ b/internal/app/users/user_manager.go @@ -156,7 +156,7 @@ func (m Manager) GetAllUsers(ctx context.Context) ([]domain.User, error) { wg := sync.WaitGroup{} workers := int(math.Min(float64(len(users)), 10)) wg.Add(workers) - for i := 0; i < workers; i++ { + for range workers { go func() { defer wg.Done() for user := range ch { @@ -500,12 +500,10 @@ func (m Manager) create(ctx context.Context, user *domain.User) (*domain.User, e now := time.Now() user.Authentications = []domain.UserAuthentication{ { - BaseModel: domain.BaseModel{ - CreatedBy: ctxUserInfo.UserId(), - UpdatedBy: ctxUserInfo.UserId(), - CreatedAt: now, - UpdatedAt: now, - }, + CreatedBy: ctxUserInfo.UserId(), + UpdatedBy: ctxUserInfo.UserId(), + CreatedAt: now, + UpdatedAt: now, UserIdentifier: user.Identifier, Source: domain.UserSourceDatabase, ProviderName: "", diff --git a/internal/app/webhooks/manager.go b/internal/app/webhooks/manager.go index b8d010cf..4897ed12 100644 --- a/internal/app/webhooks/manager.go +++ b/internal/app/webhooks/manager.go @@ -19,7 +19,7 @@ type EventBus interface { // Publish sends a message to the message bus. Publish(topic string, args ...any) // Subscribe subscribes to a topic - Subscribe(topic string, fn interface{}) error + Subscribe(topic string, fn any) error } // endregion dependencies diff --git a/internal/app/wireguard/controller_manager_opnsense_test.go b/internal/app/wireguard/controller_manager_opnsense_test.go index 9a3d401b..78dcd568 100644 --- a/internal/app/wireguard/controller_manager_opnsense_test.go +++ b/internal/app/wireguard/controller_manager_opnsense_test.go @@ -23,7 +23,8 @@ func TestRegisterOpnsenseControllers(t *testing.T) { cfg := &config.Config{} cfg.Backend.Opnsense = []config.BackendOpnsense{ { - BackendBase: config.BackendBase{Id: "opn1", DisplayName: "Edge firewall"}, + Id: "opn1", + DisplayName: "Edge firewall", ApiUrl: "https://127.0.0.1", ApiKey: "key", ApiSecret: "secret", @@ -51,10 +52,10 @@ func TestRegisterOpnsenseControllersSkipsReservedId(t *testing.T) { cfg := &config.Config{} cfg.Backend.Opnsense = []config.BackendOpnsense{ { - BackendBase: config.BackendBase{Id: config.LocalBackendName}, - ApiUrl: "https://127.0.0.1", - ApiKey: "key", - ApiSecret: "secret", + Id: config.LocalBackendName, + ApiUrl: "https://127.0.0.1", + ApiKey: "key", + ApiSecret: "secret", }, } diff --git a/internal/app/wireguard/statistics.go b/internal/app/wireguard/statistics.go index e6f6d695..f16db52f 100644 --- a/internal/app/wireguard/statistics.go +++ b/internal/app/wireguard/statistics.go @@ -36,7 +36,7 @@ type StatisticsMetricsServer interface { type StatisticsEventBus interface { // Subscribe subscribes to a topic - Subscribe(topic string, fn interface{}) error + Subscribe(topic string, fn any) error // Publish sends a message to the message bus. Publish(topic string, args ...any) } diff --git a/internal/app/wireguard/wireguard.go b/internal/app/wireguard/wireguard.go index a2a135ef..b0b6f54f 100644 --- a/internal/app/wireguard/wireguard.go +++ b/internal/app/wireguard/wireguard.go @@ -49,7 +49,7 @@ type EventBus interface { // Publish sends a message to the message bus. Publish(topic string, args ...any) // Subscribe subscribes to a topic - Subscribe(topic string, fn interface{}) error + Subscribe(topic string, fn any) error } // endregion dependencies diff --git a/internal/app/wireguard/wireguard_interfaces.go b/internal/app/wireguard/wireguard_interfaces.go index 9dc8a286..35e6bd91 100644 --- a/internal/app/wireguard/wireguard_interfaces.go +++ b/internal/app/wireguard/wireguard_interfaces.go @@ -375,12 +375,10 @@ func (m Manager) PrepareInterface(ctx context.Context) (*domain.Interface, error } freshInterface := &domain.Interface{ - BaseModel: domain.BaseModel{ - CreatedBy: string(currentUser.Id), - UpdatedBy: string(currentUser.Id), - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - }, + CreatedBy: string(currentUser.Id), + UpdatedBy: string(currentUser.Id), + CreatedAt: time.Now(), + UpdatedAt: time.Now(), Identifier: id, KeyPair: kp, ListenPort: port, diff --git a/internal/app/wireguard/wireguard_interfaces_test.go b/internal/app/wireguard/wireguard_interfaces_test.go index 37095565..319bda53 100644 --- a/internal/app/wireguard/wireguard_interfaces_test.go +++ b/internal/app/wireguard/wireguard_interfaces_test.go @@ -114,7 +114,7 @@ func TestImportPeer_AddressMapping(t *testing.T) { p := &domain.PhysicalPeer{ Identifier: "peer1", - KeyPair: domain.KeyPair{PublicKey: "peer1-public-key-is-long-enough"}, + PublicKey: "peer1-public-key-is-long-enough", AllowedIPs: allowedIPs, } diff --git a/internal/app/wireguard/wireguard_peers.go b/internal/app/wireguard/wireguard_peers.go index 7e07a452..809397e9 100644 --- a/internal/app/wireguard/wireguard_peers.go +++ b/internal/app/wireguard/wireguard_peers.go @@ -166,12 +166,10 @@ func (m Manager) PreparePeer(ctx context.Context, id domain.InterfaceIdentifier) peerId := domain.PeerIdentifier(kp.PublicKey) freshPeer := &domain.Peer{ - BaseModel: domain.BaseModel{ - CreatedBy: string(currentUser.Id), - UpdatedBy: string(currentUser.Id), - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - }, + CreatedBy: string(currentUser.Id), + UpdatedBy: string(currentUser.Id), + CreatedAt: time.Now(), + UpdatedAt: time.Now(), Endpoint: domain.NewConfigOption(iface.PeerDefEndpoint, true), EndpointPublicKey: domain.NewConfigOption(iface.PublicKey, true), AllowedIPsStr: domain.NewConfigOption(iface.PeerDefAllowedIPsStr, true), diff --git a/internal/app/wireguard/wireguard_peers_test.go b/internal/app/wireguard/wireguard_peers_test.go index 19dd1b21..5f865788 100644 --- a/internal/app/wireguard/wireguard_peers_test.go +++ b/internal/app/wireguard/wireguard_peers_test.go @@ -12,8 +12,8 @@ import ( type mockBus struct{} -func (f *mockBus) Publish(topic string, args ...any) {} -func (f *mockBus) Subscribe(topic string, fn interface{}) error { return nil } +func (f *mockBus) Publish(topic string, args ...any) {} +func (f *mockBus) Subscribe(topic string, fn any) error { return nil } type mockController struct{} diff --git a/internal/config/auth.go b/internal/config/auth.go index fef44223..a8369b55 100644 --- a/internal/config/auth.go +++ b/internal/config/auth.go @@ -130,14 +130,12 @@ type LdapFields struct { // If specific fields are not set, the default values are used. func (f LdapFields) getMappingWithDefaults() LdapFields { defaultMap := LdapFields{ - BaseFields: BaseFields{ - UserIdentifier: "mail", - Email: "mail", - Firstname: "givenName", - Lastname: "sn", - Phone: "telephoneNumber", - Department: "department", - }, + UserIdentifier: "mail", + Email: "mail", + Firstname: "givenName", + Lastname: "sn", + Phone: "telephoneNumber", + Department: "department", GroupMembership: "memberOf", } if f.UserIdentifier != "" { diff --git a/internal/config/backend_test.go b/internal/config/backend_test.go index 733879db..58d73ebf 100644 --- a/internal/config/backend_test.go +++ b/internal/config/backend_test.go @@ -16,9 +16,9 @@ func TestBackendValidate_DefaultsToLocal(t *testing.T) { func TestBackendValidate_RejectsReservedId(t *testing.T) { tests := map[string]Backend{ - "mikrotik": {Mikrotik: []BackendMikrotik{{BackendBase: BackendBase{Id: LocalBackendName}}}}, - "pfsense": {Pfsense: []BackendPfsense{{BackendBase: BackendBase{Id: LocalBackendName}}}}, - "opnsense": {Opnsense: []BackendOpnsense{{BackendBase: BackendBase{Id: LocalBackendName}}}}, + "mikrotik": {Mikrotik: []BackendMikrotik{{Id: LocalBackendName}}}, + "pfsense": {Pfsense: []BackendPfsense{{Id: LocalBackendName}}}, + "opnsense": {Opnsense: []BackendOpnsense{{Id: LocalBackendName}}}, } for name, backend := range tests { @@ -35,8 +35,8 @@ func TestBackendValidate_RejectsReservedId(t *testing.T) { // controller map would silently keep only one of them. func TestBackendValidate_RejectsDuplicateIdAcrossTypes(t *testing.T) { backend := Backend{ - Pfsense: []BackendPfsense{{BackendBase: BackendBase{Id: "fw1"}}}, - Opnsense: []BackendOpnsense{{BackendBase: BackendBase{Id: "fw1"}}}, + Pfsense: []BackendPfsense{{Id: "fw1"}}, + Opnsense: []BackendOpnsense{{Id: "fw1"}}, } err := backend.Validate() @@ -47,7 +47,7 @@ func TestBackendValidate_RejectsDuplicateIdAcrossTypes(t *testing.T) { func TestBackendValidate_RejectsUnknownDefault(t *testing.T) { backend := Backend{ Default: "does-not-exist", - Opnsense: []BackendOpnsense{{BackendBase: BackendBase{Id: "fw1"}}}, + Opnsense: []BackendOpnsense{{Id: "fw1"}}, } err := backend.Validate() @@ -58,7 +58,7 @@ func TestBackendValidate_RejectsUnknownDefault(t *testing.T) { func TestBackendValidate_AcceptsOpnsenseAsDefault(t *testing.T) { backend := Backend{ Default: "fw1", - Opnsense: []BackendOpnsense{{BackendBase: BackendBase{Id: "fw1"}}}, + Opnsense: []BackendOpnsense{{Id: "fw1"}}, } assert.NoError(t, backend.Validate()) @@ -77,7 +77,7 @@ func TestBackendOpnsenseDefaults(t *testing.T) { } func TestBackendOpnsenseDisplayName(t *testing.T) { - backend := BackendOpnsense{BackendBase: BackendBase{Id: "fw1"}} + backend := BackendOpnsense{Id: "fw1"} assert.Equal(t, "fw1", backend.GetDisplayName(), "display name falls back to the id") backend.DisplayName = "Edge firewall" diff --git a/internal/domain/interface.go b/internal/domain/interface.go index 5a9c7a6a..0b405cfe 100644 --- a/internal/domain/interface.go +++ b/internal/domain/interface.go @@ -6,6 +6,7 @@ import ( "math" "net" "regexp" + "slices" "strconv" "strings" "time" @@ -60,8 +61,8 @@ type Interface struct { DriverType string // the interface driver type (linux, software, ...) IsDynamic bool `gorm:"column:is_dynamic;default:false"` // specifies if the interface is a dynamic object - Disabled *time.Time `gorm:"index"` // flag that specifies if the interface is enabled (up) or not (down) - DisabledReason string // the reason why the interface has been disabled + Disabled *time.Time `gorm:"index"` // flag that specifies if the interface is enabled (up) or not (down) + DisabledReason string // the reason why the interface has been disabled // Default settings for the peer, used for new peers, those settings will be published to ConfigOption options of // the peer config @@ -100,10 +101,8 @@ func (i *Interface) IsUserAllowed(userId UserIdentifier, cfg *config.Config) boo } for _, allowedUsers := range i.LdapAllowedUsers { - for _, uid := range allowedUsers { - if uid == userId { - return true - } + if slices.Contains(allowedUsers, userId) { + return true } } return false diff --git a/internal/domain/peer_test.go b/internal/domain/peer_test.go index e1b6a874..e845d1ce 100644 --- a/internal/domain/peer_test.go +++ b/internal/domain/peer_test.go @@ -4,8 +4,8 @@ import ( "testing" "time" - "github.com/stretchr/testify/assert" "github.com/h44z/wg-portal/internal/config" + "github.com/stretchr/testify/assert" ) func TestPeer_IsDisabled(t *testing.T) { @@ -69,10 +69,8 @@ func TestPeer_ApplyInterfaceDefaults(t *testing.T) { }, } iface := &Interface{ - PeerDefEndpoint: "192.168.1.1", - KeyPair: KeyPair{ - PublicKey: "publicKey", - }, + PeerDefEndpoint: "192.168.1.1", + PublicKey: "publicKey", PeerDefAllowedIPsStr: "8.8.8.8/32", }