create-tigra 2.5.0 โ†’ 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/bin/create-tigra.js +5 -2
  2. package/package.json +1 -1
  3. package/template/_claude/rules/client/01-project-structure.md +6 -0
  4. package/template/_claude/rules/client/04-design-system.md +67 -44
  5. package/template/_claude/rules/client/core.md +3 -2
  6. package/template/_claude/rules/global/completion-reports.md +178 -0
  7. package/template/_claude/rules/global/core.md +6 -0
  8. package/template/client/.env.example.production +5 -0
  9. package/template/client/src/app/error.tsx +1 -1
  10. package/template/client/src/app/globals.css +18 -83
  11. package/template/client/src/app/page.tsx +10 -3
  12. package/template/client/src/components/common/ThemeSwitcher.tsx +112 -0
  13. package/template/client/src/components/layout/Header.tsx +1 -1
  14. package/template/client/src/features/auth/components/AuthInitializer.tsx +1 -1
  15. package/template/client/src/features/auth/components/LoginForm.tsx +1 -1
  16. package/template/client/src/features/auth/components/RegisterForm.tsx +1 -1
  17. package/template/client/src/features/auth/services/auth.service.ts +0 -4
  18. package/template/client/src/lib/constants/api-endpoints.ts +0 -2
  19. package/template/client/src/styles/themes/electric-indigo.css +90 -0
  20. package/template/client/src/styles/themes/ocean-teal.css +90 -0
  21. package/template/client/src/styles/themes/rose-pink.css +90 -0
  22. package/template/client/src/styles/themes/warm-orange.css +90 -0
  23. package/template/server/prisma/schema.prisma +0 -1
  24. package/template/server/src/modules/admin/admin.controller.ts +3 -9
  25. package/template/server/src/modules/admin/admin.routes.ts +7 -0
  26. package/template/server/src/modules/admin/admin.schemas.ts +13 -0
  27. package/template/server/src/modules/auth/auth.repo.ts +9 -8
  28. package/template/server/postman_collection.json +0 -666
@@ -1,666 +0,0 @@
1
- {
2
- "info": {
3
- "name": "Tigra API - Complete Collection",
4
- "description": "**Comprehensive API collection with automatic token management**\n\n## ๐Ÿš€ Quick Start\n\n1. **Start the server**: `npm run dev` (runs on port 8000)\n2. **Register or Login**: Run either endpoint - tokens are auto-saved\n3. **Test protected endpoints**: Tokens are automatically injected\n\n## ๐Ÿ” Authentication Flow\n\n- All auth tokens are **automatically managed**\n- Login/Register โ†’ Tokens saved to collection variables\n- Protected endpoints โ†’ Access token auto-injected\n- Token expired โ†’ Use Refresh Token endpoint\n\n## ๐Ÿ“ Variables Used\n\n- `base_url`: http://localhost:8000/api/v1\n- `access_token`: Auto-saved from login/register\n- `refresh_token`: Auto-saved from login/register\n- `user_id`: Auto-saved from login/register\n\n## ๐ŸŽฏ Features\n\nโœ… Pre-filled request bodies with valid examples\nโœ… Automatic token extraction and injection\nโœ… Clear descriptions and requirements\nโœ… Response validation tests\nโœ… Organized folder structure",
5
- "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
6
- "_exporter_id": "tigra-api"
7
- },
8
- "auth": {
9
- "type": "bearer",
10
- "bearer": [
11
- {
12
- "key": "token",
13
- "value": "{{access_token}}",
14
- "type": "string"
15
- }
16
- ]
17
- },
18
- "variable": [
19
- {
20
- "key": "base_url",
21
- "value": "http://localhost:8000/api/v1",
22
- "type": "string"
23
- },
24
- {
25
- "key": "access_token",
26
- "value": "",
27
- "type": "string"
28
- },
29
- {
30
- "key": "refresh_token",
31
- "value": "",
32
- "type": "string"
33
- },
34
- {
35
- "key": "user_id",
36
- "value": "",
37
- "type": "string"
38
- },
39
- {
40
- "key": "user_email",
41
- "value": "",
42
- "type": "string"
43
- }
44
- ],
45
- "item": [
46
- {
47
- "name": "๐Ÿ” Authentication",
48
- "description": "Authentication endpoints - tokens are automatically saved and managed",
49
- "item": [
50
- {
51
- "name": "Register New User",
52
- "event": [
53
- {
54
- "listen": "test",
55
- "script": {
56
- "exec": [
57
- "// Automatically save tokens and user info on successful registration",
58
- "if (pm.response.code === 201) {",
59
- " const response = pm.response.json();",
60
- " ",
61
- " if (response.success && response.data) {",
62
- " // Save tokens to collection variables",
63
- " pm.collectionVariables.set('access_token', response.data.tokens.accessToken);",
64
- " pm.collectionVariables.set('refresh_token', response.data.tokens.refreshToken);",
65
- " ",
66
- " // Save user info",
67
- " pm.collectionVariables.set('user_id', response.data.user.id);",
68
- " pm.collectionVariables.set('user_email', response.data.user.email);",
69
- " ",
70
- " console.log('โœ… Registration successful!');",
71
- " console.log('๐Ÿ“ง Email:', response.data.user.email);",
72
- " console.log('๐Ÿ”‘ Access token saved to collection variables');",
73
- " console.log('๐Ÿ”„ Refresh token saved to collection variables');",
74
- " ",
75
- " // Validation tests",
76
- " pm.test('Status code is 201', () => pm.response.to.have.status(201));",
77
- " pm.test('Response has success true', () => pm.expect(response.success).to.be.true);",
78
- " pm.test('Response contains user data', () => pm.expect(response.data.user).to.exist);",
79
- " pm.test('Response contains tokens', () => pm.expect(response.data.tokens).to.exist);",
80
- " pm.test('User has valid email', () => pm.expect(response.data.user.email).to.match(/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/));",
81
- " }",
82
- "} else {",
83
- " console.log('โŒ Registration failed');",
84
- " const error = pm.response.json();",
85
- " if (error.error) {",
86
- " console.log('Error:', error.error.message);",
87
- " }",
88
- "}"
89
- ],
90
- "type": "text/javascript"
91
- }
92
- }
93
- ],
94
- "request": {
95
- "method": "POST",
96
- "header": [
97
- {
98
- "key": "Content-Type",
99
- "value": "application/json"
100
- }
101
- ],
102
- "body": {
103
- "mode": "raw",
104
- "raw": "{\n \"email\": \"john.doe@example.com\",\n \"password\": \"SecurePass123\",\n \"firstName\": \"John\",\n \"lastName\": \"Doe\"\n}",
105
- "options": {
106
- "raw": {
107
- "language": "json"
108
- }
109
- }
110
- },
111
- "url": {
112
- "raw": "{{base_url}}/auth/register",
113
- "host": ["{{base_url}}"],
114
- "path": ["auth", "register"]
115
- },
116
- "description": "**Register a new user account**\n\n## ๐Ÿ“‹ Requirements\n\n### Email\n- Valid email format\n- Will be converted to lowercase\n- Must be unique (no duplicates)\n\n### Password\n- Minimum 8 characters\n- At least 1 uppercase letter (A-Z)\n- At least 1 lowercase letter (a-z)\n- At least 1 number (0-9)\n\n### First Name\n- Minimum 2 characters\n- Maximum 100 characters\n\n### Last Name\n- Minimum 2 characters\n- Maximum 100 characters\n\n## โšก Rate Limit\n5 requests per hour per IP\n\n## โœ… Success Response (201)\nTokens and user info automatically saved to collection variables"
117
- },
118
- "response": []
119
- },
120
- {
121
- "name": "Login",
122
- "event": [
123
- {
124
- "listen": "test",
125
- "script": {
126
- "exec": [
127
- "// Automatically save tokens and user info on successful login",
128
- "if (pm.response.code === 200) {",
129
- " const response = pm.response.json();",
130
- " ",
131
- " if (response.success && response.data) {",
132
- " // Save tokens to collection variables",
133
- " pm.collectionVariables.set('access_token', response.data.tokens.accessToken);",
134
- " pm.collectionVariables.set('refresh_token', response.data.tokens.refreshToken);",
135
- " ",
136
- " // Save user info",
137
- " pm.collectionVariables.set('user_id', response.data.user.id);",
138
- " pm.collectionVariables.set('user_email', response.data.user.email);",
139
- " ",
140
- " console.log('โœ… Login successful!');",
141
- " console.log('๐Ÿ‘ค User:', response.data.user.firstName, response.data.user.lastName);",
142
- " console.log('๐Ÿ“ง Email:', response.data.user.email);",
143
- " console.log('๐ŸŽญ Role:', response.data.user.role);",
144
- " console.log('๐Ÿ”‘ Access token saved to collection variables');",
145
- " console.log('๐Ÿ”„ Refresh token saved to collection variables');",
146
- " ",
147
- " // Validation tests",
148
- " pm.test('Status code is 200', () => pm.response.to.have.status(200));",
149
- " pm.test('Response has success true', () => pm.expect(response.success).to.be.true);",
150
- " pm.test('Response contains user data', () => pm.expect(response.data.user).to.exist);",
151
- " pm.test('Response contains tokens', () => pm.expect(response.data.tokens).to.exist);",
152
- " }",
153
- "} else {",
154
- " console.log('โŒ Login failed');",
155
- " const error = pm.response.json();",
156
- " if (error.error) {",
157
- " console.log('Error:', error.error.message);",
158
- " }",
159
- "}"
160
- ],
161
- "type": "text/javascript"
162
- }
163
- }
164
- ],
165
- "request": {
166
- "method": "POST",
167
- "header": [
168
- {
169
- "key": "Content-Type",
170
- "value": "application/json"
171
- }
172
- ],
173
- "body": {
174
- "mode": "raw",
175
- "raw": "{\n \"email\": \"john.doe@example.com\",\n \"password\": \"SecurePass123\"\n}",
176
- "options": {
177
- "raw": {
178
- "language": "json"
179
- }
180
- }
181
- },
182
- "url": {
183
- "raw": "{{base_url}}/auth/login",
184
- "host": ["{{base_url}}"],
185
- "path": ["auth", "login"]
186
- },
187
- "description": "**Login with email and password**\n\n## ๐Ÿ“‹ Requirements\n\n### Email\n- Valid email format\n- Will be converted to lowercase\n\n### Password\n- Cannot be empty\n\n## โšก Rate Limit\n10 requests per 15 minutes per IP\n\n## โœ… Success Response (200)\nTokens and user info automatically saved to collection variables\n\n## โŒ Error Responses\n- **401**: Invalid credentials\n- **422**: Validation failed"
188
- },
189
- "response": []
190
- },
191
- {
192
- "name": "Get Current User",
193
- "event": [
194
- {
195
- "listen": "test",
196
- "script": {
197
- "exec": [
198
- "// Validate current user response",
199
- "if (pm.response.code === 200) {",
200
- " const response = pm.response.json();",
201
- " ",
202
- " console.log('โœ… User info retrieved successfully!');",
203
- " console.log('๐Ÿ‘ค User:', response.data.firstName, response.data.lastName);",
204
- " console.log('๐Ÿ“ง Email:', response.data.email);",
205
- " console.log('๐ŸŽญ Role:', response.data.role);",
206
- " console.log('โœ… Active:', response.data.isActive);",
207
- " ",
208
- " // Validation tests",
209
- " pm.test('Status code is 200', () => pm.response.to.have.status(200));",
210
- " pm.test('Response has success true', () => pm.expect(response.success).to.be.true);",
211
- " pm.test('Response contains user data', () => pm.expect(response.data).to.exist);",
212
- " pm.test('User has valid ID', () => pm.expect(response.data.id).to.be.a('string'));",
213
- " pm.test('User has email', () => pm.expect(response.data.email).to.exist);",
214
- "} else if (pm.response.code === 401) {",
215
- " console.log('โŒ Unauthorized - Access token may be expired');",
216
- " console.log('๐Ÿ’ก Try refreshing the token using the Refresh Token endpoint');",
217
- "}"
218
- ],
219
- "type": "text/javascript"
220
- }
221
- },
222
- {
223
- "listen": "prerequest",
224
- "script": {
225
- "exec": [
226
- "// Check if access token exists",
227
- "const accessToken = pm.collectionVariables.get('access_token');",
228
- "",
229
- "if (!accessToken) {",
230
- " console.log('โš ๏ธ No access token found!');",
231
- " console.log('๐Ÿ’ก Please login first to get an access token');",
232
- "} else {",
233
- " console.log('๐Ÿ”‘ Using access token from collection variables');",
234
- "}"
235
- ],
236
- "type": "text/javascript"
237
- }
238
- }
239
- ],
240
- "request": {
241
- "auth": {
242
- "type": "bearer",
243
- "bearer": [
244
- {
245
- "key": "token",
246
- "value": "{{access_token}}",
247
- "type": "string"
248
- }
249
- ]
250
- },
251
- "method": "GET",
252
- "header": [],
253
- "url": {
254
- "raw": "{{base_url}}/auth/me",
255
- "host": ["{{base_url}}"],
256
- "path": ["auth", "me"]
257
- },
258
- "description": "**Get current authenticated user details**\n\n## ๐Ÿ” Authentication Required\nThis endpoint requires a valid access token in the Authorization header.\n\n## โœ… Auto-Token Injection\nThe access token is automatically injected from collection variables.\n\n## ๐Ÿ“‹ Response Includes\n- User ID\n- Email\n- First Name\n- Last Name\n- Role (USER, COMPANY, ADMIN, GUIDE, DRIVER)\n- Active status\n- Email verification status\n- Created/Updated timestamps\n\n## โŒ Error Responses\n- **401**: Unauthorized (missing or invalid token)"
259
- },
260
- "response": []
261
- },
262
- {
263
- "name": "Refresh Token",
264
- "event": [
265
- {
266
- "listen": "test",
267
- "script": {
268
- "exec": [
269
- "// Automatically update tokens on successful refresh",
270
- "if (pm.response.code === 200) {",
271
- " const response = pm.response.json();",
272
- " ",
273
- " if (response.success && response.data) {",
274
- " // Update tokens in collection variables",
275
- " pm.collectionVariables.set('access_token', response.data.accessToken);",
276
- " pm.collectionVariables.set('refresh_token', response.data.refreshToken);",
277
- " ",
278
- " console.log('โœ… Tokens refreshed successfully!');",
279
- " console.log('๐Ÿ”‘ New access token saved');",
280
- " console.log('๐Ÿ”„ New refresh token saved');",
281
- " ",
282
- " // Validation tests",
283
- " pm.test('Status code is 200', () => pm.response.to.have.status(200));",
284
- " pm.test('Response has success true', () => pm.expect(response.success).to.be.true);",
285
- " pm.test('Response contains new access token', () => pm.expect(response.data.accessToken).to.exist);",
286
- " pm.test('Response contains new refresh token', () => pm.expect(response.data.refreshToken).to.exist);",
287
- " }",
288
- "} else {",
289
- " console.log('โŒ Token refresh failed');",
290
- " const error = pm.response.json();",
291
- " if (error.error) {",
292
- " console.log('Error:', error.error.message);",
293
- " if (pm.response.code === 401) {",
294
- " console.log('๐Ÿ’ก Refresh token expired - please login again');",
295
- " }",
296
- " }",
297
- "}"
298
- ],
299
- "type": "text/javascript"
300
- }
301
- },
302
- {
303
- "listen": "prerequest",
304
- "script": {
305
- "exec": [
306
- "// Auto-populate refresh token from collection variables",
307
- "const refreshToken = pm.collectionVariables.get('refresh_token');",
308
- "",
309
- "if (refreshToken) {",
310
- " console.log('๐Ÿ”„ Using refresh token from collection variables');",
311
- "} else {",
312
- " console.log('โš ๏ธ No refresh token found!');",
313
- " console.log('๐Ÿ’ก Please login first to get a refresh token');",
314
- "}"
315
- ],
316
- "type": "text/javascript"
317
- }
318
- }
319
- ],
320
- "request": {
321
- "method": "POST",
322
- "header": [
323
- {
324
- "key": "Content-Type",
325
- "value": "application/json"
326
- }
327
- ],
328
- "body": {
329
- "mode": "raw",
330
- "raw": "{\n \"refreshToken\": \"{{refresh_token}}\"\n}",
331
- "options": {
332
- "raw": {
333
- "language": "json"
334
- }
335
- }
336
- },
337
- "url": {
338
- "raw": "{{base_url}}/auth/refresh",
339
- "host": ["{{base_url}}"],
340
- "path": ["auth", "refresh"]
341
- },
342
- "description": "**Refresh access token using refresh token**\n\n## ๐Ÿ”„ Usage\n\nWhen your access token expires (default: 15 minutes), use this endpoint to get a new pair of tokens without requiring login.\n\n## ๐Ÿ“‹ Requirements\n\n### Refresh Token\n- Must be valid and not expired (default: 7 days)\n- Automatically populated from collection variables\n\n## โšก Rate Limit\n20 requests per 15 minutes per IP\n\n## โœ… Success Response (200)\nNew tokens automatically saved to collection variables\n\n## โŒ Error Responses\n- **401**: Refresh token invalid or expired (login required)\n- **422**: Validation failed"
343
- },
344
- "response": []
345
- },
346
- {
347
- "name": "Logout",
348
- "event": [
349
- {
350
- "listen": "test",
351
- "script": {
352
- "exec": [
353
- "// Clear tokens on successful logout",
354
- "if (pm.response.code === 200) {",
355
- " const response = pm.response.json();",
356
- " ",
357
- " // Clear all auth-related variables",
358
- " pm.collectionVariables.set('access_token', '');",
359
- " pm.collectionVariables.set('refresh_token', '');",
360
- " pm.collectionVariables.set('user_id', '');",
361
- " pm.collectionVariables.set('user_email', '');",
362
- " ",
363
- " console.log('โœ… Logout successful!');",
364
- " console.log('๐Ÿงน All tokens cleared from collection variables');",
365
- " ",
366
- " // Validation tests",
367
- " pm.test('Status code is 200', () => pm.response.to.have.status(200));",
368
- " pm.test('Response has success true', () => pm.expect(response.success).to.be.true);",
369
- "} else {",
370
- " console.log('โŒ Logout failed');",
371
- "}"
372
- ],
373
- "type": "text/javascript"
374
- }
375
- },
376
- {
377
- "listen": "prerequest",
378
- "script": {
379
- "exec": [
380
- "// Auto-populate refresh token from collection variables",
381
- "const refreshToken = pm.collectionVariables.get('refresh_token');",
382
- "",
383
- "if (refreshToken) {",
384
- " console.log('๐Ÿ”„ Using refresh token from collection variables');",
385
- "} else {",
386
- " console.log('โš ๏ธ No refresh token found - you may already be logged out');",
387
- "}"
388
- ],
389
- "type": "text/javascript"
390
- }
391
- }
392
- ],
393
- "request": {
394
- "method": "POST",
395
- "header": [
396
- {
397
- "key": "Content-Type",
398
- "value": "application/json"
399
- }
400
- ],
401
- "body": {
402
- "mode": "raw",
403
- "raw": "{\n \"refreshToken\": \"{{refresh_token}}\"\n}",
404
- "options": {
405
- "raw": {
406
- "language": "json"
407
- }
408
- }
409
- },
410
- "url": {
411
- "raw": "{{base_url}}/auth/logout",
412
- "host": ["{{base_url}}"],
413
- "path": ["auth", "logout"]
414
- },
415
- "description": "**Logout and invalidate refresh token**\n\n## ๐Ÿ”’ Security\n\nThis endpoint invalidates the refresh token on the server, preventing it from being used again.\n\n## ๐Ÿ“‹ Requirements\n\n### Refresh Token\n- Must be valid\n- Automatically populated from collection variables\n\n## โšก Rate Limit\n50 requests per 15 minutes per IP\n\n## โœ… Success Response (200)\nAll tokens automatically cleared from collection variables\n\n## โŒ Error Responses\n- **422**: Validation failed"
416
- },
417
- "response": []
418
- },
419
- {
420
- "name": "Get Active Sessions",
421
- "event": [
422
- {
423
- "listen": "test",
424
- "script": {
425
- "exec": [
426
- "// Validate sessions response",
427
- "if (pm.response.code === 200) {",
428
- " const response = pm.response.json();",
429
- " ",
430
- " console.log('โœ… Sessions retrieved successfully!');",
431
- " console.log('๐Ÿ“ฑ Active sessions:', response.data.length);",
432
- " ",
433
- " if (response.data.length > 0) {",
434
- " response.data.forEach((session, index) => {",
435
- " console.log(`Session ${index + 1}:`, {",
436
- " device: session.deviceInfo || 'Unknown',",
437
- " ip: session.ipAddress || 'Unknown',",
438
- " lastActive: session.lastActiveAt",
439
- " });",
440
- " });",
441
- " }",
442
- " ",
443
- " // Validation tests",
444
- " pm.test('Status code is 200', () => pm.response.to.have.status(200));",
445
- " pm.test('Response has success true', () => pm.expect(response.success).to.be.true);",
446
- " pm.test('Response contains sessions array', () => pm.expect(response.data).to.be.an('array'));",
447
- "} else if (pm.response.code === 401) {",
448
- " console.log('โŒ Unauthorized - Access token may be expired');",
449
- " console.log('๐Ÿ’ก Try refreshing the token using the Refresh Token endpoint');",
450
- "}"
451
- ],
452
- "type": "text/javascript"
453
- }
454
- },
455
- {
456
- "listen": "prerequest",
457
- "script": {
458
- "exec": [
459
- "// Check if access token exists",
460
- "const accessToken = pm.collectionVariables.get('access_token');",
461
- "",
462
- "if (!accessToken) {",
463
- " console.log('โš ๏ธ No access token found!');",
464
- " console.log('๐Ÿ’ก Please login first to get an access token');",
465
- "} else {",
466
- " console.log('๐Ÿ”‘ Using access token from collection variables');",
467
- "}"
468
- ],
469
- "type": "text/javascript"
470
- }
471
- }
472
- ],
473
- "request": {
474
- "auth": {
475
- "type": "bearer",
476
- "bearer": [
477
- {
478
- "key": "token",
479
- "value": "{{access_token}}",
480
- "type": "string"
481
- }
482
- ]
483
- },
484
- "method": "GET",
485
- "header": [],
486
- "url": {
487
- "raw": "{{base_url}}/auth/sessions",
488
- "host": ["{{base_url}}"],
489
- "path": ["auth", "sessions"]
490
- },
491
- "description": "**Get all active sessions for the current user**\n\n## ๐Ÿ” Authentication Required\nThis endpoint requires a valid access token in the Authorization header.\n\n## โœ… Auto-Token Injection\nThe access token is automatically injected from collection variables.\n\n## ๐Ÿ“‹ Response Includes\nFor each active session:\n- Session ID\n- Device information (user agent)\n- IP address\n- Last active timestamp\n- Expiration timestamp\n- Created timestamp\n\n## ๐Ÿ’ก Use Cases\n- View all devices/locations where you're logged in\n- Monitor session activity\n- Check for unauthorized access\n- Review session details before logging out all sessions\n\n## โŒ Error Responses\n- **401**: Unauthorized (missing or invalid token)"
492
- },
493
- "response": []
494
- },
495
- {
496
- "name": "Logout All Sessions",
497
- "event": [
498
- {
499
- "listen": "test",
500
- "script": {
501
- "exec": [
502
- "// Clear tokens on successful logout from all sessions",
503
- "if (pm.response.code === 200) {",
504
- " const response = pm.response.json();",
505
- " ",
506
- " // Clear all auth-related variables",
507
- " pm.collectionVariables.set('access_token', '');",
508
- " pm.collectionVariables.set('refresh_token', '');",
509
- " pm.collectionVariables.set('user_id', '');",
510
- " pm.collectionVariables.set('user_email', '');",
511
- " ",
512
- " console.log('โœ… Logged out from all sessions successfully!');",
513
- " console.log('๐Ÿ“ฑ Sessions terminated:', response.data.count);",
514
- " console.log('๐Ÿงน All tokens cleared from collection variables');",
515
- " console.log('๐Ÿ’ก All devices have been logged out');",
516
- " console.log('๐Ÿ”’ Please login again to continue');",
517
- " ",
518
- " // Validation tests",
519
- " pm.test('Status code is 200', () => pm.response.to.have.status(200));",
520
- " pm.test('Response has success true', () => pm.expect(response.success).to.be.true);",
521
- " pm.test('Response contains count', () => pm.expect(response.data.count).to.exist);",
522
- "} else if (pm.response.code === 401) {",
523
- " console.log('โŒ Unauthorized - Access token may be expired');",
524
- " console.log('๐Ÿ’ก Try refreshing the token first');",
525
- "} else {",
526
- " console.log('โŒ Logout from all sessions failed');",
527
- "}"
528
- ],
529
- "type": "text/javascript"
530
- }
531
- },
532
- {
533
- "listen": "prerequest",
534
- "script": {
535
- "exec": [
536
- "// Check if access token exists",
537
- "const accessToken = pm.collectionVariables.get('access_token');",
538
- "",
539
- "if (accessToken) {",
540
- " console.log('๐Ÿ”‘ Using access token from collection variables');",
541
- " console.log('โš ๏ธ This will log you out from ALL devices');",
542
- "} else {",
543
- " console.log('โš ๏ธ No access token found - you may already be logged out');",
544
- "}"
545
- ],
546
- "type": "text/javascript"
547
- }
548
- }
549
- ],
550
- "request": {
551
- "auth": {
552
- "type": "bearer",
553
- "bearer": [
554
- {
555
- "key": "token",
556
- "value": "{{access_token}}",
557
- "type": "string"
558
- }
559
- ]
560
- },
561
- "method": "POST",
562
- "header": [],
563
- "url": {
564
- "raw": "{{base_url}}/auth/logout-all",
565
- "host": ["{{base_url}}"],
566
- "path": ["auth", "logout-all"]
567
- },
568
- "description": "**Logout from all active sessions on all devices**\n\n## ๐Ÿ” Authentication Required\nThis endpoint requires a valid access token in the Authorization header.\n\n## ๐Ÿ”’ Security\n\nThis endpoint performs a complete security logout:\n- Deletes ALL refresh tokens for the user\n- Terminates ALL active sessions across all devices\n- Invalidates all current access tokens\n- Forces re-authentication on all devices\n\n## โšก Rate Limit\n10 requests per 15 minutes per IP\n\n## ๐Ÿ’ก Use Cases\n\n### Security Breach\n- Suspect unauthorized access\n- Lost or stolen device\n- Compromised credentials\n- Want to revoke all access immediately\n\n### Password Reset\n- Automatically called after password reset\n- Ensures old sessions can't be used\n\n### Device Management\n- Clear all sessions before selling/giving away device\n- Remove access from forgotten logins\n\n## โœ… Success Response (200)\n- All sessions terminated\n- All tokens invalidated\n- Tokens automatically cleared from collection variables\n- Must login again on ALL devices\n\n## ๐Ÿ“‹ Response Includes\n- Count of sessions terminated\n- Success message\n\n## โŒ Error Responses\n- **401**: Unauthorized (missing or invalid token)\n\n## ๐Ÿ”„ After Logout\n1. All devices will be logged out\n2. Any active requests will fail with 401\n3. Must login again to get new tokens\n4. Previous refresh tokens cannot be used"
569
- },
570
- "response": []
571
- }
572
- ]
573
- },
574
- {
575
- "name": "๐Ÿ“‹ Example Flows",
576
- "description": "Common workflow examples for testing",
577
- "item": [
578
- {
579
- "name": "Complete Auth Flow",
580
- "item": [],
581
- "description": "**Complete Authentication Workflow**\n\n## ๐Ÿ”„ Flow Steps\n\n1. **Register** โ†’ Auto-saves tokens\n2. **Get Current User** โ†’ Uses saved access token\n3. **Logout** โ†’ Clears all tokens\n4. **Login** โ†’ Get new tokens\n5. **Refresh Token** โ†’ Get new access token when expired\n\n## ๐Ÿ’ก Tips\n\n- All endpoints in Authentication folder are already configured\n- Just run them in order to test the complete flow\n- Watch the Postman console for detailed logs"
582
- },
583
- {
584
- "name": "Token Expiry Handling",
585
- "item": [],
586
- "description": "**Handling Expired Access Tokens**\n\n## ๐Ÿ”„ Flow Steps\n\n1. **Login** โ†’ Get tokens (access token expires in 15 min by default)\n2. **Wait for expiration** (or manually clear access token)\n3. **Get Current User** โ†’ Will fail with 401\n4. **Refresh Token** โ†’ Get new access token\n5. **Get Current User** โ†’ Success with new token\n\n## ๐Ÿ’ก Tips\n\n- Access tokens are short-lived (15 minutes default)\n- Refresh tokens are long-lived (7 days default)\n- The Refresh Token endpoint gives you both new tokens"
587
- }
588
- ]
589
- },
590
- {
591
- "name": "๐Ÿ”ง Utilities",
592
- "description": "Utility endpoints and helpers",
593
- "item": [
594
- {
595
- "name": "Health Check",
596
- "request": {
597
- "method": "GET",
598
- "header": [],
599
- "url": {
600
- "raw": "http://localhost:8000/health",
601
- "protocol": "http",
602
- "host": ["localhost"],
603
- "port": "8000",
604
- "path": ["health"]
605
- },
606
- "description": "**Check if the server is running**\n\n## โœ… Expected Response\n```json\n{\n \"status\": \"ok\",\n \"timestamp\": \"2024-01-01T00:00:00.000Z\"\n}\n```"
607
- },
608
- "response": []
609
- },
610
- {
611
- "name": "API Documentation (Swagger)",
612
- "request": {
613
- "method": "GET",
614
- "header": [],
615
- "url": {
616
- "raw": "http://localhost:8000/docs",
617
- "protocol": "http",
618
- "host": ["localhost"],
619
- "port": "8000",
620
- "path": ["docs"]
621
- },
622
- "description": "**Open API documentation in browser**\n\n## ๐Ÿ“š Swagger UI\n\nOpens the interactive Swagger UI documentation where you can:\n- Browse all available endpoints\n- See request/response schemas\n- Test endpoints directly from the browser"
623
- },
624
- "response": []
625
- },
626
- {
627
- "name": "Clear All Tokens (Manual)",
628
- "event": [
629
- {
630
- "listen": "prerequest",
631
- "script": {
632
- "exec": [
633
- "// Manually clear all tokens and user info",
634
- "pm.collectionVariables.set('access_token', '');",
635
- "pm.collectionVariables.set('refresh_token', '');",
636
- "pm.collectionVariables.set('user_id', '');",
637
- "pm.collectionVariables.set('user_email', '');",
638
- "",
639
- "console.log('๐Ÿงน All tokens and user info cleared from collection variables');",
640
- "console.log('๐Ÿ’ก You can now test registration/login as a fresh user');"
641
- ],
642
- "type": "text/javascript"
643
- }
644
- }
645
- ],
646
- "request": {
647
- "method": "GET",
648
- "header": [],
649
- "url": {
650
- "raw": "{{base_url}}/auth/me",
651
- "host": ["{{base_url}}"],
652
- "path": ["auth", "me"]
653
- },
654
- "description": "**Utility to manually clear all stored tokens**\n\n## ๐Ÿงน Usage\n\nRun this request to clear:\n- Access token\n- Refresh token\n- User ID\n- User email\n\n## ๐Ÿ’ก When to Use\n\n- Testing with a fresh start\n- Switching between different test users\n- After logout to ensure clean state\n\n**Note**: This request will fail (401) since tokens are cleared, but that's expected!"
655
- },
656
- "response": []
657
- }
658
- ]
659
- },
660
- {
661
- "name": "๐Ÿ“– README",
662
- "item": [],
663
- "description": "# ๐ŸŽฏ Tigra API - Postman Collection\n\n## ๐Ÿš€ Quick Start Guide\n\n### 1. Prerequisites\n- Server must be running on port 8000\n- Run: `npm run dev` in the server directory\n\n### 2. First Time Setup\n\n**Option A: Register New User**\n1. Go to **Authentication** โ†’ **Register New User**\n2. Modify the email if needed (must be unique)\n3. Click **Send**\n4. โœ… Tokens automatically saved!\n\n**Option B: Login Existing User**\n1. Go to **Authentication** โ†’ **Login**\n2. Enter your credentials\n3. Click **Send**\n4. โœ… Tokens automatically saved!\n\n### 3. Testing Protected Endpoints\n\nAfter login/register, all protected endpoints will work automatically:\n- Go to **Authentication** โ†’ **Get Current User**\n- Click **Send**\n- โœ… Access token automatically injected!\n\n---\n\n## ๐ŸŽจ Collection Features\n\n### โœ… Automatic Token Management\n- **Login/Register** โ†’ Tokens saved automatically\n- **Protected endpoints** โ†’ Access token auto-injected\n- **Logout** โ†’ Tokens cleared automatically\n- **Refresh** โ†’ Tokens updated automatically\n\n### โœ… Smart Request Bodies\n- All requests have pre-filled example data\n- Easy to modify for your test cases\n- Follows validation requirements\n\n### โœ… Console Logging\n- Open Postman Console (View โ†’ Show Postman Console)\n- See detailed logs for each request\n- Helpful tips and error messages\n\n### โœ… Response Validation\n- Automatic tests for status codes\n- Validates response structure\n- Checks data integrity\n\n---\n\n## ๐Ÿ” How Token Management Works\n\n### Collection Variables\nThe collection uses these variables (auto-managed):\n\n| Variable | Description | Set By |\n|----------|-------------|--------|\n| `base_url` | API base URL | Manual |\n| `access_token` | JWT access token (15 min) | Login/Register/Refresh |\n| `refresh_token` | JWT refresh token (7 days) | Login/Register/Refresh |\n| `user_id` | Current user ID | Login/Register |\n| `user_email` | Current user email | Login/Register |\n\n### Automatic Token Injection\nProtected endpoints use this auth configuration:\n```\nAuthorization: Bearer {{access_token}}\n```\n\nNo manual token copying needed! ๐ŸŽ‰\n\n---\n\n## ๐Ÿ”„ Common Workflows\n\n### New User Registration Flow\n1. **Register New User**\n2. **Get Current User** (verify registration)\n3. Use other endpoints as needed\n\n### Returning User Flow\n1. **Login**\n2. **Get Current User** (verify login)\n3. Use other endpoints as needed\n\n### Token Refresh Flow\n1. Wait for access token to expire (15 min)\n2. OR manually clear access token\n3. Try **Get Current User** โ†’ Will fail with 401\n4. **Refresh Token** โ†’ Get new tokens\n5. **Get Current User** โ†’ Success!\n\n### Logout Flow\n1. **Logout**\n2. All tokens automatically cleared\n3. Protected endpoints will fail (expected)\n4. Login again when needed\n\n---\n\n## ๐Ÿ› Troubleshooting\n\n### \"Server not responding\"\n- โœ… Check server is running: `npm run dev`\n- โœ… Verify port 8000 is not in use\n- โœ… Check `base_url` variable is correct\n\n### \"401 Unauthorized\"\n- โœ… Run Login or Register first\n- โœ… Check access token exists in variables\n- โœ… Try Refresh Token if expired\n\n### \"422 Validation Failed\"\n- โœ… Check request body format\n- โœ… Verify all required fields are present\n- โœ… Check password meets requirements\n\n### \"409 Conflict (Email Already Exists)\"\n- โœ… Change the email in Register request\n- โœ… Or use Login instead\n\n---\n\n## ๐Ÿ’ก Pro Tips\n\n### 1. Use Postman Console\n```\nView โ†’ Show Postman Console\n```\nSee detailed logs for every request!\n\n### 2. Check Variables\n```\nClick collection โ†’ Variables tab\n```\nSee current token values!\n\n### 3. Run Requests in Sequence\nUse Postman's Collection Runner:\n1. Right-click collection\n2. \"Run collection\"\n3. Watch automated flow!\n\n### 4. Environment Variables (Optional)\nFor multiple environments (dev/staging/prod):\n1. Create environments\n2. Override `base_url` in each\n3. Switch environments easily\n\n---\n\n## ๐Ÿ“‹ Password Requirements\n\nWhen registering, password must have:\n- โœ… Minimum 8 characters\n- โœ… At least 1 uppercase letter (A-Z)\n- โœ… At least 1 lowercase letter (a-z)\n- โœ… At least 1 number (0-9)\n\n**Example valid passwords:**\n- `SecurePass123`\n- `MyPassword1`\n- `Test1234Pass`\n\n---\n\n## ๐ŸŽฏ Rate Limits\n\n| Endpoint | Limit |\n|----------|-------|\n| Register | 5 req/hour |\n| Login | 10 req/15min |\n| Logout | 50 req/15min |\n| Refresh | 20 req/15min |\n\n---\n\n## ๐Ÿ†˜ Need Help?\n\n1. Check the **Utilities** folder for helper endpoints\n2. Open Postman Console for detailed logs\n3. Review endpoint descriptions (click info icon)\n4. Check server logs: `npm run dev`\n\n---\n\n**Happy Testing! ๐Ÿš€**"
664
- }
665
- ]
666
- }