diff --git a/ExpressAPI/package-lock.json b/ExpressAPI/package-lock.json
index 0027a6b91b80290192918c9dc84d9c3b7da28385..0987c18cee784aae12380c520864468962d055d8 100644
--- a/ExpressAPI/package-lock.json
+++ b/ExpressAPI/package-lock.json
@@ -12,6 +12,7 @@
                 "@dotenvx/dotenvx": "^0.44.1",
                 "@gitbeaker/rest": "^40.0.3",
                 "@prisma/client": "^5.14.0",
+                "archiver": "^7.0.1",
                 "axios": "^1.7.2",
                 "compression": "^1.7.4",
                 "cors": "^2.8.5",
@@ -1659,7 +1660,6 @@
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
             "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
-            "dev": true,
             "dependencies": {
                 "event-target-shim": "^5.0.0"
             },
@@ -1804,6 +1804,180 @@
                 }
             ]
         },
+        "node_modules/archiver": {
+            "version": "7.0.1",
+            "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz",
+            "integrity": "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==",
+            "license": "MIT",
+            "dependencies": {
+                "archiver-utils": "^5.0.2",
+                "async": "^3.2.4",
+                "buffer-crc32": "^1.0.0",
+                "readable-stream": "^4.0.0",
+                "readdir-glob": "^1.1.2",
+                "tar-stream": "^3.0.0",
+                "zip-stream": "^6.0.1"
+            },
+            "engines": {
+                "node": ">= 14"
+            }
+        },
+        "node_modules/archiver-utils": {
+            "version": "5.0.2",
+            "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.2.tgz",
+            "integrity": "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==",
+            "license": "MIT",
+            "dependencies": {
+                "glob": "^10.0.0",
+                "graceful-fs": "^4.2.0",
+                "is-stream": "^2.0.1",
+                "lazystream": "^1.0.0",
+                "lodash": "^4.17.15",
+                "normalize-path": "^3.0.0",
+                "readable-stream": "^4.0.0"
+            },
+            "engines": {
+                "node": ">= 14"
+            }
+        },
+        "node_modules/archiver-utils/node_modules/buffer": {
+            "version": "6.0.3",
+            "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+            "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+            "funding": [
+                {
+                    "type": "github",
+                    "url": "https://github.com/sponsors/feross"
+                },
+                {
+                    "type": "patreon",
+                    "url": "https://www.patreon.com/feross"
+                },
+                {
+                    "type": "consulting",
+                    "url": "https://feross.org/support"
+                }
+            ],
+            "license": "MIT",
+            "dependencies": {
+                "base64-js": "^1.3.1",
+                "ieee754": "^1.2.1"
+            }
+        },
+        "node_modules/archiver-utils/node_modules/readable-stream": {
+            "version": "4.5.2",
+            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz",
+            "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==",
+            "license": "MIT",
+            "dependencies": {
+                "abort-controller": "^3.0.0",
+                "buffer": "^6.0.3",
+                "events": "^3.3.0",
+                "process": "^0.11.10",
+                "string_decoder": "^1.3.0"
+            },
+            "engines": {
+                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+            }
+        },
+        "node_modules/archiver-utils/node_modules/safe-buffer": {
+            "version": "5.2.1",
+            "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+            "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+            "funding": [
+                {
+                    "type": "github",
+                    "url": "https://github.com/sponsors/feross"
+                },
+                {
+                    "type": "patreon",
+                    "url": "https://www.patreon.com/feross"
+                },
+                {
+                    "type": "consulting",
+                    "url": "https://feross.org/support"
+                }
+            ],
+            "license": "MIT"
+        },
+        "node_modules/archiver-utils/node_modules/string_decoder": {
+            "version": "1.3.0",
+            "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+            "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+            "license": "MIT",
+            "dependencies": {
+                "safe-buffer": "~5.2.0"
+            }
+        },
+        "node_modules/archiver/node_modules/buffer": {
+            "version": "6.0.3",
+            "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+            "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+            "funding": [
+                {
+                    "type": "github",
+                    "url": "https://github.com/sponsors/feross"
+                },
+                {
+                    "type": "patreon",
+                    "url": "https://www.patreon.com/feross"
+                },
+                {
+                    "type": "consulting",
+                    "url": "https://feross.org/support"
+                }
+            ],
+            "license": "MIT",
+            "dependencies": {
+                "base64-js": "^1.3.1",
+                "ieee754": "^1.2.1"
+            }
+        },
+        "node_modules/archiver/node_modules/readable-stream": {
+            "version": "4.5.2",
+            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz",
+            "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==",
+            "license": "MIT",
+            "dependencies": {
+                "abort-controller": "^3.0.0",
+                "buffer": "^6.0.3",
+                "events": "^3.3.0",
+                "process": "^0.11.10",
+                "string_decoder": "^1.3.0"
+            },
+            "engines": {
+                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+            }
+        },
+        "node_modules/archiver/node_modules/safe-buffer": {
+            "version": "5.2.1",
+            "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+            "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+            "funding": [
+                {
+                    "type": "github",
+                    "url": "https://github.com/sponsors/feross"
+                },
+                {
+                    "type": "patreon",
+                    "url": "https://www.patreon.com/feross"
+                },
+                {
+                    "type": "consulting",
+                    "url": "https://feross.org/support"
+                }
+            ],
+            "license": "MIT"
+        },
+        "node_modules/archiver/node_modules/string_decoder": {
+            "version": "1.3.0",
+            "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+            "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+            "license": "MIT",
+            "dependencies": {
+                "safe-buffer": "~5.2.0"
+            }
+        },
         "node_modules/argparse": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
@@ -2029,6 +2203,15 @@
                 "ieee754": "^1.1.13"
             }
         },
+        "node_modules/buffer-crc32": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz",
+            "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==",
+            "license": "MIT",
+            "engines": {
+                "node": ">=8.0.0"
+            }
+        },
         "node_modules/buffer-equal-constant-time": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
@@ -2301,6 +2484,91 @@
                 "node": ">=16"
             }
         },
+        "node_modules/compress-commons": {
+            "version": "6.0.2",
+            "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz",
+            "integrity": "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==",
+            "license": "MIT",
+            "dependencies": {
+                "crc-32": "^1.2.0",
+                "crc32-stream": "^6.0.0",
+                "is-stream": "^2.0.1",
+                "normalize-path": "^3.0.0",
+                "readable-stream": "^4.0.0"
+            },
+            "engines": {
+                "node": ">= 14"
+            }
+        },
+        "node_modules/compress-commons/node_modules/buffer": {
+            "version": "6.0.3",
+            "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+            "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+            "funding": [
+                {
+                    "type": "github",
+                    "url": "https://github.com/sponsors/feross"
+                },
+                {
+                    "type": "patreon",
+                    "url": "https://www.patreon.com/feross"
+                },
+                {
+                    "type": "consulting",
+                    "url": "https://feross.org/support"
+                }
+            ],
+            "license": "MIT",
+            "dependencies": {
+                "base64-js": "^1.3.1",
+                "ieee754": "^1.2.1"
+            }
+        },
+        "node_modules/compress-commons/node_modules/readable-stream": {
+            "version": "4.5.2",
+            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz",
+            "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==",
+            "license": "MIT",
+            "dependencies": {
+                "abort-controller": "^3.0.0",
+                "buffer": "^6.0.3",
+                "events": "^3.3.0",
+                "process": "^0.11.10",
+                "string_decoder": "^1.3.0"
+            },
+            "engines": {
+                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+            }
+        },
+        "node_modules/compress-commons/node_modules/safe-buffer": {
+            "version": "5.2.1",
+            "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+            "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+            "funding": [
+                {
+                    "type": "github",
+                    "url": "https://github.com/sponsors/feross"
+                },
+                {
+                    "type": "patreon",
+                    "url": "https://www.patreon.com/feross"
+                },
+                {
+                    "type": "consulting",
+                    "url": "https://feross.org/support"
+                }
+            ],
+            "license": "MIT"
+        },
+        "node_modules/compress-commons/node_modules/string_decoder": {
+            "version": "1.3.0",
+            "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+            "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+            "license": "MIT",
+            "dependencies": {
+                "safe-buffer": "~5.2.0"
+            }
+        },
         "node_modules/compressible": {
             "version": "2.0.18",
             "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
@@ -2451,6 +2719,100 @@
                 "node": ">= 0.10"
             }
         },
+        "node_modules/crc-32": {
+            "version": "1.2.2",
+            "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
+            "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
+            "license": "Apache-2.0",
+            "bin": {
+                "crc32": "bin/crc32.njs"
+            },
+            "engines": {
+                "node": ">=0.8"
+            }
+        },
+        "node_modules/crc32-stream": {
+            "version": "6.0.0",
+            "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-6.0.0.tgz",
+            "integrity": "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==",
+            "license": "MIT",
+            "dependencies": {
+                "crc-32": "^1.2.0",
+                "readable-stream": "^4.0.0"
+            },
+            "engines": {
+                "node": ">= 14"
+            }
+        },
+        "node_modules/crc32-stream/node_modules/buffer": {
+            "version": "6.0.3",
+            "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+            "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+            "funding": [
+                {
+                    "type": "github",
+                    "url": "https://github.com/sponsors/feross"
+                },
+                {
+                    "type": "patreon",
+                    "url": "https://www.patreon.com/feross"
+                },
+                {
+                    "type": "consulting",
+                    "url": "https://feross.org/support"
+                }
+            ],
+            "license": "MIT",
+            "dependencies": {
+                "base64-js": "^1.3.1",
+                "ieee754": "^1.2.1"
+            }
+        },
+        "node_modules/crc32-stream/node_modules/readable-stream": {
+            "version": "4.5.2",
+            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz",
+            "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==",
+            "license": "MIT",
+            "dependencies": {
+                "abort-controller": "^3.0.0",
+                "buffer": "^6.0.3",
+                "events": "^3.3.0",
+                "process": "^0.11.10",
+                "string_decoder": "^1.3.0"
+            },
+            "engines": {
+                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+            }
+        },
+        "node_modules/crc32-stream/node_modules/safe-buffer": {
+            "version": "5.2.1",
+            "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+            "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+            "funding": [
+                {
+                    "type": "github",
+                    "url": "https://github.com/sponsors/feross"
+                },
+                {
+                    "type": "patreon",
+                    "url": "https://www.patreon.com/feross"
+                },
+                {
+                    "type": "consulting",
+                    "url": "https://feross.org/support"
+                }
+            ],
+            "license": "MIT"
+        },
+        "node_modules/crc32-stream/node_modules/string_decoder": {
+            "version": "1.3.0",
+            "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+            "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+            "license": "MIT",
+            "dependencies": {
+                "safe-buffer": "~5.2.0"
+            }
+        },
         "node_modules/cross-spawn": {
             "version": "7.0.3",
             "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -3079,7 +3441,6 @@
             "version": "5.0.1",
             "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
             "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
-            "dev": true,
             "engines": {
                 "node": ">=6"
             }
@@ -3090,6 +3451,15 @@
             "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
             "dev": true
         },
+        "node_modules/events": {
+            "version": "3.3.0",
+            "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+            "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+            "license": "MIT",
+            "engines": {
+                "node": ">=0.8.x"
+            }
+        },
         "node_modules/execa": {
             "version": "5.1.1",
             "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
@@ -3667,6 +4037,12 @@
                 "url": "https://github.com/sponsors/ljharb"
             }
         },
+        "node_modules/graceful-fs": {
+            "version": "4.2.11",
+            "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+            "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+            "license": "ISC"
+        },
         "node_modules/graphemer": {
             "version": "1.4.0",
             "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
@@ -4205,6 +4581,18 @@
             "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
             "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A=="
         },
+        "node_modules/lazystream": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz",
+            "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==",
+            "license": "MIT",
+            "dependencies": {
+                "readable-stream": "^2.0.5"
+            },
+            "engines": {
+                "node": ">= 0.6.3"
+            }
+        },
         "node_modules/levn": {
             "version": "0.4.1",
             "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
@@ -4455,7 +4843,6 @@
             "version": "5.1.6",
             "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
             "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
-            "dev": true,
             "dependencies": {
                 "brace-expansion": "^2.0.1"
             },
@@ -4843,7 +5230,6 @@
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
             "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
-            "dev": true,
             "engines": {
                 "node": ">=0.10.0"
             }
@@ -8019,6 +8405,15 @@
                 "node": ">=6"
             }
         },
+        "node_modules/process": {
+            "version": "0.11.10",
+            "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+            "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
+            "license": "MIT",
+            "engines": {
+                "node": ">= 0.6.0"
+            }
+        },
         "node_modules/process-nextick-args": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@@ -8207,6 +8602,15 @@
                 "util-deprecate": "~1.0.1"
             }
         },
+        "node_modules/readdir-glob": {
+            "version": "1.1.3",
+            "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz",
+            "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==",
+            "license": "Apache-2.0",
+            "dependencies": {
+                "minimatch": "^5.1.0"
+            }
+        },
         "node_modules/readdirp": {
             "version": "3.6.0",
             "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
@@ -9497,6 +9901,89 @@
                 "url": "https://github.com/sponsors/sindresorhus"
             }
         },
+        "node_modules/zip-stream": {
+            "version": "6.0.1",
+            "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz",
+            "integrity": "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==",
+            "license": "MIT",
+            "dependencies": {
+                "archiver-utils": "^5.0.0",
+                "compress-commons": "^6.0.2",
+                "readable-stream": "^4.0.0"
+            },
+            "engines": {
+                "node": ">= 14"
+            }
+        },
+        "node_modules/zip-stream/node_modules/buffer": {
+            "version": "6.0.3",
+            "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+            "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+            "funding": [
+                {
+                    "type": "github",
+                    "url": "https://github.com/sponsors/feross"
+                },
+                {
+                    "type": "patreon",
+                    "url": "https://www.patreon.com/feross"
+                },
+                {
+                    "type": "consulting",
+                    "url": "https://feross.org/support"
+                }
+            ],
+            "license": "MIT",
+            "dependencies": {
+                "base64-js": "^1.3.1",
+                "ieee754": "^1.2.1"
+            }
+        },
+        "node_modules/zip-stream/node_modules/readable-stream": {
+            "version": "4.5.2",
+            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz",
+            "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==",
+            "license": "MIT",
+            "dependencies": {
+                "abort-controller": "^3.0.0",
+                "buffer": "^6.0.3",
+                "events": "^3.3.0",
+                "process": "^0.11.10",
+                "string_decoder": "^1.3.0"
+            },
+            "engines": {
+                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+            }
+        },
+        "node_modules/zip-stream/node_modules/safe-buffer": {
+            "version": "5.2.1",
+            "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+            "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+            "funding": [
+                {
+                    "type": "github",
+                    "url": "https://github.com/sponsors/feross"
+                },
+                {
+                    "type": "patreon",
+                    "url": "https://www.patreon.com/feross"
+                },
+                {
+                    "type": "consulting",
+                    "url": "https://feross.org/support"
+                }
+            ],
+            "license": "MIT"
+        },
+        "node_modules/zip-stream/node_modules/string_decoder": {
+            "version": "1.3.0",
+            "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+            "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+            "license": "MIT",
+            "dependencies": {
+                "safe-buffer": "~5.2.0"
+            }
+        },
         "node_modules/zod": {
             "version": "3.23.8",
             "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz",
diff --git a/ExpressAPI/package.json b/ExpressAPI/package.json
index 89dc5f3285609f5f22b54ec5f37fa4a9a93dd319..78d1a12d9be6b3eaa63866eb7a8906bdc780d385 100644
--- a/ExpressAPI/package.json
+++ b/ExpressAPI/package.json
@@ -1,80 +1,81 @@
 {
-    "name"           : "dojo_backend_api",
-    "description"    : "Backend API of the Dojo project",
-    "version"        : "4.1.0",
-    "license"        : "AGPLv3",
-    "author"         : "Michaël Minelli <dojo@minelli.me>",
-    "main"           : "dist/src/app.js",
-    "scripts"        : {
-        "clean"                  : "rm -R dist/*",
-        "dotenv:build"           : "npx dotenvx encrypt",
-        "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": "4.1.0",
+    "license": "AGPLv3",
+    "author": "Michaël Minelli <dojo@minelli.me>",
+    "main": "dist/src/app.js",
+    "scripts": {
+        "clean": "rm -R dist/*",
+        "dotenv:build": "npx dotenvx encrypt",
+        "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"   : {
-        "@dotenvx/dotenvx"    : "^0.44.1",
-        "@gitbeaker/rest"     : "^40.0.3",
-        "@prisma/client"      : "^5.14.0",
-        "axios"               : "^1.7.2",
-        "compression"         : "^1.7.4",
-        "cors"                : "^2.8.5",
-        "express"             : "^4.19.2",
-        "express-validator"   : "^7.1.0",
-        "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.11.0",
-        "parse-link-header"   : "^2.0.0",
-        "semver"              : "^7.6.2",
-        "swagger-ui-express"  : "^5.0.0",
-        "tar-stream"          : "^3.1.7",
-        "uuid"                : "^9.0.1",
-        "winston"             : "^3.13.0",
-        "zod"                 : "^3.23.8",
+    "dependencies": {
+        "@dotenvx/dotenvx": "^0.44.1",
+        "@gitbeaker/rest": "^40.0.3",
+        "@prisma/client": "^5.14.0",
+        "archiver": "^7.0.1",
+        "axios": "^1.7.2",
+        "compression": "^1.7.4",
+        "cors": "^2.8.5",
+        "express": "^4.19.2",
+        "express-validator": "^7.1.0",
+        "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.11.0",
+        "parse-link-header": "^2.0.0",
+        "semver": "^7.6.2",
+        "swagger-ui-express": "^5.0.0",
+        "tar-stream": "^3.1.7",
+        "uuid": "^9.0.1",
+        "winston": "^3.13.0",
+        "zod": "^3.23.8",
         "zod-validation-error": "^3.3.0"
     },
     "devDependencies": {
-        "@redocly/cli"             : "^1.13.0",
-        "@types/compression"       : "^1.7.5",
-        "@types/cors"              : "^2.8.17",
-        "@types/express"           : "^4.17.21",
-        "@types/jsonwebtoken"      : "^9.0.6",
-        "@types/morgan"            : "^1.9.9",
-        "@types/multer"            : "^1.4.11",
-        "@types/node"              : "^20.12.12",
-        "@types/parse-link-header" : "^2.0.3",
-        "@types/semver"            : "^7.5.8",
+        "@redocly/cli": "^1.13.0",
+        "@types/compression": "^1.7.5",
+        "@types/cors": "^2.8.17",
+        "@types/express": "^4.17.21",
+        "@types/jsonwebtoken": "^9.0.6",
+        "@types/morgan": "^1.9.9",
+        "@types/multer": "^1.4.11",
+        "@types/node": "^20.12.12",
+        "@types/parse-link-header": "^2.0.3",
+        "@types/semver": "^7.5.8",
         "@types/swagger-ui-express": "^4.1.6",
-        "@types/tar-stream"        : "^3.1.3",
-        "@types/uuid"              : "^9.0.8",
-        "eslint"                   : "^8.57.0",
-        "genversion"               : "^3.2.0",
-        "nodemon"                  : "^3.1.1",
-        "npm"                      : "^10.8.0",
-        "prisma"                   : "^5.14.0",
-        "tsx"                      : "^4.11.0",
-        "typescript"               : "^5.4.5",
-        "typescript-eslint"        : "^7.11.0"
+        "@types/tar-stream": "^3.1.3",
+        "@types/uuid": "^9.0.8",
+        "eslint": "^8.57.0",
+        "genversion": "^3.2.0",
+        "nodemon": "^3.1.1",
+        "npm": "^10.8.0",
+        "prisma": "^5.14.0",
+        "tsx": "^4.11.0",
+        "typescript": "^5.4.5",
+        "typescript-eslint": "^7.11.0"
     }
 }
diff --git a/ExpressAPI/src/managers/GitlabManager.ts b/ExpressAPI/src/managers/GitlabManager.ts
index 7daaf8d27b0d2f95ddc51076ce30887613c170bb..145ec4fa77d81ef508fe19e7def8a49296b1eb70 100644
--- a/ExpressAPI/src/managers/GitlabManager.ts
+++ b/ExpressAPI/src/managers/GitlabManager.ts
@@ -1,34 +1,34 @@
-import Config                                                                                                                                                                                 from '../config/Config.js';
-import { StatusCodes }                                                                                                                                                                        from 'http-status-codes';
-import GitlabVisibility                                                                                                                                                                       from '../shared/types/Gitlab/GitlabVisibility.js';
-import express                                                                                                                                                                                from 'express';
-import SharedConfig                                                                                                                                                                           from '../shared/config/SharedConfig.js';
-import { ArchiveType, CommitSchema, ExpandedUserSchema, Gitlab, MemberSchema, ProjectBadgeSchema, ProjectSchema, ReleaseSchema, RepositoryFileExpandedSchema, RepositoryFileSchema, RepositoryTreeSchema } from '@gitbeaker/rest';
-import logger                                                                                                                                                                                 from '../shared/logging/WinstonLogger.js';
-import { AccessLevel, EditProjectOptions, ProjectVariableSchema, ProtectedBranchAccessLevel, ProtectedBranchSchema }                                                                          from '@gitbeaker/core';
-import DojoStatusCode                                                                                                                                                                         from '../shared/types/Dojo/DojoStatusCode.js';
-import SharedGitlabManager                                                                                                                                                                    from '../shared/managers/SharedGitlabManager.js';
-import * as fs from 'fs';
+import Config from '../config/Config.js';
+import { StatusCodes } from 'http-status-codes';
+import GitlabVisibility from '../shared/types/Gitlab/GitlabVisibility.js';
+import express from 'express';
+import SharedConfig from '../shared/config/SharedConfig.js';
+import { CommitSchema, ExpandedUserSchema, Gitlab, MemberSchema, ProjectBadgeSchema, ProjectSchema, ReleaseSchema, RepositoryFileExpandedSchema, RepositoryFileSchema, RepositoryTreeSchema } from '@gitbeaker/rest';
+import logger from '../shared/logging/WinstonLogger.js';
+import { AccessLevel, EditProjectOptions, ProjectVariableSchema, ProtectedBranchAccessLevel, ProtectedBranchSchema } from '@gitbeaker/core';
+import DojoStatusCode from '../shared/types/Dojo/DojoStatusCode.js';
+import SharedGitlabManager from '../shared/managers/SharedGitlabManager.js';
+import fs                          from 'fs';
 
 class GitlabManager extends SharedGitlabManager {
     constructor() {
         super(Config.gitlab.account.token);
     }
-
+    
     getUserProfile(token: string): Promise<ExpandedUserSchema> | undefined {
         try {
             const profileApi = new Gitlab({
-                                              host      : SharedConfig.gitlab.URL,
-                                              oauthToken: token
-                                          });
-
+                host      : SharedConfig.gitlab.URL,
+                oauthToken: token
+            });
+            
             return profileApi.Users.showCurrentUser();
         } catch ( e ) {
             logger.error(JSON.stringify(e));
             return undefined;
         }
     }
-
+    
     async getRepositoryMembers(idOrNamespace: string): Promise<Array<MemberSchema>> {
         try {
             return await this.api.ProjectMembers.all(idOrNamespace, { includeInherited: true });
@@ -37,7 +37,7 @@ class GitlabManager extends SharedGitlabManager {
             return Promise.reject(e);
         }
     }
-
+    
     async getRepositoryReleases(repoId: number): Promise<Array<ReleaseSchema>> {
         try {
             return await this.api.ProjectReleases.all(repoId);
@@ -46,7 +46,7 @@ class GitlabManager extends SharedGitlabManager {
             return Promise.reject(e);
         }
     }
-
+    
     async getRepositoryLastCommit(repoId: number, branch: string = 'main'): Promise<CommitSchema | undefined> {
         try {
             const commits = await this.api.Commits.all(repoId, {
@@ -54,14 +54,14 @@ class GitlabManager extends SharedGitlabManager {
                 maxPages: 1,
                 perPage : 1
             });
-
+            
             return commits.length > 0 ? commits[0] : undefined;
         } catch ( e ) {
             logger.error(JSON.stringify(e));
             return undefined;
         }
     }
-
+    
     async getRepositoryCommit(repoId: number, commitSha: string): Promise<CommitSchema | undefined> {
         try {
             return await this.api.Commits.show(repoId, commitSha);
@@ -70,25 +70,25 @@ class GitlabManager extends SharedGitlabManager {
             return undefined;
         }
     }
-
+    
     async createRepository(name: string, description: string, visibility: 'public' | 'internal' | 'private', initializeWithReadme: boolean, namespace: number, sharedRunnersEnabled: boolean, wikiEnabled: boolean, importUrl: string): Promise<ProjectSchema> {
         try {
             return await this.api.Projects.create({
-                                                      name                : name,
-                                                      description         : description,
-                                                      importUrl           : importUrl,
-                                                      initializeWithReadme: initializeWithReadme,
-                                                      namespaceId         : namespace,
-                                                      sharedRunnersEnabled: sharedRunnersEnabled,
-                                                      visibility          : visibility,
-                                                      wikiAccessLevel     : wikiEnabled ? 'enabled' : 'disabled'
-                                                  });
+                name                : name,
+                description         : description,
+                importUrl           : importUrl,
+                initializeWithReadme: initializeWithReadme,
+                namespaceId         : namespace,
+                sharedRunnersEnabled: sharedRunnersEnabled,
+                visibility          : visibility,
+                wikiAccessLevel     : wikiEnabled ? 'enabled' : 'disabled'
+            });
         } catch ( e ) {
             logger.error(JSON.stringify(e));
             return Promise.reject(e);
         }
     }
-
+    
     async deleteRepository(repoId: number): Promise<void> {
         try {
             return await this.api.Projects.remove(repoId);
@@ -97,7 +97,7 @@ class GitlabManager extends SharedGitlabManager {
             return Promise.reject(e);
         }
     }
-
+    
     async forkRepository(forkId: number, name: string, path: string, description: string, visibility: 'public' | 'internal' | 'private', namespace: number): Promise<ProjectSchema> {
         try {
             return await this.api.Projects.fork(forkId, {
@@ -112,7 +112,7 @@ class GitlabManager extends SharedGitlabManager {
             return Promise.reject(e);
         }
     }
-
+    
     async editRepository(repoId: number, newAttributes: EditProjectOptions): Promise<ProjectSchema> {
         try {
             return await this.api.Projects.edit(repoId, newAttributes);
@@ -121,11 +121,11 @@ class GitlabManager extends SharedGitlabManager {
             return Promise.reject(e);
         }
     }
-
+    
     changeRepositoryVisibility(repoId: number, visibility: GitlabVisibility): Promise<ProjectSchema> {
         return this.editRepository(repoId, { visibility: visibility });
     }
-
+    
     async addRepositoryMember(repoId: number, userId: number, accessLevel: Exclude<AccessLevel, AccessLevel.ADMIN>): Promise<MemberSchema> {
         try {
             return await this.api.ProjectMembers.add(repoId, userId, accessLevel);
@@ -134,7 +134,7 @@ class GitlabManager extends SharedGitlabManager {
             return Promise.reject(e);
         }
     }
-
+    
     async addRepositoryVariable(repoId: number, key: string, value: string, isProtected: boolean, isMasked: boolean): Promise<ProjectVariableSchema> {
         try {
             return await this.api.ProjectVariables.create(repoId, key, value, {
@@ -147,7 +147,7 @@ class GitlabManager extends SharedGitlabManager {
             return Promise.reject(e);
         }
     }
-
+    
     async addRepositoryBadge(repoId: number, linkUrl: string, imageUrl: string, name: string): Promise<ProjectBadgeSchema> {
         try {
             return await this.api.ProjectBadges.add(repoId, linkUrl, imageUrl, {
@@ -158,12 +158,12 @@ class GitlabManager extends SharedGitlabManager {
             return Promise.reject(e);
         }
     }
-
+    
     async checkTemplateAccess(projectIdOrNamespace: string, req: express.Request, res?: express.Response): Promise<boolean> {
         // Get the Gitlab project and check if it have public or internal visibility
         try {
             const project: ProjectSchema = await this.getRepository(projectIdOrNamespace);
-
+            
             if ( [ 'public', 'internal' ].includes(project.visibility) ) {
                 req.session.sendResponse(res, StatusCodes.OK);
                 return true;
@@ -172,7 +172,7 @@ class GitlabManager extends SharedGitlabManager {
             req.session.sendResponse(res, StatusCodes.NOT_FOUND, undefined, 'Template not found', DojoStatusCode.GITLAB_TEMPLATE_NOT_FOUND);
             return false;
         }
-
+        
         // Check if the user and dojo are members (with at least reporter access) of the project
         const members = await this.getRepositoryMembers(projectIdOrNamespace);
         const isUsersAtLeastReporter = {
@@ -188,7 +188,7 @@ class GitlabManager extends SharedGitlabManager {
                 }
             }
         });
-
+        
         if ( isUsersAtLeastReporter.user && isUsersAtLeastReporter.dojo ) {
             req.session.sendResponse(res, StatusCodes.OK);
             return true;
@@ -197,7 +197,7 @@ class GitlabManager extends SharedGitlabManager {
             return false;
         }
     }
-
+    
     async protectBranch(repoId: number, branchName: string, allowForcePush: boolean, allowedToMerge: ProtectedBranchAccessLevel, allowedToPush: ProtectedBranchAccessLevel, allowedToUnprotect: ProtectedBranchAccessLevel): Promise<ProtectedBranchSchema> {
         try {
             return await this.api.ProtectedBranches.protect(repoId, branchName, {
@@ -211,7 +211,7 @@ class GitlabManager extends SharedGitlabManager {
             return Promise.reject(e);
         }
     }
-
+    
     async getRepositoryTree(repoId: number, recursive: boolean = true, branch: string = 'main'): Promise<Array<RepositoryTreeSchema>> {
         try {
             return await this.api.Repositories.allRepositoryTrees(repoId, {
@@ -223,7 +223,7 @@ class GitlabManager extends SharedGitlabManager {
             return Promise.reject(e);
         }
     }
-
+    
     async getFile(repoId: number, filePath: string, branch: string = 'main'): Promise<RepositoryFileExpandedSchema> {
         try {
             return await this.api.RepositoryFiles.show(repoId, filePath, branch);
@@ -232,11 +232,11 @@ class GitlabManager extends SharedGitlabManager {
             return Promise.reject(e);
         }
     }
-
+    
     private async createUpdateFile(create: boolean, repoId: number, filePath: string, fileBase64: string, commitMessage: string, branch: string = 'main', authorName: string = 'Dojo', authorMail: string | undefined = undefined): Promise<RepositoryFileSchema> {
         try {
             const gitFunction = create ? this.api.RepositoryFiles.create.bind(this.api) : this.api.RepositoryFiles.edit.bind(this.api);
-
+            
             return await gitFunction(repoId, filePath, branch, fileBase64, commitMessage, {
                 encoding   : 'base64',
                 authorName : authorName,
@@ -247,15 +247,15 @@ class GitlabManager extends SharedGitlabManager {
             return Promise.reject(e);
         }
     }
-
+    
     createFile(repoId: number, filePath: string, fileBase64: string, commitMessage: string, branch: string = 'main', authorName: string = 'Dojo', authorMail: string | undefined = undefined): Promise<RepositoryFileSchema> {
         return this.createUpdateFile(true, repoId, filePath, fileBase64, commitMessage, branch, authorName, authorMail);
     }
-
+    
     updateFile(repoId: number, filePath: string, fileBase64: string, commitMessage: string, branch: string = 'main', authorName: string = 'Dojo', authorMail: string | undefined = undefined): Promise<RepositoryFileSchema> {
         return this.createUpdateFile(false, repoId, filePath, fileBase64, commitMessage, branch, authorName, authorMail);
     }
-
+    
     async deleteFile(repoId: number, filePath: string, commitMessage: string, branch: string = 'main', authorName: string = 'Dojo', authorMail: string | undefined = undefined): Promise<void> {
         try {
             return await this.api.RepositoryFiles.remove(repoId, filePath, branch, commitMessage, {
@@ -267,22 +267,9 @@ class GitlabManager extends SharedGitlabManager {
             return Promise.reject(e);
         }
     }
-
-    async exportRepository(repoId: number) : Promise<Blob>{
+    
+    async archiveRepository(repoId: number) : Promise<Blob>{
         try {
-            this.api.Repositories.showArchive(repoId).then(async archive => {
-                const buffer = Buffer.from(await archive.arrayBuffer());
-                
-                fs.writeFile('repository-archive.tar.gz', buffer, (err) => {
-                  if (err) {
-                    console.error('Error saving archive:', err);
-                  } else {
-                    console.log('Archive saved successfully!');
-                  }
-                });
-              }).catch(error => {
-                console.error('Error fetching archive:', error);
-              });
             return await this.api.Repositories.showArchive(repoId);
         } catch ( e ) {
             logger.error(JSON.stringify(e));
diff --git a/ExpressAPI/src/routes/ApiRoutesManager.ts b/ExpressAPI/src/routes/ApiRoutesManager.ts
index 57a418842eb2003e5cab56d24344877837f90691..461649252be9b9d2bcabdb6c674515b818b61c1b 100644
--- a/ExpressAPI/src/routes/ApiRoutesManager.ts
+++ b/ExpressAPI/src/routes/ApiRoutesManager.ts
@@ -5,6 +5,7 @@ import SessionRoutes    from './SessionRoutes.js';
 import AssignmentRoutes from './AssignmentRoutes.js';
 import GitlabRoutes     from './GitlabRoutes.js';
 import ExerciseRoutes   from './ExerciseRoutes.js';
+import UserRoutes from './UserRoutes.js';
 
 
 class AdminRoutesManager implements RoutesManager {
@@ -14,6 +15,7 @@ class AdminRoutesManager implements RoutesManager {
         GitlabRoutes.registerOnBackend(backend);
         AssignmentRoutes.registerOnBackend(backend);
         ExerciseRoutes.registerOnBackend(backend);
+        UserRoutes.registerOnBackend(backend);
     }
 }
 
diff --git a/ExpressAPI/src/routes/AssignmentRoutes.ts b/ExpressAPI/src/routes/AssignmentRoutes.ts
index cfe103cefacc5396c107c8c0588f8e66147aadc5..211ddb17c54d5d692159868c653ea812dd48661d 100644
--- a/ExpressAPI/src/routes/AssignmentRoutes.ts
+++ b/ExpressAPI/src/routes/AssignmentRoutes.ts
@@ -23,7 +23,7 @@ import DojoModelsHelper            from '../helpers/DojoModelsHelper.js';
 import * as Gitlab                 from '@gitbeaker/rest';
 import { GitbeakerRequestError }   from '@gitbeaker/requester-utils';
 import SharedConfig                from '../shared/config/SharedConfig.js';
-
+import archiver                    from 'archiver';
 
 class AssignmentRoutes implements RoutesManager {
     private readonly assignmentValidator: ExpressValidator.Schema = {
@@ -80,7 +80,7 @@ class AssignmentRoutes implements RoutesManager {
         backend.post('/assignments/:assignmentNameOrUrl/corrections', SecurityMiddleware.check(true, SecurityCheckType.ASSIGNMENT_STAFF), ParamsValidatorMiddleware.validate(this.assignmentAddCorrigeValidator), this.linkUpdateAssignmentCorrection(false).bind(this) as RequestHandler);
         backend.patch('/assignments/:assignmentNameOrUrl/corrections/:exerciseIdOrUrl', SecurityMiddleware.check(true, SecurityCheckType.ASSIGNMENT_STAFF), ParamsValidatorMiddleware.validate(this.assignmentUpdateCorrigeValidator), this.linkUpdateAssignmentCorrection(true).bind(this) as RequestHandler);
         backend.delete('/assignments/:assignmentNameOrUrl/corrections/:exerciseIdOrUrl', SecurityMiddleware.check(true, SecurityCheckType.ASSIGNMENT_STAFF), this.unlinkAssignmentCorrection.bind(this) as RequestHandler);
-        backend.get('/assignments/:assignmentNameOrUrl/export', SecurityMiddleware.check(true, SecurityCheckType.ASSIGNMENT_STAFF), this.exportAssignment.bind(this) as RequestHandler);
+        backend.get('/assignments/:assignmentNameOrUrl/export', SecurityMiddleware.check(true, SecurityCheckType.ASSIGNMENT_STAFF), this.exportLightAssignment.bind(this) as RequestHandler);
     }
     
     // Get an assignment by its name or gitlab url
@@ -301,9 +301,75 @@ class AssignmentRoutes implements RoutesManager {
         return req.session.sendResponse(res, StatusCodes.OK);
     }
     
-    private async exportAssignment(req: express.Request, res: express.Response) {
-        const resDl = await GitlabManager.exportRepository(req.boundParams.assignment!.gitlabId);
-        return req.session.sendResponse(res, StatusCodes.OK, resDl);
+    // private async exportLightAssignment(req: express.Request, res: express.Response) {
+    //     const resDl = await GitlabManager.archiveRepository(req.boundParams.assignment!.gitlabId).then(async archive => {
+    //         const buffer = Buffer.from(await archive.arrayBuffer());
+    
+    //         const zipName = req.boundParams.assignment?.name.replace(/ /g, "_") + '.tar.gz';
+    //         fs.writeFile(zipName, buffer, (err) => {
+    //             if (err) {
+    //                 console.error('Error saving archive:', err);
+    //             } else {
+    //                 console.log('Archive saved successfully!');
+    //             }
+    //         });
+    //     }).catch(error => {
+    //         console.error('Error fetching archive:', error);
+    //     });
+    //     return req.session.sendResponse(res, StatusCodes.OK, resDl);
+    // }
+    
+    private async exportLightAssignment(req: express.Request, res: express.Response) {
+        try {
+            const folderName = 'tmp2';
+            const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
+            // const parentDir = path.join('/tmp', `export_${timestamp}`);
+            const parentDir = path.join('/tmp', folderName);
+            fs.mkdirSync(parentDir, { recursive: true });
+            
+            const archive = await GitlabManager.archiveRepository(req.boundParams.assignment!.gitlabId);
+            const buffer = Buffer.from(await archive.arrayBuffer());
+            const zipName = req.boundParams.assignment?.name.replace(/ /g, "_") + '.tar.gz';
+            const zipPath = path.join(parentDir, zipName);
+            
+            fs.writeFileSync(zipPath, buffer);
+            // fs.writeFile(zipPath, buffer, (err) => {
+            //     if (err) {
+            //         console.error('Error saving archive:', err);
+            //     } else {
+            //         console.log('Archive saved successfully!');
+            //     }
+            // });
+            // console.log('Archive saved successfully!');
+            
+            // const finalZipPath = path.join('/tmp', `export_${timestamp}.zip`);
+            const finalZipPath = path.join('/tmp', `${folderName}.zip`);
+            const output = fs.createWriteStream(finalZipPath);
+            const archiveZip = archiver('zip', {
+                zlib: { level: 9 } // Compression maximale
+            });
+            
+            archiveZip.pipe(output);
+            archiveZip.directory(parentDir, false);
+            await archiveZip.finalize();
+            
+            res.download(finalZipPath, `${folderName}.zip`, (err) => {
+                // res.download(finalZipPath, `export_${timestamp}.zip`, (err) => {
+                if (err) {
+                    console.error('Error sending zip:', err);
+                    res.status(500).send('Error sending zip');
+                } else {
+                    console.log('Zip sent successfully!');
+                    // Nettoyage des fichiers temporaires après envoi
+                    // fs.rmSync(parentDir, { recursive: true, force: true });
+                    // fs.unlinkSync(finalZipPath);
+                }
+            });
+            
+        } catch (error) {
+            console.error('Error exporting assignment:', error);
+            res.status(500).send('Error exporting assignment');
+        }
     }
 }
 
diff --git a/ExpressAPI/src/routes/UserRoutes.ts b/ExpressAPI/src/routes/UserRoutes.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3755d01ff394f30214000b6030986bd0f53be3c4
--- /dev/null
+++ b/ExpressAPI/src/routes/UserRoutes.ts
@@ -0,0 +1,57 @@
+import { Express }               from 'express-serve-static-core';
+import express, { RequestHandler }                   from 'express';
+import RoutesManager from '../express/RoutesManager';
+import SecurityMiddleware from '../middlewares/SecurityMiddleware';
+import SecurityCheckType from '../types/SecurityCheckType';
+import db from '../helpers/DatabaseHelper';
+import { StatusCodes } from 'http-status-codes';
+
+class UserRoutes implements RoutesManager {
+     registerOnBackend(backend: Express): void {
+          backend.get('/users', SecurityMiddleware.check(true, SecurityCheckType.ADMIN), this.getUsers.bind(this) as RequestHandler);
+          backend.patch('/users/:userId/role', SecurityMiddleware.check(true, SecurityCheckType.ADMIN), this.changeRole.bind(this) as RequestHandler);
+          backend.get('/users/:userId/assignments', SecurityMiddleware.check(true, SecurityCheckType.TEACHING_STAFF), this.getUsersAssignments.bind(this) as RequestHandler);
+     }
+     
+     private async getUsers(req: express.Request, res: express.Response) {          
+          const users = await db.user.findMany();
+          return req.session.sendResponse(res, StatusCodes.OK, users);
+     }
+     
+     private async getUsersAssignments(req: express.Request, res: express.Response) {
+          const id = +req.params.userId;
+          const user = await db.user.findUnique({
+               where: { 
+                    id: id,
+               },
+               include: {
+                    assignments: true,
+                    
+               }, // Include the assignments related to the user
+          });
+          return req.session.sendResponse(res, StatusCodes.OK, user);    
+     }
+     
+     private async changeRole(req: express.Request, res: express.Response) {
+          const id = +req.params.userId;
+          const newRole = req.body.newRole;
+          // check admin
+          
+          if (id != req.session.profile.id) {
+               
+               await db.user.update({
+                    where : {
+                         id : id
+                    },
+                    data : {
+                         role: newRole
+                    }
+               });
+               return req.session.sendResponse(res, StatusCodes.OK);
+          } else {
+               return req.session.sendResponse(res, StatusCodes.FORBIDDEN);
+          }
+     }
+}
+
+export default new UserRoutes();
diff --git a/ExpressAPI/src/shared b/ExpressAPI/src/shared
index c2afa861bf6306ddec79ffd465a4c7b0edcd3453..cb6c4459a5b192a428844b0625d5cfb8558ca89f 160000
--- a/ExpressAPI/src/shared
+++ b/ExpressAPI/src/shared
@@ -1 +1 @@
-Subproject commit c2afa861bf6306ddec79ffd465a4c7b0edcd3453
+Subproject commit cb6c4459a5b192a428844b0625d5cfb8558ca89f
diff --git a/ExpressAPI/src/types/SecurityCheckType.ts b/ExpressAPI/src/types/SecurityCheckType.ts
index 3a0b733103af4604e10f917ec3edc4c7f56b3b66..4b048b3e6a05d284ec8df54d555915e0047f1dac 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',
 }