From ecb28b9328a48db60b8469036c442585e6d94012 Mon Sep 17 00:00:00 2001 From: Kentaro Fukunaga Date: Mon, 19 Feb 2024 04:32:59 +0000 Subject: [PATCH] =?UTF-8?q?Merged=20PR=20759:=20API=20IF=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 概要 [Task3711: API IF実装](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/3711) - アカウント利用制限更新APIのIFを実装し、openapi生成しました。 ## レビューポイント - メソッド名で他に案あれば。 ## 動作確認状況 - 特になし --- dictation_server/src/api/odms/openapi.json | 70 +++++++++++++++++ .../features/accounts/accounts.controller.ts | 76 +++++++++++++++++++ .../src/features/accounts/types/types.ts | 14 ++++ 3 files changed, 160 insertions(+) diff --git a/dictation_server/src/api/odms/openapi.json b/dictation_server/src/api/odms/openapi.json index eb999e6..38b804a 100644 --- a/dictation_server/src/api/odms/openapi.json +++ b/dictation_server/src/api/odms/openapi.json @@ -1609,6 +1609,61 @@ "security": [{ "bearer": [] }] } }, + "/accounts/restriction-status": { + "post": { + "operationId": "updateRestrictionStatus", + "summary": "", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateRestrictionStatusRequest" + } + } + } + }, + "responses": { + "200": { + "description": "成功時のレスポンス", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateRestrictionStatusResponse" + } + } + } + }, + "400": { + "description": "パラメータ不正/アカウント不在", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ErrorResponse" } + } + } + }, + "401": { + "description": "認証エラー", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ErrorResponse" } + } + } + }, + "500": { + "description": "想定外のサーバーエラー", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ErrorResponse" } + } + } + } + }, + "tags": ["accounts"], + "security": [{ "bearer": [] }] + } + }, "/users/confirm": { "post": { "operationId": "confirmUser", @@ -4359,6 +4414,21 @@ "properties": { "companyName": { "type": "string" } }, "required": ["companyName"] }, + "UpdateRestrictionStatusRequest": { + "type": "object", + "properties": { + "accountId": { + "type": "number", + "description": "操作対象の第五階層アカウントID" + }, + "restricted": { + "type": "boolean", + "description": "制限をかけるかどうか(trur:制限をかける)" + } + }, + "required": ["accountId", "restricted"] + }, + "UpdateRestrictionStatusResponse": { "type": "object", "properties": {} }, "ConfirmRequest": { "type": "object", "properties": { "token": { "type": "string" } }, diff --git a/dictation_server/src/features/accounts/accounts.controller.ts b/dictation_server/src/features/accounts/accounts.controller.ts index 1dacf58..ef75727 100644 --- a/dictation_server/src/features/accounts/accounts.controller.ts +++ b/dictation_server/src/features/accounts/accounts.controller.ts @@ -75,6 +75,8 @@ import { DeleteTypistGroupResponse, UpdateFileDeleteSettingRequest, UpdateFileDeleteSettingResponse, + UpdateRestrictionStatusRequest, + UpdateRestrictionStatusResponse, } from './types/types'; import { USER_ROLES, ADMIN_ROLES, TIERS } from '../../constants'; import { AuthGuard } from '../../common/guards/auth/authguards'; @@ -2240,4 +2242,78 @@ export class AccountsController { ); return companyName; } + + @ApiResponse({ + status: HttpStatus.OK, + type: UpdateRestrictionStatusResponse, + 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: 'updateRestrictionStatus' }) + @ApiBearerAuth() + @UseGuards(AuthGuard) + @UseGuards( + RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN], tiers: [TIERS.TIER1] }), + ) + @Post('restriction-status') + async updateRestrictionStatus( + @Req() req: Request, + @Body() body: UpdateRestrictionStatusRequest, + ): Promise { + const accessToken = retrieveAuthorizationToken(req); + if (!accessToken) { + throw new HttpException( + makeErrorResponse('E000107'), + HttpStatus.UNAUTHORIZED, + ); + } + + const ip = retrieveIp(req); + if (!ip) { + throw new HttpException( + makeErrorResponse('E000401'), + HttpStatus.UNAUTHORIZED, + ); + } + + const requestId = retrieveRequestId(req); + if (!requestId) { + throw new HttpException( + makeErrorResponse('E000501'), + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + 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, requestId); + this.logger.log(`[${context.getTrackingId()}] ip : ${ip}`); + + // service層を呼び出す + const { accountId, restricted } = body; + // TODO:service層実装時に削除する + this.logger.log(`accountId: ${accountId}, restricted: ${restricted}`); + + return {}; + } } diff --git a/dictation_server/src/features/accounts/types/types.ts b/dictation_server/src/features/accounts/types/types.ts index 08217f8..22da103 100644 --- a/dictation_server/src/features/accounts/types/types.ts +++ b/dictation_server/src/features/accounts/types/types.ts @@ -357,6 +357,18 @@ export class GetCompanyNameRequest { accountId: number; } +export class UpdateRestrictionStatusRequest { + @ApiProperty({ description: '操作対象の第五階層アカウントID' }) + @Type(() => Number) + @IsInt() + @Min(1) + accountId: number; + + @ApiProperty({ description: '制限をかけるかどうか(trur:制限をかける)' }) + @Type(() => Boolean) + restricted: boolean; +} + // ============================== // RESPONSE // ============================== @@ -672,6 +684,8 @@ export class UpdateFileDeleteSettingRequest { export class UpdateFileDeleteSettingResponse {} +export class UpdateRestrictionStatusResponse {} + // ============================== // Request/Response外の型 // TODO: Request/Response/その他の型を別ファイルに分ける