mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-25 19:56:46 +00:00
200 lines
6.7 KiB
Go
200 lines
6.7 KiB
Go
package manager
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/netbirdio/netbird/management/internals/modules/services"
|
|
"github.com/netbirdio/netbird/management/server/account"
|
|
"github.com/netbirdio/netbird/management/server/activity"
|
|
"github.com/netbirdio/netbird/management/server/permissions"
|
|
"github.com/netbirdio/netbird/management/server/permissions/modules"
|
|
"github.com/netbirdio/netbird/management/server/permissions/operations"
|
|
"github.com/netbirdio/netbird/management/server/store"
|
|
"github.com/netbirdio/netbird/shared/management/status"
|
|
)
|
|
|
|
type managerImpl struct {
|
|
store store.Store
|
|
accountManager account.Manager
|
|
permissionsManager permissions.Manager
|
|
}
|
|
|
|
func NewManager(store store.Store, accountManager account.Manager, permissionsManager permissions.Manager) services.Manager {
|
|
return &managerImpl{
|
|
store: store,
|
|
accountManager: accountManager,
|
|
permissionsManager: permissionsManager,
|
|
}
|
|
}
|
|
|
|
func (m *managerImpl) GetAllServices(ctx context.Context, accountID, userID string) ([]*services.Service, error) {
|
|
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Services, operations.Read)
|
|
if err != nil {
|
|
return nil, status.NewPermissionValidationError(err)
|
|
}
|
|
if !ok {
|
|
return nil, status.NewPermissionDeniedError()
|
|
}
|
|
|
|
return m.store.GetAccountServices(ctx, store.LockingStrengthNone, accountID)
|
|
}
|
|
|
|
func (m *managerImpl) GetService(ctx context.Context, accountID, userID, serviceID string) (*services.Service, error) {
|
|
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Services, operations.Read)
|
|
if err != nil {
|
|
return nil, status.NewPermissionValidationError(err)
|
|
}
|
|
if !ok {
|
|
return nil, status.NewPermissionDeniedError()
|
|
}
|
|
|
|
return m.store.GetServiceByID(ctx, store.LockingStrengthNone, accountID, serviceID)
|
|
}
|
|
|
|
func (m *managerImpl) CreateService(ctx context.Context, accountID, userID string, service *services.Service) (*services.Service, error) {
|
|
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Services, operations.Create)
|
|
if err != nil {
|
|
return nil, status.NewPermissionValidationError(err)
|
|
}
|
|
if !ok {
|
|
return nil, status.NewPermissionDeniedError()
|
|
}
|
|
|
|
// Store auth config before creating new service
|
|
authType := service.AuthType
|
|
authBasicUsername := service.AuthBasicUsername
|
|
authBasicPassword := service.AuthBasicPassword
|
|
authPINValue := service.AuthPINValue
|
|
authPINHeader := service.AuthPINHeader
|
|
authBearerEnabled := service.AuthBearerEnabled
|
|
|
|
service = services.NewService(accountID, service.Name, service.Description, service.Domain, service.Targets, service.DistributionGroups, service.Enabled, service.Exposed)
|
|
|
|
// Restore auth config
|
|
service.AuthType = authType
|
|
service.AuthBasicUsername = authBasicUsername
|
|
service.AuthBasicPassword = authBasicPassword
|
|
service.AuthPINValue = authPINValue
|
|
service.AuthPINHeader = authPINHeader
|
|
service.AuthBearerEnabled = authBearerEnabled
|
|
|
|
err = m.store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
|
// Check for duplicate domain
|
|
existingService, err := transaction.GetServiceByDomain(ctx, accountID, service.Domain)
|
|
if err != nil {
|
|
if sErr, ok := status.FromError(err); !ok || sErr.Type() != status.NotFound {
|
|
return fmt.Errorf("failed to check existing service: %w", err)
|
|
}
|
|
}
|
|
if existingService != nil {
|
|
return status.Errorf(status.AlreadyExists, "service with domain %s already exists", service.Domain)
|
|
}
|
|
|
|
// Validate distribution groups exist
|
|
for _, groupID := range service.DistributionGroups {
|
|
_, err = transaction.GetGroupByID(ctx, store.LockingStrengthNone, accountID, groupID)
|
|
if err != nil {
|
|
return status.Errorf(status.InvalidArgument, "%s", err.Error())
|
|
}
|
|
}
|
|
|
|
if err = transaction.CreateService(ctx, service); err != nil {
|
|
return fmt.Errorf("failed to create service: %w", err)
|
|
}
|
|
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
m.accountManager.StoreEvent(ctx, userID, service.ID, accountID, activity.ServiceCreated, service.EventMeta())
|
|
|
|
return service, nil
|
|
}
|
|
|
|
func (m *managerImpl) UpdateService(ctx context.Context, accountID, userID string, service *services.Service) (*services.Service, error) {
|
|
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Services, operations.Update)
|
|
if err != nil {
|
|
return nil, status.NewPermissionValidationError(err)
|
|
}
|
|
if !ok {
|
|
return nil, status.NewPermissionDeniedError()
|
|
}
|
|
|
|
err = m.store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
|
// Get existing service
|
|
existingService, err := transaction.GetServiceByID(ctx, store.LockingStrengthUpdate, accountID, service.ID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Check if domain changed and if it conflicts
|
|
if existingService.Domain != service.Domain {
|
|
conflictService, err := transaction.GetServiceByDomain(ctx, accountID, service.Domain)
|
|
if err != nil {
|
|
if sErr, ok := status.FromError(err); !ok || sErr.Type() != status.NotFound {
|
|
return fmt.Errorf("failed to check existing service: %w", err)
|
|
}
|
|
}
|
|
if conflictService != nil && conflictService.ID != service.ID {
|
|
return status.Errorf(status.AlreadyExists, "service with domain %s already exists", service.Domain)
|
|
}
|
|
}
|
|
|
|
// Validate distribution groups exist
|
|
for _, groupID := range service.DistributionGroups {
|
|
_, err = transaction.GetGroupByID(ctx, store.LockingStrengthNone, accountID, groupID)
|
|
if err != nil {
|
|
return status.Errorf(status.InvalidArgument, "%s", err.Error())
|
|
}
|
|
}
|
|
|
|
if err = transaction.UpdateService(ctx, service); err != nil {
|
|
return fmt.Errorf("failed to update service: %w", err)
|
|
}
|
|
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
m.accountManager.StoreEvent(ctx, userID, service.ID, accountID, activity.ServiceUpdated, service.EventMeta())
|
|
|
|
return service, nil
|
|
}
|
|
|
|
func (m *managerImpl) DeleteService(ctx context.Context, accountID, userID, serviceID string) error {
|
|
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Services, operations.Delete)
|
|
if err != nil {
|
|
return status.NewPermissionValidationError(err)
|
|
}
|
|
if !ok {
|
|
return status.NewPermissionDeniedError()
|
|
}
|
|
|
|
var service *services.Service
|
|
err = m.store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
|
var err error
|
|
service, err = transaction.GetServiceByID(ctx, store.LockingStrengthUpdate, accountID, serviceID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = transaction.DeleteService(ctx, accountID, serviceID); err != nil {
|
|
return fmt.Errorf("failed to delete service: %w", err)
|
|
}
|
|
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
m.accountManager.StoreEvent(ctx, userID, serviceID, accountID, activity.ServiceDeleted, service.EventMeta())
|
|
|
|
return nil
|
|
}
|