diff --git a/dictation_server/src/api/odms/openapi.json b/dictation_server/src/api/odms/openapi.json index ddc9bf4..f980577 100644 --- a/dictation_server/src/api/odms/openapi.json +++ b/dictation_server/src/api/odms/openapi.json @@ -882,6 +882,62 @@ "security": [{ "bearer": [] }] } }, + "/users/license/allocate": { + "post": { + "operationId": "allocateLicense", + "summary": "", + "description": "ライセンスを割り当てます", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AllocateLicenseRequest" + } + } + } + }, + "responses": { + "200": { + "description": "成功時のレスポンス", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AllocateLicenseResponse" + } + } + } + }, + "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": ["users"], + "security": [{ "bearer": [] }] + } + }, "/files/audio/upload-finished": { "post": { "operationId": "uploadFinished", @@ -1816,6 +1872,54 @@ "security": [{ "bearer": [] }] } }, + "/licenses/allocatable": { + "get": { + "operationId": "getAllocatableLicenses", + "summary": "", + "description": "割り当て可能なライセンスを取得します", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetAllocatableLicensesRequest" + } + } + } + }, + "responses": { + "200": { + "description": "成功時のレスポンス", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetAllocatableLicensesResponse" + } + } + } + }, + "401": { + "description": "認証エラー", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ErrorResponse" } + } + } + }, + "500": { + "description": "想定外のサーバーエラー", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ErrorResponse" } + } + } + } + }, + "tags": ["licenses"], + "security": [{ "bearer": [] }] + } + }, "/notification/register": { "post": { "operationId": "register", @@ -2373,6 +2477,18 @@ "required": ["id", "role", "autoRenew", "licenseAlart", "notification"] }, "PostUpdateUserResponse": { "type": "object", "properties": {} }, + "AllocateLicenseRequest": { + "type": "object", + "properties": { + "userId": { "type": "number", "description": "ユーザーID" }, + "newLicenseId": { + "type": "number", + "description": "割り当てるライセンスのID" + } + }, + "required": ["userId", "newLicenseId"] + }, + "AllocateLicenseResponse": { "type": "object", "properties": {} }, "AudioOptionItem": { "type": "object", "properties": { @@ -2671,6 +2787,25 @@ "required": ["cardLicenseKey"] }, "ActivateCardLicensesResponse": { "type": "object", "properties": {} }, + "GetAllocatableLicensesRequest": { "type": "object", "properties": {} }, + "AllocatableLicenseInfo": { + "type": "object", + "properties": { + "licenseId": { "type": "number" }, + "expiryDate": { "format": "date-time", "type": "string" } + }, + "required": ["licenseId", "expiryDate"] + }, + "GetAllocatableLicensesResponse": { + "type": "object", + "properties": { + "allocatableLicenses": { + "type": "array", + "items": { "$ref": "#/components/schemas/AllocatableLicenseInfo" } + } + }, + "required": ["allocatableLicenses"] + }, "RegisterRequest": { "type": "object", "properties": { diff --git a/dictation_server/src/features/licenses/licenses.controller.ts b/dictation_server/src/features/licenses/licenses.controller.ts index 9ce59f0..c119052 100644 --- a/dictation_server/src/features/licenses/licenses.controller.ts +++ b/dictation_server/src/features/licenses/licenses.controller.ts @@ -1,6 +1,7 @@ import { Body, Controller, + Get, HttpStatus, Post, Req, @@ -21,6 +22,8 @@ import { IssueCardLicensesRequest, ActivateCardLicensesResponse, ActivateCardLicensesRequest, + GetAllocatableLicensesResponse, + GetAllocatableLicensesRequest, } from './types/types'; import { Request } from 'express'; import { retrieveAuthorizationToken } from '../../common/http/helper'; @@ -169,4 +172,45 @@ export class LicensesController { return {}; } + + @ApiResponse({ + status: HttpStatus.OK, + type: GetAllocatableLicensesResponse, + description: '成功時のレスポンス', + }) + @ApiResponse({ + status: HttpStatus.UNAUTHORIZED, + description: '認証エラー', + type: ErrorResponse, + }) + @ApiResponse({ + status: HttpStatus.INTERNAL_SERVER_ERROR, + description: '想定外のサーバーエラー', + type: ErrorResponse, + }) + @ApiOperation({ + operationId: 'getAllocatableLicenses', + description: '割り当て可能なライセンスを取得します', + }) + @ApiBearerAuth() + @UseGuards(AuthGuard) + @UseGuards( + RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN], tiers: [TIERS.TIER5] }), + ) + @Get('/allocatable') + async getAllocatableLicenses( + @Req() req: Request, + @Body() body: GetAllocatableLicensesRequest, + ): Promise { + + // TODO 仮の戻り値 + return { + allocatableLicenses: [ + { licenseId: 1, expiryDate: null }, + { licenseId: 2, expiryDate: null }, + { licenseId: 3, expiryDate: new Date(2023, 12, 31, 23, 59, 59) }, + { licenseId: 4, expiryDate: new Date(2023, 10, 31, 23, 59, 59) }, + ], + }; + } } diff --git a/dictation_server/src/features/licenses/types/types.ts b/dictation_server/src/features/licenses/types/types.ts index ad6b933..71d8344 100644 --- a/dictation_server/src/features/licenses/types/types.ts +++ b/dictation_server/src/features/licenses/types/types.ts @@ -38,6 +38,19 @@ export class ActivateCardLicensesRequest { export class ActivateCardLicensesResponse {} +export class GetAllocatableLicensesRequest {} + +export class AllocatableLicenseInfo { + @ApiProperty() + licenseId: number; + @ApiProperty() + expiryDate: Date; +} +export class GetAllocatableLicensesResponse { + @ApiProperty({ type: [AllocatableLicenseInfo] }) + allocatableLicenses: AllocatableLicenseInfo[]; +} + // ライセンス算出用に、その日の始まりの時刻(0:00:00.000)の日付を取得する export class DateWithZeroTime extends Date { constructor(...args: any[]) { diff --git a/dictation_server/src/features/users/types/types.ts b/dictation_server/src/features/users/types/types.ts index d70d6ac..135d77b 100644 --- a/dictation_server/src/features/users/types/types.ts +++ b/dictation_server/src/features/users/types/types.ts @@ -239,3 +239,12 @@ export class PostUpdateUserRequest { } export class PostUpdateUserResponse {} + +export class AllocateLicenseRequest { + @ApiProperty({ description: 'ユーザーID' }) + userId: number; + @ApiProperty({ description: '割り当てるライセンスのID' }) + newLicenseId: number; +} + +export class AllocateLicenseResponse{} \ No newline at end of file diff --git a/dictation_server/src/features/users/users.controller.ts b/dictation_server/src/features/users/users.controller.ts index f908b6d..a4277c0 100644 --- a/dictation_server/src/features/users/users.controller.ts +++ b/dictation_server/src/features/users/users.controller.ts @@ -33,6 +33,8 @@ import { GetSortCriteriaResponse, PostUpdateUserRequest, PostUpdateUserResponse, + AllocateLicenseResponse, + AllocateLicenseRequest, } from './types/types'; import { UsersService } from './users.service'; import jwt from 'jsonwebtoken'; @@ -41,7 +43,7 @@ import { isSortDirection, isTaskListSortableAttribute, } from '../../common/types/sort'; -import { ADMIN_ROLES } from '../../constants'; +import { ADMIN_ROLES, TIERS } from '../../constants'; import { RoleGuard } from '../../common/guards/role/roleguards'; import { makeContext } from '../../common/log'; import { UserRoles } from '../../common/types/role'; @@ -372,4 +374,42 @@ export class UsersController { ); return {}; } + + @ApiResponse({ + status: HttpStatus.OK, + type: AllocateLicenseResponse, + 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: 'allocateLicense', + description: 'ライセンスを割り当てます', + }) + @ApiBearerAuth() + @UseGuards(AuthGuard) + @UseGuards( + RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN], tiers: [TIERS.TIER5] }), + ) + @Post('/license/allocate') + async allocateLicense( + @Body() body: AllocateLicenseRequest, + @Req() req: Request, + ): Promise { + return {}; + } } +