diff --git a/ExpressAPI/.env.vault b/ExpressAPI/.env.vault index 572ab9aee9287e08cf3ff581a9b915a5e78f41d7..a0ee539e734f17934dec0c407b8c10aa432ccdd8 100644 --- a/ExpressAPI/.env.vault +++ b/ExpressAPI/.env.vault @@ -4,11 +4,11 @@ #/--------------------------------------------------/ # development -DOTENV_VAULT_DEVELOPMENT="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" +DOTENV_VAULT_DEVELOPMENT="+GjUUvMphJDIEddcLopaiS2p37yQUQ4ESFsuy9XYRKUMZ2EYppRX3137EvNs1kSKqYnP5Qv1zjfnWbPL8UpKugOHgp8cGeTtu/1YirDd8EC8Hc4hXQ9v/nNIbz3wSVBx89yJTugc6D3rckutYkgZFLb4uBCjKZ/u5BcrOi7CJJDCMNlrlk4cR8RR2W7G7IUBwrnr89H1TIFsVGyB+aZFW5Q7enTl8za5l0t3WLFQFXSvKEsKwFzPLPZ3W0gDvtZjjk7RoUafB7KM5mFZ55FM8uR4fL/CzzRiTn0HeRTZuy/gGqI4wqHa5cEuJzzVQYLrH2HpRJn7U3+TDkteYWiGKdM8iXGkylArE0eP5LA8uRZFyMNZDkvPkFJ/2FUcqgj077bM6fsuhlYwYuKQl5sVgwEJAbda4ejCS7baO9UGHP2m0Fmo5dw7B/eLGYM4jDVc4AYgajDgV+HgmNr6n+JeIqMzhewF4fWYrezIGPu3dV2hs4I6EmtxlSxJEZEVx4k7L0biKb982KYUAabvS5IGigMA+z5S3Pi/FlPPfVXefPi0r48cwjXFC0sSXnGSCv49OMkaAe4D6bkrbxyRC9gAnvPrJe5v3Ievr5VmldZbewrQ38IVD8B5bZX4uWOUETVucn2hHqx9znGHCXWQfpDuyNs2TmCtOF+hG/C44HeYY+eBObbHLjKsCnT28tMBIcPyT2cJdnKHoqLUhx820B3j+1PxelX/T6zjxyHInk5RCM5TNThMpV42r1QVD+XzOTQt3D4JlZ6mNi1kutezKAiiTrK3SYD74rcT9zz96xWE0CmQmdkMnfwU1EUTXwZdilotMbNgpFSMxKArlAvDVmUzvPwMYkcNWLhCXPwMn0xzCzgF8tcKi7Mj3aBCd6FzacoLEMikxcfPRuPLHVrtEHqEpFc8Jpb9uJ6031gfmnutqVlCy2jH4cZTTPUVa7ZXONBNc93/zl2QXd7UZ5TXtJISplaQ94i/0w3O52zCnYPyEDOqgzhrtMWWbvM0DEqs4+VI69BtLtCKywqwPCbuywfoWEL8sXNpQAFL7IEIIVeJfFdxjXk2WZhVk9YIAJ9nWIlwP87S8yKFhGaIMySGcQPB1CGDKEXKaDwUWbzxihrgtZUQPUQ082+kOwrWV/SAfB+vVi8H3CVtAZ8nZHcqoZNKr/JKKhSHDDzZ8x4+0l67lQanKsgWFzsRDbaoxiivFX5eeHtVUmm8jJmX3TU4wMGYIx3dXDCd7lwrKMYRCVM5of4s0roWiaXrvkREBhJiQyUJVUaZs7yLClu5rFMCNBX7uOv4Ycmeva+KU1hu+MRfg6NTdTzSoTPLFGk3hEzKobrpAzQbtyuFmgfeDBFIr9vm8kOYgjJ2DE46d3GB6G/rfr1JmBvVSzluESGcdQ2/eGLVAka06IPmJomflrwophZpKV8zo5boJSWR9lcRGvqOmPfVadI76LSI+3iqbRYpI9YObUfn+4XUZ+NsSYlrTr6D+UQLvZF2HmNWkI5W57lbM1eG8rifAxpv1wKIxXtjd93cn6Bqb5x5GbSvsw8MkHb2JTsAx6lNEcTT4Y/jnCflc45yvCSuNhKpjigrBdHSrEXCsBSMgAb0FmY7eylMDP33XlGPCRs6PneQgozOM1rwKXgyXZh6DQ+DiJmgL3R5ccwZYK+mYlahu05Xg5rL0E+8apH2IKlLWVfLnJjrhUUrAOojOFFdNmmo3M5ep2+8H5SPMfhfD6lOGeQ6jUM+nVIgmVSHLHFCGBRsiujKLLuALgQEIuemqFZrQXNnDm9I02AtGgXJ5tjFkwFx5Oom9fz3GIxHQ1G/D4o+eQ2aoMK6jxtJDL9eRixcnOFaztsse0jmC9a4v+TfNMPa8XBLScJrAceYbdkY1XMTB+SmHhZ3GajHkC911IZr9uabu5qrUxcHN/MGQ43Q99vMg/ydZPy7r3KgPu/gtHzMIo/TEsaHlAsSiTXQnqjnCGtFY+3xwNKdTkPOZKJTSFE5LL/BWFNx2Zt8yHZIvsa5iD9ellDVAXL4JpVICkmuabzXR4Mo0KTUoo3gyPfeC1fn9C1/5FIc0qSPyCVpHJtlLDXkgTF9KcKIzzNZQ8WejFG/4oP36E/EVv5+HHFuQvVvDLHsfFl6y2YPK6zxG5xTBI4LxMozLhadI4IuIxk/X4LUzHbql/D37c9kHbXwwA0x1Xv7CQfQoR9KHFg9BwybB6EgMX6xL3YgtqHbNLvj6ECa3nNvgiMS0GHnmHA628vUL8q122Z1mJA+ERmrXwxr4PSoJKkXMVeo8NEVqirKRmnc3SibLFXL4QCz4/iMC7RnSghrp3BMepDf2zF3UQRVHVYUKe2T1pkB5WJxyMrrIQC1pq23s56D57JNw3PsS/dPjdvDM4Z9xGkzJtzdUTq2D8llqqrMZeME9vTMn61HJFFeRYSSk5zgyJfjzn6CevNKQVf3uOo6lkuwi6I70Edsj4nibX1ZdnvDcoOPs+2rl2Dy/d4Js8xcQKg1t3zz7oGIlJgbei4R3Hl3WbIiPovruXaP1atYlWRyffX6UOG6vBnzq5dR3Th21RLvFu0LXuy2rWn6ANhyyed5hAAM6WFtUzluEywd3Ig+3AYUvOgew91PMsMRlQ44t9AD4iExlEvJ4PfXMqYJA8OOr6UDglbJj2NTzA6LEdnNIpKss8nh/kgS9nF6PmZpjjJii/Fx67Xb3eTqrU0NmCGQz46k84mqNKxLauYOzmoWwZM1voz6qpBh5OMpWQ+SFIKGkvg3Uheyz4XazmW91yVgXMSrG/lOZWg+kHr09z11HJzmSDnNxc5jlV7VFQ1jj+ejR91SzjjhZZ/fWXHmp7NTzVWGMzCnDXEXqRyb1VlR0zYDNHJ4l9ygxpKR8GrlK/EGZX2cxTzaZ7WsK+zAAFiNp2GOFgE/a7wMnIt9XZ+tHxmpAsA0YhIaP/N13joAiPRCxr0jLns4L4Nr4id1VRhRiO0k+JO01MU0F9suNaQVduzrMCBO+RllciL/Mhj82bJuZF6xXSDv772EK6SiJwOZbfsxT/xnzZGD2eSdXLB6iDazk9R/LS3R6lL3D4KmBTcA21+sMp2LnVBlFIApZNtc0libIv1864aVzFhq93usEO+bnltPUxlEJUOzpm2oiVmeDJScj0ZZyqkS/dyFRcpbTrwdtj0DT+LM5bWaK6g0cyZFu8NCrkLVB493e4cbwKPppKG4lcq2UHTkIpaEcduDZWwst0qS5K3dvKVQH/ldIJKG8zgL/5BstDWui1HOGi97VWvd7U2ViEFqcozWfGDFoprqx0uNUpgMEON1ULjjmlldqGwtFyxgj92e13lXbaaYWYD4aT8419JfGjagTf1vpnWEfrvPSFt5yL7aSdyIfrc8I9cBlQ0TZe8Ka1dOiOI28ibEM+7VEoZcIcv+NdW4aJCSOTgyTv4pAUQtUG30cyZT8MPUlX9R4jzp7E13EhvDUjyx59itj/AHyYtdFfDQ321MiCaWt7RzhxRkDgaIGI0wBi76Nqv76wAxFyPdRLOe7Ma18aHrlx6aLMe0k9a3ZdS8BTnv0OPsSVetVZ8DhT8Zx9yjJRVtRf2uGsSd+C4a+kNlH1emskxbYfIJz5FhqkAiv69j2UHXukhBXcFKMsLr+qq4AaHHNvG0R55GSwY/fRO1N/We+NXPqfrguWvvKMXyBv39aMx3dNUy+CrsPzRPU5NEi6AiPnk+AHNQd3IlRchqVrWhCgWgJpVmYTtGuWfbkmGpsReNHh3MJy0nDxCyn078rJDjQzjlrEwOsLOnxJ0vdpHpockmBEyHn7C+QW8L6L5BaI6W6Q9NDiY33uaxezWgao/LbCx9+Xc9pg7GFIAWyv2vnMM1IbSVBID0LnAqoxBv+b+umaYQ9moRLXtF6x5VYG5Q8TD2IZJho3sStNNlH1f3E9Zo29kkj9YI5cX5zNuuGkIx6Ha1o8NREe7jfL3ru/Y3HcFgzca/QCz+mmbnMvxVSH6PD7sezs3F17kr+LIHKvc=" # production -DOTENV_VAULT_PRODUCTION="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" +DOTENV_VAULT_PRODUCTION="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" # test -DOTENV_VAULT_TEST="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" +DOTENV_VAULT_TEST="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" diff --git a/ExpressAPI/prisma/migrations/20240325151023_add_sonar_infos/migration.sql b/ExpressAPI/prisma/migrations/20240325151023_add_sonar_infos/migration.sql new file mode 100644 index 0000000000000000000000000000000000000000..d2cfe2a38931593c5fd97561fbdb16a82e5280c5 --- /dev/null +++ b/ExpressAPI/prisma/migrations/20240325151023_add_sonar_infos/migration.sql @@ -0,0 +1,7 @@ +-- AlterTable +ALTER TABLE `Assignment` ADD COLUMN `sonarCreationInfo` JSON NULL, + ADD COLUMN `sonarKey` VARCHAR(191) NULL; + +-- AlterTable +ALTER TABLE `Exercise` ADD COLUMN `sonarCreationInfo` JSON NULL, + ADD COLUMN `sonarKey` VARCHAR(191) NULL; diff --git a/ExpressAPI/prisma/schema.prisma b/ExpressAPI/prisma/schema.prisma index 12188c2dd5b8b104ddfa6e0c76078b311972a18d..6d1603dc9f58666d2a8c4967d42cc6f992320e9b 100644 --- a/ExpressAPI/prisma/schema.prisma +++ b/ExpressAPI/prisma/schema.prisma @@ -34,9 +34,12 @@ model Assignment { gitlabLastInfo Json @db.Json gitlabLastInfoDate DateTime published Boolean @default(false) - useSonar Boolean @default(false) language Language @default(other) + useSonar Boolean @default(false) + sonarKey String? + sonarCreationInfo Json? @db.Json + exercises Exercise[] staff User[] } @@ -52,6 +55,9 @@ model Exercise { gitlabLastInfo Json @db.Json gitlabLastInfoDate DateTime + sonarKey String? + sonarCreationInfo Json? @db.Json + correctionCommit Json? @db.Json assignment Assignment @relation(fields: [assignmentName], references: [name], onDelete: NoAction, onUpdate: Cascade) diff --git a/ExpressAPI/src/helpers/GlobalHelper.ts b/ExpressAPI/src/helpers/GlobalHelper.ts index 18f0d57714f6febb5063fcbfe92cb5d9875e0a13..65fea1ae8c8c8b3ea10258ecfeca72f0aab67018 100644 --- a/ExpressAPI/src/helpers/GlobalHelper.ts +++ b/ExpressAPI/src/helpers/GlobalHelper.ts @@ -29,21 +29,6 @@ class GlobalHelper { return req.session.sendResponse(res, StatusCodes.INTERNAL_SERVER_ERROR, {}, `Unknown error: ${ message }`, internalError); } - - async isSonarSupported(): Promise<boolean> { - try { - // Use custom instance to allow self-signed certificates - const instance = axios.create({ - httpsAgent: new https.Agent({ - rejectUnauthorized: false - }) - }); - const sonar = await instance.get(SharedConfig.sonar.url); - return SharedConfig.sonar.enabled && sonar.status == 200; - } catch ( error ) { - return false; - } - } } diff --git a/ExpressAPI/src/managers/HttpManager.ts b/ExpressAPI/src/managers/HttpManager.ts index 075e72717a56923fe0d962b72ac14d11fad0d9e8..ccc1cd96815fe6729efe1741e40560f8972853b3 100644 --- a/ExpressAPI/src/managers/HttpManager.ts +++ b/ExpressAPI/src/managers/HttpManager.ts @@ -29,6 +29,7 @@ class HttpManager { delete config.headers.DojoOverrideAuthorization; delete config.headers.DojoAuthorizationHeader; delete config.headers.DojoAuthorizationValue; + } return config; diff --git a/ExpressAPI/src/managers/SonarManager.ts b/ExpressAPI/src/managers/SonarManager.ts new file mode 100644 index 0000000000000000000000000000000000000000..3bfdc9e318cf313e0dc2e7e9fca3641f6a72a9d9 --- /dev/null +++ b/ExpressAPI/src/managers/SonarManager.ts @@ -0,0 +1,58 @@ +import SharedConfig from '../shared/config/SharedConfig'; +import SonarRoute from '../shared/types/Sonar/SonarRoute'; +import axios, { AxiosInstance } from 'axios'; +import Config from '../config/Config'; +import SonarProjectCreation from '../shared/types/Sonar/SonarProjectCreation'; +import https from 'https'; + + +class SonarManager { + private instance: AxiosInstance = axios.create({ + httpsAgent: new https.Agent({ + rejectUnauthorized: false + }) + }); + + private getApiUrl(route: SonarRoute): string { + return `${ SharedConfig.sonar.url }${ route }`; + } + + /** + * Assign a Gitlab Personal Access Token to a Sonar account (needed for any other request linked to gitlab) + * @private + */ + private async setPAT() { + const formData = new FormData(); + formData.append('almSetting', 'dojo'); + formData.append('pat', Config.gitlab.account.token); + + await this.instance.post(this.getApiUrl(SonarRoute.SET_PAT), formData, { + headers: { + Authorization: `Basic ${ btoa(SharedConfig.sonar.token + ":") }` + } + }); + } + + private async executePostRequest<T>(url: string, data?: FormData) { + console.log("dhdidid"); + await this.setPAT(); // Always set PAT to be sure it has been set + console.log("hehe",btoa(SharedConfig.sonar.token)); + + return (await this.instance.post<T>(url, data, { + headers: { + Authorization: `Basic ${ btoa(SharedConfig.sonar.token + ":") }` + } + })).data; + } + + async createProjectFromGitlab(projectId: number) { + const formData = new FormData(); + formData.append('almSetting', 'dojo'); + formData.append('gitlabProjectId', projectId.toString()); + console.log(formData); + + return await this.executePostRequest<SonarProjectCreation>(this.getApiUrl(SonarRoute.PROJECT_CREATE_GITLAB), formData) + } +} + +export default new SonarManager(); \ No newline at end of file diff --git a/ExpressAPI/src/routes/AssignmentRoutes.ts b/ExpressAPI/src/routes/AssignmentRoutes.ts index d76f386e80502dfbcd2aa7fc505e1677977d4f89..8f217b0a15a85c06524fe7e2a8f58729b6980c00 100644 --- a/ExpressAPI/src/routes/AssignmentRoutes.ts +++ b/ExpressAPI/src/routes/AssignmentRoutes.ts @@ -26,6 +26,9 @@ import SharedAssignmentHelper from '../shared/helpers/Dojo/SharedAssignm import GlobalHelper from '../helpers/GlobalHelper'; import DojoStatusCode from '../shared/types/Dojo/DojoStatusCode'; import DojoModelsHelper from '../helpers/DojoModelsHelper'; +import SonarManager from '../managers/SonarManager'; +import SonarProjectCreation from '../shared/types/Sonar/SonarProjectCreation'; +import SharedSonarManager from '../shared/managers/SharedSonarManager'; class AssignmentRoutes implements RoutesManager { @@ -104,7 +107,7 @@ class AssignmentRoutes implements RoutesManager { params.members = [ await req.session.profile.gitlabProfile.value, ...params.members ]; params.members = params.members.removeObjectDuplicates(gitlabUser => gitlabUser.id); - if (useSonar && !(await GlobalHelper.isSonarSupported())) { + if (useSonar && !(await SharedSonarManager.isSonarSupported())) { return req.session.sendResponse(res, StatusCodes.UNPROCESSABLE_ENTITY, {}, `Sonar integration is not supported`, DojoStatusCode.ASSIGNMENT_CREATION_SONAR_ERROR); } @@ -156,7 +159,24 @@ class AssignmentRoutes implements RoutesManager { return false; } })); + } catch ( error ) { + return GlobalHelper.repositoryCreationError('CI file error', error, req, res, DojoStatusCode.ASSIGNMENT_CREATION_GITLAB_ERROR, DojoStatusCode.ASSIGNMENT_CREATION_INTERNAL_ERROR, repository); + } + + // Create Sonar project + let sonarProject: SonarProjectCreation | undefined = undefined; + if (useSonar) { + try { + sonarProject = await SonarManager.createProjectFromGitlab(repository.id); + } catch ( error ) { + console.log(JSON.stringify(error)); + logger.error("Sonar project creation error"); + logger.error(error); + return GlobalHelper.repositoryCreationError('Sonar error', error, req, res, DojoStatusCode.ASSIGNMENT_CREATION_SONAR_ERROR, DojoStatusCode.ASSIGNMENT_CREATION_INTERNAL_ERROR, repository); + } + } + try { const assignment: Assignment = await db.assignment.create({ data: { name : repository.name, @@ -166,6 +186,8 @@ class AssignmentRoutes implements RoutesManager { gitlabLastInfo : repository as unknown as Prisma.JsonObject, gitlabLastInfoDate: new Date(), useSonar : useSonar, + sonarKey : sonarProject?.project.key, + sonarCreationInfo : sonarProject?.project, language : Language[params.language as keyof typeof Language], staff : { connectOrCreate: [ ...params.members.map(gitlabUser => { @@ -185,7 +207,7 @@ class AssignmentRoutes implements RoutesManager { 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); + return GlobalHelper.repositoryCreationError('DB error', error, req, res, DojoStatusCode.ASSIGNMENT_CREATION_INTERNAL_ERROR, DojoStatusCode.ASSIGNMENT_CREATION_INTERNAL_ERROR, repository); } } diff --git a/ExpressAPI/src/routes/BaseRoutes.ts b/ExpressAPI/src/routes/BaseRoutes.ts index 6db7ef7d1aa585a9695472a32d7b67dcbdd9280c..962b668873a18535ed277a9a761cf10477245264 100644 --- a/ExpressAPI/src/routes/BaseRoutes.ts +++ b/ExpressAPI/src/routes/BaseRoutes.ts @@ -2,7 +2,7 @@ import { Express } from 'express-serve-static-core'; import express from 'express'; import { StatusCodes } from 'http-status-codes'; import RoutesManager from '../express/RoutesManager'; -import GlobalHelper from '../helpers/GlobalHelper'; +import SharedSonarManager from '../shared/managers/SharedSonarManager'; class BaseRoutes implements RoutesManager { @@ -22,7 +22,7 @@ class BaseRoutes implements RoutesManager { private async sonar(req: express.Request, res: express.Response) { const data = { - sonarEnabled: await GlobalHelper.isSonarSupported() + sonarEnabled: await SharedSonarManager.isSonarSupported() }; return req.session.sendResponse(res, StatusCodes.OK, data); }