create-lyrajs 1.0.16 → 1.0.17

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-lyrajs",
3
- "version": "1.0.16",
3
+ "version": "1.0.17",
4
4
  "description": "CLI tool to create new LyraJS projects",
5
5
  "keywords": [
6
6
  "create",
@@ -7,7 +7,7 @@
7
7
  "maestro": "maestro"
8
8
  },
9
9
  "dependencies": {
10
- "@lyra-js/core": "^1.0.14",
10
+ "@lyra-js/core": "^1.0.15",
11
11
  "bcrypt": "^6.0.0",
12
12
  "cookie-parser": "^1.4.7",
13
13
  "cors": "^2.8.5",
@@ -15,6 +15,7 @@
15
15
  "express": "^5.1.0",
16
16
  "express-rate-limit": "^8.2.1",
17
17
  "jsonwebtoken": "^9.0.2",
18
+ "md5": "^2.3.0",
18
19
  "mysql2": "^3.14.1",
19
20
  "nodemailer": "^7.0.7",
20
21
  "reflect-metadata": "^0.2.2",
@@ -1,9 +1,10 @@
1
+ import { AccessControl, ProtectedRouteType, SecurityConfig } from "@lyra-js/core"
2
+ import { AuthenticatedRequest, UnauthorizedException, Validator } from "@lyra-js/core"
1
3
  import bcrypt from "bcrypt"
2
4
  import { NextFunction, Request, Response } from "express"
3
5
  import jwt from "jsonwebtoken"
6
+ import md5 from "md5"
4
7
 
5
- import { SecurityConfig } from "@lyra-js/core"
6
- import { AuthenticatedRequest, UnauthorizedException, Validator } from "@lyra-js/core"
7
8
  import { User } from "@entity/User"
8
9
  import { userRepository } from "@repository/UserRepository"
9
10
 
@@ -44,7 +45,7 @@ export class AuthController {
44
45
  user.lastname = lastname
45
46
  user.email = email
46
47
  user.password = hashedPassword
47
- user.role = 'ROLE_USER'
48
+ user.role = "ROLE_USER"
48
49
 
49
50
  await userRepository.save(user)
50
51
 
@@ -77,11 +78,13 @@ export class AuthController {
77
78
  expiresIn: securityConfig.jwt.token_expiration
78
79
  })
79
80
 
80
- user.refresh_token = jwt.sign({ id: user.id }, securityConfig.jwt.secret_key_refresh as string, {
81
+ const refreshToken = jwt.sign({ id: user.id }, securityConfig.jwt.secret_key_refresh as string, {
81
82
  algorithm: securityConfig.jwt.algorithm as string,
82
83
  expiresIn: securityConfig.jwt.refresh_token_expiration
83
84
  })
84
85
 
86
+ user.refresh_token = md5(refreshToken)
87
+
85
88
  await userRepository.save(user)
86
89
 
87
90
  res.cookie("Token", token, {
@@ -92,9 +95,18 @@ export class AuthController {
92
95
  partitioned: false
93
96
  })
94
97
 
98
+ res.cookie("RefreshToken", refreshToken, {
99
+ sameSite: "Lax",
100
+ httpOnly: true,
101
+ secure: process.env.ENV === "production",
102
+ maxAge: 1000 * 60 * 60 * 24,
103
+ partitioned: false
104
+ })
105
+
95
106
  delete user.password
107
+ delete user.refresh_token
96
108
 
97
- res.status(200).json({ message: "User authenticated in successfully", user, token })
109
+ res.status(200).json({ message: "User authenticated in successfully", user, token, refreshToken })
98
110
  } catch (error) {
99
111
  next(error)
100
112
  }
@@ -119,6 +131,72 @@ export class AuthController {
119
131
 
120
132
  static signOut = async (_req: Request, res: Response) => {
121
133
  res.clearCookie("Token")
134
+ res.clearCookie("RefreshToken")
122
135
  res.status(200).json({ message: "Unauthenticated successfully" })
123
136
  }
137
+
138
+ static updateProfile = async (req: AuthenticatedRequest<Request>, res: Response, next: NextFunction) => {
139
+ try {
140
+ const { data }: { data: User } = req.body
141
+ const user = req.user as User
142
+ if (!user) throw new UnauthorizedException()
143
+ if (data?.id && data.id !== user.id) throw new UnauthorizedException()
144
+ if (data.role) delete data.role
145
+ if (data.created_at) delete data.created_at
146
+ if (data.refresh_token) delete data.refresh_token
147
+ data.updated_at = new Date()
148
+ if (user && data.password) data.password = await bcrypt.hash(data.password, 10)
149
+ if (user) await userRepository.save(data)
150
+ res.status(200).json({ message: "Users updated successfully" })
151
+ } catch (error) {
152
+ next(error)
153
+ }
154
+ }
155
+
156
+ static refreshToken = async (req: Request, res: Response, next: NextFunction) => {
157
+ try {
158
+ const securityConfig = new SecurityConfig().getConfig()
159
+ const refreshToken = req.cookies.RefreshToken
160
+ const decoded = await AccessControl.decodeToken(refreshToken)
161
+
162
+ if (!decoded || !decoded.id) throw new UnauthorizedException("Invalid refresh token")
163
+
164
+ const user = await userRepository.find(decoded.id)
165
+
166
+ if (!user || md5(refreshToken) !== user.refresh_token) throw new UnauthorizedException("Invalid refresh token")
167
+
168
+ AccessControl.checkRefreshTokenValid(refreshToken)
169
+
170
+ const newToken = await AccessControl.getNewToken(user)
171
+
172
+ await userRepository.save({ ...user })
173
+
174
+ res.cookie("Token", newToken, {
175
+ sameSite: "lax",
176
+ httpOnly: true,
177
+ secure: process.env.ENV === "production",
178
+ maxAge: securityConfig.jwt.token_expiration
179
+ })
180
+
181
+ delete user.password
182
+ delete user.refresh_token
183
+
184
+ res.status(200).json({ message: "User authenticated in successfully", user, refreshToken })
185
+ } catch (_refreshError) {
186
+ return res.redirect(securityConfig.auth_routes.sign_out)
187
+ }
188
+ }
189
+
190
+ static removeUser = async (req: AuthenticatedRequest<Request>, res: Response, next: NextFunction) => {
191
+ const user = req.user
192
+
193
+ if (!user) throw new UnauthorizedException()
194
+
195
+ await userRepository.delete(user.id)
196
+
197
+ res.clearCookie("Token")
198
+ res.clearCookie("RefreshToken")
199
+
200
+ res.status(200).json({ message: "User deleted successfully" })
201
+ }
124
202
  }
@@ -89,6 +89,7 @@ export class UserController {
89
89
  const user = await userRepository.find(data.id)
90
90
  if (!user) res.status(404).json({ message: "User not found" })
91
91
  if (user && data.password) data.password = await bcrypt.hash(data.password, 10);
92
+ user.updated_at = new Date()
92
93
  if (user) await userRepository.save(data)
93
94
  res.status(200).json({ message: "Users updated successfully" })
94
95
  } catch (error) {
@@ -8,3 +8,6 @@ authRoutes.post("/sign-up", AuthController.signUp)
8
8
  authRoutes.post("/sign-in", rateLimiter, AuthController.signIn)
9
9
  authRoutes.get("/user", AuthController.getAuthenticatedUser)
10
10
  authRoutes.get("/sign-out", AuthController.signOut)
11
+ authRoutes.get("/refresh-token", AuthController.refreshToken)
12
+ authRoutes.post("/update-account", AuthController.updateProfile)
13
+ authRoutes.delete("/delete-account", AuthController.removeUser)
@@ -1,10 +1,11 @@
1
1
  import { UserController } from "@controller/UserController"
2
2
  import { Router } from "express"
3
+ import { isAdmin } from "@lyrajs/core"
3
4
 
4
5
  export const userRoutes = Router()
5
6
 
6
- userRoutes.get("/all", UserController.list)
7
- userRoutes.get("/:id", UserController.read)
8
- userRoutes.post("/", UserController.create)
9
- userRoutes.patch("/:id", UserController.update)
10
- userRoutes.delete("/:id", UserController.delete)
7
+ userRoutes.get("/all", isAdmin, UserController.list)
8
+ userRoutes.get("/:id", isAdmin, UserController.read)
9
+ userRoutes.post("/", isAdmin, UserController.create)
10
+ userRoutes.patch("/:id", isAdmin, UserController.update)
11
+ userRoutes.delete("/:id", isAdmin, UserController.delete)
@@ -22,7 +22,6 @@ app.use(express.urlencoded({ limit: securityConfig.limits.request_max_size || "1
22
22
  app.use(
23
23
  cors({
24
24
  origin: `${process.env.CLIENT_APP_URL}`,
25
- methods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"],
26
25
  credentials: true
27
26
  })
28
27
  )