exguard-backend 1.0.16 → 1.0.18
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.
- package/README.md +68 -10
- package/package.json +1 -1
- package/scripts/setup-nestjs.cjs +50 -21
package/README.md
CHANGED
|
@@ -31,22 +31,33 @@ pnpm add exguard-backend
|
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
33
|
# Install exguard-backend
|
|
34
|
-
npm install exguard-backend@1.0.
|
|
34
|
+
npm install exguard-backend@1.0.17
|
|
35
35
|
|
|
36
|
-
# Run automatic setup
|
|
37
|
-
npx exguard-backend
|
|
36
|
+
# Run automatic setup (overwrites existing files)
|
|
37
|
+
npx exguard-backend@1.0.17
|
|
38
38
|
# OR
|
|
39
39
|
npm run setup-nestjs
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
**
|
|
42
|
+
**Quick Start - NestJS Integration:**
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
After running the setup script, you can quickly start using ExGuard:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Start development server
|
|
48
|
+
npm run start:dev
|
|
49
|
+
|
|
50
|
+
# The setup script automatically:
|
|
51
|
+
# ✅ Creates src/exguard/ directory with all guards and decorators
|
|
52
|
+
# ✅ Updates src/app.module.ts with ExGuardModule import
|
|
53
|
+
# ✅ Creates src/events/events.controller.ts with working examples
|
|
54
|
+
# ✅ Adds npm scripts for easy access
|
|
55
|
+
```
|
|
56
|
+
✅ **Improved module detection** - More reliable NestJS project detection
|
|
57
|
+
✅ **Enhanced file creation** - Better file path handling
|
|
58
|
+
✅ **TypeScript error fixes** - All generated code is type-safe
|
|
59
|
+
✅ **Complete imports** - All factory functions properly imported
|
|
60
|
+
✅ **Working permission checks** - Guards actually enforce permissions
|
|
50
61
|
|
|
51
62
|
### 📋 Option 2: Manual Setup
|
|
52
63
|
|
|
@@ -446,6 +457,53 @@ describe('AppController (e2e)', () => {
|
|
|
446
457
|
});
|
|
447
458
|
```
|
|
448
459
|
|
|
460
|
+
## 🚀 Quick Implementation Guide
|
|
461
|
+
|
|
462
|
+
### **Step 1: Install and Setup**
|
|
463
|
+
```bash
|
|
464
|
+
# Install latest version
|
|
465
|
+
npm install exguard-backend@1.0.16
|
|
466
|
+
|
|
467
|
+
# Run automatic setup (overwrites existing files)
|
|
468
|
+
npx exguard-backend@1.0.16
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
### **Step 2: Controller Implementation**
|
|
472
|
+
```typescript
|
|
473
|
+
import { Controller, Get, Post, UseGuards, Request, Body } from '@nestjs/common';
|
|
474
|
+
import { createPermissionGuard, createRoleGuard, createModuleGuard } from '../exguard/exguard.guard';
|
|
475
|
+
|
|
476
|
+
@Controller('your-controller')
|
|
477
|
+
export class YourController {
|
|
478
|
+
@Get()
|
|
479
|
+
@UseGuards(createPermissionGuard(['your-resource:read']))
|
|
480
|
+
async getAll(@Request() req) {
|
|
481
|
+
return { success: true, data: [] };
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
@Post()
|
|
485
|
+
@UseGuards(createPermissionGuard(['your-resource:create']))
|
|
486
|
+
async create(@Body() createDto: any, @Request() req) {
|
|
487
|
+
return { success: true, data: createDto };
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
### **Step 3: Test Your Implementation**
|
|
493
|
+
```bash
|
|
494
|
+
# Test with valid permissions
|
|
495
|
+
curl http://localhost:3000/your-controller -H "Authorization: Bearer YOUR_TOKEN"
|
|
496
|
+
|
|
497
|
+
# Test with invalid permissions (should return 403)
|
|
498
|
+
curl http://localhost:3000/your-controller -H "Authorization: Bearer TOKEN_WITHOUT_PERMISSIONS"
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
### **Important Notes:**
|
|
502
|
+
- ✅ **File Overwriting**: The setup script now overwrites existing files to ensure you get the latest fixes
|
|
503
|
+
- ✅ **Permission Checking**: Guards now actually check and enforce permissions
|
|
504
|
+
- ✅ **TypeScript Safe**: All generated code is TypeScript compliant
|
|
505
|
+
- ✅ **Working Examples**: The generated controller demonstrates all protection patterns
|
|
506
|
+
|
|
449
507
|
## 🎯 Controller Implementation Examples
|
|
450
508
|
|
|
451
509
|
### **Basic Permission Protection**
|
package/package.json
CHANGED
package/scripts/setup-nestjs.cjs
CHANGED
|
@@ -143,8 +143,7 @@ export class ExGuardModule {}
|
|
|
143
143
|
const modulePath = path.join(process.cwd(), 'src/exguard/exguard.module.ts');
|
|
144
144
|
|
|
145
145
|
if (fs.existsSync(modulePath)) {
|
|
146
|
-
logWarning('
|
|
147
|
-
return;
|
|
146
|
+
logWarning('ExGuard module already exists. Overwriting...');
|
|
148
147
|
}
|
|
149
148
|
|
|
150
149
|
fs.writeFileSync(modulePath, moduleContent);
|
|
@@ -227,21 +226,40 @@ export class ExGuardRoleGuard extends ExGuardNestGuard {
|
|
|
227
226
|
export function createPermissionGuard(permissions: string[], requireAll = false) {
|
|
228
227
|
return class extends ExGuardNestGuard {
|
|
229
228
|
public async checkPermissions(context: GuardContext) {
|
|
229
|
+
console.log('🔍 DEBUG: Permission guard called');
|
|
230
|
+
console.log('🔍 DEBUG: Required permissions:', permissions);
|
|
231
|
+
console.log('🔍 DEBUG: Require all:', requireAll);
|
|
232
|
+
|
|
230
233
|
// First authenticate the user
|
|
231
234
|
const authResult = await this.exGuard.authenticate(context);
|
|
232
235
|
|
|
236
|
+
console.log('🔍 DEBUG: Auth result:', {
|
|
237
|
+
allowed: authResult.allowed,
|
|
238
|
+
hasUser: !!authResult.user,
|
|
239
|
+
error: authResult.error
|
|
240
|
+
});
|
|
241
|
+
|
|
233
242
|
if (!authResult.allowed) {
|
|
243
|
+
console.log('🔍 DEBUG: Authentication failed');
|
|
234
244
|
return authResult;
|
|
235
245
|
}
|
|
236
246
|
|
|
237
247
|
// Then check specific permissions
|
|
238
248
|
// Extract permissions from modules array
|
|
239
|
-
|
|
249
|
+
if (!authResult.user) {
|
|
250
|
+
console.log('🔍 DEBUG: No user found in auth result');
|
|
251
|
+
return { allowed: false, error: 'User not found in authentication result' };
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const userPermissions = authResult.user.modules?.flatMap(module => module.permissions) || [];
|
|
255
|
+
console.log('🔍 DEBUG: User permissions:', userPermissions);
|
|
240
256
|
|
|
241
257
|
if (requireAll) {
|
|
242
258
|
// User must have ALL permissions
|
|
243
259
|
const hasAllPermissions = permissions.every(perm => userPermissions.includes(perm));
|
|
260
|
+
console.log('🔍 DEBUG: Has all permissions check:', hasAllPermissions);
|
|
244
261
|
if (!hasAllPermissions) {
|
|
262
|
+
console.log('🔍 DEBUG: Missing required permissions (ALL)');
|
|
245
263
|
return {
|
|
246
264
|
allowed: false,
|
|
247
265
|
error: 'Insufficient permissions. Required all of: ' + permissions.join(', ')
|
|
@@ -250,7 +268,9 @@ export function createPermissionGuard(permissions: string[], requireAll = false)
|
|
|
250
268
|
} else {
|
|
251
269
|
// User must have ANY permission
|
|
252
270
|
const hasAnyPermission = permissions.some(perm => userPermissions.includes(perm));
|
|
271
|
+
console.log('🔍 DEBUG: Has any permission check:', hasAnyPermission);
|
|
253
272
|
if (!hasAnyPermission) {
|
|
273
|
+
console.log('🔍 DEBUG: Missing required permissions (ANY)');
|
|
254
274
|
return {
|
|
255
275
|
allowed: false,
|
|
256
276
|
error: 'Insufficient permissions. Required any of: ' + permissions.join(', ')
|
|
@@ -258,15 +278,10 @@ export function createPermissionGuard(permissions: string[], requireAll = false)
|
|
|
258
278
|
}
|
|
259
279
|
}
|
|
260
280
|
|
|
281
|
+
console.log('🔍 DEBUG: Permission check passed');
|
|
261
282
|
return {
|
|
262
283
|
allowed: true,
|
|
263
|
-
user:
|
|
264
|
-
...authResult.user,
|
|
265
|
-
permissions: authResult.modules?.flatMap(module => module.permissions) || [],
|
|
266
|
-
roles: authResult.roles || [],
|
|
267
|
-
modules: authResult.modules || [],
|
|
268
|
-
fieldOffices: authResult.fieldOffices || []
|
|
269
|
-
}
|
|
284
|
+
user: authResult.user
|
|
270
285
|
};
|
|
271
286
|
}
|
|
272
287
|
};
|
|
@@ -292,8 +307,7 @@ export function createModuleGuard(modules: string[], requireAll = false) {
|
|
|
292
307
|
const guardPath = path.join(process.cwd(), 'src/exguard/exguard.guard.ts');
|
|
293
308
|
|
|
294
309
|
if (fs.existsSync(guardPath)) {
|
|
295
|
-
logWarning('ExGuard guards already exist.
|
|
296
|
-
return;
|
|
310
|
+
logWarning('ExGuard guards already exist. Overwriting...');
|
|
297
311
|
}
|
|
298
312
|
|
|
299
313
|
fs.writeFileSync(guardPath, guardContent);
|
|
@@ -376,8 +390,7 @@ export const Require = (requirements: {
|
|
|
376
390
|
const decoratorPath = path.join(process.cwd(), 'src/exguard/exguard.decorators.ts');
|
|
377
391
|
|
|
378
392
|
if (fs.existsSync(decoratorPath)) {
|
|
379
|
-
logWarning('ExGuard decorators already exist.
|
|
380
|
-
return;
|
|
393
|
+
logWarning('ExGuard decorators already exist. Overwriting...');
|
|
381
394
|
}
|
|
382
395
|
|
|
383
396
|
fs.writeFileSync(decoratorPath, decoratorContent);
|
|
@@ -466,18 +479,17 @@ export class EventsController {
|
|
|
466
479
|
}
|
|
467
480
|
`;
|
|
468
481
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
// Check if events directory exists
|
|
482
|
+
// Ensure directory exists
|
|
472
483
|
const eventsDir = path.join(process.cwd(), 'src/events');
|
|
473
484
|
if (!fs.existsSync(eventsDir)) {
|
|
474
485
|
fs.mkdirSync(eventsDir, { recursive: true });
|
|
475
486
|
logSuccess('Created events directory');
|
|
476
487
|
}
|
|
477
488
|
|
|
489
|
+
const controllerPath = path.join(process.cwd(), 'src/events/events.controller.ts');
|
|
490
|
+
|
|
478
491
|
if (fs.existsSync(controllerPath)) {
|
|
479
|
-
logWarning('Example controller already exists.
|
|
480
|
-
return;
|
|
492
|
+
logWarning('Example controller already exists. Overwriting...');
|
|
481
493
|
}
|
|
482
494
|
|
|
483
495
|
fs.writeFileSync(controllerPath, controllerContent);
|
|
@@ -491,7 +503,23 @@ function updateAppModule() {
|
|
|
491
503
|
const appModulePath = path.join(process.cwd(), 'src/app.module.ts');
|
|
492
504
|
|
|
493
505
|
if (!fs.existsSync(appModulePath)) {
|
|
494
|
-
logWarning('app.module.ts not found.
|
|
506
|
+
logWarning('app.module.ts not found. Creating basic app.module.ts...');
|
|
507
|
+
|
|
508
|
+
// Create basic app.module.ts
|
|
509
|
+
const basicAppModule = `import { Module } from '@nestjs/common';
|
|
510
|
+
import { ExGuardModule } from './exguard/exguard.module';
|
|
511
|
+
|
|
512
|
+
@Module({
|
|
513
|
+
imports: [
|
|
514
|
+
ExGuardModule
|
|
515
|
+
],
|
|
516
|
+
controllers: [],
|
|
517
|
+
})
|
|
518
|
+
export class AppModule {}
|
|
519
|
+
`;
|
|
520
|
+
|
|
521
|
+
fs.writeFileSync(appModulePath, basicAppModule);
|
|
522
|
+
logSuccess('Created basic app.module.ts with ExGuardModule');
|
|
495
523
|
return;
|
|
496
524
|
}
|
|
497
525
|
|
|
@@ -594,7 +622,8 @@ function updatePackageScripts() {
|
|
|
594
622
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
595
623
|
|
|
596
624
|
const scriptsToAdd = {
|
|
597
|
-
'
|
|
625
|
+
'setup-nestjs': 'node node_modules/exguard-backend/scripts/setup-nestjs.cjs',
|
|
626
|
+
'exguard:setup': 'node node_modules/exguard-backend/scripts/setup-nestjs.cjs',
|
|
598
627
|
'exguard:example': 'node node_modules/exguard-backend/scripts/create-example.cjs'
|
|
599
628
|
};
|
|
600
629
|
|