mirror of
https://github.com/netbirdio/netbird.git
synced 2025-07-24 17:35:47 +02:00
130 lines
3.2 KiB
Go
130 lines
3.2 KiB
Go
package permissions
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/netbirdio/netbird/management/server/status"
|
|
"github.com/netbirdio/netbird/management/server/store"
|
|
"github.com/netbirdio/netbird/management/server/types"
|
|
)
|
|
|
|
type Module string
|
|
|
|
const (
|
|
Networks Module = "networks"
|
|
Peers Module = "peers"
|
|
Groups Module = "groups"
|
|
Settings Module = "settings"
|
|
Accounts Module = "accounts"
|
|
)
|
|
|
|
type Operation string
|
|
|
|
const (
|
|
Read Operation = "read"
|
|
Write Operation = "write"
|
|
)
|
|
|
|
type Manager interface {
|
|
ValidateUserPermissions(ctx context.Context, accountID, userID string, module Module, operation Operation) (bool, error)
|
|
ValidateAccountAccess(ctx context.Context, accountID string, user *types.User, allowOwnerAndAdmin bool) error
|
|
}
|
|
|
|
type managerImpl struct {
|
|
store store.Store
|
|
}
|
|
|
|
type managerMock struct {
|
|
}
|
|
|
|
func NewManager(store store.Store) Manager {
|
|
return &managerImpl{
|
|
store: store,
|
|
}
|
|
}
|
|
|
|
func (m *managerImpl) ValidateUserPermissions(ctx context.Context, accountID, userID string, module Module, operation Operation) (bool, error) {
|
|
user, err := m.store.GetUserByUserID(ctx, store.LockingStrengthShare, userID)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
if user == nil {
|
|
return false, status.NewUserNotFoundError(userID)
|
|
}
|
|
|
|
if err := m.ValidateAccountAccess(ctx, accountID, user, false); err != nil {
|
|
return false, err
|
|
}
|
|
|
|
switch module {
|
|
case Accounts:
|
|
if operation == Write && user.Role != types.UserRoleOwner {
|
|
return false, nil
|
|
}
|
|
return true, nil
|
|
default:
|
|
}
|
|
|
|
switch user.Role {
|
|
case types.UserRoleAdmin, types.UserRoleOwner:
|
|
return true, nil
|
|
case types.UserRoleUser:
|
|
return m.validateRegularUserPermissions(ctx, accountID, module, operation)
|
|
case types.UserRoleBillingAdmin:
|
|
return false, nil
|
|
default:
|
|
return false, errors.New("invalid role")
|
|
}
|
|
}
|
|
|
|
func (m *managerImpl) validateRegularUserPermissions(ctx context.Context, accountID string, module Module, operation Operation) (bool, error) {
|
|
settings, err := m.store.GetAccountSettings(ctx, store.LockingStrengthShare, accountID)
|
|
if err != nil {
|
|
return false, fmt.Errorf("failed to get settings: %w", err)
|
|
}
|
|
if settings.RegularUsersViewBlocked {
|
|
return false, nil
|
|
}
|
|
|
|
if operation == Write {
|
|
return false, nil
|
|
}
|
|
|
|
if module == Peers {
|
|
return true, nil
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
func (m *managerImpl) ValidateAccountAccess(ctx context.Context, accountID string, user *types.User, allowOwnerAndAdmin bool) error {
|
|
if user.AccountID != accountID {
|
|
return status.NewUserNotPartOfAccountError()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func NewManagerMock() Manager {
|
|
return &managerMock{}
|
|
}
|
|
|
|
func (m *managerMock) ValidateUserPermissions(ctx context.Context, accountID, userID string, module Module, operation Operation) (bool, error) {
|
|
switch userID {
|
|
case "a23efe53-63fb-11ec-90d6-0242ac120003", "allowedUser", "testingUser", "account_creator", "serviceUserID", "test_user":
|
|
return true, nil
|
|
default:
|
|
return false, nil
|
|
}
|
|
}
|
|
|
|
func (m *managerMock) ValidateAccountAccess(ctx context.Context, accountID string, user *types.User, allowOwnerAndAdmin bool) error {
|
|
// @note managers explicitly checked this, so should the mock
|
|
if user.AccountID != accountID {
|
|
return status.NewUserNotPartOfAccountError()
|
|
}
|
|
return nil
|
|
}
|