From 82117339461f4a43f2ce188ac60f6d795febcb77 Mon Sep 17 00:00:00 2001
From: Negin Moshki <133236446+NeginMoshki@users.noreply.github.com>
Date: Fri, 4 Aug 2023 17:04:11 +0200
Subject: [PATCH] Add js doc comments (#43)

* Add comments for auth and browser package

* DocUpdate user.controller.spec.ts

* DocUpdate user.controller.ts

* DocUpdate user.entity.ts

* DocUpdate user.controller.spec.ts

* DocUpdate user.controller.spec.ts

* DocUpdate user.controller.ts

* DocUpdate user.entity.ts

* DocUpdate user.module.ts

* DocUpdate user.service.spec.ts

* DocUpdate user.service.ts

* DocUpdate mikro-orm.config.ts

* Add comments for the backend classes

* Format code

* Remove @fileoverview comments

---------

Co-authored-by: neda_moshki <uzijb@student.kit.edu>
Co-authored-by: Neda Moshki <133236496+NedaMoshki@users.noreply.github.com>
Co-authored-by: Florian Raith <florianraith00@gmail.com>
---
 src/app.module.ts                        |  3 +
 src/auth/auth.controller.spec.ts         | 11 +++
 src/auth/auth.controller.ts              | 34 +++++++++
 src/auth/auth.dto.ts                     | 15 ++++
 src/auth/auth.guard.ts                   | 12 ++++
 src/auth/auth.module.ts                  |  3 +
 src/auth/auth.service.spec.ts            | 11 +++
 src/auth/auth.service.ts                 | 38 ++++++++++
 src/auth/jwt.strategy.ts                 | 18 +++++
 src/browser/browser.module.ts            |  3 +
 src/browser/browser.service.ts           | 87 ++++++++++++++++++++++
 src/browser/browser.ts                   | 63 ++++++++++++++++
 src/category/category.controller.spec.ts |  4 ++
 src/category/category.controller.ts      | 28 ++++++++
 src/category/category.dto.ts             | 10 +++
 src/category/category.entity.ts          | 30 ++++++++
 src/category/category.module.ts          |  4 ++
 src/category/category.service.spec.ts    | 10 +++
 src/category/category.service.ts         | 44 ++++++++++++
 src/channel/browser.gateway.ts           | 75 +++++++++++++++++++
 src/channel/channel.gateway.spec.ts      |  3 +
 src/channel/channel.gateway.ts           | 69 ++++++++++++++++++
 src/channel/channel.module.ts            |  3 +
 src/channel/channel.service.ts           | 65 +++++++++++++++++
 src/channel/channel.ts                   | 92 ++++++++++++++++++++++++
 src/channel/notes.gateway.ts             | 27 +++++++
 src/channel/whiteboard.gateway.ts        | 14 ++++
 src/common/constraints/exists.ts         | 13 +++-
 src/common/constraints/match.ts          | 14 ++++
 src/common/constraints/unique.ts         | 18 +++++
 src/common/guards/admin.guard.ts         | 13 ++++
 src/common/not-found.interceptor.ts      | 10 ++-
 src/main.ts                              | 15 +++-
 src/mikro-orm.config.ts                  | 12 ++++
 src/note/note.entity.ts                  |  8 +++
 src/note/note.module.ts                  |  3 +
 src/note/note.service.ts                 | 27 +++++++
 src/room/room.controller.spec.ts         |  9 +++
 src/room/room.controller.ts              | 32 +++++++++
 src/room/room.dto.ts                     |  6 ++
 src/room/room.entity.ts                  | 12 ++++
 src/room/room.module.ts                  |  3 +
 src/room/room.service.spec.ts            |  9 +++
 src/room/room.service.ts                 | 44 ++++++++++++
 src/user/user.controller.spec.ts         | 14 ++++
 src/user/user.controller.ts              | 30 ++++++++
 src/user/user.entity.ts                  | 14 ++++
 src/user/user.module.ts                  |  3 +
 src/user/user.service.spec.ts            | 13 ++++
 src/user/user.service.ts                 | 46 ++++++++++++
 50 files changed, 1141 insertions(+), 3 deletions(-)

diff --git a/src/app.module.ts b/src/app.module.ts
index 3aafd79..76bd509 100644
--- a/src/app.module.ts
+++ b/src/app.module.ts
@@ -10,6 +10,9 @@ import { ExistsConstraint } from './common/constraints/exists';
 import { ChannelModule } from './channel/channel.module';
 import { BrowserModule } from './browser/browser.module';
 
+/**
+ * Main application module where other modules are imported and configured.
+ */
 @Module({
   imports: [
     MikroOrmModule.forRoot(),
diff --git a/src/auth/auth.controller.spec.ts b/src/auth/auth.controller.spec.ts
index 27a31e6..a2234ed 100644
--- a/src/auth/auth.controller.spec.ts
+++ b/src/auth/auth.controller.spec.ts
@@ -1,9 +1,17 @@
 import { Test, TestingModule } from '@nestjs/testing';
 import { AuthController } from './auth.controller';
 
+/**
+ * Test suite for the AuthController class.
+ */
 describe('AuthController', () => {
   let controller: AuthController;
 
+  /**
+   * Executes before each individual test case.
+   * Creates a TestingModule containing the AuthController.
+   * Retrieves an instance of AuthController from the module.
+   */
   beforeEach(async () => {
     const module: TestingModule = await Test.createTestingModule({
       controllers: [AuthController],
@@ -12,6 +20,9 @@ describe('AuthController', () => {
     controller = module.get<AuthController>(AuthController);
   });
 
+  /**
+   * Single test case: Verifies if the AuthController is defined.
+   */
   it('should be defined', () => {
     expect(controller).toBeDefined();
   });
diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts
index 5de5800..e0ef93a 100644
--- a/src/auth/auth.controller.ts
+++ b/src/auth/auth.controller.ts
@@ -14,10 +14,20 @@ import { AuthGuard } from './auth.guard';
 import { Response } from 'express';
 import { RegisterUser, LoginUser } from './auth.dto';
 
+/**
+ * Controller handling authentication-related operations.
+ */
 @Controller('auth')
 export class AuthController {
   constructor(private readonly auth: AuthService) {}
 
+  /**
+   * Registers a new user.
+   *
+   * @param data - Registration data for the new user.
+   * @param response - Express response object to set cookies.
+   * @returns The registration payload.
+   */
   @HttpCode(HttpStatus.OK)
   @Post('register')
   public async register(
@@ -31,6 +41,13 @@ export class AuthController {
     return payload;
   }
 
+  /**
+   * Logs in a user.
+   *
+   * @param data - Login credentials of the user.
+   * @param response - Express response object to set cookies.
+   * @returns The login payload.
+   */
   @HttpCode(HttpStatus.OK)
   @Post('login')
   public async login(
@@ -44,6 +61,11 @@ export class AuthController {
     return payload;
   }
 
+  /**
+   * Retrieves the user's profile information.
+   *
+   * @returns The user's profile and token expiration.
+   */
   @UseGuards(AuthGuard)
   @Get('profile')
   public async profile() {
@@ -53,6 +75,12 @@ export class AuthController {
     return { user, exp: token.exp };
   }
 
+  /**
+   * Logs out the currently authenticated user.
+   *
+   * @param response - Express response object to clear cookies.
+   * @returns A success message.
+   */
   @UseGuards(AuthGuard)
   @Post('logout')
   public async logout(@Res({ passthrough: true }) response: Response) {
@@ -61,6 +89,12 @@ export class AuthController {
     return { message: 'success' };
   }
 
+  /**
+   * Deletes the account of the currently authenticated user.
+   *
+   * @param response - Express response object to clear cookies.
+   * @returns A success message.
+   */
   @UseGuards(AuthGuard)
   @Delete('delete')
   public async delete(@Res({ passthrough: true }) response: Response) {
diff --git a/src/auth/auth.dto.ts b/src/auth/auth.dto.ts
index cc46691..3505179 100644
--- a/src/auth/auth.dto.ts
+++ b/src/auth/auth.dto.ts
@@ -4,6 +4,9 @@ import { User } from '../user/user.entity';
 import { IsUnique } from '../common/constraints/unique';
 import { Match } from '../common/constraints/match';
 
+/**
+ * Data structure for registering a new user.
+ */
 export class RegisterUser {
   @IsNotEmpty({
     message: 'Schule / Universität oder Organisation darf nicht leer sein',
@@ -43,8 +46,14 @@ export class RegisterUser {
   confirmPassword: string;
 }
 
+/**
+ * Data structure for creating a new user, based on the RegisterUser class but without confirmPassword field.
+ */
 export class CreateUser extends OmitType(RegisterUser, ['confirmPassword']) {}
 
+/**
+ * Data structure for user login.
+ */
 export class LoginUser {
   @IsEmail(
     {},
@@ -60,6 +69,9 @@ export class LoginUser {
   password: string;
 }
 
+/**
+ * Data structure for changing user password.
+ */
 export class ChangePassword {
   @IsNotEmpty({
     message: 'Bitte gib dein aktuelles Passwort ein',
@@ -83,6 +95,9 @@ export class ChangePassword {
   confirmNewPassword: string;
 }
 
+/**
+ * Payload structure returned after successful authentication.
+ */
 export interface AuthPayload {
   token: string;
   user: User;
diff --git a/src/auth/auth.guard.ts b/src/auth/auth.guard.ts
index b10c95e..12c79e4 100644
--- a/src/auth/auth.guard.ts
+++ b/src/auth/auth.guard.ts
@@ -3,6 +3,9 @@ import { AuthGuard as PassportAuthGuard } from '@nestjs/passport';
 import { AuthService } from './auth.service';
 import { JwtService } from '@nestjs/jwt';
 
+/**
+ * Custom authentication guard extending PassportAuthGuard for JWT-based authentication.
+ */
 @Injectable()
 export class AuthGuard extends PassportAuthGuard('jwt') {
   constructor(
@@ -11,6 +14,14 @@ export class AuthGuard extends PassportAuthGuard('jwt') {
   ) {
     super();
   }
+
+  /**
+   * Determines if the request is authorized.
+   * Extends the default canActivate method of PassportAuthGuard.
+   *
+   * @param context - ExecutionContext containing the request and response objects.
+   * @returns A boolean indicating if the request is authorized.
+   */
   async canActivate(context) {
     const canActivateResult = (await super.canActivate(context)) as boolean;
 
@@ -20,6 +31,7 @@ export class AuthGuard extends PassportAuthGuard('jwt') {
 
       const payload = { sub: user.id };
       const token = this.jwtService.sign(payload);
+
       response.cookie('jwt', token, { httpOnly: true });
     }
 
diff --git a/src/auth/auth.module.ts b/src/auth/auth.module.ts
index d85de9a..76c89df 100644
--- a/src/auth/auth.module.ts
+++ b/src/auth/auth.module.ts
@@ -5,6 +5,9 @@ import { UserModule } from '../user/user.module';
 import { JwtModule } from '@nestjs/jwt';
 import { JwtStrategy } from './jwt.strategy';
 
+/**
+ * Module handling authentication-related components.
+ */
 @Global()
 @Module({
   imports: [
diff --git a/src/auth/auth.service.spec.ts b/src/auth/auth.service.spec.ts
index 800ab66..55c24e1 100644
--- a/src/auth/auth.service.spec.ts
+++ b/src/auth/auth.service.spec.ts
@@ -1,9 +1,17 @@
 import { Test, TestingModule } from '@nestjs/testing';
 import { AuthService } from './auth.service';
 
+/**
+ * Test suite for the AuthService class.
+ */
 describe('AuthService', () => {
   let service: AuthService;
 
+  /**
+   * Executes before each individual test case.
+   * Creates a TestingModule containing the AuthService.
+   * Retrieves an instance of AuthService from the module.
+   */
   beforeEach(async () => {
     const module: TestingModule = await Test.createTestingModule({
       providers: [AuthService],
@@ -12,6 +20,9 @@ describe('AuthService', () => {
     service = module.get<AuthService>(AuthService);
   });
 
+  /**
+   * Single test case: Verifies if the AuthService is defined.
+   */
   it('should be defined', () => {
     expect(service).toBeDefined();
   });
diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts
index 0d085dd..5d9bbab 100644
--- a/src/auth/auth.service.ts
+++ b/src/auth/auth.service.ts
@@ -8,6 +8,9 @@ import { REQUEST } from '@nestjs/core';
 import { JwtToken } from './jwt.strategy';
 import * as bcrypt from 'bcrypt';
 
+/**
+ * Service responsible for authentication-related operations.
+ */
 @Injectable()
 export class AuthService {
   constructor(
@@ -16,6 +19,13 @@ export class AuthService {
     @Inject(REQUEST) private readonly request: Request,
   ) {}
 
+  /**
+   * Handles user login.
+   *
+   * @param loginUser - Login credentials of the user.
+   * @returns Authentication payload containing token, user, and expiration.
+   * @throws UnauthorizedException if credentials are invalid.
+   */
   public async login({ email, password }: LoginUser): Promise<AuthPayload> {
     const user = await this.users.findByEmail(email);
 
@@ -26,6 +36,12 @@ export class AuthService {
     return this.createToken(user);
   }
 
+  /**
+   * Handles user registration.
+   *
+   * @param data - Registration data for the new user.
+   * @returns Authentication payload containing token, user, and expiration.
+   */
   public async register(data: CreateUser): Promise<AuthPayload> {
     // TODO: email verification
 
@@ -34,10 +50,22 @@ export class AuthService {
     return this.createToken(user);
   }
 
+  /**
+   * Deletes a user by their ID.
+   *
+   * @param id - ID of the user to be deleted.
+   * @returns Resolves when deletion is successful.
+   */
   public async delete(id: number): Promise<void> {
     return await this.users.delete(id);
   }
 
+  /**
+   * Creates an authentication payload (token, user, expiration).
+   *
+   * @param user - User entity for which to create the payload.
+   * @returns Authentication payload containing token, user, and expiration.
+   */
   private createToken(user: User): AuthPayload {
     const payload = { sub: user.id };
     const token = this.jwtService.sign(payload);
@@ -46,10 +74,20 @@ export class AuthService {
     return { token, user, exp };
   }
 
+  /**
+   * Retrieves the currently authenticated user.
+   *
+   * @returns A Promise that resolves to the authenticated user entity.
+   */
   public async user(): Promise<User> {
     return await this.users.findOne(this.token().sub);
   }
 
+  /**
+   * Retrieves the JWT token from the request.
+   *
+   * @returns The JWT token.
+   */
   public token(): JwtToken {
     return this.request.user as JwtToken;
   }
diff --git a/src/auth/jwt.strategy.ts b/src/auth/jwt.strategy.ts
index 868a2d4..fbe247e 100644
--- a/src/auth/jwt.strategy.ts
+++ b/src/auth/jwt.strategy.ts
@@ -4,12 +4,18 @@ import { Injectable } from '@nestjs/common';
 import { UserService } from '../user/user.service';
 import { Request } from 'express';
 
+/**
+ * Interface representing the JWT token structure.
+ */
 export interface JwtToken {
   sub: number;
   iat: number;
   exp: number;
 }
 
+/**
+ * JWT authentication strategy using PassportStrategy.
+ */
 @Injectable()
 export class JwtStrategy extends PassportStrategy(Strategy) {
   constructor(private readonly userService: UserService) {
@@ -20,6 +26,12 @@ export class JwtStrategy extends PassportStrategy(Strategy) {
     });
   }
 
+  /**
+   * Retrieves the JWT token from the request cookie.
+   *
+   * @param req - Express request object.
+   * @returns The JWT token from the cookie.
+   */
   public static fromCookie(req: Request): string {
     if (req && req.cookies) {
       return req.cookies['jwt'];
@@ -28,6 +40,12 @@ export class JwtStrategy extends PassportStrategy(Strategy) {
     return null;
   }
 
+  /**
+   * Validates the JWT token payload.
+   *
+   * @param payload - Decoded JWT token payload.
+   * @returns The validated payload.
+   */
   public async validate(payload: JwtToken) {
     return payload;
   }
diff --git a/src/browser/browser.module.ts b/src/browser/browser.module.ts
index 6b383e5..fabedce 100644
--- a/src/browser/browser.module.ts
+++ b/src/browser/browser.module.ts
@@ -1,6 +1,9 @@
 import { Global, Module } from '@nestjs/common';
 import { BrowserService } from './browser.service';
 
+/**
+ * Global module providing services related to browser functionality.
+ */
 @Global()
 @Module({
   providers: [BrowserService],
diff --git a/src/browser/browser.service.ts b/src/browser/browser.service.ts
index e4d8831..f341046 100644
--- a/src/browser/browser.service.ts
+++ b/src/browser/browser.service.ts
@@ -11,10 +11,18 @@ const LOGGER = new Logger('BrowserService');
 const PATH_TO_EXTENSION = path.join(process.cwd(), 'browser-extension');
 const EXTENSION_ID = 'jjndjgheafjngoipoacpjgeicjeomjli';
 
+/**
+ * Service responsible for managing browser instances and interactions.
+ */
 @Injectable()
 export class BrowserService implements OnModuleDestroy {
   private browserContexts: Map<string, Browser> = new Map();
 
+  /**
+   * Opens a new Puppeteer browser instance.
+   *
+   * @returns The Puppeteer browser instance.
+   */
   private async openBrowser() {
     const args = [];
 
@@ -37,6 +45,13 @@ export class BrowserService implements OnModuleDestroy {
     });
   }
 
+  /**
+   * Opens a website in a browser context.
+   *
+   * @param channelId - Identifier for the channel.
+   * @param url - URL of the website to open.
+   * @returns Peer ID associated with the browser context.
+   */
   public async openWebsite(
     channelId: string,
     url: string,
@@ -62,14 +77,32 @@ export class BrowserService implements OnModuleDestroy {
     return browser.peerId;
   }
 
+  /**
+   * Retrieves the Peer ID associated with a channel.
+   *
+   * @param channelId - Identifier for the channel.
+   * @returns The Peer ID associated with the browser context.
+   */
   public getPeerId(channelId: string): string {
     return this.browserContexts.get(channelId)?.peerId;
   }
 
+  /**
+   * Retrieve the browser context associated with a specific channel.
+   * @param channel The channel for which to retrieve the browser context.
+   * @returns The browser context associated with the channel, or null if not found.
+   */
   public getFromChannel(channel: Channel): Browser | null {
     return this.browserContexts.get(channel.id) ?? null;
   }
 
+  /**
+   * Moves the mouse cursor to a specific position in a browser context.
+   *
+   * @param channelId - Identifier for the channel.
+   * @param x - The X-coordinate of the mouse cursor.
+   * @param y - The Y-coordinate of the mouse cursor.
+   */
   public async moveMouse(
     channelId: string,
     x: number,
@@ -78,49 +111,103 @@ export class BrowserService implements OnModuleDestroy {
     await this.browserContexts.get(channelId)?.moveMouse(x, y);
   }
 
+  /**
+   * Initiates a mouse down event in a browser context.
+   *
+   * @param channelId - Identifier for the channel.
+   */
   public async mouseDown(channelId: string): Promise<void> {
     await this.browserContexts.get(channelId)?.mouseDown();
   }
 
+  /**
+   * Initiates a mouse up event in a browser context.
+   *
+   * @param channelId - Identifier for the channel.
+   */
   public async mouseUp(channelId: string): Promise<void> {
     await this.browserContexts.get(channelId)?.mouseUp();
   }
 
+  /**
+   * Initiates a key down event in a browser context.
+   *
+   * @param channelId - Identifier for the channel.
+   * @param key - The key to be pressed.
+   */
   public async keyDown(channelId: string, key: string): Promise<void> {
     await this.browserContexts.get(channelId)?.keyDown(key);
   }
 
+  /**
+   * Initiates a key up event in a browser context.
+   *
+   * @param channelId - Identifier for the channel.
+   * @param key - The key to be released.
+   */
   public async keyUp(channelId: string, key: string): Promise<void> {
     await this.browserContexts.get(channelId)?.keyUp(key);
   }
 
+  /**
+   * Initiates a scroll event in a browser context.
+   *
+   * @param channelId - Identifier for the channel.
+   * @param deltaY - The amount to scroll along the Y-axis.
+   */
   public async scroll(channelId: string, deltaY: number): Promise<void> {
     await this.browserContexts.get(channelId)?.scroll(deltaY);
   }
 
+  /**
+   * Reloads the current page in a browser context.
+   *
+   * @param channelId - Identifier for the channel.
+   */
   public async reload(channelId: string): Promise<void> {
     await this.browserContexts.get(channelId)?.reload();
   }
 
+  /**
+   * Navigates back to the previous page in a browser context.
+   *
+   * @param channelId - Identifier for the channel.
+   */
   public async navigateBack(channelId: string): Promise<void> {
     await this.browserContexts.get(channelId)?.navigateBack();
   }
 
+  /**
+   * Navigates forward to the next page in a browser context.
+   *
+   * @param channelId - Identifier for the channel.
+   */
   public async navigateForward(channelId: string): Promise<void> {
     await this.browserContexts.get(channelId)?.navigateForward();
   }
 
+  /**
+   * Closes a specific browser context.
+   *
+   * @param channelId - Identifier for the channel.
+   */
   public async closeBrowserContext(channelId: string): Promise<void> {
     await this.browserContexts.get(channelId)?.close();
     this.browserContexts.delete(channelId);
   }
 
+  /**
+   * Closes the service, disposing of browser instances and contexts.
+   */
   public async close(): Promise<void> {
     for (const browser of this.browserContexts.values()) {
       await browser.close();
     }
   }
 
+  /**
+   * Handles cleanup on module destruction.
+   */
   public async onModuleDestroy(): Promise<void> {
     await this.close();
   }
diff --git a/src/browser/browser.ts b/src/browser/browser.ts
index 10c7fa0..05a9702 100644
--- a/src/browser/browser.ts
+++ b/src/browser/browser.ts
@@ -9,10 +9,19 @@ const LOGGER = new Logger('Browser');
 const PATH_TO_EXTENSION = path.join(process.cwd(), 'browser-extension');
 const EXTENSION_ID = 'jjndjgheafjngoipoacpjgeicjeomjli';
 
+/**
+ * Represents a Puppeteer-based browser instance.
+ */
 export class Browser {
   public peerId: string;
   private page: Page;
 
+  /**
+   * Creates an instance of the Browser class.
+   *
+   * @param browser - The Puppeteer browser instance.
+   * @param url - The initial URL to open.
+   */
   constructor(
     private browser: PuppeteerBrowser,
     public url: string,
@@ -20,6 +29,11 @@ export class Browser {
     private readonly channelId: string,
   ) {}
 
+  /**
+   * Opens a new page in the browser instance and initializes mouse tracking.
+   *
+   * @returns The ID associated with the started recording.
+   */
   public async open(): Promise<string> {
     LOGGER.debug(`Opening page with url: ${this.url}`);
     this.page = await this.browser.newPage();
@@ -63,46 +77,90 @@ export class Browser {
     return id;
   }
 
+  /**
+   * Opens a specific website in the current page.
+   *
+   * @param url - The URL of the website to open.
+   */
   public async openWebsite(url: string): Promise<void> {
     await this.page.goto(url);
   }
 
+  /**
+   * Moves the mouse cursor to a specific position.
+   *
+   * @param x - The X-coordinate of the mouse cursor.
+   * @param y - The Y-coordinate of the mouse cursor.
+   */
   public async moveMouse(x: number, y: number): Promise<void> {
     await this.page.mouse.move(x, y);
   }
 
+  /**
+   * Initiates a mouse down event.
+   */
   public async mouseDown(): Promise<void> {
     await this.page.mouse.down();
   }
 
+  /**
+   * Initiates a mouse up event.
+   */
   public async mouseUp(): Promise<void> {
     await this.page.mouse.up();
   }
 
+  /**
+   * Initiates a key down event.
+   *
+   * @param key - The key to be pressed.
+   */
   public async keyDown(key: string): Promise<void> {
     await this.page.keyboard.down(key as KeyInput);
   }
 
+  /**
+   * Initiates a key up event.
+   *
+   * @param key - The key to be released.
+   */
   public async keyUp(key: string): Promise<void> {
     await this.page.keyboard.up(key as KeyInput);
   }
 
+  /**
+   * Initiates a scroll event.
+   *
+   * @param deltaY - The amount to scroll along the Y-axis.
+   */
   public async scroll(deltaY: number): Promise<void> {
     await this.page.mouse.wheel({ deltaY });
   }
 
+  /**
+   * Reloads the current page.
+   */
   public async reload(): Promise<void> {
     await this.page.reload();
   }
 
+  /**
+   * Navigates back to the previous page.
+   */
   public async navigateBack(): Promise<void> {
     await this.page.goBack();
   }
 
+  /**
+   * Navigates forward to the next page.
+   */
   public async navigateForward(): Promise<void> {
     await this.page.goForward();
   }
 
+  /**
+   * Closes the browser instance.
+   */
   public async close(): Promise<void> {
     if (this.browser) {
       LOGGER.debug('Closing browser');
@@ -111,6 +169,11 @@ export class Browser {
   }
 }
 
+/**
+ * Helper function to install mouse tracking for puppeteer pages.
+ *
+ * @param page - The puppeteer page to install the mouse tracking on.
+ */
 async function installMouseHelper(page) {
   await page.evaluateOnNewDocument(() => {
     // Install mouse helper only for top-level frame.
diff --git a/src/category/category.controller.spec.ts b/src/category/category.controller.spec.ts
index bc8ce79..9eff6dc 100644
--- a/src/category/category.controller.spec.ts
+++ b/src/category/category.controller.spec.ts
@@ -12,6 +12,10 @@ describe('CategoryController', () => {
     controller = module.get<CategoryController>(CategoryController);
   });
 
+  /**
+   * Test case to ensure that the CategoryController is defined.
+   * It checks whether the controller instance is created successfully.
+   */
   it('should be defined', () => {
     expect(controller).toBeDefined();
   });
diff --git a/src/category/category.controller.ts b/src/category/category.controller.ts
index 4022f55..c116a54 100644
--- a/src/category/category.controller.ts
+++ b/src/category/category.controller.ts
@@ -13,6 +13,10 @@ import { CreateCategory, UpdateCategory } from './category.dto';
 import { AuthGuard } from '../auth/auth.guard';
 import { AuthService } from '../auth/auth.service';
 
+/**
+ * Controller responsible for handling category-related operations.
+ * This controller is protected by an authentication guard.
+ */
 @Controller('category')
 @UseGuards(AuthGuard)
 export class CategoryController {
@@ -21,24 +25,48 @@ export class CategoryController {
     private readonly auth: AuthService,
   ) {}
 
+  /**
+   * Retrieves all categories associated with the authenticated user.
+   *
+   * @returns An array of categories.
+   */
   @Get('/')
   public async index() {
     const user = await this.auth.user();
     return this.categories.allFromUser(user);
   }
 
+  /**
+   * Creates a new category for the authenticated user.
+   *
+   * @param data - The category data to be created.
+   * @returns The created category.
+   */
   @Post('/')
   public async create(@Body() data: CreateCategory) {
     const user = await this.auth.user();
     return this.categories.create(data.name, user);
   }
 
+  /**
+   * Updates an existing category for the authenticated user.
+   *
+   * @param id - The ID of the category to be updated.
+   * @param data - The updated category data.
+   * @returns The updated category.
+   */
   @Put('/:id')
   public async update(@Param('id') id: number, @Body() data: UpdateCategory) {
     const user = await this.auth.user();
     return this.categories.update(id, user, data.name);
   }
 
+  /**
+   * Deletes a category for the authenticated user.
+   *
+   * @param id - The ID of the category to be deleted.
+   * @returns A message indicating the deletion status.
+   */
   @Delete('/:id')
   public async delete(@Param('id') id: number) {
     const user = await this.auth.user();
diff --git a/src/category/category.dto.ts b/src/category/category.dto.ts
index 1d1bc23..e2ff905 100644
--- a/src/category/category.dto.ts
+++ b/src/category/category.dto.ts
@@ -1,10 +1,20 @@
 import { IsNotEmpty } from 'class-validator';
 
+/**
+ * Data transfer object (DTO) for creating a new category.
+ */
 export class CreateCategory {
+  /**
+   * The name of the category to be created.
+   */
   @IsNotEmpty({
     message: 'Name darf nicht leer sein',
   })
   name: string;
 }
 
+/**
+ * Data transfer object (DTO) for updating an existing category.
+ * Inherits properties from the CreateCategory DTO.
+ */
 export class UpdateCategory extends CreateCategory {}
diff --git a/src/category/category.entity.ts b/src/category/category.entity.ts
index 98f60b7..273dacc 100644
--- a/src/category/category.entity.ts
+++ b/src/category/category.entity.ts
@@ -9,26 +9,56 @@ import {
 import { User } from '../user/user.entity';
 import { Room } from '../room/room.entity';
 
+/**
+ * Entity representing a category for rooms.
+ */
 @Entity({ tableName: 'categories' })
 export class Category {
+  /**
+   * The primary key ID of the category.
+   */
   @PrimaryKey()
   id: number;
 
+  /**
+   * The name of the category.
+   */
   @Property()
   name: string;
 
+  /**
+   * The owner of the category.
+   * Represents a many-to-one relationship with the User entity.
+   */
   @ManyToOne({ hidden: true, onDelete: 'cascade' })
   owner: User;
 
+  /**
+   * Collection of rooms associated with this category.
+   * Represents a one-to-many relationship with the Room entity.
+   */
   @OneToMany(() => Room, (room) => room.category)
   rooms = new Collection<Room>(this);
 
+  /**
+   * The creation timestamp of the category.
+   */
   @Property()
   createdAt: Date = new Date();
 
+  /**
+   * The update timestamp of the category.
+   * Automatically updated when the category is modified.
+   */
   @Property({ onUpdate: () => new Date() })
   updatedAt: Date = new Date();
 
+  /**
+   * Initializes a new Category instance.
+   *
+   * @param name - The name of the category.
+   * @param owner - The owner of the category.
+   */
   constructor(name: string, owner: User) {
     this.name = name;
     this.owner = owner;
diff --git a/src/category/category.module.ts b/src/category/category.module.ts
index b1b4abf..171139c 100644
--- a/src/category/category.module.ts
+++ b/src/category/category.module.ts
@@ -5,6 +5,10 @@ import { MikroOrmModule } from '@mikro-orm/nestjs';
 import { Category } from './category.entity';
 import { ChannelModule } from '../channel/channel.module';
 
+/**
+ * Global module for handling category-related functionality.
+ * Provides services, controllers, and exports related to categories.
+ */
 @Global()
 @Module({
   imports: [MikroOrmModule.forFeature([Category]), ChannelModule],
diff --git a/src/category/category.service.spec.ts b/src/category/category.service.spec.ts
index 7afa05f..f18af0c 100644
--- a/src/category/category.service.spec.ts
+++ b/src/category/category.service.spec.ts
@@ -1,9 +1,16 @@
 import { Test, TestingModule } from '@nestjs/testing';
 import { CategoryService } from './category.service';
 
+/**
+ * Test suite for the CategoryService class.
+ */
 describe('CategoryService', () => {
   let service: CategoryService;
 
+  /**
+   * Setup before each test case by creating a testing module and
+   * obtaining an instance of the CategoryService.
+   */
   beforeEach(async () => {
     const module: TestingModule = await Test.createTestingModule({
       providers: [CategoryService],
@@ -12,6 +19,9 @@ describe('CategoryService', () => {
     service = module.get<CategoryService>(CategoryService);
   });
 
+  /**
+   * Test case to check if the CategoryService instance is defined.
+   */
   it('should be defined', () => {
     expect(service).toBeDefined();
   });
diff --git a/src/category/category.service.ts b/src/category/category.service.ts
index 96e8a8b..169feb0 100644
--- a/src/category/category.service.ts
+++ b/src/category/category.service.ts
@@ -6,8 +6,18 @@ import { EntityRepository } from '@mikro-orm/mysql';
 import { User } from '../user/user.entity';
 import { ChannelService } from '../channel/channel.service';
 
+/**
+ * Service class responsible for handling category-related operations.
+ */
 @Injectable()
 export class CategoryService {
+  /**
+   * Initializes an instance of the CategoryService.
+   *
+   * @param em - The EntityManager instance.
+   * @param repository - The EntityRepository for the Category entity.
+   * @param channels - The ChannelService instance.
+   */
   constructor(
     private readonly em: EntityManager,
     @InjectRepository(Category)
@@ -15,6 +25,12 @@ export class CategoryService {
     private readonly channels: ChannelService,
   ) {}
 
+  /**
+   * Retrieves all categories associated with a user, including their rooms.
+   *
+   * @param user - The user whose categories to retrieve.
+   * @returns A promise that resolves to an array of Category instances.
+   */
   public async allFromUser(user: User): Promise<Category[]> {
     const categories = await user.categories.loadItems({
       populate: ['rooms'],
@@ -32,10 +48,24 @@ export class CategoryService {
     return categories;
   }
 
+  /**
+   * Retrieves a category by its ID and owner.
+   *
+   * @param id - The ID of the category to retrieve.
+   * @param owner - The owner of the category.
+   * @returns A promise that resolves to the retrieved Category instance.
+   */
   public async get(id: number, owner: User): Promise<Category> {
     return this.repository.findOneOrFail({ id, owner });
   }
 
+  /**
+   * Creates a new category.
+   *
+   * @param name - The name of the new category.
+   * @param owner - The owner of the new category.
+   * @returns A promise that resolves to the created Category instance.
+   */
   public async create(name: string, owner: User): Promise<Category> {
     const category = new Category(name, owner);
 
@@ -43,6 +73,14 @@ export class CategoryService {
     return category;
   }
 
+  /**
+   * Updates the name of a category.
+   *
+   * @param id - The ID of the category to update.
+   * @param owner - The owner of the category.
+   * @param name - The new name for the category.
+   * @returns A promise that resolves to the updated Category instance.
+   */
   public async update(
     id: number,
     owner: User,
@@ -57,6 +95,12 @@ export class CategoryService {
     return category;
   }
 
+  /**
+   * Deletes a category.
+   *
+   * @param id - The ID of the category to delete.
+   * @param owner - The owner of the category.
+   */
   public async delete(id: number, owner: User): Promise<void> {
     const category = await this.get(id, owner);
 
diff --git a/src/channel/browser.gateway.ts b/src/channel/browser.gateway.ts
index 33d34b8..61a0ee1 100644
--- a/src/channel/browser.gateway.ts
+++ b/src/channel/browser.gateway.ts
@@ -19,17 +19,34 @@ const WEB_SOCKET_OPTIONS =
     ? {}
     : { cors: { origin: process.env.FRONTEND_URL } };
 
+/**
+ * WebSocket gateway for handling browser-related operations.
+ */
 @WebSocketGateway(WEB_SOCKET_OPTIONS)
 export class BrowserGateway {
   @WebSocketServer()
   public server: Server;
 
+  /**
+   * Initializes an instance of the BrowserGateway.
+   *
+   * @param orm - The MikroORM instance.
+   * @param channels - The ChannelService instance.
+   * @param browserService - The BrowserService instance.
+   */
   constructor(
     private orm: MikroORM,
     private channels: ChannelService,
     private browserService: BrowserService,
   ) {}
 
+  /**
+   * Handles the "open-website" event, allowing a client to open a website in a browser.
+   *
+   * @param client - The connected socket client.
+   * @param payload - The message payload containing the URL to open.
+   * @returns A boolean indicating the success of opening the website.
+   */
   @SubscribeMessage('open-website')
   @UseRequestContext()
   public async openWebsite(
@@ -48,6 +65,13 @@ export class BrowserGateway {
     return true;
   }
 
+  /**
+   * Handles the "move-mouse" event, allowing a client to move the mouse in the browser.
+   *
+   * @param client - The connected socket client.
+   * @param payload - The message payload containing the coordinates to move the mouse to.
+   * @returns A boolean indicating the success of moving the mouse.
+   */
   @SubscribeMessage('move-mouse')
   @UseRequestContext()
   public async moveMouse(
@@ -61,6 +85,12 @@ export class BrowserGateway {
     return true;
   }
 
+  /**
+   * Handles the "mouse-down" event, allowing a client to simulate a mouse button press.
+   *
+   * @param client - The connected socket client.
+   * @returns A boolean indicating the success of simulating a mouse button press.
+   */
   @SubscribeMessage('mouse-down')
   @UseRequestContext()
   public async mouseDown(@ConnectedSocket() client: Socket) {
@@ -71,6 +101,12 @@ export class BrowserGateway {
     return true;
   }
 
+  /**
+   * Handles the "mouse-up" event, allowing a client to simulate a mouse button release.
+   *
+   * @param client - The connected socket client.
+   * @returns A boolean indicating the success of simulating a mouse button release.
+   */
   @SubscribeMessage('mouse-up')
   @UseRequestContext()
   public async mouseUp(@ConnectedSocket() client: Socket) {
@@ -81,6 +117,13 @@ export class BrowserGateway {
     return true;
   }
 
+  /**
+   * Handles the "key-down" event, allowing a client to simulate a keyboard key press.
+   *
+   * @param client - The connected socket client.
+   * @param payload - The message payload containing the key to press.
+   * @returns A boolean indicating the success of simulating a keyboard key press.
+   */
   @SubscribeMessage('key-down')
   @UseRequestContext()
   public async keyDown(
@@ -94,6 +137,13 @@ export class BrowserGateway {
     return true;
   }
 
+  /**
+   * Handles the "key-up" event, allowing a client to simulate releasing a keyboard key.
+   *
+   * @param client - The connected socket client.
+   * @param payload - The message payload containing the key to release.
+   * @returns A boolean indicating the success of simulating a keyboard key release.
+   */
   @SubscribeMessage('key-up')
   @UseRequestContext()
   public async keyUp(
@@ -107,6 +157,13 @@ export class BrowserGateway {
     return true;
   }
 
+  /**
+   * Handles the "scroll" event, allowing a client to simulate scrolling in the browser.
+   *
+   * @param client - The connected socket client.
+   * @param payload - The message payload containing the deltaY value for scrolling.
+   * @returns A boolean indicating the success of simulating scrolling in the browser.
+   */
   @SubscribeMessage('scroll')
   @UseRequestContext()
   public async scroll(
@@ -120,6 +177,12 @@ export class BrowserGateway {
     return true;
   }
 
+  /**
+   * Handles the "reload" event, allowing a client to simulate reloading the browser page.
+   *
+   * @param client - The connected socket client.
+   * @returns A boolean indicating the success of simulating a browser page reload.
+   */
   @SubscribeMessage('reload')
   public async reload(@ConnectedSocket() client: Socket) {
     const channel = await this.channels.fromClientOrFail(client);
@@ -129,6 +192,12 @@ export class BrowserGateway {
     return true;
   }
 
+  /**
+   * Handles the "navigate-back" event, allowing a client to simulate navigating back in the browser.
+   *
+   * @param client - The connected socket client.
+   * @returns A boolean indicating the success of simulating navigating back in the browser.
+   */
   @SubscribeMessage('navigate-back')
   public async navigateBack(@ConnectedSocket() client: Socket) {
     const channel = await this.channels.fromClientOrFail(client);
@@ -138,6 +207,12 @@ export class BrowserGateway {
     return true;
   }
 
+  /**
+   * Handles the "navigate-forward" event, allowing a client to simulate navigating forward in the browser.
+   *
+   * @param client - The connected socket client.
+   * @returns A boolean indicating the success of simulating navigating forward in the browser.
+   */
   @SubscribeMessage('navigate-forward')
   public async navigateForward(@ConnectedSocket() client: Socket) {
     const channel = await this.channels.fromClientOrFail(client);
diff --git a/src/channel/channel.gateway.spec.ts b/src/channel/channel.gateway.spec.ts
index 121aa07..8b5b7b8 100644
--- a/src/channel/channel.gateway.spec.ts
+++ b/src/channel/channel.gateway.spec.ts
@@ -12,6 +12,9 @@ describe('SocketGateway', () => {
     gateway = module.get<ChannelGateway>(ChannelGateway);
   });
 
+  /**
+   * Test to check if the ChannelGateway instance is defined.
+   */
   it('should be defined', () => {
     expect(gateway).toBeDefined();
   });
diff --git a/src/channel/channel.gateway.ts b/src/channel/channel.gateway.ts
index e7c09e0..3f24eda 100644
--- a/src/channel/channel.gateway.ts
+++ b/src/channel/channel.gateway.ts
@@ -21,6 +21,9 @@ const WEB_SOCKET_OPTIONS =
     ? {}
     : { cors: { origin: process.env.FRONTEND_URL } };
 
+/**
+ * WebSocket gateway for handling real-time communication related to channels.
+ */
 @WebSocketGateway({
   ...WEB_SOCKET_OPTIONS,
   maxHttpBufferSize: 1e8,
@@ -36,6 +39,13 @@ export class ChannelGateway implements OnGatewayConnection {
   ) {}
 
   // todo: add authentication - only a logged in teacher should be able to open a room
+  /**
+   * Handle an 'open-room' event to open a room.
+   *
+   * @param client The connected socket client.
+   * @param payload The payload containing userId and roomId.
+   * @returns The channel state.
+   */
   @SubscribeMessage('open-room')
   @UseRequestContext()
   public async openRoom(
@@ -52,6 +62,13 @@ export class ChannelGateway implements OnGatewayConnection {
     return this.channelState(channel);
   }
 
+  /**
+   * Handle a 'join-room-as-student' event to join a room as a student.
+   *
+   * @param client The connected socket client.
+   * @param payload The payload containing name, channelId, and password (optional).
+   * @returns The channel state or an error object.
+   */
   @SubscribeMessage('join-room-as-student')
   @UseRequestContext()
   public async joinChannelAsStudent(
@@ -82,6 +99,13 @@ export class ChannelGateway implements OnGatewayConnection {
     return this.channelState(channel);
   }
 
+  /**
+   * Handle a 'join-room-as-teacher' event to join a room as a teacher.
+   *
+   * @param client The connected socket client.
+   * @param payload The payload containing channelId and userId.
+   * @returns The channel state.
+   */
   @SubscribeMessage('join-room-as-teacher')
   @UseRequestContext()
   public async joinChannelAsTeacher(
@@ -139,6 +163,11 @@ export class ChannelGateway implements OnGatewayConnection {
     };
   }
 
+  /**
+   * Handle a 'leave-room' event to allow a user to leave a room.
+   *
+   * @param client The connected socket client.
+   */
   @SubscribeMessage('leave-room')
   @UseRequestContext()
   public async leaveRoom(@ConnectedSocket() client: Socket) {
@@ -150,6 +179,13 @@ export class ChannelGateway implements OnGatewayConnection {
     }
   }
 
+  /**
+   * Handle a 'change-name' event to change a user's name.
+   *
+   * @param client The connected socket client.
+   * @param payload The payload containing the new name.
+   * @returns A boolean indicating success.
+   */
   @SubscribeMessage('change-name')
   @UseRequestContext()
   public async changeName(
@@ -167,6 +203,13 @@ export class ChannelGateway implements OnGatewayConnection {
     return true;
   }
 
+  /**
+   * Handle a 'connect-webcam' event to add a webcam connection.
+   *
+   * @param client The connected socket client.
+   * @param payload The payload containing userId and peerId.
+   * @returns A boolean indicating success.
+   */
   @SubscribeMessage('connect-webcam')
   @UseRequestContext()
   public async addWebcam(
@@ -186,6 +229,13 @@ export class ChannelGateway implements OnGatewayConnection {
     return true;
   }
 
+  /**
+   * Handle an 'update-webcam' event to update webcam settings.
+   *
+   * @param client The connected socket client.
+   * @param payload The payload containing video and audio settings.
+   * @returns A boolean indicating success.
+   */
   @SubscribeMessage('update-webcam')
   @UseRequestContext()
   public async updateWebcam(
@@ -204,6 +254,13 @@ export class ChannelGateway implements OnGatewayConnection {
     return true;
   }
 
+  /**
+   * Handle an 'update-handSignal' event to update hand signal.
+   *
+   * @param client The connected socket client.
+   * @param payload The payload containing hand signal setting.
+   * @returns A boolean indicating success.
+   */
   @SubscribeMessage('update-handSignal')
   @UseRequestContext()
   public async updateHandSignal(
@@ -221,6 +278,13 @@ export class ChannelGateway implements OnGatewayConnection {
     return true;
   }
 
+  /**
+   * Handle an 'update-permission' event to update student permission.
+   *
+   * @param client The connected socket client.
+   * @param payload The payload containing studentId and permission setting.
+   * @returns A boolean indicating success.
+   */
   @SubscribeMessage('update-permission')
   @UseRequestContext()
   public async updatePermission(
@@ -238,6 +302,11 @@ export class ChannelGateway implements OnGatewayConnection {
     return true;
   }
 
+  /**
+   * Handle the connection event.
+   *
+   * @param client The connected socket client.
+   */
   public async handleConnection(client: Socket) {
     /*
      * This is a workaround for getting the client's rooms in the disconnecting event.
diff --git a/src/channel/channel.module.ts b/src/channel/channel.module.ts
index 1c171e5..0bb409e 100644
--- a/src/channel/channel.module.ts
+++ b/src/channel/channel.module.ts
@@ -6,6 +6,9 @@ import { NotesGateway } from './notes.gateway';
 import { NoteModule } from '../note/note.module';
 import { WhiteboardGateway } from './whiteboard.gateway';
 
+/**
+ * Module for handling real-time communication and operations related to channels.
+ */
 @Module({
   imports: [NoteModule],
   providers: [
diff --git a/src/channel/channel.service.ts b/src/channel/channel.service.ts
index 824b640..ed212a4 100644
--- a/src/channel/channel.service.ts
+++ b/src/channel/channel.service.ts
@@ -7,6 +7,9 @@ import { RoomService } from '../room/room.service';
 import { Room } from '../room/room.entity';
 import { BrowserService } from '../browser/browser.service';
 
+/**
+ * Service for managing channels and real-time communication.
+ */
 @Injectable()
 export class ChannelService {
   private readonly logger = new Logger(ChannelService.name);
@@ -18,6 +21,16 @@ export class ChannelService {
     private readonly browsers: BrowserService,
   ) {}
 
+  /**
+   * Opens a new channel for a teacher in a specific room.
+   *
+   * @param client - The socket client of the teacher.
+   * @param server - The socket server.
+   * @param userId - The ID of the teacher user.
+   * @param roomId - The ID of the room to open.
+   * @returns The created channel.
+   * @throws WsException if the user or room is not found.
+   */
   public async open(
     client: Socket,
     server: Server,
@@ -50,10 +63,26 @@ export class ChannelService {
     return channel;
   }
 
+  /**
+   * Checks if a channel with the given channelId exists.
+   *
+   * @param channelId - The ID of the channel to check.
+   * @returns true if the channel exists, false otherwise.
+   */
   public exists(channelId: string): boolean {
     return !!this.channels[channelId];
   }
 
+  /**
+   * Allows a student to join a channel.
+   *
+   * @param client - The socket client of the student.
+   * @param channelId - The ID of the channel to join.
+   * @param name - The name of the student.
+   * @param password - The password for the channel (if applicable).
+   * @returns The joined channel.
+   * @throws WsException if the channel is not found or password is incorrect.
+   */
   public async joinAsStudent(
     client: Socket,
     channelId: string,
@@ -78,6 +107,15 @@ export class ChannelService {
     return channel;
   }
 
+  /**
+   * Allows a teacher to join a channel.
+   *
+   * @param client - The socket client of the teacher.
+   * @param channelId - The ID of the channel to join.
+   * @param userId - The ID of the teacher user.
+   * @returns The joined channel.
+   * @throws WsException if the channel is not found or user is not found.
+   */
   public async joinAsTeacher(
     client: Socket,
     channelId: string,
@@ -103,6 +141,12 @@ export class ChannelService {
     return channel;
   }
 
+  /**
+   * Handles the process of a client leaving a channel.
+   *
+   * @param client - The socket client leaving the channel.
+   * @param channelId - The ID of the channel to leave.
+   */
   public async leave(client: Socket, channelId: string) {
     const channel = this.channels[channelId];
 
@@ -132,6 +176,13 @@ export class ChannelService {
     }
   }
 
+  /**
+   * Gets a channel associated with the given socket client.
+   *
+   * @param client - The socket client.
+   * @returns The associated channel.
+   * @throws WsException if the channel is not found.
+   */
   public fromClientOrFail(client: Socket): Channel {
     for (const room of client.rooms) {
       if (this.channels[room]) {
@@ -142,6 +193,14 @@ export class ChannelService {
     throw new WsException('Channel not found');
   }
 
+  /**
+   * Retrieves the other client's socket associated with the given client and ID.
+   *
+   * @param client - The socket client.
+   * @param otherId - The ID of the other client.
+   * @returns The other client's socket.
+   * @throws WsException if the channel is not found.
+   */
   public async getOtherClient(
     client: Socket,
     otherId: string,
@@ -151,6 +210,12 @@ export class ChannelService {
     return channel.getUser(otherId).client;
   }
 
+  /**
+   * Retrieves the channel associated with the given room.
+   *
+   * @param room - The room entity.
+   * @returns The associated channel.
+   */
   public getChannelFromRoom(room: Room): Channel {
     for (const channel of Object.values(this.channels)) {
       if (channel.room.id === room.id) {
diff --git a/src/channel/channel.ts b/src/channel/channel.ts
index 783c8d4..f770dae 100644
--- a/src/channel/channel.ts
+++ b/src/channel/channel.ts
@@ -19,6 +19,9 @@ export interface Student extends ChannelUser {
   permission: boolean;
 }
 
+/**
+ * Represents a channel for a room in the application.
+ */
 export class Channel {
   public teacher?: Teacher;
   private closeTimeout: NodeJS.Timeout;
@@ -27,6 +30,13 @@ export class Channel {
 
   public canvasJSON: string;
 
+  /**
+   * Creates a new Channel instance.
+   *
+   * @param room - The room associated with the channel.
+   * @param server - The socket server instance.
+   * @param id - The ID of the channel.
+   */
   constructor(
     public readonly room: Room,
     public readonly server: Server,
@@ -35,6 +45,12 @@ export class Channel {
     this.canvasJSON = room.whiteboardCanvas?.toString();
   }
 
+  /**
+   * Joins a client as a student to the channel.
+   *
+   * @param client - The client socket.
+   * @param name - The name of the student.
+   */
   public async joinAsStudent(client: Socket, name: string) {
     await client.join(this.id);
 
@@ -57,6 +73,12 @@ export class Channel {
     });
   }
 
+  /**
+   * Joins a client as a teacher to the channel.
+   *
+   * @param client - The client socket.
+   * @param user - The teacher's user object.
+   */
   public async joinAsTeacher(client: Socket, user: User) {
     if (this.teacher) {
       await this.leaveAsTeacher(this.teacher.client);
@@ -73,6 +95,11 @@ export class Channel {
     });
   }
 
+  /**
+   * Removes the teacher from the channel.
+   *
+   * @param client - The client socket of the teacher.
+   */
   public async leaveAsTeacher(client: Socket) {
     await client.leave(this.id);
     this.teacher = undefined;
@@ -80,6 +107,11 @@ export class Channel {
     client.broadcast.to(this.id).emit('teacher-left', {});
   }
 
+  /**
+   * Removes a student from the channel.
+   *
+   * @param client - The client socket of the student.
+   */
   public async leaveAsStudent(client: Socket) {
     const student = this.students.get(client.id);
 
@@ -92,14 +124,29 @@ export class Channel {
     }
   }
 
+  /**
+   * Checks if the channel is empty (no teacher or students).
+   *
+   * @returns `true` if the channel is empty, `false` otherwise.
+   */
   public isEmpty(): boolean {
     return !this.teacher && this.students.size === 0;
   }
 
+  /**
+   * Notifies the server that the room is closing.
+   */
   public close() {
     this.server.emit('room-closed', this.room.id);
   }
 
+  /**
+   * Gets the user (teacher or student) associated with the given client ID.
+   *
+   * @param clientId - The ID of the client.
+   * @returns The user object (teacher or student).
+   * @throws `WsException` if the user is not found.
+   */
   public getUser(clientId: string): Teacher | Student {
     if (this.teacher && this.teacher.client.id === clientId) {
       return this.teacher;
@@ -114,6 +161,13 @@ export class Channel {
     throw new WsException(`User not found in ${this}`);
   }
 
+  /**
+   * Gets the student associated with the given client ID.
+   *
+   * @param clientId - The ID of the client.
+   * @returns The student object.
+   * @throws `WsException` if the student is not found.
+   */
   public getStudent(clientId: string): Student {
     const student = this.students.get(clientId);
 
@@ -124,6 +178,12 @@ export class Channel {
     throw new WsException(`User not found in ${this}`);
   }
 
+  /**
+   * Changes the name of a student.
+   *
+   * @param client - The client socket of the student.
+   * @param name - The new name.
+   */
   public changeName(client: Socket, name: string) {
     const student = this.students.get(client.id);
 
@@ -132,6 +192,13 @@ export class Channel {
     }
   }
 
+  /**
+   * Updates the webcam settings of a user (teacher or student).
+   *
+   * @param client - The client socket of the user.
+   * @param video - The new video setting.
+   * @param audio - The new audio setting.
+   */
   public updateWebcam(client: Socket, video: boolean, audio: boolean) {
     const user = this.getUser(client.id);
 
@@ -141,6 +208,12 @@ export class Channel {
     }
   }
 
+  /**
+   * Updates the hand signal setting of a student.
+   *
+   * @param client - The client socket of the student.
+   * @param handSignal - The new hand signal setting.
+   */
   public updateHandSignal(client: Socket, handSignal: boolean) {
     const student = this.getStudent(client.id);
 
@@ -149,6 +222,12 @@ export class Channel {
     }
   }
 
+  /**
+   * Updates the permission setting of a student.
+   *
+   * @param studentId - The ID of the student.
+   * @param permission - The new permission setting.
+   */
   public updatePermission(studentId: string, permission: boolean) {
     const student = this.getStudent(studentId);
 
@@ -157,10 +236,18 @@ export class Channel {
     }
   }
 
+  /**
+   * Returns a string representation of the channel.
+   *
+   * @returns The string representation.
+   */
   public toString(): string {
     return `Channel{${this.id}}`;
   }
 
+  /**
+   * Clears the close timeout if set.
+   */
   public clearCloseTimeout() {
     if (this.closeTimeout) {
       clearTimeout(this.closeTimeout);
@@ -168,6 +255,11 @@ export class Channel {
     }
   }
 
+  /**
+   * Sets a timeout to close the channel if it becomes empty after a period of time.
+   *
+   * @param onTimeout - The callback function to be executed when the timeout triggers.
+   */
   public setCloseTimeout(onTimeout: () => void) {
     this.clearCloseTimeout();
     this.closeTimeout = setTimeout(() => {
diff --git a/src/channel/notes.gateway.ts b/src/channel/notes.gateway.ts
index 0833a3a..e604429 100644
--- a/src/channel/notes.gateway.ts
+++ b/src/channel/notes.gateway.ts
@@ -18,17 +18,32 @@ const WEB_SOCKET_OPTIONS =
     ? {}
     : { cors: { origin: process.env.FRONTEND_URL } };
 
+/**
+ * WebSocket gateway for managing notes-related communication.
+ */
 @WebSocketGateway(WEB_SOCKET_OPTIONS)
 export class NotesGateway {
   @WebSocketServer()
   public server: Server;
 
+  /**
+   * Constructor of NotesGateway.
+   * @param orm - MikroORM instance for database interactions.
+   * @param channels - Instance of ChannelService for managing channels.
+   * @param notes - Instance of NoteService for managing notes.
+   */
   constructor(
     private orm: MikroORM,
     private channels: ChannelService,
     private notes: NoteService,
   ) {}
 
+  /**
+   * Subscribe to the 'add-note' event to add a new note.
+   * @param client - The connected socket client.
+   * @param payload - The message body containing the note's name.
+   * @returns The newly added note.
+   */
   @SubscribeMessage('add-note')
   @UseRequestContext()
   public async addNote(
@@ -43,6 +58,12 @@ export class NotesGateway {
     return note;
   }
 
+  /**
+   * Subscribe to the 'update-note' event to update an existing note.
+   * @param client - The connected socket client.
+   * @param payload - The message body containing the note's ID and updated content.
+   * @returns `true` if the note was successfully updated.
+   */
   @SubscribeMessage('update-note')
   @UseRequestContext()
   public async updateNote(
@@ -60,6 +81,12 @@ export class NotesGateway {
     return true;
   }
 
+  /**
+   * Subscribe to the 'delete-note' event to delete a note.
+   * @param client - The connected socket client.
+   * @param payload - The message body containing the note's ID.
+   * @returns `true` if the note was successfully deleted.
+   */
   @SubscribeMessage('delete-note')
   @UseRequestContext()
   public async deleteNote(
diff --git a/src/channel/whiteboard.gateway.ts b/src/channel/whiteboard.gateway.ts
index cf17b98..ed324d4 100644
--- a/src/channel/whiteboard.gateway.ts
+++ b/src/channel/whiteboard.gateway.ts
@@ -16,13 +16,25 @@ const WEB_SOCKET_OPTIONS =
     ? {}
     : { cors: { origin: process.env.FRONTEND_URL } };
 
+/**
+ * WebSocket gateway for handling whiteboard-related communication.
+ */
 @WebSocketGateway(WEB_SOCKET_OPTIONS)
 export class WhiteboardGateway {
   @WebSocketServer()
   public server: Server;
 
+  /**
+   * Constructor of WhiteboardGateway.
+   * @param channels - Instance of ChannelService for managing channels.
+   */
   constructor(private channels: ChannelService) {}
 
+  /**
+   * Subscribe to the 'whiteboard-change' event to handle whiteboard canvas changes.
+   * @param client - The connected socket client.
+   * @param payload - The message body containing the updated canvas JSON.
+   */
   @SubscribeMessage('whiteboard-change')
   public async whiteboardChange(
     @ConnectedSocket() client: Socket,
@@ -30,8 +42,10 @@ export class WhiteboardGateway {
   ) {
     const channel = await this.channels.fromClientOrFail(client);
 
+    // Update the canvas JSON in the channel's data
     channel.canvasJSON = payload.canvas;
 
+    // Broadcast the whiteboard change to all clients in the channel
     client.broadcast.to(channel.id).emit('whiteboard-change', payload);
   }
 }
diff --git a/src/common/constraints/exists.ts b/src/common/constraints/exists.ts
index 7ff4f64..8b1e7ce 100644
--- a/src/common/constraints/exists.ts
+++ b/src/common/constraints/exists.ts
@@ -8,6 +8,11 @@ import {
 import { Injectable } from '@nestjs/common';
 import { EntityManager } from '@mikro-orm/core';
 
+/**
+ * Custom validation decorator that checks if an entity with the given ID exists in the database.
+ * @param entityType - The entity type to check existence for.
+ * @param options - Validation options.
+ */
 export function Exists(entityType: object, options?: ValidationOptions) {
   return (object: any, propertyName: string) => {
     registerDecorator({
@@ -20,7 +25,7 @@ export function Exists(entityType: object, options?: ValidationOptions) {
   };
 }
 
-/*
+/**
  * This constraint checks if an entity with the given id exists.
  *
  * The given id must be a string, if it is a number, 0 will be considered as an empty value.
@@ -30,6 +35,12 @@ export function Exists(entityType: object, options?: ValidationOptions) {
 export class ExistsConstraint implements ValidatorConstraintInterface {
   constructor(private readonly em: EntityManager) {}
 
+  /**
+   * Validate if an entity with the given ID exists in the database.
+   * @param value - The ID of the entity to check.
+   * @param args - Validation arguments.
+   * @returns A boolean indicating whether the entity exists.
+   */
   async validate(value: string, args: ValidationArguments): Promise<boolean> {
     if (!value) {
       // if the value is empty, we don't want to
diff --git a/src/common/constraints/match.ts b/src/common/constraints/match.ts
index d12afd6..7fef4c2 100644
--- a/src/common/constraints/match.ts
+++ b/src/common/constraints/match.ts
@@ -6,6 +6,11 @@ import {
   ValidatorConstraintInterface,
 } from 'class-validator';
 
+/**
+ * Custom validation decorator that checks if a property matches another property in the object.
+ * @param property - The name of the related property to compare with.
+ * @param options - Validation options.
+ */
 export function Match(property: string, options?: ValidationOptions) {
   return (object: any, propertyName: string) => {
     registerDecorator({
@@ -18,8 +23,17 @@ export function Match(property: string, options?: ValidationOptions) {
   };
 }
 
+/**
+ * ValidatorConstraint that checks if a property matches another property in the object.
+ */
 @ValidatorConstraint({ name: 'Match' })
 export class MatchConstraint implements ValidatorConstraintInterface {
+  /**
+   * Validate if a property matches another property in the object.
+   * @param value - The value of the property to validate.
+   * @param args - Validation arguments.
+   * @returns A boolean indicating whether the properties match.
+   */
   validate(value: any, args: ValidationArguments) {
     const [relatedPropertyName] = args.constraints;
     const relatedValue = (args.object as any)[relatedPropertyName];
diff --git a/src/common/constraints/unique.ts b/src/common/constraints/unique.ts
index 967c76c..e15dc7a 100644
--- a/src/common/constraints/unique.ts
+++ b/src/common/constraints/unique.ts
@@ -8,6 +8,11 @@ import {
 import { Injectable } from '@nestjs/common';
 import { EntityManager } from '@mikro-orm/core';
 
+/**
+ * Custom validation decorator that checks if a property value is unique within the specified entity.
+ * @param entityType - The entity type to check for uniqueness.
+ * @param options - Validation options.
+ */
 export function IsUnique(entityType: object, options?: ValidationOptions) {
   return (object: any, propertyName: string) => {
     registerDecorator({
@@ -20,11 +25,24 @@ export function IsUnique(entityType: object, options?: ValidationOptions) {
   };
 }
 
+/**
+ * ValidatorConstraint that checks if a property value is unique within the specified entity.
+ */
 @ValidatorConstraint({ name: 'IsUnique', async: true })
 @Injectable()
 export class IsUniqueConstraint implements ValidatorConstraintInterface {
+  /**
+   * Constructor that injects the EntityManager.
+   * @param em - The EntityManager instance.
+   */
   constructor(private readonly em: EntityManager) {}
 
+  /**
+   * Validate if a property value is unique within the specified entity.
+   * @param value - The value of the property to validate.
+   * @param args - Validation arguments.
+   * @returns A boolean indicating whether the property value is unique.
+   */
   async validate(value: any, args: ValidationArguments): Promise<boolean> {
     const [entityType] = args.constraints;
 
diff --git a/src/common/guards/admin.guard.ts b/src/common/guards/admin.guard.ts
index 7e97609..f8161b2 100644
--- a/src/common/guards/admin.guard.ts
+++ b/src/common/guards/admin.guard.ts
@@ -6,10 +6,23 @@ import {
 } from '@nestjs/common';
 import { AuthService } from '../../auth/auth.service';
 
+/**
+ * Guard that checks if the user has the 'admin' role.
+ */
 @Injectable()
 export class AdminGuard implements CanActivate {
+  /**
+   * Constructor that injects the AuthService.
+   * @param auth - The AuthService instance.
+   */
   constructor(private auth: AuthService) {}
 
+  /**
+   * Determine whether the user has the 'admin' role and is authorized.
+   * @param context - The execution context.
+   * @returns A boolean indicating whether the user is authorized as an admin.
+   * @throws UnauthorizedException if the user is not authorized.
+   */
   async canActivate(context: ExecutionContext): Promise<boolean> {
     const user = await this.auth.user();
 
diff --git a/src/common/not-found.interceptor.ts b/src/common/not-found.interceptor.ts
index f1a9542..e3ca8b0 100644
--- a/src/common/not-found.interceptor.ts
+++ b/src/common/not-found.interceptor.ts
@@ -8,12 +8,20 @@ import {
 import { catchError, Observable } from 'rxjs';
 import { NotFoundError } from '@mikro-orm/core';
 
-/*
+/**
  * This interceptor catches any NotFoundError thrown by MikroORM and
  * rethrows it as a NotFoundException.
  */
 @Injectable()
 export class NotFoundInterceptor implements NestInterceptor {
+  /**
+   * Intercepts the incoming observable stream of data.
+   * @param context - The execution context.
+   * @param next - The next handler in the chain.
+   * @returns An observable stream of data.
+   * @throws NotFoundException if a NotFoundError is caught.
+   * @throws Any other error that is not a NotFoundError.
+   */
   intercept(
     context: ExecutionContext,
     next: CallHandler<any>,
diff --git a/src/main.ts b/src/main.ts
index a32ee08..80d47bc 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -9,9 +9,13 @@ import {
 import { useContainer } from 'class-validator';
 import { NotFoundInterceptor } from './common/not-found.interceptor';
 
+/**
+ * Bootstrap function to initialize the NestJS application.
+ */
 async function bootstrap() {
   const app = await NestFactory.create(AppModule);
 
+  // Enable CORS in development environment
   if (process.env.NODE_ENV === 'development') {
     app.enableCors({
       origin: [process.env.FRONTEND_URL],
@@ -19,10 +23,19 @@ async function bootstrap() {
     });
   }
 
+  // Set global prefix for API routes
   app.setGlobalPrefix('api/v1');
+
+  // Configure cookie parser middleware
   app.use(cookieParser(process.env.COOKIE_PARSER_SECRET));
+
+  // Configure global validation pipe
   app.useGlobalPipes(new ValidationPipe({ exceptionFactory }));
+
+  // Attach global interceptor for handling not found errors
   app.useGlobalInterceptors(new NotFoundInterceptor());
+
+  // Enable shutdown hooks for graceful shutdown
   app.enableShutdownHooks();
 
   // allows us to use NestJS DI in class-validator custom decorators
@@ -33,7 +46,7 @@ async function bootstrap() {
 
 bootstrap();
 
-/*
+/**
  * The existing factory function returns an array of errors without
  * associating these errors with their respective properties.
  *
diff --git a/src/mikro-orm.config.ts b/src/mikro-orm.config.ts
index e9460fc..9608d15 100644
--- a/src/mikro-orm.config.ts
+++ b/src/mikro-orm.config.ts
@@ -2,19 +2,31 @@ import { defineConfig } from '@mikro-orm/mysql';
 import * as process from 'process';
 import { TsMorphMetadataProvider } from '@mikro-orm/reflection';
 
+/**
+ * MikroORM configuration object for MySQL.
+ */
 export default defineConfig({
+  // Database connection parameters
   host: process.env.DB_HOST,
   port: +process.env.DB_PORT,
   user: process.env.DB_USER,
   password: process.env.DB_PASSWORD,
   dbName: process.env.DB_NAME,
+
+  // Entity paths for JavaScript and TypeScript files
   entities: ['dist/**/*.entity.js'],
   entitiesTs: ['src/**/*.entity.ts'],
+
+  // Metadata provider using TsMorph
   metadataProvider: TsMorphMetadataProvider,
+
+  // Migration paths for JavaScript and TypeScript files
   migrations: {
     path: 'dist/database/migrations',
     pathTs: 'database/migrations',
   },
+
+  // Seeder paths for JavaScript and TypeScript files
   seeder: {
     path: 'dist/database/seeders',
     pathTs: 'database/seeders',
diff --git a/src/note/note.entity.ts b/src/note/note.entity.ts
index efbe677..638da5c 100644
--- a/src/note/note.entity.ts
+++ b/src/note/note.entity.ts
@@ -7,6 +7,9 @@ import {
 } from '@mikro-orm/core';
 import { Room } from '../room/room.entity';
 
+/**
+ * Represents a Note entity that is associated with a Room.
+ */
 @Entity({ tableName: 'notes' })
 export class Note {
   @PrimaryKey()
@@ -27,6 +30,11 @@ export class Note {
   @ManyToOne({ onDelete: 'cascade', hidden: true })
   room: Room;
 
+  /**
+   * Creates a new instance of the Note entity.
+   * @param name - The name of the note.
+   * @param room - The associated Room entity.
+   */
   constructor(name: string, room: Room) {
     this.name = name;
     this.room = room;
diff --git a/src/note/note.module.ts b/src/note/note.module.ts
index cc4e2a5..162ecd3 100644
--- a/src/note/note.module.ts
+++ b/src/note/note.module.ts
@@ -3,6 +3,9 @@ import { NoteService } from './note.service';
 import { MikroOrmModule } from '@mikro-orm/nestjs';
 import { Note } from './note.entity';
 
+/**
+ * A global module that encapsulates features related to notes.
+ */
 @Global()
 @Module({
   imports: [MikroOrmModule.forFeature([Note])],
diff --git a/src/note/note.service.ts b/src/note/note.service.ts
index 164dfea..717702f 100644
--- a/src/note/note.service.ts
+++ b/src/note/note.service.ts
@@ -5,20 +5,41 @@ import { Note } from './note.entity';
 import { EntityRepository } from '@mikro-orm/mysql';
 import { Room } from '../room/room.entity';
 
+/**
+ * A service responsible for managing notes.
+ */
 @Injectable()
 export class NoteService {
+  /**
+   * Initializes the NoteService.
+   * @param em - The EntityManager instance provided by MikroORM.
+   * @param repository - The repository for the Note entity.
+   */
   constructor(
     private readonly em: EntityManager,
     @InjectRepository(Note)
     private readonly repository: EntityRepository<Note>,
   ) {}
 
+  /**
+   * Adds a new note to the specified room.
+   * @param room - The room in which the note will be added.
+   * @param name - The name of the note.
+   * @returns The newly created Note entity.
+   */
   public async addNote(room: Room, name: string) {
     const note = new Note(name, room);
     await this.em.persistAndFlush(note);
     return note;
   }
 
+  /**
+   * Updates the content of a note with the specified ID.
+   * @param id - The ID of the note to update.
+   * @param content - The new content for the note.
+   * @returns The updated Note entity.
+   * @throws EntityNotFoundException if the note with the given ID does not exist.
+   */
   public async updateNote(id: number, content: string) {
     const note = await this.repository.findOneOrFail({ id });
     note.content = content;
@@ -26,6 +47,12 @@ export class NoteService {
     return note;
   }
 
+  /**
+   * Deletes a note with the specified ID.
+   * @param id - The ID of the note to delete.
+   * @returns `true` if the note was successfully deleted.
+   * @throws EntityNotFoundException if the note with the given ID does not exist.
+   */
   public async deleteNoteById(id: number) {
     const note = await this.repository.findOneOrFail({ id });
     await this.em.removeAndFlush(note);
diff --git a/src/room/room.controller.spec.ts b/src/room/room.controller.spec.ts
index b12398d..cf7299b 100644
--- a/src/room/room.controller.spec.ts
+++ b/src/room/room.controller.spec.ts
@@ -1,9 +1,15 @@
 import { Test, TestingModule } from '@nestjs/testing';
 import { RoomController } from './room.controller';
 
+/**
+ * Test suite for the RoomController class.
+ */
 describe('RoomController', () => {
   let controller: RoomController;
 
+  /**
+   * Before each test, create a testing module with RoomController as the controller.
+   */
   beforeEach(async () => {
     const module: TestingModule = await Test.createTestingModule({
       controllers: [RoomController],
@@ -12,6 +18,9 @@ describe('RoomController', () => {
     controller = module.get<RoomController>(RoomController);
   });
 
+  /**
+   * Test if the controller is defined.
+   */
   it('should be defined', () => {
     expect(controller).toBeDefined();
   });
diff --git a/src/room/room.controller.ts b/src/room/room.controller.ts
index 757506e..c98aa65 100644
--- a/src/room/room.controller.ts
+++ b/src/room/room.controller.ts
@@ -14,6 +14,9 @@ import { RoomService } from './room.service';
 import { AuthService } from '../auth/auth.service';
 import { CategoryService } from '../category/category.service';
 
+/**
+ * Controller responsible for handling room-related endpoints.
+ */
 @Controller('category/:category/room')
 export class RoomController {
   constructor(
@@ -22,6 +25,13 @@ export class RoomController {
     private readonly auth: AuthService,
   ) {}
 
+  /**
+   * Create a new room within a category.
+   *
+   * @param categoryId - The ID of the category.
+   * @param data - The data for creating a room.
+   * @returns The created room.
+   */
   @Post('/')
   @UseGuards(AuthGuard)
   public async create(
@@ -33,6 +43,14 @@ export class RoomController {
     return this.rooms.create(data.name, category, data.password);
   }
 
+  /**
+   * Update an existing room within a category.
+   *
+   * @param categoryId - The ID of the category.
+   * @param roomId - The ID of the room to be updated.
+   * @param data - The updated room data.
+   * @returns The updated room.
+   */
   @Put('/:room')
   @UseGuards(AuthGuard)
   public async update(
@@ -45,6 +63,13 @@ export class RoomController {
     return this.rooms.update(roomId, category, data.name);
   }
 
+  /**
+   * Delete a room within a category.
+   *
+   * @param categoryId - The ID of the category.
+   * @param roomId - The ID of the room to be deleted.
+   * @returns A boolean indicating if the deletion was successful.
+   */
   @Delete('/:room')
   @UseGuards(AuthGuard)
   public async delete(
@@ -56,6 +81,13 @@ export class RoomController {
     return this.rooms.delete(roomId, category);
   }
 
+  /**
+   * Get notes associated with a room.
+   *
+   * @param categoryId - The ID of the category.
+   * @param roomId - The ID of the room.
+   * @returns Notes associated with the specified room.
+   */
   @Get('/:room/notes')
   public async getNotes(
     @Param('category') categoryId: number,
diff --git a/src/room/room.dto.ts b/src/room/room.dto.ts
index 686da3d..c0a23d2 100644
--- a/src/room/room.dto.ts
+++ b/src/room/room.dto.ts
@@ -1,5 +1,8 @@
 import { IsNotEmpty } from 'class-validator';
 
+/**
+ * Data transfer object for creating a room.
+ */
 export class CreateRoom {
   @IsNotEmpty({
     message: 'Name darf nicht leer sein',
@@ -9,4 +12,7 @@ export class CreateRoom {
   password?: string;
 }
 
+/**
+ * Data transfer object for updating a room (inherits from CreateRoom).
+ */
 export class UpdateRoom extends CreateRoom {}
diff --git a/src/room/room.entity.ts b/src/room/room.entity.ts
index b79b6ef..928cf9a 100644
--- a/src/room/room.entity.ts
+++ b/src/room/room.entity.ts
@@ -10,6 +10,9 @@ import {
 import { Category } from '../category/category.entity';
 import { Note } from '../note/note.entity';
 
+/**
+ * Represents a room entity.
+ */
 @Entity({ tableName: 'rooms' })
 export class Room {
   @PrimaryKey()
@@ -39,12 +42,21 @@ export class Room {
   @Property({ type: types.blob, nullable: true })
   whiteboardCanvas?;
 
+  /**
+   * Creates a new instance of the Room class.
+   * @param name - The name of the room.
+   * @param category - The category that the room belongs to.
+   * @param password - The password for the room (optional).
+   */
   constructor(name: string, category: Category, password?: string) {
     this.name = name;
     this.category = category;
     this.password = password;
   }
 
+  /**
+   * Returns a string representation of the room.
+   */
   public toString(): string {
     return `Room{${this.id}: "${this.name}"}`;
   }
diff --git a/src/room/room.module.ts b/src/room/room.module.ts
index 9c448f7..bdd1c86 100644
--- a/src/room/room.module.ts
+++ b/src/room/room.module.ts
@@ -4,6 +4,9 @@ import { RoomController } from './room.controller';
 import { MikroOrmModule } from '@mikro-orm/nestjs';
 import { Room } from './room.entity';
 
+/**
+ * Represents a global module for managing rooms.
+ */
 @Global()
 @Module({
   imports: [MikroOrmModule.forFeature([Room])],
diff --git a/src/room/room.service.spec.ts b/src/room/room.service.spec.ts
index 504502b..cd60d73 100644
--- a/src/room/room.service.spec.ts
+++ b/src/room/room.service.spec.ts
@@ -1,9 +1,15 @@
 import { Test, TestingModule } from '@nestjs/testing';
 import { RoomService } from './room.service';
 
+/**
+ * Test suite for the `RoomService` class.
+ */
 describe('RoomService', () => {
   let service: RoomService;
 
+  /**
+   * Initialize the testing module and get an instance of `RoomService`.
+   */
   beforeEach(async () => {
     const module: TestingModule = await Test.createTestingModule({
       providers: [RoomService],
@@ -12,6 +18,9 @@ describe('RoomService', () => {
     service = module.get<RoomService>(RoomService);
   });
 
+  /**
+   * Test case to ensure that the `RoomService` instance is defined.
+   */
   it('should be defined', () => {
     expect(service).toBeDefined();
   });
diff --git a/src/room/room.service.ts b/src/room/room.service.ts
index ae8957f..d4169fb 100644
--- a/src/room/room.service.ts
+++ b/src/room/room.service.ts
@@ -6,6 +6,9 @@ import { EntityRepository } from '@mikro-orm/mysql';
 import { Category } from '../category/category.entity';
 import { Note } from '../note/note.entity';
 
+/**
+ * Service responsible for managing room entities.
+ */
 @Injectable()
 export class RoomService {
   constructor(
@@ -14,14 +17,32 @@ export class RoomService {
     private readonly repository: EntityRepository<Room>,
   ) {}
 
+  /**
+   * Get a room by its ID and category.
+   * @param id - The ID of the room.
+   * @param category - The category of the room.
+   * @returns The retrieved room.
+   */
   public async get(id: number, category: Category): Promise<Room> {
     return this.repository.findOneOrFail({ id, category });
   }
 
+  /**
+   * Find a room with its associated category.
+   * @param id - The ID of the room.
+   * @returns The retrieved room with its category.
+   */
   public async findOneWithCategory(id: number): Promise<Room | null> {
     return this.repository.findOne({ id }, { populate: ['category'] });
   }
 
+  /**
+   * Create a new room.
+   * @param name - The name of the room.
+   * @param category - The category of the room.
+   * @param password - The optional password for the room.
+   * @returns The created room.
+   */
   public async create(
     name: string,
     category: Category,
@@ -33,6 +54,13 @@ export class RoomService {
     return room;
   }
 
+  /**
+   * Update the name of a room.
+   * @param id - The ID of the room.
+   * @param category - The category of the room.
+   * @param name - The new name for the room.
+   * @returns The updated room.
+   */
   public async update(
     id: number,
     category: Category,
@@ -47,17 +75,33 @@ export class RoomService {
     return room;
   }
 
+  /**
+   * Delete a room.
+   * @param id - The ID of the room.
+   * @param category - The category of the room.
+   */
   public async delete(id: number, category: Category): Promise<void> {
     const room = await this.get(id, category);
 
     await this.em.removeAndFlush(room);
   }
 
+  /**
+   * Get the notes associated with a room.
+   * @param id - The ID of the room.
+   * @returns An array of notes belonging to the room.
+   */
   public async getNotes(id: number): Promise<Note[]> {
     const room = await this.repository.findOneOrFail({ id });
     return room.notes.loadItems();
   }
 
+  /**
+   * Update the whiteboard canvas of a room.
+   * @param id - The ID of the room.
+   * @param canvas - The new whiteboard canvas content.
+   * @returns The updated room.
+   */
   public async updateWhiteboard(id: number, canvas: string): Promise<Room> {
     const room = await this.repository.findOneOrFail({ id });
 
diff --git a/src/user/user.controller.spec.ts b/src/user/user.controller.spec.ts
index 7057a1a..07e8ac9 100644
--- a/src/user/user.controller.spec.ts
+++ b/src/user/user.controller.spec.ts
@@ -1,18 +1,32 @@
 import { Test, TestingModule } from '@nestjs/testing';
 import { UserController } from './user.controller';
 
+/**
+ * Test suite to verify the behavior of the UserController.
+ */
 describe('UserController', () => {
   let controller: UserController;
 
+  /**
+   * Before each test case, create a testing module with UserController.
+   * Compile the module and obtain an instance of UserController.
+   * This ensures a fresh instance is available for each test case.
+   */
   beforeEach(async () => {
     const module: TestingModule = await Test.createTestingModule({
       controllers: [UserController],
     }).compile();
 
+    // Obtain an instance of UserController from the module
     controller = module.get<UserController>(UserController);
   });
 
+  /**
+   * Test case: Ensure that UserController is defined.
+   * This test validates that the controller instance was created successfully.
+   */
   it('should be defined', () => {
+    // Assertion to check if controller is defined
     expect(controller).toBeDefined();
   });
 });
diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts
index 682b1af..cdef063 100644
--- a/src/user/user.controller.ts
+++ b/src/user/user.controller.ts
@@ -16,6 +16,9 @@ import { AuthService } from '../auth/auth.service';
 import { ChangePassword } from '../auth/auth.dto';
 import * as bcrypt from 'bcrypt';
 
+/**
+ * Interface representing user data for editing.
+ */
 export type EditUser = {
   id: number;
   organization: string;
@@ -23,6 +26,9 @@ export type EditUser = {
   email: string;
 };
 
+/**
+ * Controller managing user-related routes and operations.
+ */
 @Controller('user')
 export class UserController {
   constructor(
@@ -30,24 +36,43 @@ export class UserController {
     private readonly authService: AuthService,
   ) {}
 
+  /**
+   * Retrieve a list of all users.
+   * Requires authentication and admin privilege.
+   */
   @UseGuards(AuthGuard, AdminGuard)
   @Get('findAll')
   public async findAll() {
     return await this.userService.findAll();
   }
 
+  /**
+   * Change the role of a user.
+   * Requires authentication and admin privilege.
+   * @param data - Object containing the ID of the user.
+   */
   @UseGuards(AuthGuard, AdminGuard)
   @Post('changeRole')
   public async changeRole(@Body() data: { id: number }) {
     return await this.userService.changeRole(data.id);
   }
 
+  /**
+   * Update user data.
+   * Requires authentication.
+   * @param data - Object containing updated user data.
+   */
   @UseGuards(AuthGuard)
   @Put('changeUserData')
   public async changeUserData(@Body() data: EditUser): Promise<boolean> {
     return this.userService.changeUserData(data);
   }
 
+  /**
+   * Delete a user by ID.
+   * Requires authentication and admin privilege.
+   * @param userId - ID of the user to delete.
+   */
   @UseGuards(AuthGuard, AdminGuard)
   @Delete('/:userId')
   public async delete(@Param('userId') userId: number) {
@@ -56,6 +81,11 @@ export class UserController {
     return { message: 'success' };
   }
 
+  /**
+   * Change user password.
+   * Requires authentication.
+   * @param data - Object containing current and new passwords.
+   */
   @UseGuards(AuthGuard)
   @Post('changePassword')
   public async changePassword(@Body() data: ChangePassword) {
diff --git a/src/user/user.entity.ts b/src/user/user.entity.ts
index a9e0983..8fc6ad0 100644
--- a/src/user/user.entity.ts
+++ b/src/user/user.entity.ts
@@ -7,6 +7,9 @@ import {
 } from '@mikro-orm/core';
 import { Category } from '../category/category.entity';
 
+/**
+ * Entity representing a user.
+ */
 @Entity({ tableName: 'users' })
 export class User {
   @PrimaryKey()
@@ -36,6 +39,13 @@ export class User {
   @Property()
   role: 'user' | 'admin' = 'user';
 
+  /**
+   * Constructor to create a new User instance.
+   * @param name - The user's name.
+   * @param email - The user's email.
+   * @param organization - The user's organization.
+   * @param password - The user's password.
+   */
   constructor(
     name: string,
     email: string,
@@ -48,6 +58,10 @@ export class User {
     this.password = password;
   }
 
+  /**
+   * Get a string representation of the user.
+   * @returns A string containing user ID and name.
+   */
   public toString(): string {
     return `User{${this.id}: "${this.name}"}`;
   }
diff --git a/src/user/user.module.ts b/src/user/user.module.ts
index 6ec7ba9..fd3e7d2 100644
--- a/src/user/user.module.ts
+++ b/src/user/user.module.ts
@@ -4,6 +4,9 @@ import { MikroOrmModule } from '@mikro-orm/nestjs';
 import { User } from './user.entity';
 import { UserController } from './user.controller';
 
+/**
+ * Global module providing user-related functionality.
+ */
 @Global()
 @Module({
   imports: [MikroOrmModule.forFeature([User])],
diff --git a/src/user/user.service.spec.ts b/src/user/user.service.spec.ts
index 873de8a..ea9119a 100644
--- a/src/user/user.service.spec.ts
+++ b/src/user/user.service.spec.ts
@@ -1,18 +1,31 @@
 import { Test, TestingModule } from '@nestjs/testing';
 import { UserService } from './user.service';
 
+/**
+ * Test suite for UserService.
+ */
 describe('UserService', () => {
   let service: UserService;
 
+  /**
+   * Before each test case, create a testing module and compile it.
+   * Obtain an instance of UserService for testing.
+   */
   beforeEach(async () => {
+    // Create a testing module
     const module: TestingModule = await Test.createTestingModule({
       providers: [UserService],
     }).compile();
 
+    // Obtain an instance of UserService from the module
     service = module.get<UserService>(UserService);
   });
 
+  /**
+   * Test case to verify that UserService is defined.
+   */
   it('should be defined', () => {
+    // Assertion to check if service is defined
     expect(service).toBeDefined();
   });
 });
diff --git a/src/user/user.service.ts b/src/user/user.service.ts
index 028452e..1d7068c 100644
--- a/src/user/user.service.ts
+++ b/src/user/user.service.ts
@@ -7,6 +7,9 @@ import { CreateUser } from '../auth/auth.dto';
 import * as bcrypt from 'bcrypt';
 import { EditUser } from './user.controller';
 
+/**
+ * Service for user-related operations.
+ */
 @Injectable()
 export class UserService {
   public static readonly SALT_OR_ROUNDS = 9;
@@ -17,22 +20,46 @@ export class UserService {
     private readonly repository: EntityRepository<User>,
   ) {}
 
+  /**
+   * Find a user by ID.
+   * @param id - The user's ID.
+   * @returns A Promise that resolves to the found user or null if not found.
+   */
   public async findOne(id: number): Promise<User | null> {
     return this.repository.findOne(id);
   }
 
+  /**
+   * Find a user by email.
+   * @param email - The user's email.
+   * @returns A Promise that resolves to the found user or null if not found.
+   */
   public async findByEmail(email: string): Promise<User | null> {
     return this.repository.findOne({ email });
   }
 
+  /**
+   * Find all users.
+   * @returns A Promise that resolves to an array of all users.
+   */
   public async findAll(): Promise<User[]> {
     return this.repository.findAll();
   }
 
+  /**
+   * Find users by IDs.
+   * @param ids - An array of user IDs.
+   * @returns A Promise that resolves to an array of found users.
+   */
   public async find(ids: number[]): Promise<User[]> {
     return this.repository.find(ids);
   }
 
+  /**
+   * Create a new user.
+   * @param data - Data for creating the user.
+   * @returns A Promise that resolves to the created user.
+   */
   public async create(data: CreateUser): Promise<User> {
     const password = await bcrypt.hash(
       data.password,
@@ -46,11 +73,20 @@ export class UserService {
     return user;
   }
 
+  /**
+   * Change a user's password.
+   * @param user - The user entity.
+   * @param password - The new password.
+   */
   public async changePassword(user: User, password: string): Promise<void> {
     user.password = await bcrypt.hash(password, UserService.SALT_OR_ROUNDS);
     await this.em.persistAndFlush(user);
   }
 
+  /**
+   * Delete a user by ID.
+   * @param id - The user's ID.
+   */
   public async delete(id: number): Promise<void> {
     const user = await this.repository.findOne({ id });
 
@@ -60,6 +96,11 @@ export class UserService {
     await this.repository.nativeDelete({ id });
   }
 
+  /**
+   * Change user data.
+   * @param data - Updated user data.
+   * @returns A Promise that resolves to a boolean indicating success.
+   */
   public async changeUserData(data: EditUser): Promise<boolean> {
     const user = await this.findOne(data.id);
     user.name = data.name;
@@ -69,6 +110,11 @@ export class UserService {
     return true;
   }
 
+  /**
+   * Change user role.
+   * @param id - The user's ID.
+   * @returns A Promise that resolves to the updated user entity.
+   */
   public async changeRole(id: number): Promise<User> {
     const user = await this.repository.findOne({ id });
 
-- 
GitLab