@urbansolv/create-nestjs-app 1.0.2 → 1.2.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.
- package/dist/templates/nestjs-app/.editorconfig +12 -12
- package/dist/templates/nestjs-app/.env.example +24 -24
- package/dist/templates/nestjs-app/.eslintrc.js +25 -25
- package/dist/templates/nestjs-app/package.json +40 -30
- package/dist/templates/nestjs-app/prisma/schema.prisma +79 -79
- package/dist/templates/nestjs-app/prisma/seed.ts +153 -154
- package/dist/templates/nestjs-app/src/app.module.ts +68 -68
- package/dist/templates/nestjs-app/src/common/constants/permissions.constant.ts +27 -27
- package/dist/templates/nestjs-app/src/common/decorators/api-response.decorator.ts +44 -44
- package/dist/templates/nestjs-app/src/common/decorators/get-user.decorator.ts +11 -11
- package/dist/templates/nestjs-app/src/common/decorators/permissions.decorator.ts +5 -5
- package/dist/templates/nestjs-app/src/common/decorators/public.decorator.ts +4 -4
- package/dist/templates/nestjs-app/src/common/dto/api-response.dto.ts +21 -21
- package/dist/templates/nestjs-app/src/common/dto/pagination.dto.ts +33 -33
- package/dist/templates/nestjs-app/src/common/filters/http-exception.filter.ts +56 -56
- package/dist/templates/nestjs-app/src/common/guards/jwt-auth.guard.ts +32 -32
- package/dist/templates/nestjs-app/src/common/guards/permissions.guard.ts +53 -53
- package/dist/templates/nestjs-app/src/common/interceptors/logging.interceptor.ts +37 -37
- package/dist/templates/nestjs-app/src/common/interceptors/transform.interceptor.ts +55 -55
- package/dist/templates/nestjs-app/src/common/prisma/prisma.module.ts +9 -9
- package/dist/templates/nestjs-app/src/common/prisma/prisma.service.ts +46 -46
- package/dist/templates/nestjs-app/src/common/utils/password.util.ts +13 -13
- package/dist/templates/nestjs-app/src/config/app.config.ts +10 -10
- package/dist/templates/nestjs-app/src/config/database.config.ts +5 -5
- package/dist/templates/nestjs-app/src/config/env.validation.ts +30 -30
- package/dist/templates/nestjs-app/src/config/jwt.config.ts +8 -8
- package/dist/templates/nestjs-app/src/config/swagger.config.ts +6 -6
- package/dist/templates/nestjs-app/src/main.ts +94 -91
- package/dist/templates/nestjs-app/src/modules/auth/auth.module.ts +28 -27
- package/dist/templates/nestjs-app/src/modules/auth/auth.service.ts +180 -54
- package/dist/templates/nestjs-app/src/modules/auth/controllers/v1/auth.controller.ts +33 -33
- package/dist/templates/nestjs-app/src/modules/auth/{dto → core/dto}/auth-response.dto.ts +19 -19
- package/dist/templates/nestjs-app/src/modules/auth/core/dto/login-response.dto.ts +10 -0
- package/dist/templates/nestjs-app/src/modules/auth/{dto → core/dto}/login.dto.ts +15 -15
- package/dist/templates/nestjs-app/src/modules/auth/{dto → core/dto}/register.dto.ts +30 -30
- package/dist/templates/nestjs-app/src/modules/auth/{interfaces → core/interfaces}/jwt-payload.interface.ts +7 -7
- package/dist/templates/nestjs-app/src/modules/auth/{strategies → core/strategies}/jwt.strategy.ts +54 -54
- package/dist/templates/nestjs-app/src/modules/health/health.controller.ts +29 -29
- package/dist/templates/nestjs-app/src/modules/health/health.module.ts +7 -7
- package/dist/templates/nestjs-app/src/modules/users/controllers/v1/users.controller.ts +118 -114
- package/dist/templates/nestjs-app/src/modules/users/core/dto/change-position.dto.ts +9 -9
- package/dist/templates/nestjs-app/src/modules/users/core/dto/create-user.dto.ts +35 -35
- package/dist/templates/nestjs-app/src/modules/users/core/dto/manage-permissions.dto.ts +13 -13
- package/dist/templates/nestjs-app/src/modules/users/core/dto/update-user.dto.ts +30 -30
- package/dist/templates/nestjs-app/src/modules/users/core/dto/user-query.dto.ts +22 -22
- package/dist/templates/nestjs-app/src/modules/users/core/dto/user-response.dto.ts +32 -0
- package/dist/templates/nestjs-app/src/modules/users/core/entities/user.entity.ts +45 -45
- package/dist/templates/nestjs-app/src/modules/users/core/helpers/user-transform.helper.ts +31 -31
- package/dist/templates/nestjs-app/src/modules/users/users.module.ts +10 -10
- package/dist/templates/nestjs-app/src/modules/users/users.service.ts +340 -340
- package/package.json +2 -2
|
@@ -1,154 +1,153 @@
|
|
|
1
|
-
import { PrismaClient } from '@prisma/client';
|
|
2
|
-
import * as bcrypt from '
|
|
3
|
-
|
|
4
|
-
const prisma = new PrismaClient();
|
|
5
|
-
|
|
6
|
-
async function main() {
|
|
7
|
-
console.log('🌱 Starting database seeding...\n');
|
|
8
|
-
|
|
9
|
-
// Clear existing data
|
|
10
|
-
console.log('🗑️ Clearing existing data...');
|
|
11
|
-
await prisma.positionPermission.deleteMany();
|
|
12
|
-
await prisma.user.deleteMany();
|
|
13
|
-
await prisma.permission.deleteMany();
|
|
14
|
-
await prisma.position.deleteMany();
|
|
15
|
-
|
|
16
|
-
// ============================================
|
|
17
|
-
// Seed Positions
|
|
18
|
-
// ============================================
|
|
19
|
-
console.log('📋 Seeding positions...');
|
|
20
|
-
const adminPosition = await prisma.position.create({
|
|
21
|
-
data: {
|
|
22
|
-
name: 'Administrator',
|
|
23
|
-
description: 'Full system access with all permissions',
|
|
24
|
-
},
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
const memberPosition = await prisma.position.create({
|
|
28
|
-
data: {
|
|
29
|
-
name: 'Member',
|
|
30
|
-
description: 'Standard user with limited permissions',
|
|
31
|
-
},
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
console.log('✅ Positions seeded');
|
|
35
|
-
|
|
36
|
-
// ============================================
|
|
37
|
-
// Seed Permissions
|
|
38
|
-
// ============================================
|
|
39
|
-
console.log('🔐 Seeding permissions...');
|
|
40
|
-
|
|
41
|
-
const permissionsData = [
|
|
42
|
-
// User Management
|
|
43
|
-
{ name: 'VIEW_USER', resource: 'USER', action: 'VIEW', description: 'View user information' },
|
|
44
|
-
{ name: 'ADD_USER', resource: 'USER', action: 'ADD', description: 'Create new user' },
|
|
45
|
-
{ name: 'UPDATE_USER', resource: 'USER', action: 'UPDATE', description: 'Update user information' },
|
|
46
|
-
{ name: 'DELETE_USER', resource: 'USER', action: 'DELETE', description: 'Delete user' },
|
|
47
|
-
{ name: 'MANAGE_USER_PERMISSION', resource: 'USER', action: 'MANAGE_PERMISSION', description: 'Assign or revoke user permissions' },
|
|
48
|
-
{ name: 'CHANGE_USER_POSITION', resource: 'USER', action: 'CHANGE_POSITION', description: 'Change user position/role' },
|
|
49
|
-
|
|
50
|
-
// Position Management
|
|
51
|
-
{ name: 'VIEW_POSITION', resource: 'POSITION', action: 'VIEW', description: 'View position information' },
|
|
52
|
-
{ name: 'ADD_POSITION', resource: 'POSITION', action: 'ADD', description: 'Create new position' },
|
|
53
|
-
{ name: 'UPDATE_POSITION', resource: 'POSITION', action: 'UPDATE', description: 'Update position information' },
|
|
54
|
-
{ name: 'DELETE_POSITION', resource: 'POSITION', action: 'DELETE', description: 'Delete position' },
|
|
55
|
-
|
|
56
|
-
// Permission Management
|
|
57
|
-
{ name: 'VIEW_PERMISSION', resource: 'PERMISSION', action: 'VIEW', description: 'View permission information' },
|
|
58
|
-
{ name: 'ADD_PERMISSION', resource: 'PERMISSION', action: 'ADD', description: 'Create new permission' },
|
|
59
|
-
{ name: 'UPDATE_PERMISSION', resource: 'PERMISSION', action: 'UPDATE', description: 'Update permission information' },
|
|
60
|
-
{ name: 'DELETE_PERMISSION', resource: 'PERMISSION', action: 'DELETE', description: 'Delete permission' },
|
|
61
|
-
];
|
|
62
|
-
|
|
63
|
-
const permissions = await Promise.all(
|
|
64
|
-
permissionsData.map((permission) =>
|
|
65
|
-
prisma.permission.create({ data: permission })
|
|
66
|
-
)
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
console.log(`✅ ${permissions.length} permissions seeded`);
|
|
70
|
-
|
|
71
|
-
// ============================================
|
|
72
|
-
// Assign Permissions to Positions
|
|
73
|
-
// ============================================
|
|
74
|
-
console.log('🔗 Assigning permissions to positions...');
|
|
75
|
-
|
|
76
|
-
// Admin gets all permissions
|
|
77
|
-
const adminPermissions = permissions.map((permission) => ({
|
|
78
|
-
position_id: adminPosition.id,
|
|
79
|
-
permission_id: permission.id,
|
|
80
|
-
}));
|
|
81
|
-
|
|
82
|
-
await prisma.positionPermission.createMany({
|
|
83
|
-
data: adminPermissions,
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
// Member gets only VIEW_USER permission
|
|
87
|
-
const viewUserPermission = permissions.find((p) => p.name === 'VIEW_USER');
|
|
88
|
-
if (viewUserPermission) {
|
|
89
|
-
await prisma.positionPermission.create({
|
|
90
|
-
data: {
|
|
91
|
-
position_id: memberPosition.id,
|
|
92
|
-
permission_id: viewUserPermission.id,
|
|
93
|
-
},
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
console.log('✅ Permissions assigned to positions');
|
|
98
|
-
|
|
99
|
-
// ============================================
|
|
100
|
-
// Seed Users
|
|
101
|
-
// ============================================
|
|
102
|
-
console.log('👥 Seeding users...');
|
|
103
|
-
|
|
104
|
-
const defaultPassword = 'password123';
|
|
105
|
-
const hashedPassword = await bcrypt.hash(defaultPassword, 10);
|
|
106
|
-
|
|
107
|
-
const adminUser = await prisma.user.create({
|
|
108
|
-
data: {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
//
|
|
133
|
-
//
|
|
134
|
-
|
|
135
|
-
console.log('
|
|
136
|
-
console.log(
|
|
137
|
-
console.log(` -
|
|
138
|
-
console.log(` -
|
|
139
|
-
console.log(` -
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
console.log(
|
|
143
|
-
console.log(`
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
});
|
|
1
|
+
import { PrismaClient } from '@prisma/client';
|
|
2
|
+
import * as bcrypt from 'bcryptjs';
|
|
3
|
+
|
|
4
|
+
const prisma = new PrismaClient();
|
|
5
|
+
|
|
6
|
+
async function main() {
|
|
7
|
+
console.log('🌱 Starting database seeding...\n');
|
|
8
|
+
|
|
9
|
+
// Clear existing data
|
|
10
|
+
console.log('🗑️ Clearing existing data...');
|
|
11
|
+
await prisma.positionPermission.deleteMany();
|
|
12
|
+
await prisma.user.deleteMany();
|
|
13
|
+
await prisma.permission.deleteMany();
|
|
14
|
+
await prisma.position.deleteMany();
|
|
15
|
+
|
|
16
|
+
// ============================================
|
|
17
|
+
// Seed Positions
|
|
18
|
+
// ============================================
|
|
19
|
+
console.log('📋 Seeding positions...');
|
|
20
|
+
const adminPosition = await prisma.position.create({
|
|
21
|
+
data: {
|
|
22
|
+
name: 'Administrator',
|
|
23
|
+
description: 'Full system access with all permissions',
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const memberPosition = await prisma.position.create({
|
|
28
|
+
data: {
|
|
29
|
+
name: 'Member',
|
|
30
|
+
description: 'Standard user with limited permissions',
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
console.log('✅ Positions seeded');
|
|
35
|
+
|
|
36
|
+
// ============================================
|
|
37
|
+
// Seed Permissions
|
|
38
|
+
// ============================================
|
|
39
|
+
console.log('🔐 Seeding permissions...');
|
|
40
|
+
|
|
41
|
+
const permissionsData = [
|
|
42
|
+
// User Management
|
|
43
|
+
{ name: 'VIEW_USER', resource: 'USER', action: 'VIEW', description: 'View user information' },
|
|
44
|
+
{ name: 'ADD_USER', resource: 'USER', action: 'ADD', description: 'Create new user' },
|
|
45
|
+
{ name: 'UPDATE_USER', resource: 'USER', action: 'UPDATE', description: 'Update user information' },
|
|
46
|
+
{ name: 'DELETE_USER', resource: 'USER', action: 'DELETE', description: 'Delete user' },
|
|
47
|
+
{ name: 'MANAGE_USER_PERMISSION', resource: 'USER', action: 'MANAGE_PERMISSION', description: 'Assign or revoke user permissions' },
|
|
48
|
+
{ name: 'CHANGE_USER_POSITION', resource: 'USER', action: 'CHANGE_POSITION', description: 'Change user position/role' },
|
|
49
|
+
|
|
50
|
+
// Position Management
|
|
51
|
+
{ name: 'VIEW_POSITION', resource: 'POSITION', action: 'VIEW', description: 'View position information' },
|
|
52
|
+
{ name: 'ADD_POSITION', resource: 'POSITION', action: 'ADD', description: 'Create new position' },
|
|
53
|
+
{ name: 'UPDATE_POSITION', resource: 'POSITION', action: 'UPDATE', description: 'Update position information' },
|
|
54
|
+
{ name: 'DELETE_POSITION', resource: 'POSITION', action: 'DELETE', description: 'Delete position' },
|
|
55
|
+
|
|
56
|
+
// Permission Management
|
|
57
|
+
{ name: 'VIEW_PERMISSION', resource: 'PERMISSION', action: 'VIEW', description: 'View permission information' },
|
|
58
|
+
{ name: 'ADD_PERMISSION', resource: 'PERMISSION', action: 'ADD', description: 'Create new permission' },
|
|
59
|
+
{ name: 'UPDATE_PERMISSION', resource: 'PERMISSION', action: 'UPDATE', description: 'Update permission information' },
|
|
60
|
+
{ name: 'DELETE_PERMISSION', resource: 'PERMISSION', action: 'DELETE', description: 'Delete permission' },
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
const permissions = await Promise.all(
|
|
64
|
+
permissionsData.map((permission) =>
|
|
65
|
+
prisma.permission.create({ data: permission })
|
|
66
|
+
)
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
console.log(`✅ ${permissions.length} permissions seeded`);
|
|
70
|
+
|
|
71
|
+
// ============================================
|
|
72
|
+
// Assign Permissions to Positions
|
|
73
|
+
// ============================================
|
|
74
|
+
console.log('🔗 Assigning permissions to positions...');
|
|
75
|
+
|
|
76
|
+
// Admin gets all permissions
|
|
77
|
+
const adminPermissions = permissions.map((permission) => ({
|
|
78
|
+
position_id: adminPosition.id,
|
|
79
|
+
permission_id: permission.id,
|
|
80
|
+
}));
|
|
81
|
+
|
|
82
|
+
await prisma.positionPermission.createMany({
|
|
83
|
+
data: adminPermissions,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Member gets only VIEW_USER permission
|
|
87
|
+
const viewUserPermission = permissions.find((p) => p.name === 'VIEW_USER');
|
|
88
|
+
if (viewUserPermission) {
|
|
89
|
+
await prisma.positionPermission.create({
|
|
90
|
+
data: {
|
|
91
|
+
position_id: memberPosition.id,
|
|
92
|
+
permission_id: viewUserPermission.id,
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
console.log('✅ Permissions assigned to positions');
|
|
98
|
+
|
|
99
|
+
// ============================================
|
|
100
|
+
// Seed Users
|
|
101
|
+
// ============================================
|
|
102
|
+
console.log('👥 Seeding users...');
|
|
103
|
+
|
|
104
|
+
const defaultPassword = 'password123';
|
|
105
|
+
const hashedPassword = await bcrypt.hash(defaultPassword, 10);
|
|
106
|
+
|
|
107
|
+
const adminUser = await prisma.user.create({
|
|
108
|
+
data: {
|
|
109
|
+
email: 'admin@urbansolv.com',
|
|
110
|
+
password: hashedPassword,
|
|
111
|
+
first_name: 'Admin',
|
|
112
|
+
last_name: 'Urbansolv',
|
|
113
|
+
position_id: adminPosition.id,
|
|
114
|
+
is_active: true,
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const memberUser = await prisma.user.create({
|
|
119
|
+
data: {
|
|
120
|
+
email: 'member@urbansolv.com',
|
|
121
|
+
password: hashedPassword,
|
|
122
|
+
first_name: 'Member',
|
|
123
|
+
last_name: 'User',
|
|
124
|
+
position_id: memberPosition.id,
|
|
125
|
+
is_active: true,
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
console.log('✅ Users seeded');
|
|
130
|
+
|
|
131
|
+
// ============================================
|
|
132
|
+
// Summary
|
|
133
|
+
// ============================================
|
|
134
|
+
console.log('\n✨ Database seeding completed!\n');
|
|
135
|
+
console.log('📊 Summary:');
|
|
136
|
+
console.log(` - Positions: ${await prisma.position.count()}`);
|
|
137
|
+
console.log(` - Permissions: ${await prisma.permission.count()}`);
|
|
138
|
+
console.log(` - Users: ${await prisma.user.count()}`);
|
|
139
|
+
console.log(` - Position-Permission Links: ${await prisma.positionPermission.count()}\n`);
|
|
140
|
+
|
|
141
|
+
console.log('🔑 Default Users:');
|
|
142
|
+
console.log(` Admin: ${adminUser.email} / ${defaultPassword}`);
|
|
143
|
+
console.log(` Member: ${memberUser.email} / ${defaultPassword}\n`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
main()
|
|
147
|
+
.catch((e) => {
|
|
148
|
+
console.error('❌ Error seeding database:', e);
|
|
149
|
+
process.exit(1);
|
|
150
|
+
})
|
|
151
|
+
.finally(async () => {
|
|
152
|
+
await prisma.$disconnect();
|
|
153
|
+
});
|
|
@@ -1,68 +1,68 @@
|
|
|
1
|
-
import { Module } from '@nestjs/common';
|
|
2
|
-
import { ConfigModule } from '@nestjs/config';
|
|
3
|
-
import { APP_GUARD, APP_FILTER, APP_INTERCEPTOR } from '@nestjs/core';
|
|
4
|
-
import { validationSchema } from './config/env.validation';
|
|
5
|
-
import appConfig from './config/app.config';
|
|
6
|
-
import databaseConfig from './config/database.config';
|
|
7
|
-
import jwtConfig from './config/jwt.config';
|
|
8
|
-
import swaggerConfig from './config/swagger.config';
|
|
9
|
-
|
|
10
|
-
// Common modules
|
|
11
|
-
import { PrismaModule } from './common/prisma/prisma.module';
|
|
12
|
-
import { JwtAuthGuard } from './common/guards/jwt-auth.guard';
|
|
13
|
-
import { PermissionsGuard } from './common/guards/permissions.guard';
|
|
14
|
-
import { HttpExceptionFilter } from './common/filters/http-exception.filter';
|
|
15
|
-
import { TransformInterceptor } from './common/interceptors/transform.interceptor';
|
|
16
|
-
import { LoggingInterceptor } from './common/interceptors/logging.interceptor';
|
|
17
|
-
|
|
18
|
-
// Feature modules
|
|
19
|
-
import { AuthModule } from './modules/auth/auth.module';
|
|
20
|
-
import { UsersModule } from './modules/users/users.module';
|
|
21
|
-
import { HealthModule } from './modules/health/health.module';
|
|
22
|
-
|
|
23
|
-
@Module({
|
|
24
|
-
imports: [
|
|
25
|
-
// Configuration
|
|
26
|
-
ConfigModule.forRoot({
|
|
27
|
-
isGlobal: true,
|
|
28
|
-
validationSchema,
|
|
29
|
-
load: [appConfig, databaseConfig, jwtConfig, swaggerConfig],
|
|
30
|
-
}),
|
|
31
|
-
|
|
32
|
-
// Common modules
|
|
33
|
-
PrismaModule,
|
|
34
|
-
|
|
35
|
-
// Feature modules
|
|
36
|
-
AuthModule,
|
|
37
|
-
UsersModule,
|
|
38
|
-
HealthModule,
|
|
39
|
-
],
|
|
40
|
-
providers: [
|
|
41
|
-
// Global guards
|
|
42
|
-
{
|
|
43
|
-
provide: APP_GUARD,
|
|
44
|
-
useClass: JwtAuthGuard,
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
provide: APP_GUARD,
|
|
48
|
-
useClass: PermissionsGuard,
|
|
49
|
-
},
|
|
50
|
-
|
|
51
|
-
// Global filters
|
|
52
|
-
{
|
|
53
|
-
provide: APP_FILTER,
|
|
54
|
-
useClass: HttpExceptionFilter,
|
|
55
|
-
},
|
|
56
|
-
|
|
57
|
-
// Global interceptors
|
|
58
|
-
{
|
|
59
|
-
provide: APP_INTERCEPTOR,
|
|
60
|
-
useClass: LoggingInterceptor,
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
provide: APP_INTERCEPTOR,
|
|
64
|
-
useClass: TransformInterceptor,
|
|
65
|
-
},
|
|
66
|
-
],
|
|
67
|
-
})
|
|
68
|
-
export class AppModule {}
|
|
1
|
+
import { Module } from '@nestjs/common';
|
|
2
|
+
import { ConfigModule } from '@nestjs/config';
|
|
3
|
+
import { APP_GUARD, APP_FILTER, APP_INTERCEPTOR } from '@nestjs/core';
|
|
4
|
+
import { validationSchema } from './config/env.validation';
|
|
5
|
+
import appConfig from './config/app.config';
|
|
6
|
+
import databaseConfig from './config/database.config';
|
|
7
|
+
import jwtConfig from './config/jwt.config';
|
|
8
|
+
import swaggerConfig from './config/swagger.config';
|
|
9
|
+
|
|
10
|
+
// Common modules
|
|
11
|
+
import { PrismaModule } from './common/prisma/prisma.module';
|
|
12
|
+
import { JwtAuthGuard } from './common/guards/jwt-auth.guard';
|
|
13
|
+
import { PermissionsGuard } from './common/guards/permissions.guard';
|
|
14
|
+
import { HttpExceptionFilter } from './common/filters/http-exception.filter';
|
|
15
|
+
import { TransformInterceptor } from './common/interceptors/transform.interceptor';
|
|
16
|
+
import { LoggingInterceptor } from './common/interceptors/logging.interceptor';
|
|
17
|
+
|
|
18
|
+
// Feature modules
|
|
19
|
+
import { AuthModule } from './modules/auth/auth.module';
|
|
20
|
+
import { UsersModule } from './modules/users/users.module';
|
|
21
|
+
import { HealthModule } from './modules/health/health.module';
|
|
22
|
+
|
|
23
|
+
@Module({
|
|
24
|
+
imports: [
|
|
25
|
+
// Configuration
|
|
26
|
+
ConfigModule.forRoot({
|
|
27
|
+
isGlobal: true,
|
|
28
|
+
validationSchema,
|
|
29
|
+
load: [appConfig, databaseConfig, jwtConfig, swaggerConfig],
|
|
30
|
+
}),
|
|
31
|
+
|
|
32
|
+
// Common modules
|
|
33
|
+
PrismaModule,
|
|
34
|
+
|
|
35
|
+
// Feature modules
|
|
36
|
+
AuthModule,
|
|
37
|
+
UsersModule,
|
|
38
|
+
HealthModule,
|
|
39
|
+
],
|
|
40
|
+
providers: [
|
|
41
|
+
// Global guards
|
|
42
|
+
{
|
|
43
|
+
provide: APP_GUARD,
|
|
44
|
+
useClass: JwtAuthGuard,
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
provide: APP_GUARD,
|
|
48
|
+
useClass: PermissionsGuard,
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
// Global filters
|
|
52
|
+
{
|
|
53
|
+
provide: APP_FILTER,
|
|
54
|
+
useClass: HttpExceptionFilter,
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
// Global interceptors
|
|
58
|
+
{
|
|
59
|
+
provide: APP_INTERCEPTOR,
|
|
60
|
+
useClass: LoggingInterceptor,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
provide: APP_INTERCEPTOR,
|
|
64
|
+
useClass: TransformInterceptor,
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
})
|
|
68
|
+
export class AppModule {}
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
export const PERMISSIONS = {
|
|
2
|
-
// User Management
|
|
3
|
-
USER: {
|
|
4
|
-
VIEW: 'VIEW_USER',
|
|
5
|
-
ADD: 'ADD_USER',
|
|
6
|
-
UPDATE: 'UPDATE_USER',
|
|
7
|
-
DELETE: 'DELETE_USER',
|
|
8
|
-
MANAGE_PERMISSION: 'MANAGE_USER_PERMISSION',
|
|
9
|
-
CHANGE_POSITION: 'CHANGE_USER_POSITION',
|
|
10
|
-
},
|
|
11
|
-
|
|
12
|
-
// Position Management
|
|
13
|
-
POSITION: {
|
|
14
|
-
VIEW: 'VIEW_POSITION',
|
|
15
|
-
ADD: 'ADD_POSITION',
|
|
16
|
-
UPDATE: 'UPDATE_POSITION',
|
|
17
|
-
DELETE: 'DELETE_POSITION',
|
|
18
|
-
},
|
|
19
|
-
|
|
20
|
-
// Permission Management
|
|
21
|
-
PERMISSION: {
|
|
22
|
-
VIEW: 'VIEW_PERMISSION',
|
|
23
|
-
ADD: 'ADD_PERMISSION',
|
|
24
|
-
UPDATE: 'UPDATE_PERMISSION',
|
|
25
|
-
DELETE: 'DELETE_PERMISSION',
|
|
26
|
-
},
|
|
27
|
-
} as const;
|
|
1
|
+
export const PERMISSIONS = {
|
|
2
|
+
// User Management
|
|
3
|
+
USER: {
|
|
4
|
+
VIEW: 'VIEW_USER',
|
|
5
|
+
ADD: 'ADD_USER',
|
|
6
|
+
UPDATE: 'UPDATE_USER',
|
|
7
|
+
DELETE: 'DELETE_USER',
|
|
8
|
+
MANAGE_PERMISSION: 'MANAGE_USER_PERMISSION',
|
|
9
|
+
CHANGE_POSITION: 'CHANGE_USER_POSITION',
|
|
10
|
+
},
|
|
11
|
+
|
|
12
|
+
// Position Management
|
|
13
|
+
POSITION: {
|
|
14
|
+
VIEW: 'VIEW_POSITION',
|
|
15
|
+
ADD: 'ADD_POSITION',
|
|
16
|
+
UPDATE: 'UPDATE_POSITION',
|
|
17
|
+
DELETE: 'DELETE_POSITION',
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
// Permission Management
|
|
21
|
+
PERMISSION: {
|
|
22
|
+
VIEW: 'VIEW_PERMISSION',
|
|
23
|
+
ADD: 'ADD_PERMISSION',
|
|
24
|
+
UPDATE: 'UPDATE_PERMISSION',
|
|
25
|
+
DELETE: 'DELETE_PERMISSION',
|
|
26
|
+
},
|
|
27
|
+
} as const;
|
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
import { applyDecorators, Type } from '@nestjs/common';
|
|
2
|
-
import { ApiExtraModels, ApiOkResponse, getSchemaPath } from '@nestjs/swagger';
|
|
3
|
-
import { ApiResponseDto } from '@common/dto/api-response.dto';
|
|
4
|
-
|
|
5
|
-
export const ApiSuccessResponse = <TModel extends Type<any>>(model: TModel) => {
|
|
6
|
-
return applyDecorators(
|
|
7
|
-
ApiExtraModels(ApiResponseDto, model),
|
|
8
|
-
ApiOkResponse({
|
|
9
|
-
schema: {
|
|
10
|
-
allOf: [
|
|
11
|
-
{ $ref: getSchemaPath(ApiResponseDto) },
|
|
12
|
-
{
|
|
13
|
-
properties: {
|
|
14
|
-
data: {
|
|
15
|
-
$ref: getSchemaPath(model),
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
|
-
],
|
|
20
|
-
},
|
|
21
|
-
}),
|
|
22
|
-
);
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export const ApiSuccessArrayResponse = <TModel extends Type<any>>(model: TModel) => {
|
|
26
|
-
return applyDecorators(
|
|
27
|
-
ApiExtraModels(ApiResponseDto, model),
|
|
28
|
-
ApiOkResponse({
|
|
29
|
-
schema: {
|
|
30
|
-
allOf: [
|
|
31
|
-
{ $ref: getSchemaPath(ApiResponseDto) },
|
|
32
|
-
{
|
|
33
|
-
properties: {
|
|
34
|
-
data: {
|
|
35
|
-
type: 'array',
|
|
36
|
-
items: { $ref: getSchemaPath(model) },
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
],
|
|
41
|
-
},
|
|
42
|
-
}),
|
|
43
|
-
);
|
|
44
|
-
};
|
|
1
|
+
import { applyDecorators, Type } from '@nestjs/common';
|
|
2
|
+
import { ApiExtraModels, ApiOkResponse, getSchemaPath } from '@nestjs/swagger';
|
|
3
|
+
import { ApiResponseDto } from '@common/dto/api-response.dto';
|
|
4
|
+
|
|
5
|
+
export const ApiSuccessResponse = <TModel extends Type<any>>(model: TModel) => {
|
|
6
|
+
return applyDecorators(
|
|
7
|
+
ApiExtraModels(ApiResponseDto, model),
|
|
8
|
+
ApiOkResponse({
|
|
9
|
+
schema: {
|
|
10
|
+
allOf: [
|
|
11
|
+
{ $ref: getSchemaPath(ApiResponseDto) },
|
|
12
|
+
{
|
|
13
|
+
properties: {
|
|
14
|
+
data: {
|
|
15
|
+
$ref: getSchemaPath(model),
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
},
|
|
21
|
+
}),
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const ApiSuccessArrayResponse = <TModel extends Type<any>>(model: TModel) => {
|
|
26
|
+
return applyDecorators(
|
|
27
|
+
ApiExtraModels(ApiResponseDto, model),
|
|
28
|
+
ApiOkResponse({
|
|
29
|
+
schema: {
|
|
30
|
+
allOf: [
|
|
31
|
+
{ $ref: getSchemaPath(ApiResponseDto) },
|
|
32
|
+
{
|
|
33
|
+
properties: {
|
|
34
|
+
data: {
|
|
35
|
+
type: 'array',
|
|
36
|
+
items: { $ref: getSchemaPath(model) },
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
}),
|
|
43
|
+
);
|
|
44
|
+
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
|
|
2
|
-
import { JwtPayload } from '@modules/auth/interfaces/jwt-payload.interface';
|
|
3
|
-
|
|
4
|
-
export const GetUser = createParamDecorator(
|
|
5
|
-
(data: keyof JwtPayload | undefined, ctx: ExecutionContext): JwtPayload | any => {
|
|
6
|
-
const request = ctx.switchToHttp().getRequest();
|
|
7
|
-
const user = request.user;
|
|
8
|
-
|
|
9
|
-
return data ? user?.[data] : user;
|
|
10
|
-
},
|
|
11
|
-
);
|
|
1
|
+
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
|
|
2
|
+
import { JwtPayload } from '@modules/auth/core/interfaces/jwt-payload.interface';
|
|
3
|
+
|
|
4
|
+
export const GetUser = createParamDecorator(
|
|
5
|
+
(data: keyof JwtPayload | undefined, ctx: ExecutionContext): JwtPayload | any => {
|
|
6
|
+
const request = ctx.switchToHttp().getRequest();
|
|
7
|
+
const user = request.user;
|
|
8
|
+
|
|
9
|
+
return data ? user?.[data] : user;
|
|
10
|
+
},
|
|
11
|
+
);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { SetMetadata } from '@nestjs/common';
|
|
2
|
-
|
|
3
|
-
export const PERMISSIONS_KEY = 'permissions';
|
|
4
|
-
export const Permissions = (...permissions: string[]) =>
|
|
5
|
-
SetMetadata(PERMISSIONS_KEY, permissions);
|
|
1
|
+
import { SetMetadata } from '@nestjs/common';
|
|
2
|
+
|
|
3
|
+
export const PERMISSIONS_KEY = 'permissions';
|
|
4
|
+
export const Permissions = (...permissions: string[]) =>
|
|
5
|
+
SetMetadata(PERMISSIONS_KEY, permissions);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SetMetadata } from '@nestjs/common';
|
|
2
|
-
|
|
3
|
-
export const IS_PUBLIC_KEY = 'isPublic';
|
|
4
|
-
export const Public = () => SetMetadata(IS_PUBLIC_KEY, true);
|
|
1
|
+
import { SetMetadata } from '@nestjs/common';
|
|
2
|
+
|
|
3
|
+
export const IS_PUBLIC_KEY = 'isPublic';
|
|
4
|
+
export const Public = () => SetMetadata(IS_PUBLIC_KEY, true);
|