0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-01-13 21:30:30 -05:00

feat(core,schemas): log register (#601)

This commit is contained in:
IceHe.xyz 2022-04-26 11:49:11 +08:00 committed by GitHub
parent 3aa4342f2e
commit a10b427c87
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 85 additions and 8 deletions

View file

@ -690,6 +690,7 @@ describe('sessionRoutes', () => {
describe('POST /session/register/social', () => { describe('POST /session/register/social', () => {
it('register with social, assign result and redirect', async () => { it('register with social, assign result and redirect', async () => {
interactionDetails.mockResolvedValueOnce({ interactionDetails.mockResolvedValueOnce({
jti: 'jti',
result: { result: {
socialUserInfo: { connectorId: 'connectorId', userInfo: { id: 'user1' } }, socialUserInfo: { connectorId: 'connectorId', userInfo: { id: 'user1' } },
}, },
@ -759,6 +760,7 @@ describe('sessionRoutes', () => {
}); });
it('updates user identities', async () => { it('updates user identities', async () => {
interactionDetails.mockResolvedValueOnce({ interactionDetails.mockResolvedValueOnce({
jti: 'jti',
result: { result: {
login: { accountId: 'user1' }, login: { accountId: 'user1' },
socialUserInfo: { socialUserInfo: {

View file

@ -306,7 +306,10 @@ export default function sessionRoutes<T extends AnonymousRouter>(router: T, prov
}), }),
}), }),
async (ctx, next) => { async (ctx, next) => {
const { jti } = await provider.interactionDetails(ctx.req, ctx.res);
const { username, password } = ctx.guard.body; const { username, password } = ctx.guard.body;
const type = 'RegisterUsernamePassword';
ctx.log(type, { sessionId: jti, username });
assertThat( assertThat(
password, password,
@ -324,6 +327,8 @@ export default function sessionRoutes<T extends AnonymousRouter>(router: T, prov
); );
const id = await generateUserId(); const id = await generateUserId();
ctx.log(type, { userId: id });
const { passwordEncryptionSalt, passwordEncrypted, passwordEncryptionMethod } = const { passwordEncryptionSalt, passwordEncrypted, passwordEncryptionMethod } =
encryptUserPassword(id, password); encryptUserPassword(id, password);
@ -358,6 +363,8 @@ export default function sessionRoutes<T extends AnonymousRouter>(router: T, prov
async (ctx, next) => { async (ctx, next) => {
const { jti } = await provider.interactionDetails(ctx.req, ctx.res); const { jti } = await provider.interactionDetails(ctx.req, ctx.res);
const { phone } = ctx.guard.body; const { phone } = ctx.guard.body;
const type = 'RegisterSmsSendPasscode';
ctx.log(type, { sessionId: jti, phone });
assertThat( assertThat(
!(await hasUserWithPhone(phone)), !(await hasUserWithPhone(phone)),
@ -365,6 +372,8 @@ export default function sessionRoutes<T extends AnonymousRouter>(router: T, prov
); );
const passcode = await createPasscode(jti, PasscodeType.Register, { phone }); const passcode = await createPasscode(jti, PasscodeType.Register, { phone });
ctx.log(type, { sessionId: jti, phone, passcode });
await sendPasscode(passcode); await sendPasscode(passcode);
ctx.status = 204; ctx.status = 204;
@ -378,6 +387,8 @@ export default function sessionRoutes<T extends AnonymousRouter>(router: T, prov
async (ctx, next) => { async (ctx, next) => {
const { jti } = await provider.interactionDetails(ctx.req, ctx.res); const { jti } = await provider.interactionDetails(ctx.req, ctx.res);
const { phone, code } = ctx.guard.body; const { phone, code } = ctx.guard.body;
const type = 'RegisterSms';
ctx.log(type, { sessionId: jti, phone, code });
assertThat( assertThat(
!(await hasUserWithPhone(phone)), !(await hasUserWithPhone(phone)),
@ -386,6 +397,7 @@ export default function sessionRoutes<T extends AnonymousRouter>(router: T, prov
await verifyPasscode(jti, PasscodeType.Register, code, { phone }); await verifyPasscode(jti, PasscodeType.Register, code, { phone });
const id = await generateUserId(); const id = await generateUserId();
ctx.log(type, { userId: id });
await insertUser({ id, primaryPhone: phone }); await insertUser({ id, primaryPhone: phone });
await assignInteractionResults(ctx, provider, { login: { accountId: id } }); await assignInteractionResults(ctx, provider, { login: { accountId: id } });
@ -400,6 +412,8 @@ export default function sessionRoutes<T extends AnonymousRouter>(router: T, prov
async (ctx, next) => { async (ctx, next) => {
const { jti } = await provider.interactionDetails(ctx.req, ctx.res); const { jti } = await provider.interactionDetails(ctx.req, ctx.res);
const { email } = ctx.guard.body; const { email } = ctx.guard.body;
const type = 'RegisterEmailSendPasscode';
ctx.log(type, { sessionId: jti, email });
assertThat( assertThat(
!(await hasUserWithEmail(email)), !(await hasUserWithEmail(email)),
@ -407,6 +421,8 @@ export default function sessionRoutes<T extends AnonymousRouter>(router: T, prov
); );
const passcode = await createPasscode(jti, PasscodeType.Register, { email }); const passcode = await createPasscode(jti, PasscodeType.Register, { email });
ctx.log(type, { passcode });
await sendPasscode(passcode); await sendPasscode(passcode);
ctx.status = 204; ctx.status = 204;
@ -420,6 +436,8 @@ export default function sessionRoutes<T extends AnonymousRouter>(router: T, prov
async (ctx, next) => { async (ctx, next) => {
const { jti } = await provider.interactionDetails(ctx.req, ctx.res); const { jti } = await provider.interactionDetails(ctx.req, ctx.res);
const { email, code } = ctx.guard.body; const { email, code } = ctx.guard.body;
const type = 'RegisterEmail';
ctx.log(type, { sessionId: jti, email, code });
assertThat( assertThat(
!(await hasUserWithEmail(email)), !(await hasUserWithEmail(email)),
@ -428,6 +446,7 @@ export default function sessionRoutes<T extends AnonymousRouter>(router: T, prov
await verifyPasscode(jti, PasscodeType.Register, code, { email }); await verifyPasscode(jti, PasscodeType.Register, code, { email });
const id = await generateUserId(); const id = await generateUserId();
ctx.log(type, { userId: id });
await insertUser({ id, primaryEmail: email }); await insertUser({ id, primaryEmail: email });
await assignInteractionResults(ctx, provider, { login: { accountId: id } }); await assignInteractionResults(ctx, provider, { login: { accountId: id } });
@ -444,15 +463,18 @@ export default function sessionRoutes<T extends AnonymousRouter>(router: T, prov
}), }),
}), }),
async (ctx, next) => { async (ctx, next) => {
const { connectorId } = ctx.guard.body; const { jti, result } = await provider.interactionDetails(ctx.req, ctx.res);
const { result } = await provider.interactionDetails(ctx.req, ctx.res);
// User can not register with social directly, // User can not register with social directly,
// need to try to sign in with social first, then confirm to register and continue, // need to try to sign in with social first, then confirm to register and continue,
// so the result is expected to be exists. // so the result is expected to be exists.
assertThat(result, 'session.connector_session_not_found'); assertThat(result, 'session.connector_session_not_found');
const { connectorId } = ctx.guard.body;
const type = 'RegisterSocial';
ctx.log(type, { sessionId: jti, connectorId });
const userInfo = await getUserInfoFromInteractionResult(connectorId, result); const userInfo = await getUserInfoFromInteractionResult(connectorId, result);
ctx.log(type, { userInfo });
assertThat(!(await hasUserWithIdentity(connectorId, userInfo.id)), 'user.identity_exists'); assertThat(!(await hasUserWithIdentity(connectorId, userInfo.id)), 'user.identity_exists');
const id = await generateUserId(); const id = await generateUserId();
@ -467,6 +489,7 @@ export default function sessionRoutes<T extends AnonymousRouter>(router: T, prov
}, },
}, },
}); });
ctx.log(type, { userId: id });
await assignInteractionResults(ctx, provider, { login: { accountId: id } }); await assignInteractionResults(ctx, provider, { login: { accountId: id } });
@ -482,15 +505,20 @@ export default function sessionRoutes<T extends AnonymousRouter>(router: T, prov
}), }),
}), }),
async (ctx, next) => { async (ctx, next) => {
const { connectorId } = ctx.guard.body; const { jti, result } = await provider.interactionDetails(ctx.req, ctx.res);
const { result } = await provider.interactionDetails(ctx.req, ctx.res);
assertThat(result, 'session.connector_session_not_found'); assertThat(result, 'session.connector_session_not_found');
assertThat(result.login?.accountId, 'session.unauthorized'); const userId = result.login?.accountId;
assertThat(userId, 'session.unauthorized');
const { connectorId } = ctx.guard.body;
const type = 'RegisterSocialBind';
ctx.log(type, { sessionId: jti, connectorId, userId });
const userInfo = await getUserInfoFromInteractionResult(connectorId, result); const userInfo = await getUserInfoFromInteractionResult(connectorId, result);
const user = await findUserById(result.login.accountId); ctx.log(type, { userInfo });
const updatedUser = await updateUserById(user.id, { const user = await findUserById(userId);
const updatedUser = await updateUserById(userId, {
identities: { identities: {
...user.identities, ...user.identities,
[connectorId]: { userId: userInfo.id, details: userInfo }, [connectorId]: { userId: userInfo.id, details: userInfo },

View file

@ -11,6 +11,46 @@ interface BaseLogPayload {
error?: string; error?: string;
} }
interface RegisterUsernamePasswordLogPayload extends BaseLogPayload {
userId?: string;
username?: string;
}
interface RegisterEmailSendPasscodeLogPayload extends BaseLogPayload {
email?: string;
passcode?: Passcode;
}
interface RegisterEmailLogPayload extends BaseLogPayload {
email?: string;
code?: string;
userId?: string;
}
interface RegisterSmsSendPasscodeLogPayload extends BaseLogPayload {
phone?: string;
passcode?: Passcode;
}
interface RegisterSmsLogPayload extends BaseLogPayload {
phone?: string;
code?: string;
userId?: string;
}
interface RegisterSocialBindLogPayload extends BaseLogPayload {
connectorId?: string;
userInfo?: object;
userId?: string;
}
interface RegisterSocialLogPayload extends RegisterSocialBindLogPayload {
code?: string;
state?: string;
redirectUri?: string;
redirectTo?: string;
}
interface SignInUsernamePasswordLogPayload extends BaseLogPayload { interface SignInUsernamePasswordLogPayload extends BaseLogPayload {
userId?: string; userId?: string;
username?: string; username?: string;
@ -52,6 +92,13 @@ interface SignInSocialLogPayload extends SignInSocialBindLogPayload {
} }
export type LogPayloads = { export type LogPayloads = {
RegisterUsernamePassword: RegisterUsernamePasswordLogPayload;
RegisterEmailSendPasscode: RegisterEmailSendPasscodeLogPayload;
RegisterEmail: RegisterEmailLogPayload;
RegisterSmsSendPasscode: RegisterSmsSendPasscodeLogPayload;
RegisterSms: RegisterSmsLogPayload;
RegisterSocialBind: RegisterSocialBindLogPayload;
RegisterSocial: RegisterSocialLogPayload;
SignInUsernamePassword: SignInUsernamePasswordLogPayload; SignInUsernamePassword: SignInUsernamePasswordLogPayload;
SignInEmailSendPasscode: SignInEmailSendPasscodeLogPayload; SignInEmailSendPasscode: SignInEmailSendPasscodeLogPayload;
SignInEmail: SignInEmailLogPayload; SignInEmail: SignInEmailLogPayload;