diff --git a/backend/src/controllers/learning-objects.ts b/backend/src/controllers/learning-objects.ts index 14d200ce..ab850d6a 100644 --- a/backend/src/controllers/learning-objects.ts +++ b/backend/src/controllers/learning-objects.ts @@ -4,7 +4,7 @@ import { FilteredLearningObject, LearningObjectIdentifier, LearningPathIdentifie import learningObjectService from '../services/learning-objects/learning-object-service.js'; import { envVars, getEnvVar } from '../util/envVars.js'; import { Language } from '../entities/content/language.js'; -import { BadRequestException } from '../exceptions.js'; +import { BadRequestException } from '../exceptions/badRequestException.js'; import attachmentService from '../services/learning-objects/attachment-service.js'; import { NotFoundError } from '@mikro-orm/core'; diff --git a/backend/src/controllers/learning-paths.ts b/backend/src/controllers/learning-paths.ts index 37f92d91..90266fb9 100644 --- a/backend/src/controllers/learning-paths.ts +++ b/backend/src/controllers/learning-paths.ts @@ -2,13 +2,14 @@ import { Request, Response } from 'express'; import { themes } from '../data/themes.js'; import { FALLBACK_LANG } from '../config.js'; import learningPathService from '../services/learning-paths/learning-path-service.js'; -import { BadRequestException, NotFoundException } from '../exceptions.js'; +import { BadRequestException } from '../exceptions/badRequestException.js'; import { Language } from '../entities/content/language.js'; import { PersonalizationTarget, personalizedForGroup, personalizedForStudent, } from '../services/learning-paths/learning-path-personalization-util.js'; +import { NotFoundException } from '../exceptions/notFoundException.js'; /** * Fetch learning paths based on query parameters. diff --git a/backend/src/entities/content/educational-goal.entity.ts b/backend/src/entities/content/educational-goal.entity.ts new file mode 100644 index 00000000..fafe1a01 --- /dev/null +++ b/backend/src/entities/content/educational-goal.entity.ts @@ -0,0 +1,10 @@ +import { Embeddable, Property } from '@mikro-orm/core'; + +@Embeddable() +export class EducationalGoal { + @Property({ type: 'string' }) + source!: string; + + @Property({ type: 'string' }) + id!: string; +} diff --git a/backend/src/entities/content/learning-object.entity.ts b/backend/src/entities/content/learning-object.entity.ts index 9eda22ba..a0da9d7b 100644 --- a/backend/src/entities/content/learning-object.entity.ts +++ b/backend/src/entities/content/learning-object.entity.ts @@ -1,28 +1,12 @@ -import { Embeddable, Embedded, Entity, Enum, ManyToMany, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'; +import { Embedded, Entity, Enum, ManyToMany, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'; import { Language } from './language.js'; import { Attachment } from './attachment.entity.js'; import { Teacher } from '../users/teacher.entity.js'; import { DwengoContentType } from '../../services/learning-objects/processing/content-type.js'; import { v4 } from 'uuid'; import { LearningObjectRepository } from '../../data/content/learning-object-repository.js'; - -@Embeddable() -export class EducationalGoal { - @Property({ type: 'string' }) - source!: string; - - @Property({ type: 'string' }) - id!: string; -} - -@Embeddable() -export class ReturnValue { - @Property({ type: 'string' }) - callbackUrl!: string; - - @Property({ type: 'json' }) - callbackSchema!: string; -} +import { EducationalGoal } from './educational-goal.entity.js'; +import { ReturnValue } from './return-value.entity.js'; @Entity({ repository: () => LearningObjectRepository }) export class LearningObject { diff --git a/backend/src/entities/content/return-value.entity.ts b/backend/src/entities/content/return-value.entity.ts new file mode 100644 index 00000000..d38b0693 --- /dev/null +++ b/backend/src/entities/content/return-value.entity.ts @@ -0,0 +1,10 @@ +import { Embeddable, Property } from '@mikro-orm/core'; + +@Embeddable() +export class ReturnValue { + @Property({ type: 'string' }) + callbackUrl!: string; + + @Property({ type: 'json' }) + callbackSchema!: string; +} diff --git a/backend/src/exceptions.ts b/backend/src/exceptions.ts deleted file mode 100644 index e93a6c93..00000000 --- a/backend/src/exceptions.ts +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Exception for HTTP 400 Bad Request - */ -export class BadRequestException extends Error { - public status = 400; - - constructor(error: string) { - super(error); - } -} - -/** - * Exception for HTTP 401 Unauthorized - */ -export class UnauthorizedException extends Error { - status = 401; - constructor(message: string = 'Unauthorized') { - super(message); - } -} - -/** - * Exception for HTTP 403 Forbidden - */ -export class ForbiddenException extends Error { - status = 403; - - constructor(message: string = 'Forbidden') { - super(message); - } -} - -/** - * Exception for HTTP 404 Not Found - */ -export class NotFoundException extends Error { - public status = 404; - - constructor(error: string) { - super(error); - } -} diff --git a/backend/src/exceptions/badRequestException.ts b/backend/src/exceptions/badRequestException.ts new file mode 100644 index 00000000..7249fcc8 --- /dev/null +++ b/backend/src/exceptions/badRequestException.ts @@ -0,0 +1,11 @@ +import { HttpException } from './httpException.js'; + +/** + * Exception for HTTP 400 Bad Request + */ + +export class BadRequestException extends HttpException { + constructor(message: string = 'Bad Request') { + super(400, message); + } +} diff --git a/backend/src/exceptions/forbiddenException.ts b/backend/src/exceptions/forbiddenException.ts new file mode 100644 index 00000000..f452e390 --- /dev/null +++ b/backend/src/exceptions/forbiddenException.ts @@ -0,0 +1,10 @@ +import { HttpException } from './httpException.js'; + +/** + * Exception for HTTP 403 Forbidden + */ +export class ForbiddenException extends HttpException { + constructor(message: string = 'Forbidden') { + super(403, message); + } +} diff --git a/backend/src/exceptions/httpException.ts b/backend/src/exceptions/httpException.ts new file mode 100644 index 00000000..364def5d --- /dev/null +++ b/backend/src/exceptions/httpException.ts @@ -0,0 +1,8 @@ +export class HttpException extends Error { + constructor( + public status: number, + message: string + ) { + super(message); + } +} diff --git a/backend/src/exceptions/notFoundException.ts b/backend/src/exceptions/notFoundException.ts new file mode 100644 index 00000000..b5c6a916 --- /dev/null +++ b/backend/src/exceptions/notFoundException.ts @@ -0,0 +1,10 @@ +import { HttpException } from './httpException.js'; + +/** + * Exception for HTTP 404 Not Found + */ +export class NotFoundException extends HttpException { + constructor(message: string = 'Not Found') { + super(404, message); + } +} diff --git a/backend/src/exceptions/unauthorizedException.ts b/backend/src/exceptions/unauthorizedException.ts new file mode 100644 index 00000000..51ce04d4 --- /dev/null +++ b/backend/src/exceptions/unauthorizedException.ts @@ -0,0 +1,10 @@ +import { HttpException } from './httpException.js'; + +/** + * Exception for HTTP 401 Unauthorized + */ +export class UnauthorizedException extends HttpException { + constructor(message: string = 'Unauthorized') { + super(401, message); + } +} diff --git a/backend/src/middleware/auth/auth.ts b/backend/src/middleware/auth/auth.ts index 345bfa59..6d793590 100644 --- a/backend/src/middleware/auth/auth.ts +++ b/backend/src/middleware/auth/auth.ts @@ -6,7 +6,8 @@ import jwksClient from 'jwks-rsa'; import * as express from 'express'; import { AuthenticatedRequest } from './authenticated-request.js'; import { AuthenticationInfo } from './authentication-info.js'; -import { ForbiddenException, UnauthorizedException } from '../../exceptions.js'; +import { UnauthorizedException } from '../../exceptions/unauthorizedException.js'; +import { ForbiddenException } from '../../exceptions/forbiddenException.js'; const JWKS_CACHE = true; const JWKS_RATE_LIMIT = true; diff --git a/backend/src/util/envVars.ts b/backend/src/util/envVars.ts index aed0bebd..09287788 100644 --- a/backend/src/util/envVars.ts +++ b/backend/src/util/envVars.ts @@ -5,7 +5,11 @@ const STUDENT_IDP_PREFIX = IDP_PREFIX + 'STUDENT_'; const TEACHER_IDP_PREFIX = IDP_PREFIX + 'TEACHER_'; const CORS_PREFIX = PREFIX + 'CORS_'; -interface EnvVar { key: string; required?: boolean; defaultValue?: number | string | boolean } +interface EnvVar { + key: string; + required?: boolean; + defaultValue?: number | string | boolean; +} export const envVars: { [key: string]: EnvVar } = { Port: { key: PREFIX + 'PORT', defaultValue: 3000 }, diff --git a/backend/tests/test-assets/learning-objects/pn-werkingnotebooks/pn-werkingnotebooks-example.ts b/backend/tests/test-assets/learning-objects/pn-werkingnotebooks/pn-werkingnotebooks-example.ts index 34f49e64..835a0ed0 100644 --- a/backend/tests/test-assets/learning-objects/pn-werkingnotebooks/pn-werkingnotebooks-example.ts +++ b/backend/tests/test-assets/learning-objects/pn-werkingnotebooks/pn-werkingnotebooks-example.ts @@ -2,9 +2,11 @@ import { LearningObjectExample } from '../learning-object-example'; import { Language } from '../../../../src/entities/content/language'; import { DwengoContentType } from '../../../../src/services/learning-objects/processing/content-type'; import { loadTestAsset } from '../../../test-utils/load-test-asset'; -import { EducationalGoal, LearningObject, ReturnValue } from '../../../../src/entities/content/learning-object.entity'; +import { LearningObject } from '../../../../src/entities/content/learning-object.entity'; import { Attachment } from '../../../../src/entities/content/attachment.entity'; import { envVars, getEnvVar } from '../../../../src/util/envVars'; +import { EducationalGoal } from '../../../../src/entities/content/educational-goal.entity'; +import { ReturnValue } from '../../../../src/entities/content/return-value.entity'; const ASSETS_PREFIX = 'learning-objects/pn-werkingnotebooks/'; diff --git a/backend/tests/test_assets/content/learning-objects.testdata.ts b/backend/tests/test_assets/content/learning-objects.testdata.ts index e45bdea0..ba2c230a 100644 --- a/backend/tests/test_assets/content/learning-objects.testdata.ts +++ b/backend/tests/test_assets/content/learning-objects.testdata.ts @@ -1,7 +1,8 @@ import { EntityManager } from '@mikro-orm/core'; -import { LearningObject, ReturnValue } from '../../../src/entities/content/learning-object.entity'; +import { LearningObject } from '../../../src/entities/content/learning-object.entity'; import { Language } from '../../../src/entities/content/language'; import { DwengoContentType } from '../../../src/services/learning-objects/processing/content-type'; +import { ReturnValue } from '../../../src/entities/content/return-value.entity'; export function makeTestLearningObjects(em: EntityManager): Array { const returnValue: ReturnValue = new ReturnValue();