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:
parent
b5fce550fc
commit
a3b5b55281
4 changed files with 81 additions and 8 deletions
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -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(),
|
||||
});
|
||||
|
|
|
@ -28,7 +28,8 @@ export default class Libraries {
|
|||
signInExperiences = createSignInExperienceLibrary(
|
||||
this.queries,
|
||||
this.connectors,
|
||||
this.ssoConnector
|
||||
this.ssoConnector,
|
||||
this.cloudConnection
|
||||
);
|
||||
|
||||
constructor(
|
||||
|
|
Loading…
Reference in a new issue