737 lines
25 KiB
Plaintext
737 lines
25 KiB
Plaintext
package service
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/gochat/gochat/internal/auth"
|
|
"github.com/gochat/gochat/internal/model"
|
|
)
|
|
|
|
// ============================================================
|
|
// AccountUser Operations — Role Assignment Tests
|
|
// ============================================================
|
|
|
|
// Test1_GetAccountUser_Success verifies retrieving an existing AccountUser.
|
|
func Test1_GetAccountUser_Success(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
user := createTestUserForRBAC(t, db)
|
|
|
|
// Create AccountUser directly
|
|
au := &model.AccountUser{
|
|
UserID: user.ID,
|
|
AccountID: acc.ID,
|
|
Role: "agent",
|
|
Availability: "offline",
|
|
}
|
|
require.NoError(t, db.Create(au).Error)
|
|
|
|
result, err := svc.GetAccountUser(user.ID, acc.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, user.ID, result.UserID)
|
|
assert.Equal(t, acc.ID, result.AccountID)
|
|
assert.Equal(t, "agent", result.Role)
|
|
}
|
|
|
|
// Test2_GetAccountUser_NotFound verifies error when AccountUser doesn't exist.
|
|
func Test2_GetAccountUser_NotFound(t *testing.T) {
|
|
_, svc := setupRBACService(t)
|
|
|
|
result, err := svc.GetAccountUser(999, 999)
|
|
require.Error(t, err)
|
|
assert.Nil(t, result)
|
|
assert.Contains(t, err.Error(), "is not a member of")
|
|
}
|
|
|
|
// Test3_AddAccountUser_Success verifies adding a user to an account with agent role.
|
|
func Test3_AddAccountUser_Success(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
user := createTestUserForRBAC(t, db)
|
|
|
|
au, err := svc.AddAccountUser(user.ID, acc.ID, "agent", 0, 0)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, user.ID, au.UserID)
|
|
assert.Equal(t, acc.ID, au.AccountID)
|
|
assert.Equal(t, "agent", au.Role)
|
|
assert.Equal(t, uint(0), au.CustomRoleID)
|
|
assert.Equal(t, "offline", au.Availability)
|
|
}
|
|
|
|
// Test4_AddAccountUser_AdministratorRole verifies adding a user with administrator role.
|
|
func Test4_AddAccountUser_AdministratorRole(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
user := createTestUserForRBAC(t, db)
|
|
|
|
au, err := svc.AddAccountUser(user.ID, acc.ID, "administrator", 0, user.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "administrator", au.Role)
|
|
assert.Equal(t, user.ID, au.InvitedBy)
|
|
}
|
|
|
|
// Test5_AddAccountUser_InvalidRole verifies error when adding with invalid role.
|
|
func Test5_AddAccountUser_InvalidRole(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
user := createTestUserForRBAC(t, db)
|
|
|
|
au, err := svc.AddAccountUser(user.ID, acc.ID, "superadmin", 0, 0)
|
|
require.Error(t, err)
|
|
assert.Nil(t, au)
|
|
assert.Contains(t, err.Error(), "invalid role")
|
|
}
|
|
|
|
// Test6_AddAccountUser_AlreadyMember verifies error when user is already a member.
|
|
func Test6_AddAccountUser_AlreadyMember(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
user := createTestUserForRBAC(t, db)
|
|
|
|
_, err := svc.AddAccountUser(user.ID, acc.ID, "agent", 0, 0)
|
|
require.NoError(t, err)
|
|
|
|
au, err := svc.AddAccountUser(user.ID, acc.ID, "administrator", 0, 0)
|
|
require.Error(t, err)
|
|
assert.Nil(t, au)
|
|
assert.Contains(t, err.Error(), "already a member")
|
|
}
|
|
|
|
// Test7_AddAccountUser_WithCustomRole verifies adding a user with custom_role and customRoleID.
|
|
func Test7_AddAccountUser_WithCustomRole(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
user := createTestUserForRBAC(t, db)
|
|
|
|
// Create a custom role first
|
|
perms := auth.PermissionMatrixMap{
|
|
auth.DimensionConversationManage: auth.PermissionRead,
|
|
auth.DimensionContactManage: auth.PermissionFull,
|
|
}
|
|
cr, err := svc.CreateCustomRole(acc.ID, "Support Agent", perms, "custom support role")
|
|
require.NoError(t, err)
|
|
|
|
au, err := svc.AddAccountUser(user.ID, acc.ID, "custom_role", cr.ID, 0)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "custom_role", au.Role)
|
|
assert.Equal(t, cr.ID, au.CustomRoleID)
|
|
}
|
|
|
|
// Test8_UpdateAccountUserRole_Success verifies changing a user's role.
|
|
func Test8_UpdateAccountUserRole_Success(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
user := createTestUserForRBAC(t, db)
|
|
|
|
_, err := svc.AddAccountUser(user.ID, acc.ID, "agent", 0, 0)
|
|
require.NoError(t, err)
|
|
|
|
updated, err := svc.UpdateAccountUserRole(user.ID, acc.ID, "administrator", 0)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "administrator", updated.Role)
|
|
assert.Equal(t, uint(0), updated.CustomRoleID)
|
|
}
|
|
|
|
// Test9_UpdateAccountUserRole_InvalidRole verifies error when updating to invalid role.
|
|
func Test9_UpdateAccountUserRole_InvalidRole(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
user := createTestUserForRBAC(t, db)
|
|
|
|
_, err := svc.AddAccountUser(user.ID, acc.ID, "agent", 0, 0)
|
|
require.NoError(t, err)
|
|
|
|
updated, err := svc.UpdateAccountUserRole(user.ID, acc.ID, "invalid_role", 0)
|
|
require.Error(t, err)
|
|
assert.Nil(t, updated)
|
|
assert.Contains(t, err.Error(), "invalid role")
|
|
}
|
|
|
|
// Test10_UpdateAccountUserRole_NotFound verifies error when AccountUser doesn't exist.
|
|
func Test10_UpdateAccountUserRole_NotFound(t *testing.T) {
|
|
_, svc := setupRBACService(t)
|
|
|
|
updated, err := svc.UpdateAccountUserRole(999, 999, "agent", 0)
|
|
require.Error(t, err)
|
|
assert.Nil(t, updated)
|
|
}
|
|
|
|
// Test11_RemoveAccountUser_Success verifies removing a user from an account.
|
|
func Test11_RemoveAccountUser_Success(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
user := createTestUserForRBAC(t, db)
|
|
|
|
_, err := svc.AddAccountUser(user.ID, acc.ID, "agent", 0, 0)
|
|
require.NoError(t, err)
|
|
|
|
err = svc.RemoveAccountUser(user.ID, acc.ID)
|
|
require.NoError(t, err)
|
|
|
|
// Verify the user is no longer found
|
|
result, err := svc.GetAccountUser(user.ID, acc.ID)
|
|
require.Error(t, err)
|
|
assert.Nil(t, result)
|
|
}
|
|
|
|
// Test12_RemoveAccountUser_NotMember verifies error when removing a non-member.
|
|
func Test12_RemoveAccountUser_NotMember(t *testing.T) {
|
|
_, svc := setupRBACService(t)
|
|
|
|
err := svc.RemoveAccountUser(999, 999)
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "is not a member of")
|
|
}
|
|
|
|
// Test13_ListAccountUsers verifies listing all users in an account.
|
|
func Test13_ListAccountUsers(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
user1 := createTestUserForRBAC(t, db)
|
|
user2 := createTestUserForRBAC(t, db)
|
|
|
|
_, err := svc.AddAccountUser(user1.ID, acc.ID, "agent", 0, 0)
|
|
require.NoError(t, err)
|
|
_, err = svc.AddAccountUser(user2.ID, acc.ID, "administrator", 0, 0)
|
|
require.NoError(t, err)
|
|
|
|
users, err := svc.ListAccountUsers(acc.ID)
|
|
require.NoError(t, err)
|
|
assert.Len(t, users, 2)
|
|
}
|
|
|
|
// Test14_ListUserAccounts verifies listing all accounts a user belongs to.
|
|
func Test14_ListUserAccounts(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc1 := createTestAccountForRBAC(t, db)
|
|
acc2 := createTestAccountForRBAC(t, db)
|
|
user := createTestUserForRBAC(t, db)
|
|
|
|
_, err := svc.AddAccountUser(user.ID, acc1.ID, "agent", 0, 0)
|
|
require.NoError(t, err)
|
|
_, err = svc.AddAccountUser(user.ID, acc2.ID, "administrator", 0, 0)
|
|
require.NoError(t, err)
|
|
|
|
accounts, err := svc.ListUserAccounts(user.ID)
|
|
require.NoError(t, err)
|
|
assert.Len(t, accounts, 2)
|
|
}
|
|
|
|
// Test15_UpdateAvailability_Success verifies updating availability status.
|
|
func Test15_UpdateAvailability_Success(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
user := createTestUserForRBAC(t, db)
|
|
|
|
_, err := svc.AddAccountUser(user.ID, acc.ID, "agent", 0, 0)
|
|
require.NoError(t, err)
|
|
|
|
err = svc.UpdateAvailability(user.ID, acc.ID, "online")
|
|
require.NoError(t, err)
|
|
|
|
au, err := svc.GetAccountUser(user.ID, acc.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "online", au.Availability)
|
|
}
|
|
|
|
// Test16_UpdateAvailability_InvalidValue verifies error with invalid availability.
|
|
func Test16_UpdateAvailability_InvalidValue(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
user := createTestUserForRBAC(t, db)
|
|
|
|
_, err := svc.AddAccountUser(user.ID, acc.ID, "agent", 0, 0)
|
|
require.NoError(t, err)
|
|
|
|
err = svc.UpdateAvailability(user.ID, acc.ID, "away")
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "invalid availability")
|
|
}
|
|
|
|
// ============================================================
|
|
// Custom Role Operations Tests
|
|
// ============================================================
|
|
|
|
// Test17_CreateCustomRole_Success verifies creating a custom role with permissions.
|
|
func Test17_CreateCustomRole_Success(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
|
|
perms := auth.PermissionMatrixMap{
|
|
auth.DimensionConversationManage: auth.PermissionFull,
|
|
auth.DimensionConversationDelete: auth.PermissionRead,
|
|
auth.DimensionContactManage: auth.PermissionFull,
|
|
auth.DimensionReportManage: auth.PermissionNone,
|
|
auth.DimensionKnowledgeBaseManage: auth.PermissionRead,
|
|
auth.DimensionAutomationManage: auth.PermissionNone,
|
|
}
|
|
|
|
cr, err := svc.CreateCustomRole(acc.ID, "Team Lead", perms, "team lead role description")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, acc.ID, cr.AccountID)
|
|
assert.Equal(t, "Team Lead", cr.Name)
|
|
assert.Equal(t, "team lead role description", cr.Description)
|
|
assert.NotZero(t, cr.ID)
|
|
}
|
|
|
|
// Test18_GetCustomRole_Success verifies retrieving a custom role.
|
|
func Test18_GetCustomRole_Success(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
|
|
perms := auth.PermissionMatrixMap{
|
|
auth.DimensionConversationManage: auth.PermissionRead,
|
|
}
|
|
cr, err := svc.CreateCustomRole(acc.ID, "Viewer", perms, "view-only role")
|
|
require.NoError(t, err)
|
|
|
|
fetched, err := svc.GetCustomRole(cr.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, cr.Name, fetched.Name)
|
|
assert.Equal(t, cr.AccountID, fetched.AccountID)
|
|
}
|
|
|
|
// Test19_GetCustomRole_NotFound verifies error when custom role doesn't exist.
|
|
func Test19_GetCustomRole_NotFound(t *testing.T) {
|
|
_, svc := setupRBACService(t)
|
|
|
|
cr, err := svc.GetCustomRole(999)
|
|
require.Error(t, err)
|
|
assert.Nil(t, cr)
|
|
assert.Contains(t, err.Error(), "not found")
|
|
}
|
|
|
|
// Test20_GetCustomRolePermissionMatrix_Success verifies retrieving permission matrix of a custom role.
|
|
func Test20_GetCustomRolePermissionMatrix_Success(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
|
|
perms := auth.PermissionMatrixMap{
|
|
auth.DimensionConversationManage: auth.PermissionFull,
|
|
auth.DimensionContactManage: auth.PermissionRead,
|
|
auth.DimensionAutomationManage: auth.PermissionNone,
|
|
}
|
|
cr, err := svc.CreateCustomRole(acc.ID, "Ops Role", perms, "operations role")
|
|
require.NoError(t, err)
|
|
|
|
matrix, err := svc.GetCustomRolePermissionMatrix(cr.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, auth.PermissionFull, matrix[auth.DimensionConversationManage])
|
|
assert.Equal(t, auth.PermissionRead, matrix[auth.DimensionContactManage])
|
|
assert.Equal(t, auth.PermissionNone, matrix[auth.DimensionAutomationManage])
|
|
}
|
|
|
|
// Test21_GetCustomRolePermissionMatrix_NotFound verifies error for nonexistent role.
|
|
func Test21_GetCustomRolePermissionMatrix_NotFound(t *testing.T) {
|
|
_, svc := setupRBACService(t)
|
|
|
|
matrix, err := svc.GetCustomRolePermissionMatrix(999)
|
|
require.Error(t, err)
|
|
assert.Nil(t, matrix)
|
|
}
|
|
|
|
// Test22_UpdateCustomRole_Success verifies updating a custom role.
|
|
func Test22_UpdateCustomRole_Success(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
|
|
perms := auth.PermissionMatrixMap{
|
|
auth.DimensionConversationManage: auth.PermissionRead,
|
|
}
|
|
cr, err := svc.CreateCustomRole(acc.ID, "Initial Role", perms, "initial description")
|
|
require.NoError(t, err)
|
|
|
|
newPerms := auth.PermissionMatrixMap{
|
|
auth.DimensionConversationManage: auth.PermissionFull,
|
|
auth.DimensionContactManage: auth.PermissionRead,
|
|
}
|
|
updated, err := svc.UpdateCustomRole(cr.ID, "Updated Role", newPerms, "updated description")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "Updated Role", updated.Name)
|
|
assert.Equal(t, "updated description", updated.Description)
|
|
}
|
|
|
|
// Test23_UpdateCustomRole_NotFound verifies error when updating nonexistent role.
|
|
func Test23_UpdateCustomRole_NotFound(t *testing.T) {
|
|
_, svc := setupRBACService(t)
|
|
|
|
newPerms := auth.PermissionMatrixMap{
|
|
auth.DimensionConversationManage: auth.PermissionFull,
|
|
}
|
|
updated, err := svc.UpdateCustomRole(999, "Name", newPerms, "desc")
|
|
require.Error(t, err)
|
|
assert.Nil(t, updated)
|
|
}
|
|
|
|
// Test24_DeleteCustomRole_Success verifies deleting a custom role and downgrading users.
|
|
func Test24_DeleteCustomRole_Success(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
user := createTestUserForRBAC(t, db)
|
|
|
|
perms := auth.PermissionMatrixMap{
|
|
auth.DimensionConversationManage: auth.PermissionRead,
|
|
}
|
|
cr, err := svc.CreateCustomRole(acc.ID, "Temp Role", perms, "temporary")
|
|
require.NoError(t, err)
|
|
|
|
// Add user with custom role
|
|
au, err := svc.AddAccountUser(user.ID, acc.ID, "custom_role", cr.ID, 0)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "custom_role", au.Role)
|
|
|
|
// Delete the custom role — users should be downgraded to agent
|
|
err = svc.DeleteCustomRole(cr.ID)
|
|
require.NoError(t, err)
|
|
|
|
// Verify custom role is gone
|
|
fetched, err := svc.GetCustomRole(cr.ID)
|
|
require.Error(t, err)
|
|
assert.Nil(t, fetched)
|
|
|
|
// Verify user was downgraded to agent
|
|
downgraded, err := svc.GetAccountUser(user.ID, acc.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "agent", downgraded.Role)
|
|
assert.Equal(t, uint(0), downgraded.CustomRoleID)
|
|
}
|
|
|
|
// Test25_DeleteCustomRole_NotFound verifies error when deleting nonexistent role.
|
|
func Test25_DeleteCustomRole_NotFound(t *testing.T) {
|
|
_, svc := setupRBACService(t)
|
|
|
|
err := svc.DeleteCustomRole(999)
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "not found")
|
|
}
|
|
|
|
// Test26_ListCustomRoles verifies listing custom roles for an account.
|
|
func Test26_ListCustomRoles(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
|
|
perms1 := auth.PermissionMatrixMap{
|
|
auth.DimensionConversationManage: auth.PermissionRead,
|
|
}
|
|
perms2 := auth.PermissionMatrixMap{
|
|
auth.DimensionContactManage: auth.PermissionFull,
|
|
}
|
|
|
|
_, err := svc.CreateCustomRole(acc.ID, "Role A", perms1, "role a")
|
|
require.NoError(t, err)
|
|
_, err = svc.CreateCustomRole(acc.ID, "Role B", perms2, "role b")
|
|
require.NoError(t, err)
|
|
|
|
roles, err := svc.ListCustomRoles(acc.ID)
|
|
require.NoError(t, err)
|
|
assert.Len(t, roles, 2)
|
|
}
|
|
|
|
// ============================================================
|
|
// Permission Checking / PolicyContext Tests
|
|
// ============================================================
|
|
|
|
// Test27_BuildPolicyContext_Administrator verifies building PolicyContext for administrator.
|
|
func Test27_BuildPolicyContext_Administrator(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
user := createTestUserForRBAC(t, db)
|
|
|
|
_, err := svc.AddAccountUser(user.ID, acc.ID, "administrator", 0, 0)
|
|
require.NoError(t, err)
|
|
|
|
pc, err := svc.BuildPolicyContext(user.ID, acc.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, user.ID, pc.UserID)
|
|
assert.Equal(t, acc.ID, pc.AccountID)
|
|
assert.Equal(t, "administrator", pc.Role)
|
|
|
|
// Administrator should have full permissions on all dimensions
|
|
assert.Equal(t, auth.PermissionFull, pc.Permissions[auth.DimensionConversationManage])
|
|
assert.Equal(t, auth.PermissionFull, pc.Permissions[auth.DimensionContactManage])
|
|
}
|
|
|
|
// Test28_BuildPolicyContext_Agent verifies building PolicyContext for agent.
|
|
func Test28_BuildPolicyContext_Agent(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
user := createTestUserForRBAC(t, db)
|
|
|
|
_, err := svc.AddAccountUser(user.ID, acc.ID, "agent", 0, 0)
|
|
require.NoError(t, err)
|
|
|
|
pc, err := svc.BuildPolicyContext(user.ID, acc.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "agent", pc.Role)
|
|
|
|
// Agent defaults: conversation_manage = read, contact_manage = read
|
|
assert.Equal(t, auth.PermissionRead, pc.Permissions[auth.DimensionConversationManage])
|
|
assert.Equal(t, auth.PermissionRead, pc.Permissions[auth.DimensionContactManage])
|
|
assert.Equal(t, auth.PermissionNone, pc.Permissions[auth.DimensionAutomationManage])
|
|
}
|
|
|
|
// Test29_BuildPolicyContext_CustomRole verifies building PolicyContext for custom_role.
|
|
func Test29_BuildPolicyContext_CustomRole(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
user := createTestUserForRBAC(t, db)
|
|
|
|
perms := auth.PermissionMatrixMap{
|
|
auth.DimensionConversationManage: auth.PermissionFull,
|
|
auth.DimensionContactManage: auth.PermissionRead,
|
|
auth.DimensionAutomationManage: auth.PermissionNone,
|
|
}
|
|
cr, err := svc.CreateCustomRole(acc.ID, "Custom", perms, "custom role")
|
|
require.NoError(t, err)
|
|
|
|
_, err = svc.AddAccountUser(user.ID, acc.ID, "custom_role", cr.ID, 0)
|
|
require.NoError(t, err)
|
|
|
|
pc, err := svc.BuildPolicyContext(user.ID, acc.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "custom_role", pc.Role)
|
|
assert.Equal(t, cr.ID, pc.CustomRoleID)
|
|
assert.Equal(t, auth.PermissionFull, pc.Permissions[auth.DimensionConversationManage])
|
|
assert.Equal(t, auth.PermissionRead, pc.Permissions[auth.DimensionContactManage])
|
|
}
|
|
|
|
// Test30_BuildPolicyContext_NotFound verifies error when AccountUser doesn't exist.
|
|
func Test30_BuildPolicyContext_NotFound(t *testing.T) {
|
|
_, svc := setupRBACService(t)
|
|
|
|
pc, err := svc.BuildPolicyContext(999, 999)
|
|
require.Error(t, err)
|
|
assert.Nil(t, pc)
|
|
}
|
|
|
|
// ============================================================
|
|
// PlatformApp Operations Tests
|
|
// ============================================================
|
|
|
|
// Test31_CreatePlatformApp_Success verifies creating a platform app with API key.
|
|
func Test31_CreatePlatformApp_Success(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
|
|
pa, err := svc.CreatePlatformApp("TestBot", acc.ID, "agent_bot", "test bot description")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "TestBot", pa.Name)
|
|
assert.NotEmpty(t, pa.APIKey)
|
|
assert.Contains(t, pa.APIKey, "gchat_")
|
|
assert.Equal(t, acc.ID, pa.AccountID)
|
|
assert.Equal(t, "agent_bot", pa.Type)
|
|
assert.Equal(t, "active", pa.Status)
|
|
}
|
|
|
|
// Test32_CreatePlatformApp_PlatformLevel verifies creating a platform-level app (accountID=0).
|
|
func Test32_CreatePlatformApp_PlatformLevel(t *testing.T) {
|
|
_, svc := setupRBACService(t)
|
|
|
|
pa, err := svc.CreatePlatformApp("GlobalBot", 0, "api", "platform-level bot")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, uint(0), pa.AccountID)
|
|
assert.True(t, pa.IsPlatformLevel())
|
|
}
|
|
|
|
// Test33_GetPlatformApp_Success verifies retrieving a platform app by ID.
|
|
func Test33_GetPlatformApp_Success(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
|
|
pa, err := svc.CreatePlatformApp("FetchBot", acc.ID, "api", "fetch test")
|
|
require.NoError(t, err)
|
|
|
|
fetched, err := svc.GetPlatformApp(pa.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, pa.Name, fetched.Name)
|
|
assert.Equal(t, pa.APIKey, fetched.APIKey)
|
|
}
|
|
|
|
// Test34_GetPlatformApp_NotFound verifies error for nonexistent platform app.
|
|
func Test34_GetPlatformApp_NotFound(t *testing.T) {
|
|
_, svc := setupRBACService(t)
|
|
|
|
pa, err := svc.GetPlatformApp(999)
|
|
require.Error(t, err)
|
|
assert.Nil(t, pa)
|
|
}
|
|
|
|
// Test35_GetPlatformAppByAPIKey_Success verifies retrieving a platform app by API key.
|
|
func Test35_GetPlatformAppByAPIKey_Success(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
|
|
pa, err := svc.CreatePlatformApp("KeyBot", acc.ID, "api", "key lookup test")
|
|
require.NoError(t, err)
|
|
|
|
fetched, err := svc.GetPlatformAppByAPIKey(pa.APIKey)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, pa.ID, fetched.ID)
|
|
assert.Equal(t, pa.Name, fetched.Name)
|
|
}
|
|
|
|
// Test36_GetPlatformAppByAPIKey_NotFound verifies error for invalid API key.
|
|
func Test36_GetPlatformAppByAPIKey_NotFound(t *testing.T) {
|
|
_, svc := setupRBACService(t)
|
|
|
|
pa, err := svc.GetPlatformAppByAPIKey("gchat_invalid_key")
|
|
require.Error(t, err)
|
|
assert.Nil(t, pa)
|
|
}
|
|
|
|
// Test37_UpdatePlatformApp_Success verifies updating a platform app.
|
|
func Test37_UpdatePlatformApp_Success(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
|
|
pa, err := svc.CreatePlatformApp("OldName", acc.ID, "api", "old description")
|
|
require.NoError(t, err)
|
|
|
|
updated, err := svc.UpdatePlatformApp(pa.ID, "NewName", "new description", "")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "NewName", updated.Name)
|
|
assert.Equal(t, "new description", updated.Description)
|
|
// Status unchanged since we passed empty string
|
|
assert.Equal(t, "active", updated.Status)
|
|
}
|
|
|
|
// Test38_UpdatePlatformApp_Status verifies updating platform app status.
|
|
func Test38_UpdatePlatformApp_Status(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
|
|
pa, err := svc.CreatePlatformApp("StatusBot", acc.ID, "api", "status test")
|
|
require.NoError(t, err)
|
|
|
|
updated, err := svc.UpdatePlatformApp(pa.ID, "", "", "disabled")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "disabled", updated.Status)
|
|
// Name unchanged since we passed empty string
|
|
assert.Equal(t, "StatusBot", updated.Name)
|
|
}
|
|
|
|
// Test39_DeletePlatformApp_Success verifies deleting a platform app.
|
|
func Test39_DeletePlatformApp_Success(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
|
|
pa, err := svc.CreatePlatformApp("DeleteBot", acc.ID, "api", "delete test")
|
|
require.NoError(t, err)
|
|
|
|
err = svc.DeletePlatformApp(pa.ID)
|
|
require.NoError(t, err)
|
|
|
|
// Verify app is gone
|
|
fetched, err := svc.GetPlatformApp(pa.ID)
|
|
require.Error(t, err)
|
|
assert.Nil(t, fetched)
|
|
}
|
|
|
|
// Test40_DeletePlatformApp_NotFound verifies error when deleting nonexistent app.
|
|
func Test40_DeletePlatformApp_NotFound(t *testing.T) {
|
|
_, svc := setupRBACService(t)
|
|
|
|
err := svc.DeletePlatformApp(999)
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "not found")
|
|
}
|
|
|
|
// Test41_RegenerateAPIKey_Success verifies regenerating an API key.
|
|
func Test41_RegenerateAPIKey_Success(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
|
|
pa, err := svc.CreatePlatformApp("RegenBot", acc.ID, "api", "regen test")
|
|
require.NoError(t, err)
|
|
oldKey := pa.APIKey
|
|
|
|
newKey, err := svc.RegenerateAPIKey(pa.ID)
|
|
require.NoError(t, err)
|
|
assert.NotEqual(t, oldKey, newKey)
|
|
assert.Contains(t, newKey, "gchat_")
|
|
|
|
// Verify the new key works for lookup
|
|
fetched, err := svc.GetPlatformAppByAPIKey(newKey)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, pa.ID, fetched.ID)
|
|
}
|
|
|
|
// Test42_RegenerateAPIKey_NotFound verifies error when regenerating for nonexistent app.
|
|
func Test42_RegenerateAPIKey_NotFound(t *testing.T) {
|
|
_, svc := setupRBACService(t)
|
|
|
|
newKey, err := svc.RegenerateAPIKey(999)
|
|
require.Error(t, err)
|
|
assert.Empty(t, newKey)
|
|
}
|
|
|
|
// Test43_ListPlatformApps_WithAccountFilter verifies listing platform apps for an account.
|
|
func Test43_ListPlatformApps_WithAccountFilter(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
|
|
_, err := svc.CreatePlatformApp("Bot1", acc.ID, "api", "bot1")
|
|
require.NoError(t, err)
|
|
_, err = svc.CreatePlatformApp("Bot2", acc.ID, "agent_bot", "bot2")
|
|
require.NoError(t, err)
|
|
|
|
apps, err := svc.ListPlatformApps(acc.ID)
|
|
require.NoError(t, err)
|
|
assert.Len(t, apps, 2)
|
|
}
|
|
|
|
// Test44_ListPlatformApps_All verifies listing all platform apps (accountID=0).
|
|
func Test44_ListPlatformApps_All(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
|
|
_, err := svc.CreatePlatformApp("Global1", 0, "api", "global1")
|
|
require.NoError(t, err)
|
|
_, err = svc.CreatePlatformApp("Scoped1", acc.ID, "api", "scoped1")
|
|
require.NoError(t, err)
|
|
|
|
apps, err := svc.ListPlatformApps(0)
|
|
require.NoError(t, err)
|
|
assert.Len(t, apps, 2) // Returns all apps when accountID=0
|
|
}
|
|
|
|
// ============================================================
|
|
// RBACLookup Interface Tests
|
|
// ============================================================
|
|
|
|
// Test45_GetAccountUserRole verifies the RBACLookup interface method.
|
|
func Test45_GetAccountUserRole(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
user := createTestUserForRBAC(t, db)
|
|
|
|
_, err := svc.AddAccountUser(user.ID, acc.ID, "agent", 0, 0)
|
|
require.NoError(t, err)
|
|
|
|
role, err := svc.GetAccountUserRole(user.ID, acc.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, user.ID, role.UserID)
|
|
assert.Equal(t, acc.ID, role.AccountID)
|
|
assert.Equal(t, "agent", role.Role)
|
|
}
|
|
|
|
// Test46_GetCustomRolePermissions verifies the RBACLookup interface method.
|
|
func Test46_GetCustomRolePermissions(t *testing.T) {
|
|
db, svc := setupRBACService(t)
|
|
acc := createTestAccountForRBAC(t, db)
|
|
|
|
perms := auth.PermissionMatrixMap{
|
|
auth.DimensionConversationManage: auth.PermissionFull,
|
|
auth.DimensionContactManage: auth.PermissionRead,
|
|
}
|
|
cr, err := svc.CreateCustomRole(acc.ID, "LookupRole", perms, "test lookup")
|
|
require.NoError(t, err)
|
|
|
|
matrix, err := svc.GetCustomRolePermissions(cr.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, auth.PermissionFull, matrix[auth.DimensionConversationManage])
|
|
assert.Equal(t, auth.PermissionRead, matrix[auth.DimensionContactManage])
|
|
} |