mirror of
https://github.com/logto-io/logto.git
synced 2025-02-17 22:04:19 -05:00
refactor(core,connector): store and get fromEmail from logto email connector (#4164)
This commit is contained in:
parent
c5b0f9bdc5
commit
3e08f3c94d
7 changed files with 45 additions and 61 deletions
|
@ -95,6 +95,11 @@ export const defaultMetadata: ConnectorMetadata = {
|
|||
type: ConnectorConfigFormItemType.Text,
|
||||
},
|
||||
],
|
||||
/**
|
||||
* This is the email address that will be used as the sender of the email, should align with
|
||||
* the `fromEmail` of emailServiceProvider stored in cloud.systems table.
|
||||
*/
|
||||
fromEmail: 'no-reply@logto.email',
|
||||
};
|
||||
|
||||
export const scope = ['send:email'];
|
||||
|
|
|
@ -20,8 +20,6 @@ import { grantAccessToken } from './grant-access-token.js';
|
|||
import type { LogtoEmailConfig } from './types.js';
|
||||
import { logtoEmailConfigGuard } from './types.js';
|
||||
|
||||
export type { EmailServiceBasicConfig } from './types.js';
|
||||
|
||||
const sendMessage =
|
||||
(getConfig: GetConnectorConfig): SendMessageFunction =>
|
||||
async (data, inputConfig) => {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/* eslint-disable max-lines */
|
||||
import { buildRawConnector } from '@logto/cli/lib/connector/index.js';
|
||||
import { demoConnectorIds, validateConfig } from '@logto/connector-kit';
|
||||
import {
|
||||
|
@ -13,13 +12,12 @@ import { string, object } from 'zod';
|
|||
|
||||
import RequestError from '#src/errors/RequestError/index.js';
|
||||
import koaGuard from '#src/middleware/koa-guard.js';
|
||||
import SystemContext from '#src/tenants/SystemContext.js';
|
||||
import assertThat from '#src/utils/assert-that.js';
|
||||
import { buildExtraInfo } from '#src/utils/connectors/extra-information.js';
|
||||
import {
|
||||
loadConnectorFactories,
|
||||
transpileConnectorFactory,
|
||||
transpileLogtoConnector,
|
||||
buildExtraInfoFromEmailServiceData,
|
||||
} from '#src/utils/connectors/index.js';
|
||||
import { checkSocialConnectorTargetAndPlatformUniqueness } from '#src/utils/connectors/platform.js';
|
||||
|
||||
|
@ -46,15 +44,6 @@ export default function connectorRoutes<T extends AuthedRouter>(
|
|||
signInExperiences: { removeUnavailableSocialConnectorTargets },
|
||||
} = tenant.libraries;
|
||||
|
||||
// Will accept other source of `extraInfo` in the future.
|
||||
const { emailServiceProviderConfig } = SystemContext.shared;
|
||||
const buildExtraInfo = (connectorFactoryId: string) => {
|
||||
const extraInfo = {
|
||||
...buildExtraInfoFromEmailServiceData(connectorFactoryId, emailServiceProviderConfig),
|
||||
};
|
||||
return cleanDeep(extraInfo, { emptyObjects: false });
|
||||
};
|
||||
|
||||
router.post(
|
||||
'/connectors',
|
||||
koaGuard({
|
||||
|
@ -164,7 +153,7 @@ export default function connectorRoutes<T extends AuthedRouter>(
|
|||
}
|
||||
|
||||
const connector = await getLogtoConnectorById(insertConnectorId);
|
||||
ctx.body = await transpileLogtoConnector(connector, buildExtraInfo(connector.metadata.id));
|
||||
ctx.body = await transpileLogtoConnector(connector, buildExtraInfo(connector.metadata));
|
||||
|
||||
return next();
|
||||
}
|
||||
|
@ -200,7 +189,7 @@ export default function connectorRoutes<T extends AuthedRouter>(
|
|||
|
||||
ctx.body = await Promise.all(
|
||||
filteredConnectors.map(async (connector) =>
|
||||
transpileLogtoConnector(connector, buildExtraInfo(connector.metadata.id))
|
||||
transpileLogtoConnector(connector, buildExtraInfo(connector.metadata))
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -224,7 +213,7 @@ export default function connectorRoutes<T extends AuthedRouter>(
|
|||
// Hide demo connector
|
||||
assertThat(!demoConnectorIds.includes(connector.metadata.id), 'connector.not_found');
|
||||
|
||||
ctx.body = await transpileLogtoConnector(connector, buildExtraInfo(connector.metadata.id));
|
||||
ctx.body = await transpileLogtoConnector(connector, buildExtraInfo(connector.metadata));
|
||||
|
||||
return next();
|
||||
}
|
||||
|
@ -324,7 +313,7 @@ export default function connectorRoutes<T extends AuthedRouter>(
|
|||
jsonbMode: 'replace',
|
||||
});
|
||||
const connector = await getLogtoConnectorById(id);
|
||||
ctx.body = await transpileLogtoConnector(connector, buildExtraInfo(connector.metadata.id));
|
||||
ctx.body = await transpileLogtoConnector(connector, buildExtraInfo(connector.metadata));
|
||||
|
||||
return next();
|
||||
}
|
||||
|
@ -360,5 +349,3 @@ export default function connectorRoutes<T extends AuthedRouter>(
|
|||
connectorConfigTestingRoutes(router, tenant);
|
||||
connectorAuthorizationUriRoutes(router, tenant);
|
||||
}
|
||||
/** TODO @Darcy: refactor this file later. */
|
||||
/* eslint-enable max-lines */
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
import {
|
||||
CloudflareKey,
|
||||
EmailServiceProviderKey,
|
||||
type HostnameProviderData,
|
||||
type StorageProviderData,
|
||||
type EmailServiceData,
|
||||
hostnameProviderDataGuard,
|
||||
storageProviderDataGuard,
|
||||
emailServiceDataGuard,
|
||||
StorageProviderKey,
|
||||
type SystemKey,
|
||||
} from '@logto/schemas';
|
||||
|
@ -20,7 +17,6 @@ export default class SystemContext {
|
|||
static shared = new SystemContext();
|
||||
public storageProviderConfig?: StorageProviderData;
|
||||
public hostnameProviderConfig?: HostnameProviderData;
|
||||
public emailServiceProviderConfig?: EmailServiceData;
|
||||
|
||||
async loadProviderConfigs(pool: CommonQueryMethods) {
|
||||
await Promise.all([
|
||||
|
@ -38,13 +34,6 @@ export default class SystemContext {
|
|||
hostnameProviderDataGuard
|
||||
);
|
||||
})(),
|
||||
(async () => {
|
||||
this.emailServiceProviderConfig = await this.loadConfig(
|
||||
pool,
|
||||
EmailServiceProviderKey.EmailServiceProvider,
|
||||
emailServiceDataGuard
|
||||
);
|
||||
})(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
18
packages/core/src/utils/connectors/extra-information.ts
Normal file
18
packages/core/src/utils/connectors/extra-information.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import { type ConnectorMetadata, ServiceConnector } from '@logto/connector-kit';
|
||||
import { conditional } from '@silverhand/essentials';
|
||||
import cleanDeep from 'clean-deep';
|
||||
import { string, object } from 'zod';
|
||||
|
||||
const getFromEmailFromMetadata = (metadata: ConnectorMetadata) => {
|
||||
const result = object({ fromEmail: string() }).safeParse(metadata);
|
||||
return conditional(result.success && result.data.fromEmail);
|
||||
};
|
||||
|
||||
// Will accept other source of `extraInfo` in the future.
|
||||
export const buildExtraInfo = (metadata: ConnectorMetadata) => {
|
||||
const fromEmail = getFromEmailFromMetadata(metadata);
|
||||
const extraInfo = {
|
||||
...conditional(fromEmail && metadata.id === ServiceConnector.Email && { fromEmail }),
|
||||
};
|
||||
return cleanDeep(extraInfo, { emptyObjects: false });
|
||||
};
|
|
@ -12,11 +12,10 @@ import {
|
|||
ConnectorType,
|
||||
type EmailConnector,
|
||||
type SmsConnector,
|
||||
ServiceConnector,
|
||||
} from '@logto/connector-kit';
|
||||
import type { ConnectorFactoryResponse, ConnectorResponse, EmailServiceData } from '@logto/schemas';
|
||||
import type { ConnectorFactoryResponse, ConnectorResponse } from '@logto/schemas';
|
||||
import { findPackage } from '@logto/shared';
|
||||
import { conditional, deduplicate, pick, trySafe, type Optional } from '@silverhand/essentials';
|
||||
import { conditional, deduplicate, pick, trySafe } from '@silverhand/essentials';
|
||||
|
||||
import { EnvSet } from '#src/env-set/index.js';
|
||||
import RequestError from '#src/errors/RequestError/index.js';
|
||||
|
@ -76,20 +75,6 @@ export const transpileConnectorFactory = ({
|
|||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* `extraInfo` is only used to expose email service vendors `fromEmail` setup to Logto email connector.
|
||||
* Can extend this method in the future for other use cases.
|
||||
*/
|
||||
export const buildExtraInfoFromEmailServiceData = (
|
||||
connectorFactoryId: string,
|
||||
emailServiceProviderConfig?: EmailServiceData
|
||||
): Optional<Record<string, unknown>> => {
|
||||
return conditional(
|
||||
connectorFactoryId === ServiceConnector.Email &&
|
||||
emailServiceProviderConfig?.fromEmail && { fromEmail: emailServiceProviderConfig.fromEmail }
|
||||
);
|
||||
};
|
||||
|
||||
const checkDuplicateConnectorFactoriesId = (connectorFactories: ConnectorFactory[]) => {
|
||||
const connectorFactoryIds = connectorFactories.map(({ metadata }) => metadata.id);
|
||||
const deduplicatedConnectorFactoryIds = deduplicate(connectorFactoryIds);
|
||||
|
|
|
@ -138,7 +138,8 @@ const connectorConfigFormItemGuard = z.discriminatedUnion('type', [
|
|||
|
||||
export type ConnectorConfigFormItem = z.infer<typeof connectorConfigFormItemGuard>;
|
||||
|
||||
export const connectorMetadataGuard = z.object({
|
||||
export const connectorMetadataGuard = z
|
||||
.object({
|
||||
id: z.string(),
|
||||
target: z.string(),
|
||||
platform: z.nativeEnum(ConnectorPlatform).nullable(),
|
||||
|
@ -150,7 +151,8 @@ export const connectorMetadataGuard = z.object({
|
|||
readme: z.string(),
|
||||
configTemplate: z.string().optional(),
|
||||
formItems: connectorConfigFormItemGuard.array().optional(),
|
||||
});
|
||||
})
|
||||
.catchall(z.unknown());
|
||||
|
||||
export const configurableConnectorMetadataGuard = connectorMetadataGuard
|
||||
.pick({
|
||||
|
|
Loading…
Add table
Reference in a new issue