mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
feat(core): post /session/forgot-password/phone/verify-passcode-and-reset-password (#334)
* feat(core): add post /session/forgot-password/phone/verify-passcode and UT * feat(core): reset password once passcode verification succeed
This commit is contained in:
parent
1399c9258e
commit
9e677ca97a
2 changed files with 77 additions and 0 deletions
|
@ -780,6 +780,46 @@ describe('sessionRoutes', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('POST /session/forgot-password/phone/verify-passcode-and-reset-password', () => {
|
||||
beforeAll(() => {
|
||||
interactionDetails.mockResolvedValueOnce({
|
||||
jti: 'jti',
|
||||
});
|
||||
});
|
||||
|
||||
it('throw if no user can be found with phone', async () => {
|
||||
const response = await sessionRequest
|
||||
.post('/session/forgot-password/phone/verify-passcode-and-reset-password')
|
||||
.send({ phone: '13000000001', code: '1234', password: '123456' });
|
||||
expect(response).toHaveProperty('statusCode', 422);
|
||||
});
|
||||
|
||||
it('fail to verify passcode', async () => {
|
||||
const response = await sessionRequest
|
||||
.post('/session/forgot-password/phone/verify-passcode-and-reset-password')
|
||||
.send({ phone: '13000000000', code: '1231', password: '123456' });
|
||||
expect(response).toHaveProperty('statusCode', 400);
|
||||
});
|
||||
|
||||
it('verify passcode, reset password and assign result', async () => {
|
||||
const response = await sessionRequest
|
||||
.post('/session/forgot-password/phone/verify-passcode-and-reset-password')
|
||||
.send({ phone: '13000000000', code: '1234', password: '123456' });
|
||||
expect(response).toHaveProperty('statusCode', 200);
|
||||
expect(updateUserById).toHaveBeenCalledWith('id', {
|
||||
passwordEncryptionSalt: 'user1',
|
||||
passwordEncrypted: 'id_123456_user1',
|
||||
passwordEncryptionMethod: 'SaltAndPepper',
|
||||
});
|
||||
expect(interactionResult).toHaveBeenCalledWith(
|
||||
expect.anything(),
|
||||
expect.anything(),
|
||||
expect.objectContaining({ login: { accountId: 'id' } }),
|
||||
expect.anything()
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('POST /session/bind-social', () => {
|
||||
it('throw if session is not authorized', async () => {
|
||||
interactionDetails.mockResolvedValueOnce({});
|
||||
|
|
|
@ -503,6 +503,43 @@ export default function sessionRoutes<T extends AnonymousRouter>(router: T, prov
|
|||
}
|
||||
);
|
||||
|
||||
router.post(
|
||||
'/session/forgot-password/phone/verify-passcode-and-reset-password',
|
||||
koaGuard({
|
||||
body: object({
|
||||
phone: string().regex(phoneRegEx),
|
||||
code: string(),
|
||||
password: string().regex(passwordRegEx),
|
||||
}),
|
||||
}),
|
||||
async (ctx, next) => {
|
||||
const { jti } = await provider.interactionDetails(ctx.req, ctx.res);
|
||||
const { phone, code, password } = ctx.guard.body;
|
||||
ctx.userLog.phone = phone;
|
||||
ctx.userLog.type = UserLogType.ForgotPasswordPhone;
|
||||
|
||||
assertThat(
|
||||
await hasUserWithPhone(phone),
|
||||
new RequestError({ code: 'user.phone_not_exists', status: 422 })
|
||||
);
|
||||
|
||||
await verifyPasscode(jti, PasscodeType.ForgotPassword, code, { phone });
|
||||
const { id } = await findUserByPhone(phone);
|
||||
ctx.userLog.userId = id;
|
||||
|
||||
const { passwordEncryptionSalt, passwordEncrypted, passwordEncryptionMethod } =
|
||||
encryptUserPassword(id, password);
|
||||
await updateUserById(id, {
|
||||
passwordEncryptionSalt,
|
||||
passwordEncrypted,
|
||||
passwordEncryptionMethod,
|
||||
});
|
||||
await assignInteractionResults(ctx, provider, { login: { accountId: id } });
|
||||
|
||||
return next();
|
||||
}
|
||||
);
|
||||
|
||||
router.post(
|
||||
'/session/bind-social',
|
||||
koaGuard({
|
||||
|
|
Loading…
Reference in a new issue