mirror of
https://github.com/logto-io/logto.git
synced 2025-03-10 22:22:45 -05:00
refactor(core): split updatePasscode into increasePasscodeTryCount and consumePasscode (#1510)
This commit is contained in:
parent
988157d586
commit
f479a1566f
4 changed files with 27 additions and 48 deletions
|
@ -5,11 +5,12 @@ import { mockConnector, mockMetadata } from '@/__mocks__';
|
|||
import { getConnectorInstances } from '@/connectors';
|
||||
import RequestError from '@/errors/RequestError';
|
||||
import {
|
||||
consumePasscode,
|
||||
deletePasscodesByIds,
|
||||
findUnconsumedPasscodeByJtiAndType,
|
||||
findUnconsumedPasscodesByJtiAndType,
|
||||
increasePasscodeTryCount,
|
||||
insertPasscode,
|
||||
updatePasscode,
|
||||
} from '@/queries/passcode';
|
||||
|
||||
import {
|
||||
|
@ -39,7 +40,10 @@ const mockedInsertPasscode = insertPasscode as jest.MockedFunction<typeof insert
|
|||
const mockedGetConnectorInstances = getConnectorInstances as jest.MockedFunction<
|
||||
typeof getConnectorInstances
|
||||
>;
|
||||
const mockedUpdatePasscode = updatePasscode as jest.MockedFunction<typeof updatePasscode>;
|
||||
const mockedConsumePasscode = consumePasscode as jest.MockedFunction<typeof consumePasscode>;
|
||||
const mockedIncreasePasscodeTryCount = increasePasscodeTryCount as jest.MockedFunction<
|
||||
typeof increasePasscodeTryCount
|
||||
>;
|
||||
|
||||
beforeAll(() => {
|
||||
mockedFindUnconsumedPasscodesByJtiAndType.mockResolvedValue([]);
|
||||
|
@ -224,11 +228,7 @@ describe('verifyPasscode', () => {
|
|||
it('should mark as consumed on successful verification', async () => {
|
||||
mockedFindUnconsumedPasscodeByJtiAndType.mockResolvedValue(passcode);
|
||||
await verifyPasscode(passcode.interactionJti, passcode.type, passcode.code, { phone: 'phone' });
|
||||
expect(mockedUpdatePasscode).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
set: { consumed: true },
|
||||
})
|
||||
);
|
||||
expect(mockedConsumePasscode).toHaveBeenCalledWith(passcode.id);
|
||||
});
|
||||
|
||||
it('should fail when passcode not found', async () => {
|
||||
|
@ -285,10 +285,6 @@ describe('verifyPasscode', () => {
|
|||
await expect(
|
||||
verifyPasscode(passcode.interactionJti, passcode.type, 'invalid', { phone: 'phone' })
|
||||
).rejects.toThrow(new RequestError('passcode.code_mismatch'));
|
||||
expect(mockedUpdatePasscode).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
set: { tryCount: passcode.tryCount + 1 },
|
||||
})
|
||||
);
|
||||
expect(mockedIncreasePasscodeTryCount).toHaveBeenCalledWith(passcode.id);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,11 +5,12 @@ import { getConnectorInstances } from '@/connectors';
|
|||
import { ConnectorType, EmailConnectorInstance, SmsConnectorInstance } from '@/connectors/types';
|
||||
import RequestError from '@/errors/RequestError';
|
||||
import {
|
||||
consumePasscode,
|
||||
deletePasscodesByIds,
|
||||
findUnconsumedPasscodeByJtiAndType,
|
||||
findUnconsumedPasscodesByJtiAndType,
|
||||
increasePasscodeTryCount,
|
||||
insertPasscode,
|
||||
updatePasscode,
|
||||
} from '@/queries/passcode';
|
||||
import assertThat from '@/utils/assert-that';
|
||||
|
||||
|
@ -106,13 +107,9 @@ export const verifyPasscode = async (
|
|||
}
|
||||
|
||||
if (code !== passcode.code) {
|
||||
await updatePasscode({
|
||||
where: { id: passcode.id },
|
||||
set: { tryCount: passcode.tryCount + 1 },
|
||||
jsonbMode: 'merge',
|
||||
});
|
||||
await increasePasscodeTryCount(passcode.id);
|
||||
throw new RequestError('passcode.code_mismatch');
|
||||
}
|
||||
|
||||
await updatePasscode({ where: { id: passcode.id }, set: { consumed: true }, jsonbMode: 'merge' });
|
||||
await consumePasscode(passcode.id);
|
||||
};
|
||||
|
|
|
@ -16,7 +16,6 @@ import {
|
|||
findUnconsumedPasscodeByJtiAndType,
|
||||
findUnconsumedPasscodesByJtiAndType,
|
||||
insertPasscode,
|
||||
updatePasscode,
|
||||
deletePasscodeById,
|
||||
deletePasscodesByIds,
|
||||
} from './passcode';
|
||||
|
@ -94,32 +93,6 @@ describe('passcode query', () => {
|
|||
await expect(insertPasscode(mockPasscode)).resolves.toEqual(mockPasscode);
|
||||
});
|
||||
|
||||
it('updatePasscode', async () => {
|
||||
const id = 'foo';
|
||||
const tryCount = 3;
|
||||
|
||||
const expectSql = sql`
|
||||
update ${table}
|
||||
set ${fields.tryCount}=$1
|
||||
where ${fields.id}=$2
|
||||
returning *
|
||||
`;
|
||||
|
||||
mockQuery.mockImplementationOnce(async (sql, values) => {
|
||||
expectSqlAssert(sql, expectSql.sql);
|
||||
expect(values).toEqual([tryCount, id]);
|
||||
|
||||
return createMockQueryResult([{ ...mockPasscode, tryCount }]);
|
||||
});
|
||||
|
||||
await expect(
|
||||
updatePasscode({ where: { id }, set: { tryCount }, jsonbMode: 'merge' })
|
||||
).resolves.toEqual({
|
||||
...mockPasscode,
|
||||
tryCount,
|
||||
});
|
||||
});
|
||||
|
||||
it('deletePasscodeById', async () => {
|
||||
const id = 'foo';
|
||||
const expectSql = sql`
|
||||
|
|
|
@ -2,7 +2,6 @@ import { PasscodeType, Passcode, Passcodes, CreatePasscode } from '@logto/schema
|
|||
import { sql } from 'slonik';
|
||||
|
||||
import { buildInsertInto } from '@/database/insert-into';
|
||||
import { buildUpdateWhere } from '@/database/update-where';
|
||||
import { convertToIdentifiers } from '@/database/utils';
|
||||
import envSet from '@/env-set';
|
||||
import { DeletionError } from '@/errors/SlonikError';
|
||||
|
@ -27,7 +26,21 @@ export const insertPasscode = buildInsertInto<CreatePasscode, Passcode>(Passcode
|
|||
returning: true,
|
||||
});
|
||||
|
||||
export const updatePasscode = buildUpdateWhere<CreatePasscode, Passcode>(Passcodes, true);
|
||||
export const consumePasscode = async (id: string) =>
|
||||
envSet.pool.query<Passcode>(sql`
|
||||
update ${table}
|
||||
set ${fields.consumed}=true
|
||||
where ${fields.id}=${sql`${id}`}
|
||||
returning ${sql.join(Object.values(fields), sql`, `)}
|
||||
`);
|
||||
|
||||
export const increasePasscodeTryCount = async (id: string) =>
|
||||
envSet.pool.query<Passcode>(sql`
|
||||
update ${table}
|
||||
set ${fields.tryCount}=${fields.tryCount}+1
|
||||
where ${fields.id}=${sql`${id}`}
|
||||
returning ${sql.join(Object.values(fields), sql`, `)}
|
||||
`);
|
||||
|
||||
export const deletePasscodeById = async (id: string) => {
|
||||
const { rowCount } = await envSet.pool.query(sql`
|
||||
|
|
Loading…
Add table
Reference in a new issue