0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-01-06 20:40:08 -05:00

feat(core): add isDevelopmentTenant to SIE well-known api (#4825)

This commit is contained in:
wangsijie 2023-11-07 04:30:20 -05:00 committed by GitHub
parent b5fce550fc
commit a3b5b55281
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 81 additions and 8 deletions

View file

@ -12,6 +12,7 @@ import {
import RequestError from '#src/errors/RequestError/index.js';
import { ssoConnectorFactories } from '#src/sso/index.js';
import { createCloudConnectionLibrary } from '../cloud-connection.js';
import { createConnectorLibrary } from '../connector.js';
const { jest } = import.meta;
@ -49,12 +50,20 @@ const queries = new MockQueries({
const connectorLibrary = createConnectorLibrary(queries, {
getClient: jest.fn(),
});
const cloudConnection = createCloudConnectionLibrary({
getCloudConnectionData: jest.fn().mockResolvedValue({
appId: 'appId',
appSecret: 'appSecret',
resource: 'resource',
}),
getOidcConfigs: jest.fn(),
});
const getLogtoConnectors = jest.spyOn(connectorLibrary, 'getLogtoConnectors');
const { createSignInExperienceLibrary } = await import('./index.js');
const { validateLanguageInfo, removeUnavailableSocialConnectorTargets, getFullSignInExperience } =
createSignInExperienceLibrary(queries, connectorLibrary, ssoConnectorLibrary);
createSignInExperienceLibrary(queries, connectorLibrary, ssoConnectorLibrary, cloudConnection);
beforeEach(() => {
jest.clearAllMocks();
@ -129,6 +138,37 @@ describe('remove unavailable social connector targets', () => {
});
});
describe('getFullSignInExperience()', () => {
it('should return full sign-in experience', async () => {
findDefaultSignInExperience.mockResolvedValueOnce(mockSignInExperience);
getLogtoConnectors.mockResolvedValueOnce(mockSocialConnectors);
ssoConnectorLibrary.getAvailableSsoConnectors.mockResolvedValueOnce([
wellConfiguredSsoConnector,
]);
const fullSignInExperience = await getFullSignInExperience();
expect(fullSignInExperience).toStrictEqual({
...mockSignInExperience,
socialConnectors: [],
socialSignInConnectorTargets: ['github', 'facebook', 'wechat'],
forgotPassword: {
email: false,
phone: false,
},
ssoConnectors: [
{
id: wellConfiguredSsoConnector.id,
connectorName: wellConfiguredSsoConnector.connectorName,
logo: ssoConnectorFactories[wellConfiguredSsoConnector.providerName].logo,
darkLogo: undefined,
},
],
isDevelopmentTenant: false,
});
});
});
describe('get sso connectors', () => {
it('should return sso connectors metadata', async () => {
getLogtoConnectors.mockResolvedValueOnce(mockSocialConnectors);

View file

@ -10,18 +10,24 @@ import type { SsoConnectorLibrary } from '#src/libraries/sso-connector.js';
import { ssoConnectorFactories } from '#src/sso/index.js';
import type Queries from '#src/tenants/Queries.js';
import assertThat from '#src/utils/assert-that.js';
import { getTenantSubscriptionPlan } from '#src/utils/subscription/index.js';
import { type CloudConnectionLibrary } from '../cloud-connection.js';
import { type FullSignInExperience } from './types.js';
export * from './sign-up.js';
export * from './sign-in.js';
export const developmentTenantPlanId = 'dev-tenant';
export type SignInExperienceLibrary = ReturnType<typeof createSignInExperienceLibrary>;
export const createSignInExperienceLibrary = (
queries: Queries,
{ getLogtoConnectors }: ConnectorLibrary,
{ getAvailableSsoConnectors }: SsoConnectorLibrary
{ getAvailableSsoConnectors }: SsoConnectorLibrary,
cloudConnection: CloudConnectionLibrary
) => {
const {
customPhrases: { findAllCustomLanguageTags },
@ -79,12 +85,35 @@ export const createSignInExperienceLibrary = (
);
};
/**
* Query the tenant subscription plan to determine if the tenant is a development tenant.
*/
const getIsDevelopmentTenant = async (): Promise<boolean> => {
const { isCloud, isIntegrationTest } = EnvSet.values;
// Cloud only feature, return false in non-cloud environments
if (!isCloud) {
return false;
}
// Disable in integration tests
if (isIntegrationTest) {
return false;
}
const plan = await getTenantSubscriptionPlan(cloudConnection);
return plan.id === developmentTenantPlanId;
};
const getFullSignInExperience = async (): Promise<FullSignInExperience> => {
const [signInExperience, logtoConnectors, ssoConnectors] = await Promise.all([
findDefaultSignInExperience(),
getLogtoConnectors(),
getActiveSsoConnectors(),
]);
const [signInExperience, logtoConnectors, ssoConnectors, isDevelopmentTenant] =
await Promise.all([
findDefaultSignInExperience(),
getLogtoConnectors(),
getActiveSsoConnectors(),
getIsDevelopmentTenant(),
]);
const forgotPassword = {
phone: logtoConnectors.some(({ type }) => type === ConnectorType.Sms),
@ -109,6 +138,7 @@ export const createSignInExperienceLibrary = (
socialConnectors,
ssoConnectors,
forgotPassword,
isDevelopmentTenant,
};
};

View file

@ -18,6 +18,7 @@ export type FullSignInExperience = SignInExperience & {
socialConnectors: ConnectorMetadataWithId[];
ssoConnectors: SsoConnectorMetadata[];
forgotPassword: ForgotPassword;
isDevelopmentTenant: boolean;
};
export const guardFullSignInExperience: z.ZodType<FullSignInExperience> =
@ -25,4 +26,5 @@ export const guardFullSignInExperience: z.ZodType<FullSignInExperience> =
socialConnectors: connectorMetadataGuard.extend({ id: z.string() }).array(),
ssoConnectors: ssoConnectorMetadataGuard.array(),
forgotPassword: z.object({ phone: z.boolean(), email: z.boolean() }),
isDevelopmentTenant: z.boolean(),
});

View file

@ -28,7 +28,8 @@ export default class Libraries {
signInExperiences = createSignInExperienceLibrary(
this.queries,
this.connectors,
this.ssoConnector
this.ssoConnector,
this.cloudConnection
);
constructor(