0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00

feat(schemas): sign-in-experiences (#361)

* chore(schemas): remove useless table sign_in_methods

* feat(schemas): sign-in-experiences

* chore(core): update mock.ts and sign-in-experience.test.ts about sign-in-experiences schema

* chore(core): fix typo in test
This commit is contained in:
IceHe.xyz 2022-03-15 16:46:23 +08:00 committed by GitHub
parent bb467a518f
commit 9f3fc5a5cc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 87 additions and 136 deletions

View file

@ -21,11 +21,11 @@ describe('sign-in-experience query', () => {
const { table, fields } = convertToIdentifiers(SignInExperiences);
const dbvalue = {
...mockSignInExperience,
companyInfo: JSON.stringify(mockSignInExperience.companyInfo),
branding: JSON.stringify(mockSignInExperience.branding),
termsOfUse: JSON.stringify(mockSignInExperience.termsOfUse),
localization: JSON.stringify(mockSignInExperience.localization),
signInMethods: JSON.stringify(mockSignInExperience.signInMethods),
languageInfo: JSON.stringify(mockSignInExperience.languageInfo),
signInMethods: JSON.stringify(mockSignInExperience.socialSignInConnectorIds),
socialSignInConnectorIds: JSON.stringify(mockSignInExperience.socialSignInConnectorIds),
};
it('findDefaultSignInExperience', async () => {

View file

@ -1,4 +1,4 @@
import { SignInExperience, CreateSignInExperience } from '@logto/schemas';
import { SignInExperience, CreateSignInExperience, BrandingStyle, Branding } from '@logto/schemas';
import { mockSignInExperience } from '@/utils/mock';
import { createRequester } from '@/utils/test-utils';
@ -25,38 +25,37 @@ describe('signInExperiences routes', () => {
});
it('PATCH /sign-in-ex/:id', async () => {
const companyInfo = {
name: 'silverhand',
logo: 'http://silverhand.png',
};
const signInMethods = {
primary: ['phone'],
secondary: ['email'],
disabled: [],
const branding: Branding = {
primaryColor: '#000',
backgroundColor: '#fff',
darkMode: true,
darkBackgroundColor: '#000',
darkPrimaryColor: '#fff',
style: BrandingStyle.Logo,
logoUrl: 'http://silverhand.png',
slogan: 'silverhand',
};
const socialSignInConnectorIds = ['abc', 'def'];
const response = await signInExperienceRequester.patch('/sign-in-ex/default').send({
companyInfo,
signInMethods,
branding,
socialSignInConnectorIds,
});
expect(response.status).toEqual(200);
expect(response.body).toEqual({
...mockSignInExperience,
companyInfo,
signInMethods,
branding,
socialSignInConnectorIds,
});
});
it('PATH /sign-in-ex/:id should throw with invalid inputs', async () => {
const signInMethods = {
primary: [],
secondary: ['email'],
disabled: [],
};
it('PATCH /sign-in-ex/:id should throw with invalid inputs', async () => {
const socialSignInConnectorIds = [123, 456];
const response = await signInExperienceRequester.patch('/sign-in-ex/default').send({
signInMethods,
socialSignInConnectorIds,
});
expect(response.status).toEqual(400);
});

View file

@ -18,6 +18,7 @@ import {
UserLogType,
UserLogResult,
ConnectorType,
SignInMethodState,
} from '@logto/schemas';
import pick from 'lodash.pick';
@ -155,39 +156,32 @@ export const mockSetting: Setting = {
export const mockSignInExperience: SignInExperience = {
id: 'foo',
companyInfo: {
name: 'logto',
logo: 'http://logto.png',
},
branding: {
primaryColor: '#000',
backgroundColor: '#fff',
darkMode: true,
darkBackgroundColor: '#000',
darkPrimaryColor: '#fff',
style: BrandingStyle.CompanyLogo_AppLogo_CompanyName_AppName,
style: BrandingStyle.Logo,
logoUrl: 'http://logto.png',
slogan: 'logto',
},
termsOfUse: {
enabled: false,
},
forgetPasswordEnabled: true,
localization: {
languageInfo: {
autoDetect: true,
primaryLanguage: Language.chinese,
fallbackLanguage: Language.english,
fixedLanguage: Language.chinese,
},
signInMethods: {
primary: ['email'],
secondary: [],
disabled: [],
username: SignInMethodState.primary,
email: SignInMethodState.disabled,
sms: SignInMethodState.disabled,
social: SignInMethodState.secondary,
},
};
export const mockConnector: Connector = {
id: 'foo',
enabled: true,
config: {},
createdAt: 1_645_334_775_356,
socialSignInConnectorIds: ['foo', 'bar'],
};
export const mockConnectorList: Connector[] = [

View file

@ -10,6 +10,5 @@ export * from './resource';
export * from './role';
export * from './setting';
export * from './sign-in-experience';
export * from './sign-in-method';
export * from './user-log';
export * from './user';

View file

@ -3,48 +3,48 @@
import { z } from 'zod';
import {
CompanyInfo,
companyInfoGuard,
Branding,
brandingGuard,
LanguageInfo,
languageInfoGuard,
TermsOfUse,
termsOfUseGuard,
Localization,
localizationGuard,
SignInMethodSettings,
signInMethodSettingsGuard,
SignInMethods,
signInMethodsGuard,
ConnectorIds,
connectorIdsGuard,
GeneratedSchema,
Guard,
} from '../foundations';
export type CreateSignInExperience = {
id: string;
companyInfo: CompanyInfo;
branding: Branding;
termsOfUse: TermsOfUse;
branding?: Branding;
languageInfo?: LanguageInfo;
termsOfUse?: TermsOfUse;
forgetPasswordEnabled?: boolean;
localization: Localization;
signInMethods: SignInMethodSettings;
signInMethods?: SignInMethods;
socialSignInConnectorIds?: ConnectorIds;
};
export type SignInExperience = {
id: string;
companyInfo: CompanyInfo;
branding: Branding;
languageInfo: LanguageInfo;
termsOfUse: TermsOfUse;
forgetPasswordEnabled: boolean;
localization: Localization;
signInMethods: SignInMethodSettings;
signInMethods: SignInMethods;
socialSignInConnectorIds: ConnectorIds;
};
const createGuard: Guard<CreateSignInExperience> = z.object({
id: z.string(),
companyInfo: companyInfoGuard,
branding: brandingGuard,
termsOfUse: termsOfUseGuard,
branding: brandingGuard.optional(),
languageInfo: languageInfoGuard.optional(),
termsOfUse: termsOfUseGuard.optional(),
forgetPasswordEnabled: z.boolean().optional(),
localization: localizationGuard,
signInMethods: signInMethodSettingsGuard,
signInMethods: signInMethodsGuard.optional(),
socialSignInConnectorIds: connectorIdsGuard.optional(),
});
export const SignInExperiences: GeneratedSchema<CreateSignInExperience> = Object.freeze({
@ -52,21 +52,21 @@ export const SignInExperiences: GeneratedSchema<CreateSignInExperience> = Object
tableSingular: 'sign_in_experience',
fields: {
id: 'id',
companyInfo: 'company_info',
branding: 'branding',
languageInfo: 'language_info',
termsOfUse: 'terms_of_use',
forgetPasswordEnabled: 'forget_password_enabled',
localization: 'localization',
signInMethods: 'sign_in_methods',
socialSignInConnectorIds: 'social_sign_in_connector_ids',
},
fieldKeys: [
'id',
'companyInfo',
'branding',
'languageInfo',
'termsOfUse',
'forgetPasswordEnabled',
'localization',
'signInMethods',
'socialSignInConnectorIds',
],
createGuard,
});

View file

@ -1,35 +0,0 @@
// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
import { z } from 'zod';
import { GeneratedSchema, Guard } from '../foundations';
export type CreateSignInMethod = {
id: string;
name: string;
connectorId?: string | null;
};
export type SignInMethod = {
id: string;
name: string;
connectorId: string | null;
};
const createGuard: Guard<CreateSignInMethod> = z.object({
id: z.string(),
name: z.string(),
connectorId: z.string().nullable().optional(),
});
export const SignInMethods: GeneratedSchema<CreateSignInMethod> = Object.freeze({
table: 'sign_in_methods',
tableSingular: 'sign_in_method',
fields: {
id: 'id',
name: 'name',
connectorId: 'connector_id',
},
fieldKeys: ['id', 'name', 'connectorId'],
createGuard,
});

View file

@ -79,20 +79,12 @@ export const adminConsoleConfigGuard = z.object({
export type AdminConsoleConfig = z.infer<typeof adminConsoleConfigGuard>;
/**
* SignIn Experience
* SignIn Experiences
*/
export const companyInfoGuard = z.object({
name: z.string(),
logo: z.string(),
});
export type CompanyInfo = z.infer<typeof companyInfoGuard>;
export enum BrandingStyle {
CompanyLogo_CompanyName_AppName = 'CompanyLogo_CompanyName_AppName',
CompanyLogo_AppLogo_CompanyName_AppName = 'CompanyLogo_AppLogo_CompanyName_AppName',
AppLogo_CompanyName_AppName = 'AppLogo_CompanyName_AppName',
Logo = 'Logo',
Logo_Slogan = 'Logo_Slogan',
}
export const brandingGuard = z.object({
@ -102,13 +94,14 @@ export const brandingGuard = z.object({
darkPrimaryColor: z.string(),
darkBackgroundColor: z.string(),
style: z.nativeEnum(BrandingStyle),
logoUrl: z.string().optional(),
slogan: z.string().optional(),
});
export type Branding = z.infer<typeof brandingGuard>;
export const termsOfUseGuard = z.object({
enabled: z.boolean(),
content: z.string().optional(),
contentUrl: z.string().optional(),
});
@ -119,21 +112,32 @@ export enum Language {
chinese = 'zh-cn',
}
export const localizationGuard = z.object({
export const languageInfoGuard = z.object({
autoDetect: z.boolean(),
primaryLanguage: z.nativeEnum(Language),
fallbackLanguage: z.nativeEnum(Language),
fixedLanguage: z.nativeEnum(Language),
});
export type Localization = z.infer<typeof localizationGuard>;
export type LanguageInfo = z.infer<typeof languageInfoGuard>;
export const signInMethodSettingsGuard = z.object({
primary: z.string().array().nonempty().max(3),
secondary: z.string().array(),
disabled: z.string().array(),
export enum SignInMethodState {
primary = 'primary',
secondary = 'secondary',
disabled = 'disabled',
}
export const signInMethodsGuard = z.object({
username: z.nativeEnum(SignInMethodState),
email: z.nativeEnum(SignInMethodState),
sms: z.nativeEnum(SignInMethodState),
social: z.nativeEnum(SignInMethodState),
});
export type SignInMethodSettings = z.infer<typeof signInMethodSettingsGuard>;
export type SignInMethods = z.infer<typeof signInMethodsGuard>;
export const connectorIdsGuard = z.string().array();
export type ConnectorIds = z.infer<typeof connectorIdsGuard>;
/**
* Commonly Used

View file

@ -1,10 +1,10 @@
create table sign_in_experiences (
id varchar(128) not null,
company_info jsonb /* @use CompanyInfo */ not null,
branding jsonb /* @use Branding */ not null,
terms_of_use jsonb /* @use TermsOfUse */ not null,
forget_password_enabled boolean not null default(true),
localization jsonb /* @use Localization */ not null,
sign_in_methods jsonb /* @use SignInMethodSettings */ not null,
branding jsonb /* @use Branding */ not null default '{}'::jsonb,
language_info jsonb /* @use LanguageInfo */ not null default '{}'::jsonb,
terms_of_use jsonb /* @use TermsOfUse */ not null default '{}'::jsonb,
forget_password_enabled boolean not null default false,
sign_in_methods jsonb /* @use SignInMethods */ not null default '{}'::jsonb,
social_sign_in_connector_ids jsonb /* @use ConnectorIds */ not null default '[]'::jsonb,
primary key (id)
)
);

View file

@ -1,10 +0,0 @@
create table sign_in_methods (
id varchar(128) not null,
name varchar(128) not null,
connector_id varchar(128),
primary key (id),
constraint fk__sign_in_methods__connector_id
foreign key (connector_id)
references connectors(id)
on delete cascade
)