From b07252f9b2ed013e9494710c2b2938317ac94566 Mon Sep 17 00:00:00 2001 From: Gao Sun Date: Sat, 28 Jan 2023 13:05:45 +0800 Subject: [PATCH] refactor: fix build --- .../core/src/__mocks__/connector-base-data.ts | 7 +++++++ packages/core/src/__mocks__/connector.ts | 3 +++ packages/core/src/__mocks__/custom-phrase.ts | 21 ++++++++++++++----- packages/core/src/__mocks__/index.ts | 8 +++++++ .../core/src/__mocks__/sign-in-experience.ts | 1 + packages/core/src/__mocks__/user.ts | 7 +++++++ packages/core/src/libraries/connector.test.ts | 1 + packages/core/src/libraries/passcode.test.ts | 4 ++++ packages/core/src/libraries/phrase.test.ts | 6 ++++-- .../src/libraries/sign-in-experience/index.ts | 6 +++++- packages/core/src/libraries/user.ts | 6 ++++-- .../core/src/queries/applications-roles.ts | 4 ++-- packages/core/src/queries/roles-scopes.ts | 4 ++-- packages/core/src/queries/roles.ts | 2 +- packages/core/src/queries/users-roles.ts | 4 ++-- packages/core/src/routes/admin-user-role.ts | 5 ++++- packages/core/src/routes/admin-user.test.ts | 4 +++- packages/core/src/routes/application.ts | 4 +++- .../core/src/routes/custom-phrase.test.ts | 7 +++++-- packages/core/src/routes/custom-phrase.ts | 3 ++- packages/core/src/routes/log.test.ts | 2 +- packages/core/src/routes/phrase.test.ts | 7 ++++++- packages/core/src/routes/role.scope.ts | 5 ++++- packages/core/src/routes/role.ts | 10 ++++++--- packages/schemas/src/gen/schema.ts | 7 +++++-- packages/ui/src/__mocks__/logto.tsx | 2 ++ 26 files changed, 109 insertions(+), 31 deletions(-) diff --git a/packages/core/src/__mocks__/connector-base-data.ts b/packages/core/src/__mocks__/connector-base-data.ts index 85911a7a3..2ce37dd06 100644 --- a/packages/core/src/__mocks__/connector-base-data.ts +++ b/packages/core/src/__mocks__/connector-base-data.ts @@ -76,6 +76,7 @@ export const mockMetadata6: ConnectorMetadata = { }; export const mockConnector0: Connector = { + tenantId: 'fake_tenant', id: 'id0', config: {}, createdAt: 1_234_567_890_123, @@ -85,6 +86,7 @@ export const mockConnector0: Connector = { }; export const mockConnector1: Connector = { + tenantId: 'fake_tenant', id: 'id1', config: {}, createdAt: 1_234_567_890_234, @@ -94,6 +96,7 @@ export const mockConnector1: Connector = { }; export const mockConnector2: Connector = { + tenantId: 'fake_tenant', id: 'id2', config: {}, createdAt: 1_234_567_890_345, @@ -103,6 +106,7 @@ export const mockConnector2: Connector = { }; export const mockConnector3: Connector = { + tenantId: 'fake_tenant', id: 'id3', config: {}, createdAt: 1_234_567_890_456, @@ -112,6 +116,7 @@ export const mockConnector3: Connector = { }; export const mockConnector4: Connector = { + tenantId: 'fake_tenant', id: 'id4', config: {}, createdAt: 1_234_567_890_567, @@ -121,6 +126,7 @@ export const mockConnector4: Connector = { }; export const mockConnector5: Connector = { + tenantId: 'fake_tenant', id: 'id5', config: {}, createdAt: 1_234_567_890_567, @@ -130,6 +136,7 @@ export const mockConnector5: Connector = { }; export const mockConnector6: Connector = { + tenantId: 'fake_tenant', id: 'id6', config: {}, createdAt: 1_234_567_890_567, diff --git a/packages/core/src/__mocks__/connector.ts b/packages/core/src/__mocks__/connector.ts index 63db4132d..b07ae8214 100644 --- a/packages/core/src/__mocks__/connector.ts +++ b/packages/core/src/__mocks__/connector.ts @@ -36,6 +36,7 @@ export { const { jest } = import.meta; export const mockConnector: Connector = { + tenantId: 'fake_tenant', id: 'id', config: {}, createdAt: 1_234_567_890_123, @@ -235,6 +236,7 @@ export const socialTarget02 = 'socialTarget-id02'; export const mockSocialConnectors: LogtoConnector[] = [ { dbEntry: { + tenantId: 'fake_tenant', id: 'id0', config: {}, createdAt: 1_234_567_890_123, @@ -251,6 +253,7 @@ export const mockSocialConnectors: LogtoConnector[] = [ }, { dbEntry: { + tenantId: 'fake_tenant', id: 'id1', config: {}, createdAt: 1_234_567_890_123, diff --git a/packages/core/src/__mocks__/custom-phrase.ts b/packages/core/src/__mocks__/custom-phrase.ts index 6c2c848b5..b1e7cf467 100644 --- a/packages/core/src/__mocks__/custom-phrase.ts +++ b/packages/core/src/__mocks__/custom-phrase.ts @@ -1,4 +1,5 @@ import en from '@logto/phrases-ui/lib/locales/en.js'; +import { CustomPhrase } from '@logto/schemas'; export const enTag = 'en'; export const trTrTag = 'tr-TR'; @@ -6,6 +7,8 @@ export const zhCnTag = 'zh-CN'; export const zhHkTag = 'zh-HK'; export const mockEnCustomPhrase = { + tenantId: 'fake_tenant', + id: 'fake_id', languageTag: enTag, translation: { input: { @@ -16,17 +19,21 @@ export const mockEnCustomPhrase = { confirm_password: 'Confirm password 5', }, }, -}; +} satisfies CustomPhrase; export const mockEnPhrase = { + tenantId: 'fake_tenant', + id: 'fake_id', languageTag: enTag, translation: { ...en.translation, ...mockEnCustomPhrase.translation, }, -}; +} satisfies CustomPhrase; export const mockTrTrCustomPhrase = { + tenantId: 'fake_tenant', + id: 'fake_id', languageTag: trTrTag, translation: { input: { @@ -37,9 +44,11 @@ export const mockTrTrCustomPhrase = { confirm_password: 'Şifreyi Doğrula 5', }, }, -}; +} satisfies CustomPhrase; export const mockZhCnCustomPhrase = { + tenantId: 'fake_tenant', + id: 'fake_id', languageTag: zhCnTag, translation: { input: { @@ -50,9 +59,11 @@ export const mockZhCnCustomPhrase = { confirm_password: '确认密码 5', }, }, -}; +} satisfies CustomPhrase; export const mockZhHkCustomPhrase = { + tenantId: 'fake_tenant', + id: 'fake_id', languageTag: zhHkTag, translation: { input: { @@ -63,4 +74,4 @@ export const mockZhHkCustomPhrase = { confirm_password: '確認密碼 5', }, }, -}; +} satisfies CustomPhrase; diff --git a/packages/core/src/__mocks__/index.ts b/packages/core/src/__mocks__/index.ts index d57050588..c1d316b6e 100644 --- a/packages/core/src/__mocks__/index.ts +++ b/packages/core/src/__mocks__/index.ts @@ -7,6 +7,7 @@ export * from './sign-in-experience.js'; export * from './user.js'; export const mockApplication: Application = { + tenantId: 'fake_tenant', id: 'foo', secret: 'randomId', name: 'foo', @@ -25,6 +26,7 @@ export const mockApplication: Application = { }; export const mockResource: Resource = { + tenantId: 'fake_tenant', id: 'logto_api', name: 'management api', indicator: 'logto.dev/api', @@ -32,6 +34,7 @@ export const mockResource: Resource = { }; export const mockResource2: Resource = { + tenantId: 'fake_tenant', id: 'logto_api2', name: 'management api', indicator: 'logto.dev/api', @@ -39,6 +42,7 @@ export const mockResource2: Resource = { }; export const mockResource3: Resource = { + tenantId: 'fake_tenant', id: 'logto_api3', name: 'management api', indicator: 'logto.dev/api', @@ -46,6 +50,7 @@ export const mockResource3: Resource = { }; export const mockScope: Scope = { + tenantId: 'fake_tenant', id: 'scope_id', name: 'read:users', description: 'read users', @@ -54,12 +59,14 @@ export const mockScope: Scope = { }; export const mockRole: Role = { + tenantId: 'fake_tenant', id: 'role_id', name: 'admin', description: 'admin', }; export const mockSetting: Setting = { + tenantId: 'fake_tenant', id: 'foo setting', adminConsole: { demoChecked: false, @@ -72,6 +79,7 @@ export const mockSetting: Setting = { }; export const mockPasscode: Passcode = { + tenantId: 'fake_tenant', id: 'foo', interactionJti: 'jti', phone: '888 888 8888', diff --git a/packages/core/src/__mocks__/sign-in-experience.ts b/packages/core/src/__mocks__/sign-in-experience.ts index 6ead6e855..9a7d87232 100644 --- a/packages/core/src/__mocks__/sign-in-experience.ts +++ b/packages/core/src/__mocks__/sign-in-experience.ts @@ -45,6 +45,7 @@ export const mockSignIn = { }; export const mockSignInExperience: SignInExperience = { + tenantId: 'fake_tenant', id: 'foo', color: { primaryColor: '#000', diff --git a/packages/core/src/__mocks__/user.ts b/packages/core/src/__mocks__/user.ts index 557a8d8a8..195eacc53 100644 --- a/packages/core/src/__mocks__/user.ts +++ b/packages/core/src/__mocks__/user.ts @@ -3,6 +3,7 @@ import { userInfoSelectFields, UsersPasswordEncryptionMethod } from '@logto/sche import { pick } from '@silverhand/essentials'; export const mockUser: User = { + tenantId: 'fake_tenant', id: 'foo', username: 'foo', primaryEmail: 'foo@logto.io', @@ -25,6 +26,7 @@ export const mockUserResponse = pick(mockUser, ...userInfoSelectFields); export const mockPasswordEncrypted = 'a1b2c3'; export const mockUserWithPassword: User = { + tenantId: 'fake_tenant', id: 'id', username: 'username', primaryEmail: 'foo@logto.io', @@ -45,6 +47,7 @@ export const mockUserWithPassword: User = { export const mockUserList: User[] = [ { + tenantId: 'fake_tenant', id: '1', username: 'foo1', primaryEmail: 'foo1@logto.io', @@ -61,6 +64,7 @@ export const mockUserList: User[] = [ isSuspended: false, }, { + tenantId: 'fake_tenant', id: '2', username: 'foo2', primaryEmail: 'foo2@logto.io', @@ -77,6 +81,7 @@ export const mockUserList: User[] = [ isSuspended: false, }, { + tenantId: 'fake_tenant', id: '3', username: 'foo3', primaryEmail: 'foo3@logto.io', @@ -93,6 +98,7 @@ export const mockUserList: User[] = [ isSuspended: false, }, { + tenantId: 'fake_tenant', id: '4', username: 'bar1', primaryEmail: 'bar1@logto.io', @@ -109,6 +115,7 @@ export const mockUserList: User[] = [ isSuspended: false, }, { + tenantId: 'fake_tenant', id: '5', username: 'bar2', primaryEmail: 'bar2@logto.io', diff --git a/packages/core/src/libraries/connector.test.ts b/packages/core/src/libraries/connector.test.ts index 4914630d3..3c10a652f 100644 --- a/packages/core/src/libraries/connector.test.ts +++ b/packages/core/src/libraries/connector.test.ts @@ -5,6 +5,7 @@ import { MockQueries } from '#src/test-utils/tenant.js'; const connectors: Connector[] = [ { + tenantId: 'fake_tenant', id: 'id', config: { foo: 'bar' }, createdAt: 0, diff --git a/packages/core/src/libraries/passcode.test.ts b/packages/core/src/libraries/passcode.test.ts index d5b2c7333..027f1e6fa 100644 --- a/packages/core/src/libraries/passcode.test.ts +++ b/packages/core/src/libraries/passcode.test.ts @@ -148,6 +148,7 @@ describe('createPasscode', () => { describe('sendPasscode', () => { it('should throw error when email and phone are both empty', async () => { const passcode: Passcode = { + tenantId: 'fake_tenant', id: 'id', interactionJti: 'jti', phone: null, @@ -181,6 +182,7 @@ describe('sendPasscode', () => { }, ]); const passcode: Passcode = { + tenantId: 'fake_tenant', id: 'id', interactionJti: 'jti', phone: 'phone', @@ -232,6 +234,7 @@ describe('sendPasscode', () => { }, ]); const passcode: Passcode = { + tenantId: 'fake_tenant', id: 'passcode_id', interactionJti: 'jti', phone: 'phone', @@ -255,6 +258,7 @@ describe('sendPasscode', () => { describe('verifyPasscode', () => { const passcode = { + tenantId: 'fake_tenant', id: 'id', interactionJti: 'jti', phone: 'phone', diff --git a/packages/core/src/libraries/phrase.test.ts b/packages/core/src/libraries/phrase.test.ts index ac1cb79df..e3100490f 100644 --- a/packages/core/src/libraries/phrase.test.ts +++ b/packages/core/src/libraries/phrase.test.ts @@ -1,5 +1,5 @@ import resource from '@logto/phrases-ui'; -import type { CustomPhrase } from '@logto/schemas'; +import { CustomPhrase } from '@logto/schemas'; import deepmerge from 'deepmerge'; import { @@ -57,6 +57,8 @@ it('should ignore empty string values from the custom phrase', async () => { confirm_password: 'Confirm password 5', }; const mockEnCustomPhraseWithEmptyStringValues = { + tenantId: 'fake_tenant', + id: 'fake_id', languageTag: enTag, translation: { input: { @@ -66,7 +68,7 @@ it('should ignore empty string values from the custom phrase', async () => { password: '', }, }, - }; + } satisfies CustomPhrase; findCustomPhraseByLanguageTag.mockResolvedValueOnce(mockEnCustomPhraseWithEmptyStringValues); await expect(getPhrases(enTag, [enTag])).resolves.toEqual( diff --git a/packages/core/src/libraries/sign-in-experience/index.ts b/packages/core/src/libraries/sign-in-experience/index.ts index 3d1009670..74c3150a3 100644 --- a/packages/core/src/libraries/sign-in-experience/index.ts +++ b/packages/core/src/libraries/sign-in-experience/index.ts @@ -1,6 +1,7 @@ import { builtInLanguages } from '@logto/phrases-ui'; import type { Branding, LanguageInfo, SignInExperience } from '@logto/schemas'; import { + defaultTenantId, SignInMode, ConnectorType, BrandingStyle, @@ -73,9 +74,12 @@ export const createSignInExperienceLibrary = ( ): Promise => { const signInExperience = await findDefaultSignInExperience(); - // Hard code AdminConsole sign-in methods settings. + // Hard code Admin Console sign-in methods settings. if (applicationId === adminConsoleApplicationId) { return { + // If we need to hard code, it implies Logto is running in the single-tenant mode; + // Thus we can hard code Tenant ID as well. + tenantId: defaultTenantId, ...adminConsoleSignInExperience, branding: { ...adminConsoleSignInExperience.branding, diff --git a/packages/core/src/libraries/user.ts b/packages/core/src/libraries/user.ts index bf3271611..24f6fe5f9 100644 --- a/packages/core/src/libraries/user.ts +++ b/packages/core/src/libraries/user.ts @@ -1,4 +1,4 @@ -import { buildIdGenerator } from '@logto/core-kit'; +import { buildIdGenerator, generateStandardId } from '@logto/core-kit'; import type { User, CreateUser, Scope } from '@logto/schemas'; import { Users, UsersPasswordEncryptionMethod, defaultRole } from '@logto/schemas'; import type { OmitAutoSetFields } from '@logto/shared'; @@ -95,7 +95,9 @@ export const createUserLibrary = (queries: Queries) => { const user = await insertUserQuery(data); if (roles.length > 0) { - await insertUsersRoles(roles.map(({ id }) => ({ userId: user.id, roleId: id }))); + await insertUsersRoles( + roles.map(({ id }) => ({ id: generateStandardId(), userId: user.id, roleId: id })) + ); } return user; diff --git a/packages/core/src/queries/applications-roles.ts b/packages/core/src/queries/applications-roles.ts index c6008a0da..1ff3fe115 100644 --- a/packages/core/src/queries/applications-roles.ts +++ b/packages/core/src/queries/applications-roles.ts @@ -1,4 +1,4 @@ -import type { ApplicationsRole } from '@logto/schemas'; +import type { ApplicationsRole, CreateApplicationsRole } from '@logto/schemas'; import { ApplicationsRoles, RolesScopes } from '@logto/schemas'; import { convertToIdentifiers } from '@logto/shared'; import type { CommonQueryMethods } from 'slonik'; @@ -16,7 +16,7 @@ export const createApplicationsRolesQueries = (pool: CommonQueryMethods) => { where ${fields.applicationId}=${applicationId} `); - const insertApplicationsRoles = async (applicationsRoles: ApplicationsRole[]) => + const insertApplicationsRoles = async (applicationsRoles: CreateApplicationsRole[]) => pool.query(sql` insert into ${table} (${fields.applicationId}, ${fields.roleId}) values ${sql.join( diff --git a/packages/core/src/queries/roles-scopes.ts b/packages/core/src/queries/roles-scopes.ts index 23d75290f..9d6641f6e 100644 --- a/packages/core/src/queries/roles-scopes.ts +++ b/packages/core/src/queries/roles-scopes.ts @@ -1,4 +1,4 @@ -import type { RolesScope } from '@logto/schemas'; +import type { CreateRolesScope, RolesScope } from '@logto/schemas'; import { RolesScopes } from '@logto/schemas'; import { convertToIdentifiers } from '@logto/shared'; import type { CommonQueryMethods } from 'slonik'; @@ -9,7 +9,7 @@ import { DeletionError } from '#src/errors/SlonikError/index.js'; const { table, fields } = convertToIdentifiers(RolesScopes); export const createRolesScopesQueries = (pool: CommonQueryMethods) => { - const insertRolesScopes = async (rolesScopes: RolesScope[]) => + const insertRolesScopes = async (rolesScopes: CreateRolesScope[]) => pool.query(sql` insert into ${table} (${fields.scopeId}, ${fields.roleId}) values ${sql.join( diff --git a/packages/core/src/queries/roles.ts b/packages/core/src/queries/roles.ts index cdfcad2ab..beeb5f1c7 100644 --- a/packages/core/src/queries/roles.ts +++ b/packages/core/src/queries/roles.ts @@ -99,7 +99,7 @@ export const createRolesQueries = (pool: CommonQueryMethods) => { ${conditionalSql(excludeRoleId, (id) => sql`and ${fields.id}<>${id}`)} `); - const insertRoles = async (roles: Role[]) => + const insertRoles = async (roles: CreateRole[]) => pool.query(sql` insert into ${table} (${fields.id}, ${fields.name}, ${fields.description}) values ${sql.join( diff --git a/packages/core/src/queries/users-roles.ts b/packages/core/src/queries/users-roles.ts index 2caf5dbd5..b8c3de7d4 100644 --- a/packages/core/src/queries/users-roles.ts +++ b/packages/core/src/queries/users-roles.ts @@ -1,4 +1,4 @@ -import type { UsersRole } from '@logto/schemas'; +import type { CreateUsersRole, UsersRole } from '@logto/schemas'; import { RolesScopes, UsersRoles } from '@logto/schemas'; import { conditionalSql, convertToIdentifiers } from '@logto/shared'; import type { CommonQueryMethods } from 'slonik'; @@ -42,7 +42,7 @@ export const createUsersRolesQueries = (pool: CommonQueryMethods) => { ${conditionalSql(limit, (value) => sql`limit ${value}`)} `); - const insertUsersRoles = async (usersRoles: UsersRole[]) => + const insertUsersRoles = async (usersRoles: CreateUsersRole[]) => pool.query(sql` insert into ${table} (${fields.userId}, ${fields.roleId}) values ${sql.join( diff --git a/packages/core/src/routes/admin-user-role.ts b/packages/core/src/routes/admin-user-role.ts index 7f2581940..bc126fd91 100644 --- a/packages/core/src/routes/admin-user-role.ts +++ b/packages/core/src/routes/admin-user-role.ts @@ -1,3 +1,4 @@ +import { generateStandardId } from '@logto/core-kit'; import { tryThat } from '@logto/shared'; import { object, string } from 'zod'; @@ -89,7 +90,9 @@ export default function adminUserRoleRoutes( } await Promise.all(roleIds.map(async (roleId) => findRoleById(roleId))); - await insertUsersRoles(roleIds.map((roleId) => ({ userId, roleId }))); + await insertUsersRoles( + roleIds.map((roleId) => ({ id: generateStandardId(), userId, roleId })) + ); ctx.status = 201; return next(); diff --git a/packages/core/src/routes/admin-user.test.ts b/packages/core/src/routes/admin-user.test.ts index 2a91976db..2ebe72f6f 100644 --- a/packages/core/src/routes/admin-user.test.ts +++ b/packages/core/src/routes/admin-user.test.ts @@ -67,7 +67,9 @@ const mockedQueries = { }, roles: { findRolesByRoleNames: jest.fn( - async (): Promise => [{ id: 'role_id', name: 'admin', description: 'none' }] + async (): Promise => [ + { tenantId: 'fake_tenant', id: 'role_id', name: 'admin', description: 'none' }, + ] ), }, usersRoles: { diff --git a/packages/core/src/routes/application.ts b/packages/core/src/routes/application.ts index 3a6f120ad..b292f4467 100644 --- a/packages/core/src/routes/application.ts +++ b/packages/core/src/routes/application.ts @@ -112,7 +112,9 @@ export default function applicationRoutes( ); if (isAdmin && !originalIsAdmin) { - await insertApplicationsRoles([{ applicationId: id, roleId: adminConsoleAdminRoleId }]); + await insertApplicationsRoles([ + { id: generateStandardId(), applicationId: id, roleId: adminConsoleAdminRoleId }, + ]); } else if (!isAdmin && originalIsAdmin) { await deleteApplicationRole(id, adminConsoleAdminRoleId); } diff --git a/packages/core/src/routes/custom-phrase.test.ts b/packages/core/src/routes/custom-phrase.test.ts index 4d1439df5..87b07ff14 100644 --- a/packages/core/src/routes/custom-phrase.test.ts +++ b/packages/core/src/routes/custom-phrase.test.ts @@ -1,5 +1,6 @@ import en from '@logto/phrases-ui/lib/locales/en.js'; -import type { CustomPhrase, SignInExperience } from '@logto/schemas'; +import { CustomPhrase } from '@logto/schemas'; +import type { SignInExperience } from '@logto/schemas'; import { pickDefault, createMockUtils } from '@logto/shared/esm'; import { mockZhCnCustomPhrase, trTrTag, zhCnTag } from '#src/__mocks__/custom-phrase.js'; @@ -78,11 +79,13 @@ describe('customPhraseRoutes', () => { it('should return all custom phrases', async () => { const mockCustomPhrase = { + tenantId: 'fake_tenant', + id: 'fake_id', languageTag: 'zh-HK', translation: { input: { username: '用戶名', password: '密碼' }, }, - }; + } satisfies CustomPhrase; findAllCustomPhrases.mockImplementationOnce(async () => [mockCustomPhrase]); const response = await customPhraseRequest.get('/custom-phrases'); expect(response.status).toEqual(200); diff --git a/packages/core/src/routes/custom-phrase.ts b/packages/core/src/routes/custom-phrase.ts index 4e1f0a0b2..e3cf1496d 100644 --- a/packages/core/src/routes/custom-phrase.ts +++ b/packages/core/src/routes/custom-phrase.ts @@ -1,3 +1,4 @@ +import { generateStandardId } from '@logto/core-kit'; import { languageTagGuard } from '@logto/language-kit'; import resource from '@logto/phrases-ui'; import type { Translation } from '@logto/schemas'; @@ -79,7 +80,7 @@ export default function customPhraseRoutes( new RequestError('localization.invalid_translation_structure') ); - ctx.body = await upsertCustomPhrase({ languageTag, translation }); + ctx.body = await upsertCustomPhrase({ id: generateStandardId(), languageTag, translation }); return next(); } diff --git a/packages/core/src/routes/log.test.ts b/packages/core/src/routes/log.test.ts index 10b64635b..dffd14c3b 100644 --- a/packages/core/src/routes/log.test.ts +++ b/packages/core/src/routes/log.test.ts @@ -8,7 +8,7 @@ import { createRequester } from '#src/utils/test-utils.js'; const { jest } = import.meta; const mockBody = { key: 'a', payload: { key: 'a', result: LogResult.Success }, createdAt: 123 }; -const mockLog: Log = { id: '1', ...mockBody }; +const mockLog: Log = { tenantId: 'fake_tenant', id: '1', ...mockBody }; const mockLogs = [mockLog, { id: '2', ...mockBody }]; const logs = { diff --git a/packages/core/src/routes/phrase.test.ts b/packages/core/src/routes/phrase.test.ts index 2c78b3c73..dfb1746c5 100644 --- a/packages/core/src/routes/phrase.test.ts +++ b/packages/core/src/routes/phrase.test.ts @@ -32,7 +32,12 @@ const { default: detectLanguageSpy } = mockEsm('#src/i18n/detect-language.js', ( const customPhrases = { findAllCustomLanguageTags: jest.fn(async () => [customizedLanguage]), findCustomPhraseByLanguageTag: jest.fn( - async (tag: string): Promise => ({ languageTag: tag, translation: {} }) + async (tag: string): Promise => ({ + tenantId: 'fake_tenant', + id: 'fake_id', + languageTag: tag, + translation: {}, + }) ), } satisfies Partial; const { findAllCustomLanguageTags } = customPhrases; diff --git a/packages/core/src/routes/role.scope.ts b/packages/core/src/routes/role.scope.ts index dff3f986e..b609c0785 100644 --- a/packages/core/src/routes/role.scope.ts +++ b/packages/core/src/routes/role.scope.ts @@ -1,3 +1,4 @@ +import { generateStandardId } from '@logto/core-kit'; import type { ScopeResponse } from '@logto/schemas'; import { tryThat } from '@logto/shared'; import { object, string } from 'zod'; @@ -110,7 +111,9 @@ export default function roleScopeRoutes( } await Promise.all(scopeIds.map(async (scopeId) => findScopeById(scopeId))); - await insertRolesScopes(scopeIds.map((scopeId) => ({ roleId: id, scopeId }))); + await insertRolesScopes( + scopeIds.map((scopeId) => ({ id: generateStandardId(), roleId: id, scopeId })) + ); const newRolesScopes = await findRolesScopesByRoleId(id); const scopes = await findScopesByIds(newRolesScopes.map(({ scopeId }) => scopeId)); diff --git a/packages/core/src/routes/role.ts b/packages/core/src/routes/role.ts index aa80efd8d..45453d548 100644 --- a/packages/core/src/routes/role.ts +++ b/packages/core/src/routes/role.ts @@ -1,4 +1,4 @@ -import { buildIdGenerator } from '@logto/core-kit'; +import { buildIdGenerator, generateStandardId } from '@logto/core-kit'; import type { RoleResponse } from '@logto/schemas'; import { userInfoSelectFields, Roles } from '@logto/schemas'; import { tryThat } from '@logto/shared'; @@ -113,7 +113,9 @@ export default function roleRoutes( if (scopeIds) { await Promise.all(scopeIds.map(async (scopeId) => findScopeById(scopeId))); - await insertRolesScopes(scopeIds.map((scopeId) => ({ roleId: role.id, scopeId }))); + await insertRolesScopes( + scopeIds.map((scopeId) => ({ id: generateStandardId(), roleId: role.id, scopeId })) + ); } ctx.body = role; @@ -250,7 +252,9 @@ export default function roleRoutes( } await Promise.all(userIds.map(async (userId) => findUserById(userId))); - await insertUsersRoles(userIds.map((userId) => ({ roleId: id, userId }))); + await insertUsersRoles( + userIds.map((userId) => ({ id: generateStandardId(), roleId: id, userId })) + ); ctx.status = 201; return next(); diff --git a/packages/schemas/src/gen/schema.ts b/packages/schemas/src/gen/schema.ts index 73213cd66..964441d8e 100644 --- a/packages/schemas/src/gen/schema.ts +++ b/packages/schemas/src/gen/schema.ts @@ -6,6 +6,9 @@ import pluralize from 'pluralize'; import type { TableWithType } from './types.js'; +// Tenant ID should be optional for create types since it'll be generated by the database trigger +const tenantId = 'tenant_id'; + export const generateSchema = ({ name, fields }: TableWithType) => { const modelName = pluralize(camelcase(name, { pascalCase: true }), 1); const databaseEntryType = `Create${modelName}`; @@ -15,7 +18,7 @@ export const generateSchema = ({ name, fields }: TableWithType) => { ...fields.map( ({ name, type, isArray, nullable, hasDefaultValue }) => ` ${camelcase(name)}${conditionalString( - (nullable || hasDefaultValue) && '?' + (nullable || hasDefaultValue || name === tenantId) && '?' )}: ${type}${conditionalString(isArray && '[]')}${conditionalString( nullable && !hasDefaultValue && ' | null' )};` @@ -47,7 +50,7 @@ export const generateSchema = ({ name, fields }: TableWithType) => { }${conditionalString(isString && maxLength && `.max(${maxLength})`)}${conditionalString( isArray && '.array()' )}${conditionalString(nullable && '.nullable()')}${conditionalString( - (nullable || hasDefaultValue) && '.optional()' + (nullable || hasDefaultValue || name === tenantId) && '.optional()' )},`; } ), diff --git a/packages/ui/src/__mocks__/logto.tsx b/packages/ui/src/__mocks__/logto.tsx index 35b438c03..433c4c502 100644 --- a/packages/ui/src/__mocks__/logto.tsx +++ b/packages/ui/src/__mocks__/logto.tsx @@ -181,6 +181,7 @@ export const usernameSignInMethod = { }; export const mockSignInExperience: SignInExperience = { + tenantId: 'default', id: 'foo', color: { primaryColor: '#000', @@ -210,6 +211,7 @@ export const mockSignInExperience: SignInExperience = { }; export const mockSignInExperienceSettings: SignInExperienceResponse = { + tenantId: 'default', id: mockSignInExperience.id, color: mockSignInExperience.color, branding: mockSignInExperience.branding,