From f637f133c2d5350385aa2626a880db9c53c52dbf Mon Sep 17 00:00:00 2001 From: Max Bischof Date: Wed, 31 Jul 2024 14:48:30 +0200 Subject: [PATCH 1/8] Exchange AuthorizationReferenceService with AuthorizationClientAdapter --- .../models/authorization-body-params.ts | 4 +- .../models/authorization-context-params.ts | 32 ++++---- .../authorization-client.adapter.ts | 31 ++++++-- .../src/infra/authorization-client/index.ts | 2 + .../mapper/authorization-context.builder.ts | 23 ++++++ .../authorization-client/mapper/index.ts | 1 + .../authorization-client-config.ts | 6 ++ .../controller/files-storage.controller.ts | 38 +++------ .../files-storage/files-storage-api.module.ts | 5 +- .../files-storage/files-storage.const.ts | 2 +- .../mapper/files-storage.mapper.ts | 26 +++---- .../files-storage/uc/files-storage.uc.ts | 77 +++++++++---------- 12 files changed, 139 insertions(+), 108 deletions(-) create mode 100644 apps/server/src/infra/authorization-client/mapper/authorization-context.builder.ts create mode 100644 apps/server/src/infra/authorization-client/mapper/index.ts create mode 100644 apps/server/src/modules/files-storage/authorization-client-config.ts diff --git a/apps/server/src/infra/authorization-client/authorization-api-client/models/authorization-body-params.ts b/apps/server/src/infra/authorization-client/authorization-api-client/models/authorization-body-params.ts index 1bf892fbe0f..cea578bd6f3 100644 --- a/apps/server/src/infra/authorization-client/authorization-api-client/models/authorization-body-params.ts +++ b/apps/server/src/infra/authorization-client/authorization-api-client/models/authorization-body-params.ts @@ -54,7 +54,9 @@ export const AuthorizationBodyParamsReferenceType = { SUBMISSIONS: 'submissions', SCHOOL_EXTERNAL_TOOLS: 'school-external-tools', BOARDNODES: 'boardnodes', - CONTEXT_EXTERNAL_TOOLS: 'context-external-tools' + CONTEXT_EXTERNAL_TOOLS: 'context-external-tools', + EXTERNAL_TOOLS: 'external-tools', + INSTANCES: 'instances' } as const; export type AuthorizationBodyParamsReferenceType = typeof AuthorizationBodyParamsReferenceType[keyof typeof AuthorizationBodyParamsReferenceType]; diff --git a/apps/server/src/infra/authorization-client/authorization-api-client/models/authorization-context-params.ts b/apps/server/src/infra/authorization-client/authorization-api-client/models/authorization-context-params.ts index 055adfae85a..7ff5255cec6 100644 --- a/apps/server/src/infra/authorization-client/authorization-api-client/models/authorization-context-params.ts +++ b/apps/server/src/infra/authorization-client/authorization-api-client/models/authorization-context-params.ts @@ -5,14 +5,13 @@ * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. * * The version of the OpenAPI document: 3.0 - * + * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * https://openapi-generator.tech * Do not edit the class manually. */ - // May contain unused imports in some cases // @ts-ignore import type { Action } from './action'; @@ -21,24 +20,21 @@ import type { Action } from './action'; import type { Permission } from './permission'; /** - * + * * @export * @interface AuthorizationContextParams */ export interface AuthorizationContextParams { - /** - * - * @type {Action} - * @memberof AuthorizationContextParams - */ - 'action': Action; - /** - * User permissions that are needed to execute the operation. - * @type {Array} - * @memberof AuthorizationContextParams - */ - 'requiredPermissions': Array; + /** + * + * @type {Action} + * @memberof AuthorizationContextParams + */ + action: Action; + /** + * User permissions that are needed to execute the operation. + * @type {Array} + * @memberof AuthorizationContextParams + */ + requiredPermissions: Array; } - - - diff --git a/apps/server/src/infra/authorization-client/authorization-client.adapter.ts b/apps/server/src/infra/authorization-client/authorization-client.adapter.ts index 711aec8717f..d5e7277321b 100644 --- a/apps/server/src/infra/authorization-client/authorization-client.adapter.ts +++ b/apps/server/src/infra/authorization-client/authorization-client.adapter.ts @@ -1,23 +1,42 @@ import { Inject, Injectable } from '@nestjs/common'; import { REQUEST } from '@nestjs/core'; +import { extractJwtFromHeader } from '@shared/common'; import { RawAxiosRequestConfig } from 'axios'; import { Request } from 'express'; -import { extractJwtFromHeader } from '@shared/common'; -import { AuthorizationApi, AuthorizationBodyParams } from './authorization-api-client'; +import { + AuthorizationApi, + AuthorizationBodyParamsReferenceType, + AuthorizationContextParams, +} from './authorization-api-client'; import { AuthorizationErrorLoggableException, AuthorizationForbiddenLoggableException } from './error'; @Injectable() export class AuthorizationClientAdapter { constructor(private readonly authorizationApi: AuthorizationApi, @Inject(REQUEST) private request: Request) {} - public async checkPermissionsByReference(params: AuthorizationBodyParams): Promise { - const hasPermission = await this.hasPermissionsByReference(params); + public async checkPermissionsByReference( + referenceType: AuthorizationBodyParamsReferenceType, + referenceId: string, + context: AuthorizationContextParams + ): Promise { + const hasPermission = await this.hasPermissionsByReference(referenceType, referenceId, context); + if (!hasPermission) { - throw new AuthorizationForbiddenLoggableException(params); + throw new AuthorizationForbiddenLoggableException({ referenceType, referenceId, context }); } } - public async hasPermissionsByReference(params: AuthorizationBodyParams): Promise { + public async hasPermissionsByReference( + referenceType: AuthorizationBodyParamsReferenceType, + referenceId: string, + context: AuthorizationContextParams + ): Promise { + const params = { + referenceType, + referenceId, + context, + }; + try { const options = this.createOptionParams(); diff --git a/apps/server/src/infra/authorization-client/index.ts b/apps/server/src/infra/authorization-client/index.ts index d67234adb75..7a01f4c692a 100644 --- a/apps/server/src/infra/authorization-client/index.ts +++ b/apps/server/src/infra/authorization-client/index.ts @@ -1,2 +1,4 @@ +export { Action, AuthorizationBodyParamsReferenceType, AuthorizationContextParams } from './authorization-api-client'; export { AuthorizationClientAdapter } from './authorization-client.adapter'; export { AuthorizationClientModule } from './authorization-client.module'; +export { AuthorizationContextBuilder } from './mapper'; diff --git a/apps/server/src/infra/authorization-client/mapper/authorization-context.builder.ts b/apps/server/src/infra/authorization-client/mapper/authorization-context.builder.ts new file mode 100644 index 00000000000..16b55a5564c --- /dev/null +++ b/apps/server/src/infra/authorization-client/mapper/authorization-context.builder.ts @@ -0,0 +1,23 @@ +import { Permission } from '@shared/domain/interface'; +import { Action, AuthorizationContextParams } from '../authorization-api-client'; + +export class AuthorizationContextBuilder { + static build(requiredPermissions: Array, action: Action): AuthorizationContextParams { + return { + action, + requiredPermissions, + }; + } + + static write(requiredPermissions: Permission[]): AuthorizationContextParams { + const context = this.build(requiredPermissions, Action.WRITE); + + return context; + } + + static read(requiredPermissions: Permission[]): AuthorizationContextParams { + const context = this.build(requiredPermissions, Action.READ); + + return context; + } +} diff --git a/apps/server/src/infra/authorization-client/mapper/index.ts b/apps/server/src/infra/authorization-client/mapper/index.ts new file mode 100644 index 00000000000..6f21d79acad --- /dev/null +++ b/apps/server/src/infra/authorization-client/mapper/index.ts @@ -0,0 +1 @@ +export * from './authorization-context.builder'; diff --git a/apps/server/src/modules/files-storage/authorization-client-config.ts b/apps/server/src/modules/files-storage/authorization-client-config.ts new file mode 100644 index 00000000000..1e1e8bf9095 --- /dev/null +++ b/apps/server/src/modules/files-storage/authorization-client-config.ts @@ -0,0 +1,6 @@ +import { Configuration } from '@hpi-schul-cloud/commons'; +import { AuthorizationClientConfig } from '@src/infra/authorization-client/authorization-client.module'; + +export const authorizationClientConfig: AuthorizationClientConfig = { + basePath: `${Configuration.get('API_HOST') as string}/v3/`, +}; diff --git a/apps/server/src/modules/files-storage/controller/files-storage.controller.ts b/apps/server/src/modules/files-storage/controller/files-storage.controller.ts index b64196c3fe6..b8f38cf62ff 100644 --- a/apps/server/src/modules/files-storage/controller/files-storage.controller.ts +++ b/apps/server/src/modules/files-storage/controller/files-storage.controller.ts @@ -108,7 +108,7 @@ export class FilesStorageController { @Res({ passthrough: true }) response: Response, @Headers('Range') bytesRange?: string ): Promise { - const fileResponse = await this.filesStorageUC.download(currentUser.userId, params, bytesRange); + const fileResponse = await this.filesStorageUC.download(params, bytesRange); const streamableFile = this.streamFileToClient(req, fileResponse, response, bytesRange); @@ -190,10 +190,9 @@ export class FilesStorageController { @Get('/list/:storageLocation/:storageLocationId/:parentType/:parentId') async list( @Param() params: FileRecordParams, - @CurrentUser() currentUser: ICurrentUser, @Query() pagination: PaginationParams ): Promise { - const [fileRecords, total] = await this.filesStorageUC.getFileRecordsOfParent(currentUser.userId, params); + const [fileRecords, total] = await this.filesStorageUC.getFileRecordsOfParent(params); const { skip, limit } = pagination; const response = FileRecordMapper.mapToFileRecordListResponse(fileRecords, total, skip, limit); @@ -214,10 +213,9 @@ export class FilesStorageController { @UseInterceptors(RequestLoggingInterceptor) async patchFilename( @Param() params: SingleFileParams, - @Body() renameFileParam: RenameFileParams, - @CurrentUser() currentUser: ICurrentUser + @Body() renameFileParam: RenameFileParams ): Promise { - const fileRecord = await this.filesStorageUC.patchFilename(currentUser.userId, params, renameFileParam); + const fileRecord = await this.filesStorageUC.patchFilename(params, renameFileParam); const response = FileRecordMapper.mapToFileRecordResponse(fileRecord); @@ -234,11 +232,8 @@ export class FilesStorageController { @ApiResponse({ status: 500, type: InternalServerErrorException }) @Delete('/delete/:storageLocation/:storageLocationId/:parentType/:parentId') @UseInterceptors(RequestLoggingInterceptor) - async deleteByParent( - @Param() params: FileRecordParams, - @CurrentUser() currentUser: ICurrentUser - ): Promise { - const [fileRecords, total] = await this.filesStorageUC.deleteFilesOfParent(currentUser.userId, params); + async deleteByParent(@Param() params: FileRecordParams): Promise { + const [fileRecords, total] = await this.filesStorageUC.deleteFilesOfParent(params); const response = FileRecordMapper.mapToFileRecordListResponse(fileRecords, total); return response; @@ -251,11 +246,8 @@ export class FilesStorageController { @ApiResponse({ status: 500, type: InternalServerErrorException }) @Delete('/delete/:fileRecordId') @UseInterceptors(RequestLoggingInterceptor) - async deleteFile( - @Param() params: SingleFileParams, - @CurrentUser() currentUser: ICurrentUser - ): Promise { - const fileRecord = await this.filesStorageUC.deleteOneFile(currentUser.userId, params); + async deleteFile(@Param() params: SingleFileParams): Promise { + const fileRecord = await this.filesStorageUC.deleteOneFile(params); const response = FileRecordMapper.mapToFileRecordResponse(fileRecord); @@ -267,11 +259,8 @@ export class FilesStorageController { @ApiResponse({ status: 400, type: ApiValidationError }) @ApiResponse({ status: 403, type: ForbiddenException }) @Post('/restore/:storageLocation/:storageLocationId/:parentType/:parentId') - async restore( - @Param() params: FileRecordParams, - @CurrentUser() currentUser: ICurrentUser - ): Promise { - const [fileRecords, total] = await this.filesStorageUC.restoreFilesOfParent(currentUser.userId, params); + async restore(@Param() params: FileRecordParams): Promise { + const [fileRecords, total] = await this.filesStorageUC.restoreFilesOfParent(params); const response = FileRecordMapper.mapToFileRecordListResponse(fileRecords, total); @@ -283,11 +272,8 @@ export class FilesStorageController { @ApiResponse({ status: 400, type: ApiValidationError }) @ApiResponse({ status: 403, type: ForbiddenException }) @Post('/restore/:fileRecordId') - async restoreFile( - @Param() params: SingleFileParams, - @CurrentUser() currentUser: ICurrentUser - ): Promise { - const fileRecord = await this.filesStorageUC.restoreOneFile(currentUser.userId, params); + async restoreFile(@Param() params: SingleFileParams): Promise { + const fileRecord = await this.filesStorageUC.restoreOneFile(params); const response = FileRecordMapper.mapToFileRecordResponse(fileRecord); diff --git a/apps/server/src/modules/files-storage/files-storage-api.module.ts b/apps/server/src/modules/files-storage/files-storage-api.module.ts index b6675ece9b1..9b2fd24e259 100644 --- a/apps/server/src/modules/files-storage/files-storage-api.module.ts +++ b/apps/server/src/modules/files-storage/files-storage-api.module.ts @@ -1,10 +1,11 @@ +import { AuthorizationClientModule } from '@infra/authorization-client'; import { AuthenticationModule } from '@modules/authentication'; -import { AuthorizationReferenceModule } from '@modules/authorization/authorization-reference.module'; import { HttpModule } from '@nestjs/axios'; import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import { createConfigModuleOptions } from '@src/config'; import { CoreModule } from '@src/core'; +import { authorizationClientConfig } from './authorization-client-config'; import { FileSecurityController, FilesStorageConfigController, FilesStorageController } from './controller'; import { config } from './files-storage.config'; import { FilesStorageModule } from './files-storage.module'; @@ -12,9 +13,9 @@ import { FilesStorageUC } from './uc'; @Module({ imports: [ - AuthorizationReferenceModule, FilesStorageModule, AuthenticationModule, + AuthorizationClientModule.register(authorizationClientConfig), CoreModule, HttpModule, ConfigModule.forRoot(createConfigModuleOptions(config)), diff --git a/apps/server/src/modules/files-storage/files-storage.const.ts b/apps/server/src/modules/files-storage/files-storage.const.ts index 87240256afe..970f575b327 100644 --- a/apps/server/src/modules/files-storage/files-storage.const.ts +++ b/apps/server/src/modules/files-storage/files-storage.const.ts @@ -1,5 +1,5 @@ +import { AuthorizationContextBuilder } from '@infra/authorization-client'; import { Permission } from '@shared/domain/interface'; -import { AuthorizationContextBuilder } from '../authorization'; export enum FilesStorageInternalActions { downloadBySecurityToken = '/file-security/download/:token', diff --git a/apps/server/src/modules/files-storage/mapper/files-storage.mapper.ts b/apps/server/src/modules/files-storage/mapper/files-storage.mapper.ts index 14a2a1f931a..6f649e70a0e 100644 --- a/apps/server/src/modules/files-storage/mapper/files-storage.mapper.ts +++ b/apps/server/src/modules/files-storage/mapper/files-storage.mapper.ts @@ -1,5 +1,5 @@ -import { AuthorizableReferenceType } from '@modules/authorization/domain'; import { NotImplementedException, StreamableFile } from '@nestjs/common'; +import { AuthorizationBodyParamsReferenceType } from '@src/infra/authorization-client/authorization-api-client'; import { plainToClass } from 'class-transformer'; import { DownloadFileParams, @@ -12,20 +12,20 @@ import { FileRecord } from '../entity'; import { FileRecordParentType, GetFileResponse } from '../interface'; export class FilesStorageMapper { - private static authorizationEntityMap: Map = new Map([ - [FileRecordParentType.Task, AuthorizableReferenceType.Task], - [FileRecordParentType.Course, AuthorizableReferenceType.Course], - [FileRecordParentType.User, AuthorizableReferenceType.User], - [FileRecordParentType.School, AuthorizableReferenceType.School], - [FileRecordParentType.Lesson, AuthorizableReferenceType.Lesson], - [FileRecordParentType.Submission, AuthorizableReferenceType.Submission], - [FileRecordParentType.Grading, AuthorizableReferenceType.Submission], - [FileRecordParentType.BoardNode, AuthorizableReferenceType.BoardNode], - [FileRecordParentType.ExternalTool, AuthorizableReferenceType.ExternalTool], + private static authorizationEntityMap: Map = new Map([ + [FileRecordParentType.Task, AuthorizationBodyParamsReferenceType.TASKS], + [FileRecordParentType.Course, AuthorizationBodyParamsReferenceType.COURSES], + [FileRecordParentType.User, AuthorizationBodyParamsReferenceType.USERS], + [FileRecordParentType.School, AuthorizationBodyParamsReferenceType.SCHOOLS], + [FileRecordParentType.Lesson, AuthorizationBodyParamsReferenceType.LESSONS], + [FileRecordParentType.Submission, AuthorizationBodyParamsReferenceType.SUBMISSIONS], + [FileRecordParentType.Grading, AuthorizationBodyParamsReferenceType.SUBMISSIONS], + [FileRecordParentType.BoardNode, AuthorizationBodyParamsReferenceType.BOARDNODES], + [FileRecordParentType.ExternalTool, AuthorizationBodyParamsReferenceType.EXTERNAL_TOOLS], ]); - public static mapToAllowedAuthorizationEntityType(type: FileRecordParentType): AuthorizableReferenceType { - const res: AuthorizableReferenceType | undefined = this.authorizationEntityMap.get(type); + public static mapToAllowedAuthorizationEntityType(type: FileRecordParentType): AuthorizationBodyParamsReferenceType { + const res: AuthorizationBodyParamsReferenceType | undefined = this.authorizationEntityMap.get(type); if (!res) { throw new NotImplementedException(); diff --git a/apps/server/src/modules/files-storage/uc/files-storage.uc.ts b/apps/server/src/modules/files-storage/uc/files-storage.uc.ts index f4ed46d6d28..ac80e3d45a8 100644 --- a/apps/server/src/modules/files-storage/uc/files-storage.uc.ts +++ b/apps/server/src/modules/files-storage/uc/files-storage.uc.ts @@ -1,6 +1,10 @@ +import { + AuthorizationBodyParamsReferenceType, + AuthorizationClientAdapter, + AuthorizationContextBuilder, + AuthorizationContextParams, +} from '@infra/authorization-client'; import { EntityManager, RequestContext } from '@mikro-orm/core'; -import { AuthorizableReferenceType, AuthorizationContext, AuthorizationContextBuilder } from '@modules/authorization'; -import { AuthorizationReferenceService } from '@modules/authorization/domain'; import { HttpService } from '@nestjs/axios'; import { Injectable, NotFoundException } from '@nestjs/common'; import { Permission } from '@shared/domain/interface'; @@ -36,7 +40,7 @@ import { FilesStorageService, PreviewService } from '../service'; export class FilesStorageUC { constructor( private readonly logger: LegacyLogger, - private readonly authorizationReferenceService: AuthorizationReferenceService, + private readonly authorizationClientAdapter: AuthorizationClientAdapter, private readonly httpService: HttpService, private readonly filesStorageService: FilesStorageService, private readonly previewService: PreviewService, @@ -48,14 +52,13 @@ export class FilesStorageUC { } private async checkPermission( - userId: EntityId, parentType: FileRecordParentType, parentId: EntityId, - context: AuthorizationContext + context: AuthorizationContextParams ): Promise { - const allowedType: AuthorizableReferenceType = FilesStorageMapper.mapToAllowedAuthorizationEntityType(parentType); + const referenceType = FilesStorageMapper.mapToAllowedAuthorizationEntityType(parentType); - await this.authorizationReferenceService.checkPermissionByReferences(userId, allowedType, parentId, context); + await this.authorizationClientAdapter.checkPermissionsByReference(referenceType, parentId, context); } public getPublicConfig(): FilesStorageConfigResponse { @@ -68,33 +71,27 @@ export class FilesStorageUC { // upload public async upload(userId: EntityId, params: FileRecordParams, req: Request): Promise { - await this.checkPermission(userId, params.parentType, params.parentId, FileStorageAuthorizationContext.create); + await this.checkPermission(params.parentType, params.parentId, FileStorageAuthorizationContext.create); - await this.checkStorageLocation(userId, params.storageLocation, params.storageLocationId); + await this.checkStorageLocation(params.storageLocation, params.storageLocationId); const fileRecord = await this.uploadFileWithBusboy(userId, params, req); return fileRecord; } - private async checkStorageLocation( - userId: EntityId, - storageLocation: StorageLocation, - storageLocationId: EntityId - ): Promise { + private async checkStorageLocation(storageLocation: StorageLocation, storageLocationId: EntityId): Promise { if (storageLocation === StorageLocation.INSTANCE) { - await this.authorizationReferenceService.checkPermissionByReferences( - userId, - AuthorizableReferenceType.Instance, + await this.authorizationClientAdapter.checkPermissionsByReference( + AuthorizationBodyParamsReferenceType.INSTANCES, storageLocationId, AuthorizationContextBuilder.write([Permission.INSTANCE_VIEW]) ); } if (storageLocation === StorageLocation.SCHOOL) { - await this.authorizationReferenceService.checkPermissionByReferences( - userId, - AuthorizableReferenceType.School, + await this.authorizationClientAdapter.checkPermissionsByReference( + AuthorizationBodyParamsReferenceType.SCHOOLS, storageLocationId, AuthorizationContextBuilder.write([]) ); @@ -132,9 +129,9 @@ export class FilesStorageUC { } public async uploadFromUrl(userId: EntityId, params: FileRecordParams & FileUrlParams) { - await this.checkPermission(userId, params.parentType, params.parentId, FileStorageAuthorizationContext.create); + await this.checkPermission(params.parentType, params.parentId, FileStorageAuthorizationContext.create); - await this.checkStorageLocation(userId, params.storageLocation, params.storageLocationId); + await this.checkStorageLocation(params.storageLocation, params.storageLocationId); const response = await this.getResponse(params); @@ -175,12 +172,12 @@ export class FilesStorageUC { } // download - public async download(userId: EntityId, params: DownloadFileParams, bytesRange?: string): Promise { + public async download(params: DownloadFileParams, bytesRange?: string): Promise { const singleFileParams = FilesStorageMapper.mapToSingleFileParams(params); const fileRecord = await this.filesStorageService.getFileRecord(singleFileParams); const { parentType, parentId } = fileRecord.getParentInfo(); - await this.checkPermission(userId, parentType, parentId, FileStorageAuthorizationContext.read); + await this.checkPermission(parentType, parentId, FileStorageAuthorizationContext.read); return this.filesStorageService.download(fileRecord, params, bytesRange); } @@ -202,7 +199,7 @@ export class FilesStorageUC { const fileRecord = await this.filesStorageService.getFileRecord(singleFileParams); const { parentType, parentId } = fileRecord.getParentInfo(); - await this.checkPermission(userId, parentType, parentId, FileStorageAuthorizationContext.read); + await this.checkPermission(parentType, parentId, FileStorageAuthorizationContext.read); this.filesStorageService.checkFileName(fileRecord, params); @@ -212,8 +209,8 @@ export class FilesStorageUC { } // delete - public async deleteFilesOfParent(userId: EntityId, params: FileRecordParams): Promise> { - await this.checkPermission(userId, params.parentType, params.parentId, FileStorageAuthorizationContext.delete); + public async deleteFilesOfParent(params: FileRecordParams): Promise> { + await this.checkPermission(params.parentType, params.parentId, FileStorageAuthorizationContext.delete); const [fileRecords, count] = await this.filesStorageService.getFileRecordsOfParent(params.parentId); await this.previewService.deletePreviews(fileRecords); await this.filesStorageService.deleteFilesOfParent(fileRecords); @@ -221,11 +218,11 @@ export class FilesStorageUC { return [fileRecords, count]; } - public async deleteOneFile(userId: EntityId, params: SingleFileParams): Promise { + public async deleteOneFile(params: SingleFileParams): Promise { const fileRecord = await this.filesStorageService.getFileRecord(params); const { parentType, parentId } = fileRecord.getParentInfo(); - await this.checkPermission(userId, parentType, parentId, FileStorageAuthorizationContext.delete); + await this.checkPermission(parentType, parentId, FileStorageAuthorizationContext.delete); await this.previewService.deletePreviews([fileRecord]); await this.filesStorageService.delete([fileRecord]); @@ -233,18 +230,18 @@ export class FilesStorageUC { } // restore - public async restoreFilesOfParent(userId: EntityId, params: FileRecordParams): Promise> { - await this.checkPermission(userId, params.parentType, params.parentId, FileStorageAuthorizationContext.create); + public async restoreFilesOfParent(params: FileRecordParams): Promise> { + await this.checkPermission(params.parentType, params.parentId, FileStorageAuthorizationContext.create); const [fileRecords, count] = await this.filesStorageService.restoreFilesOfParent(params); return [fileRecords, count]; } - public async restoreOneFile(userId: EntityId, params: SingleFileParams): Promise { + public async restoreOneFile(params: SingleFileParams): Promise { const fileRecord = await this.filesStorageService.getFileRecordMarkedForDelete(params); const { parentType, parentId } = fileRecord.getParentInfo(); - await this.checkPermission(userId, parentType, parentId, FileStorageAuthorizationContext.create); + await this.checkPermission(parentType, parentId, FileStorageAuthorizationContext.create); await this.filesStorageService.restore([fileRecord]); return fileRecord; @@ -257,9 +254,8 @@ export class FilesStorageUC { copyFilesParams: CopyFilesOfParentParams ): Promise> { await Promise.all([ - this.checkPermission(userId, params.parentType, params.parentId, FileStorageAuthorizationContext.create), + this.checkPermission(params.parentType, params.parentId, FileStorageAuthorizationContext.create), this.checkPermission( - userId, copyFilesParams.target.parentType, copyFilesParams.target.parentId, FileStorageAuthorizationContext.create @@ -280,9 +276,8 @@ export class FilesStorageUC { const { parentType, parentId } = fileRecord.getParentInfo(); await Promise.all([ - this.checkPermission(userId, parentType, parentId, FileStorageAuthorizationContext.create), + this.checkPermission(parentType, parentId, FileStorageAuthorizationContext.create), this.checkPermission( - userId, copyFileParams.target.parentType, copyFileParams.target.parentId, FileStorageAuthorizationContext.create @@ -295,11 +290,11 @@ export class FilesStorageUC { } // update - public async patchFilename(userId: EntityId, params: SingleFileParams, data: RenameFileParams): Promise { + public async patchFilename(params: SingleFileParams, data: RenameFileParams): Promise { const fileRecord = await this.filesStorageService.getFileRecord(params); const { parentType, parentId } = fileRecord.getParentInfo(); - await this.checkPermission(userId, parentType, parentId, FileStorageAuthorizationContext.update); + await this.checkPermission(parentType, parentId, FileStorageAuthorizationContext.update); const modifiedFileRecord = await this.filesStorageService.patchFilename(fileRecord, data); @@ -312,8 +307,8 @@ export class FilesStorageUC { } // get - public async getFileRecordsOfParent(userId: EntityId, params: FileRecordParams): Promise> { - await this.checkPermission(userId, params.parentType, params.parentId, FileStorageAuthorizationContext.read); + public async getFileRecordsOfParent(params: FileRecordParams): Promise> { + await this.checkPermission(params.parentType, params.parentId, FileStorageAuthorizationContext.read); const countedFileRecords = await this.filesStorageService.getFileRecordsOfParent(params.parentId); From 0aa419ed87a37569ab97da521abfcaf9012ca6c3 Mon Sep 17 00:00:00 2001 From: Max Bischof Date: Wed, 31 Jul 2024 15:47:17 +0200 Subject: [PATCH 2/8] Move authorization client config to file storage config --- .../modules/files-storage/authorization-client-config.ts | 6 ------ .../src/modules/files-storage/files-storage-api.module.ts | 3 +-- .../src/modules/files-storage/files-storage.config.ts | 6 ++++++ 3 files changed, 7 insertions(+), 8 deletions(-) delete mode 100644 apps/server/src/modules/files-storage/authorization-client-config.ts diff --git a/apps/server/src/modules/files-storage/authorization-client-config.ts b/apps/server/src/modules/files-storage/authorization-client-config.ts deleted file mode 100644 index 1e1e8bf9095..00000000000 --- a/apps/server/src/modules/files-storage/authorization-client-config.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Configuration } from '@hpi-schul-cloud/commons'; -import { AuthorizationClientConfig } from '@src/infra/authorization-client/authorization-client.module'; - -export const authorizationClientConfig: AuthorizationClientConfig = { - basePath: `${Configuration.get('API_HOST') as string}/v3/`, -}; diff --git a/apps/server/src/modules/files-storage/files-storage-api.module.ts b/apps/server/src/modules/files-storage/files-storage-api.module.ts index 9b2fd24e259..837553c7a45 100644 --- a/apps/server/src/modules/files-storage/files-storage-api.module.ts +++ b/apps/server/src/modules/files-storage/files-storage-api.module.ts @@ -5,9 +5,8 @@ import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import { createConfigModuleOptions } from '@src/config'; import { CoreModule } from '@src/core'; -import { authorizationClientConfig } from './authorization-client-config'; import { FileSecurityController, FilesStorageConfigController, FilesStorageController } from './controller'; -import { config } from './files-storage.config'; +import { authorizationClientConfig, config } from './files-storage.config'; import { FilesStorageModule } from './files-storage.module'; import { FilesStorageUC } from './uc'; diff --git a/apps/server/src/modules/files-storage/files-storage.config.ts b/apps/server/src/modules/files-storage/files-storage.config.ts index 985aa728ff4..b0e74bd7816 100644 --- a/apps/server/src/modules/files-storage/files-storage.config.ts +++ b/apps/server/src/modules/files-storage/files-storage.config.ts @@ -1,6 +1,7 @@ import { Configuration } from '@hpi-schul-cloud/commons'; import { S3Config } from '@infra/s3-client'; import { CoreModuleConfig } from '@src/core'; +import { AuthorizationClientConfig } from '@src/infra/authorization-client/authorization-client.module'; export const FILES_STORAGE_S3_CONNECTION = 'FILES_STORAGE_S3_CONNECTION'; export interface FileStorageConfig extends CoreModuleConfig { @@ -14,10 +15,15 @@ export const defaultConfig = { INCOMING_REQUEST_TIMEOUT: Configuration.get('FILES_STORAGE__INCOMING_REQUEST_TIMEOUT') as number, }; +export const authorizationClientConfig: AuthorizationClientConfig = { + basePath: `${Configuration.get('API_HOST') as string}/v3/`, +}; + const fileStorageConfig: FileStorageConfig = { MAX_FILE_SIZE: Configuration.get('FILES_STORAGE__MAX_FILE_SIZE') as number, MAX_SECURITY_CHECK_FILE_SIZE: Configuration.get('FILES_STORAGE__MAX_FILE_SIZE') as number, USE_STREAM_TO_ANTIVIRUS: Configuration.get('FILES_STORAGE__USE_STREAM_TO_ANTIVIRUS') as boolean, + ...authorizationClientConfig, ...defaultConfig, }; From aee89c6d7d02c2064f7dab744e35a4a9b539036f Mon Sep 17 00:00:00 2001 From: Max Bischof Date: Thu, 1 Aug 2024 08:36:09 +0200 Subject: [PATCH 3/8] Adjust uc tests --- .../uc/files-storage-copy.uc.spec.ts | 42 +++---- .../uc/files-storage-delete.uc.spec.ts | 112 +++++++++--------- .../files-storage-download-preview.uc.spec.ts | 15 ++- .../uc/files-storage-download.uc.spec.ts | 65 +++++----- .../uc/files-storage-get.uc.spec.ts | 48 ++++---- .../uc/files-storage-restore.uc.spec.ts | 102 ++++++++-------- .../uc/files-storage-update.uc.spec.ts | 34 +++--- .../uc/files-storage-upload.uc.spec.ts | 32 ++--- 8 files changed, 212 insertions(+), 238 deletions(-) diff --git a/apps/server/src/modules/files-storage/uc/files-storage-copy.uc.spec.ts b/apps/server/src/modules/files-storage/uc/files-storage-copy.uc.spec.ts index 92d3ebd6e81..e3b623e11db 100644 --- a/apps/server/src/modules/files-storage/uc/files-storage-copy.uc.spec.ts +++ b/apps/server/src/modules/files-storage/uc/files-storage-copy.uc.spec.ts @@ -1,9 +1,9 @@ import { createMock, DeepMocked } from '@golevelup/ts-jest'; import { AntivirusService } from '@infra/antivirus'; +import { AuthorizationClientAdapter } from '@infra/authorization-client'; import { S3ClientAdapter } from '@infra/s3-client'; import { EntityManager } from '@mikro-orm/core'; import { ObjectId } from '@mikro-orm/mongodb'; -import { AuthorizationReferenceService } from '@modules/authorization/domain'; import { HttpService } from '@nestjs/axios'; import { ForbiddenException } from '@nestjs/common'; import { Test, TestingModule } from '@nestjs/testing'; @@ -75,7 +75,7 @@ describe('FilesStorageUC', () => { let module: TestingModule; let filesStorageUC: FilesStorageUC; let filesStorageService: DeepMocked; - let authorizationReferenceService: DeepMocked; + let authorizationClientAdapter: DeepMocked; beforeEach(() => { jest.resetAllMocks(); @@ -108,8 +108,8 @@ describe('FilesStorageUC', () => { useValue: createMock(), }, { - provide: AuthorizationReferenceService, - useValue: createMock(), + provide: AuthorizationClientAdapter, + useValue: createMock(), }, { provide: HttpService, @@ -127,7 +127,7 @@ describe('FilesStorageUC', () => { }).compile(); filesStorageUC = module.get(FilesStorageUC); - authorizationReferenceService = module.get(AuthorizationReferenceService); + authorizationClientAdapter = module.get(AuthorizationClientAdapter); filesStorageService = module.get(FilesStorageService); }); @@ -149,7 +149,7 @@ describe('FilesStorageUC', () => { const fileResponse = CopyFileResponseBuilder.build(targetFile.id, sourceFile.id, targetFile.name); - authorizationReferenceService.checkPermissionByReferences.mockResolvedValueOnce().mockResolvedValueOnce(); + authorizationClientAdapter.checkPermissionsByReference.mockResolvedValueOnce().mockResolvedValueOnce(); filesStorageService.copyFilesOfParent.mockResolvedValueOnce([[fileResponse], 1]); return { sourceParams, targetParams, userId, fileResponse }; @@ -160,9 +160,8 @@ describe('FilesStorageUC', () => { await filesStorageUC.copyFilesOfParent(userId, sourceParams, targetParams); - expect(authorizationReferenceService.checkPermissionByReferences).toHaveBeenNthCalledWith( + expect(authorizationClientAdapter.checkPermissionsByReference).toHaveBeenNthCalledWith( 1, - userId, sourceParams.parentType, sourceParams.parentId, FileStorageAuthorizationContext.create @@ -174,9 +173,8 @@ describe('FilesStorageUC', () => { await filesStorageUC.copyFilesOfParent(userId, sourceParams, targetParams); - expect(authorizationReferenceService.checkPermissionByReferences).toHaveBeenNthCalledWith( + expect(authorizationClientAdapter.checkPermissionsByReference).toHaveBeenNthCalledWith( 2, - userId, targetParams.target.parentType, targetParams.target.parentId, FileStorageAuthorizationContext.create @@ -206,7 +204,7 @@ describe('FilesStorageUC', () => { const targetParams = createTargetParams(); const error = new ForbiddenException(); - authorizationReferenceService.checkPermissionByReferences.mockRejectedValueOnce(error).mockResolvedValueOnce(); + authorizationClientAdapter.checkPermissionsByReference.mockRejectedValueOnce(error).mockResolvedValueOnce(); return { sourceParams, targetParams, userId, error }; }; @@ -225,7 +223,7 @@ describe('FilesStorageUC', () => { const targetParams = createTargetParams(); const error = new ForbiddenException(); - authorizationReferenceService.checkPermissionByReferences.mockResolvedValueOnce().mockRejectedValueOnce(error); + authorizationClientAdapter.checkPermissionsByReference.mockResolvedValueOnce().mockRejectedValueOnce(error); return { sourceParams, targetParams, userId, error }; }; @@ -244,7 +242,7 @@ describe('FilesStorageUC', () => { const targetParams = createTargetParams(); const error = new ForbiddenException(); - authorizationReferenceService.checkPermissionByReferences + authorizationClientAdapter.checkPermissionsByReference .mockRejectedValueOnce(error) .mockRejectedValueOnce(error); @@ -266,7 +264,7 @@ describe('FilesStorageUC', () => { const error = new Error('test'); - authorizationReferenceService.checkPermissionByReferences.mockResolvedValueOnce().mockResolvedValueOnce(); + authorizationClientAdapter.checkPermissionsByReference.mockResolvedValueOnce().mockResolvedValueOnce(); filesStorageService.copyFilesOfParent.mockRejectedValueOnce(error); return { sourceParams, targetParams, userId, error }; @@ -306,7 +304,7 @@ describe('FilesStorageUC', () => { ); filesStorageService.getFileRecord.mockResolvedValue(fileRecord); - authorizationReferenceService.checkPermissionByReferences.mockResolvedValueOnce().mockResolvedValueOnce(); + authorizationClientAdapter.checkPermissionsByReference.mockResolvedValueOnce().mockResolvedValueOnce(); filesStorageService.copy.mockResolvedValueOnce([fileResponse]); return { singleFileParams, copyFileParams, userId, fileResponse, fileRecord }; @@ -325,9 +323,8 @@ describe('FilesStorageUC', () => { await filesStorageUC.copyOneFile(userId, singleFileParams, copyFileParams); - expect(authorizationReferenceService.checkPermissionByReferences).toHaveBeenNthCalledWith( + expect(authorizationClientAdapter.checkPermissionsByReference).toHaveBeenNthCalledWith( 1, - userId, fileRecord.parentType, fileRecord.parentId, FileStorageAuthorizationContext.create @@ -339,9 +336,8 @@ describe('FilesStorageUC', () => { await filesStorageUC.copyOneFile(userId, singleFileParams, copyFileParams); - expect(authorizationReferenceService.checkPermissionByReferences).toHaveBeenNthCalledWith( + expect(authorizationClientAdapter.checkPermissionsByReference).toHaveBeenNthCalledWith( 2, - userId, copyFileParams.target.parentType, copyFileParams.target.parentId, FileStorageAuthorizationContext.create @@ -372,7 +368,7 @@ describe('FilesStorageUC', () => { const error = new ForbiddenException(); filesStorageService.getFileRecord.mockResolvedValueOnce(fileRecord); - authorizationReferenceService.checkPermissionByReferences.mockRejectedValueOnce(error).mockResolvedValueOnce(); + authorizationClientAdapter.checkPermissionsByReference.mockRejectedValueOnce(error).mockResolvedValueOnce(); return { singleFileParams, copyFileParams, userId, fileRecord, error }; }; @@ -392,7 +388,7 @@ describe('FilesStorageUC', () => { const error = new ForbiddenException(); filesStorageService.getFileRecord.mockResolvedValue(fileRecord); - authorizationReferenceService.checkPermissionByReferences.mockResolvedValueOnce().mockRejectedValueOnce(error); + authorizationClientAdapter.checkPermissionsByReference.mockResolvedValueOnce().mockRejectedValueOnce(error); return { singleFileParams, copyFileParams, userId, fileRecord, error }; }; @@ -412,7 +408,7 @@ describe('FilesStorageUC', () => { const error = new ForbiddenException(); filesStorageService.getFileRecord.mockResolvedValue(fileRecord); - authorizationReferenceService.checkPermissionByReferences + authorizationClientAdapter.checkPermissionsByReference .mockRejectedValueOnce(error) .mockRejectedValueOnce(error); @@ -453,7 +449,7 @@ describe('FilesStorageUC', () => { const error = new Error('test'); filesStorageService.getFileRecord.mockResolvedValue(fileRecord); - authorizationReferenceService.checkPermissionByReferences.mockResolvedValueOnce().mockResolvedValueOnce(); + authorizationClientAdapter.checkPermissionsByReference.mockResolvedValueOnce().mockResolvedValueOnce(); filesStorageService.copy.mockRejectedValueOnce(error); return { singleFileParams, copyFileParams, userId, fileRecord, error }; diff --git a/apps/server/src/modules/files-storage/uc/files-storage-delete.uc.spec.ts b/apps/server/src/modules/files-storage/uc/files-storage-delete.uc.spec.ts index 87fb8e86cbb..8213b6132a8 100644 --- a/apps/server/src/modules/files-storage/uc/files-storage-delete.uc.spec.ts +++ b/apps/server/src/modules/files-storage/uc/files-storage-delete.uc.spec.ts @@ -1,9 +1,9 @@ import { createMock, DeepMocked } from '@golevelup/ts-jest'; import { AntivirusService } from '@infra/antivirus'; +import { AuthorizationClientAdapter } from '@infra/authorization-client'; import { S3ClientAdapter } from '@infra/s3-client'; import { EntityManager } from '@mikro-orm/core'; import { ObjectId } from '@mikro-orm/mongodb'; -import { AuthorizationReferenceService } from '@modules/authorization/domain'; import { HttpService } from '@nestjs/axios'; import { ForbiddenException } from '@nestjs/common'; import { Test, TestingModule } from '@nestjs/testing'; @@ -62,7 +62,7 @@ describe('FilesStorageUC delete methods', () => { let filesStorageUC: FilesStorageUC; let filesStorageService: DeepMocked; let previewService: DeepMocked; - let authorizationReferenceService: DeepMocked; + let authorizationClientAdapter: DeepMocked; beforeAll(async () => { await setupEntities([FileRecord]); @@ -91,8 +91,8 @@ describe('FilesStorageUC delete methods', () => { useValue: createMock(), }, { - provide: AuthorizationReferenceService, - useValue: createMock(), + provide: AuthorizationClientAdapter, + useValue: createMock(), }, { provide: HttpService, @@ -110,7 +110,7 @@ describe('FilesStorageUC delete methods', () => { }).compile(); filesStorageUC = module.get(FilesStorageUC); - authorizationReferenceService = module.get(AuthorizationReferenceService); + authorizationClientAdapter = module.get(AuthorizationClientAdapter); filesStorageService = module.get(FilesStorageService); previewService = module.get(PreviewService); }); @@ -130,25 +130,24 @@ describe('FilesStorageUC delete methods', () => { describe('deleteFilesOfParent is called', () => { describe('WHEN user is authorized and service deletes successful', () => { const setup = () => { - const { params, userId, fileRecords } = buildFileRecordsWithParams(); + const { params, fileRecords } = buildFileRecordsWithParams(); const { requestParams } = createParams(); const fileRecord = fileRecords[0]; const mockedResult = [[fileRecord], 0] as Counted; - authorizationReferenceService.checkPermissionByReferences.mockResolvedValueOnce(); + authorizationClientAdapter.checkPermissionsByReference.mockResolvedValueOnce(); filesStorageService.getFileRecordsOfParent.mockResolvedValueOnce(mockedResult); - return { params, userId, mockedResult, requestParams, fileRecord }; + return { params, mockedResult, requestParams, fileRecord }; }; it('should call authorizationService.checkPermissionByReferences', async () => { - const { userId, requestParams } = setup(); + const { requestParams } = setup(); const allowedType = FilesStorageMapper.mapToAllowedAuthorizationEntityType(requestParams.parentType); - await filesStorageUC.deleteFilesOfParent(userId, requestParams); + await filesStorageUC.deleteFilesOfParent(requestParams); - expect(authorizationReferenceService.checkPermissionByReferences).toBeCalledWith( - userId, + expect(authorizationClientAdapter.checkPermissionsByReference).toBeCalledWith( allowedType, requestParams.parentId, FileStorageAuthorizationContext.delete @@ -156,25 +155,25 @@ describe('FilesStorageUC delete methods', () => { }); it('should call service with correct params', async () => { - const { requestParams, userId, fileRecord } = setup(); + const { requestParams, fileRecord } = setup(); - await filesStorageUC.deleteFilesOfParent(userId, requestParams); + await filesStorageUC.deleteFilesOfParent(requestParams); expect(filesStorageService.deleteFilesOfParent).toHaveBeenCalledWith([fileRecord]); }); it('should call deletePreviews', async () => { - const { requestParams, userId, fileRecord } = setup(); + const { requestParams, fileRecord } = setup(); - await filesStorageUC.deleteFilesOfParent(userId, requestParams); + await filesStorageUC.deleteFilesOfParent(requestParams); expect(previewService.deletePreviews).toHaveBeenCalledWith([fileRecord]); }); it('should return results of service', async () => { - const { params, userId, mockedResult } = setup(); + const { params, mockedResult } = setup(); - const result = await filesStorageUC.deleteFilesOfParent(userId, params); + const result = await filesStorageUC.deleteFilesOfParent(params); expect(result).toEqual(mockedResult); }); @@ -182,19 +181,17 @@ describe('FilesStorageUC delete methods', () => { describe('WHEN user is not authorized', () => { const setup = () => { - const { requestParams, userId } = createParams(); + const { requestParams } = createParams(); - authorizationReferenceService.checkPermissionByReferences.mockRejectedValueOnce(new ForbiddenException()); + authorizationClientAdapter.checkPermissionsByReference.mockRejectedValueOnce(new ForbiddenException()); - return { requestParams, userId }; + return { requestParams }; }; it('should throw forbidden error', async () => { - const { requestParams, userId } = setup(); + const { requestParams } = setup(); - await expect(filesStorageUC.deleteFilesOfParent(userId, requestParams)).rejects.toThrow( - new ForbiddenException() - ); + await expect(filesStorageUC.deleteFilesOfParent(requestParams)).rejects.toThrow(new ForbiddenException()); expect(filesStorageService.deleteFilesOfParent).toHaveBeenCalledTimes(0); }); @@ -204,11 +201,11 @@ describe('FilesStorageUC delete methods', () => { const setup = () => { const { fileRecords } = buildFileRecordsWithParams(); - authorizationReferenceService.checkPermissionByReferences.mockResolvedValueOnce(); + authorizationClientAdapter.checkPermissionsByReference.mockResolvedValueOnce(); const { requestParams, userId } = createParams(); const error = new Error('test'); - authorizationReferenceService.checkPermissionByReferences.mockResolvedValueOnce(); + authorizationClientAdapter.checkPermissionsByReference.mockResolvedValueOnce(); filesStorageService.getFileRecordsOfParent.mockResolvedValueOnce([fileRecords, fileRecords.length]); filesStorageService.deleteFilesOfParent.mockRejectedValueOnce(error); @@ -216,9 +213,9 @@ describe('FilesStorageUC delete methods', () => { }; it('should return error of service', async () => { - const { requestParams, userId, error } = setup(); + const { requestParams, error } = setup(); - await expect(filesStorageUC.deleteFilesOfParent(userId, requestParams)).rejects.toThrow(error); + await expect(filesStorageUC.deleteFilesOfParent(requestParams)).rejects.toThrow(error); }); }); }); @@ -226,26 +223,25 @@ describe('FilesStorageUC delete methods', () => { describe('deleteOneFile is called', () => { describe('WHEN user is authorized, file is found and delete was successful ', () => { const setup = () => { - const { fileRecords, userId } = buildFileRecordsWithParams(); + const { fileRecords } = buildFileRecordsWithParams(); const fileRecord = fileRecords[0]; const requestParams = { fileRecordId: fileRecord.id, parentType: fileRecord.parentType }; filesStorageService.getFileRecord.mockResolvedValueOnce(fileRecord); - authorizationReferenceService.checkPermissionByReferences.mockResolvedValueOnce(); + authorizationClientAdapter.checkPermissionsByReference.mockResolvedValueOnce(); filesStorageService.delete.mockResolvedValueOnce(); - return { requestParams, userId, fileRecord }; + return { requestParams, fileRecord }; }; it('should call authorizationService.checkPermissionByReferences', async () => { - const { requestParams, userId, fileRecord } = setup(); + const { requestParams, fileRecord } = setup(); - await filesStorageUC.deleteOneFile(userId, requestParams); + await filesStorageUC.deleteOneFile(requestParams); const allowedType = FilesStorageMapper.mapToAllowedAuthorizationEntityType(requestParams.parentType); - expect(authorizationReferenceService.checkPermissionByReferences).toBeCalledWith( - userId, + expect(authorizationClientAdapter.checkPermissionsByReference).toBeCalledWith( allowedType, fileRecord.parentId, FileStorageAuthorizationContext.delete @@ -253,41 +249,41 @@ describe('FilesStorageUC delete methods', () => { }); it('should call getFile once', async () => { - const { userId, requestParams } = setup(); + const { requestParams } = setup(); - await filesStorageUC.deleteOneFile(userId, requestParams); + await filesStorageUC.deleteOneFile(requestParams); expect(filesStorageService.getFileRecord).toHaveBeenCalledTimes(1); }); it('should call getFile with correctly params', async () => { - const { userId, requestParams } = setup(); + const { requestParams } = setup(); - await filesStorageUC.deleteOneFile(userId, requestParams); + await filesStorageUC.deleteOneFile(requestParams); expect(filesStorageService.getFileRecord).toHaveBeenCalledWith(requestParams); }); it('should call delete with correct params', async () => { - const { userId, requestParams, fileRecord } = setup(); + const { requestParams, fileRecord } = setup(); - await filesStorageUC.deleteOneFile(userId, requestParams); + await filesStorageUC.deleteOneFile(requestParams); expect(filesStorageService.delete).toHaveBeenCalledWith([fileRecord]); }); it('should call deletePreviews', async () => { - const { userId, requestParams, fileRecord } = setup(); + const { requestParams, fileRecord } = setup(); - await filesStorageUC.deleteOneFile(userId, requestParams); + await filesStorageUC.deleteOneFile(requestParams); expect(previewService.deletePreviews).toHaveBeenCalledWith([fileRecord]); }); it('should return fileRecord', async () => { - const { userId, requestParams, fileRecord } = setup(); + const { requestParams, fileRecord } = setup(); - const result = await filesStorageUC.deleteOneFile(userId, requestParams); + const result = await filesStorageUC.deleteOneFile(requestParams); expect(result).toEqual(fileRecord); }); @@ -305,50 +301,50 @@ describe('FilesStorageUC delete methods', () => { }; it('should throw error if entity not found', async () => { - const { userId, requestParams, error } = setup(); + const { requestParams, error } = setup(); - await expect(filesStorageUC.deleteOneFile(userId, requestParams)).rejects.toThrow(error); + await expect(filesStorageUC.deleteOneFile(requestParams)).rejects.toThrow(error); }); }); describe('WHEN user is not authorized', () => { const setup = () => { - const { fileRecords, userId } = buildFileRecordsWithParams(); + const { fileRecords } = buildFileRecordsWithParams(); const fileRecord = fileRecords[0]; const requestParams = { fileRecordId: fileRecord.id, parentType: fileRecord.parentType }; filesStorageService.getFileRecord.mockResolvedValueOnce(fileRecord); - authorizationReferenceService.checkPermissionByReferences.mockRejectedValueOnce(new ForbiddenException()); + authorizationClientAdapter.checkPermissionsByReference.mockRejectedValueOnce(new ForbiddenException()); - return { requestParams, userId }; + return { requestParams }; }; it('should throw forbidden exception', async () => { - const { requestParams, userId } = setup(); + const { requestParams } = setup(); - await expect(filesStorageUC.deleteOneFile(userId, requestParams)).rejects.toThrow(new ForbiddenException()); + await expect(filesStorageUC.deleteOneFile(requestParams)).rejects.toThrow(new ForbiddenException()); expect(filesStorageService.delete).toHaveBeenCalledTimes(0); }); }); describe('WHEN delete throws error', () => { const setup = () => { - const { fileRecords, userId } = buildFileRecordsWithParams(); + const { fileRecords } = buildFileRecordsWithParams(); const fileRecord = fileRecords[0]; const requestParams = { fileRecordId: fileRecord.id }; const error = new Error('test'); filesStorageService.getFileRecord.mockResolvedValueOnce(fileRecord); - authorizationReferenceService.checkPermissionByReferences.mockResolvedValueOnce(); + authorizationClientAdapter.checkPermissionsByReference.mockResolvedValueOnce(); filesStorageService.delete.mockRejectedValueOnce(error); - return { requestParams, userId, error }; + return { requestParams, error }; }; it('should throw error', async () => { - const { userId, requestParams, error } = setup(); + const { requestParams, error } = setup(); - await expect(filesStorageUC.deleteOneFile(userId, requestParams)).rejects.toThrow(error); + await expect(filesStorageUC.deleteOneFile(requestParams)).rejects.toThrow(error); }); }); }); diff --git a/apps/server/src/modules/files-storage/uc/files-storage-download-preview.uc.spec.ts b/apps/server/src/modules/files-storage/uc/files-storage-download-preview.uc.spec.ts index 22f0d437801..eeede8b551e 100644 --- a/apps/server/src/modules/files-storage/uc/files-storage-download-preview.uc.spec.ts +++ b/apps/server/src/modules/files-storage/uc/files-storage-download-preview.uc.spec.ts @@ -1,9 +1,9 @@ import { createMock, DeepMocked } from '@golevelup/ts-jest'; import { AntivirusService } from '@infra/antivirus'; +import { AuthorizationClientAdapter } from '@infra/authorization-client'; import { S3ClientAdapter } from '@infra/s3-client'; import { EntityManager } from '@mikro-orm/core'; import { ObjectId } from '@mikro-orm/mongodb'; -import { AuthorizationReferenceService } from '@modules/authorization/domain'; import { HttpService } from '@nestjs/axios'; import { ForbiddenException } from '@nestjs/common'; import { Test, TestingModule } from '@nestjs/testing'; @@ -45,7 +45,7 @@ describe('FilesStorageUC', () => { let filesStorageUC: FilesStorageUC; let filesStorageService: DeepMocked; let previewService: DeepMocked; - let authorizationReferenceService: DeepMocked; + let authorizationClientAdapter: DeepMocked; beforeAll(async () => { await setupEntities([FileRecord]); @@ -78,8 +78,8 @@ describe('FilesStorageUC', () => { useValue: createMock(), }, { - provide: AuthorizationReferenceService, - useValue: createMock(), + provide: AuthorizationClientAdapter, + useValue: createMock(), }, { provide: HttpService, @@ -93,7 +93,7 @@ describe('FilesStorageUC', () => { }).compile(); filesStorageUC = module.get(FilesStorageUC); - authorizationReferenceService = module.get(AuthorizationReferenceService); + authorizationClientAdapter = module.get(AuthorizationClientAdapter); filesStorageService = module.get(FilesStorageService); previewService = module.get(PreviewService); }); @@ -148,8 +148,7 @@ describe('FilesStorageUC', () => { await filesStorageUC.downloadPreview(userId, fileDownloadParams, previewParams); const allowedType = FilesStorageMapper.mapToAllowedAuthorizationEntityType(fileRecord.parentType); - expect(authorizationReferenceService.checkPermissionByReferences).toHaveBeenCalledWith( - userId, + expect(authorizationClientAdapter.checkPermissionsByReference).toHaveBeenCalledWith( allowedType, fileRecord.parentId, FileStorageAuthorizationContext.read @@ -195,7 +194,7 @@ describe('FilesStorageUC', () => { filesStorageService.getFileRecord.mockResolvedValueOnce(fileRecord); const error = new ForbiddenException(); - authorizationReferenceService.checkPermissionByReferences.mockRejectedValueOnce(error); + authorizationClientAdapter.checkPermissionsByReference.mockRejectedValueOnce(error); return { fileDownloadParams, userId, fileRecord, previewParams, error }; }; diff --git a/apps/server/src/modules/files-storage/uc/files-storage-download.uc.spec.ts b/apps/server/src/modules/files-storage/uc/files-storage-download.uc.spec.ts index 7f7795d8c90..c2597e11b6a 100644 --- a/apps/server/src/modules/files-storage/uc/files-storage-download.uc.spec.ts +++ b/apps/server/src/modules/files-storage/uc/files-storage-download.uc.spec.ts @@ -1,9 +1,9 @@ import { createMock, DeepMocked } from '@golevelup/ts-jest'; import { AntivirusService } from '@infra/antivirus'; +import { AuthorizationClientAdapter } from '@infra/authorization-client'; import { S3ClientAdapter } from '@infra/s3-client'; import { EntityManager } from '@mikro-orm/core'; import { ObjectId } from '@mikro-orm/mongodb'; -import { AuthorizationReferenceService } from '@modules/authorization/domain'; import { HttpService } from '@nestjs/axios'; import { ForbiddenException } from '@nestjs/common'; import { Test, TestingModule } from '@nestjs/testing'; @@ -29,14 +29,14 @@ const buildFileRecordWithParams = () => { fileRecordId: fileRecord.id, }; - return { params, fileRecord, userId }; + return { params, fileRecord }; }; describe('FilesStorageUC', () => { let module: TestingModule; let filesStorageUC: FilesStorageUC; let filesStorageService: DeepMocked; - let authorizationReferenceService: DeepMocked; + let authorizationClientAdapter: DeepMocked; beforeAll(async () => { await setupEntities([FileRecord]); @@ -65,8 +65,8 @@ describe('FilesStorageUC', () => { useValue: createMock(), }, { - provide: AuthorizationReferenceService, - useValue: createMock(), + provide: AuthorizationClientAdapter, + useValue: createMock(), }, { provide: HttpService, @@ -84,7 +84,7 @@ describe('FilesStorageUC', () => { }).compile(); filesStorageUC = module.get(FilesStorageUC); - authorizationReferenceService = module.get(AuthorizationReferenceService); + authorizationClientAdapter = module.get(AuthorizationClientAdapter); filesStorageService = module.get(FilesStorageService); }); @@ -103,22 +103,22 @@ describe('FilesStorageUC', () => { describe('download is called', () => { describe('WHEN file is found, user is authorized and file is successfully downloaded', () => { const setup = () => { - const { fileRecord, params, userId } = buildFileRecordWithParams(); + const { fileRecord, params } = buildFileRecordWithParams(); const fileDownloadParams = { ...params, fileName: fileRecord.name }; const fileResponse = createMock(); filesStorageService.getFileRecord.mockResolvedValueOnce(fileRecord); - authorizationReferenceService.checkPermissionByReferences.mockResolvedValue(); + authorizationClientAdapter.checkPermissionsByReference.mockResolvedValue(); filesStorageService.download.mockResolvedValueOnce(fileResponse); - return { fileDownloadParams, userId, fileRecord, fileResponse }; + return { fileDownloadParams, fileRecord, fileResponse }; }; it('should call getFile with correct params', async () => { - const { fileDownloadParams, userId } = setup(); + const { fileDownloadParams } = setup(); - await filesStorageUC.download(userId, fileDownloadParams); + await filesStorageUC.download(fileDownloadParams); expect(filesStorageService.getFileRecord).toHaveBeenCalledWith({ fileRecordId: fileDownloadParams.fileRecordId, @@ -126,13 +126,12 @@ describe('FilesStorageUC', () => { }); it('should call checkPermissionByReferences with correct params', async () => { - const { fileDownloadParams, userId, fileRecord } = setup(); + const { fileDownloadParams, fileRecord } = setup(); - await filesStorageUC.download(userId, fileDownloadParams); + await filesStorageUC.download(fileDownloadParams); const allowedType = FilesStorageMapper.mapToAllowedAuthorizationEntityType(fileRecord.parentType); - expect(authorizationReferenceService.checkPermissionByReferences).toHaveBeenCalledWith( - userId, + expect(authorizationClientAdapter.checkPermissionsByReference).toHaveBeenCalledWith( allowedType, fileRecord.parentId, FileStorageAuthorizationContext.read @@ -140,17 +139,17 @@ describe('FilesStorageUC', () => { }); it('should call donwload with correct params', async () => { - const { fileDownloadParams, userId, fileRecord } = setup(); + const { fileDownloadParams, fileRecord } = setup(); - await filesStorageUC.download(userId, fileDownloadParams); + await filesStorageUC.download(fileDownloadParams); expect(filesStorageService.download).toHaveBeenCalledWith(fileRecord, fileDownloadParams, undefined); }); it('should return correct result', async () => { - const { fileDownloadParams, userId, fileResponse } = setup(); + const { fileDownloadParams, fileResponse } = setup(); - const result = await filesStorageUC.download(userId, fileDownloadParams); + const result = await filesStorageUC.download(fileDownloadParams); expect(result).toEqual(fileResponse); }); @@ -158,58 +157,58 @@ describe('FilesStorageUC', () => { describe('WHEN getFile throws error', () => { const setup = () => { - const { fileRecord, params, userId } = buildFileRecordWithParams(); + const { fileRecord, params } = buildFileRecordWithParams(); const fileDownloadParams = { ...params, fileName: fileRecord.name }; const error = new Error('test'); filesStorageService.getFileRecord.mockRejectedValueOnce(error); - return { fileDownloadParams, userId, error }; + return { fileDownloadParams, error }; }; it('should pass error', async () => { - const { fileDownloadParams, error, userId } = setup(); + const { fileDownloadParams, error } = setup(); - await expect(filesStorageUC.download(userId, fileDownloadParams)).rejects.toThrowError(error); + await expect(filesStorageUC.download(fileDownloadParams)).rejects.toThrowError(error); }); }); describe('WHEN user is not authorized', () => { const setup = () => { - const { fileRecord, params, userId } = buildFileRecordWithParams(); + const { fileRecord, params } = buildFileRecordWithParams(); const fileDownloadParams = { ...params, fileName: fileRecord.name }; const error = new ForbiddenException(); filesStorageService.getFileRecord.mockResolvedValueOnce(fileRecord); - authorizationReferenceService.checkPermissionByReferences.mockRejectedValueOnce(error); + authorizationClientAdapter.checkPermissionsByReference.mockRejectedValueOnce(error); - return { fileDownloadParams, userId, fileRecord }; + return { fileDownloadParams, fileRecord }; }; it('should throw Error', async () => { - const { fileDownloadParams, userId } = setup(); + const { fileDownloadParams } = setup(); - await expect(filesStorageUC.download(userId, fileDownloadParams)).rejects.toThrow(); + await expect(filesStorageUC.download(fileDownloadParams)).rejects.toThrow(); }); }); describe('WHEN service throws error', () => { const setup = () => { - const { fileRecord, params, userId } = buildFileRecordWithParams(); + const { fileRecord, params } = buildFileRecordWithParams(); const fileDownloadParams = { ...params, fileName: fileRecord.name }; const error = new Error('test'); filesStorageService.getFileRecord.mockResolvedValueOnce(fileRecord); - authorizationReferenceService.checkPermissionByReferences.mockResolvedValue(); + authorizationClientAdapter.checkPermissionsByReference.mockResolvedValue(); filesStorageService.download.mockRejectedValueOnce(error); - return { fileDownloadParams, userId, error }; + return { fileDownloadParams, error }; }; it('should pass error', async () => { - const { fileDownloadParams, userId, error } = setup(); + const { fileDownloadParams, error } = setup(); - await expect(filesStorageUC.download(userId, fileDownloadParams)).rejects.toThrow(error); + await expect(filesStorageUC.download(fileDownloadParams)).rejects.toThrow(error); }); }); }); diff --git a/apps/server/src/modules/files-storage/uc/files-storage-get.uc.spec.ts b/apps/server/src/modules/files-storage/uc/files-storage-get.uc.spec.ts index a2a6e499844..6305938c159 100644 --- a/apps/server/src/modules/files-storage/uc/files-storage-get.uc.spec.ts +++ b/apps/server/src/modules/files-storage/uc/files-storage-get.uc.spec.ts @@ -1,9 +1,9 @@ import { createMock, DeepMocked } from '@golevelup/ts-jest'; import { AntivirusService } from '@infra/antivirus'; +import { AuthorizationClientAdapter } from '@infra/authorization-client'; import { S3ClientAdapter } from '@infra/s3-client'; import { EntityManager } from '@mikro-orm/core'; import { ObjectId } from '@mikro-orm/mongodb'; -import { AuthorizationReferenceService } from '@modules/authorization/domain'; import { HttpService } from '@nestjs/axios'; import { Test, TestingModule } from '@nestjs/testing'; import { fileRecordFactory, setupEntities } from '@shared/testing'; @@ -41,7 +41,7 @@ describe('FilesStorageUC', () => { let module: TestingModule; let filesStorageUC: FilesStorageUC; let filesStorageService: DeepMocked; - let authorizationReferenceService: DeepMocked; + let authorizationClientAdapter: DeepMocked; beforeAll(async () => { await setupEntities([FileRecord]); @@ -70,8 +70,8 @@ describe('FilesStorageUC', () => { useValue: createMock(), }, { - provide: AuthorizationReferenceService, - useValue: createMock(), + provide: AuthorizationClientAdapter, + useValue: createMock(), }, { provide: HttpService, @@ -89,7 +89,7 @@ describe('FilesStorageUC', () => { }).compile(); filesStorageUC = module.get(FilesStorageUC); - authorizationReferenceService = module.get(AuthorizationReferenceService); + authorizationClientAdapter = module.get(AuthorizationClientAdapter); filesStorageService = module.get(FilesStorageService); }); @@ -108,22 +108,20 @@ describe('FilesStorageUC', () => { describe('getFileRecordsOfParent is called', () => { describe('when user is authorised and valid files exist', () => { const setup = () => { - const userId = new ObjectId().toHexString(); const { fileRecords, params } = buildFileRecordsWithParams(); filesStorageService.getFileRecordsOfParent.mockResolvedValueOnce([fileRecords, fileRecords.length]); - authorizationReferenceService.checkPermissionByReferences.mockResolvedValueOnce(); + authorizationClientAdapter.checkPermissionsByReference.mockResolvedValueOnce(); - return { userId, params, fileRecords }; + return { params, fileRecords }; }; it('should call authorisation with right parameters', async () => { - const { userId, params } = setup(); + const { params } = setup(); - await filesStorageUC.getFileRecordsOfParent(userId, params); + await filesStorageUC.getFileRecordsOfParent(params); - expect(authorizationReferenceService.checkPermissionByReferences).toHaveBeenCalledWith( - userId, + expect(authorizationClientAdapter.checkPermissionsByReference).toHaveBeenCalledWith( params.parentType, params.parentId, FileStorageAuthorizationContext.read @@ -131,17 +129,17 @@ describe('FilesStorageUC', () => { }); it('should call service method getFilesOfParent with right parameters', async () => { - const { userId, params } = setup(); + const { params } = setup(); - await filesStorageUC.getFileRecordsOfParent(userId, params); + await filesStorageUC.getFileRecordsOfParent(params); expect(filesStorageService.getFileRecordsOfParent).toHaveBeenCalledWith(params.parentId); }); it('should return counted file records', async () => { - const { userId, params, fileRecords } = setup(); + const { params, fileRecords } = setup(); - const result = await filesStorageUC.getFileRecordsOfParent(userId, params); + const result = await filesStorageUC.getFileRecordsOfParent(params); expect(result).toEqual([fileRecords, fileRecords.length]); }); @@ -149,38 +147,36 @@ describe('FilesStorageUC', () => { describe('when user is not authorised', () => { const setup = () => { - const userId = new ObjectId().toHexString(); const { fileRecords, params } = buildFileRecordsWithParams(); filesStorageService.getFileRecordsOfParent.mockResolvedValueOnce([fileRecords, fileRecords.length]); - authorizationReferenceService.checkPermissionByReferences.mockRejectedValueOnce(new Error('Bla')); + authorizationClientAdapter.checkPermissionsByReference.mockRejectedValueOnce(new Error('Bla')); - return { userId, params, fileRecords }; + return { params, fileRecords }; }; it('should pass the error', async () => { - const { userId, params } = setup(); + const { params } = setup(); - await expect(filesStorageUC.getFileRecordsOfParent(userId, params)).rejects.toThrowError(new Error('Bla')); + await expect(filesStorageUC.getFileRecordsOfParent(params)).rejects.toThrowError(new Error('Bla')); }); }); describe('when user is authorised but no files exist', () => { const setup = () => { - const userId = new ObjectId().toHexString(); const { params } = buildFileRecordsWithParams(); const fileRecords = []; filesStorageService.getFileRecordsOfParent.mockResolvedValueOnce([fileRecords, fileRecords.length]); - authorizationReferenceService.checkPermissionByReferences.mockResolvedValueOnce(); + authorizationClientAdapter.checkPermissionsByReference.mockResolvedValueOnce(); - return { userId, params, fileRecords }; + return { params, fileRecords }; }; it('should return empty counted file records', async () => { - const { userId, params } = setup(); + const { params } = setup(); - const result = await filesStorageUC.getFileRecordsOfParent(userId, params); + const result = await filesStorageUC.getFileRecordsOfParent(params); expect(result).toEqual([[], 0]); }); diff --git a/apps/server/src/modules/files-storage/uc/files-storage-restore.uc.spec.ts b/apps/server/src/modules/files-storage/uc/files-storage-restore.uc.spec.ts index 4e1f074f077..d463f4b14a6 100644 --- a/apps/server/src/modules/files-storage/uc/files-storage-restore.uc.spec.ts +++ b/apps/server/src/modules/files-storage/uc/files-storage-restore.uc.spec.ts @@ -1,9 +1,9 @@ import { createMock, DeepMocked } from '@golevelup/ts-jest'; import { AntivirusService } from '@infra/antivirus'; +import { AuthorizationClientAdapter } from '@infra/authorization-client'; import { S3ClientAdapter } from '@infra/s3-client'; import { EntityManager } from '@mikro-orm/core'; import { ObjectId } from '@mikro-orm/mongodb'; -import { AuthorizationReferenceService } from '@modules/authorization/domain'; import { HttpService } from '@nestjs/axios'; import { ForbiddenException } from '@nestjs/common'; import { Test, TestingModule } from '@nestjs/testing'; @@ -58,7 +58,7 @@ describe('FilesStorageUC', () => { let module: TestingModule; let filesStorageUC: FilesStorageUC; let filesStorageService: DeepMocked; - let authorizationReferenceService: DeepMocked; + let authorizationClientAdapter: DeepMocked; beforeAll(async () => { await setupEntities([FileRecord]); @@ -87,8 +87,8 @@ describe('FilesStorageUC', () => { useValue: createMock(), }, { - provide: AuthorizationReferenceService, - useValue: createMock(), + provide: AuthorizationClientAdapter, + useValue: createMock(), }, { provide: HttpService, @@ -106,7 +106,7 @@ describe('FilesStorageUC', () => { }).compile(); filesStorageUC = module.get(FilesStorageUC); - authorizationReferenceService = module.get(AuthorizationReferenceService); + authorizationClientAdapter = module.get(AuthorizationClientAdapter); filesStorageService = module.get(FilesStorageService); }); @@ -125,22 +125,21 @@ describe('FilesStorageUC', () => { describe('restoreFilesOfParent is called', () => { describe('WHEN user is authorised and files to restore exist', () => { const setup = () => { - const { params, userId, fileRecords } = buildFileRecordsWithParams(); + const { params, fileRecords } = buildFileRecordsWithParams(); - authorizationReferenceService.checkPermissionByReferences.mockResolvedValueOnce(); + authorizationClientAdapter.checkPermissionsByReference.mockResolvedValueOnce(); filesStorageService.restoreFilesOfParent.mockResolvedValueOnce([fileRecords, fileRecords.length]); - return { params, userId, fileRecords }; + return { params, fileRecords }; }; it('should call authorisation with right parameters', async () => { - const { params, userId } = setup(); + const { params } = setup(); const allowedType = FilesStorageMapper.mapToAllowedAuthorizationEntityType(params.parentType); - await filesStorageUC.restoreFilesOfParent(userId, params); + await filesStorageUC.restoreFilesOfParent(params); - expect(authorizationReferenceService.checkPermissionByReferences).toHaveBeenCalledWith( - userId, + expect(authorizationClientAdapter.checkPermissionsByReference).toHaveBeenCalledWith( allowedType, params.parentId, FileStorageAuthorizationContext.create @@ -148,17 +147,17 @@ describe('FilesStorageUC', () => { }); it('should call filesStorageService with right parameters', async () => { - const { params, userId } = setup(); + const { params } = setup(); - await filesStorageUC.restoreFilesOfParent(userId, params); + await filesStorageUC.restoreFilesOfParent(params); expect(filesStorageService.restoreFilesOfParent).toHaveBeenCalledWith(params); }); it('should return counted result', async () => { - const { params, userId, fileRecords } = setup(); + const { params, fileRecords } = setup(); - const result = await filesStorageUC.restoreFilesOfParent(userId, params); + const result = await filesStorageUC.restoreFilesOfParent(params); expect(result).toEqual([fileRecords, 3]); }); @@ -166,33 +165,33 @@ describe('FilesStorageUC', () => { describe('WHEN user is not authorised ', () => { const setup = () => { - const { params, userId } = buildFileRecordsWithParams(); - authorizationReferenceService.checkPermissionByReferences.mockRejectedValueOnce(new ForbiddenException()); + const { params } = buildFileRecordsWithParams(); + authorizationClientAdapter.checkPermissionsByReference.mockRejectedValueOnce(new ForbiddenException()); - return { params, userId }; + return { params }; }; it('should throw forbidden error', async () => { - const { params, userId } = setup(); - await expect(filesStorageUC.restoreFilesOfParent(userId, params)).rejects.toThrow(new ForbiddenException()); + const { params } = setup(); + await expect(filesStorageUC.restoreFilesOfParent(params)).rejects.toThrow(new ForbiddenException()); expect(filesStorageService.getFileRecordsOfParent).toHaveBeenCalledTimes(0); }); }); describe('WHEN service throws an error', () => { const setup = () => { - const { params, userId } = buildFileRecordsWithParams(); + const { params } = buildFileRecordsWithParams(); const error = new Error('test'); filesStorageService.restoreFilesOfParent.mockRejectedValueOnce(error); - return { params, userId, error }; + return { params, error }; }; it('should return error of service', async () => { - const { params, userId, error } = setup(); + const { params, error } = setup(); - await expect(filesStorageUC.restoreFilesOfParent(userId, params)).rejects.toThrow(error); + await expect(filesStorageUC.restoreFilesOfParent(params)).rejects.toThrow(error); }); }); }); @@ -200,31 +199,30 @@ describe('FilesStorageUC', () => { describe('restoreOneFile is called', () => { describe('WHEN user is authorised', () => { const setup = () => { - const { params, userId, fileRecord } = buildFileRecordWithParams(); + const { params, fileRecord } = buildFileRecordWithParams(); filesStorageService.getFileRecordMarkedForDelete.mockResolvedValueOnce(fileRecord); - authorizationReferenceService.checkPermissionByReferences.mockResolvedValueOnce(); + authorizationClientAdapter.checkPermissionsByReference.mockResolvedValueOnce(); filesStorageService.restore.mockResolvedValueOnce(); - return { params, userId, fileRecord }; + return { params, fileRecord }; }; it('should call filesStorageService.getMarkForDeletedFile with right parameters', async () => { - const { params, userId } = setup(); + const { params } = setup(); - await filesStorageUC.restoreOneFile(userId, params); + await filesStorageUC.restoreOneFile(params); expect(filesStorageService.getFileRecordMarkedForDelete).toHaveBeenCalledWith(params); }); it('should call authorisation with right parameters', async () => { - const { params, userId, fileRecord } = setup(); + const { params, fileRecord } = setup(); const allowedType = FilesStorageMapper.mapToAllowedAuthorizationEntityType(fileRecord.parentType); - await filesStorageUC.restoreOneFile(userId, params); + await filesStorageUC.restoreOneFile(params); - expect(authorizationReferenceService.checkPermissionByReferences).toHaveBeenCalledWith( - userId, + expect(authorizationClientAdapter.checkPermissionsByReference).toHaveBeenCalledWith( allowedType, fileRecord.parentId, FileStorageAuthorizationContext.create @@ -232,17 +230,17 @@ describe('FilesStorageUC', () => { }); it('should call filesStorageService with right parameters', async () => { - const { params, userId, fileRecord } = setup(); + const { params, fileRecord } = setup(); - await filesStorageUC.restoreOneFile(userId, params); + await filesStorageUC.restoreOneFile(params); expect(filesStorageService.restore).toHaveBeenCalledWith([fileRecord]); }); it('should return counted result', async () => { - const { params, userId, fileRecord } = setup(); + const { params, fileRecord } = setup(); - const result = await filesStorageUC.restoreOneFile(userId, params); + const result = await filesStorageUC.restoreOneFile(params); expect(result).toEqual(fileRecord); }); @@ -250,18 +248,18 @@ describe('FilesStorageUC', () => { describe('WHEN user is not authorised ', () => { const setup = () => { - const { params, userId, fileRecord } = buildFileRecordWithParams(); + const { params, fileRecord } = buildFileRecordWithParams(); filesStorageService.getFileRecordMarkedForDelete.mockResolvedValueOnce(fileRecord); - authorizationReferenceService.checkPermissionByReferences.mockRejectedValueOnce(new ForbiddenException()); + authorizationClientAdapter.checkPermissionsByReference.mockRejectedValueOnce(new ForbiddenException()); - return { params, userId }; + return { params }; }; it('should throw forbidden error', async () => { - const { params, userId } = setup(); + const { params } = setup(); - await expect(filesStorageUC.restoreOneFile(userId, params)).rejects.toThrow(new ForbiddenException()); + await expect(filesStorageUC.restoreOneFile(params)).rejects.toThrow(new ForbiddenException()); expect(filesStorageService.restore).toHaveBeenCalledTimes(0); }); @@ -269,37 +267,37 @@ describe('FilesStorageUC', () => { describe('WHEN service getMarkForDeletedFile throws an error', () => { const setup = () => { - const { params, userId } = buildFileRecordWithParams(); + const { params } = buildFileRecordWithParams(); const error = new Error('test'); filesStorageService.getFileRecordMarkedForDelete.mockRejectedValueOnce(error); - return { params, userId, error }; + return { params, error }; }; it('should return error of service', async () => { - const { params, userId, error } = setup(); + const { params, error } = setup(); - await expect(filesStorageUC.restoreOneFile(userId, params)).rejects.toThrow(error); + await expect(filesStorageUC.restoreOneFile(params)).rejects.toThrow(error); }); }); describe('WHEN service restore throws an error', () => { const setup = () => { - const { params, userId, fileRecord } = buildFileRecordWithParams(); + const { params, fileRecord } = buildFileRecordWithParams(); const error = new Error('test'); filesStorageService.getFileRecordMarkedForDelete.mockResolvedValueOnce(fileRecord); - authorizationReferenceService.checkPermissionByReferences.mockResolvedValueOnce(); + authorizationClientAdapter.checkPermissionsByReference.mockResolvedValueOnce(); filesStorageService.restore.mockRejectedValueOnce(error); - return { params, userId, error }; + return { params, error }; }; it('should return error of service', async () => { - const { params, userId, error } = setup(); + const { params, error } = setup(); - await expect(filesStorageUC.restoreOneFile(userId, params)).rejects.toThrow(error); + await expect(filesStorageUC.restoreOneFile(params)).rejects.toThrow(error); }); }); }); diff --git a/apps/server/src/modules/files-storage/uc/files-storage-update.uc.spec.ts b/apps/server/src/modules/files-storage/uc/files-storage-update.uc.spec.ts index cdb579c3d2f..db8d340e11e 100644 --- a/apps/server/src/modules/files-storage/uc/files-storage-update.uc.spec.ts +++ b/apps/server/src/modules/files-storage/uc/files-storage-update.uc.spec.ts @@ -1,9 +1,9 @@ import { createMock, DeepMocked } from '@golevelup/ts-jest'; import { AntivirusService } from '@infra/antivirus'; +import { AuthorizationClientAdapter } from '@infra/authorization-client'; import { S3ClientAdapter } from '@infra/s3-client'; import { EntityManager } from '@mikro-orm/core'; import { ObjectId } from '@mikro-orm/mongodb'; -import { AuthorizationReferenceService } from '@modules/authorization/domain'; import { HttpService } from '@nestjs/axios'; import { Test, TestingModule } from '@nestjs/testing'; import { fileRecordFactory, setupEntities } from '@shared/testing'; @@ -33,7 +33,7 @@ describe('FilesStorageUC', () => { let module: TestingModule; let filesStorageUC: FilesStorageUC; let filesStorageService: DeepMocked; - let authorizationReferenceService: DeepMocked; + let authorizationClientAdapter: DeepMocked; beforeAll(async () => { await setupEntities([FileRecord]); @@ -62,8 +62,8 @@ describe('FilesStorageUC', () => { useValue: createMock(), }, { - provide: AuthorizationReferenceService, - useValue: createMock(), + provide: AuthorizationClientAdapter, + useValue: createMock(), }, { provide: HttpService, @@ -81,7 +81,7 @@ describe('FilesStorageUC', () => { }).compile(); filesStorageUC = module.get(FilesStorageUC); - authorizationReferenceService = module.get(AuthorizationReferenceService); + authorizationClientAdapter = module.get(AuthorizationClientAdapter); filesStorageService = module.get(FilesStorageService); }); @@ -142,31 +142,29 @@ describe('FilesStorageUC', () => { describe('patchFilename is called', () => { describe('WHEN user is authorised and single file exists', () => { const setup = () => { - const userId = new ObjectId().toHexString(); const { fileRecord, params } = buildFileRecordWithParams(); const data: RenameFileParams = { fileName: 'test_new_name.txt' }; filesStorageService.getFileRecord.mockResolvedValueOnce(fileRecord); - authorizationReferenceService.checkPermissionByReferences.mockResolvedValueOnce(); + authorizationClientAdapter.checkPermissionsByReference.mockResolvedValueOnce(); filesStorageService.patchFilename.mockResolvedValueOnce(fileRecord); - return { userId, params, fileRecord, data }; + return { params, fileRecord, data }; }; it('should call service method getFile with right parameters', async () => { - const { userId, params, data } = setup(); - await filesStorageUC.patchFilename(userId, params, data); + const { params, data } = setup(); + await filesStorageUC.patchFilename(params, data); expect(filesStorageService.getFileRecord).toHaveBeenCalledWith(params); }); it('should call authorisation with right parameters', async () => { - const { userId, params, data, fileRecord } = setup(); + const { params, data, fileRecord } = setup(); - await filesStorageUC.patchFilename(userId, params, data); + await filesStorageUC.patchFilename(params, data); - expect(authorizationReferenceService.checkPermissionByReferences).toHaveBeenCalledWith( - userId, + expect(authorizationClientAdapter.checkPermissionsByReference).toHaveBeenCalledWith( fileRecord.parentType, fileRecord.parentId, FileStorageAuthorizationContext.update @@ -174,17 +172,17 @@ describe('FilesStorageUC', () => { }); it('should call service method patchFilename with right parameters', async () => { - const { userId, params, fileRecord, data } = setup(); + const { params, fileRecord, data } = setup(); - await filesStorageUC.patchFilename(userId, params, data); + await filesStorageUC.patchFilename(params, data); expect(filesStorageService.patchFilename).toHaveBeenCalledWith(fileRecord, data); }); it('should return modified fileRecord', async () => { - const { userId, params, fileRecord, data } = setup(); + const { params, fileRecord, data } = setup(); - const result = await filesStorageUC.patchFilename(userId, params, data); + const result = await filesStorageUC.patchFilename(params, data); expect(result).toEqual(fileRecord); }); diff --git a/apps/server/src/modules/files-storage/uc/files-storage-upload.uc.spec.ts b/apps/server/src/modules/files-storage/uc/files-storage-upload.uc.spec.ts index 754d345d409..cf395fa9752 100644 --- a/apps/server/src/modules/files-storage/uc/files-storage-upload.uc.spec.ts +++ b/apps/server/src/modules/files-storage/uc/files-storage-upload.uc.spec.ts @@ -1,14 +1,10 @@ import { createMock, DeepMocked } from '@golevelup/ts-jest'; import { AntivirusService } from '@infra/antivirus'; +import { AuthorizationClientAdapter } from '@infra/authorization-client'; import { S3ClientAdapter } from '@infra/s3-client'; import { EntityManager } from '@mikro-orm/core'; import { ObjectId } from '@mikro-orm/mongodb'; -import { - Action, - AuthorizableReferenceType, - AuthorizationContextBuilder, - AuthorizationReferenceService, -} from '@modules/authorization/domain'; +import { Action, AuthorizableReferenceType, AuthorizationContextBuilder } from '@modules/authorization/domain'; import { HttpService } from '@nestjs/axios'; import { ForbiddenException, NotFoundException } from '@nestjs/common'; import { Test, TestingModule } from '@nestjs/testing'; @@ -81,7 +77,7 @@ describe('FilesStorageUC upload methods', () => { let module: TestingModule; let filesStorageUC: FilesStorageUC; let filesStorageService: DeepMocked; - let authorizationReferenceService: DeepMocked; + let authorizationClientAdapter: DeepMocked; let httpService: DeepMocked; beforeAll(async () => { @@ -111,8 +107,8 @@ describe('FilesStorageUC upload methods', () => { useValue: createMock(), }, { - provide: AuthorizationReferenceService, - useValue: createMock(), + provide: AuthorizationClientAdapter, + useValue: createMock(), }, { provide: HttpService, @@ -130,7 +126,7 @@ describe('FilesStorageUC upload methods', () => { }).compile(); filesStorageUC = module.get(FilesStorageUC); - authorizationReferenceService = module.get(AuthorizationReferenceService); + authorizationClientAdapter = module.get(AuthorizationClientAdapter); httpService = module.get(HttpService); filesStorageService = module.get(FilesStorageService); }); @@ -188,8 +184,7 @@ describe('FilesStorageUC upload methods', () => { await filesStorageUC.uploadFromUrl(userId, uploadFromUrlParams); - expect(authorizationReferenceService.checkPermissionByReferences).toBeCalledWith( - userId, + expect(authorizationClientAdapter.checkPermissionsByReference).toBeCalledWith( uploadFromUrlParams.parentType, uploadFromUrlParams.parentId, { action: Action.write, requiredPermissions: [Permission.FILESTORAGE_CREATE] } @@ -201,8 +196,7 @@ describe('FilesStorageUC upload methods', () => { await filesStorageUC.uploadFromUrl(userId, uploadFromUrlParams); - expect(authorizationReferenceService.checkPermissionByReferences).toHaveBeenCalledWith( - userId, + expect(authorizationClientAdapter.checkPermissionsByReference).toHaveBeenCalledWith( AuthorizableReferenceType.School, uploadFromUrlParams.storageLocationId, AuthorizationContextBuilder.write([]) @@ -248,7 +242,7 @@ describe('FilesStorageUC upload methods', () => { const setup = () => { const { userId, uploadFromUrlParams } = createUploadFromUrlParams(); const error = new Error('test'); - authorizationReferenceService.checkPermissionByReferences.mockRejectedValueOnce(error); + authorizationClientAdapter.checkPermissionsByReference.mockRejectedValueOnce(error); return { uploadFromUrlParams, userId, error }; }; @@ -338,8 +332,7 @@ describe('FilesStorageUC upload methods', () => { await filesStorageUC.upload(userId, params, request); const allowedType = FilesStorageMapper.mapToAllowedAuthorizationEntityType(params.parentType); - expect(authorizationReferenceService.checkPermissionByReferences).toHaveBeenCalledWith( - userId, + expect(authorizationClientAdapter.checkPermissionsByReference).toHaveBeenCalledWith( allowedType, params.parentId, FileStorageAuthorizationContext.create @@ -351,8 +344,7 @@ describe('FilesStorageUC upload methods', () => { await filesStorageUC.upload(userId, params, request); - expect(authorizationReferenceService.checkPermissionByReferences).toHaveBeenCalledWith( - userId, + expect(authorizationClientAdapter.checkPermissionsByReference).toHaveBeenCalledWith( AuthorizableReferenceType.Instance, params.storageLocationId, AuthorizationContextBuilder.write([Permission.INSTANCE_VIEW]) @@ -422,7 +414,7 @@ describe('FilesStorageUC upload methods', () => { const request = createRequest(); const error = new ForbiddenException(); - authorizationReferenceService.checkPermissionByReferences.mockRejectedValueOnce(error); + authorizationClientAdapter.checkPermissionsByReference.mockRejectedValueOnce(error); return { params, userId, request, error }; }; From 15ac977cb282dcd97e3dff55fb0b7dadb99b8fc6 Mon Sep 17 00:00:00 2001 From: Max Bischof Date: Thu, 1 Aug 2024 09:21:31 +0200 Subject: [PATCH 4/8] Add mock to api tests and remove authorization module from test module --- .../controller/api-test/files-storage-copy-files.api.spec.ts | 3 +++ .../controller/api-test/files-storage-delete-files.api.spec.ts | 3 +++ .../api-test/files-storage-download-upload.api.spec.ts | 3 +++ .../controller/api-test/files-storage-list-files.api.spec.ts | 3 +++ .../controller/api-test/files-storage-preview.api.spec.ts | 3 +++ .../controller/api-test/files-storage-rename-file.api.spec.ts | 3 +++ .../api-test/files-storage-restore-files.api.spec.ts | 3 +++ .../src/modules/files-storage/files-storage-test.module.ts | 2 -- 8 files changed, 21 insertions(+), 2 deletions(-) diff --git a/apps/server/src/modules/files-storage/controller/api-test/files-storage-copy-files.api.spec.ts b/apps/server/src/modules/files-storage/controller/api-test/files-storage-copy-files.api.spec.ts index f82ef6ef757..7d6bb2216ce 100644 --- a/apps/server/src/modules/files-storage/controller/api-test/files-storage-copy-files.api.spec.ts +++ b/apps/server/src/modules/files-storage/controller/api-test/files-storage-copy-files.api.spec.ts @@ -1,5 +1,6 @@ import { createMock } from '@golevelup/ts-jest'; import { AntivirusService } from '@infra/antivirus'; +import { AuthorizationClientAdapter } from '@infra/authorization-client'; import { S3ClientAdapter } from '@infra/s3-client'; import { EntityManager } from '@mikro-orm/mongodb'; import { ICurrentUser } from '@modules/authentication'; @@ -105,6 +106,8 @@ describe(`${baseRouteName} (api)`, () => { }) .overrideProvider(NodeClam) .useValue(createMock()) + .overrideProvider(AuthorizationClientAdapter) + .useValue(createMock()) .compile(); app = module.createNestApplication(); diff --git a/apps/server/src/modules/files-storage/controller/api-test/files-storage-delete-files.api.spec.ts b/apps/server/src/modules/files-storage/controller/api-test/files-storage-delete-files.api.spec.ts index 11c10182495..f8e39d8e066 100644 --- a/apps/server/src/modules/files-storage/controller/api-test/files-storage-delete-files.api.spec.ts +++ b/apps/server/src/modules/files-storage/controller/api-test/files-storage-delete-files.api.spec.ts @@ -8,6 +8,7 @@ import { ExecutionContext, INestApplication } from '@nestjs/common'; import { Test, TestingModule } from '@nestjs/testing'; import { ApiValidationError } from '@shared/common'; +import { AuthorizationClientAdapter } from '@infra/authorization-client'; import { EntityId } from '@shared/domain/types'; import { cleanupCollections, @@ -106,6 +107,8 @@ describe(`${baseRouteName} (api)`, () => { }) .overrideProvider(NodeClam) .useValue(createMock()) + .overrideProvider(AuthorizationClientAdapter) + .useValue(createMock()) .compile(); app = module.createNestApplication(); diff --git a/apps/server/src/modules/files-storage/controller/api-test/files-storage-download-upload.api.spec.ts b/apps/server/src/modules/files-storage/controller/api-test/files-storage-download-upload.api.spec.ts index 4b550b516c5..2acc42bde47 100644 --- a/apps/server/src/modules/files-storage/controller/api-test/files-storage-download-upload.api.spec.ts +++ b/apps/server/src/modules/files-storage/controller/api-test/files-storage-download-upload.api.spec.ts @@ -1,5 +1,6 @@ import { createMock, DeepMocked } from '@golevelup/ts-jest'; import { AntivirusService } from '@infra/antivirus'; +import { AuthorizationClientAdapter } from '@infra/authorization-client'; import { S3ClientAdapter } from '@infra/s3-client'; import { EntityManager } from '@mikro-orm/mongodb'; import { ICurrentUser } from '@modules/authentication'; @@ -124,6 +125,8 @@ describe('files-storage controller (API)', () => { }) .overrideProvider(NodeClam) .useValue(createMock()) + .overrideProvider(AuthorizationClientAdapter) + .useValue(createMock()) .compile(); app = module.createNestApplication(); diff --git a/apps/server/src/modules/files-storage/controller/api-test/files-storage-list-files.api.spec.ts b/apps/server/src/modules/files-storage/controller/api-test/files-storage-list-files.api.spec.ts index 42356d4cd54..fd0b4489ce4 100644 --- a/apps/server/src/modules/files-storage/controller/api-test/files-storage-list-files.api.spec.ts +++ b/apps/server/src/modules/files-storage/controller/api-test/files-storage-list-files.api.spec.ts @@ -1,4 +1,5 @@ import { createMock } from '@golevelup/ts-jest'; +import { AuthorizationClientAdapter } from '@infra/authorization-client'; import { EntityManager } from '@mikro-orm/mongodb'; import { ICurrentUser } from '@modules/authentication'; import { JwtAuthGuard } from '@modules/authentication/guard/jwt-auth.guard'; @@ -66,6 +67,8 @@ describe(`${baseRouteName} (api)`, () => { }) .overrideProvider(NodeClam) .useValue(createMock()) + .overrideProvider(AuthorizationClientAdapter) + .useValue(createMock()) .compile(); app = module.createNestApplication(); diff --git a/apps/server/src/modules/files-storage/controller/api-test/files-storage-preview.api.spec.ts b/apps/server/src/modules/files-storage/controller/api-test/files-storage-preview.api.spec.ts index ae1667f7b38..73c230730ec 100644 --- a/apps/server/src/modules/files-storage/controller/api-test/files-storage-preview.api.spec.ts +++ b/apps/server/src/modules/files-storage/controller/api-test/files-storage-preview.api.spec.ts @@ -1,5 +1,6 @@ import { createMock, DeepMocked } from '@golevelup/ts-jest'; import { AntivirusService } from '@infra/antivirus'; +import { AuthorizationClientAdapter } from '@infra/authorization-client'; import { PreviewProducer } from '@infra/preview-generator'; import { S3ClientAdapter } from '@infra/s3-client'; import { EntityManager, ObjectId } from '@mikro-orm/mongodb'; @@ -137,6 +138,8 @@ describe('File Controller (API) - preview', () => { }) .overrideProvider(NodeClam) .useValue(createMock()) + .overrideProvider(AuthorizationClientAdapter) + .useValue(createMock()) .compile(); app = module.createNestApplication(); diff --git a/apps/server/src/modules/files-storage/controller/api-test/files-storage-rename-file.api.spec.ts b/apps/server/src/modules/files-storage/controller/api-test/files-storage-rename-file.api.spec.ts index e4d8cbee799..020bf9cd9e8 100644 --- a/apps/server/src/modules/files-storage/controller/api-test/files-storage-rename-file.api.spec.ts +++ b/apps/server/src/modules/files-storage/controller/api-test/files-storage-rename-file.api.spec.ts @@ -1,4 +1,5 @@ import { createMock } from '@golevelup/ts-jest'; +import { AuthorizationClientAdapter } from '@infra/authorization-client'; import { EntityManager } from '@mikro-orm/mongodb'; import { ICurrentUser } from '@modules/authentication'; import { JwtAuthGuard } from '@modules/authentication/guard/jwt-auth.guard'; @@ -65,6 +66,8 @@ describe(`${baseRouteName} (api)`, () => { }) .overrideProvider(NodeClam) .useValue(createMock()) + .overrideProvider(AuthorizationClientAdapter) + .useValue(createMock()) .compile(); app = module.createNestApplication(); diff --git a/apps/server/src/modules/files-storage/controller/api-test/files-storage-restore-files.api.spec.ts b/apps/server/src/modules/files-storage/controller/api-test/files-storage-restore-files.api.spec.ts index 328987c33a5..13aec56c321 100644 --- a/apps/server/src/modules/files-storage/controller/api-test/files-storage-restore-files.api.spec.ts +++ b/apps/server/src/modules/files-storage/controller/api-test/files-storage-restore-files.api.spec.ts @@ -1,5 +1,6 @@ import { createMock } from '@golevelup/ts-jest'; import { AntivirusService } from '@infra/antivirus'; +import { AuthorizationClientAdapter } from '@infra/authorization-client'; import { S3ClientAdapter } from '@infra/s3-client'; import { EntityManager, ObjectId } from '@mikro-orm/mongodb'; import { ICurrentUser } from '@modules/authentication'; @@ -132,6 +133,8 @@ describe(`${baseRouteName} (api)`, () => { }) .overrideProvider(NodeClam) .useValue(createMock()) + .overrideProvider(AuthorizationClientAdapter) + .useValue(createMock()) .compile(); app = module.createNestApplication(); diff --git a/apps/server/src/modules/files-storage/files-storage-test.module.ts b/apps/server/src/modules/files-storage/files-storage-test.module.ts index 3cc524c18d1..fa11dfb0dec 100644 --- a/apps/server/src/modules/files-storage/files-storage-test.module.ts +++ b/apps/server/src/modules/files-storage/files-storage-test.module.ts @@ -3,7 +3,6 @@ import { DynamicModule, Module } from '@nestjs/common'; import { MongoDatabaseModuleOptions, MongoMemoryDatabaseModule } from '@infra/database'; import { RabbitMQWrapperTestModule } from '@infra/rabbitmq'; import { AuthenticationModule } from '@modules/authentication'; -import { AuthorizationModule } from '@modules/authorization'; import { ALL_ENTITIES } from '@shared/domain/entity'; import { CoreModule } from '@src/core'; import { LoggerModule } from '@src/core/logger'; @@ -14,7 +13,6 @@ const imports = [ FilesStorageApiModule, MongoMemoryDatabaseModule.forRoot({ entities: [...ALL_ENTITIES, FileRecord] }), RabbitMQWrapperTestModule, - AuthorizationModule, AuthenticationModule, CoreModule, LoggerModule, From bc20c366e32592dc2e2d309e1462edf9056a0127 Mon Sep 17 00:00:00 2001 From: Max Bischof Date: Thu, 1 Aug 2024 12:20:32 +0200 Subject: [PATCH 5/8] Adjust client adapter test --- .../authorization-client.adapter.spec.ts | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/apps/server/src/infra/authorization-client/authorization-client.adapter.spec.ts b/apps/server/src/infra/authorization-client/authorization-client.adapter.spec.ts index 35d08e38221..e2b68d63e56 100644 --- a/apps/server/src/infra/authorization-client/authorization-client.adapter.spec.ts +++ b/apps/server/src/infra/authorization-client/authorization-client.adapter.spec.ts @@ -83,7 +83,7 @@ describe(AuthorizationClientAdapter.name, () => { const expectedOptions = { headers: { authorization: `Bearer ${jwtToken}` } }; - await service.checkPermissionsByReference(params); + await service.checkPermissionsByReference(params.referenceType, params.referenceId, params.context); expect(authorizationApi.authorizationReferenceControllerAuthorizeByReference).toHaveBeenCalledWith( params, @@ -95,7 +95,9 @@ describe(AuthorizationClientAdapter.name, () => { it('should resolve', async () => { const { params } = setup({ isAuthorized: true }); - await expect(service.checkPermissionsByReference(params)).resolves.toBeUndefined(); + await expect( + service.checkPermissionsByReference(params.referenceType, params.referenceId, params.context) + ).resolves.toBeUndefined(); }); }); @@ -105,7 +107,9 @@ describe(AuthorizationClientAdapter.name, () => { const expectedError = new AuthorizationForbiddenLoggableException(params); - await expect(service.checkPermissionsByReference(params)).rejects.toThrowError(expectedError); + await expect( + service.checkPermissionsByReference(params.referenceType, params.referenceId, params.context) + ).rejects.toThrowError(expectedError); }); }); }); @@ -132,7 +136,9 @@ describe(AuthorizationClientAdapter.name, () => { const expectedError = new AuthorizationErrorLoggableException(error, params); - await expect(service.checkPermissionsByReference(params)).rejects.toThrowError(expectedError); + await expect( + service.checkPermissionsByReference(params.referenceType, params.referenceId, params.context) + ).rejects.toThrowError(expectedError); }); }); }); @@ -165,7 +171,7 @@ describe(AuthorizationClientAdapter.name, () => { const expectedOptions = { headers: { authorization: `Bearer ${jwtToken}` } }; - await service.hasPermissionsByReference(params); + await service.hasPermissionsByReference(params.referenceType, params.referenceId, params.context); expect(authorizationApi.authorizationReferenceControllerAuthorizeByReference).toHaveBeenCalledWith( params, @@ -176,7 +182,11 @@ describe(AuthorizationClientAdapter.name, () => { it('should return isAuthorized', async () => { const { params, response } = setup(); - const result = await service.hasPermissionsByReference(params); + const result = await service.hasPermissionsByReference( + params.referenceType, + params.referenceId, + params.context + ); expect(result).toEqual(response.data.isAuthorized); }); @@ -216,7 +226,7 @@ describe(AuthorizationClientAdapter.name, () => { const expectedOptions = { headers: { authorization: `Bearer ${jwtToken}` } }; - await adapter.hasPermissionsByReference(params); + await adapter.hasPermissionsByReference(params.referenceType, params.referenceId, params.context); expect(authorizationApi.authorizationReferenceControllerAuthorizeByReference).toHaveBeenCalledWith( params, @@ -259,7 +269,7 @@ describe(AuthorizationClientAdapter.name, () => { const expectedOptions = { headers: { authorization: `Bearer ${jwtToken}` } }; - await adapter.hasPermissionsByReference(params); + await adapter.hasPermissionsByReference(params.referenceType, params.referenceId, params.context); expect(authorizationApi.authorizationReferenceControllerAuthorizeByReference).toHaveBeenCalledWith( params, @@ -294,7 +304,9 @@ describe(AuthorizationClientAdapter.name, () => { const expectedError = new AuthorizationErrorLoggableException(error, params); - await expect(adapter.hasPermissionsByReference(params)).rejects.toThrowError(expectedError); + await expect( + adapter.hasPermissionsByReference(params.referenceType, params.referenceId, params.context) + ).rejects.toThrowError(expectedError); }); }); @@ -320,7 +332,9 @@ describe(AuthorizationClientAdapter.name, () => { const expectedError = new AuthorizationErrorLoggableException(error, params); - await expect(service.hasPermissionsByReference(params)).rejects.toThrowError(expectedError); + await expect( + service.hasPermissionsByReference(params.referenceType, params.referenceId, params.context) + ).rejects.toThrowError(expectedError); }); }); }); From 503276b157bb0b902b39f049c185d34c1fe4211c Mon Sep 17 00:00:00 2001 From: Max Bischof Date: Thu, 1 Aug 2024 15:08:29 +0200 Subject: [PATCH 6/8] Fix imports --- apps/server/src/infra/authorization-client/index.ts | 2 +- apps/server/src/modules/files-storage/files-storage.config.ts | 2 +- .../src/modules/files-storage/mapper/files-storage.mapper.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/server/src/infra/authorization-client/index.ts b/apps/server/src/infra/authorization-client/index.ts index 7a01f4c692a..3965174bf62 100644 --- a/apps/server/src/infra/authorization-client/index.ts +++ b/apps/server/src/infra/authorization-client/index.ts @@ -1,4 +1,4 @@ export { Action, AuthorizationBodyParamsReferenceType, AuthorizationContextParams } from './authorization-api-client'; export { AuthorizationClientAdapter } from './authorization-client.adapter'; -export { AuthorizationClientModule } from './authorization-client.module'; +export { AuthorizationClientConfig, AuthorizationClientModule } from './authorization-client.module'; export { AuthorizationContextBuilder } from './mapper'; diff --git a/apps/server/src/modules/files-storage/files-storage.config.ts b/apps/server/src/modules/files-storage/files-storage.config.ts index b0e74bd7816..984967a2930 100644 --- a/apps/server/src/modules/files-storage/files-storage.config.ts +++ b/apps/server/src/modules/files-storage/files-storage.config.ts @@ -1,7 +1,7 @@ import { Configuration } from '@hpi-schul-cloud/commons'; +import { AuthorizationClientConfig } from '@infra/authorization-client'; import { S3Config } from '@infra/s3-client'; import { CoreModuleConfig } from '@src/core'; -import { AuthorizationClientConfig } from '@src/infra/authorization-client/authorization-client.module'; export const FILES_STORAGE_S3_CONNECTION = 'FILES_STORAGE_S3_CONNECTION'; export interface FileStorageConfig extends CoreModuleConfig { diff --git a/apps/server/src/modules/files-storage/mapper/files-storage.mapper.ts b/apps/server/src/modules/files-storage/mapper/files-storage.mapper.ts index 6f649e70a0e..370f79350c1 100644 --- a/apps/server/src/modules/files-storage/mapper/files-storage.mapper.ts +++ b/apps/server/src/modules/files-storage/mapper/files-storage.mapper.ts @@ -1,5 +1,5 @@ +import { AuthorizationBodyParamsReferenceType } from '@infra/authorization-client'; import { NotImplementedException, StreamableFile } from '@nestjs/common'; -import { AuthorizationBodyParamsReferenceType } from '@src/infra/authorization-client/authorization-api-client'; import { plainToClass } from 'class-transformer'; import { DownloadFileParams, From d570119ff69ccff68b11995385657a2b424f46a8 Mon Sep 17 00:00:00 2001 From: Max Bischof Date: Fri, 2 Aug 2024 07:57:08 +0200 Subject: [PATCH 7/8] Make basePath property mandatory --- .../infra/authorization-client/authorization-client.module.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/server/src/infra/authorization-client/authorization-client.module.ts b/apps/server/src/infra/authorization-client/authorization-client.module.ts index fdd6beebaaf..3cd5ba36418 100644 --- a/apps/server/src/infra/authorization-client/authorization-client.module.ts +++ b/apps/server/src/infra/authorization-client/authorization-client.module.ts @@ -3,7 +3,7 @@ import { AuthorizationApi, Configuration, ConfigurationParameters } from './auth import { AuthorizationClientAdapter } from './authorization-client.adapter'; export interface AuthorizationClientConfig extends ConfigurationParameters { - basePath?: string; + basePath: string; } @Module({}) From c48d0d09cf1a9f4978a29448e4acedfbe2076408 Mon Sep 17 00:00:00 2001 From: Max Bischof Date: Fri, 2 Aug 2024 13:10:36 +0200 Subject: [PATCH 8/8] FileStorageConfig extends AuthorizationClientConfig --- apps/server/src/modules/files-storage/files-storage.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/server/src/modules/files-storage/files-storage.config.ts b/apps/server/src/modules/files-storage/files-storage.config.ts index 984967a2930..722cc31b0c6 100644 --- a/apps/server/src/modules/files-storage/files-storage.config.ts +++ b/apps/server/src/modules/files-storage/files-storage.config.ts @@ -4,7 +4,7 @@ import { S3Config } from '@infra/s3-client'; import { CoreModuleConfig } from '@src/core'; export const FILES_STORAGE_S3_CONNECTION = 'FILES_STORAGE_S3_CONNECTION'; -export interface FileStorageConfig extends CoreModuleConfig { +export interface FileStorageConfig extends CoreModuleConfig, AuthorizationClientConfig { MAX_FILE_SIZE: number; MAX_SECURITY_CHECK_FILE_SIZE: number; USE_STREAM_TO_ANTIVIRUS: boolean;