75f3dd141c
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CI and Release / lint-frontend (push) Has been cancelled
CI and Release / dockerfile-scan (push) Has been cancelled
CI and Release / test-frontend (push) Has been cancelled
CI and Release / lint-verification-agent (push) Has been cancelled
CI and Release / test-verification-agent (push) Has been cancelled
CI and Release / e2e-verification-agent (push) Has been cancelled
CI and Release / test-backend (push) Has been cancelled
CI and Release / build-dev-image (push) Has been cancelled
CI and Release / push-dev-image (push) Has been cancelled
CI and Release / build-image (push) Has been cancelled
CI and Release / build-verification-image (push) Has been cancelled
CI and Release / determine-version (push) Has been cancelled
CI and Release / push-image (push) Has been cancelled
CI and Release / push-verification-image (12) (push) Has been cancelled
CI and Release / lint-backend (push) Has been cancelled
CI and Release / push-verification-image (17) (push) Has been cancelled
CI and Release / push-verification-image (18) (push) Has been cancelled
CI and Release / release (push) Has been cancelled
CI and Release / publish-helm-chart (push) Has been cancelled
CI and Release / push-verification-image (13) (push) Has been cancelled
CI and Release / push-verification-image (14) (push) Has been cancelled
CI and Release / push-verification-image (15) (push) Has been cancelled
CI and Release / push-verification-image (16) (push) Has been cancelled
1349 lines
41 KiB
Go
1349 lines
41 KiB
Go
package workspaces_controllers
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
users_enums "databasus-backend/internal/features/users/enums"
|
|
users_testing "databasus-backend/internal/features/users/testing"
|
|
workspaces_dto "databasus-backend/internal/features/workspaces/dto"
|
|
workspaces_testing "databasus-backend/internal/features/workspaces/testing"
|
|
test_utils "databasus-backend/internal/util/testing"
|
|
)
|
|
|
|
// ListMembers Tests
|
|
|
|
func Test_GetWorkspaceMembers_PermissionsEnforced(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
workspaceRole *users_enums.WorkspaceRole
|
|
isGlobalAdmin bool
|
|
expectSuccess bool
|
|
expectedStatusCode int
|
|
}{
|
|
{
|
|
name: "workspace owner can view members",
|
|
workspaceRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleOwner; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: true,
|
|
expectedStatusCode: http.StatusOK,
|
|
},
|
|
{
|
|
name: "workspace admin can view members",
|
|
workspaceRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleAdmin; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: true,
|
|
expectedStatusCode: http.StatusOK,
|
|
},
|
|
{
|
|
name: "workspace member can view members",
|
|
workspaceRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleMember; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: true,
|
|
expectedStatusCode: http.StatusOK,
|
|
},
|
|
{
|
|
name: "workspace viewer can view members",
|
|
workspaceRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleViewer; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: true,
|
|
expectedStatusCode: http.StatusOK,
|
|
},
|
|
{
|
|
name: "non-member cannot view members",
|
|
workspaceRole: nil,
|
|
isGlobalAdmin: false,
|
|
expectSuccess: false,
|
|
expectedStatusCode: http.StatusForbidden,
|
|
},
|
|
{
|
|
name: "global admin can view members",
|
|
workspaceRole: nil,
|
|
isGlobalAdmin: true,
|
|
expectSuccess: true,
|
|
expectedStatusCode: http.StatusOK,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
router := workspaces_testing.CreateTestRouter(
|
|
GetWorkspaceController(),
|
|
GetMembershipController(),
|
|
)
|
|
owner := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
workspace, _ := workspaces_testing.CreateTestWorkspaceViaAPI(
|
|
"Test Workspace",
|
|
owner,
|
|
router,
|
|
)
|
|
defer workspaces_testing.RemoveTestWorkspace(workspace, router)
|
|
defer workspaces_testing.RemoveTestWorkspace(workspace, router)
|
|
|
|
var testUserToken string
|
|
if tt.isGlobalAdmin {
|
|
admin := users_testing.CreateTestUser(users_enums.UserRoleAdmin)
|
|
testUserToken = admin.Token
|
|
} else if tt.workspaceRole != nil && *tt.workspaceRole == users_enums.WorkspaceRoleOwner {
|
|
testUserToken = owner.Token
|
|
} else if tt.workspaceRole != nil {
|
|
member := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
workspaces_testing.AddMemberToWorkspaceViaOwner(
|
|
workspace,
|
|
member,
|
|
*tt.workspaceRole,
|
|
router,
|
|
)
|
|
testUserToken = member.Token
|
|
} else {
|
|
nonMember := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
testUserToken = nonMember.Token
|
|
}
|
|
|
|
if tt.expectSuccess {
|
|
var response workspaces_dto.GetMembersResponseDTO
|
|
test_utils.MakeGetRequestAndUnmarshal(
|
|
t,
|
|
router,
|
|
"/api/v1/workspaces/memberships/"+workspace.ID.String()+"/members",
|
|
"Bearer "+testUserToken,
|
|
tt.expectedStatusCode,
|
|
&response,
|
|
)
|
|
|
|
assert.GreaterOrEqual(t, len(response.Members), 1)
|
|
} else {
|
|
resp := test_utils.MakeGetRequest(
|
|
t,
|
|
router,
|
|
"/api/v1/workspaces/memberships/"+workspace.ID.String()+"/members",
|
|
"Bearer "+testUserToken,
|
|
tt.expectedStatusCode,
|
|
)
|
|
assert.Contains(
|
|
t,
|
|
string(resp.Body),
|
|
"insufficient permissions to view workspace members",
|
|
)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_GetWorkspaceMembers_WithInvalidWorkspaceID_ReturnsBadRequest(t *testing.T) {
|
|
router := workspaces_testing.CreateTestRouter(
|
|
GetWorkspaceController(),
|
|
GetMembershipController(),
|
|
)
|
|
user := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
|
|
resp := test_utils.MakeGetRequest(
|
|
t,
|
|
router,
|
|
"/api/v1/workspaces/memberships/invalid-uuid/members",
|
|
"Bearer "+user.Token,
|
|
http.StatusBadRequest,
|
|
)
|
|
assert.Contains(t, string(resp.Body), "Invalid workspace ID")
|
|
}
|
|
|
|
// AddMember Tests
|
|
|
|
func Test_AddMemberToWorkspace_PermissionsEnforced(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
requesterRole *users_enums.WorkspaceRole
|
|
isGlobalAdmin bool
|
|
expectSuccess bool
|
|
expectedStatusCode int
|
|
}{
|
|
{
|
|
name: "workspace owner can add member",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleOwner; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: true,
|
|
expectedStatusCode: http.StatusOK,
|
|
},
|
|
{
|
|
name: "global admin can add member",
|
|
requesterRole: nil,
|
|
isGlobalAdmin: true,
|
|
expectSuccess: true,
|
|
expectedStatusCode: http.StatusOK,
|
|
},
|
|
{
|
|
name: "workspace admin can add member",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleAdmin; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: true,
|
|
expectedStatusCode: http.StatusOK,
|
|
},
|
|
{
|
|
name: "workspace member cannot add member",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleMember; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: false,
|
|
expectedStatusCode: http.StatusForbidden,
|
|
},
|
|
{
|
|
name: "workspace viewer cannot add member",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleViewer; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: false,
|
|
expectedStatusCode: http.StatusForbidden,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
router := workspaces_testing.CreateTestRouter(
|
|
GetWorkspaceController(),
|
|
GetMembershipController(),
|
|
)
|
|
owner := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
newMember := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
workspace, _ := workspaces_testing.CreateTestWorkspaceViaAPI(
|
|
"Test Workspace",
|
|
owner,
|
|
router,
|
|
)
|
|
defer workspaces_testing.RemoveTestWorkspace(workspace, router)
|
|
defer workspaces_testing.RemoveTestWorkspace(workspace, router)
|
|
|
|
var testUserToken string
|
|
if tt.isGlobalAdmin {
|
|
admin := users_testing.CreateTestUser(users_enums.UserRoleAdmin)
|
|
testUserToken = admin.Token
|
|
} else if tt.requesterRole != nil && *tt.requesterRole == users_enums.WorkspaceRoleOwner {
|
|
testUserToken = owner.Token
|
|
} else if tt.requesterRole != nil {
|
|
requester := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
workspaces_testing.AddMemberToWorkspaceViaOwner(
|
|
workspace,
|
|
requester,
|
|
*tt.requesterRole,
|
|
router,
|
|
)
|
|
testUserToken = requester.Token
|
|
}
|
|
|
|
request := workspaces_dto.AddMemberRequestDTO{
|
|
Email: newMember.Email,
|
|
Role: users_enums.WorkspaceRoleViewer,
|
|
}
|
|
|
|
if tt.expectSuccess {
|
|
var response workspaces_dto.AddMemberResponseDTO
|
|
test_utils.MakePostRequestAndUnmarshal(
|
|
t,
|
|
router,
|
|
"/api/v1/workspaces/memberships/"+workspace.ID.String()+"/members",
|
|
"Bearer "+testUserToken,
|
|
request,
|
|
tt.expectedStatusCode,
|
|
&response,
|
|
)
|
|
|
|
assert.True(t, response.Status == workspaces_dto.AddStatusAdded)
|
|
} else {
|
|
resp := test_utils.MakePostRequest(
|
|
t,
|
|
router,
|
|
"/api/v1/workspaces/memberships/"+workspace.ID.String()+"/members",
|
|
"Bearer "+testUserToken,
|
|
request,
|
|
tt.expectedStatusCode,
|
|
)
|
|
assert.Contains(t, string(resp.Body), "insufficient permissions to manage members")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_AddMemberToWorkspace_WhenUserIsAlreadyMember_ReturnsBadRequest(t *testing.T) {
|
|
router := workspaces_testing.CreateTestRouter(
|
|
GetWorkspaceController(),
|
|
GetMembershipController(),
|
|
)
|
|
owner := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
member := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
|
|
workspace, _ := workspaces_testing.CreateTestWorkspaceViaAPI("Test Workspace", owner, router)
|
|
defer workspaces_testing.RemoveTestWorkspace(workspace, router)
|
|
|
|
workspaces_testing.AddMemberToWorkspaceViaOwner(
|
|
workspace,
|
|
member,
|
|
users_enums.WorkspaceRoleViewer,
|
|
router,
|
|
)
|
|
|
|
// Try to add the same user again
|
|
request := workspaces_dto.AddMemberRequestDTO{
|
|
Email: member.Email,
|
|
Role: users_enums.WorkspaceRoleViewer,
|
|
}
|
|
|
|
resp := test_utils.MakePostRequest(
|
|
t,
|
|
router,
|
|
"/api/v1/workspaces/memberships/"+workspace.ID.String()+"/members",
|
|
"Bearer "+owner.Token,
|
|
request,
|
|
http.StatusBadRequest,
|
|
)
|
|
assert.Contains(t, string(resp.Body), "user is already a member of this workspace")
|
|
}
|
|
|
|
func Test_AddMemberToWorkspace_WithNonExistentUser_ReturnsInvited(t *testing.T) {
|
|
router := workspaces_testing.CreateTestRouter(
|
|
GetWorkspaceController(),
|
|
GetMembershipController(),
|
|
)
|
|
owner := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
|
|
workspace, _ := workspaces_testing.CreateTestWorkspaceViaAPI("Test Workspace", owner, router)
|
|
defer workspaces_testing.RemoveTestWorkspace(workspace, router)
|
|
|
|
request := workspaces_dto.AddMemberRequestDTO{
|
|
Email: uuid.New().String() + "@example.com", // Non-existent user
|
|
Role: users_enums.WorkspaceRoleViewer,
|
|
}
|
|
|
|
var response workspaces_dto.AddMemberResponseDTO
|
|
test_utils.MakePostRequestAndUnmarshal(
|
|
t,
|
|
router,
|
|
"/api/v1/workspaces/memberships/"+workspace.ID.String()+"/members",
|
|
"Bearer "+owner.Token,
|
|
request,
|
|
http.StatusOK,
|
|
&response,
|
|
)
|
|
|
|
assert.True(t, response.Status == workspaces_dto.AddStatusInvited)
|
|
}
|
|
|
|
func Test_AddMemberToWorkspace_WhenWorkspaceAdminTriesToAddAdmin_ReturnsBadRequest(t *testing.T) {
|
|
router := workspaces_testing.CreateTestRouter(
|
|
GetWorkspaceController(),
|
|
GetMembershipController(),
|
|
)
|
|
owner := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
workspaceAdmin := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
newMember := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
|
|
workspace, _ := workspaces_testing.CreateTestWorkspaceViaAPI("Test Workspace", owner, router)
|
|
defer workspaces_testing.RemoveTestWorkspace(workspace, router)
|
|
|
|
workspaces_testing.AddMemberToWorkspaceViaOwner(
|
|
workspace,
|
|
workspaceAdmin,
|
|
users_enums.WorkspaceRoleAdmin,
|
|
router,
|
|
)
|
|
|
|
// Workspace admin tries to add another admin (should fail)
|
|
request := workspaces_dto.AddMemberRequestDTO{
|
|
Email: newMember.Email,
|
|
Role: users_enums.WorkspaceRoleAdmin,
|
|
}
|
|
|
|
resp := test_utils.MakePostRequest(
|
|
t,
|
|
router,
|
|
"/api/v1/workspaces/memberships/"+workspace.ID.String()+"/members",
|
|
"Bearer "+workspaceAdmin.Token,
|
|
request,
|
|
http.StatusForbidden,
|
|
)
|
|
assert.Contains(t, string(resp.Body), "only workspace owner can add/manage admins")
|
|
}
|
|
|
|
func Test_AddMemberToWorkspace_WhenWorkspaceAdminTriesToAddWorkspaceAdmin_ReturnsBadRequest(
|
|
t *testing.T,
|
|
) {
|
|
router := workspaces_testing.CreateTestRouter(
|
|
GetWorkspaceController(),
|
|
GetMembershipController(),
|
|
)
|
|
owner := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
workspaceAdmin := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
newMember := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
|
|
workspace, _ := workspaces_testing.CreateTestWorkspaceViaAPI("Test Workspace", owner, router)
|
|
defer workspaces_testing.RemoveTestWorkspace(workspace, router)
|
|
|
|
workspaces_testing.AddMemberToWorkspaceViaOwner(
|
|
workspace,
|
|
workspaceAdmin,
|
|
users_enums.WorkspaceRoleAdmin,
|
|
router,
|
|
)
|
|
|
|
// WorkspaceAdmin tries to add another WorkspaceAdmin (should fail)
|
|
request := workspaces_dto.AddMemberRequestDTO{
|
|
Email: newMember.Email,
|
|
Role: users_enums.WorkspaceRoleAdmin,
|
|
}
|
|
|
|
resp := test_utils.MakePostRequest(
|
|
t,
|
|
router,
|
|
"/api/v1/workspaces/memberships/"+workspace.ID.String()+"/members",
|
|
"Bearer "+workspaceAdmin.Token,
|
|
request,
|
|
http.StatusForbidden,
|
|
)
|
|
assert.Contains(t, string(resp.Body), "only workspace owner can add/manage admins")
|
|
}
|
|
|
|
func Test_AddWorkspaceAdmin_PermissionsEnforced(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
requesterRole *users_enums.WorkspaceRole
|
|
isGlobalAdmin bool
|
|
expectSuccess bool
|
|
expectedStatusCode int
|
|
}{
|
|
{
|
|
name: "workspace owner can add workspace admin",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleOwner; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: true,
|
|
expectedStatusCode: http.StatusOK,
|
|
},
|
|
{
|
|
name: "global admin can add workspace admin",
|
|
requesterRole: nil,
|
|
isGlobalAdmin: true,
|
|
expectSuccess: true,
|
|
expectedStatusCode: http.StatusOK,
|
|
},
|
|
{
|
|
name: "workspace admin cannot add workspace admin",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleAdmin; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: false,
|
|
expectedStatusCode: http.StatusForbidden,
|
|
},
|
|
{
|
|
name: "workspace member cannot add workspace admin",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleMember; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: false,
|
|
expectedStatusCode: http.StatusForbidden,
|
|
},
|
|
{
|
|
name: "workspace viewer cannot add workspace admin",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleViewer; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: false,
|
|
expectedStatusCode: http.StatusForbidden,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
router := workspaces_testing.CreateTestRouter(
|
|
GetWorkspaceController(),
|
|
GetMembershipController(),
|
|
)
|
|
owner := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
newMember := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
workspace, _ := workspaces_testing.CreateTestWorkspaceViaAPI(
|
|
"Test Workspace",
|
|
owner,
|
|
router,
|
|
)
|
|
defer workspaces_testing.RemoveTestWorkspace(workspace, router)
|
|
defer workspaces_testing.RemoveTestWorkspace(workspace, router)
|
|
|
|
var testUserToken string
|
|
if tt.isGlobalAdmin {
|
|
admin := users_testing.CreateTestUser(users_enums.UserRoleAdmin)
|
|
testUserToken = admin.Token
|
|
} else if tt.requesterRole != nil && *tt.requesterRole == users_enums.WorkspaceRoleOwner {
|
|
testUserToken = owner.Token
|
|
} else if tt.requesterRole != nil {
|
|
requester := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
workspaces_testing.AddMemberToWorkspaceViaOwner(
|
|
workspace,
|
|
requester,
|
|
*tt.requesterRole,
|
|
router,
|
|
)
|
|
testUserToken = requester.Token
|
|
}
|
|
|
|
request := workspaces_dto.AddMemberRequestDTO{
|
|
Email: newMember.Email,
|
|
Role: users_enums.WorkspaceRoleAdmin,
|
|
}
|
|
|
|
if tt.expectSuccess {
|
|
var response workspaces_dto.AddMemberResponseDTO
|
|
test_utils.MakePostRequestAndUnmarshal(
|
|
t,
|
|
router,
|
|
"/api/v1/workspaces/memberships/"+workspace.ID.String()+"/members",
|
|
"Bearer "+testUserToken,
|
|
request,
|
|
tt.expectedStatusCode,
|
|
&response,
|
|
)
|
|
|
|
assert.True(t, response.Status == workspaces_dto.AddStatusAdded)
|
|
} else {
|
|
resp := test_utils.MakePostRequest(
|
|
t,
|
|
router,
|
|
"/api/v1/workspaces/memberships/"+workspace.ID.String()+"/members",
|
|
"Bearer "+testUserToken,
|
|
request,
|
|
tt.expectedStatusCode,
|
|
)
|
|
assert.Contains(t, string(resp.Body), "only workspace owner can add/manage admins")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_InviteMemberToWorkspace_PermissionsEnforced(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
requesterRole *users_enums.WorkspaceRole
|
|
isGlobalAdmin bool
|
|
expectSuccess bool
|
|
expectedStatusCode int
|
|
}{
|
|
{
|
|
name: "workspace owner can invite member",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleOwner; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: true,
|
|
expectedStatusCode: http.StatusOK,
|
|
},
|
|
{
|
|
name: "global admin can invite member",
|
|
requesterRole: nil,
|
|
isGlobalAdmin: true,
|
|
expectSuccess: true,
|
|
expectedStatusCode: http.StatusOK,
|
|
},
|
|
{
|
|
name: "workspace admin can invite member",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleAdmin; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: true,
|
|
expectedStatusCode: http.StatusOK,
|
|
},
|
|
{
|
|
name: "workspace member cannot invite member",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleMember; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: false,
|
|
expectedStatusCode: http.StatusForbidden,
|
|
},
|
|
{
|
|
name: "workspace viewer cannot invite member",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleViewer; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: false,
|
|
expectedStatusCode: http.StatusForbidden,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
router := workspaces_testing.CreateTestRouter(
|
|
GetWorkspaceController(),
|
|
GetMembershipController(),
|
|
)
|
|
users_testing.EnableMemberInvitations()
|
|
defer users_testing.ResetSettingsToDefaults()
|
|
|
|
owner := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
workspace, _ := workspaces_testing.CreateTestWorkspaceViaAPI(
|
|
"Test Workspace",
|
|
owner,
|
|
router,
|
|
)
|
|
defer workspaces_testing.RemoveTestWorkspace(workspace, router)
|
|
|
|
var testUserToken string
|
|
if tt.isGlobalAdmin {
|
|
admin := users_testing.CreateTestUser(users_enums.UserRoleAdmin)
|
|
testUserToken = admin.Token
|
|
} else if tt.requesterRole != nil && *tt.requesterRole == users_enums.WorkspaceRoleOwner {
|
|
testUserToken = owner.Token
|
|
} else if tt.requesterRole != nil {
|
|
requester := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
workspaces_testing.AddMemberToWorkspaceViaOwner(
|
|
workspace,
|
|
requester,
|
|
*tt.requesterRole,
|
|
router,
|
|
)
|
|
testUserToken = requester.Token
|
|
}
|
|
|
|
request := workspaces_dto.AddMemberRequestDTO{
|
|
Email: fmt.Sprintf("invite-%s@example.com", uuid.New().String()),
|
|
Role: users_enums.WorkspaceRoleViewer,
|
|
}
|
|
|
|
if tt.expectSuccess {
|
|
var response workspaces_dto.AddMemberResponseDTO
|
|
test_utils.MakePostRequestAndUnmarshal(
|
|
t,
|
|
router,
|
|
"/api/v1/workspaces/memberships/"+workspace.ID.String()+"/members",
|
|
"Bearer "+testUserToken,
|
|
request,
|
|
tt.expectedStatusCode,
|
|
&response,
|
|
)
|
|
|
|
assert.True(t, response.Status == workspaces_dto.AddStatusInvited)
|
|
} else {
|
|
resp := test_utils.MakePostRequest(
|
|
t,
|
|
router,
|
|
"/api/v1/workspaces/memberships/"+workspace.ID.String()+"/members",
|
|
"Bearer "+testUserToken,
|
|
request,
|
|
tt.expectedStatusCode,
|
|
)
|
|
assert.Contains(t, string(resp.Body), "insufficient permissions to manage members")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// ChangeMemberRole Tests
|
|
|
|
func Test_ChangeMemberRole_PermissionsEnforced(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
requesterRole *users_enums.WorkspaceRole
|
|
isGlobalAdmin bool
|
|
expectSuccess bool
|
|
expectedStatusCode int
|
|
}{
|
|
{
|
|
name: "workspace owner can change member role",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleOwner; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: true,
|
|
expectedStatusCode: http.StatusOK,
|
|
},
|
|
{
|
|
name: "workspace admin can change member role",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleAdmin; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: true,
|
|
expectedStatusCode: http.StatusOK,
|
|
},
|
|
{
|
|
name: "global admin can change member role",
|
|
requesterRole: nil,
|
|
isGlobalAdmin: true,
|
|
expectSuccess: true,
|
|
expectedStatusCode: http.StatusOK,
|
|
},
|
|
{
|
|
name: "workspace member cannot change member role",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleMember; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: false,
|
|
expectedStatusCode: http.StatusForbidden,
|
|
},
|
|
{
|
|
name: "workspace viewer cannot change member role",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleViewer; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: false,
|
|
expectedStatusCode: http.StatusForbidden,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
router := workspaces_testing.CreateTestRouter(
|
|
GetWorkspaceController(),
|
|
GetMembershipController(),
|
|
)
|
|
owner := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
targetMember := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
workspace, _ := workspaces_testing.CreateTestWorkspaceViaAPI(
|
|
"Test Workspace",
|
|
owner,
|
|
router,
|
|
)
|
|
defer workspaces_testing.RemoveTestWorkspace(workspace, router)
|
|
|
|
workspaces_testing.AddMemberToWorkspaceViaOwner(
|
|
workspace,
|
|
targetMember,
|
|
users_enums.WorkspaceRoleViewer,
|
|
router,
|
|
)
|
|
|
|
var testUserToken string
|
|
if tt.isGlobalAdmin {
|
|
admin := users_testing.CreateTestUser(users_enums.UserRoleAdmin)
|
|
testUserToken = admin.Token
|
|
} else if tt.requesterRole != nil && *tt.requesterRole == users_enums.WorkspaceRoleOwner {
|
|
testUserToken = owner.Token
|
|
} else if tt.requesterRole != nil {
|
|
requester := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
workspaces_testing.AddMemberToWorkspaceViaOwner(
|
|
workspace,
|
|
requester,
|
|
*tt.requesterRole,
|
|
router,
|
|
)
|
|
testUserToken = requester.Token
|
|
}
|
|
|
|
request := workspaces_dto.ChangeMemberRoleRequestDTO{
|
|
Role: users_enums.WorkspaceRoleViewer,
|
|
}
|
|
|
|
resp := test_utils.MakePutRequest(
|
|
t,
|
|
router,
|
|
fmt.Sprintf(
|
|
"/api/v1/workspaces/memberships/%s/members/%s/role",
|
|
workspace.ID.String(),
|
|
targetMember.UserID.String(),
|
|
),
|
|
"Bearer "+testUserToken,
|
|
request,
|
|
tt.expectedStatusCode,
|
|
)
|
|
|
|
if tt.expectSuccess {
|
|
assert.Contains(t, string(resp.Body), "Member role changed successfully")
|
|
} else {
|
|
assert.Contains(t, string(resp.Body), "insufficient permissions to manage members")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_ChangeMemberRoleToAdmin_PermissionsEnforced(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
requesterRole *users_enums.WorkspaceRole
|
|
isGlobalAdmin bool
|
|
expectSuccess bool
|
|
expectedStatusCode int
|
|
}{
|
|
{
|
|
name: "workspace owner can promote to admin",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleOwner; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: true,
|
|
expectedStatusCode: http.StatusOK,
|
|
},
|
|
{
|
|
name: "global admin can promote to admin",
|
|
requesterRole: nil,
|
|
isGlobalAdmin: true,
|
|
expectSuccess: true,
|
|
expectedStatusCode: http.StatusOK,
|
|
},
|
|
{
|
|
name: "workspace admin cannot promote to admin",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleAdmin; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: false,
|
|
expectedStatusCode: http.StatusForbidden,
|
|
},
|
|
{
|
|
name: "workspace member cannot promote to admin",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleMember; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: false,
|
|
expectedStatusCode: http.StatusForbidden,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
router := workspaces_testing.CreateTestRouter(
|
|
GetWorkspaceController(),
|
|
GetMembershipController(),
|
|
)
|
|
owner := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
targetMember := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
workspace, _ := workspaces_testing.CreateTestWorkspaceViaAPI(
|
|
"Test Workspace",
|
|
owner,
|
|
router,
|
|
)
|
|
defer workspaces_testing.RemoveTestWorkspace(workspace, router)
|
|
|
|
workspaces_testing.AddMemberToWorkspaceViaOwner(
|
|
workspace,
|
|
targetMember,
|
|
users_enums.WorkspaceRoleViewer,
|
|
router,
|
|
)
|
|
|
|
var testUserToken string
|
|
if tt.isGlobalAdmin {
|
|
admin := users_testing.CreateTestUser(users_enums.UserRoleAdmin)
|
|
testUserToken = admin.Token
|
|
} else if tt.requesterRole != nil && *tt.requesterRole == users_enums.WorkspaceRoleOwner {
|
|
testUserToken = owner.Token
|
|
} else if tt.requesterRole != nil {
|
|
requester := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
workspaces_testing.AddMemberToWorkspaceViaOwner(
|
|
workspace,
|
|
requester,
|
|
*tt.requesterRole,
|
|
router,
|
|
)
|
|
testUserToken = requester.Token
|
|
}
|
|
|
|
request := workspaces_dto.ChangeMemberRoleRequestDTO{
|
|
Role: users_enums.WorkspaceRoleAdmin,
|
|
}
|
|
|
|
resp := test_utils.MakePutRequest(
|
|
t,
|
|
router,
|
|
fmt.Sprintf(
|
|
"/api/v1/workspaces/memberships/%s/members/%s/role",
|
|
workspace.ID.String(),
|
|
targetMember.UserID.String(),
|
|
),
|
|
"Bearer "+testUserToken,
|
|
request,
|
|
tt.expectedStatusCode,
|
|
)
|
|
|
|
if tt.expectSuccess {
|
|
assert.Contains(t, string(resp.Body), "Member role changed successfully")
|
|
} else {
|
|
assert.Contains(t, string(resp.Body), "only workspace owner can add/manage admins")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_ChangeMemberRole_WhenChangingOwnRole_ReturnsBadRequest(t *testing.T) {
|
|
router := workspaces_testing.CreateTestRouter(
|
|
GetWorkspaceController(),
|
|
GetMembershipController(),
|
|
)
|
|
owner := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
workspace, _ := workspaces_testing.CreateTestWorkspaceViaAPI("Test Workspace", owner, router)
|
|
defer workspaces_testing.RemoveTestWorkspace(workspace, router)
|
|
|
|
request := workspaces_dto.ChangeMemberRoleRequestDTO{
|
|
Role: users_enums.WorkspaceRoleMember,
|
|
}
|
|
|
|
resp := test_utils.MakePutRequest(
|
|
t,
|
|
router,
|
|
fmt.Sprintf(
|
|
"/api/v1/workspaces/memberships/%s/members/%s/role",
|
|
workspace.ID.String(),
|
|
owner.UserID.String(),
|
|
),
|
|
"Bearer "+owner.Token,
|
|
request,
|
|
http.StatusBadRequest,
|
|
)
|
|
assert.Contains(t, string(resp.Body), "cannot change your own role")
|
|
}
|
|
|
|
func Test_ChangeMemberRole_WhenChangingOwnerRole_ReturnsBadRequest(t *testing.T) {
|
|
router := workspaces_testing.CreateTestRouter(
|
|
GetWorkspaceController(),
|
|
GetMembershipController(),
|
|
)
|
|
admin := users_testing.CreateTestUser(users_enums.UserRoleAdmin)
|
|
owner := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
|
|
workspace, _ := workspaces_testing.CreateTestWorkspaceViaAPI("Test Workspace", owner, router)
|
|
defer workspaces_testing.RemoveTestWorkspace(workspace, router)
|
|
|
|
request := workspaces_dto.ChangeMemberRoleRequestDTO{
|
|
Role: users_enums.WorkspaceRoleMember,
|
|
}
|
|
|
|
resp := test_utils.MakePutRequest(
|
|
t,
|
|
router,
|
|
fmt.Sprintf(
|
|
"/api/v1/workspaces/memberships/%s/members/%s/role",
|
|
workspace.ID.String(),
|
|
owner.UserID.String(),
|
|
),
|
|
"Bearer "+admin.Token,
|
|
request,
|
|
http.StatusBadRequest,
|
|
)
|
|
assert.Contains(t, string(resp.Body), "cannot change owner role")
|
|
}
|
|
|
|
// RemoveMember Tests
|
|
|
|
func Test_RemoveMemberFromWorkspace_PermissionsEnforced(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
requesterRole *users_enums.WorkspaceRole
|
|
isGlobalAdmin bool
|
|
expectSuccess bool
|
|
expectedStatusCode int
|
|
}{
|
|
{
|
|
name: "workspace owner can remove member",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleOwner; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: true,
|
|
expectedStatusCode: http.StatusOK,
|
|
},
|
|
{
|
|
name: "global admin can remove member",
|
|
requesterRole: nil,
|
|
isGlobalAdmin: true,
|
|
expectSuccess: true,
|
|
expectedStatusCode: http.StatusOK,
|
|
},
|
|
{
|
|
name: "workspace admin can remove member",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleAdmin; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: true,
|
|
expectedStatusCode: http.StatusOK,
|
|
},
|
|
{
|
|
name: "workspace member cannot remove member",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleMember; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: false,
|
|
expectedStatusCode: http.StatusForbidden,
|
|
},
|
|
{
|
|
name: "workspace viewer cannot remove member",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleViewer; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: false,
|
|
expectedStatusCode: http.StatusForbidden,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
router := workspaces_testing.CreateTestRouter(
|
|
GetWorkspaceController(),
|
|
GetMembershipController(),
|
|
)
|
|
owner := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
targetMember := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
workspace, _ := workspaces_testing.CreateTestWorkspaceViaAPI(
|
|
"Test Workspace",
|
|
owner,
|
|
router,
|
|
)
|
|
defer workspaces_testing.RemoveTestWorkspace(workspace, router)
|
|
|
|
workspaces_testing.AddMemberToWorkspaceViaOwner(
|
|
workspace,
|
|
targetMember,
|
|
users_enums.WorkspaceRoleViewer,
|
|
router,
|
|
)
|
|
|
|
var testUserToken string
|
|
if tt.isGlobalAdmin {
|
|
admin := users_testing.CreateTestUser(users_enums.UserRoleAdmin)
|
|
testUserToken = admin.Token
|
|
} else if tt.requesterRole != nil && *tt.requesterRole == users_enums.WorkspaceRoleOwner {
|
|
testUserToken = owner.Token
|
|
} else if tt.requesterRole != nil {
|
|
requester := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
workspaces_testing.AddMemberToWorkspaceViaOwner(
|
|
workspace,
|
|
requester,
|
|
*tt.requesterRole,
|
|
router,
|
|
)
|
|
testUserToken = requester.Token
|
|
}
|
|
|
|
resp := test_utils.MakeRequest(t, router, test_utils.RequestOptions{
|
|
Method: "DELETE",
|
|
URL: fmt.Sprintf(
|
|
"/api/v1/workspaces/memberships/%s/members/%s",
|
|
workspace.ID.String(),
|
|
targetMember.UserID.String(),
|
|
),
|
|
AuthToken: "Bearer " + testUserToken,
|
|
ExpectedStatus: tt.expectedStatusCode,
|
|
})
|
|
|
|
if tt.expectSuccess {
|
|
assert.Contains(t, string(resp.Body), "Member removed successfully")
|
|
} else {
|
|
assert.Contains(t, string(resp.Body), "insufficient permissions to remove members")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_RemoveMemberFromWorkspace_WhenRemovingOwner_ReturnsBadRequest(t *testing.T) {
|
|
router := workspaces_testing.CreateTestRouter(
|
|
GetWorkspaceController(),
|
|
GetMembershipController(),
|
|
)
|
|
admin := users_testing.CreateTestUser(users_enums.UserRoleAdmin)
|
|
owner := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
|
|
workspace, _ := workspaces_testing.CreateTestWorkspaceViaAPI("Test Workspace", owner, router)
|
|
defer workspaces_testing.RemoveTestWorkspace(workspace, router)
|
|
|
|
resp := test_utils.MakeRequest(t, router, test_utils.RequestOptions{
|
|
Method: "DELETE",
|
|
URL: fmt.Sprintf(
|
|
"/api/v1/workspaces/memberships/%s/members/%s",
|
|
workspace.ID.String(),
|
|
owner.UserID.String(),
|
|
),
|
|
AuthToken: "Bearer " + admin.Token,
|
|
ExpectedStatus: http.StatusBadRequest,
|
|
})
|
|
|
|
assert.Contains(t, string(resp.Body), "cannot remove workspace owner, transfer ownership first")
|
|
}
|
|
|
|
func Test_RemoveWorkspaceAdmin_PermissionsEnforced(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
requesterRole *users_enums.WorkspaceRole
|
|
isGlobalAdmin bool
|
|
expectSuccess bool
|
|
expectedStatusCode int
|
|
}{
|
|
{
|
|
name: "workspace owner can remove workspace admin",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleOwner; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: true,
|
|
expectedStatusCode: http.StatusOK,
|
|
},
|
|
{
|
|
name: "global admin can remove workspace admin",
|
|
requesterRole: nil,
|
|
isGlobalAdmin: true,
|
|
expectSuccess: true,
|
|
expectedStatusCode: http.StatusOK,
|
|
},
|
|
{
|
|
name: "workspace admin cannot remove workspace admin",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleAdmin; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: false,
|
|
expectedStatusCode: http.StatusForbidden,
|
|
},
|
|
{
|
|
name: "workspace member cannot remove workspace admin",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleMember; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: false,
|
|
expectedStatusCode: http.StatusForbidden,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
router := workspaces_testing.CreateTestRouter(
|
|
GetWorkspaceController(),
|
|
GetMembershipController(),
|
|
)
|
|
owner := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
targetAdmin := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
workspace, _ := workspaces_testing.CreateTestWorkspaceViaAPI(
|
|
"Test Workspace",
|
|
owner,
|
|
router,
|
|
)
|
|
defer workspaces_testing.RemoveTestWorkspace(workspace, router)
|
|
|
|
workspaces_testing.AddMemberToWorkspaceViaOwner(
|
|
workspace,
|
|
targetAdmin,
|
|
users_enums.WorkspaceRoleAdmin,
|
|
router,
|
|
)
|
|
|
|
var testUserToken string
|
|
if tt.isGlobalAdmin {
|
|
admin := users_testing.CreateTestUser(users_enums.UserRoleAdmin)
|
|
testUserToken = admin.Token
|
|
} else if tt.requesterRole != nil && *tt.requesterRole == users_enums.WorkspaceRoleOwner {
|
|
testUserToken = owner.Token
|
|
} else if tt.requesterRole != nil {
|
|
requester := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
workspaces_testing.AddMemberToWorkspaceViaOwner(
|
|
workspace,
|
|
requester,
|
|
*tt.requesterRole,
|
|
router,
|
|
)
|
|
testUserToken = requester.Token
|
|
}
|
|
|
|
resp := test_utils.MakeRequest(t, router, test_utils.RequestOptions{
|
|
Method: "DELETE",
|
|
URL: fmt.Sprintf(
|
|
"/api/v1/workspaces/memberships/%s/members/%s",
|
|
workspace.ID.String(),
|
|
targetAdmin.UserID.String(),
|
|
),
|
|
AuthToken: "Bearer " + testUserToken,
|
|
ExpectedStatus: tt.expectedStatusCode,
|
|
})
|
|
|
|
if tt.expectSuccess {
|
|
assert.Contains(t, string(resp.Body), "Member removed successfully")
|
|
} else {
|
|
// Workspace admins get specific error about removing admins
|
|
// Members/viewers get generic insufficient permissions error
|
|
body := string(resp.Body)
|
|
assert.True(t,
|
|
strings.Contains(body, "only workspace owner can remove admins") ||
|
|
strings.Contains(body, "insufficient permissions to remove members"),
|
|
"Expected permission error, got: %s", body)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TransferOwnership Tests
|
|
|
|
func Test_TransferWorkspaceOwnership_PermissionsEnforced(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
requesterRole *users_enums.WorkspaceRole
|
|
isGlobalAdmin bool
|
|
expectSuccess bool
|
|
expectedStatusCode int
|
|
}{
|
|
{
|
|
name: "workspace owner can transfer ownership",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleOwner; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: true,
|
|
expectedStatusCode: http.StatusOK,
|
|
},
|
|
{
|
|
name: "global admin can transfer ownership",
|
|
requesterRole: nil,
|
|
isGlobalAdmin: true,
|
|
expectSuccess: true,
|
|
expectedStatusCode: http.StatusOK,
|
|
},
|
|
{
|
|
name: "workspace member cannot transfer ownership",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleViewer; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: false,
|
|
expectedStatusCode: http.StatusForbidden,
|
|
},
|
|
{
|
|
name: "workspace admin cannot transfer ownership",
|
|
requesterRole: func() *users_enums.WorkspaceRole { r := users_enums.WorkspaceRoleMember; return &r }(),
|
|
isGlobalAdmin: false,
|
|
expectSuccess: false,
|
|
expectedStatusCode: http.StatusForbidden,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
router := workspaces_testing.CreateTestRouter(
|
|
GetWorkspaceController(),
|
|
GetMembershipController(),
|
|
)
|
|
owner := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
newOwner := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
workspace, _ := workspaces_testing.CreateTestWorkspaceViaAPI(
|
|
"Test Workspace",
|
|
owner,
|
|
router,
|
|
)
|
|
defer workspaces_testing.RemoveTestWorkspace(workspace, router)
|
|
|
|
workspaces_testing.AddMemberToWorkspaceViaOwner(
|
|
workspace,
|
|
newOwner,
|
|
users_enums.WorkspaceRoleMember,
|
|
router,
|
|
)
|
|
|
|
var testUserToken string
|
|
if tt.isGlobalAdmin {
|
|
admin := users_testing.CreateTestUser(users_enums.UserRoleAdmin)
|
|
testUserToken = admin.Token
|
|
} else if tt.requesterRole != nil && *tt.requesterRole == users_enums.WorkspaceRoleOwner {
|
|
testUserToken = owner.Token
|
|
} else if tt.requesterRole != nil {
|
|
requester := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
workspaces_testing.AddMemberToWorkspaceViaOwner(
|
|
workspace,
|
|
requester,
|
|
*tt.requesterRole,
|
|
router,
|
|
)
|
|
testUserToken = requester.Token
|
|
}
|
|
|
|
request := workspaces_dto.TransferOwnershipRequestDTO{
|
|
NewOwnerEmail: newOwner.Email,
|
|
}
|
|
|
|
resp := test_utils.MakePostRequest(
|
|
t,
|
|
router,
|
|
"/api/v1/workspaces/memberships/"+workspace.ID.String()+"/transfer-ownership",
|
|
"Bearer "+testUserToken,
|
|
request,
|
|
tt.expectedStatusCode,
|
|
)
|
|
|
|
if tt.expectSuccess {
|
|
assert.Contains(t, string(resp.Body), "Ownership transferred successfully")
|
|
} else {
|
|
assert.Contains(
|
|
t,
|
|
string(resp.Body),
|
|
"only workspace owner or admin can transfer ownership",
|
|
)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_TransferWorkspaceOwnership_WhenNewOwnerIsNotMember_ReturnsBadRequest(t *testing.T) {
|
|
router := workspaces_testing.CreateTestRouter(
|
|
GetWorkspaceController(),
|
|
GetMembershipController(),
|
|
)
|
|
owner := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
nonMember := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
|
|
workspace, _ := workspaces_testing.CreateTestWorkspaceViaAPI("Test Workspace", owner, router)
|
|
defer workspaces_testing.RemoveTestWorkspace(workspace, router)
|
|
|
|
request := workspaces_dto.TransferOwnershipRequestDTO{
|
|
NewOwnerEmail: nonMember.Email,
|
|
}
|
|
|
|
resp := test_utils.MakePostRequest(
|
|
t,
|
|
router,
|
|
"/api/v1/workspaces/memberships/"+workspace.ID.String()+"/transfer-ownership",
|
|
"Bearer "+owner.Token,
|
|
request,
|
|
http.StatusBadRequest,
|
|
)
|
|
assert.Contains(t, string(resp.Body), "new owner must be a workspace member")
|
|
}
|
|
|
|
func Test_TransferWorkspaceOwnership_ThereIsOnlyOneOwner_OldOwnerBecomeAdmin(t *testing.T) {
|
|
router := workspaces_testing.CreateTestRouter(
|
|
GetWorkspaceController(),
|
|
GetMembershipController(),
|
|
)
|
|
owner := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
member := users_testing.CreateTestUser(users_enums.UserRoleMember)
|
|
|
|
workspace, _ := workspaces_testing.CreateTestWorkspaceViaAPI("Test Workspace", owner, router)
|
|
defer workspaces_testing.RemoveTestWorkspace(workspace, router)
|
|
|
|
workspaces_testing.AddMemberToWorkspaceViaOwner(
|
|
workspace,
|
|
member,
|
|
users_enums.WorkspaceRoleMember,
|
|
router,
|
|
)
|
|
|
|
// Transfer ownership to the member
|
|
request := workspaces_dto.TransferOwnershipRequestDTO{
|
|
NewOwnerEmail: member.Email,
|
|
}
|
|
|
|
resp := test_utils.MakePostRequest(
|
|
t,
|
|
router,
|
|
"/api/v1/workspaces/memberships/"+workspace.ID.String()+"/transfer-ownership",
|
|
"Bearer "+owner.Token,
|
|
request,
|
|
http.StatusOK,
|
|
)
|
|
assert.Contains(t, string(resp.Body), "Ownership transferred successfully")
|
|
|
|
// Get all members using the new owner's token
|
|
var membersResponse workspaces_dto.GetMembersResponseDTO
|
|
test_utils.MakeGetRequestAndUnmarshal(
|
|
t,
|
|
router,
|
|
"/api/v1/workspaces/memberships/"+workspace.ID.String()+"/members",
|
|
"Bearer "+member.Token,
|
|
http.StatusOK,
|
|
&membersResponse,
|
|
)
|
|
|
|
// Verify there is only one owner
|
|
ownerCount := 0
|
|
var currentOwner *workspaces_dto.WorkspaceMemberResponseDTO
|
|
for _, m := range membersResponse.Members {
|
|
if m.Role == users_enums.WorkspaceRoleOwner {
|
|
ownerCount++
|
|
currentOwner = &m
|
|
}
|
|
}
|
|
|
|
assert.Equal(t, 1, ownerCount, "There should be exactly one owner")
|
|
assert.NotNil(t, currentOwner, "Owner should exist")
|
|
assert.Equal(
|
|
t,
|
|
member.UserID,
|
|
currentOwner.UserID,
|
|
"The new owner should be the member we transferred to",
|
|
)
|
|
assert.Equal(
|
|
t,
|
|
member.Email,
|
|
currentOwner.Email,
|
|
"Owner email should match the transferred member",
|
|
)
|
|
|
|
// verify previous owner is now an admin
|
|
for _, m := range membersResponse.Members {
|
|
if m.UserID == owner.UserID {
|
|
assert.Equal(
|
|
t,
|
|
users_enums.WorkspaceRoleAdmin,
|
|
m.Role,
|
|
"Previous owner should now be admin",
|
|
)
|
|
break
|
|
}
|
|
}
|
|
}
|