makabe.t bd4aaa8ae1 Merged PR 63: API実装(メール認証)
## 概要
[Task1497: API実装(メール認証)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/1497)

- メール認証APIとテストを実装しました。

- IDトークンの型を現状と合わせて修正しました
  - `family_name`と`given_name`を削除しました。
- auth.serviceのテストも併せて修正しました。
  - テストケースのIDトークンを環境変数の鍵で生成するように修正しました。

## レビューポイント
- DBのユーザを検証済みにする処理について、トランザクション内で取得と更新をしていますがトランザクションの使い方として問題ないでしょうか?
- 本APIで使用するカスタムエラーを`common/error/types`に暫定的においていますがどこに配置するのが適切でしょうか?
  - `common/error/types`に配置する、もしくは`common`配下にカスタムエラー用のフォルダを作成してその下に配置するのが良いかと考えています。
- テストのモックでエラーを発生させる際に、テストケース内でエラーを設定していますがモックファイル内でエラー用のモックを設定するべきでしょうか?

## UIの変更
- なし

## 動作確認状況
- ローカルで確認
  - テストが通ることを確認
2023-04-10 04:44:16 +00:00

107 lines
3.2 KiB
TypeScript

import { Test, TestingModule } from '@nestjs/testing';
import { AdB2cService } from '../../../gateways/adb2c/adb2c.service';
import { CryptoService } from '../../../gateways/crypto/crypto.service';
import { JwkSignKey, B2cMetadata } from '../../../common/token';
import { AuthService } from '../auth.service';
import { ConfigService } from '@nestjs/config';
import { UsersRepositoryService } from '../../../repositories/users/users.repository.service';
export type AdB2cMockValue = {
getMetaData: B2cMetadata | Error;
getSignKeySets: JwkSignKey[] | Error;
};
export type CryptoMockValue = {
getPublicKeyFromJwk: string | Error;
};
export const makeAuthServiceMock = async (
adB2cMockValue: AdB2cMockValue,
cryptoMockValue: CryptoMockValue,
): Promise<AuthService> => {
const module: TestingModule = await Test.createTestingModule({
providers: [AuthService],
})
.useMocker((token) => {
switch (token) {
case AdB2cService:
return makeAdB2cServiceMock(adB2cMockValue);
case CryptoService:
return makeCryptoServiceMock(cryptoMockValue);
case ConfigService:
return {};
case UsersRepositoryService:
return {};
}
})
.compile();
return module.get<AuthService>(AuthService);
};
export const makeDefaultAdB2cMockValue = (): AdB2cMockValue => {
return {
getMetaData: {
issuer: 'issuer',
},
getSignKeySets: [
{
kid: 'kid',
nbf: 1111111111,
use: 'sig',
kty: 'RSA',
e: 'e',
n: 'n',
},
],
};
};
export const makeAdB2cServiceMock = (value: AdB2cMockValue) => {
const { getMetaData, getSignKeySets } = 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),
};
};
export const makeDefaultCryptoMockValue = (): CryptoMockValue => {
return {
getPublicKeyFromJwk: [
'-----BEGIN PUBLIC KEY-----',
'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5IZZNgDew9eGmuFTezwd',
'HYLSaJvUPPIKYoiOeVLD1paWNI517Vkaoh0ngprcKOdv6T1N07V4igK7mOim2zY3',
'yCTR6wcWR3PfFJrl9vh5SOo79koZoJb27YiM4jtxfx2dezzp0T2GoNR5rRolPUbW',
'FJXnDe0DVXYXpJLb4LAlF2XAyYX0SYKUVUsJnzm5k4xbXtnwPwVbpm0EdswBE6qS',
'fiL9zWk9dvHoKzSnfSDzDFoFcEoVchawzYXf/MM1YR4wo5XyzECc6Q5Ah4z522//',
'mBNNaDHv83Yuw3mGShT73iJ0JQdkTturshv2Ecma38r6ftrIwNYXw4VVatJM8+GO',
'OQIDAQAB',
'-----END PUBLIC KEY-----',
].join('\n'),
};
};
export const makeCryptoServiceMock = (value: CryptoMockValue) => {
const { getPublicKeyFromJwk } = value;
return {
getPublicKeyFromJwk:
getPublicKeyFromJwk instanceof Error
? jest
.fn<Promise<void>, [JwkSignKey]>()
.mockRejectedValue(getPublicKeyFromJwk)
: jest
.fn<Promise<string>, [JwkSignKey]>()
.mockResolvedValue(getPublicKeyFromJwk),
};
};