@flowerforce/flowerbase 1.7.6-beta.8 → 1.7.6-beta.9
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/auth/providers/local-userpass/controller.d.ts.map +1 -1
- package/dist/auth/providers/local-userpass/controller.js +30 -12
- package/dist/auth/providers/local-userpass/dtos.d.ts +5 -1
- package/dist/auth/providers/local-userpass/dtos.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/auth/providers/local-userpass/controller.ts +49 -31
- package/src/auth/providers/local-userpass/dtos.ts +6 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../../src/auth/providers/local-userpass/controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../../src/auth/providers/local-userpass/controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AA4CzC;;;;GAIG;AACH,wBAAsB,uBAAuB,CAAC,GAAG,EAAE,eAAe,iBAmajE"}
|
|
@@ -49,14 +49,22 @@ function localUserPassController(app) {
|
|
|
49
49
|
const resetMaxAttempts = constants_1.DEFAULT_CONFIG.AUTH_RESET_MAX_ATTEMPTS;
|
|
50
50
|
const refreshTokenTtlMs = constants_1.DEFAULT_CONFIG.REFRESH_TOKEN_TTL_DAYS * 24 * 60 * 60 * 1000;
|
|
51
51
|
const resolveLocalUserpassProvider = () => { var _a; return (_a = constants_1.AUTH_CONFIG.authProviders) === null || _a === void 0 ? void 0 : _a['local-userpass']; };
|
|
52
|
+
const invalidPasswordError = {
|
|
53
|
+
error: 'unauthorized',
|
|
54
|
+
error_code: 'InvalidPassword'
|
|
55
|
+
};
|
|
52
56
|
try {
|
|
53
|
-
yield authDb
|
|
57
|
+
yield authDb
|
|
58
|
+
.collection(resetPasswordCollection)
|
|
59
|
+
.createIndex({ createdAt: 1 }, { expireAfterSeconds: resetPasswordTtlSeconds });
|
|
54
60
|
}
|
|
55
61
|
catch (error) {
|
|
56
62
|
console.error('Failed to ensure reset password TTL index', error);
|
|
57
63
|
}
|
|
58
64
|
try {
|
|
59
|
-
yield authDb
|
|
65
|
+
yield authDb
|
|
66
|
+
.collection(refreshTokensCollection)
|
|
67
|
+
.createIndex({ expiresAt: 1 }, { expireAfterSeconds: 0 });
|
|
60
68
|
}
|
|
61
69
|
catch (error) {
|
|
62
70
|
console.error('Failed to ensure refresh token TTL index', error);
|
|
@@ -80,8 +88,10 @@ function localUserPassController(app) {
|
|
|
80
88
|
const services = state_1.StateManager.select('services');
|
|
81
89
|
const currentFunction = functionsList[resetPasswordConfig.resetFunctionName];
|
|
82
90
|
const baseArgs = { token, tokenId, email, password, username: email };
|
|
83
|
-
const args = Array.isArray(extraArguments)
|
|
84
|
-
|
|
91
|
+
const args = Array.isArray(extraArguments)
|
|
92
|
+
? [baseArgs, ...extraArguments]
|
|
93
|
+
: [baseArgs];
|
|
94
|
+
const response = (yield (0, context_1.GenerateContext)({
|
|
85
95
|
args,
|
|
86
96
|
app,
|
|
87
97
|
rules: {},
|
|
@@ -91,7 +101,7 @@ function localUserPassController(app) {
|
|
|
91
101
|
functionsList,
|
|
92
102
|
services,
|
|
93
103
|
runAsSystem: true
|
|
94
|
-
});
|
|
104
|
+
}));
|
|
95
105
|
const resetStatus = response === null || response === void 0 ? void 0 : response.status;
|
|
96
106
|
if (resetStatus === 'success') {
|
|
97
107
|
if (!password) {
|
|
@@ -138,13 +148,17 @@ function localUserPassController(app) {
|
|
|
138
148
|
}
|
|
139
149
|
let result;
|
|
140
150
|
try {
|
|
141
|
-
result = yield (0, handleUserRegistration_1.default)(app, {
|
|
151
|
+
result = yield (0, handleUserRegistration_1.default)(app, {
|
|
152
|
+
run_as_system: true,
|
|
153
|
+
provider: handleUserRegistration_model_1.PROVIDER.LOCAL_USERPASS
|
|
154
|
+
})({
|
|
142
155
|
email: req.body.email.toLowerCase(),
|
|
143
156
|
password: req.body.password
|
|
144
157
|
});
|
|
145
158
|
}
|
|
146
159
|
catch (error) {
|
|
147
|
-
if (error instanceof Error &&
|
|
160
|
+
if (error instanceof Error &&
|
|
161
|
+
error.message === 'This email address is already used') {
|
|
148
162
|
res.status(409).send({
|
|
149
163
|
error: 'name already in use',
|
|
150
164
|
error_code: 'AccountNameInUse'
|
|
@@ -179,10 +193,10 @@ function localUserPassController(app) {
|
|
|
179
193
|
res.status(429).send({ message: 'Too many requests' });
|
|
180
194
|
return;
|
|
181
195
|
}
|
|
182
|
-
const existing = yield authDb.collection(authCollection).findOne({
|
|
196
|
+
const existing = (yield authDb.collection(authCollection).findOne({
|
|
183
197
|
confirmationToken: req.body.token,
|
|
184
198
|
confirmationTokenId: req.body.tokenId
|
|
185
|
-
});
|
|
199
|
+
}));
|
|
186
200
|
if (!existing) {
|
|
187
201
|
res.status(500);
|
|
188
202
|
throw new Error(utils_1.AUTH_ERRORS.INVALID_TOKEN);
|
|
@@ -220,11 +234,13 @@ function localUserPassController(app) {
|
|
|
220
234
|
email: req.body.username
|
|
221
235
|
});
|
|
222
236
|
if (!authUser) {
|
|
223
|
-
|
|
237
|
+
res.status(401);
|
|
238
|
+
return invalidPasswordError;
|
|
224
239
|
}
|
|
225
240
|
const passwordMatches = yield (0, crypto_1.comparePassword)(req.body.password, authUser.password);
|
|
226
241
|
if (!passwordMatches) {
|
|
227
|
-
|
|
242
|
+
res.status(401);
|
|
243
|
+
return invalidPasswordError;
|
|
228
244
|
}
|
|
229
245
|
const user = user_id_field && userCollection
|
|
230
246
|
? yield customUserDb
|
|
@@ -246,7 +262,9 @@ function localUserPassController(app) {
|
|
|
246
262
|
expiresAt: new Date(Date.now() + refreshTokenTtlMs),
|
|
247
263
|
revokedAt: null
|
|
248
264
|
});
|
|
249
|
-
yield authDb
|
|
265
|
+
yield authDb
|
|
266
|
+
.collection(authCollection)
|
|
267
|
+
.updateOne({ _id: authUser._id }, { $set: { lastLoginAt: now } });
|
|
250
268
|
return {
|
|
251
269
|
access_token: this.createAccessToken(userWithCustomData),
|
|
252
270
|
refresh_token: refreshToken,
|
|
@@ -15,12 +15,16 @@ export type LoginSuccessDto = {
|
|
|
15
15
|
export type ErrorResponseDto = {
|
|
16
16
|
message: string;
|
|
17
17
|
};
|
|
18
|
+
export type InvalidPasswordResponseDto = {
|
|
19
|
+
error: 'unauthorized';
|
|
20
|
+
error_code: 'InvalidPassword';
|
|
21
|
+
};
|
|
18
22
|
export interface RegistrationDto {
|
|
19
23
|
Body: RegisterUserDto;
|
|
20
24
|
}
|
|
21
25
|
export interface LoginDto {
|
|
22
26
|
Body: LoginUserDto;
|
|
23
|
-
Reply: LoginSuccessDto | ErrorResponseDto;
|
|
27
|
+
Reply: LoginSuccessDto | ErrorResponseDto | InvalidPasswordResponseDto;
|
|
24
28
|
}
|
|
25
29
|
export interface ResetPasswordSendDto {
|
|
26
30
|
Body: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dtos.d.ts","sourceRoot":"","sources":["../../../../src/auth/providers/local-userpass/dtos.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,eAAe,CAAA;CACtB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,YAAY,CAAA;IAClB,KAAK,EAAE,eAAe,GAAG,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"dtos.d.ts","sourceRoot":"","sources":["../../../../src/auth/providers/local-userpass/dtos.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,0BAA0B,GAAG;IACvC,KAAK,EAAE,cAAc,CAAA;IACrB,UAAU,EAAE,iBAAiB,CAAA;CAC9B,CAAA;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,eAAe,CAAA;CACtB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,YAAY,CAAA;IAClB,KAAK,EAAE,eAAe,GAAG,gBAAgB,GAAG,0BAA0B,CAAA;CACvE;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAA;KACd,CAAA;CACF;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAA;QACb,QAAQ,EAAE,MAAM,CAAA;QAChB,SAAS,CAAC,EAAE,OAAO,EAAE,CAAA;KACtB,CAAA;CACF;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAA;QACb,OAAO,EAAE,MAAM,CAAA;QACf,QAAQ,EAAE,MAAM,CAAA;KACjB,CAAA;CACF;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAA;QACb,OAAO,EAAE,MAAM,CAAA;KAChB,CAAA;CACF"}
|
package/package.json
CHANGED
|
@@ -5,7 +5,12 @@ import handleUserRegistration from '../../../shared/handleUserRegistration'
|
|
|
5
5
|
import { PROVIDER } from '../../../shared/models/handleUserRegistration.model'
|
|
6
6
|
import { StateManager } from '../../../state'
|
|
7
7
|
import { GenerateContext } from '../../../utils/context'
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
comparePassword,
|
|
10
|
+
generateToken,
|
|
11
|
+
hashPassword,
|
|
12
|
+
hashToken
|
|
13
|
+
} from '../../../utils/crypto'
|
|
9
14
|
import {
|
|
10
15
|
AUTH_ENDPOINTS,
|
|
11
16
|
AUTH_ERRORS,
|
|
@@ -55,21 +60,23 @@ export async function localUserPassController(app: FastifyInstance) {
|
|
|
55
60
|
const resetMaxAttempts = DEFAULT_CONFIG.AUTH_RESET_MAX_ATTEMPTS
|
|
56
61
|
const refreshTokenTtlMs = DEFAULT_CONFIG.REFRESH_TOKEN_TTL_DAYS * 24 * 60 * 60 * 1000
|
|
57
62
|
const resolveLocalUserpassProvider = () => AUTH_CONFIG.authProviders?.['local-userpass']
|
|
63
|
+
const invalidPasswordError = {
|
|
64
|
+
error: 'unauthorized',
|
|
65
|
+
error_code: 'InvalidPassword'
|
|
66
|
+
} as const
|
|
58
67
|
|
|
59
68
|
try {
|
|
60
|
-
await authDb
|
|
61
|
-
|
|
62
|
-
{ expireAfterSeconds: resetPasswordTtlSeconds }
|
|
63
|
-
)
|
|
69
|
+
await authDb
|
|
70
|
+
.collection(resetPasswordCollection)
|
|
71
|
+
.createIndex({ createdAt: 1 }, { expireAfterSeconds: resetPasswordTtlSeconds })
|
|
64
72
|
} catch (error) {
|
|
65
73
|
console.error('Failed to ensure reset password TTL index', error)
|
|
66
74
|
}
|
|
67
75
|
|
|
68
76
|
try {
|
|
69
|
-
await authDb
|
|
70
|
-
|
|
71
|
-
{ expireAfterSeconds: 0 }
|
|
72
|
-
)
|
|
77
|
+
await authDb
|
|
78
|
+
.collection(refreshTokensCollection)
|
|
79
|
+
.createIndex({ expiresAt: 1 }, { expireAfterSeconds: 0 })
|
|
73
80
|
} catch (error) {
|
|
74
81
|
console.error('Failed to ensure refresh token TTL index', error)
|
|
75
82
|
}
|
|
@@ -107,8 +114,10 @@ export async function localUserPassController(app: FastifyInstance) {
|
|
|
107
114
|
const services = StateManager.select('services')
|
|
108
115
|
const currentFunction = functionsList[resetPasswordConfig.resetFunctionName]
|
|
109
116
|
const baseArgs = { token, tokenId, email, password, username: email }
|
|
110
|
-
const args = Array.isArray(extraArguments)
|
|
111
|
-
|
|
117
|
+
const args = Array.isArray(extraArguments)
|
|
118
|
+
? [baseArgs, ...extraArguments]
|
|
119
|
+
: [baseArgs]
|
|
120
|
+
const response = (await GenerateContext({
|
|
112
121
|
args,
|
|
113
122
|
app,
|
|
114
123
|
rules: {},
|
|
@@ -118,7 +127,7 @@ export async function localUserPassController(app: FastifyInstance) {
|
|
|
118
127
|
functionsList,
|
|
119
128
|
services,
|
|
120
129
|
runAsSystem: true
|
|
121
|
-
}) as ResetFunctionResult
|
|
130
|
+
})) as ResetFunctionResult
|
|
122
131
|
const resetStatus = response?.status
|
|
123
132
|
|
|
124
133
|
if (resetStatus === 'success') {
|
|
@@ -179,12 +188,18 @@ export async function localUserPassController(app: FastifyInstance) {
|
|
|
179
188
|
|
|
180
189
|
let result
|
|
181
190
|
try {
|
|
182
|
-
result = await handleUserRegistration(app, {
|
|
191
|
+
result = await handleUserRegistration(app, {
|
|
192
|
+
run_as_system: true,
|
|
193
|
+
provider: PROVIDER.LOCAL_USERPASS
|
|
194
|
+
})({
|
|
183
195
|
email: req.body.email.toLowerCase(),
|
|
184
196
|
password: req.body.password
|
|
185
197
|
})
|
|
186
198
|
} catch (error) {
|
|
187
|
-
if (
|
|
199
|
+
if (
|
|
200
|
+
error instanceof Error &&
|
|
201
|
+
error.message === 'This email address is already used'
|
|
202
|
+
) {
|
|
188
203
|
res.status(409).send({
|
|
189
204
|
error: 'name already in use',
|
|
190
205
|
error_code: 'AccountNameInUse'
|
|
@@ -227,10 +242,10 @@ export async function localUserPassController(app: FastifyInstance) {
|
|
|
227
242
|
return
|
|
228
243
|
}
|
|
229
244
|
|
|
230
|
-
const existing = await authDb.collection(authCollection!).findOne({
|
|
245
|
+
const existing = (await authDb.collection(authCollection!).findOne({
|
|
231
246
|
confirmationToken: req.body.token,
|
|
232
247
|
confirmationTokenId: req.body.tokenId
|
|
233
|
-
}) as { _id: ObjectId; status?: string } | null
|
|
248
|
+
})) as { _id: ObjectId; status?: string } | null
|
|
234
249
|
|
|
235
250
|
if (!existing) {
|
|
236
251
|
res.status(500)
|
|
@@ -279,23 +294,22 @@ export async function localUserPassController(app: FastifyInstance) {
|
|
|
279
294
|
})
|
|
280
295
|
|
|
281
296
|
if (!authUser) {
|
|
282
|
-
|
|
297
|
+
res.status(401)
|
|
298
|
+
return invalidPasswordError
|
|
283
299
|
}
|
|
284
300
|
|
|
285
|
-
const passwordMatches = await comparePassword(
|
|
286
|
-
req.body.password,
|
|
287
|
-
authUser.password
|
|
288
|
-
)
|
|
301
|
+
const passwordMatches = await comparePassword(req.body.password, authUser.password)
|
|
289
302
|
|
|
290
303
|
if (!passwordMatches) {
|
|
291
|
-
|
|
304
|
+
res.status(401)
|
|
305
|
+
return invalidPasswordError
|
|
292
306
|
}
|
|
293
307
|
|
|
294
308
|
const user =
|
|
295
309
|
user_id_field && userCollection
|
|
296
310
|
? await customUserDb
|
|
297
|
-
|
|
298
|
-
|
|
311
|
+
.collection(userCollection)
|
|
312
|
+
.findOne({ [user_id_field]: authUser._id.toString() })
|
|
299
313
|
: {}
|
|
300
314
|
delete authUser?.password
|
|
301
315
|
|
|
@@ -325,10 +339,9 @@ export async function localUserPassController(app: FastifyInstance) {
|
|
|
325
339
|
expiresAt: new Date(Date.now() + refreshTokenTtlMs),
|
|
326
340
|
revokedAt: null
|
|
327
341
|
})
|
|
328
|
-
await authDb
|
|
329
|
-
|
|
330
|
-
{ $set: { lastLoginAt: now } }
|
|
331
|
-
)
|
|
342
|
+
await authDb
|
|
343
|
+
.collection(authCollection!)
|
|
344
|
+
.updateOne({ _id: authUser._id }, { $set: { lastLoginAt: now } })
|
|
332
345
|
|
|
333
346
|
return {
|
|
334
347
|
access_token: this.createAccessToken(userWithCustomData),
|
|
@@ -427,12 +440,15 @@ export async function localUserPassController(app: FastifyInstance) {
|
|
|
427
440
|
}
|
|
428
441
|
|
|
429
442
|
const createdAt = resetRequest.createdAt ? new Date(resetRequest.createdAt) : null
|
|
430
|
-
const isExpired =
|
|
443
|
+
const isExpired =
|
|
444
|
+
!createdAt ||
|
|
431
445
|
Number.isNaN(createdAt.getTime()) ||
|
|
432
446
|
Date.now() - createdAt.getTime() > resetPasswordTtlSeconds * 1000
|
|
433
447
|
|
|
434
448
|
if (isExpired) {
|
|
435
|
-
await authDb
|
|
449
|
+
await authDb
|
|
450
|
+
?.collection(resetPasswordCollection)
|
|
451
|
+
.deleteOne({ _id: resetRequest._id })
|
|
436
452
|
throw new Error(AUTH_ERRORS.INVALID_RESET_PARAMS)
|
|
437
453
|
}
|
|
438
454
|
const hashedPassword = await hashPassword(password)
|
|
@@ -445,7 +461,9 @@ export async function localUserPassController(app: FastifyInstance) {
|
|
|
445
461
|
}
|
|
446
462
|
)
|
|
447
463
|
|
|
448
|
-
await authDb
|
|
464
|
+
await authDb
|
|
465
|
+
?.collection(resetPasswordCollection)
|
|
466
|
+
.deleteOne({ _id: resetRequest._id })
|
|
449
467
|
}
|
|
450
468
|
)
|
|
451
469
|
}
|
|
@@ -19,13 +19,18 @@ export type ErrorResponseDto = {
|
|
|
19
19
|
message: string
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
export type InvalidPasswordResponseDto = {
|
|
23
|
+
error: 'unauthorized'
|
|
24
|
+
error_code: 'InvalidPassword'
|
|
25
|
+
}
|
|
26
|
+
|
|
22
27
|
export interface RegistrationDto {
|
|
23
28
|
Body: RegisterUserDto
|
|
24
29
|
}
|
|
25
30
|
|
|
26
31
|
export interface LoginDto {
|
|
27
32
|
Body: LoginUserDto
|
|
28
|
-
Reply: LoginSuccessDto | ErrorResponseDto
|
|
33
|
+
Reply: LoginSuccessDto | ErrorResponseDto | InvalidPasswordResponseDto
|
|
29
34
|
}
|
|
30
35
|
|
|
31
36
|
export interface ResetPasswordSendDto {
|