## 概要 [Task2353: アカウント登録APIを修正](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2353) - アカウント登録時にコンテナを作成するように修正 - ログ追加 - リクエストのバリデータを追加 ## レビューポイント - 処理の流れに問題はないか - テストケースに不足はないか - バリデータに問題はないか ## UIの変更 - なし ## 動作確認状況 - ローカルで確認
885 lines
26 KiB
TypeScript
885 lines
26 KiB
TypeScript
import { HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common';
|
|
import { ConfigService } from '@nestjs/config';
|
|
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
|
|
import { isVerifyError, verify } from '../../common/jwt';
|
|
import { getPublicKey } from '../../common/jwt/jwt';
|
|
import { makePassword } from '../../common/password/password';
|
|
import { AccessToken } from '../../common/token';
|
|
import {
|
|
SortDirection,
|
|
TaskListSortableAttribute,
|
|
isSortDirection,
|
|
isTaskListSortableAttribute,
|
|
} from '../../common/types/sort';
|
|
import {
|
|
AdB2cService,
|
|
ConflictError,
|
|
isConflictError,
|
|
} from '../../gateways/adb2c/adb2c.service';
|
|
import { SendGridService } from '../../gateways/sendgrid/sendgrid.service';
|
|
import { SortCriteriaRepositoryService } from '../../repositories/sort_criteria/sort_criteria.repository.service';
|
|
import {
|
|
User as EntityUser,
|
|
newUser,
|
|
} from '../../repositories/users/entity/user.entity';
|
|
import { UsersRepositoryService } from '../../repositories/users/users.repository.service';
|
|
import { LicensesRepositoryService } from '../../repositories/licenses/licenses.repository.service';
|
|
import { GetRelationsResponse, User } from './types/types';
|
|
import {
|
|
AuthorIdAlreadyExistsError,
|
|
EmailAlreadyVerifiedError,
|
|
EncryptionPasswordNeedError,
|
|
InvalidRoleChangeError,
|
|
UserNotFoundError,
|
|
} from '../../repositories/users/errors/types';
|
|
import {
|
|
LICENSE_EXPIRATION_THRESHOLD_DAYS,
|
|
USER_LICENSE_STATUS,
|
|
USER_ROLES,
|
|
} from '../../constants';
|
|
import { DateWithZeroTime } from '../licenses/types/types';
|
|
import { Context } from '../../common/log';
|
|
import { UserRoles } from '../../common/types/role';
|
|
import {
|
|
LicenseExpiredError,
|
|
LicenseUnavailableError,
|
|
} from '../../repositories/licenses/errors/types';
|
|
|
|
@Injectable()
|
|
export class UsersService {
|
|
constructor(
|
|
private readonly usersRepository: UsersRepositoryService,
|
|
private readonly licensesRepository: LicensesRepositoryService,
|
|
private readonly sortCriteriaRepository: SortCriteriaRepositoryService,
|
|
private readonly adB2cService: AdB2cService,
|
|
private readonly configService: ConfigService,
|
|
private readonly sendgridService: SendGridService,
|
|
) {}
|
|
private readonly logger = new Logger(UsersService.name);
|
|
|
|
/**
|
|
* Confirms user
|
|
* @param token ユーザ仮登録時に払いだされるトークン
|
|
*/
|
|
async confirmUser(token: string): Promise<void> {
|
|
this.logger.log(`[IN] ${this.confirmUser.name}`);
|
|
const pubKey = getPublicKey(this.configService);
|
|
|
|
const decodedToken = verify<{
|
|
accountId: number;
|
|
userId: number;
|
|
email: string;
|
|
}>(token, pubKey);
|
|
if (isVerifyError(decodedToken)) {
|
|
throw new HttpException(
|
|
makeErrorResponse('E000101'),
|
|
HttpStatus.BAD_REQUEST,
|
|
);
|
|
}
|
|
|
|
try {
|
|
// トランザクションで取得と更新をまとめる
|
|
const userId = decodedToken.userId;
|
|
await this.usersRepository.updateUserVerifiedAndCreateTrialLicense(
|
|
userId,
|
|
);
|
|
} catch (e) {
|
|
this.logger.error(e);
|
|
if (e instanceof Error) {
|
|
switch (e.constructor) {
|
|
case EmailAlreadyVerifiedError:
|
|
throw new HttpException(
|
|
makeErrorResponse('E010202'),
|
|
HttpStatus.BAD_REQUEST,
|
|
);
|
|
default:
|
|
throw new HttpException(
|
|
makeErrorResponse('E009999'),
|
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
);
|
|
}
|
|
}
|
|
|
|
throw new HttpException(
|
|
makeErrorResponse('E009999'),
|
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates user
|
|
* @param accessToken
|
|
* @param name
|
|
* @param role
|
|
* @param email
|
|
* @param autoRenew
|
|
* @param licenseAlert
|
|
* @param notification
|
|
* @param [authorId]
|
|
* @param [encryption]
|
|
* @param [encryptionPassword]
|
|
* @param [prompt]
|
|
* @returns void
|
|
*/
|
|
async createUser(
|
|
context: Context,
|
|
accessToken: AccessToken,
|
|
name: string,
|
|
role: UserRoles,
|
|
email: string,
|
|
autoRenew: boolean,
|
|
licenseAlert: boolean,
|
|
notification: boolean,
|
|
authorId?: string | undefined,
|
|
encryption?: boolean | undefined,
|
|
encryptionPassword?: string | undefined,
|
|
prompt?: boolean | undefined,
|
|
): Promise<void> {
|
|
this.logger.log(`[IN] [${context.trackingId}] ${this.createUser.name}`);
|
|
|
|
//DBよりアクセス者の所属するアカウントIDを取得する
|
|
let adminUser: EntityUser;
|
|
try {
|
|
adminUser = await this.usersRepository.findUserByExternalId(
|
|
accessToken.userId,
|
|
);
|
|
} catch (e) {
|
|
this.logger.error(`error=${e}`);
|
|
throw new HttpException(
|
|
makeErrorResponse('E009999'),
|
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
);
|
|
}
|
|
|
|
const accountId = adminUser.account_id;
|
|
|
|
//authorIdが重複していないかチェックする
|
|
if (authorId) {
|
|
let isAuthorIdDuplicated = false;
|
|
try {
|
|
isAuthorIdDuplicated = await this.usersRepository.existsAuthorId(
|
|
accountId,
|
|
authorId,
|
|
);
|
|
} catch (e) {
|
|
this.logger.error(`error=${e}`);
|
|
throw new HttpException(
|
|
makeErrorResponse('E009999'),
|
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
);
|
|
}
|
|
if (isAuthorIdDuplicated) {
|
|
throw new HttpException(
|
|
makeErrorResponse('E010302'),
|
|
HttpStatus.BAD_REQUEST,
|
|
);
|
|
}
|
|
}
|
|
|
|
// ランダムなパスワードを生成する
|
|
const ramdomPassword = makePassword();
|
|
|
|
//Azure AD B2Cにユーザーを新規登録する
|
|
let externalUser: { sub: string } | ConflictError;
|
|
try {
|
|
// idpにユーザーを作成
|
|
externalUser = await this.adB2cService.createUser(
|
|
context,
|
|
email,
|
|
ramdomPassword,
|
|
name,
|
|
);
|
|
} catch (e) {
|
|
this.logger.error(`error=${e}`);
|
|
this.logger.error('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(
|
|
role,
|
|
accountId,
|
|
externalUser.sub,
|
|
autoRenew,
|
|
licenseAlert,
|
|
notification,
|
|
authorId,
|
|
encryption,
|
|
encryptionPassword,
|
|
prompt,
|
|
);
|
|
// ユーザ作成
|
|
newUser = await this.usersRepository.createNormalUser(newUserInfo);
|
|
} catch (e) {
|
|
this.logger.error(`error=${e}`);
|
|
this.logger.error('create user failed');
|
|
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,
|
|
);
|
|
}
|
|
}
|
|
|
|
//Email送信用のコンテンツを作成する
|
|
try {
|
|
// メールの送信元を取得
|
|
const from = this.configService.get<string>('MAIL_FROM') ?? '';
|
|
|
|
// メールの内容を構成
|
|
const { subject, text, html } =
|
|
await this.sendgridService.createMailContentFromEmailConfirmForNormalUser(
|
|
accountId,
|
|
newUser.id,
|
|
email,
|
|
);
|
|
|
|
//SendGridAPIを呼び出してメールを送信する
|
|
await this.sendgridService.sendMail(
|
|
context,
|
|
email,
|
|
from,
|
|
subject,
|
|
text,
|
|
html,
|
|
);
|
|
} catch (e) {
|
|
this.logger.error(`error=${e}`);
|
|
this.logger.error('create user failed');
|
|
this.logger.error(`[NOT IMPLEMENT] [RECOVER] delete user: ${newUser.id}`);
|
|
throw new HttpException(
|
|
makeErrorResponse('E009999'),
|
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
);
|
|
}
|
|
this.logger.log(`[OUT] ${this.createUser.name}`);
|
|
return;
|
|
}
|
|
|
|
// roleを受け取って、roleに応じたnewUserを作成して返却する
|
|
private createNewUserInfo(
|
|
role: UserRoles,
|
|
accountId: number,
|
|
externalId: string,
|
|
autoRenew: boolean,
|
|
licenseAlert: boolean,
|
|
notification: boolean,
|
|
authorId?: string | undefined,
|
|
encryption?: boolean | undefined,
|
|
encryptionPassword?: string | undefined,
|
|
prompt?: boolean | undefined,
|
|
): newUser {
|
|
switch (role) {
|
|
case USER_ROLES.NONE:
|
|
case USER_ROLES.TYPIST:
|
|
return {
|
|
account_id: accountId,
|
|
external_id: externalId,
|
|
auto_renew: autoRenew,
|
|
license_alert: licenseAlert,
|
|
notification,
|
|
role,
|
|
};
|
|
case USER_ROLES.AUTHOR:
|
|
return {
|
|
account_id: accountId,
|
|
external_id: externalId,
|
|
auto_renew: autoRenew,
|
|
license_alert: licenseAlert,
|
|
notification,
|
|
role,
|
|
author_id: authorId,
|
|
encryption,
|
|
encryption_password: encryptionPassword,
|
|
prompt,
|
|
};
|
|
default:
|
|
//不正なroleが指定された場合はログを出力してエラーを返す
|
|
this.logger.error(`[NOT IMPLEMENT] [RECOVER] role: ${role}`);
|
|
throw new HttpException(
|
|
makeErrorResponse('E009999'),
|
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* confirm User And Init Password
|
|
* @param token ユーザ仮登録時に払いだされるトークン
|
|
*/
|
|
async confirmUserAndInitPassword(
|
|
context: Context,
|
|
token: string,
|
|
): Promise<void> {
|
|
this.logger.log(
|
|
`[IN] [${context.trackingId}] ${this.confirmUserAndInitPassword.name}`,
|
|
);
|
|
|
|
const pubKey = getPublicKey(this.configService);
|
|
|
|
const decodedToken = verify<{
|
|
accountId: number;
|
|
userId: number;
|
|
email: string;
|
|
}>(token, pubKey);
|
|
if (isVerifyError(decodedToken)) {
|
|
throw new HttpException(
|
|
makeErrorResponse('E000101'),
|
|
HttpStatus.BAD_REQUEST,
|
|
);
|
|
}
|
|
|
|
// ランダムなパスワードを生成する
|
|
const ramdomPassword = makePassword();
|
|
const { userId, email } = decodedToken;
|
|
|
|
try {
|
|
// ユーザー情報からAzure AD B2CのIDを特定する
|
|
const user = await this.usersRepository.findUserById(userId);
|
|
const extarnalId = user.external_id;
|
|
// パスワードを変更する
|
|
await this.adB2cService.changePassword(extarnalId, ramdomPassword);
|
|
// ユーザを認証済みにする
|
|
await this.usersRepository.updateUserVerified(userId);
|
|
// メールの送信元を取得
|
|
const from = this.configService.get<string>('MAIL_FROM') ?? '';
|
|
// TODO [Task2163] ODMS側が正式にメッセージを決めるまで仮のメール内容とする
|
|
const subject = 'A temporary password has been issued.';
|
|
const text = 'temporary password: ' + ramdomPassword;
|
|
const domains = this.configService.get<string>('APP_DOMAIN');
|
|
const html = `<p>OMDS TOP PAGE URL.<p><a href="${domains}">${domains}"</a><br>temporary password: ${ramdomPassword}`;
|
|
|
|
// メールを送信
|
|
await this.sendgridService.sendMail(
|
|
context,
|
|
email,
|
|
from,
|
|
subject,
|
|
text,
|
|
html,
|
|
);
|
|
} catch (e) {
|
|
this.logger.error(`error=${e}`);
|
|
if (e instanceof Error) {
|
|
switch (e.constructor) {
|
|
case EmailAlreadyVerifiedError:
|
|
throw new HttpException(
|
|
makeErrorResponse('E010202'),
|
|
HttpStatus.BAD_REQUEST,
|
|
);
|
|
default:
|
|
throw new HttpException(
|
|
makeErrorResponse('E009999'),
|
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get Users
|
|
* @param accessToken
|
|
* @returns users
|
|
*/
|
|
async getUsers(externalId: string): Promise<User[]> {
|
|
this.logger.log(`[IN] ${this.getUsers.name}`);
|
|
|
|
try {
|
|
// DBから同一アカウントのユーザ一覧を取得する
|
|
const dbUsers = await this.usersRepository.findSameAccountUsers(
|
|
externalId,
|
|
);
|
|
|
|
// DBから取得したユーザーの外部IDをもとにADB2Cからユーザーを取得する
|
|
const externalIds = dbUsers.map((x) => x.external_id);
|
|
const adb2cUsers = await this.adB2cService.getUsers(
|
|
// TODO: 外部連携以外のログ強化時に、ContollerからContextを取得するように修正する
|
|
{ trackingId: 'dummy' },
|
|
externalIds,
|
|
);
|
|
|
|
// DBから取得した各ユーザーをもとにADB2C情報をマージしライセンス情報を算出
|
|
const users = dbUsers.map((x) => {
|
|
// ユーザーの所属グループ名を取得する
|
|
const groupNames =
|
|
x.userGroupMembers?.map((group) => group.userGroup?.name) ?? [];
|
|
|
|
const adb2cUser = adb2cUsers.find((user) => user.id === x.external_id);
|
|
|
|
// メールアドレスを取得する
|
|
const mail = adb2cUser.identities.find(
|
|
(identity) => identity.signInType === 'emailAddress',
|
|
).issuerAssignedId;
|
|
|
|
let status = USER_LICENSE_STATUS.NORMAL;
|
|
|
|
// ライセンスの有効期限と残日数は、ライセンスが存在する場合のみ算出する
|
|
// ライセンスが存在しない場合は、undefinedのままとする
|
|
let expiration: string | undefined = undefined;
|
|
let remaining: number | undefined = undefined;
|
|
|
|
if (x.license) {
|
|
// 有効期限日付 YYYY/MM/DD
|
|
const expiry_date = x.license.expiry_date;
|
|
expiration = `${expiry_date.getFullYear()}/${
|
|
expiry_date.getMonth() + 1
|
|
}/${expiry_date.getDate()}`;
|
|
|
|
const currentDate = new DateWithZeroTime();
|
|
// 有効期限までの日数
|
|
remaining = Math.floor(
|
|
(expiry_date.getTime() - currentDate.getTime()) /
|
|
(1000 * 60 * 60 * 24),
|
|
);
|
|
if (remaining <= LICENSE_EXPIRATION_THRESHOLD_DAYS) {
|
|
status = x.auto_renew
|
|
? USER_LICENSE_STATUS.RENEW
|
|
: USER_LICENSE_STATUS.ALERT;
|
|
}
|
|
} else {
|
|
status = USER_LICENSE_STATUS.NO_LICENSE;
|
|
}
|
|
|
|
return {
|
|
id: x.id,
|
|
name: adb2cUser.displayName,
|
|
role: x.role,
|
|
authorId: x.author_id ?? undefined,
|
|
typistGroupName: groupNames,
|
|
email: mail,
|
|
emailVerified: x.email_verified,
|
|
autoRenew: x.auto_renew,
|
|
licenseAlert: x.license_alert,
|
|
notification: x.notification,
|
|
encryption: x.encryption,
|
|
prompt: x.prompt,
|
|
expiration: expiration,
|
|
remaining: remaining,
|
|
licenseStatus: status,
|
|
};
|
|
});
|
|
|
|
return users;
|
|
} catch (e) {
|
|
this.logger.error(`error=${e}`);
|
|
throw new HttpException(
|
|
makeErrorResponse('E009999'),
|
|
HttpStatus.NOT_FOUND,
|
|
);
|
|
} finally {
|
|
this.logger.log(`[OUT] ${this.getUsers.name}`);
|
|
}
|
|
}
|
|
/**
|
|
* Updates sort criteria
|
|
* @param paramName
|
|
* @param direction
|
|
* @param token
|
|
* @returns sort criteria
|
|
*/
|
|
async updateSortCriteria(
|
|
paramName: TaskListSortableAttribute,
|
|
direction: SortDirection,
|
|
token: AccessToken,
|
|
): Promise<void> {
|
|
this.logger.log(`[IN] ${this.updateSortCriteria.name}`);
|
|
let user: EntityUser;
|
|
try {
|
|
// ユーザー情報を取得
|
|
const sub = token.userId;
|
|
user = await this.usersRepository.findUserByExternalId(sub);
|
|
} catch (e) {
|
|
this.logger.error(`error=${e}`);
|
|
|
|
throw new HttpException(
|
|
makeErrorResponse('E009999'),
|
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
);
|
|
}
|
|
|
|
try {
|
|
// ユーザーのソート条件を更新
|
|
await this.sortCriteriaRepository.updateSortCriteria(
|
|
user.id,
|
|
paramName,
|
|
direction,
|
|
);
|
|
} catch (e) {
|
|
this.logger.error(`error=${e}`);
|
|
throw new HttpException(
|
|
makeErrorResponse('E009999'),
|
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
);
|
|
} finally {
|
|
this.logger.log(`[OUT] ${this.updateSortCriteria.name}`);
|
|
}
|
|
}
|
|
/**
|
|
* Gets sort criteria
|
|
* @param token
|
|
* @returns sort criteria
|
|
*/
|
|
async getSortCriteria(token: AccessToken): Promise<{
|
|
paramName: TaskListSortableAttribute;
|
|
direction: SortDirection;
|
|
}> {
|
|
this.logger.log(`[IN] ${this.getSortCriteria.name}`);
|
|
let user: EntityUser;
|
|
try {
|
|
// ユーザー情報を取得
|
|
const sub = token.userId;
|
|
user = await this.usersRepository.findUserByExternalId(sub);
|
|
} catch (e) {
|
|
this.logger.error(`error=${e}`);
|
|
|
|
throw new HttpException(
|
|
makeErrorResponse('E009999'),
|
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
);
|
|
}
|
|
|
|
try {
|
|
// ユーザーのソート条件を取得
|
|
const sortCriteria = await this.sortCriteriaRepository.getSortCriteria(
|
|
user.id,
|
|
);
|
|
const { direction, parameter } = sortCriteria;
|
|
//型チェック
|
|
if (
|
|
!isTaskListSortableAttribute(parameter) ||
|
|
!isSortDirection(direction)
|
|
) {
|
|
throw new Error('The value stored in the DB is invalid.');
|
|
}
|
|
return { direction, paramName: parameter };
|
|
} catch (e) {
|
|
this.logger.error(`error=${e}`);
|
|
throw new HttpException(
|
|
makeErrorResponse('E009999'),
|
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
);
|
|
} finally {
|
|
this.logger.log(`[OUT] ${this.getSortCriteria.name}`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 指定したユーザーの文字起こし業務に関連する情報を取得します
|
|
* @param userId
|
|
* @returns relations
|
|
*/
|
|
async getRelations(
|
|
context: Context,
|
|
userId: string,
|
|
): Promise<GetRelationsResponse> {
|
|
this.logger.log(`[IN] [${context.trackingId}] ${this.getRelations.name}`);
|
|
try {
|
|
const user = await this.usersRepository.findUserByExternalId(userId);
|
|
|
|
// TODO: PBI2105 本実装時に修正すること
|
|
return {
|
|
authorId: user.author_id,
|
|
authorIdList: [user.author_id, 'XXX'],
|
|
isEncrypted: true,
|
|
encryptionPassword: 'abcd@123?dcba',
|
|
audioFormat: 'DS2(QP)',
|
|
prompt: true,
|
|
workTypeList: [
|
|
{
|
|
workTypeId: 'workType1',
|
|
optionItemList: [
|
|
{
|
|
label: 'optionItem11',
|
|
initialValueType: 2,
|
|
defaultValue: 'default11',
|
|
},
|
|
{
|
|
label: 'optionItem12',
|
|
initialValueType: 2,
|
|
defaultValue: 'default12',
|
|
},
|
|
{
|
|
label: 'optionItem13',
|
|
initialValueType: 2,
|
|
defaultValue: 'default13',
|
|
},
|
|
{
|
|
label: 'optionItem14',
|
|
initialValueType: 2,
|
|
defaultValue: 'default14',
|
|
},
|
|
{
|
|
label: 'optionItem15',
|
|
initialValueType: 2,
|
|
defaultValue: 'default15',
|
|
},
|
|
{
|
|
label: 'optionItem16',
|
|
initialValueType: 2,
|
|
defaultValue: 'default16',
|
|
},
|
|
{
|
|
label: 'optionItem17',
|
|
initialValueType: 2,
|
|
defaultValue: 'default17',
|
|
},
|
|
{
|
|
label: 'optionItem18',
|
|
initialValueType: 2,
|
|
defaultValue: 'default18',
|
|
},
|
|
{
|
|
label: 'optionItem19',
|
|
initialValueType: 1,
|
|
defaultValue: '',
|
|
},
|
|
{
|
|
label: 'optionItem110',
|
|
initialValueType: 3,
|
|
defaultValue: '',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
workTypeId: 'workType2',
|
|
optionItemList: [
|
|
{
|
|
label: 'optionItem21',
|
|
initialValueType: 2,
|
|
defaultValue: 'default21',
|
|
},
|
|
{
|
|
label: 'optionItem22',
|
|
initialValueType: 2,
|
|
defaultValue: 'default22',
|
|
},
|
|
{
|
|
label: 'optionItem23',
|
|
initialValueType: 2,
|
|
defaultValue: 'defaul23',
|
|
},
|
|
{
|
|
label: 'optionItem24',
|
|
initialValueType: 2,
|
|
defaultValue: 'default24',
|
|
},
|
|
{
|
|
label: 'optionItem25',
|
|
initialValueType: 2,
|
|
defaultValue: 'default25',
|
|
},
|
|
{
|
|
label: 'optionItem26',
|
|
initialValueType: 2,
|
|
defaultValue: 'default26',
|
|
},
|
|
{
|
|
label: 'optionItem27',
|
|
initialValueType: 2,
|
|
defaultValue: 'default27',
|
|
},
|
|
{
|
|
label: 'optionItem28',
|
|
initialValueType: 2,
|
|
defaultValue: 'default28',
|
|
},
|
|
{
|
|
label: 'optionItem29',
|
|
initialValueType: 1,
|
|
defaultValue: '',
|
|
},
|
|
{
|
|
label: 'optionItem210',
|
|
initialValueType: 3,
|
|
defaultValue: '',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
activeWorktype: 'workType1',
|
|
};
|
|
} catch (e) {
|
|
this.logger.error(`error=${e}`);
|
|
|
|
throw new HttpException(
|
|
makeErrorResponse('E009999'),
|
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
);
|
|
} finally {
|
|
this.logger.log(
|
|
`[OUT] [${context.trackingId}] ${this.getRelations.name}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 指定したユーザーの情報を更新します
|
|
* @param context
|
|
* @param extarnalId
|
|
* @param id
|
|
* @param role
|
|
* @param authorId
|
|
* @param autoRenew
|
|
* @param licenseAlart
|
|
* @param notification
|
|
* @param encryption
|
|
* @param encryptionPassword
|
|
* @param prompt
|
|
* @returns user
|
|
*/
|
|
async updateUser(
|
|
context: Context,
|
|
extarnalId: string,
|
|
id: number,
|
|
role: string,
|
|
authorId: string | undefined,
|
|
autoRenew: boolean,
|
|
licenseAlart: boolean,
|
|
notification: boolean,
|
|
encryption: boolean | undefined,
|
|
encryptionPassword: string | undefined,
|
|
prompt: boolean | undefined,
|
|
): Promise<void> {
|
|
try {
|
|
this.logger.log(
|
|
`[IN] [${context.trackingId}] ${this.updateUser.name} | params: { ` +
|
|
`role: ${role}, ` +
|
|
`authorId: ${authorId}, ` +
|
|
`autoRenew: ${autoRenew}, ` +
|
|
`licenseAlart: ${licenseAlart}, ` +
|
|
`notification: ${notification}, ` +
|
|
`encryption: ${encryption}, ` +
|
|
`encryptionPassword: ********, ` +
|
|
`prompt: ${prompt} }`,
|
|
);
|
|
|
|
// 実行ユーザーのアカウントIDを取得
|
|
const accountId = (
|
|
await this.usersRepository.findUserByExternalId(extarnalId)
|
|
).account_id;
|
|
|
|
// ユーザー情報を更新
|
|
await this.usersRepository.update(
|
|
accountId,
|
|
id,
|
|
role,
|
|
authorId,
|
|
autoRenew,
|
|
licenseAlart,
|
|
notification,
|
|
encryption,
|
|
encryptionPassword,
|
|
prompt,
|
|
);
|
|
} catch (e) {
|
|
this.logger.error(`error=${e}`);
|
|
if (e instanceof Error) {
|
|
switch (e.constructor) {
|
|
case UserNotFoundError:
|
|
throw new HttpException(
|
|
makeErrorResponse('E010204'),
|
|
HttpStatus.BAD_REQUEST,
|
|
);
|
|
case AuthorIdAlreadyExistsError:
|
|
throw new HttpException(
|
|
makeErrorResponse('E010302'),
|
|
HttpStatus.BAD_REQUEST,
|
|
);
|
|
case InvalidRoleChangeError:
|
|
throw new HttpException(
|
|
makeErrorResponse('E010207'),
|
|
HttpStatus.BAD_REQUEST,
|
|
);
|
|
case EncryptionPasswordNeedError:
|
|
throw new HttpException(
|
|
makeErrorResponse('E010208'),
|
|
HttpStatus.BAD_REQUEST,
|
|
);
|
|
default:
|
|
throw new HttpException(
|
|
makeErrorResponse('E009999'),
|
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
);
|
|
}
|
|
}
|
|
throw new HttpException(
|
|
makeErrorResponse('E009999'),
|
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
);
|
|
} finally {
|
|
this.logger.log(`[OUT] [${context.trackingId}] ${this.updateUser.name}`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* ライセンスをユーザーに割り当てます
|
|
* @param context
|
|
* @param userId
|
|
* @param newLicenseId
|
|
*/
|
|
async allocateLicense(
|
|
context: Context,
|
|
userId: number,
|
|
newLicenseId: number,
|
|
): Promise<void> {
|
|
this.logger.log(
|
|
`[IN] [${context.trackingId}] ${this.allocateLicense.name} | params: { ` +
|
|
`userId: ${userId}, ` +
|
|
`newLicenseId: ${newLicenseId}, `,
|
|
);
|
|
|
|
try {
|
|
await this.licensesRepository.allocateLicense(userId, newLicenseId);
|
|
} catch (e) {
|
|
this.logger.error(`error=${e}`);
|
|
if (e instanceof Error) {
|
|
switch (e.constructor) {
|
|
case LicenseExpiredError:
|
|
throw new HttpException(
|
|
makeErrorResponse('E010805'),
|
|
HttpStatus.BAD_REQUEST,
|
|
);
|
|
case LicenseUnavailableError:
|
|
throw new HttpException(
|
|
makeErrorResponse('E010806'),
|
|
HttpStatus.BAD_REQUEST,
|
|
);
|
|
default:
|
|
throw new HttpException(
|
|
makeErrorResponse('E009999'),
|
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
);
|
|
}
|
|
}
|
|
} finally {
|
|
this.logger.log(
|
|
`[OUT] [${context.trackingId}] ${this.allocateLicense.name}`,
|
|
);
|
|
}
|
|
}
|
|
}
|