## 概要 [Task1950: typist名をAzure AD B2Cから取得し表示できるようにする](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/1950) - チェックアウト権限にあるTypistのユーザー名をB2Cから取得する - チェックアウト権限に含まれているuser.externalIdを列挙 - ExternalIdでフィルターをかけてユーザー情報を取得 - B2Cへのリクエスト上限超過時のエラーを制御するために専用エラーを定義 - import文が常に絶対パスで指定されていて、それでテストがこけるので相対パスでインポートするようにvscodeを設定 ## レビューポイント - convert.tsの修正は問題ないか ## UIの変更 - Before/Afterのスクショなど - スクショ置き場 ## 動作確認状況 - ローカルで確認 ## 補足 - 取得方法についてはMSに問い合わせ中
161 lines
5.3 KiB
TypeScript
161 lines
5.3 KiB
TypeScript
import { HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common';
|
|
import { TasksRepositoryService } from '../../repositories/tasks/tasks.repository.service';
|
|
import { AccessToken } from '../../common/token';
|
|
import { Task } from './types/types';
|
|
import { Task as TaskEntity } from '../../repositories/tasks/entity/task.entity';
|
|
import { createTasks } from './types/convert';
|
|
import { UsersRepositoryService } from '../../repositories/users/users.repository.service';
|
|
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
|
|
import {
|
|
SortDirection,
|
|
TaskListSortableAttribute,
|
|
} from '../../common/types/sort';
|
|
import { ADMIN_ROLES, USER_ROLES } from '../../constants';
|
|
import {
|
|
AdB2cService,
|
|
Adb2cTooManyRequestsError,
|
|
} from '../../gateways/adb2c/adb2c.service';
|
|
import { AdB2cUser } from '../../gateways/adb2c/types/types';
|
|
import { CheckoutPermission } from '../../repositories/checkout_permissions/entity/checkout_permission.entity';
|
|
|
|
@Injectable()
|
|
export class TasksService {
|
|
private readonly logger = new Logger(TasksService.name);
|
|
constructor(
|
|
private readonly taskRepository: TasksRepositoryService,
|
|
private readonly usersRepository: UsersRepositoryService,
|
|
private readonly adB2cService: AdB2cService,
|
|
) {}
|
|
|
|
// TODO: 引数にAccessTokenがあるのは不適切なのでController側で分解したい
|
|
async getTasks(
|
|
accessToken: AccessToken,
|
|
offset: number,
|
|
limit: number,
|
|
status: string[],
|
|
paramName?: TaskListSortableAttribute,
|
|
direction?: SortDirection,
|
|
): Promise<{ tasks: Task[]; total: number }> {
|
|
const { role, userId } = accessToken;
|
|
const roles = role.split(' '); // TODO: Roleを型で定義されているものに修正する
|
|
|
|
// パラメータが省略された場合のデフォルト値: 保存するソート条件の値の初期値と揃える
|
|
const defaultParamName: TaskListSortableAttribute = 'JOB_NUMBER';
|
|
const defaultDirection: SortDirection = 'ASC';
|
|
|
|
try {
|
|
const { account_id, author_id } =
|
|
await this.usersRepository.findUserByExternalId(userId);
|
|
|
|
if (roles.includes(ADMIN_ROLES.ADMIN)) {
|
|
const result = await this.taskRepository.getTasksFromAccountId(
|
|
account_id,
|
|
offset,
|
|
limit,
|
|
paramName ?? defaultParamName,
|
|
direction ?? defaultDirection,
|
|
status,
|
|
);
|
|
|
|
// B2Cからユーザー名を取得する
|
|
const b2cUsers = await this.getB2cUsers(
|
|
result.tasks,
|
|
result.permissions,
|
|
);
|
|
|
|
const tasks = createTasks(result.tasks, result.permissions, b2cUsers);
|
|
|
|
return { tasks: tasks, total: result.count };
|
|
}
|
|
if (roles.includes(USER_ROLES.AUTHOR)) {
|
|
const result =
|
|
await this.taskRepository.getTasksFromAuthorIdAndAccountId(
|
|
author_id,
|
|
account_id,
|
|
offset,
|
|
limit,
|
|
paramName ?? defaultParamName,
|
|
direction ?? defaultDirection,
|
|
status,
|
|
);
|
|
|
|
// B2Cからユーザー名を取得する
|
|
const b2cUsers = await this.getB2cUsers(
|
|
result.tasks,
|
|
result.permissions,
|
|
);
|
|
|
|
const tasks = createTasks(result.tasks, result.permissions, b2cUsers);
|
|
return { tasks: tasks, total: result.count };
|
|
}
|
|
|
|
if (roles.includes(USER_ROLES.TYPIST)) {
|
|
const result = await this.taskRepository.getTasksFromTypistRelations(
|
|
userId,
|
|
offset,
|
|
limit,
|
|
paramName ?? defaultParamName,
|
|
direction ?? defaultDirection,
|
|
status,
|
|
);
|
|
// B2Cからユーザー名を取得する
|
|
const b2cUsers = await this.getB2cUsers(
|
|
result.tasks,
|
|
result.permissions,
|
|
);
|
|
|
|
const tasks = createTasks(result.tasks, result.permissions, b2cUsers);
|
|
|
|
return { tasks: tasks, total: result.count };
|
|
}
|
|
|
|
throw new Error(`invalid roles: ${roles.join(',')}`);
|
|
} catch (e) {
|
|
this.logger.error(`error=${e}`);
|
|
if (e instanceof Error) {
|
|
if (e.constructor === Adb2cTooManyRequestsError) {
|
|
throw new HttpException(
|
|
makeErrorResponse('E000301'),
|
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
);
|
|
}
|
|
}
|
|
throw new HttpException(
|
|
makeErrorResponse('E009999'),
|
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
);
|
|
}
|
|
}
|
|
private async getB2cUsers(
|
|
tasks: TaskEntity[],
|
|
permissions: CheckoutPermission[],
|
|
): Promise<AdB2cUser[]> {
|
|
// 割り当て候補の外部IDを列挙
|
|
const assigneesExternalIds = permissions.map((x) => {
|
|
if (x.user) {
|
|
return x.user.external_id;
|
|
}
|
|
});
|
|
// 割り当てられているタイピストの外部IDを列挙
|
|
const typistExternalIds = tasks.flatMap((x) => {
|
|
if (x.typist_user) {
|
|
return x.typist_user.external_id;
|
|
}
|
|
});
|
|
console.log(assigneesExternalIds.concat(undefined));
|
|
|
|
//重複をなくす
|
|
const distinctedExternalIds = [
|
|
...new Set(assigneesExternalIds.concat(typistExternalIds)),
|
|
];
|
|
|
|
// undefinedがあった場合、取り除く
|
|
const filteredExternalIds: string[] = distinctedExternalIds.filter(
|
|
(x): x is string => x !== undefined,
|
|
);
|
|
|
|
// B2Cからユーザー名を取得する
|
|
return await this.adB2cService.getUsers(filteredExternalIds);
|
|
}
|
|
}
|