mirror of
https://github.com/h44z/wg-portal.git
synced 2025-09-14 06:51:15 +00:00
fix self provisioning feature (#272)
This commit is contained in:
@@ -68,6 +68,34 @@ func (m Manager) GetAllInterfacesAndPeers(ctx context.Context) ([]domain.Interfa
|
||||
return interfaces, allPeers, nil
|
||||
}
|
||||
|
||||
// GetUserInterfaces returns all interfaces that are available for users to create new peers.
|
||||
// If self-provisioning is disabled, this function will return an empty list.
|
||||
func (m Manager) GetUserInterfaces(ctx context.Context, id domain.UserIdentifier) ([]domain.Interface, error) {
|
||||
if !m.cfg.Core.SelfProvisioningAllowed {
|
||||
return nil, nil // self-provisioning is disabled - no interfaces for users
|
||||
}
|
||||
|
||||
interfaces, err := m.db.GetAllInterfaces(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to load all interfaces: %w", err)
|
||||
}
|
||||
|
||||
// strip sensitive data, users only need very limited information
|
||||
userInterfaces := make([]domain.Interface, 0, len(interfaces))
|
||||
for _, iface := range interfaces {
|
||||
if iface.IsDisabled() {
|
||||
continue // skip disabled interfaces
|
||||
}
|
||||
if iface.Type != domain.InterfaceTypeServer {
|
||||
continue // skip client interfaces
|
||||
}
|
||||
|
||||
userInterfaces = append(userInterfaces, iface.PublicInfo())
|
||||
}
|
||||
|
||||
return userInterfaces, nil
|
||||
}
|
||||
|
||||
func (m Manager) ImportNewInterfaces(ctx context.Context, filter ...domain.InterfaceIdentifier) (int, error) {
|
||||
if err := domain.ValidateAdminAccessRights(ctx); err != nil {
|
||||
return 0, err
|
||||
|
@@ -62,8 +62,10 @@ func (m Manager) GetUserPeers(ctx context.Context, id domain.UserIdentifier) ([]
|
||||
}
|
||||
|
||||
func (m Manager) PreparePeer(ctx context.Context, id domain.InterfaceIdentifier) (*domain.Peer, error) {
|
||||
if err := domain.ValidateAdminAccessRights(ctx); err != nil {
|
||||
return nil, err // TODO: self provisioning?
|
||||
if !m.cfg.Core.SelfProvisioningAllowed {
|
||||
if err := domain.ValidateAdminAccessRights(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
currentUser := domain.GetUserInfo(ctx)
|
||||
@@ -73,6 +75,10 @@ func (m Manager) PreparePeer(ctx context.Context, id domain.InterfaceIdentifier)
|
||||
return nil, fmt.Errorf("unable to find interface %s: %w", id, err)
|
||||
}
|
||||
|
||||
if m.cfg.Core.SelfProvisioningAllowed && iface.Type != domain.InterfaceTypeServer {
|
||||
return nil, fmt.Errorf("self provisioning is only allowed for server interfaces: %w", domain.ErrNoPermission)
|
||||
}
|
||||
|
||||
ips, err := m.getFreshPeerIpConfig(ctx, iface)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to get fresh ip addresses: %w", err)
|
||||
@@ -149,10 +155,18 @@ func (m Manager) GetPeer(ctx context.Context, id domain.PeerIdentifier) (*domain
|
||||
}
|
||||
|
||||
func (m Manager) CreatePeer(ctx context.Context, peer *domain.Peer) (*domain.Peer, error) {
|
||||
if err := domain.ValidateUserAccessRights(ctx, peer.UserIdentifier); err != nil {
|
||||
return nil, err
|
||||
if !m.cfg.Core.SelfProvisioningAllowed {
|
||||
if err := domain.ValidateAdminAccessRights(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
if err := domain.ValidateUserAccessRights(ctx, peer.UserIdentifier); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
sessionUser := domain.GetUserInfo(ctx)
|
||||
|
||||
existingPeer, err := m.db.GetPeer(ctx, peer.Identifier)
|
||||
if err != nil && !errors.Is(err, domain.ErrNotFound) {
|
||||
return nil, fmt.Errorf("unable to load existing peer %s: %w", peer.Identifier, err)
|
||||
@@ -161,6 +175,18 @@ func (m Manager) CreatePeer(ctx context.Context, peer *domain.Peer) (*domain.Pee
|
||||
return nil, fmt.Errorf("peer %s already exists: %w", peer.Identifier, domain.ErrDuplicateEntry)
|
||||
}
|
||||
|
||||
// if a peer is self provisioned, ensure that only allowed fields are set from the request
|
||||
if !sessionUser.IsAdmin {
|
||||
preparedPeer, err := m.PreparePeer(ctx, peer.InterfaceIdentifier)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to prepare peer for interface %s: %w", peer.InterfaceIdentifier, err)
|
||||
}
|
||||
|
||||
preparedPeer.OverwriteUserEditableFields(peer)
|
||||
|
||||
peer = preparedPeer
|
||||
}
|
||||
|
||||
if err := m.validatePeerCreation(ctx, existingPeer, peer); err != nil {
|
||||
return nil, fmt.Errorf("creation not allowed: %w", err)
|
||||
}
|
||||
@@ -229,6 +255,19 @@ func (m Manager) UpdatePeer(ctx context.Context, peer *domain.Peer) (*domain.Pee
|
||||
return nil, fmt.Errorf("update not allowed: %w", err)
|
||||
}
|
||||
|
||||
sessionUser := domain.GetUserInfo(ctx)
|
||||
|
||||
// if a peer is self provisioned, ensure that only allowed fields are set from the request
|
||||
if !sessionUser.IsAdmin {
|
||||
originalPeer, err := m.db.GetPeer(ctx, peer.Identifier)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to load existing peer %s: %w", peer.Identifier, err)
|
||||
}
|
||||
originalPeer.OverwriteUserEditableFields(peer)
|
||||
|
||||
peer = originalPeer
|
||||
}
|
||||
|
||||
// handle peer identifier change (new public key)
|
||||
if existingPeer.Identifier != domain.PeerIdentifier(peer.Interface.PublicKey) {
|
||||
peer.Identifier = domain.PeerIdentifier(peer.Interface.PublicKey) // set new identifier
|
||||
@@ -438,7 +477,7 @@ func (m Manager) getFreshPeerIpConfig(ctx context.Context, iface *domain.Interfa
|
||||
func (m Manager) validatePeerModifications(ctx context.Context, old, new *domain.Peer) error {
|
||||
currentUser := domain.GetUserInfo(ctx)
|
||||
|
||||
if !currentUser.IsAdmin {
|
||||
if !currentUser.IsAdmin && !m.cfg.Core.SelfProvisioningAllowed {
|
||||
return domain.ErrNoPermission
|
||||
}
|
||||
|
||||
@@ -452,7 +491,7 @@ func (m Manager) validatePeerCreation(ctx context.Context, old, new *domain.Peer
|
||||
return fmt.Errorf("invalid peer identifier: %w", domain.ErrInvalidData)
|
||||
}
|
||||
|
||||
if !currentUser.IsAdmin {
|
||||
if !currentUser.IsAdmin && !m.cfg.Core.SelfProvisioningAllowed {
|
||||
return domain.ErrNoPermission
|
||||
}
|
||||
|
||||
@@ -467,7 +506,7 @@ func (m Manager) validatePeerCreation(ctx context.Context, old, new *domain.Peer
|
||||
func (m Manager) validatePeerDeletion(ctx context.Context, del *domain.Peer) error {
|
||||
currentUser := domain.GetUserInfo(ctx)
|
||||
|
||||
if !currentUser.IsAdmin {
|
||||
if !currentUser.IsAdmin && !m.cfg.Core.SelfProvisioningAllowed {
|
||||
return domain.ErrNoPermission
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user