From 5c0d5f6476a5d1f03262c15209fff60eb6f39504 Mon Sep 17 00:00:00 2001 From: "makabe.t" Date: Tue, 14 Nov 2023 02:10:32 +0000 Subject: [PATCH] =?UTF-8?q?Merged=20PR=20574:=20=E6=9C=AA=E8=AA=8D?= =?UTF-8?q?=E8=A8=BC=E3=81=AEAuthorID=E3=81=AF=E9=81=B8=E6=8A=9E=E3=81=A7?= =?UTF-8?q?=E3=81=8D=E3=81=AA=E3=81=84=E3=82=88=E3=81=86=E3=81=AB=E3=81=99?= =?UTF-8?q?=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 概要 [Task2819: 未認証のAuthorIDは選択できないようにする](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2819) - Author取得APIではメール認証済みのユーザーのみ取得するように修正しました。 - Workflowの追加/編集APIでメール未認証のAuthorを指定して実行するとエラーとなるように修正しました。 - 修正APIに対応したテストケースを追加しました。 ## レビューポイント - 対応箇所は適切でしょうか? ## UIの変更 - なし ## 動作確認状況 - ローカルで確認 --- .../accounts/accounts.service.spec.ts | 38 +++++ .../workflows/workflows.service.spec.ts | 137 ++++++++++++++++++ .../users/users.repository.service.ts | 3 +- .../workflows/workflows.repository.service.ts | 12 +- 4 files changed, 185 insertions(+), 5 deletions(-) diff --git a/dictation_server/src/features/accounts/accounts.service.spec.ts b/dictation_server/src/features/accounts/accounts.service.spec.ts index 3742cad..a69b6b1 100644 --- a/dictation_server/src/features/accounts/accounts.service.spec.ts +++ b/dictation_server/src/features/accounts/accounts.service.spec.ts @@ -5754,6 +5754,44 @@ describe('getAuthors', () => { expect(authors[1].authorId).toBe('AUTHOR_ID_2'); } }); + it('アカウント内のAuthorユーザーの一覧を取得できる(未認証ユーザー以外)', 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.AUTHOR, + author_id: 'AUTHOR_ID_1', + }); + const userId2 = await makeTestUser(source, { + account_id: account.id, + role: USER_ROLES.AUTHOR, + author_id: 'AUTHOR_ID_2', + email_verified: false, + }); + + // 作成したデータを確認 + { + const users = await getUsers(source); + expect(users.length).toBe(3); + expect(users[1].id).toBe(userId1.id); + expect(users[2].id).toBe(userId2.id); + } + + const service = module.get(AccountsService); + const context = makeContext(admin.external_id); + const authors = await service.getAuthors(context, admin.external_id); + + //実行結果を確認 + { + expect(authors.length).toBe(1); + expect(authors[0].id).toBe(userId1.id); + expect(authors[0].authorId).toBe('AUTHOR_ID_1'); + } + }); it('アカウント内のAuthorユーザーの一覧を取得できる(0件)', async () => { if (!source) fail(); const module = await makeTestingModule(source); diff --git a/dictation_server/src/features/workflows/workflows.service.spec.ts b/dictation_server/src/features/workflows/workflows.service.spec.ts index 3d4a65d..4c17dad 100644 --- a/dictation_server/src/features/workflows/workflows.service.spec.ts +++ b/dictation_server/src/features/workflows/workflows.service.spec.ts @@ -588,6 +588,56 @@ describe('createWorkflows', () => { } }); + it('Authorがメール未認証の場合、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, + email_verified: false, + }); + const { id: typistId } = await makeTestUser(source, { + external_id: 'typist1', + account_id: account.id, + role: USER_ROLES.TYPIST, + }); + + //作成したデータを確認 + { + 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 }], + undefined, + undefined, + ); + fail(); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); + expect(e.getResponse()).toEqual(makeErrorResponse('E010204')); + } else { + fail(); + } + } + }); + it('DBにAuthorが存在しない場合、400エラーとなること', async () => { if (!source) fail(); const module = await makeTestingModule(source); @@ -639,6 +689,7 @@ describe('createWorkflows', () => { worktypeId, templateId, ); + fail(); } catch (e) { if (e instanceof HttpException) { expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); @@ -699,6 +750,7 @@ describe('createWorkflows', () => { 9999, templateId, ); + fail(); } catch (e) { if (e instanceof HttpException) { expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); @@ -758,6 +810,7 @@ describe('createWorkflows', () => { worktypeId, 9999, ); + fail(); } catch (e) { if (e instanceof HttpException) { expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); @@ -819,6 +872,7 @@ describe('createWorkflows', () => { worktypeId, templateId, ); + fail(); } catch (e) { if (e instanceof HttpException) { expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); @@ -880,6 +934,7 @@ describe('createWorkflows', () => { worktypeId, templateId, ); + fail(); } catch (e) { if (e instanceof HttpException) { expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); @@ -950,6 +1005,7 @@ describe('createWorkflows', () => { worktypeId, templateId, ); + fail(); } catch (e) { if (e instanceof HttpException) { expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); @@ -1024,6 +1080,7 @@ describe('createWorkflows', () => { worktypeId, templateId, ); + fail(); } catch (e) { if (e instanceof HttpException) { expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR); @@ -1514,6 +1571,78 @@ describe('updateWorkflow', () => { } }); + it('Authorがメール未認証の場合、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: authorId2 } = await makeTestUser(source, { + external_id: 'author2', + author_id: 'AUTHOR2', + account_id: account.id, + role: USER_ROLES.AUTHOR, + email_verified: false, + }); + const { id: typistId1 } = await makeTestUser(source, { + external_id: 'typist1', + account_id: account.id, + role: USER_ROLES.TYPIST, + }); + + const preWorkflow = await createWorkflow( + source, + account.id, + authorId1, + undefined, + undefined, + ); + await createWorkflowTypist(source, preWorkflow.id, typistId1); + + //作成したデータを確認 + { + const workflows = await getWorkflows(source, account.id); + const workflowTypists = await getAllWorkflowTypists(source); + expect(workflows.length).toBe(1); + expect(workflows[0].id).toBe(preWorkflow.id); + expect(workflows[0].account_id).toBe(account.id); + expect(workflows[0].author_id).toBe(authorId1); + expect(workflows[0].worktype_id).toBe(null); + expect(workflows[0].template_id).toBe(null); + expect(workflowTypists.length).toBe(1); + } + + const service = module.get(WorkflowsService); + const context = makeContext(admin.external_id); + + //実行結果を確認 + try { + await service.updateWorkflow( + context, + admin.external_id, + preWorkflow.id, + authorId2, + [{ typistId: typistId1 }], + undefined, + undefined, + ); + fail(); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); + expect(e.getResponse()).toEqual(makeErrorResponse('E010204')); + } else { + fail(); + } + } + }); + it('DBにWorkflowが存在しない場合、400エラーとなること', async () => { if (!source) fail(); const module = await makeTestingModule(source); @@ -1550,6 +1679,7 @@ describe('updateWorkflow', () => { undefined, undefined, ); + fail(); } catch (e) { if (e instanceof HttpException) { expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); @@ -1623,6 +1753,7 @@ describe('updateWorkflow', () => { worktypeId, templateId, ); + fail(); } catch (e) { if (e instanceof HttpException) { expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); @@ -1691,6 +1822,7 @@ describe('updateWorkflow', () => { 9999, templateId, ); + fail(); } catch (e) { if (e instanceof HttpException) { expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); @@ -1758,6 +1890,7 @@ describe('updateWorkflow', () => { worktypeId, 9999, ); + fail(); } catch (e) { if (e instanceof HttpException) { expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); @@ -1832,6 +1965,7 @@ describe('updateWorkflow', () => { worktypeId, templateId, ); + fail(); } catch (e) { if (e instanceof HttpException) { expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); @@ -1906,6 +2040,7 @@ describe('updateWorkflow', () => { worktypeId, templateId, ); + fail(); } catch (e) { if (e instanceof HttpException) { expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); @@ -1974,6 +2109,7 @@ describe('updateWorkflow', () => { worktypeId1, undefined, ); + fail(); } catch (e) { if (e instanceof HttpException) { expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); @@ -2050,6 +2186,7 @@ describe('updateWorkflow', () => { undefined, undefined, ); + fail(); } catch (e) { if (e instanceof HttpException) { expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR); diff --git a/dictation_server/src/repositories/users/users.repository.service.ts b/dictation_server/src/repositories/users/users.repository.service.ts index 7f393c0..e28e386 100644 --- a/dictation_server/src/repositories/users/users.repository.service.ts +++ b/dictation_server/src/repositories/users/users.repository.service.ts @@ -398,7 +398,7 @@ export class UsersRepositoryService { } /** - * アカウント内のAuthorユーザーを取得する + * アカウント内のEmail認証済みのAuthorユーザーを取得する * @param accountId * @returns author users */ @@ -409,6 +409,7 @@ export class UsersRepositoryService { where: { account_id: accountId, role: USER_ROLES.AUTHOR, + 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 8a4ccf3..72c05a0 100644 --- a/dictation_server/src/repositories/workflows/workflows.repository.service.ts +++ b/dictation_server/src/repositories/workflows/workflows.repository.service.ts @@ -69,10 +69,12 @@ export class WorkflowsRepositoryService { // authorの存在確認 const userRepo = entityManager.getRepository(User); const author = await userRepo.findOne({ - where: { account_id: accountId, id: authorId }, + where: { account_id: accountId, id: authorId, email_verified: true }, }); if (!author) { - throw new UserNotFoundError(`author not found. id: ${authorId}`); + throw new UserNotFoundError( + `author not found or email not verified. id: ${authorId}`, + ); } // worktypeの存在確認 @@ -198,10 +200,12 @@ export class WorkflowsRepositoryService { // authorの存在確認 const userRepo = entityManager.getRepository(User); const author = await userRepo.findOne({ - where: { account_id: accountId, id: authorId }, + where: { account_id: accountId, id: authorId, email_verified: true }, }); if (!author) { - throw new UserNotFoundError(`author not found. id: ${authorId}`); + throw new UserNotFoundError( + `author not found or email not verified. id: ${authorId}`, + ); } // worktypeの存在確認