import { v4 as uuidv4 } from 'uuid'; import { DataSource } from 'typeorm'; import { User, UserArchive } from '../../repositories/users/entity/user.entity'; import { Account } from '../../repositories/accounts/entity/account.entity'; import { ADMIN_ROLES, FILE_RETENTION_DAYS_DEFAULT, USER_ROLES, } from '../../constants'; import { License } from '../../repositories/licenses/entity/license.entity'; import { AccountArchive } from '../../repositories/accounts/entity/account_archive.entity'; import { Task } from '../../repositories/tasks/entity/task.entity'; import { JobNumber } from '../../repositories/job_number/entity/job_number.entity'; import { SortCriteria } from '../../repositories/sort_criteria/entity/sort_criteria.entity'; 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 tier1 = state.tier1Accounts.slice().shift(); { const { account, admin } = await makeTestAccount(datasource, { tier: 2, parent_account_id: tier1?.account.id, company_name: 'OMDS_US', }); state.tier2Accounts.push({ account: account, users: [admin], }); } { const { account, admin } = await makeTestAccount(datasource, { tier: 2, parent_account_id: tier1?.account.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, auto_file_delete: d?.auto_file_delete ?? false, file_retention_days: d?.file_retention_days ?? FILE_RETENTION_DAYS_DEFAULT, 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_eula_version: d?.accepted_eula_version ?? '1.0', accepted_privacy_notice_version: d?.accepted_privacy_notice_version ?? '1.0', accepted_dpa_version: d?.accepted_dpa_version ?? '1.0', email_verified: d?.email_verified ?? true, auto_renew: d?.auto_renew ?? 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: number | null = 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, }, }); if (!account || !admin) { throw new Error('Unexpected null'); } // sort_criteriaテーブルにデータを追加 await createSortCriteria(datasource, userId, 'JOB_NUMBER', 'ASC'); // job_numberテーブルにデータを追加 await createJobNumber(datasource, accountId, '00000000'); 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, auto_file_delete: d?.auto_file_delete ?? false, file_retention_days: d?.file_retention_days ?? FILE_RETENTION_DAYS_DEFAULT, 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, }, }); if (!account) { throw new Error('Unexpected null'); } 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_eula_version: d?.accepted_eula_version ?? '1.0', accepted_dpa_version: d?.accepted_dpa_version ?? '1.0', email_verified: d?.email_verified ?? true, auto_renew: d?.auto_renew ?? 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; const user = await datasource.getRepository(User).findOne({ where: { id: result.id, }, }); if (!user) { throw new Error('Unexpected null'); } // sort_criteriaテーブルにデータを追加 await createSortCriteria(datasource, user.id, 'FILE_LENGTH', 'ASC'); return user; }; /** * テスト ユーティリティ: 指定IDのアカウントを取得する * @param dataSource データソース * @param id アカウントID * @returns 該当アカウント */ export const getAccount = async ( dataSource: DataSource, id: number, ): Promise => { 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(); }; /** * テスト ユーティリティ: ユーザー退避テーブルの内容を取得する * @param dataSource データソース * @returns ユーザー退避テーブルの内容 */ export const getAccountArchive = async ( dataSource: DataSource, ): Promise => { return await dataSource.getRepository(AccountArchive).find(); }; export const getUserArchive = async ( dataSource: DataSource, ): Promise => { return await dataSource.getRepository(UserArchive).find(); }; export const getLicenses = async ( datasource: DataSource, account_id: number, ): Promise => { const licenses = await datasource.getRepository(License).find({ where: { account_id: account_id, }, }); return licenses; }; export const getTasks = async ( datasource: DataSource, account_id: number, ): Promise => { const tasks = await datasource.getRepository(Task).find({ where: { account_id: account_id }, }); return tasks; }; // job_numberテーブルにレコードを作成する export const createJobNumber = async ( datasource: DataSource, accountId: number, jobNumber: string, ): Promise => { await datasource.getRepository(JobNumber).insert({ account_id: accountId, job_number: jobNumber, }); }; // job_numberテーブルのレコードを更新する export const updateJobNumber = async ( datasource: DataSource, accountId: number, jobNumber: string, ): Promise => { await datasource.getRepository(JobNumber).update( { account_id: accountId }, { job_number: jobNumber, }, ); }; // job_numberを取得する export const getJobNumber = async ( datasource: DataSource, account_id: number, ): Promise => { const jobNumber = await datasource.getRepository(JobNumber).findOne({ where: { account_id: account_id, }, }); return jobNumber; }; // sort_criteriaを作成する export const createSortCriteria = async ( datasource: DataSource, userId: number, parameter: string, direction: string, ): Promise => { await datasource.getRepository(SortCriteria).insert({ user_id: userId, parameter: parameter, direction: direction, }); }; // 指定したユーザーのsort_criteriaを更新する export const updateSortCriteria = async ( datasource: DataSource, userId: number, parameter: string, direction: string, ): Promise => { await datasource.getRepository(SortCriteria).update( { user_id: userId }, { parameter: parameter, direction: direction, }, ); }; // 指定したユーザーのsort_criteriaを取得する export const getSortCriteria = async ( datasource: DataSource, userId: number, ): Promise => { const sortCriteria = await datasource.getRepository(SortCriteria).findOne({ where: { user_id: userId, }, }); return sortCriteria; };