diff --git a/packages/cli/src/commands/database/seed/cloud.ts b/packages/cli/src/commands/database/seed/cloud.ts index 18d14392b..a6cc6446d 100644 --- a/packages/cli/src/commands/database/seed/cloud.ts +++ b/packages/cli/src/commands/database/seed/cloud.ts @@ -1,9 +1,18 @@ -import { adminConsoleApplicationId, adminTenantId, defaultTenantId } from '@logto/schemas'; +import { + adminConsoleApplicationId, + adminTenantId, + defaultTenantId, + createTenantMachineToMachineApplication, + createAdminTenantApplicationRole, + createCloudConnectionConfig, + AdminTenantRole, +} from '@logto/schemas'; import { GlobalValues } from '@logto/shared'; import { appendPath } from '@silverhand/essentials'; import type { CommonQueryMethods } from 'slonik'; import { sql } from 'slonik'; +import { insertInto } from '../../../database.js'; import { consoleLog } from '../../../utils.js'; /** @@ -40,3 +49,46 @@ export const appendAdminConsoleRedirectUris = async (pool: CommonQueryMethods) = consoleLog.succeed('Appended initial Redirect URIs to Admin Console:', redirectUris.map(String)); }; + +/** + * Create Cloud Service M2M application for the tenant. + * + * This is a built-in M2M application for the tenant to communicate with the cloud service. + * - default + * - admin + */ +export const seedTenantCloudServiceApplication = async ( + pool: CommonQueryMethods, + tenantId: string +) => { + // Create Cloud Service M2M application + const cloudServiceApplication = createTenantMachineToMachineApplication(tenantId); + await pool.query(insertInto(cloudServiceApplication, 'applications')); + + // Assign tenantApplicationRole to Cloud Service M2M application + const { id: tenantApplicationRoleId } = await pool.one<{ id: string }>(sql` + select id from roles + where name = ${AdminTenantRole.TenantApplication} + and tenant_id = ${adminTenantId} + `); + await pool.query( + insertInto( + createAdminTenantApplicationRole(cloudServiceApplication.id, tenantApplicationRoleId), + 'applications_roles' + ) + ); + + // Create Cloud Service M2M application logto_config + await pool.query( + insertInto( + createCloudConnectionConfig( + tenantId, + cloudServiceApplication.id, + cloudServiceApplication.secret + ), + 'logto_configs' + ) + ); + + consoleLog.succeed('Cloud Service Application successfully created for:', tenantId); +}; diff --git a/packages/cli/src/commands/database/seed/tables.ts b/packages/cli/src/commands/database/seed/tables.ts index f5e1d7390..29714f2c3 100644 --- a/packages/cli/src/commands/database/seed/tables.ts +++ b/packages/cli/src/commands/database/seed/tables.ts @@ -3,7 +3,6 @@ import path from 'node:path'; import { createDefaultAdminConsoleConfig, - createCloudConnectionConfig, defaultTenantId, adminTenantId, defaultManagementApi, @@ -14,8 +13,6 @@ import { createDefaultAdminConsoleApplication, createCloudApi, createTenantApplicationRole, - createTenantMachineToMachineApplication, - createAdminTenantApplicationRole, CloudScope, } from '@logto/schemas'; import { Tenants } from '@logto/schemas/models'; @@ -28,7 +25,7 @@ import { getDatabaseName } from '../../../queries/database.js'; import { updateDatabaseTimestamp } from '../../../queries/system.js'; import { consoleLog, getPathInModule } from '../../../utils.js'; -import { appendAdminConsoleRedirectUris } from './cloud.js'; +import { appendAdminConsoleRedirectUris, seedTenantCloudServiceApplication } from './cloud.js'; import { seedOidcConfigs } from './oidc-config.js'; import { assignScopesToRole, createTenant, seedAdminData } from './tenant.js'; @@ -134,8 +131,10 @@ export const seedTables = async ( await seedAdminData(connection, createMeApiInAdminTenant()); const [cloudData, ...cloudAdditionalScopes] = createCloudApi(); - const applicationRole = createTenantApplicationRole(); await seedAdminData(connection, cloudData, ...cloudAdditionalScopes); + + // Create tenant application role + const applicationRole = createTenantApplicationRole(); await connection.query(insertInto(applicationRole, 'roles')); await assignScopesToRole( connection, @@ -146,16 +145,6 @@ export const seedTables = async ( .map(({ id }) => id) ); - // Add M2M app for default tenant - const defaultTenantApplication = createTenantMachineToMachineApplication(defaultTenantId); - await connection.query(insertInto(defaultTenantApplication, 'applications')); - await connection.query( - insertInto( - createAdminTenantApplicationRole(defaultTenantApplication.id, applicationRole.id), - 'applications_roles' - ) - ); - // Assign all cloud API scopes to role `admin:admin` await assignScopesToRole( connection, @@ -164,22 +153,15 @@ export const seedTables = async ( ...cloudAdditionalScopes.map(({ id }) => id) ); + // FIXME: @wangsijie should not create tenant Cloud Service application in the OSS DB. + await seedTenantCloudServiceApplication(connection, defaultTenantId); + await Promise.all([ connection.query(insertInto(createDefaultAdminConsoleConfig(defaultTenantId), 'logto_configs')), - connection.query( - insertInto( - createCloudConnectionConfig( - defaultTenantId, - defaultTenantApplication.id, - defaultTenantApplication.secret - ), - 'logto_configs' - ) - ), + connection.query(insertInto(createDefaultAdminConsoleConfig(adminTenantId), 'logto_configs')), connection.query( insertInto(createDefaultSignInExperience(defaultTenantId, isCloud), 'sign_in_experiences') ), - connection.query(insertInto(createDefaultAdminConsoleConfig(adminTenantId), 'logto_configs')), connection.query(insertInto(createAdminTenantSignInExperience(), 'sign_in_experiences')), connection.query(insertInto(createDefaultAdminConsoleApplication(), 'applications')), updateDatabaseTimestamp(connection, latestTimestamp), @@ -189,5 +171,8 @@ export const seedTables = async ( }; export const seedCloud = async (connection: DatabaseTransactionConnection) => { - await appendAdminConsoleRedirectUris(connection); + await Promise.all([ + appendAdminConsoleRedirectUris(connection), + seedTenantCloudServiceApplication(connection, adminTenantId), + ]); };