Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BC-5424 - persistent storage for tldraw #4685

Merged
merged 34 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a40ee1b
add env vars related to tldraw asset upload
davwas Jan 9, 2024
4190ed4
fix resolved user school id
davwas Jan 9, 2024
16665ea
fix package lock json
davwas Jan 10, 2024
9844450
Merge branch 'main' into BC-5424-tldraw-persistent-storage
davwas Jan 10, 2024
5ae793e
fix tldraw configs
davwas Jan 11, 2024
a52712c
Merge branch 'main' into BC-5424-tldraw-persistent-storage
davwas Jan 11, 2024
5971daf
Merge branch 'main' into BC-5424-tldraw-persistent-storage
davwas Jan 12, 2024
2727511
fix formatting
davwas Jan 12, 2024
9fe419a
Add recursive deletion of files for drawing entity
blazejpass Jan 15, 2024
d6f7cf4
Merge branch 'main' into BC-5424-tldraw-persistent-storage
davwas Jan 18, 2024
b1649b2
Change roles permission for users to upload images for students in tl…
blazejpass Jan 22, 2024
6bd3dc6
Fix lint
blazejpass Jan 22, 2024
d112e77
Merge remote-tracking branch 'origin/BC-5424-tldraw-persistent-storag…
blazejpass Jan 22, 2024
31de79e
Merge branch 'main' into BC-5424-tldraw-persistent-storage
davwas Jan 22, 2024
f5d4d63
Add test for drawing authorizable in reference loader
blazejpass Jan 22, 2024
5a79db3
Merge remote-tracking branch 'origin/BC-5424-tldraw-persistent-storag…
blazejpass Jan 22, 2024
1c61198
fix user permissions for tldraw assets
davwas Jan 22, 2024
937d407
test tldraw db url env var
davwas Jan 22, 2024
9906ee8
test tldraw db url env var 2
davwas Jan 22, 2024
eccb43b
Merge branch 'main' into BC-5424-tldraw-persistent-storage
davwas Jan 23, 2024
11ad9f3
Merge branch 'main' into BC-5424-tldraw-persistent-storage
CeEv Jan 24, 2024
d10a186
update packages
davwas Jan 24, 2024
107de35
hacky temporary solution proposal
davwas Jan 26, 2024
4fd2c1d
Merge branch 'main' into BC-5424-tldraw-persistent-storage
davwas Jan 26, 2024
4c36cbf
fix test config
davwas Jan 26, 2024
e681fb7
Merge branch 'main' into BC-5424-tldraw-persistent-storage
davwas Jan 29, 2024
9d0745e
fix conflicts
davwas Jan 29, 2024
cf34896
fix schema
davwas Jan 29, 2024
156e6b3
fix comments
davwas Jan 29, 2024
80a6900
Merge branch 'main' into BC-5424-tldraw-persistent-storage
davwas Jan 29, 2024
57c51d5
fix import
davwas Jan 29, 2024
465124d
fix tests
davwas Jan 29, 2024
31fd8cc
Merge branch 'main' into BC-5424-tldraw-persistent-storage
davwas Jan 29, 2024
0d24bb5
Merge branch 'main' into BC-5424-tldraw-persistent-storage
davwas Jan 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions apps/server/src/config/database.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ interface GlobalConstants {
DB_URL: string;
DB_PASSWORD?: string;
DB_USERNAME?: string;
TLDRAW_DB_URL: string;
}

const usedGlobals: GlobalConstants = globals;

/** Database URL */
export const { DB_URL, DB_PASSWORD, DB_USERNAME, TLDRAW_DB_URL } = usedGlobals;
export const { DB_URL, DB_PASSWORD, DB_USERNAME } = usedGlobals;
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export class RecursiveDeleteVisitor implements BoardCompositeVisitorAsync {

async visitDrawingElementAsync(drawingElement: DrawingElement): Promise<void> {
await this.drawingElementAdapterService.deleteDrawingBinData(drawingElement.id);
await this.filesStorageClientAdapterService.deleteFilesOfParent(drawingElement.id);
CeEv marked this conversation as resolved.
Show resolved Hide resolved

this.deleteNode(drawingElement);
await this.visitChildrenAsync(drawingElement);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
BoardExternalReferenceType,
BoardRoles,
ColumnBoard,
isDrawingElement,
UserBoardRoles,
UserRoleEnum,
} from '@shared/domain/domainobject';
Expand Down Expand Up @@ -34,10 +35,12 @@ export class BoardDoAuthorizableService implements AuthorizationLoaderService {
const ids = [...ancestorIds, boardDo.id];
const rootId = ids[0];
const rootBoardDo = await this.boardDoRepo.findById(rootId, 1);
const isDrawing = isDrawingElement(boardDo);

if (rootBoardDo instanceof ColumnBoard) {
if (rootBoardDo.context?.type === BoardExternalReferenceType.Course) {
const course = await this.courseRepo.findById(rootBoardDo.context.id);
const users = this.mapCourseUsersToUsergroup(course);
const users = this.mapCourseUsersToUsergroup(course, isDrawing);
return new BoardDoAuthorizable({ users, id: boardDo.id });
}
} else {
Expand All @@ -47,7 +50,7 @@ export class BoardDoAuthorizableService implements AuthorizationLoaderService {
return new BoardDoAuthorizable({ users: [], id: boardDo.id });
}

private mapCourseUsersToUsergroup(course: Course): UserBoardRoles[] {
private mapCourseUsersToUsergroup(course: Course, isDrawing: boolean): UserBoardRoles[] {
const users = [
...course.getTeachersList().map((user) => {
return {
Expand All @@ -72,7 +75,10 @@ export class BoardDoAuthorizableService implements AuthorizationLoaderService {
userId: user.id,
firstName: user.firstName,
lastName: user.lastName,
roles: [BoardRoles.READER],
// TODO: fix this temporary hack allowing students to upload files to the DrawingElement
// linked with getElementWithWritePermission method in element.uc.ts
// this is needed to allow students to upload/delete files to/from the tldraw whiteboard (DrawingElement)
roles: isDrawing ? [BoardRoles.EDITOR] : [BoardRoles.READER],
CeEv marked this conversation as resolved.
Show resolved Hide resolved
userRoleEnum: UserRoleEnum.STUDENT,
};
}),
Expand Down
8 changes: 8 additions & 0 deletions apps/server/src/modules/board/uc/element.uc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ForbiddenException, forwardRef, Inject, Injectable, UnprocessableEntity
import {
AnyBoardDo,
AnyContentElementDo,
isDrawingElement,
isSubmissionContainerElement,
isSubmissionItem,
SubmissionItem,
Expand Down Expand Up @@ -53,6 +54,13 @@ export class ElementUc extends BaseUc {

if (isSubmissionItem(parent)) {
await this.checkSubmissionItemWritePermission(userId, parent);
} else if (isDrawingElement(element)) {
// TODO: fix this temporary hack preventing students from deleting the DrawingElement
// linked with getBoardAuthorizable method in board-do-authorizable.service.ts
// the roles are hacked for the DrawingElement to allow students for file upload
// so because students have BoardRoles.EDITOR role, they can delete the DrawingElement by calling delete endpoint directly
// to prevent this, we add UserRoleEnum.TEACHER to the requiredUserRole
await this.checkPermission(userId, element, Action.write, UserRoleEnum.TEACHER);
} else {
await this.checkPermission(userId, element, Action.write);
}
Expand Down
12 changes: 11 additions & 1 deletion apps/server/src/modules/tldraw/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Configuration } from '@hpi-schul-cloud/commons';

export interface TldrawConfig {
TLDRAW_DB_URL: string;
NEST_LOG_LEVEL: string;
INCOMING_REQUEST_TIMEOUT: number;
TLDRAW_DB_FLUSH_SIZE: string;
Expand All @@ -9,11 +10,18 @@ export interface TldrawConfig {
TLDRAW_PING_TIMEOUT: number;
TLDRAW_GC_ENABLED: number;
REDIS_URI: string;
TLDRAW_ASSETS_ENABLED: boolean;
TLDRAW_ASSETS_MAX_SIZE: number;
TLDRAW_ASSETS_ALLOWED_EXTENSIONS_LIST: string;
API_HOST: number;
TLDRAW_MAX_DOCUMENT_SIZE: number;
}

export const TLDRAW_DB_URL: string = Configuration.get('TLDRAW_DB_URL') as string;
export const TLDRAW_SOCKET_PORT = Configuration.get('TLDRAW__SOCKET_PORT') as number;

const tldrawConfig = {
TLDRAW_DB_URL,
NEST_LOG_LEVEL: Configuration.get('NEST_LOG_LEVEL') as string,
INCOMING_REQUEST_TIMEOUT: Configuration.get('INCOMING_REQUEST_TIMEOUT_API') as number,
TLDRAW_DB_FLUSH_SIZE: Configuration.get('TLDRAW__DB_FLUSH_SIZE') as number,
Expand All @@ -22,9 +30,11 @@ const tldrawConfig = {
TLDRAW_PING_TIMEOUT: Configuration.get('TLDRAW__PING_TIMEOUT') as number,
TLDRAW_GC_ENABLED: Configuration.get('TLDRAW__GC_ENABLED') as boolean,
REDIS_URI: Configuration.has('REDIS_URI') ? (Configuration.get('REDIS_URI') as string) : null,
TLDRAW_ASSETS_ENABLED: Configuration.get('TLDRAW__ASSETS_ENABLED') as boolean,
TLDRAW_ASSETS_MAX_SIZE: Configuration.get('TLDRAW__ASSETS_MAX_SIZE') as number,
TLDRAW_ASSETS_ALLOWED_EXTENSIONS_LIST: Configuration.get('TLDRAW__ASSETS_ALLOWED_EXTENSIONS_LIST') as string,
API_HOST: Configuration.get('API_HOST') as string,
TLDRAW_MAX_DOCUMENT_SIZE: Configuration.get('TLDRAW__MAX_DOCUMENT_SIZE') as number,
};

export const SOCKET_PORT = Configuration.get('TLDRAW__SOCKET_PORT') as number;
export const config = () => tldrawConfig;
4 changes: 2 additions & 2 deletions apps/server/src/modules/tldraw/controller/tldraw.ws.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import { AxiosError } from 'axios';
import { firstValueFrom } from 'rxjs';
import { HttpService } from '@nestjs/axios';
import { WebsocketCloseErrorLoggable } from '../loggable';
import { TldrawConfig, SOCKET_PORT } from '../config';
import { TldrawConfig, TLDRAW_SOCKET_PORT } from '../config';
import { WsCloseCodeEnum, WsCloseMessageEnum } from '../types';
import { TldrawWsService } from '../service';

@WebSocketGateway(SOCKET_PORT)
@WebSocketGateway(TLDRAW_SOCKET_PORT)
export class TldrawWs implements OnGatewayInit, OnGatewayConnection {
@WebSocketServer()
server!: Server;
Expand Down
4 changes: 2 additions & 2 deletions apps/server/src/modules/tldraw/tldraw-ws.module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Module, NotFoundException } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { createConfigModuleOptions, DB_PASSWORD, DB_USERNAME, TLDRAW_DB_URL } from '@src/config';
import { createConfigModuleOptions, DB_PASSWORD, DB_USERNAME } from '@src/config';
import { CoreModule } from '@src/core';
import { LoggerModule } from '@src/core/logger';
import { MikroOrmModule, MikroOrmModuleSyncOptions } from '@mikro-orm/nestjs';
Expand All @@ -11,7 +11,7 @@ import { MetricsService } from './metrics';
import { TldrawBoardRepo, TldrawRepo, YMongodb } from './repo';
import { TldrawWsService } from './service';
import { TldrawWs } from './controller';
import { config } from './config';
import { config, TLDRAW_DB_URL } from './config';
import { TldrawRedisFactory } from './redis';

const defaultMikroOrmOptions: MikroOrmModuleSyncOptions = {
Expand Down
4 changes: 2 additions & 2 deletions apps/server/src/modules/tldraw/tldraw.module.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { Module, NotFoundException } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { createConfigModuleOptions, DB_PASSWORD, DB_USERNAME, TLDRAW_DB_URL } from '@src/config';
import { createConfigModuleOptions, DB_PASSWORD, DB_USERNAME } from '@src/config';
import { CoreModule } from '@src/core';
import { LoggerModule } from '@src/core/logger';
import { MikroOrmModule, MikroOrmModuleSyncOptions } from '@mikro-orm/nestjs';
import { AuthenticationModule } from '@src/modules/authentication/authentication.module';
import { RabbitMQWrapperModule } from '@infra/rabbitmq';
import { Dictionary, IPrimaryKey } from '@mikro-orm/core';
import { AuthorizationModule } from '@modules/authorization';
import { config } from './config';
import { config, TLDRAW_DB_URL } from './config';
import { TldrawDrawing } from './entities';
import { TldrawController } from './controller';
import { TldrawService } from './service';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export class ResolvedUserMapper {
dto.lastName = user.lastName;
dto.createdAt = user.createdAt;
dto.updatedAt = user.updatedAt;
dto.schoolId = user.school.toString();
dto.schoolId = user.school.id;
dto.roles = roles.map((role) => {
return { name: role.name, id: role.id };
});
Expand Down
34 changes: 25 additions & 9 deletions config/default.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1439,10 +1439,15 @@
"API_KEY": ""
}
},
"FEATURE_TLDRAW_ENABLED": {
"type": "boolean",
"default": true,
"description": "Enables tldraw feature"
},
"TLDRAW": {
"type": "object",
"description": "Tldraw managing variables.",
"required": ["PING_TIMEOUT", "SOCKET_PORT","GC_ENABLED", "DB_FLUSH_SIZE", "MAX_DOCUMENT_SIZE"],
"description": "Configuration of tldraw related settings",
"required": ["PING_TIMEOUT", "SOCKET_PORT","GC_ENABLED", "DB_FLUSH_SIZE", "MAX_DOCUMENT_SIZE", "ASSETS_ENABLED", "ASSETS_MAX_SIZE", "ASSETS_ALLOWED_EXTENSIONS_LIST"],
"properties": {
"SOCKET_PORT": {
"type": "number",
Expand All @@ -1463,26 +1468,37 @@
"MAX_DOCUMENT_SIZE": {
"type": "number",
"description": "Maximum size of a single tldraw document in mongo"
},
"ASSETS_ENABLED": {
"type": "boolean",
"description": "Enables uploading assets to tldraw board"
},
"ASSETS_MAX_SIZE": {
"type": "integer",
"description": "Maximum asset size in bytes"
},
"ASSETS_ALLOWED_EXTENSIONS_LIST": {
"type": "string",
"description": "List with allowed assets extensions, comma separated, empty if all extensions should be allowed",
"examples": ["png,jpg,jpeg,svg,webp"]
}
},
"default": {
"SOCKET_PORT": 3345,
"PING_TIMEOUT": 10000,
"PING_TIMEOUT": 30000,
"GC_ENABLED": true,
"DB_FLUSH_SIZE": 400,
"MAX_DOCUMENT_SIZE": 15000000
"MAX_DOCUMENT_SIZE": 15000000,
"ASSETS_ENABLED": true,
"ASSETS_MAX_SIZE": 25000000,
"ASSETS_ALLOWED_EXTENSIONS_LIST": ""
}
},
"TLDRAW_DB_URL": {
"type": "string",
"default": "mongodb://127.0.0.1:27017/tldraw",
"description": "DB connection url"
},
"FEATURE_TLDRAW_ENABLED": {
"type": "boolean",
"default": true,
"description": "Tldraw feature enabled"
},
"TLDRAW_URI": {
"type": "string",
"default": "http://localhost:3349",
Expand Down
5 changes: 0 additions & 5 deletions config/globals.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,12 @@ switch (NODE_ENV) {
}

let defaultDbUrl = null;
let defaultTldrawDbUrl = null;
switch (NODE_ENV) {
case ENVIRONMENTS.TEST:
defaultDbUrl = 'mongodb://127.0.0.1:27017/schulcloud-test';
break;
default:
defaultDbUrl = 'mongodb://127.0.0.1:27017/schulcloud';
defaultTldrawDbUrl = 'mongodb://127.0.0.1:27017/tldraw';
}

const globals = {
Expand Down Expand Up @@ -106,9 +104,6 @@ const globals = {

// calendar
CALENDAR_URI: process.env.CALENDAR_URI,

// tldraw
TLDRAW_DB_URL: process.env.TLDRAW_DB_URL || defaultTldrawDbUrl,
};

// validation /////////////////////////////////////////////////
Expand Down
4 changes: 3 additions & 1 deletion config/test.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@
"GC_ENABLED": true,
"DB_FLUSH_SIZE": 400,
"MAX_DOCUMENT_SIZE": 15000000,
"DB_MULTIPLE_COLLECTIONS": false
"ASSETS_ENABLED": true,
"ASSETS_MAX_SIZE": 25000000,
"ASSETS_ALLOWED_EXTENSIONS_LIST": ""
},
"SCHULCONNEX_CLIENT": {
"API_URL": "http://localhost:8888/v1/",
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@
"winston": "^3.8.2",
"ws": "^8.16.0",
"y-protocols": "^1.0.6",
"yjs": "^13.6.10"
"yjs": "^13.6.11"
},
"devDependencies": {
"@aws-sdk/client-s3": "^3.352.0",
Expand Down
5 changes: 4 additions & 1 deletion src/services/config/publicAppConfigService.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,13 @@ const exposedVars = [
'FEATURE_ENABLE_LDAP_SYNC_DURING_MIGRATION',
'FEATURE_CTL_CONTEXT_CONFIGURATION_ENABLED',
'FEATURE_SHOW_NEW_CLASS_VIEW_ENABLED',
'FEATURE_TLDRAW_ENABLED',
'FEATURE_CTL_TOOLS_COPY_ENABLED',
'FEATURE_SHOW_MIGRATION_WIZARD',
'MIGRATION_WIZARD_DOCUMENTATION_LINK',
'FEATURE_TLDRAW_ENABLED',
'TLDRAW__ASSETS_ENABLED',
'TLDRAW__ASSETS_MAX_SIZE',
'TLDRAW__ASSETS_ALLOWED_EXTENSIONS_LIST',
];

/**
Expand Down
Loading