mirror of
https://github.com/netbirdio/netbird.git
synced 2025-06-19 08:17:01 +02:00
Merge branch 'main' into feature/peer-approval
This commit is contained in:
commit
d5bf79bc51
@ -488,7 +488,18 @@ func (s *DefaultServer) addHostRootZone() {
|
|||||||
handler := newUpstreamResolver(s.ctx)
|
handler := newUpstreamResolver(s.ctx)
|
||||||
handler.upstreamServers = make([]string, len(s.hostsDnsList))
|
handler.upstreamServers = make([]string, len(s.hostsDnsList))
|
||||||
for n, ua := range s.hostsDnsList {
|
for n, ua := range s.hostsDnsList {
|
||||||
handler.upstreamServers[n] = fmt.Sprintf("%s:53", ua)
|
a, err := netip.ParseAddr(ua)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("invalid upstream IP address: %s, error: %s", ua, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ipString := ua
|
||||||
|
if !a.Is4() {
|
||||||
|
ipString = fmt.Sprintf("[%s]", ua)
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.upstreamServers[n] = fmt.Sprintf("%s:53", ipString)
|
||||||
}
|
}
|
||||||
handler.deactivate = func() {}
|
handler.deactivate = func() {}
|
||||||
handler.reactivate = func() {}
|
handler.reactivate = func() {}
|
||||||
|
@ -905,7 +905,7 @@ func (am *DefaultAccountManager) UpdateAccountSettings(accountID, userID string,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !user.IsAdmin() {
|
if !user.HasAdminPower() {
|
||||||
return nil, status.Errorf(status.PermissionDenied, "user is not allowed to update account")
|
return nil, status.Errorf(status.PermissionDenied, "user is not allowed to update account")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1047,7 +1047,7 @@ func (am *DefaultAccountManager) DeleteAccount(accountID, userID string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !user.IsAdmin() {
|
if !user.HasAdminPower() {
|
||||||
return status.Errorf(status.PermissionDenied, "user is not allowed to delete account")
|
return status.Errorf(status.PermissionDenied, "user is not allowed to delete account")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1731,7 +1731,7 @@ func newAccountWithId(accountID, userID, domain string) *Account {
|
|||||||
routes := make(map[string]*route.Route)
|
routes := make(map[string]*route.Route)
|
||||||
setupKeys := map[string]*SetupKey{}
|
setupKeys := map[string]*SetupKey{}
|
||||||
nameServersGroups := make(map[string]*nbdns.NameServerGroup)
|
nameServersGroups := make(map[string]*nbdns.NameServerGroup)
|
||||||
users[userID] = NewAdminUser(userID)
|
users[userID] = NewOwnerUser(userID)
|
||||||
dnsSettings := DNSSettings{
|
dnsSettings := DNSSettings{
|
||||||
DisabledManagementGroups: make([]string, 0),
|
DisabledManagementGroups: make([]string, 0),
|
||||||
}
|
}
|
||||||
|
@ -462,7 +462,7 @@ func TestDefaultAccountManager_GetAccountFromToken(t *testing.T) {
|
|||||||
inputInitUserParams: defaultInitAccount,
|
inputInitUserParams: defaultInitAccount,
|
||||||
testingFunc: require.NotEqual,
|
testingFunc: require.NotEqual,
|
||||||
expectedMSG: "account IDs shouldn't match",
|
expectedMSG: "account IDs shouldn't match",
|
||||||
expectedUserRole: UserRoleAdmin,
|
expectedUserRole: UserRoleOwner,
|
||||||
expectedDomainCategory: "",
|
expectedDomainCategory: "",
|
||||||
expectedDomain: publicDomain,
|
expectedDomain: publicDomain,
|
||||||
expectedPrimaryDomainStatus: false,
|
expectedPrimaryDomainStatus: false,
|
||||||
@ -484,7 +484,7 @@ func TestDefaultAccountManager_GetAccountFromToken(t *testing.T) {
|
|||||||
inputInitUserParams: initUnknown,
|
inputInitUserParams: initUnknown,
|
||||||
testingFunc: require.NotEqual,
|
testingFunc: require.NotEqual,
|
||||||
expectedMSG: "account IDs shouldn't match",
|
expectedMSG: "account IDs shouldn't match",
|
||||||
expectedUserRole: UserRoleAdmin,
|
expectedUserRole: UserRoleOwner,
|
||||||
expectedDomain: unknownDomain,
|
expectedDomain: unknownDomain,
|
||||||
expectedDomainCategory: "",
|
expectedDomainCategory: "",
|
||||||
expectedPrimaryDomainStatus: false,
|
expectedPrimaryDomainStatus: false,
|
||||||
@ -502,7 +502,7 @@ func TestDefaultAccountManager_GetAccountFromToken(t *testing.T) {
|
|||||||
inputInitUserParams: defaultInitAccount,
|
inputInitUserParams: defaultInitAccount,
|
||||||
testingFunc: require.NotEqual,
|
testingFunc: require.NotEqual,
|
||||||
expectedMSG: "account IDs shouldn't match",
|
expectedMSG: "account IDs shouldn't match",
|
||||||
expectedUserRole: UserRoleAdmin,
|
expectedUserRole: UserRoleOwner,
|
||||||
expectedDomain: privateDomain,
|
expectedDomain: privateDomain,
|
||||||
expectedDomainCategory: PrivateCategory,
|
expectedDomainCategory: PrivateCategory,
|
||||||
expectedPrimaryDomainStatus: true,
|
expectedPrimaryDomainStatus: true,
|
||||||
@ -543,7 +543,7 @@ func TestDefaultAccountManager_GetAccountFromToken(t *testing.T) {
|
|||||||
inputInitUserParams: defaultInitAccount,
|
inputInitUserParams: defaultInitAccount,
|
||||||
testingFunc: require.Equal,
|
testingFunc: require.Equal,
|
||||||
expectedMSG: "account IDs should match",
|
expectedMSG: "account IDs should match",
|
||||||
expectedUserRole: UserRoleAdmin,
|
expectedUserRole: UserRoleOwner,
|
||||||
expectedDomain: defaultInitAccount.Domain,
|
expectedDomain: defaultInitAccount.Domain,
|
||||||
expectedDomainCategory: PrivateCategory,
|
expectedDomainCategory: PrivateCategory,
|
||||||
expectedPrimaryDomainStatus: true,
|
expectedPrimaryDomainStatus: true,
|
||||||
@ -562,7 +562,7 @@ func TestDefaultAccountManager_GetAccountFromToken(t *testing.T) {
|
|||||||
inputInitUserParams: defaultInitAccount,
|
inputInitUserParams: defaultInitAccount,
|
||||||
testingFunc: require.Equal,
|
testingFunc: require.Equal,
|
||||||
expectedMSG: "account IDs should match",
|
expectedMSG: "account IDs should match",
|
||||||
expectedUserRole: UserRoleAdmin,
|
expectedUserRole: UserRoleOwner,
|
||||||
expectedDomain: defaultInitAccount.Domain,
|
expectedDomain: defaultInitAccount.Domain,
|
||||||
expectedDomainCategory: PrivateCategory,
|
expectedDomainCategory: PrivateCategory,
|
||||||
expectedPrimaryDomainStatus: true,
|
expectedPrimaryDomainStatus: true,
|
||||||
@ -580,7 +580,7 @@ func TestDefaultAccountManager_GetAccountFromToken(t *testing.T) {
|
|||||||
inputInitUserParams: defaultInitAccount,
|
inputInitUserParams: defaultInitAccount,
|
||||||
testingFunc: require.NotEqual,
|
testingFunc: require.NotEqual,
|
||||||
expectedMSG: "account IDs shouldn't match",
|
expectedMSG: "account IDs shouldn't match",
|
||||||
expectedUserRole: UserRoleAdmin,
|
expectedUserRole: UserRoleOwner,
|
||||||
expectedDomain: "",
|
expectedDomain: "",
|
||||||
expectedDomainCategory: "",
|
expectedDomainCategory: "",
|
||||||
expectedPrimaryDomainStatus: false,
|
expectedPrimaryDomainStatus: false,
|
||||||
@ -1339,7 +1339,7 @@ func TestGetUsersFromAccount(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
users := map[string]*User{"1": {Id: "1", Role: "admin"}, "2": {Id: "2", Role: "user"}, "3": {Id: "3", Role: "user"}}
|
users := map[string]*User{"1": {Id: "1", Role: UserRoleOwner}, "2": {Id: "2", Role: "user"}, "3": {Id: "3", Role: "user"}}
|
||||||
accountId := "test_account_id"
|
accountId := "test_account_id"
|
||||||
|
|
||||||
account, err := createAccount(manager, accountId, users["1"].Id, "")
|
account, err := createAccount(manager, accountId, users["1"].Id, "")
|
||||||
|
@ -128,6 +128,8 @@ const (
|
|||||||
PeerApproved
|
PeerApproved
|
||||||
// PeerApprovalRevoked indicates that the peer approval has been revoked
|
// PeerApprovalRevoked indicates that the peer approval has been revoked
|
||||||
PeerApprovalRevoked
|
PeerApprovalRevoked
|
||||||
|
// TransferredOwnerRole indicates that the user transferred the owner role of the account
|
||||||
|
TransferredOwnerRole
|
||||||
)
|
)
|
||||||
|
|
||||||
var activityMap = map[Activity]Code{
|
var activityMap = map[Activity]Code{
|
||||||
@ -190,6 +192,7 @@ var activityMap = map[Activity]Code{
|
|||||||
AccountPeerApprovalDisabled: {"Account peer approval disabled", "account.setting.peer.approval.disable"},
|
AccountPeerApprovalDisabled: {"Account peer approval disabled", "account.setting.peer.approval.disable"},
|
||||||
PeerApproved: {"Peer approved", "peer.approve"},
|
PeerApproved: {"Peer approved", "peer.approve"},
|
||||||
PeerApprovalRevoked: {"Peer approval revoked", "peer.approval.revoke"},
|
PeerApprovalRevoked: {"Peer approval revoked", "peer.approval.revoke"},
|
||||||
|
TransferredOwnerRole: {"Transferred owner role", "transferred.owner.role"},
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringCode returns a string code of the activity
|
// StringCode returns a string code of the activity
|
||||||
|
@ -48,8 +48,8 @@ func (am *DefaultAccountManager) GetDNSSettings(accountID string, userID string)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !user.IsAdmin() {
|
if !user.HasAdminPower() {
|
||||||
return nil, status.Errorf(status.PermissionDenied, "only admins are allowed to view DNS settings")
|
return nil, status.Errorf(status.PermissionDenied, "only users with admin power are allowed to view DNS settings")
|
||||||
}
|
}
|
||||||
dnsSettings := account.DNSSettings.Copy()
|
dnsSettings := account.DNSSettings.Copy()
|
||||||
return &dnsSettings, nil
|
return &dnsSettings, nil
|
||||||
@ -70,8 +70,8 @@ func (am *DefaultAccountManager) SaveDNSSettings(accountID string, userID string
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !user.IsAdmin() {
|
if !user.HasAdminPower() {
|
||||||
return status.Errorf(status.PermissionDenied, "only admins are allowed to update DNS settings")
|
return status.Errorf(status.PermissionDenied, "only users with admin power are allowed to update DNS settings")
|
||||||
}
|
}
|
||||||
|
|
||||||
if dnsSettingsToSave == nil {
|
if dnsSettingsToSave == nil {
|
||||||
|
@ -170,7 +170,7 @@ func (am *DefaultAccountManager) DeleteGroup(accountId, userId, groupID string)
|
|||||||
return status.Errorf(status.NotFound, "user not found")
|
return status.Errorf(status.NotFound, "user not found")
|
||||||
}
|
}
|
||||||
if executingUser.Role != UserRoleAdmin || !executingUser.IsServiceUser {
|
if executingUser.Role != UserRoleAdmin || !executingUser.IsServiceUser {
|
||||||
return status.Errorf(status.PermissionDenied, "only admins service user can delete integration group")
|
return status.Errorf(status.PermissionDenied, "only service users with admin power can delete integration group")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ func TestDefaultAccountManager_DeleteGroup(t *testing.T) {
|
|||||||
{
|
{
|
||||||
"integration",
|
"integration",
|
||||||
"grp-for-integration",
|
"grp-for-integration",
|
||||||
"only admins service user can delete integration group",
|
"only service users with admin power can delete integration group",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ func (h *AccountsHandler) GetAllAccounts(w http.ResponseWriter, r *http.Request)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !user.IsAdmin() {
|
if !user.HasAdminPower() {
|
||||||
util.WriteError(status.Errorf(status.PermissionDenied, "the user has no permission to access account data"), w)
|
util.WriteError(status.Errorf(status.PermissionDenied, "the user has no permission to access account data"), w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ func (a *AccessControl) Handler(h http.Handler) http.Handler {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !user.IsAdmin() {
|
if !user.HasAdminPower() {
|
||||||
switch r.Method {
|
switch r.Method {
|
||||||
case http.MethodDelete, http.MethodPost, http.MethodPatch, http.MethodPut:
|
case http.MethodDelete, http.MethodPost, http.MethodPatch, http.MethodPut:
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ func (a *AccessControl) Handler(h http.Handler) http.Handler {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
util.WriteError(status.Errorf(status.PermissionDenied, "only admin can perform this operation"), w)
|
util.WriteError(status.Errorf(status.PermissionDenied, "only users with admin power can perform this operation"), w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
77
management/server/idp/mock.go
Normal file
77
management/server/idp/mock.go
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
package idp
|
||||||
|
|
||||||
|
// MockIDP is a mock implementation of the IDP interface
|
||||||
|
type MockIDP struct {
|
||||||
|
UpdateUserAppMetadataFunc func(userId string, appMetadata AppMetadata) error
|
||||||
|
GetUserDataByIDFunc func(userId string, appMetadata AppMetadata) (*UserData, error)
|
||||||
|
GetAccountFunc func(accountId string) ([]*UserData, error)
|
||||||
|
GetAllAccountsFunc func() (map[string][]*UserData, error)
|
||||||
|
CreateUserFunc func(email, name, accountID, invitedByEmail string) (*UserData, error)
|
||||||
|
GetUserByEmailFunc func(email string) ([]*UserData, error)
|
||||||
|
InviteUserByIDFunc func(userID string) error
|
||||||
|
DeleteUserFunc func(userID string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateUserAppMetadata is a mock implementation of the IDP interface UpdateUserAppMetadata method
|
||||||
|
func (m *MockIDP) UpdateUserAppMetadata(userId string, appMetadata AppMetadata) error {
|
||||||
|
if m.UpdateUserAppMetadataFunc != nil {
|
||||||
|
return m.UpdateUserAppMetadataFunc(userId, appMetadata)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserDataByID is a mock implementation of the IDP interface GetUserDataByID method
|
||||||
|
func (m *MockIDP) GetUserDataByID(userId string, appMetadata AppMetadata) (*UserData, error) {
|
||||||
|
if m.GetUserDataByIDFunc != nil {
|
||||||
|
return m.GetUserDataByIDFunc(userId, appMetadata)
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAccount is a mock implementation of the IDP interface GetAccount method
|
||||||
|
func (m *MockIDP) GetAccount(accountId string) ([]*UserData, error) {
|
||||||
|
if m.GetAccountFunc != nil {
|
||||||
|
return m.GetAccountFunc(accountId)
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAllAccounts is a mock implementation of the IDP interface GetAllAccounts method
|
||||||
|
func (m *MockIDP) GetAllAccounts() (map[string][]*UserData, error) {
|
||||||
|
if m.GetAllAccountsFunc != nil {
|
||||||
|
return m.GetAllAccountsFunc()
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateUser is a mock implementation of the IDP interface CreateUser method
|
||||||
|
func (m *MockIDP) CreateUser(email, name, accountID, invitedByEmail string) (*UserData, error) {
|
||||||
|
if m.CreateUserFunc != nil {
|
||||||
|
return m.CreateUserFunc(email, name, accountID, invitedByEmail)
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserByEmail is a mock implementation of the IDP interface GetUserByEmail method
|
||||||
|
func (m *MockIDP) GetUserByEmail(email string) ([]*UserData, error) {
|
||||||
|
if m.GetUserByEmailFunc != nil {
|
||||||
|
return m.GetUserByEmailFunc(email)
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// InviteUserByID is a mock implementation of the IDP interface InviteUserByID method
|
||||||
|
func (m *MockIDP) InviteUserByID(userID string) error {
|
||||||
|
if m.InviteUserByIDFunc != nil {
|
||||||
|
return m.InviteUserByIDFunc(userID)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteUser is a mock implementation of the IDP interface DeleteUser method
|
||||||
|
func (m *MockIDP) DeleteUser(userID string) error {
|
||||||
|
if m.DeleteUserFunc != nil {
|
||||||
|
return m.DeleteUserFunc(userID)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -53,7 +53,7 @@ func (am *DefaultAccountManager) GetPeers(accountID, userID string) ([]*nbpeer.P
|
|||||||
peers := make([]*nbpeer.Peer, 0)
|
peers := make([]*nbpeer.Peer, 0)
|
||||||
peersMap := make(map[string]*nbpeer.Peer)
|
peersMap := make(map[string]*nbpeer.Peer)
|
||||||
for _, peer := range account.Peers {
|
for _, peer := range account.Peers {
|
||||||
if !user.IsAdmin() && user.Id != peer.UserID {
|
if !user.HasAdminPower() && user.Id != peer.UserID {
|
||||||
// only display peers that belong to the current user if the current user is not an admin
|
// only display peers that belong to the current user if the current user is not an admin
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -701,7 +701,7 @@ func (am *DefaultAccountManager) GetPeer(accountID, peerID, userID string) (*nbp
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if admin or user owns this peer, return peer
|
// if admin or user owns this peer, return peer
|
||||||
if user.IsAdmin() || peer.UserID == userID {
|
if user.HasAdminPower() || peer.UserID == userID {
|
||||||
return peer, nil
|
return peer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,8 +320,8 @@ func (am *DefaultAccountManager) GetPolicy(accountID, policyID, userID string) (
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !user.IsAdmin() {
|
if !user.HasAdminPower() {
|
||||||
return nil, status.Errorf(status.PermissionDenied, "only admins are allowed to view policies")
|
return nil, status.Errorf(status.PermissionDenied, "only users with admin power are allowed to view policies")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, policy := range account.Policies {
|
for _, policy := range account.Policies {
|
||||||
@ -403,8 +403,8 @@ func (am *DefaultAccountManager) ListPolicies(accountID, userID string) ([]*Poli
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !user.IsAdmin() {
|
if !user.HasAdminPower() {
|
||||||
return nil, status.Errorf(status.PermissionDenied, "Only Administrators can view policies")
|
return nil, status.Errorf(status.PermissionDenied, "only users with admin power can view policies")
|
||||||
}
|
}
|
||||||
|
|
||||||
return account.Policies, nil
|
return account.Policies, nil
|
||||||
|
@ -27,8 +27,8 @@ func (am *DefaultAccountManager) GetRoute(accountID, routeID, userID string) (*r
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !user.IsAdmin() {
|
if !user.HasAdminPower() {
|
||||||
return nil, status.Errorf(status.PermissionDenied, "Only administrators can view Network Routes")
|
return nil, status.Errorf(status.PermissionDenied, "only users with admin power can view Network Routes")
|
||||||
}
|
}
|
||||||
|
|
||||||
wantedRoute, found := account.Routes[routeID]
|
wantedRoute, found := account.Routes[routeID]
|
||||||
@ -296,8 +296,8 @@ func (am *DefaultAccountManager) ListRoutes(accountID, userID string) ([]*route.
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !user.IsAdmin() {
|
if !user.HasAdminPower() {
|
||||||
return nil, status.Errorf(status.PermissionDenied, "Only administrators can view Network Routes")
|
return nil, status.Errorf(status.PermissionDenied, "only users with admin power can view Network Routes")
|
||||||
}
|
}
|
||||||
|
|
||||||
routes := make([]*route.Route, 0, len(account.Routes))
|
routes := make([]*route.Route, 0, len(account.Routes))
|
||||||
|
@ -342,7 +342,7 @@ func (am *DefaultAccountManager) ListSetupKeys(accountID, userID string) ([]*Set
|
|||||||
keys := make([]*SetupKey, 0, len(account.SetupKeys))
|
keys := make([]*SetupKey, 0, len(account.SetupKeys))
|
||||||
for _, key := range account.SetupKeys {
|
for _, key := range account.SetupKeys {
|
||||||
var k *SetupKey
|
var k *SetupKey
|
||||||
if !user.IsAdmin() {
|
if !user.HasAdminPower() {
|
||||||
k = key.HiddenCopy(999)
|
k = key.HiddenCopy(999)
|
||||||
} else {
|
} else {
|
||||||
k = key.Copy()
|
k = key.Copy()
|
||||||
@ -384,7 +384,7 @@ func (am *DefaultAccountManager) GetSetupKey(accountID, userID, keyID string) (*
|
|||||||
foundKey.UpdatedAt = foundKey.CreatedAt
|
foundKey.UpdatedAt = foundKey.CreatedAt
|
||||||
}
|
}
|
||||||
|
|
||||||
if !user.IsAdmin() {
|
if !user.HasAdminPower() {
|
||||||
foundKey = foundKey.HiddenCopy(999)
|
foundKey = foundKey.HiddenCopy(999)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
UserRoleOwner UserRole = "owner"
|
||||||
UserRoleAdmin UserRole = "admin"
|
UserRoleAdmin UserRole = "admin"
|
||||||
UserRoleUser UserRole = "user"
|
UserRoleUser UserRole = "user"
|
||||||
UserRoleUnknown UserRole = "unknown"
|
UserRoleUnknown UserRole = "unknown"
|
||||||
@ -31,6 +32,8 @@ const (
|
|||||||
// StrRoleToUserRole returns UserRole for a given strRole or UserRoleUnknown if the specified role is unknown
|
// StrRoleToUserRole returns UserRole for a given strRole or UserRoleUnknown if the specified role is unknown
|
||||||
func StrRoleToUserRole(strRole string) UserRole {
|
func StrRoleToUserRole(strRole string) UserRole {
|
||||||
switch strings.ToLower(strRole) {
|
switch strings.ToLower(strRole) {
|
||||||
|
case "owner":
|
||||||
|
return UserRoleOwner
|
||||||
case "admin":
|
case "admin":
|
||||||
return UserRoleAdmin
|
return UserRoleAdmin
|
||||||
case "user":
|
case "user":
|
||||||
@ -98,9 +101,9 @@ func (u *User) LastDashboardLoginChanged(LastLogin time.Time) bool {
|
|||||||
return LastLogin.After(u.LastLogin) && !u.LastLogin.IsZero()
|
return LastLogin.After(u.LastLogin) && !u.LastLogin.IsZero()
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsAdmin returns true if the user is an admin, false otherwise
|
// HasAdminPower returns true if the user has admin or owner roles, false otherwise
|
||||||
func (u *User) IsAdmin() bool {
|
func (u *User) HasAdminPower() bool {
|
||||||
return u.Role == UserRoleAdmin
|
return u.Role == UserRoleAdmin || u.Role == UserRoleOwner
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToUserInfo converts a User object to a UserInfo object.
|
// ToUserInfo converts a User object to a UserInfo object.
|
||||||
@ -194,6 +197,11 @@ func NewAdminUser(id string) *User {
|
|||||||
return NewUser(id, UserRoleAdmin, false, false, "", []string{}, UserIssuedAPI)
|
return NewUser(id, UserRoleAdmin, false, false, "", []string{}, UserIssuedAPI)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewOwnerUser creates a new user with role UserRoleOwner
|
||||||
|
func NewOwnerUser(id string) *User {
|
||||||
|
return NewUser(id, UserRoleOwner, false, false, "", []string{}, UserIssuedAPI)
|
||||||
|
}
|
||||||
|
|
||||||
// createServiceUser creates a new service user under the given account.
|
// createServiceUser creates a new service user under the given account.
|
||||||
func (am *DefaultAccountManager) createServiceUser(accountID string, initiatorUserID string, role UserRole, serviceUserName string, nonDeletable bool, autoGroups []string) (*UserInfo, error) {
|
func (am *DefaultAccountManager) createServiceUser(accountID string, initiatorUserID string, role UserRole, serviceUserName string, nonDeletable bool, autoGroups []string) (*UserInfo, error) {
|
||||||
unlock := am.Store.AcquireAccountLock(accountID)
|
unlock := am.Store.AcquireAccountLock(accountID)
|
||||||
@ -208,8 +216,12 @@ func (am *DefaultAccountManager) createServiceUser(accountID string, initiatorUs
|
|||||||
if executingUser == nil {
|
if executingUser == nil {
|
||||||
return nil, status.Errorf(status.NotFound, "user not found")
|
return nil, status.Errorf(status.NotFound, "user not found")
|
||||||
}
|
}
|
||||||
if executingUser.Role != UserRoleAdmin {
|
if !executingUser.HasAdminPower() {
|
||||||
return nil, status.Errorf(status.PermissionDenied, "only admins can create service users")
|
return nil, status.Errorf(status.PermissionDenied, "only users with admin power can create service users")
|
||||||
|
}
|
||||||
|
|
||||||
|
if role == UserRoleOwner {
|
||||||
|
return nil, status.Errorf(status.InvalidArgument, "can't create a service user with owner role")
|
||||||
}
|
}
|
||||||
|
|
||||||
newUserID := uuid.New().String()
|
newUserID := uuid.New().String()
|
||||||
@ -259,11 +271,15 @@ func (am *DefaultAccountManager) inviteNewUser(accountID, userID string, invite
|
|||||||
return nil, fmt.Errorf("provided user update is nil")
|
return nil, fmt.Errorf("provided user update is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
invitedRole := StrRoleToUserRole(invite.Role)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case invite.Name == "":
|
case invite.Name == "":
|
||||||
return nil, status.Errorf(status.InvalidArgument, "name can't be empty")
|
return nil, status.Errorf(status.InvalidArgument, "name can't be empty")
|
||||||
case invite.Email == "":
|
case invite.Email == "":
|
||||||
return nil, status.Errorf(status.InvalidArgument, "email can't be empty")
|
return nil, status.Errorf(status.InvalidArgument, "email can't be empty")
|
||||||
|
case invitedRole == UserRoleOwner:
|
||||||
|
return nil, status.Errorf(status.InvalidArgument, "can't invite a user with owner role")
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,10 +328,9 @@ func (am *DefaultAccountManager) inviteNewUser(accountID, userID string, invite
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
role := StrRoleToUserRole(invite.Role)
|
|
||||||
newUser := &User{
|
newUser := &User{
|
||||||
Id: idpUser.ID,
|
Id: idpUser.ID,
|
||||||
Role: role,
|
Role: invitedRole,
|
||||||
AutoGroups: invite.AutoGroups,
|
AutoGroups: invite.AutoGroups,
|
||||||
Issued: invite.Issued,
|
Issued: invite.Issued,
|
||||||
IntegrationReference: invite.IntegrationReference,
|
IntegrationReference: invite.IntegrationReference,
|
||||||
@ -417,8 +432,8 @@ func (am *DefaultAccountManager) DeleteUser(accountID, initiatorUserID string, t
|
|||||||
if executingUser == nil {
|
if executingUser == nil {
|
||||||
return status.Errorf(status.NotFound, "user not found")
|
return status.Errorf(status.NotFound, "user not found")
|
||||||
}
|
}
|
||||||
if executingUser.Role != UserRoleAdmin {
|
if !executingUser.HasAdminPower() {
|
||||||
return status.Errorf(status.PermissionDenied, "only admins can delete users")
|
return status.Errorf(status.PermissionDenied, "only users with admin power can delete users")
|
||||||
}
|
}
|
||||||
|
|
||||||
targetUser := account.Users[targetUserID]
|
targetUser := account.Users[targetUserID]
|
||||||
@ -426,9 +441,13 @@ func (am *DefaultAccountManager) DeleteUser(accountID, initiatorUserID string, t
|
|||||||
return status.Errorf(status.NotFound, "target user not found")
|
return status.Errorf(status.NotFound, "target user not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if targetUser.Role == UserRoleOwner {
|
||||||
|
return status.Errorf(status.PermissionDenied, "unable to delete a user with owner role")
|
||||||
|
}
|
||||||
|
|
||||||
// disable deleting integration user if the initiator is not admin service user
|
// disable deleting integration user if the initiator is not admin service user
|
||||||
if targetUser.Issued == UserIssuedIntegration && !executingUser.IsServiceUser {
|
if targetUser.Issued == UserIssuedIntegration && !executingUser.IsServiceUser {
|
||||||
return status.Errorf(status.PermissionDenied, "only admin service user can delete this user")
|
return status.Errorf(status.PermissionDenied, "only integration service user can delete this user")
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle service user first and exit, no need to fetch extra data from IDP, etc
|
// handle service user first and exit, no need to fetch extra data from IDP, etc
|
||||||
@ -567,7 +586,7 @@ func (am *DefaultAccountManager) CreatePAT(accountID string, initiatorUserID str
|
|||||||
return nil, status.Errorf(status.NotFound, "user not found")
|
return nil, status.Errorf(status.NotFound, "user not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !(initiatorUserID == targetUserID || (executingUser.IsAdmin() && targetUser.IsServiceUser)) {
|
if !(initiatorUserID == targetUserID || (executingUser.HasAdminPower() && targetUser.IsServiceUser)) {
|
||||||
return nil, status.Errorf(status.PermissionDenied, "no permission to create PAT for this user")
|
return nil, status.Errorf(status.PermissionDenied, "no permission to create PAT for this user")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -609,7 +628,7 @@ func (am *DefaultAccountManager) DeletePAT(accountID string, initiatorUserID str
|
|||||||
return status.Errorf(status.NotFound, "user not found")
|
return status.Errorf(status.NotFound, "user not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !(initiatorUserID == targetUserID || (executingUser.IsAdmin() && targetUser.IsServiceUser)) {
|
if !(initiatorUserID == targetUserID || (executingUser.HasAdminPower() && targetUser.IsServiceUser)) {
|
||||||
return status.Errorf(status.PermissionDenied, "no permission to delete PAT for this user")
|
return status.Errorf(status.PermissionDenied, "no permission to delete PAT for this user")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -659,7 +678,7 @@ func (am *DefaultAccountManager) GetPAT(accountID string, initiatorUserID string
|
|||||||
return nil, status.Errorf(status.NotFound, "user not found")
|
return nil, status.Errorf(status.NotFound, "user not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !(initiatorUserID == targetUserID || (executingUser.IsAdmin() && targetUser.IsServiceUser)) {
|
if !(initiatorUserID == targetUserID || (executingUser.HasAdminPower() && targetUser.IsServiceUser)) {
|
||||||
return nil, status.Errorf(status.PermissionDenied, "no permission to get PAT for this userser")
|
return nil, status.Errorf(status.PermissionDenied, "no permission to get PAT for this userser")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -691,7 +710,7 @@ func (am *DefaultAccountManager) GetAllPATs(accountID string, initiatorUserID st
|
|||||||
return nil, status.Errorf(status.NotFound, "user not found")
|
return nil, status.Errorf(status.NotFound, "user not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !(initiatorUserID == targetUserID || (executingUser.IsAdmin() && targetUser.IsServiceUser)) {
|
if !(initiatorUserID == targetUserID || (executingUser.HasAdminPower() && targetUser.IsServiceUser)) {
|
||||||
return nil, status.Errorf(status.PermissionDenied, "no permission to get PAT for this user")
|
return nil, status.Errorf(status.PermissionDenied, "no permission to get PAT for this user")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -728,8 +747,8 @@ func (am *DefaultAccountManager) SaveOrAddUser(accountID, initiatorUserID string
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !initiatorUser.IsAdmin() || initiatorUser.IsBlocked() {
|
if !initiatorUser.HasAdminPower() || initiatorUser.IsBlocked() {
|
||||||
return nil, status.Errorf(status.PermissionDenied, "only admins are authorized to perform user update operations")
|
return nil, status.Errorf(status.PermissionDenied, "only users with admin power are authorized to perform user update operations")
|
||||||
}
|
}
|
||||||
|
|
||||||
oldUser := account.Users[update.Id]
|
oldUser := account.Users[update.Id]
|
||||||
@ -741,14 +760,38 @@ func (am *DefaultAccountManager) SaveOrAddUser(accountID, initiatorUserID string
|
|||||||
oldUser = update
|
oldUser = update
|
||||||
}
|
}
|
||||||
|
|
||||||
if initiatorUser.IsAdmin() && initiatorUserID == update.Id && oldUser.Blocked != update.Blocked {
|
if initiatorUser.HasAdminPower() && initiatorUserID == update.Id && oldUser.Blocked != update.Blocked {
|
||||||
return nil, status.Errorf(status.PermissionDenied, "admins can't block or unblock themselves")
|
return nil, status.Errorf(status.PermissionDenied, "admins can't block or unblock themselves")
|
||||||
}
|
}
|
||||||
|
|
||||||
if initiatorUser.IsAdmin() && initiatorUserID == update.Id && update.Role != UserRoleAdmin {
|
if initiatorUser.HasAdminPower() && initiatorUserID == update.Id && update.Role != initiatorUser.Role {
|
||||||
return nil, status.Errorf(status.PermissionDenied, "admins can't change their role")
|
return nil, status.Errorf(status.PermissionDenied, "admins can't change their role")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if initiatorUser.Role == UserRoleAdmin && oldUser.Role == UserRoleOwner && update.Role != oldUser.Role {
|
||||||
|
return nil, status.Errorf(status.PermissionDenied, "only owners can remove owner role from their user")
|
||||||
|
}
|
||||||
|
|
||||||
|
if initiatorUser.Role == UserRoleAdmin && oldUser.Role == UserRoleOwner && update.IsBlocked() && !oldUser.IsBlocked() {
|
||||||
|
return nil, status.Errorf(status.PermissionDenied, "unable to block owner user")
|
||||||
|
}
|
||||||
|
|
||||||
|
if initiatorUser.Role == UserRoleAdmin && update.Role == UserRoleOwner && update.Role != oldUser.Role {
|
||||||
|
return nil, status.Errorf(status.PermissionDenied, "only owners can add owner role to other users")
|
||||||
|
}
|
||||||
|
|
||||||
|
if oldUser.IsServiceUser && update.Role == UserRoleOwner {
|
||||||
|
return nil, status.Errorf(status.PermissionDenied, "can't update a service user with owner role")
|
||||||
|
}
|
||||||
|
|
||||||
|
transferedOwnerRole := false
|
||||||
|
if initiatorUser.Role == UserRoleOwner && initiatorUserID != update.Id && update.Role == UserRoleOwner {
|
||||||
|
newInitiatorUser := initiatorUser.Copy()
|
||||||
|
newInitiatorUser.Role = UserRoleAdmin
|
||||||
|
account.Users[initiatorUserID] = newInitiatorUser
|
||||||
|
transferedOwnerRole = true
|
||||||
|
}
|
||||||
|
|
||||||
// only auto groups, revoked status, and integration reference can be updated for now
|
// only auto groups, revoked status, and integration reference can be updated for now
|
||||||
newUser := oldUser.Copy()
|
newUser := oldUser.Copy()
|
||||||
newUser.Role = update.Role
|
newUser.Role = update.Role
|
||||||
@ -807,9 +850,12 @@ func (am *DefaultAccountManager) SaveOrAddUser(accountID, initiatorUserID string
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// store activity logs
|
switch {
|
||||||
if oldUser.Role != newUser.Role {
|
case transferedOwnerRole:
|
||||||
|
am.StoreEvent(initiatorUserID, oldUser.Id, accountID, activity.TransferredOwnerRole, nil)
|
||||||
|
case oldUser.Role != newUser.Role:
|
||||||
am.StoreEvent(initiatorUserID, oldUser.Id, accountID, activity.UserRoleUpdated, map[string]any{"role": newUser.Role})
|
am.StoreEvent(initiatorUserID, oldUser.Id, accountID, activity.UserRoleUpdated, map[string]any{"role": newUser.Role})
|
||||||
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
if update.AutoGroups != nil {
|
if update.AutoGroups != nil {
|
||||||
@ -883,7 +929,7 @@ func (am *DefaultAccountManager) GetOrCreateAccountByUser(userID, domain string)
|
|||||||
|
|
||||||
userObj := account.Users[userID]
|
userObj := account.Users[userID]
|
||||||
|
|
||||||
if account.Domain != lowerDomain && userObj.Role == UserRoleAdmin {
|
if account.Domain != lowerDomain && userObj.Role == UserRoleOwner {
|
||||||
account.Domain = lowerDomain
|
account.Domain = lowerDomain
|
||||||
err = am.Store.SaveAccount(account)
|
err = am.Store.SaveAccount(account)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -941,7 +987,7 @@ func (am *DefaultAccountManager) GetUsersFromAccount(accountID, userID string) (
|
|||||||
// in case of self-hosted, or IDP doesn't return anything, we will return the locally stored userInfo
|
// in case of self-hosted, or IDP doesn't return anything, we will return the locally stored userInfo
|
||||||
if len(queriedUsers) == 0 {
|
if len(queriedUsers) == 0 {
|
||||||
for _, accountUser := range account.Users {
|
for _, accountUser := range account.Users {
|
||||||
if !user.IsAdmin() && user.Id != accountUser.Id {
|
if !user.HasAdminPower() && user.Id != accountUser.Id {
|
||||||
// if user is not an admin then show only current user and do not show other users
|
// if user is not an admin then show only current user and do not show other users
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -955,7 +1001,7 @@ func (am *DefaultAccountManager) GetUsersFromAccount(accountID, userID string) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, localUser := range account.Users {
|
for _, localUser := range account.Users {
|
||||||
if !user.IsAdmin() && user.Id != localUser.Id {
|
if !user.HasAdminPower() && user.Id != localUser.Id {
|
||||||
// if user is not an admin then show only current user and do not show other users
|
// if user is not an admin then show only current user and do not show other users
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -348,6 +348,11 @@ func TestUser_CreateServiceUser(t *testing.T) {
|
|||||||
assert.Zero(t, user.Email)
|
assert.Zero(t, user.Email)
|
||||||
assert.True(t, user.IsServiceUser)
|
assert.True(t, user.IsServiceUser)
|
||||||
assert.Equal(t, "active", user.Status)
|
assert.Equal(t, "active", user.Status)
|
||||||
|
|
||||||
|
_, err = am.createServiceUser(mockAccountID, mockUserID, UserRoleOwner, mockServiceUserName, false, nil)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("should return error when creating service user with owner role")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUser_CreateUser_ServiceUser(t *testing.T) {
|
func TestUser_CreateUser_ServiceUser(t *testing.T) {
|
||||||
@ -412,6 +417,75 @@ func TestUser_CreateUser_RegularUser(t *testing.T) {
|
|||||||
assert.Errorf(t, err, "Not configured IDP will throw error but right path used")
|
assert.Errorf(t, err, "Not configured IDP will throw error but right path used")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUser_InviteNewUser(t *testing.T) {
|
||||||
|
store := newStore(t)
|
||||||
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
||||||
|
|
||||||
|
err := store.SaveAccount(account)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error when saving account: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
am := DefaultAccountManager{
|
||||||
|
Store: store,
|
||||||
|
eventStore: &activity.InMemoryEventStore{},
|
||||||
|
cacheLoading: map[string]chan struct{}{},
|
||||||
|
}
|
||||||
|
|
||||||
|
goCacheClient := gocache.New(CacheExpirationMax, 30*time.Minute)
|
||||||
|
goCacheStore := cacheStore.NewGoCache(goCacheClient)
|
||||||
|
am.cacheManager = cache.NewLoadable[[]*idp.UserData](am.loadAccount, cache.New[[]*idp.UserData](goCacheStore))
|
||||||
|
|
||||||
|
mockData := []*idp.UserData{
|
||||||
|
{
|
||||||
|
Email: "user@test.com",
|
||||||
|
Name: "user",
|
||||||
|
ID: mockUserID,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
idpMock := idp.MockIDP{
|
||||||
|
CreateUserFunc: func(email, name, accountID, invitedByEmail string) (*idp.UserData, error) {
|
||||||
|
newData := &idp.UserData{
|
||||||
|
Email: email,
|
||||||
|
Name: name,
|
||||||
|
ID: "id",
|
||||||
|
}
|
||||||
|
|
||||||
|
mockData = append(mockData, newData)
|
||||||
|
|
||||||
|
return newData, nil
|
||||||
|
},
|
||||||
|
GetAccountFunc: func(accountId string) ([]*idp.UserData, error) {
|
||||||
|
return mockData, nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
am.idpManager = &idpMock
|
||||||
|
|
||||||
|
// test if new invite with regular role works
|
||||||
|
_, err = am.inviteNewUser(mockAccountID, mockUserID, &UserInfo{
|
||||||
|
Name: mockServiceUserName,
|
||||||
|
Role: mockRole,
|
||||||
|
Email: "test@teste.com",
|
||||||
|
IsServiceUser: false,
|
||||||
|
AutoGroups: []string{"group1", "group2"},
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.NoErrorf(t, err, "Invite user should not throw error")
|
||||||
|
|
||||||
|
// test if new invite with owner role fails
|
||||||
|
_, err = am.inviteNewUser(mockAccountID, mockUserID, &UserInfo{
|
||||||
|
Name: mockServiceUserName,
|
||||||
|
Role: string(UserRoleOwner),
|
||||||
|
Email: "test2@teste.com",
|
||||||
|
IsServiceUser: false,
|
||||||
|
AutoGroups: []string{"group1", "group2"},
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Errorf(t, err, "Invite user with owner role should throw error")
|
||||||
|
}
|
||||||
|
|
||||||
func TestUser_DeleteUser_ServiceUser(t *testing.T) {
|
func TestUser_DeleteUser_ServiceUser(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@ -514,6 +588,14 @@ func TestUser_DeleteUser_regularUser(t *testing.T) {
|
|||||||
Issued: UserIssuedIntegration,
|
Issued: UserIssuedIntegration,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
targetId = "user5"
|
||||||
|
account.Users[targetId] = &User{
|
||||||
|
Id: targetId,
|
||||||
|
IsServiceUser: false,
|
||||||
|
Issued: UserIssuedAPI,
|
||||||
|
Role: UserRoleOwner,
|
||||||
|
}
|
||||||
|
|
||||||
err := store.SaveAccount(account)
|
err := store.SaveAccount(account)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error when saving account: %s", err)
|
t.Fatalf("Error when saving account: %s", err)
|
||||||
@ -546,6 +628,12 @@ func TestUser_DeleteUser_regularUser(t *testing.T) {
|
|||||||
assertErrFunc: assert.Error,
|
assertErrFunc: assert.Error,
|
||||||
assertErrMessage: "only admin service user can delete this user",
|
assertErrMessage: "only admin service user can delete this user",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Delete user with owner role should return permission denied ",
|
||||||
|
userID: "user5",
|
||||||
|
assertErrFunc: assert.Error,
|
||||||
|
assertErrMessage: "unable to delete a user with owner role",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
@ -581,7 +669,7 @@ func TestDefaultAccountManager_GetUser(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, mockUserID, user.Id)
|
assert.Equal(t, mockUserID, user.Id)
|
||||||
assert.True(t, user.IsAdmin())
|
assert.True(t, user.HasAdminPower())
|
||||||
assert.False(t, user.IsBlocked())
|
assert.False(t, user.IsBlocked())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -609,7 +697,7 @@ func TestDefaultAccountManager_ListUsers(t *testing.T) {
|
|||||||
admins := 0
|
admins := 0
|
||||||
regular := 0
|
regular := 0
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
if user.IsAdmin() {
|
if user.HasAdminPower() {
|
||||||
admins++
|
admins++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -677,10 +765,10 @@ func TestDefaultAccountManager_ExternalCache(t *testing.T) {
|
|||||||
func TestUser_IsAdmin(t *testing.T) {
|
func TestUser_IsAdmin(t *testing.T) {
|
||||||
|
|
||||||
user := NewAdminUser(mockUserID)
|
user := NewAdminUser(mockUserID)
|
||||||
assert.True(t, user.IsAdmin())
|
assert.True(t, user.HasAdminPower())
|
||||||
|
|
||||||
user = NewRegularUser(mockUserID)
|
user = NewRegularUser(mockUserID)
|
||||||
assert.False(t, user.IsAdmin())
|
assert.False(t, user.HasAdminPower())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUser_GetUsersFromAccount_ForAdmin(t *testing.T) {
|
func TestUser_GetUsersFromAccount_ForAdmin(t *testing.T) {
|
||||||
@ -746,28 +834,31 @@ func TestDefaultAccountManager_SaveUser(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
regularUserID := "regularUser"
|
regularUserID := "regularUser"
|
||||||
|
serviceUserID := "serviceUser"
|
||||||
|
adminUserID := "adminUser"
|
||||||
|
ownerUserID := "ownerUser"
|
||||||
|
|
||||||
tt := []struct {
|
tt := []struct {
|
||||||
name string
|
name string
|
||||||
adminInitiator bool
|
initiatorID string
|
||||||
update *User
|
update *User
|
||||||
expectedErr bool
|
expectedErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Should_Fail_To_Update_Admin_Role",
|
name: "Should_Fail_To_Update_Admin_Role",
|
||||||
expectedErr: true,
|
expectedErr: true,
|
||||||
adminInitiator: true,
|
initiatorID: adminUserID,
|
||||||
update: &User{
|
update: &User{
|
||||||
Id: userID,
|
Id: adminUserID,
|
||||||
Role: UserRoleUser,
|
Role: UserRoleUser,
|
||||||
Blocked: false,
|
Blocked: false,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "Should_Fail_When_Admin_Blocks_Themselves",
|
name: "Should_Fail_When_Admin_Blocks_Themselves",
|
||||||
expectedErr: true,
|
expectedErr: true,
|
||||||
adminInitiator: true,
|
initiatorID: adminUserID,
|
||||||
update: &User{
|
update: &User{
|
||||||
Id: userID,
|
Id: adminUserID,
|
||||||
Role: UserRoleAdmin,
|
Role: UserRoleAdmin,
|
||||||
Blocked: true,
|
Blocked: true,
|
||||||
},
|
},
|
||||||
@ -775,7 +866,7 @@ func TestDefaultAccountManager_SaveUser(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "Should_Fail_To_Update_Non_Existing_User",
|
name: "Should_Fail_To_Update_Non_Existing_User",
|
||||||
expectedErr: true,
|
expectedErr: true,
|
||||||
adminInitiator: true,
|
initiatorID: adminUserID,
|
||||||
update: &User{
|
update: &User{
|
||||||
Id: userID,
|
Id: userID,
|
||||||
Role: UserRoleAdmin,
|
Role: UserRoleAdmin,
|
||||||
@ -785,9 +876,9 @@ func TestDefaultAccountManager_SaveUser(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "Should_Fail_To_Update_When_Initiator_Is_Not_An_Admin",
|
name: "Should_Fail_To_Update_When_Initiator_Is_Not_An_Admin",
|
||||||
expectedErr: true,
|
expectedErr: true,
|
||||||
adminInitiator: false,
|
initiatorID: regularUserID,
|
||||||
update: &User{
|
update: &User{
|
||||||
Id: userID,
|
Id: adminUserID,
|
||||||
Role: UserRoleAdmin,
|
Role: UserRoleAdmin,
|
||||||
Blocked: true,
|
Blocked: true,
|
||||||
},
|
},
|
||||||
@ -795,36 +886,104 @@ func TestDefaultAccountManager_SaveUser(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "Should_Update_User",
|
name: "Should_Update_User",
|
||||||
expectedErr: false,
|
expectedErr: false,
|
||||||
adminInitiator: true,
|
initiatorID: adminUserID,
|
||||||
update: &User{
|
update: &User{
|
||||||
Id: regularUserID,
|
Id: regularUserID,
|
||||||
Role: UserRoleAdmin,
|
Role: UserRoleAdmin,
|
||||||
Blocked: true,
|
Blocked: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Should_Transfer_Owner_Role_To_User",
|
||||||
|
expectedErr: false,
|
||||||
|
initiatorID: ownerUserID,
|
||||||
|
update: &User{
|
||||||
|
Id: adminUserID,
|
||||||
|
Role: UserRoleAdmin,
|
||||||
|
Blocked: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Should_Fail_To_Transfer_Owner_Role_To_Service_User",
|
||||||
|
expectedErr: true,
|
||||||
|
initiatorID: ownerUserID,
|
||||||
|
update: &User{
|
||||||
|
Id: serviceUserID,
|
||||||
|
Role: UserRoleOwner,
|
||||||
|
Blocked: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Should_Fail_To_Update_Owner_User_Role_By_Admin",
|
||||||
|
expectedErr: true,
|
||||||
|
initiatorID: adminUserID,
|
||||||
|
update: &User{
|
||||||
|
Id: ownerUserID,
|
||||||
|
Role: UserRoleAdmin,
|
||||||
|
Blocked: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Should_Fail_To_Update_Owner_User_Role_By_User",
|
||||||
|
expectedErr: true,
|
||||||
|
initiatorID: regularUserID,
|
||||||
|
update: &User{
|
||||||
|
Id: ownerUserID,
|
||||||
|
Role: UserRoleAdmin,
|
||||||
|
Blocked: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Should_Fail_To_Update_Owner_User_Role_By_Service_User",
|
||||||
|
expectedErr: true,
|
||||||
|
initiatorID: serviceUserID,
|
||||||
|
update: &User{
|
||||||
|
Id: ownerUserID,
|
||||||
|
Role: UserRoleAdmin,
|
||||||
|
Blocked: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Should_Fail_To_Update_Owner_Role_By_Admin",
|
||||||
|
expectedErr: true,
|
||||||
|
initiatorID: adminUserID,
|
||||||
|
update: &User{
|
||||||
|
Id: regularUserID,
|
||||||
|
Role: UserRoleOwner,
|
||||||
|
Blocked: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Should_Fail_To_Block_Owner_Role_By_Admin",
|
||||||
|
expectedErr: true,
|
||||||
|
initiatorID: adminUserID,
|
||||||
|
update: &User{
|
||||||
|
Id: ownerUserID,
|
||||||
|
Role: UserRoleOwner,
|
||||||
|
Blocked: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tt {
|
for _, tc := range tt {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
|
||||||
// create an account and an admin user
|
// create an account and an admin user
|
||||||
account, err := manager.GetOrCreateAccountByUser(userID, "netbird.io")
|
account, err := manager.GetOrCreateAccountByUser(ownerUserID, "netbird.io")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a regular user
|
// create other users
|
||||||
account.Users[regularUserID] = NewRegularUser(regularUserID)
|
account.Users[regularUserID] = NewRegularUser(regularUserID)
|
||||||
|
account.Users[adminUserID] = NewAdminUser(adminUserID)
|
||||||
|
account.Users[serviceUserID] = &User{IsServiceUser: true, Id: serviceUserID, Role: UserRoleAdmin, ServiceUserName: "service"}
|
||||||
err = manager.Store.SaveAccount(account)
|
err = manager.Store.SaveAccount(account)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
initiatorID := userID
|
updated, err := manager.SaveUser(account.Id, tc.initiatorID, tc.update)
|
||||||
if !tc.adminInitiator {
|
|
||||||
initiatorID = regularUserID
|
|
||||||
}
|
|
||||||
|
|
||||||
updated, err := manager.SaveUser(account.Id, initiatorID, tc.update)
|
|
||||||
if tc.expectedErr {
|
if tc.expectedErr {
|
||||||
require.Errorf(t, err, "expecting SaveUser to throw an error")
|
require.Errorf(t, err, "expecting SaveUser to throw an error")
|
||||||
} else {
|
} else {
|
||||||
@ -834,5 +993,6 @@ func TestDefaultAccountManager_SaveUser(t *testing.T) {
|
|||||||
assert.Equal(t, string(tc.update.Role), updated.Role)
|
assert.Equal(t, string(tc.update.Role), updated.Role)
|
||||||
assert.Equal(t, tc.update.IsBlocked(), updated.IsBlocked)
|
assert.Equal(t, tc.update.IsBlocked(), updated.IsBlocked)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user