API - CRUD for peers, interfaces and users (#340)

Public REST API implementation to handle peers, interfaces and users. It also includes some simple provisioning endpoints.

The Swagger API documentation is available under /api/v1/doc.html
This commit is contained in:
h44z
2025-01-11 18:44:55 +01:00
committed by GitHub
parent ad267ed0a8
commit d596f578f6
53 changed files with 11028 additions and 274 deletions

View File

@@ -6,7 +6,6 @@ import (
"fmt"
"time"
"github.com/h44z/wg-portal/internal"
"github.com/h44z/wg-portal/internal/app"
"github.com/h44z/wg-portal/internal/domain"
"github.com/sirupsen/logrus"
@@ -34,9 +33,9 @@ func (m Manager) CreateDefaultPeer(ctx context.Context, userId domain.UserIdenti
}
peer.UserIdentifier = userId
peer.DisplayName = fmt.Sprintf("Default Peer %s", internal.TruncateString(string(peer.Identifier), 8))
peer.Notes = fmt.Sprintf("Default peer created for user %s", userId)
peer.AutomaticallyCreated = true
peer.GenerateDisplayName("Default")
newPeers = append(newPeers, *peer)
}
@@ -108,7 +107,6 @@ func (m Manager) PreparePeer(ctx context.Context, id domain.InterfaceIdentifier)
ExtraAllowedIPsStr: "",
PresharedKey: pk,
PersistentKeepalive: domain.NewConfigOption(iface.PeerDefPersistentKeepalive, true),
DisplayName: fmt.Sprintf("Peer %s", internal.TruncateString(string(peerId), 8)),
Identifier: peerId,
UserIdentifier: currentUser.Id,
InterfaceIdentifier: iface.Identifier,
@@ -132,6 +130,7 @@ func (m Manager) PreparePeer(ctx context.Context, id domain.InterfaceIdentifier)
PostDown: domain.NewConfigOption(iface.PeerDefPostDown, true),
},
}
freshPeer.GenerateDisplayName("")
return freshPeer, nil
}
@@ -159,7 +158,7 @@ func (m Manager) CreatePeer(ctx context.Context, peer *domain.Peer) (*domain.Pee
return nil, fmt.Errorf("unable to load existing peer %s: %w", peer.Identifier, err)
}
if existingPeer != nil {
return nil, fmt.Errorf("peer %s already exists", peer.Identifier)
return nil, fmt.Errorf("peer %s already exists: %w", peer.Identifier, domain.ErrDuplicateEntry)
}
if err := m.validatePeerCreation(ctx, existingPeer, peer); err != nil {
@@ -234,6 +233,15 @@ func (m Manager) UpdatePeer(ctx context.Context, peer *domain.Peer) (*domain.Pee
if existingPeer.Identifier != domain.PeerIdentifier(peer.Interface.PublicKey) {
peer.Identifier = domain.PeerIdentifier(peer.Interface.PublicKey) // set new identifier
// check for already existing peer with new identifier
duplicatePeer, 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)
}
if duplicatePeer != nil {
return nil, fmt.Errorf("peer %s already exists: %w", peer.Identifier, domain.ErrDuplicateEntry)
}
// delete old peer
err = m.DeletePeer(ctx, existingPeer.Identifier)
if err != nil {
@@ -431,7 +439,7 @@ func (m Manager) validatePeerModifications(ctx context.Context, old, new *domain
currentUser := domain.GetUserInfo(ctx)
if !currentUser.IsAdmin {
return fmt.Errorf("insufficient permissions")
return domain.ErrNoPermission
}
return nil
@@ -441,11 +449,16 @@ func (m Manager) validatePeerCreation(ctx context.Context, old, new *domain.Peer
currentUser := domain.GetUserInfo(ctx)
if new.Identifier == "" {
return fmt.Errorf("invalid peer identifier")
return fmt.Errorf("invalid peer identifier: %w", domain.ErrInvalidData)
}
if !currentUser.IsAdmin {
return fmt.Errorf("insufficient permissions")
return domain.ErrNoPermission
}
_, err := m.db.GetInterface(ctx, new.InterfaceIdentifier)
if err != nil {
return fmt.Errorf("invalid interface: %w", domain.ErrInvalidData)
}
return nil
@@ -455,7 +468,7 @@ func (m Manager) validatePeerDeletion(ctx context.Context, del *domain.Peer) err
currentUser := domain.GetUserInfo(ctx)
if !currentUser.IsAdmin {
return fmt.Errorf("insufficient permissions")
return domain.ErrNoPermission
}
return nil