Merge branch 'dev' into refactor/linting
This commit is contained in:
		
						commit
						97a5b26884
					
				
					 20 changed files with 223 additions and 95 deletions
				
			
		|  | @ -1,15 +1,24 @@ | |||
| # | ||||
| # Basic configuration | ||||
| # Development environment configuration | ||||
| # | ||||
| # You probably don't need to change these values, as this configuration takes | ||||
| # the docker services and their default ports into account. | ||||
| # | ||||
| 
 | ||||
| DWENGO_PORT=3000 # The port the backend will listen on | ||||
| ### Dwengo ### | ||||
| 
 | ||||
| #DWENGO_PORT=3000 | ||||
| #DWENGO_LEARNING_CONTENT_REPO_API_BASE_URL=https://dwengo.org/backend/api | ||||
| #DWENGO_FALLBACK_LANGUAGE=nl | ||||
| #DWENGO_RUN_MODE=dev | ||||
| 
 | ||||
| DWENGO_DB_HOST=localhost | ||||
| DWENGO_DB_PORT=5431 | ||||
| #DWENGO_DB_NAME=dwengo | ||||
| DWENGO_DB_USERNAME=postgres | ||||
| DWENGO_DB_PASSWORD=postgres | ||||
| DWENGO_DB_UPDATE=true | ||||
| 
 | ||||
| # Auth | ||||
| #DWENGO_DB_CONTENT_PREFIX=u_ | ||||
| 
 | ||||
| DWENGO_AUTH_STUDENT_URL=http://localhost:7080/realms/student | ||||
| DWENGO_AUTH_STUDENT_CLIENT_ID=dwengo | ||||
|  | @ -17,12 +26,12 @@ DWENGO_AUTH_STUDENT_JWKS_ENDPOINT=http://localhost:7080/realms/student/protocol/ | |||
| DWENGO_AUTH_TEACHER_URL=http://localhost:7080/realms/teacher | ||||
| DWENGO_AUTH_TEACHER_CLIENT_ID=dwengo | ||||
| DWENGO_AUTH_TEACHER_JWKS_ENDPOINT=http://localhost:7080/realms/teacher/protocol/openid-connect/certs | ||||
| #DWENGO_AUTH_AUDIENCE=account | ||||
| 
 | ||||
| # Allow Vite dev-server to access the backend (for testing purposes). Don't forget to remove this in production! | ||||
| DWENGO_CORS_ALLOWED_ORIGINS=http://localhost:5173 | ||||
| #DWENGO_CORS_ALLOWED_HEADERS=Authorization,Content-Type | ||||
| 
 | ||||
| # | ||||
| # Advanced configuration | ||||
| # | ||||
| ### Advanced configuration ### | ||||
| 
 | ||||
| # LOKI_HOST=http://localhost:9001      # The address of the Loki instance, used for logging | ||||
| DWENGO_LOGGING_LEVEL=debug | ||||
| #DWENGO_LOGGING_LOKI_HOST=http://localhost:3102 | ||||
|  |  | |||
|  | @ -1,27 +1,68 @@ | |||
| # | ||||
| # Basic configuration | ||||
| # | ||||
| # Change the values of the variables below to match your environment! | ||||
| # Default values are commented out. | ||||
| # | ||||
| 
 | ||||
| DWENGO_PORT=3000 # The port the backend will listen on | ||||
| ### Dwengo ### | ||||
| 
 | ||||
| # Port the backend will listen on | ||||
| #DWENGO_PORT=3000 | ||||
| # The hostname or IP address of the remote learning content API. | ||||
| #DWENGO_LEARNING_CONTENT_REPO_API_BASE_URL=https://dwengo.org/backend/api | ||||
| # The default fallback language. | ||||
| #DWENGO_FALLBACK_LANGUAGE=nl | ||||
| # Whether running in production mode or not. Possible values are "prod" or "dev". | ||||
| #DWENGO_RUN_MODE=dev | ||||
| 
 | ||||
| # ! Change this! The hostname or IP address of the database | ||||
| # If running your stack in docker, this should use the docker service name. | ||||
| DWENGO_DB_HOST=domain-or-ip-of-database | ||||
| DWENGO_DB_PORT=5431 | ||||
| 
 | ||||
| # Change this to the actual credentials of the user Dwengo should use in the backend | ||||
| DWENGO_DB_USERNAME=postgres | ||||
| DWENGO_DB_PASSWORD=postgres | ||||
| 
 | ||||
| # The port of the database. | ||||
| #DWENGO_DB_PORT=5432 | ||||
| # The name of the database. | ||||
| #DWENGO_DB_NAME=dwengo | ||||
| # ! Change this! The username of the database user. | ||||
| DWENGO_DB_USERNAME=username | ||||
| # ! Change this! The password of the database user. | ||||
| DWENGO_DB_PASSWORD=password | ||||
| # Whether the database scheme needs to be updated. | ||||
| # Set this to true when the database scheme needs to be updated. In that case, take a backup first. | ||||
| DWENGO_DB_UPDATE=false | ||||
| #DWENGO_DB_UPDATE=false | ||||
| # The prefix used for custom user content. | ||||
| #DWENGO_DB_CONTENT_PREFIX=u_ | ||||
| 
 | ||||
| # Data for the identity provider via which the students authenticate. | ||||
| DWENGO_AUTH_STUDENT_URL=http://localhost:7080/realms/student | ||||
| # ! Change this! The external URL for student authentication. Should be reachable by the client. | ||||
| # E.g. https://sel2-1.ugent.be/idp/realms/student | ||||
| DWENGO_AUTH_STUDENT_URL=http://hostname/idp/realms/student | ||||
| # ! Change this! The client ID for student authentication. | ||||
| DWENGO_AUTH_STUDENT_CLIENT_ID=dwengo | ||||
| DWENGO_AUTH_STUDENT_JWKS_ENDPOINT=http://localhost:7080/realms/student/protocol/openid-connect/certs | ||||
| 
 | ||||
| # Data for the identity provider via which the teachers authenticate. | ||||
| DWENGO_AUTH_TEACHER_URL=http://localhost:7080/realms/teacher | ||||
| # ! Change this! The internal URL for retrieving the JWKS for student authentication. | ||||
| # Should be reachable by the backend. If running your stack in docker, this should use the docker service name. | ||||
| # E.g. http://idp:7080/realms/student/protocol/openid-connect/certs | ||||
| DWENGO_AUTH_STUDENT_JWKS_ENDPOINT=http://hostname/realms/student/protocol/openid-connect/certs | ||||
| # ! Change this! The external URL for teacher authentication. Should be reachable by the client. | ||||
| # E.g. https://sel2-1.ugent.be/idp/realms/teacher | ||||
| DWENGO_AUTH_TEACHER_URL=http://hostname/idp/realms/teacher | ||||
| # ! Change this! The client ID for teacher authentication. | ||||
| DWENGO_AUTH_TEACHER_CLIENT_ID=dwengo | ||||
| DWENGO_AUTH_TEACHER_JWKS_ENDPOINT=http://localhost:7080/realms/teacher/protocol/openid-connect/certs | ||||
| # ! Change this! The internal URL for retrieving the JWKS for teacher authentication. | ||||
| # Should be reachable by the backend. If running your stack in docker, this should use the docker service name. | ||||
| # E.g. http://idp:7080/realms/teacher/protocol/openid-connect/certs | ||||
| DWENGO_AUTH_TEACHER_JWKS_ENDPOINT=http://hostname/realms/teacher/protocol/openid-connect/certs | ||||
| # The IDP audience | ||||
| #DWENGO_AUTH_AUDIENCE=account | ||||
| 
 | ||||
| # The address of the Lokiinstance, used for logging | ||||
| # LOKI_HOST=http://localhost:3102 | ||||
| # Allowed origins for CORS requests. Separate multiple origins with a comma. | ||||
| #DWENGO_CORS_ALLOWED_ORIGINS= | ||||
| # Allowed headers for CORS requests. Separate multiple headers with a comma. | ||||
| #DWENGO_CORS_ALLOWED_HEADERS=Authorization,Content-Type | ||||
| 
 | ||||
| ### Advanced configuration ### | ||||
| 
 | ||||
| # The logging level. Possible values are "debug", "info", "warn", "error". | ||||
| #DWENGO_LOGGING_LEVEL=info | ||||
| # The address of the Loki instance, a log aggregation system. | ||||
| # If running your stack in docker, this should use the docker service name. | ||||
| #DWENGO_LOGGING_LOKI_HOST=http://localhost:3102 | ||||
|  |  | |||
|  | @ -1,28 +1,37 @@ | |||
| DWENGO_PORT=3000 # The port the backend will listen on | ||||
| DWENGO_DB_HOST=db # Name of the database container | ||||
| DWENGO_DB_PORT=5431 | ||||
| # | ||||
| # Production environment configuration | ||||
| # | ||||
| # Change the values of the variables below to match your production environment! | ||||
| # See .env.example for more information. | ||||
| # | ||||
| 
 | ||||
| # Change this to the actual credentials of the user Dwengo should use in the backend | ||||
| ### Dwengo ### | ||||
| 
 | ||||
| DWENGO_PORT=3000 | ||||
| #DWENGO_LEARNING_CONTENT_REPO_API_BASE_URL=https://dwengo.org/backend/api | ||||
| #DWENGO_FALLBACK_LANGUAGE=nl | ||||
| DWENGO_RUN_MODE=prod | ||||
| 
 | ||||
| DWENGO_DB_HOST=db | ||||
| DWENGO_DB_PORT=5432 | ||||
| DWENGO_DB_NAME=postgres | ||||
| DWENGO_DB_USERNAME=postgres | ||||
| DWENGO_DB_PASSWORD=postgres | ||||
| 
 | ||||
| # Set this to true when the database scheme needs to be updated. In that case, take a backup first. | ||||
| DWENGO_DB_UPDATE=false | ||||
| #DWENGO_DB_CONTENT_PREFIX=u_ | ||||
| 
 | ||||
| # Data for the identity provider via which the students authenticate. | ||||
| DWENGO_AUTH_STUDENT_URL=https://sel2-1.ugent.be/idp/realms/student | ||||
| DWENGO_AUTH_STUDENT_CLIENT_ID=dwengo | ||||
| DWENGO_AUTH_STUDENT_JWKS_ENDPOINT=http://idp:7080/idp/realms/student/protocol/openid-connect/certs # Name of the idp container | ||||
| # Data for the identity provider via which the teachers authenticate. | ||||
| DWENGO_AUTH_TEACHER_URL=https://sel2-1.ugent.be/idp/realms/teacher | ||||
| DWENGO_AUTH_TEACHER_CLIENT_ID=dwengo | ||||
| DWENGO_AUTH_TEACHER_JWKS_ENDPOINT=http://idp:7080/idp/realms/teacher/protocol/openid-connect/certs # Name of the idp container | ||||
| #DWENGO_AUTH_AUDIENCE=account | ||||
| 
 | ||||
| # | ||||
| # Advanced configuration | ||||
| # | ||||
| #DWENGO_CORS_ALLOWED_ORIGINS= | ||||
| #DWENGO_CORS_ALLOWED_HEADERS=Authorization,Content-Type | ||||
| 
 | ||||
| # Logging and monitoring | ||||
| ### Advanced configuration ### | ||||
| 
 | ||||
| # LOKI_HOST=http://logging:3102 # The address of the Loki instance, used for logging | ||||
| DWENGO_LOGGING_LEVEL=info | ||||
| DWENGO_LOGGING_LOKI_HOST=http://logging:3102 | ||||
|  |  | |||
|  | @ -1,3 +1,13 @@ | |||
| PORT=3000 | ||||
| DWENGO_DB_UPDATE=true | ||||
| # | ||||
| # Test environment configuration | ||||
| # | ||||
| # Should not need to be modified. | ||||
| # See .env.example for more information. | ||||
| # | ||||
| 
 | ||||
| ### Dwengo ### | ||||
| 
 | ||||
| DWENGO_PORT=3000 | ||||
| 
 | ||||
| DWENGO_DB_NAME=":memory:" | ||||
| DWENGO_DB_UPDATE=true | ||||
|  |  | |||
|  | @ -30,6 +30,7 @@ COPY package-lock.json backend/package.json ./ | |||
| RUN npm install --silent --only=production | ||||
| 
 | ||||
| COPY ./docs /docs | ||||
| COPY ./backend/i18n /app/i18n | ||||
| COPY --from=build-stage /app/backend/dist ./dist/ | ||||
| 
 | ||||
| EXPOSE 3000 | ||||
|  |  | |||
|  | @ -4,23 +4,24 @@ | |||
| 
 | ||||
| ```shell | ||||
| npm install | ||||
| 
 | ||||
| # Start de nodige services voor ontwikkeling | ||||
| cd ../ # Ga naar de root van de repository | ||||
| docker compose up -d | ||||
| ``` | ||||
| 
 | ||||
| Setup the environment variables in a `.env` file in the root of the project. You can use the `.env.example` file as a template. | ||||
| Zet de omgevingsvariabelen in een `.env` bestand in de root van het project. | ||||
| Je kan het `.env.example` bestand als template gebruiken. | ||||
| 
 | ||||
| ### Development | ||||
| ### Ontwikkeling | ||||
| 
 | ||||
| ```shell | ||||
| # Omgevingsvariabelen | ||||
| cp .env.development.example .env.development.local | ||||
| 
 | ||||
| npm run dev | ||||
| ``` | ||||
| 
 | ||||
| ### Production | ||||
| 
 | ||||
| ```shell | ||||
| npm run build | ||||
| npm run start | ||||
| ``` | ||||
| 
 | ||||
| ### Tests | ||||
| 
 | ||||
| Voer volgend commando uit om de unit tests uit te voeren: | ||||
|  | @ -29,6 +30,18 @@ Voer volgend commando uit om de unit tests uit te voeren: | |||
| npm run test:unit | ||||
| ``` | ||||
| 
 | ||||
| ### Productie | ||||
| 
 | ||||
| ```shell | ||||
| # Omgevingsvariabelen | ||||
| cp .env.development.example .env | ||||
| 
 | ||||
| npm run build | ||||
| npm run start | ||||
| ``` | ||||
| 
 | ||||
| Zie ook de [installatiehandleiding](https://github.com/SELab-2/Dwengo-1/wiki/Administrator:-Productie-omgeving). | ||||
| 
 | ||||
| ## Keycloak configuratie | ||||
| 
 | ||||
| Tijdens development is het voldoende om gebruik te maken van de keycloak configuratie die automatisch ingeladen wordt. | ||||
|  |  | |||
|  | @ -4,8 +4,4 @@ import { envVars, getEnvVar } from './util/envVars.js'; | |||
| export const DWENGO_API_BASE = getEnvVar(envVars.LearningContentRepoApiBaseUrl); | ||||
| export const FALLBACK_LANG = getEnvVar(envVars.FallbackLanguage); | ||||
| 
 | ||||
| // Logging
 | ||||
| export const LOG_LEVEL: string = 'development' === process.env.NODE_ENV ? 'debug' : 'info'; | ||||
| export const LOKI_HOST: string = process.env.LOKI_HOST || 'http://localhost:3102'; | ||||
| 
 | ||||
| export const FALLBACK_SEQ_NUM = 1; | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| import { createLogger, format, Logger as WinstonLogger, transports } from 'winston'; | ||||
| import LokiTransport from 'winston-loki'; | ||||
| import { LokiLabels } from 'loki-logger-ts'; | ||||
| import { LOG_LEVEL, LOKI_HOST } from '../config.js'; | ||||
| import { envVars, getEnvVar } from '../util/envVars.js'; | ||||
| 
 | ||||
| export class Logger extends WinstonLogger { | ||||
|     constructor() { | ||||
|  | @ -22,10 +22,25 @@ function initializeLogger(): Logger { | |||
|         return logger; | ||||
|     } | ||||
| 
 | ||||
|     const logLevel = getEnvVar(envVars.LogLevel); | ||||
| 
 | ||||
|     const consoleTransport = new transports.Console({ | ||||
|         level: getEnvVar(envVars.LogLevel), | ||||
|         format: format.combine(format.cli(), format.colorize()), | ||||
|     }); | ||||
| 
 | ||||
|     if (getEnvVar(envVars.RunMode) === 'dev') { | ||||
|         return createLogger({ | ||||
|             transports: [consoleTransport], | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     const lokiHost = getEnvVar(envVars.LokiHost); | ||||
| 
 | ||||
|     const lokiTransport: LokiTransport = new LokiTransport({ | ||||
|         host: LOKI_HOST, | ||||
|         host: lokiHost, | ||||
|         labels: lokiLabels, | ||||
|         level: LOG_LEVEL, | ||||
|         level: logLevel, | ||||
|         json: true, | ||||
|         format: format.combine(format.timestamp(), format.json()), | ||||
|         onConnectionError: (err): void => { | ||||
|  | @ -34,16 +49,11 @@ function initializeLogger(): Logger { | |||
|         }, | ||||
|     }); | ||||
| 
 | ||||
|     const consoleTransport = new transports.Console({ | ||||
|         level: LOG_LEVEL, | ||||
|         format: format.combine(format.cli(), format.colorize()), | ||||
|     }); | ||||
| 
 | ||||
|     logger = createLogger({ | ||||
|         transports: [lokiTransport, consoleTransport], | ||||
|     }); | ||||
| 
 | ||||
|     logger.debug(`Logger initialized with level ${LOG_LEVEL}, Loki host ${LOKI_HOST}`); | ||||
|     logger.debug(`Logger initialized with level ${logLevel} to Loki host ${lokiHost}`); | ||||
|     return logger; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,7 +3,6 @@ import { PostgreSqlDriver } from '@mikro-orm/postgresql'; | |||
| import { envVars, getEnvVar, getNumericEnvVar } from './util/envVars.js'; | ||||
| import { SqliteDriver } from '@mikro-orm/sqlite'; | ||||
| import { MikroOrmLogger } from './logging/mikroOrmLogger.js'; | ||||
| import { LOG_LEVEL } from './config.js'; | ||||
| 
 | ||||
| // Import alle entity-bestanden handmatig
 | ||||
| import { User } from './entities/users/user.entity.js'; | ||||
|  | @ -69,7 +68,7 @@ function config(testingMode = false): Options { | |||
|         // EntitiesTs: entitiesTs,
 | ||||
| 
 | ||||
|         // Logging
 | ||||
|         debug: LOG_LEVEL === 'debug', | ||||
|         debug: getEnvVar(envVars.LogLevel) === 'debug', | ||||
|         loggerFactory: (options: LoggerOptions) => new MikroOrmLogger(options), | ||||
|     }; | ||||
| } | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ const IDP_PREFIX = PREFIX + 'AUTH_'; | |||
| const STUDENT_IDP_PREFIX = IDP_PREFIX + 'STUDENT_'; | ||||
| const TEACHER_IDP_PREFIX = IDP_PREFIX + 'TEACHER_'; | ||||
| const CORS_PREFIX = PREFIX + 'CORS_'; | ||||
| const LOGGING_PREFIX = PREFIX + 'LOGGING_'; | ||||
| 
 | ||||
| interface EnvVar { | ||||
|     key: string; | ||||
|  | @ -13,15 +14,18 @@ interface EnvVar { | |||
| 
 | ||||
| export const envVars: Record<string, EnvVar> = { | ||||
|     Port: { key: PREFIX + 'PORT', defaultValue: 3000 }, | ||||
|     LearningContentRepoApiBaseUrl: { key: PREFIX + 'LEARNING_CONTENT_REPO_API_BASE_URL', defaultValue: 'https://dwengo.org/backend/api' }, | ||||
|     FallbackLanguage: { key: PREFIX + 'FALLBACK_LANGUAGE', defaultValue: 'nl' }, | ||||
|     RunMode: { key: PREFIX + 'RUN_MODE', defaultValue: 'dev' }, | ||||
| 
 | ||||
|     DbHost: { key: DB_PREFIX + 'HOST', required: true }, | ||||
|     DbPort: { key: DB_PREFIX + 'PORT', defaultValue: 5432 }, | ||||
|     DbName: { key: DB_PREFIX + 'NAME', defaultValue: 'dwengo' }, | ||||
|     DbUsername: { key: DB_PREFIX + 'USERNAME', required: true }, | ||||
|     DbPassword: { key: DB_PREFIX + 'PASSWORD', required: true }, | ||||
|     DbUpdate: { key: DB_PREFIX + 'UPDATE', defaultValue: false }, | ||||
|     LearningContentRepoApiBaseUrl: { key: PREFIX + 'LEARNING_CONTENT_REPO_API_BASE_URL', defaultValue: 'https://dwengo.org/backend/api' }, | ||||
|     FallbackLanguage: { key: PREFIX + 'FALLBACK_LANGUAGE', defaultValue: 'nl' }, | ||||
|     UserContentPrefix: { key: DB_PREFIX + 'USER_CONTENT_PREFIX', defaultValue: 'u_' }, | ||||
| 
 | ||||
|     IdpStudentUrl: { key: STUDENT_IDP_PREFIX + 'URL', required: true }, | ||||
|     IdpStudentClientId: { key: STUDENT_IDP_PREFIX + 'CLIENT_ID', required: true }, | ||||
|     IdpStudentJwksEndpoint: { key: STUDENT_IDP_PREFIX + 'JWKS_ENDPOINT', required: true }, | ||||
|  | @ -29,8 +33,12 @@ export const envVars: Record<string, EnvVar> = { | |||
|     IdpTeacherClientId: { key: TEACHER_IDP_PREFIX + 'CLIENT_ID', required: true }, | ||||
|     IdpTeacherJwksEndpoint: { key: TEACHER_IDP_PREFIX + 'JWKS_ENDPOINT', required: true }, | ||||
|     IdpAudience: { key: IDP_PREFIX + 'AUDIENCE', defaultValue: 'account' }, | ||||
| 
 | ||||
|     CorsAllowedOrigins: { key: CORS_PREFIX + 'ALLOWED_ORIGINS', defaultValue: '' }, | ||||
|     CorsAllowedHeaders: { key: CORS_PREFIX + 'ALLOWED_HEADERS', defaultValue: 'Authorization,Content-Type' }, | ||||
| 
 | ||||
|     LogLevel: { key: LOGGING_PREFIX + 'LEVEL', defaultValue: 'info' }, | ||||
|     LokiHost: { key: LOGGING_PREFIX + 'LOKI_HOST', defaultValue: 'http://localhost:3102' }, | ||||
| } as const; | ||||
| 
 | ||||
| /** | ||||
|  |  | |||
|  | @ -8,12 +8,12 @@ const logger: Logger = getLogger(); | |||
| 
 | ||||
| export function loadTranslations<T>(language: string): T { | ||||
|     try { | ||||
|         const filePath = path.join(process.cwd(), '_i18n', `${language}.yml`); | ||||
|         const filePath = path.join(process.cwd(), 'i18n', `${language}.yml`); | ||||
|         const yamlFile = fs.readFileSync(filePath, 'utf8'); | ||||
|         return yaml.load(yamlFile) as T; | ||||
|     } catch (error) { | ||||
|         logger.warn(`Cannot load translation for ${language}, fallen back to dutch`, error); | ||||
|         const fallbackPath = path.join(process.cwd(), '_i18n', `${FALLBACK_LANG}.yml`); | ||||
|         const fallbackPath = path.join(process.cwd(), 'i18n', `${FALLBACK_LANG}.yml`); | ||||
|         return yaml.load(fs.readFileSync(fallbackPath, 'utf8')) as T; | ||||
|     } | ||||
| } | ||||
|  |  | |||
		Reference in a new issue