saito.k 8ace80de74 Merged PR 517: API IF実装(代行操作用トークン生成)
## 概要
[Task2904: API IF](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2904)

- 以下のAPIのIF実装
  - POST /api/auth/delegation-token
  - POST /api/auth/delegation-access-token
- OpenApiを生成
- 不要なas変換を削除

## レビューポイント
- リクエスト・レスポンスの型は認識通りか
  - 代行操作用トークン生成APIの引数のパラメータ名はよさそうか(delegatedAccountId)
- アクセストークン再生成APIについてはガードを付けず、service内で引数に受け取ったリフレッシュトークンを検証し、正しいロール、階層かチェックする方向でよさそうか(通常のアクセストークン再生成と同様に)

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

## 補足
- 相談、参考資料などがあれば
2023-10-26 01:37:35 +00:00

1453 lines
39 KiB
TypeScript

import {
Body,
Controller,
HttpStatus,
Post,
Get,
Req,
UseGuards,
Param,
Query,
HttpException,
} from '@nestjs/common';
import {
ApiOperation,
ApiResponse,
ApiTags,
ApiBearerAuth,
} from '@nestjs/swagger';
import { ErrorResponse } from '../../common/error/types/types';
import { Request } from 'express';
import { AccountsService } from './accounts.service';
import {
CreateAccountRequest,
CreateAccountResponse,
GetLicenseSummaryRequest,
GetLicenseSummaryResponse,
GetMyAccountResponse,
GetTypistGroupsResponse,
GetTypistsResponse,
CreatePartnerAccountRequest,
CreatePartnerAccountResponse,
GetPartnerLicensesRequest,
GetPartnerLicensesResponse,
GetOrderHistoriesRequest,
GetOrderHistoriesResponse,
IssueLicenseRequest,
IssueLicenseResponse,
GetDealersResponse,
CreateTypistGroupResponse,
CreateTypistGroupRequest,
GetTypistGroupResponse,
GetTypistGroupRequest,
UpdateTypistGroupRequest,
UpdateTypistGroupRequestParam,
CancelIssueRequest,
CancelIssueResponse,
GetWorktypesResponse,
CreateWorktypeResponse,
CreateWorktypesRequest,
GetPartnersRequest,
GetPartnersResponse,
UpdateWorktypeRequestParam,
UpdateWorktypeResponse,
UpdateWorktypesRequest,
GetOptionItemsRequestParam,
GetOptionItemsResponse,
UpdateOptionItemsResponse,
UpdateOptionItemsRequestParam,
UpdateOptionItemsRequest,
PostActiveWorktypeRequest,
PostActiveWorktypeResponse,
UpdateAccountInfoRequest,
UpdateAccountInfoResponse,
DeleteAccountRequest,
DeleteAccountResponse,
GetAuthorsResponse,
GetAccountInfoMinimalAccessRequest,
GetAccountInfoMinimalAccessResponse,
DeleteWorktypeRequestParam,
DeleteWorktypeResponse,
} from './types/types';
import { USER_ROLES, ADMIN_ROLES, TIERS } from '../../constants';
import { AuthGuard } from '../../common/guards/auth/authguards';
import { RoleGuard } from '../../common/guards/role/roleguards';
import { retrieveAuthorizationToken } from '../../common/http/helper';
import { AccessToken } from '../../common/token';
import jwt from 'jsonwebtoken';
import { makeContext } from '../../common/log';
import { v4 as uuidv4 } from 'uuid';
import { AuthService } from '../auth/auth.service';
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
@ApiTags('accounts')
@Controller('accounts')
export class AccountsController {
constructor(
private readonly accountService: AccountsService, //private readonly cryptoService: CryptoService,
private readonly authService: AuthService,
) {}
@Post()
@ApiResponse({
status: HttpStatus.OK,
type: CreateAccountResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: '登録済みユーザーからの登録など',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'createAccount' })
async createAccount(
@Body() body: CreateAccountRequest,
): Promise<CreateAccountResponse> {
const {
companyName,
country,
dealerAccountId,
adminMail,
adminPassword,
adminName,
acceptedEulaVersion,
acceptedDpaVersion,
} = body;
const role = USER_ROLES.NONE;
const context = makeContext(uuidv4());
await this.accountService.createAccount(
context,
companyName,
country,
dealerAccountId,
adminMail,
adminPassword,
adminName,
role,
acceptedEulaVersion,
acceptedDpaVersion,
);
return {};
}
@ApiResponse({
status: HttpStatus.OK,
type: GetLicenseSummaryResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({
operationId: 'getLicenseSummary',
description: '指定したアカウントのライセンス集計情報を取得します',
})
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
@Post('licenses/summary')
async getLicenseSummary(
@Req() req: Request,
@Body() body: GetLicenseSummaryRequest,
): Promise<GetLicenseSummaryResponse> {
const response = await this.accountService.getLicenseSummary(
body.accountId,
);
return response;
}
@ApiResponse({
status: HttpStatus.OK,
type: GetMyAccountResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: '該当アカウントがDBに存在しない場合',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({
operationId: 'getMyAccount',
description: 'ログインしているユーザーのアカウント情報を取得します',
})
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
@Get('me')
async getMyAccount(@Req() req: Request): Promise<GetMyAccountResponse> {
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
HttpStatus.UNAUTHORIZED,
);
}
const decodedAccessToken = jwt.decode(accessToken, { json: true });
if (!decodedAccessToken) {
throw new HttpException(
makeErrorResponse('E000101'),
HttpStatus.UNAUTHORIZED,
);
}
const { userId } = decodedAccessToken as AccessToken;
const context = makeContext(userId);
//アカウントID取得処理
const accountInfo = await this.accountService.getAccountInfo(
context,
userId,
);
return accountInfo;
}
@ApiResponse({
status: HttpStatus.OK,
type: GetAuthorsResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({
operationId: 'getAuthors',
description:
'ログインしているユーザーのアカウント配下のAuthor一覧を取得します',
})
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
@Get('authors')
async getAuthors(@Req() req: Request): Promise<GetAuthorsResponse> {
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
HttpStatus.UNAUTHORIZED,
);
}
const decodedAccessToken = jwt.decode(accessToken, { json: true });
if (!decodedAccessToken) {
throw new HttpException(
makeErrorResponse('E000101'),
HttpStatus.UNAUTHORIZED,
);
}
const { userId } = decodedAccessToken as AccessToken;
const context = makeContext(userId);
const authors = await this.accountService.getAuthors(context, userId);
return { authors };
}
@ApiResponse({
status: HttpStatus.OK,
type: GetTypistsResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({
operationId: 'getTypists',
description:
'ログインしているユーザーのアカウント配下のタイピスト一覧を取得します',
})
@ApiBearerAuth()
@UseGuards(AuthGuard)
@Get('typists')
async getTypists(@Req() req: Request): Promise<GetTypistsResponse> {
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
HttpStatus.UNAUTHORIZED,
);
}
const decodedAccessToken = jwt.decode(accessToken, { json: true });
if (!decodedAccessToken) {
throw new HttpException(
makeErrorResponse('E000101'),
HttpStatus.UNAUTHORIZED,
);
}
const { userId } = decodedAccessToken as AccessToken;
const typists = await this.accountService.getTypists(userId);
return { typists };
}
@ApiResponse({
status: HttpStatus.OK,
type: GetTypistGroupsResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({
operationId: 'getTypistGroups',
description:
'ログインしているユーザーのアカウント配下のタイピストグループ一覧を取得します',
})
@ApiBearerAuth()
@UseGuards(AuthGuard)
@Get('typist-groups')
async getTypistGroups(@Req() req: Request): Promise<GetTypistGroupsResponse> {
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
HttpStatus.UNAUTHORIZED,
);
}
const decodedAccessToken = jwt.decode(accessToken, { json: true });
if (!decodedAccessToken) {
throw new HttpException(
makeErrorResponse('E000101'),
HttpStatus.UNAUTHORIZED,
);
}
const { userId } = decodedAccessToken as AccessToken;
const typistGroups = await this.accountService.getTypistGroups(userId);
return { typistGroups };
}
@ApiResponse({
status: HttpStatus.OK,
type: GetTypistGroupResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: 'グループが存在しない場合',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({
operationId: 'getTypistGroup',
description:
'ログインしているユーザーのアカウント配下でIDで指定されたタイピストグループを取得します',
})
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
@Get('typist-groups/:typistGroupId')
async getTypistGroup(
@Req() req: Request,
@Param() param: GetTypistGroupRequest,
): Promise<GetTypistGroupResponse> {
const { typistGroupId } = param;
// アクセストークン取得
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
HttpStatus.UNAUTHORIZED,
);
}
const decodedAccessToken = jwt.decode(accessToken, { json: true });
if (!decodedAccessToken) {
throw new HttpException(
makeErrorResponse('E000101'),
HttpStatus.UNAUTHORIZED,
);
}
const { userId } = decodedAccessToken as AccessToken;
const context = makeContext(userId);
const typistGroup = await this.accountService.getTypistGroup(
context,
userId,
typistGroupId,
);
return typistGroup;
}
@ApiResponse({
status: HttpStatus.OK,
type: CreateTypistGroupResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: 'グループ名が空の場合/ユーザーが存在しない場合',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({
operationId: 'createTypistGroup',
description:
'ログインしているユーザーのアカウント配下にタイピストグループを追加します',
})
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
@Post('typist-groups')
async createTypistGroup(
@Req() req: Request,
@Body() body: CreateTypistGroupRequest,
): Promise<CreateTypistGroupResponse> {
const { typistGroupName, typistIds } = body;
// アクセストークン取得
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
HttpStatus.UNAUTHORIZED,
);
}
const decodedAccessToken = jwt.decode(accessToken, { json: true });
if (!decodedAccessToken) {
throw new HttpException(
makeErrorResponse('E000101'),
HttpStatus.UNAUTHORIZED,
);
}
const { userId } = decodedAccessToken as AccessToken;
const context = makeContext(userId);
await this.accountService.createTypistGroup(
context,
userId,
typistGroupName,
typistIds,
);
return {};
}
@ApiResponse({
status: HttpStatus.OK,
type: CreateTypistGroupResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: 'グループ名が空の場合/ユーザーが存在しない場合',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({
operationId: 'updateTypistGroup',
description:
'ログインしているユーザーのアカウント配下でIDで指定されたタイピストグループを更新します',
})
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
@Post('typist-groups/:typistGroupId')
async updateTypistGroup(
@Req() req: Request,
@Body() body: UpdateTypistGroupRequest,
@Param() param: UpdateTypistGroupRequestParam,
): Promise<CreateTypistGroupResponse> {
const { typistGroupName, typistIds } = body;
const { typistGroupId } = param;
// アクセストークン取得
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
HttpStatus.UNAUTHORIZED,
);
}
const decodedAccessToken = jwt.decode(accessToken, { json: true });
if (!decodedAccessToken) {
throw new HttpException(
makeErrorResponse('E000101'),
HttpStatus.UNAUTHORIZED,
);
}
const { userId } = decodedAccessToken as AccessToken;
const context = makeContext(userId);
await this.accountService.updateTypistGroup(
context,
userId,
typistGroupId,
typistGroupName,
typistIds,
);
return {};
}
@Post('partner')
@ApiResponse({
status: HttpStatus.OK,
type: CreatePartnerAccountResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: '登録済みユーザーからの登録など',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'createPartnerAccount' })
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(
RoleGuard.requireds({
roles: [ADMIN_ROLES.ADMIN],
tiers: [TIERS.TIER1, TIERS.TIER2, TIERS.TIER3],
}),
)
async createPartnerAccount(
@Req() req: Request,
@Body() body: CreatePartnerAccountRequest,
): Promise<CreatePartnerAccountResponse> {
const { companyName, country, email, adminName } = body;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
HttpStatus.UNAUTHORIZED,
);
}
const decodedAccessToken = jwt.decode(accessToken, { json: true });
if (!decodedAccessToken) {
throw new HttpException(
makeErrorResponse('E000101'),
HttpStatus.UNAUTHORIZED,
);
}
const { userId, tier } = decodedAccessToken as AccessToken;
const context = makeContext(userId);
await this.accountService.createPartnerAccount(
context,
companyName,
country,
email,
adminName,
userId,
tier,
);
return {};
}
@Post('partner-licenses')
@ApiResponse({
status: HttpStatus.OK,
type: GetPartnerLicensesResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'getPartnerLicenses' })
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(
RoleGuard.requireds({
roles: [ADMIN_ROLES.ADMIN],
tiers: [TIERS.TIER1, TIERS.TIER2, TIERS.TIER3, TIERS.TIER4],
}),
)
async getPartnerLicenses(
@Req() req: Request,
@Body() body: GetPartnerLicensesRequest,
): Promise<GetPartnerLicensesResponse> {
const { limit, offset, accountId } = body;
const getPartnerLicensesResponse =
await this.accountService.getPartnerLicenses(limit, offset, accountId);
return getPartnerLicensesResponse;
}
@Post('order-histories')
@ApiResponse({
status: HttpStatus.OK,
type: GetOrderHistoriesResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'getOrderHistories' })
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(
RoleGuard.requireds({
roles: [ADMIN_ROLES.ADMIN],
}),
)
async getOrderHistories(
@Req() req: Request,
@Body() body: GetOrderHistoriesRequest,
): Promise<GetOrderHistoriesResponse> {
const { limit, offset, accountId } = body;
const getOrderHistoriesResponse =
await this.accountService.getOrderHistories(limit, offset, accountId);
return getOrderHistoriesResponse;
}
@Post('/licenses/issue')
@ApiResponse({
status: HttpStatus.OK,
type: IssueLicenseResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description:
'自身のライセンス数が不足している場合/すでに対象注文が発行済の場合',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'issueLicense' })
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(
RoleGuard.requireds({
roles: [ADMIN_ROLES.ADMIN],
tiers: [TIERS.TIER1, TIERS.TIER2, TIERS.TIER3, TIERS.TIER4],
}),
)
async issueLicense(
@Req() req: Request,
@Body() body: IssueLicenseRequest,
): Promise<IssueLicenseResponse> {
const { orderedAccountId, poNumber } = body;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
HttpStatus.UNAUTHORIZED,
);
}
const decodedAccessToken = jwt.decode(accessToken, { json: true });
if (!decodedAccessToken) {
throw new HttpException(
makeErrorResponse('E000101'),
HttpStatus.UNAUTHORIZED,
);
}
const { userId, tier } = decodedAccessToken as AccessToken;
const context = makeContext(userId);
await this.accountService.issueLicense(
context,
orderedAccountId,
userId,
tier,
poNumber,
);
return {};
}
@Get('/dealers')
@ApiResponse({
status: HttpStatus.OK,
type: GetDealersResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'getDealers' })
async getDealers(): Promise<GetDealersResponse> {
return await this.accountService.getDealers();
}
@Post('/issue/cancel')
@ApiResponse({
status: HttpStatus.OK,
type: CancelIssueResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description:
'対象注文のステータスが発行済以外/発行日から15日以降/ライセンスをユーザに割り当てている',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({
operationId: 'cancelIssue',
description: 'ライセンス発行をキャンセルします',
})
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(
RoleGuard.requireds({
roles: [ADMIN_ROLES.ADMIN],
tiers: [TIERS.TIER1, TIERS.TIER2],
}),
)
async cancelIssue(
@Req() req: Request,
@Body() body: CancelIssueRequest,
): Promise<CancelIssueResponse> {
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
HttpStatus.UNAUTHORIZED,
);
}
const decodedAccessToken = jwt.decode(accessToken, { json: true });
if (!decodedAccessToken) {
throw new HttpException(
makeErrorResponse('E000101'),
HttpStatus.UNAUTHORIZED,
);
}
const { userId } = decodedAccessToken as AccessToken;
const context = makeContext(userId);
await this.accountService.cancelIssue(
context,
userId,
body.poNumber,
body.orderedAccountId,
);
return {};
}
@Get('/worktypes')
@ApiResponse({
status: HttpStatus.OK,
type: GetWorktypesResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'getWorktypes' })
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
async getWorktypes(@Req() req: Request): Promise<GetWorktypesResponse> {
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
HttpStatus.UNAUTHORIZED,
);
}
const decodedAccessToken = jwt.decode(accessToken, { json: true });
if (!decodedAccessToken) {
throw new HttpException(
makeErrorResponse('E000101'),
HttpStatus.UNAUTHORIZED,
);
}
const { userId } = decodedAccessToken as AccessToken;
const context = makeContext(userId);
const worktypes = await this.accountService.getWorktypes(context, userId);
return worktypes;
}
@Post('/worktypes')
@ApiResponse({
status: HttpStatus.OK,
type: CreateWorktypeResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: 'WorktypeIDが重複 / WorktypeIDが空 / WorktypeIDが20件登録済み',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'createWorktype' })
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
async createWorktype(
@Req() req: Request,
@Body() body: CreateWorktypesRequest,
): Promise<CreateWorktypeResponse> {
const { worktypeId, description } = body;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
HttpStatus.UNAUTHORIZED,
);
}
const decodedAccessToken = jwt.decode(accessToken, { json: true });
if (!decodedAccessToken) {
throw new HttpException(
makeErrorResponse('E000101'),
HttpStatus.UNAUTHORIZED,
);
}
const { userId } = decodedAccessToken as AccessToken;
const context = makeContext(userId);
await this.accountService.createWorktype(
context,
userId,
worktypeId,
description,
);
return {};
}
@Post('/worktypes/:id')
@ApiResponse({
status: HttpStatus.OK,
type: UpdateWorktypeResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: 'WorktypeIDが重複 / WorktypeIDが空',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'updateWorktype' })
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
async updateWorktype(
@Req() req: Request,
@Param() param: UpdateWorktypeRequestParam,
@Body() body: UpdateWorktypesRequest,
): Promise<UpdateWorktypeResponse> {
const { worktypeId, description } = body;
const { id } = param;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
HttpStatus.UNAUTHORIZED,
);
}
const decodedAccessToken = jwt.decode(accessToken, { json: true });
if (!decodedAccessToken) {
throw new HttpException(
makeErrorResponse('E000101'),
HttpStatus.UNAUTHORIZED,
);
}
const { userId } = decodedAccessToken as AccessToken;
const context = makeContext(userId);
await this.accountService.updateWorktype(
context,
userId,
id,
worktypeId,
description,
);
return {};
}
@Post('/worktypes/:id/delete')
@ApiResponse({
status: HttpStatus.OK,
type: DeleteWorktypeResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: '指定WorktypeIDが削除済み / 指定WorktypeIDがWorkflowで使用中',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'deleteWorktype' })
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
async deleteWorktype(
@Req() req: Request,
@Param() param: DeleteWorktypeRequestParam,
): Promise<DeleteWorktypeResponse> {
const { id } = param;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
HttpStatus.UNAUTHORIZED,
);
}
const decodedAccessToken = jwt.decode(accessToken, { json: true });
if (!decodedAccessToken) {
throw new HttpException(
makeErrorResponse('E000101'),
HttpStatus.UNAUTHORIZED,
);
}
const { userId } = decodedAccessToken as AccessToken;
const context = makeContext(userId);
await this.accountService.deleteWorktype(context, userId, id);
return {};
}
@Get('/worktypes/:id/option-items')
@ApiResponse({
status: HttpStatus.OK,
type: GetOptionItemsResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: 'WorktypeIDが不在',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'getOptionItems' })
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
async getOptionItems(
@Req() req: Request,
@Param() param: GetOptionItemsRequestParam,
): Promise<GetOptionItemsResponse> {
const { id } = param;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
HttpStatus.UNAUTHORIZED,
);
}
const decodedAccessToken = jwt.decode(accessToken, { json: true });
if (!decodedAccessToken) {
throw new HttpException(
makeErrorResponse('E000101'),
HttpStatus.UNAUTHORIZED,
);
}
const { userId } = decodedAccessToken as AccessToken;
const context = makeContext(userId);
const optionItems = await this.accountService.getOptionItems(
context,
userId,
id,
);
return optionItems;
}
@Post('/worktypes/:id/option-items')
@ApiResponse({
status: HttpStatus.OK,
type: UpdateOptionItemsResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: 'WorktypeIDが不在',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'updateOptionItems' })
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
async updateOptionItems(
@Req() req: Request,
@Param() param: UpdateOptionItemsRequestParam,
@Body() body: UpdateOptionItemsRequest,
): Promise<UpdateOptionItemsResponse> {
const { optionItems } = body;
const { id } = param;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
HttpStatus.UNAUTHORIZED,
);
}
const decodedAccessToken = jwt.decode(accessToken, { json: true });
if (!decodedAccessToken) {
throw new HttpException(
makeErrorResponse('E000101'),
HttpStatus.UNAUTHORIZED,
);
}
const { userId } = decodedAccessToken as AccessToken;
const context = makeContext(userId);
await this.accountService.updateOptionItems(
context,
userId,
id,
optionItems,
);
return {};
}
@Post('/active-worktype')
@ApiResponse({
status: HttpStatus.OK,
type: PostActiveWorktypeResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: 'WorktypeIDが存在しない',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'activeWorktype' })
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
async activeWorktype(
@Req() req: Request,
@Body() body: PostActiveWorktypeRequest,
): Promise<PostActiveWorktypeResponse> {
const { id } = body;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
HttpStatus.UNAUTHORIZED,
);
}
const decodedAccessToken = jwt.decode(accessToken, { json: true });
if (!decodedAccessToken) {
throw new HttpException(
makeErrorResponse('E000101'),
HttpStatus.UNAUTHORIZED,
);
}
const { userId } = decodedAccessToken as AccessToken;
const context = makeContext(userId);
await this.accountService.updateActiveWorktype(context, userId, id);
return {};
}
@Get('/partners')
@ApiResponse({
status: HttpStatus.OK,
type: GetPartnersResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: 'パラメータ不正',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'getPartners' })
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(
RoleGuard.requireds({
roles: [ADMIN_ROLES.ADMIN],
tiers: [TIERS.TIER1, TIERS.TIER2, TIERS.TIER3, TIERS.TIER4],
}),
)
async getPartners(
@Req() req: Request,
@Query() query: GetPartnersRequest,
): Promise<GetPartnersResponse> {
const { limit, offset } = query;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
HttpStatus.UNAUTHORIZED,
);
}
const decodedAccessToken = jwt.decode(accessToken, { json: true });
if (!decodedAccessToken) {
throw new HttpException(
makeErrorResponse('E000101'),
HttpStatus.UNAUTHORIZED,
);
}
const { userId } = decodedAccessToken as AccessToken;
const context = makeContext(userId);
const response = await this.accountService.getPartners(
context,
userId,
limit,
offset,
);
return response;
}
@Post('/me')
@ApiResponse({
status: HttpStatus.OK,
type: UpdateAccountInfoResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: 'パラメータ不正/アカウント・ユーザー不在/管理者ユーザ不在',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'updateAccountInfo' })
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(
RoleGuard.requireds({
roles: [ADMIN_ROLES.ADMIN],
}),
)
async updateAccountInfo(
@Req() req: Request,
@Body() body: UpdateAccountInfoRequest,
): Promise<UpdateAccountInfoResponse> {
const {
parentAccountId,
delegationPermission,
primaryAdminUserId,
secondryAdminUserId,
} = body;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
HttpStatus.UNAUTHORIZED,
);
}
const decodedAccessToken = jwt.decode(accessToken, { json: true });
if (!decodedAccessToken) {
throw new HttpException(
makeErrorResponse('E000101'),
HttpStatus.UNAUTHORIZED,
);
}
const { userId, tier } = decodedAccessToken as AccessToken;
const context = makeContext(userId);
await this.accountService.updateAccountInfo(
context,
userId,
tier,
delegationPermission,
primaryAdminUserId,
parentAccountId,
secondryAdminUserId,
);
return {};
}
@Post('/delete')
@ApiResponse({
status: HttpStatus.OK,
type: UpdateAccountInfoResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: 'DBアクセスに失敗しログインできる状態で処理が終了した場合',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'deleteAccountAndData' })
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(
RoleGuard.requireds({
roles: [ADMIN_ROLES.ADMIN],
}),
)
async deleteAccountAndData(
@Req() req: Request,
@Body() body: DeleteAccountRequest,
): Promise<DeleteAccountResponse> {
const { accountId } = body;
const accessToken = retrieveAuthorizationToken(req);
if (!accessToken) {
throw new HttpException(
makeErrorResponse('E000107'),
HttpStatus.UNAUTHORIZED,
);
}
const decodedAccessToken = jwt.decode(accessToken, { json: true });
if (!decodedAccessToken) {
throw new HttpException(
makeErrorResponse('E000101'),
HttpStatus.UNAUTHORIZED,
);
}
const { userId } = decodedAccessToken as AccessToken;
const context = makeContext(userId);
await this.accountService.deleteAccountAndData(context, userId, accountId);
return {};
}
@Post('/minimal-access')
@ApiResponse({
status: HttpStatus.OK,
type: GetAccountInfoMinimalAccessResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: '対象のユーザーIDが存在しない場合',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'getAccountInfoMinimalAccess' })
async getAccountInfoMinimalAccess(
@Body() body: GetAccountInfoMinimalAccessRequest,
): Promise<GetAccountInfoMinimalAccessResponse> {
// IDトークンの検証
const idToken = await this.authService.getVerifiedIdToken(body.idToken);
const isVerified = await this.authService.isVerifiedUser(idToken);
if (!isVerified) {
throw new HttpException(
makeErrorResponse('E010201'),
HttpStatus.BAD_REQUEST,
);
}
const context = makeContext(idToken.sub);
const tier = await this.accountService.getAccountInfoMinimalAccess(
context,
idToken.sub,
);
return { tier };
}
}