From ace32f3a8b5536b88df7fdd7ebcfae05bbfc5736 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joonas=20H=C3=A4kkinen?= Date: Fri, 27 Dec 2024 09:52:53 +0200 Subject: [PATCH] Move role check to proper authorization service --- app/src/authorization/authorization.module.ts | 8 ++++++ .../authorization/authorization.service.ts | 26 +++++++++++++++++++ .../exceptions/user-not-found.exception.ts | 8 ++++++ .../office-management.controller.ts | 14 +++------- .../office-management.module.ts | 3 ++- 5 files changed, 48 insertions(+), 11 deletions(-) create mode 100644 app/src/authorization/authorization.module.ts create mode 100644 app/src/authorization/authorization.service.ts create mode 100644 app/src/common/exceptions/user-not-found.exception.ts diff --git a/app/src/authorization/authorization.module.ts b/app/src/authorization/authorization.module.ts new file mode 100644 index 0000000..b50e10c --- /dev/null +++ b/app/src/authorization/authorization.module.ts @@ -0,0 +1,8 @@ +import { Module } from "@nestjs/common"; +import { AuthorizationService } from "./authorization.service"; + +@Module({ + providers: [AuthorizationService], + exports: [AuthorizationService], +}) +export class AuthorizationModule {} diff --git a/app/src/authorization/authorization.service.ts b/app/src/authorization/authorization.service.ts new file mode 100644 index 0000000..68c7438 --- /dev/null +++ b/app/src/authorization/authorization.service.ts @@ -0,0 +1,26 @@ +import { Injectable, Logger, UnauthorizedException } from "@nestjs/common"; +import { BoltService } from "../bolt/bolt.service"; +import { UserNotFoundException } from "../common/exceptions/user-not-found.exception"; + +@Injectable() +export class AuthorizationService { + logger = new Logger(AuthorizationService.name); + + constructor(private boltService: BoltService) {} + + async requireOwnerRole(userId: string): Promise { + const bolt = this.boltService.getBolt(); + const { user } = await bolt.client.users.info({ user: userId }); + + if (!user) { + throw new UserNotFoundException(); + } + + if (!user.is_owner) { + this.logger.warn( + `User ${userId} tried to access a protected resource requiring workspace owner privileges.`, + ); + throw new UnauthorizedException(); + } + } +} diff --git a/app/src/common/exceptions/user-not-found.exception.ts b/app/src/common/exceptions/user-not-found.exception.ts new file mode 100644 index 0000000..f43787e --- /dev/null +++ b/app/src/common/exceptions/user-not-found.exception.ts @@ -0,0 +1,8 @@ +import { HttpStatus } from "@nestjs/common"; +import { KaikuAppException } from "./kaiku-app.exception"; + +export class UserNotFoundException extends KaikuAppException { + constructor() { + super("User was not found in Slack workspace.", HttpStatus.NOT_FOUND); + } +} diff --git a/app/src/gui/home-tab/views/settings/office-management/office-management.controller.ts b/app/src/gui/home-tab/views/settings/office-management/office-management.controller.ts index bfe76a6..197217b 100644 --- a/app/src/gui/home-tab/views/settings/office-management/office-management.controller.ts +++ b/app/src/gui/home-tab/views/settings/office-management/office-management.controller.ts @@ -1,10 +1,6 @@ -import { - Controller, - ForbiddenException, - InternalServerErrorException, - Logger, -} from "@nestjs/common"; +import { Controller, InternalServerErrorException, Logger } from "@nestjs/common"; import { get } from "lodash"; +import { AuthorizationService } from "../../../../../authorization/authorization.service"; import BoltAction from "../../../../../bolt/decorators/bolt-action.decorator"; import BoltViewAction from "../../../../../bolt/decorators/bolt-view-action.decorator"; import Action from "../../../../../bolt/enums/action.enum"; @@ -23,6 +19,7 @@ export class OfficeManagementController { private officeMgmtModal: OfficeManagementModal, private addOfficeModal: AddOfficeModal, private officeService: OfficeService, + private authService: AuthorizationService, ) {} @BoltAction(Action.OPEN_OFFICE_MANAGEMENT_MODAL) @@ -43,10 +40,7 @@ export class OfficeManagementController { @BoltViewAction(ViewAction.CREATE_OFFICE) async createOffice({ view, client, body }: BoltViewActionArgs) { - const { user } = await client.users.info({ user: body.user.id }); - if (!user.is_owner) { - throw new ForbiddenException(); - } + await this.authService.requireOwnerRole(body.user.id); const officeName = get(view, "state.values.new_office.name.value"); diff --git a/app/src/gui/home-tab/views/settings/office-management/office-management.module.ts b/app/src/gui/home-tab/views/settings/office-management/office-management.module.ts index 9a7d302..f07ab4d 100644 --- a/app/src/gui/home-tab/views/settings/office-management/office-management.module.ts +++ b/app/src/gui/home-tab/views/settings/office-management/office-management.module.ts @@ -1,11 +1,12 @@ import { Module } from "@nestjs/common"; +import { AuthorizationModule } from "../../../../../authorization/authorization.module"; import { OfficeModule } from "../../../../../entities/office/office.module"; import { AddOfficeModal } from "./add-office.modal"; import { OfficeManagementController } from "./office-management.controller"; import { OfficeManagementModal } from "./office-management.modal"; @Module({ - imports: [OfficeModule], + imports: [OfficeModule, AuthorizationModule], providers: [OfficeManagementModal, AddOfficeModal], controllers: [OfficeManagementController], })