From c67d4a382ff223f3773112ff2055f19448855f96 Mon Sep 17 00:00:00 2001 From: wangsijie Date: Mon, 10 Oct 2022 14:04:00 +0800 Subject: [PATCH] feat(schemas): add sie v2 alteration (#2077) --- .../next-1665300135-sign-in-sign-up.ts | 174 ++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 packages/schemas/alterations/next-1665300135-sign-in-sign-up.ts diff --git a/packages/schemas/alterations/next-1665300135-sign-in-sign-up.ts b/packages/schemas/alterations/next-1665300135-sign-in-sign-up.ts new file mode 100644 index 000000000..4593b77a3 --- /dev/null +++ b/packages/schemas/alterations/next-1665300135-sign-in-sign-up.ts @@ -0,0 +1,174 @@ +import { sql } from 'slonik'; + +import { AlterationScript } from '../lib/types/alteration'; + +enum SignInMethodState { + Primary = 'primary', + Secondary = 'secondary', + Disabled = 'disabled', +} + +enum SignInMethodKey { + Username = 'username', + Email = 'email', + Sms = 'sms', + Social = 'social', +} + +type SignInExperience = { + sign_in_methods: { + [SignInMethodKey.Username]: SignInMethodState; + [SignInMethodKey.Email]: SignInMethodState; + [SignInMethodKey.Sms]: SignInMethodState; + [SignInMethodKey.Social]: SignInMethodState; + }; +}; + +enum SignUpIdentifier { + Email = 'email', + Phone = 'phone', + Username = 'username', + EmailOrPhone = 'emailOrPhone', + None = 'none', +} + +enum SignInIdentifier { + Email = 'email', + Phone = 'phone', + Username = 'username', +} + +type SignIn = { + methods: Array<{ + identifier: SignInIdentifier; + password: boolean; + verificationCode: boolean; + isPasswordPrimary: boolean; + }>; +}; + +type SignUp = { + identifier: SignUpIdentifier; + password: boolean; + verify: boolean; +}; + +const parseSignInMethodToSignInIdentifier = ( + method: SignInMethodKey +): SignInIdentifier | undefined => { + if (method === SignInMethodKey.Username) { + return SignInIdentifier.Username; + } + + if (method === SignInMethodKey.Email) { + return SignInIdentifier.Email; + } + + if (method === SignInMethodKey.Sms) { + return SignInIdentifier.Phone; + } +}; + +const parseSignInMethodToSignUpIdentifier = (method?: SignInMethodKey): SignUpIdentifier => { + if (method === SignInMethodKey.Username) { + return SignUpIdentifier.Username; + } + + if (method === SignInMethodKey.Email) { + return SignUpIdentifier.Email; + } + + if (method === SignInMethodKey.Sms) { + return SignUpIdentifier.Phone; + } + + return SignUpIdentifier.None; +}; + +const alteration: AlterationScript = { + up: async (pool) => { + await pool.query(sql` + alter table sign_in_experiences add column sign_in jsonb + `); + await pool.query(sql` + alter table sign_in_experiences add column sign_up jsonb + `); + await pool.query(sql` + alter table sign_in_experiences add column forgot_password boolean not null default false + `); + + const id = 'default'; + const data = await pool.maybeOne( + sql`select * from sign_in_experiences where id = ${id}` + ); + + /* eslint-disable @silverhand/fp/no-mutating-methods */ + if (data) { + const { sign_in_methods: signInMethods } = data; + const methodKeys = Object.values(SignInMethodKey); + const primaryMethod = methodKeys.find( + (key) => signInMethods[key] === SignInMethodState.Primary + ); + const secondaryMethods = methodKeys.filter( + (key) => signInMethods[key] === SignInMethodState.Secondary + ); + const signIn: SignIn = { + methods: [], + }; + + const methods = [primaryMethod, ...secondaryMethods]; + + for (const method of methods) { + if (!method) { + continue; + } + + const identifier = parseSignInMethodToSignInIdentifier(method); + + if (identifier) { + signIn.methods.push({ + identifier, + password: identifier === SignInIdentifier.Username, + verificationCode: identifier !== SignInIdentifier.Username, + isPasswordPrimary: false, + }); + } + } + + const signUpIdentifier = parseSignInMethodToSignUpIdentifier(primaryMethod); + const signUp: SignUp = { + identifier: signUpIdentifier, + verify: true, + password: signUpIdentifier === SignUpIdentifier.Username, + }; + + await pool.query(sql` + update sign_in_experiences set sign_in = ${JSON.stringify(signIn)} where id = ${id} + `); + await pool.query(sql` + update sign_in_experiences set sign_up = ${JSON.stringify(signUp)} where id = ${id} + `); + } + /* eslint-enable @silverhand/fp/no-mutating-methods */ + + await pool.query(sql` + alter table sign_in_experiences alter column sign_in set not null + `); + await pool.query(sql` + alter table sign_in_experiences alter column sign_up set not null + `); + }, + down: async (pool) => { + await pool.query(sql` + alter table sign_in_experiences drop column sign_in + `); + await pool.query(sql` + alter table sign_in_experiences drop column sign_up + `); + await pool.query(sql` + alter table sign_in_experiences drop column forgot_password + `); + }, +}; + +export default alteration;