mirror of
https://github.com/netbirdio/netbird.git
synced 2024-12-24 15:48:52 +01:00
c38d65ef4c
* extends user and group structure by introducing fields for issued and integration references * Add integration checks to group management to prevent groups added by integration. * Add integration checks to user management to prevent deleting user added by integration. * Fix broken user update tests * Initialize all user fields for testing * Change a serializer option to embedded for IntegrationReference in user and group models * Add issued field to user api response * Add IntegrationReference to Group in update groups handler * Set the default issued field for users in file store
715 lines
18 KiB
Go
715 lines
18 KiB
Go
package server
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/netbirdio/netbird/management/server/activity"
|
|
"github.com/netbirdio/netbird/management/server/jwtclaims"
|
|
)
|
|
|
|
const (
|
|
mockAccountID = "accountID"
|
|
mockUserID = "userID"
|
|
mockServiceUserID = "serviceUserID"
|
|
mockRole = "user"
|
|
mockServiceUserName = "serviceUserName"
|
|
mockTargetUserId = "targetUserID"
|
|
mockTokenID1 = "tokenID1"
|
|
mockToken1 = "SoMeHaShEdToKeN1"
|
|
mockTokenID2 = "tokenID2"
|
|
mockToken2 = "SoMeHaShEdToKeN2"
|
|
mockTokenName = "tokenName"
|
|
mockEmptyTokenName = ""
|
|
mockExpiresIn = 7
|
|
mockWrongExpiresIn = 4506
|
|
)
|
|
|
|
func TestUser_CreatePAT_ForSameUser(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{},
|
|
}
|
|
|
|
pat, err := am.CreatePAT(mockAccountID, mockUserID, mockUserID, mockTokenName, mockExpiresIn)
|
|
if err != nil {
|
|
t.Fatalf("Error when adding PAT to user: %s", err)
|
|
}
|
|
|
|
assert.Equal(t, pat.CreatedBy, mockUserID)
|
|
|
|
fileStore := am.Store.(*FileStore)
|
|
tokenID := fileStore.HashedPAT2TokenID[pat.HashedToken]
|
|
|
|
if tokenID == "" {
|
|
t.Fatal("GetTokenIDByHashedToken failed after adding PAT")
|
|
}
|
|
|
|
assert.Equal(t, pat.ID, tokenID)
|
|
|
|
userID := fileStore.TokenID2UserID[tokenID]
|
|
if userID == "" {
|
|
t.Fatal("GetUserByTokenId failed after adding PAT")
|
|
}
|
|
assert.Equal(t, mockUserID, userID)
|
|
}
|
|
|
|
func TestUser_CreatePAT_ForDifferentUser(t *testing.T) {
|
|
store := newStore(t)
|
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
|
account.Users[mockTargetUserId] = &User{
|
|
Id: mockTargetUserId,
|
|
IsServiceUser: false,
|
|
}
|
|
err := store.SaveAccount(account)
|
|
if err != nil {
|
|
t.Fatalf("Error when saving account: %s", err)
|
|
}
|
|
|
|
am := DefaultAccountManager{
|
|
Store: store,
|
|
eventStore: &activity.InMemoryEventStore{},
|
|
}
|
|
|
|
_, err = am.CreatePAT(mockAccountID, mockUserID, mockTargetUserId, mockTokenName, mockExpiresIn)
|
|
assert.Errorf(t, err, "Creating PAT for different user should thorw error")
|
|
}
|
|
|
|
func TestUser_CreatePAT_ForServiceUser(t *testing.T) {
|
|
store := newStore(t)
|
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
|
account.Users[mockTargetUserId] = &User{
|
|
Id: mockTargetUserId,
|
|
IsServiceUser: true,
|
|
}
|
|
err := store.SaveAccount(account)
|
|
if err != nil {
|
|
t.Fatalf("Error when saving account: %s", err)
|
|
}
|
|
|
|
am := DefaultAccountManager{
|
|
Store: store,
|
|
eventStore: &activity.InMemoryEventStore{},
|
|
}
|
|
|
|
pat, err := am.CreatePAT(mockAccountID, mockUserID, mockTargetUserId, mockTokenName, mockExpiresIn)
|
|
if err != nil {
|
|
t.Fatalf("Error when adding PAT to user: %s", err)
|
|
}
|
|
|
|
assert.Equal(t, pat.CreatedBy, mockUserID)
|
|
}
|
|
|
|
func TestUser_CreatePAT_WithWrongExpiration(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{},
|
|
}
|
|
|
|
_, err = am.CreatePAT(mockAccountID, mockUserID, mockUserID, mockTokenName, mockWrongExpiresIn)
|
|
assert.Errorf(t, err, "Wrong expiration should thorw error")
|
|
}
|
|
|
|
func TestUser_CreatePAT_WithEmptyName(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{},
|
|
}
|
|
|
|
_, err = am.CreatePAT(mockAccountID, mockUserID, mockUserID, mockEmptyTokenName, mockExpiresIn)
|
|
assert.Errorf(t, err, "Wrong expiration should thorw error")
|
|
}
|
|
|
|
func TestUser_DeletePAT(t *testing.T) {
|
|
store := newStore(t)
|
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
|
account.Users[mockUserID] = &User{
|
|
Id: mockUserID,
|
|
PATs: map[string]*PersonalAccessToken{
|
|
mockTokenID1: {
|
|
ID: mockTokenID1,
|
|
HashedToken: mockToken1,
|
|
},
|
|
},
|
|
}
|
|
err := store.SaveAccount(account)
|
|
if err != nil {
|
|
t.Fatalf("Error when saving account: %s", err)
|
|
}
|
|
|
|
am := DefaultAccountManager{
|
|
Store: store,
|
|
eventStore: &activity.InMemoryEventStore{},
|
|
}
|
|
|
|
err = am.DeletePAT(mockAccountID, mockUserID, mockUserID, mockTokenID1)
|
|
if err != nil {
|
|
t.Fatalf("Error when adding PAT to user: %s", err)
|
|
}
|
|
|
|
assert.Nil(t, store.Accounts[mockAccountID].Users[mockUserID].PATs[mockTokenID1])
|
|
assert.Empty(t, store.HashedPAT2TokenID[mockToken1])
|
|
assert.Empty(t, store.TokenID2UserID[mockTokenID1])
|
|
}
|
|
|
|
func TestUser_GetPAT(t *testing.T) {
|
|
store := newStore(t)
|
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
|
account.Users[mockUserID] = &User{
|
|
Id: mockUserID,
|
|
PATs: map[string]*PersonalAccessToken{
|
|
mockTokenID1: {
|
|
ID: mockTokenID1,
|
|
HashedToken: mockToken1,
|
|
},
|
|
},
|
|
}
|
|
err := store.SaveAccount(account)
|
|
if err != nil {
|
|
t.Fatalf("Error when saving account: %s", err)
|
|
}
|
|
|
|
am := DefaultAccountManager{
|
|
Store: store,
|
|
eventStore: &activity.InMemoryEventStore{},
|
|
}
|
|
|
|
pat, err := am.GetPAT(mockAccountID, mockUserID, mockUserID, mockTokenID1)
|
|
if err != nil {
|
|
t.Fatalf("Error when adding PAT to user: %s", err)
|
|
}
|
|
|
|
assert.Equal(t, mockTokenID1, pat.ID)
|
|
assert.Equal(t, mockToken1, pat.HashedToken)
|
|
}
|
|
|
|
func TestUser_GetAllPATs(t *testing.T) {
|
|
store := newStore(t)
|
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
|
account.Users[mockUserID] = &User{
|
|
Id: mockUserID,
|
|
PATs: map[string]*PersonalAccessToken{
|
|
mockTokenID1: {
|
|
ID: mockTokenID1,
|
|
HashedToken: mockToken1,
|
|
},
|
|
mockTokenID2: {
|
|
ID: mockTokenID2,
|
|
HashedToken: mockToken2,
|
|
},
|
|
},
|
|
}
|
|
err := store.SaveAccount(account)
|
|
if err != nil {
|
|
t.Fatalf("Error when saving account: %s", err)
|
|
}
|
|
|
|
am := DefaultAccountManager{
|
|
Store: store,
|
|
eventStore: &activity.InMemoryEventStore{},
|
|
}
|
|
|
|
pats, err := am.GetAllPATs(mockAccountID, mockUserID, mockUserID)
|
|
if err != nil {
|
|
t.Fatalf("Error when adding PAT to user: %s", err)
|
|
}
|
|
|
|
assert.Equal(t, 2, len(pats))
|
|
}
|
|
|
|
func TestUser_Copy(t *testing.T) {
|
|
// this is an imaginary case which will never be in DB this way
|
|
user := User{
|
|
Id: "userId",
|
|
AccountID: "accountId",
|
|
Role: "role",
|
|
IsServiceUser: true,
|
|
ServiceUserName: "servicename",
|
|
AutoGroups: []string{"group1", "group2"},
|
|
PATs: map[string]*PersonalAccessToken{
|
|
"pat1": {
|
|
ID: "pat1",
|
|
Name: "First PAT",
|
|
HashedToken: "SoMeHaShEdToKeN",
|
|
ExpirationDate: time.Now().AddDate(0, 0, 7),
|
|
CreatedBy: "userId",
|
|
CreatedAt: time.Now(),
|
|
LastUsed: time.Now(),
|
|
},
|
|
},
|
|
Blocked: false,
|
|
LastLogin: time.Now(),
|
|
Issued: "test",
|
|
IntegrationReference: IntegrationReference{
|
|
ID: 0,
|
|
IntegrationType: "test",
|
|
},
|
|
}
|
|
|
|
err := validateStruct(user)
|
|
if err != nil {
|
|
t.Fatalf("Test needs update: dummy struct has not all fields set : %s", err)
|
|
}
|
|
|
|
copiedUser := user.Copy()
|
|
|
|
assert.True(t, cmp.Equal(user, *copiedUser))
|
|
}
|
|
|
|
// based on https://medium.com/@anajankow/fast-check-if-all-struct-fields-are-set-in-golang-bba1917213d2
|
|
func validateStruct(s interface{}) (err error) {
|
|
|
|
structType := reflect.TypeOf(s)
|
|
structVal := reflect.ValueOf(s)
|
|
fieldNum := structVal.NumField()
|
|
|
|
for i := 0; i < fieldNum; i++ {
|
|
field := structVal.Field(i)
|
|
fieldName := structType.Field(i).Name
|
|
|
|
// skip gorm internal fields
|
|
if json, ok := structType.Field(i).Tag.Lookup("json"); ok && json == "-" {
|
|
continue
|
|
}
|
|
|
|
isSet := field.IsValid() && (!field.IsZero() || field.Type().String() == "bool")
|
|
|
|
if !isSet {
|
|
err = fmt.Errorf("%v%s in not set; ", err, fieldName)
|
|
}
|
|
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
func TestUser_CreateServiceUser(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{},
|
|
}
|
|
|
|
user, err := am.createServiceUser(mockAccountID, mockUserID, mockRole, mockServiceUserName, []string{"group1", "group2"})
|
|
if err != nil {
|
|
t.Fatalf("Error when creating service user: %s", err)
|
|
}
|
|
|
|
assert.Equal(t, 2, len(store.Accounts[mockAccountID].Users))
|
|
assert.NotNil(t, store.Accounts[mockAccountID].Users[user.ID])
|
|
assert.True(t, store.Accounts[mockAccountID].Users[user.ID].IsServiceUser)
|
|
assert.Equal(t, mockServiceUserName, store.Accounts[mockAccountID].Users[user.ID].ServiceUserName)
|
|
assert.Equal(t, UserRole(mockRole), store.Accounts[mockAccountID].Users[user.ID].Role)
|
|
assert.Equal(t, []string{"group1", "group2"}, store.Accounts[mockAccountID].Users[user.ID].AutoGroups)
|
|
assert.Equal(t, map[string]*PersonalAccessToken{}, store.Accounts[mockAccountID].Users[user.ID].PATs)
|
|
|
|
assert.Zero(t, user.Email)
|
|
assert.True(t, user.IsServiceUser)
|
|
assert.Equal(t, "active", user.Status)
|
|
}
|
|
|
|
func TestUser_CreateUser_ServiceUser(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{},
|
|
}
|
|
|
|
user, err := am.CreateUser(mockAccountID, mockUserID, &UserInfo{
|
|
Name: mockServiceUserName,
|
|
Role: mockRole,
|
|
IsServiceUser: true,
|
|
AutoGroups: []string{"group1", "group2"},
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatalf("Error when creating user: %s", err)
|
|
}
|
|
|
|
assert.True(t, user.IsServiceUser)
|
|
assert.Equal(t, 2, len(store.Accounts[mockAccountID].Users))
|
|
assert.True(t, store.Accounts[mockAccountID].Users[user.ID].IsServiceUser)
|
|
assert.Equal(t, mockServiceUserName, store.Accounts[mockAccountID].Users[user.ID].ServiceUserName)
|
|
assert.Equal(t, UserRole(mockRole), store.Accounts[mockAccountID].Users[user.ID].Role)
|
|
assert.Equal(t, []string{"group1", "group2"}, store.Accounts[mockAccountID].Users[user.ID].AutoGroups)
|
|
|
|
assert.Equal(t, mockServiceUserName, user.Name)
|
|
assert.Equal(t, mockRole, user.Role)
|
|
assert.Equal(t, []string{"group1", "group2"}, user.AutoGroups)
|
|
assert.Equal(t, "active", user.Status)
|
|
}
|
|
|
|
func TestUser_CreateUser_RegularUser(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{},
|
|
}
|
|
|
|
_, err = am.CreateUser(mockAccountID, mockUserID, &UserInfo{
|
|
Name: mockServiceUserName,
|
|
Role: mockRole,
|
|
IsServiceUser: false,
|
|
AutoGroups: []string{"group1", "group2"},
|
|
})
|
|
|
|
assert.Errorf(t, err, "Not configured IDP will throw error but right path used")
|
|
}
|
|
|
|
func TestUser_DeleteUser_ServiceUser(t *testing.T) {
|
|
store := newStore(t)
|
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
|
account.Users[mockServiceUserID] = &User{
|
|
Id: mockServiceUserID,
|
|
IsServiceUser: true,
|
|
ServiceUserName: mockServiceUserName,
|
|
}
|
|
|
|
err := store.SaveAccount(account)
|
|
if err != nil {
|
|
t.Fatalf("Error when saving account: %s", err)
|
|
}
|
|
|
|
am := DefaultAccountManager{
|
|
Store: store,
|
|
eventStore: &activity.InMemoryEventStore{},
|
|
}
|
|
|
|
err = am.DeleteUser(mockAccountID, mockUserID, mockServiceUserID)
|
|
if err != nil {
|
|
t.Fatalf("Error when deleting user: %s", err)
|
|
}
|
|
|
|
assert.Equal(t, 1, len(store.Accounts[mockAccountID].Users))
|
|
assert.Nil(t, store.Accounts[mockAccountID].Users[mockServiceUserID])
|
|
}
|
|
|
|
func TestUser_DeleteUser_SelfDelete(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{},
|
|
}
|
|
|
|
err = am.DeleteUser(mockAccountID, mockUserID, mockUserID)
|
|
if err == nil {
|
|
t.Fatalf("failed to prevent self deletion")
|
|
}
|
|
}
|
|
|
|
func TestUser_DeleteUser_regularUser(t *testing.T) {
|
|
store := newStore(t)
|
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
|
|
|
targetId := "user2"
|
|
account.Users[targetId] = &User{
|
|
Id: targetId,
|
|
IsServiceUser: true,
|
|
ServiceUserName: "user2username",
|
|
}
|
|
targetId = "user3"
|
|
account.Users[targetId] = &User{
|
|
Id: targetId,
|
|
IsServiceUser: false,
|
|
Issued: UserIssuedAPI,
|
|
}
|
|
targetId = "user4"
|
|
account.Users[targetId] = &User{
|
|
Id: targetId,
|
|
IsServiceUser: false,
|
|
Issued: UserIssuedIntegration,
|
|
}
|
|
|
|
err := store.SaveAccount(account)
|
|
if err != nil {
|
|
t.Fatalf("Error when saving account: %s", err)
|
|
}
|
|
|
|
am := DefaultAccountManager{
|
|
Store: store,
|
|
eventStore: &activity.InMemoryEventStore{},
|
|
}
|
|
|
|
testCases := []struct {
|
|
name string
|
|
userID string
|
|
assertErrFunc assert.ErrorAssertionFunc
|
|
assertErrMessage string
|
|
}{
|
|
{
|
|
name: "Delete service user successfully ",
|
|
userID: "user2",
|
|
assertErrFunc: assert.NoError,
|
|
},
|
|
{
|
|
name: "Delete regular user successfully ",
|
|
userID: "user3",
|
|
assertErrFunc: assert.NoError,
|
|
},
|
|
{
|
|
name: "Delete integration regular user permission denied ",
|
|
userID: "user4",
|
|
assertErrFunc: assert.Error,
|
|
assertErrMessage: "only integration can delete this user",
|
|
},
|
|
}
|
|
|
|
for _, testCase := range testCases {
|
|
t.Run(testCase.name, func(t *testing.T) {
|
|
err = am.DeleteUser(mockAccountID, mockUserID, testCase.userID)
|
|
testCase.assertErrFunc(t, err, testCase.assertErrMessage)
|
|
})
|
|
}
|
|
|
|
}
|
|
|
|
func TestDefaultAccountManager_GetUser(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{},
|
|
}
|
|
|
|
claims := jwtclaims.AuthorizationClaims{
|
|
UserId: mockUserID,
|
|
}
|
|
|
|
user, err := am.GetUser(claims)
|
|
if err != nil {
|
|
t.Fatalf("Error when checking user role: %s", err)
|
|
}
|
|
|
|
assert.Equal(t, mockUserID, user.Id)
|
|
assert.True(t, user.IsAdmin())
|
|
assert.False(t, user.IsBlocked())
|
|
}
|
|
|
|
func TestUser_IsAdmin(t *testing.T) {
|
|
|
|
user := NewAdminUser(mockUserID)
|
|
assert.True(t, user.IsAdmin())
|
|
|
|
user = NewRegularUser(mockUserID)
|
|
assert.False(t, user.IsAdmin())
|
|
}
|
|
|
|
func TestUser_GetUsersFromAccount_ForAdmin(t *testing.T) {
|
|
store := newStore(t)
|
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
|
account.Users[mockServiceUserID] = &User{
|
|
Id: mockServiceUserID,
|
|
Role: "user",
|
|
IsServiceUser: true,
|
|
}
|
|
|
|
err := store.SaveAccount(account)
|
|
if err != nil {
|
|
t.Fatalf("Error when saving account: %s", err)
|
|
}
|
|
|
|
am := DefaultAccountManager{
|
|
Store: store,
|
|
eventStore: &activity.InMemoryEventStore{},
|
|
}
|
|
|
|
users, err := am.GetUsersFromAccount(mockAccountID, mockUserID)
|
|
if err != nil {
|
|
t.Fatalf("Error when getting users from account: %s", err)
|
|
}
|
|
|
|
assert.Equal(t, 2, len(users))
|
|
}
|
|
|
|
func TestUser_GetUsersFromAccount_ForUser(t *testing.T) {
|
|
store := newStore(t)
|
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
|
account.Users[mockServiceUserID] = &User{
|
|
Id: mockServiceUserID,
|
|
Role: "user",
|
|
IsServiceUser: true,
|
|
}
|
|
|
|
err := store.SaveAccount(account)
|
|
if err != nil {
|
|
t.Fatalf("Error when saving account: %s", err)
|
|
}
|
|
|
|
am := DefaultAccountManager{
|
|
Store: store,
|
|
eventStore: &activity.InMemoryEventStore{},
|
|
}
|
|
|
|
users, err := am.GetUsersFromAccount(mockAccountID, mockServiceUserID)
|
|
if err != nil {
|
|
t.Fatalf("Error when getting users from account: %s", err)
|
|
}
|
|
|
|
assert.Equal(t, 1, len(users))
|
|
assert.Equal(t, mockServiceUserID, users[0].ID)
|
|
}
|
|
|
|
func TestDefaultAccountManager_SaveUser(t *testing.T) {
|
|
manager, err := createManager(t)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
return
|
|
}
|
|
|
|
regularUserID := "regularUser"
|
|
|
|
tt := []struct {
|
|
name string
|
|
adminInitiator bool
|
|
update *User
|
|
expectedErr bool
|
|
}{
|
|
{
|
|
name: "Should_Fail_To_Update_Admin_Role",
|
|
expectedErr: true,
|
|
adminInitiator: true,
|
|
update: &User{
|
|
Id: userID,
|
|
Role: UserRoleUser,
|
|
Blocked: false,
|
|
},
|
|
}, {
|
|
name: "Should_Fail_When_Admin_Blocks_Themselves",
|
|
expectedErr: true,
|
|
adminInitiator: true,
|
|
update: &User{
|
|
Id: userID,
|
|
Role: UserRoleAdmin,
|
|
Blocked: true,
|
|
},
|
|
},
|
|
{
|
|
name: "Should_Fail_To_Update_Non_Existing_User",
|
|
expectedErr: true,
|
|
adminInitiator: true,
|
|
update: &User{
|
|
Id: userID,
|
|
Role: UserRoleAdmin,
|
|
Blocked: true,
|
|
},
|
|
},
|
|
{
|
|
name: "Should_Fail_To_Update_When_Initiator_Is_Not_An_Admin",
|
|
expectedErr: true,
|
|
adminInitiator: false,
|
|
update: &User{
|
|
Id: userID,
|
|
Role: UserRoleAdmin,
|
|
Blocked: true,
|
|
},
|
|
},
|
|
{
|
|
name: "Should_Update_User",
|
|
expectedErr: false,
|
|
adminInitiator: true,
|
|
update: &User{
|
|
Id: regularUserID,
|
|
Role: UserRoleAdmin,
|
|
Blocked: true,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range tt {
|
|
|
|
// create an account and an admin user
|
|
account, err := manager.GetOrCreateAccountByUser(userID, "netbird.io")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// create a regular user
|
|
account.Users[regularUserID] = NewRegularUser(regularUserID)
|
|
err = manager.Store.SaveAccount(account)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
initiatorID := userID
|
|
if !tc.adminInitiator {
|
|
initiatorID = regularUserID
|
|
}
|
|
|
|
updated, err := manager.SaveUser(account.Id, initiatorID, tc.update)
|
|
if tc.expectedErr {
|
|
require.Errorf(t, err, "expecting SaveUser to throw an error")
|
|
} else {
|
|
require.NoError(t, err, "expecting SaveUser not to throw an error")
|
|
assert.NotNil(t, updated)
|
|
|
|
assert.Equal(t, string(tc.update.Role), updated.Role)
|
|
assert.Equal(t, tc.update.IsBlocked(), updated.IsBlocked)
|
|
}
|
|
}
|
|
|
|
}
|