mirror of
https://github.com/logto-io/logto.git
synced 2025-01-06 20:40:08 -05:00
feat(cloud,schemas): add demo social connectors for tenant (#3444)
This commit is contained in:
parent
63be7d04a5
commit
5b8d8c8c14
7 changed files with 118 additions and 5 deletions
7
.changeset-staged/breezy-moose-greet.md
Normal file
7
.changeset-staged/breezy-moose-greet.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
"@logto/cloud": minor
|
||||
"@logto/schemas": minor
|
||||
"@logto/shared": minor
|
||||
---
|
||||
|
||||
Add demo social connectors for new tenant
|
|
@ -26,12 +26,15 @@ import { createApplicationsQueries } from '#src/queries/application.js';
|
|||
import { createConnectorsQuery } from '#src/queries/connector.js';
|
||||
import type { Queries } from '#src/queries/index.js';
|
||||
import { createRolesQuery } from '#src/queries/roles.js';
|
||||
import { createSystemsQuery } from '#src/queries/system.js';
|
||||
import { createTenantsQueries } from '#src/queries/tenants.js';
|
||||
import { createUsersQueries } from '#src/queries/users.js';
|
||||
import { getDatabaseName } from '#src/queries/utils.js';
|
||||
import { insertInto } from '#src/utils/query.js';
|
||||
import { getTenantIdFromManagementApiIndicator } from '#src/utils/tenant.js';
|
||||
|
||||
const demoSocialConnectorId = 'logto-social-demo';
|
||||
|
||||
export const tenantInfoGuard: ZodType<TenantInfo> = z.object({
|
||||
id: z.string(),
|
||||
indicator: z.string(),
|
||||
|
@ -71,6 +74,7 @@ export class TenantsLibrary {
|
|||
const applications = createApplicationsQueries(transaction);
|
||||
const roles = createRolesQuery(transaction);
|
||||
const connectors = createConnectorsQuery(transaction);
|
||||
const systems = createSystemsQuery(transaction);
|
||||
|
||||
/* === Start === */
|
||||
await transaction.start();
|
||||
|
@ -128,6 +132,32 @@ export class TenantsLibrary {
|
|||
},
|
||||
});
|
||||
|
||||
// Create demo social connectors
|
||||
const presetSocialConnectors = await systems.getDemoSocialValue();
|
||||
|
||||
if (presetSocialConnectors) {
|
||||
await Promise.all(
|
||||
presetSocialConnectors.map(async (connector) => {
|
||||
return connectors.insertConnector({
|
||||
id: generateStandardId(),
|
||||
tenantId,
|
||||
connectorId: demoSocialConnectorId,
|
||||
metadata: {
|
||||
name: { en: connector.name },
|
||||
target: connector.provider,
|
||||
logo: connector.logo,
|
||||
logoDark: connector.logoDark,
|
||||
},
|
||||
config: {
|
||||
provider: connector.provider,
|
||||
clientId: connector.clientId,
|
||||
redirectUri: `${cloudUrlSet.endpoint.toString()}social-demo-callback`,
|
||||
},
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// Update Redirect URI for Admin Console
|
||||
await tenants.appendAdminConsoleRedirectUris(
|
||||
...['http://localhost:3003', 'https://cloud.logto.dev'].map(
|
||||
|
|
|
@ -22,7 +22,10 @@ export const createConnectorsQuery = (client: Queryable<PostgreSql>) => {
|
|||
|
||||
const insertConnector = async (
|
||||
// TODO @sijie update with-typed "JsonObject" to support "unknown" value
|
||||
connector: Pick<CreateConnector, 'id' | 'tenantId' | 'connectorId'> & { config: JsonObject }
|
||||
connector: Pick<CreateConnector, 'id' | 'tenantId' | 'connectorId'> & {
|
||||
config: JsonObject;
|
||||
metadata?: JsonObject;
|
||||
}
|
||||
) => client.query(insertInto(connector, 'connectors'));
|
||||
|
||||
return { findAllConnectors, insertConnector };
|
||||
|
|
|
@ -6,6 +6,7 @@ import { parseDsn } from '#src/utils/postgres.js';
|
|||
import { createApplicationsQueries } from './application.js';
|
||||
import { createConnectorsQuery } from './connector.js';
|
||||
import { createServiceLogsQueries } from './service-logs.js';
|
||||
import { createSystemsQuery } from './system.js';
|
||||
import { createTenantsQueries } from './tenants.js';
|
||||
import { createUsersQueries } from './users.js';
|
||||
|
||||
|
@ -18,4 +19,5 @@ export class Queries {
|
|||
public readonly applications = createApplicationsQueries(this.client);
|
||||
public readonly connectors = createConnectorsQuery(this.client);
|
||||
public readonly serviceLogs = createServiceLogsQueries(this.client);
|
||||
public readonly systems = createSystemsQuery(this.client);
|
||||
}
|
||||
|
|
29
packages/cloud/src/queries/system.ts
Normal file
29
packages/cloud/src/queries/system.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
import type { System } from '@logto/schemas';
|
||||
import { demoSocialDataGuard, DemoSocialKey } from '@logto/schemas';
|
||||
import type { PostgreSql } from '@withtyped/postgres';
|
||||
import { sql } from '@withtyped/postgres';
|
||||
import type { Queryable } from '@withtyped/server';
|
||||
|
||||
export type SystemsQuery = ReturnType<typeof createSystemsQuery>;
|
||||
|
||||
export const createSystemsQuery = (client: Queryable<PostgreSql>) => {
|
||||
const getDemoSocialValue = async () => {
|
||||
const { rows } = await client.query<System>(sql`
|
||||
select key, value
|
||||
from systems
|
||||
where key=${DemoSocialKey.DemoSocial}
|
||||
`);
|
||||
|
||||
if (!rows[0]) {
|
||||
return;
|
||||
}
|
||||
|
||||
const result = demoSocialDataGuard.safeParse(rows[0].value);
|
||||
|
||||
if (result.success) {
|
||||
return result.data;
|
||||
}
|
||||
};
|
||||
|
||||
return { getDemoSocialValue };
|
||||
};
|
|
@ -64,17 +64,54 @@ export const storageProviderGuard: Readonly<{
|
|||
[StorageProviderKey.StorageProvider]: storageProviderDataGuard,
|
||||
});
|
||||
|
||||
// Demo social connectors
|
||||
export enum DemoSocialProvider {
|
||||
Google = 'google',
|
||||
GitHub = 'github',
|
||||
Discord = 'discord',
|
||||
}
|
||||
|
||||
export const demoSocialDataGuard = z
|
||||
.object({
|
||||
name: z.string(),
|
||||
logo: z.string(),
|
||||
logoDark: z.string(),
|
||||
provider: z.nativeEnum(DemoSocialProvider),
|
||||
clientId: z.string(),
|
||||
})
|
||||
.array();
|
||||
|
||||
export type DemoSocialData = z.infer<typeof demoSocialDataGuard>;
|
||||
|
||||
export enum DemoSocialKey {
|
||||
DemoSocial = 'demoSocial',
|
||||
}
|
||||
|
||||
export type DemoSocialType = {
|
||||
[DemoSocialKey.DemoSocial]: DemoSocialData;
|
||||
};
|
||||
|
||||
export const demoSocialGuard: Readonly<{
|
||||
[key in DemoSocialKey]: ZodType<DemoSocialType[key]>;
|
||||
}> = Object.freeze({
|
||||
[DemoSocialKey.DemoSocial]: demoSocialDataGuard,
|
||||
});
|
||||
|
||||
// Summary
|
||||
export type SystemKey = AlterationStateKey | StorageProviderKey;
|
||||
export type SystemType = AlterationStateType | StorageProviderType;
|
||||
export type SystemGuard = typeof alterationStateGuard & typeof storageProviderGuard;
|
||||
export type SystemKey = AlterationStateKey | StorageProviderKey | DemoSocialKey;
|
||||
export type SystemType = AlterationStateType | StorageProviderType | DemoSocialType;
|
||||
export type SystemGuard = typeof alterationStateGuard &
|
||||
typeof storageProviderGuard &
|
||||
typeof demoSocialGuard;
|
||||
|
||||
export const systemKeys: readonly SystemKey[] = Object.freeze([
|
||||
...Object.values(AlterationStateKey),
|
||||
...Object.values(StorageProviderKey),
|
||||
...Object.values(DemoSocialKey),
|
||||
]);
|
||||
|
||||
export const systemGuards: SystemGuard = Object.freeze({
|
||||
...alterationStateGuard,
|
||||
...storageProviderGuard,
|
||||
...demoSocialGuard,
|
||||
});
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
export enum DemoConnector {
|
||||
Sms = 'logto-sms',
|
||||
Email = 'logto-email',
|
||||
Social = 'logto-social-demo',
|
||||
}
|
||||
|
||||
export const demoConnectorIds: string[] = [DemoConnector.Sms, DemoConnector.Email];
|
||||
export const demoConnectorIds: string[] = [
|
||||
DemoConnector.Sms,
|
||||
DemoConnector.Email,
|
||||
DemoConnector.Social,
|
||||
];
|
||||
|
|
Loading…
Reference in a new issue