mirror of https://github.com/h44z/wg-portal.git
				
				
				
			
		
			
				
	
	
		
			175 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			175 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Go
		
	
	
	
| package backend
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 	"io"
 | |
| 
 | |
| 	"github.com/h44z/wg-portal/internal/app/api/v1/models"
 | |
| 	"github.com/h44z/wg-portal/internal/config"
 | |
| 	"github.com/h44z/wg-portal/internal/domain"
 | |
| )
 | |
| 
 | |
| type ProvisioningServiceUserManagerRepo interface {
 | |
| 	GetUser(ctx context.Context, id domain.UserIdentifier) (*domain.User, error)
 | |
| 	GetUserByEmail(ctx context.Context, email string) (*domain.User, error)
 | |
| }
 | |
| 
 | |
| type ProvisioningServicePeerManagerRepo interface {
 | |
| 	GetPeer(ctx context.Context, id domain.PeerIdentifier) (*domain.Peer, error)
 | |
| 	GetUserPeers(context.Context, domain.UserIdentifier) ([]domain.Peer, error)
 | |
| 	PreparePeer(ctx context.Context, id domain.InterfaceIdentifier) (*domain.Peer, error)
 | |
| 	CreatePeer(ctx context.Context, p *domain.Peer) (*domain.Peer, error)
 | |
| }
 | |
| 
 | |
| type ProvisioningServiceConfigFileManagerRepo interface {
 | |
| 	GetPeerConfig(ctx context.Context, id domain.PeerIdentifier) (io.Reader, error)
 | |
| 	GetPeerConfigQrCode(ctx context.Context, id domain.PeerIdentifier) (io.Reader, error)
 | |
| }
 | |
| 
 | |
| type ProvisioningService struct {
 | |
| 	cfg *config.Config
 | |
| 
 | |
| 	users       ProvisioningServiceUserManagerRepo
 | |
| 	peers       ProvisioningServicePeerManagerRepo
 | |
| 	configFiles ProvisioningServiceConfigFileManagerRepo
 | |
| }
 | |
| 
 | |
| func NewProvisioningService(
 | |
| 	cfg *config.Config,
 | |
| 	users ProvisioningServiceUserManagerRepo,
 | |
| 	peers ProvisioningServicePeerManagerRepo,
 | |
| 	configFiles ProvisioningServiceConfigFileManagerRepo,
 | |
| ) *ProvisioningService {
 | |
| 	return &ProvisioningService{
 | |
| 		cfg: cfg,
 | |
| 
 | |
| 		users:       users,
 | |
| 		peers:       peers,
 | |
| 		configFiles: configFiles,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (p ProvisioningService) GetUserAndPeers(
 | |
| 	ctx context.Context,
 | |
| 	userId domain.UserIdentifier,
 | |
| 	email string,
 | |
| ) (*domain.User, []domain.Peer, error) {
 | |
| 	// first fetch user
 | |
| 	var user *domain.User
 | |
| 	switch {
 | |
| 	case userId != "":
 | |
| 		u, err := p.users.GetUser(ctx, userId)
 | |
| 		if err != nil {
 | |
| 			return nil, nil, err
 | |
| 		}
 | |
| 		user = u
 | |
| 	case email != "":
 | |
| 		u, err := p.users.GetUserByEmail(ctx, email)
 | |
| 		if err != nil {
 | |
| 			return nil, nil, err
 | |
| 		}
 | |
| 		user = u
 | |
| 	default:
 | |
| 		return nil, nil, fmt.Errorf("either UserId or Email must be set: %w", domain.ErrInvalidData)
 | |
| 	}
 | |
| 
 | |
| 	if err := domain.ValidateUserAccessRights(ctx, user.Identifier); err != nil {
 | |
| 		return nil, nil, err
 | |
| 	}
 | |
| 
 | |
| 	peers, err := p.peers.GetUserPeers(ctx, user.Identifier)
 | |
| 	if err != nil {
 | |
| 		return nil, nil, err
 | |
| 	}
 | |
| 
 | |
| 	return user, peers, nil
 | |
| }
 | |
| 
 | |
| func (p ProvisioningService) GetPeerConfig(ctx context.Context, peerId domain.PeerIdentifier) ([]byte, error) {
 | |
| 	peer, err := p.peers.GetPeer(ctx, peerId)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	if err := domain.ValidateUserAccessRights(ctx, peer.UserIdentifier); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	peerCfgReader, err := p.configFiles.GetPeerConfig(ctx, peer.Identifier)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	peerCfgData, err := io.ReadAll(peerCfgReader)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	return peerCfgData, nil
 | |
| }
 | |
| 
 | |
| func (p ProvisioningService) GetPeerQrPng(ctx context.Context, peerId domain.PeerIdentifier) ([]byte, error) {
 | |
| 	peer, err := p.peers.GetPeer(ctx, peerId)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	if err := domain.ValidateUserAccessRights(ctx, peer.UserIdentifier); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	peerCfgQrReader, err := p.configFiles.GetPeerConfigQrCode(ctx, peer.Identifier)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	peerCfgQrData, err := io.ReadAll(peerCfgQrReader)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	return peerCfgQrData, nil
 | |
| }
 | |
| 
 | |
| func (p ProvisioningService) NewPeer(ctx context.Context, req models.ProvisioningRequest) (*domain.Peer, error) {
 | |
| 	if req.UserIdentifier == "" {
 | |
| 		req.UserIdentifier = string(domain.GetUserInfo(ctx).Id) // use authenticated user id if not set
 | |
| 	}
 | |
| 
 | |
| 	// check permissions
 | |
| 	if err := domain.ValidateUserAccessRights(ctx, domain.UserIdentifier(req.UserIdentifier)); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if !p.cfg.Core.SelfProvisioningAllowed {
 | |
| 		// only admins can create new peers if self-provisioning is disabled
 | |
| 		if err := domain.ValidateAdminAccessRights(ctx); err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// prepare new peer
 | |
| 	peer, err := p.peers.PreparePeer(ctx, domain.InterfaceIdentifier(req.InterfaceIdentifier))
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("failed to prepare new peer: %w", err)
 | |
| 	}
 | |
| 	peer.UserIdentifier = domain.UserIdentifier(req.UserIdentifier) // overwrite context user id with the one from the request
 | |
| 	if req.PublicKey != "" {
 | |
| 		peer.Identifier = domain.PeerIdentifier(req.PublicKey)
 | |
| 		peer.Interface.PublicKey = req.PublicKey
 | |
| 		peer.Interface.PrivateKey = "" // clear private key if public key is set, WireGuard Portal does not know the private key in that case
 | |
| 	}
 | |
| 	if req.PresharedKey != "" {
 | |
| 		peer.PresharedKey = domain.PreSharedKey(req.PresharedKey)
 | |
| 	}
 | |
| 	peer.GenerateDisplayName("API")
 | |
| 
 | |
| 	// save new peer
 | |
| 	peer, err = p.peers.CreatePeer(ctx, peer)
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("failed to create new peer: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	return peer, nil
 | |
| }
 |