mirror of
https://github.com/h44z/wg-portal.git
synced 2026-10-19 04:02:03 +00:00
go fix changes
This commit is contained in:
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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{})
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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") {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
|
||||
+4
-6
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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$",
|
||||
|
||||
+27
-41
@@ -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),
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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: "",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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{}
|
||||
|
||||
|
||||
@@ -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 != "" {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user