From 0457df0e3535037b17b68d6d5f20ac1b3ce32649 Mon Sep 17 00:00:00 2001 From: 5aaee9 <7685264+5aaee9@users.noreply.github.com> Date: Fri, 1 Mar 2024 12:50:49 +0800 Subject: [PATCH] fix(schemas): set default password for tenant (#4535) (#5339) * fix(schemas): set default password for tenant (#4535) * feat(schemas): set password when enable encrypt --- .../cli/src/commands/database/seed/index.ts | 30 +++++++++++++++---- .../cli/src/commands/database/seed/tables.ts | 13 ++++++-- packages/schemas/tables/_before_all.sql | 2 +- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/packages/cli/src/commands/database/seed/index.ts b/packages/cli/src/commands/database/seed/index.ts index c5ef9b2ac..282c17087 100644 --- a/packages/cli/src/commands/database/seed/index.ts +++ b/packages/cli/src/commands/database/seed/index.ts @@ -9,7 +9,12 @@ import { getAlterationDirectory } from '../alteration/utils.js'; import { createTables, seedCloud, seedTables, seedTest } from './tables.js'; -export const seedByPool = async (pool: DatabasePool, cloud = false, test = false) => { +export const seedByPool = async ( + pool: DatabasePool, + cloud = false, + test = false, + encryptBaseRole = false +) => { await pool.transaction(async (connection) => { // Check alteration scripts available in order to insert correct timestamp const latestTimestamp = await getLatestAlterationTimestamp(); @@ -21,9 +26,14 @@ export const seedByPool = async (pool: DatabasePool, cloud = false, test = false ); } - await oraPromise(createTables(connection), { + const tableInfo = await oraPromise(createTables(connection, encryptBaseRole), { text: 'Create tables', }); + + if (tableInfo.password.length > 0) { + consoleLog.info('base role password:', tableInfo.password); + } + await seedTables(connection, latestTimestamp, cloud); if (cloud) { @@ -44,7 +54,13 @@ const seedLegacyTestData = async (pool: DatabasePool) => { const seed: CommandModule< Record, - { swe?: boolean; cloud?: boolean; test?: boolean; 'legacy-test-data'?: boolean } + { + swe?: boolean; + cloud?: boolean; + test?: boolean; + 'legacy-test-data'?: boolean; + 'encrypt-base-role'?: boolean; + } > = { command: 'seed [type]', describe: 'Create database then seed tables and data', @@ -67,8 +83,12 @@ const seed: CommandModule< describe: 'Seed test data only for legacy Logto versions (<=1.12.0), this option conflicts with others', type: 'boolean', + }) + .option('encrypt-base-role', { + describe: 'Seed base role with password', + type: 'boolean', }), - handler: async ({ swe, cloud, test, legacyTestData }) => { + handler: async ({ swe, cloud, test, legacyTestData, encryptBaseRole }) => { const pool = await createPoolAndDatabaseIfNeeded(); if (legacyTestData) { @@ -92,7 +112,7 @@ const seed: CommandModule< } try { - await seedByPool(pool, cloud, test); + await seedByPool(pool, cloud, test, encryptBaseRole); } catch (error: unknown) { consoleLog.error(error); consoleLog.error( diff --git a/packages/cli/src/commands/database/seed/tables.ts b/packages/cli/src/commands/database/seed/tables.ts index a4af57ed2..33723c080 100644 --- a/packages/cli/src/commands/database/seed/tables.ts +++ b/packages/cli/src/commands/database/seed/tables.ts @@ -82,7 +82,10 @@ const lifecycleNames: readonly string[] = Object.freeze([ 'after_each', ] satisfies Lifecycle[]); -export const createTables = async (connection: DatabaseTransactionConnection) => { +export const createTables = async ( + connection: DatabaseTransactionConnection, + encryptBaseRole: boolean +): Promise<{ password: string }> => { const tableDirectory = getPathInModule('@logto/schemas', 'tables'); const directoryFiles = await readdir(tableDirectory); const tableFiles = directoryFiles.filter((file) => file.endsWith('.sql')); @@ -95,7 +98,7 @@ export const createTables = async (connection: DatabaseTransactionConnection) => const runLifecycleQuery = async ( lifecycle: Lifecycle, - parameters: { name?: string; database?: string } = {} + parameters: { name?: string; database?: string; password?: string } = {} ) => { const query = queries.find(([file]) => file.slice(1, -4) === lifecycle)?.[1]; @@ -106,6 +109,7 @@ export const createTables = async (connection: DatabaseTransactionConnection) => query .replaceAll('${name}', parameters.name ?? '') .replaceAll('${database}', parameters.database ?? '') + .replaceAll('${password}', parameters.password ?? '') /* eslint-enable no-template-curly-in-string */ )}` ); @@ -118,8 +122,9 @@ export const createTables = async (connection: DatabaseTransactionConnection) => ]; const sorted = allQueries.slice().sort(compareQuery); const database = await getDatabaseName(connection, true); + const password = encryptBaseRole ? generateStandardId(32) : ''; - await runLifecycleQuery('before_all', { database }); + await runLifecycleQuery('before_all', { database, password }); /* eslint-disable no-await-in-loop */ for (const [file, query] of sorted) { @@ -132,6 +137,8 @@ export const createTables = async (connection: DatabaseTransactionConnection) => /* eslint-enable no-await-in-loop */ await runLifecycleQuery('after_all', { database }); + + return { password }; }; export const seedTables = async ( diff --git a/packages/schemas/tables/_before_all.sql b/packages/schemas/tables/_before_all.sql index 6bdbf7866..138db367d 100644 --- a/packages/schemas/tables/_before_all.sql +++ b/packages/schemas/tables/_before_all.sql @@ -1,3 +1,3 @@ /* This SQL will run before all other queries. */ -create role logto_tenant_${database} noinherit; +create role logto_tenant_${database} password '${password}' noinherit;