From 7d54ac3265475047ce17702993d14bdbaa015392 Mon Sep 17 00:00:00 2001 From: "kelly.nguyen" <kelly.nguyen@etu.hesge.ch> Date: Fri, 16 Feb 2024 15:53:28 +0100 Subject: [PATCH] add route for assignments --- .gitmodules | 3 + ExpressAPI/.env.vault | 1 - ExpressAPI/assets/OpenAPI/OpenAPI.yaml | 2 +- ExpressAPI/package-lock.json | 18 +- ExpressAPI/package.json | 142 +- ExpressAPI/prisma/seed.ts | 3054 ++++++++--------- ExpressAPI/src/express/API.ts | 56 +- ExpressAPI/src/helpers/DatabaseHelper.ts | 28 +- ExpressAPI/src/helpers/DojoValidators.ts | 150 +- .../Prisma/Extensions/UserQueryExtension.ts | 50 +- .../Prisma/Extensions/UserResultExtension.ts | 56 +- ExpressAPI/src/managers/AssignmentManager.ts | 24 +- ExpressAPI/src/managers/UserManager.ts | 76 +- .../ClientVersionCheckerMiddleware.ts | 4 +- .../src/middlewares/ParamsCallbackManager.ts | 3 +- .../src/middlewares/SecurityMiddleware.ts | 3 + ExpressAPI/src/routes/ApiRoutesManager.ts | 3 +- ExpressAPI/src/routes/AssignmentRoutes.ts | 134 +- ExpressAPI/src/routes/BaseRoutes.ts | 1 - ExpressAPI/src/routes/ExerciseRoutes.ts | 136 +- ExpressAPI/src/routes/UserRoutes.ts | 22 + ExpressAPI/src/shared | 1 - ExpressAPI/src/types/DatabaseTypes.ts | 34 +- ExpressAPI/src/types/SecurityCheckType.ts | 1 + ExpressAPI/src/types/express/index.d.ts | 3 +- 25 files changed, 2027 insertions(+), 1978 deletions(-) create mode 100644 ExpressAPI/src/routes/UserRoutes.ts delete mode 160000 ExpressAPI/src/shared diff --git a/.gitmodules b/.gitmodules index c08b30d..c4eff04 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "ExpressAPI/src/shared"] path = ExpressAPI/src/shared url = ../../shared/nodesharedcode.git +[submodule "shared"] + path = shared + url = ../../shared/nodesharedcode.git diff --git a/ExpressAPI/.env.vault b/ExpressAPI/.env.vault index 7f2cb5b..f58da09 100644 --- a/ExpressAPI/.env.vault +++ b/ExpressAPI/.env.vault @@ -11,4 +11,3 @@ DOTENV_VAULT_PRODUCTION="fqZ2Zu+kkjbiEJNNWjfsjbZiFcrleU5ze7xtNufRGcufZqVL4SFvTL3 # test DOTENV_VAULT_TEST="MQ8nAyrw7KMw91lx03on7lfA+i9ecZbxh5C+yturX+QIhCU3fOLS714djD0vRvCpR+go+IJCPEQ+cYTgc1bKaGP1NMs3kHkHIpBW3Ow3MXasE2986K8rwc+MaHh6vMMjFNfBogBowBCDlC0UGBbTwE5JkFU+iBAGRyvgcdysKyPV1Ij5ypsJBGYzfSQ7ItRLI23wlEnx5Dy9+dQMZ6xgBQKeRlLqouVIfHVhymBefTYu6D5F1CEKI7rip8ZOGrYFXnsxvGicg2L2+xDVzzjL/l1rr7I7gD+w/q6+17Tc+SQxyNyfrDC0NJ6Z6yLYY/+CXAG4HZnomM1glaLHJ8Gakz/X/cfAJP+bAJeoGnscNne90Wldr1m9zd1Dmeh9anQVy47ISVMuOnk4KsstYlkpXqWPNUJglzBvXXJnJa6d+3T0Ht7gc/ckOW4dRCU3EikiujftnWy2Dw+VygV94nh9YdHuUAqVQyuzku3lLKBMtqBQF627uoMY8lhTTNdiDuEMtCbcmvNFXe9GKioiBcQQgkuVNG/cjaD5qUf0neKstIRH1bn4O+JAutgqSdb8L28WY8p0gJ7z5GHXxPsaI5vGEUed2zHo6qzpcv9AfFqhsMGr54k93OiifX1MWjtSrS7KQm0rw/w8G1QOjZTmzU5VOPOw7IvAMV/UD3BT2AAd0UCoD58XyVHXNGxIceWi1yR4XkCiYLkvmYFVz0uMHgyMgFtgJb51THiW7wMJa9KQtdNQg9S45mITPVhtSQCAmFWnB7eqbfrCcWVfv73QAOZfeuONW6LUxfBPuKo0K9fSW2QDXx/XUyfYvouSEPEYB2QXMftaxph86o6mriqjCNo8Ff0dAxcfBUGj/0aLVgKmvC/4FsXXWLPS4TZIhUmNNdDlcUuV4RwPt2J0gWW0DslfoQdxGZj66pXAX3aQVmX9BpVWlcjH5CcX0fVWEYK3mRMkUDKKYap4zX+EtGEKb2tcoxosTryDFr7oYjpnBjqSTkmMLvvECiRQUhB3SckLkOXjQ5CJCSu0rc5I0JOL4cQzAj2bGjVPaEoWiSp6YzmgnnUcrWzBhxdcuS8ez0zYQtyyWLteb7ZVjPqDOR3Et/W82xnrJLNJ8TyLvgfI1LF2Dmzln0UVEhRz/1vUTZ+xExjQ17EAlcsx5F7624Eohzb6RupYz5BmWrmQ1DLsgAQpYcZ4V9jhYp/oF+q3bYLQgcLu/pHcPiHgGK2hrFXi24mRhl9eB7BzFGq9xkcpQuobPcBpxOmzEd6E79uEF4lscWE21PfC0gUYo3FBUXrwAjYb75Z7JQRdMTaMOMkmqv5tVG6HZlhn/C4yGXeOduaS3F7M/4WZZoq3ewdVJ+97nJHIb0sXostRWOdX/sj0M0qnchV2qEFm4LzLFXeZ6JJFrvxDzQXzIvzQbbPynAmQ7jXYKVasqV4CPF6divp7+xxa+AejWGBiak57unA2hsyqFyMh+gJ030SY4QRKwrFNyA+vHy3yYioM0lQAQbWc8tp/S4Q8+2WhmbdSuOgDPMncEdtsP9dJO/x4K+6ZQ6EKqB2w48qZA+qYt9/aQ3SvoQjLPE4BjGuzEjJBaL2JcRfngsAe3xq8H358XTFQrSkcmGW44n2tPDZyOFBMuMSsUL8MOSyOyS+1dokpz1EnY/iiPmmX+32uh0XXPoZ55jDuV9x3MdQPVDyl8o9AUOyvUOvDybGmu3iRY4uarWsOCLrA7mrC0ut2leAHkanFyouMGrW49LZ2rXJzPpL7cU00Q2LHkBugj1qtbeAboYcwdanQSarVv8wWY5U+3uhAo7+isSn1oT4pmKqBPPYih7U7Dt2DzTIBMN1e5GrVsEUxPBAODdHzV/pdnk+Xy08NvSYU6vvIpe31EXyzmy36xCIxNwkkFwwS/vnVNXfIQxudHtEOWwlSoZtCZ6R9MCx1npVNzrinLrt6rgoDRS9hHQtzFte/6a0DibCyd+KaG+i+N6jN5bg9+NYzgLJ0BoJqokgeV7d3r/MhE0py1ib+0OP9a37WrAwpkhxH3PYBcMBHp1tZIzSybOtavE6nAGRrZRp4OYLSrS/ZQMPD3xPAdLO4XrNdZ/kUG1spIk4WmiKzII9l5X3jjNd69t+NgDW8JK8DaVNVksE1M1+Fiwk88zodfS5FXWL6lvrwcaHoTcFV/91xUuQzc5IHqDiuO0sVB5qBLxsRmZDMJPyLeyQO3PK3idGh8umhpV0OCDYP0Ye5Jl7bZdCab4jE1QlOCNoX6tWEphzdrD6AfMoC887R2lWfIT50XSf/SFYBgJgZen9xYIJdCotuJGISnMkn2jm3fLpi1F3NyYzFsyEYkUCk9WMrqjr+mF9rVEfdupM5+J2mBpflTweeUWghXXzXqa292FVos1J32xwcA2Jj1F1Uqq8q23vaUAmXLynlyzI8qEZLB9DqwRrEPNYFKcqa9fOlAxeFNTMh7oMKbPnDsSX7B+WUBXseCDsv4KUJqTERxhEO63Q67aN8uTviUPBmUDa5UFl5hJ/gbYtCMqozIn3GY3au9FWjCm3HZIFKhHH2H5Nh5kHO/oGgo8AuVN6RNRbJ0HKVarOdoxL56KyOJdPyob9Nda3puulHXl00gAmvoIaZORl5R95+CRWVjh01Jczx3Ym1INh4VDHL4dEegwJB9SbS8NrpGYlISensui+62YivisFvSaNqXvHAT7LAcDlNwYLmhhydKcajEYRIADH11MEfx/N9pKT9XAhHfIRxXQdBdb60ckRM6BtZZITXVVET+qYGkcLW0ukPhrq0s0RbjWYnxq5jbFgNvdEd/MxFrgCvl4fikWkdupYn7BrX/UQHuMWUwlz0LG7gNAw1+JPsg3U/eM3RsiXyBGTp/LKrwa5IcjrldUERiXkF7uGCWgUCftl6XvqJpZZbz4UjkDd/SiNVqo69RERQnAevWDAnfnhLfoHJ+7G6ie/LZA9ejMGzNS/a6Sqxw57xgkCPkkv8vRHJkzI1KhaQUaR/QiT76367m1XakQZPysXR+3ETbYz1S0ibPReEXQVCJpSJbOPHHkfxvB0Glk/tfIwJq/ugCUGiNaSY6uUhHOaJdAVPe6rVCfUld6pgo5LbZzgpVYmg7lBKBn00Ur5mItUVZ8xndVlinJGcYdbtYNn97SLtRgAP1SIuQ1KNt0WBINOM3fSbSivbhrxS/Wc37L3TjBfoVqIXdpIhXvtpjTxyChIZlPePZcrapFIib0m4KHdDDYnyTYmav8XHKv6I4bkOnMtAE3mWfwkkShQ8NkaY5hsC+wMNID5i9HzvAWpoxi3kciLyRP2ckxQDKotdNnoYLFHvzv5goxciG5ATM6xKfuMM6WYMysLYNulMf2h4/Qq31t9jApyP1ZmQ51JLnQvbCV+C/9p2uFSWR5KExWX7CwAzV7hF+8DoUqriNZ1Y0a9HdZuepfGVRuxHno6BvbRElQKvyz0ny8VSEfwQl4VoTnzLYofzFENoxaxDoQW5H6Q/J5TaLBTyeNbQ22nmii4Ziw3ZW72EMLcruJFhR9cyBmcRJw2FfqcIgon/5x6Zh0X3rod9xiuCvpUzVR5EyiyFJps7tNRygP/1WbjGrMUIynIs/NfClS/Lwf8FCG77qcSqdBxV5cb7FukrsAKahWNbPVsrexqAdzptj3AVisDyh9XE6W6j+uBfPjMSrqyUJVYqO8Tznrnmbw8BNPpxfeGPFNSPFpqtdF1j6crd8rR0x+vXfYAyJeVcYs6Rd/WR9UAAkldhNrg/M3zlERwMROtg" - diff --git a/ExpressAPI/assets/OpenAPI/OpenAPI.yaml b/ExpressAPI/assets/OpenAPI/OpenAPI.yaml index 2bbe1d3..f42ac39 100644 --- a/ExpressAPI/assets/OpenAPI/OpenAPI.yaml +++ b/ExpressAPI/assets/OpenAPI/OpenAPI.yaml @@ -1,7 +1,7 @@ openapi: 3.1.0 info: title: Dojo API - version: 3.4.2 + version: 3.4.0 description: | **Backend API of the Dojo project.** diff --git a/ExpressAPI/package-lock.json b/ExpressAPI/package-lock.json index 1d60411..8289b9e 100644 --- a/ExpressAPI/package-lock.json +++ b/ExpressAPI/package-lock.json @@ -1,12 +1,12 @@ { "name": "dojo_backend_api", - "version": "3.4.2", + "version": "3.4.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "dojo_backend_api", - "version": "3.4.2", + "version": "3.4.1", "license": "AGPLv3", "dependencies": { "@prisma/client": "^5.8.1", @@ -52,7 +52,7 @@ "@typescript-eslint/eslint-plugin": "^6.18.1", "@typescript-eslint/parser": "^6.18.1", "dotenv-cli": "^7.3.0", - "dotenv-vault": "^1.25.0", + "dotenv-vault": "^1.26.0", "genversion": "^3.2.0", "nodemon": "^3.0.3", "npm": "^10.3.0", @@ -2355,16 +2355,16 @@ } }, "node_modules/dotenv-vault": { - "version": "1.25.0", - "resolved": "https://registry.npmjs.org/dotenv-vault/-/dotenv-vault-1.25.0.tgz", - "integrity": "sha512-+3isN+iq0E5VE+pfluBcNYb2qFf/Zu5q44Neh3Bazl82vk86xdUbI2z2cYHgJq5bMgRW1kUOaGWsgXjYlGUhng==", + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/dotenv-vault/-/dotenv-vault-1.26.0.tgz", + "integrity": "sha512-2PNnlprtOdFEG9+hAAZxXegcjlJVZMSy88arnRR4YjwU/PwkDbdtk1uzw/D88D5EZ0b84n7YVQ6RccRXmW/Qzg==", "dev": true, "dependencies": { "@oclif/core": "^1", - "@oclif/plugin-help": "^5.2.11", - "@oclif/plugin-not-found": "^2.3.24", + "@oclif/plugin-help": "^5.2.15", + "@oclif/plugin-not-found": "^2.3.34", "@oclif/plugin-update": "^3.1.16", - "@oclif/plugin-warn-if-update-available": "^2.0.40", + "@oclif/plugin-warn-if-update-available": "^2.0.46", "axios": "^0.27.2", "chalk": "^4.1.2", "dotenv": "^16.3.1" diff --git a/ExpressAPI/package.json b/ExpressAPI/package.json index bce35f7..3807034 100644 --- a/ExpressAPI/package.json +++ b/ExpressAPI/package.json @@ -1,82 +1,82 @@ { - "name" : "dojo_backend_api", - "description" : "Backend API of the Dojo project", - "version" : "3.4.2", - "license" : "AGPLv3", - "author" : "Michaël Minelli <dojo@minelli.me>", - "main" : "dist/src/app.js", - "scripts" : { - "clean" : "rm -R dist/*", - "dotenv:build" : "npx dotenv-vault local build", - "lint" : "npx eslint .", - "genversion" : "npx genversion -s -e src/config/Version.ts", - "build:openapi" : "sed -i -r \"1,20 s/^\\([ ]*version:\\).*$/\\1 $(jq -r .version package.json)/\" assets/OpenAPI/OpenAPI.yaml; npx @redocly/cli build-docs assets/OpenAPI/OpenAPI.yaml --output=assets/OpenAPI/redoc.html", - "build:project" : "npm run genversion; npx prisma generate && npx tsc --project ./ && cp -R assets dist/assets", - "build" : "npm run build:openapi; npm run build:project", + "name": "dojo_backend_api", + "description": "Backend API of the Dojo project", + "version": "3.4.1", + "license": "AGPLv3", + "author": "Michaël Minelli <dojo@minelli.me>", + "main": "dist/src/app.js", + "scripts": { + "clean": "rm -R dist/*", + "dotenv:build": "npx dotenv-vault local build", + "lint": "npx eslint .", + "genversion": "npx genversion -s -e src/config/Version.ts", + "build:openapi": "sed -i -r \"1,20 s/^\\([ ]*version:\\).*$/\\1 $(jq -r .version package.json)/\" assets/OpenAPI/OpenAPI.yaml; npx @redocly/cli build-docs assets/OpenAPI/OpenAPI.yaml --output=assets/OpenAPI/redoc.html", + "build:project": "npm run genversion; npx prisma generate && npx tsc --project ./ && cp -R assets dist/assets", + "build": "npm run build:openapi; npm run build:project", "database:migrate:create": "npx dotenv -e .env.development -- npx prisma migrate dev", - "database:migrate:dev" : "npx dotenv -e .env.development -- npx prisma migrate deploy", - "database:migrate:prod" : "npx prisma migrate deploy", - "database:seed:dev" : "npm run genversion; npm run build; npx dotenv -e .env.development -- npx prisma db seed", - "database:seed:prod" : "npm run genversion; npm run build; NODE_ENV=production npx prisma db seed", - "database:deploy:dev" : "npm run database:migrate:dev && npm run database:seed:dev", - "database:deploy:prod" : "npm run database:migrate:prod && npm run database:seed:prod", - "start:dev" : "npm run genversion; npx nodemon src/app.ts", - "start:prod" : "npm run genversion; NODE_ENV=production npx node --max-http-header-size=1048576 dist/src/app.js", - "start:migrate:prod" : "npm run genversion; npm run database:deploy:prod && npm run start:prod" + "database:migrate:dev": "npx dotenv -e .env.development -- npx prisma migrate deploy", + "database:migrate:prod": "npx prisma migrate deploy", + "database:seed:dev": "npm run genversion; npm run build; npx dotenv -e .env.development -- npx prisma db seed", + "database:seed:prod": "npm run genversion; npm run build; NODE_ENV=production npx prisma db seed", + "database:deploy:dev": "npm run database:migrate:dev && npm run database:seed:dev", + "database:deploy:prod": "npm run database:migrate:prod && npm run database:seed:prod", + "start:dev": "npm run genversion; npx nodemon src/app.ts", + "start:prod": "npm run genversion; NODE_ENV=production npx node --max-http-header-size=1048576 dist/src/app.js", + "start:migrate:prod": "npm run genversion; npm run database:deploy:prod && npm run start:prod" }, - "prisma" : { + "prisma": { "seed": "node dist/prisma/seed" }, - "dependencies" : { - "@prisma/client" : "^5.8.1", - "axios" : "^1.6.5", - "compression" : "^1.7.4", - "cors" : "^2.8.5", - "dotenv" : "^16.3.1", - "dotenv-expand" : "^10.0.0", - "express" : "^4.18.2", - "express-validator" : "^7.0.1", - "form-data" : "^4.0.0", - "helmet" : "^7.1.0", - "http-status-codes" : "^2.3.0", - "json5" : "^2.2.3", - "jsonwebtoken" : "^9.0.2", - "morgan" : "^1.10.0", - "multer" : "^1.4.5-lts.1", - "mysql" : "^2.18.1", - "node" : "^20.10.0", - "parse-link-header" : "^2.0.0", - "semver" : "^7.5.4", - "swagger-ui-express" : "^5.0.0", - "tar-stream" : "^3.1.6", - "uuid" : "^9.0.1", - "winston" : "^3.11.0", - "zod" : "^3.22.4", + "dependencies": { + "@prisma/client": "^5.8.1", + "axios": "^1.6.5", + "compression": "^1.7.4", + "cors": "^2.8.5", + "dotenv": "^16.3.1", + "dotenv-expand": "^10.0.0", + "express": "^4.18.2", + "express-validator": "^7.0.1", + "form-data": "^4.0.0", + "helmet": "^7.1.0", + "http-status-codes": "^2.3.0", + "json5": "^2.2.3", + "jsonwebtoken": "^9.0.2", + "morgan": "^1.10.0", + "multer": "^1.4.5-lts.1", + "mysql": "^2.18.1", + "node": "^20.10.0", + "parse-link-header": "^2.0.0", + "semver": "^7.5.4", + "swagger-ui-express": "^5.0.0", + "tar-stream": "^3.1.6", + "uuid": "^9.0.1", + "winston": "^3.11.0", + "zod": "^3.22.4", "zod-validation-error": "^3.0.0" }, "devDependencies": { - "@redocly/cli" : "^1.6.0", - "@types/compression" : "^1.7.5", - "@types/cors" : "^2.8.17", - "@types/express" : "^4.17.21", - "@types/jsonwebtoken" : "^9.0.5", - "@types/morgan" : "^1.9.9", - "@types/multer" : "^1.4.11", - "@types/node" : "^20.11.5", - "@types/parse-link-header" : "^2.0.3", - "@types/semver" : "^7.5.6", - "@types/swagger-ui-express" : "^4.1.6", - "@types/tar-stream" : "^3.1.3", - "@types/uuid" : "^9.0.7", + "@redocly/cli": "^1.6.0", + "@types/compression": "^1.7.5", + "@types/cors": "^2.8.17", + "@types/express": "^4.17.21", + "@types/jsonwebtoken": "^9.0.5", + "@types/morgan": "^1.9.9", + "@types/multer": "^1.4.11", + "@types/node": "^20.11.5", + "@types/parse-link-header": "^2.0.3", + "@types/semver": "^7.5.6", + "@types/swagger-ui-express": "^4.1.6", + "@types/tar-stream": "^3.1.3", + "@types/uuid": "^9.0.7", "@typescript-eslint/eslint-plugin": "^6.18.1", - "@typescript-eslint/parser" : "^6.18.1", - "dotenv-cli" : "^7.3.0", - "dotenv-vault" : "^1.25.0", - "genversion" : "^3.2.0", - "nodemon" : "^3.0.3", - "npm" : "^10.3.0", - "prisma" : "^5.8.1", - "ts-node" : "^10.9.2", - "typescript" : "^5.3.3" + "@typescript-eslint/parser": "^6.18.1", + "dotenv-cli": "^7.3.0", + "dotenv-vault": "^1.26.0", + "genversion": "^3.2.0", + "nodemon": "^3.0.3", + "npm": "^10.3.0", + "prisma": "^5.8.1", + "ts-node": "^10.9.2", + "typescript": "^5.3.3" } } diff --git a/ExpressAPI/prisma/seed.ts b/ExpressAPI/prisma/seed.ts index 20249cf..4e2c1d4 100644 --- a/ExpressAPI/prisma/seed.ts +++ b/ExpressAPI/prisma/seed.ts @@ -26,1557 +26,1557 @@ main().then(async () => { async function users() { await db.user.upsert({ - where : { id: 142 }, - update: {}, - create: { - id : 142, - gitlabUsername: 'michael.minelli', - gitlabLastInfo: {}, - role : UserRole.ADMIN, - deleted : false - } - }); + where : { id: 142 }, + update: {}, + create: { + id : 142, + gitlabUsername: 'michael.minelli', + gitlabLastInfo: {}, + role : UserRole.ADMIN, + deleted : false + } + }); await db.user.upsert({ - where : { id: 133 }, - update: {}, - create: { - id : 133, - gitlabUsername: 'orestis.malaspin', - gitlabLastInfo: {}, - role : UserRole.ADMIN, - deleted : false - } - }); + where : { id: 133 }, + update: {}, + create: { + id : 133, + gitlabUsername: 'orestis.malaspin', + gitlabLastInfo: {}, + role : UserRole.ADMIN, + deleted : false + } + }); if ( !SharedConfig.production ) { await db.user.upsert({ - where : { id: 627 }, - update: {}, - create: { - id : 627, - gitlabUsername: 'kelly.nguyen', - gitlabLastInfo: {}, - role : UserRole.ADMIN, - deleted : false - } - }); + where : { id: 627 }, + update: {}, + create: { + id : 627, + gitlabUsername: 'kelly.nguyen', + gitlabLastInfo: {}, + role : UserRole.ADMIN, + deleted : false + } + }); await db.user.upsert({ - where : { id: 623 }, - update: {}, - create: { - id : 623, - gitlabUsername: 'bedran.sezer', - gitlabLastInfo: {}, - role : UserRole.ADMIN, - deleted : false - } - }); + where : { id: 623 }, + update: {}, + create: { + id : 623, + gitlabUsername: 'bedran.sezer', + gitlabLastInfo: {}, + role : UserRole.ADMIN, + deleted : false + } + }); await db.user.upsert({ - where : { id: 642 }, - update: {}, - create: { - id : 642, - gitlabUsername: 'vincent.steinman', - gitlabLastInfo: {}, - role : UserRole.ADMIN, - deleted : false - } - }); + where : { id: 642 }, + update: {}, + create: { + id : 642, + gitlabUsername: 'vincent.steinman', + gitlabLastInfo: {}, + role : UserRole.ADMIN, + deleted : false + } + }); } } async function assignments() { if ( !SharedConfig.production ) { await db.assignment.upsert({ - where : { name: 'c_hello_world' }, - update: {}, - create: { - name : 'c_hello_world', - gitlabId : 13862, - gitlabLink : 'https://gitedu.hesge.ch/dojodev/assignment/c_hello_world', - gitlabCreationInfo: { - 'id' : 13862, - 'description' : 'Dojo assignment repository.\n\nName of the assignment: c_hello_world', - 'name' : 'c_hello_world', - 'name_with_namespace' : 'DojoDev / Assignment / c_hello_world', - 'path' : 'c_hello_world', - 'path_with_namespace' : 'dojodev/assignment/c_hello_world', - 'created_at' : '2023-11-02T22:20:15.239+01:00', - 'default_branch' : 'main', - 'tag_list' : [], - 'topics' : [], - 'ssh_url_to_repo' : 'ssh://git@ssh.hesge.ch:10572/dojodev/assignment/c_hello_world.git', - 'http_url_to_repo' : 'https://gitedu.hesge.ch/dojodev/assignment/c_hello_world.git', - 'web_url' : 'https://gitedu.hesge.ch/dojodev/assignment/c_hello_world', - 'readme_url' : null, - 'forks_count' : 0, - 'avatar_url' : null, - 'star_count' : 0, - 'last_activity_at' : '2023-11-02T22:20:15.239+01:00', - 'namespace' : { - 'id' : 14190, - 'name' : 'Assignment', - 'path' : 'assignment', - 'kind' : 'group', - 'full_path' : 'dojodev/assignment', - 'parent_id' : 14189, - 'avatar_url': null, - 'web_url' : 'https://gitedu.hesge.ch/groups/dojodev/assignment' - }, - '_links' : { - 'self' : 'https://gitedu.hesge.ch/api/v4/projects/13862', - 'issues' : 'https://gitedu.hesge.ch/api/v4/projects/13862/issues', - 'merge_requests': 'https://gitedu.hesge.ch/api/v4/projects/13862/merge_requests', - 'repo_branches' : 'https://gitedu.hesge.ch/api/v4/projects/13862/repository/branches', - 'labels' : 'https://gitedu.hesge.ch/api/v4/projects/13862/labels', - 'events' : 'https://gitedu.hesge.ch/api/v4/projects/13862/events', - 'members' : 'https://gitedu.hesge.ch/api/v4/projects/13862/members', - 'cluster_agents': 'https://gitedu.hesge.ch/api/v4/projects/13862/cluster_agents' - }, - 'packages_enabled' : true, - 'empty_repo' : true, - 'archived' : false, - 'visibility' : 'private', - 'resolve_outdated_diff_discussions' : false, - 'container_expiration_policy' : { - 'cadence' : '1d', - 'enabled' : false, - 'keep_n' : 10, - 'older_than' : '90d', - 'name_regex' : '.*', - 'name_regex_keep': null, - 'next_run_at' : '2023-11-03T22:20:15.275+01:00' - }, - 'issues_enabled' : true, - 'merge_requests_enabled' : true, - 'wiki_enabled' : false, - 'jobs_enabled' : true, - 'snippets_enabled' : true, - 'container_registry_enabled' : true, - 'service_desk_enabled' : false, - 'service_desk_address' : null, - 'can_create_merge_request_in' : true, - 'issues_access_level' : 'enabled', - 'repository_access_level' : 'enabled', - 'merge_requests_access_level' : 'enabled', - 'forking_access_level' : 'enabled', - 'wiki_access_level' : 'disabled', - 'builds_access_level' : 'enabled', - 'snippets_access_level' : 'enabled', - 'pages_access_level' : 'private', - 'analytics_access_level' : 'enabled', - 'container_registry_access_level' : 'enabled', - 'security_and_compliance_access_level' : 'private', - 'releases_access_level' : 'enabled', - 'environments_access_level' : 'enabled', - 'feature_flags_access_level' : 'enabled', - 'infrastructure_access_level' : 'enabled', - 'monitor_access_level' : 'enabled', - 'emails_disabled' : null, - 'shared_runners_enabled' : true, - 'lfs_enabled' : true, - 'creator_id' : 1076, - 'import_url' : 'https://gitedu.hesge.ch/dojodev/template/empty_template.git', - 'import_type' : 'git', - 'import_status' : 'scheduled', - 'import_error' : null, - 'open_issues_count' : 0, - 'description_html' : '<p data-sourcepos="1:1-1:27" dir="auto">Dojo assignment repository.</p>\n<p data-sourcepos="3:1-3:37" dir="auto">Name of the assignment: c_hello_world</p>', - 'updated_at' : '2023-11-02T22:20:15.239+01:00', - 'ci_default_git_depth' : 20, - 'ci_forward_deployment_enabled' : true, - 'ci_job_token_scope_enabled' : false, - 'ci_separated_caches' : true, - 'ci_allow_fork_pipelines_to_run_in_parent_project': true, - 'build_git_strategy' : 'fetch', - 'keep_latest_artifact' : true, - 'restrict_user_defined_variables' : false, - 'runners_token' : 'GR1348941TZKVMY5xH7ecxwLxn1x7', - 'runner_token_expiration_interval' : null, - 'group_runners_enabled' : true, - 'auto_cancel_pending_pipelines' : 'enabled', - 'build_timeout' : 3600, - 'auto_devops_enabled' : false, - 'auto_devops_deploy_strategy' : 'continuous', - 'ci_config_path' : '', - 'public_jobs' : true, - 'shared_with_groups' : [], - 'only_allow_merge_if_pipeline_succeeds' : false, - 'allow_merge_on_skipped_pipeline' : null, - 'request_access_enabled' : true, - 'only_allow_merge_if_all_discussions_are_resolved': false, - 'remove_source_branch_after_merge' : true, - 'printing_merge_request_link_enabled' : true, - 'merge_method' : 'merge', - 'squash_option' : 'default_off', - 'enforce_auth_checks_on_uploads' : true, - 'suggestion_commit_message' : null, - 'merge_commit_template' : null, - 'squash_commit_template' : null, - 'issue_branch_template' : null, - 'autoclose_referenced_issues' : true - }, - gitlabLastInfo : { - 'id' : 13862, - 'description' : 'Dojo assignment repository.\n\nName of the assignment: c_hello_world', - 'name' : 'c_hello_world', - 'name_with_namespace' : 'DojoDev / Assignment / c_hello_world', - 'path' : 'c_hello_world', - 'path_with_namespace' : 'dojodev/assignment/c_hello_world', - 'created_at' : '2023-11-02T22:20:15.239+01:00', - 'default_branch' : 'main', - 'tag_list' : [], - 'topics' : [], - 'ssh_url_to_repo' : 'ssh://git@ssh.hesge.ch:10572/dojodev/assignment/c_hello_world.git', - 'http_url_to_repo' : 'https://gitedu.hesge.ch/dojodev/assignment/c_hello_world.git', - 'web_url' : 'https://gitedu.hesge.ch/dojodev/assignment/c_hello_world', - 'readme_url' : null, - 'forks_count' : 0, - 'avatar_url' : null, - 'star_count' : 0, - 'last_activity_at' : '2023-11-02T22:20:15.239+01:00', - 'namespace' : { - 'id' : 14190, - 'name' : 'Assignment', - 'path' : 'assignment', - 'kind' : 'group', - 'full_path' : 'dojodev/assignment', - 'parent_id' : 14189, - 'avatar_url': null, - 'web_url' : 'https://gitedu.hesge.ch/groups/dojodev/assignment' - }, - '_links' : { - 'self' : 'https://gitedu.hesge.ch/api/v4/projects/13862', - 'issues' : 'https://gitedu.hesge.ch/api/v4/projects/13862/issues', - 'merge_requests': 'https://gitedu.hesge.ch/api/v4/projects/13862/merge_requests', - 'repo_branches' : 'https://gitedu.hesge.ch/api/v4/projects/13862/repository/branches', - 'labels' : 'https://gitedu.hesge.ch/api/v4/projects/13862/labels', - 'events' : 'https://gitedu.hesge.ch/api/v4/projects/13862/events', - 'members' : 'https://gitedu.hesge.ch/api/v4/projects/13862/members', - 'cluster_agents': 'https://gitedu.hesge.ch/api/v4/projects/13862/cluster_agents' - }, - 'packages_enabled' : true, - 'empty_repo' : true, - 'archived' : false, - 'visibility' : 'private', - 'resolve_outdated_diff_discussions' : false, - 'container_expiration_policy' : { - 'cadence' : '1d', - 'enabled' : false, - 'keep_n' : 10, - 'older_than' : '90d', - 'name_regex' : '.*', - 'name_regex_keep': null, - 'next_run_at' : '2023-11-03T22:20:15.275+01:00' - }, - 'issues_enabled' : true, - 'merge_requests_enabled' : true, - 'wiki_enabled' : false, - 'jobs_enabled' : true, - 'snippets_enabled' : true, - 'container_registry_enabled' : true, - 'service_desk_enabled' : false, - 'service_desk_address' : null, - 'can_create_merge_request_in' : true, - 'issues_access_level' : 'enabled', - 'repository_access_level' : 'enabled', - 'merge_requests_access_level' : 'enabled', - 'forking_access_level' : 'enabled', - 'wiki_access_level' : 'disabled', - 'builds_access_level' : 'enabled', - 'snippets_access_level' : 'enabled', - 'pages_access_level' : 'private', - 'analytics_access_level' : 'enabled', - 'container_registry_access_level' : 'enabled', - 'security_and_compliance_access_level' : 'private', - 'releases_access_level' : 'enabled', - 'environments_access_level' : 'enabled', - 'feature_flags_access_level' : 'enabled', - 'infrastructure_access_level' : 'enabled', - 'monitor_access_level' : 'enabled', - 'emails_disabled' : null, - 'shared_runners_enabled' : true, - 'lfs_enabled' : true, - 'creator_id' : 1076, - 'import_url' : 'https://gitedu.hesge.ch/dojodev/template/empty_template.git', - 'import_type' : 'git', - 'import_status' : 'scheduled', - 'import_error' : null, - 'open_issues_count' : 0, - 'description_html' : '<p data-sourcepos="1:1-1:27" dir="auto">Dojo assignment repository.</p>\n<p data-sourcepos="3:1-3:37" dir="auto">Name of the assignment: c_hello_world</p>', - 'updated_at' : '2023-11-02T22:20:15.239+01:00', - 'ci_default_git_depth' : 20, - 'ci_forward_deployment_enabled' : true, - 'ci_job_token_scope_enabled' : false, - 'ci_separated_caches' : true, - 'ci_allow_fork_pipelines_to_run_in_parent_project': true, - 'build_git_strategy' : 'fetch', - 'keep_latest_artifact' : true, - 'restrict_user_defined_variables' : false, - 'runners_token' : 'GR1348941TZKVMY5xH7ecxwLxn1x7', - 'runner_token_expiration_interval' : null, - 'group_runners_enabled' : true, - 'auto_cancel_pending_pipelines' : 'enabled', - 'build_timeout' : 3600, - 'auto_devops_enabled' : false, - 'auto_devops_deploy_strategy' : 'continuous', - 'ci_config_path' : '', - 'public_jobs' : true, - 'shared_with_groups' : [], - 'only_allow_merge_if_pipeline_succeeds' : false, - 'allow_merge_on_skipped_pipeline' : null, - 'request_access_enabled' : true, - 'only_allow_merge_if_all_discussions_are_resolved': false, - 'remove_source_branch_after_merge' : true, - 'printing_merge_request_link_enabled' : true, - 'merge_method' : 'merge', - 'squash_option' : 'default_off', - 'enforce_auth_checks_on_uploads' : true, - 'suggestion_commit_message' : null, - 'merge_commit_template' : null, - 'squash_commit_template' : null, - 'issue_branch_template' : null, - 'autoclose_referenced_issues' : true - }, - gitlabLastInfoDate: new Date('2021-10-14T14:20:15.239Z'), - published : false - } - }); + where : { name: 'c_hello_world' }, + update: {}, + create: { + name : 'c_hello_world', + gitlabId : 13862, + gitlabLink : 'https://gitedu.hesge.ch/dojodev/assignment/c_hello_world', + gitlabCreationInfo: { + 'id' : 13862, + 'description' : 'Dojo assignment repository.\n\nName of the assignment: c_hello_world', + 'name' : 'c_hello_world', + 'name_with_namespace' : 'DojoDev / Assignment / c_hello_world', + 'path' : 'c_hello_world', + 'path_with_namespace' : 'dojodev/assignment/c_hello_world', + 'created_at' : '2023-11-02T22:20:15.239+01:00', + 'default_branch' : 'main', + 'tag_list' : [], + 'topics' : [], + 'ssh_url_to_repo' : 'ssh://git@ssh.hesge.ch:10572/dojodev/assignment/c_hello_world.git', + 'http_url_to_repo' : 'https://gitedu.hesge.ch/dojodev/assignment/c_hello_world.git', + 'web_url' : 'https://gitedu.hesge.ch/dojodev/assignment/c_hello_world', + 'readme_url' : null, + 'forks_count' : 0, + 'avatar_url' : null, + 'star_count' : 0, + 'last_activity_at' : '2023-11-02T22:20:15.239+01:00', + 'namespace' : { + 'id' : 14190, + 'name' : 'Assignment', + 'path' : 'assignment', + 'kind' : 'group', + 'full_path' : 'dojodev/assignment', + 'parent_id' : 14189, + 'avatar_url': null, + 'web_url' : 'https://gitedu.hesge.ch/groups/dojodev/assignment' + }, + '_links' : { + 'self' : 'https://gitedu.hesge.ch/api/v4/projects/13862', + 'issues' : 'https://gitedu.hesge.ch/api/v4/projects/13862/issues', + 'merge_requests': 'https://gitedu.hesge.ch/api/v4/projects/13862/merge_requests', + 'repo_branches' : 'https://gitedu.hesge.ch/api/v4/projects/13862/repository/branches', + 'labels' : 'https://gitedu.hesge.ch/api/v4/projects/13862/labels', + 'events' : 'https://gitedu.hesge.ch/api/v4/projects/13862/events', + 'members' : 'https://gitedu.hesge.ch/api/v4/projects/13862/members', + 'cluster_agents': 'https://gitedu.hesge.ch/api/v4/projects/13862/cluster_agents' + }, + 'packages_enabled' : true, + 'empty_repo' : true, + 'archived' : false, + 'visibility' : 'private', + 'resolve_outdated_diff_discussions' : false, + 'container_expiration_policy' : { + 'cadence' : '1d', + 'enabled' : false, + 'keep_n' : 10, + 'older_than' : '90d', + 'name_regex' : '.*', + 'name_regex_keep': null, + 'next_run_at' : '2023-11-03T22:20:15.275+01:00' + }, + 'issues_enabled' : true, + 'merge_requests_enabled' : true, + 'wiki_enabled' : false, + 'jobs_enabled' : true, + 'snippets_enabled' : true, + 'container_registry_enabled' : true, + 'service_desk_enabled' : false, + 'service_desk_address' : null, + 'can_create_merge_request_in' : true, + 'issues_access_level' : 'enabled', + 'repository_access_level' : 'enabled', + 'merge_requests_access_level' : 'enabled', + 'forking_access_level' : 'enabled', + 'wiki_access_level' : 'disabled', + 'builds_access_level' : 'enabled', + 'snippets_access_level' : 'enabled', + 'pages_access_level' : 'private', + 'analytics_access_level' : 'enabled', + 'container_registry_access_level' : 'enabled', + 'security_and_compliance_access_level' : 'private', + 'releases_access_level' : 'enabled', + 'environments_access_level' : 'enabled', + 'feature_flags_access_level' : 'enabled', + 'infrastructure_access_level' : 'enabled', + 'monitor_access_level' : 'enabled', + 'emails_disabled' : null, + 'shared_runners_enabled' : true, + 'lfs_enabled' : true, + 'creator_id' : 1076, + 'import_url' : 'https://gitedu.hesge.ch/dojodev/template/empty_template.git', + 'import_type' : 'git', + 'import_status' : 'scheduled', + 'import_error' : null, + 'open_issues_count' : 0, + 'description_html' : '<p data-sourcepos="1:1-1:27" dir="auto">Dojo assignment repository.</p>\n<p data-sourcepos="3:1-3:37" dir="auto">Name of the assignment: c_hello_world</p>', + 'updated_at' : '2023-11-02T22:20:15.239+01:00', + 'ci_default_git_depth' : 20, + 'ci_forward_deployment_enabled' : true, + 'ci_job_token_scope_enabled' : false, + 'ci_separated_caches' : true, + 'ci_allow_fork_pipelines_to_run_in_parent_project': true, + 'build_git_strategy' : 'fetch', + 'keep_latest_artifact' : true, + 'restrict_user_defined_variables' : false, + 'runners_token' : 'GR1348941TZKVMY5xH7ecxwLxn1x7', + 'runner_token_expiration_interval' : null, + 'group_runners_enabled' : true, + 'auto_cancel_pending_pipelines' : 'enabled', + 'build_timeout' : 3600, + 'auto_devops_enabled' : false, + 'auto_devops_deploy_strategy' : 'continuous', + 'ci_config_path' : '', + 'public_jobs' : true, + 'shared_with_groups' : [], + 'only_allow_merge_if_pipeline_succeeds' : false, + 'allow_merge_on_skipped_pipeline' : null, + 'request_access_enabled' : true, + 'only_allow_merge_if_all_discussions_are_resolved': false, + 'remove_source_branch_after_merge' : true, + 'printing_merge_request_link_enabled' : true, + 'merge_method' : 'merge', + 'squash_option' : 'default_off', + 'enforce_auth_checks_on_uploads' : true, + 'suggestion_commit_message' : null, + 'merge_commit_template' : null, + 'squash_commit_template' : null, + 'issue_branch_template' : null, + 'autoclose_referenced_issues' : true + }, + gitlabLastInfo : { + 'id' : 13862, + 'description' : 'Dojo assignment repository.\n\nName of the assignment: c_hello_world', + 'name' : 'c_hello_world', + 'name_with_namespace' : 'DojoDev / Assignment / c_hello_world', + 'path' : 'c_hello_world', + 'path_with_namespace' : 'dojodev/assignment/c_hello_world', + 'created_at' : '2023-11-02T22:20:15.239+01:00', + 'default_branch' : 'main', + 'tag_list' : [], + 'topics' : [], + 'ssh_url_to_repo' : 'ssh://git@ssh.hesge.ch:10572/dojodev/assignment/c_hello_world.git', + 'http_url_to_repo' : 'https://gitedu.hesge.ch/dojodev/assignment/c_hello_world.git', + 'web_url' : 'https://gitedu.hesge.ch/dojodev/assignment/c_hello_world', + 'readme_url' : null, + 'forks_count' : 0, + 'avatar_url' : null, + 'star_count' : 0, + 'last_activity_at' : '2023-11-02T22:20:15.239+01:00', + 'namespace' : { + 'id' : 14190, + 'name' : 'Assignment', + 'path' : 'assignment', + 'kind' : 'group', + 'full_path' : 'dojodev/assignment', + 'parent_id' : 14189, + 'avatar_url': null, + 'web_url' : 'https://gitedu.hesge.ch/groups/dojodev/assignment' + }, + '_links' : { + 'self' : 'https://gitedu.hesge.ch/api/v4/projects/13862', + 'issues' : 'https://gitedu.hesge.ch/api/v4/projects/13862/issues', + 'merge_requests': 'https://gitedu.hesge.ch/api/v4/projects/13862/merge_requests', + 'repo_branches' : 'https://gitedu.hesge.ch/api/v4/projects/13862/repository/branches', + 'labels' : 'https://gitedu.hesge.ch/api/v4/projects/13862/labels', + 'events' : 'https://gitedu.hesge.ch/api/v4/projects/13862/events', + 'members' : 'https://gitedu.hesge.ch/api/v4/projects/13862/members', + 'cluster_agents': 'https://gitedu.hesge.ch/api/v4/projects/13862/cluster_agents' + }, + 'packages_enabled' : true, + 'empty_repo' : true, + 'archived' : false, + 'visibility' : 'private', + 'resolve_outdated_diff_discussions' : false, + 'container_expiration_policy' : { + 'cadence' : '1d', + 'enabled' : false, + 'keep_n' : 10, + 'older_than' : '90d', + 'name_regex' : '.*', + 'name_regex_keep': null, + 'next_run_at' : '2023-11-03T22:20:15.275+01:00' + }, + 'issues_enabled' : true, + 'merge_requests_enabled' : true, + 'wiki_enabled' : false, + 'jobs_enabled' : true, + 'snippets_enabled' : true, + 'container_registry_enabled' : true, + 'service_desk_enabled' : false, + 'service_desk_address' : null, + 'can_create_merge_request_in' : true, + 'issues_access_level' : 'enabled', + 'repository_access_level' : 'enabled', + 'merge_requests_access_level' : 'enabled', + 'forking_access_level' : 'enabled', + 'wiki_access_level' : 'disabled', + 'builds_access_level' : 'enabled', + 'snippets_access_level' : 'enabled', + 'pages_access_level' : 'private', + 'analytics_access_level' : 'enabled', + 'container_registry_access_level' : 'enabled', + 'security_and_compliance_access_level' : 'private', + 'releases_access_level' : 'enabled', + 'environments_access_level' : 'enabled', + 'feature_flags_access_level' : 'enabled', + 'infrastructure_access_level' : 'enabled', + 'monitor_access_level' : 'enabled', + 'emails_disabled' : null, + 'shared_runners_enabled' : true, + 'lfs_enabled' : true, + 'creator_id' : 1076, + 'import_url' : 'https://gitedu.hesge.ch/dojodev/template/empty_template.git', + 'import_type' : 'git', + 'import_status' : 'scheduled', + 'import_error' : null, + 'open_issues_count' : 0, + 'description_html' : '<p data-sourcepos="1:1-1:27" dir="auto">Dojo assignment repository.</p>\n<p data-sourcepos="3:1-3:37" dir="auto">Name of the assignment: c_hello_world</p>', + 'updated_at' : '2023-11-02T22:20:15.239+01:00', + 'ci_default_git_depth' : 20, + 'ci_forward_deployment_enabled' : true, + 'ci_job_token_scope_enabled' : false, + 'ci_separated_caches' : true, + 'ci_allow_fork_pipelines_to_run_in_parent_project': true, + 'build_git_strategy' : 'fetch', + 'keep_latest_artifact' : true, + 'restrict_user_defined_variables' : false, + 'runners_token' : 'GR1348941TZKVMY5xH7ecxwLxn1x7', + 'runner_token_expiration_interval' : null, + 'group_runners_enabled' : true, + 'auto_cancel_pending_pipelines' : 'enabled', + 'build_timeout' : 3600, + 'auto_devops_enabled' : false, + 'auto_devops_deploy_strategy' : 'continuous', + 'ci_config_path' : '', + 'public_jobs' : true, + 'shared_with_groups' : [], + 'only_allow_merge_if_pipeline_succeeds' : false, + 'allow_merge_on_skipped_pipeline' : null, + 'request_access_enabled' : true, + 'only_allow_merge_if_all_discussions_are_resolved': false, + 'remove_source_branch_after_merge' : true, + 'printing_merge_request_link_enabled' : true, + 'merge_method' : 'merge', + 'squash_option' : 'default_off', + 'enforce_auth_checks_on_uploads' : true, + 'suggestion_commit_message' : null, + 'merge_commit_template' : null, + 'squash_commit_template' : null, + 'issue_branch_template' : null, + 'autoclose_referenced_issues' : true + }, + gitlabLastInfoDate: new Date('2021-10-14T14:20:15.239Z'), + published : false + } + }); await db.assignment.upsert({ - where : { name: 'Technique de compilation - TP' }, - update: {}, - create: { - name : 'Technique de compilation - TP', - gitlabId : 13893, - gitlabLink : 'https://gitedu.hesge.ch/dojodev/assignment/technique-de-compilation-tp', - gitlabCreationInfo: { - 'id' : 13893, - 'description' : 'Dojo assignment repository.\n\nName of the assignment: Technique de compilation - TP', - 'name' : 'Technique de compilation - TP', - 'name_with_namespace' : 'DojoDev / Assignment / Technique de compilation - TP', - 'path' : 'technique-de-compilation-tp', - 'path_with_namespace' : 'dojodev/assignment/technique-de-compilation-tp', - 'created_at' : '2023-11-07T21:35:48.454+01:00', - 'default_branch' : 'main', - 'tag_list' : [], - 'topics' : [], - 'ssh_url_to_repo' : 'ssh://git@ssh.hesge.ch:10572/dojodev/assignment/technique-de-compilation-tp.git', - 'http_url_to_repo' : 'https://gitedu.hesge.ch/dojodev/assignment/technique-de-compilation-tp.git', - 'web_url' : 'https://gitedu.hesge.ch/dojodev/assignment/technique-de-compilation-tp', - 'readme_url' : null, - 'forks_count' : 0, - 'avatar_url' : null, - 'star_count' : 0, - 'last_activity_at' : '2023-11-07T21:35:48.454+01:00', - 'namespace' : { - 'id' : 14190, - 'name' : 'Assignment', - 'path' : 'assignment', - 'kind' : 'group', - 'full_path' : 'dojodev/assignment', - 'parent_id' : 14189, - 'avatar_url': null, - 'web_url' : 'https://gitedu.hesge.ch/groups/dojodev/assignment' - }, - '_links' : { - 'self' : 'https://gitedu.hesge.ch/api/v4/projects/13893', - 'issues' : 'https://gitedu.hesge.ch/api/v4/projects/13893/issues', - 'merge_requests': 'https://gitedu.hesge.ch/api/v4/projects/13893/merge_requests', - 'repo_branches' : 'https://gitedu.hesge.ch/api/v4/projects/13893/repository/branches', - 'labels' : 'https://gitedu.hesge.ch/api/v4/projects/13893/labels', - 'events' : 'https://gitedu.hesge.ch/api/v4/projects/13893/events', - 'members' : 'https://gitedu.hesge.ch/api/v4/projects/13893/members', - 'cluster_agents': 'https://gitedu.hesge.ch/api/v4/projects/13893/cluster_agents' - }, - 'packages_enabled' : true, - 'empty_repo' : true, - 'archived' : false, - 'visibility' : 'private', - 'resolve_outdated_diff_discussions' : false, - 'container_expiration_policy' : { - 'cadence' : '1d', - 'enabled' : false, - 'keep_n' : 10, - 'older_than' : '90d', - 'name_regex' : '.*', - 'name_regex_keep': null, - 'next_run_at' : '2023-11-08T21:35:48.543+01:00' - }, - 'issues_enabled' : true, - 'merge_requests_enabled' : true, - 'wiki_enabled' : false, - 'jobs_enabled' : true, - 'snippets_enabled' : true, - 'container_registry_enabled' : true, - 'service_desk_enabled' : false, - 'service_desk_address' : null, - 'can_create_merge_request_in' : true, - 'issues_access_level' : 'enabled', - 'repository_access_level' : 'enabled', - 'merge_requests_access_level' : 'enabled', - 'forking_access_level' : 'enabled', - 'wiki_access_level' : 'disabled', - 'builds_access_level' : 'enabled', - 'snippets_access_level' : 'enabled', - 'pages_access_level' : 'private', - 'analytics_access_level' : 'enabled', - 'container_registry_access_level' : 'enabled', - 'security_and_compliance_access_level' : 'private', - 'releases_access_level' : 'enabled', - 'environments_access_level' : 'enabled', - 'feature_flags_access_level' : 'enabled', - 'infrastructure_access_level' : 'enabled', - 'monitor_access_level' : 'enabled', - 'emails_disabled' : null, - 'shared_runners_enabled' : true, - 'lfs_enabled' : true, - 'creator_id' : 1076, - 'import_url' : 'https://gitedu.hesge.ch/dojodev/template/empty_template.git', - 'import_type' : 'git', - 'import_status' : 'scheduled', - 'import_error' : null, - 'open_issues_count' : 0, - 'description_html' : '<p data-sourcepos="1:1-1:27" dir="auto">Dojo assignment repository.</p>\n<p data-sourcepos="3:1-3:53" dir="auto">Name of the assignment: Technique de compilation - TP</p>', - 'updated_at' : '2023-11-07T21:35:48.454+01:00', - 'ci_default_git_depth' : 20, - 'ci_forward_deployment_enabled' : true, - 'ci_job_token_scope_enabled' : false, - 'ci_separated_caches' : true, - 'ci_allow_fork_pipelines_to_run_in_parent_project': true, - 'build_git_strategy' : 'fetch', - 'keep_latest_artifact' : true, - 'restrict_user_defined_variables' : false, - 'runners_token' : 'GR1348941qn9Ju1u5yTSLoWUTWLZy', - 'runner_token_expiration_interval' : null, - 'group_runners_enabled' : true, - 'auto_cancel_pending_pipelines' : 'enabled', - 'build_timeout' : 3600, - 'auto_devops_enabled' : false, - 'auto_devops_deploy_strategy' : 'continuous', - 'ci_config_path' : '', - 'public_jobs' : true, - 'shared_with_groups' : [], - 'only_allow_merge_if_pipeline_succeeds' : false, - 'allow_merge_on_skipped_pipeline' : null, - 'request_access_enabled' : true, - 'only_allow_merge_if_all_discussions_are_resolved': false, - 'remove_source_branch_after_merge' : true, - 'printing_merge_request_link_enabled' : true, - 'merge_method' : 'merge', - 'squash_option' : 'default_off', - 'enforce_auth_checks_on_uploads' : true, - 'suggestion_commit_message' : null, - 'merge_commit_template' : null, - 'squash_commit_template' : null, - 'issue_branch_template' : null, - 'autoclose_referenced_issues' : true - }, - gitlabLastInfo : { - 'id' : 13893, - 'description' : 'Dojo assignment repository.\n\nName of the assignment: Technique de compilation - TP', - 'name' : 'Technique de compilation - TP', - 'name_with_namespace' : 'DojoDev / Assignment / Technique de compilation - TP', - 'path' : 'technique-de-compilation-tp', - 'path_with_namespace' : 'dojodev/assignment/technique-de-compilation-tp', - 'created_at' : '2023-11-07T21:35:48.454+01:00', - 'default_branch' : 'main', - 'tag_list' : [], - 'topics' : [], - 'ssh_url_to_repo' : 'ssh://git@ssh.hesge.ch:10572/dojodev/assignment/technique-de-compilation-tp.git', - 'http_url_to_repo' : 'https://gitedu.hesge.ch/dojodev/assignment/technique-de-compilation-tp.git', - 'web_url' : 'https://gitedu.hesge.ch/dojodev/assignment/technique-de-compilation-tp', - 'readme_url' : null, - 'forks_count' : 0, - 'avatar_url' : null, - 'star_count' : 0, - 'last_activity_at' : '2023-11-07T21:35:48.454+01:00', - 'namespace' : { - 'id' : 14190, - 'name' : 'Assignment', - 'path' : 'assignment', - 'kind' : 'group', - 'full_path' : 'dojodev/assignment', - 'parent_id' : 14189, - 'avatar_url': null, - 'web_url' : 'https://gitedu.hesge.ch/groups/dojodev/assignment' - }, - '_links' : { - 'self' : 'https://gitedu.hesge.ch/api/v4/projects/13893', - 'issues' : 'https://gitedu.hesge.ch/api/v4/projects/13893/issues', - 'merge_requests': 'https://gitedu.hesge.ch/api/v4/projects/13893/merge_requests', - 'repo_branches' : 'https://gitedu.hesge.ch/api/v4/projects/13893/repository/branches', - 'labels' : 'https://gitedu.hesge.ch/api/v4/projects/13893/labels', - 'events' : 'https://gitedu.hesge.ch/api/v4/projects/13893/events', - 'members' : 'https://gitedu.hesge.ch/api/v4/projects/13893/members', - 'cluster_agents': 'https://gitedu.hesge.ch/api/v4/projects/13893/cluster_agents' - }, - 'packages_enabled' : true, - 'empty_repo' : true, - 'archived' : false, - 'visibility' : 'private', - 'resolve_outdated_diff_discussions' : false, - 'container_expiration_policy' : { - 'cadence' : '1d', - 'enabled' : false, - 'keep_n' : 10, - 'older_than' : '90d', - 'name_regex' : '.*', - 'name_regex_keep': null, - 'next_run_at' : '2023-11-08T21:35:48.543+01:00' - }, - 'issues_enabled' : true, - 'merge_requests_enabled' : true, - 'wiki_enabled' : false, - 'jobs_enabled' : true, - 'snippets_enabled' : true, - 'container_registry_enabled' : true, - 'service_desk_enabled' : false, - 'service_desk_address' : null, - 'can_create_merge_request_in' : true, - 'issues_access_level' : 'enabled', - 'repository_access_level' : 'enabled', - 'merge_requests_access_level' : 'enabled', - 'forking_access_level' : 'enabled', - 'wiki_access_level' : 'disabled', - 'builds_access_level' : 'enabled', - 'snippets_access_level' : 'enabled', - 'pages_access_level' : 'private', - 'analytics_access_level' : 'enabled', - 'container_registry_access_level' : 'enabled', - 'security_and_compliance_access_level' : 'private', - 'releases_access_level' : 'enabled', - 'environments_access_level' : 'enabled', - 'feature_flags_access_level' : 'enabled', - 'infrastructure_access_level' : 'enabled', - 'monitor_access_level' : 'enabled', - 'emails_disabled' : null, - 'shared_runners_enabled' : true, - 'lfs_enabled' : true, - 'creator_id' : 1076, - 'import_url' : 'https://gitedu.hesge.ch/dojodev/template/empty_template.git', - 'import_type' : 'git', - 'import_status' : 'scheduled', - 'import_error' : null, - 'open_issues_count' : 0, - 'description_html' : '<p data-sourcepos="1:1-1:27" dir="auto">Dojo assignment repository.</p>\n<p data-sourcepos="3:1-3:53" dir="auto">Name of the assignment: Technique de compilation - TP</p>', - 'updated_at' : '2023-11-07T21:35:48.454+01:00', - 'ci_default_git_depth' : 20, - 'ci_forward_deployment_enabled' : true, - 'ci_job_token_scope_enabled' : false, - 'ci_separated_caches' : true, - 'ci_allow_fork_pipelines_to_run_in_parent_project': true, - 'build_git_strategy' : 'fetch', - 'keep_latest_artifact' : true, - 'restrict_user_defined_variables' : false, - 'runners_token' : 'GR1348941qn9Ju1u5yTSLoWUTWLZy', - 'runner_token_expiration_interval' : null, - 'group_runners_enabled' : true, - 'auto_cancel_pending_pipelines' : 'enabled', - 'build_timeout' : 3600, - 'auto_devops_enabled' : false, - 'auto_devops_deploy_strategy' : 'continuous', - 'ci_config_path' : '', - 'public_jobs' : true, - 'shared_with_groups' : [], - 'only_allow_merge_if_pipeline_succeeds' : false, - 'allow_merge_on_skipped_pipeline' : null, - 'request_access_enabled' : true, - 'only_allow_merge_if_all_discussions_are_resolved': false, - 'remove_source_branch_after_merge' : true, - 'printing_merge_request_link_enabled' : true, - 'merge_method' : 'merge', - 'squash_option' : 'default_off', - 'enforce_auth_checks_on_uploads' : true, - 'suggestion_commit_message' : null, - 'merge_commit_template' : null, - 'squash_commit_template' : null, - 'issue_branch_template' : null, - 'autoclose_referenced_issues' : true - }, - gitlabLastInfoDate: new Date('2023-11-07T20:35:54.692Z'), - published : true - } - }); + where : { name: 'Technique de compilation - TP' }, + update: {}, + create: { + name : 'Technique de compilation - TP', + gitlabId : 13893, + gitlabLink : 'https://gitedu.hesge.ch/dojodev/assignment/technique-de-compilation-tp', + gitlabCreationInfo: { + 'id' : 13893, + 'description' : 'Dojo assignment repository.\n\nName of the assignment: Technique de compilation - TP', + 'name' : 'Technique de compilation - TP', + 'name_with_namespace' : 'DojoDev / Assignment / Technique de compilation - TP', + 'path' : 'technique-de-compilation-tp', + 'path_with_namespace' : 'dojodev/assignment/technique-de-compilation-tp', + 'created_at' : '2023-11-07T21:35:48.454+01:00', + 'default_branch' : 'main', + 'tag_list' : [], + 'topics' : [], + 'ssh_url_to_repo' : 'ssh://git@ssh.hesge.ch:10572/dojodev/assignment/technique-de-compilation-tp.git', + 'http_url_to_repo' : 'https://gitedu.hesge.ch/dojodev/assignment/technique-de-compilation-tp.git', + 'web_url' : 'https://gitedu.hesge.ch/dojodev/assignment/technique-de-compilation-tp', + 'readme_url' : null, + 'forks_count' : 0, + 'avatar_url' : null, + 'star_count' : 0, + 'last_activity_at' : '2023-11-07T21:35:48.454+01:00', + 'namespace' : { + 'id' : 14190, + 'name' : 'Assignment', + 'path' : 'assignment', + 'kind' : 'group', + 'full_path' : 'dojodev/assignment', + 'parent_id' : 14189, + 'avatar_url': null, + 'web_url' : 'https://gitedu.hesge.ch/groups/dojodev/assignment' + }, + '_links' : { + 'self' : 'https://gitedu.hesge.ch/api/v4/projects/13893', + 'issues' : 'https://gitedu.hesge.ch/api/v4/projects/13893/issues', + 'merge_requests': 'https://gitedu.hesge.ch/api/v4/projects/13893/merge_requests', + 'repo_branches' : 'https://gitedu.hesge.ch/api/v4/projects/13893/repository/branches', + 'labels' : 'https://gitedu.hesge.ch/api/v4/projects/13893/labels', + 'events' : 'https://gitedu.hesge.ch/api/v4/projects/13893/events', + 'members' : 'https://gitedu.hesge.ch/api/v4/projects/13893/members', + 'cluster_agents': 'https://gitedu.hesge.ch/api/v4/projects/13893/cluster_agents' + }, + 'packages_enabled' : true, + 'empty_repo' : true, + 'archived' : false, + 'visibility' : 'private', + 'resolve_outdated_diff_discussions' : false, + 'container_expiration_policy' : { + 'cadence' : '1d', + 'enabled' : false, + 'keep_n' : 10, + 'older_than' : '90d', + 'name_regex' : '.*', + 'name_regex_keep': null, + 'next_run_at' : '2023-11-08T21:35:48.543+01:00' + }, + 'issues_enabled' : true, + 'merge_requests_enabled' : true, + 'wiki_enabled' : false, + 'jobs_enabled' : true, + 'snippets_enabled' : true, + 'container_registry_enabled' : true, + 'service_desk_enabled' : false, + 'service_desk_address' : null, + 'can_create_merge_request_in' : true, + 'issues_access_level' : 'enabled', + 'repository_access_level' : 'enabled', + 'merge_requests_access_level' : 'enabled', + 'forking_access_level' : 'enabled', + 'wiki_access_level' : 'disabled', + 'builds_access_level' : 'enabled', + 'snippets_access_level' : 'enabled', + 'pages_access_level' : 'private', + 'analytics_access_level' : 'enabled', + 'container_registry_access_level' : 'enabled', + 'security_and_compliance_access_level' : 'private', + 'releases_access_level' : 'enabled', + 'environments_access_level' : 'enabled', + 'feature_flags_access_level' : 'enabled', + 'infrastructure_access_level' : 'enabled', + 'monitor_access_level' : 'enabled', + 'emails_disabled' : null, + 'shared_runners_enabled' : true, + 'lfs_enabled' : true, + 'creator_id' : 1076, + 'import_url' : 'https://gitedu.hesge.ch/dojodev/template/empty_template.git', + 'import_type' : 'git', + 'import_status' : 'scheduled', + 'import_error' : null, + 'open_issues_count' : 0, + 'description_html' : '<p data-sourcepos="1:1-1:27" dir="auto">Dojo assignment repository.</p>\n<p data-sourcepos="3:1-3:53" dir="auto">Name of the assignment: Technique de compilation - TP</p>', + 'updated_at' : '2023-11-07T21:35:48.454+01:00', + 'ci_default_git_depth' : 20, + 'ci_forward_deployment_enabled' : true, + 'ci_job_token_scope_enabled' : false, + 'ci_separated_caches' : true, + 'ci_allow_fork_pipelines_to_run_in_parent_project': true, + 'build_git_strategy' : 'fetch', + 'keep_latest_artifact' : true, + 'restrict_user_defined_variables' : false, + 'runners_token' : 'GR1348941qn9Ju1u5yTSLoWUTWLZy', + 'runner_token_expiration_interval' : null, + 'group_runners_enabled' : true, + 'auto_cancel_pending_pipelines' : 'enabled', + 'build_timeout' : 3600, + 'auto_devops_enabled' : false, + 'auto_devops_deploy_strategy' : 'continuous', + 'ci_config_path' : '', + 'public_jobs' : true, + 'shared_with_groups' : [], + 'only_allow_merge_if_pipeline_succeeds' : false, + 'allow_merge_on_skipped_pipeline' : null, + 'request_access_enabled' : true, + 'only_allow_merge_if_all_discussions_are_resolved': false, + 'remove_source_branch_after_merge' : true, + 'printing_merge_request_link_enabled' : true, + 'merge_method' : 'merge', + 'squash_option' : 'default_off', + 'enforce_auth_checks_on_uploads' : true, + 'suggestion_commit_message' : null, + 'merge_commit_template' : null, + 'squash_commit_template' : null, + 'issue_branch_template' : null, + 'autoclose_referenced_issues' : true + }, + gitlabLastInfo : { + 'id' : 13893, + 'description' : 'Dojo assignment repository.\n\nName of the assignment: Technique de compilation - TP', + 'name' : 'Technique de compilation - TP', + 'name_with_namespace' : 'DojoDev / Assignment / Technique de compilation - TP', + 'path' : 'technique-de-compilation-tp', + 'path_with_namespace' : 'dojodev/assignment/technique-de-compilation-tp', + 'created_at' : '2023-11-07T21:35:48.454+01:00', + 'default_branch' : 'main', + 'tag_list' : [], + 'topics' : [], + 'ssh_url_to_repo' : 'ssh://git@ssh.hesge.ch:10572/dojodev/assignment/technique-de-compilation-tp.git', + 'http_url_to_repo' : 'https://gitedu.hesge.ch/dojodev/assignment/technique-de-compilation-tp.git', + 'web_url' : 'https://gitedu.hesge.ch/dojodev/assignment/technique-de-compilation-tp', + 'readme_url' : null, + 'forks_count' : 0, + 'avatar_url' : null, + 'star_count' : 0, + 'last_activity_at' : '2023-11-07T21:35:48.454+01:00', + 'namespace' : { + 'id' : 14190, + 'name' : 'Assignment', + 'path' : 'assignment', + 'kind' : 'group', + 'full_path' : 'dojodev/assignment', + 'parent_id' : 14189, + 'avatar_url': null, + 'web_url' : 'https://gitedu.hesge.ch/groups/dojodev/assignment' + }, + '_links' : { + 'self' : 'https://gitedu.hesge.ch/api/v4/projects/13893', + 'issues' : 'https://gitedu.hesge.ch/api/v4/projects/13893/issues', + 'merge_requests': 'https://gitedu.hesge.ch/api/v4/projects/13893/merge_requests', + 'repo_branches' : 'https://gitedu.hesge.ch/api/v4/projects/13893/repository/branches', + 'labels' : 'https://gitedu.hesge.ch/api/v4/projects/13893/labels', + 'events' : 'https://gitedu.hesge.ch/api/v4/projects/13893/events', + 'members' : 'https://gitedu.hesge.ch/api/v4/projects/13893/members', + 'cluster_agents': 'https://gitedu.hesge.ch/api/v4/projects/13893/cluster_agents' + }, + 'packages_enabled' : true, + 'empty_repo' : true, + 'archived' : false, + 'visibility' : 'private', + 'resolve_outdated_diff_discussions' : false, + 'container_expiration_policy' : { + 'cadence' : '1d', + 'enabled' : false, + 'keep_n' : 10, + 'older_than' : '90d', + 'name_regex' : '.*', + 'name_regex_keep': null, + 'next_run_at' : '2023-11-08T21:35:48.543+01:00' + }, + 'issues_enabled' : true, + 'merge_requests_enabled' : true, + 'wiki_enabled' : false, + 'jobs_enabled' : true, + 'snippets_enabled' : true, + 'container_registry_enabled' : true, + 'service_desk_enabled' : false, + 'service_desk_address' : null, + 'can_create_merge_request_in' : true, + 'issues_access_level' : 'enabled', + 'repository_access_level' : 'enabled', + 'merge_requests_access_level' : 'enabled', + 'forking_access_level' : 'enabled', + 'wiki_access_level' : 'disabled', + 'builds_access_level' : 'enabled', + 'snippets_access_level' : 'enabled', + 'pages_access_level' : 'private', + 'analytics_access_level' : 'enabled', + 'container_registry_access_level' : 'enabled', + 'security_and_compliance_access_level' : 'private', + 'releases_access_level' : 'enabled', + 'environments_access_level' : 'enabled', + 'feature_flags_access_level' : 'enabled', + 'infrastructure_access_level' : 'enabled', + 'monitor_access_level' : 'enabled', + 'emails_disabled' : null, + 'shared_runners_enabled' : true, + 'lfs_enabled' : true, + 'creator_id' : 1076, + 'import_url' : 'https://gitedu.hesge.ch/dojodev/template/empty_template.git', + 'import_type' : 'git', + 'import_status' : 'scheduled', + 'import_error' : null, + 'open_issues_count' : 0, + 'description_html' : '<p data-sourcepos="1:1-1:27" dir="auto">Dojo assignment repository.</p>\n<p data-sourcepos="3:1-3:53" dir="auto">Name of the assignment: Technique de compilation - TP</p>', + 'updated_at' : '2023-11-07T21:35:48.454+01:00', + 'ci_default_git_depth' : 20, + 'ci_forward_deployment_enabled' : true, + 'ci_job_token_scope_enabled' : false, + 'ci_separated_caches' : true, + 'ci_allow_fork_pipelines_to_run_in_parent_project': true, + 'build_git_strategy' : 'fetch', + 'keep_latest_artifact' : true, + 'restrict_user_defined_variables' : false, + 'runners_token' : 'GR1348941qn9Ju1u5yTSLoWUTWLZy', + 'runner_token_expiration_interval' : null, + 'group_runners_enabled' : true, + 'auto_cancel_pending_pipelines' : 'enabled', + 'build_timeout' : 3600, + 'auto_devops_enabled' : false, + 'auto_devops_deploy_strategy' : 'continuous', + 'ci_config_path' : '', + 'public_jobs' : true, + 'shared_with_groups' : [], + 'only_allow_merge_if_pipeline_succeeds' : false, + 'allow_merge_on_skipped_pipeline' : null, + 'request_access_enabled' : true, + 'only_allow_merge_if_all_discussions_are_resolved': false, + 'remove_source_branch_after_merge' : true, + 'printing_merge_request_link_enabled' : true, + 'merge_method' : 'merge', + 'squash_option' : 'default_off', + 'enforce_auth_checks_on_uploads' : true, + 'suggestion_commit_message' : null, + 'merge_commit_template' : null, + 'squash_commit_template' : null, + 'issue_branch_template' : null, + 'autoclose_referenced_issues' : true + }, + gitlabLastInfoDate: new Date('2023-11-07T20:35:54.692Z'), + published : true + } + }); } } async function exercises() { if ( !SharedConfig.production ) { await db.exercise.upsert({ - where : { id: 'dc7e1433-23f8-4c8a-a7f3-478b65fa9815' }, - update: {}, - create: { - id : 'dc7e1433-23f8-4c8a-a7f3-478b65fa9815', - assignmentName : 'Technique de compilation - TP', - name : 'DojoEx - Technique de compilation - TP - michael.minelli', - gitlabId : 14232, - gitlabLink : 'https://gitedu.hesge.ch/dojodev/exercise/dojo-ex_technique-de-compilation-tp_dc7e1433-23f8-4c8a-a7f3-478b65fa9815', - gitlabCreationInfo: { - 'id' : 14232, - 'description' : 'Dojo exercise repository based on the the assignment: Technique de compilation - TP', - 'name' : 'DojoEx - Technique de compilation - TP - michael.minelli', - 'name_with_namespace' : 'DojoDev / Exercise / DojoEx - Technique de compilation - TP - michael.minelli', - 'path' : 'dojo-ex_technique-de-compilation-tp_dc7e1433-23f8-4c8a-a7f3-478b65fa9815', - 'path_with_namespace' : 'dojodev/exercise/dojo-ex_technique-de-compilation-tp_dc7e1433-23f8-4c8a-a7f3-478b65fa9815', - 'created_at' : '2023-12-14T17:58:48.185+01:00', - 'default_branch' : 'main', - 'tag_list' : [], - 'topics' : [], - 'ssh_url_to_repo' : 'ssh://git@ssh.hesge.ch:10572/dojodev/exercise/dojo-ex_technique-de-compilation-tp_dc7e1433-23f8-4c8a-a7f3-478b65fa9815.git', - 'http_url_to_repo' : 'https://gitedu.hesge.ch/dojodev/exercise/dojo-ex_technique-de-compilation-tp_dc7e1433-23f8-4c8a-a7f3-478b65fa9815.git', - 'web_url' : 'https://gitedu.hesge.ch/dojodev/exercise/dojo-ex_technique-de-compilation-tp_dc7e1433-23f8-4c8a-a7f3-478b65fa9815', - 'readme_url' : null, - 'forks_count' : 0, - 'avatar_url' : null, - 'star_count' : 0, - 'last_activity_at' : '2023-12-14T17:58:48.185+01:00', - 'namespace' : { - 'id' : 14191, - 'name' : 'Exercise', - 'path' : 'exercise', - 'kind' : 'group', - 'full_path' : 'dojodev/exercise', - 'parent_id' : 14189, - 'avatar_url': null, - 'web_url' : 'https://gitedu.hesge.ch/groups/dojodev/exercise' - }, - '_links' : { - 'self' : 'https://gitedu.hesge.ch/api/v4/projects/14232', - 'issues' : 'https://gitedu.hesge.ch/api/v4/projects/14232/issues', - 'merge_requests': 'https://gitedu.hesge.ch/api/v4/projects/14232/merge_requests', - 'repo_branches' : 'https://gitedu.hesge.ch/api/v4/projects/14232/repository/branches', - 'labels' : 'https://gitedu.hesge.ch/api/v4/projects/14232/labels', - 'events' : 'https://gitedu.hesge.ch/api/v4/projects/14232/events', - 'members' : 'https://gitedu.hesge.ch/api/v4/projects/14232/members', - 'cluster_agents': 'https://gitedu.hesge.ch/api/v4/projects/14232/cluster_agents' - }, - 'packages_enabled' : true, - 'empty_repo' : true, - 'archived' : false, - 'visibility' : 'private', - 'resolve_outdated_diff_discussions' : false, - 'container_expiration_policy' : { - 'cadence' : '1d', - 'enabled' : false, - 'keep_n' : 10, - 'older_than' : '90d', - 'name_regex' : '.*', - 'name_regex_keep': null, - 'next_run_at' : '2023-12-15T17:58:48.207+01:00' - }, - 'issues_enabled' : true, - 'merge_requests_enabled' : true, - 'wiki_enabled' : false, - 'jobs_enabled' : true, - 'snippets_enabled' : true, - 'container_registry_enabled' : true, - 'service_desk_enabled' : false, - 'service_desk_address' : null, - 'can_create_merge_request_in' : true, - 'issues_access_level' : 'enabled', - 'repository_access_level' : 'enabled', - 'merge_requests_access_level' : 'enabled', - 'forking_access_level' : 'enabled', - 'wiki_access_level' : 'disabled', - 'builds_access_level' : 'enabled', - 'snippets_access_level' : 'enabled', - 'pages_access_level' : 'private', - 'analytics_access_level' : 'enabled', - 'container_registry_access_level' : 'enabled', - 'security_and_compliance_access_level' : 'private', - 'releases_access_level' : 'enabled', - 'environments_access_level' : 'enabled', - 'feature_flags_access_level' : 'enabled', - 'infrastructure_access_level' : 'enabled', - 'monitor_access_level' : 'enabled', - 'emails_disabled' : null, - 'shared_runners_enabled' : true, - 'lfs_enabled' : true, - 'creator_id' : 1076, - 'forked_from_project' : { - 'id' : 13893, - 'description' : 'Dojo assignment repository.\n\nName of the assignment: Technique de compilation - TP', - 'name' : 'Technique de compilation - TP', - 'name_with_namespace': 'DojoDev / Assignment / Technique de compilation - TP', - 'path' : 'technique-de-compilation-tp', - 'path_with_namespace': 'dojodev/assignment/technique-de-compilation-tp', - 'created_at' : '2023-11-07T21:35:48.454+01:00', - 'default_branch' : 'main', - 'tag_list' : [], - 'topics' : [], - 'ssh_url_to_repo' : 'ssh://git@ssh.hesge.ch:10572/dojodev/assignment/technique-de-compilation-tp.git', - 'http_url_to_repo' : 'https://gitedu.hesge.ch/dojodev/assignment/technique-de-compilation-tp.git', - 'web_url' : 'https://gitedu.hesge.ch/dojodev/assignment/technique-de-compilation-tp', - 'readme_url' : 'https://gitedu.hesge.ch/dojodev/assignment/technique-de-compilation-tp/-/blob/main/README.md', - 'forks_count' : 1, - 'avatar_url' : null, - 'star_count' : 0, - 'last_activity_at' : '2023-11-14T13:14:13.820+01:00', - 'namespace' : { - 'id' : 14190, - 'name' : 'Assignment', - 'path' : 'assignment', - 'kind' : 'group', - 'full_path' : 'dojodev/assignment', - 'parent_id' : 14189, - 'avatar_url': null, - 'web_url' : 'https://gitedu.hesge.ch/groups/dojodev/assignment' - } - }, - 'mr_default_target_self' : false, - 'import_url' : null, - 'import_type' : null, - 'import_status' : 'scheduled', - 'import_error' : null, - 'open_issues_count' : 0, - 'description_html' : '<p data-sourcepos="1:1-1:83" dir="auto">Dojo exercise repository based on the the assignment: Technique de compilation - TP</p>', - 'updated_at' : '2023-12-14T17:58:48.185+01:00', - 'ci_default_git_depth' : 20, - 'ci_forward_deployment_enabled' : true, - 'ci_job_token_scope_enabled' : false, - 'ci_separated_caches' : true, - 'ci_allow_fork_pipelines_to_run_in_parent_project': true, - 'build_git_strategy' : 'fetch', - 'keep_latest_artifact' : true, - 'restrict_user_defined_variables' : false, - 'runners_token' : 'GR1348941tdWz3ZxaqbRBmjL5A6r2', - 'runner_token_expiration_interval' : null, - 'group_runners_enabled' : true, - 'auto_cancel_pending_pipelines' : 'enabled', - 'build_timeout' : 3600, - 'auto_devops_enabled' : false, - 'auto_devops_deploy_strategy' : 'continuous', - 'ci_config_path' : '', - 'public_jobs' : true, - 'shared_with_groups' : [], - 'only_allow_merge_if_pipeline_succeeds' : false, - 'allow_merge_on_skipped_pipeline' : null, - 'request_access_enabled' : true, - 'only_allow_merge_if_all_discussions_are_resolved': false, - 'remove_source_branch_after_merge' : true, - 'printing_merge_request_link_enabled' : true, - 'merge_method' : 'merge', - 'squash_option' : 'default_off', - 'enforce_auth_checks_on_uploads' : true, - 'suggestion_commit_message' : null, - 'merge_commit_template' : null, - 'squash_commit_template' : null, - 'issue_branch_template' : null, - 'autoclose_referenced_issues' : true - }, - gitlabLastInfo : { - 'id' : 14232, - 'description' : 'Dojo exercise repository based on the the assignment: Technique de compilation - TP', - 'name' : 'DojoEx - Technique de compilation - TP - michael.minelli', - 'name_with_namespace' : 'DojoDev / Exercise / DojoEx - Technique de compilation - TP - michael.minelli', - 'path' : 'dojo-ex_technique-de-compilation-tp_dc7e1433-23f8-4c8a-a7f3-478b65fa9815', - 'path_with_namespace' : 'dojodev/exercise/dojo-ex_technique-de-compilation-tp_dc7e1433-23f8-4c8a-a7f3-478b65fa9815', - 'created_at' : '2023-12-14T17:58:48.185+01:00', - 'default_branch' : 'main', - 'tag_list' : [], - 'topics' : [], - 'ssh_url_to_repo' : 'ssh://git@ssh.hesge.ch:10572/dojodev/exercise/dojo-ex_technique-de-compilation-tp_dc7e1433-23f8-4c8a-a7f3-478b65fa9815.git', - 'http_url_to_repo' : 'https://gitedu.hesge.ch/dojodev/exercise/dojo-ex_technique-de-compilation-tp_dc7e1433-23f8-4c8a-a7f3-478b65fa9815.git', - 'web_url' : 'https://gitedu.hesge.ch/dojodev/exercise/dojo-ex_technique-de-compilation-tp_dc7e1433-23f8-4c8a-a7f3-478b65fa9815', - 'readme_url' : null, - 'forks_count' : 0, - 'avatar_url' : null, - 'star_count' : 0, - 'last_activity_at' : '2023-12-14T17:58:48.185+01:00', - 'namespace' : { - 'id' : 14191, - 'name' : 'Exercise', - 'path' : 'exercise', - 'kind' : 'group', - 'full_path' : 'dojodev/exercise', - 'parent_id' : 14189, - 'avatar_url': null, - 'web_url' : 'https://gitedu.hesge.ch/groups/dojodev/exercise' - }, - '_links' : { - 'self' : 'https://gitedu.hesge.ch/api/v4/projects/14232', - 'issues' : 'https://gitedu.hesge.ch/api/v4/projects/14232/issues', - 'merge_requests': 'https://gitedu.hesge.ch/api/v4/projects/14232/merge_requests', - 'repo_branches' : 'https://gitedu.hesge.ch/api/v4/projects/14232/repository/branches', - 'labels' : 'https://gitedu.hesge.ch/api/v4/projects/14232/labels', - 'events' : 'https://gitedu.hesge.ch/api/v4/projects/14232/events', - 'members' : 'https://gitedu.hesge.ch/api/v4/projects/14232/members', - 'cluster_agents': 'https://gitedu.hesge.ch/api/v4/projects/14232/cluster_agents' - }, - 'packages_enabled' : true, - 'empty_repo' : true, - 'archived' : false, - 'visibility' : 'private', - 'resolve_outdated_diff_discussions' : false, - 'container_expiration_policy' : { - 'cadence' : '1d', - 'enabled' : false, - 'keep_n' : 10, - 'older_than' : '90d', - 'name_regex' : '.*', - 'name_regex_keep': null, - 'next_run_at' : '2023-12-15T17:58:48.207+01:00' - }, - 'issues_enabled' : true, - 'merge_requests_enabled' : true, - 'wiki_enabled' : false, - 'jobs_enabled' : true, - 'snippets_enabled' : true, - 'container_registry_enabled' : true, - 'service_desk_enabled' : false, - 'service_desk_address' : null, - 'can_create_merge_request_in' : true, - 'issues_access_level' : 'enabled', - 'repository_access_level' : 'enabled', - 'merge_requests_access_level' : 'enabled', - 'forking_access_level' : 'enabled', - 'wiki_access_level' : 'disabled', - 'builds_access_level' : 'enabled', - 'snippets_access_level' : 'enabled', - 'pages_access_level' : 'private', - 'analytics_access_level' : 'enabled', - 'container_registry_access_level' : 'enabled', - 'security_and_compliance_access_level' : 'private', - 'releases_access_level' : 'enabled', - 'environments_access_level' : 'enabled', - 'feature_flags_access_level' : 'enabled', - 'infrastructure_access_level' : 'enabled', - 'monitor_access_level' : 'enabled', - 'emails_disabled' : null, - 'shared_runners_enabled' : true, - 'lfs_enabled' : true, - 'creator_id' : 1076, - 'forked_from_project' : { - 'id' : 13893, - 'description' : 'Dojo assignment repository.\n\nName of the assignment: Technique de compilation - TP', - 'name' : 'Technique de compilation - TP', - 'name_with_namespace': 'DojoDev / Assignment / Technique de compilation - TP', - 'path' : 'technique-de-compilation-tp', - 'path_with_namespace': 'dojodev/assignment/technique-de-compilation-tp', - 'created_at' : '2023-11-07T21:35:48.454+01:00', - 'default_branch' : 'main', - 'tag_list' : [], - 'topics' : [], - 'ssh_url_to_repo' : 'ssh://git@ssh.hesge.ch:10572/dojodev/assignment/technique-de-compilation-tp.git', - 'http_url_to_repo' : 'https://gitedu.hesge.ch/dojodev/assignment/technique-de-compilation-tp.git', - 'web_url' : 'https://gitedu.hesge.ch/dojodev/assignment/technique-de-compilation-tp', - 'readme_url' : 'https://gitedu.hesge.ch/dojodev/assignment/technique-de-compilation-tp/-/blob/main/README.md', - 'forks_count' : 1, - 'avatar_url' : null, - 'star_count' : 0, - 'last_activity_at' : '2023-11-14T13:14:13.820+01:00', - 'namespace' : { - 'id' : 14190, - 'name' : 'Assignment', - 'path' : 'assignment', - 'kind' : 'group', - 'full_path' : 'dojodev/assignment', - 'parent_id' : 14189, - 'avatar_url': null, - 'web_url' : 'https://gitedu.hesge.ch/groups/dojodev/assignment' - } - }, - 'mr_default_target_self' : false, - 'import_url' : null, - 'import_type' : null, - 'import_status' : 'scheduled', - 'import_error' : null, - 'open_issues_count' : 0, - 'description_html' : '<p data-sourcepos="1:1-1:83" dir="auto">Dojo exercise repository based on the the assignment: Technique de compilation - TP</p>', - 'updated_at' : '2023-12-14T17:58:48.185+01:00', - 'ci_default_git_depth' : 20, - 'ci_forward_deployment_enabled' : true, - 'ci_job_token_scope_enabled' : false, - 'ci_separated_caches' : true, - 'ci_allow_fork_pipelines_to_run_in_parent_project': true, - 'build_git_strategy' : 'fetch', - 'keep_latest_artifact' : true, - 'restrict_user_defined_variables' : false, - 'runners_token' : 'GR1348941tdWz3ZxaqbRBmjL5A6r2', - 'runner_token_expiration_interval' : null, - 'group_runners_enabled' : true, - 'auto_cancel_pending_pipelines' : 'enabled', - 'build_timeout' : 3600, - 'auto_devops_enabled' : false, - 'auto_devops_deploy_strategy' : 'continuous', - 'ci_config_path' : '', - 'public_jobs' : true, - 'shared_with_groups' : [], - 'only_allow_merge_if_pipeline_succeeds' : false, - 'allow_merge_on_skipped_pipeline' : null, - 'request_access_enabled' : true, - 'only_allow_merge_if_all_discussions_are_resolved': false, - 'remove_source_branch_after_merge' : true, - 'printing_merge_request_link_enabled' : true, - 'merge_method' : 'merge', - 'squash_option' : 'default_off', - 'enforce_auth_checks_on_uploads' : true, - 'suggestion_commit_message' : null, - 'merge_commit_template' : null, - 'squash_commit_template' : null, - 'issue_branch_template' : null, - 'autoclose_referenced_issues' : true - }, - gitlabLastInfoDate: new Date('2023-12-14T14:54:35.692Z'), - secret : 'ea01568d-2b84-49b7-8603-7d58346f21c6' - } - }); + where : { id: 'dc7e1433-23f8-4c8a-a7f3-478b65fa9815' }, + update: {}, + create: { + id : 'dc7e1433-23f8-4c8a-a7f3-478b65fa9815', + assignmentName : 'Technique de compilation - TP', + name : 'DojoEx - Technique de compilation - TP - michael.minelli', + gitlabId : 14232, + gitlabLink : 'https://gitedu.hesge.ch/dojodev/exercise/dojo-ex_technique-de-compilation-tp_dc7e1433-23f8-4c8a-a7f3-478b65fa9815', + gitlabCreationInfo: { + 'id' : 14232, + 'description' : 'Dojo exercise repository based on the the assignment: Technique de compilation - TP', + 'name' : 'DojoEx - Technique de compilation - TP - michael.minelli', + 'name_with_namespace' : 'DojoDev / Exercise / DojoEx - Technique de compilation - TP - michael.minelli', + 'path' : 'dojo-ex_technique-de-compilation-tp_dc7e1433-23f8-4c8a-a7f3-478b65fa9815', + 'path_with_namespace' : 'dojodev/exercise/dojo-ex_technique-de-compilation-tp_dc7e1433-23f8-4c8a-a7f3-478b65fa9815', + 'created_at' : '2023-12-14T17:58:48.185+01:00', + 'default_branch' : 'main', + 'tag_list' : [], + 'topics' : [], + 'ssh_url_to_repo' : 'ssh://git@ssh.hesge.ch:10572/dojodev/exercise/dojo-ex_technique-de-compilation-tp_dc7e1433-23f8-4c8a-a7f3-478b65fa9815.git', + 'http_url_to_repo' : 'https://gitedu.hesge.ch/dojodev/exercise/dojo-ex_technique-de-compilation-tp_dc7e1433-23f8-4c8a-a7f3-478b65fa9815.git', + 'web_url' : 'https://gitedu.hesge.ch/dojodev/exercise/dojo-ex_technique-de-compilation-tp_dc7e1433-23f8-4c8a-a7f3-478b65fa9815', + 'readme_url' : null, + 'forks_count' : 0, + 'avatar_url' : null, + 'star_count' : 0, + 'last_activity_at' : '2023-12-14T17:58:48.185+01:00', + 'namespace' : { + 'id' : 14191, + 'name' : 'Exercise', + 'path' : 'exercise', + 'kind' : 'group', + 'full_path' : 'dojodev/exercise', + 'parent_id' : 14189, + 'avatar_url': null, + 'web_url' : 'https://gitedu.hesge.ch/groups/dojodev/exercise' + }, + '_links' : { + 'self' : 'https://gitedu.hesge.ch/api/v4/projects/14232', + 'issues' : 'https://gitedu.hesge.ch/api/v4/projects/14232/issues', + 'merge_requests': 'https://gitedu.hesge.ch/api/v4/projects/14232/merge_requests', + 'repo_branches' : 'https://gitedu.hesge.ch/api/v4/projects/14232/repository/branches', + 'labels' : 'https://gitedu.hesge.ch/api/v4/projects/14232/labels', + 'events' : 'https://gitedu.hesge.ch/api/v4/projects/14232/events', + 'members' : 'https://gitedu.hesge.ch/api/v4/projects/14232/members', + 'cluster_agents': 'https://gitedu.hesge.ch/api/v4/projects/14232/cluster_agents' + }, + 'packages_enabled' : true, + 'empty_repo' : true, + 'archived' : false, + 'visibility' : 'private', + 'resolve_outdated_diff_discussions' : false, + 'container_expiration_policy' : { + 'cadence' : '1d', + 'enabled' : false, + 'keep_n' : 10, + 'older_than' : '90d', + 'name_regex' : '.*', + 'name_regex_keep': null, + 'next_run_at' : '2023-12-15T17:58:48.207+01:00' + }, + 'issues_enabled' : true, + 'merge_requests_enabled' : true, + 'wiki_enabled' : false, + 'jobs_enabled' : true, + 'snippets_enabled' : true, + 'container_registry_enabled' : true, + 'service_desk_enabled' : false, + 'service_desk_address' : null, + 'can_create_merge_request_in' : true, + 'issues_access_level' : 'enabled', + 'repository_access_level' : 'enabled', + 'merge_requests_access_level' : 'enabled', + 'forking_access_level' : 'enabled', + 'wiki_access_level' : 'disabled', + 'builds_access_level' : 'enabled', + 'snippets_access_level' : 'enabled', + 'pages_access_level' : 'private', + 'analytics_access_level' : 'enabled', + 'container_registry_access_level' : 'enabled', + 'security_and_compliance_access_level' : 'private', + 'releases_access_level' : 'enabled', + 'environments_access_level' : 'enabled', + 'feature_flags_access_level' : 'enabled', + 'infrastructure_access_level' : 'enabled', + 'monitor_access_level' : 'enabled', + 'emails_disabled' : null, + 'shared_runners_enabled' : true, + 'lfs_enabled' : true, + 'creator_id' : 1076, + 'forked_from_project' : { + 'id' : 13893, + 'description' : 'Dojo assignment repository.\n\nName of the assignment: Technique de compilation - TP', + 'name' : 'Technique de compilation - TP', + 'name_with_namespace': 'DojoDev / Assignment / Technique de compilation - TP', + 'path' : 'technique-de-compilation-tp', + 'path_with_namespace': 'dojodev/assignment/technique-de-compilation-tp', + 'created_at' : '2023-11-07T21:35:48.454+01:00', + 'default_branch' : 'main', + 'tag_list' : [], + 'topics' : [], + 'ssh_url_to_repo' : 'ssh://git@ssh.hesge.ch:10572/dojodev/assignment/technique-de-compilation-tp.git', + 'http_url_to_repo' : 'https://gitedu.hesge.ch/dojodev/assignment/technique-de-compilation-tp.git', + 'web_url' : 'https://gitedu.hesge.ch/dojodev/assignment/technique-de-compilation-tp', + 'readme_url' : 'https://gitedu.hesge.ch/dojodev/assignment/technique-de-compilation-tp/-/blob/main/README.md', + 'forks_count' : 1, + 'avatar_url' : null, + 'star_count' : 0, + 'last_activity_at' : '2023-11-14T13:14:13.820+01:00', + 'namespace' : { + 'id' : 14190, + 'name' : 'Assignment', + 'path' : 'assignment', + 'kind' : 'group', + 'full_path' : 'dojodev/assignment', + 'parent_id' : 14189, + 'avatar_url': null, + 'web_url' : 'https://gitedu.hesge.ch/groups/dojodev/assignment' + } + }, + 'mr_default_target_self' : false, + 'import_url' : null, + 'import_type' : null, + 'import_status' : 'scheduled', + 'import_error' : null, + 'open_issues_count' : 0, + 'description_html' : '<p data-sourcepos="1:1-1:83" dir="auto">Dojo exercise repository based on the the assignment: Technique de compilation - TP</p>', + 'updated_at' : '2023-12-14T17:58:48.185+01:00', + 'ci_default_git_depth' : 20, + 'ci_forward_deployment_enabled' : true, + 'ci_job_token_scope_enabled' : false, + 'ci_separated_caches' : true, + 'ci_allow_fork_pipelines_to_run_in_parent_project': true, + 'build_git_strategy' : 'fetch', + 'keep_latest_artifact' : true, + 'restrict_user_defined_variables' : false, + 'runners_token' : 'GR1348941tdWz3ZxaqbRBmjL5A6r2', + 'runner_token_expiration_interval' : null, + 'group_runners_enabled' : true, + 'auto_cancel_pending_pipelines' : 'enabled', + 'build_timeout' : 3600, + 'auto_devops_enabled' : false, + 'auto_devops_deploy_strategy' : 'continuous', + 'ci_config_path' : '', + 'public_jobs' : true, + 'shared_with_groups' : [], + 'only_allow_merge_if_pipeline_succeeds' : false, + 'allow_merge_on_skipped_pipeline' : null, + 'request_access_enabled' : true, + 'only_allow_merge_if_all_discussions_are_resolved': false, + 'remove_source_branch_after_merge' : true, + 'printing_merge_request_link_enabled' : true, + 'merge_method' : 'merge', + 'squash_option' : 'default_off', + 'enforce_auth_checks_on_uploads' : true, + 'suggestion_commit_message' : null, + 'merge_commit_template' : null, + 'squash_commit_template' : null, + 'issue_branch_template' : null, + 'autoclose_referenced_issues' : true + }, + gitlabLastInfo : { + 'id' : 14232, + 'description' : 'Dojo exercise repository based on the the assignment: Technique de compilation - TP', + 'name' : 'DojoEx - Technique de compilation - TP - michael.minelli', + 'name_with_namespace' : 'DojoDev / Exercise / DojoEx - Technique de compilation - TP - michael.minelli', + 'path' : 'dojo-ex_technique-de-compilation-tp_dc7e1433-23f8-4c8a-a7f3-478b65fa9815', + 'path_with_namespace' : 'dojodev/exercise/dojo-ex_technique-de-compilation-tp_dc7e1433-23f8-4c8a-a7f3-478b65fa9815', + 'created_at' : '2023-12-14T17:58:48.185+01:00', + 'default_branch' : 'main', + 'tag_list' : [], + 'topics' : [], + 'ssh_url_to_repo' : 'ssh://git@ssh.hesge.ch:10572/dojodev/exercise/dojo-ex_technique-de-compilation-tp_dc7e1433-23f8-4c8a-a7f3-478b65fa9815.git', + 'http_url_to_repo' : 'https://gitedu.hesge.ch/dojodev/exercise/dojo-ex_technique-de-compilation-tp_dc7e1433-23f8-4c8a-a7f3-478b65fa9815.git', + 'web_url' : 'https://gitedu.hesge.ch/dojodev/exercise/dojo-ex_technique-de-compilation-tp_dc7e1433-23f8-4c8a-a7f3-478b65fa9815', + 'readme_url' : null, + 'forks_count' : 0, + 'avatar_url' : null, + 'star_count' : 0, + 'last_activity_at' : '2023-12-14T17:58:48.185+01:00', + 'namespace' : { + 'id' : 14191, + 'name' : 'Exercise', + 'path' : 'exercise', + 'kind' : 'group', + 'full_path' : 'dojodev/exercise', + 'parent_id' : 14189, + 'avatar_url': null, + 'web_url' : 'https://gitedu.hesge.ch/groups/dojodev/exercise' + }, + '_links' : { + 'self' : 'https://gitedu.hesge.ch/api/v4/projects/14232', + 'issues' : 'https://gitedu.hesge.ch/api/v4/projects/14232/issues', + 'merge_requests': 'https://gitedu.hesge.ch/api/v4/projects/14232/merge_requests', + 'repo_branches' : 'https://gitedu.hesge.ch/api/v4/projects/14232/repository/branches', + 'labels' : 'https://gitedu.hesge.ch/api/v4/projects/14232/labels', + 'events' : 'https://gitedu.hesge.ch/api/v4/projects/14232/events', + 'members' : 'https://gitedu.hesge.ch/api/v4/projects/14232/members', + 'cluster_agents': 'https://gitedu.hesge.ch/api/v4/projects/14232/cluster_agents' + }, + 'packages_enabled' : true, + 'empty_repo' : true, + 'archived' : false, + 'visibility' : 'private', + 'resolve_outdated_diff_discussions' : false, + 'container_expiration_policy' : { + 'cadence' : '1d', + 'enabled' : false, + 'keep_n' : 10, + 'older_than' : '90d', + 'name_regex' : '.*', + 'name_regex_keep': null, + 'next_run_at' : '2023-12-15T17:58:48.207+01:00' + }, + 'issues_enabled' : true, + 'merge_requests_enabled' : true, + 'wiki_enabled' : false, + 'jobs_enabled' : true, + 'snippets_enabled' : true, + 'container_registry_enabled' : true, + 'service_desk_enabled' : false, + 'service_desk_address' : null, + 'can_create_merge_request_in' : true, + 'issues_access_level' : 'enabled', + 'repository_access_level' : 'enabled', + 'merge_requests_access_level' : 'enabled', + 'forking_access_level' : 'enabled', + 'wiki_access_level' : 'disabled', + 'builds_access_level' : 'enabled', + 'snippets_access_level' : 'enabled', + 'pages_access_level' : 'private', + 'analytics_access_level' : 'enabled', + 'container_registry_access_level' : 'enabled', + 'security_and_compliance_access_level' : 'private', + 'releases_access_level' : 'enabled', + 'environments_access_level' : 'enabled', + 'feature_flags_access_level' : 'enabled', + 'infrastructure_access_level' : 'enabled', + 'monitor_access_level' : 'enabled', + 'emails_disabled' : null, + 'shared_runners_enabled' : true, + 'lfs_enabled' : true, + 'creator_id' : 1076, + 'forked_from_project' : { + 'id' : 13893, + 'description' : 'Dojo assignment repository.\n\nName of the assignment: Technique de compilation - TP', + 'name' : 'Technique de compilation - TP', + 'name_with_namespace': 'DojoDev / Assignment / Technique de compilation - TP', + 'path' : 'technique-de-compilation-tp', + 'path_with_namespace': 'dojodev/assignment/technique-de-compilation-tp', + 'created_at' : '2023-11-07T21:35:48.454+01:00', + 'default_branch' : 'main', + 'tag_list' : [], + 'topics' : [], + 'ssh_url_to_repo' : 'ssh://git@ssh.hesge.ch:10572/dojodev/assignment/technique-de-compilation-tp.git', + 'http_url_to_repo' : 'https://gitedu.hesge.ch/dojodev/assignment/technique-de-compilation-tp.git', + 'web_url' : 'https://gitedu.hesge.ch/dojodev/assignment/technique-de-compilation-tp', + 'readme_url' : 'https://gitedu.hesge.ch/dojodev/assignment/technique-de-compilation-tp/-/blob/main/README.md', + 'forks_count' : 1, + 'avatar_url' : null, + 'star_count' : 0, + 'last_activity_at' : '2023-11-14T13:14:13.820+01:00', + 'namespace' : { + 'id' : 14190, + 'name' : 'Assignment', + 'path' : 'assignment', + 'kind' : 'group', + 'full_path' : 'dojodev/assignment', + 'parent_id' : 14189, + 'avatar_url': null, + 'web_url' : 'https://gitedu.hesge.ch/groups/dojodev/assignment' + } + }, + 'mr_default_target_self' : false, + 'import_url' : null, + 'import_type' : null, + 'import_status' : 'scheduled', + 'import_error' : null, + 'open_issues_count' : 0, + 'description_html' : '<p data-sourcepos="1:1-1:83" dir="auto">Dojo exercise repository based on the the assignment: Technique de compilation - TP</p>', + 'updated_at' : '2023-12-14T17:58:48.185+01:00', + 'ci_default_git_depth' : 20, + 'ci_forward_deployment_enabled' : true, + 'ci_job_token_scope_enabled' : false, + 'ci_separated_caches' : true, + 'ci_allow_fork_pipelines_to_run_in_parent_project': true, + 'build_git_strategy' : 'fetch', + 'keep_latest_artifact' : true, + 'restrict_user_defined_variables' : false, + 'runners_token' : 'GR1348941tdWz3ZxaqbRBmjL5A6r2', + 'runner_token_expiration_interval' : null, + 'group_runners_enabled' : true, + 'auto_cancel_pending_pipelines' : 'enabled', + 'build_timeout' : 3600, + 'auto_devops_enabled' : false, + 'auto_devops_deploy_strategy' : 'continuous', + 'ci_config_path' : '', + 'public_jobs' : true, + 'shared_with_groups' : [], + 'only_allow_merge_if_pipeline_succeeds' : false, + 'allow_merge_on_skipped_pipeline' : null, + 'request_access_enabled' : true, + 'only_allow_merge_if_all_discussions_are_resolved': false, + 'remove_source_branch_after_merge' : true, + 'printing_merge_request_link_enabled' : true, + 'merge_method' : 'merge', + 'squash_option' : 'default_off', + 'enforce_auth_checks_on_uploads' : true, + 'suggestion_commit_message' : null, + 'merge_commit_template' : null, + 'squash_commit_template' : null, + 'issue_branch_template' : null, + 'autoclose_referenced_issues' : true + }, + gitlabLastInfoDate: new Date('2023-12-14T14:54:35.692Z'), + secret : 'ea01568d-2b84-49b7-8603-7d58346f21c6' + } + }); } } async function results() { if ( !SharedConfig.production ) { await db.result.upsert({ - where : { - exerciseId_dateTime: { - exerciseId: 'dc7e1433-23f8-4c8a-a7f3-478b65fa9815', - dateTime : new Date('2023-12-14T14:55:35.692Z') - } - }, - update: {}, - create: { - exerciseId: 'dc7e1433-23f8-4c8a-a7f3-478b65fa9815', - dateTime : new Date('2023-12-14T14:55:35.692Z'), - commit : { - 'shortSha' : '0444bfb5', - 'description' : '', - 'refName' : 'main', - 'refProtected': 'true', - 'sha' : '0444bfb5e986a15b9dadd96c06a6e08b92d230b4', - 'timestamp' : '2023-12-08T13:57:37+01:00', - 'title' : 'Add .gitlab-ci.yml (DO NOT MODIFY THIS FILE)', - 'author' : 'Dojo <hepia.dojo@protonmail.com>', - 'branch' : 'main', - 'refSlug' : 'main', - 'beforeSha' : '2a48bd3c2cc2f810bf10d2b948acab9229253068', - 'message' : 'Add .gitlab-ci.yml (DO NOT MODIFY THIS FILE)' - }, - exitCode : 1, - files : [ { - 'mode' : 33188, - 'size' : 10546, - 'mtime' : '2023-12-08T12:58:31.109Z', - 'birthtime': '2023-12-08T12:58:31.109Z', - 'ext' : 'txt', - 'name' : 'dockerComposeLogs.txt', - 'path' : 'Dojo/dockerComposeLogs.txt' - }, { - 'mode' : 33188, - 'size' : 493, - 'mtime' : '2023-12-08T12:58:31.562Z', - 'birthtime': '2023-12-08T12:58:31.562Z', - 'ext' : 'json', - 'name' : 'results.json', - 'path' : 'Dojo/results.json' - }, { - 'mode' : 33188, - 'size' : 5593, - 'mtime' : '2023-12-08T12:58:30.891Z', - 'birthtime': '2023-12-08T12:58:30.891Z', - 'ext' : 'txt', - 'name' : 'detailedResults.txt', - 'path' : 'Exercise/detailedResults.txt' - }, { - 'mode' : 33188, - 'size' : 149, - 'mtime' : '2023-12-08T12:58:25.855Z', - 'birthtime': '2023-12-08T12:58:30.892Z', - 'ext' : 'bytecode', - 'name' : 'test_1.bytecode', - 'path' : 'Exercise/TestsResults/test_1.bytecode' - }, { - 'mode' : 33188, - 'size' : 1, - 'mtime' : '2023-12-08T12:58:25.983Z', - 'birthtime': '2023-12-08T12:58:30.892Z', - 'ext' : 'output', - 'name' : 'test_1.output', - 'path' : 'Exercise/TestsResults/test_1.output' - }, { - 'mode' : 33188, - 'size' : 468, - 'mtime' : '2023-12-08T12:58:25.702Z', - 'birthtime': '2023-12-08T12:58:30.892Z', - 'ext' : 'source', - 'name' : 'test_1.source', - 'path' : 'Exercise/TestsResults/test_1.source' - }, { - 'mode' : 33188, - 'size' : 149, - 'mtime' : '2023-12-08T12:58:30.247Z', - 'birthtime': '2023-12-08T12:58:30.894Z', - 'ext' : 'bytecode', - 'name' : 'test_10.bytecode', - 'path' : 'Exercise/TestsResults/test_10.bytecode' - }, { - 'mode' : 33188, - 'size' : 1, - 'mtime' : '2023-12-08T12:58:30.376Z', - 'birthtime': '2023-12-08T12:58:30.894Z', - 'ext' : 'output', - 'name' : 'test_10.output', - 'path' : 'Exercise/TestsResults/test_10.output' - }, { - 'mode' : 33188, - 'size' : 468, - 'mtime' : '2023-12-08T12:58:30.098Z', - 'birthtime': '2023-12-08T12:58:30.894Z', - 'ext' : 'source', - 'name' : 'test_10.source', - 'path' : 'Exercise/TestsResults/test_10.source' - }, { - 'mode' : 33188, - 'size' : 149, - 'mtime' : '2023-12-08T12:58:30.737Z', - 'birthtime': '2023-12-08T12:58:30.894Z', - 'ext' : 'bytecode', - 'name' : 'test_11.bytecode', - 'path' : 'Exercise/TestsResults/test_11.bytecode' - }, { - 'mode' : 33188, - 'size' : 468, - 'mtime' : '2023-12-08T12:58:30.584Z', - 'birthtime': '2023-12-08T12:58:30.894Z', - 'ext' : 'source', - 'name' : 'test_11.source', - 'path' : 'Exercise/TestsResults/test_11.source' - }, { - 'mode' : 33188, - 'size' : 1, - 'mtime' : '2023-12-08T12:58:30.890Z', - 'birthtime': '2023-12-08T12:58:30.894Z', - 'ext' : 'output', - 'name' : 'test_11.output', - 'path' : 'Exercise/TestsResults/test_11.output' - }, { - 'mode' : 33188, - 'size' : 149, - 'mtime' : '2023-12-08T12:58:26.322Z', - 'birthtime': '2023-12-08T12:58:30.892Z', - 'ext' : 'bytecode', - 'name' : 'test_2.bytecode', - 'path' : 'Exercise/TestsResults/test_2.bytecode' - }, { - 'mode' : 33188, - 'size' : 1, - 'mtime' : '2023-12-08T12:58:26.455Z', - 'birthtime': '2023-12-08T12:58:30.892Z', - 'ext' : 'output', - 'name' : 'test_2.output', - 'path' : 'Exercise/TestsResults/test_2.output' - }, { - 'mode' : 33188, - 'size' : 639, - 'mtime' : '2023-12-08T12:58:26.178Z', - 'birthtime': '2023-12-08T12:58:30.892Z', - 'ext' : 'source', - 'name' : 'test_2.source', - 'path' : 'Exercise/TestsResults/test_2.source' - }, { - 'mode' : 33188, - 'size' : 149, - 'mtime' : '2023-12-08T12:58:26.781Z', - 'birthtime': '2023-12-08T12:58:30.892Z', - 'ext' : 'bytecode', - 'name' : 'test_3.bytecode', - 'path' : 'Exercise/TestsResults/test_3.bytecode' - }, { - 'mode' : 33188, - 'size' : 1, - 'mtime' : '2023-12-08T12:58:26.884Z', - 'birthtime': '2023-12-08T12:58:30.892Z', - 'ext' : 'output', - 'name' : 'test_3.output', - 'path' : 'Exercise/TestsResults/test_3.output' - }, { - 'mode' : 33188, - 'size' : 468, - 'mtime' : '2023-12-08T12:58:26.637Z', - 'birthtime': '2023-12-08T12:58:30.892Z', - 'ext' : 'source', - 'name' : 'test_3.source', - 'path' : 'Exercise/TestsResults/test_3.source' - }, { - 'mode' : 33188, - 'size' : 149, - 'mtime' : '2023-12-08T12:58:27.228Z', - 'birthtime': '2023-12-08T12:58:30.893Z', - 'ext' : 'bytecode', - 'name' : 'test_4.bytecode', - 'path' : 'Exercise/TestsResults/test_4.bytecode' - }, { - 'mode' : 33188, - 'size' : 1, - 'mtime' : '2023-12-08T12:58:27.331Z', - 'birthtime': '2023-12-08T12:58:30.893Z', - 'ext' : 'output', - 'name' : 'test_4.output', - 'path' : 'Exercise/TestsResults/test_4.output' - }, { - 'mode' : 33188, - 'size' : 468, - 'mtime' : '2023-12-08T12:58:27.092Z', - 'birthtime': '2023-12-08T12:58:30.893Z', - 'ext' : 'source', - 'name' : 'test_4.source', - 'path' : 'Exercise/TestsResults/test_4.source' - }, { - 'mode' : 33188, - 'size' : 149, - 'mtime' : '2023-12-08T12:58:27.688Z', - 'birthtime': '2023-12-08T12:58:30.893Z', - 'ext' : 'bytecode', - 'name' : 'test_5.bytecode', - 'path' : 'Exercise/TestsResults/test_5.bytecode' - }, { - 'mode' : 33188, - 'size' : 1, - 'mtime' : '2023-12-08T12:58:27.820Z', - 'birthtime': '2023-12-08T12:58:30.893Z', - 'ext' : 'output', - 'name' : 'test_5.output', - 'path' : 'Exercise/TestsResults/test_5.output' - }, { - 'mode' : 33188, - 'size' : 639, - 'mtime' : '2023-12-08T12:58:27.533Z', - 'birthtime': '2023-12-08T12:58:30.893Z', - 'ext' : 'source', - 'name' : 'test_5.source', - 'path' : 'Exercise/TestsResults/test_5.source' - }, { - 'mode' : 33188, - 'size' : 149, - 'mtime' : '2023-12-08T12:58:28.177Z', - 'birthtime': '2023-12-08T12:58:30.893Z', - 'ext' : 'bytecode', - 'name' : 'test_6.bytecode', - 'path' : 'Exercise/TestsResults/test_6.bytecode' - }, { - 'mode' : 33188, - 'size' : 1, - 'mtime' : '2023-12-08T12:58:28.322Z', - 'birthtime': '2023-12-08T12:58:30.893Z', - 'ext' : 'output', - 'name' : 'test_6.output', - 'path' : 'Exercise/TestsResults/test_6.output' - }, { - 'mode' : 33188, - 'size' : 639, - 'mtime' : '2023-12-08T12:58:28.033Z', - 'birthtime': '2023-12-08T12:58:30.893Z', - 'ext' : 'source', - 'name' : 'test_6.source', - 'path' : 'Exercise/TestsResults/test_6.source' - }, { - 'mode' : 33188, - 'size' : 149, - 'mtime' : '2023-12-08T12:58:28.696Z', - 'birthtime': '2023-12-08T12:58:30.893Z', - 'ext' : 'bytecode', - 'name' : 'test_7.bytecode', - 'path' : 'Exercise/TestsResults/test_7.bytecode' - }, { - 'mode' : 33188, - 'size' : 1, - 'mtime' : '2023-12-08T12:58:28.871Z', - 'birthtime': '2023-12-08T12:58:30.893Z', - 'ext' : 'output', - 'name' : 'test_7.output', - 'path' : 'Exercise/TestsResults/test_7.output' - }, { - 'mode' : 33188, - 'size' : 468, - 'mtime' : '2023-12-08T12:58:28.538Z', - 'birthtime': '2023-12-08T12:58:30.893Z', - 'ext' : 'source', - 'name' : 'test_7.source', - 'path' : 'Exercise/TestsResults/test_7.source' - }, { - 'mode' : 33188, - 'size' : 149, - 'mtime' : '2023-12-08T12:58:29.229Z', - 'birthtime': '2023-12-08T12:58:30.893Z', - 'ext' : 'bytecode', - 'name' : 'test_8.bytecode', - 'path' : 'Exercise/TestsResults/test_8.bytecode' - }, { - 'mode' : 33188, - 'size' : 1, - 'mtime' : '2023-12-08T12:58:29.352Z', - 'birthtime': '2023-12-08T12:58:30.893Z', - 'ext' : 'output', - 'name' : 'test_8.output', - 'path' : 'Exercise/TestsResults/test_8.output' - }, { - 'mode' : 33188, - 'size' : 468, - 'mtime' : '2023-12-08T12:58:29.087Z', - 'birthtime': '2023-12-08T12:58:30.893Z', - 'ext' : 'source', - 'name' : 'test_8.source', - 'path' : 'Exercise/TestsResults/test_8.source' - }, { - 'mode' : 33188, - 'size' : 149, - 'mtime' : '2023-12-08T12:58:29.723Z', - 'birthtime': '2023-12-08T12:58:30.894Z', - 'ext' : 'bytecode', - 'name' : 'test_9.bytecode', - 'path' : 'Exercise/TestsResults/test_9.bytecode' - }, { - 'mode' : 33188, - 'size' : 1, - 'mtime' : '2023-12-08T12:58:29.886Z', - 'birthtime': '2023-12-08T12:58:30.894Z', - 'ext' : 'output', - 'name' : 'test_9.output', - 'path' : 'Exercise/TestsResults/test_9.output' - }, { - 'mode' : 33188, - 'size' : 468, - 'mtime' : '2023-12-08T12:58:29.570Z', - 'birthtime': '2023-12-08T12:58:30.894Z', - 'ext' : 'source', - 'name' : 'test_9.source', - 'path' : 'Exercise/TestsResults/test_9.source' - } ], - results : { - 'successfulTests' : 0, - 'failedTests' : 16, - 'successfulTestsList': [], - 'failedTestsList' : [ 'Test 1', 'Test 2', 'Test 3', 'Test 4', 'Test 5', 'Test 6', 'Test 7', 'Test 8', 'Test 9', 'Test 10', 'Test 11', 'Semantic error 1', 'Semantic error 2', 'Semantic error 3', 'Semantic error 4', 'Semantic error 5' ], - 'success' : false, - 'containerExitCode' : 1 - }, - success : false - } - }); - + where : { + exerciseId_dateTime: { + exerciseId: 'dc7e1433-23f8-4c8a-a7f3-478b65fa9815', + dateTime : new Date('2023-12-14T14:55:35.692Z') + } + }, + update: {}, + create: { + exerciseId: 'dc7e1433-23f8-4c8a-a7f3-478b65fa9815', + dateTime : new Date('2023-12-14T14:55:35.692Z'), + commit : { + 'shortSha' : '0444bfb5', + 'description' : '', + 'refName' : 'main', + 'refProtected': 'true', + 'sha' : '0444bfb5e986a15b9dadd96c06a6e08b92d230b4', + 'timestamp' : '2023-12-08T13:57:37+01:00', + 'title' : 'Add .gitlab-ci.yml (DO NOT MODIFY THIS FILE)', + 'author' : 'Dojo <hepia.dojo@protonmail.com>', + 'branch' : 'main', + 'refSlug' : 'main', + 'beforeSha' : '2a48bd3c2cc2f810bf10d2b948acab9229253068', + 'message' : 'Add .gitlab-ci.yml (DO NOT MODIFY THIS FILE)' + }, + exitCode : 1, + files : [ { + 'mode' : 33188, + 'size' : 10546, + 'mtime' : '2023-12-08T12:58:31.109Z', + 'birthtime': '2023-12-08T12:58:31.109Z', + 'ext' : 'txt', + 'name' : 'dockerComposeLogs.txt', + 'path' : 'Dojo/dockerComposeLogs.txt' + }, { + 'mode' : 33188, + 'size' : 493, + 'mtime' : '2023-12-08T12:58:31.562Z', + 'birthtime': '2023-12-08T12:58:31.562Z', + 'ext' : 'json', + 'name' : 'results.json', + 'path' : 'Dojo/results.json' + }, { + 'mode' : 33188, + 'size' : 5593, + 'mtime' : '2023-12-08T12:58:30.891Z', + 'birthtime': '2023-12-08T12:58:30.891Z', + 'ext' : 'txt', + 'name' : 'detailedResults.txt', + 'path' : 'Exercise/detailedResults.txt' + }, { + 'mode' : 33188, + 'size' : 149, + 'mtime' : '2023-12-08T12:58:25.855Z', + 'birthtime': '2023-12-08T12:58:30.892Z', + 'ext' : 'bytecode', + 'name' : 'test_1.bytecode', + 'path' : 'Exercise/TestsResults/test_1.bytecode' + }, { + 'mode' : 33188, + 'size' : 1, + 'mtime' : '2023-12-08T12:58:25.983Z', + 'birthtime': '2023-12-08T12:58:30.892Z', + 'ext' : 'output', + 'name' : 'test_1.output', + 'path' : 'Exercise/TestsResults/test_1.output' + }, { + 'mode' : 33188, + 'size' : 468, + 'mtime' : '2023-12-08T12:58:25.702Z', + 'birthtime': '2023-12-08T12:58:30.892Z', + 'ext' : 'source', + 'name' : 'test_1.source', + 'path' : 'Exercise/TestsResults/test_1.source' + }, { + 'mode' : 33188, + 'size' : 149, + 'mtime' : '2023-12-08T12:58:30.247Z', + 'birthtime': '2023-12-08T12:58:30.894Z', + 'ext' : 'bytecode', + 'name' : 'test_10.bytecode', + 'path' : 'Exercise/TestsResults/test_10.bytecode' + }, { + 'mode' : 33188, + 'size' : 1, + 'mtime' : '2023-12-08T12:58:30.376Z', + 'birthtime': '2023-12-08T12:58:30.894Z', + 'ext' : 'output', + 'name' : 'test_10.output', + 'path' : 'Exercise/TestsResults/test_10.output' + }, { + 'mode' : 33188, + 'size' : 468, + 'mtime' : '2023-12-08T12:58:30.098Z', + 'birthtime': '2023-12-08T12:58:30.894Z', + 'ext' : 'source', + 'name' : 'test_10.source', + 'path' : 'Exercise/TestsResults/test_10.source' + }, { + 'mode' : 33188, + 'size' : 149, + 'mtime' : '2023-12-08T12:58:30.737Z', + 'birthtime': '2023-12-08T12:58:30.894Z', + 'ext' : 'bytecode', + 'name' : 'test_11.bytecode', + 'path' : 'Exercise/TestsResults/test_11.bytecode' + }, { + 'mode' : 33188, + 'size' : 468, + 'mtime' : '2023-12-08T12:58:30.584Z', + 'birthtime': '2023-12-08T12:58:30.894Z', + 'ext' : 'source', + 'name' : 'test_11.source', + 'path' : 'Exercise/TestsResults/test_11.source' + }, { + 'mode' : 33188, + 'size' : 1, + 'mtime' : '2023-12-08T12:58:30.890Z', + 'birthtime': '2023-12-08T12:58:30.894Z', + 'ext' : 'output', + 'name' : 'test_11.output', + 'path' : 'Exercise/TestsResults/test_11.output' + }, { + 'mode' : 33188, + 'size' : 149, + 'mtime' : '2023-12-08T12:58:26.322Z', + 'birthtime': '2023-12-08T12:58:30.892Z', + 'ext' : 'bytecode', + 'name' : 'test_2.bytecode', + 'path' : 'Exercise/TestsResults/test_2.bytecode' + }, { + 'mode' : 33188, + 'size' : 1, + 'mtime' : '2023-12-08T12:58:26.455Z', + 'birthtime': '2023-12-08T12:58:30.892Z', + 'ext' : 'output', + 'name' : 'test_2.output', + 'path' : 'Exercise/TestsResults/test_2.output' + }, { + 'mode' : 33188, + 'size' : 639, + 'mtime' : '2023-12-08T12:58:26.178Z', + 'birthtime': '2023-12-08T12:58:30.892Z', + 'ext' : 'source', + 'name' : 'test_2.source', + 'path' : 'Exercise/TestsResults/test_2.source' + }, { + 'mode' : 33188, + 'size' : 149, + 'mtime' : '2023-12-08T12:58:26.781Z', + 'birthtime': '2023-12-08T12:58:30.892Z', + 'ext' : 'bytecode', + 'name' : 'test_3.bytecode', + 'path' : 'Exercise/TestsResults/test_3.bytecode' + }, { + 'mode' : 33188, + 'size' : 1, + 'mtime' : '2023-12-08T12:58:26.884Z', + 'birthtime': '2023-12-08T12:58:30.892Z', + 'ext' : 'output', + 'name' : 'test_3.output', + 'path' : 'Exercise/TestsResults/test_3.output' + }, { + 'mode' : 33188, + 'size' : 468, + 'mtime' : '2023-12-08T12:58:26.637Z', + 'birthtime': '2023-12-08T12:58:30.892Z', + 'ext' : 'source', + 'name' : 'test_3.source', + 'path' : 'Exercise/TestsResults/test_3.source' + }, { + 'mode' : 33188, + 'size' : 149, + 'mtime' : '2023-12-08T12:58:27.228Z', + 'birthtime': '2023-12-08T12:58:30.893Z', + 'ext' : 'bytecode', + 'name' : 'test_4.bytecode', + 'path' : 'Exercise/TestsResults/test_4.bytecode' + }, { + 'mode' : 33188, + 'size' : 1, + 'mtime' : '2023-12-08T12:58:27.331Z', + 'birthtime': '2023-12-08T12:58:30.893Z', + 'ext' : 'output', + 'name' : 'test_4.output', + 'path' : 'Exercise/TestsResults/test_4.output' + }, { + 'mode' : 33188, + 'size' : 468, + 'mtime' : '2023-12-08T12:58:27.092Z', + 'birthtime': '2023-12-08T12:58:30.893Z', + 'ext' : 'source', + 'name' : 'test_4.source', + 'path' : 'Exercise/TestsResults/test_4.source' + }, { + 'mode' : 33188, + 'size' : 149, + 'mtime' : '2023-12-08T12:58:27.688Z', + 'birthtime': '2023-12-08T12:58:30.893Z', + 'ext' : 'bytecode', + 'name' : 'test_5.bytecode', + 'path' : 'Exercise/TestsResults/test_5.bytecode' + }, { + 'mode' : 33188, + 'size' : 1, + 'mtime' : '2023-12-08T12:58:27.820Z', + 'birthtime': '2023-12-08T12:58:30.893Z', + 'ext' : 'output', + 'name' : 'test_5.output', + 'path' : 'Exercise/TestsResults/test_5.output' + }, { + 'mode' : 33188, + 'size' : 639, + 'mtime' : '2023-12-08T12:58:27.533Z', + 'birthtime': '2023-12-08T12:58:30.893Z', + 'ext' : 'source', + 'name' : 'test_5.source', + 'path' : 'Exercise/TestsResults/test_5.source' + }, { + 'mode' : 33188, + 'size' : 149, + 'mtime' : '2023-12-08T12:58:28.177Z', + 'birthtime': '2023-12-08T12:58:30.893Z', + 'ext' : 'bytecode', + 'name' : 'test_6.bytecode', + 'path' : 'Exercise/TestsResults/test_6.bytecode' + }, { + 'mode' : 33188, + 'size' : 1, + 'mtime' : '2023-12-08T12:58:28.322Z', + 'birthtime': '2023-12-08T12:58:30.893Z', + 'ext' : 'output', + 'name' : 'test_6.output', + 'path' : 'Exercise/TestsResults/test_6.output' + }, { + 'mode' : 33188, + 'size' : 639, + 'mtime' : '2023-12-08T12:58:28.033Z', + 'birthtime': '2023-12-08T12:58:30.893Z', + 'ext' : 'source', + 'name' : 'test_6.source', + 'path' : 'Exercise/TestsResults/test_6.source' + }, { + 'mode' : 33188, + 'size' : 149, + 'mtime' : '2023-12-08T12:58:28.696Z', + 'birthtime': '2023-12-08T12:58:30.893Z', + 'ext' : 'bytecode', + 'name' : 'test_7.bytecode', + 'path' : 'Exercise/TestsResults/test_7.bytecode' + }, { + 'mode' : 33188, + 'size' : 1, + 'mtime' : '2023-12-08T12:58:28.871Z', + 'birthtime': '2023-12-08T12:58:30.893Z', + 'ext' : 'output', + 'name' : 'test_7.output', + 'path' : 'Exercise/TestsResults/test_7.output' + }, { + 'mode' : 33188, + 'size' : 468, + 'mtime' : '2023-12-08T12:58:28.538Z', + 'birthtime': '2023-12-08T12:58:30.893Z', + 'ext' : 'source', + 'name' : 'test_7.source', + 'path' : 'Exercise/TestsResults/test_7.source' + }, { + 'mode' : 33188, + 'size' : 149, + 'mtime' : '2023-12-08T12:58:29.229Z', + 'birthtime': '2023-12-08T12:58:30.893Z', + 'ext' : 'bytecode', + 'name' : 'test_8.bytecode', + 'path' : 'Exercise/TestsResults/test_8.bytecode' + }, { + 'mode' : 33188, + 'size' : 1, + 'mtime' : '2023-12-08T12:58:29.352Z', + 'birthtime': '2023-12-08T12:58:30.893Z', + 'ext' : 'output', + 'name' : 'test_8.output', + 'path' : 'Exercise/TestsResults/test_8.output' + }, { + 'mode' : 33188, + 'size' : 468, + 'mtime' : '2023-12-08T12:58:29.087Z', + 'birthtime': '2023-12-08T12:58:30.893Z', + 'ext' : 'source', + 'name' : 'test_8.source', + 'path' : 'Exercise/TestsResults/test_8.source' + }, { + 'mode' : 33188, + 'size' : 149, + 'mtime' : '2023-12-08T12:58:29.723Z', + 'birthtime': '2023-12-08T12:58:30.894Z', + 'ext' : 'bytecode', + 'name' : 'test_9.bytecode', + 'path' : 'Exercise/TestsResults/test_9.bytecode' + }, { + 'mode' : 33188, + 'size' : 1, + 'mtime' : '2023-12-08T12:58:29.886Z', + 'birthtime': '2023-12-08T12:58:30.894Z', + 'ext' : 'output', + 'name' : 'test_9.output', + 'path' : 'Exercise/TestsResults/test_9.output' + }, { + 'mode' : 33188, + 'size' : 468, + 'mtime' : '2023-12-08T12:58:29.570Z', + 'birthtime': '2023-12-08T12:58:30.894Z', + 'ext' : 'source', + 'name' : 'test_9.source', + 'path' : 'Exercise/TestsResults/test_9.source' + } ], + results : { + 'successfulTests' : 0, + 'failedTests' : 16, + 'successfulTestsList': [], + 'failedTestsList' : [ 'Test 1', 'Test 2', 'Test 3', 'Test 4', 'Test 5', 'Test 6', 'Test 7', 'Test 8', 'Test 9', 'Test 10', 'Test 11', 'Semantic error 1', 'Semantic error 2', 'Semantic error 3', 'Semantic error 4', 'Semantic error 5' ], + 'success' : false, + 'containerExitCode' : 1 + }, + success : false + } + }); + await db.result.upsert({ - where : { - exerciseId_dateTime: { - exerciseId: 'dc7e1433-23f8-4c8a-a7f3-478b65fa9815', - dateTime : new Date('2023-12-14T15:35:35.692Z') - } - }, - update: {}, - create: { - exerciseId: 'dc7e1433-23f8-4c8a-a7f3-478b65fa9815', - dateTime : new Date('2023-12-14T15:35:35.692Z'), - commit : { - 'shortSha' : 'bacb58a8', - 'description' : '', - 'refName' : 'main', - 'refProtected': 'true', - 'sha' : 'bacb58a801f93ab9eb08a4a5949a498588c656ff', - 'timestamp' : '2023-12-08T14:05:39+01:00', - 'title' : 'Commit final', - 'author' : 'Michaël Minelli <michael@minelli.me>', - 'branch' : 'main', - 'refSlug' : 'main', - 'beforeSha' : '0444bfb5e986a15b9dadd96c06a6e08b92d230b4', - 'message' : 'Commit final\n' - }, - exitCode : 0, - files : [ { - 'mode' : 33188, - 'size' : 10256, - 'mtime' : '2023-12-08T13:06:36.546Z', - 'birthtime': '2023-12-08T13:06:36.546Z', - 'ext' : 'txt', - 'name' : 'dockerComposeLogs.txt', - 'path' : 'Dojo/dockerComposeLogs.txt' - }, { - 'mode' : 33188, - 'size' : 492, - 'mtime' : '2023-12-08T13:06:36.960Z', - 'birthtime': '2023-12-08T13:06:36.960Z', - 'ext' : 'json', - 'name' : 'results.json', - 'path' : 'Dojo/results.json' - }, { - 'mode' : 33188, - 'size' : 852, - 'mtime' : '2023-12-08T13:06:36.336Z', - 'birthtime': '2023-12-08T13:06:36.336Z', - 'ext' : 'txt', - 'name' : 'detailedResults.txt', - 'path' : 'Exercise/detailedResults.txt' - }, { - 'mode' : 33188, - 'size' : 783, - 'mtime' : '2023-12-08T13:06:30.478Z', - 'birthtime': '2023-12-08T13:06:36.337Z', - 'ext' : 'bytecode', - 'name' : 'test_1.bytecode', - 'path' : 'Exercise/TestsResults/test_1.bytecode' - }, { - 'mode' : 33188, - 'size' : 31, - 'mtime' : '2023-12-08T13:06:30.591Z', - 'birthtime': '2023-12-08T13:06:36.337Z', - 'ext' : 'output', - 'name' : 'test_1.output', - 'path' : 'Exercise/TestsResults/test_1.output' - }, { - 'mode' : 33188, - 'size' : 115, - 'mtime' : '2023-12-08T13:06:30.274Z', - 'birthtime': '2023-12-08T13:06:36.337Z', - 'ext' : 'source', - 'name' : 'test_1.source', - 'path' : 'Exercise/TestsResults/test_1.source' - }, { - 'mode' : 33188, - 'size' : 919, - 'mtime' : '2023-12-08T13:06:35.694Z', - 'birthtime': '2023-12-08T13:06:36.341Z', - 'ext' : 'bytecode', - 'name' : 'test_10.bytecode', - 'path' : 'Exercise/TestsResults/test_10.bytecode' - }, { - 'mode' : 33188, - 'size' : 45, - 'mtime' : '2023-12-08T13:06:35.812Z', - 'birthtime': '2023-12-08T13:06:36.341Z', - 'ext' : 'output', - 'name' : 'test_10.output', - 'path' : 'Exercise/TestsResults/test_10.output' - }, { - 'mode' : 33188, - 'size' : 147, - 'mtime' : '2023-12-08T13:06:35.509Z', - 'birthtime': '2023-12-08T13:06:36.341Z', - 'ext' : 'source', - 'name' : 'test_10.source', - 'path' : 'Exercise/TestsResults/test_10.source' - }, { - 'mode' : 33188, - 'size' : 517, - 'mtime' : '2023-12-08T13:06:36.221Z', - 'birthtime': '2023-12-08T13:06:36.341Z', - 'ext' : 'bytecode', - 'name' : 'test_11.bytecode', - 'path' : 'Exercise/TestsResults/test_11.bytecode' - }, { - 'mode' : 33188, - 'size' : 8, - 'mtime' : '2023-12-08T13:06:36.333Z', - 'birthtime': '2023-12-08T13:06:36.341Z', - 'ext' : 'output', - 'name' : 'test_11.output', - 'path' : 'Exercise/TestsResults/test_11.output' - }, { - 'mode' : 33188, - 'size' : 121, - 'mtime' : '2023-12-08T13:06:36.041Z', - 'birthtime': '2023-12-08T13:06:36.341Z', - 'ext' : 'source', - 'name' : 'test_11.source', - 'path' : 'Exercise/TestsResults/test_11.source' - }, { - 'mode' : 33188, - 'size' : 915, - 'mtime' : '2023-12-08T13:06:31.011Z', - 'birthtime': '2023-12-08T13:06:36.338Z', - 'ext' : 'bytecode', - 'name' : 'test_2.bytecode', - 'path' : 'Exercise/TestsResults/test_2.bytecode' - }, { - 'mode' : 33188, - 'size' : 23, - 'mtime' : '2023-12-08T13:06:31.120Z', - 'birthtime': '2023-12-08T13:06:36.338Z', - 'ext' : 'output', - 'name' : 'test_2.output', - 'path' : 'Exercise/TestsResults/test_2.output' - }, { - 'mode' : 33188, - 'size' : 192, - 'mtime' : '2023-12-08T13:06:30.843Z', - 'birthtime': '2023-12-08T13:06:36.338Z', - 'ext' : 'source', - 'name' : 'test_2.source', - 'path' : 'Exercise/TestsResults/test_2.source' - }, { - 'mode' : 33188, - 'size' : 1730, - 'mtime' : '2023-12-08T13:06:31.592Z', - 'birthtime': '2023-12-08T13:06:36.338Z', - 'ext' : 'bytecode', - 'name' : 'test_3.bytecode', - 'path' : 'Exercise/TestsResults/test_3.bytecode' - }, { - 'mode' : 33188, - 'size' : 32, - 'mtime' : '2023-12-08T13:06:31.695Z', - 'birthtime': '2023-12-08T13:06:36.338Z', - 'ext' : 'output', - 'name' : 'test_3.output', - 'path' : 'Exercise/TestsResults/test_3.output' - }, { - 'mode' : 33188, - 'size' : 331, - 'mtime' : '2023-12-08T13:06:31.399Z', - 'birthtime': '2023-12-08T13:06:36.338Z', - 'ext' : 'source', - 'name' : 'test_3.source', - 'path' : 'Exercise/TestsResults/test_3.source' - }, { - 'mode' : 33188, - 'size' : 1392, - 'mtime' : '2023-12-08T13:06:32.151Z', - 'birthtime': '2023-12-08T13:06:36.339Z', - 'ext' : 'bytecode', - 'name' : 'test_4.bytecode', - 'path' : 'Exercise/TestsResults/test_4.bytecode' - }, { - 'mode' : 33188, - 'size' : 41, - 'mtime' : '2023-12-08T13:06:32.268Z', - 'birthtime': '2023-12-08T13:06:36.339Z', - 'ext' : 'output', - 'name' : 'test_4.output', - 'path' : 'Exercise/TestsResults/test_4.output' - }, { - 'mode' : 33188, - 'size' : 280, - 'mtime' : '2023-12-08T13:06:31.953Z', - 'birthtime': '2023-12-08T13:06:36.339Z', - 'ext' : 'source', - 'name' : 'test_4.source', - 'path' : 'Exercise/TestsResults/test_4.source' - }, { - 'mode' : 33188, - 'size' : 14810, - 'mtime' : '2023-12-08T13:06:32.728Z', - 'birthtime': '2023-12-08T13:06:36.339Z', - 'ext' : 'bytecode', - 'name' : 'test_5.bytecode', - 'path' : 'Exercise/TestsResults/test_5.bytecode' - }, { - 'mode' : 33188, - 'size' : 315, - 'mtime' : '2023-12-08T13:06:32.892Z', - 'birthtime': '2023-12-08T13:06:36.339Z', - 'ext' : 'output', - 'name' : 'test_5.output', - 'path' : 'Exercise/TestsResults/test_5.output' - }, { - 'mode' : 33188, - 'size' : 1383, - 'mtime' : '2023-12-08T13:06:32.533Z', - 'birthtime': '2023-12-08T13:06:36.339Z', - 'ext' : 'source', - 'name' : 'test_5.source', - 'path' : 'Exercise/TestsResults/test_5.source' - }, { - 'mode' : 33188, - 'size' : 1374, - 'mtime' : '2023-12-08T13:06:33.396Z', - 'birthtime': '2023-12-08T13:06:36.339Z', - 'ext' : 'bytecode', - 'name' : 'test_6.bytecode', - 'path' : 'Exercise/TestsResults/test_6.bytecode' - }, { - 'mode' : 33188, - 'size' : 15, - 'mtime' : '2023-12-08T13:06:33.504Z', - 'birthtime': '2023-12-08T13:06:36.339Z', - 'ext' : 'output', - 'name' : 'test_6.output', - 'path' : 'Exercise/TestsResults/test_6.output' - }, { - 'mode' : 33188, - 'size' : 410, - 'mtime' : '2023-12-08T13:06:33.180Z', - 'birthtime': '2023-12-08T13:06:36.339Z', - 'ext' : 'source', - 'name' : 'test_6.source', - 'path' : 'Exercise/TestsResults/test_6.source' - }, { - 'mode' : 33188, - 'size' : 1471, - 'mtime' : '2023-12-08T13:06:33.958Z', - 'birthtime': '2023-12-08T13:06:36.340Z', - 'ext' : 'bytecode', - 'name' : 'test_7.bytecode', - 'path' : 'Exercise/TestsResults/test_7.bytecode' - }, { - 'mode' : 33188, - 'size' : 68, - 'mtime' : '2023-12-08T13:06:34.060Z', - 'birthtime': '2023-12-08T13:06:36.340Z', - 'ext' : 'output', - 'name' : 'test_7.output', - 'path' : 'Exercise/TestsResults/test_7.output' - }, { - 'mode' : 33188, - 'size' : 417, - 'mtime' : '2023-12-08T13:06:33.764Z', - 'birthtime': '2023-12-08T13:06:36.340Z', - 'ext' : 'source', - 'name' : 'test_7.source', - 'path' : 'Exercise/TestsResults/test_7.source' - }, { - 'mode' : 33188, - 'size' : 1301, - 'mtime' : '2023-12-08T13:06:34.524Z', - 'birthtime': '2023-12-08T13:06:36.340Z', - 'ext' : 'bytecode', - 'name' : 'test_8.bytecode', - 'path' : 'Exercise/TestsResults/test_8.bytecode' - }, { - 'mode' : 33188, - 'size' : 72, - 'mtime' : '2023-12-08T13:06:34.654Z', - 'birthtime': '2023-12-08T13:06:36.340Z', - 'ext' : 'output', - 'name' : 'test_8.output', - 'path' : 'Exercise/TestsResults/test_8.output' - }, { - 'mode' : 33188, - 'size' : 352, - 'mtime' : '2023-12-08T13:06:34.336Z', - 'birthtime': '2023-12-08T13:06:36.340Z', - 'ext' : 'source', - 'name' : 'test_8.source', - 'path' : 'Exercise/TestsResults/test_8.source' - }, { - 'mode' : 33188, - 'size' : 771, - 'mtime' : '2023-12-08T13:06:35.117Z', - 'birthtime': '2023-12-08T13:06:36.340Z', - 'ext' : 'bytecode', - 'name' : 'test_9.bytecode', - 'path' : 'Exercise/TestsResults/test_9.bytecode' - }, { - 'mode' : 33188, - 'size' : 31, - 'mtime' : '2023-12-08T13:06:35.257Z', - 'birthtime': '2023-12-08T13:06:36.341Z', - 'ext' : 'output', - 'name' : 'test_9.output', - 'path' : 'Exercise/TestsResults/test_9.output' - }, { - 'mode' : 33188, - 'size' : 132, - 'mtime' : '2023-12-08T13:06:34.916Z', - 'birthtime': '2023-12-08T13:06:36.340Z', - 'ext' : 'source', - 'name' : 'test_9.source', - 'path' : 'Exercise/TestsResults/test_9.source' - } ], - results : { - 'successfulTests' : 16, - 'failedTests' : 0, - 'successfulTestsList': [ 'Test 1', 'Test 2', 'Test 3', 'Test 4', 'Test 5', 'Test 6', 'Test 7', 'Test 8', 'Test 9', 'Test 10', 'Test 11', 'Semantic error 1', 'Semantic error 2', 'Semantic error 3', 'Semantic error 4', 'Semantic error 5' ], - 'failedTestsList' : [], - 'success' : true, - 'containerExitCode' : 0 - }, - success : true - } - }); + where : { + exerciseId_dateTime: { + exerciseId: 'dc7e1433-23f8-4c8a-a7f3-478b65fa9815', + dateTime : new Date('2023-12-14T15:35:35.692Z') + } + }, + update: {}, + create: { + exerciseId: 'dc7e1433-23f8-4c8a-a7f3-478b65fa9815', + dateTime : new Date('2023-12-14T15:35:35.692Z'), + commit : { + 'shortSha' : 'bacb58a8', + 'description' : '', + 'refName' : 'main', + 'refProtected': 'true', + 'sha' : 'bacb58a801f93ab9eb08a4a5949a498588c656ff', + 'timestamp' : '2023-12-08T14:05:39+01:00', + 'title' : 'Commit final', + 'author' : 'Michaël Minelli <michael@minelli.me>', + 'branch' : 'main', + 'refSlug' : 'main', + 'beforeSha' : '0444bfb5e986a15b9dadd96c06a6e08b92d230b4', + 'message' : 'Commit final\n' + }, + exitCode : 0, + files : [ { + 'mode' : 33188, + 'size' : 10256, + 'mtime' : '2023-12-08T13:06:36.546Z', + 'birthtime': '2023-12-08T13:06:36.546Z', + 'ext' : 'txt', + 'name' : 'dockerComposeLogs.txt', + 'path' : 'Dojo/dockerComposeLogs.txt' + }, { + 'mode' : 33188, + 'size' : 492, + 'mtime' : '2023-12-08T13:06:36.960Z', + 'birthtime': '2023-12-08T13:06:36.960Z', + 'ext' : 'json', + 'name' : 'results.json', + 'path' : 'Dojo/results.json' + }, { + 'mode' : 33188, + 'size' : 852, + 'mtime' : '2023-12-08T13:06:36.336Z', + 'birthtime': '2023-12-08T13:06:36.336Z', + 'ext' : 'txt', + 'name' : 'detailedResults.txt', + 'path' : 'Exercise/detailedResults.txt' + }, { + 'mode' : 33188, + 'size' : 783, + 'mtime' : '2023-12-08T13:06:30.478Z', + 'birthtime': '2023-12-08T13:06:36.337Z', + 'ext' : 'bytecode', + 'name' : 'test_1.bytecode', + 'path' : 'Exercise/TestsResults/test_1.bytecode' + }, { + 'mode' : 33188, + 'size' : 31, + 'mtime' : '2023-12-08T13:06:30.591Z', + 'birthtime': '2023-12-08T13:06:36.337Z', + 'ext' : 'output', + 'name' : 'test_1.output', + 'path' : 'Exercise/TestsResults/test_1.output' + }, { + 'mode' : 33188, + 'size' : 115, + 'mtime' : '2023-12-08T13:06:30.274Z', + 'birthtime': '2023-12-08T13:06:36.337Z', + 'ext' : 'source', + 'name' : 'test_1.source', + 'path' : 'Exercise/TestsResults/test_1.source' + }, { + 'mode' : 33188, + 'size' : 919, + 'mtime' : '2023-12-08T13:06:35.694Z', + 'birthtime': '2023-12-08T13:06:36.341Z', + 'ext' : 'bytecode', + 'name' : 'test_10.bytecode', + 'path' : 'Exercise/TestsResults/test_10.bytecode' + }, { + 'mode' : 33188, + 'size' : 45, + 'mtime' : '2023-12-08T13:06:35.812Z', + 'birthtime': '2023-12-08T13:06:36.341Z', + 'ext' : 'output', + 'name' : 'test_10.output', + 'path' : 'Exercise/TestsResults/test_10.output' + }, { + 'mode' : 33188, + 'size' : 147, + 'mtime' : '2023-12-08T13:06:35.509Z', + 'birthtime': '2023-12-08T13:06:36.341Z', + 'ext' : 'source', + 'name' : 'test_10.source', + 'path' : 'Exercise/TestsResults/test_10.source' + }, { + 'mode' : 33188, + 'size' : 517, + 'mtime' : '2023-12-08T13:06:36.221Z', + 'birthtime': '2023-12-08T13:06:36.341Z', + 'ext' : 'bytecode', + 'name' : 'test_11.bytecode', + 'path' : 'Exercise/TestsResults/test_11.bytecode' + }, { + 'mode' : 33188, + 'size' : 8, + 'mtime' : '2023-12-08T13:06:36.333Z', + 'birthtime': '2023-12-08T13:06:36.341Z', + 'ext' : 'output', + 'name' : 'test_11.output', + 'path' : 'Exercise/TestsResults/test_11.output' + }, { + 'mode' : 33188, + 'size' : 121, + 'mtime' : '2023-12-08T13:06:36.041Z', + 'birthtime': '2023-12-08T13:06:36.341Z', + 'ext' : 'source', + 'name' : 'test_11.source', + 'path' : 'Exercise/TestsResults/test_11.source' + }, { + 'mode' : 33188, + 'size' : 915, + 'mtime' : '2023-12-08T13:06:31.011Z', + 'birthtime': '2023-12-08T13:06:36.338Z', + 'ext' : 'bytecode', + 'name' : 'test_2.bytecode', + 'path' : 'Exercise/TestsResults/test_2.bytecode' + }, { + 'mode' : 33188, + 'size' : 23, + 'mtime' : '2023-12-08T13:06:31.120Z', + 'birthtime': '2023-12-08T13:06:36.338Z', + 'ext' : 'output', + 'name' : 'test_2.output', + 'path' : 'Exercise/TestsResults/test_2.output' + }, { + 'mode' : 33188, + 'size' : 192, + 'mtime' : '2023-12-08T13:06:30.843Z', + 'birthtime': '2023-12-08T13:06:36.338Z', + 'ext' : 'source', + 'name' : 'test_2.source', + 'path' : 'Exercise/TestsResults/test_2.source' + }, { + 'mode' : 33188, + 'size' : 1730, + 'mtime' : '2023-12-08T13:06:31.592Z', + 'birthtime': '2023-12-08T13:06:36.338Z', + 'ext' : 'bytecode', + 'name' : 'test_3.bytecode', + 'path' : 'Exercise/TestsResults/test_3.bytecode' + }, { + 'mode' : 33188, + 'size' : 32, + 'mtime' : '2023-12-08T13:06:31.695Z', + 'birthtime': '2023-12-08T13:06:36.338Z', + 'ext' : 'output', + 'name' : 'test_3.output', + 'path' : 'Exercise/TestsResults/test_3.output' + }, { + 'mode' : 33188, + 'size' : 331, + 'mtime' : '2023-12-08T13:06:31.399Z', + 'birthtime': '2023-12-08T13:06:36.338Z', + 'ext' : 'source', + 'name' : 'test_3.source', + 'path' : 'Exercise/TestsResults/test_3.source' + }, { + 'mode' : 33188, + 'size' : 1392, + 'mtime' : '2023-12-08T13:06:32.151Z', + 'birthtime': '2023-12-08T13:06:36.339Z', + 'ext' : 'bytecode', + 'name' : 'test_4.bytecode', + 'path' : 'Exercise/TestsResults/test_4.bytecode' + }, { + 'mode' : 33188, + 'size' : 41, + 'mtime' : '2023-12-08T13:06:32.268Z', + 'birthtime': '2023-12-08T13:06:36.339Z', + 'ext' : 'output', + 'name' : 'test_4.output', + 'path' : 'Exercise/TestsResults/test_4.output' + }, { + 'mode' : 33188, + 'size' : 280, + 'mtime' : '2023-12-08T13:06:31.953Z', + 'birthtime': '2023-12-08T13:06:36.339Z', + 'ext' : 'source', + 'name' : 'test_4.source', + 'path' : 'Exercise/TestsResults/test_4.source' + }, { + 'mode' : 33188, + 'size' : 14810, + 'mtime' : '2023-12-08T13:06:32.728Z', + 'birthtime': '2023-12-08T13:06:36.339Z', + 'ext' : 'bytecode', + 'name' : 'test_5.bytecode', + 'path' : 'Exercise/TestsResults/test_5.bytecode' + }, { + 'mode' : 33188, + 'size' : 315, + 'mtime' : '2023-12-08T13:06:32.892Z', + 'birthtime': '2023-12-08T13:06:36.339Z', + 'ext' : 'output', + 'name' : 'test_5.output', + 'path' : 'Exercise/TestsResults/test_5.output' + }, { + 'mode' : 33188, + 'size' : 1383, + 'mtime' : '2023-12-08T13:06:32.533Z', + 'birthtime': '2023-12-08T13:06:36.339Z', + 'ext' : 'source', + 'name' : 'test_5.source', + 'path' : 'Exercise/TestsResults/test_5.source' + }, { + 'mode' : 33188, + 'size' : 1374, + 'mtime' : '2023-12-08T13:06:33.396Z', + 'birthtime': '2023-12-08T13:06:36.339Z', + 'ext' : 'bytecode', + 'name' : 'test_6.bytecode', + 'path' : 'Exercise/TestsResults/test_6.bytecode' + }, { + 'mode' : 33188, + 'size' : 15, + 'mtime' : '2023-12-08T13:06:33.504Z', + 'birthtime': '2023-12-08T13:06:36.339Z', + 'ext' : 'output', + 'name' : 'test_6.output', + 'path' : 'Exercise/TestsResults/test_6.output' + }, { + 'mode' : 33188, + 'size' : 410, + 'mtime' : '2023-12-08T13:06:33.180Z', + 'birthtime': '2023-12-08T13:06:36.339Z', + 'ext' : 'source', + 'name' : 'test_6.source', + 'path' : 'Exercise/TestsResults/test_6.source' + }, { + 'mode' : 33188, + 'size' : 1471, + 'mtime' : '2023-12-08T13:06:33.958Z', + 'birthtime': '2023-12-08T13:06:36.340Z', + 'ext' : 'bytecode', + 'name' : 'test_7.bytecode', + 'path' : 'Exercise/TestsResults/test_7.bytecode' + }, { + 'mode' : 33188, + 'size' : 68, + 'mtime' : '2023-12-08T13:06:34.060Z', + 'birthtime': '2023-12-08T13:06:36.340Z', + 'ext' : 'output', + 'name' : 'test_7.output', + 'path' : 'Exercise/TestsResults/test_7.output' + }, { + 'mode' : 33188, + 'size' : 417, + 'mtime' : '2023-12-08T13:06:33.764Z', + 'birthtime': '2023-12-08T13:06:36.340Z', + 'ext' : 'source', + 'name' : 'test_7.source', + 'path' : 'Exercise/TestsResults/test_7.source' + }, { + 'mode' : 33188, + 'size' : 1301, + 'mtime' : '2023-12-08T13:06:34.524Z', + 'birthtime': '2023-12-08T13:06:36.340Z', + 'ext' : 'bytecode', + 'name' : 'test_8.bytecode', + 'path' : 'Exercise/TestsResults/test_8.bytecode' + }, { + 'mode' : 33188, + 'size' : 72, + 'mtime' : '2023-12-08T13:06:34.654Z', + 'birthtime': '2023-12-08T13:06:36.340Z', + 'ext' : 'output', + 'name' : 'test_8.output', + 'path' : 'Exercise/TestsResults/test_8.output' + }, { + 'mode' : 33188, + 'size' : 352, + 'mtime' : '2023-12-08T13:06:34.336Z', + 'birthtime': '2023-12-08T13:06:36.340Z', + 'ext' : 'source', + 'name' : 'test_8.source', + 'path' : 'Exercise/TestsResults/test_8.source' + }, { + 'mode' : 33188, + 'size' : 771, + 'mtime' : '2023-12-08T13:06:35.117Z', + 'birthtime': '2023-12-08T13:06:36.340Z', + 'ext' : 'bytecode', + 'name' : 'test_9.bytecode', + 'path' : 'Exercise/TestsResults/test_9.bytecode' + }, { + 'mode' : 33188, + 'size' : 31, + 'mtime' : '2023-12-08T13:06:35.257Z', + 'birthtime': '2023-12-08T13:06:36.341Z', + 'ext' : 'output', + 'name' : 'test_9.output', + 'path' : 'Exercise/TestsResults/test_9.output' + }, { + 'mode' : 33188, + 'size' : 132, + 'mtime' : '2023-12-08T13:06:34.916Z', + 'birthtime': '2023-12-08T13:06:36.340Z', + 'ext' : 'source', + 'name' : 'test_9.source', + 'path' : 'Exercise/TestsResults/test_9.source' + } ], + results : { + 'successfulTests' : 16, + 'failedTests' : 0, + 'successfulTestsList': [ 'Test 1', 'Test 2', 'Test 3', 'Test 4', 'Test 5', 'Test 6', 'Test 7', 'Test 8', 'Test 9', 'Test 10', 'Test 11', 'Semantic error 1', 'Semantic error 2', 'Semantic error 3', 'Semantic error 4', 'Semantic error 5' ], + 'failedTestsList' : [], + 'success' : true, + 'containerExitCode' : 0 + }, + success : true + } + }); } } \ No newline at end of file diff --git a/ExpressAPI/src/express/API.ts b/ExpressAPI/src/express/API.ts index 0d61b88..9cbd33a 100644 --- a/ExpressAPI/src/express/API.ts +++ b/ExpressAPI/src/express/API.ts @@ -22,35 +22,35 @@ import DojoCliVersionHelper from '../helpers/DojoCliVersionHelper'; class API implements WorkerTask { private readonly backend: Express; private server: http.Server | undefined; - + constructor() { this.backend = express(); - + this.initOpenAPI(); this.initBaseMiddlewares(); - + this.backend.use(ClientVersionCheckerMiddleware.register()); - + ParamsCallbackManager.registerOnBackend(this.backend); SessionMiddleware.registerOnBackend(this.backend); ApiRoutesManager.registerOnBackend(this.backend); } - + private initBaseMiddlewares() { this.backend.use(multer({ - limits: { fieldSize: 100 * 1024 * 1024 } - }).none()); //Used for extract params from body with format "form-data", The none is for say that we do not wait a file in params + limits: { fieldSize: 100 * 1024 * 1024 } + }).none()); //Used for extract params from body with format "form-data", The none is for say that we do not wait a file in params this.backend.use(morganMiddleware); //Log API accesses this.backend.use(helmet()); //Help to secure express, https://helmetjs.github.io/ this.backend.use(cors()); //Allow CORS requests this.backend.use(compression()); //Compress responses - + this.backend.use(async (req, res, next) => { res.header('dojocli-latest-version', await DojoCliVersionHelper.getLatestVersion()); next(); }); } - + private initOpenAPI() { const options = { customSiteTitle: 'Dojo API', @@ -62,34 +62,34 @@ class API implements WorkerTask { this.backend.get('/docs/OpenAPI.yaml', (req, res) => res.sendFile(path.resolve(__dirname + '/../../assets/OpenAPI/OpenAPI.yaml'))); this.backend.use('/docs/swagger', swaggerUi.serveFiles(undefined, options), swaggerUi.setup(undefined, options)); this.backend.get('/docs/redoc.html', (req, res) => res.sendFile(path.resolve(__dirname + '/../../assets/OpenAPI/redoc.html'))); - + this.backend.get('/docs/', (req, res) => { const prefix = req.url.slice(-1) === '/' ? '' : 'docs/'; res.send(` - <!DOCTYPE html> - <html lang="en"> - <body> - <ul> - <li><a href="${ prefix }OpenAPI.yaml">OpenAPI</a></li> - <li>GUI - <ul> - <li><a href="${ prefix }swagger/">Swagger</a></li> - <li><a href="${ prefix }redoc.html">Redoc</a></li> - </ul> - </li> - </ul> - </body> - </html> + <!DOCTYPE html> + <html lang="en"> + <body> + <ul> + <li><a href="${ prefix }OpenAPI.yaml">OpenAPI</a></li> + <li>GUI + <ul> + <li><a href="${ prefix }swagger/">Swagger</a></li> + <li><a href="${ prefix }redoc.html">Redoc</a></li> + </ul> + </li> + </ul> + </body> + </html> `); }); } - + run() { this.server = this.backend.listen(Config.api.port, '0.0.0.0', () => { const { - port, - address - } = this.server!.address() as AddressInfo; + port, + address + } = this.server!.address() as AddressInfo; logger.info(`Server started on http://${ address }:${ port }`); }); } diff --git a/ExpressAPI/src/helpers/DatabaseHelper.ts b/ExpressAPI/src/helpers/DatabaseHelper.ts index 89ec9c7..ec96921 100644 --- a/ExpressAPI/src/helpers/DatabaseHelper.ts +++ b/ExpressAPI/src/helpers/DatabaseHelper.ts @@ -5,20 +5,20 @@ import UserResultExtension from './Prisma/Extensions/UserResultExtension'; const prisma = new PrismaClient({ - log: [ { - emit : 'event', - level: 'query' - }, { - emit : 'event', - level: 'info' - }, { - emit : 'event', - level: 'warn' - }, { - emit : 'event', - level: 'error' - } ] - }); + log: [ { + emit : 'event', + level: 'query' + }, { + emit : 'event', + level: 'info' + }, { + emit : 'event', + level: 'warn' + }, { + emit : 'event', + level: 'error' + } ] +}); prisma.$on('query', e => { logger.debug(`Prisma => Query (${ e.duration }ms): ${ e.query }`); diff --git a/ExpressAPI/src/helpers/DojoValidators.ts b/ExpressAPI/src/helpers/DojoValidators.ts index 98a2825..3c5ab2e 100644 --- a/ExpressAPI/src/helpers/DojoValidators.ts +++ b/ExpressAPI/src/helpers/DojoValidators.ts @@ -23,89 +23,89 @@ class DojoValidators { // This is a hack to make the types work with req arg as express.Request instead of Request defined by express-validator return arg as unknown as DojoCustomValidatorSchemaOptions; } - + private getParamValue(req: express.Request, path: string): unknown { return 'body' in req && path in req.body ? req.body[path] : req.query[path]; } - + readonly nullSanitizer = this.toValidatorSchemaOptions({ - options: (value) => { - try { - return value == 'null' || value == 'undefined' || value == '' ? null : value; - } catch ( error ) { - logger.error(`null sanitizer error: ${ error }`); - - return value; - } - } - }); - + options: (value) => { + try { + return value == 'null' || value == 'undefined' || value == '' ? null : value; + } catch ( error ) { + logger.error(`null sanitizer error: ${ error }`); + + return value; + } + } + }); + readonly jsonSanitizer = this.toValidatorSchemaOptions({ - options: (value) => { - try { - return JSON.parse(value as string); - } catch ( e ) { - return value; - } - } - }); - + options: (value) => { + try { + return JSON.parse(value as string); + } catch ( e ) { + return value; + } + } + }); + readonly templateUrlValidator = this.toValidatorSchemaOptions({ - bail : true, - errorMessage: 'Template doesn\'t exist or you don\'t have access to it', - options : (_value, { - req, - path - }) => { - return new Promise((resolve, reject) => { - const template = this.getParamValue(req, path) as string; - if ( template ) { - GitlabManager.checkTemplateAccess(template, req).then((templateAccess) => { - templateAccess !== StatusCodes.OK ? reject() : resolve(true); - }); - } - resolve(true); - }); - } - }); - + bail : true, + errorMessage: 'Template doesn\'t exist or you don\'t have access to it', + options : (_value, { + req, + path + }) => { + return new Promise((resolve, reject) => { + const template = this.getParamValue(req, path) as string; + if ( template ) { + GitlabManager.checkTemplateAccess(template, req).then((templateAccess) => { + templateAccess !== StatusCodes.OK ? reject() : resolve(true); + }); + } + resolve(true); + }); + } + }); + readonly templateUrlSanitizer = this.toValidatorSchemaOptions({ - options: (value, { - req, - path - }) => { - try { - const template = this.getParamValue(req, path); - if ( template ) { - return `${ Config.gitlab.urls[0].replace(/^([a-z]{3,5}:\/{2})?(.*)/, `$1${ Config.gitlab.account.username }:${ Config.gitlab.account.token }@$2`) }${ template }.git`; - } else { - return Config.assignment.default.template; - } - } catch ( error ) { - logger.error(`Template url sanitizer error: ${ error }`); - - return value; - } - } - }); - + options: (value, { + req, + path + }) => { + try { + const template = this.getParamValue(req, path); + if ( template ) { + return `${ Config.gitlab.urls[0].replace(/^([a-z]{3,5}:\/{2})?(.*)/, `$1${ Config.gitlab.account.username }:${ Config.gitlab.account.token }@$2`) }${ template }.git`; + } else { + return Config.assignment.default.template; + } + } catch ( error ) { + logger.error(`Template url sanitizer error: ${ error }`); + + return value; + } + } + }); + readonly exerciseResultsValidator = this.toValidatorSchemaOptions({ - bail : true, - errorMessage: 'Results: not provided or invalid format', - options : (_value, { - req, - path - }) => { - return new Promise((resolve, reject) => { - const results = this.getParamValue(req, path) as string; - if ( results ) { - Json5FileValidator.validateFile(ExerciseResultsFile, results, false).isValid ? resolve(true) : reject(); - } else { - reject(); - } - }); - } - }); + bail : true, + errorMessage: 'Results: not provided or invalid format', + options : (_value, { + req, + path + }) => { + return new Promise((resolve, reject) => { + const results = this.getParamValue(req, path) as string; + if ( results ) { + Json5FileValidator.validateFile(ExerciseResultsFile, results, false).isValid ? resolve(true) : reject(); + } else { + reject(); + } + }); + } + }); } diff --git a/ExpressAPI/src/helpers/Prisma/Extensions/UserQueryExtension.ts b/ExpressAPI/src/helpers/Prisma/Extensions/UserQueryExtension.ts index 0627c77..33d2f93 100644 --- a/ExpressAPI/src/helpers/Prisma/Extensions/UserQueryExtension.ts +++ b/ExpressAPI/src/helpers/Prisma/Extensions/UserQueryExtension.ts @@ -3,29 +3,29 @@ import { Prisma } from '@prisma/client'; export default Prisma.defineExtension(client => { return client.$extends({ - query: { - user: { - async delete({ - args - }) { - - return client.user.update(Object.assign(args, { - data: { - deleted: true - } - })); - }, - async deleteMany({ - args - }) { - - return client.user.updateMany(Object.assign(args, { - data: { - deleted: true - } - })); - } - } - } - }); + query: { + user: { + async delete({ + args + }) { + + return client.user.update(Object.assign(args, { + data: { + deleted: true + } + })); + }, + async deleteMany({ + args + }) { + + return client.user.updateMany(Object.assign(args, { + data: { + deleted: true + } + })); + } + } + } + }); }); \ No newline at end of file diff --git a/ExpressAPI/src/helpers/Prisma/Extensions/UserResultExtension.ts b/ExpressAPI/src/helpers/Prisma/Extensions/UserResultExtension.ts index 9ece43d..5ed3634 100644 --- a/ExpressAPI/src/helpers/Prisma/Extensions/UserResultExtension.ts +++ b/ExpressAPI/src/helpers/Prisma/Extensions/UserResultExtension.ts @@ -6,32 +6,32 @@ import GitlabManager from '../../../managers/GitlabManager'; export default Prisma.defineExtension(client => { return client.$extends({ - result: { - user: { - isTeachingStaff: { - needs: { - role: true - }, - compute(user) { - return user.role == UserRole.TEACHING_STAFF || user.role == UserRole.ADMIN; - } - }, - isAdmin : { - needs: { - role: true - }, - compute(user) { - return user.role == UserRole.ADMIN; - } - }, - gitlabProfile : { - compute(user) { - return new LazyVal<GitlabUser | undefined>(() => { - return GitlabManager.getUserById(user.id); - }); - } - } - } - } - }); + result: { + user: { + isTeachingStaff: { + needs: { + role: true + }, + compute(user) { + return user.role == UserRole.TEACHING_STAFF || user.role == UserRole.ADMIN; + } + }, + isAdmin : { + needs: { + role: true + }, + compute(user) { + return user.role == UserRole.ADMIN; + } + }, + gitlabProfile : { + compute(user) { + return new LazyVal<GitlabUser | undefined>(() => { + return GitlabManager.getUserById(user.id); + }); + } + } + } + } + }); }); \ No newline at end of file diff --git a/ExpressAPI/src/managers/AssignmentManager.ts b/ExpressAPI/src/managers/AssignmentManager.ts index 0f2bc54..e4a5209 100644 --- a/ExpressAPI/src/managers/AssignmentManager.ts +++ b/ExpressAPI/src/managers/AssignmentManager.ts @@ -7,28 +7,28 @@ class AssignmentManager { async isUserAllowedToAccessAssignment(assignment: Assignment, user: User): Promise<boolean> { if ( !assignment.staff ) { assignment.staff = await db.assignment.findUnique({ - where: { - name: assignment.name - } - }).staff() ?? []; + where: { + name: assignment.name + } + }).staff() ?? []; } return assignment.staff.findIndex(staff => staff.id === user.id) !== -1; } - + async getByName(name: string, include: Prisma.AssignmentInclude | undefined = undefined): Promise<Assignment | undefined> { return await db.assignment.findUnique({ - where : { - name: name - }, include: include - }) as unknown as Assignment ?? undefined; + where : { + name: name + }, include: include + }) as unknown as Assignment ?? undefined; } - + getByGitlabLink(gitlabLink: string, include: Prisma.AssignmentInclude | undefined = undefined): Promise<Assignment | undefined> { const name = gitlabLink.replace('.git', '').split('/').pop()!; - + return this.getByName(name, include); } - + get(nameOrUrl: string, include: Prisma.AssignmentInclude | undefined = undefined): Promise<Assignment | undefined> { // We can use the same function for both name and url because the name is the last part of the url and the name extraction from the url doesn't corrupt the name return this.getByGitlabLink(nameOrUrl, include); diff --git a/ExpressAPI/src/managers/UserManager.ts b/ExpressAPI/src/managers/UserManager.ts index 686ee26..ae472e2 100644 --- a/ExpressAPI/src/managers/UserManager.ts +++ b/ExpressAPI/src/managers/UserManager.ts @@ -8,59 +8,59 @@ import { User } from '../types/DatabaseTypes'; class UserManager { async getByMail(mail: string, include: Prisma.UserInclude | undefined = undefined): Promise<User | undefined> { return await db.user.findUnique({ - where : { - mail: mail - }, - include: include - }) as unknown as User ?? undefined; + where : { + mail: mail + }, + include: include + }) as unknown as User ?? undefined; } - + async getById(id: number, include: Prisma.UserInclude | undefined = undefined): Promise<User | undefined> { return await db.user.findUnique({ - where : { - id: id - }, - include: include - }) as unknown as User ?? undefined; + where : { + id: id + }, + include: include + }) as unknown as User ?? undefined; } - + async getUpdateFromGitlabProfile(gitlabProfile: GitlabProfile): Promise<User> { await db.user.upsert({ - where : { - id: gitlabProfile.id - }, - update: { - mail : gitlabProfile.email, - gitlabLastInfo: gitlabProfile - }, - create: { - id : gitlabProfile.id, - name : gitlabProfile.name, - mail : gitlabProfile.email, - gitlabUsername: gitlabProfile.username, - gitlabLastInfo: gitlabProfile, - deleted : false - } - }); - + where : { + id: gitlabProfile.id + }, + update: { + mail : gitlabProfile.email, + gitlabLastInfo: gitlabProfile + }, + create: { + id : gitlabProfile.id, + name : gitlabProfile.name, + mail : gitlabProfile.email, + gitlabUsername: gitlabProfile.username, + gitlabLastInfo: gitlabProfile, + deleted : false + } + }); + return (await this.getById(gitlabProfile.id))!; } - + async getFromGitlabUser(gitlabUser: GitlabUser, createIfNotExist: boolean = false, include: Prisma.UserInclude | undefined = undefined): Promise<User | number | undefined> { let user = await this.getById(gitlabUser.id, include) ?? gitlabUser.id; - + if ( typeof user === 'number' && createIfNotExist ) { user = (await db.user.create({ - data: { - id : gitlabUser.id, - gitlabUsername: gitlabUser.name - } - })).id; + data: { + id : gitlabUser.id, + gitlabUsername: gitlabUser.name + } + })).id; } - + return user; } - + async getFromGitlabUsers(gitlabUsers: Array<GitlabUser>, createIfNotExist: boolean = false, include: Prisma.UserInclude | undefined = undefined): Promise<Array<User | number | undefined>> { return Promise.all(gitlabUsers.map(gitlabUser => this.getFromGitlabUser(gitlabUser, createIfNotExist, include))); } diff --git a/ExpressAPI/src/middlewares/ClientVersionCheckerMiddleware.ts b/ExpressAPI/src/middlewares/ClientVersionCheckerMiddleware.ts index 1503abd..3fcf9e7 100644 --- a/ExpressAPI/src/middlewares/ClientVersionCheckerMiddleware.ts +++ b/ExpressAPI/src/middlewares/ClientVersionCheckerMiddleware.ts @@ -12,7 +12,7 @@ class ClientVersionCheckerMiddleware { if ( req.headers['client'] && req.headers['client-version'] ) { const requestClient = req.headers['client'] as string; const requestClientVersion = req.headers['client-version'] as string; - + for ( const [ client, condition ] of Object.entries(Config.requestClientValidation.version) ) { if ( requestClient === client ) { if ( semver.satisfies(semver.valid(semver.coerce(requestClientVersion)) || '0', condition) ) { @@ -24,7 +24,7 @@ class ClientVersionCheckerMiddleware { } } } - + new Session().sendResponse(res, HttpStatusCode.MethodNotAllowed, {}, `Unsupported client.`, DojoStatusCode.CLIENT_NOT_SUPPORTED); } }; diff --git a/ExpressAPI/src/middlewares/ParamsCallbackManager.ts b/ExpressAPI/src/middlewares/ParamsCallbackManager.ts index cfcb275..b01c230 100644 --- a/ExpressAPI/src/middlewares/ParamsCallbackManager.ts +++ b/ExpressAPI/src/middlewares/ParamsCallbackManager.ts @@ -28,7 +28,8 @@ class ParamsCallbackManager { if ( !req.boundParams ) { req.boundParams = { assignment: undefined, - exercise : undefined + exercise : undefined, + user : undefined }; } } diff --git a/ExpressAPI/src/middlewares/SecurityMiddleware.ts b/ExpressAPI/src/middlewares/SecurityMiddleware.ts index 37e6e4a..d1e06ca 100644 --- a/ExpressAPI/src/middlewares/SecurityMiddleware.ts +++ b/ExpressAPI/src/middlewares/SecurityMiddleware.ts @@ -21,6 +21,9 @@ class SecurityMiddleware { for ( const checkType of checkTypes ) { try { switch ( String(checkType) ) { + case SecurityCheckType.ADMIN: + isAllowed = isAllowed || req.session.profile.isAdmin; + break; case SecurityCheckType.TEACHING_STAFF: isAllowed = isAllowed || req.session.profile.isTeachingStaff; break; diff --git a/ExpressAPI/src/routes/ApiRoutesManager.ts b/ExpressAPI/src/routes/ApiRoutesManager.ts index ec4eeb9..f542183 100644 --- a/ExpressAPI/src/routes/ApiRoutesManager.ts +++ b/ExpressAPI/src/routes/ApiRoutesManager.ts @@ -5,6 +5,7 @@ import SessionRoutes from './SessionRoutes'; import AssignmentRoutes from './AssignmentRoutes'; import GitlabRoutes from './GitlabRoutes'; import ExerciseRoutes from './ExerciseRoutes'; +import UserRoutes from './UserRoutes'; class AdminRoutesManager implements RoutesManager { @@ -14,8 +15,8 @@ class AdminRoutesManager implements RoutesManager { GitlabRoutes.registerOnBackend(backend); AssignmentRoutes.registerOnBackend(backend); ExerciseRoutes.registerOnBackend(backend); + UserRoutes.registerOnBackend(backend); } } - export default new AdminRoutesManager(); diff --git a/ExpressAPI/src/routes/AssignmentRoutes.ts b/ExpressAPI/src/routes/AssignmentRoutes.ts index ab2bd23..6129686 100644 --- a/ExpressAPI/src/routes/AssignmentRoutes.ts +++ b/ExpressAPI/src/routes/AssignmentRoutes.ts @@ -26,7 +26,6 @@ import SharedAssignmentHelper from '../shared/helpers/Dojo/SharedAssignm import GlobalHelper from '../helpers/GlobalHelper'; import DojoStatusCode from '../shared/types/Dojo/DojoStatusCode'; - class AssignmentRoutes implements RoutesManager { private readonly assignmentValidator: ExpressValidator.Schema = { name : { @@ -44,19 +43,21 @@ class AssignmentRoutes implements RoutesManager { customSanitizer: DojoValidators.templateUrlSanitizer } }; - + registerOnBackend(backend: Express) { backend.get('/assignments/:assignmentNameOrUrl', SecurityMiddleware.check(true), this.getAssignment.bind(this)); backend.post('/assignments', SecurityMiddleware.check(true, SecurityCheckType.TEACHING_STAFF), ParamsValidatorMiddleware.validate(this.assignmentValidator), this.createAssignment.bind(this)); - + backend.patch('/assignments/:assignmentNameOrUrl/publish', SecurityMiddleware.check(true, SecurityCheckType.ASSIGNMENT_STAFF), this.publishAssignment.bind(this)); backend.patch('/assignments/:assignmentNameOrUrl/unpublish', SecurityMiddleware.check(true, SecurityCheckType.ASSIGNMENT_STAFF), this.unpublishAssignment.bind(this)); + + // backend.get('/assignments/:onlyMine', SecurityMiddleware.check(false, SecurityCheckType.TEACHING_STAFF),this.getAssignmentById.bind(this)); + backend.get('/assignmentss', SecurityMiddleware.check(false, SecurityCheckType.TEACHING_STAFF),this.getAssignmentById.bind(this)); } - // Get an assignment by its name or gitlab url private async getAssignment(req: express.Request, res: express.Response) { const assignment: Assignment | undefined = req.boundParams.assignment; - + if ( assignment && !assignment.published && !await AssignmentManager.isUserAllowedToAccessAssignment(assignment, req.session.profile) ) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore @@ -80,56 +81,56 @@ class AssignmentRoutes implements RoutesManager { // @ts-ignore delete assignment.exercises; } - + return assignment ? req.session.sendResponse(res, StatusCodes.OK, assignment) : res.status(StatusCodes.NOT_FOUND).send(); } - + private async createAssignment(req: express.Request, res: express.Response) { const params: { name: string, members: Array<GitlabUser>, template: string } = req.body; params.members = [ await req.session.profile.gitlabProfile.value, ...params.members ]; params.members = params.members.removeObjectDuplicates(gitlabUser => gitlabUser.id); - - + + let repository: GitlabRepository; try { repository = await GitlabManager.createRepository(params.name, Config.assignment.default.description.replace('{{ASSIGNMENT_NAME}}', params.name), Config.assignment.default.visibility, Config.assignment.default.initReadme, Config.gitlab.group.assignments, Config.assignment.default.sharedRunnersEnabled, Config.assignment.default.wikiEnabled, params.template); } catch ( error ) { logger.error('Repo creation error'); logger.error(error); - + if ( error instanceof AxiosError ) { if ( error.response?.data.message.name && error.response.data.message.name == 'has already been taken' ) { return res.status(StatusCodes.CONFLICT).send(); } - + return res.status(error.response?.status ?? HttpStatusCode.InternalServerError).send(); } - + return res.status(StatusCodes.INTERNAL_SERVER_ERROR).send(); } - + await new Promise(resolve => setTimeout(resolve, Config.gitlab.repository.timeoutAfterCreation)); - + try { await GitlabManager.protectBranch(repository.id, '*', true, GitlabAccessLevel.DEVELOPER, GitlabAccessLevel.DEVELOPER, GitlabAccessLevel.OWNER); - + await GitlabManager.addRepositoryBadge(repository.id, Config.gitlab.badges.pipeline.link, Config.gitlab.badges.pipeline.imageUrl, 'Pipeline Status'); } catch ( error ) { return GlobalHelper.repositoryCreationError('Repo params error', error, req, res, DojoStatusCode.ASSIGNMENT_CREATION_GITLAB_ERROR, DojoStatusCode.ASSIGNMENT_CREATION_INTERNAL_ERROR, repository); } - + try { await GitlabManager.deleteFile(repository.id, '.gitlab-ci.yml', 'Remove .gitlab-ci.yml'); } catch ( error ) { /* empty */ } - + try { await GitlabManager.createFile(repository.id, '.gitlab-ci.yml', fs.readFileSync(path.join(__dirname, '../../assets/assignment_gitlab_ci.yml'), 'base64'), 'Add .gitlab-ci.yml (DO NOT MODIFY THIS FILE)'); } catch ( error ) { return GlobalHelper.repositoryCreationError('CI file error', error, req, res, DojoStatusCode.ASSIGNMENT_CREATION_GITLAB_ERROR, DojoStatusCode.ASSIGNMENT_CREATION_INTERNAL_ERROR, repository); } - + try { await Promise.all(params.members.map(member => member.id).map(async (memberId: number): Promise<GitlabMember | false> => { try { @@ -140,45 +141,45 @@ class AssignmentRoutes implements RoutesManager { return false; } })); - + const assignment: Assignment = await db.assignment.create({ - data: { - name : repository.name, - gitlabId : repository.id, - gitlabLink : repository.web_url, - gitlabCreationInfo: repository as unknown as Prisma.JsonObject, - gitlabLastInfo : repository as unknown as Prisma.JsonObject, - gitlabLastInfoDate: new Date(), - staff : { - connectOrCreate: [ ...params.members.map(gitlabUser => { - return { - create: { - id : gitlabUser.id, - gitlabUsername: gitlabUser.name - }, - where : { - id: gitlabUser.id - } - }; - }) ] - } - } - }) as unknown as Assignment; - + data: { + name : repository.name, + gitlabId : repository.id, + gitlabLink : repository.web_url, + gitlabCreationInfo: repository as unknown as Prisma.JsonObject, + gitlabLastInfo : repository as unknown as Prisma.JsonObject, + gitlabLastInfoDate: new Date(), + staff : { + connectOrCreate: [ ...params.members.map(gitlabUser => { + return { + create: { + id : gitlabUser.id, + gitlabUsername: gitlabUser.name + }, + where : { + id: gitlabUser.id + } + }; + }) ] + } + } + }) as unknown as Assignment; + return req.session.sendResponse(res, StatusCodes.OK, assignment); } catch ( error ) { return GlobalHelper.repositoryCreationError('DB error', error, req, res, DojoStatusCode.ASSIGNMENT_CREATION_GITLAB_ERROR, DojoStatusCode.ASSIGNMENT_CREATION_INTERNAL_ERROR, repository); } } - + private async publishAssignment(req: express.Request, res: express.Response) { return this.changeAssignmentPublishedStatus(true)(req, res); } - + private async unpublishAssignment(req: express.Request, res: express.Response) { return this.changeAssignmentPublishedStatus(false)(req, res); } - + private changeAssignmentPublishedStatus(publish: boolean): (req: express.Request, res: express.Response) => Promise<void> { return async (req: express.Request, res: express.Response): Promise<void> => { if ( publish ) { @@ -187,32 +188,51 @@ class AssignmentRoutes implements RoutesManager { return req.session.sendResponse(res, StatusCodes.BAD_REQUEST, { lastPipeline: isPublishable.lastPipeline }, isPublishable.status?.message, isPublishable.status?.code); } } - + try { await GitlabManager.changeRepositoryVisibility(req.boundParams.assignment!.gitlabId, publish ? GitlabVisibility.INTERNAL : GitlabVisibility.PRIVATE); - + await db.assignment.update({ - where: { - name: req.boundParams.assignment!.name - }, - data : { - published: publish - } - }); - + where: { + name: req.boundParams.assignment!.name + }, + data : { + published: publish + } + }); + req.session.sendResponse(res, StatusCodes.OK); } catch ( error ) { if ( error instanceof AxiosError ) { res.status(error.response?.status ?? HttpStatusCode.InternalServerError).send(); return; } - + logger.error(error); res.status(StatusCodes.INTERNAL_SERVER_ERROR).send(); } }; } - + + private async getAssignmentById(req : express.Request, res : express.Response) { + // const onlyMine = req.boundParams.user?.id; + // const users = await db.assignment.findMany(); + // console.log(onlyMine); + // const assign = await db.user.findUnique({ + // where: { + // id: onlyMine, + // }, + // include: { + // assignments: true, + // }, + // }); + const assign = await db.assignment.findMany(); + return req.session.sendResponse(res, StatusCodes.OK, assign); + } + + // private async deleteAssignment(req : express.Request, res : express.Response) { + + // } } diff --git a/ExpressAPI/src/routes/BaseRoutes.ts b/ExpressAPI/src/routes/BaseRoutes.ts index 474f5bb..c704310 100644 --- a/ExpressAPI/src/routes/BaseRoutes.ts +++ b/ExpressAPI/src/routes/BaseRoutes.ts @@ -19,5 +19,4 @@ class BaseRoutes implements RoutesManager { } } - export default new BaseRoutes(); diff --git a/ExpressAPI/src/routes/ExerciseRoutes.ts b/ExpressAPI/src/routes/ExerciseRoutes.ts index 0642d3a..a0b7a34 100644 --- a/ExpressAPI/src/routes/ExerciseRoutes.ts +++ b/ExpressAPI/src/routes/ExerciseRoutes.ts @@ -41,7 +41,7 @@ class ExerciseRoutes implements RoutesManager { customSanitizer: DojoValidators.jsonSanitizer } }; - + private readonly resultValidator: ExpressValidator.Schema = { exitCode : { isInt: true, @@ -68,29 +68,29 @@ class ExerciseRoutes implements RoutesManager { notEmpty: true } }; - + registerOnBackend(backend: Express) { backend.post('/assignments/:assignmentNameOrUrl/exercises', SecurityMiddleware.check(true, SecurityCheckType.ASSIGNMENT_IS_PUBLISHED), ParamsValidatorMiddleware.validate(this.exerciseValidator), this.createExercise.bind(this)); - + backend.get('/exercises/:exerciseId/assignment', SecurityMiddleware.check(false, SecurityCheckType.EXERCISE_SECRET), this.getAssignment.bind(this)); - + backend.post('/exercises/:exerciseId/results', SecurityMiddleware.check(false, SecurityCheckType.EXERCISE_SECRET), ParamsValidatorMiddleware.validate(this.resultValidator), this.createResult.bind(this)); } - + private getExerciseName(assignment: Assignment, members: Array<GitlabUser>, suffix: number): string { return `DojoEx - ${ assignment.name } - ${ members.map(member => member.username).sort((a, b) => a.localeCompare(b)).join(' + ') }${ suffix > 0 ? ` - ${ suffix }` : '' }`; } - + private getExercisePath(assignment: Assignment, exerciseId: string): string { return `dojo-ex_${ (assignment.gitlabLastInfo as unknown as GitlabRepository).path }_${ exerciseId }`; } - + private async createExercise(req: express.Request, res: express.Response) { const params: { members: Array<GitlabUser> } = req.body; params.members = [ await req.session.profile.gitlabProfile!.value, ...params.members ].removeObjectDuplicates(gitlabUser => gitlabUser.id); const assignment: Assignment = req.boundParams.assignment!; - - + + const exercises: Array<Exercise> | undefined = await ExerciseManager.getFromAssignment(assignment.name, { members: true }); const reachedLimitUsers: Array<GitlabUser> = []; if ( exercises ) { @@ -104,12 +104,12 @@ class ExerciseRoutes implements RoutesManager { if ( reachedLimitUsers.length > 0 ) { return req.session.sendResponse(res, StatusCodes.INSUFFICIENT_SPACE_ON_RESOURCE, reachedLimitUsers, 'Max exercise per assignment reached', DojoStatusCode.MAX_EXERCISE_PER_ASSIGNMENT_REACHED); } - - + + const exerciseId: string = uuidv4(); const secret: string = uuidv4(); let repository!: GitlabRepository; - + let suffix: number = 0; do { try { @@ -118,7 +118,7 @@ class ExerciseRoutes implements RoutesManager { } catch ( error ) { logger.error('Repo creation error'); logger.error(error); - + if ( error instanceof AxiosError ) { if ( error.response?.data.message.name && error.response.data.message.name == 'has already been taken' ) { suffix++; @@ -130,32 +130,32 @@ class ExerciseRoutes implements RoutesManager { } } } while ( suffix < Config.exercise.maxSameName ); - + if ( suffix >= Config.exercise.maxSameName ) { logger.error('Max exercise with same name reached'); return res.status(StatusCodes.INSUFFICIENT_SPACE_ON_RESOURCE).send(); } - + await new Promise(resolve => setTimeout(resolve, Config.gitlab.repository.timeoutAfterCreation)); - + try { await GitlabManager.protectBranch(repository.id, '*', false, GitlabAccessLevel.DEVELOPER, GitlabAccessLevel.DEVELOPER, GitlabAccessLevel.OWNER); - + await GitlabManager.addRepositoryVariable(repository.id, 'DOJO_EXERCISE_ID', exerciseId, false, true); await GitlabManager.addRepositoryVariable(repository.id, 'DOJO_SECRET', secret, false, true); await GitlabManager.addRepositoryVariable(repository.id, 'DOJO_RESULTS_FOLDER', Config.exercise.pipelineResultsFolder, false, false); - + await GitlabManager.addRepositoryBadge(repository.id, Config.gitlab.badges.pipeline.link, Config.gitlab.badges.pipeline.imageUrl, 'Pipeline Status'); } catch ( error ) { return GlobalHelper.repositoryCreationError('Repo params error', error, req, res, DojoStatusCode.EXERCISE_CREATION_GITLAB_ERROR, DojoStatusCode.EXERCISE_CREATION_INTERNAL_ERROR, repository); } - + try { await GitlabManager.updateFile(repository.id, '.gitlab-ci.yml', fs.readFileSync(path.join(__dirname, '../../assets/exercise_gitlab_ci.yml'), 'base64'), 'Add .gitlab-ci.yml (DO NOT MODIFY THIS FILE)'); } catch ( error ) { return GlobalHelper.repositoryCreationError('CI file update error', error, req, res, DojoStatusCode.EXERCISE_CREATION_GITLAB_ERROR, DojoStatusCode.EXERCISE_CREATION_INTERNAL_ERROR, repository); } - + try { await Promise.all([ ...new Set([ ...assignment.staff.map(user => user.id), ...params.members.map(member => member.id) ]) ].map(async (memberId: number): Promise<GitlabMember | false> => { try { @@ -166,58 +166,58 @@ class ExerciseRoutes implements RoutesManager { return false; } })); - + const exercise: Exercise = await db.exercise.create({ - data: { - id : exerciseId, - assignmentName : assignment.name, - name : repository.name, - secret : secret, - gitlabId : repository.id, - gitlabLink : repository.web_url, - gitlabCreationInfo: repository as unknown as Prisma.JsonObject, - gitlabLastInfo : repository as unknown as Prisma.JsonObject, - gitlabLastInfoDate: new Date(), - members : { - connectOrCreate: [ ...params.members.map(gitlabUser => { - return { - create: { - id : gitlabUser.id, - gitlabUsername: gitlabUser.name - }, - where : { - id: gitlabUser.id - } - }; - }) ] - } - } - }) as unknown as Exercise; - + data: { + id : exerciseId, + assignmentName : assignment.name, + name : repository.name, + secret : secret, + gitlabId : repository.id, + gitlabLink : repository.web_url, + gitlabCreationInfo: repository as unknown as Prisma.JsonObject, + gitlabLastInfo : repository as unknown as Prisma.JsonObject, + gitlabLastInfoDate: new Date(), + members : { + connectOrCreate: [ ...params.members.map(gitlabUser => { + return { + create: { + id : gitlabUser.id, + gitlabUsername: gitlabUser.name + }, + where : { + id: gitlabUser.id + } + }; + }) ] + } + } + }) as unknown as Exercise; + return req.session.sendResponse(res, StatusCodes.OK, exercise); } catch ( error ) { return GlobalHelper.repositoryCreationError('DB error', error, req, res, DojoStatusCode.EXERCISE_CREATION_GITLAB_ERROR, DojoStatusCode.EXERCISE_CREATION_INTERNAL_ERROR, repository); } } - + private async getAssignment(req: express.Request, res: express.Response) { const repoTree: Array<GitlabTreeFile> = await GitlabManager.getRepositoryTree(req.boundParams.exercise!.assignment.gitlabId); - + let assignmentHjsonFile!: GitlabFile; const immutableFiles: Array<GitlabFile> = await Promise.all(Config.assignment.baseFiles.map(async (baseFile: string) => { const file = await GitlabManager.getFile(req.boundParams.exercise!.assignment.gitlabId, baseFile); - + if ( baseFile === Config.assignment.filename ) { assignmentHjsonFile = file; } - + return file; })); - + const dojoAssignmentFile: AssignmentFile = JSON5.parse(atob(assignmentHjsonFile.content)) as AssignmentFile; - + const immutablePaths = dojoAssignmentFile.immutable.map(fileDescriptor => fileDescriptor.path); - + await Promise.all(repoTree.map(async gitlabTreeFile => { if ( gitlabTreeFile.type == GitlabTreeFileType.BLOB ) { for ( const immutablePath of immutablePaths ) { @@ -228,31 +228,31 @@ class ExerciseRoutes implements RoutesManager { } } })); - + return req.session.sendResponse(res, StatusCodes.OK, { assignment : (req.boundParams.exercise as Exercise).assignment, assignmentFile: dojoAssignmentFile, immutable : immutableFiles }); } - + private async createResult(req: express.Request, res: express.Response) { const params: { exitCode: number, commit: Record<string, string>, results: ExerciseResultsFile, files: Array<IFileDirStat>, archiveBase64: string } = req.body; const exercise: Exercise = req.boundParams.exercise!; - + const result = await db.result.create({ - data: { - exerciseId: exercise.id, - exitCode : params.exitCode, - success : params.results.success!, - commit : params.commit, - results : params.results as unknown as Prisma.JsonObject, - files : params.files - } - }); - + data: { + exerciseId: exercise.id, + exitCode : params.exitCode, + success : params.results.success!, + commit : params.commit, + results : params.results as unknown as Prisma.JsonObject, + files : params.files + } + }); + fs.writeFileSync(path.join(Config.getResultsFolder(exercise), `${ result.dateTime.toISOString().replace(/:/g, '_') }.tar.gz`), params.archiveBase64, 'base64'); - + req.session.sendResponse(res, StatusCodes.OK); } } diff --git a/ExpressAPI/src/routes/UserRoutes.ts b/ExpressAPI/src/routes/UserRoutes.ts new file mode 100644 index 0000000..d514b7b --- /dev/null +++ b/ExpressAPI/src/routes/UserRoutes.ts @@ -0,0 +1,22 @@ +import { Express } from 'express-serve-static-core'; +import express from 'express'; +import RoutesManager from '../express/RoutesManager'; +import SecurityMiddleware from '../middlewares/SecurityMiddleware'; +import SecurityCheckType from '../types/SecurityCheckType'; +import db from '../helpers/DatabaseHelper'; +// import { User, UserRole } from '@prisma/client'; +import { StatusCodes } from 'http-status-codes'; + +class UserRoutes implements RoutesManager { + registerOnBackend(backend: Express): void { + backend.get('/users', SecurityMiddleware.check(false, SecurityCheckType.ADMIN), this.getUsers.bind(this)); + // backend.patch('/users/:userId/role', SecurityMiddleware.check(true, SecurityCheckType.ADMIN), this.changeRole.bind(this)) + } + + private async getUsers(req: express.Request, res: express.Response) { + const users = await db.user.findMany() + return req.session.sendResponse(res, StatusCodes.OK, users); + } +} + +export default new UserRoutes(); diff --git a/ExpressAPI/src/shared b/ExpressAPI/src/shared deleted file mode 160000 index 75f67b6..0000000 --- a/ExpressAPI/src/shared +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 75f67b647da34337f3b220cacf78b2115d6022bc diff --git a/ExpressAPI/src/types/DatabaseTypes.ts b/ExpressAPI/src/types/DatabaseTypes.ts index 632b05b..34e4734 100644 --- a/ExpressAPI/src/types/DatabaseTypes.ts +++ b/ExpressAPI/src/types/DatabaseTypes.ts @@ -4,26 +4,26 @@ import GitlabUser from '../shared/types/Gitlab/GitlabUser'; const userBase = Prisma.validator<Prisma.UserDefaultArgs>()({ - include: { exercises: true } - }); + include: { exercises: true } +}); const assignmentBase = Prisma.validator<Prisma.AssignmentDefaultArgs>()({ - include: { - exercises: true, - staff : true - } - }); + include: { + exercises: true, + staff : true + } +}); const exerciseBase = Prisma.validator<Prisma.ExerciseDefaultArgs>()({ - include: { - assignment: true, - members : true, - results : true - } - }); + include: { + assignment: true, + members : true, + results : true + } +}); const resultBase = Prisma.validator<Prisma.ResultDefaultArgs>()({ - include: { - exercise: true - } - }); + include: { + exercise: true + } +}); export type User = Prisma.UserGetPayload<typeof userBase> & { diff --git a/ExpressAPI/src/types/SecurityCheckType.ts b/ExpressAPI/src/types/SecurityCheckType.ts index 3a0b733..2796e7b 100644 --- a/ExpressAPI/src/types/SecurityCheckType.ts +++ b/ExpressAPI/src/types/SecurityCheckType.ts @@ -3,6 +3,7 @@ enum SecurityCheckType { ASSIGNMENT_STAFF = 'assignmentStaff', ASSIGNMENT_IS_PUBLISHED = 'assignmentIsPublished', EXERCISE_SECRET = 'exerciseSecret', + ADMIN = 'admin' } diff --git a/ExpressAPI/src/types/express/index.d.ts b/ExpressAPI/src/types/express/index.d.ts index e7ac814..3e2f31a 100644 --- a/ExpressAPI/src/types/express/index.d.ts +++ b/ExpressAPI/src/types/express/index.d.ts @@ -1,3 +1,4 @@ + import { User } from '@prisma/client'; import Session from '../../controllers/Session'; import { Assignment, Exercise } from '../DatabaseTypes'; @@ -9,7 +10,7 @@ declare global { export interface Request { session: Session, boundParams: { - assignment: Assignment | undefined, exercise: Exercise | undefined + assignment: Assignment | undefined, exercise: Exercise | undefined, user: User | undefined } } } -- GitLab