maruyama.t cad3a99f70 Merged PR 794: 登録ツールにログを仕込む
## 概要
[Task3839: 登録ツールにログを仕込む](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/3839)

登録ツールが途中で動かなくなってしまう原因調査のために各関数にログを仕込みました。

## レビューポイント
- 特になし

## 動作確認状況
- ローカルで確認

## 補足
- 相談、参考資料などがあれば
2024-02-29 12:50:17 +00:00

311 lines
9.4 KiB
TypeScript

import { HttpException, HttpStatus, Injectable, Logger } from "@nestjs/common";
import { makeErrorResponse } from "../../common/error/makeErrorResponse";
import { makePassword } from "../../common/password/password";
import {
AdB2cService,
ConflictError,
isConflictError,
} from "../../gateways/adb2c/adb2c.service";
import {
User as EntityUser,
newUser,
} from "../../repositories/users/entity/user.entity";
import { UsersRepositoryService } from "../../repositories/users/users.repository.service";
import { MANUAL_RECOVERY_REQUIRED, USER_ROLES } from "../../constants";
import { Context } from "../../common/log";
import { UserRoles } from "../../common/types/role";
@Injectable()
export class UsersService {
private readonly logger = new Logger(UsersService.name);
constructor(
private readonly usersRepository: UsersRepositoryService,
private readonly adB2cService: AdB2cService
) {}
/**
* Creates user
* @param context
* @param name
* @param role
* @param email
* @param autoRenew
* @param notification
* @param accountId
* @param userid
* @param [authorId]
* @param [encryption]
* @param [encryptionPassword]
* @param [prompt]
* @returns user
*/
async createUser(
context: Context,
name: string,
role: UserRoles,
email: string,
autoRenew: boolean,
notification: boolean,
accountId: number,
userid: number,
authorId?: string | undefined,
encryption?: boolean | undefined,
encryptionPassword?: string | undefined,
prompt?: boolean | undefined
): Promise<void> {
this.logger.log(
`[IN] [${context.getTrackingId()}] ${this.createUser.name} | params: { ` +
`role: ${role}, ` +
`autoRenew: ${autoRenew}, ` +
`notification: ${notification}, ` +
`accountId: ${accountId}, ` +
`userid: ${userid}, ` +
`authorId: ${authorId}, ` +
`encryption: ${encryption}, ` +
`prompt: ${prompt} };`
);
//authorIdが重複していないかチェックする
if (authorId) {
let isAuthorIdDuplicated = false;
try {
isAuthorIdDuplicated = await this.usersRepository.existsAuthorId(
context,
accountId,
authorId
);
this.logger.log(
`[${context.getTrackingId()}] isAuthorIdDuplicated=${isAuthorIdDuplicated}`
);
} catch (e) {
this.logger.error(`[${context.getTrackingId()}] error=${e}`);
throw new HttpException(
makeErrorResponse("E009999"),
HttpStatus.INTERNAL_SERVER_ERROR
);
}
if (isAuthorIdDuplicated) {
throw new HttpException(
makeErrorResponse("E010302"),
HttpStatus.BAD_REQUEST
);
}
}
this.logger.log("ランダムパスワード生成開始");
// ランダムなパスワードを生成する
const ramdomPassword = makePassword();
this.logger.log("ランダムパスワード生成完了");
//Azure AD B2Cにユーザーを新規登録する
let externalUser: { sub: string } | ConflictError;
try {
this.logger.log(`name=${name}`);
// idpにユーザーを作成
externalUser = await this.adB2cService.createUser(
context,
email,
ramdomPassword,
name
);
} catch (e) {
this.logger.error(`[${context.getTrackingId()}] error=${e}`);
this.logger.error(
`[${context.getTrackingId()}] create externalUser failed`
);
throw new HttpException(
makeErrorResponse("E009999"),
HttpStatus.INTERNAL_SERVER_ERROR
);
}
// メールアドレス重複エラー
if (isConflictError(externalUser)) {
throw new HttpException(
makeErrorResponse("E010301"),
HttpStatus.BAD_REQUEST
);
}
//Azure AD B2Cに登録したユーザー情報のID(sub)と受け取った情報を使ってDBにユーザーを登録する
let newUser: EntityUser;
try {
//roleに応じてユーザー情報を作成する
const newUserInfo = this.createNewUserInfo(
context,
userid,
role,
accountId,
externalUser.sub,
autoRenew,
notification,
authorId,
encryption,
encryptionPassword,
prompt
);
// ユーザ作成
newUser = await this.usersRepository.createNormalUser(
context,
newUserInfo
);
} catch (e) {
this.logger.error(`[${context.getTrackingId()}] error=${e}`);
this.logger.error(`[${context.getTrackingId()}]create user failed`);
//リカバリー処理
//Azure AD B2Cに登録したユーザー情報を削除する
await this.deleteB2cUser(externalUser.sub, context);
switch (e.code) {
case "ER_DUP_ENTRY":
//AuthorID重複エラー
throw new HttpException(
makeErrorResponse("E010302"),
HttpStatus.BAD_REQUEST
);
default:
throw new HttpException(
makeErrorResponse("E009999"),
HttpStatus.INTERNAL_SERVER_ERROR
);
}
}
this.logger.log(
`[OUT] [${context.getTrackingId()}] ${this.createUser.name}`
);
return;
}
// Azure AD B2Cに登録したユーザー情報を削除する
// TODO 「タスク 2452: リトライ処理を入れる箇所を検討し、実装する」の候補
private async deleteB2cUser(externalUserId: string, context: Context) {
this.logger.log(
`[IN] [${context.getTrackingId()}] ${
this.deleteB2cUser.name
} | params: { externalUserId: ${externalUserId} }`
);
try {
await this.adB2cService.deleteUser(externalUserId, context);
this.logger.log(
`[${context.getTrackingId()}] delete externalUser: ${externalUserId}`
);
} catch (error) {
this.logger.error(`[${context.getTrackingId()}] error=${error}`);
this.logger.error(
`${MANUAL_RECOVERY_REQUIRED} [${context.getTrackingId()}] Failed to delete externalUser: ${externalUserId}`
);
} finally {
this.logger.log(
`[OUT] [${context.getTrackingId()}] ${this.deleteB2cUser.name}`
);
}
}
// DBに登録したユーザー情報を削除する
private async deleteUser(userId: number, context: Context) {
this.logger.log(
`[IN] [${context.getTrackingId()}] ${
this.deleteUser.name
} | params: { userId: ${userId} }`
);
try {
await this.usersRepository.deleteNormalUser(context, userId);
this.logger.log(`[${context.getTrackingId()}] delete user: ${userId}`);
} catch (error) {
this.logger.error(`[${context.getTrackingId()}] error=${error}`);
this.logger.error(
`${MANUAL_RECOVERY_REQUIRED} [${context.getTrackingId()}] Failed to delete user: ${userId}`
);
} finally {
this.logger.log(
`[OUT] [${context.getTrackingId()}] ${this.deleteUser.name}`
);
}
}
// roleを受け取って、roleに応じたnewUserを作成して返却する
private createNewUserInfo(
context: Context,
id: number,
role: UserRoles,
accountId: number,
externalId: string,
autoRenew: boolean,
notification: boolean,
authorId?: string | undefined,
encryption?: boolean | undefined,
encryptionPassword?: string | undefined,
prompt?: boolean | undefined
): newUser {
this.logger.log(
`[IN] [${context.getTrackingId()}] ${
this.createNewUserInfo.name
} | params: { ` +
`id: ${id}, ` +
`role: ${role}, ` +
`accountId: ${accountId}, ` +
`authorId: ${authorId}, ` +
`externalId: ${externalId}, ` +
`autoRenew: ${autoRenew}, ` +
`notification: ${notification}, ` +
`authorId: ${authorId}, ` +
`encryption: ${encryption}, ` +
`prompt: ${prompt} };`
);
try {
switch (role) {
case USER_ROLES.NONE:
case USER_ROLES.TYPIST:
return {
id,
account_id: accountId,
external_id: externalId,
auto_renew: autoRenew,
notification,
role,
accepted_dpa_version: null,
accepted_eula_version: null,
accepted_privacy_notice_version: null,
encryption: false,
encryption_password: null,
prompt: false,
author_id: null,
};
case USER_ROLES.AUTHOR:
return {
id,
account_id: accountId,
external_id: externalId,
auto_renew: autoRenew,
notification,
role,
author_id: authorId ?? null,
encryption: encryption ?? false,
encryption_password: encryptionPassword ?? null,
prompt: prompt ?? false,
accepted_dpa_version: null,
accepted_eula_version: null,
accepted_privacy_notice_version: null,
};
default:
//不正なroleが指定された場合はログを出力してエラーを返す
this.logger.error(
`[${context.getTrackingId()}] [NOT IMPLEMENT] [RECOVER] role: ${role}`
);
throw new HttpException(
makeErrorResponse("E009999"),
HttpStatus.INTERNAL_SERVER_ERROR
);
}
} catch (e) {
this.logger.error(`[${context.getTrackingId()}] error=${e}`);
return e;
} finally {
this.logger.log(
`[OUT] [${context.getTrackingId()}] ${this.createNewUserInfo.name}`
);
}
}
}