create-lyrajs 1.1.2 → 2.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.
Files changed (29) hide show
  1. package/package.json +2 -2
  2. package/template/backups/README.md +93 -0
  3. package/template/config/security.yaml +0 -1
  4. package/template/migrations/README.md +247 -0
  5. package/template/package.json +2 -6
  6. package/template/public/assets/styles/app.css +0 -0
  7. package/template/src/controller/AuthController.ts +100 -71
  8. package/template/src/controller/ErrorController.ts +126 -0
  9. package/template/src/controller/ExampleController.ts +28 -0
  10. package/template/src/controller/ExampleStaticController.ts +40 -0
  11. package/template/src/controller/UserController.ts +63 -44
  12. package/template/src/fixtures/{AppFixtures.ts → UserFixtures.ts} +4 -5
  13. package/template/src/jobs/ExampleJob.ts +63 -0
  14. package/template/src/middleware/YourMiddleware.ts +1 -1
  15. package/template/src/repository/UserRepository.ts +2 -3
  16. package/template/src/router/index.ts +3 -10
  17. package/template/src/router/routes/exampleRoutes.ts +7 -0
  18. package/template/src/router/routes/index.ts +4 -6
  19. package/template/src/server.ts +38 -27
  20. package/template/src/services/YourService.ts +3 -1
  21. package/template/src/templates/ExampleRender.tsx +20 -0
  22. package/template/src/templates/README.md +271 -0
  23. package/template/src/templates/layout/Base.tsx +21 -0
  24. package/template/src/templates/layout/Footer.tsx +7 -0
  25. package/template/src/templates/layout/Header.tsx +19 -0
  26. package/template/tsconfig.json +8 -4
  27. package/template/migrations/migration_1752052338457.sql +0 -4
  28. package/template/src/router/routes/authRoutes.ts +0 -13
  29. package/template/src/router/routes/userRoutes.ts +0 -11
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-lyrajs",
3
- "version": "1.1.2",
3
+ "version": "2.0.0",
4
4
  "description": "CLI tool to create new LyraJS projects",
5
5
  "keywords": [
6
6
  "create",
@@ -12,7 +12,7 @@
12
12
  "cli",
13
13
  "scaffold"
14
14
  ],
15
- "author": "Matthieu Fergola & Anthony Dewitte",
15
+ "author": "Matthieu Fergola",
16
16
  "license": "GPL-3.0",
17
17
  "repository": {
18
18
  "type": "git",
@@ -0,0 +1,93 @@
1
+ # Database Backups
2
+
3
+ This directory stores automatic database backups created by the LyraJS migration system.
4
+
5
+ ## Purpose
6
+
7
+ The `backups/` folder contains SQL dump files that serve as safety checkpoints for your database. These backups are automatically created before destructive migration operations to ensure data can be recovered if needed.
8
+
9
+ ## When Backups Are Created
10
+
11
+ Backups are automatically generated in the following scenarios:
12
+
13
+ - **Before destructive migrations**: When running migrations marked as `isDestructive = true`
14
+ - **Before rollback operations**: When using `maestro migration:rollback`
15
+ - **Before refresh operations**: When using `maestro migration:refresh`
16
+ - **Before fresh migrations**: When using `maestro migration:fresh`
17
+
18
+ ## Backup File Format
19
+
20
+ Backup files follow this naming convention:
21
+
22
+ ```
23
+ backup_YYYY-MM-DD_HH-MM-SS_<version>.sql
24
+ ```
25
+
26
+ Example: `backup_2026-01-05_14-30-45_1767607917120.sql`
27
+
28
+ Where:
29
+ - **Date/Time**: Timestamp of when the backup was created
30
+ - **Version**: Migration version number associated with the backup
31
+
32
+ ## Managing Backups
33
+
34
+ ### List All Backups
35
+
36
+ ```bash
37
+ npx maestro list:backups
38
+ ```
39
+
40
+ ### Restore a Backup
41
+
42
+ ```bash
43
+ npx maestro restore:backup <filename>
44
+ ```
45
+
46
+ Example:
47
+ ```bash
48
+ npx maestro restore:backup backup_2026-01-05_14-30-45_1767607917120.sql
49
+ ```
50
+
51
+ ### Clean Up Old Backups
52
+
53
+ ```bash
54
+ npx maestro cleanup:backups --days=30
55
+ ```
56
+
57
+ This removes backups older than 30 days (default: 7 days).
58
+
59
+ ## Best Practices
60
+
61
+ 1. **Keep backups**: Don't delete backups immediately after migrations succeed
62
+ 2. **Regular cleanup**: Use `cleanup:backups` to manage disk space
63
+ 3. **External backups**: Consider copying important backups to external storage
64
+ 4. **Test restores**: Periodically test backup restoration in development
65
+
66
+ ## Storage Considerations
67
+
68
+ - Backup files can be large depending on database size
69
+ - Regular cleanup is recommended to prevent disk space issues
70
+ - The migration system tracks backup paths in the `migrations` table
71
+
72
+ ## Security
73
+
74
+ - Backup files contain your complete database schema and data
75
+ - Keep this directory secure and excluded from version control
76
+ - The `.gitignore` should include `backups/*.sql`
77
+
78
+ ## Related Commands
79
+
80
+ ```bash
81
+ # View migration status with backup information
82
+ npx maestro migration:status
83
+
84
+ # Run migration with automatic backup
85
+ npx maestro migration:migrate
86
+
87
+ # Rollback with automatic backup
88
+ npx maestro migration:rollback
89
+ ```
90
+
91
+ ---
92
+
93
+ For more information, visit the [LyraJS Documentation](https://lyrajs.dev/).
@@ -14,7 +14,6 @@ security:
14
14
  max_attempts: 5
15
15
  message: 'Too many login attempts, please try again later'
16
16
  access_control:
17
- - { path: /api/auth/sign-out, roles: [ROLE_USER] }
18
17
  - { path: /api/auth/user, roles: [ROLE_USER] }
19
18
  - { path: /api/admin, roles: [ROLE_ADMIN] }
20
19
  role_hierarchy:
@@ -0,0 +1,247 @@
1
+ # Database Migrations
2
+
3
+ This directory contains database migration files that track and version your database schema changes.
4
+
5
+ ## Purpose
6
+
7
+ The `migrations/` folder stores TypeScript migration files that define how your database schema evolves over time. Each migration represents a specific change to your database structure.
8
+
9
+ ## What Are Migrations?
10
+
11
+ Migrations are version control for your database. They allow you to:
12
+
13
+ - **Track schema changes**: Every database modification is recorded
14
+ - **Collaborate safely**: Team members can sync database changes through version control
15
+ - **Rollback changes**: Undo migrations if something goes wrong
16
+ - **Deploy consistently**: Apply the same schema changes across environments
17
+
18
+ ## Migration File Structure
19
+
20
+ Migration files follow this naming convention:
21
+
22
+ ```
23
+ Migration_<timestamp>.ts
24
+ ```
25
+
26
+ Example: `Migration_1767607917120.ts`
27
+
28
+ Each migration file implements the `MigrationInterface` with three methods:
29
+
30
+ ```typescript
31
+ import { MigrationInterface } from "@lyra-js/core"
32
+
33
+ export class Migration_1767607917120 implements MigrationInterface {
34
+ readonly version = "1767607917120"
35
+ readonly isDestructive = false
36
+ readonly canRunInParallel = false
37
+
38
+ async up(connection: any): Promise<void> {
39
+ // SQL to apply the migration
40
+ }
41
+
42
+ async down(connection: any): Promise<void> {
43
+ // SQL to undo the migration
44
+ }
45
+
46
+ async dryRun(connection: any): Promise<string[]> {
47
+ // Return SQL statements for preview
48
+ }
49
+ }
50
+ ```
51
+
52
+ ## Generating Migrations
53
+
54
+ ### Automatic Generation (Recommended)
55
+
56
+ LyraJS automatically detects schema changes by comparing your entities to the database:
57
+
58
+ ```bash
59
+ npx maestro make:migration
60
+ ```
61
+
62
+ This command:
63
+ 1. Introspects your current database schema
64
+ 2. Compares it with your entity definitions
65
+ 3. Generates migration code for detected differences
66
+ 4. Includes smart rename detection to prevent data loss
67
+
68
+ ### Manual Migration
69
+
70
+ For complex operations, you can create migrations manually by copying the file structure above.
71
+
72
+ ## Running Migrations
73
+
74
+ ### Apply Pending Migrations
75
+
76
+ ```bash
77
+ npx maestro migration:migrate
78
+ ```
79
+
80
+ ### View Migration Status
81
+
82
+ ```bash
83
+ npx maestro migration:status
84
+ ```
85
+
86
+ ### Rollback Last Migration
87
+
88
+ ```bash
89
+ npx maestro migration:rollback
90
+ ```
91
+
92
+ ### Rollback Multiple Migrations
93
+
94
+ ```bash
95
+ npx maestro migration:rollback --steps=3
96
+ ```
97
+
98
+ ### Fresh Installation (⚠️ Destructive)
99
+
100
+ Drops all tables and re-runs all migrations:
101
+
102
+ ```bash
103
+ npx maestro migration:fresh
104
+ ```
105
+
106
+ ### Refresh Database (⚠️ Destructive)
107
+
108
+ Rolls back all migrations and re-runs them:
109
+
110
+ ```bash
111
+ npx maestro migration:refresh
112
+ ```
113
+
114
+ ## Migration Squashing
115
+
116
+ For mature projects with many migrations, you can combine them into a single baseline migration:
117
+
118
+ ```bash
119
+ # Squash all executed migrations
120
+ npx maestro migration:squash
121
+
122
+ # Squash up to a specific version
123
+ npx maestro migration:squash --to=1767607917120
124
+ ```
125
+
126
+ Squashed migrations:
127
+ - Reduce migration count for fresh installations
128
+ - Improve migration performance
129
+ - Keep the migrations folder organized
130
+ - Mark old migrations as archived
131
+
132
+ ## Migration Features
133
+
134
+ ### Smart Rename Detection
135
+
136
+ The migration generator can detect when columns or tables are renamed (instead of dropped and recreated):
137
+
138
+ ```
139
+ ? Detected potential rename: firstname -> first_name (85% confidence)
140
+ Do you want to rename instead of drop+create? (Y/n)
141
+ ```
142
+
143
+ ### Automatic Backups
144
+
145
+ Backups are automatically created before destructive operations:
146
+ - The backup is saved to `backups/backup_YYYY-MM-DD_HH-MM-SS_<version>.sql`
147
+ - Tracked in the migrations table for easy restoration
148
+
149
+ ### Migration Batching
150
+
151
+ Migrations are organized in batches, making it easy to rollback related changes together.
152
+
153
+ ### Parallel Execution
154
+
155
+ Some migrations can run in parallel for better performance (set `canRunInParallel = true`).
156
+
157
+ ## Best Practices
158
+
159
+ 1. **Never modify executed migrations**: Create new migrations for changes
160
+ 2. **Test migrations**: Always test in development before production
161
+ 3. **Write reversible migrations**: Ensure `down()` properly undoes `up()`
162
+ 4. **Use transactions**: Migrations run in transactions by default
163
+ 5. **Keep migrations small**: One logical change per migration
164
+ 6. **Review generated SQL**: Check auto-generated migrations before running
165
+ 7. **Version control**: Commit migration files to your repository
166
+
167
+ ## Common Operations
168
+
169
+ ### Adding a Column
170
+
171
+ ```bash
172
+ # 1. Add column to your entity
173
+ # 2. Generate migration
174
+ npx maestro make:migration
175
+
176
+ # 3. Review and run
177
+ npx maestro migration:migrate
178
+ ```
179
+
180
+ ### Creating a Table
181
+
182
+ ```bash
183
+ # 1. Create entity class
184
+ # 2. Generate migration
185
+ npx maestro make:migration
186
+
187
+ # 3. Run migration
188
+ npx maestro migration:migrate
189
+ ```
190
+
191
+ ### Renaming a Column
192
+
193
+ ```bash
194
+ # 1. Rename field in entity
195
+ # 2. Generate migration (will detect rename)
196
+ npx maestro make:migration
197
+
198
+ # 3. Confirm rename when prompted
199
+ # 4. Run migration
200
+ npx maestro migration:migrate
201
+ ```
202
+
203
+ ## Troubleshooting
204
+
205
+ ### Migration Failed
206
+
207
+ If a migration fails:
208
+ 1. Check the error message
209
+ 2. Fix the migration file or database state
210
+ 3. Rollback if needed: `npx maestro migration:rollback`
211
+ 4. Re-run: `npx maestro migration:migrate`
212
+
213
+ ### Out of Sync
214
+
215
+ If your database is out of sync with migrations:
216
+ 1. Use `npx maestro migration:status` to check state
217
+ 2. Manually fix the database or migrations table
218
+ 3. Or use `npx maestro migration:fresh` (⚠️ destroys data)
219
+
220
+ ### Restore from Backup
221
+
222
+ If something goes wrong:
223
+
224
+ ```bash
225
+ npx maestro list:backups
226
+ npx maestro restore:backup <filename>
227
+ ```
228
+
229
+ ## Related Commands
230
+
231
+ ```bash
232
+ # Show all controllers
233
+ npx maestro show:controllers
234
+
235
+ # Show all entities
236
+ npx maestro show:entities
237
+
238
+ # Show all migrations
239
+ npx maestro show:migrations
240
+
241
+ # Show database structure
242
+ npx maestro show:routes
243
+ ```
244
+
245
+ ---
246
+
247
+ For more information, visit the [LyraJS Documentation](https://lyrajs.dev/).
@@ -7,13 +7,11 @@
7
7
  "maestro": "maestro"
8
8
  },
9
9
  "dependencies": {
10
- "@lyra-js/core": "^1.1.2",
10
+ "@lyra-js/core": "^2.0.0",
11
11
  "bcrypt": "^6.0.0",
12
- "cookie-parser": "^1.4.7",
13
12
  "cors": "^2.8.5",
14
13
  "dotenv": "^16.5.0",
15
- "express": "^5.1.0",
16
- "express-rate-limit": "^8.2.1",
14
+ "esbuild": "^0.27.2",
17
15
  "jsonwebtoken": "^9.0.2",
18
16
  "mysql2": "^3.14.1",
19
17
  "nodemailer": "^7.0.7",
@@ -22,9 +20,7 @@
22
20
  },
23
21
  "devDependencies": {
24
22
  "@types/bcrypt": "^5.0.2",
25
- "@types/cookie-parser": "^1.4.8",
26
23
  "@types/cors": "^2.8.18",
27
- "@types/express": "^5.0.1",
28
24
  "@types/jsonwebtoken": "^9.0.9",
29
25
  "@types/node": "^22.15.17",
30
26
  "@types/nodemailer": "^6.4.17",
File without changes
@@ -1,44 +1,51 @@
1
- import { AccessControl, SecurityConfig } from "@lyra-js/core"
2
- import { AuthenticatedRequest, UnauthorizedException, Validator } from "@lyra-js/core"
3
- import bcrypt from "bcrypt"
4
- import { NextFunction, Request, Response } from "express"
5
- import jwt from "jsonwebtoken"
6
- import md5 from "md5"
1
+ import { AccessControl, isAuthenticated, SecurityConfig } from "@lyra-js/core"
2
+ import {
3
+ Controller,
4
+ Delete,
5
+ Get,
6
+ Patch,
7
+ Post,
8
+ rateLimiter,
9
+ Route,
10
+ UnauthorizedException,
11
+ Validator
12
+ } from "@lyra-js/core"
7
13
 
8
14
  import { User } from "@entity/User"
9
- import { userRepository } from "@repository/UserRepository"
10
15
 
11
16
  const securityConfig = new SecurityConfig().getConfig()
12
17
 
13
- export class AuthController {
14
- static signUp = async (req: Request, res: Response, next: NextFunction) => {
18
+ @Route({ path: "/auth" })
19
+ export class AuthController extends Controller {
20
+ @Post({ path: "/sign-up" })
21
+ async signUp() {
15
22
  try {
16
- const { username, firstname, lastname, email, password } = req.body
23
+ const { username, firstname, lastname, email, password } = this.req.body
17
24
 
18
25
  if (!username || !firstname || !lastname || !email || !password) {
19
- throw new Error("Missing required fields")
26
+ this.badRequest("Missing required fields")
20
27
  }
21
28
 
22
29
  if (!Validator.isUsernameValid(username)) {
23
- throw new Error("Invalid username")
30
+ this.badRequest("Invalid username")
24
31
  }
25
32
 
26
33
  if (!Validator.isEmailValid(email)) {
27
- throw new Error("Invalid email")
34
+ this.badRequest("Invalid email")
28
35
  }
29
36
 
30
- const isEmailUsed = await userRepository.findOneBy({ email })
37
+ const isEmailUsed = await this.userRepository.findOneBy({ email })
31
38
 
32
39
  if (isEmailUsed) {
33
- throw new Error("Email already in use")
40
+ this.badRequest("Email already in use")
34
41
  }
35
42
 
36
43
  if (!Validator.isPasswordValid(password)) {
37
- throw new Error("Invalid password")
44
+ this.badRequest("Invalid password")
38
45
  }
39
46
 
40
47
  const user = new User()
41
- const hashedPassword = await bcrypt.hash(password, 10)
48
+ const hashedPassword = await this.bcrypt.hash(password, 10)
42
49
 
43
50
  user.username = username
44
51
  user.firstname = firstname
@@ -47,45 +54,45 @@ export class AuthController {
47
54
  user.password = hashedPassword
48
55
  user.role = "ROLE_USER"
49
56
 
50
- await userRepository.save(user)
57
+ await this.userRepository.save(user)
51
58
 
52
- const registeredUser = await userRepository.findOneBy({ email })
59
+ const registeredUser = await this.userRepository.findOneBy({ email })
60
+ const { password: _, ...userWithoutPassword } = registeredUser || {}
53
61
 
54
- delete registeredUser?.password
55
-
56
- res.status(201).json({ message: "User registered successfully", user: registeredUser })
62
+ this.res.status(201).json({ message: "User registered successfully", user: userWithoutPassword })
57
63
  } catch (error) {
58
- next(error)
64
+ this.next(error)
59
65
  }
60
66
  }
61
67
 
62
- static signIn = async (req: Request, res: Response, next: NextFunction) => {
68
+ @Post({ path: "/sign-in", middlewares: [rateLimiter] })
69
+ async signIn() {
63
70
  try {
64
- const { email, password } = req.body
71
+ const { email, password } = this.req.body
65
72
 
66
73
  if (!email || !password) {
67
- throw new Error("Missing required fields")
74
+ this.badRequest("Missing required fields")
68
75
  }
69
76
 
70
- const user = await userRepository.findOneBy({ email })
77
+ const user = await this.userRepository.findOneBy({ email })
71
78
 
72
- if (!user || !(user && (await bcrypt.compare(password, user.password)))) {
73
- throw new Error("Invalid credentials")
79
+ if (!user || !(user && (await this.bcrypt.compare(password, user.password)))) {
80
+ this.unauthorized("Invalid credentials")
74
81
  }
75
82
 
76
- const token = jwt.sign({ id: user.id }, securityConfig.jwt.secret_key as string, {
83
+ const token = this.jwt.sign({ id: user.id }, securityConfig.jwt.secret_key as string, {
77
84
  algorithm: securityConfig.jwt.algorithm as string,
78
85
  expiresIn: securityConfig.jwt.token_expiration
79
86
  })
80
87
 
81
- const refreshToken = jwt.sign({ id: user.id }, securityConfig.jwt.secret_key_refresh as string, {
88
+ const refreshToken = this.jwt.sign({ id: user.id }, securityConfig.jwt.secret_key_refresh as string, {
82
89
  algorithm: securityConfig.jwt.algorithm as string,
83
90
  expiresIn: securityConfig.jwt.refresh_token_expiration
84
91
  })
85
92
 
86
- await userRepository.save(user)
93
+ await this.userRepository.save(user)
87
94
 
88
- res.cookie("Token", token, {
95
+ this.res.cookie("Token", token, {
89
96
  sameSite: "Lax",
90
97
  httpOnly: true,
91
98
  secure: process.env.ENV === "production",
@@ -93,7 +100,7 @@ export class AuthController {
93
100
  partitioned: false
94
101
  })
95
102
 
96
- res.cookie("RefreshToken", refreshToken, {
103
+ this.res.cookie("RefreshToken", refreshToken, {
97
104
  sameSite: "Lax",
98
105
  httpOnly: true,
99
106
  secure: process.env.ENV === "production",
@@ -101,21 +108,24 @@ export class AuthController {
101
108
  partitioned: false
102
109
  })
103
110
 
104
- delete user.password
111
+ const { password: _, ...userWithoutPassword } = user
105
112
 
106
- res.status(200).json({ message: "User authenticated in successfully", user, token, refreshToken })
113
+ this.res
114
+ .status(200)
115
+ .json({ message: "User authenticated in successfully", user: userWithoutPassword, token, refreshToken })
107
116
  } catch (error) {
108
- next(error)
117
+ this.next(error)
109
118
  }
110
119
  }
111
120
 
112
- static getAuthenticatedUser = async (req: AuthenticatedRequest<Request>, res: Response, next: NextFunction) => {
121
+ @Get({ path: "/user", middlewares: [isAuthenticated] })
122
+ async getAuthenticatedUser() {
113
123
  try {
114
- const user = req.user as User
124
+ const user = this.req.user as User
115
125
 
116
126
  if (!user) throw new UnauthorizedException()
117
127
 
118
- res.status(200).json({
128
+ this.res.status(200).json({
119
129
  id: user.id,
120
130
  firstname: user.firstname,
121
131
  lastname: user.lastname,
@@ -123,40 +133,56 @@ export class AuthController {
123
133
  role: user.role
124
134
  })
125
135
  } catch (error) {
126
- next(error)
136
+ this.next(error)
127
137
  }
128
138
  }
129
139
 
130
- static signOut = async (_req: Request, res: Response) => {
131
- res.clearCookie("Token")
132
- res.clearCookie("RefreshToken")
133
- res.status(200).json({ message: "Unauthenticated successfully" })
140
+ @Get({ path: "/sign-out" })
141
+ async signOut() {
142
+ try {
143
+ this.res.clearCookie("Token")
144
+ this.res.clearCookie("RefreshToken")
145
+ return this.res.status(200).json({ message: "Unauthenticated successfully" })
146
+ } catch (error) {
147
+ this.next(error)
148
+ }
134
149
  }
135
150
 
136
- static updateProfile = async (req: AuthenticatedRequest<Request>, res: Response, next: NextFunction) => {
151
+ @Patch({ path: "/update-account", middlewares: [isAuthenticated] })
152
+ async updateProfile() {
137
153
  try {
138
- const { data }: { data: User } = req.body
139
- const user = req.user as User
154
+ const { data }: { data: User } = this.req.body
155
+ const user = this.req.user as User
140
156
  if (!user) throw new UnauthorizedException()
141
157
  if (data?.id && data.id !== user.id) throw new UnauthorizedException()
142
- if (data.role) delete data.role
143
- if (data.created_at) delete data.created_at
144
- data.updated_at = new Date()
145
- if (user && data.password) data.password = await bcrypt.hash(data.password, 10)
146
- if (user) await userRepository.save(data)
147
- res.status(200).json({ message: "Users updated successfully" })
158
+
159
+ // Remove protected fields
160
+ const { role: _role, created_at: _created_at, password, ...updateData } = data
161
+
162
+ // Hash password if provided
163
+ const hashedPassword = password ? await this.bcrypt.hash(password, 10) : undefined
164
+
165
+ const finalData = {
166
+ ...updateData,
167
+ ...(hashedPassword && { password: hashedPassword }),
168
+ updated_at: new Date()
169
+ }
170
+
171
+ if (user) await this.userRepository.save(finalData)
172
+ this.res.status(200).json({ message: "Users updated successfully" })
148
173
  } catch (error) {
149
- next(error)
174
+ this.next(error)
150
175
  }
151
176
  }
152
177
 
153
- static refreshToken = async (req: Request, res: Response, next: NextFunction) => {
178
+ @Get({ path: "/refresh-token" })
179
+ async refreshToken() {
154
180
  try {
155
181
  const securityConfig = new SecurityConfig().getConfig()
156
- let refreshToken = req.cookies.RefreshToken
182
+ let refreshToken = this.req.cookies.RefreshToken
157
183
  if (!refreshToken) {
158
- const authHeader = req.headers.authorization
159
- if (authHeader && authHeader.startsWith('Bearer ')) {
184
+ const authHeader = this.req.headers.authorization
185
+ if (authHeader && authHeader.startsWith("Bearer ")) {
160
186
  refreshToken = authHeader.substring(7)
161
187
  }
162
188
  }
@@ -167,38 +193,41 @@ export class AuthController {
167
193
 
168
194
  if (!decoded || !decoded.id) throw new UnauthorizedException("Invalid refresh token")
169
195
 
170
- const user = await userRepository.find(decoded.id)
196
+ const user = await this.userRepository.find(decoded.id)
171
197
 
172
198
  if (!user) throw new UnauthorizedException("Invalid refresh token")
173
199
 
174
200
  const token = await AccessControl.getNewToken(user)
175
201
 
176
- res.cookie("Token", token, {
177
- sameSite: "lax",
202
+ this.res.cookie("Token", token, {
203
+ sameSite: "Lax",
178
204
  httpOnly: true,
179
205
  secure: process.env.ENV === "production",
180
206
  maxAge: securityConfig.jwt.token_expiration * 1000,
181
207
  partitioned: false
182
208
  })
183
209
 
184
- delete user.password
210
+ const { password: _, ...userWithoutPassword } = user
185
211
 
186
- res.status(200).json({ message: "User authenticated in successfully", user, token, refreshToken })
212
+ this.res
213
+ .status(200)
214
+ .json({ message: "User authenticated in successfully", user: userWithoutPassword, token, refreshToken })
187
215
  } catch (_refreshError) {
188
- return res.redirect(securityConfig.auth_routes.sign_out)
216
+ return this.res.redirect(securityConfig.auth_routes.sign_out)
189
217
  }
190
218
  }
191
219
 
192
- static removeUser = async (req: AuthenticatedRequest<Request>, res: Response, next: NextFunction) => {
193
- const user = req.user
220
+ @Delete({ path: "/delete-account", middlewares: [isAuthenticated] })
221
+ async removeUser() {
222
+ const user = this.req.user
194
223
 
195
224
  if (!user) throw new UnauthorizedException()
196
225
 
197
- await userRepository.delete(user.id)
226
+ await this.userRepository.delete(user.id)
198
227
 
199
- res.clearCookie("Token")
200
- res.clearCookie("RefreshToken")
228
+ this.res.clearCookie("Token")
229
+ this.res.clearCookie("RefreshToken")
201
230
 
202
- res.status(200).json({ message: "User deleted successfully" })
231
+ this.res.status(200).json({ message: "User deleted successfully" })
203
232
  }
204
233
  }