import { v4 as uuidv4 } from 'uuid'; import { DataSource } from 'typeorm'; import { User } from '../../repositories/users/entity/user.entity'; import { Account } from '../../repositories/accounts/entity/account.entity'; import { ADMIN_ROLES, USER_ROLES } from '../../constants'; type InitialTestDBState = { tier1Accounts: { account: Account; users: User[] }[]; tier2Accounts: { account: Account; users: User[] }[]; tier3Accounts: { account: Account; users: User[] }[]; tier4Accounts: { account: Account; users: User[] }[]; tier5Accounts: { account: Account; users: User[] }[]; }; // 上書きされたら困る項目を除外したAccount型 type OverrideAccount = Omit< Account, 'id' | 'primary_admin_user_id' | 'secondary_admin_user_id' | 'user' >; // 上書きされたら困る項目を除外したUser型 type OverrideUser = Omit< User, 'id' | 'account' | 'license' | 'userGroupMembers' >; type AccountDefault = { [K in keyof OverrideAccount]?: OverrideAccount[K] }; type UserDefault = { [K in keyof OverrideUser]?: OverrideUser[K] }; /** * テスト ユーティリティ: 1~4階層のアカウントとその管理者ユーザーを作成します * @param dataSource データソース * @returns 作成されたデータセット */ export const makeHierarchicalAccounts = async ( datasource: DataSource, ): Promise => { const state: InitialTestDBState = { tier1Accounts: [], tier2Accounts: [], tier3Accounts: [], tier4Accounts: [], tier5Accounts: [], }; // 第1階層を作成 { const { account, admin } = await makeTestAccount(datasource, { tier: 1, company_name: 'OMDS', }); state.tier1Accounts.push({ account: account, users: [admin], }); } // 第2階層を作成 { const { account: tier1 } = state.tier1Accounts.slice().shift(); { const { account, admin } = await makeTestAccount(datasource, { tier: 2, parent_account_id: tier1.id, company_name: 'OMDS_US', }); state.tier2Accounts.push({ account: account, users: [admin], }); } { const { account, admin } = await makeTestAccount(datasource, { tier: 2, parent_account_id: tier1.id, company_name: 'OMDS_EU', }); state.tier2Accounts.push({ account: account, users: [admin], }); } } // 第3階層を作成 { for (const v of state.tier2Accounts) { { const { account, admin } = await makeTestAccount(datasource, { tier: 3, parent_account_id: v.account.id, company_name: `Agency_${v.account.id}_01`, }); state.tier3Accounts.push({ account: account, users: [admin], }); } { const { account, admin } = await makeTestAccount(datasource, { tier: 3, parent_account_id: v.account.id, company_name: `Agency_${v.account.id}_02`, }); state.tier3Accounts.push({ account: account, users: [admin], }); } } // 第4階層を作成 for (const v of state.tier3Accounts) { { const { account, admin } = await makeTestAccount(datasource, { tier: 4, parent_account_id: v.account.id, company_name: `Distributor_${v.account.id}_01`, }); state.tier4Accounts.push({ account: account, users: [admin], }); } { const { account, admin } = await makeTestAccount(datasource, { tier: 4, parent_account_id: v.account.id, company_name: `Distributor_${v.account.id}_02`, }); state.tier4Accounts.push({ account: account, users: [admin], }); } } } return state; }; /** * テスト ユーティリティ: 指定したプロパティを上書きしたアカウントとその管理者ユーザーを作成する * @param dataSource データソース * @param defaultUserValue Account型と同等かつoptionalなプロパティを持つ上書き箇所指定用オブジェクト * @param defaultAdminUserValue User型と同等かつoptionalなプロパティを持つ上書き箇所指定用オブジェクト(account_id等の所属関係が破壊される上書きは無視する) * @returns 作成したアカウント */ export const makeTestAccount = async ( datasource: DataSource, defaultAccountValue?: AccountDefault, defaultAdminUserValue?: UserDefault, isPrimaryAdminNotExist?: boolean, isSecondaryAdminNotExist?: boolean, ): Promise<{ account: Account; admin: User }> => { let accountId: number; let userId: number; { const d = defaultAccountValue; const { identifiers } = await datasource.getRepository(Account).insert({ tier: d?.tier ?? 1, parent_account_id: d?.parent_account_id ?? undefined, country: d?.country ?? 'US', delegation_permission: d?.delegation_permission ?? false, locked: d?.locked ?? false, company_name: d?.company_name ?? 'test inc.', verified: d?.verified ?? true, deleted_at: d?.deleted_at ?? '', created_by: d?.created_by ?? 'test_runner', created_at: d?.created_at ?? new Date(), updated_by: d?.updated_by ?? 'updater', updated_at: d?.updated_at ?? new Date(), }); const result = identifiers.pop() as Account; accountId = result.id; } { const d = defaultAdminUserValue; const { identifiers } = await datasource.getRepository(User).insert({ external_id: d?.external_id ?? uuidv4(), account_id: accountId, role: d?.role ?? 'admin none', author_id: d?.author_id ?? undefined, accepted_terms_version: d?.accepted_terms_version ?? '1.0', email_verified: d?.email_verified ?? true, auto_renew: d?.auto_renew ?? true, license_alert: d?.license_alert ?? true, notification: d?.notification ?? true, encryption: d?.encryption ?? true, encryption_password: d?.encryption_password ?? 'password', prompt: d?.prompt ?? true, deleted_at: d?.deleted_at ?? '', created_by: d?.created_by ?? 'test_runner', created_at: d?.created_at ?? new Date(), updated_by: d?.updated_by ?? 'updater', updated_at: d?.updated_at ?? new Date(), }); const result = identifiers.pop() as User; userId = result.id; } // Accountの管理者を設定する let secondaryAdminUserId = null; if (isPrimaryAdminNotExist && !isSecondaryAdminNotExist) { secondaryAdminUserId = userId; } await datasource.getRepository(Account).update( { id: accountId }, { primary_admin_user_id: isPrimaryAdminNotExist ? null : userId, secondary_admin_user_id: secondaryAdminUserId, }, ); const account = await datasource.getRepository(Account).findOne({ where: { id: accountId, }, }); const admin = await datasource.getRepository(User).findOne({ where: { id: userId, }, }); return { account: account, admin: admin, }; }; /** * テスト ユーティリティ: 指定したプロパティを上書きした管理者ユーザーの存在しないアカウントを作成する * @param dataSource データソース * @param defaultUserValue Account型と同等かつoptionalなプロパティを持つ上書き箇所指定用オブジェクト * @returns 作成したアカウント */ export const makeTestSimpleAccount = async ( datasource: DataSource, defaultAccountValue?: AccountDefault, ): Promise => { const d = defaultAccountValue; const { identifiers } = await datasource.getRepository(Account).insert({ tier: d?.tier ?? 1, parent_account_id: d?.parent_account_id ?? undefined, country: d?.country ?? 'US', delegation_permission: d?.delegation_permission ?? false, locked: d?.locked ?? false, company_name: d?.company_name ?? 'test inc.', verified: d?.verified ?? true, deleted_at: d?.deleted_at ?? '', created_by: d?.created_by ?? 'test_runner', created_at: d?.created_at ?? new Date(), updated_by: d?.updated_by ?? 'updater', updated_at: d?.updated_at ?? new Date(), }); const result = identifiers.pop() as Account; const account = await datasource.getRepository(Account).findOne({ where: { id: result.id, }, }); return account; }; /** * テスト ユーティリティ: 指定したプロパティを上書きしたユーザーを作成する * @param dataSource データソース * @param defaultUserValue User型と同等かつoptionalなプロパティを持つ上書き箇所指定用オブジェクト * @returns 作成したユーザー */ export const makeTestUser = async ( datasource: DataSource, defaultUserValue?: UserDefault, ): Promise => { const d = defaultUserValue; const { identifiers } = await datasource.getRepository(User).insert({ account_id: d?.account_id ?? -1, external_id: d?.external_id ?? uuidv4(), role: d?.role ?? `${ADMIN_ROLES.STANDARD} ${USER_ROLES.NONE}`, author_id: d?.author_id, accepted_terms_version: d?.accepted_terms_version, email_verified: d?.email_verified ?? true, auto_renew: d?.auto_renew ?? true, license_alert: d?.license_alert ?? true, notification: d?.notification ?? true, encryption: d?.encryption ?? true, encryption_password: d?.encryption_password, prompt: d?.prompt ?? true, created_by: d?.created_by ?? 'test_runner', created_at: d?.created_at ?? new Date(), updated_by: d?.updated_by ?? 'updater', updated_at: d?.updated_at ?? new Date(), }); const result = identifiers.pop() as User; return await datasource.getRepository(User).findOne({ where: { id: result.id, }, }); }; /** * テスト ユーティリティ: 指定IDのアカウントを取得する * @param dataSource データソース * @param id アカウントID * @returns 該当アカウント */ export const getAccount = async (dataSource: DataSource, id: number) => { return await dataSource.getRepository(Account).findOne({ where: { id: id }, }); }; /** * テスト ユーティリティ: すべてのアカウントを取得する * @param dataSource データソース * @returns 該当アカウント一覧 */ export const getAccounts = async ( dataSource: DataSource, ): Promise => { return await dataSource.getRepository(Account).find(); }; /** * テスト ユーティリティ: 指定ExternalIdのユーザーを取得する * @param dataSource データソース * @param externalId 外部ID * @returns 該当ユーザー */ export const getUserFromExternalId = async ( dataSource: DataSource, externalId: string, ) => { return await dataSource.getRepository(User).findOne({ where: { external_id: externalId }, }); }; /** * テスト ユーティリティ: 指定Idのユーザーを取得する * @param dataSource データソース * @param externalId 外部ID * @returns 該当ユーザー */ export const getUser = async ( datasource: DataSource, id: number, ): Promise => { const user = await datasource.getRepository(User).findOne({ where: { id: id, }, }); return user; }; /** * テスト ユーティリティ: すべてのユーザーを取得する * @param dataSource データソース * @returns 該当ユーザー一覧 */ export const getUsers = async (dataSource: DataSource): Promise => { return await dataSource.getRepository(User).find(); };