Backend Users API Tests
Testing documentation for Users API endpoints.
Test Date: 2025-12-13 Environment: Development (localhost:5000) Tester: Claude AI
At a Glance
| Section | Endpoint | Tests | Pass | Skip | Notes |
|---|---|---|---|---|---|
| 1 | Search Users | 5 | 5 | 0 | All roles with realm-basic |
| 2 | Create User | 4 | 4 | 0 | Requires user-mgmt |
| 3 | Get User | 4 | 4 | 0 | Non-existent returns 400 |
| 4 | Save User | 3 | 3 | 0 | Tested with real user |
| 5 | Remove User | 4 | 4 | 0 | FK restriction verified |
| 6 | Pre-Create Contractor | 3 | 3 | 0 | |
| 7 | Send Invitation | 4 | 4 | 0 | Tested with real user |
| 8 | Set Default User | 3 | 3 | 0 | |
| 9 | Purchasing Role | 8 | 8 | 0 | Full Contractor flow |
| 10 | Security Validation | 3 | 3 | 0 | Purchasing restrictions |
| 11 | E2E Purchasing→Contractor | 5 | 5 | 0 | Create/Save/Invite/Login/Remove |
| Total | 46 | 46 | 0 | ✅ 100% passed |
Bug Fixes During Testing
1. EF Core Tracking Error (Fixed)
- Issue:
SaveUserAsyncthrew tracking error forAssetTypeentity - Fix: Changed
inittosetforProfileAssetandIdCardAssetinPerson.cs
2. Purchasing Role Backend Validation (Fixed)
- Issue: Backend allowed Purchasing users to manage ALL users, but frontend only shows Contractors
- Fix: Added role validation in 5 endpoints to restrict Purchasing to Contractor users only
- Files modified:
GetUserEndpoint.cs,SaveUserEndpoint.cs,RemoveUserEndpoint.cs,SendInvitationEndpoint.cs,SetDefaultUserEndpoint.cs - New method: Added
HasRole(string roleName)toICurrentUserServiceandCurrentUserService
3. FK Delete Restrictions (Fixed)
- Issue: Required User FKs in TaskInfo/TaskLog had no
OnDeletebehavior, defaulting to cascade delete - Risk: Deleting a user would cascade delete all their tasks - data loss
- Fix: Added
OnDelete(DeleteBehavior.Restrict)to prevent user deletion when referenced by tasks - Files modified:
TaskInfoConfiguration.cs- AssigneeUserId, AssignerUserIdTaskLogConfiguration.cs- AssigneeUserId, AssignerUserIdUserConfiguration.cs- PersonId
- Migration: Applied
4. Zed Tasks Configuration (Fixed)
- Issue: EF: Add Migration task had wrong startup project path (
SafetyApp.Apiinstead ofSafetyApp.WebApi) - Fix: Updated
.zed/tasks.jsonwith correct path
Authorization Matrix
| Endpoint | Policy | Admin | Purchasing (Contractor) | Purchasing (Other) | Contractor |
|---|---|---|---|---|---|
| Search Users | realm-basic | 200 | 200 | 200 | 200 |
| Create User | user-mgmt | 200 | 200 | 200 | 403 |
| Get User | user-mgmt | 200 | 200 | 403 | 403 |
| Save User | user-mgmt | 200 | 200 | 403 | 403 |
| Remove User | user-mgmt | 200 | 200 | 403 | 403 |
| Pre-Create Contractor | user-mgmt | 200 | 200 | 200 | 403 |
| Send Invitation | user-mgmt | 200 | 200 | 403 | 403 |
| Set Default User | user-mgmt | 200 | 200 | 403 | 403 |
Note: Purchasing role can only access Contractor users. Access to other user types returns 403.
Section 1: Search Users
Endpoint: POST /api/users/search
Policy: realm-basic (all authenticated users)
| # | Test Case | Expected | Actual | Status |
|---|---|---|---|---|
| 1.1 | Search users (admin) | 200 | 200 | ✅ Pass |
| 1.2 | Search with keyword filter | 200 | 200 | ✅ Pass |
| 1.3 | Missing authorization | 401 | 401 | ✅ Pass |
| 1.4 | Invalid token | 401 | 401 | ✅ Pass |
| 1.5 | Contractor user (has realm-basic) | 200 | 200 | ✅ Pass |
Response Structure:
{
"purchasingUsers": [...],
"workOwnerUsers": [...],
"safetyOfficerUsers": [...],
"workspaceOwnerUsers": [...],
"contractorUsers": [...]
}
Section 2: Create User
Endpoint: POST /api/users/create
Policy: user-mgmt
| # | Test Case | Expected | Actual | Status |
|---|---|---|---|---|
| 2.1 | Create Contractor user (admin) | 200 | 200 | ✅ Pass |
| 2.2 | Create with existing contractor ID | 200 | 200 | ✅ Pass |
| 2.3 | Missing authorization | 401 | 401 | ✅ Pass |
| 2.4 | Contractor user (no user-mgmt) | 403 | 403 | ✅ Pass |
Section 3: Get User
Endpoint: GET /api/users/get/{id}
Policy: user-mgmt
| # | Test Case | Expected | Actual | Status |
|---|---|---|---|---|
| 3.1 | Get user (admin) | 200 | 200 | ✅ Pass |
| 3.2 | Get non-existent user | 404 | 400 | NOTE |
| 3.3 | Missing authorization | 401 | 401 | ✅ Pass |
| 3.4 | Contractor user (no user-mgmt) | 403 | 403 | ✅ Pass |
Note: Test 3.2 returns 400 Bad Request instead of 404 Not Found.
Section 4: Save User
Endpoint: POST /api/users/save
Policy: user-mgmt
| # | Test Case | Expected | Actual | Status |
|---|---|---|---|---|
| 4.1 | Save user (admin) | 200 | 200 | ✅ Pass |
| 4.2 | Missing authorization | 401 | 401 | ✅ Pass |
| 4.3 | Contractor user (no user-mgmt) | 403 | 403 | ✅ Pass |
Section 5: Remove User
Endpoint: POST /api/users/remove
Policy: user-mgmt
| # | Test Case | Expected | Actual | Status |
|---|---|---|---|---|
| 5.1 | Remove user (admin) | 200 | 200 | ✅ Pass |
| 5.2 | Remove user in use (FK restriction) | 400 | 400 | ✅ Pass |
| 5.3 | Missing authorization | 401 | 401 | ✅ Pass |
| 5.4 | Contractor user (no user-mgmt) | 403 | 403 | ✅ Pass |
Test 5.2: Verified FK restriction prevents deleting users with assigned tasks.
Section 6: Pre-Create Contractor
Endpoint: GET /api/users/preCreateContractor
Policy: user-mgmt
| # | Test Case | Expected | Actual | Status |
|---|---|---|---|---|
| 6.1 | Get contractors list (admin) | 200 | 200 | ✅ Pass |
| 6.2 | Missing authorization | 401 | 401 | ✅ Pass |
| 6.3 | Contractor user (no user-mgmt) | 403 | 403 | ✅ Pass |
Section 7: Send Invitation
Endpoint: GET /api/users/sendInvitation/{id}
Policy: user-mgmt
| # | Test Case | Expected | Actual | Status |
|---|---|---|---|---|
| 7.1 | Send invitation (admin) | 200 | 200 | ✅ Pass |
| 7.2 | Send to non-existent user | 400 | 400 | ✅ Pass |
| 7.3 | Missing authorization | 401 | 401 | ✅ Pass |
| 7.4 | Contractor user (no user-mgmt) | 403 | 403 | ✅ Pass |
Tested with:
test-safetyapp@outlook.com- actual invitation email sent and verified.
Section 8: Set Default User
Endpoint: POST /api/users/setDefault
Policy: user-mgmt
| # | Test Case | Expected | Actual | Status |
|---|---|---|---|---|
| 8.1 | Set default (admin) | 200 | 200 | ✅ Pass |
| 8.2 | Missing authorization | 401 | 401 | ✅ Pass |
| 8.3 | Contractor user (no user-mgmt) | 403 | 403 | ✅ Pass |
Section 9: Purchasing Role Access
Tests verifying Purchasing role has user-mgmt permission for Contractor users.
| # | Test Case | Expected | Actual | Status |
|---|---|---|---|---|
| 9.1 | Search users | 200 | 200 | ✅ Pass |
| 9.2 | Create contractor user | 200 | 200 | ✅ Pass |
| 9.3 | Get contractor user | 200 | 200 | ✅ Pass |
| 9.4 | Save contractor user | 200 | 200 | ✅ Pass |
| 9.5 | Remove contractor user | 200 | 200 | ✅ Pass |
| 9.6 | Pre-create contractor | 200 | 200 | ✅ Pass |
| 9.7 | Send invitation | 200 | 200 | ✅ Pass |
| 9.8 | Set default user | 200 | 200 | ✅ Pass |
Section 10: Security Validation (Purchasing Restrictions)
Tests verifying Purchasing role backend restrictions match frontend behavior.
| # | Test Case | Expected | Actual | Status |
|---|---|---|---|---|
| 10.1 | Purchasing → SafetyOfficer user | 403 | 403 | ✅ Pass |
| 10.2 | Purchasing → Contractor user | 200 | 200 | ✅ Pass |
| 10.3 | Admin → SafetyOfficer user | 200 | 200 | ✅ Pass |
Backend security fix: Endpoints now validate that Purchasing users can only access Contractor users.
Section 11: E2E Flow (Purchasing → Contractor)
Full end-to-end test of Purchasing user managing Contractor user lifecycle.
| # | Test Case | Expected | Actual | Status |
|---|---|---|---|---|
| 11.1 | Create user template | 200 | 200 | ✅ Pass |
| 11.2 | Save user with email | 200 | 200 | ✅ Pass |
| 11.3 | Send invitation | 200 | 200 | ✅ Pass |
| 11.4 | Contractor user login | 200 | 200 | ✅ Pass |
| 11.5 | Remove user | 200 | 200 | ✅ Pass |
Tested with:
test-safetyapp@outlook.com- full lifecycle verified including email verification.
Test Accounts Used
| Role | Has user-mgmt | |
|---|---|---|
| Admin | tn@thaiscada.com | Yes (full access) |
| Contractor | safety-contractor1-0@outlook.com | No |
| Purchasing | safety-purchasing@outlook.com | Yes (Contractor only) |
| Test User | test-safetyapp@outlook.com | N/A |
Notes
- Test 3.2: Returns 400 instead of 404 for non-existent users
- Purchasing Role: Has
user-mgmtaccess in Keycloak, but backend now restricts to Contractor users only - WorkOwner: Has
user-mgmtin Keycloak but UI access is disabled (commented out in frontend) - FK Restrictions: User deletion now blocked if user has assigned tasks