mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
fix(core,schemas): fix email and sms verification for continue route (#2349)
This commit is contained in:
parent
92b93e6e36
commit
e699e3fb62
6 changed files with 75 additions and 11 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
import { PasscodeType } from '@logto/schemas';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { Provider } from 'oidc-provider';
|
import { Provider } from 'oidc-provider';
|
||||||
|
|
||||||
|
@ -137,6 +138,7 @@ describe('session -> continueRoutes', () => {
|
||||||
continueSignIn: {
|
continueSignIn: {
|
||||||
userId: mockUser.id,
|
userId: mockUser.id,
|
||||||
expiresAt: dayjs().add(1, 'day').toISOString(),
|
expiresAt: dayjs().add(1, 'day').toISOString(),
|
||||||
|
type: PasscodeType.Continue,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -168,6 +170,7 @@ describe('session -> continueRoutes', () => {
|
||||||
continueSignIn: {
|
continueSignIn: {
|
||||||
userId: mockUser.id,
|
userId: mockUser.id,
|
||||||
expiresAt: dayjs().add(1, 'day').toISOString(),
|
expiresAt: dayjs().add(1, 'day').toISOString(),
|
||||||
|
type: PasscodeType.Continue,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -17,7 +17,7 @@ import {
|
||||||
import assertThat from '@/utils/assert-that';
|
import assertThat from '@/utils/assert-that';
|
||||||
|
|
||||||
import type { AnonymousRouter } from '../types';
|
import type { AnonymousRouter } from '../types';
|
||||||
import { emailSessionResultGuard, smsSessionResultGuard } from './types';
|
import { continueEmailSessionResultGuard, continueSmsSessionResultGuard } from './types';
|
||||||
import {
|
import {
|
||||||
checkRequiredProfile,
|
checkRequiredProfile,
|
||||||
getContinueSignInResult,
|
getContinueSignInResult,
|
||||||
|
@ -104,7 +104,7 @@ export default function continueRoutes<T extends AnonymousRouter>(router: T, pro
|
||||||
const { email } = await getVerificationStorageFromInteraction(
|
const { email } = await getVerificationStorageFromInteraction(
|
||||||
ctx,
|
ctx,
|
||||||
provider,
|
provider,
|
||||||
emailSessionResultGuard
|
continueEmailSessionResultGuard
|
||||||
);
|
);
|
||||||
const user = await findUserById(userId);
|
const user = await findUserById(userId);
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ export default function continueRoutes<T extends AnonymousRouter>(router: T, pro
|
||||||
const { phone } = await getVerificationStorageFromInteraction(
|
const { phone } = await getVerificationStorageFromInteraction(
|
||||||
ctx,
|
ctx,
|
||||||
provider,
|
provider,
|
||||||
smsSessionResultGuard
|
continueSmsSessionResultGuard
|
||||||
);
|
);
|
||||||
const user = await findUserById(userId);
|
const user = await findUserById(userId);
|
||||||
|
|
||||||
|
|
|
@ -117,14 +117,22 @@ export default function passwordlessRoutes<T extends AnonymousRouter>(
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flow === PasscodeType.SignIn) {
|
||||||
await assignVerificationResult(ctx, provider, { flow, phone });
|
await assignVerificationResult(ctx, provider, { flow, phone });
|
||||||
|
|
||||||
if (flow === PasscodeType.SignIn) {
|
|
||||||
return smsSignInAction(provider)(ctx, next);
|
return smsSignInAction(provider)(ctx, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flow === PasscodeType.Register) {
|
||||||
|
await assignVerificationResult(ctx, provider, { flow, phone });
|
||||||
|
|
||||||
return smsRegisterAction(provider)(ctx, next);
|
return smsRegisterAction(provider)(ctx, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await assignVerificationResult(ctx, provider, { flow, phone });
|
||||||
|
|
||||||
|
return next();
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
|
@ -161,14 +169,22 @@ export default function passwordlessRoutes<T extends AnonymousRouter>(
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flow === PasscodeType.SignIn) {
|
||||||
await assignVerificationResult(ctx, provider, { flow, email });
|
await assignVerificationResult(ctx, provider, { flow, email });
|
||||||
|
|
||||||
if (flow === PasscodeType.SignIn) {
|
|
||||||
return emailSignInAction(provider)(ctx, next);
|
return emailSignInAction(provider)(ctx, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flow === PasscodeType.Register) {
|
||||||
|
await assignVerificationResult(ctx, provider, { flow, email });
|
||||||
|
|
||||||
return emailRegisterAction(provider)(ctx, next);
|
return emailRegisterAction(provider)(ctx, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await assignVerificationResult(ctx, provider, { flow, email });
|
||||||
|
|
||||||
|
return next();
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
router.post(`${signInRoute}/sms`, smsSignInAction(provider));
|
router.post(`${signInRoute}/sms`, smsSignInAction(provider));
|
||||||
|
|
|
@ -45,10 +45,36 @@ export const forgotPasswordSessionResultGuard = z.object({
|
||||||
verification: forgotPasswordSessionStorageGuard,
|
verification: forgotPasswordSessionStorageGuard,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const continueEmailSessionStorageGuard = z.object({
|
||||||
|
flow: z.literal(PasscodeType.Continue),
|
||||||
|
expiresAt: z.string(),
|
||||||
|
email: z.string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type ContinueEmailSessionStorage = z.infer<typeof continueEmailSessionStorageGuard>;
|
||||||
|
|
||||||
|
export const continueEmailSessionResultGuard = z.object({
|
||||||
|
verification: continueEmailSessionStorageGuard,
|
||||||
|
});
|
||||||
|
|
||||||
|
const continueSmsSessionStorageGuard = z.object({
|
||||||
|
flow: z.literal(PasscodeType.Continue),
|
||||||
|
expiresAt: z.string(),
|
||||||
|
phone: z.string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type ContinueSmsSessionStorage = z.infer<typeof continueSmsSessionStorageGuard>;
|
||||||
|
|
||||||
|
export const continueSmsSessionResultGuard = z.object({
|
||||||
|
verification: continueSmsSessionStorageGuard,
|
||||||
|
});
|
||||||
|
|
||||||
export type VerificationStorage =
|
export type VerificationStorage =
|
||||||
| SmsSessionStorage
|
| SmsSessionStorage
|
||||||
| EmailSessionStorage
|
| EmailSessionStorage
|
||||||
| ForgotPasswordSessionStorage;
|
| ForgotPasswordSessionStorage
|
||||||
|
| ContinueEmailSessionStorage
|
||||||
|
| ContinueSmsSessionStorage;
|
||||||
|
|
||||||
export type VerificationResult<T = VerificationStorage> = { verification: T };
|
export type VerificationResult<T = VerificationStorage> = { verification: T };
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { sql } from 'slonik';
|
||||||
|
|
||||||
|
import type { AlterationScript } from '../lib/types/alteration';
|
||||||
|
|
||||||
|
const alteration: AlterationScript = {
|
||||||
|
up: async (pool) => {
|
||||||
|
await pool.query(sql`
|
||||||
|
alter type passcode_type add value 'Continue'
|
||||||
|
`);
|
||||||
|
},
|
||||||
|
down: async (pool) => {
|
||||||
|
await pool.query(sql`
|
||||||
|
drop type passcode_type
|
||||||
|
create type passcode_type as enum ('SignIn', 'Register', 'ForgotPassword');
|
||||||
|
`);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default alteration;
|
|
@ -1,4 +1,4 @@
|
||||||
create type passcode_type as enum ('SignIn', 'Register', 'ForgotPassword');
|
create type passcode_type as enum ('SignIn', 'Register', 'ForgotPassword', 'Continue');
|
||||||
|
|
||||||
create table passcodes (
|
create table passcodes (
|
||||||
id varchar(21) not null,
|
id varchar(21) not null,
|
||||||
|
|
Loading…
Reference in a new issue