nest-authme 1.0.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/LICENSE +21 -0
- package/README.md +305 -0
- package/bin/cli.js +11 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +1619 -0
- package/dist/cli.js.map +1 -0
- package/dist/generator/templates/decorators/current-user.decorator.ts.hbs +8 -0
- package/dist/generator/templates/decorators/public.decorator.ts.hbs +4 -0
- package/dist/generator/templates/decorators/roles.decorator.ts.hbs +4 -0
- package/dist/generator/templates/dto/auth-response.dto.ts.hbs +42 -0
- package/dist/generator/templates/dto/change-password.dto.ts.hbs +22 -0
- package/dist/generator/templates/dto/create-user.dto.ts.hbs +38 -0
- package/dist/generator/templates/dto/forgot-password.dto.ts.hbs +13 -0
- package/dist/generator/templates/dto/login.dto.ts.hbs +21 -0
- package/dist/generator/templates/dto/register.dto.ts.hbs +33 -0
- package/dist/generator/templates/dto/reset-password.dto.ts.hbs +22 -0
- package/dist/generator/templates/entities/refresh-token.entity.typeorm.hbs +24 -0
- package/dist/generator/templates/entities/user.entity.typeorm.hbs +51 -0
- package/dist/generator/templates/jwt/auth.controller.ts.hbs +177 -0
- package/dist/generator/templates/jwt/auth.module.ts.hbs +81 -0
- package/dist/generator/templates/jwt/auth.service.ts.hbs +416 -0
- package/dist/generator/templates/jwt/jwt-auth.guard.ts.hbs +24 -0
- package/dist/generator/templates/jwt/jwt.strategy.ts.hbs +61 -0
- package/dist/generator/templates/jwt/local-auth.guard.ts.hbs +5 -0
- package/dist/generator/templates/jwt/local.strategy.ts.hbs +22 -0
- package/dist/generator/templates/prisma/prisma.module.ts.hbs +9 -0
- package/dist/generator/templates/prisma/prisma.service.ts.hbs +9 -0
- package/dist/generator/templates/prisma/schema.prisma.additions.hbs +40 -0
- package/dist/generator/templates/rbac/role.enum.ts.hbs +5 -0
- package/dist/generator/templates/rbac/roles.guard.ts.hbs +22 -0
- package/dist/generator/templates/shared/README.auth.md.hbs +306 -0
- package/dist/generator/templates/shared/env.hbs +36 -0
- package/dist/generator/templates/shared/env.template.hbs +36 -0
- package/dist/generator/templates/shared/main.ts.snippet.hbs +49 -0
- package/dist/generator/templates/tests/auth.controller.spec.ts.hbs +189 -0
- package/dist/generator/templates/tests/auth.service.spec.ts.hbs +334 -0
- package/dist/generator/templates/users/users.controller.ts.hbs +55 -0
- package/dist/generator/templates/users/users.module.ts.hbs +31 -0
- package/dist/generator/templates/users/users.service.ts.hbs +192 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +1566 -0
- package/dist/index.js.map +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
|
2
|
+
import { PassportStrategy } from '@nestjs/passport';
|
|
3
|
+
import { ExtractJwt, Strategy } from 'passport-jwt';
|
|
4
|
+
import { ConfigService } from '@nestjs/config';
|
|
5
|
+
{{#if (eq orm "typeorm")}}
|
|
6
|
+
import { InjectRepository } from '@nestjs/typeorm';
|
|
7
|
+
import { Repository } from 'typeorm';
|
|
8
|
+
import { User } from '../../users/entities/user.entity';
|
|
9
|
+
{{else}}
|
|
10
|
+
import { UsersService } from '../../users/users.service';
|
|
11
|
+
{{/if}}
|
|
12
|
+
|
|
13
|
+
@Injectable()
|
|
14
|
+
export class JwtStrategy extends PassportStrategy(Strategy) {
|
|
15
|
+
constructor(
|
|
16
|
+
{{#if (eq orm "typeorm")}}
|
|
17
|
+
@InjectRepository(User)
|
|
18
|
+
private usersRepository: Repository<User>,
|
|
19
|
+
{{else}}
|
|
20
|
+
private usersService: UsersService,
|
|
21
|
+
{{/if}}
|
|
22
|
+
private configService: ConfigService,
|
|
23
|
+
) {
|
|
24
|
+
const secret = configService.get<string>('JWT_SECRET');
|
|
25
|
+
|
|
26
|
+
if (!secret) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
'JWT_SECRET is not defined. Please add JWT_SECRET to your .env file.'
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
super({
|
|
33
|
+
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
|
|
34
|
+
ignoreExpiration: false,
|
|
35
|
+
secretOrKey: secret,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async validate(payload: any) {
|
|
40
|
+
{{#if (eq orm "typeorm")}}
|
|
41
|
+
const user = await this.usersRepository.findOne({
|
|
42
|
+
where: { id: payload.sub },
|
|
43
|
+
});
|
|
44
|
+
{{else}}
|
|
45
|
+
const user = await this.usersService.findById(payload.sub);
|
|
46
|
+
{{/if}}
|
|
47
|
+
|
|
48
|
+
if (!user) {
|
|
49
|
+
throw new UnauthorizedException();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Return user object (will be attached to request.user)
|
|
53
|
+
return {
|
|
54
|
+
id: user.id,
|
|
55
|
+
email: user.email,
|
|
56
|
+
{{#if rbac.enabled}}
|
|
57
|
+
roles: user.roles,
|
|
58
|
+
{{/if}}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
|
2
|
+
import { PassportStrategy } from '@nestjs/passport';
|
|
3
|
+
import { Strategy } from 'passport-local';
|
|
4
|
+
import { AuthService } from '../auth.service';
|
|
5
|
+
|
|
6
|
+
@Injectable()
|
|
7
|
+
export class LocalStrategy extends PassportStrategy(Strategy) {
|
|
8
|
+
constructor(private authService: AuthService) {
|
|
9
|
+
super({
|
|
10
|
+
usernameField: 'email',
|
|
11
|
+
passwordField: 'password',
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async validate(email: string, password: string): Promise<any> {
|
|
16
|
+
const user = await this.authService.validateUser(email, password);
|
|
17
|
+
if (!user) {
|
|
18
|
+
throw new UnauthorizedException('Invalid credentials');
|
|
19
|
+
}
|
|
20
|
+
return user;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// Add these models to your prisma/schema.prisma file
|
|
3
|
+
// Then run: npx prisma migrate dev --name add-auth-models
|
|
4
|
+
// ============================================================
|
|
5
|
+
|
|
6
|
+
model User {
|
|
7
|
+
id String @id @default(uuid())
|
|
8
|
+
email String @unique
|
|
9
|
+
{{#if features.useUsername}}
|
|
10
|
+
username String @unique
|
|
11
|
+
{{/if}}
|
|
12
|
+
password String
|
|
13
|
+
{{#if rbac.enabled}}
|
|
14
|
+
roles String[] @default(["User"])
|
|
15
|
+
{{/if}}
|
|
16
|
+
{{#if features.emailVerification}}
|
|
17
|
+
isEmailVerified Boolean @default(false)
|
|
18
|
+
emailVerificationToken String?
|
|
19
|
+
{{/if}}
|
|
20
|
+
{{#if features.resetPassword}}
|
|
21
|
+
passwordResetToken String?
|
|
22
|
+
passwordResetExpires DateTime?
|
|
23
|
+
{{/if}}
|
|
24
|
+
{{#if features.refreshTokens}}
|
|
25
|
+
refreshTokens RefreshToken[]
|
|
26
|
+
{{/if}}
|
|
27
|
+
createdAt DateTime @default(now())
|
|
28
|
+
updatedAt DateTime @updatedAt
|
|
29
|
+
}
|
|
30
|
+
{{#if features.refreshTokens}}
|
|
31
|
+
|
|
32
|
+
model RefreshToken {
|
|
33
|
+
id String @id @default(uuid())
|
|
34
|
+
token String @unique
|
|
35
|
+
userId String
|
|
36
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
37
|
+
expiresAt DateTime
|
|
38
|
+
createdAt DateTime @default(now())
|
|
39
|
+
}
|
|
40
|
+
{{/if}}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
|
|
2
|
+
import { Reflector } from '@nestjs/core';
|
|
3
|
+
import { ROLES_KEY } from '../decorators/roles.decorator';
|
|
4
|
+
|
|
5
|
+
@Injectable()
|
|
6
|
+
export class RolesGuard implements CanActivate {
|
|
7
|
+
constructor(private reflector: Reflector) {}
|
|
8
|
+
|
|
9
|
+
canActivate(context: ExecutionContext): boolean {
|
|
10
|
+
const requiredRoles = this.reflector.getAllAndOverride<string[]>(ROLES_KEY, [
|
|
11
|
+
context.getHandler(),
|
|
12
|
+
context.getClass(),
|
|
13
|
+
]);
|
|
14
|
+
|
|
15
|
+
if (!requiredRoles) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const { user } = context.switchToHttp().getRequest();
|
|
20
|
+
return requiredRoles.some((role) => user.roles?.includes(role));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
# Authentication Module
|
|
2
|
+
|
|
3
|
+
Generated by **nest-authme** on {{timestamp}}
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This authentication module provides:
|
|
8
|
+
- ✅ JWT-based authentication
|
|
9
|
+
{{#if rbac.enabled}}
|
|
10
|
+
- ✅ Role-Based Access Control (RBAC)
|
|
11
|
+
{{/if}}
|
|
12
|
+
{{#if features.refreshTokens}}
|
|
13
|
+
- ✅ Refresh token rotation
|
|
14
|
+
{{/if}}
|
|
15
|
+
- ✅ Password hashing with bcrypt
|
|
16
|
+
- ✅ Request validation with class-validator
|
|
17
|
+
{{#if (eq orm "typeorm")}}
|
|
18
|
+
- ✅ TypeORM integration
|
|
19
|
+
{{/if}}
|
|
20
|
+
|
|
21
|
+
## Endpoints
|
|
22
|
+
|
|
23
|
+
### Public Endpoints (No authentication required)
|
|
24
|
+
|
|
25
|
+
#### POST /auth/register
|
|
26
|
+
Register a new user.
|
|
27
|
+
|
|
28
|
+
**Request body:**
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"email": "user@example.com",
|
|
32
|
+
"password": "your-password"
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Response:**
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
|
|
40
|
+
{{#if features.refreshTokens}}
|
|
41
|
+
"refreshToken": "eyJhbGciOiJIUzI1NiIs...",
|
|
42
|
+
{{/if}}
|
|
43
|
+
"user": {
|
|
44
|
+
"id": "uuid",
|
|
45
|
+
"email": "user@example.com"{{#if rbac.enabled}},
|
|
46
|
+
"roles": ["User"]{{/if}}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
#### POST /auth/login
|
|
52
|
+
Login with existing credentials.
|
|
53
|
+
|
|
54
|
+
**Request body:**
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"email": "user@example.com",
|
|
58
|
+
"password": "your-password"
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Response:** Same as register
|
|
63
|
+
|
|
64
|
+
{{#if features.refreshTokens}}
|
|
65
|
+
#### POST /auth/refresh
|
|
66
|
+
Refresh access token using refresh token.
|
|
67
|
+
|
|
68
|
+
**Request body:**
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
"refreshToken": "eyJhbGciOiJIUzI1NiIs..."
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Response:**
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"accessToken": "eyJhbGciOiJIUzI1NiIs..."
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
{{/if}}
|
|
82
|
+
|
|
83
|
+
### Protected Endpoints (Authentication required)
|
|
84
|
+
|
|
85
|
+
#### GET /users/profile
|
|
86
|
+
Get current user profile.
|
|
87
|
+
|
|
88
|
+
**Headers:**
|
|
89
|
+
```
|
|
90
|
+
Authorization: Bearer <accessToken>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Response:**
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"id": "uuid",
|
|
97
|
+
"email": "user@example.com"{{#if rbac.enabled}},
|
|
98
|
+
"roles": ["User"]{{/if}}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
{{#if rbac.enabled}}
|
|
103
|
+
#### GET /users (Admin only)
|
|
104
|
+
Get all users.
|
|
105
|
+
|
|
106
|
+
**Headers:**
|
|
107
|
+
```
|
|
108
|
+
Authorization: Bearer <accessToken>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**Response:**
|
|
112
|
+
```json
|
|
113
|
+
[
|
|
114
|
+
{
|
|
115
|
+
"id": "uuid",
|
|
116
|
+
"email": "user@example.com",
|
|
117
|
+
"roles": ["User"],
|
|
118
|
+
"createdAt": "2026-01-01T00:00:00.000Z"
|
|
119
|
+
}
|
|
120
|
+
]
|
|
121
|
+
```
|
|
122
|
+
{{/if}}
|
|
123
|
+
|
|
124
|
+
## Setup
|
|
125
|
+
|
|
126
|
+
### Enable Global JWT Guard (Recommended)
|
|
127
|
+
|
|
128
|
+
To automatically protect all routes by default, add the JWT guard globally in your `main.ts`.
|
|
129
|
+
|
|
130
|
+
**📄 See `main.ts.example` in your project root for a complete setup example.**
|
|
131
|
+
|
|
132
|
+
Quick setup - add these lines to your `main.ts`:
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import { Reflector } from '@nestjs/core';
|
|
136
|
+
import { JwtAuthGuard } from './auth/guards/jwt-auth.guard';
|
|
137
|
+
|
|
138
|
+
// In bootstrap() function:
|
|
139
|
+
const reflector = app.get(Reflector);
|
|
140
|
+
app.useGlobalGuards(new JwtAuthGuard(reflector));
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
This makes all routes protected by default. Use `@Public()` to make specific routes public.
|
|
144
|
+
|
|
145
|
+
**Alternative:** Manually add `@UseGuards(JwtAuthGuard)` to each protected controller/route.
|
|
146
|
+
|
|
147
|
+
## Usage
|
|
148
|
+
|
|
149
|
+
### Protect Routes
|
|
150
|
+
|
|
151
|
+
By default (with global guard), all routes require authentication. Use the `@Public()` decorator to make routes public:
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
import { Public } from './auth/decorators/public.decorator';
|
|
155
|
+
|
|
156
|
+
@Public()
|
|
157
|
+
@Get('public')
|
|
158
|
+
getPublicData() {
|
|
159
|
+
return 'This endpoint is public';
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Get Current User
|
|
164
|
+
|
|
165
|
+
Use the `@CurrentUser()` decorator to access the authenticated user:
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
import { CurrentUser } from './auth/decorators/current-user.decorator';
|
|
169
|
+
|
|
170
|
+
@Get('me')
|
|
171
|
+
getMe(@CurrentUser() user: any) {
|
|
172
|
+
return user;
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
{{#if rbac.enabled}}
|
|
177
|
+
### Role-Based Access Control
|
|
178
|
+
|
|
179
|
+
Use the `@Roles()` decorator to restrict access by role:
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
import { Roles } from './auth/decorators/roles.decorator';
|
|
183
|
+
import { RolesGuard } from './auth/guards/roles.guard';
|
|
184
|
+
|
|
185
|
+
@UseGuards(JwtAuthGuard, RolesGuard)
|
|
186
|
+
@Roles('Admin')
|
|
187
|
+
@Get('admin-only')
|
|
188
|
+
adminOnlyRoute() {
|
|
189
|
+
return 'Only admins can see this';
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Available roles: {{#each rbac.roles}}{{this}}{{#unless @last}}, {{/unless}}{{/each}}
|
|
194
|
+
{{/if}}
|
|
195
|
+
|
|
196
|
+
## Environment Variables
|
|
197
|
+
|
|
198
|
+
Copy `.env.example` to `.env` and update the values:
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
cp .env.example .env
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Required variables:
|
|
205
|
+
- `JWT_SECRET` - Secret key for JWT signing (auto-generated, but you can change it)
|
|
206
|
+
- `JWT_EXPIRES_IN` - Access token expiration (e.g., "1h", "15m")
|
|
207
|
+
{{#if features.refreshTokens}}
|
|
208
|
+
- `JWT_REFRESH_EXPIRES_IN` - Refresh token expiration (e.g., "7d")
|
|
209
|
+
{{/if}}
|
|
210
|
+
{{#if (eq orm "typeorm")}}
|
|
211
|
+
- `DATABASE_*` - Database connection details
|
|
212
|
+
{{/if}}
|
|
213
|
+
|
|
214
|
+
{{#if (eq orm "typeorm")}}
|
|
215
|
+
## Database Setup
|
|
216
|
+
|
|
217
|
+
### Create Migration
|
|
218
|
+
|
|
219
|
+
Generate a migration for the auth tables:
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
npm run migration:generate -- src/migrations/CreateAuthTables
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Run Migration
|
|
226
|
+
|
|
227
|
+
Apply the migration:
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
npm run migration:run
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Revert Migration
|
|
234
|
+
|
|
235
|
+
Rollback the migration:
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
npm run migration:revert
|
|
239
|
+
```
|
|
240
|
+
{{/if}}
|
|
241
|
+
|
|
242
|
+
## Security Best Practices
|
|
243
|
+
|
|
244
|
+
1. **Never commit .env file** - It contains sensitive secrets
|
|
245
|
+
2. **Use strong JWT secrets** - At least 32 characters, random
|
|
246
|
+
3. **HTTPS in production** - Always use HTTPS to protect tokens
|
|
247
|
+
4. **Short token expiration** - Keep access tokens short-lived
|
|
248
|
+
{{#if features.refreshTokens}}
|
|
249
|
+
5. **Rotate refresh tokens** - Refresh tokens are automatically rotated
|
|
250
|
+
{{/if}}
|
|
251
|
+
6. **Rate limiting** - Add rate limiting to auth endpoints
|
|
252
|
+
7. **Password requirements** - Enforce strong password policies
|
|
253
|
+
|
|
254
|
+
## Testing
|
|
255
|
+
|
|
256
|
+
### Register a User
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
curl -X POST http://localhost:3000/auth/register \
|
|
260
|
+
-H "Content-Type: application/json" \
|
|
261
|
+
-d '{"email":"test@example.com","password":"Password123!"}'
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### Login
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
curl -X POST http://localhost:3000/auth/login \
|
|
268
|
+
-H "Content-Type: application/json" \
|
|
269
|
+
-d '{"email":"test@example.com","password":"Password123!"}'
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Access Protected Route
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
curl http://localhost:3000/users/profile \
|
|
276
|
+
-H "Authorization: Bearer <your-access-token>"
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## Troubleshooting
|
|
280
|
+
|
|
281
|
+
### "JWT secret not found"
|
|
282
|
+
Make sure `.env` file exists and contains `JWT_SECRET`.
|
|
283
|
+
|
|
284
|
+
### "Database connection failed"
|
|
285
|
+
Check your database is running and credentials in `.env` are correct.
|
|
286
|
+
|
|
287
|
+
### "Invalid credentials"
|
|
288
|
+
Ensure email and password are correct. Passwords are case-sensitive.
|
|
289
|
+
|
|
290
|
+
{{#if (eq orm "typeorm")}}
|
|
291
|
+
### "Entity not found"
|
|
292
|
+
Run migrations: `npm run migration:run`
|
|
293
|
+
{{/if}}
|
|
294
|
+
|
|
295
|
+
## Documentation
|
|
296
|
+
|
|
297
|
+
- [NestJS Authentication](https://docs.nestjs.com/security/authentication)
|
|
298
|
+
- [Passport.js](http://www.passportjs.org/)
|
|
299
|
+
- [JWT](https://jwt.io/)
|
|
300
|
+
{{#if (eq orm "typeorm")}}
|
|
301
|
+
- [TypeORM](https://typeorm.io/)
|
|
302
|
+
{{/if}}
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
Generated with ❤️ by [nest-authme](https://www.npmjs.com/package/nest-authme)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# JWT Configuration
|
|
2
|
+
JWT_SECRET={{jwt.secret}}
|
|
3
|
+
JWT_EXPIRES_IN={{jwt.accessExpiration}}
|
|
4
|
+
{{#if features.refreshTokens}}
|
|
5
|
+
JWT_REFRESH_EXPIRES_IN={{jwt.refreshExpiration}}
|
|
6
|
+
{{/if}}
|
|
7
|
+
|
|
8
|
+
# Bcrypt
|
|
9
|
+
BCRYPT_ROUNDS=10
|
|
10
|
+
|
|
11
|
+
# Database Configuration
|
|
12
|
+
{{#if (eq orm "prisma")}}
|
|
13
|
+
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/{{projectName}}?schema=public
|
|
14
|
+
{{else}}
|
|
15
|
+
{{#if (eq database "postgres")}}
|
|
16
|
+
DATABASE_HOST=localhost
|
|
17
|
+
DATABASE_PORT=5432
|
|
18
|
+
DATABASE_USER=postgres
|
|
19
|
+
DATABASE_PASSWORD=postgres
|
|
20
|
+
DATABASE_NAME={{projectName}}
|
|
21
|
+
{{/if}}
|
|
22
|
+
{{#if (eq database "mysql")}}
|
|
23
|
+
DATABASE_HOST=localhost
|
|
24
|
+
DATABASE_PORT=3306
|
|
25
|
+
DATABASE_USER=root
|
|
26
|
+
DATABASE_PASSWORD=root
|
|
27
|
+
DATABASE_NAME={{projectName}}
|
|
28
|
+
{{/if}}
|
|
29
|
+
{{#if (eq database "mongodb")}}
|
|
30
|
+
MONGODB_URI=mongodb://localhost:27017/{{projectName}}
|
|
31
|
+
{{/if}}
|
|
32
|
+
{{/if}}
|
|
33
|
+
|
|
34
|
+
# Application
|
|
35
|
+
NODE_ENV=development
|
|
36
|
+
PORT=3000
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# JWT Configuration
|
|
2
|
+
JWT_SECRET=CHANGE_ME_GENERATE_WITH_openssl_rand_base64_32
|
|
3
|
+
JWT_EXPIRES_IN={{jwt.accessExpiration}}
|
|
4
|
+
{{#if features.refreshTokens}}
|
|
5
|
+
JWT_REFRESH_EXPIRES_IN={{jwt.refreshExpiration}}
|
|
6
|
+
{{/if}}
|
|
7
|
+
|
|
8
|
+
# Bcrypt
|
|
9
|
+
BCRYPT_ROUNDS=10
|
|
10
|
+
|
|
11
|
+
# Database Configuration
|
|
12
|
+
{{#if (eq orm "prisma")}}
|
|
13
|
+
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/{{projectName}}?schema=public
|
|
14
|
+
{{else}}
|
|
15
|
+
{{#if (eq database "postgres")}}
|
|
16
|
+
DATABASE_HOST=localhost
|
|
17
|
+
DATABASE_PORT=5432
|
|
18
|
+
DATABASE_USER=postgres
|
|
19
|
+
DATABASE_PASSWORD=postgres
|
|
20
|
+
DATABASE_NAME={{projectName}}
|
|
21
|
+
{{/if}}
|
|
22
|
+
{{#if (eq database "mysql")}}
|
|
23
|
+
DATABASE_HOST=localhost
|
|
24
|
+
DATABASE_PORT=3306
|
|
25
|
+
DATABASE_USER=root
|
|
26
|
+
DATABASE_PASSWORD=root
|
|
27
|
+
DATABASE_NAME={{projectName}}
|
|
28
|
+
{{/if}}
|
|
29
|
+
{{#if (eq database "mongodb")}}
|
|
30
|
+
MONGODB_URI=mongodb://localhost:27017/{{projectName}}
|
|
31
|
+
{{/if}}
|
|
32
|
+
{{/if}}
|
|
33
|
+
|
|
34
|
+
# Application
|
|
35
|
+
NODE_ENV=development
|
|
36
|
+
PORT=3000
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Add this to your main.ts for global JWT authentication
|
|
2
|
+
// Location: src/main.ts
|
|
3
|
+
|
|
4
|
+
import { NestFactory, Reflector } from '@nestjs/core';
|
|
5
|
+
import { AppModule } from './app.module';
|
|
6
|
+
import { JwtAuthGuard } from './auth/guards/jwt-auth.guard';
|
|
7
|
+
import { ValidationPipe } from '@nestjs/common';
|
|
8
|
+
{{#if features.swagger}}
|
|
9
|
+
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
|
|
10
|
+
{{/if}}
|
|
11
|
+
|
|
12
|
+
async function bootstrap() {
|
|
13
|
+
const app = await NestFactory.create(AppModule);
|
|
14
|
+
|
|
15
|
+
// Enable global validation pipe
|
|
16
|
+
app.useGlobalPipes(
|
|
17
|
+
new ValidationPipe({
|
|
18
|
+
whitelist: true,
|
|
19
|
+
forbidNonWhitelisted: true,
|
|
20
|
+
transform: true,
|
|
21
|
+
}),
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
// Enable global JWT guard (all routes protected by default)
|
|
25
|
+
const reflector = app.get(Reflector);
|
|
26
|
+
app.useGlobalGuards(new JwtAuthGuard(reflector));
|
|
27
|
+
|
|
28
|
+
{{#if features.swagger}}
|
|
29
|
+
// Swagger API documentation
|
|
30
|
+
const swaggerConfig = new DocumentBuilder()
|
|
31
|
+
.setTitle('API Documentation')
|
|
32
|
+
.setDescription('JWT Authentication API')
|
|
33
|
+
.setVersion('1.0')
|
|
34
|
+
.addBearerAuth()
|
|
35
|
+
.build();
|
|
36
|
+
const document = SwaggerModule.createDocument(app, swaggerConfig);
|
|
37
|
+
SwaggerModule.setup('api', app, document);
|
|
38
|
+
|
|
39
|
+
{{/if}}
|
|
40
|
+
// Enable CORS if needed
|
|
41
|
+
app.enableCors();
|
|
42
|
+
|
|
43
|
+
await app.listen(3000);
|
|
44
|
+
console.log('🚀 Application is running on: http://localhost:3000');
|
|
45
|
+
{{#if features.swagger}}
|
|
46
|
+
console.log('📚 Swagger docs: http://localhost:3000/api');
|
|
47
|
+
{{/if}}
|
|
48
|
+
}
|
|
49
|
+
bootstrap();
|