mirror of
https://github.com/logto-io/logto.git
synced 2025-03-03 22:15:32 -05:00
refactor(core): migrate connector library to factory mode
This commit is contained in:
parent
d0a81e76a8
commit
3b3b35b883
18 changed files with 238 additions and 239 deletions
|
@ -1,10 +1,7 @@
|
|||
import type { Connector } from '@logto/schemas';
|
||||
import { createMockUtils } from '@logto/shared/esm';
|
||||
|
||||
import RequestError from '#src/errors/RequestError/index.js';
|
||||
|
||||
const { jest } = import.meta;
|
||||
const { mockEsmWithActual } = createMockUtils(jest);
|
||||
import { MockQueries } from '#src/test-utils/tenant.js';
|
||||
|
||||
const connectors: Connector[] = [
|
||||
{
|
||||
|
@ -17,11 +14,10 @@ const connectors: Connector[] = [
|
|||
},
|
||||
];
|
||||
|
||||
await mockEsmWithActual('#src/queries/connector.js', () => ({
|
||||
findAllConnectors: jest.fn(async () => connectors),
|
||||
}));
|
||||
|
||||
const { getConnectorConfig } = await import('./connector.js');
|
||||
const { createConnectorLibrary } = await import('./connector.js');
|
||||
const { getConnectorConfig } = createConnectorLibrary(
|
||||
new MockQueries({ connectors: { findAllConnectors: async () => connectors } })
|
||||
);
|
||||
|
||||
it('getConnectorConfig() should return right config', async () => {
|
||||
const config = await getConnectorConfig('id');
|
||||
|
|
|
@ -2,85 +2,102 @@ import type { AllConnector } from '@logto/connector-kit';
|
|||
import { validateConfig } from '@logto/connector-kit';
|
||||
|
||||
import RequestError from '#src/errors/RequestError/index.js';
|
||||
import { findAllConnectors } from '#src/queries/connector.js';
|
||||
import type Queries from '#src/tenants/Queries.js';
|
||||
import assertThat from '#src/utils/assert-that.js';
|
||||
import { defaultConnectorMethods } from '#src/utils/connectors/consts.js';
|
||||
import { loadConnectorFactories } from '#src/utils/connectors/factories.js';
|
||||
import { validateConnectorModule, parseMetadata } from '#src/utils/connectors/index.js';
|
||||
import type { LogtoConnector } from '#src/utils/connectors/types.js';
|
||||
|
||||
export const getConnectorConfig = async (id: string): Promise<unknown> => {
|
||||
const connectors = await findAllConnectors();
|
||||
const connector = connectors.find((connector) => connector.id === id);
|
||||
import { defaultQueries } from './shared.js';
|
||||
|
||||
assertThat(connector, new RequestError({ code: 'entity.not_found', id, status: 404 }));
|
||||
export type ConnectorLibrary = ReturnType<typeof createConnectorLibrary>;
|
||||
|
||||
return connector.config;
|
||||
export const createConnectorLibrary = (queries: Queries) => {
|
||||
const { findAllConnectors } = queries.connectors;
|
||||
|
||||
const getConnectorConfig = async (id: string): Promise<unknown> => {
|
||||
const connectors = await findAllConnectors();
|
||||
const connector = connectors.find((connector) => connector.id === id);
|
||||
|
||||
assertThat(connector, new RequestError({ code: 'entity.not_found', id, status: 404 }));
|
||||
|
||||
return connector.config;
|
||||
};
|
||||
|
||||
const getLogtoConnectors = async (): Promise<LogtoConnector[]> => {
|
||||
const databaseConnectors = await findAllConnectors();
|
||||
|
||||
const logtoConnectors = await Promise.all(
|
||||
databaseConnectors.map(async (databaseConnector) => {
|
||||
const { id, metadata, connectorId } = databaseConnector;
|
||||
|
||||
const connectorFactories = await loadConnectorFactories();
|
||||
const connectorFactory = connectorFactories.find(
|
||||
({ metadata }) => metadata.id === connectorId
|
||||
);
|
||||
|
||||
if (!connectorFactory) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { createConnector, path: packagePath } = connectorFactory;
|
||||
|
||||
try {
|
||||
const rawConnector = await createConnector({
|
||||
getConfig: async () => {
|
||||
return getConnectorConfig(id);
|
||||
},
|
||||
});
|
||||
validateConnectorModule(rawConnector);
|
||||
const rawMetadata = await parseMetadata(rawConnector.metadata, packagePath);
|
||||
|
||||
const connector: AllConnector = {
|
||||
...defaultConnectorMethods,
|
||||
...rawConnector,
|
||||
metadata: {
|
||||
...rawMetadata,
|
||||
...metadata,
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
...connector,
|
||||
validateConfig: (config: unknown) => {
|
||||
validateConfig(config, rawConnector.configGuard);
|
||||
},
|
||||
dbEntry: databaseConnector,
|
||||
};
|
||||
} catch {}
|
||||
})
|
||||
);
|
||||
|
||||
return logtoConnectors.filter(
|
||||
(logtoConnector): logtoConnector is LogtoConnector => logtoConnector !== undefined
|
||||
);
|
||||
};
|
||||
|
||||
const getLogtoConnectorById = async (id: string): Promise<LogtoConnector> => {
|
||||
const connectors = await getLogtoConnectors();
|
||||
const pickedConnector = connectors.find(({ dbEntry }) => dbEntry.id === id);
|
||||
|
||||
if (!pickedConnector) {
|
||||
throw new RequestError({
|
||||
code: 'entity.not_found',
|
||||
id,
|
||||
status: 404,
|
||||
});
|
||||
}
|
||||
|
||||
return pickedConnector;
|
||||
};
|
||||
|
||||
return { getConnectorConfig, getLogtoConnectors, getLogtoConnectorById };
|
||||
};
|
||||
|
||||
export const getLogtoConnectors = async (): Promise<LogtoConnector[]> => {
|
||||
const databaseConnectors = await findAllConnectors();
|
||||
/** @deprecated Don't use. This is for transition only and will be removed soon. */
|
||||
export const defaultConnectorLibrary = createConnectorLibrary(defaultQueries);
|
||||
|
||||
const logtoConnectors = await Promise.all(
|
||||
databaseConnectors.map(async (databaseConnector) => {
|
||||
const { id, metadata, connectorId } = databaseConnector;
|
||||
|
||||
const connectorFactories = await loadConnectorFactories();
|
||||
const connectorFactory = connectorFactories.find(
|
||||
({ metadata }) => metadata.id === connectorId
|
||||
);
|
||||
|
||||
if (!connectorFactory) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { createConnector, path: packagePath } = connectorFactory;
|
||||
|
||||
try {
|
||||
const rawConnector = await createConnector({
|
||||
getConfig: async () => {
|
||||
return getConnectorConfig(id);
|
||||
},
|
||||
});
|
||||
validateConnectorModule(rawConnector);
|
||||
const rawMetadata = await parseMetadata(rawConnector.metadata, packagePath);
|
||||
|
||||
const connector: AllConnector = {
|
||||
...defaultConnectorMethods,
|
||||
...rawConnector,
|
||||
metadata: {
|
||||
...rawMetadata,
|
||||
...metadata,
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
...connector,
|
||||
validateConfig: (config: unknown) => {
|
||||
validateConfig(config, rawConnector.configGuard);
|
||||
},
|
||||
dbEntry: databaseConnector,
|
||||
};
|
||||
} catch {}
|
||||
})
|
||||
);
|
||||
|
||||
return logtoConnectors.filter(
|
||||
(logtoConnector): logtoConnector is LogtoConnector => logtoConnector !== undefined
|
||||
);
|
||||
};
|
||||
|
||||
export const getLogtoConnectorById = async (id: string): Promise<LogtoConnector> => {
|
||||
const connectors = await getLogtoConnectors();
|
||||
const pickedConnector = connectors.find(({ dbEntry }) => dbEntry.id === id);
|
||||
|
||||
if (!pickedConnector) {
|
||||
throw new RequestError({
|
||||
code: 'entity.not_found',
|
||||
id,
|
||||
status: 404,
|
||||
});
|
||||
}
|
||||
|
||||
return pickedConnector;
|
||||
};
|
||||
/** @deprecated Don't use. This is for transition only and will be removed soon. */
|
||||
export const { getConnectorConfig, getLogtoConnectors, getLogtoConnectorById } =
|
||||
defaultConnectorLibrary;
|
||||
|
|
|
@ -2,7 +2,6 @@ import type { LanguageTag } from '@logto/language-kit';
|
|||
import { builtInLanguages } from '@logto/phrases-ui';
|
||||
import type { CreateSignInExperience, SignInExperience } from '@logto/schemas';
|
||||
import { BrandingStyle } from '@logto/schemas';
|
||||
import { createMockUtils } from '@logto/shared/esm';
|
||||
|
||||
import {
|
||||
socialTarget01,
|
||||
|
@ -13,8 +12,9 @@ import {
|
|||
} from '#src/__mocks__/index.js';
|
||||
import RequestError from '#src/errors/RequestError/index.js';
|
||||
|
||||
import { createConnectorLibrary } from '../connector.js';
|
||||
|
||||
const { jest } = import.meta;
|
||||
const { mockEsm } = createMockUtils(jest);
|
||||
|
||||
const allCustomLanguageTags: LanguageTag[] = [];
|
||||
|
||||
|
@ -23,10 +23,6 @@ const customPhrases = {
|
|||
};
|
||||
const { findAllCustomLanguageTags } = customPhrases;
|
||||
|
||||
const { getLogtoConnectors } = mockEsm('#src/libraries/connector.js', () => ({
|
||||
getLogtoConnectors: jest.fn(),
|
||||
}));
|
||||
|
||||
const signInExperiences = {
|
||||
findDefaultSignInExperience: jest.fn(),
|
||||
updateDefaultSignInExperience: jest.fn(
|
||||
|
@ -43,10 +39,12 @@ const queries = new MockQueries({
|
|||
customPhrases,
|
||||
signInExperiences,
|
||||
});
|
||||
const connectorLibrary = createConnectorLibrary(queries);
|
||||
const getLogtoConnectors = jest.spyOn(connectorLibrary, 'getLogtoConnectors');
|
||||
|
||||
const { validateBranding, createSignInExperienceLibrary } = await import('./index.js');
|
||||
const { validateLanguageInfo, removeUnavailableSocialConnectorTargets } =
|
||||
createSignInExperienceLibrary(queries);
|
||||
createSignInExperienceLibrary(queries, connectorLibrary);
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
|
|
@ -12,7 +12,8 @@ import { deduplicate } from '@silverhand/essentials';
|
|||
import i18next from 'i18next';
|
||||
|
||||
import RequestError from '#src/errors/RequestError/index.js';
|
||||
import { getLogtoConnectors } from '#src/libraries/connector.js';
|
||||
import type { ConnectorLibrary } from '#src/libraries/connector.js';
|
||||
import { defaultConnectorLibrary } from '#src/libraries/connector.js';
|
||||
import type Queries from '#src/tenants/Queries.js';
|
||||
import assertThat from '#src/utils/assert-that.js';
|
||||
|
||||
|
@ -29,7 +30,10 @@ export const validateBranding = (branding: Branding) => {
|
|||
assertThat(branding.logoUrl.trim(), 'sign_in_experiences.empty_logo');
|
||||
};
|
||||
|
||||
export const createSignInExperienceLibrary = (queries: Queries) => {
|
||||
export const createSignInExperienceLibrary = (
|
||||
queries: Queries,
|
||||
connectorLibrary: ConnectorLibrary
|
||||
) => {
|
||||
const {
|
||||
customPhrases: { findAllCustomLanguageTags },
|
||||
signInExperiences: { findDefaultSignInExperience, updateDefaultSignInExperience },
|
||||
|
@ -49,7 +53,7 @@ export const createSignInExperienceLibrary = (queries: Queries) => {
|
|||
};
|
||||
|
||||
const removeUnavailableSocialConnectorTargets = async () => {
|
||||
const connectors = await getLogtoConnectors();
|
||||
const connectors = await connectorLibrary.getLogtoConnectors();
|
||||
const availableSocialConnectorTargets = deduplicate(
|
||||
connectors
|
||||
.filter(({ type }) => type === ConnectorType.Social)
|
||||
|
@ -113,4 +117,4 @@ export const {
|
|||
validateLanguageInfo,
|
||||
removeUnavailableSocialConnectorTargets,
|
||||
getSignInExperienceForApplication,
|
||||
} = createSignInExperienceLibrary(defaultQueries);
|
||||
} = createSignInExperienceLibrary(defaultQueries, defaultConnectorLibrary);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { UsersPasswordEncryptionMethod } from '@logto/schemas';
|
||||
import { createMockPool } from 'slonik';
|
||||
|
||||
import Queries from '#src/tenants/Queries.js';
|
||||
import { MockQueries } from '#src/test-utils/tenant.js';
|
||||
|
||||
const { jest } = import.meta;
|
||||
|
||||
|
@ -11,9 +11,8 @@ const pool = createMockPool({
|
|||
|
||||
const { encryptUserPassword, createUserLibrary } = await import('./user.js');
|
||||
|
||||
const queries = new Queries(pool);
|
||||
|
||||
const hasUserWithId = jest.spyOn(queries.users, 'hasUserWithId');
|
||||
const hasUserWithId = jest.fn();
|
||||
const queries = new MockQueries({ users: { hasUserWithId } });
|
||||
|
||||
describe('generateUserId()', () => {
|
||||
const { generateUserId } = createUserLibrary(queries);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* eslint-disable max-lines */
|
||||
import type { EmailConnector, SmsConnector } from '@logto/connector-kit';
|
||||
import { ConnectorPlatform, VerificationCodeType } from '@logto/connector-kit';
|
||||
import type { Connector } from '@logto/schemas';
|
||||
import { ConnectorType } from '@logto/schemas';
|
||||
import { pickDefault, createMockUtils } from '@logto/shared/esm';
|
||||
import { any } from 'zod';
|
||||
|
@ -17,6 +18,8 @@ import {
|
|||
mockLogtoConnector,
|
||||
} from '#src/__mocks__/index.js';
|
||||
import RequestError from '#src/errors/RequestError/index.js';
|
||||
import Queries from '#src/tenants/Queries.js';
|
||||
import { MockTenant } from '#src/test-utils/tenant.js';
|
||||
import assertThat from '#src/utils/assert-that.js';
|
||||
import { defaultConnectorMethods } from '#src/utils/connectors/consts.js';
|
||||
import type { LogtoConnector } from '#src/utils/connectors/types.js';
|
||||
|
@ -29,26 +32,22 @@ mockEsm('#src/utils/connectors/platform.js', () => ({
|
|||
checkSocialConnectorTargetAndPlatformUniqueness: jest.fn(),
|
||||
}));
|
||||
|
||||
const { removeUnavailableSocialConnectorTargets } = mockEsm(
|
||||
'#src/libraries/sign-in-experience/index.js',
|
||||
() => ({
|
||||
removeUnavailableSocialConnectorTargets: jest.fn(),
|
||||
})
|
||||
);
|
||||
const removeUnavailableSocialConnectorTargets = jest.fn();
|
||||
|
||||
const connectorQueries = {
|
||||
findConnectorById: jest.fn(),
|
||||
countConnectorByConnectorId: jest.fn(),
|
||||
deleteConnectorById: jest.fn(),
|
||||
deleteConnectorByIds: jest.fn(),
|
||||
insertConnector: jest.fn(async (body) => body as Connector),
|
||||
} satisfies Partial<Queries['connectors']>;
|
||||
const {
|
||||
findConnectorById,
|
||||
countConnectorByConnectorId,
|
||||
deleteConnectorById,
|
||||
deleteConnectorByIds,
|
||||
insertConnector,
|
||||
} = await mockEsmWithActual('#src/queries/connector.js', () => ({
|
||||
findConnectorById: jest.fn(),
|
||||
countConnectorByConnectorId: jest.fn(),
|
||||
deleteConnectorById: jest.fn(),
|
||||
deleteConnectorByIds: jest.fn(),
|
||||
insertConnector: jest.fn(async (body: unknown) => body),
|
||||
}));
|
||||
} = connectorQueries;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
const getLogtoConnectors = jest.fn<Promise<LogtoConnector[]>, []>();
|
||||
|
@ -57,27 +56,35 @@ const { loadConnectorFactories } = mockEsm('#src/utils/connectors/factories.js',
|
|||
loadConnectorFactories: jest.fn(),
|
||||
}));
|
||||
|
||||
mockEsm('#src/libraries/connector.js', () => ({
|
||||
getLogtoConnectors,
|
||||
getLogtoConnectorById: async (connectorId: string) => {
|
||||
const connectors = await getLogtoConnectors();
|
||||
const connector = connectors.find(({ dbEntry }) => dbEntry.id === connectorId);
|
||||
assertThat(
|
||||
connector,
|
||||
new RequestError({
|
||||
code: 'entity.not_found',
|
||||
connectorId,
|
||||
status: 404,
|
||||
})
|
||||
);
|
||||
const tenantContext = new MockTenant(
|
||||
undefined,
|
||||
{ connectors: connectorQueries },
|
||||
{
|
||||
signInExperiences: { removeUnavailableSocialConnectorTargets },
|
||||
connectors: {
|
||||
getLogtoConnectors,
|
||||
getLogtoConnectorById: async (connectorId: string) => {
|
||||
const connectors = await getLogtoConnectors();
|
||||
const connector = connectors.find(({ dbEntry }) => dbEntry.id === connectorId);
|
||||
assertThat(
|
||||
connector,
|
||||
new RequestError({
|
||||
code: 'entity.not_found',
|
||||
connectorId,
|
||||
status: 404,
|
||||
})
|
||||
);
|
||||
|
||||
return connector;
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
return connector;
|
||||
},
|
||||
}));
|
||||
const connectorRoutes = await pickDefault(import('./connector.js'));
|
||||
|
||||
describe('connector route', () => {
|
||||
const connectorRequest = createRequester({ authedRoutes: connectorRoutes });
|
||||
const connectorRequest = createRequester({ authedRoutes: connectorRoutes, tenantContext });
|
||||
|
||||
describe('GET /connectors', () => {
|
||||
afterEach(() => {
|
||||
|
|
|
@ -6,17 +6,7 @@ import cleanDeep from 'clean-deep';
|
|||
import { object, string } from 'zod';
|
||||
|
||||
import RequestError from '#src/errors/RequestError/index.js';
|
||||
import { getLogtoConnectorById, getLogtoConnectors } from '#src/libraries/connector.js';
|
||||
import { removeUnavailableSocialConnectorTargets } from '#src/libraries/sign-in-experience/index.js';
|
||||
import koaGuard from '#src/middleware/koa-guard.js';
|
||||
import {
|
||||
findConnectorById,
|
||||
countConnectorByConnectorId,
|
||||
deleteConnectorById,
|
||||
deleteConnectorByIds,
|
||||
insertConnector,
|
||||
updateConnector,
|
||||
} from '#src/queries/connector.js';
|
||||
import assertThat from '#src/utils/assert-that.js';
|
||||
import { loadConnectorFactories } from '#src/utils/connectors/factories.js';
|
||||
import { checkSocialConnectorTargetAndPlatformUniqueness } from '#src/utils/connectors/platform.js';
|
||||
|
@ -36,7 +26,22 @@ const transpileLogtoConnector = ({
|
|||
|
||||
const generateConnectorId = buildIdGenerator(12);
|
||||
|
||||
export default function connectorRoutes<T extends AuthedRouter>(...[router]: RouterInitArgs<T>) {
|
||||
export default function connectorRoutes<T extends AuthedRouter>(
|
||||
...[router, { queries, libraries }]: RouterInitArgs<T>
|
||||
) {
|
||||
const {
|
||||
findConnectorById,
|
||||
countConnectorByConnectorId,
|
||||
deleteConnectorById,
|
||||
deleteConnectorByIds,
|
||||
insertConnector,
|
||||
updateConnector,
|
||||
} = queries.connectors;
|
||||
const {
|
||||
connectors: { getLogtoConnectorById, getLogtoConnectors },
|
||||
signInExperiences: { removeUnavailableSocialConnectorTargets },
|
||||
} = libraries;
|
||||
|
||||
router.get(
|
||||
'/connectors',
|
||||
koaGuard({
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { ConnectorError, ConnectorErrorCodes } from '@logto/connector-kit';
|
||||
import { ConnectorType } from '@logto/schemas';
|
||||
import { pickDefault, createMockUtils } from '@logto/shared/esm';
|
||||
import { pickDefault } from '@logto/shared/esm';
|
||||
|
||||
import {
|
||||
mockMetadata,
|
||||
|
@ -9,53 +9,56 @@ import {
|
|||
mockLogtoConnector,
|
||||
} from '#src/__mocks__/index.js';
|
||||
import RequestError from '#src/errors/RequestError/index.js';
|
||||
import { MockTenant } from '#src/test-utils/tenant.js';
|
||||
import assertThat from '#src/utils/assert-that.js';
|
||||
import type { LogtoConnector } from '#src/utils/connectors/types.js';
|
||||
import { createRequester } from '#src/utils/test-utils.js';
|
||||
|
||||
const { jest } = import.meta;
|
||||
const { mockEsm, mockEsmWithActual } = createMockUtils(jest);
|
||||
|
||||
const getLogtoConnectors = jest.fn() as jest.MockedFunction<() => Promise<LogtoConnector[]>>;
|
||||
const getLogtoConnectorById = jest.fn(async (connectorId: string) => {
|
||||
const connectors = await getLogtoConnectors();
|
||||
const connector = connectors.find(({ dbEntry }) => dbEntry.id === connectorId);
|
||||
const getLogtoConnectors: jest.MockedFunction<() => Promise<LogtoConnector[]>> = jest.fn();
|
||||
const getLogtoConnectorById: jest.MockedFunction<(connectorId: string) => Promise<LogtoConnector>> =
|
||||
jest.fn(async (connectorId: string) => {
|
||||
const connectors = await getLogtoConnectors();
|
||||
const connector = connectors.find(({ dbEntry }) => dbEntry.id === connectorId);
|
||||
|
||||
assertThat(
|
||||
connector,
|
||||
new RequestError({
|
||||
code: 'entity.not_found',
|
||||
connectorId,
|
||||
status: 404,
|
||||
})
|
||||
);
|
||||
assertThat(
|
||||
connector,
|
||||
new RequestError({
|
||||
code: 'entity.not_found',
|
||||
connectorId,
|
||||
status: 404,
|
||||
})
|
||||
);
|
||||
|
||||
return {
|
||||
...connector,
|
||||
sendMessage: sendMessagePlaceHolder,
|
||||
};
|
||||
}) as jest.MockedFunction<(connectorId: string) => Promise<LogtoConnector>>;
|
||||
return {
|
||||
...connector,
|
||||
sendMessage: sendMessagePlaceHolder,
|
||||
};
|
||||
});
|
||||
|
||||
const sendMessagePlaceHolder = jest.fn();
|
||||
const updateConnector = jest.fn();
|
||||
|
||||
const { updateConnector } = await mockEsmWithActual('#src/queries/connector.js', () => ({
|
||||
updateConnector: jest.fn(),
|
||||
}));
|
||||
|
||||
await mockEsmWithActual('#src/libraries/connector.js', () => ({
|
||||
getLogtoConnectors,
|
||||
getLogtoConnectorById,
|
||||
}));
|
||||
|
||||
mockEsm('#src/libraries/sign-in-experience.js', () => ({
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
removeUnavailableSocialConnectorTargets: async () => {},
|
||||
}));
|
||||
const tenantContext = new MockTenant(
|
||||
undefined,
|
||||
{ connectors: { updateConnector } },
|
||||
{
|
||||
connectors: {
|
||||
getLogtoConnectors,
|
||||
getLogtoConnectorById,
|
||||
},
|
||||
signInExperiences: {
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
removeUnavailableSocialConnectorTargets: async () => {},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const connectorRoutes = await pickDefault(import('./connector.js'));
|
||||
|
||||
describe('connector PATCH routes', () => {
|
||||
const connectorRequest = createRequester({ authedRoutes: connectorRoutes });
|
||||
const connectorRequest = createRequester({ authedRoutes: connectorRoutes, tenantContext });
|
||||
|
||||
describe('PATCH /connectors/:id', () => {
|
||||
afterEach(() => {
|
||||
|
|
|
@ -3,7 +3,7 @@ import type { SocialUserInfo } from '@logto/connector-kit';
|
|||
import type { User } from '@logto/schemas';
|
||||
import Provider from 'oidc-provider';
|
||||
|
||||
import { mockLogtoConnectorList, mockSignInExperience, mockUser } from '#src/__mocks__/index.js';
|
||||
import { mockSignInExperience, mockUser } from '#src/__mocks__/index.js';
|
||||
import RequestError from '#src/errors/RequestError/index.js';
|
||||
import { getLogtoConnectorById } from '#src/libraries/connector.js';
|
||||
import { createRequester } from '#src/utils/test-utils.js';
|
||||
|
@ -91,7 +91,6 @@ const getLogtoConnectorByIdHelper = jest.fn(async (connectorId: string) => {
|
|||
});
|
||||
|
||||
jest.mock('#src/libraries/connector.js', () => ({
|
||||
getLogtoConnectors: jest.fn(async () => mockLogtoConnectorList),
|
||||
getLogtoConnectorById: jest.fn(async (connectorId: string) => {
|
||||
const connector = await getLogtoConnectorByIdHelper(connectorId);
|
||||
|
||||
|
|
|
@ -1,17 +1,11 @@
|
|||
import type { CreateSignInExperience, SignInExperience } from '@logto/schemas';
|
||||
import { BrandingStyle } from '@logto/schemas';
|
||||
import { pickDefault, createMockUtils } from '@logto/shared/esm';
|
||||
import { pickDefault } from '@logto/shared/esm';
|
||||
|
||||
import { mockBranding, mockSignInExperience } from '#src/__mocks__/index.js';
|
||||
import { MockTenant } from '#src/test-utils/tenant.js';
|
||||
import { createRequester } from '#src/utils/test-utils.js';
|
||||
|
||||
const { mockEsm } = createMockUtils(import.meta.jest);
|
||||
|
||||
mockEsm('#src/libraries/connector.js', () => ({
|
||||
getLogtoConnectors: async () => [],
|
||||
}));
|
||||
|
||||
const tenantContext = new MockTenant(undefined, {
|
||||
signInExperiences: {
|
||||
updateDefaultSignInExperience: async (
|
||||
|
|
|
@ -7,10 +7,6 @@ import { createRequester } from '#src/utils/test-utils.js';
|
|||
|
||||
const { mockEsm } = createMockUtils(import.meta.jest);
|
||||
|
||||
mockEsm('#src/libraries/connector.js', () => ({
|
||||
getLogtoConnectors: async () => [],
|
||||
}));
|
||||
|
||||
const signInExperiencesRoutes = await pickDefault(import('./index.js'));
|
||||
const signInExperienceRequester = createRequester({
|
||||
authedRoutes: signInExperiencesRoutes,
|
||||
|
|
|
@ -1,29 +1,10 @@
|
|||
import type { CreateSignInExperience, SignInExperience } from '@logto/schemas';
|
||||
import { pickDefault, createMockUtils } from '@logto/shared/esm';
|
||||
import { pickDefault } from '@logto/shared/esm';
|
||||
|
||||
import {
|
||||
mockAliyunDmConnector,
|
||||
mockAliyunSmsConnector,
|
||||
mockFacebookConnector,
|
||||
mockGithubConnector,
|
||||
mockGoogleConnector,
|
||||
mockLanguageInfo,
|
||||
mockSignInExperience,
|
||||
} from '#src/__mocks__/index.js';
|
||||
import { mockLanguageInfo, mockSignInExperience } from '#src/__mocks__/index.js';
|
||||
import { MockTenant } from '#src/test-utils/tenant.js';
|
||||
|
||||
const { jest } = import.meta;
|
||||
const { mockEsm } = createMockUtils(jest);
|
||||
|
||||
mockEsm('#src/libraries/connector.js', () => ({
|
||||
getLogtoConnectors: jest.fn(async () => [
|
||||
mockAliyunDmConnector,
|
||||
mockAliyunSmsConnector,
|
||||
mockFacebookConnector,
|
||||
mockGithubConnector,
|
||||
mockGoogleConnector,
|
||||
]),
|
||||
}));
|
||||
|
||||
const validateLanguageInfo = jest.fn();
|
||||
|
||||
|
|
|
@ -29,10 +29,6 @@ const logtoConnectors = [
|
|||
mockAliyunSmsConnector,
|
||||
];
|
||||
|
||||
await mockEsmWithActual('#src/libraries/connector.js', () => ({
|
||||
getLogtoConnectors: async () => logtoConnectors,
|
||||
}));
|
||||
|
||||
const { validateBranding, validateSignIn, validateSignUp } = await mockEsmWithActual(
|
||||
'#src/libraries/sign-in-experience/index.js',
|
||||
() => ({
|
||||
|
@ -58,7 +54,10 @@ const validateLanguageInfo = jest.fn();
|
|||
const tenantContext = new MockTenant(
|
||||
undefined,
|
||||
{ signInExperiences, customPhrases: { findAllCustomLanguageTags: async () => [] } },
|
||||
{ signInExperiences: { validateLanguageInfo } }
|
||||
{
|
||||
signInExperiences: { validateLanguageInfo },
|
||||
connectors: { getLogtoConnectors: async () => logtoConnectors },
|
||||
}
|
||||
);
|
||||
|
||||
const signInExperiencesRoutes = await pickDefault(import('./index.js'));
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { ConnectorType, SignInExperiences } from '@logto/schemas';
|
||||
import { literal, object, string } from 'zod';
|
||||
|
||||
import { getLogtoConnectors } from '#src/libraries/connector.js';
|
||||
import {
|
||||
validateBranding,
|
||||
validateSignUp,
|
||||
|
@ -15,7 +14,10 @@ export default function signInExperiencesRoutes<T extends AuthedRouter>(
|
|||
...[router, { queries, libraries }]: RouterInitArgs<T>
|
||||
) {
|
||||
const { findDefaultSignInExperience, updateDefaultSignInExperience } = queries.signInExperiences;
|
||||
const { validateLanguageInfo } = libraries.signInExperiences;
|
||||
const {
|
||||
signInExperiences: { validateLanguageInfo },
|
||||
connectors: { getLogtoConnectors },
|
||||
} = libraries;
|
||||
|
||||
/**
|
||||
* As we only support single signInExperience settings for V1
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
} from '#src/__mocks__/index.js';
|
||||
|
||||
const { jest } = import.meta;
|
||||
const { mockEsm, mockEsmWithActual } = createMockUtils(jest);
|
||||
const { mockEsmWithActual } = createMockUtils(jest);
|
||||
|
||||
await mockEsmWithActual('i18next', () => ({
|
||||
default: {
|
||||
|
@ -31,18 +31,6 @@ const sieQueries = {
|
|||
};
|
||||
const { findDefaultSignInExperience } = sieQueries;
|
||||
|
||||
mockEsm('#src/libraries/connector.js', () => ({
|
||||
getLogtoConnectors: jest.fn(async () => [
|
||||
mockAliyunDmConnector,
|
||||
mockAliyunSmsConnector,
|
||||
mockFacebookConnector,
|
||||
mockGithubConnector,
|
||||
mockGoogleConnector,
|
||||
mockWechatConnector,
|
||||
mockWechatNativeConnector,
|
||||
]),
|
||||
}));
|
||||
|
||||
const wellKnownRoutes = await pickDefault(import('#src/routes/well-known.js'));
|
||||
const { createMockProvider } = await import('#src/test-utils/oidc-provider.js');
|
||||
const { MockTenant } = await import('#src/test-utils/tenant.js');
|
||||
|
@ -56,10 +44,26 @@ describe('GET /.well-known/sign-in-exp', () => {
|
|||
const provider = createMockProvider();
|
||||
const sessionRequest = createRequester({
|
||||
anonymousRoutes: wellKnownRoutes,
|
||||
tenantContext: new MockTenant(provider, {
|
||||
signInExperiences: sieQueries,
|
||||
users: { hasActiveUsers: jest.fn().mockResolvedValue(true) },
|
||||
}),
|
||||
tenantContext: new MockTenant(
|
||||
provider,
|
||||
{
|
||||
signInExperiences: sieQueries,
|
||||
users: { hasActiveUsers: jest.fn().mockResolvedValue(true) },
|
||||
},
|
||||
{
|
||||
connectors: {
|
||||
getLogtoConnectors: jest.fn(async () => [
|
||||
mockAliyunDmConnector,
|
||||
mockAliyunSmsConnector,
|
||||
mockFacebookConnector,
|
||||
mockGithubConnector,
|
||||
mockGoogleConnector,
|
||||
mockWechatConnector,
|
||||
mockWechatNativeConnector,
|
||||
]),
|
||||
},
|
||||
}
|
||||
),
|
||||
middlewares: [
|
||||
async (ctx, next) => {
|
||||
ctx.addLogContext = jest.fn();
|
||||
|
|
|
@ -3,7 +3,6 @@ import { ConnectorType } from '@logto/connector-kit';
|
|||
import { adminConsoleApplicationId } from '@logto/schemas';
|
||||
import etag from 'etag';
|
||||
|
||||
import { getLogtoConnectors } from '#src/libraries/connector.js';
|
||||
import { getApplicationIdFromInteraction } from '#src/libraries/session.js';
|
||||
|
||||
import type { AnonymousRouter, RouterInitArgs } from './types.js';
|
||||
|
@ -11,7 +10,10 @@ import type { AnonymousRouter, RouterInitArgs } from './types.js';
|
|||
export default function wellKnownRoutes<T extends AnonymousRouter>(
|
||||
...[router, { provider, libraries }]: RouterInitArgs<T>
|
||||
) {
|
||||
const { getSignInExperienceForApplication } = libraries.signInExperiences;
|
||||
const {
|
||||
signInExperiences: { getSignInExperienceForApplication },
|
||||
connectors: { getLogtoConnectors },
|
||||
} = libraries;
|
||||
|
||||
router.get(
|
||||
'/.well-known/sign-in-exp',
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import { createConnectorLibrary } from '#src/libraries/connector.js';
|
||||
import { createSignInExperienceLibrary } from '#src/libraries/sign-in-experience/index.js';
|
||||
import { createUserLibrary } from '#src/libraries/user.js';
|
||||
|
||||
import type Queries from './Queries.js';
|
||||
|
||||
export default class Libraries {
|
||||
connectors = createConnectorLibrary(this.queries);
|
||||
users = createUserLibrary(this.queries);
|
||||
signInExperiences = createSignInExperienceLibrary(this.queries);
|
||||
signInExperiences = createSignInExperienceLibrary(this.queries, this.connectors);
|
||||
|
||||
constructor(public readonly queries: Queries) {}
|
||||
}
|
||||
|
|
|
@ -6,15 +6,6 @@ import type TenantContext from '#src/tenants/TenantContext.js';
|
|||
|
||||
import { createMockProvider } from './oidc-provider.js';
|
||||
|
||||
export const createQueriesWithMockPool = () =>
|
||||
new Queries(
|
||||
createMockPool({
|
||||
query: async (sql, values) => {
|
||||
return createMockQueryResult([]);
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
export class MockQueries extends Queries {
|
||||
constructor(queriesOverride?: Partial2<Queries>) {
|
||||
super(
|
||||
|
|
Loading…
Add table
Reference in a new issue