Skip to content

Commit

Permalink
N21-1967 Adjust Filestorage for instance files (#5051)
Browse files Browse the repository at this point in the history
* adds fileStorageLocation and fileStorageId
  • Loading branch information
MarvinOehlerkingCap authored Jun 12, 2024
1 parent e1417ed commit d2edfc0
Show file tree
Hide file tree
Showing 111 changed files with 1,775 additions and 682 deletions.
1 change: 1 addition & 0 deletions apps/server/src/infra/rabbitmq/exchange/files-storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export enum FileRecordParentType {
'Submission' = 'submissions',
'Grading' = 'gradings',
'BoardNode' = 'boardnodes',
'ExternalTool' = 'externaltools',
}

export interface CopyFilesOfParentParams {
Expand Down
44 changes: 44 additions & 0 deletions apps/server/src/migrations/mikro-orm/Migration20240604131554.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Migration } from '@mikro-orm/migrations-mongodb';
import * as process from 'node:process';

export class Migration20240604131554 extends Migration {
async up(): Promise<void> {
// eslint-disable-next-line no-process-env
if (process.env.SC_THEME === 'n21') {
await this.driver.nativeInsert('instances', {
name: 'nbc',
});
console.info('Instance was added for nbc');
}

// eslint-disable-next-line no-process-env
if (process.env.SC_THEME === 'brb') {
await this.driver.nativeInsert('instances', {
name: 'brb',
});
console.info('Instance was added for brb');
}

// eslint-disable-next-line no-process-env
if (process.env.SC_THEME === 'thr') {
await this.driver.nativeInsert('instances', {
name: 'thr',
});
console.info('Instance was added for thr');
}

// eslint-disable-next-line no-process-env
if (process.env.SC_THEME === 'default') {
await this.driver.nativeInsert('instances', {
name: 'dbc',
});
console.info('Instance was added for default');
}
}

async down(): Promise<void> {
await this.getCollection('instances').drop();

console.info('Collection "instances" was dropped');
}
}
23 changes: 23 additions & 0 deletions apps/server/src/migrations/mikro-orm/Migration20240605065231.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Migration } from '@mikro-orm/migrations-mongodb';

export class Migration20240605065231 extends Migration {
async up(): Promise<void> {
const filerecords = await this.driver.nativeUpdate(
'filerecords',
{},
{ $rename: { schoolId: 'storageLocationId' }, $set: { storageLocation: 'school' } }
);

console.info(`${filerecords.affectedRows} Filerecords were migrated to "storageLocationId" and "storageLocation"`);
}

async down(): Promise<void> {
const filerecords = await this.driver.nativeUpdate(
'filerecords',
{},
{ $rename: { storageLocationId: 'schoolId' }, $unset: { storageLocation: '' } }
);

console.info(`${filerecords.affectedRows} Filerecords were rolled back to use "schoolId"`);
}
}
39 changes: 39 additions & 0 deletions apps/server/src/migrations/mikro-orm/Migration20240606142059.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Migration } from '@mikro-orm/migrations-mongodb';

export class Migration20240606142059 extends Migration {
async up(): Promise<void> {
const superheroRole = await this.driver.nativeUpdate(
'roles',
{ name: 'superhero' },
{
$addToSet: {
permissions: {
$each: ['INSTANCE_VIEW'],
},
},
}
);

if (superheroRole.affectedRows > 0) {
console.info('Permissions INSTANCE_VIEW was added to role superhero.');
}
}

async down(): Promise<void> {
const superheroRole = await this.driver.nativeUpdate(
'roles',
{ name: 'superhero' },
{
$pull: {
permissions: {
$in: ['INSTANCE_VIEW'],
},
},
}
);

if (superheroRole.affectedRows > 0) {
console.info('Permissions INSTANCE_VIEW was removed to role superhero.');
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { BoardModule } from '@modules/board';
import { InstanceModule } from '@modules/instance';
import { LessonModule } from '@modules/lesson';
import { ToolModule } from '@modules/tool';
import { forwardRef, Module } from '@nestjs/common';
Expand Down Expand Up @@ -29,6 +30,7 @@ import { AuthorizationHelper, AuthorizationReferenceService, ReferenceLoader } f
forwardRef(() => ToolModule),
forwardRef(() => BoardModule),
LoggerModule,
InstanceModule,
],
providers: [
AuthorizationHelper,
Expand Down
4 changes: 4 additions & 0 deletions apps/server/src/modules/authorization/authorization.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import {
ContextExternalToolRule,
CourseGroupRule,
CourseRule,
ExternalToolRule,
GroupRule,
InstanceRule,
LegacySchoolRule,
LessonRule,
SchoolExternalToolRule,
Expand Down Expand Up @@ -49,6 +51,8 @@ import { FeathersAuthorizationService, FeathersAuthProvider } from './feathers';
LegacySchoolRule,
SystemRule,
SchoolSystemOptionsRule,
ExternalToolRule,
InstanceRule,
],
exports: [FeathersAuthorizationService, AuthorizationService, SystemRule],
})
Expand Down
24 changes: 10 additions & 14 deletions apps/server/src/modules/authorization/domain/rules/board-do.rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,43 +14,39 @@ import { AuthorizationHelper } from '../service/authorization.helper';
import { Action, AuthorizationContext, Rule } from '../type';

@Injectable()
export class BoardDoRule implements Rule {
export class BoardDoRule implements Rule<BoardDoAuthorizable> {
constructor(private readonly authorizationHelper: AuthorizationHelper) {}

public isApplicable(user: User, boardDoAuthorizable: unknown): boolean {
const isMatched = boardDoAuthorizable instanceof BoardDoAuthorizable;
public isApplicable(user: User, object: unknown): boolean {
const isMatched = object instanceof BoardDoAuthorizable;

return isMatched;
}

public hasPermission(user: User, boardDoAuthorizable: BoardDoAuthorizable, context: AuthorizationContext): boolean {
public hasPermission(user: User, object: BoardDoAuthorizable, context: AuthorizationContext): boolean {
const hasPermission = this.authorizationHelper.hasAllPermissions(user, context.requiredPermissions);
if (!hasPermission) {
return false;
}

const userWithBoardRoles = boardDoAuthorizable.users.find(({ userId }) => userId === user.id);
const userWithBoardRoles = object.users.find(({ userId }) => userId === user.id);
if (!userWithBoardRoles) {
return false;
}

if (
boardDoAuthorizable.rootDo instanceof ColumnBoard &&
!boardDoAuthorizable.rootDo.isVisible &&
!this.isBoardEditor(userWithBoardRoles)
) {
if (object.rootDo instanceof ColumnBoard && !object.rootDo.isVisible && !this.isBoardEditor(userWithBoardRoles)) {
return false;
}

if (this.shouldProcessSubmissionItem(boardDoAuthorizable)) {
return this.hasPermissionForSubmissionItem(user, userWithBoardRoles, boardDoAuthorizable, context);
if (this.shouldProcessSubmissionItem(object)) {
return this.hasPermissionForSubmissionItem(user, userWithBoardRoles, object, context);
}

if (this.shouldProcessDrawingElementFile(boardDoAuthorizable, context)) {
if (this.shouldProcessDrawingElementFile(object, context)) {
return this.hasPermissionForDrawingElementFile(userWithBoardRoles);
}

if (this.shouldProcessDrawingElement(boardDoAuthorizable)) {
if (this.shouldProcessDrawingElement(object)) {
return this.hasPermissionForDrawingElement(userWithBoardRoles, context);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
import { Injectable } from '@nestjs/common';
import { ContextExternalTool } from '@modules/tool/context-external-tool/domain';
import { ContextExternalToolEntity } from '@modules/tool/context-external-tool/entity';
import { Injectable } from '@nestjs/common';
import { User } from '@shared/domain/entity';
import { AuthorizationContext, Rule } from '../type';
import { AuthorizationHelper } from '../service/authorization.helper';
import { AuthorizationContext, Rule } from '../type';

@Injectable()
export class ContextExternalToolRule implements Rule {
export class ContextExternalToolRule implements Rule<ContextExternalToolEntity | ContextExternalTool> {
constructor(private readonly authorizationHelper: AuthorizationHelper) {}

public isApplicable(user: User, entity: ContextExternalToolEntity | ContextExternalTool): boolean {
const isMatched: boolean = entity instanceof ContextExternalToolEntity || entity instanceof ContextExternalTool;
public isApplicable(user: User, object: unknown): boolean {
const isMatched: boolean = object instanceof ContextExternalToolEntity || object instanceof ContextExternalTool;

return isMatched;
}

public hasPermission(
user: User,
entity: ContextExternalToolEntity | ContextExternalTool,
object: ContextExternalToolEntity | ContextExternalTool,
context: AuthorizationContext
): boolean {
let hasPermission: boolean;
if (entity instanceof ContextExternalToolEntity) {
if (object instanceof ContextExternalToolEntity) {
hasPermission =
this.authorizationHelper.hasAllPermissions(user, context.requiredPermissions) &&
user.school.id === entity.schoolTool.school.id;
user.school.id === object.schoolTool.school.id;
} else {
hasPermission =
this.authorizationHelper.hasAllPermissions(user, context.requiredPermissions) &&
user.school.id === entity.schoolToolRef.schoolId;
user.school.id === object.schoolToolRef.schoolId;
}
return hasPermission;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
import { Injectable } from '@nestjs/common';
import { CourseGroup, User } from '@shared/domain/entity';
import { CourseRule } from './course.rule';
import { Action, AuthorizationContext, Rule } from '../type';
import { AuthorizationHelper } from '../service/authorization.helper';
import { Action, AuthorizationContext, Rule } from '../type';
import { CourseRule } from './course.rule';

@Injectable()
export class CourseGroupRule implements Rule {
export class CourseGroupRule implements Rule<CourseGroup> {
constructor(private readonly authorizationHelper: AuthorizationHelper, private readonly courseRule: CourseRule) {}

public isApplicable(user: User, entity: CourseGroup): boolean {
const isMatched = entity instanceof CourseGroup;
public isApplicable(user: User, object: unknown): boolean {
const isMatched = object instanceof CourseGroup;

return isMatched;
}

public hasPermission(user: User, entity: CourseGroup, context: AuthorizationContext): boolean {
public hasPermission(user: User, object: CourseGroup, context: AuthorizationContext): boolean {
const { requiredPermissions } = context;

const hasAllPermissions = this.authorizationHelper.hasAllPermissions(user, requiredPermissions);
const hasPermission =
this.authorizationHelper.hasAccessToEntity(user, entity, ['students']) ||
this.courseRule.hasPermission(user, entity.course, { action: Action.write, requiredPermissions: [] });
this.authorizationHelper.hasAccessToEntity(user, object, ['students']) ||
this.courseRule.hasPermission(user, object.course, { action: Action.write, requiredPermissions: [] });

return hasAllPermissions && hasPermission;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,22 @@ import { AuthorizationHelper } from '../service/authorization.helper';
import { Action, AuthorizationContext, Rule } from '../type';

@Injectable()
export class CourseRule implements Rule {
export class CourseRule implements Rule<CourseEntity | Course> {
constructor(private readonly authorizationHelper: AuthorizationHelper) {}

public isApplicable(user: User, entity: unknown): boolean {
const isMatched = entity instanceof CourseEntity || entity instanceof Course;
public isApplicable(user: User, object: unknown): boolean {
const isMatched = object instanceof CourseEntity || object instanceof Course;

return isMatched;
}

public hasPermission(user: User, entity: CourseEntity | Course, context: AuthorizationContext): boolean {
public hasPermission(user: User, object: CourseEntity | Course, context: AuthorizationContext): boolean {
const { action, requiredPermissions } = context;
const hasPermission =
this.authorizationHelper.hasAllPermissions(user, requiredPermissions) &&
this.authorizationHelper.hasAccessToEntity(
user,
entity,
object,
action === Action.read ? ['teachers', 'substitutionTeachers', 'students'] : ['teachers', 'substitutionTeachers']
);

Expand Down
Loading

0 comments on commit d2edfc0

Please sign in to comment.