Skip to content

Commit

Permalink
Add initial authorisation
Browse files Browse the repository at this point in the history
  • Loading branch information
blazejpass committed Dec 5, 2023
1 parent 73d7602 commit 7d4b9b0
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,13 @@ export class ContentElementUrlParams {
})
contentElementId!: string;
}

export class DrawingPermissionUrlParams {
@IsMongoId()
@ApiProperty({
description: 'The name of a drawing.',
required: true,
nullable: false,
})
drawingName!: string;
}
16 changes: 16 additions & 0 deletions apps/server/src/modules/board/controller/element.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
Controller,
Delete,
ForbiddenException,
Get,
HttpCode,
NotFoundException,
Param,
Expand All @@ -21,6 +22,7 @@ import {
CreateSubmissionItemBodyParams,
DrawingElementContentBody,
DrawingElementResponse,
DrawingPermissionUrlParams,
ExternalToolElementContentBody,
ExternalToolElementResponse,
FileElementContentBody,
Expand Down Expand Up @@ -141,4 +143,18 @@ export class ElementController {

return response;
}

@ApiOperation({ summary: 'Check permission for a drawing element.' })
@ApiResponse({ status: 204 })
@ApiResponse({ status: 400, type: ApiValidationError })
@ApiResponse({ status: 403, type: ForbiddenException })
@ApiResponse({ status: 404, type: NotFoundException })
@HttpCode(204)
@Get(':drawingName/permission')
async checkDrawingPermission(
@Param() urlParams: DrawingPermissionUrlParams,
@CurrentUser() currentUser: ICurrentUser
): Promise<void> {
await this.elementUc.checkElementReadPermission(currentUser.userId, urlParams.drawingName);
}
}
5 changes: 5 additions & 0 deletions apps/server/src/modules/board/uc/element.uc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ export class ElementUc extends BaseUc {
return element;
}

async checkElementReadPermission(userId: EntityId, elementId: EntityId): Promise<void> {
const element = await this.elementService.findById(elementId);
await this.checkPermission(userId, element, Action.read);
}

async createSubmissionItem(
userId: EntityId,
contentElementId: EntityId,
Expand Down
17 changes: 15 additions & 2 deletions apps/server/src/modules/tldraw/controller/tldraw.ws.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { WebSocketGateway, WebSocketServer, OnGatewayInit, OnGatewayConnection } from '@nestjs/websockets';
import { Server, WebSocket } from 'ws';
import { Request } from 'express';
import { ConfigService } from '@nestjs/config';
import cookie from 'cookie';
import { TldrawConfig, SOCKET_PORT } from '../config';
import { WsCloseCodeEnum } from '../types';
import { TldrawWsService } from '../service';
Expand All @@ -15,9 +17,20 @@ export class TldrawWs implements OnGatewayInit, OnGatewayConnection {
private readonly tldrawWsService: TldrawWsService
) {}

public handleConnection(client: WebSocket, request: Request): void {
async handleConnection(client: WebSocket, request: Request): Promise<void> {
const docName = this.getDocNameFromRequest(request);

const cookies = cookie.parse(request.headers.cookie || '');
if (!cookies?.jwt) {
client.close(WsCloseCodeEnum.WS_CLIENT_UNAUTHORISED_CONNECTION_CODE, 'Unauthorised connection.');
}
try {
await this.tldrawWsService.authorizeConnection(docName, cookies.jwt);
} catch (e) {
client.close(
WsCloseCodeEnum.WS_CLIENT_UNAUTHORISED_CONNECTION_CODE,
"Unauthorised connection - you don't have permission to this drawing."
);
}
if (docName.length > 0 && this.configService.get<string>('FEATURE_TLDRAW_ENABLED')) {
this.tldrawWsService.setupWSConnection(client, docName);
} else {
Expand Down
17 changes: 16 additions & 1 deletion apps/server/src/modules/tldraw/service/tldraw.ws.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import WebSocket from 'ws';
import { applyAwarenessUpdate, encodeAwarenessUpdate, removeAwarenessStates } from 'y-protocols/awareness';
import { encoding, decoding, map } from 'lib0';
import { readSyncMessage, writeSyncStep1, writeUpdate } from 'y-protocols/sync';
import { firstValueFrom } from 'rxjs';
import { HttpService } from '@nestjs/axios';
import { Configuration } from '@hpi-schul-cloud/commons/lib';
import { Persitence, WSConnectionState, WSMessageType } from '../types';
import { TldrawConfig } from '../config';
import { WsSharedDocDo } from '../domain/ws-shared-doc.do';
Expand All @@ -19,7 +22,8 @@ export class TldrawWsService {

constructor(
private readonly configService: ConfigService<TldrawConfig, true>,
private readonly tldrawBoardRepo: TldrawBoardRepo
private readonly tldrawBoardRepo: TldrawBoardRepo,
private readonly httpService: HttpService
) {
this.pingTimeout = this.configService.get<number>('TLDRAW_PING_TIMEOUT');
}
Expand Down Expand Up @@ -206,4 +210,15 @@ export class TldrawWsService {
public async flushDocument(docName: string): Promise<void> {
await this.tldrawBoardRepo.flushDocument(docName);
}

async authorizeConnection(drawingName: string, token: string) {
await firstValueFrom(
this.httpService.get(`${Configuration.get('HOST') as string}/api/v3/elements/${drawingName}/permission`, {
headers: {
Accept: 'Application/json',
Authorization: `Bearer ${token}`,
},
})
);
}
}
3 changes: 2 additions & 1 deletion apps/server/src/modules/tldraw/tldraw-ws.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ import { ConfigModule } from '@nestjs/config';
import { createConfigModuleOptions } from '@src/config';
import { CoreModule } from '@src/core';
import { Logger } from '@src/core/logger';
import { HttpModule } from '@nestjs/axios';
import { TldrawBoardRepo } from './repo';
import { TldrawWsService } from './service';
import { TldrawWs } from './controller';
import { config } from './config';

@Module({
imports: [CoreModule, ConfigModule.forRoot(createConfigModuleOptions(config))],
imports: [CoreModule, ConfigModule.forRoot(createConfigModuleOptions(config)), HttpModule],
providers: [Logger, TldrawWs, TldrawWsService, TldrawBoardRepo],
})
export class TldrawWsModule {}
1 change: 1 addition & 0 deletions apps/server/src/modules/tldraw/types/ws-close-code-enum.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export enum WsCloseCodeEnum {
WS_CLIENT_BAD_REQUEST_CODE = 4400,
WS_CLIENT_UNAUTHORISED_CONNECTION_CODE = 4401,
}

0 comments on commit 7d4b9b0

Please sign in to comment.