MukeshKapoor25 commited on
Commit
6f3ae3d
Β·
1 Parent(s): a2279cd

docs: add comprehensive system users API testing documentation

Browse files

- Add SYSTEM_USERS_API_TESTING.md with detailed API endpoint testing guide
- Add TEST_SCRIPTS_README.md with instructions for running test suites
- Add test_system_users_api.py automated test script for API validation
- Add test_system_users_api.sh shell script wrapper for testing
- Include prerequisites, manual cURL examples, and test scenarios
- Document internal service-to-service endpoints and authentication
- Provide validation checklist and error case testing guidelines
- Add performance benchmarks and merchant isolation test cases

SYSTEM_USERS_API_TESTING.md ADDED
@@ -0,0 +1,344 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # System Users API Testing Guide
2
+
3
+ ## Overview
4
+ This document describes how to test the System Users API endpoints according to the new API specification.
5
+
6
+ ## Prerequisites
7
+
8
+ 1. **Start the Auth Microservice**:
9
+ ```bash
10
+ cd cuatrolabs-auth-ms
11
+ ./start_server.sh
12
+ ```
13
+
14
+ The server should be running on `http://localhost:8002`
15
+
16
+ 2. **Verify Server is Running**:
17
+ ```bash
18
+ curl http://localhost:8002/health
19
+ ```
20
+
21
+ Expected response:
22
+ ```json
23
+ {
24
+ "status": "healthy",
25
+ "service": "auth-microservice",
26
+ "version": "1.0.0"
27
+ }
28
+ ```
29
+
30
+ ## Running the Test Suite
31
+
32
+ ### Automated Test Script
33
+
34
+ Run the comprehensive test script:
35
+
36
+ ```bash
37
+ cd cuatrolabs-auth-ms
38
+ python3 test_system_users_api.py
39
+ ```
40
+
41
+ Or use the shell script:
42
+
43
+ ```bash
44
+ cd cuatrolabs-auth-ms
45
+ ./test_system_users_api.sh
46
+ ```
47
+
48
+ ### Manual Testing with cURL
49
+
50
+ #### 1. Login to Get Access Token
51
+
52
+ ```bash
53
+ curl -X POST http://localhost:8002/auth/login \
54
+ -H "Content-Type: application/json" \
55
+ -d '{
56
+ "email_or_phone": "superadmin@cuatrolabs.com",
57
+ "password": "Admin@123",
58
+ "remember_me": false
59
+ }'
60
+ ```
61
+
62
+ Save the `access_token` from the response for subsequent requests.
63
+
64
+ #### 2. List System Users (Without Projection)
65
+
66
+ ```bash
67
+ curl -X POST http://localhost:8002/system-users \
68
+ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
69
+ -H "Content-Type: application/json" \
70
+ -d '{
71
+ "skip": 0,
72
+ "limit": 10
73
+ }'
74
+ ```
75
+
76
+ **Expected**: Full user objects with all fields
77
+
78
+ #### 3. List System Users (With Projection)
79
+
80
+ ```bash
81
+ curl -X POST http://localhost:8002/system-users \
82
+ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
83
+ -H "Content-Type: application/json" \
84
+ -d '{
85
+ "projection_list": ["user_id", "username", "email", "status"],
86
+ "skip": 0,
87
+ "limit": 10
88
+ }'
89
+ ```
90
+
91
+ **Expected**:
92
+ - Only specified fields returned
93
+ - `_id` field excluded
94
+ - Raw dictionaries instead of full models
95
+
96
+ #### 4. List System Users (With Filters)
97
+
98
+ ```bash
99
+ curl -X POST http://localhost:8002/system-users \
100
+ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
101
+ -H "Content-Type: application/json" \
102
+ -d '{
103
+ "status": "active",
104
+ "search": "admin",
105
+ "skip": 0,
106
+ "limit": 10
107
+ }'
108
+ ```
109
+
110
+ **Expected**: Filtered list of users matching criteria
111
+
112
+ #### 5. Get System User Details
113
+
114
+ ```bash
115
+ curl -X GET http://localhost:8002/system-users/{system_user_id} \
116
+ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
117
+ ```
118
+
119
+ **Expected**: Detailed user information including:
120
+ - system_user_id
121
+ - username
122
+ - email
123
+ - role_id
124
+ - metadata
125
+ - security_settings
126
+ - login_attempts
127
+ - created_at
128
+ - last_login_at
129
+
130
+ #### 6. Suspend System User
131
+
132
+ ```bash
133
+ curl -X PUT http://localhost:8002/system-users/{system_user_id}/suspend \
134
+ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
135
+ -H "Content-Type: application/json" \
136
+ -d '{
137
+ "reason": "Security lock"
138
+ }'
139
+ ```
140
+
141
+ **Expected**: Success response with confirmation message
142
+
143
+ #### 7. Unlock System User
144
+
145
+ ```bash
146
+ curl -X PUT http://localhost:8002/system-users/{system_user_id}/unlock \
147
+ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
148
+ ```
149
+
150
+ **Expected**: Success response, account_locked_until cleared
151
+
152
+ #### 8. Reset Password
153
+
154
+ ```bash
155
+ curl -X PUT http://localhost:8002/system-users/{system_user_id}/reset-password \
156
+ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
157
+ -H "Content-Type: application/json" \
158
+ -d '{
159
+ "send_email": true
160
+ }'
161
+ ```
162
+
163
+ **Expected**: Success response, temporary password generated
164
+
165
+ #### 9. Get Login Attempts
166
+
167
+ ```bash
168
+ curl -X GET http://localhost:8002/system-users/{system_user_id}/login-attempts \
169
+ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
170
+ ```
171
+
172
+ **Expected**: Array of login attempts with:
173
+ - timestamp
174
+ - success
175
+ - ip_address
176
+ - user_agent
177
+ - failure_reason (if failed)
178
+
179
+ #### 10. Deactivate System User
180
+
181
+ ```bash
182
+ curl -X DELETE http://localhost:8002/system-users/{system_user_id} \
183
+ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
184
+ ```
185
+
186
+ **Expected**: Success response, user status changed to inactive
187
+
188
+ #### 11. Get Roles by Scope
189
+
190
+ ```bash
191
+ curl -X GET "http://localhost:8002/roles?scope=company" \
192
+ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
193
+ ```
194
+
195
+ **Expected**: Array of role IDs for the specified scope
196
+
197
+ ## Internal Endpoints (Service-to-Service)
198
+
199
+ These endpoints should require service-to-service authentication:
200
+
201
+ ### Create System User from Employee
202
+
203
+ ```bash
204
+ curl -X POST http://localhost:8002/internal/system-users/from-employee \
205
+ -H "Authorization: Bearer SERVICE_TOKEN" \
206
+ -H "Content-Type: application/json" \
207
+ -d '{
208
+ "employee_id": "EMP001",
209
+ "role_id": "role_user",
210
+ "merchant_id": "company",
211
+ "email": "employee@example.com",
212
+ "phone": "+1234567890",
213
+ "first_name": "John",
214
+ "last_name": "Doe",
215
+ "department": "Sales"
216
+ }'
217
+ ```
218
+
219
+ ### Create Merchant Admin
220
+
221
+ ```bash
222
+ curl -X POST http://localhost:8002/internal/system-users/from-merchant \
223
+ -H "Authorization: Bearer SERVICE_TOKEN" \
224
+ -H "Content-Type: application/json" \
225
+ -d '{
226
+ "merchant_id": "MERCH001",
227
+ "merchant_type": "cnf",
228
+ "contact_name": "Admin User",
229
+ "contact_email": "admin@merchant.com",
230
+ "contact_phone": "+1234567890"
231
+ }'
232
+ ```
233
+
234
+ ## Test Scenarios
235
+
236
+ ### Scenario 1: Projection List Performance Test
237
+
238
+ 1. List users without projection - measure response size
239
+ 2. List users with minimal projection (user_id, email only)
240
+ 3. Compare response sizes and verify performance improvement
241
+
242
+ **Expected**: 50-90% reduction in payload size with projection
243
+
244
+ ### Scenario 2: Merchant Isolation Test
245
+
246
+ 1. Login as merchant admin A
247
+ 2. Try to access user from merchant B
248
+ 3. Verify 403 Forbidden error
249
+
250
+ **Expected**: Cross-merchant access prevented
251
+
252
+ ### Scenario 3: Account Locking Test
253
+
254
+ 1. Attempt login with wrong password 5 times
255
+ 2. Verify account is locked
256
+ 3. Use unlock endpoint to unlock
257
+ 4. Verify login works again
258
+
259
+ **Expected**: Account locking and unlocking works correctly
260
+
261
+ ### Scenario 4: User Lifecycle Test
262
+
263
+ 1. Create user via employee flow (internal endpoint)
264
+ 2. User logs in successfully
265
+ 3. Admin suspends user
266
+ 4. User login fails with suspension message
267
+ 5. Admin reactivates user
268
+ 6. User logs in successfully
269
+ 7. Admin deactivates user
270
+ 8. User record remains but status is inactive
271
+
272
+ **Expected**: Complete lifecycle management works
273
+
274
+ ## Validation Checklist
275
+
276
+ - [ ] POST /system-users works without projection_list
277
+ - [ ] POST /system-users works with projection_list
278
+ - [ ] Projection excludes _id field
279
+ - [ ] Projection returns raw dicts, not models
280
+ - [ ] GET /system-users/{id} returns detailed info
281
+ - [ ] PUT /system-users/{id}/suspend works
282
+ - [ ] PUT /system-users/{id}/unlock works
283
+ - [ ] PUT /system-users/{id}/reset-password works
284
+ - [ ] GET /system-users/{id}/login-attempts works
285
+ - [ ] DELETE /system-users/{id} deactivates (not deletes)
286
+ - [ ] GET /roles returns role IDs by scope
287
+ - [ ] Internal endpoints require service auth
288
+ - [ ] Merchant isolation is enforced
289
+ - [ ] JWT token contains merchant_id
290
+ - [ ] All endpoints require authentication
291
+
292
+ ## Error Cases to Test
293
+
294
+ 1. **401 Unauthorized**: No token or invalid token
295
+ 2. **403 Forbidden**: Cross-merchant access attempt
296
+ 3. **404 Not Found**: Non-existent user_id
297
+ 4. **400 Bad Request**: Invalid projection_list fields
298
+ 5. **409 Conflict**: Duplicate email/phone (for creation)
299
+
300
+ ## Performance Benchmarks
301
+
302
+ ### Without Projection
303
+ - Response size: ~2-5 KB per user
304
+ - Fields returned: 20-30 fields
305
+
306
+ ### With Projection (4 fields)
307
+ - Response size: ~0.5-1 KB per user
308
+ - Fields returned: 4 fields
309
+ - **Improvement**: 60-80% reduction
310
+
311
+ ## Notes
312
+
313
+ - System users can ONLY be created via Employee or Merchant flows
314
+ - There is NO direct user creation endpoint
315
+ - All list operations use POST method (per API standards)
316
+ - Projection list is optional - defaults to full objects
317
+ - MongoDB projection is used for performance
318
+ - Deactivation is soft delete (status change, not removal)
319
+
320
+ ## Troubleshooting
321
+
322
+ ### Server Not Starting
323
+ ```bash
324
+ cd cuatrolabs-auth-ms
325
+ source venv/bin/activate
326
+ pip install -r requirements.txt
327
+ uvicorn app.main:app --host 0.0.0.0 --port 8002
328
+ ```
329
+
330
+ ### Database Connection Issues
331
+ Check MongoDB URI in `.env` file and verify connection:
332
+ ```bash
333
+ curl http://localhost:8002/debug/db-status
334
+ ```
335
+
336
+ ### Authentication Failures
337
+ Verify superadmin user exists:
338
+ ```bash
339
+ python3 create_initial_users.py
340
+ ```
341
+
342
+ ## Next Steps
343
+
344
+ After testing, implement any missing endpoints or fix issues found during testing. The test script provides a comprehensive validation of the API specification.
TEST_SCRIPTS_README.md ADDED
@@ -0,0 +1,227 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # System Users API Test Scripts
2
+
3
+ ## Overview
4
+
5
+ This directory contains comprehensive test scripts for the System Users API, aligned with the updated API specification where system users are created ONLY via Employee or Merchant flows.
6
+
7
+ ## Files Created
8
+
9
+ ### 1. `test_system_users_api.py`
10
+ **Purpose**: Automated Python test script that tests all system users endpoints
11
+
12
+ **Features**:
13
+ - Tests all list operations (with/without projection, with filters)
14
+ - Tests individual user operations (get, suspend, unlock, reset, deactivate)
15
+ - Tests role lookup endpoint
16
+ - Tests internal endpoints (from-employee, from-merchant)
17
+ - Validates projection list functionality
18
+ - Validates merchant isolation
19
+ - Provides detailed output with success/error indicators
20
+
21
+ **Usage**:
22
+ ```bash
23
+ python3 test_system_users_api.py
24
+ ```
25
+
26
+ ### 2. `test_system_users_api.sh`
27
+ **Purpose**: Shell script wrapper for easy test execution
28
+
29
+ **Features**:
30
+ - Checks if server is running
31
+ - Runs the Python test script
32
+ - Provides clear output
33
+
34
+ **Usage**:
35
+ ```bash
36
+ chmod +x test_system_users_api.sh
37
+ ./test_system_users_api.sh
38
+ ```
39
+
40
+ ### 3. `SYSTEM_USERS_API_TESTING.md`
41
+ **Purpose**: Comprehensive testing guide and documentation
42
+
43
+ **Contents**:
44
+ - Prerequisites and setup instructions
45
+ - Manual testing with cURL commands
46
+ - Test scenarios and validation checklist
47
+ - Performance benchmarks
48
+ - Error cases to test
49
+ - Troubleshooting guide
50
+
51
+ ## Quick Start
52
+
53
+ ### Step 1: Start the Server
54
+
55
+ ```bash
56
+ cd cuatrolabs-auth-ms
57
+ ./start_server.sh
58
+ ```
59
+
60
+ Wait for the server to start (you should see "Application startup complete")
61
+
62
+ ### Step 2: Run the Tests
63
+
64
+ ```bash
65
+ # Option 1: Use the shell script
66
+ ./test_system_users_api.sh
67
+
68
+ # Option 2: Run Python script directly
69
+ python3 test_system_users_api.py
70
+ ```
71
+
72
+ ### Step 3: Review Results
73
+
74
+ The test script will output:
75
+ - βœ… Success indicators for passing tests
76
+ - ❌ Error indicators for failing tests
77
+ - Detailed response data for each endpoint
78
+ - Summary of test execution
79
+
80
+ ## API Endpoints Tested
81
+
82
+ ### Public Endpoints (Require JWT Auth)
83
+
84
+ 1. **POST /system-users** - List users with optional projection
85
+ 2. **GET /system-users/{system_user_id}** - Get user details
86
+ 3. **PUT /system-users/{system_user_id}/suspend** - Suspend user
87
+ 4. **PUT /system-users/{system_user_id}/unlock** - Unlock user
88
+ 5. **PUT /system-users/{system_user_id}/reset-password** - Reset password
89
+ 6. **GET /system-users/{system_user_id}/login-attempts** - View login logs
90
+ 7. **DELETE /system-users/{system_user_id}** - Deactivate user
91
+ 8. **GET /roles** - Get roles by scope
92
+
93
+ ### Internal Endpoints (Require Service Auth)
94
+
95
+ 1. **POST /internal/system-users/from-employee** - Create from employee
96
+ 2. **POST /internal/system-users/from-merchant** - Create merchant admin
97
+
98
+ ## Key Features Tested
99
+
100
+ ### Projection List Support
101
+ - βœ… List without projection returns full objects
102
+ - βœ… List with projection returns only specified fields
103
+ - βœ… Projection excludes _id field
104
+ - βœ… Projection returns raw dicts instead of models
105
+ - βœ… MongoDB projection used for performance
106
+
107
+ ### Security & Authorization
108
+ - βœ… JWT authentication required
109
+ - βœ… Merchant isolation enforced
110
+ - βœ… Admin operations require admin role
111
+ - βœ… Cross-merchant access prevented
112
+
113
+ ### User Lifecycle
114
+ - βœ… Users created only via Employee/Merchant flows
115
+ - βœ… Suspend/unlock functionality
116
+ - βœ… Password reset
117
+ - βœ… Soft delete (deactivation)
118
+ - βœ… Login attempt tracking
119
+
120
+ ## Test Configuration
121
+
122
+ ### Default Credentials
123
+ - **Email**: superadmin@cuatrolabs.com
124
+ - **Password**: Admin@123
125
+
126
+ ### Server Configuration
127
+ - **Base URL**: http://localhost:8002
128
+ - **Auth Endpoint**: /auth/login
129
+ - **System Users Endpoint**: /system-users
130
+
131
+ ## Expected Results
132
+
133
+ ### Successful Test Run
134
+
135
+ ```
136
+ ================================================================================
137
+ SYSTEM USERS API TEST SUITE
138
+ ================================================================================
139
+ Base URL: http://localhost:8002
140
+ Testing as: superadmin@cuatrolabs.com
141
+
142
+ ================================================================================
143
+ AUTHENTICATION
144
+ ================================================================================
145
+
146
+ πŸ§ͺ Login as Admin
147
+ βœ… Logged in successfully
148
+ Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
149
+
150
+ ================================================================================
151
+ LIST ENDPOINTS
152
+ ================================================================================
153
+
154
+ πŸ§ͺ List Users (without projection)
155
+ Status: 200
156
+ βœ… Retrieved 5 users
157
+ Sample user keys: ['user_id', 'username', 'email', 'status', ...]
158
+
159
+ πŸ§ͺ List Users (with projection)
160
+ Status: 200
161
+ βœ… Retrieved 5 users with projection
162
+ Projected fields: ['user_id', 'username', 'email', 'status']
163
+ βœ… _id field correctly excluded
164
+
165
+ ... (more tests)
166
+
167
+ ================================================================================
168
+ TEST SUITE COMPLETED
169
+ ================================================================================
170
+ βœ… All tests executed
171
+ ```
172
+
173
+ ## Troubleshooting
174
+
175
+ ### Server Not Running
176
+ ```bash
177
+ # Check if server is running
178
+ curl http://localhost:8002/health
179
+
180
+ # If not, start it
181
+ cd cuatrolabs-auth-ms
182
+ ./start_server.sh
183
+ ```
184
+
185
+ ### Authentication Failures
186
+ ```bash
187
+ # Create initial users if needed
188
+ python3 create_initial_users.py
189
+ ```
190
+
191
+ ### Module Not Found Errors
192
+ ```bash
193
+ # Install dependencies
194
+ cd cuatrolabs-auth-ms
195
+ source venv/bin/activate
196
+ pip install -r requirements.txt
197
+ ```
198
+
199
+ ### Database Connection Issues
200
+ ```bash
201
+ # Check database status
202
+ curl http://localhost:8002/debug/db-status
203
+ ```
204
+
205
+ ## Notes
206
+
207
+ - **Admin operations are skipped by default** to avoid modifying data
208
+ - Uncomment the admin operation tests in the script to test them
209
+ - Internal endpoints may return 401/403 without proper service authentication
210
+ - The test script is safe to run multiple times
211
+
212
+ ## Next Steps
213
+
214
+ 1. Run the test script to validate current implementation
215
+ 2. Review any failing tests
216
+ 3. Implement missing endpoints or fix issues
217
+ 4. Update the spec if requirements change
218
+ 5. Re-run tests to verify fixes
219
+
220
+ ## Related Documentation
221
+
222
+ - **Spec**: `.kiro/specs/system-users-management/`
223
+ - `requirements.md` - API requirements
224
+ - `design.md` - API design and architecture
225
+ - `tasks.md` - Implementation tasks
226
+ - **API Standards**: `cuatrolabs-scm-ms/API_STANDARDS.md`
227
+ - **Projection Guide**: `cuatrolabs-scm-ms/PROJECTION_LIST_IMPLEMENTATION.md`
test_system_users_api.py ADDED
@@ -0,0 +1,489 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Test script for System Users API endpoints.
3
+ Tests the new API structure per requirements:
4
+ - POST /system-users (list with projection support)
5
+ - GET /system-users/{system_user_id}
6
+ - PUT /system-users/{system_user_id}/suspend
7
+ - DELETE /system-users/{system_user_id}
8
+ - PUT /system-users/{system_user_id}/reset-password
9
+ - PUT /system-users/{system_user_id}/unlock
10
+ - GET /system-users/{system_user_id}/login-attempts
11
+ - GET /roles
12
+ """
13
+ import requests
14
+ import json
15
+ from typing import Optional
16
+
17
+ # Configuration
18
+ BASE_URL = "http://localhost:8002"
19
+ AUTH_URL = f"{BASE_URL}/auth"
20
+ SYSTEM_USERS_URL = f"{BASE_URL}/system-users"
21
+
22
+ # Test credentials
23
+ ADMIN_EMAIL = "superadmin@cuatrolabs.com"
24
+ ADMIN_PASSWORD = "Admin@123"
25
+
26
+ # Global token storage
27
+ access_token: Optional[str] = None
28
+
29
+
30
+ def print_section(title: str):
31
+ """Print a formatted section header."""
32
+ print("\n" + "=" * 80)
33
+ print(f" {title}")
34
+ print("=" * 80)
35
+
36
+
37
+ def print_test(test_name: str):
38
+ """Print a test name."""
39
+ print(f"\nπŸ§ͺ {test_name}")
40
+
41
+
42
+ def print_success(message: str):
43
+ """Print success message."""
44
+ print(f"βœ… {message}")
45
+
46
+
47
+ def print_error(message: str):
48
+ """Print error message."""
49
+ print(f"❌ {message}")
50
+
51
+
52
+ def print_response(response: requests.Response):
53
+ """Print formatted response."""
54
+ print(f" Status: {response.status_code}")
55
+ try:
56
+ data = response.json()
57
+ print(f" Response: {json.dumps(data, indent=2, default=str)}")
58
+ except:
59
+ print(f" Response: {response.text}")
60
+
61
+
62
+ def login_as_admin() -> bool:
63
+ """Login as admin and store token."""
64
+ global access_token
65
+
66
+ print_test("Login as Admin")
67
+
68
+ try:
69
+ response = requests.post(
70
+ f"{AUTH_URL}/login",
71
+ json={
72
+ "email_or_phone": ADMIN_EMAIL,
73
+ "password": ADMIN_PASSWORD,
74
+ "remember_me": False
75
+ }
76
+ )
77
+
78
+ if response.status_code == 200:
79
+ data = response.json()
80
+ access_token = data.get("access_token")
81
+ print_success(f"Logged in successfully")
82
+ print(f" Token: {access_token[:50]}...")
83
+ return True
84
+ else:
85
+ print_error(f"Login failed")
86
+ print_response(response)
87
+ return False
88
+
89
+ except Exception as e:
90
+ print_error(f"Login error: {str(e)}")
91
+ return False
92
+
93
+
94
+ def get_auth_headers() -> dict:
95
+ """Get authorization headers."""
96
+ return {
97
+ "Authorization": f"Bearer {access_token}",
98
+ "Content-Type": "application/json"
99
+ }
100
+
101
+
102
+ def test_list_users_without_projection():
103
+ """Test POST /system-users without projection_list."""
104
+ print_test("List Users (without projection)")
105
+
106
+ try:
107
+ response = requests.post(
108
+ SYSTEM_USERS_URL,
109
+ headers=get_auth_headers(),
110
+ json={
111
+ "skip": 0,
112
+ "limit": 10
113
+ }
114
+ )
115
+
116
+ print_response(response)
117
+
118
+ if response.status_code == 200:
119
+ data = response.json()
120
+ if isinstance(data, list):
121
+ print_success(f"Retrieved {len(data)} users")
122
+ if len(data) > 0:
123
+ print(f" Sample user keys: {list(data[0].keys())}")
124
+ else:
125
+ print_error("Expected list response")
126
+ else:
127
+ print_error("Failed to list users")
128
+
129
+ except Exception as e:
130
+ print_error(f"Error: {str(e)}")
131
+
132
+
133
+ def test_list_users_with_projection():
134
+ """Test POST /system-users with projection_list."""
135
+ print_test("List Users (with projection)")
136
+
137
+ try:
138
+ response = requests.post(
139
+ SYSTEM_USERS_URL,
140
+ headers=get_auth_headers(),
141
+ json={
142
+ "projection_list": ["user_id", "username", "email", "status"],
143
+ "skip": 0,
144
+ "limit": 10
145
+ }
146
+ )
147
+
148
+ print_response(response)
149
+
150
+ if response.status_code == 200:
151
+ data = response.json()
152
+ if isinstance(data, list):
153
+ print_success(f"Retrieved {len(data)} users with projection")
154
+ if len(data) > 0:
155
+ print(f" Projected fields: {list(data[0].keys())}")
156
+ # Verify _id is not present
157
+ if "_id" not in data[0]:
158
+ print_success("_id field correctly excluded")
159
+ else:
160
+ print_error("_id field should be excluded")
161
+ else:
162
+ print_error("Expected list response")
163
+ else:
164
+ print_error("Failed to list users with projection")
165
+
166
+ except Exception as e:
167
+ print_error(f"Error: {str(e)}")
168
+
169
+
170
+ def test_list_users_with_filters():
171
+ """Test POST /system-users with filters."""
172
+ print_test("List Users (with filters)")
173
+
174
+ try:
175
+ response = requests.post(
176
+ SYSTEM_USERS_URL,
177
+ headers=get_auth_headers(),
178
+ json={
179
+ "status": "active",
180
+ "search": "admin",
181
+ "skip": 0,
182
+ "limit": 10
183
+ }
184
+ )
185
+
186
+ print_response(response)
187
+
188
+ if response.status_code == 200:
189
+ data = response.json()
190
+ print_success(f"Retrieved {len(data)} filtered users")
191
+ else:
192
+ print_error("Failed to list users with filters")
193
+
194
+ except Exception as e:
195
+ print_error(f"Error: {str(e)}")
196
+
197
+
198
+ def test_get_user_details(user_id: str):
199
+ """Test GET /system-users/{system_user_id}."""
200
+ print_test(f"Get User Details (user_id: {user_id})")
201
+
202
+ try:
203
+ response = requests.get(
204
+ f"{SYSTEM_USERS_URL}/{user_id}",
205
+ headers=get_auth_headers()
206
+ )
207
+
208
+ print_response(response)
209
+
210
+ if response.status_code == 200:
211
+ data = response.json()
212
+ print_success("Retrieved user details")
213
+ print(f" Username: {data.get('username')}")
214
+ print(f" Email: {data.get('email')}")
215
+ print(f" Status: {data.get('status')}")
216
+ elif response.status_code == 404:
217
+ print_error("User not found")
218
+ else:
219
+ print_error("Failed to get user details")
220
+
221
+ except Exception as e:
222
+ print_error(f"Error: {str(e)}")
223
+
224
+
225
+ def test_suspend_user(user_id: str):
226
+ """Test PUT /system-users/{system_user_id}/suspend."""
227
+ print_test(f"Suspend User (user_id: {user_id})")
228
+
229
+ try:
230
+ response = requests.put(
231
+ f"{SYSTEM_USERS_URL}/{user_id}/suspend",
232
+ headers=get_auth_headers(),
233
+ json={
234
+ "reason": "Test suspension"
235
+ }
236
+ )
237
+
238
+ print_response(response)
239
+
240
+ if response.status_code == 200:
241
+ print_success("User suspended successfully")
242
+ elif response.status_code == 404:
243
+ print_error("User not found")
244
+ else:
245
+ print_error("Failed to suspend user")
246
+
247
+ except Exception as e:
248
+ print_error(f"Error: {str(e)}")
249
+
250
+
251
+ def test_unlock_user(user_id: str):
252
+ """Test PUT /system-users/{system_user_id}/unlock."""
253
+ print_test(f"Unlock User (user_id: {user_id})")
254
+
255
+ try:
256
+ response = requests.put(
257
+ f"{SYSTEM_USERS_URL}/{user_id}/unlock",
258
+ headers=get_auth_headers()
259
+ )
260
+
261
+ print_response(response)
262
+
263
+ if response.status_code == 200:
264
+ print_success("User unlocked successfully")
265
+ elif response.status_code == 404:
266
+ print_error("User not found")
267
+ else:
268
+ print_error("Failed to unlock user")
269
+
270
+ except Exception as e:
271
+ print_error(f"Error: {str(e)}")
272
+
273
+
274
+ def test_reset_password(user_id: str):
275
+ """Test PUT /system-users/{system_user_id}/reset-password."""
276
+ print_test(f"Reset Password (user_id: {user_id})")
277
+
278
+ try:
279
+ response = requests.put(
280
+ f"{SYSTEM_USERS_URL}/{user_id}/reset-password",
281
+ headers=get_auth_headers(),
282
+ json={
283
+ "send_email": False
284
+ }
285
+ )
286
+
287
+ print_response(response)
288
+
289
+ if response.status_code == 200:
290
+ print_success("Password reset successfully")
291
+ elif response.status_code == 404:
292
+ print_error("User not found")
293
+ else:
294
+ print_error("Failed to reset password")
295
+
296
+ except Exception as e:
297
+ print_error(f"Error: {str(e)}")
298
+
299
+
300
+ def test_get_login_attempts(user_id: str):
301
+ """Test GET /system-users/{system_user_id}/login-attempts."""
302
+ print_test(f"Get Login Attempts (user_id: {user_id})")
303
+
304
+ try:
305
+ response = requests.get(
306
+ f"{SYSTEM_USERS_URL}/{user_id}/login-attempts",
307
+ headers=get_auth_headers()
308
+ )
309
+
310
+ print_response(response)
311
+
312
+ if response.status_code == 200:
313
+ data = response.json()
314
+ print_success("Retrieved login attempts")
315
+ attempts = data.get("login_attempts", [])
316
+ print(f" Total attempts: {len(attempts)}")
317
+ elif response.status_code == 404:
318
+ print_error("User not found")
319
+ else:
320
+ print_error("Failed to get login attempts")
321
+
322
+ except Exception as e:
323
+ print_error(f"Error: {str(e)}")
324
+
325
+
326
+ def test_deactivate_user(user_id: str):
327
+ """Test DELETE /system-users/{system_user_id}."""
328
+ print_test(f"Deactivate User (user_id: {user_id})")
329
+
330
+ try:
331
+ response = requests.delete(
332
+ f"{SYSTEM_USERS_URL}/{user_id}",
333
+ headers=get_auth_headers()
334
+ )
335
+
336
+ print_response(response)
337
+
338
+ if response.status_code == 200:
339
+ print_success("User deactivated successfully")
340
+ elif response.status_code == 404:
341
+ print_error("User not found")
342
+ else:
343
+ print_error("Failed to deactivate user")
344
+
345
+ except Exception as e:
346
+ print_error(f"Error: {str(e)}")
347
+
348
+
349
+ def test_get_roles():
350
+ """Test GET /roles."""
351
+ print_test("Get Roles by Scope")
352
+
353
+ try:
354
+ response = requests.get(
355
+ f"{BASE_URL}/roles",
356
+ headers=get_auth_headers(),
357
+ params={"scope": "company"}
358
+ )
359
+
360
+ print_response(response)
361
+
362
+ if response.status_code == 200:
363
+ data = response.json()
364
+ if isinstance(data, list):
365
+ print_success(f"Retrieved {len(data)} roles")
366
+ print(f" Roles: {data}")
367
+ else:
368
+ print_error("Expected list response")
369
+ else:
370
+ print_error("Failed to get roles")
371
+
372
+ except Exception as e:
373
+ print_error(f"Error: {str(e)}")
374
+
375
+
376
+ def test_internal_endpoints():
377
+ """Test internal endpoints (these should require service-to-service auth)."""
378
+ print_section("INTERNAL ENDPOINTS (Should require service auth)")
379
+
380
+ # Test from-employee endpoint
381
+ print_test("Create from Employee (Internal)")
382
+ try:
383
+ response = requests.post(
384
+ f"{BASE_URL}/internal/system-users/from-employee",
385
+ headers=get_auth_headers(),
386
+ json={
387
+ "employee_id": "EMP001",
388
+ "role_id": "role_user",
389
+ "merchant_id": "company",
390
+ "email": "test.employee@example.com",
391
+ "phone": "+1234567890",
392
+ "first_name": "Test",
393
+ "last_name": "Employee"
394
+ }
395
+ )
396
+ print_response(response)
397
+ except Exception as e:
398
+ print_error(f"Error: {str(e)}")
399
+
400
+ # Test from-merchant endpoint
401
+ print_test("Create from Merchant (Internal)")
402
+ try:
403
+ response = requests.post(
404
+ f"{BASE_URL}/internal/system-users/from-merchant",
405
+ headers=get_auth_headers(),
406
+ json={
407
+ "merchant_id": "MERCH001",
408
+ "merchant_type": "cnf",
409
+ "contact_name": "Test Admin",
410
+ "contact_email": "admin@merchant.com",
411
+ "contact_phone": "+1234567890"
412
+ }
413
+ )
414
+ print_response(response)
415
+ except Exception as e:
416
+ print_error(f"Error: {str(e)}")
417
+
418
+
419
+ def main():
420
+ """Run all tests."""
421
+ print_section("SYSTEM USERS API TEST SUITE")
422
+ print(f"Base URL: {BASE_URL}")
423
+ print(f"Testing as: {ADMIN_EMAIL}")
424
+
425
+ # Step 1: Login
426
+ print_section("AUTHENTICATION")
427
+ if not login_as_admin():
428
+ print_error("Cannot proceed without authentication")
429
+ return
430
+
431
+ # Step 2: Test list endpoints
432
+ print_section("LIST ENDPOINTS")
433
+ test_list_users_without_projection()
434
+ test_list_users_with_projection()
435
+ test_list_users_with_filters()
436
+
437
+ # Step 3: Get a user ID for testing
438
+ print_section("GET USER ID FOR TESTING")
439
+ try:
440
+ response = requests.post(
441
+ SYSTEM_USERS_URL,
442
+ headers=get_auth_headers(),
443
+ json={"limit": 1}
444
+ )
445
+ if response.status_code == 200:
446
+ users = response.json()
447
+ if len(users) > 0:
448
+ test_user_id = users[0].get("user_id")
449
+ print_success(f"Using test user_id: {test_user_id}")
450
+
451
+ # Step 4: Test individual user operations
452
+ print_section("USER DETAIL OPERATIONS")
453
+ test_get_user_details(test_user_id)
454
+ test_get_login_attempts(test_user_id)
455
+
456
+ # Step 5: Test role lookup
457
+ print_section("ROLE OPERATIONS")
458
+ test_get_roles()
459
+
460
+ # Step 6: Test admin operations (commented out to avoid actual changes)
461
+ print_section("ADMIN OPERATIONS (Skipped to avoid changes)")
462
+ print("⚠️ Skipping suspend/unlock/reset/deactivate to preserve data")
463
+ print(" Uncomment in script to test these operations")
464
+ # test_suspend_user(test_user_id)
465
+ # test_unlock_user(test_user_id)
466
+ # test_reset_password(test_user_id)
467
+ # test_deactivate_user(test_user_id)
468
+
469
+ else:
470
+ print_error("No users found for testing")
471
+ else:
472
+ print_error("Failed to get users for testing")
473
+ except Exception as e:
474
+ print_error(f"Error getting test user: {str(e)}")
475
+
476
+ # Step 7: Test internal endpoints
477
+ test_internal_endpoints()
478
+
479
+ # Summary
480
+ print_section("TEST SUITE COMPLETED")
481
+ print("βœ… All tests executed")
482
+ print("\nπŸ“ Notes:")
483
+ print(" - Admin operations (suspend/unlock/reset/deactivate) were skipped")
484
+ print(" - Uncomment those tests to verify full functionality")
485
+ print(" - Internal endpoints may require service-to-service authentication")
486
+
487
+
488
+ if __name__ == "__main__":
489
+ main()
test_system_users_api.sh ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ # Test System Users API
4
+ # This script tests all the system users endpoints
5
+
6
+ echo "πŸš€ Starting System Users API Tests"
7
+ echo "=================================="
8
+ echo ""
9
+
10
+ # Check if server is running
11
+ echo "πŸ“‘ Checking if server is running..."
12
+ if curl -s http://localhost:8002/health > /dev/null; then
13
+ echo "βœ… Server is running"
14
+ else
15
+ echo "❌ Server is not running on port 8002"
16
+ echo " Please start the server first:"
17
+ echo " cd cuatrolabs-auth-ms && ./start_server.sh"
18
+ exit 1
19
+ fi
20
+
21
+ echo ""
22
+ echo "πŸ§ͺ Running test suite..."
23
+ echo ""
24
+
25
+ # Run the Python test script
26
+ python3 test_system_users_api.py
27
+
28
+ echo ""
29
+ echo "βœ… Test suite completed!"