saito.k 0907bd28af Merged PR 138: SendGridService内のprivateキーの取得方法を修正する
## 概要
[Task1736: SendGridService内のprivateキーの取得方法を修正する](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/1736)

- CryptoServiceの削除
- トークン発行・認証に使用するKeyを環境変数から取得するように修正
- 既存テストの修正

## レビューポイント
- Keyの取得関数の配置場所は妥当か

## UIの変更
- Before/Afterのスクショなど
- スクショ置き場

## 動作確認状況
- ローカルでテストが通ることを確認
- keyを使う処理(ユーザー追加)を実行して、成功することを確認

## 補足
- 修正した箇所のロールチェックはレビュー対象外
  - 「タスク 1830: 認証・認可を宣言的に扱える仕組みを既存処理に適用する」で調整してもらう想定
2023-06-09 05:35:39 +00:00

383 lines
12 KiB
TypeScript

import { ConfigModule, ConfigService } from '@nestjs/config';
import { Test, TestingModule } from '@nestjs/testing';
import { Aadb2cUser, B2cMetadata, JwkSignKey } from '../../../common/token';
import {
AdB2cService,
ConflictError,
} from '../../../gateways/adb2c/adb2c.service';
import { SendGridService } from '../../../gateways/sendgrid/sendgrid.service';
import { User } from '../../../repositories/users/entity/user.entity';
import { UsersRepositoryService } from '../../../repositories/users/users.repository.service';
import { UsersService } from '../users.service';
import { SortCriteria } from '../../../repositories/sort_criteria/entity/sort_criteria.entity';
import { SortCriteriaRepositoryService } from '../../../repositories/sort_criteria/sort_criteria.repository.service';
import {
SortDirection,
TaskListSortableAttribute,
} from '../../../common/types/sort';
export type CryptoMockValue = {
getPublicKey: string | Error;
};
export type SortCriteriaRepositoryMockValue = {
updateSortCriteria: SortCriteria | Error;
getSortCriteria: SortCriteria | Error;
};
export type UsersRepositoryMockValue = {
updateUserVerified: undefined | Error;
findUserById: User | Error;
createNormalUser: User | Error;
findSameAccountUsers: User[] | Error;
findUserByExternalId: User | Error;
existsAuthorId: boolean | Error;
};
export type AdB2cMockValue = {
getMetaData: B2cMetadata | Error;
getSignKeySets: JwkSignKey[] | Error;
changePassword: { sub: string } | Error;
createUser: string | ConflictError | Error;
getUser: Aadb2cUser | Error;
};
export type SendGridMockValue = {
createMailContentFromEmailConfirm: {
subject: string;
text: string;
html: string;
};
createMailContentFromEmailConfirmForNormalUser:
| { subject: string; text: string; html: string }
| Error;
sendMail: undefined | Error;
};
export const makeUsersServiceMock = async (
usersRepositoryMockValue: UsersRepositoryMockValue,
adB2cMockValue: AdB2cMockValue,
sendGridMockValue: SendGridMockValue,
configMockValue: ConfigMockValue,
sortCriteriaRepositoryMockValue: SortCriteriaRepositoryMockValue,
): Promise<UsersService> => {
const module: TestingModule = await Test.createTestingModule({
providers: [UsersService],
imports: [
ConfigModule.forRoot({
envFilePath: ['.env.local', '.env'],
}),
],
})
.useMocker((token) => {
switch (token) {
case UsersRepositoryService:
return makeUsersRepositoryMock(usersRepositoryMockValue);
case AdB2cService:
return makeAdB2cServiceMock(adB2cMockValue);
case SendGridService:
return makeSendGridMock(sendGridMockValue);
case ConfigService:
return makeConfigMock(configMockValue);
case SortCriteriaRepositoryService:
return makeSortCriteriaRepositoryMock(
sortCriteriaRepositoryMockValue,
);
}
})
.compile();
return module.get<UsersService>(UsersService);
};
export const makeSortCriteriaRepositoryMock = (
value: SortCriteriaRepositoryMockValue,
) => {
const { updateSortCriteria, getSortCriteria } = value;
return {
updateSortCriteria:
updateSortCriteria instanceof Error
? jest
.fn<
Promise<void>,
[number, TaskListSortableAttribute, SortDirection]
>()
.mockRejectedValue(updateSortCriteria)
: jest
.fn<
Promise<SortCriteria>,
[number, TaskListSortableAttribute, SortDirection]
>()
.mockResolvedValue(updateSortCriteria),
getSortCriteria:
getSortCriteria instanceof Error
? jest.fn<Promise<void>, [number]>().mockRejectedValue(getSortCriteria)
: jest
.fn<Promise<SortCriteria>, [number]>()
.mockResolvedValue(getSortCriteria),
};
};
export const makeSendGridServiceMock = (value: SendGridMockValue) => {
const { createMailContentFromEmailConfirm, sendMail } = value;
return {
createMailContentFromEmailConfirm:
createMailContentFromEmailConfirm instanceof Error
? jest
.fn<Promise<void>, []>()
.mockRejectedValue(createMailContentFromEmailConfirm)
: jest
.fn<Promise<{ subject: string; text: string; html: string }>, []>()
.mockResolvedValue(createMailContentFromEmailConfirm),
sendMail:
sendMail instanceof Error
? jest.fn<Promise<void>, []>().mockRejectedValue(sendMail)
: jest.fn<Promise<void>, []>().mockResolvedValue(sendMail),
};
};
export const makeAdB2cServiceMock = (value: AdB2cMockValue) => {
const { getMetaData, getSignKeySets, changePassword, createUser, getUser } =
value;
return {
getMetaData:
getMetaData instanceof Error
? jest.fn<Promise<void>, []>().mockRejectedValue(getMetaData)
: jest.fn<Promise<B2cMetadata>, []>().mockResolvedValue(getMetaData),
getSignKeySets:
getSignKeySets instanceof Error
? jest.fn<Promise<void>, []>().mockRejectedValue(getSignKeySets)
: jest
.fn<Promise<JwkSignKey[]>, []>()
.mockResolvedValue(getSignKeySets),
changePassword:
changePassword instanceof Error
? jest.fn<Promise<void>, []>().mockRejectedValue(changePassword)
: jest
.fn<Promise<{ sub: string }>, []>()
.mockResolvedValue(changePassword),
createUser:
createUser instanceof Error
? jest.fn<Promise<ConflictError>, []>().mockRejectedValue(createUser)
: jest
.fn<Promise<string | ConflictError>, []>()
.mockResolvedValue(createUser),
getUser:
getUser instanceof Error
? jest
.fn<Promise<Aadb2cUser | undefined>, []>()
.mockRejectedValue(getUser)
: jest
.fn<Promise<Aadb2cUser | undefined>, []>()
.mockResolvedValue(getUser),
};
};
export type ConfigMockValue = {
get: string | Error;
};
export const makeCryptoServiceMock = (value: CryptoMockValue) => {
const { getPublicKey } = value;
return {
getPublicKey:
getPublicKey instanceof Error
? jest.fn<Promise<void>, []>().mockRejectedValue(getPublicKey)
: jest.fn<Promise<string>, []>().mockResolvedValue(getPublicKey),
};
};
class authorIdError extends Error {
constructor(public code: string, e?: string) {
super(e);
}
}
export const makeUsersRepositoryMock = (value: UsersRepositoryMockValue) => {
const {
updateUserVerified,
findUserById,
createNormalUser,
findSameAccountUsers,
findUserByExternalId,
existsAuthorId,
} = value;
const aIdError = new authorIdError('ER_DUP_ENTRY');
return {
updateUserVerified:
updateUserVerified instanceof Error
? jest.fn<Promise<void>, []>().mockRejectedValue(updateUserVerified)
: jest.fn<Promise<void>, []>().mockResolvedValue(updateUserVerified),
findUserById:
findUserById instanceof Error
? jest.fn<Promise<void>, []>().mockRejectedValue(findUserById)
: jest.fn<Promise<User>, []>().mockResolvedValue(findUserById),
createNormalUser:
createNormalUser instanceof Error
? createNormalUser.name == 'ER_DUP_ENTRY'
? jest.fn<Promise<void>, []>().mockRejectedValue(aIdError)
: jest.fn<Promise<void>, []>().mockRejectedValue(createNormalUser)
: jest.fn<Promise<User>, []>().mockResolvedValue(createNormalUser),
findSameAccountUsers:
findSameAccountUsers instanceof Error
? jest
.fn<Promise<User[] | undefined>, []>()
.mockRejectedValue(findSameAccountUsers)
: jest
.fn<Promise<User[] | undefined>, []>()
.mockResolvedValue(findSameAccountUsers),
findUserByExternalId:
findUserByExternalId instanceof Error
? jest.fn<Promise<void>, []>().mockRejectedValue(findUserByExternalId)
: jest.fn<Promise<User>, []>().mockResolvedValue(findUserByExternalId),
existsAuthorId:
existsAuthorId instanceof Error
? jest.fn<Promise<void>, []>().mockRejectedValue(existsAuthorId)
: jest.fn<Promise<boolean>, []>().mockResolvedValue(existsAuthorId),
};
};
export const makeSendGridMock = (value: SendGridMockValue) => {
const { sendMail, createMailContentFromEmailConfirmForNormalUser } = value;
return {
sendMail:
sendMail instanceof Error
? jest.fn<Promise<void>, []>().mockRejectedValue(sendMail)
: jest.fn<Promise<void>, []>().mockResolvedValue(sendMail),
createMailContentFromEmailConfirmForNormalUser:
createMailContentFromEmailConfirmForNormalUser instanceof Error
? jest
.fn<Promise<void>, []>()
.mockRejectedValue(createMailContentFromEmailConfirmForNormalUser)
: jest
.fn<Promise<{ subject: string; text: string; html: string }>, []>()
.mockResolvedValue(createMailContentFromEmailConfirmForNormalUser),
};
};
export const makeConfigMock = (value: ConfigMockValue) => {
const { get } = value;
return {
get:
get instanceof Error
? jest.fn<Promise<void>, []>().mockRejectedValue(get)
: jest.fn<Promise<string>, []>().mockResolvedValue(get),
};
};
export const makeDefaultSendGridlValue = (): SendGridMockValue => {
return {
sendMail: undefined,
createMailContentFromEmailConfirm: { subject: '', text: '', html: '' },
createMailContentFromEmailConfirmForNormalUser: {
subject: 'test',
text: 'test',
html: 'test',
},
};
};
export const makeDefaultConfigValue = (): ConfigMockValue => {
return {
get: `test@example.co.jp`,
};
};
export const makeDefaultSortCriteriaRepositoryMockValue =
(): SortCriteriaRepositoryMockValue => {
const sortCriteria = new SortCriteria();
{
sortCriteria.id = 1;
sortCriteria.direction = 'ASC';
sortCriteria.parameter = 'JOB_NUMBER';
sortCriteria.user_id = 1;
}
return {
updateSortCriteria: sortCriteria,
getSortCriteria: sortCriteria,
};
};
export const makeDefaultAdB2cMockValue = (): AdB2cMockValue => {
return {
getMetaData: {
issuer: 'issuer',
},
getSignKeySets: [
{
kid: 'kid',
nbf: 1111111111,
use: 'sig',
kty: 'RSA',
e: 'e',
n: 'n',
},
],
changePassword: {
sub: 'TEST9999',
},
createUser: '001',
getUser: {
displayName: 'Hanako Sato',
mail: 'hanako@sample.com',
},
};
};
// 個別のテストケースに対応してそれぞれのMockを用意するのは無駄が多いのでテストケース内で個別の値を設定する
export const makeDefaultUsersRepositoryMockValue =
(): UsersRepositoryMockValue => {
const newUser = new User();
newUser.id = 111;
const user1 = new User();
user1.id = 2;
user1.external_id = 'ede66c43-9b9d-4222-93ed-5f11c96e08e2';
user1.account_id = 1234567890123456;
user1.role = 'none';
user1.author_id = '6cce347f-0cf1-a15e-19ab-d00988b643f9';
user1.accepted_terms_version = '1.0';
user1.email_verified = true;
user1.auto_renew = false;
user1.license_alert = false;
user1.notification = false;
user1.deleted_at = null;
user1.created_by = 'test';
user1.created_at = new Date();
user1.updated_by = null;
user1.updated_at = null;
const user2 = new User();
user2.id = 3;
user2.external_id = '698176dc-4028-4638-a452-f00bf62a7781';
user2.account_id = 1234567890123456;
user2.role = 'none';
user2.author_id = '551c4077-5b55-a38c-2c55-cd1edd537aa8';
user2.accepted_terms_version = '1.0';
user2.email_verified = true;
user2.auto_renew = false;
user2.license_alert = false;
user2.notification = false;
user2.deleted_at = null;
user2.created_by = 'test';
user2.created_at = new Date();
user2.updated_by = null;
user2.updated_at = null;
return {
updateUserVerified: undefined,
findUserById: newUser,
createNormalUser: newUser,
findSameAccountUsers: [user1, user2],
findUserByExternalId: newUser,
existsAuthorId: false,
};
};