diff --git a/dictation_server/src/features/accounts/accounts.service.spec.ts b/dictation_server/src/features/accounts/accounts.service.spec.ts index a69b6b1..abe01f2 100644 --- a/dictation_server/src/features/accounts/accounts.service.spec.ts +++ b/dictation_server/src/features/accounts/accounts.service.spec.ts @@ -2752,7 +2752,6 @@ describe('createTypistGroup', () => { expect(typistGroupUsers.map((user) => user.user_id)).toEqual(userIds); } }); - it('typistIdsにRole:typist以外のユーザーが含まれていた場合、400エラーを返却する', async () => { if (!source) fail(); const module = await makeTestingModule(source); @@ -2859,6 +2858,58 @@ describe('createTypistGroup', () => { new HttpException(makeErrorResponse('E010204'), HttpStatus.BAD_REQUEST), ); }); + it('typistIdsにメール未認証のユーザーが含まれていた場合、400エラーを返却する', async () => { + if (!source) fail(); + const module = await makeTestingModule(source); + if (!module) fail(); + const adminExternalId = 'admin-external-id'; + // 第五階層のアカウント作成 + const { id: accountId } = ( + await makeTestAccount( + source, + { tier: 5 }, + { external_id: adminExternalId }, + ) + ).account; + // 作成したアカウントにユーザーを3名追加する + const typiptUserExternalIds = [ + 'typist-user-external-id1', + 'typist-user-external-id2', + 'typist-user-external-id3', + ]; + const userIds: number[] = []; + for (const typiptUserExternalId of typiptUserExternalIds) { + const user = await makeTestUser(source, { + account_id: accountId, + external_id: typiptUserExternalId, + role: 'typist', + email_verified: false, // メール未認証のユーザーを追加 + }); + userIds.push(user?.id ?? 0); + } + //作成したデータを確認 + { + const accounts = await getAccounts(source); + expect(accounts.length).toBe(1); + expect(accounts[0].id).toBe(accountId); + const users = await getUsers(source); + expect(users.length).toBe(4); + } + const service = module.get(AccountsService); + const typistGroupName = 'typist-group-name'; + const typistUserIds = [...userIds]; + const context = makeContext(adminExternalId); + await expect( + service.createTypistGroup( + context, + adminExternalId, + typistGroupName, + typistUserIds, + ), + ).rejects.toEqual( + new HttpException(makeErrorResponse('E010204'), HttpStatus.BAD_REQUEST), + ); + }); it('DBアクセスに失敗した場合、500エラーを返却する', async () => { if (!source) fail(); const module = await makeTestingModule(source); @@ -3338,6 +3389,69 @@ describe('updateTypistGroup', () => { } } }); + it('typistIdsにメール未認証のユーザーが含まれていた場合、400エラーを返却する', async () => { + if (!source) fail(); + const module = await makeTestingModule(source); + if (!module) fail(); + // 第五階層のアカウント作成 + const { account, admin } = await makeTestAccount(source, { tier: 5 }); + // 作成したアカウントにユーザーを3名追加する + const typiptUserExternalIds = [ + 'typist-user-external-id1', + 'typist-user-external-id2', + 'typist-user-external-id3', + ]; + const userIds: number[] = []; + for (const typiptUserExternalId of typiptUserExternalIds) { + const user = await makeTestUser(source, { + account_id: account.id, + external_id: typiptUserExternalId, + role: USER_ROLES.TYPIST, + email_verified: typiptUserExternalId !== 'typist-user-external-id3', //typist-user-external-id3のみメール未認証 + }); + userIds.push(user?.id ?? 0); + } + + const typistGroupName = 'typist-group-name'; + const service = module.get(AccountsService); + const typistUserIds = [...userIds]; + const context = makeContext(admin.external_id); + await service.createTypistGroup( + context, + admin.external_id, + typistGroupName, + [userIds[0]], + ); + + //作成したデータを確認 + const group = await getTypistGroup(source, account.id); + { + expect(group.length).toBe(1); + expect(group[0].name).toBe(typistGroupName); + const groupUsers = await getTypistGroupMember(source, group[0].id); + expect(groupUsers.length).toBe(1); + expect(groupUsers[0].user_group_id).toEqual(group[0].id); + expect(groupUsers[0].user_id).toEqual(userIds[0]); + } + const updateTypistGroupName = 'typist-group-name-update'; + + try { + await service.updateTypistGroup( + context, + admin.external_id, + group[0].id, + updateTypistGroupName, + typistUserIds, + ); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); + expect(e.getResponse()).toEqual(makeErrorResponse('E010204')); + } else { + fail(); + } + } + }); it('タイピストグループが存在しない場合、400エラーを返却する', async () => { if (!source) fail(); const module = await makeTestingModule(source); @@ -5843,6 +5957,185 @@ describe('getAuthors', () => { } }); }); + +describe('getTypists', () => { + let source: DataSource | null = null; + beforeEach(async () => { + source = new DataSource({ + type: 'sqlite', + database: ':memory:', + logging: false, + entities: [__dirname + '/../../**/*.entity{.ts,.js}'], + synchronize: true, // trueにすると自動的にmigrationが行われるため注意 + }); + return source.initialize(); + }); + + afterEach(async () => { + if (!source) return; + await source.destroy(); + source = null; + }); + it('アカウント内のTypistユーザーの一覧を取得できる', async () => { + if (!source) fail(); + const module = await makeTestingModule(source); + if (!module) fail(); + // 第五階層のアカウント作成 + const { account, admin } = await makeTestAccount(source, { tier: 5 }); + + const userId1 = await makeTestUser(source, { + account_id: account.id, + role: USER_ROLES.TYPIST, + external_id: 'typist1', + }); + const userId2 = await makeTestUser(source, { + account_id: account.id, + role: USER_ROLES.TYPIST, + external_id: 'typist2', + }); + const userId3 = await makeTestUser(source, { + account_id: account.id, + role: USER_ROLES.AUTHOR, + author_id: 'AUTHOR_ID_1', + external_id: 'author1', + }); + + // 作成したデータを確認 + { + const users = await getUsers(source); + expect(users.length).toBe(4); + expect(users[1].id).toBe(userId1.id); + expect(users[2].id).toBe(userId2.id); + expect(users[3].id).toBe(userId3.id); + } + + const service = module.get(AccountsService); + overrideAdB2cService(service, { + getUsers: async () => [ + { id: admin.external_id, displayName: '' }, + { id: userId1.external_id, displayName: '' }, + { id: userId2.external_id, displayName: '' }, + { id: userId3.external_id, displayName: '' }, + ], + }); + + const typists = await service.getTypists(admin.external_id); + + //実行結果を確認 + { + expect(typists.length).toBe(2); + expect(typists[0].id).toBe(userId1.id); + expect(typists[1].id).toBe(userId2.id); + } + }); + it('アカウント内のTypistユーザーの一覧を取得できる(0件)', async () => { + if (!source) fail(); + const module = await makeTestingModule(source); + if (!module) fail(); + // 第五階層のアカウント作成 + const { admin } = await makeTestAccount(source, { tier: 5 }); + + // 作成したデータを確認 + { + const users = await getUsers(source); + expect(users.length).toBe(1); + } + + const service = module.get(AccountsService); + + overrideAdB2cService(service, { + getUsers: async () => [{ id: admin.external_id, displayName: '' }], + }); + const typists = await service.getTypists(admin.external_id); + + //実行結果を確認 + { + expect(typists.length).toBe(0); + } + }); + + it('アカウント内のTypistユーザーの一覧を取得できる(メール認証済みユーザーのみ)', async () => { + if (!source) fail(); + const module = await makeTestingModule(source); + if (!module) fail(); + // 第五階層のアカウント作成 + const { account, admin } = await makeTestAccount(source, { tier: 5 }); + + const userId1 = await makeTestUser(source, { + account_id: account.id, + role: USER_ROLES.TYPIST, + }); + const userId2 = await makeTestUser(source, { + account_id: account.id, + role: USER_ROLES.TYPIST, + }); + const userId3 = await makeTestUser(source, { + account_id: account.id, + role: USER_ROLES.TYPIST, + email_verified: false, + }); + + // 作成したデータを確認 + { + const users = await getUsers(source); + expect(users.length).toBe(4); + expect(users[1].id).toBe(userId1.id); + expect(users[2].id).toBe(userId2.id); + expect(users[3].id).toBe(userId3.id); + } + + const service = module.get(AccountsService); + overrideAdB2cService(service, { + getUsers: async () => [ + { id: admin.external_id, displayName: '' }, + { id: userId1.external_id, displayName: '' }, + { id: userId2.external_id, displayName: '' }, + { id: userId3.external_id, displayName: '' }, + ], + }); + + const typists = await service.getTypists(admin.external_id); + + //実行結果を確認 + { + expect(typists.length).toBe(2); + expect(typists[0].id).toBe(userId1.id); + expect(typists[1].id).toBe(userId2.id); + } + }); + it('DBアクセスに失敗した場合、500エラーとなる', async () => { + if (!source) fail(); + const module = await makeTestingModule(source); + if (!module) fail(); + // 第五階層のアカウント作成 + const { admin } = await makeTestAccount(source, { tier: 5 }); + + const service = module.get(AccountsService); + overrideAdB2cService(service, { + getUsers: async () => [{ id: admin.external_id, displayName: '' }], + }); + + //DBアクセスに失敗するようにする + const usersService = module.get( + UsersRepositoryService, + ); + usersService.findTypistUsers = jest.fn().mockRejectedValue('DB failed'); + + //実行結果を確認 + try { + await service.getTypists(admin.external_id); + fail(); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR); + expect(e.getResponse()).toEqual(makeErrorResponse('E009999')); + } else { + fail(); + } + } + }); +}); + describe('deleteAccountAndData', () => { let source: DataSource | null = null; beforeEach(async () => { diff --git a/dictation_server/src/features/tasks/tasks.service.spec.ts b/dictation_server/src/features/tasks/tasks.service.spec.ts index e8b0fdb..d997da1 100644 --- a/dictation_server/src/features/tasks/tasks.service.spec.ts +++ b/dictation_server/src/features/tasks/tasks.service.spec.ts @@ -1012,17 +1012,89 @@ describe('changeCheckoutPermission', () => { await createCheckoutPermissions(source, taskId, undefined, userGroupId); const service = module.get(TasksService); - await expect( - service.changeCheckoutPermission( + try { + await service.changeCheckoutPermission( makeContext('trackingId'), 1, [{ typistName: 'not-exist-user', typistUserId: 999 }], 'author-user-external-id', ['admin'], - ), - ).rejects.toEqual( - new HttpException(makeErrorResponse('E010204'), HttpStatus.BAD_REQUEST), + ); + fail(); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); + expect(e.getResponse()).toEqual(makeErrorResponse('E010204')); + } else { + fail(); + } + } + }); + + it('ユーザーがメール認証されていない場合、タスクのチェックアウト権限を変更できない', async () => { + if (!source) fail(); + const notificationhubServiceMockValue = + makeDefaultNotificationhubServiceMockValue(); + const module = await makeTaskTestingModuleWithNotificaiton( + source, + notificationhubServiceMockValue, ); + if (!module) fail(); + const { id: accountId } = await makeTestSimpleAccount(source); + const { id: typistUserId_1 } = await makeTestUser(source, { + account_id: accountId, + external_id: 'typist-user-external-id_1', + role: 'typist', + }); + const { id: typistUserId_2 } = await makeTestUser(source, { + account_id: accountId, + external_id: 'typist-user-external-id_2', + role: 'typist', + email_verified: false, + }); + const { id: authorUserId } = await makeTestUser(source, { + account_id: accountId, + external_id: 'author-user-external-id', + role: 'author', + author_id: 'MY_AUTHOR_ID', + }); + const { taskId } = await createTask( + source, + accountId, + authorUserId, + 'MY_AUTHOR_ID', + '', + '01', + '00000001', + 'Uploaded', + ); + const { userGroupId } = await createUserGroup( + source, + accountId, + 'USER_GROUP_A', + [typistUserId_1], + ); + await createCheckoutPermissions(source, taskId, typistUserId_1); + await createCheckoutPermissions(source, taskId, undefined, userGroupId); + const service = module.get(TasksService); + + try { + await service.changeCheckoutPermission( + makeContext('trackingId'), + 1, + [{ typistName: 'not-verified-user', typistUserId: typistUserId_2 }], + 'author-user-external-id', + ['admin'], + ); + fail(); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); + expect(e.getResponse()).toEqual(makeErrorResponse('E010204')); + } else { + fail(); + } + } }); it('ユーザーグループが存在しない場合、タスクのチェックアウト権限を変更できない', async () => { @@ -1066,17 +1138,23 @@ describe('changeCheckoutPermission', () => { await createCheckoutPermissions(source, taskId, undefined, userGroupId); const service = module.get(TasksService); - await expect( - service.changeCheckoutPermission( + try { + await service.changeCheckoutPermission( makeContext('trackingId'), 1, [{ typistName: 'not-exist-user-group', typistGroupId: 999 }], 'author-user-external-id', ['admin'], ), - ).rejects.toEqual( - new HttpException(makeErrorResponse('E010204'), HttpStatus.BAD_REQUEST), - ); + fail(); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); + expect(e.getResponse()).toEqual(makeErrorResponse('E010204')); + } else { + fail(); + } + } }); it('タスクが存在しない場合、タスクのチェックアウト権限を変更できない', async () => { @@ -1102,17 +1180,23 @@ describe('changeCheckoutPermission', () => { }); const service = module.get(TasksService); - await expect( - service.changeCheckoutPermission( + try { + await service.changeCheckoutPermission( makeContext('trackingId'), 1, [{ typistName: 'typist-user', typistUserId: typistUserId }], 'author-user-external-id', ['admin'], ), - ).rejects.toEqual( - new HttpException(makeErrorResponse('E010601'), HttpStatus.BAD_REQUEST), - ); + fail(); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); + expect(e.getResponse()).toEqual(makeErrorResponse('E010601')); + } else { + fail(); + } + } }); it('タスクのステータスがUploadedでない場合、タスクのチェックアウト権限を変更できない', async () => { @@ -1148,17 +1232,23 @@ describe('changeCheckoutPermission', () => { ); const service = module.get(TasksService); - await expect( - service.changeCheckoutPermission( + try { + await service.changeCheckoutPermission( makeContext('trackingId'), 1, [{ typistName: 'typist-user', typistUserId: typistUserId }], 'author-user-external-id', ['admin'], ), - ).rejects.toEqual( - new HttpException(makeErrorResponse('E010601'), HttpStatus.BAD_REQUEST), - ); + fail(); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); + expect(e.getResponse()).toEqual(makeErrorResponse('E010601')); + } else { + fail(); + } + } }); it('ユーザーのRoleがAuthorでタスクのAuthorIDと自身のAuthorIDが一致しない場合、タスクのチェックアウト権限を変更できない', async () => { @@ -1194,17 +1284,23 @@ describe('changeCheckoutPermission', () => { ); const service = module.get(TasksService); - await expect( - service.changeCheckoutPermission( + try { + await service.changeCheckoutPermission( makeContext('trackingId'), 1, [{ typistName: 'typist-user', typistUserId: typistUserId }], 'author-user-external-id', ['author'], ), - ).rejects.toEqual( - new HttpException(makeErrorResponse('E010601'), HttpStatus.BAD_REQUEST), - ); + fail(); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); + expect(e.getResponse()).toEqual(makeErrorResponse('E010601')); + } else { + fail(); + } + } }); it('通知に失敗した場合、エラーとなる', async () => { @@ -1254,20 +1350,23 @@ describe('changeCheckoutPermission', () => { await createCheckoutPermissions(source, taskId, undefined, userGroupId); const service = module.get(TasksService); - await expect( - service.changeCheckoutPermission( + try { + await service.changeCheckoutPermission( makeContext('trackingId'), 1, [{ typistName: 'typist-user-2', typistUserId: typistUserId_2 }], 'author-user-external-id', ['admin'], ), - ).rejects.toEqual( - new HttpException( - makeErrorResponse('E009999'), - HttpStatus.INTERNAL_SERVER_ERROR, - ), - ); + fail(); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR); + expect(e.getResponse()).toEqual(makeErrorResponse('E009999')); + } else { + fail(); + } + } }); }); diff --git a/dictation_server/src/features/workflows/workflows.service.spec.ts b/dictation_server/src/features/workflows/workflows.service.spec.ts index 4c17dad..e868605 100644 --- a/dictation_server/src/features/workflows/workflows.service.spec.ts +++ b/dictation_server/src/features/workflows/workflows.service.spec.ts @@ -883,6 +883,74 @@ describe('createWorkflows', () => { } }); + it('ルーティング候補ユーザーがメール未認証の場合、400エラーとなること', async () => { + if (!source) fail(); + const module = await makeTestingModule(source); + if (!module) fail(); + // 第五階層のアカウント作成 + const { account, admin } = await makeTestAccount(source, { tier: 5 }); + const { id: authorId } = await makeTestUser(source, { + external_id: 'author1', + author_id: 'AUTHOR1', + account_id: account.id, + role: USER_ROLES.AUTHOR, + }); + const { id: typistId } = await makeTestUser(source, { + external_id: 'typist1', + account_id: account.id, + role: USER_ROLES.TYPIST, + email_verified: false, + }); + + const { id: worktypeId } = await createWorktype( + source, + account.id, + 'worktype1', + ); + + const { id: templateId } = await createTemplateFile( + source, + account.id, + 'fileName1', + 'url1', + ); + + //作成したデータを確認 + { + const workflows = await getWorkflows(source, account.id); + const workflowTypists = await getAllWorkflowTypists(source); + expect(workflows.length).toBe(0); + expect(workflowTypists.length).toBe(0); + } + + const service = module.get(WorkflowsService); + const context = makeContext(admin.external_id); + + //実行結果を確認 + try { + await service.createWorkflow( + context, + admin.external_id, + authorId, + [ + { + typistId: typistId, + }, + ], + worktypeId, + templateId, + ); + fail(); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); + expect(e.getResponse()).toEqual(makeErrorResponse('E010204')); + } else { + fail(); + } + } + }); + it('DBにルーティング候補グループが存在しない場合、400エラーとなること', async () => { if (!source) fail(); const module = await makeTestingModule(source); @@ -1976,6 +2044,87 @@ describe('updateWorkflow', () => { } }); + it('Dルーティング候補ユーザーがメール未認証の場合、400エラーとなること', async () => { + if (!source) fail(); + const module = await makeTestingModule(source); + if (!module) fail(); + // 第五階層のアカウント作成 + const { account, admin } = await makeTestAccount(source, { tier: 5 }); + const { id: authorId1 } = await makeTestUser(source, { + external_id: 'author1', + author_id: 'AUTHOR1', + account_id: account.id, + role: USER_ROLES.AUTHOR, + }); + const { id: typistId1 } = await makeTestUser(source, { + external_id: 'typist1', + account_id: account.id, + role: USER_ROLES.TYPIST, + }); + const { id: typistId2 } = await makeTestUser(source, { + external_id: 'typist2', + account_id: account.id, + role: USER_ROLES.TYPIST, + email_verified: false, + }); + + const { id: worktypeId } = await createWorktype( + source, + account.id, + 'worktype1', + ); + + const { id: templateId } = await createTemplateFile( + source, + account.id, + 'fileName1', + 'url1', + ); + + const preWorkflow = await createWorkflow( + source, + account.id, + authorId1, + undefined, + undefined, + ); + await createWorkflowTypist(source, preWorkflow.id, typistId1); + + //作成したデータを確認 + { + const workflows = await getWorkflows(source, account.id); + expect(workflows.length).toBe(1); + } + + const service = module.get(WorkflowsService); + const context = makeContext(admin.external_id); + + //実行結果を確認 + try { + await service.updateWorkflow( + context, + admin.external_id, + preWorkflow.id, + authorId1, + [ + { + typistId: typistId2, + }, + ], + worktypeId, + templateId, + ); + fail(); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); + expect(e.getResponse()).toEqual(makeErrorResponse('E010204')); + } else { + fail(); + } + } + }); + it('DBにルーティング候補グループが存在しない場合、400エラーとなること', async () => { if (!source) fail(); const module = await makeTestingModule(source); diff --git a/dictation_server/src/repositories/tasks/tasks.repository.service.ts b/dictation_server/src/repositories/tasks/tasks.repository.service.ts index e3daecb..0c8b4cc 100644 --- a/dictation_server/src/repositories/tasks/tasks.repository.service.ts +++ b/dictation_server/src/repositories/tasks/tasks.repository.service.ts @@ -804,13 +804,14 @@ export class TasksRepositoryService { id: In(typistUserIds), account_id: account_id, role: USER_ROLES.TYPIST, + email_verified: true, deleted_at: IsNull(), }, }); // idはユニークであるため取得件数の一致でユーザーの存在を確認 if (typistUserIds.length !== userRecords.length) { throw new TypistUserNotFoundError( - `User not exists Error. reqUserId:${typistUserIds}; resUserId:${userRecords.map( + `User not exists or email not verified Error. reqUserId:${typistUserIds}; resUserId:${userRecords.map( (x) => x.id, )}`, ); diff --git a/dictation_server/src/repositories/user_groups/user_groups.repository.service.ts b/dictation_server/src/repositories/user_groups/user_groups.repository.service.ts index 2c15584..061e9e9 100644 --- a/dictation_server/src/repositories/user_groups/user_groups.repository.service.ts +++ b/dictation_server/src/repositories/user_groups/user_groups.repository.service.ts @@ -102,11 +102,12 @@ export class UserGroupsRepositoryService { id: In(typistIds), account_id: accountId, role: USER_ROLES.TYPIST, + email_verified: true, }, }); if (userRecords.length !== typistIds.length) { throw new TypistIdInvalidError( - `Typist user not exists Error. typistIds:${typistIds}; typistIds(DB):${userRecords.map( + `Typist user not exists or email not verified Error. typistIds:${typistIds}; typistIds(DB):${userRecords.map( (x) => x.id, )}`, ); @@ -153,11 +154,12 @@ export class UserGroupsRepositoryService { id: In(typistIds), account_id: accountId, role: USER_ROLES.TYPIST, + email_verified: true, }, }); if (userRecords.length !== typistIds.length) { throw new TypistIdInvalidError( - `Typist user not exists Error. typistIds:${typistIds}; typistIds(DB):${userRecords.map( + `Typist user not exists or email not verified Error. typistIds:${typistIds}; typistIds(DB):${userRecords.map( (x) => x.id, )}`, ); diff --git a/dictation_server/src/repositories/users/users.repository.service.ts b/dictation_server/src/repositories/users/users.repository.service.ts index e28e386..0331bcc 100644 --- a/dictation_server/src/repositories/users/users.repository.service.ts +++ b/dictation_server/src/repositories/users/users.repository.service.ts @@ -366,7 +366,7 @@ export class UsersRepositoryService { } /** - * アカウント内のタイピストユーザーを取得する + * アカウント内のメール認証済みのタイピストユーザーを取得する * @param sub * @returns typist users */ @@ -389,6 +389,7 @@ export class UsersRepositoryService { where: { account_id: user.account_id, role: USER_ROLES.TYPIST, + email_verified: true, deleted_at: IsNull(), }, }); diff --git a/dictation_server/src/repositories/workflows/workflows.repository.service.ts b/dictation_server/src/repositories/workflows/workflows.repository.service.ts index 72c05a0..fb9cb9b 100644 --- a/dictation_server/src/repositories/workflows/workflows.repository.service.ts +++ b/dictation_server/src/repositories/workflows/workflows.repository.service.ts @@ -106,10 +106,16 @@ export class WorkflowsRepositoryService { typist.typistId ? [typist.typistId] : [], ); const typistUsers = await userRepo.find({ - where: { account_id: accountId, id: In(typistIds) }, + where: { + account_id: accountId, + id: In(typistIds), + email_verified: true, + }, }); if (typistUsers.length !== typistIds.length) { - throw new UserNotFoundError(`typist not found. ids: ${typistIds}`); + throw new UserNotFoundError( + `typist not found or email not verified. ids: ${typistIds}`, + ); } // ルーティング候補ユーザーグループの存在確認 @@ -239,10 +245,16 @@ export class WorkflowsRepositoryService { typist.typistId ? [typist.typistId] : [], ); const typistUsers = await userRepo.find({ - where: { account_id: accountId, id: In(typistIds) }, + where: { + account_id: accountId, + id: In(typistIds), + email_verified: true, + }, }); if (typistUsers.length !== typistIds.length) { - throw new UserNotFoundError(`typist not found. ids: ${typistIds}`); + throw new UserNotFoundError( + `typist not found or email not verified. ids: ${typistIds}`, + ); } // ルーティング候補ユーザーグループの存在確認