diff --git a/dictation_server/src/common/auth/auth.ts b/dictation_server/src/common/auth/auth.ts deleted file mode 100644 index 231f181..0000000 --- a/dictation_server/src/common/auth/auth.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * 権限の過不足を確認する - * @param {string[]} - * @return {boolean} - */ -// XXX: deprecated 削除予定 -export const confirmPermission = (authority: string): boolean => { - console.log(authority); - - return true; -}; diff --git a/dictation_server/src/common/guards/role/roleguards.spec.ts b/dictation_server/src/common/guards/role/roleguards.spec.ts index b863438..ef6fc99 100644 --- a/dictation_server/src/common/guards/role/roleguards.spec.ts +++ b/dictation_server/src/common/guards/role/roleguards.spec.ts @@ -1,17 +1,18 @@ +import { ADMIN_ROLES, USER_ROLES } from '../../../constants'; import { RoleGuard } from './roleguards'; describe('RoleGuard', () => { it('1つの許可Roleが設定時、完全に一致するroleを持つ場合、許可される', () => { - const guards = RoleGuard.requireds({ roles: ['author'] }); + const guards = RoleGuard.requireds({ roles: [USER_ROLES.AUTHOR] }); expect(guards.checkRole('author')).toBeTruthy(); }); it('1つの許可Roleが設定時、その許可roleを含むroleを持つ場合、許可される', () => { - const guards = RoleGuard.requireds({ roles: ['author'] }); + const guards = RoleGuard.requireds({ roles: [USER_ROLES.AUTHOR] }); // 'author admin'が許可リスト(author)に含まれるので許可 expect(guards.checkRole('author admin')).toBeTruthy(); }); it('author OR adminの許可Roleが設定時、その許可roleを含むroleを持つ場合、許可される', () => { - const guards = RoleGuard.requireds({ roles: ['author', 'admin'] }); + const guards = RoleGuard.requireds({ roles: [USER_ROLES.AUTHOR, ADMIN_ROLES.ADMIN] }); // authorが許可リスト([authorまたはadmin])に含まれるので許可 expect(guards.checkRole('author')).toBeTruthy(); // adminが許可リスト([authorまたはadmin])に含まれるので許可 @@ -20,19 +21,25 @@ describe('RoleGuard', () => { expect(guards.checkRole('author admin')).toBeTruthy(); }); it('author OR adminの許可Roleが設定時、その許可roleを含むroleを持たない場合、拒否される', () => { - const guards = RoleGuard.requireds({ roles: ['author', 'admin'] }); + const guards = RoleGuard.requireds({ + roles: [USER_ROLES.AUTHOR, ADMIN_ROLES.ADMIN], + }); // typistが許可リスト([authorまたはadmin])に含まれないので拒否 expect(guards.checkRole('typist')).toBeFalsy(); }); it('author AND adminの許可Roleが設定時、その許可roleを含むroleを持つ場合、許可される', () => { - const guards = RoleGuard.requireds({ roles: [['author', 'admin']] }); + const guards = RoleGuard.requireds({ + roles: [[USER_ROLES.AUTHOR, ADMIN_ROLES.ADMIN]], + }); // 'author admin'が許可リスト([authorかつadmin])に含まれるので許可 expect(guards.checkRole('author admin')).toBeTruthy(); // 'typist author admin'が許可リスト([authorかつadmin])に含まれるので許可 expect(guards.checkRole('typist author admin')).toBeTruthy(); }); it('author AND adminの許可Roleが設定時、その許可roleに合致しないroleを持つ場合、拒否される', () => { - const guards = RoleGuard.requireds({ roles: [['author', 'admin']] }); + const guards = RoleGuard.requireds({ + roles: [[USER_ROLES.AUTHOR, ADMIN_ROLES.ADMIN]], + }); // authorが許可リスト([authorかつadmin])に含まれないので拒否 expect(guards.checkRole('author')).toBeFalsy(); // adminが許可リスト([authorかつadmin])に含まれないので拒否 @@ -42,7 +49,7 @@ describe('RoleGuard', () => { }); it('(author AND admin) OR typistの許可Roleが設定時、その許可roleを含むroleを持つ場合、許可される', () => { const guards = RoleGuard.requireds({ - roles: [['author', 'admin'], 'typist'], + roles: [[USER_ROLES.AUTHOR, ADMIN_ROLES.ADMIN], USER_ROLES.TYPIST], }); // typistが許可リスト(typist)に含まれないので許可 expect(guards.checkRole('typist')).toBeTruthy(); @@ -53,7 +60,7 @@ describe('RoleGuard', () => { }); it('(author AND admin) OR typistの許可Roleが設定時、その許可roleを含むroleを持たない場合、拒否される', () => { const guards = RoleGuard.requireds({ - roles: [['author', 'admin'], 'typist'], + roles: [[USER_ROLES.AUTHOR, ADMIN_ROLES.ADMIN], USER_ROLES.TYPIST], }); // authorが許可リスト([authorかつadmin])に含まれないので拒否 expect(guards.checkRole('author')).toBeFalsy(); diff --git a/dictation_server/src/features/auth/auth.controller.ts b/dictation_server/src/features/auth/auth.controller.ts index 2fcd54c..cf29a4e 100644 --- a/dictation_server/src/features/auth/auth.controller.ts +++ b/dictation_server/src/features/auth/auth.controller.ts @@ -98,9 +98,9 @@ export class AuthController { }) async accessToken(@Req() req): Promise { const refreshToken = retrieveAuthorizationToken(req); - if (refreshToken !== undefined) { + if (!refreshToken) { throw new HttpException( - makeErrorResponse('E009999'), + makeErrorResponse('E000107'), HttpStatus.UNAUTHORIZED, ); } diff --git a/dictation_server/src/features/auth/auth.service.ts b/dictation_server/src/features/auth/auth.service.ts index 8852ff6..c06605b 100644 --- a/dictation_server/src/features/auth/auth.service.ts +++ b/dictation_server/src/features/auth/auth.service.ts @@ -145,7 +145,11 @@ export class AuthService { const token = verify(refreshToken, pubkey); if (isVerifyError(token)) { - throw new Error(`${token.reason} | ${token.message}`); + this.logger.error(`${token.reason} | ${token.message}`); + throw new HttpException( + makeErrorResponse('E000101'), + HttpStatus.UNAUTHORIZED, + ); } const accessToken = sign( diff --git a/dictation_server/src/features/files/files.controller.ts b/dictation_server/src/features/files/files.controller.ts index 7d37307..8efd206 100644 --- a/dictation_server/src/features/files/files.controller.ts +++ b/dictation_server/src/features/files/files.controller.ts @@ -30,6 +30,7 @@ import { } from './types/types'; import { AuthGuard } from '../../common/guards/auth/authguards'; import { RoleGuard } from '../../common/guards/role/roleguards'; +import { USER_ROLES } from '../../constants'; @ApiTags('files') @Controller('files') @@ -63,7 +64,7 @@ export class FilesController { }) @ApiBearerAuth() @UseGuards(AuthGuard) - @UseGuards(RoleGuard.requireds({ roles: ['author'] })) + @UseGuards(RoleGuard.requireds({ roles: [USER_ROLES.AUTHOR] })) @Post('audio/upload-finished') async uploadFinished( @Headers('authorization') authorization: string, @@ -134,12 +135,14 @@ export class FilesController { 'ログイン中ユーザー用のBlob Storage上の音声ファイルのアップロード先アクセスURLを取得します', }) @ApiBearerAuth() + @UseGuards(AuthGuard) + @UseGuards(RoleGuard.requireds({ roles: [USER_ROLES.AUTHOR] })) async uploadLocation( @Headers('authorization') authorization: string, - @Query() query: AudioUploadLocationRequest, - ): Promise { - const {} = query; - //TODO Guardsで認証するからここではデコードするだけ + // クエリパラメータ AudioUploadLocationRequest は空であるため内部で使用しない。 + // 使用しないことを宣言するために先頭にプレフィックス_(アンダースコア)をつけている + @Query() _query: AudioUploadLocationRequest, + ): Promise { const token = authorization.substring( 'Bearer '.length, authorization.length, diff --git a/dictation_server/src/features/licenses/licenses.controller.ts b/dictation_server/src/features/licenses/licenses.controller.ts index 9c3eeb2..ef6a95a 100644 --- a/dictation_server/src/features/licenses/licenses.controller.ts +++ b/dictation_server/src/features/licenses/licenses.controller.ts @@ -8,21 +8,22 @@ import { UseGuards, } from '@nestjs/common'; import { - ApiBearerAuth, - ApiOperation, ApiResponse, - ApiTags, + ApiTags, + ApiOperation, + ApiBearerAuth, } from '@nestjs/swagger'; -import { Request } from 'express'; -import { decode } from 'jsonwebtoken'; import { makeErrorResponse } from '../../common/error/makeErrorResponse'; import { ErrorResponse } from '../../common/error/types/types'; -import { AuthGuard } from '../../common/guards/auth/authguards'; -import { RoleGuard } from '../../common/guards/role/roleguards'; +import { LicensesService } from './licenses.service'; +import { CreateOrdersResponse, CreateOrdersRequest } from './types/types'; +import { Request } from 'express'; import { retrieveAuthorizationToken } from '../../common/http/helper'; import { AccessToken } from '../../common/token'; -import { LicensesService } from './licenses.service'; -import { CreateOrdersRequest, CreateOrdersResponse } from './types/types'; +import { AuthGuard } from '../../common/guards/auth/authguards'; +import { RoleGuard } from '../../common/guards/role/roleguards'; +import { ADMIN_ROLES } from '../../constants'; +import jwt from 'jsonwebtoken'; @ApiTags('licenses') @Controller('licenses') @@ -51,7 +52,7 @@ export class LicensesController { @ApiOperation({ operationId: 'createOrders' }) @ApiBearerAuth() @UseGuards(AuthGuard) - @UseGuards(RoleGuard.requireds({ roles: ['admin', 'author'] })) + @UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] })) @Post('/orders') async createOrders( @Req() req: Request, @@ -60,22 +61,13 @@ export class LicensesController { console.log(req.header('Authorization')); console.log(body); + // AuthGuardでチェック済みなのでここでのアクセストークンチェックはしない const accessToken = retrieveAuthorizationToken(req); - - //アクセストークンが存在しない場合のエラー - if (accessToken == undefined) { - throw new HttpException( - makeErrorResponse('E000107'), - HttpStatus.UNAUTHORIZED, - ); - } - const decodedToken = decode(accessToken, { - json: true, - }) as AccessToken; + const payload = jwt.decode(accessToken, { json: true }) as AccessToken; // ライセンス注文処理 await this.licensesService.licenseOrders( - decodedToken, + payload, body.poNumber, body.orderCount, ); diff --git a/dictation_server/src/features/users/users.controller.ts b/dictation_server/src/features/users/users.controller.ts index 80bd654..86fc302 100644 --- a/dictation_server/src/features/users/users.controller.ts +++ b/dictation_server/src/features/users/users.controller.ts @@ -16,30 +16,31 @@ import { ApiTags, } from '@nestjs/swagger'; import { Request } from 'express'; -import { decode } from 'jsonwebtoken'; import { makeErrorResponse } from '../../common/error/makeErrorResponse'; import { ErrorResponse } from '../../common/error/types/types'; -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 { - isSortDirection, - isTaskListSortableAttribute, -} from '../../common/types/sort'; import { ConfirmRequest, ConfirmResponse, GetRelationsResponse, - GetSortCriteriaRequest, - GetSortCriteriaResponse, GetUsersResponse, - PostSortCriteriaRequest, - PostSortCriteriaResponse, SignupRequest, SignupResponse, + PostSortCriteriaRequest, + PostSortCriteriaResponse, + GetSortCriteriaRequest, + GetSortCriteriaResponse, } from './types/types'; import { UsersService } from './users.service'; +import jwt from 'jsonwebtoken'; +import { AuthGuard } from '../../common/guards/auth/authguards'; +import { + isSortDirection, + isTaskListSortableAttribute, +} from '../../common/types/sort'; +import { ADMIN_ROLES } from '../../constants'; +import { RoleGuard } from '../../common/guards/role/roleguards'; @ApiTags('users') @Controller('users') @@ -111,21 +112,13 @@ export class UsersController { @ApiOperation({ operationId: 'getUsers' }) @ApiBearerAuth() @UseGuards(AuthGuard) - @UseGuards(RoleGuard.requireds({ roles: ['admin', 'author'] })) + @UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] })) @Get() async getUsers(@Req() req: Request): Promise { console.log(req.header('Authorization')); const accessToken = retrieveAuthorizationToken(req); - - // アクセストークンが存在しない場合のエラー - if (accessToken == undefined) { - throw new HttpException( - makeErrorResponse('E000107'), - HttpStatus.UNAUTHORIZED, - ); - } - const decodedToken = decode(accessToken, { json: true }) as AccessToken; + const decodedToken = jwt.decode(accessToken, { json: true }) as AccessToken; const users = await this.usersService.getUsers(decodedToken); return { users }; @@ -153,9 +146,9 @@ export class UsersController { }) @ApiOperation({ operationId: 'signup' }) @ApiBearerAuth() - @UseGuards(AuthGuard) - @UseGuards(RoleGuard.requireds({ roles: ['admin', 'author'] })) @Post('/signup') + @UseGuards(AuthGuard) + @UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] })) async signup( @Req() req: Request, @Body() body: SignupRequest, @@ -172,19 +165,11 @@ export class UsersController { } = body; const accessToken = retrieveAuthorizationToken(req); - // アクセストークンが存在しない場合のエラー - if (accessToken == undefined) { - throw new HttpException( - makeErrorResponse('E000107'), - HttpStatus.UNAUTHORIZED, - ); - } - - const decodedToken = decode(accessToken, { json: true }) as AccessToken; + const payload = jwt.decode(accessToken, { json: true }) as AccessToken; //ユーザ作成処理 await this.usersService.createUser( - decodedToken, + payload, name, role, email, @@ -276,7 +261,7 @@ export class UsersController { ): Promise { const { direction, paramName } = body; const accessToken = retrieveAuthorizationToken(req); - const decodedToken = decode(accessToken, { json: true }) as AccessToken; + const decodedToken = jwt.decode(accessToken, { json: true }) as AccessToken; //型チェック if ( @@ -324,7 +309,7 @@ export class UsersController { ): Promise { const {} = query; const accessToken = retrieveAuthorizationToken(req); - const decodedToken = decode(accessToken, { json: true }) as AccessToken; + const decodedToken = jwt.decode(accessToken, { json: true }) as AccessToken; const { direction, paramName } = await this.usersService.getSortCriteria( decodedToken,