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]) }