mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
refactor(core,schemas,cli): save cloud service m2m app credentials (#4109)
This commit is contained in:
parent
759adf0f18
commit
61c49845a6
8 changed files with 147 additions and 6 deletions
|
@ -3,6 +3,7 @@ import path from 'node:path';
|
|||
|
||||
import {
|
||||
createDefaultAdminConsoleConfig,
|
||||
createCloudConnectionConfig,
|
||||
defaultTenantId,
|
||||
adminTenantId,
|
||||
defaultManagementApi,
|
||||
|
@ -165,6 +166,16 @@ export const seedTables = async (
|
|||
|
||||
await Promise.all([
|
||||
connection.query(insertInto(createDefaultAdminConsoleConfig(defaultTenantId), 'logto_configs')),
|
||||
connection.query(
|
||||
insertInto(
|
||||
createCloudConnectionConfig(
|
||||
defaultTenantId,
|
||||
defaultTenantApplication.id,
|
||||
defaultTenantApplication.secret
|
||||
),
|
||||
'logto_configs'
|
||||
)
|
||||
),
|
||||
connection.query(
|
||||
insertInto(createDefaultSignInExperience(defaultTenantId, isCloud), 'sign_in_experiences')
|
||||
),
|
||||
|
|
|
@ -69,7 +69,9 @@ export class EnvSet {
|
|||
|
||||
this.#pool = pool;
|
||||
|
||||
const { getOidcConfigs } = createLogtoConfigLibrary(createLogtoConfigQueries(pool));
|
||||
const { getOidcConfigs } = createLogtoConfigLibrary({
|
||||
logtoConfigs: createLogtoConfigQueries(pool),
|
||||
});
|
||||
|
||||
const oidcConfigs = await getOidcConfigs();
|
||||
const endpoint = getTenantEndpoint(this.tenantId, EnvSet.values);
|
||||
|
|
|
@ -1,12 +1,19 @@
|
|||
import type { LogtoOidcConfigType } from '@logto/schemas';
|
||||
import { logtoOidcConfigGuard, LogtoOidcConfigKey } from '@logto/schemas';
|
||||
import {
|
||||
cloudApiIndicator,
|
||||
cloudConnectionDataGuard,
|
||||
logtoOidcConfigGuard,
|
||||
LogtoOidcConfigKey,
|
||||
} from '@logto/schemas';
|
||||
import chalk from 'chalk';
|
||||
import { z, ZodError } from 'zod';
|
||||
|
||||
import type Queries from '#src/tenants/Queries.js';
|
||||
import { consoleLog } from '#src/utils/console.js';
|
||||
|
||||
export const createLogtoConfigLibrary = ({ getRowsByKeys }: Queries['logtoConfigs']) => {
|
||||
export const createLogtoConfigLibrary = ({
|
||||
logtoConfigs: { getRowsByKeys, getCloudConnectionData: queryCloudConnectionData },
|
||||
}: Pick<Queries, 'logtoConfigs'>) => {
|
||||
const getOidcConfigs = async (): Promise<LogtoOidcConfigType> => {
|
||||
try {
|
||||
const { rows } = await getRowsByKeys(Object.values(LogtoOidcConfigKey));
|
||||
|
@ -35,5 +42,20 @@ export const createLogtoConfigLibrary = ({ getRowsByKeys }: Queries['logtoConfig
|
|||
}
|
||||
};
|
||||
|
||||
return { getOidcConfigs };
|
||||
const getCloudConnectionData = async () => {
|
||||
const { value } = await queryCloudConnectionData();
|
||||
const result = cloudConnectionDataGuard.safeParse(value);
|
||||
|
||||
if (!result.success) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
appId: result.data.appId,
|
||||
appSecret: result.data.appSecret,
|
||||
resource: cloudApiIndicator,
|
||||
};
|
||||
};
|
||||
|
||||
return { getOidcConfigs, getCloudConnectionData };
|
||||
};
|
||||
|
|
|
@ -21,11 +21,17 @@ export const createLogtoConfigQueries = (pool: CommonQueryMethods) => {
|
|||
returning ${fields.value}
|
||||
`);
|
||||
|
||||
const getCloudConnectionData = async () =>
|
||||
pool.one<Record<string, unknown>>(sql`
|
||||
select ${fields.value} from ${table}
|
||||
where ${fields.key} = ${LogtoTenantConfigKey.CloudConnection}
|
||||
`);
|
||||
|
||||
const getRowsByKeys = async (keys: LogtoConfigKey[]) =>
|
||||
pool.query<LogtoConfig>(sql`
|
||||
select ${sql.join([fields.key, fields.value], sql`,`)} from ${table}
|
||||
where ${fields.key} in (${sql.join(keys, sql`,`)})
|
||||
`);
|
||||
|
||||
return { getAdminConsoleConfig, updateAdminConsoleConfig, getRowsByKeys };
|
||||
return { getAdminConsoleConfig, updateAdminConsoleConfig, getCloudConnectionData, getRowsByKeys };
|
||||
};
|
||||
|
|
|
@ -2,6 +2,7 @@ import { createApplicationLibrary } from '#src/libraries/application.js';
|
|||
import type { ConnectorLibrary } from '#src/libraries/connector.js';
|
||||
import { createDomainLibrary } from '#src/libraries/domain.js';
|
||||
import { createHookLibrary } from '#src/libraries/hook/index.js';
|
||||
import { createLogtoConfigLibrary } from '#src/libraries/logto-config.js';
|
||||
import { createPasscodeLibrary } from '#src/libraries/passcode.js';
|
||||
import { createPhraseLibrary } from '#src/libraries/phrase.js';
|
||||
import { createResourceLibrary } from '#src/libraries/resource.js';
|
||||
|
@ -23,6 +24,7 @@ export default class Libraries {
|
|||
applications = createApplicationLibrary(this.queries);
|
||||
verificationStatuses = createVerificationStatusLibrary(this.queries);
|
||||
domains = createDomainLibrary(this.queries);
|
||||
logtoConfigs = createLogtoConfigLibrary(this.queries);
|
||||
|
||||
constructor(
|
||||
public readonly tenantId: string,
|
||||
|
|
13
packages/core/src/utils/endpoint.ts
Normal file
13
packages/core/src/utils/endpoint.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { appendPath } from '@silverhand/essentials';
|
||||
|
||||
import { EnvSet } from '#src/env-set/index.js';
|
||||
|
||||
/** Will use this method in upcoming changes. */
|
||||
// eslint-disable-next-line import/no-unused-modules
|
||||
export const getCloudConnectionEndpoints = async () => {
|
||||
const { cloudUrlSet, adminUrlSet } = EnvSet.values;
|
||||
return {
|
||||
tokenEndpoint: appendPath(adminUrlSet.endpoint, 'oidc/token').toString(),
|
||||
endpoint: appendPath(cloudUrlSet.endpoint, 'api').toString(),
|
||||
};
|
||||
};
|
|
@ -0,0 +1,85 @@
|
|||
import { sql } from 'slonik';
|
||||
|
||||
import type { AlterationScript } from '../lib/types/alteration.js';
|
||||
|
||||
const adminTenantId = 'admin';
|
||||
|
||||
const cloudServiceApplicationName = 'Cloud Service';
|
||||
|
||||
const cloudConnectionResourceIndicator = 'https://cloud.logto.io/api';
|
||||
|
||||
enum ApplicationType {
|
||||
Native = 'Native',
|
||||
SPA = 'SPA',
|
||||
Traditional = 'Traditional',
|
||||
MachineToMachine = 'MachineToMachine',
|
||||
}
|
||||
|
||||
const cloudConnectionConfigKey = 'cloudConnection';
|
||||
|
||||
type Application = {
|
||||
tenantId: string;
|
||||
id: string;
|
||||
name: string;
|
||||
secret: string;
|
||||
description: string;
|
||||
type: ApplicationType;
|
||||
oidcClientMetadata: unknown;
|
||||
customClientMetadata: {
|
||||
tenantId: string;
|
||||
};
|
||||
createdAt: number;
|
||||
};
|
||||
|
||||
type CloudConnectionConfig = {
|
||||
tenantId: string;
|
||||
key: string;
|
||||
value: unknown;
|
||||
};
|
||||
|
||||
const alteration: AlterationScript = {
|
||||
up: async (pool) => {
|
||||
const rows = await pool.many<Application>(
|
||||
sql`select * from applications where type = ${ApplicationType.MachineToMachine} and tenant_id = ${adminTenantId} and name = ${cloudServiceApplicationName}`
|
||||
);
|
||||
|
||||
const { rows: existingCloudConnections } = await pool.query<CloudConnectionConfig>(sql`
|
||||
select * from logto_configs where key = ${cloudConnectionConfigKey}
|
||||
`);
|
||||
const tenantIdsWithExistingRecords = new Set(
|
||||
existingCloudConnections.map(({ tenantId }) => tenantId)
|
||||
);
|
||||
const filteredRows = rows.filter(
|
||||
({ customClientMetadata: { tenantId } }) => !tenantIdsWithExistingRecords.has(tenantId)
|
||||
);
|
||||
|
||||
if (filteredRows.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
await pool.query(sql`
|
||||
insert into logto_configs (tenant_id, key, value) values ${sql.join(
|
||||
filteredRows.map(({ id, secret, customClientMetadata }) => {
|
||||
const { tenantId } = customClientMetadata;
|
||||
const cloudConnectionValue = {
|
||||
appId: id,
|
||||
appSecret: secret,
|
||||
resource: cloudConnectionResourceIndicator,
|
||||
};
|
||||
|
||||
return sql`(${tenantId}, ${cloudConnectionConfigKey}, ${JSON.stringify(
|
||||
cloudConnectionValue
|
||||
)})`;
|
||||
}),
|
||||
sql`,`
|
||||
)}
|
||||
`);
|
||||
},
|
||||
down: async (pool) => {
|
||||
await pool.query(sql`
|
||||
delete from logto_configs where key = ${cloudConnectionConfigKey}
|
||||
`);
|
||||
},
|
||||
};
|
||||
|
||||
export default alteration;
|
|
@ -26,7 +26,7 @@ export const createDefaultAdminConsoleConfig = (
|
|||
},
|
||||
} satisfies CreateLogtoConfig);
|
||||
|
||||
export const createDefaultCloudConnectionConfig = (
|
||||
export const createCloudConnectionConfig = (
|
||||
forTenantId: string,
|
||||
appId: string,
|
||||
appSecret: string
|
||||
|
|
Loading…
Reference in a new issue