From f4499deb6a2924d4310b4ed9a516c0e68d1e3760 Mon Sep 17 00:00:00 2001 From: N7ghtm4r3 Date: Tue, 17 Sep 2024 21:53:44 +0200 Subject: [PATCH 01/25] Reorganized the project structure in two different submodules --- .idea/gradle.xml | 3 +- .idea/misc.xml | 1 - README.md | 8 +- backend/build.gradle.kts | 49 ++++++++++++ .../java/com/tecknobit/nova/Launcher.java | 7 +- .../nova/controllers/NovaController.java | 6 +- .../nova/controllers/UsersController.java | 10 +-- .../projectmanagers/ProjectManager.java | 2 +- .../projectmanagers/ProjectsController.java | 6 +- .../projectmanagers/ReleasesController.java | 0 .../nova/helpers/ReportsProvider.java | 21 +++-- .../helpers/resources/ResourcesManager.java | 22 +++--- .../helpers/resources/ResourcesProvider.java | 0 .../nova/helpers/services/ProjectsHelper.java | 7 +- .../nova/helpers/services/ReleasesHelper.java | 0 .../nova/helpers/services/UsersHelper.java | 2 +- .../repositories/UsersRepository.java | 0 .../JoiningQRCodeRepository.java | 0 .../projectsutils/ProjectsRepository.java | 0 .../releaseutils/NotificationsRepository.java | 0 .../releaseutils/ReleaseEventsRepository.java | 0 .../releaseutils/ReleaseTagRepository.java | 0 .../releaseutils/ReleasesRepository.java | 0 .../src}/main/resources/app.properties | 0 .../src}/main/resources/report_template.md | 0 .../src}/main/resources/resources.mantis | 0 build.gradle.kts | 73 +++++++----------- {Nova-core => core}/build.gradle.kts | 6 +- .../tecknobit/novacore/InputValidator.java | 0 .../tecknobit/novacore/helpers/Endpoints.java | 0 .../novacore/helpers/LocalSessionUtils.java | 0 .../tecknobit/novacore/helpers/Requester.kt | 76 +++++++++---------- .../novacore/records/NotificationsTarget.java | 0 .../tecknobit/novacore/records/NovaItem.java | 0 .../novacore/records/NovaNotification.java | 0 .../com/tecknobit/novacore/records/User.java | 0 .../records/project/JoiningQRCode.java | 0 .../novacore/records/project/Project.java | 0 .../novacore/records/release/Release.java | 0 .../release/events/AssetUploadingEvent.java | 0 .../release/events/RejectedReleaseEvent.java | 0 .../records/release/events/RejectedTag.java | 0 .../records/release/events/ReleaseEvent.java | 0 .../release/events/ReleaseStandardEvent.java | 0 core/src/main/resources/resources.mantis | 21 +++++ settings.gradle.kts | 3 +- 46 files changed, 185 insertions(+), 138 deletions(-) create mode 100644 backend/build.gradle.kts rename {src => backend/src}/main/java/com/tecknobit/nova/Launcher.java (93%) rename {src => backend/src}/main/java/com/tecknobit/nova/controllers/NovaController.java (95%) rename {src => backend/src}/main/java/com/tecknobit/nova/controllers/UsersController.java (97%) rename {src => backend/src}/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectManager.java (100%) rename {src => backend/src}/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectsController.java (98%) rename {src => backend/src}/main/java/com/tecknobit/nova/controllers/projectmanagers/ReleasesController.java (100%) rename {src => backend/src}/main/java/com/tecknobit/nova/helpers/ReportsProvider.java (91%) rename {src => backend/src}/main/java/com/tecknobit/nova/helpers/resources/ResourcesManager.java (85%) rename {src => backend/src}/main/java/com/tecknobit/nova/helpers/resources/ResourcesProvider.java (100%) rename {src => backend/src}/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java (97%) rename {src => backend/src}/main/java/com/tecknobit/nova/helpers/services/ReleasesHelper.java (100%) rename {src => backend/src}/main/java/com/tecknobit/nova/helpers/services/UsersHelper.java (98%) rename {src => backend/src}/main/java/com/tecknobit/nova/helpers/services/repositories/UsersRepository.java (100%) rename {src => backend/src}/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/JoiningQRCodeRepository.java (100%) rename {src => backend/src}/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/ProjectsRepository.java (100%) rename {src => backend/src}/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/NotificationsRepository.java (100%) rename {src => backend/src}/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/ReleaseEventsRepository.java (100%) rename {src => backend/src}/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/ReleaseTagRepository.java (100%) rename {src => backend/src}/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/ReleasesRepository.java (100%) rename {src => backend/src}/main/resources/app.properties (100%) rename {src => backend/src}/main/resources/report_template.md (100%) rename {src => backend/src}/main/resources/resources.mantis (100%) rename {Nova-core => core}/build.gradle.kts (92%) rename {Nova-core => core}/src/main/java/com/tecknobit/novacore/InputValidator.java (100%) rename {Nova-core => core}/src/main/java/com/tecknobit/novacore/helpers/Endpoints.java (100%) rename {Nova-core => core}/src/main/java/com/tecknobit/novacore/helpers/LocalSessionUtils.java (100%) rename {Nova-core => core}/src/main/java/com/tecknobit/novacore/helpers/Requester.kt (93%) rename {Nova-core => core}/src/main/java/com/tecknobit/novacore/records/NotificationsTarget.java (100%) rename {Nova-core => core}/src/main/java/com/tecknobit/novacore/records/NovaItem.java (100%) rename {Nova-core => core}/src/main/java/com/tecknobit/novacore/records/NovaNotification.java (100%) rename {Nova-core => core}/src/main/java/com/tecknobit/novacore/records/User.java (100%) rename {Nova-core => core}/src/main/java/com/tecknobit/novacore/records/project/JoiningQRCode.java (100%) rename {Nova-core => core}/src/main/java/com/tecknobit/novacore/records/project/Project.java (100%) rename {Nova-core => core}/src/main/java/com/tecknobit/novacore/records/release/Release.java (100%) rename {Nova-core => core}/src/main/java/com/tecknobit/novacore/records/release/events/AssetUploadingEvent.java (100%) rename {Nova-core => core}/src/main/java/com/tecknobit/novacore/records/release/events/RejectedReleaseEvent.java (100%) rename {Nova-core => core}/src/main/java/com/tecknobit/novacore/records/release/events/RejectedTag.java (100%) rename {Nova-core => core}/src/main/java/com/tecknobit/novacore/records/release/events/ReleaseEvent.java (100%) rename {Nova-core => core}/src/main/java/com/tecknobit/novacore/records/release/events/ReleaseStandardEvent.java (100%) create mode 100644 core/src/main/resources/resources.mantis diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 58d18f8..412c6aa 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -9,7 +9,8 @@ diff --git a/.idea/misc.xml b/.idea/misc.xml index 86cd4cb..87ab658 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,3 @@ - diff --git a/README.md b/README.md index 92d8528..1e8e28b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Nova -**v1.0.0** +**v1.0.1** This project, based on Java and the Spring Boot framework, is an open source self-hosted tool to manage and improve the developments of your releases. Improve the development of your releases with **Nova**! @@ -29,7 +29,7 @@ repositories { } dependencies { - implementation 'com.tecknobit.novacore:Nova-core:1.0.0' + implementation 'com.tecknobit.novacore:Nova-core:1.0.1' } ``` @@ -42,7 +42,7 @@ repositories { } dependencies { - implementation("com.tecknobit.novacore:Nova-core:1.0.0") + implementation("com.tecknobit.novacore:Nova-core:1.0.1") } ``` @@ -60,7 +60,7 @@ steps: - Android - iOS -> planned - Desktop version -- Backend service "out-of-the-box" +- Backend service "out-of-the-box" ## Usages diff --git a/backend/build.gradle.kts b/backend/build.gradle.kts new file mode 100644 index 0000000..5826583 --- /dev/null +++ b/backend/build.gradle.kts @@ -0,0 +1,49 @@ +plugins { + id("java") + id("maven-publish") + id("org.springframework.boot") version "3.2.3" + kotlin("jvm") +} + +group = "com.tecknobit" +version = "1.0.1" + +repositories { + mavenCentral() + mavenLocal() + maven("https://jitpack.io") + maven("https://repo.clojars.org") +} + +dependencies { + testImplementation("org.springframework.boot:spring-boot-starter-test:3.2.3") + implementation("org.springframework.boot:spring-boot-starter-web:3.2.3") + implementation("org.springframework.boot:spring-boot-maven-plugin:3.2.0") + implementation("org.springframework.boot:spring-boot-starter-data-jpa:3.2.3") + implementation("mysql:mysql-connector-java:8.0.33") + implementation("com.github.N7ghtm4r3:APIManager:2.2.4") + implementation("org.json:json:20231013") + implementation("com.vladsch.flexmark:flexmark-all:0.64.8") + implementation("com.github.N7ghtm4r3:Mantis:1.0.0") + implementation("org.apache.commons:commons-lang3:3.12.0") + implementation("com.tecknobit.novacore:novacore:1.0.1") +} + +afterEvaluate { + publishing { + publications { + create("maven") { + groupId = "com.tecknobit.nova" + artifactId = "Nova" + version = "1.0.1" + from(components["java"]) + } + } + } +} + +configurations.all { + exclude("commons-logging", "commons-logging") +} + +tasks.withType { duplicatesStrategy = DuplicatesStrategy.EXCLUDE } \ No newline at end of file diff --git a/src/main/java/com/tecknobit/nova/Launcher.java b/backend/src/main/java/com/tecknobit/nova/Launcher.java similarity index 93% rename from src/main/java/com/tecknobit/nova/Launcher.java rename to backend/src/main/java/com/tecknobit/nova/Launcher.java index 7ba5dee..75b47b7 100644 --- a/src/main/java/com/tecknobit/nova/Launcher.java +++ b/backend/src/main/java/com/tecknobit/nova/Launcher.java @@ -19,9 +19,6 @@ import java.security.NoSuchAlgorithmException; import java.util.UUID; -import static com.tecknobit.nova.helpers.resources.ResourcesProvider.CUSTOM_CONFIGURATION_FILE_PATH; -import static com.tecknobit.nova.helpers.resources.ResourcesProvider.DEFAULT_CONFIGURATION_FILE_PATH; - /** * The {@code Launcher} class is useful to launch Nova's backend service * @@ -29,8 +26,8 @@ */ @SpringBootApplication @PropertySources({ - @PropertySource(value = "classpath:" + DEFAULT_CONFIGURATION_FILE_PATH), - @PropertySource(value = "file:" + CUSTOM_CONFIGURATION_FILE_PATH, ignoreResourceNotFound = true) + @PropertySource(value = "classpath:" + ResourcesProvider.DEFAULT_CONFIGURATION_FILE_PATH), + @PropertySource(value = "file:" + ResourcesProvider.CUSTOM_CONFIGURATION_FILE_PATH, ignoreResourceNotFound = true) }) @EnableJpaRepositories("com.tecknobit.*") @EntityScan("com.tecknobit.*") diff --git a/src/main/java/com/tecknobit/nova/controllers/NovaController.java b/backend/src/main/java/com/tecknobit/nova/controllers/NovaController.java similarity index 95% rename from src/main/java/com/tecknobit/nova/controllers/NovaController.java rename to backend/src/main/java/com/tecknobit/nova/controllers/NovaController.java index e555f93..c50b6ef 100644 --- a/src/main/java/com/tecknobit/nova/controllers/NovaController.java +++ b/backend/src/main/java/com/tecknobit/nova/controllers/NovaController.java @@ -101,7 +101,7 @@ protected boolean isMe(String id, String token) { * @return the payload for a successful response as {@link String} */ protected String successResponse() { - return plainResponse(SUCCESSFUL, RESPONSE_SUCCESSFUL_MESSAGE); + return plainResponse(StandardResponseCode.SUCCESSFUL, RESPONSE_SUCCESSFUL_MESSAGE); } /** @@ -126,7 +126,7 @@ protected HashMap successResponse(V value) { */ protected String successResponse(JSONObject message) { return new JSONObject() - .put(RESPONSE_STATUS_KEY, SUCCESSFUL) + .put(RESPONSE_STATUS_KEY, StandardResponseCode.SUCCESSFUL) .put(RESPONSE_MESSAGE_KEY, message).toString(); } @@ -137,7 +137,7 @@ protected String successResponse(JSONObject message) { * @return the payload for a failed response as {@link String} */ protected String failedResponse(String error) { - return plainResponse(FAILED, error); + return plainResponse(StandardResponseCode.FAILED, error); } /** diff --git a/src/main/java/com/tecknobit/nova/controllers/UsersController.java b/backend/src/main/java/com/tecknobit/nova/controllers/UsersController.java similarity index 97% rename from src/main/java/com/tecknobit/nova/controllers/UsersController.java rename to backend/src/main/java/com/tecknobit/nova/controllers/UsersController.java index 0c1ce00..387a0c4 100644 --- a/src/main/java/com/tecknobit/nova/controllers/UsersController.java +++ b/backend/src/main/java/com/tecknobit/nova/controllers/UsersController.java @@ -1,6 +1,7 @@ package com.tecknobit.nova.controllers; import com.tecknobit.apimanager.annotations.RequestPath; +import com.tecknobit.nova.Launcher; import com.tecknobit.nova.helpers.services.UsersHelper; import com.tecknobit.nova.helpers.services.repositories.releaseutils.NotificationsRepository; import com.tecknobit.novacore.records.NovaNotification; @@ -14,10 +15,7 @@ import java.util.Map; import static com.tecknobit.apimanager.apis.APIRequest.RequestMethod.*; -import static com.tecknobit.nova.Launcher.generateIdentifier; -import static com.tecknobit.nova.Launcher.protector; import static com.tecknobit.novacore.InputValidator.*; -import static com.tecknobit.novacore.helpers.Endpoints.BASE_ENDPOINT; import static com.tecknobit.novacore.helpers.Endpoints.*; import static com.tecknobit.novacore.records.NovaNotification.NOTIFICATIONS_KEY; import static com.tecknobit.novacore.records.User.*; @@ -75,7 +73,7 @@ public UsersController(UsersHelper usersHelper) { @RequestPath(path = "/api/v1/users/signUp", method = POST) public String signUp(@RequestBody Map payload) { loadJsonHelper(payload); - if(protector.serverSecretMatches(jsonHelper.getString(SERVER_SECRET_KEY))) { + if(Launcher.protector.serverSecretMatches(jsonHelper.getString(SERVER_SECRET_KEY))) { String name = jsonHelper.getString(NAME_KEY); String surname = jsonHelper.getString(SURNAME_KEY); if(isNameValid(name)) { @@ -130,8 +128,8 @@ private String executeAuth(Map payload, String ... personalData) String profilePicUrl; JSONObject response = new JSONObject(); if(personalData.length == 2) { - id = generateIdentifier(); - token = generateIdentifier(); + id = Launcher.generateIdentifier(); + token = Launcher.generateIdentifier(); profilePicUrl = DEFAULT_PROFILE_PIC; try { usersHelper.signUpUser( diff --git a/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectManager.java b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectManager.java similarity index 100% rename from src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectManager.java rename to backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectManager.java index de28c48..b6a3dcc 100644 --- a/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectManager.java +++ b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectManager.java @@ -1,7 +1,7 @@ package com.tecknobit.nova.controllers.projectmanagers; -import com.tecknobit.nova.controllers.NovaController; import com.tecknobit.nova.helpers.services.ProjectsHelper; +import com.tecknobit.nova.controllers.NovaController; import com.tecknobit.novacore.records.User.Role; import com.tecknobit.novacore.records.project.Project; import org.springframework.beans.factory.annotation.Autowired; diff --git a/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectsController.java b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectsController.java similarity index 98% rename from src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectsController.java rename to backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectsController.java index d73a778..68d81f4 100644 --- a/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectsController.java +++ b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectsController.java @@ -4,7 +4,6 @@ import com.tecknobit.apimanager.formatters.JsonHelper; import com.tecknobit.nova.controllers.NovaController; import com.tecknobit.nova.helpers.services.ProjectsHelper; -import com.tecknobit.nova.helpers.services.ProjectsHelper.ProjectPayload; import com.tecknobit.nova.helpers.services.UsersHelper; import com.tecknobit.novacore.records.User; import com.tecknobit.novacore.records.project.JoiningQRCode; @@ -23,12 +22,11 @@ import static com.tecknobit.nova.Launcher.generateIdentifier; import static com.tecknobit.novacore.InputValidator.*; import static com.tecknobit.novacore.helpers.Endpoints.*; -import static com.tecknobit.novacore.helpers.Endpoints.BASE_ENDPOINT; import static com.tecknobit.novacore.records.NovaItem.IDENTIFIER_KEY; import static com.tecknobit.novacore.records.User.*; import static com.tecknobit.novacore.records.project.JoiningQRCode.*; import static com.tecknobit.novacore.records.project.Project.PROJECT_IDENTIFIER_KEY; -import static com.tecknobit.novacore.records.project.Project.*; +import static com.tecknobit.novacore.records.project.Project.PROJECT_MEMBERS_KEY; /** * The {@code ProjectsController} class is useful to manage all the project operations @@ -110,7 +108,7 @@ public T list( public String addProject( @PathVariable(IDENTIFIER_KEY) String id, @RequestHeader(TOKEN_KEY) String token, - @ModelAttribute ProjectPayload payload + @ModelAttribute ProjectsHelper.ProjectPayload payload ) { if(isMe(id, token) && me.isVendor()) { try { diff --git a/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ReleasesController.java b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ReleasesController.java similarity index 100% rename from src/main/java/com/tecknobit/nova/controllers/projectmanagers/ReleasesController.java rename to backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ReleasesController.java diff --git a/src/main/java/com/tecknobit/nova/helpers/ReportsProvider.java b/backend/src/main/java/com/tecknobit/nova/helpers/ReportsProvider.java similarity index 91% rename from src/main/java/com/tecknobit/nova/helpers/ReportsProvider.java rename to backend/src/main/java/com/tecknobit/nova/helpers/ReportsProvider.java index 4ee4fc5..203d318 100644 --- a/src/main/java/com/tecknobit/nova/helpers/ReportsProvider.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/ReportsProvider.java @@ -1,6 +1,9 @@ package com.tecknobit.nova.helpers; +import com.tecknobit.apimanager.apis.ResourcesUtils; +import com.tecknobit.apimanager.trading.TradingTools; import com.tecknobit.mantis.Mantis; +import com.tecknobit.nova.helpers.resources.ResourcesProvider; import com.tecknobit.novacore.records.project.Project; import com.tecknobit.novacore.records.release.Release; import com.tecknobit.novacore.records.release.Release.ReleaseStatus; @@ -19,10 +22,6 @@ import java.util.Locale; import java.util.Objects; -import static com.tecknobit.apimanager.apis.ResourcesUtils.getResourceContent; -import static com.tecknobit.apimanager.trading.TradingTools.roundValue; -import static com.tecknobit.nova.helpers.resources.ResourcesProvider.*; - /** * The {@code ReportsProvider} class is useful to create and provide the reports for the releases * @@ -73,7 +72,7 @@ public class ReportsProvider { { try { - reportTemplate = getResourceContent("report_template.md", this.getClass()); + reportTemplate = ResourcesUtils.getResourceContent("report_template.md", this.getClass()); } catch (IOException e) { throw new RuntimeException(e); } @@ -138,7 +137,7 @@ public String getReleaseReport(Release release) throws Exception { * @throws Exception when an error occurred */ private void deleteReleaseReportIfExists() throws Exception { - File reports = new File(RESOURCES_REPORTS_PATH); + File reports = new File(ResourcesProvider.RESOURCES_REPORTS_PATH); File reportToDelete = null; for (File report : Objects.requireNonNull(reports.listFiles())) { String checkReportName = report.getName(); @@ -160,7 +159,7 @@ private void deleteReleaseReportIfExists() throws Exception { private void setCurrentRelease(Release currentRelease) { this.currentRelease = currentRelease; releaseId = currentRelease.getId(); - reportName = REPORTS_DIRECTORY + "/" + currentRelease.getId() + "_" + currentRelease.getLastEvent() + ".pdf"; + reportName = ResourcesProvider.REPORTS_DIRECTORY + "/" + currentRelease.getId() + "_" + currentRelease.getLastEvent() + ".pdf"; } /** @@ -179,7 +178,7 @@ private void createReport() { .build(); Node document = parser.parse(reportTemplate); String html = renderer.render(document); - PdfConverterExtension.exportToPdf(RESOURCES_PATH + reportName, html, "", DataHolder.NULL); + PdfConverterExtension.exportToPdf(ResourcesProvider.RESOURCES_PATH + reportName, html, "", DataHolder.NULL); } /** @@ -205,7 +204,7 @@ private void insertHeader() { * @return the {@link #reportTemplate} changed with the project logo inserted */ private String insertLogo(Project project) { - return reportTemplate.replaceAll(PROJECT_LOGO_TAG, RESOURCES_PATH + project.getLogoUrl()); + return reportTemplate.replaceAll(PROJECT_LOGO_TAG, ResourcesProvider.RESOURCES_PATH + project.getLogoUrl()); } /** @@ -241,11 +240,11 @@ private void insertReleaseEvents() { List assets = assetUploadingEvent.getAssetsUploaded(); for(int j = 0; j < assets.size(); j++) { AssetUploaded asset = assets.get(j); - double spaceOccupied = new File(RESOURCES_PATH + asset.getUrl()).length(); + double spaceOccupied = new File(ResourcesProvider.RESOURCES_PATH + asset.getUrl()).length(); report.append("- Asset #") .append(j + 1) .append(" ") - .append(roundValue(((spaceOccupied) / (1024 * 1024)), 2)) + .append(TradingTools.roundValue(((spaceOccupied) / (1024 * 1024)), 2)) .append(" MB") .append(BREAK_LINE); } diff --git a/src/main/java/com/tecknobit/nova/helpers/resources/ResourcesManager.java b/backend/src/main/java/com/tecknobit/nova/helpers/resources/ResourcesManager.java similarity index 85% rename from src/main/java/com/tecknobit/nova/helpers/resources/ResourcesManager.java rename to backend/src/main/java/com/tecknobit/nova/helpers/resources/ResourcesManager.java index 28b70ab..b0af1f9 100644 --- a/src/main/java/com/tecknobit/nova/helpers/resources/ResourcesManager.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/resources/ResourcesManager.java @@ -9,8 +9,6 @@ import java.io.OutputStream; import java.util.Objects; -import static com.tecknobit.nova.helpers.resources.ResourcesProvider.*; - /** * The {@code ResourcesManager} interface is useful to create and manage the resources files as profile pic, * project logo, asset and report @@ -28,7 +26,7 @@ public interface ResourcesManager { */ @Wrapper default String createProfileResource(MultipartFile resource, String resourceId) { - return createResource(resource, PROFILES_DIRECTORY, resourceId); + return createResource(resource, ResourcesProvider.PROFILES_DIRECTORY, resourceId); } /** @@ -40,7 +38,7 @@ default String createProfileResource(MultipartFile resource, String resourceId) */ @Wrapper default String createLogoResource(MultipartFile resource, String resourceId) { - return createResource(resource, LOGOS_DIRECTORY, resourceId); + return createResource(resource, ResourcesProvider.LOGOS_DIRECTORY, resourceId); } /** @@ -52,7 +50,7 @@ default String createLogoResource(MultipartFile resource, String resourceId) { */ @Wrapper default String createAssetResource(MultipartFile resource, String resourceId) { - return createResource(resource, ASSETS_DIRECTORY, resourceId); + return createResource(resource, ResourcesProvider.ASSETS_DIRECTORY, resourceId); } /** @@ -64,7 +62,7 @@ default String createAssetResource(MultipartFile resource, String resourceId) { */ @Wrapper default String createReportResource(MultipartFile resource, String resourceId) { - return createResource(resource, REPORTS_DIRECTORY, resourceId); + return createResource(resource, ResourcesProvider.REPORTS_DIRECTORY, resourceId); } /** @@ -98,7 +96,7 @@ private String getSuffixResource(MultipartFile resource) { * @throws IOException when an error occurred during the resource file saving */ default void saveResource(MultipartFile resource, String path) throws IOException { - File resourceFile = new File(RESOURCES_PATH + path); + File resourceFile = new File(ResourcesProvider.RESOURCES_PATH + path); try (OutputStream outputStream = new FileOutputStream(resourceFile)) { outputStream.write(resource.getBytes()); } @@ -112,7 +110,7 @@ default void saveResource(MultipartFile resource, String path) throws IOExceptio */ @Wrapper default boolean deleteProfileResource(String profileId) { - return deleteResource(PROFILES_DIRECTORY, profileId); + return deleteResource(ResourcesProvider.PROFILES_DIRECTORY, profileId); } /** @@ -123,7 +121,7 @@ default boolean deleteProfileResource(String profileId) { */ @Wrapper default boolean deleteLogoResource(String logoId) { - return deleteResource(LOGOS_DIRECTORY, logoId); + return deleteResource(ResourcesProvider.LOGOS_DIRECTORY, logoId); } /** @@ -134,7 +132,7 @@ default boolean deleteLogoResource(String logoId) { */ @Wrapper default boolean deleteAssetResource(String assetId) { - return deleteResource(ASSETS_DIRECTORY, assetId); + return deleteResource(ResourcesProvider.ASSETS_DIRECTORY, assetId); } /** @@ -145,7 +143,7 @@ default boolean deleteAssetResource(String assetId) { */ @Wrapper default boolean deleteReportResource(String reportId) { - return deleteResource(REPORTS_DIRECTORY, reportId); + return deleteResource(ResourcesProvider.REPORTS_DIRECTORY, reportId); } /** @@ -156,7 +154,7 @@ default boolean deleteReportResource(String reportId) { * @return whether the resource has been deleted as boolean */ private boolean deleteResource(String resourcesDirectory, String resourceId) { - File resourceFolder = new File(RESOURCES_PATH + resourcesDirectory); + File resourceFolder = new File(ResourcesProvider.RESOURCES_PATH + resourcesDirectory); for (File resourceFile : Objects.requireNonNull(resourceFolder.listFiles())) if(resourceFile.getName().contains(resourceId)) return resourceFile.delete(); diff --git a/src/main/java/com/tecknobit/nova/helpers/resources/ResourcesProvider.java b/backend/src/main/java/com/tecknobit/nova/helpers/resources/ResourcesProvider.java similarity index 100% rename from src/main/java/com/tecknobit/nova/helpers/resources/ResourcesProvider.java rename to backend/src/main/java/com/tecknobit/nova/helpers/resources/ResourcesProvider.java diff --git a/src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java similarity index 97% rename from src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java rename to backend/src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java index 5c07928..e2b6d2a 100644 --- a/src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java @@ -9,6 +9,7 @@ import com.tecknobit.novacore.records.project.JoiningQRCode; import com.tecknobit.novacore.records.project.Project; import com.tecknobit.novacore.records.release.Release; +import org.apache.commons.lang3.RandomStringUtils; import org.json.JSONObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -21,11 +22,11 @@ import static com.tecknobit.nova.Launcher.generateIdentifier; import static com.tecknobit.novacore.records.NovaItem.IDENTIFIER_KEY; -import static com.tecknobit.novacore.records.User.*; +import static com.tecknobit.novacore.records.User.NAME_KEY; +import static com.tecknobit.novacore.records.User.PROJECTS_KEY; import static com.tecknobit.novacore.records.project.Project.AUTHOR_KEY; import static com.tecknobit.novacore.records.project.Project.LOGO_URL_KEY; import static java.lang.System.currentTimeMillis; -import static org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric; /** * The {@code ProjectsHelper} class is useful to manage all the project database operations @@ -124,7 +125,7 @@ public String createJoiningQrcode(String QRCodeId, String projectId, List("maven") { - groupId = "com.tecknobit.nova" - artifactId = "Nova" - version = "1.0.0" - from(components["java"]) - } +subprojects { + apply(plugin = "org.jetbrains.dokka") + tasks.withType().configureEach { + dokkaSourceSets.configureEach { + sourceRoots.from(file("src/main/kotlin")) + sourceRoots.from(file("src/main/java")) + includeNonPublic.set(true) + documentedVisibilities.set(setOf(PUBLIC, PROTECTED, PRIVATE)) } } } -tasks.test { - useJUnitPlatform() -} - -configurations.all { - exclude("commons-logging", "commons-logging") +repositories { + mavenCentral() } -tasks.withType { duplicatesStrategy = DuplicatesStrategy.EXCLUDE } \ No newline at end of file +tasks.withType { + outputDirectory.set(layout.projectDirectory.dir("docs")) + pluginConfiguration { + customAssets = listOf(file("docs/logo-icon.svg")) + footerMessage = "(c) 2024 Tecknobit" + } +} \ No newline at end of file diff --git a/Nova-core/build.gradle.kts b/core/build.gradle.kts similarity index 92% rename from Nova-core/build.gradle.kts rename to core/build.gradle.kts index a780f6f..40452aa 100644 --- a/Nova-core/build.gradle.kts +++ b/core/build.gradle.kts @@ -5,7 +5,7 @@ plugins { } group = "com.tecknobit" -version = "1.0.0" +version = "1.0.1" repositories { mavenCentral() @@ -30,8 +30,8 @@ afterEvaluate { publications { create("maven") { groupId = "com.tecknobit.novacore" - artifactId = "Nova-core" - version = "1.0.0" + artifactId = "novacore" + version = "1.0.1" from(components["java"]) } } diff --git a/Nova-core/src/main/java/com/tecknobit/novacore/InputValidator.java b/core/src/main/java/com/tecknobit/novacore/InputValidator.java similarity index 100% rename from Nova-core/src/main/java/com/tecknobit/novacore/InputValidator.java rename to core/src/main/java/com/tecknobit/novacore/InputValidator.java diff --git a/Nova-core/src/main/java/com/tecknobit/novacore/helpers/Endpoints.java b/core/src/main/java/com/tecknobit/novacore/helpers/Endpoints.java similarity index 100% rename from Nova-core/src/main/java/com/tecknobit/novacore/helpers/Endpoints.java rename to core/src/main/java/com/tecknobit/novacore/helpers/Endpoints.java diff --git a/Nova-core/src/main/java/com/tecknobit/novacore/helpers/LocalSessionUtils.java b/core/src/main/java/com/tecknobit/novacore/helpers/LocalSessionUtils.java similarity index 100% rename from Nova-core/src/main/java/com/tecknobit/novacore/helpers/LocalSessionUtils.java rename to core/src/main/java/com/tecknobit/novacore/helpers/LocalSessionUtils.java diff --git a/Nova-core/src/main/java/com/tecknobit/novacore/helpers/Requester.kt b/core/src/main/java/com/tecknobit/novacore/helpers/Requester.kt similarity index 93% rename from Nova-core/src/main/java/com/tecknobit/novacore/helpers/Requester.kt rename to core/src/main/java/com/tecknobit/novacore/helpers/Requester.kt index 7f02c72..6b6b84e 100644 --- a/Nova-core/src/main/java/com/tecknobit/novacore/helpers/Requester.kt +++ b/core/src/main/java/com/tecknobit/novacore/helpers/Requester.kt @@ -138,7 +138,7 @@ open class Requester ( * @return the result of the request as [JSONObject] * */ - @RequestPath(path = "/api/v1/users/signUp", method = RequestMethod.POST) + @RequestPath(path = "/api/v1/users/signUp", method = APIRequest.RequestMethod.POST) fun signUp( serverSecret: String, name: String, @@ -174,7 +174,7 @@ open class Requester ( * @return the result of the request as [JSONObject] * */ - @RequestPath(path = "/api/v1/users/signIn", method = RequestMethod.POST) + @RequestPath(path = "/api/v1/users/signIn", method = APIRequest.RequestMethod.POST) fun signIn( email: String, password: String @@ -195,7 +195,7 @@ open class Requester ( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/users/{id}/changeProfilePic", method = RequestMethod.POST) + @RequestPath(path = "/api/v1/users/{id}/changeProfilePic", method = APIRequest.RequestMethod.POST) open fun changeProfilePic( profilePic: File ) : JSONObject { @@ -214,7 +214,7 @@ open class Requester ( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/users/{id}/changeEmail", method = RequestMethod.PATCH) + @RequestPath(path = "/api/v1/users/{id}/changeEmail", method = APIRequest.RequestMethod.PATCH) fun changeEmail( newEmail: String ): JSONObject { @@ -233,7 +233,7 @@ open class Requester ( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/users/{id}/changePassword", method = RequestMethod.PATCH) + @RequestPath(path = "/api/v1/users/{id}/changePassword", method = APIRequest.RequestMethod.PATCH) fun changePassword( newPassword: String ): JSONObject { @@ -252,7 +252,7 @@ open class Requester ( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/users/{id}/changeLanguage", method = RequestMethod.PATCH) + @RequestPath(path = "/api/v1/users/{id}/changeLanguage", method = APIRequest.RequestMethod.PATCH) fun changeLanguage( newLanguage: String ): JSONObject { @@ -271,7 +271,7 @@ open class Requester ( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/users/{id}/notifications", method = RequestMethod.GET) + @RequestPath(path = "/api/v1/users/{id}/notifications", method = APIRequest.RequestMethod.GET) fun getNotifications(): JSONObject { return execGet( endpoint = assembleUsersEndpointPath("/$NOTIFICATIONS_KEY") @@ -285,7 +285,7 @@ open class Requester ( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/users/{id}", method = RequestMethod.DELETE) + @RequestPath(path = "/api/v1/users/{id}", method = APIRequest.RequestMethod.DELETE) fun deleteAccount(): JSONObject { return execDelete( endpoint = assembleUsersEndpointPath() @@ -312,7 +312,7 @@ open class Requester ( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/{id}/projects", method = RequestMethod.GET) + @RequestPath(path = "/api/v1/{id}/projects", method = APIRequest.RequestMethod.GET) fun listProjects() : JSONObject { return execGet( endpoint = assembleProjectsEndpointPath() @@ -327,7 +327,7 @@ open class Requester ( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/{id}/projects", method = RequestMethod.POST) + @RequestPath(path = "/api/v1/{id}/projects", method = APIRequest.RequestMethod.POST) open fun addProject( logoPic: File, projectName: String @@ -348,7 +348,7 @@ open class Requester ( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/{id}/projects/{projectId}", method = RequestMethod.GET) + @RequestPath(path = "/api/v1/{id}/projects/{projectId}", method = APIRequest.RequestMethod.GET) fun getProject( projectId: String ) : JSONObject { @@ -367,7 +367,7 @@ open class Requester ( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/{id}/projects/{projectId}/addMembers", method = RequestMethod.PUT) + @RequestPath(path = "/api/v1/{id}/projects/{projectId}/addMembers", method = APIRequest.RequestMethod.PUT) fun addMembers( projectId: String, mailingList: String, @@ -396,7 +396,7 @@ open class Requester ( * @return the result of the request as [JSONObject] * */ - @RequestPath(path = "/api/v1/projects/join", method = RequestMethod.POST) + @RequestPath(path = "/api/v1/projects/join", method = APIRequest.RequestMethod.POST) @Wrapper fun joinWithId( id: String, @@ -428,7 +428,7 @@ open class Requester ( * @return the result of the request as [JSONObject] * */ - @RequestPath(path = "/api/v1/projects/join", method = RequestMethod.POST) + @RequestPath(path = "/api/v1/projects/join", method = APIRequest.RequestMethod.POST) @Wrapper fun joinWithCode( joinCode: String, @@ -460,7 +460,7 @@ open class Requester ( * @return the result of the request as [JSONObject] * */ - @RequestPath(path = "/api/v1/projects/join", method = RequestMethod.POST) + @RequestPath(path = "/api/v1/projects/join", method = APIRequest.RequestMethod.POST) private fun join( payload: Params, email: String, @@ -488,7 +488,7 @@ open class Requester ( * @return the result of the request as [JSONObject] * */ - @RequestPath(path = "/api/v1/{id}/projects/{projectId}/removeMember", method = RequestMethod.DELETE) + @RequestPath(path = "/api/v1/{id}/projects/{projectId}/removeMember", method = APIRequest.RequestMethod.DELETE) fun removeMember( projectId: String, memberId: String @@ -509,7 +509,7 @@ open class Requester ( * @return the result of the request as [JSONObject] * */ - @RequestPath(path = "/api/v1/{id}/projects/{projectId}/leave", method = RequestMethod.DELETE) + @RequestPath(path = "/api/v1/{id}/projects/{projectId}/leave", method = APIRequest.RequestMethod.DELETE) fun leaveProject( projectId: String ) : JSONObject { @@ -526,7 +526,7 @@ open class Requester ( * @return the result of the request as [JSONObject] * */ - @RequestPath(path = "/api/v1/{id}/projects/{projectId}", method = RequestMethod.DELETE) + @RequestPath(path = "/api/v1/{id}/projects/{projectId}", method = APIRequest.RequestMethod.DELETE) fun deleteProject( projectId: String ) : JSONObject { @@ -560,7 +560,7 @@ open class Requester ( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/addRelease", method = RequestMethod.POST) + @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/addRelease", method = APIRequest.RequestMethod.POST) fun addRelease( projectId: String, releaseVersion: String, @@ -586,7 +586,7 @@ open class Requester ( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}", method = RequestMethod.GET) + @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}", method = APIRequest.RequestMethod.GET) fun getRelease( projectId: String, releaseId: String @@ -608,7 +608,7 @@ open class Requester ( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}", method = RequestMethod.POST) + @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}", method = APIRequest.RequestMethod.POST) open fun uploadAsset( projectId: String, releaseId: String, @@ -666,7 +666,7 @@ open class Requester ( @Wrapper @RequestPath( path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}/comment/{asset_uploading_event_id}", - method = RequestMethod.POST + method = APIRequest.RequestMethod.POST ) fun approveAssets( projectId: String, @@ -695,7 +695,7 @@ open class Requester ( @Wrapper @RequestPath( path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}/comment/{asset_uploading_event_id}", - method = RequestMethod.POST + method = APIRequest.RequestMethod.POST ) fun rejectAssets( projectId: String, @@ -728,7 +728,7 @@ open class Requester ( */ @RequestPath( path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}/comment/{asset_uploading_event_id}", - method = RequestMethod.POST + method = APIRequest.RequestMethod.POST ) private fun commentAssets( projectId: String, @@ -772,7 +772,7 @@ open class Requester ( */ @RequestPath( path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}/events/{release_event_id}/tags/{release_tag_id}", - method = RequestMethod.PUT + method = APIRequest.RequestMethod.PUT ) fun fillRejectedTag( projectId: String, @@ -803,7 +803,7 @@ open class Requester ( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}", method = RequestMethod.PATCH) + @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}", method = APIRequest.RequestMethod.PATCH) fun promoteRelease( projectId: String, releaseId: String, @@ -830,7 +830,7 @@ open class Requester ( */ @RequestPath( path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}/createReport", - method = RequestMethod.GET + method = APIRequest.RequestMethod.GET ) fun createReportRelease( projectId: String, @@ -853,7 +853,7 @@ open class Requester ( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}", method = RequestMethod.DELETE) + @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}", method = APIRequest.RequestMethod.DELETE) fun deleteRelease( projectId: String, releaseId: String @@ -906,7 +906,7 @@ open class Requester ( } /** - * Function to execute a [RequestMethod.GET] request to the backend + * Function to execute a [APIRequest.RequestMethod.GET] request to the backend * * @param endpoint: the endpoint path of the request url * @@ -917,13 +917,13 @@ open class Requester ( endpoint: String ) : JSONObject { return execRequest( - method = RequestMethod.GET, + method = APIRequest.RequestMethod.GET, endpoint = endpoint ) } /** - * Function to execute a [RequestMethod.POST] request to the backend + * Function to execute a [APIRequest.RequestMethod.POST] request to the backend * * @param endpoint: the endpoint path of the request url * @param payload: the payload of the request @@ -936,14 +936,14 @@ open class Requester ( payload: Params ) : JSONObject { return execRequest( - method = RequestMethod.POST, + method = APIRequest.RequestMethod.POST, endpoint = endpoint, payload = payload ) } /** - * Function to execute a [RequestMethod.PUT] request to the backend + * Function to execute a [APIRequest.RequestMethod.PUT] request to the backend * * @param endpoint: the endpoint path of the request url * @param payload: the payload of the request @@ -956,14 +956,14 @@ open class Requester ( payload: Params ) : JSONObject { return execRequest( - method = RequestMethod.PUT, + method = APIRequest.RequestMethod.PUT, endpoint = endpoint, payload = payload ) } /** - * Function to execute a [RequestMethod.PATCH] request to the backend + * Function to execute a [APIRequest.RequestMethod.PATCH] request to the backend * * @param endpoint: the endpoint path of the request url * @param payload: the payload of the request @@ -976,14 +976,14 @@ open class Requester ( payload: Params ) : JSONObject { return execRequest( - method = RequestMethod.PATCH, + method = APIRequest.RequestMethod.PATCH, endpoint = endpoint, payload = payload ) } /** - * Function to execute a [RequestMethod.DELETE] request to the backend + * Function to execute a [APIRequest.RequestMethod.DELETE] request to the backend * * @param endpoint: the endpoint path of the request url * @param payload: the payload of the request @@ -996,7 +996,7 @@ open class Requester ( payload: Params? = null ) : JSONObject { return execRequest( - method = RequestMethod.DELETE, + method = APIRequest.RequestMethod.DELETE, endpoint = endpoint, payload = payload ) diff --git a/Nova-core/src/main/java/com/tecknobit/novacore/records/NotificationsTarget.java b/core/src/main/java/com/tecknobit/novacore/records/NotificationsTarget.java similarity index 100% rename from Nova-core/src/main/java/com/tecknobit/novacore/records/NotificationsTarget.java rename to core/src/main/java/com/tecknobit/novacore/records/NotificationsTarget.java diff --git a/Nova-core/src/main/java/com/tecknobit/novacore/records/NovaItem.java b/core/src/main/java/com/tecknobit/novacore/records/NovaItem.java similarity index 100% rename from Nova-core/src/main/java/com/tecknobit/novacore/records/NovaItem.java rename to core/src/main/java/com/tecknobit/novacore/records/NovaItem.java diff --git a/Nova-core/src/main/java/com/tecknobit/novacore/records/NovaNotification.java b/core/src/main/java/com/tecknobit/novacore/records/NovaNotification.java similarity index 100% rename from Nova-core/src/main/java/com/tecknobit/novacore/records/NovaNotification.java rename to core/src/main/java/com/tecknobit/novacore/records/NovaNotification.java diff --git a/Nova-core/src/main/java/com/tecknobit/novacore/records/User.java b/core/src/main/java/com/tecknobit/novacore/records/User.java similarity index 100% rename from Nova-core/src/main/java/com/tecknobit/novacore/records/User.java rename to core/src/main/java/com/tecknobit/novacore/records/User.java diff --git a/Nova-core/src/main/java/com/tecknobit/novacore/records/project/JoiningQRCode.java b/core/src/main/java/com/tecknobit/novacore/records/project/JoiningQRCode.java similarity index 100% rename from Nova-core/src/main/java/com/tecknobit/novacore/records/project/JoiningQRCode.java rename to core/src/main/java/com/tecknobit/novacore/records/project/JoiningQRCode.java diff --git a/Nova-core/src/main/java/com/tecknobit/novacore/records/project/Project.java b/core/src/main/java/com/tecknobit/novacore/records/project/Project.java similarity index 100% rename from Nova-core/src/main/java/com/tecknobit/novacore/records/project/Project.java rename to core/src/main/java/com/tecknobit/novacore/records/project/Project.java diff --git a/Nova-core/src/main/java/com/tecknobit/novacore/records/release/Release.java b/core/src/main/java/com/tecknobit/novacore/records/release/Release.java similarity index 100% rename from Nova-core/src/main/java/com/tecknobit/novacore/records/release/Release.java rename to core/src/main/java/com/tecknobit/novacore/records/release/Release.java diff --git a/Nova-core/src/main/java/com/tecknobit/novacore/records/release/events/AssetUploadingEvent.java b/core/src/main/java/com/tecknobit/novacore/records/release/events/AssetUploadingEvent.java similarity index 100% rename from Nova-core/src/main/java/com/tecknobit/novacore/records/release/events/AssetUploadingEvent.java rename to core/src/main/java/com/tecknobit/novacore/records/release/events/AssetUploadingEvent.java diff --git a/Nova-core/src/main/java/com/tecknobit/novacore/records/release/events/RejectedReleaseEvent.java b/core/src/main/java/com/tecknobit/novacore/records/release/events/RejectedReleaseEvent.java similarity index 100% rename from Nova-core/src/main/java/com/tecknobit/novacore/records/release/events/RejectedReleaseEvent.java rename to core/src/main/java/com/tecknobit/novacore/records/release/events/RejectedReleaseEvent.java diff --git a/Nova-core/src/main/java/com/tecknobit/novacore/records/release/events/RejectedTag.java b/core/src/main/java/com/tecknobit/novacore/records/release/events/RejectedTag.java similarity index 100% rename from Nova-core/src/main/java/com/tecknobit/novacore/records/release/events/RejectedTag.java rename to core/src/main/java/com/tecknobit/novacore/records/release/events/RejectedTag.java diff --git a/Nova-core/src/main/java/com/tecknobit/novacore/records/release/events/ReleaseEvent.java b/core/src/main/java/com/tecknobit/novacore/records/release/events/ReleaseEvent.java similarity index 100% rename from Nova-core/src/main/java/com/tecknobit/novacore/records/release/events/ReleaseEvent.java rename to core/src/main/java/com/tecknobit/novacore/records/release/events/ReleaseEvent.java diff --git a/Nova-core/src/main/java/com/tecknobit/novacore/records/release/events/ReleaseStandardEvent.java b/core/src/main/java/com/tecknobit/novacore/records/release/events/ReleaseStandardEvent.java similarity index 100% rename from Nova-core/src/main/java/com/tecknobit/novacore/records/release/events/ReleaseStandardEvent.java rename to core/src/main/java/com/tecknobit/novacore/records/release/events/ReleaseStandardEvent.java diff --git a/core/src/main/resources/resources.mantis b/core/src/main/resources/resources.mantis new file mode 100644 index 0000000..6416143 --- /dev/null +++ b/core/src/main/resources/resources.mantis @@ -0,0 +1,21 @@ +{ + "en": { + "new_asset_uploaded_key": "New asset uploaded", + "asset_has_been_approved_key": "Asset has been approved", + "beta_timeline_message_key": "Asset has been promoted to Beta version", + "latest_timeline_message_key": "Release promoted as latest!", + "creation_date_key": "Date of creation:", + "alpha_timeline_message_key": "Asset has been promoted to Alpha version", + "new_asset_has_been_uploaded_key": "New asset has been uploaded" + }, + "ignored_resources": {}, + "it": { + "new_asset_uploaded_key": "Nuovo asset caricato", + "asset_has_been_approved_key": "L'asset e' stato approvato", + "beta_timeline_message_key": "L'asset e' stato promosso alla versione Beta", + "latest_timeline_message_key": "Release promosso come ultimo!", + "creation_date_key": "Data creazione:", + "alpha_timeline_message_key": "L'asset e' stato promosso alla versione Alpha", + "new_asset_has_been_uploaded_key": "Un nuovo asset e' stato caricato" + } +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index df60519..bd974af 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -7,4 +7,5 @@ plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "0.5.0" } rootProject.name = "Nova" -include("Nova-core") +include("core") +include("backend") From 326393682fff47e651d0a2519c09277841a83228 Mon Sep 17 00:00:00 2001 From: N7ghtm4r3 Date: Tue, 17 Sep 2024 23:39:44 +0200 Subject: [PATCH 02/25] Working on Equinox implementation --- backend/build.gradle.kts | 1 + .../java/com/tecknobit/nova/Launcher.java | 101 +-- .../controllers/DefaultNovaController.java | 14 + .../nova/controllers/NovaController.java | 157 ----- .../nova/controllers/NovaUsersController.java | 85 +++ .../nova/controllers/UsersController.java | 400 ------------ .../projectmanagers/ProjectManager.java | 8 +- .../projectmanagers/ProjectsController.java | 22 +- .../projectmanagers/ReleasesController.java | 9 +- .../nova/helpers/ReportsProvider.java | 15 +- .../nova/helpers/resources/CORSAdvice.java | 36 ++ .../resources/NovaResourcesManager.java | 105 ++++ .../helpers/resources/ResourcesConfig.java | 34 + .../helpers/resources/ResourcesManager.java | 164 ----- .../helpers/resources/ResourcesProvider.java | 134 ---- .../helpers/services/NovaUsersHelper.java | 26 + .../nova/helpers/services/ProjectsHelper.java | 22 +- .../nova/helpers/services/ReleasesHelper.java | 22 +- .../nova/helpers/services/UsersHelper.java | 137 ----- .../repositories/UsersRepository.java | 111 ---- .../JoiningQRCodeRepository.java | 2 +- .../projectsutils/ProjectsRepository.java | 4 +- .../releaseutils/NotificationsRepository.java | 2 +- backend/src/main/resources/resources.mantis | 62 +- core/build.gradle.kts | 4 +- .../novacore/helpers/LocalSessionUtils.java | 6 +- .../novacore/records/NovaNotification.java | 10 +- .../records/{User.java => NovaUser.java} | 255 +------- .../records/project/JoiningQRCode.java | 4 +- .../novacore/records/project/Project.java | 34 +- .../novacore/records/release/Release.java | 10 +- .../release/events/AssetUploadingEvent.java | 2 +- .../records/release/events/ReleaseEvent.java | 6 +- .../novacore/helpers/NovaRequester.kt} | 582 ++---------------- core/src/main/resources/resources.mantis | 21 - 35 files changed, 548 insertions(+), 2059 deletions(-) create mode 100644 backend/src/main/java/com/tecknobit/nova/controllers/DefaultNovaController.java delete mode 100644 backend/src/main/java/com/tecknobit/nova/controllers/NovaController.java create mode 100644 backend/src/main/java/com/tecknobit/nova/controllers/NovaUsersController.java delete mode 100644 backend/src/main/java/com/tecknobit/nova/controllers/UsersController.java create mode 100644 backend/src/main/java/com/tecknobit/nova/helpers/resources/CORSAdvice.java create mode 100644 backend/src/main/java/com/tecknobit/nova/helpers/resources/NovaResourcesManager.java create mode 100644 backend/src/main/java/com/tecknobit/nova/helpers/resources/ResourcesConfig.java delete mode 100644 backend/src/main/java/com/tecknobit/nova/helpers/resources/ResourcesManager.java delete mode 100644 backend/src/main/java/com/tecknobit/nova/helpers/resources/ResourcesProvider.java create mode 100644 backend/src/main/java/com/tecknobit/nova/helpers/services/NovaUsersHelper.java delete mode 100644 backend/src/main/java/com/tecknobit/nova/helpers/services/UsersHelper.java delete mode 100644 backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/UsersRepository.java rename core/src/main/java/com/tecknobit/novacore/records/{User.java => NovaUser.java} (55%) rename core/src/main/{java/com/tecknobit/novacore/helpers/Requester.kt => kotlin/com/tecknobit/novacore/helpers/NovaRequester.kt} (54%) delete mode 100644 core/src/main/resources/resources.mantis diff --git a/backend/build.gradle.kts b/backend/build.gradle.kts index 5826583..51889f2 100644 --- a/backend/build.gradle.kts +++ b/backend/build.gradle.kts @@ -27,6 +27,7 @@ dependencies { implementation("com.github.N7ghtm4r3:Mantis:1.0.0") implementation("org.apache.commons:commons-lang3:3.12.0") implementation("com.tecknobit.novacore:novacore:1.0.1") + implementation("com.github.N7ghtm4r3:Equinox:1.0.3") } afterEvaluate { diff --git a/backend/src/main/java/com/tecknobit/nova/Launcher.java b/backend/src/main/java/com/tecknobit/nova/Launcher.java index 75b47b7..9176268 100644 --- a/backend/src/main/java/com/tecknobit/nova/Launcher.java +++ b/backend/src/main/java/com/tecknobit/nova/Launcher.java @@ -1,70 +1,45 @@ package com.tecknobit.nova; -import com.tecknobit.apimanager.apis.ServerProtector; -import com.tecknobit.apimanager.exceptions.SaveData; -import com.tecknobit.nova.helpers.resources.ResourcesProvider; +import com.tecknobit.equinox.environment.controllers.EquinoxController; +import com.tecknobit.equinox.resourcesutils.ResourcesProvider; import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.domain.EntityScan; -import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.PropertySource; import org.springframework.context.annotation.PropertySources; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -import org.springframework.web.cors.CorsConfiguration; -import org.springframework.web.cors.UrlBasedCorsConfigurationSource; -import org.springframework.web.filter.CorsFilter; -import java.security.NoSuchAlgorithmException; -import java.util.UUID; +import static com.tecknobit.equinox.resourcesutils.ResourcesProvider.CUSTOM_CONFIGURATION_FILE_PATH; +import static com.tecknobit.equinox.resourcesutils.ResourcesProvider.DEFAULT_CONFIGURATION_FILE_PATH; +import static com.tecknobit.nova.helpers.resources.NovaResourcesManager.*; /** * The {@code Launcher} class is useful to launch Nova's backend service * * @author N7ghtm4r3 - Tecknobit */ -@SpringBootApplication @PropertySources({ - @PropertySource(value = "classpath:" + ResourcesProvider.DEFAULT_CONFIGURATION_FILE_PATH), - @PropertySource(value = "file:" + ResourcesProvider.CUSTOM_CONFIGURATION_FILE_PATH, ignoreResourceNotFound = true) + @PropertySource(value = "classpath:" + DEFAULT_CONFIGURATION_FILE_PATH), + @PropertySource(value = "file:" + CUSTOM_CONFIGURATION_FILE_PATH, ignoreResourceNotFound = true) }) +@EnableAutoConfiguration @EnableJpaRepositories("com.tecknobit.*") @EntityScan("com.tecknobit.*") +@ComponentScan("com.tecknobit.nova.*") +@SpringBootApplication public class Launcher { - /** - * {@code protector} the instance to launch the server protector to manage the server accesses - * - * @apiNote the commands scheme: - *
    - *
  • - * rss -> launch your java application with "rss" to recreate the server secret
    - * e.g java -jar Nova.jar rss - *
  • - *
  • - * dss -> launch your java application with "dss" to delete the current server secret
    - * e.g java -jar Nova.jar dss - *
  • - *
  • - * dssi -> launch your java application with "dssi" to delete the current server secret and interrupt - * the current workflow of the server
    - * e.g java -jar Nova.jar dssi - *
  • - *
- */ - public static final ServerProtector protector = new ServerProtector("tecknobit/nova/backend", - " to correctly register a new user in the Nova system "); - /** * Main method to start the backend, will be created also the resources directories if not exist invoking the * {@link ResourcesProvider} routine * - * @param args: custom arguments to share with {@link SpringApplication} and with the {@link #protector} + * @param args: custom arguments to share with {@link SpringApplication} and with the {@link EquinoxController#protector} * @apiNote the arguments scheme: *
    *
  • - * {@link #protector} -> + * {@link EquinoxController#protector} -> *
      *
    • * rss -> launch your java application with "rss" to recreate the server secret
      @@ -86,48 +61,14 @@ public class Launcher { *
    • *
    */ - public static void main(String[] args) throws NoSuchAlgorithmException, SaveData { - ResourcesProvider.createResourceDirectories(); - protector.launch(args); + public static void main(String[] args) { + EquinoxController.initEquinoxEnvironment( + "tecknobit/nova/backend", + " to correctly register a new user in the Nova system ", + Launcher.class, + args, + LOGOS_DIRECTORY, ASSETS_DIRECTORY, REPORTS_DIRECTORY); SpringApplication.run(Launcher.class, args); } - /** - * Method to generate a {@link UUID} as identifier for the entities
    - * No-any params required - * - * @return {@link UUID} identifier as {@link String} - */ - public static String generateIdentifier() { - return UUID.randomUUID().toString().replaceAll("-", ""); - } - - /** - * The {@code CORSAdvice} class is useful to set the CORS policy - * - * @author N7ghtm4r3 - Tecknobit - */ - @Configuration - public static class CORSAdvice { - - /** - * Method to set the CORS filter
    - * No any-params required - */ - @Bean - public FilterRegistrationBean corsFilter() { - UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); - CorsConfiguration config = new CorsConfiguration(); - config.setAllowCredentials(false); - config.addAllowedOrigin("*"); - config.addAllowedHeader("*"); - config.addAllowedMethod("*"); - source.registerCorsConfiguration("/**", config); - FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source)); - bean.setOrder(0); - return bean; - } - - } - } diff --git a/backend/src/main/java/com/tecknobit/nova/controllers/DefaultNovaController.java b/backend/src/main/java/com/tecknobit/nova/controllers/DefaultNovaController.java new file mode 100644 index 0000000..66c79b9 --- /dev/null +++ b/backend/src/main/java/com/tecknobit/nova/controllers/DefaultNovaController.java @@ -0,0 +1,14 @@ +package com.tecknobit.nova.controllers; + +import com.tecknobit.apimanager.annotations.Structure; +import com.tecknobit.equinox.environment.controllers.EquinoxController; +import com.tecknobit.novacore.records.NovaUser; + +/** + * The {@code DefaultNovaController} class is useful to give the base behavior of the Nova's controllers + * + * @author N7ghtm4r3 - Tecknobit + */ +@Structure +public abstract class DefaultNovaController extends EquinoxController { +} diff --git a/backend/src/main/java/com/tecknobit/nova/controllers/NovaController.java b/backend/src/main/java/com/tecknobit/nova/controllers/NovaController.java deleted file mode 100644 index c50b6ef..0000000 --- a/backend/src/main/java/com/tecknobit/nova/controllers/NovaController.java +++ /dev/null @@ -1,157 +0,0 @@ -package com.tecknobit.nova.controllers; - -import com.tecknobit.apimanager.annotations.Structure; -import com.tecknobit.apimanager.apis.sockets.SocketManager; -import com.tecknobit.apimanager.apis.sockets.SocketManager.StandardResponseCode; -import com.tecknobit.apimanager.formatters.JsonHelper; -import com.tecknobit.nova.helpers.services.repositories.UsersRepository; -import com.tecknobit.novacore.records.User; -import org.json.JSONObject; -import org.springframework.beans.factory.annotation.Autowired; - -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - -import static com.tecknobit.apimanager.apis.sockets.SocketManager.StandardResponseCode.FAILED; -import static com.tecknobit.apimanager.apis.sockets.SocketManager.StandardResponseCode.SUCCESSFUL; -import static com.tecknobit.novacore.helpers.Requester.RESPONSE_MESSAGE_KEY; -import static com.tecknobit.novacore.helpers.Requester.RESPONSE_STATUS_KEY; - -/** - * The {@code NovaController} class is useful to give the base behavior of the Nova's controllers - * - * @author N7ghtm4r3 - Tecknobit - */ -@Structure -public abstract class NovaController { - - /** - * {@code WRONG_PROCEDURE_MESSAGE} message to use when the procedure is wrong - */ - public static final String WRONG_PROCEDURE_MESSAGE = "Wrong procedure"; - - /** - * {@code NOT_AUTHORIZED_OR_WRONG_DETAILS_MESSAGE} message to use when the request is by a not authorized user or - * tried to fetch wrong details - */ - public static final String NOT_AUTHORIZED_OR_WRONG_DETAILS_MESSAGE = "Not authorized or wrong details"; - - /** - * {@code RESPONSE_SUCCESSFUL_MESSAGE} message to use when the request has been successful - */ - public static final String RESPONSE_SUCCESSFUL_MESSAGE = "Operation executed successfully"; - - /** - * {@code usersRepository} instance for the user repository - */ - @Autowired - protected UsersRepository usersRepository; - - /** - * {@code jsonHelper} helper to work with JSON values - */ - protected JsonHelper jsonHelper = new JsonHelper("{}"); - - /** - * {@code me} user representing the user who made a request on the server - */ - protected User me; - - /** - * Method to load the {@link #jsonHelper} - * - * @param payload: the payload received with the request - * @param generic type for the values in the payload - */ - protected void loadJsonHelper(Map payload) { - jsonHelper.setJSONObjectSource(new JSONObject(payload)); - } - - /** - * Method to load the {@link #jsonHelper} - * - * @param payload: the payload received with the request - */ - protected void loadJsonHelper(String payload) { - jsonHelper.setJSONObjectSource(payload); - } - - /** - * Method to check whether the user who made a request is an authorized user
    - * If the user is authorized the {@link #me} instance is loaded - * - * @param id: the identifier of the user - * @param token: the token of the user - * @return whether the user is an authorized user as boolean - */ - protected boolean isMe(String id, String token) { - Optional query = usersRepository.findById(id); - me = query.orElse(null); - boolean isMe = me != null && me.getToken().equals(token); - if(!isMe) - me = null; - return isMe; - } - - /** - * Method to get the payload for a successful response
    - * No-any params required - * - * @return the payload for a successful response as {@link String} - */ - protected String successResponse() { - return plainResponse(StandardResponseCode.SUCCESSFUL, RESPONSE_SUCCESSFUL_MESSAGE); - } - - /** - * Method to get the payload for a successful response - * - * @param value: the value to send as response - * @return the payload for a successful response as {@link HashMap} of {@link V} - * @param generic type for the values in the payload - */ - protected HashMap successResponse(V value) { - HashMap response = new HashMap<>(); - response.put(RESPONSE_MESSAGE_KEY, value); - response.put(RESPONSE_STATUS_KEY, (V) SocketManager.StandardResponseCode.SUCCESSFUL); - return response; - } - - /** - * Method to get the payload for a successful response - * - * @param message: the message to send as response - * @return the payload for a successful response as {@link String} - */ - protected String successResponse(JSONObject message) { - return new JSONObject() - .put(RESPONSE_STATUS_KEY, StandardResponseCode.SUCCESSFUL) - .put(RESPONSE_MESSAGE_KEY, message).toString(); - } - - /** - * Method to get the payload for a failed response - * - * @param error: the error message to send as response - * @return the payload for a failed response as {@link String} - */ - protected String failedResponse(String error) { - return plainResponse(StandardResponseCode.FAILED, error); - } - - /** - * Method to assemble the payload for a response - * - * @param responseCode: the response code value - * @param message: the message to send as response - * - * @return the payload for a response as {@link String} - */ - private String plainResponse(StandardResponseCode responseCode, String message) { - return new JSONObject() - .put(RESPONSE_STATUS_KEY, responseCode) - .put(RESPONSE_MESSAGE_KEY, message).toString(); - } - -} diff --git a/backend/src/main/java/com/tecknobit/nova/controllers/NovaUsersController.java b/backend/src/main/java/com/tecknobit/nova/controllers/NovaUsersController.java new file mode 100644 index 0000000..31ea590 --- /dev/null +++ b/backend/src/main/java/com/tecknobit/nova/controllers/NovaUsersController.java @@ -0,0 +1,85 @@ +package com.tecknobit.nova.controllers; + +import com.tecknobit.apimanager.annotations.RequestPath; +import com.tecknobit.equinox.annotations.CustomParametersOrder; +import com.tecknobit.equinox.environment.controllers.EquinoxUsersController; +import com.tecknobit.nova.helpers.services.NovaUsersHelper; +import com.tecknobit.nova.helpers.services.repositories.releaseutils.NotificationsRepository; +import com.tecknobit.novacore.records.NovaNotification; +import com.tecknobit.novacore.records.NovaUser; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Primary; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +import static com.tecknobit.apimanager.apis.APIRequest.RequestMethod.GET; +import static com.tecknobit.equinox.environment.records.EquinoxItem.IDENTIFIER_KEY; +import static com.tecknobit.equinox.environment.records.EquinoxUser.TOKEN_KEY; +import static com.tecknobit.equinox.environment.records.EquinoxUser.USERS_KEY; +import static com.tecknobit.novacore.records.NovaNotification.NOTIFICATIONS_KEY; +import static com.tecknobit.novacore.records.NovaUser.ROLE_KEY; +import static com.tecknobit.novacore.records.NovaUser.Role.Vendor; + +/** + * The {@code UsersController} class is useful to manage all the user operations + * + * @author N7ghtm4r3 - Tecknobit + * @see DefaultNovaController + */ +@Primary +@RestController +public class NovaUsersController extends EquinoxUsersController { + + /** + * {@code notificationsRepository} instance useful to manage the notifications + */ + @Autowired + private NotificationsRepository notificationsRepository; + + /** + * Constructor to init the {@link EquinoxUsersController} controller + * + * @param usersHelper : helper to manage the users database operations + */ + public NovaUsersController(NovaUsersHelper usersHelper) { + super(usersHelper); + } + + @Override + @CustomParametersOrder(order = ROLE_KEY) + protected Object[] getSignUpCustomParams() { + return new Object[]{Vendor}; + } + + /** + * Method to get the notifications of the user + * + * @param id: the identifier of the user + * @param token: the token of the user + * + * @return the result of the request as {@link String} + */ + @GetMapping( + path = USERS_KEY + "/{" + IDENTIFIER_KEY + "}/" + NOTIFICATIONS_KEY, + headers = { + TOKEN_KEY + } + ) + @RequestPath(path = "/api/v1/users/{id}/notifications", method = GET) + public T getNotifications( + @PathVariable(IDENTIFIER_KEY) String id, + @RequestHeader(TOKEN_KEY) String token + ) { + if(isMe(id, token)) { + List notifications = notificationsRepository.getUserNotifications(id); + notificationsRepository.setUserNotificationsAsSent(id); + return (T) successResponse(notifications); + } else + return (T) failedResponse(NOT_AUTHORIZED_OR_WRONG_DETAILS_MESSAGE); + } + +} diff --git a/backend/src/main/java/com/tecknobit/nova/controllers/UsersController.java b/backend/src/main/java/com/tecknobit/nova/controllers/UsersController.java deleted file mode 100644 index 387a0c4..0000000 --- a/backend/src/main/java/com/tecknobit/nova/controllers/UsersController.java +++ /dev/null @@ -1,400 +0,0 @@ -package com.tecknobit.nova.controllers; - -import com.tecknobit.apimanager.annotations.RequestPath; -import com.tecknobit.nova.Launcher; -import com.tecknobit.nova.helpers.services.UsersHelper; -import com.tecknobit.nova.helpers.services.repositories.releaseutils.NotificationsRepository; -import com.tecknobit.novacore.records.NovaNotification; -import com.tecknobit.novacore.records.User; -import org.json.JSONObject; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import java.util.List; -import java.util.Map; - -import static com.tecknobit.apimanager.apis.APIRequest.RequestMethod.*; -import static com.tecknobit.novacore.InputValidator.*; -import static com.tecknobit.novacore.helpers.Endpoints.*; -import static com.tecknobit.novacore.records.NovaNotification.NOTIFICATIONS_KEY; -import static com.tecknobit.novacore.records.User.*; - -/** - * The {@code UsersController} class is useful to manage all the user operations - * - * @author N7ghtm4r3 - Tecknobit - * @see NovaController - */ -@RestController -@RequestMapping(path = BASE_ENDPOINT) -public class UsersController extends NovaController { - - /** - * {@code usersHelper} helper to manage the users database operations - */ - private final UsersHelper usersHelper; - - /** - * {@code notificationsRepository} instance useful to manage the notifications - */ - @Autowired - private NotificationsRepository notificationsRepository; - - /** - * Constructor to init the {@link UsersController} controller - * - * @param usersHelper: helper to manage the users database operations - */ - @Autowired - public UsersController(UsersHelper usersHelper) { - this.usersHelper = usersHelper; - } - - /** - * Method to sign up in the Nova's system - * - * @param payload: payload of the request - *
    -     *      {@code
    -     *              {
    -     *                  "server_secret" : "the secret of the server" -> [String],
    -     *                  "name" : "the name of the user" -> [String],
    -     *                  "surname": "the surname of the user" -> [String],
    -     *                  "email": "the email of the user" -> [String],
    -     *                  "password": "the password of the user" -> [String]
    -     *              }
    -     *      }
    -     * 
    - * - * @return the result of the request as {@link String} - */ - @PostMapping(path = SIGN_UP_ENDPOINT) - @RequestPath(path = "/api/v1/users/signUp", method = POST) - public String signUp(@RequestBody Map payload) { - loadJsonHelper(payload); - if(Launcher.protector.serverSecretMatches(jsonHelper.getString(SERVER_SECRET_KEY))) { - String name = jsonHelper.getString(NAME_KEY); - String surname = jsonHelper.getString(SURNAME_KEY); - if(isNameValid(name)) { - if(isSurnameValid(surname)) - return executeAuth(payload, name, surname); - else - return failedResponse(WRONG_SURNAME_MESSAGE); - } else - return failedResponse(WRONG_NAME_MESSAGE); - } else - return failedResponse(NOT_AUTHORIZED_OR_WRONG_DETAILS_MESSAGE); - } - - /** - * Method to sign in the Nova's system - * - * @param payload: payload of the request - *
    -     *      {@code
    -     *              {
    -     *                  "email": "the email of the user", -> [String]
    -     *                  "password": "the password of the user" -> [String]
    -     *              }
    -     *      }
    -     * 
    - * - * @return the result of the request as {@link String} - */ - @PostMapping(path = SIGN_IN_ENDPOINT) - @RequestPath(path = "/api/v1/users/signIn", method = POST) - public String signIn(@RequestBody Map payload) { - return executeAuth(payload); - } - - /** - * Method to execute the auth operations - * - * @param payload: the payload received with the auth request - * @param personalData: the personal data of the user like name and surname - * @return the result of the auth operation as {@link String} - */ - private String executeAuth(Map payload, String ... personalData) { - loadJsonHelper(payload); - String email = jsonHelper.getString(EMAIL_KEY); - String password = jsonHelper.getString(PASSWORD_KEY); - String language = jsonHelper.getString(LANGUAGE_KEY, DEFAULT_LANGUAGE); - if(isEmailValid(email)) { - if(isPasswordValid(password)) { - if(isLanguageValid(language)) { - String id; - String token; - String profilePicUrl; - JSONObject response = new JSONObject(); - if(personalData.length == 2) { - id = Launcher.generateIdentifier(); - token = Launcher.generateIdentifier(); - profilePicUrl = DEFAULT_PROFILE_PIC; - try { - usersHelper.signUpUser( - id, - token, - personalData[0], - personalData[1], - email.toLowerCase(), - password, - language, - Role.Vendor - ); - } catch (Exception e) { - return failedResponse(NOT_AUTHORIZED_OR_WRONG_DETAILS_MESSAGE); - } - } else { - try { - User user = usersHelper.signInUser(email.toLowerCase(), password); - if(user != null) { - id = user.getId(); - token = user.getToken(); - profilePicUrl = user.getProfilePicUrl(); - response.put(NAME_KEY, user.getName()); - response.put(SURNAME_KEY, user.getSurname()); - response.put(LANGUAGE_KEY, user.getLanguage()); - response.put(ROLE_KEY, user.getRole()); - } else - return failedResponse(NOT_AUTHORIZED_OR_WRONG_DETAILS_MESSAGE); - } catch (Exception e) { - return failedResponse(WRONG_PROCEDURE_MESSAGE); - } - } - return successResponse(response - .put(IDENTIFIER_KEY, id) - .put(TOKEN_KEY, token) - .put(PROFILE_PIC_URL_KEY, profilePicUrl) - ); - } else - return failedResponse(WRONG_LANGUAGE_MESSAGE); - } else - return failedResponse(WRONG_PASSWORD_MESSAGE); - } else - return failedResponse(WRONG_EMAIL_MESSAGE); - } - - /** - * Method to change the profile pic of the user - * - * @param id: the identifier of the user - * @param token: the token of the user - * @param profilePic: the profile pic chosen by the user to set as the new profile pic - * - * @return the result of the request as {@link String} - */ - @PostMapping( - path = USERS_KEY + "/{" + IDENTIFIER_KEY + "}" + CHANGE_PROFILE_PIC_ENDPOINT, - headers = { - TOKEN_KEY - } - ) - @RequestPath(path = "/api/v1/users/{id}/changeProfilePic", method = POST) - public String changeProfilePic( - @PathVariable(IDENTIFIER_KEY) String id, - @RequestHeader(TOKEN_KEY) String token, - @RequestParam(PROFILE_PIC_URL_KEY) MultipartFile profilePic - ) { - if(isMe(id, token)) { - if(!profilePic.isEmpty()) { - JSONObject response = new JSONObject(); - try { - String profilePicUrl = usersHelper.changeProfilePic(profilePic, id); - response.put(PROFILE_PIC_URL_KEY, profilePicUrl); - } catch (Exception e) { - response.put(PROFILE_PIC_URL_KEY, DEFAULT_PROFILE_PIC); - } - return successResponse(response); - } else - return failedResponse(WRONG_PROCEDURE_MESSAGE); - } else - return failedResponse(NOT_AUTHORIZED_OR_WRONG_DETAILS_MESSAGE); - } - - /** - * Method to change the email of the user - * - * @param id: the identifier of the user - * @param token: the token of the user - * @param payload: payload of the request - *
    -     *      {@code
    -     *              {
    -     *                  "email": "the new email of the user" -> [String]
    -     *              }
    -     *      }
    -     * 
    - * - * @return the result of the request as {@link String} - */ - @PatchMapping( - path = USERS_KEY + "/{" + IDENTIFIER_KEY + "}" + CHANGE_EMAIL_ENDPOINT, - headers = { - TOKEN_KEY - } - ) - @RequestPath(path = "/api/v1/users/{id}/changeEmail", method = PATCH) - public String changeEmail( - @PathVariable(IDENTIFIER_KEY) String id, - @RequestHeader(TOKEN_KEY) String token, - @RequestBody Map payload - ) { - if(isMe(id, token)) { - loadJsonHelper(payload); - String email = jsonHelper.getString(EMAIL_KEY); - if(isEmailValid(email)) { - try { - usersHelper.changeEmail(email, id); - return successResponse(); - } catch (Exception e) { - return failedResponse(WRONG_PROCEDURE_MESSAGE); - } - } else - return failedResponse(WRONG_EMAIL_MESSAGE); - } else - return failedResponse(NOT_AUTHORIZED_OR_WRONG_DETAILS_MESSAGE); - } - - /** - * Method to change the password of the user - * - * @param id: the identifier of the user - * @param token: the token of the user - * @param payload: payload of the request - *
    -     *      {@code
    -     *              {
    -     *                  "password": "the new password of the user" -> [String]
    -     *              }
    -     *      }
    -     * 
    - * - * @return the result of the request as {@link String} - */ - @PatchMapping( - path = USERS_KEY + "/{" + IDENTIFIER_KEY + "}" + CHANGE_PASSWORD_ENDPOINT, - headers = { - TOKEN_KEY - } - ) - @RequestPath(path = "/api/v1/users/{id}/changePassword", method = PATCH) - public String changePassword( - @PathVariable(IDENTIFIER_KEY) String id, - @RequestHeader(TOKEN_KEY) String token, - @RequestBody Map payload - ) { - if(isMe(id, token)) { - loadJsonHelper(payload); - String password = jsonHelper.getString(PASSWORD_KEY); - if(isPasswordValid(password)) { - try { - usersHelper.changePassword(password, id); - return successResponse(); - } catch (Exception e) { - return failedResponse(WRONG_PROCEDURE_MESSAGE); - } - } else - return failedResponse(WRONG_PASSWORD_MESSAGE); - } else - return failedResponse(NOT_AUTHORIZED_OR_WRONG_DETAILS_MESSAGE); - } - - /** - * Method to change the language of the user - * - * @param id: the identifier of the user - * @param token: the token of the user - * @param payload: payload of the request - *
    -     *      {@code
    -     *              {
    -     *                  "language": "the new language of the user" -> [String]
    -     *              }
    -     *      }
    -     * 
    - * - * @return the result of the request as {@link String} - */ - @PatchMapping( - path = USERS_KEY + "/{" + IDENTIFIER_KEY + "}" + CHANGE_LANGUAGE_ENDPOINT, - headers = { - TOKEN_KEY - } - ) - @RequestPath(path = "/api/v1/users/{id}/changeLanguage", method = PATCH) - public String changeLanguage( - @PathVariable(IDENTIFIER_KEY) String id, - @RequestHeader(TOKEN_KEY) String token, - @RequestBody Map payload - ) { - if(isMe(id, token)) { - loadJsonHelper(payload); - String language = jsonHelper.getString(LANGUAGE_KEY); - if(isLanguageValid(language)) { - try { - usersHelper.changeLanguage(language, id); - return successResponse(); - } catch (Exception e) { - return failedResponse(WRONG_PROCEDURE_MESSAGE); - } - } else - return failedResponse(WRONG_LANGUAGE_MESSAGE); - } else - return failedResponse(NOT_AUTHORIZED_OR_WRONG_DETAILS_MESSAGE); - } - - /** - * Method to get the notifications of the user - * - * @param id: the identifier of the user - * @param token: the token of the user - * - * @return the result of the request as {@link String} - */ - @GetMapping( - path = USERS_KEY + "/{" + IDENTIFIER_KEY + "}/" + NOTIFICATIONS_KEY, - headers = { - TOKEN_KEY - } - ) - @RequestPath(path = "/api/v1/users/{id}/notifications", method = GET) - public T getNotifications( - @PathVariable(IDENTIFIER_KEY) String id, - @RequestHeader(TOKEN_KEY) String token - ) { - if(isMe(id, token)) { - List notifications = notificationsRepository.getUserNotifications(id); - notificationsRepository.setUserNotificationsAsSent(id); - return (T) successResponse(notifications); - } else - return (T) failedResponse(NOT_AUTHORIZED_OR_WRONG_DETAILS_MESSAGE); - } - - /** - * Method to delete the account of the user - * - * @param id: the identifier of the user - * @param token: the token of the user - * - * @return the result of the request as {@link String} - */ - @DeleteMapping( - path = USERS_KEY + "/{" + IDENTIFIER_KEY + "}", - headers = { - TOKEN_KEY - } - ) - @RequestPath(path = "/api/v1/users/{id}", method = DELETE) - public String deleteAccount( - @PathVariable(IDENTIFIER_KEY) String id, - @RequestHeader(TOKEN_KEY) String token - ) { - if(isMe(id, token)) { - usersHelper.deleteUser(id); - return successResponse(); - } else - return failedResponse(NOT_AUTHORIZED_OR_WRONG_DETAILS_MESSAGE); - } - -} diff --git a/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectManager.java b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectManager.java index b6a3dcc..abb92f3 100644 --- a/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectManager.java +++ b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectManager.java @@ -1,8 +1,8 @@ package com.tecknobit.nova.controllers.projectmanagers; +import com.tecknobit.nova.controllers.DefaultNovaController; import com.tecknobit.nova.helpers.services.ProjectsHelper; -import com.tecknobit.nova.controllers.NovaController; -import com.tecknobit.novacore.records.User.Role; +import com.tecknobit.novacore.records.NovaUser.Role; import com.tecknobit.novacore.records.project.Project; import org.springframework.beans.factory.annotation.Autowired; @@ -10,9 +10,9 @@ * The {@code ProjectManager} class is useful to give the base utilities to work with project database operations * * @author N7ghtm4r3 - Tecknobit - * @see NovaController + * @see DefaultNovaController */ -public abstract class ProjectManager extends NovaController { +public abstract class ProjectManager extends DefaultNovaController { /** * {@code projectsHelper} helper to manage the project database operations diff --git a/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectsController.java b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectsController.java index 68d81f4..3e74677 100644 --- a/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectsController.java +++ b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectsController.java @@ -2,10 +2,10 @@ import com.tecknobit.apimanager.annotations.RequestPath; import com.tecknobit.apimanager.formatters.JsonHelper; -import com.tecknobit.nova.controllers.NovaController; +import com.tecknobit.equinox.environment.helpers.services.EquinoxUsersHelper; +import com.tecknobit.nova.controllers.DefaultNovaController; import com.tecknobit.nova.helpers.services.ProjectsHelper; -import com.tecknobit.nova.helpers.services.UsersHelper; -import com.tecknobit.novacore.records.User; +import com.tecknobit.novacore.records.NovaUser; import com.tecknobit.novacore.records.project.JoiningQRCode; import com.tecknobit.novacore.records.project.Project; import org.json.JSONArray; @@ -19,11 +19,11 @@ import java.util.Map; import static com.tecknobit.apimanager.apis.APIRequest.RequestMethod.*; -import static com.tecknobit.nova.Launcher.generateIdentifier; +import static com.tecknobit.equinox.environment.records.EquinoxUser.TOKEN_KEY; import static com.tecknobit.novacore.InputValidator.*; import static com.tecknobit.novacore.helpers.Endpoints.*; import static com.tecknobit.novacore.records.NovaItem.IDENTIFIER_KEY; -import static com.tecknobit.novacore.records.User.*; +import static com.tecknobit.novacore.records.NovaUser.*; import static com.tecknobit.novacore.records.project.JoiningQRCode.*; import static com.tecknobit.novacore.records.project.Project.PROJECT_IDENTIFIER_KEY; import static com.tecknobit.novacore.records.project.Project.PROJECT_MEMBERS_KEY; @@ -32,7 +32,7 @@ * The {@code ProjectsController} class is useful to manage all the project operations * * @author N7ghtm4r3 - Tecknobit - * @see NovaController + * @see DefaultNovaController * @see ProjectManager */ @RestController @@ -42,7 +42,7 @@ public class ProjectsController extends ProjectManager { /** * {@code usersHelper} helper to manage the users database operations */ - private final UsersHelper usersHelper; + private final EquinoxUsersHelper usersHelper; /** * Constructor to init the {@link ProjectsController} controller @@ -51,7 +51,7 @@ public class ProjectsController extends ProjectManager { * @param usersHelper: helper to manage the users database operations */ @Autowired - public ProjectsController(ProjectsHelper projectsHelper, UsersHelper usersHelper) { + public ProjectsController(ProjectsHelper projectsHelper, EquinoxUsersHelper usersHelper) { super(projectsHelper); this.usersHelper = usersHelper; } @@ -193,7 +193,7 @@ public String addMembers( List membersEmails = JsonHelper.toList(jsonHelper.getJSONArray(PROJECT_MEMBERS_KEY, new JSONArray())); if(isMailingListValid(membersEmails)) { try { - User.Role role = User.Role.valueOf(jsonHelper.getString(ROLE_KEY)); + NovaUser.Role role = NovaUser.Role.valueOf(jsonHelper.getString(ROLE_KEY)); String QRCodeId = generateIdentifier(); String joinCode = projectsHelper.createJoiningQrcode(QRCodeId, projectId, membersEmails, role, jsonHelper.getBoolean(CREATE_JOIN_CODE_KEY, false)); @@ -254,7 +254,7 @@ public String join( Project project = joiningQRCode.getProject(); if(project.hasNotMemberEmail(email)) { if(joiningQRCode.listEmails().contains(email)) { - User user = usersRepository.findUserByEmail(email); + NovaUser user = usersRepository.findUserByEmail(email); JSONObject response = new JSONObject(); String userId; if(user == null) { @@ -280,7 +280,7 @@ public String join( role ); response.put(TOKEN_KEY, token) - .put(PROFILE_PIC_URL_KEY, DEFAULT_PROFILE_PIC) + .put(PROFILE_PIC_KEY, DEFAULT_PROFILE_PIC) .put(ROLE_KEY, role); } catch (NoSuchAlgorithmException e) { return failedResponse(WRONG_PASSWORD_MESSAGE); diff --git a/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ReleasesController.java b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ReleasesController.java index 14e6384..8adb18d 100644 --- a/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ReleasesController.java +++ b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ReleasesController.java @@ -1,7 +1,7 @@ package com.tecknobit.nova.controllers.projectmanagers; import com.tecknobit.apimanager.annotations.RequestPath; -import com.tecknobit.nova.controllers.NovaController; +import com.tecknobit.nova.controllers.DefaultNovaController; import com.tecknobit.nova.helpers.ReportsProvider; import com.tecknobit.nova.helpers.services.ProjectsHelper; import com.tecknobit.nova.helpers.services.ReleasesHelper; @@ -19,12 +19,11 @@ import java.util.Map; import static com.tecknobit.apimanager.apis.APIRequest.RequestMethod.*; -import static com.tecknobit.nova.Launcher.generateIdentifier; +import static com.tecknobit.equinox.environment.records.EquinoxUser.TOKEN_KEY; import static com.tecknobit.novacore.InputValidator.*; import static com.tecknobit.novacore.helpers.Endpoints.*; import static com.tecknobit.novacore.records.NovaItem.IDENTIFIER_KEY; -import static com.tecknobit.novacore.records.User.PROJECTS_KEY; -import static com.tecknobit.novacore.records.User.TOKEN_KEY; +import static com.tecknobit.novacore.records.NovaUser.PROJECTS_KEY; import static com.tecknobit.novacore.records.project.Project.PROJECT_IDENTIFIER_KEY; import static com.tecknobit.novacore.records.release.Release.*; import static com.tecknobit.novacore.records.release.Release.ReleaseStatus.*; @@ -41,7 +40,7 @@ * The {@code ReleasesController} class is useful to manage all the release operations * * @author N7ghtm4r3 - Tecknobit - * @see NovaController + * @see DefaultNovaController * @see ProjectManager */ @RestController diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/ReportsProvider.java b/backend/src/main/java/com/tecknobit/nova/helpers/ReportsProvider.java index 203d318..8810410 100644 --- a/backend/src/main/java/com/tecknobit/nova/helpers/ReportsProvider.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/ReportsProvider.java @@ -3,7 +3,6 @@ import com.tecknobit.apimanager.apis.ResourcesUtils; import com.tecknobit.apimanager.trading.TradingTools; import com.tecknobit.mantis.Mantis; -import com.tecknobit.nova.helpers.resources.ResourcesProvider; import com.tecknobit.novacore.records.project.Project; import com.tecknobit.novacore.records.release.Release; import com.tecknobit.novacore.records.release.Release.ReleaseStatus; @@ -22,6 +21,10 @@ import java.util.Locale; import java.util.Objects; +import static com.tecknobit.equinox.resourcesutils.ResourcesManager.RESOURCES_PATH; +import static com.tecknobit.nova.helpers.resources.NovaResourcesManager.REPORTS_DIRECTORY; +import static com.tecknobit.nova.helpers.resources.NovaResourcesManager.RESOURCES_REPORTS_PATH; + /** * The {@code ReportsProvider} class is useful to create and provide the reports for the releases * @@ -137,7 +140,7 @@ public String getReleaseReport(Release release) throws Exception { * @throws Exception when an error occurred */ private void deleteReleaseReportIfExists() throws Exception { - File reports = new File(ResourcesProvider.RESOURCES_REPORTS_PATH); + File reports = new File(RESOURCES_REPORTS_PATH); File reportToDelete = null; for (File report : Objects.requireNonNull(reports.listFiles())) { String checkReportName = report.getName(); @@ -159,7 +162,7 @@ private void deleteReleaseReportIfExists() throws Exception { private void setCurrentRelease(Release currentRelease) { this.currentRelease = currentRelease; releaseId = currentRelease.getId(); - reportName = ResourcesProvider.REPORTS_DIRECTORY + "/" + currentRelease.getId() + "_" + currentRelease.getLastEvent() + ".pdf"; + reportName = REPORTS_DIRECTORY + "/" + currentRelease.getId() + "_" + currentRelease.getLastEvent() + ".pdf"; } /** @@ -178,7 +181,7 @@ private void createReport() { .build(); Node document = parser.parse(reportTemplate); String html = renderer.render(document); - PdfConverterExtension.exportToPdf(ResourcesProvider.RESOURCES_PATH + reportName, html, "", DataHolder.NULL); + PdfConverterExtension.exportToPdf(RESOURCES_PATH + reportName, html, "", DataHolder.NULL); } /** @@ -204,7 +207,7 @@ private void insertHeader() { * @return the {@link #reportTemplate} changed with the project logo inserted */ private String insertLogo(Project project) { - return reportTemplate.replaceAll(PROJECT_LOGO_TAG, ResourcesProvider.RESOURCES_PATH + project.getLogoUrl()); + return reportTemplate.replaceAll(PROJECT_LOGO_TAG, RESOURCES_PATH + project.getLogoUrl()); } /** @@ -240,7 +243,7 @@ private void insertReleaseEvents() { List assets = assetUploadingEvent.getAssetsUploaded(); for(int j = 0; j < assets.size(); j++) { AssetUploaded asset = assets.get(j); - double spaceOccupied = new File(ResourcesProvider.RESOURCES_PATH + asset.getUrl()).length(); + double spaceOccupied = new File(RESOURCES_PATH + asset.getUrl()).length(); report.append("- Asset #") .append(j + 1) .append(" ") diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/resources/CORSAdvice.java b/backend/src/main/java/com/tecknobit/nova/helpers/resources/CORSAdvice.java new file mode 100644 index 0000000..df4f1c0 --- /dev/null +++ b/backend/src/main/java/com/tecknobit/nova/helpers/resources/CORSAdvice.java @@ -0,0 +1,36 @@ +package com.tecknobit.nova.helpers.resources; + +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; + +/** + * The {@code CORSAdvice} class is useful to set the CORS policy + * + * @author N7ghtm4r3 - Tecknobit + */ +@Configuration +public class CORSAdvice { + + /** + * Method to set the CORS filter
    + * No any-params required + */ + @Bean + public FilterRegistrationBean corsFilter() { + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + CorsConfiguration config = new CorsConfiguration(); + config.setAllowCredentials(false); + config.addAllowedOrigin("*"); + config.addAllowedHeader("*"); + config.addAllowedMethod("*"); + source.registerCorsConfiguration("/**", config); + FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source)); + bean.setOrder(0); + return bean; + } + +} \ No newline at end of file diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/resources/NovaResourcesManager.java b/backend/src/main/java/com/tecknobit/nova/helpers/resources/NovaResourcesManager.java new file mode 100644 index 0000000..ca29e81 --- /dev/null +++ b/backend/src/main/java/com/tecknobit/nova/helpers/resources/NovaResourcesManager.java @@ -0,0 +1,105 @@ +package com.tecknobit.nova.helpers.resources; + +import com.tecknobit.apimanager.annotations.Wrapper; +import com.tecknobit.equinox.resourcesutils.ResourcesManager; +import org.springframework.web.multipart.MultipartFile; + +/** + * The {@code NovaResourcesManager} interface is useful to create and manage the resources files as profile pic, + * project logo, asset and report + * + * @author N7ghtm4r3 - Tecknobit + * @see ResourcesManager + */ +public interface NovaResourcesManager extends ResourcesManager { + + /** + * {@code LOGOS_DIRECTORY} the logos directory where are stored the logos of the projects + */ + String LOGOS_DIRECTORY = "logos"; + + /** + * {@code ASSETS_DIRECTORY} the assets directory where are stored the assets of the releases uploaded + */ + String ASSETS_DIRECTORY = "assets"; + + /** + * {@code REPORTS_DIRECTORY} the reports directory where are stored the reports of the releases created + */ + String REPORTS_DIRECTORY = "reports"; + + /** + * {@code RESOURCES_REPORTS_PATH} the complete reports path from resources directory + */ + String RESOURCES_REPORTS_PATH = RESOURCES_PATH + REPORTS_DIRECTORY + "/"; + + /** + * Method to create the pathname for a project logo + * + * @param resource: the resource from create its pathname + * @param resourceId: the resource identifier + * @return the pathname created for a project logo + */ + @Wrapper + default String createLogoResource(MultipartFile resource, String resourceId) { + return createResource(resource, LOGOS_DIRECTORY, resourceId); + } + + /** + * Method to create the pathname for an asset + * + * @param resource: the resource from create its pathname + * @param resourceId: the resource identifier + * @return the pathname created for an asset + */ + @Wrapper + default String createAssetResource(MultipartFile resource, String resourceId) { + return createResource(resource, ASSETS_DIRECTORY, resourceId); + } + + /** + * Method to create the pathname for a report + * + * @param resource: the resource from create its pathname + * @param resourceId: the resource identifier + * @return the pathname created for a report + */ + @Wrapper + default String createReportResource(MultipartFile resource, String resourceId) { + return createResource(resource, REPORTS_DIRECTORY, resourceId); + } + + /** + * Method to delete a project logo + * + * @param logoId: the project logo identifier of the logo to delete + * @return whether the project logo has been deleted as boolean + */ + @Wrapper + default boolean deleteLogoResource(String logoId) { + return deleteResource(LOGOS_DIRECTORY, logoId); + } + + /** + * Method to delete an asset + * + * @param assetId: the asset identifier of the asset to delete + * @return whether the asset has been deleted as boolean + */ + @Wrapper + default boolean deleteAssetResource(String assetId) { + return deleteResource(ASSETS_DIRECTORY, assetId); + } + + /** + * Method to delete a report + * + * @param reportId: the report identifier of the report to delete + * @return whether the report has been deleted as boolean + */ + @Wrapper + default boolean deleteReportResource(String reportId) { + return deleteResource(REPORTS_DIRECTORY, reportId); + } + +} diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/resources/ResourcesConfig.java b/backend/src/main/java/com/tecknobit/nova/helpers/resources/ResourcesConfig.java new file mode 100644 index 0000000..e1bd2d2 --- /dev/null +++ b/backend/src/main/java/com/tecknobit/nova/helpers/resources/ResourcesConfig.java @@ -0,0 +1,34 @@ +package com.tecknobit.nova.helpers.resources; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.resource.PathResourceResolver; + +/** + * The {@code ResourceConfigs} class is useful to set the configuration of the resources to correctly serve the + * images by the server + * + * @author N7ghtm4r3 - Tecknobit + * @see WebMvcConfigurer + */ +@Configuration +public class ResourcesConfig implements WebMvcConfigurer { + + /** + * Add handlers to serve static resources such as images, js, and, css + * files from specific locations under web application root, the classpath, + * and others. + * + * @see ResourceHandlerRegistry + */ + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/**") + .addResourceLocations("file:resources/") + .setCachePeriod(0) + .resourceChain(true) + .addResolver(new PathResourceResolver()); + } + +} \ No newline at end of file diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/resources/ResourcesManager.java b/backend/src/main/java/com/tecknobit/nova/helpers/resources/ResourcesManager.java deleted file mode 100644 index b0af1f9..0000000 --- a/backend/src/main/java/com/tecknobit/nova/helpers/resources/ResourcesManager.java +++ /dev/null @@ -1,164 +0,0 @@ -package com.tecknobit.nova.helpers.resources; - -import com.tecknobit.apimanager.annotations.Wrapper; -import org.springframework.web.multipart.MultipartFile; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.Objects; - -/** - * The {@code ResourcesManager} interface is useful to create and manage the resources files as profile pic, - * project logo, asset and report - * - * @author N7ghtm4r3 - Tecknobit - */ -public interface ResourcesManager { - - /** - * Method to create the pathname for a profile pic - * - * @param resource: the resource from create its pathname - * @param resourceId: the resource identifier - * @return the pathname created for a profile pic - */ - @Wrapper - default String createProfileResource(MultipartFile resource, String resourceId) { - return createResource(resource, ResourcesProvider.PROFILES_DIRECTORY, resourceId); - } - - /** - * Method to create the pathname for a project logo - * - * @param resource: the resource from create its pathname - * @param resourceId: the resource identifier - * @return the pathname created for a project logo - */ - @Wrapper - default String createLogoResource(MultipartFile resource, String resourceId) { - return createResource(resource, ResourcesProvider.LOGOS_DIRECTORY, resourceId); - } - - /** - * Method to create the pathname for an asset - * - * @param resource: the resource from create its pathname - * @param resourceId: the resource identifier - * @return the pathname created for an asset - */ - @Wrapper - default String createAssetResource(MultipartFile resource, String resourceId) { - return createResource(resource, ResourcesProvider.ASSETS_DIRECTORY, resourceId); - } - - /** - * Method to create the pathname for a report - * - * @param resource: the resource from create its pathname - * @param resourceId: the resource identifier - * @return the pathname created for a report - */ - @Wrapper - default String createReportResource(MultipartFile resource, String resourceId) { - return createResource(resource, ResourcesProvider.REPORTS_DIRECTORY, resourceId); - } - - /** - * Method to create the pathname of a resource file - * - * @param resource: the resource from create its pathname - * @param resourcesDirectory: the specific resources directory to store the resource file - * @param resourceId: the resource identifier - * @return the pathname created of the resource file - */ - private String createResource(MultipartFile resource, String resourcesDirectory, String resourceId) { - return resourcesDirectory + "/" + resourceId + getSuffixResource(resource); - } - - /** - * Method to get the suffix of a resource file - * - * @param resource: the resource file from get its suffix - * @return the suffix of the resource file as {@link String} - */ - private String getSuffixResource(MultipartFile resource) { - String resourceName = Objects.requireNonNull(resource.getResource().getFilename()); - return resourceName.replace(resourceName.substring(0, resourceName.lastIndexOf(".")), ""); - } - - /** - * Method to save a resource file - * - * @param resource: the resource to save - * @param path: the path where save the resource file - * @throws IOException when an error occurred during the resource file saving - */ - default void saveResource(MultipartFile resource, String path) throws IOException { - File resourceFile = new File(ResourcesProvider.RESOURCES_PATH + path); - try (OutputStream outputStream = new FileOutputStream(resourceFile)) { - outputStream.write(resource.getBytes()); - } - } - - /** - * Method to delete a profile pic - * - * @param profileId: the profile pic identifier of the profile pic to delete - * @return whether the profile pic has been deleted as boolean - */ - @Wrapper - default boolean deleteProfileResource(String profileId) { - return deleteResource(ResourcesProvider.PROFILES_DIRECTORY, profileId); - } - - /** - * Method to delete a project logo - * - * @param logoId: the project logo identifier of the logo to delete - * @return whether the project logo has been deleted as boolean - */ - @Wrapper - default boolean deleteLogoResource(String logoId) { - return deleteResource(ResourcesProvider.LOGOS_DIRECTORY, logoId); - } - - /** - * Method to delete an asset - * - * @param assetId: the asset identifier of the asset to delete - * @return whether the asset has been deleted as boolean - */ - @Wrapper - default boolean deleteAssetResource(String assetId) { - return deleteResource(ResourcesProvider.ASSETS_DIRECTORY, assetId); - } - - /** - * Method to delete a report - * - * @param reportId: the report identifier of the report to delete - * @return whether the report has been deleted as boolean - */ - @Wrapper - default boolean deleteReportResource(String reportId) { - return deleteResource(ResourcesProvider.REPORTS_DIRECTORY, reportId); - } - - /** - * Method to delete a resource file - * - * @param resourcesDirectory: the resources directory where delete a resource file - * @param resourceId: the resource identifier of the resource to delete - * @return whether the resource has been deleted as boolean - */ - private boolean deleteResource(String resourcesDirectory, String resourceId) { - File resourceFolder = new File(ResourcesProvider.RESOURCES_PATH + resourcesDirectory); - for (File resourceFile : Objects.requireNonNull(resourceFolder.listFiles())) - if(resourceFile.getName().contains(resourceId)) - return resourceFile.delete(); - return false; - } - -} diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/resources/ResourcesProvider.java b/backend/src/main/java/com/tecknobit/nova/helpers/resources/ResourcesProvider.java deleted file mode 100644 index 748c652..0000000 --- a/backend/src/main/java/com/tecknobit/nova/helpers/resources/ResourcesProvider.java +++ /dev/null @@ -1,134 +0,0 @@ -package com.tecknobit.nova.helpers.resources; - -import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import org.springframework.web.servlet.resource.PathResourceResolver; - -import java.io.File; - -/** - * The {@code ResourcesProvider} class is useful to create the resources directories and manage the main resources files - * such as the properties for the server - * - * @author N7ghtm4r3 - Tecknobit - */ -public class ResourcesProvider { - - /** - * {@code DEFAULT_CONFIGURATION_FILE_PATH} the default path where find the default server configuration - */ - public static final String DEFAULT_CONFIGURATION_FILE_PATH = "app.properties"; - - /** - * {@code CUSTOM_CONFIGURATION_FILE_PATH} the path of the custom server configuration file - * - * @apiNote to use your custom configuration you must save the file in the same folder where you placed the - * server file (.jar) and call it "nova.properties" - * @implSpec take a look here - * to get more information about the custom configuration for properties that you can use - */ - public static final String CUSTOM_CONFIGURATION_FILE_PATH = "nova.properties"; - - /** - * {@code RESOURCES_PATH} the main path of the resources directories - */ - public static final String RESOURCES_PATH = "resources/"; - - /** - * {@code RESOURCES_DIRECTORIES} the list of the resources directories - */ - public static final String[] RESOURCES_DIRECTORIES = {"profiles", "logos", "assets", "reports"}; - - /** - * {@code PROFILES_DIRECTORY} the profiles directory where are stored the pics of the users - */ - public static final String PROFILES_DIRECTORY = RESOURCES_DIRECTORIES[0]; - - /** - * {@code LOGOS_DIRECTORY} the logos directory where are stored the logos of the projects - */ - public static final String LOGOS_DIRECTORY = RESOURCES_DIRECTORIES[1]; - - /** - * {@code ASSETS_DIRECTORY} the assets directory where are stored the assets of the releases uploaded - */ - public static final String ASSETS_DIRECTORY = RESOURCES_DIRECTORIES[2]; - - /** - * {@code REPORTS_DIRECTORY} the reports directory where are stored the reports of the releases created - */ - public static final String REPORTS_DIRECTORY = RESOURCES_DIRECTORIES[3]; - - /** - * {@code RESOURCES_REPORTS_PATH} the complete reports path from resources directory - */ - public static final String RESOURCES_REPORTS_PATH = RESOURCES_PATH + REPORTS_DIRECTORY + "/"; - - /** - * Constructor to init the {@link ResourcesProvider} controller
    - * No-any params required - */ - private ResourcesProvider() { - } - - /** - * Method to create all the resources directories
    - * No-any params required - */ - public static void createResourceDirectories() { - createResourceDirectory(RESOURCES_PATH); - for (String directory : RESOURCES_DIRECTORIES) - createResourceDirectory(RESOURCES_PATH + directory); - } - - /** - * Method to create a specific resources directory from {@link #RESOURCES_DIRECTORIES} list - * - * @param resDirectory: the specific resources directory to create - */ - private static void createResourceDirectory(String resDirectory) { - File directory = new File(resDirectory); - if(!directory.exists()) - if(!directory.mkdir()) - printError(resDirectory.replaceAll("/", "")); - } - - /** - * Method to print the error occurred during the creation of a resources directory - * @param directory: the directory when, during the creation, occurred an error - */ - private static void printError(String directory) { - System.err.println("Error during the creation of the \"" + directory + "\" folder"); - System.exit(-1); - } - - /** - * The {@code ResourceConfigs} class is useful to set the configuration of the resources to correctly serve the - * images by the server - * - * @author N7ghtm4r3 - Tecknobit - * @see WebMvcConfigurer - */ - @Configuration - public static class ResourcesConfigs implements WebMvcConfigurer { - - /** - * Add handlers to serve static resources such as images, js, and, css - * files from specific locations under web application root, the classpath, - * and others. - * - * @see ResourceHandlerRegistry - */ - @Override - public void addResourceHandlers(ResourceHandlerRegistry registry) { - registry.addResourceHandler("/**") - .addResourceLocations("file:" + RESOURCES_PATH) - .setCachePeriod(0) - .resourceChain(true) - .addResolver(new PathResourceResolver()); - } - - } - -} diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/NovaUsersHelper.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/NovaUsersHelper.java new file mode 100644 index 0000000..736d904 --- /dev/null +++ b/backend/src/main/java/com/tecknobit/nova/helpers/services/NovaUsersHelper.java @@ -0,0 +1,26 @@ +package com.tecknobit.nova.helpers.services; + +import com.tecknobit.equinox.annotations.CustomParametersOrder; +import com.tecknobit.equinox.environment.helpers.services.EquinoxUsersHelper; +import com.tecknobit.novacore.records.NovaUser; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +import static com.tecknobit.novacore.records.NovaUser.ROLE_KEY; + +@Primary +@Service +public class NovaUsersHelper extends EquinoxUsersHelper { + + @Override + @CustomParametersOrder(order = ROLE_KEY) + protected List getQueryValuesKeys() { + ArrayList custom = new ArrayList<>(super.getQueryValuesKeys()); + custom.add(ROLE_KEY); + return custom; + } + +} diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java index e2b6d2a..93ef2bf 100644 --- a/backend/src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java @@ -1,11 +1,11 @@ package com.tecknobit.nova.helpers.services; import com.tecknobit.nova.controllers.projectmanagers.ProjectsController; -import com.tecknobit.nova.helpers.resources.ResourcesManager; +import com.tecknobit.nova.helpers.resources.NovaResourcesManager; import com.tecknobit.nova.helpers.services.repositories.projectsutils.JoiningQRCodeRepository; import com.tecknobit.nova.helpers.services.repositories.projectsutils.ProjectsRepository; import com.tecknobit.nova.helpers.services.repositories.releaseutils.NotificationsRepository; -import com.tecknobit.novacore.records.User; +import com.tecknobit.novacore.records.NovaUser; import com.tecknobit.novacore.records.project.JoiningQRCode; import com.tecknobit.novacore.records.project.Project; import com.tecknobit.novacore.records.release.Release; @@ -20,10 +20,10 @@ import java.util.HashMap; import java.util.List; -import static com.tecknobit.nova.Launcher.generateIdentifier; +import static com.tecknobit.equinox.environment.controllers.EquinoxController.generateIdentifier; import static com.tecknobit.novacore.records.NovaItem.IDENTIFIER_KEY; -import static com.tecknobit.novacore.records.User.NAME_KEY; -import static com.tecknobit.novacore.records.User.PROJECTS_KEY; +import static com.tecknobit.novacore.records.NovaUser.NAME_KEY; +import static com.tecknobit.novacore.records.NovaUser.PROJECTS_KEY; import static com.tecknobit.novacore.records.project.Project.AUTHOR_KEY; import static com.tecknobit.novacore.records.project.Project.LOGO_URL_KEY; import static java.lang.System.currentTimeMillis; @@ -32,10 +32,10 @@ * The {@code ProjectsHelper} class is useful to manage all the project database operations * * @author N7ghtm4r3 - Tecknobit - * @see ResourcesManager + * @see NovaResourcesManager */ @Service -public class ProjectsHelper implements ResourcesManager { +public class ProjectsHelper implements NovaResourcesManager { /** * {@code projectsRepository} instance for the projects repository @@ -62,7 +62,7 @@ public class ProjectsHelper implements ResourcesManager { private NotificationsRepository notificationsRepository; /** - * Method to get the project of a {@link User} + * Method to get the project of a {@link NovaUser} * * @param userId: the user identifier * @return the projects list, also where the user is the author, as {@link HashMap} of {@link String} and {@link List} @@ -121,7 +121,7 @@ public Project getProject(String userId, String projectId) { * @param createJoinQRCode: whether create a textual join code * @return the textual join code, if created, as {@link String} */ - public String createJoiningQrcode(String QRCodeId, String projectId, List membersEmails, User.Role role, + public String createJoiningQrcode(String QRCodeId, String projectId, List membersEmails, NovaUser.Role role, boolean createJoinQRCode) { String joinCode = null; if(createJoinQRCode) @@ -230,9 +230,9 @@ public void deleteProject(String authorId, Project project) { for (Release release : project.getReleases()) releasesHelper.deleteRelease(null, null, release); projectsRepository.removeAllMembers(projectId); - List members = project.getProjectMembers(); + List members = project.getProjectMembers(); members.add(project.getAuthor()); - for(User member : members) { + for(NovaUser member : members) { String memberId = member.getId(); if(!memberId.equals(authorId)) { notificationsRepository.insertProjectDeletedNotification( diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/ReleasesHelper.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/ReleasesHelper.java index 7bb061d..8887582 100644 --- a/backend/src/main/java/com/tecknobit/nova/helpers/services/ReleasesHelper.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/services/ReleasesHelper.java @@ -1,13 +1,13 @@ package com.tecknobit.nova.helpers.services; import com.tecknobit.apimanager.annotations.Wrapper; -import com.tecknobit.nova.helpers.resources.ResourcesManager; +import com.tecknobit.nova.helpers.resources.NovaResourcesManager; import com.tecknobit.nova.helpers.services.repositories.releaseutils.NotificationsRepository; import com.tecknobit.nova.helpers.services.repositories.releaseutils.ReleaseEventsRepository; import com.tecknobit.nova.helpers.services.repositories.releaseutils.ReleaseTagRepository; import com.tecknobit.nova.helpers.services.repositories.releaseutils.ReleasesRepository; import com.tecknobit.novacore.records.NovaNotification; -import com.tecknobit.novacore.records.User; +import com.tecknobit.novacore.records.NovaUser; import com.tecknobit.novacore.records.project.Project; import com.tecknobit.novacore.records.release.Release; import com.tecknobit.novacore.records.release.Release.ReleaseStatus; @@ -24,17 +24,17 @@ import java.util.ArrayList; import java.util.List; -import static com.tecknobit.nova.Launcher.generateIdentifier; +import static com.tecknobit.equinox.environment.controllers.EquinoxController.generateIdentifier; import static com.tecknobit.novacore.records.release.Release.ReleaseStatus.*; /** * The {@code ReleasesHelper} class is useful to manage all the release database operations * * @author N7ghtm4r3 - Tecknobit - * @see ResourcesManager + * @see NovaResourcesManager */ @Service -public class ReleasesHelper implements ResourcesManager { +public class ReleasesHelper implements NovaResourcesManager { /** * {@code releasesRepository} instance for the releases repository @@ -78,9 +78,9 @@ public void addRelease(String requesterUser, Project project, String releaseId, project.getId(), releaseNotesContent ); - List members = project.getProjectMembers(); + List members = project.getProjectMembers(); members.add(project.getAuthor()); - for(User member : members) { + for(NovaUser member : members) { String memberId = member.getId(); if(!memberId.equals(requesterUser)) { notificationsRepository.insertNotification( @@ -320,9 +320,9 @@ private void setReleaseStatus(String requesterUser, Project project, String rele status.name() ); } - List members = project.getProjectMembers(); + List members = project.getProjectMembers(); members.add(project.getAuthor()); - for(User member : members) { + for(NovaUser member : members) { String memberId = member.getId(); if(!memberId.equals(requesterUser)) { notificationsRepository.insertNotification( @@ -360,9 +360,9 @@ public void deleteRelease(String requesterUser, Project project, Release release deleteReportResource(releaseId); releasesRepository.deleteRelease(releaseId); if(project != null) { - List members = project.getProjectMembers(); + List members = project.getProjectMembers(); members.add(project.getAuthor()); - for (User member : project.getProjectMembers()) { + for (NovaUser member : project.getProjectMembers()) { String memberId = member.getId(); if(!memberId.equals(requesterUser)) { notificationsRepository.insertReleaseDeletedNotification( diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/UsersHelper.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/UsersHelper.java deleted file mode 100644 index 0c9af10..0000000 --- a/backend/src/main/java/com/tecknobit/nova/helpers/services/UsersHelper.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.tecknobit.nova.helpers.services; - -import com.tecknobit.apimanager.apis.APIRequest; -import com.tecknobit.nova.helpers.resources.ResourcesManager; -import com.tecknobit.nova.helpers.services.repositories.UsersRepository; -import com.tecknobit.novacore.records.User; -import com.tecknobit.novacore.records.User.Role; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; - -import java.io.IOException; -import java.security.NoSuchAlgorithmException; - -import static com.tecknobit.apimanager.apis.APIRequest.SHA256_ALGORITHM; -import static java.lang.System.currentTimeMillis; - -/** - * The {@code UsersHelper} class is useful to manage all the user database operations - * - * @author N7ghtm4r3 - Tecknobit - * @see ResourcesManager - */ -@Service -public class UsersHelper implements ResourcesManager { - - /** - * {@code usersRepository} instance for the users repository - */ - @Autowired - private UsersRepository usersRepository; - - /** - * Method to sign up a new user in the Nova's system - * - * @param id: the identifier of the user - * @param token: the token of the user - * @param name: the name of the user - * @param surname: the surname of the user - * @param email: the email of the user - * @param password: the password of the user - * @param language: the language of the user - * @param role: the role of the user - */ - public void signUpUser(String id, String token, String name, String surname, String email, String password, - String language, Role role) throws NoSuchAlgorithmException { - usersRepository.save(new User( - id, - token, - name, - surname, - email, - hash(password), - language, - role - )); - } - - /** - * Method to sign in an existing user - * - * @param email: the email of the user - * @param password: the password of the user - * - * @return the authenticated user as {@link User} if the credentials inserted were correct - */ - public User signInUser(String email, String password) throws NoSuchAlgorithmException { - User user = usersRepository.findUserByEmail(email); - if(user != null && user.getPassword().equals(hash(password))) - return user; - return null; - } - - /** - * Method to change the profile pic of the {@link User} - * - * @param profilePic: the profile pic resource - * @param userId: the identifier of the user - */ - public String changeProfilePic(MultipartFile profilePic, String userId) throws IOException { - String profilePicPath = createProfileResource(profilePic, userId + currentTimeMillis()); - usersRepository.changeProfilePic(profilePicPath, userId); - deleteProfileResource(userId); - saveResource(profilePic, profilePicPath); - return profilePicPath; - } - - /** - * Method to change the email of the {@link User} - * - * @param newEmail: the new email of the user - * @param userId: the identifier of the user - */ - public void changeEmail(String newEmail, String userId) { - usersRepository.changeEmail(newEmail, userId); - } - - /** - * Method to change the password of the {@link User} - * - * @param newPassword: the new password of the user - * @param userId: the identifier of the user - */ - public void changePassword(String newPassword, String userId) throws NoSuchAlgorithmException { - usersRepository.changePassword(hash(newPassword), userId); - } - - /** - * Method to change the language of the {@link User} - * - * @param newLanguage: the new language of the user - * @param userId: the identifier of the user - */ - public void changeLanguage(String newLanguage, String userId) { - usersRepository.changeLanguage(newLanguage, userId); - } - - /** - * Method to delete a user - * @param id: the identifier of the user to delete - */ - public void deleteUser(String id) { - usersRepository.deleteById(id); - deleteProfileResource(id); - } - - /** - * Method to hash a sensitive user data - * - * @param secret: the user value to hash - * @throws NoSuchAlgorithmException when the hash of the user value fails - */ - private String hash(String secret) throws NoSuchAlgorithmException { - return APIRequest.base64Digest(secret, APIRequest.SHA256_ALGORITHM); - } - -} diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/UsersRepository.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/UsersRepository.java deleted file mode 100644 index 6c0d27f..0000000 --- a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/UsersRepository.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.tecknobit.nova.helpers.services.repositories; - -import com.tecknobit.novacore.records.User; -import jakarta.transaction.Transactional; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Modifying; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; -import org.springframework.stereotype.Repository; -import org.springframework.stereotype.Service; - -import static com.tecknobit.novacore.records.User.*; - -/** - * The {@code ReleaseTagRepository} interface is useful to manage the queries for the users operations - * - * @author N7ghtm4r3 - Tecknobit - * @see JpaRepository - * @see User - */ -@Service -@Repository -public interface UsersRepository extends JpaRepository { - - /** - * Method to execute the query to find a {@link User} by email field - * - * @param email: the email to find the user - * @return the user, if exists, as {@link User} - */ - @Query( - value = "SELECT * FROM " + USERS_KEY + " WHERE " + EMAIL_KEY + "=:" + EMAIL_KEY, - nativeQuery = true - ) - User findUserByEmail( - @Param(EMAIL_KEY) String email - ); - - /** - * Method to execute the query to change the profile pic of the {@link User} - * - * @param profilePicUrl: the profile pic formatted as url - * @param id: the identifier of the user - */ - @Modifying(clearAutomatically = true) - @Transactional - @Query( - value = "UPDATE " + USERS_KEY + " SET " + PROFILE_PIC_URL_KEY + "=:" + PROFILE_PIC_URL_KEY + " WHERE " - + IDENTIFIER_KEY + "=:" + IDENTIFIER_KEY, - nativeQuery = true - ) - void changeProfilePic( - @Param(PROFILE_PIC_URL_KEY) String profilePicUrl, - @Param(IDENTIFIER_KEY) String id - ); - - /** - * Method to execute the query to change the email of the {@link User} - * - * @param newEmail: the new email of the user - * @param id: the identifier of the user - */ - @Modifying(clearAutomatically = true) - @Transactional - @Query( - value = "UPDATE " + USERS_KEY + " SET " + EMAIL_KEY + "=:" + EMAIL_KEY + " WHERE " - + IDENTIFIER_KEY + "=:" + IDENTIFIER_KEY, - nativeQuery = true - ) - void changeEmail( - @Param(EMAIL_KEY) String newEmail, - @Param(IDENTIFIER_KEY) String id - ); - - /** - * Method to execute the query to change the password of the {@link User} - * - * @param newPassword: the new password of the user - * @param id: the identifier of the user - */ - @Modifying(clearAutomatically = true) - @Transactional - @Query( - value = "UPDATE " + USERS_KEY + " SET " + PASSWORD_KEY + "=:" + PASSWORD_KEY + " WHERE " - + IDENTIFIER_KEY + "=:" + IDENTIFIER_KEY, - nativeQuery = true - ) - void changePassword( - @Param(PASSWORD_KEY) String newPassword, - @Param(IDENTIFIER_KEY) String id - ); - - /** - * Method to execute the query to change the language of the {@link User} - * - * @param newLanguage: the new language of the user - * @param id: the identifier of the user - */ - @Modifying(clearAutomatically = true) - @Transactional - @Query( - value = "UPDATE " + USERS_KEY + " SET " + LANGUAGE_KEY + "=:" + LANGUAGE_KEY + " WHERE " - + IDENTIFIER_KEY + "=:" + IDENTIFIER_KEY, - nativeQuery = true - ) - void changeLanguage( - @Param(LANGUAGE_KEY) String newLanguage, - @Param(IDENTIFIER_KEY) String id - ); - -} diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/JoiningQRCodeRepository.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/JoiningQRCodeRepository.java index 95cd445..d33fa21 100644 --- a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/JoiningQRCodeRepository.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/JoiningQRCodeRepository.java @@ -10,7 +10,7 @@ import org.springframework.stereotype.Service; import static com.tecknobit.novacore.records.NovaItem.IDENTIFIER_KEY; -import static com.tecknobit.novacore.records.User.ROLE_KEY; +import static com.tecknobit.novacore.records.NovaUser.ROLE_KEY; import static com.tecknobit.novacore.records.project.JoiningQRCode.JOINING_QRCODES_TABLE; import static com.tecknobit.novacore.records.project.JoiningQRCode.JOIN_CODE_KEY; import static com.tecknobit.novacore.records.project.Project.PROJECT_IDENTIFIER_KEY; diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/ProjectsRepository.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/ProjectsRepository.java index 4628405..13fef4e 100644 --- a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/ProjectsRepository.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/ProjectsRepository.java @@ -11,8 +11,10 @@ import java.util.List; +import static com.tecknobit.equinox.environment.records.EquinoxUser.NAME_KEY; import static com.tecknobit.novacore.records.NovaItem.IDENTIFIER_KEY; -import static com.tecknobit.novacore.records.User.*; +import static com.tecknobit.novacore.records.NovaUser.MEMBER_IDENTIFIER_KEY; +import static com.tecknobit.novacore.records.NovaUser.PROJECTS_KEY; import static com.tecknobit.novacore.records.project.Project.*; /** diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/NotificationsRepository.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/NotificationsRepository.java index e3872fd..25cc9dc 100644 --- a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/NotificationsRepository.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/NotificationsRepository.java @@ -15,7 +15,7 @@ import static com.tecknobit.novacore.records.NovaItem.IDENTIFIER_KEY; import static com.tecknobit.novacore.records.NovaNotification.IS_SENT_KEY; import static com.tecknobit.novacore.records.NovaNotification.NOTIFICATIONS_KEY; -import static com.tecknobit.novacore.records.User.USER_KEY; +import static com.tecknobit.novacore.records.NovaUser.USER_KEY; import static com.tecknobit.novacore.records.project.Project.LOGO_URL_KEY; import static com.tecknobit.novacore.records.release.Release.*; diff --git a/backend/src/main/resources/resources.mantis b/backend/src/main/resources/resources.mantis index 6416143..965bf99 100644 --- a/backend/src/main/resources/resources.mantis +++ b/backend/src/main/resources/resources.mantis @@ -6,7 +6,17 @@ "latest_timeline_message_key": "Release promoted as latest!", "creation_date_key": "Date of creation:", "alpha_timeline_message_key": "Asset has been promoted to Alpha version", - "new_asset_has_been_uploaded_key": "New asset has been uploaded" + "new_asset_has_been_uploaded_key": "New asset has been uploaded", + "connection_error_message_key": "Server is temporarily unavailable", + "wrong_procedure_key": "Wrong procedure", + "wrong_password_key": "Password is not valid", + "wrong_currency_key": "Currency is not supported", + "operation_executed_successfully_key": "Operation executed successfully", + "wrong_name_key": "Name is not valid", + "wrong_surname_key": "Surname is not valid", + "wrong_language_key": "Language is not supported", + "wrong_email_key": "Email is not valid", + "not_authorized_key": "Not authorized or wrong details" }, "ignored_resources": {}, "it": { @@ -16,6 +26,52 @@ "latest_timeline_message_key": "Release promosso come ultimo!", "creation_date_key": "Data creazione:", "alpha_timeline_message_key": "L'asset e' stato promosso alla versione Alpha", - "new_asset_has_been_uploaded_key": "Un nuovo asset e' stato caricato" + "new_asset_has_been_uploaded_key": "Un nuovo asset e' stato caricato", + "connection_error_message_key": "Il server è temporaneamente non disponibile", + "wrong_procedure_key": "Procedura sbagliata", + "wrong_password_key": "Password non valida", + "wrong_currency_key": "Valuta non supportata", + "operation_executed_successfully_key": "Operazione eseguita con successo", + "wrong_name_key": "Nome non valido", + "wrong_surname_key": "Cognome non valido", + "wrong_language_key": "Lingua non supportata", + "wrong_email_key": "Email non valida", + "not_authorized_key": "Non autorizzat o dati errati" + }, + "fr": { + "new_asset_uploaded_key": "Nouvel actif téléchargé", + "asset_has_been_approved_key": "L'actif a été approuvé", + "beta_timeline_message_key": "L'élément a été promu en version bêta", + "latest_timeline_message_key": "La version est promue comme la plus récente !", + "creation_date_key": "Date de création :", + "alpha_timeline_message_key": "L'élément a été promu en version Alpha", + "connection_error_message_key": "Le serveur est temporairement indisponible", + "wrong_procedure_key": "Mauvaise procadure", + "wrong_password_key": "Mot de passe n'est pas valide", + "wrong_currency_key": "La monnaie n'est pas prise en charge", + "operation_executed_successfully_key": "Oparation exacutae avec succas", + "wrong_name_key": "Le nom n'est pas valide", + "wrong_surname_key": "Le nom n'est pas valide", + "wrong_language_key": "La langue n'est pas prise en charge", + "wrong_email_key": "Le courriel n'est pas valide", + "not_authorized_key": "Non autorisa ou faux datails" + }, + "es": { + "new_asset_uploaded_key": "Nuevo recurso cargado", + "asset_has_been_approved_key": "El activo ha sido aprobado", + "beta_timeline_message_key": "El recurso ha sido ascendido a la versión Beta", + "latest_timeline_message_key": "¡Lanzamiento promocionado como el más reciente!", + "creation_date_key": "Fecha de creación:", + "alpha_timeline_message_key": "El activo ha sido ascendido a la versión Alpha", + "connection_error_message_key": "El servidor no està disponible temporalmente", + "wrong_procedure_key": "Procedimiento incorrecto", + "wrong_password_key": "La contraseña no es valida", + "wrong_currency_key": "No se admite la moneda", + "operation_executed_successfully_key": "Operacia ejecutada con axito", + "wrong_name_key": "El nombre no es valido", + "wrong_surname_key": "El apellido no es valido", + "wrong_language_key": "El idioma no es compatible", + "wrong_email_key": "El correo electrinico no es valido", + "not_authorized_key": "No autorizados o datos incorrectos" } -} \ No newline at end of file +} diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 40452aa..78e720c 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -20,7 +20,9 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-data-jpa:3.2.3") implementation("org.springframework:spring-web:6.1.5") implementation("com.fasterxml.jackson.core:jackson-databind:2.15.4") - implementation("com.github.N7ghtm4r3:APIManager:2.2.1") + implementation("com.github.N7ghtm4r3:APIManager:2.2.4") + implementation("com.github.N7ghtm4r3:Equinox:1.0.3") + implementation("com.squareup.okhttp3:okhttp:4.12.0") implementation("org.json:json:20230227") implementation(kotlin("stdlib-jdk8")) } diff --git a/core/src/main/java/com/tecknobit/novacore/helpers/LocalSessionUtils.java b/core/src/main/java/com/tecknobit/novacore/helpers/LocalSessionUtils.java index 8986f76..2ede9ae 100644 --- a/core/src/main/java/com/tecknobit/novacore/helpers/LocalSessionUtils.java +++ b/core/src/main/java/com/tecknobit/novacore/helpers/LocalSessionUtils.java @@ -7,7 +7,7 @@ import static com.tecknobit.novacore.helpers.LocalSessionUtils.NovaSession.HOST_ADDRESS_KEY; import static com.tecknobit.novacore.helpers.LocalSessionUtils.NovaSession.IS_ACTIVE_SESSION_KEY; import static com.tecknobit.novacore.records.NovaItem.IDENTIFIER_KEY; -import static com.tecknobit.novacore.records.User.*; +import static com.tecknobit.novacore.records.NovaUser.*; /** * The {@code LocalSessionUtils} class is useful to manage the local sessions of the user, so manage the credentials @@ -34,7 +34,7 @@ public interface LocalSessionUtils { "CREATE TABLE IF NOT EXISTS " + SESSIONS_TABLE + " (" + IDENTIFIER_KEY + " VARCHAR(32) PRIMARY KEY,\n" + TOKEN_KEY + " VARCHAR(32) NOT NULL,\n" + - PROFILE_PIC_URL_KEY + " TEXT NOT NULL,\n" + + PROFILE_PIC_KEY + " TEXT NOT NULL,\n" + NAME_KEY + " VARCHAR(20) NOT NULL,\n" + SURNAME_KEY + " VARCHAR(30) NOT NULL,\n" + EMAIL_KEY + " VARCHAR(75) NOT NULL,\n" + @@ -118,7 +118,7 @@ default void changeActiveSession(String id) { */ @Wrapper default void changeProfilePic(String profilePic) { - changeSessionValue(PROFILE_PIC_URL_KEY, getActiveSession().hostAddress + "/" + profilePic); + changeSessionValue(PROFILE_PIC_KEY, getActiveSession().hostAddress + "/" + profilePic); } /** diff --git a/core/src/main/java/com/tecknobit/novacore/records/NovaNotification.java b/core/src/main/java/com/tecknobit/novacore/records/NovaNotification.java index 699792c..7907ecb 100644 --- a/core/src/main/java/com/tecknobit/novacore/records/NovaNotification.java +++ b/core/src/main/java/com/tecknobit/novacore/records/NovaNotification.java @@ -15,7 +15,7 @@ import java.util.List; import static com.tecknobit.novacore.records.NovaNotification.NOTIFICATIONS_KEY; -import static com.tecknobit.novacore.records.User.*; +import static com.tecknobit.novacore.records.NovaUser.*; import static com.tecknobit.novacore.records.project.Project.LOGO_URL_KEY; import static com.tecknobit.novacore.records.release.Release.*; @@ -63,7 +63,7 @@ public class NovaNotification extends NovaItem { "handler" }) @OnDelete(action = OnDeleteAction.CASCADE) - private final User user; + private final NovaUser user; /** * {@code releaseId} the identifier of the related release @@ -149,7 +149,7 @@ public NovaNotification(JSONObject jNotification) { * @param isSent: whether the notification has been sent already before * */ - public NovaNotification(String id, String projectLogo, User user, String releaseId, ReleaseStatus status, + public NovaNotification(String id, String projectLogo, NovaUser user, String releaseId, ReleaseStatus status, String releaseVersion, boolean isSent) { super(id); this.projectLogo = projectLogo; @@ -186,9 +186,9 @@ public String getProjectId() { * Method to get {@link #user} instance
    * No-any params required * - * @return {@link #user} instance as {@link User} + * @return {@link #user} instance as {@link NovaUser} */ - public User getUser() { + public NovaUser getUser() { return user; } diff --git a/core/src/main/java/com/tecknobit/novacore/records/User.java b/core/src/main/java/com/tecknobit/novacore/records/NovaUser.java similarity index 55% rename from core/src/main/java/com/tecknobit/novacore/records/User.java rename to core/src/main/java/com/tecknobit/novacore/records/NovaUser.java index bf13802..ebd1eb5 100644 --- a/core/src/main/java/com/tecknobit/novacore/records/User.java +++ b/core/src/main/java/com/tecknobit/novacore/records/NovaUser.java @@ -1,9 +1,9 @@ package com.tecknobit.novacore.records; -import com.fasterxml.jackson.annotation.JsonGetter; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.tecknobit.apimanager.annotations.Returner; +import com.tecknobit.equinox.environment.records.EquinoxUser; import com.tecknobit.novacore.records.project.Project; import jakarta.persistence.*; import org.json.JSONArray; @@ -19,90 +19,14 @@ import static jakarta.persistence.EnumType.STRING; /** - * The {@code User} class is useful to represent a Nova's user + * The {@code NovaUser} class is useful to represent a Nova's user * * @author N7ghtm4r3 - Tecknobit * @see NovaItem * @see Serializable */ @Entity -@Table(name = User.USERS_KEY) -public class User extends NovaItem { - - /** - * {@code DEFAULT_PROFILE_PIC} the default profile pic path when the user has not set own image - */ - public static final String DEFAULT_PROFILE_PIC = "profiles/defProfilePic.png"; - - /** - * {@code USER_KEY} the key for the "user" field - */ - public static final String USER_KEY = "user"; - - /** - * {@code MEMBER_IDENTIFIER_KEY} the key for the "member_id" field - */ - public static final String MEMBER_IDENTIFIER_KEY = "member_id"; - - /** - * {@code SERVER_SECRET_KEY} the key for the "server_secret" field - */ - public static final String SERVER_SECRET_KEY = "server_secret"; - - /** - * {@code USERS_KEY} the key for the "users" field - */ - public static final String USERS_KEY = "users"; - - /** - * {@code TOKEN_KEY} the key for the "token" field - */ - public static final String TOKEN_KEY = "token"; - - /** - * {@code PASSWORD_KEY} the key for the "password" field - */ - public static final String PASSWORD_KEY = "password"; - - /** - * {@code AUTHORED_PROJECTS_KEY} the key for the "authoredProjects" field - */ - public static final String AUTHORED_PROJECTS_KEY = "authoredProjects"; - - /** - * {@code PROJECTS_KEY} the key for the "projects" field - */ - public static final String PROJECTS_KEY = "projects"; - - /** - * {@code NAME_KEY} the key for the "name" field - */ - public static final String NAME_KEY = "name"; - - /** - * {@code SURNAME_KEY} the key for the "surname" field - */ - public static final String SURNAME_KEY = "surname"; - - /** - * {@code EMAIL_KEY} the key for the "email" field - */ - public static final String EMAIL_KEY = "email"; - - /** - * {@code PROFILE_PIC_URL_KEY} the key for the "profile_pic_url" field - */ - public static final String PROFILE_PIC_URL_KEY = "profile_pic_url"; - - /** - * {@code LANGUAGE_KEY} the key for the "language" field - */ - public static final String LANGUAGE_KEY = "language"; - - /** - * {@code ROLE_KEY} the key for the "role" field - */ - public static final String ROLE_KEY = "role"; +public class NovaUser extends EquinoxUser { /** * {@code Role} list of available roles for a user @@ -124,51 +48,29 @@ public enum Role { } /** - * {@code name} the name of the user - */ - @Column(name = NAME_KEY) - private final String name; - - /** - * {@code surname} the surname of the user + * {@code USER_KEY} the key for the "user" field */ - @Column(name = SURNAME_KEY) - private final String surname; + public static final String USER_KEY = "user"; /** - * {@code email} the email of the user + * {@code MEMBER_IDENTIFIER_KEY} the key for the "member_id" field */ - @Column( - name = EMAIL_KEY, - unique = true - ) - private final String email; + public static final String MEMBER_IDENTIFIER_KEY = "member_id"; /** - * {@code profilePicUrl} the profile pic of the user formatted as url + * {@code AUTHORED_PROJECTS_KEY} the key for the "authoredProjects" field */ - @Column( - name = PROFILE_PIC_URL_KEY, - columnDefinition = "TEXT DEFAULT '" + DEFAULT_PROFILE_PIC + "'", - insertable = false - ) - private final String profilePicUrl; + public static final String AUTHORED_PROJECTS_KEY = "authoredProjects"; /** - * {@code token} the token which the user is allowed to operate on server + * {@code PROJECTS_KEY} the key for the "projects" field */ - @Column( - name = TOKEN_KEY, - unique = true - ) - private final String token; + public static final String PROJECTS_KEY = "projects"; /** - * {@code password} the password of the user + * {@code ROLE_KEY} the key for the "role" field */ - @Column(name = PASSWORD_KEY) - @JsonIgnore - private final String password; + public static final String ROLE_KEY = "role"; /** * {@code authoredProjects} list of projects which user is the author @@ -191,12 +93,6 @@ public enum Role { ) private final List projects; - /** - * {@code language} the language selected by the user - */ - @Column(name = LANGUAGE_KEY) - private final String language; - /** * {@code role} the role of the user on the server * @@ -223,39 +119,32 @@ public enum Role { private final List notifications; /** - * Constructor to init the {@link User} class
    + * Constructor to init the {@link NovaUser} class
    * * No-any params required * * @apiNote empty constructor required */ - public User() { + public NovaUser() { this(null, null, null, null, null, null, null, List.of(), List.of(), null, null, List.of()); } /** - * Constructor to init the {@link User} class + * Constructor to init the {@link NovaUser} class * * @param jUser: user details formatted as JSON * */ - public User(JSONObject jUser) { + public NovaUser(JSONObject jUser) { super(jUser); - name = hItem.getString(NAME_KEY); - surname = hItem.getString(SURNAME_KEY); - email = hItem.getString(EMAIL_KEY); - profilePicUrl = hItem.getString(PROFILE_PIC_URL_KEY); - token = hItem.getString(TOKEN_KEY); - password = hItem.getString(PASSWORD_KEY); authoredProjects = null; projects = Project.returnProjectsList(hItem.getJSONArray(PROJECTS_KEY)); - language = hItem.getString(LANGUAGE_KEY); role = Role.valueOf(hItem.getString(ROLE_KEY)); notifications = NovaNotification.returnNotificationsList(hItem.getJSONArray(NOTIFICATIONS_KEY)); } /** - * Constructor to init the {@link User} class + * Constructor to init the {@link NovaUser} class * * @param id: identifier of the user * @param token:{@code token} the token which the user is allowed to operate on server @@ -266,13 +155,13 @@ public User(JSONObject jUser) { * @param language:{@code language} the language selected by the user * @param role:{@code role} the role of the user on the server @apiNote this value cannot change on server, this means when the user execute the authentication on the server with a role it will be ever the same */ - public User(String id, String token, String name, String surname, String email, String password, String language, - Role role) { + public NovaUser(String id, String token, String name, String surname, String email, String password, String language, + Role role) { this(id, name, surname, email, null, token, password, List.of(), List.of(), language, role, List.of()); } /** - * Constructor to init the {@link User} class + * Constructor to init the {@link NovaUser} class * * * @param id: identifier of the user @@ -288,84 +177,16 @@ public User(String id, String token, String name, String surname, String email, * @param role:{@code role} the role of the user on the server @apiNote this value cannot change on server, this means when the user execute the authentication on the server with a role it will be ever the same * @param notifications:{@code NovaNotification} the list of the notifications which belong to the user */ - public User(String id, String name, String surname, String email, String profilePicUrl, String token, String password, - List authoredProjects, List projects, String language, Role role, - List notifications) { - super(id); - this.name = name; - this.surname = surname; - this.email = email; - this.profilePicUrl = profilePicUrl; - this.token = token; - this.password = password; + public NovaUser(String id, String name, String surname, String email, String profilePicUrl, String token, String password, + List authoredProjects, List projects, String language, Role role, + List notifications) { + super(id, token, name, surname, email, password, language); this.authoredProjects = authoredProjects; this.projects = projects; - this.language = language; this.role = role; this.notifications = notifications; } - /** - * Method to get {@link #name} instance
    - * No-any params required - * - * @return {@link #name} instance as {@link String} - */ - public String getName() { - return name; - } - - /** - * Method to get {@link #surname} instance
    - * No-any params required - * - * @return {@link #surname} instance as {@link String} - */ - public String getSurname() { - return surname; - } - - /** - * Method to get {@link #email} instance
    - * No-any params required - * - * @return {@link #email} instance as {@link String} - */ - public String getEmail() { - return email; - } - - /** - * Method to get {@link #profilePicUrl} instance
    - * No-any params required - * - * @return {@link #profilePicUrl} instance as {@link String} - */ - @JsonGetter(PROFILE_PIC_URL_KEY) - public String getProfilePicUrl() { - return profilePicUrl; - } - - /** - * Method to get {@link #token} instance
    - * No-any params required - * - * @return {@link #token} instance as {@link String} - */ - public String getToken() { - return token; - } - - /** - * Method to get {@link #password} instance
    - * No-any params required - * - * @return {@link #password} instance as {@link String} - */ - public String getPassword() { - return password; - } - /** * Method to get {@link #projects} instance
    * No-any params required @@ -376,16 +197,6 @@ public List getProjects() { return projects; } - /** - * Method to get {@link #language} instance
    - * No-any params required - * - * @return {@link #language} instance as {@link String} - */ - public String getLanguage() { - return language; - } - /** * Method to get {@link #role} instance
    * No-any params required @@ -429,16 +240,16 @@ public boolean isCustomer() { } /** - * Method to assemble and return a {@link User} instance + * Method to assemble and return a {@link NovaUser} instance * * @param jUser: user details formatted as JSON * - * @return the user instance as {@link User} + * @return the user instance as {@link NovaUser} */ @Returner - public static User returnUserInstance(JSONObject jUser) { + public static NovaUser returnUserInstance(JSONObject jUser) { if(jUser != null) - return new User(jUser); + return new NovaUser(jUser); return null; } @@ -447,14 +258,14 @@ public static User returnUserInstance(JSONObject jUser) { * * @param jUsers: users list details formatted as JSON * - * @return the users list as {@link List} of {@link User} + * @return the users list as {@link List} of {@link NovaUser} */ @Returner - public static List returnUsersList(JSONArray jUsers) { - List users = new ArrayList<>(); + public static List returnUsersList(JSONArray jUsers) { + List users = new ArrayList<>(); if(jUsers != null) for (int j = 0; j < jUsers.length(); j++) - users.add(new User(jUsers.getJSONObject(j))); + users.add(new NovaUser(jUsers.getJSONObject(j))); return users; } diff --git a/core/src/main/java/com/tecknobit/novacore/records/project/JoiningQRCode.java b/core/src/main/java/com/tecknobit/novacore/records/project/JoiningQRCode.java index aacd990..3c5da7e 100644 --- a/core/src/main/java/com/tecknobit/novacore/records/project/JoiningQRCode.java +++ b/core/src/main/java/com/tecknobit/novacore/records/project/JoiningQRCode.java @@ -2,7 +2,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.tecknobit.novacore.records.NovaItem; -import com.tecknobit.novacore.records.User.Role; +import com.tecknobit.novacore.records.NovaUser.Role; import jakarta.persistence.*; import org.hibernate.annotations.OnDelete; import org.hibernate.annotations.OnDeleteAction; @@ -12,7 +12,7 @@ import java.util.List; import java.util.concurrent.TimeUnit; -import static com.tecknobit.novacore.records.User.ROLE_KEY; +import static com.tecknobit.novacore.records.NovaUser.ROLE_KEY; import static com.tecknobit.novacore.records.project.Project.PROJECT_IDENTIFIER_KEY; import static com.tecknobit.novacore.records.project.Project.PROJECT_MEMBERS_KEY; import static com.tecknobit.novacore.records.release.Release.CREATION_DATE_KEY; diff --git a/core/src/main/java/com/tecknobit/novacore/records/project/Project.java b/core/src/main/java/com/tecknobit/novacore/records/project/Project.java index 9df7032..8df30ea 100644 --- a/core/src/main/java/com/tecknobit/novacore/records/project/Project.java +++ b/core/src/main/java/com/tecknobit/novacore/records/project/Project.java @@ -7,7 +7,7 @@ import com.tecknobit.novacore.records.NotificationsTarget; import com.tecknobit.novacore.records.NovaItem; import com.tecknobit.novacore.records.NovaNotification; -import com.tecknobit.novacore.records.User; +import com.tecknobit.novacore.records.NovaUser; import com.tecknobit.novacore.records.release.Release; import jakarta.persistence.*; import org.hibernate.annotations.Fetch; @@ -22,7 +22,7 @@ import java.util.List; import static com.tecknobit.novacore.records.NovaNotification.NOTIFICATIONS_KEY; -import static com.tecknobit.novacore.records.User.*; +import static com.tecknobit.novacore.records.NovaUser.*; import static com.tecknobit.novacore.records.release.Release.RELEASES_KEY; /** @@ -100,7 +100,7 @@ public class Project extends NovaItem implements NotificationsTarget { "handler" }) @OnDelete(action = OnDeleteAction.CASCADE) - private final User author; + private final NovaUser author; /** * {@code logoUrl} the logo of the project formatted as url @@ -139,7 +139,7 @@ public class Project extends NovaItem implements NotificationsTarget { "hibernateLazyInitializer", "handler" }) - private final List projectMembers; + private final List projectMembers; /** * {@code releases} the releases of the project @@ -185,7 +185,7 @@ public Project(JSONObject jProject) { author = returnUserInstance(hItem.getJSONObject(AUTHOR_KEY)); logoUrl = hItem.getString(LOGO_URL_KEY); name = hItem.getString(PROJECT_NAME_KEY); - projectMembers = User.returnUsersList(hItem.getJSONArray(PROJECT_MEMBERS_KEY)); + projectMembers = NovaUser.returnUsersList(hItem.getJSONArray(PROJECT_MEMBERS_KEY)); releases = Release.returnReleasesList(hItem.getJSONArray(RELEASES_KEY)); joiningQRCodes = null; } @@ -204,7 +204,7 @@ public Project(JSONObject jProject) { * @apiNote this is useful for the server-side, so for the clients will be ever hidden * */ - public Project(String id, User author, String logoUrl, String name, List projectMembers, + public Project(String id, NovaUser author, String logoUrl, String name, List projectMembers, List releases, List joiningQRCodes) { super(id); this.author = author; @@ -219,9 +219,9 @@ public Project(String id, User author, String logoUrl, String name, List p * Method to get {@link #author} instance
    * No-any params required * - * @return {@link #author} instance as {@link User} + * @return {@link #author} instance as {@link NovaUser} */ - public User getAuthor() { + public NovaUser getAuthor() { return author; } @@ -250,9 +250,9 @@ public String getName() { * Method to get {@link #projectMembers} instance
    * No-any params required * - * @return {@link #projectMembers} instance as {@link List} of {@link User} + * @return {@link #projectMembers} instance as {@link List} of {@link NovaUser} */ - public List getProjectMembers() { + public List getProjectMembers() { return projectMembers; } @@ -291,7 +291,7 @@ public List getJoiningQRCodes() { } /** - * Method to get whether a {@link User#MEMBER_IDENTIFIER_KEY} is the author of the current project + * Method to get whether a {@link NovaUser#MEMBER_IDENTIFIER_KEY} is the author of the current project * * @param memberId: the member identifier to check * @@ -304,7 +304,7 @@ public boolean amITheProjectAuthor(String memberId) { } /** - * Method to get whether a {@link User#MEMBER_IDENTIFIER_KEY} is a member of the checked project + * Method to get whether a {@link NovaUser#MEMBER_IDENTIFIER_KEY} is a member of the checked project * * @param memberId: the member identifier to check * @@ -312,7 +312,7 @@ public boolean amITheProjectAuthor(String memberId) { */ public boolean hasMemberId(String memberId) { if(memberId != null) { - for (User member : projectMembers) + for (NovaUser member : projectMembers) if(member.getId().equals(memberId)) return true; } @@ -324,11 +324,11 @@ public boolean hasMemberId(String memberId) { * * @param memberId: the identifier of the member to get * - * @return the member as {@link User} if exists or null if not exists + * @return the member as {@link NovaUser} if exists or null if not exists */ - public User getMember(String memberId) { + public NovaUser getMember(String memberId) { if(memberId != null) { - for (User projectMember : projectMembers) + for (NovaUser projectMember : projectMembers) if(projectMember.getId().equals(memberId)) return projectMember; } @@ -343,7 +343,7 @@ public User getMember(String memberId) { * @return whether a member's email is not contained by the checked project as boolean */ public boolean hasNotMemberEmail(String memberEmail) { - for (User member : projectMembers) + for (NovaUser member : projectMembers) if(member.getEmail().equals(memberEmail)) return false; return true; diff --git a/core/src/main/java/com/tecknobit/novacore/records/release/Release.java b/core/src/main/java/com/tecknobit/novacore/records/release/Release.java index d9a5d20..eb0294e 100644 --- a/core/src/main/java/com/tecknobit/novacore/records/release/Release.java +++ b/core/src/main/java/com/tecknobit/novacore/records/release/Release.java @@ -4,11 +4,11 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.tecknobit.apimanager.annotations.Returner; -import com.tecknobit.apimanager.formatters.TimeFormatter; +import com.tecknobit.equinox.environment.records.EquinoxItem; import com.tecknobit.novacore.records.NotificationsTarget; import com.tecknobit.novacore.records.NovaItem; import com.tecknobit.novacore.records.NovaNotification; -import com.tecknobit.novacore.records.User.Role; +import com.tecknobit.novacore.records.NovaUser.Role; import com.tecknobit.novacore.records.project.Project; import com.tecknobit.novacore.records.release.events.AssetUploadingEvent; import com.tecknobit.novacore.records.release.events.AssetUploadingEvent.AssetUploaded; @@ -40,7 +40,7 @@ */ @Entity @Table(name = Release.RELEASES_KEY) -public class Release extends NovaItem implements NotificationsTarget { +public class Release extends EquinoxItem implements NotificationsTarget { /** * {@code ALLOWED_ASSETS_TYPE} list of allowed type to upload as assets @@ -383,7 +383,7 @@ public long getCreationTimestamp() { */ @JsonIgnore public String getCreationDate() { - return TimeFormatter.getStringDate(creationDate); + return timeFormatter.formatAsString(creationDate); } /** @@ -416,7 +416,7 @@ public long getApprobationTimestamp() { */ @JsonIgnore public String getApprobationDate() { - return TimeFormatter.getStringDate(approbationDate); + return timeFormatter.formatAsString(approbationDate); } /** diff --git a/core/src/main/java/com/tecknobit/novacore/records/release/events/AssetUploadingEvent.java b/core/src/main/java/com/tecknobit/novacore/records/release/events/AssetUploadingEvent.java index 5d9602a..4d152ce 100644 --- a/core/src/main/java/com/tecknobit/novacore/records/release/events/AssetUploadingEvent.java +++ b/core/src/main/java/com/tecknobit/novacore/records/release/events/AssetUploadingEvent.java @@ -17,7 +17,7 @@ import java.util.ArrayList; import java.util.List; -import static com.tecknobit.novacore.records.User.Role; +import static com.tecknobit.novacore.records.NovaUser.Role; import static com.tecknobit.novacore.records.release.Release.ReleaseStatus.Verifying; import static com.tecknobit.novacore.records.release.events.AssetUploadingEvent.AssetUploaded.ASSETS_UPLOADED_KEY; diff --git a/core/src/main/java/com/tecknobit/novacore/records/release/events/ReleaseEvent.java b/core/src/main/java/com/tecknobit/novacore/records/release/events/ReleaseEvent.java index fb40228..e3b8112 100644 --- a/core/src/main/java/com/tecknobit/novacore/records/release/events/ReleaseEvent.java +++ b/core/src/main/java/com/tecknobit/novacore/records/release/events/ReleaseEvent.java @@ -5,7 +5,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.tecknobit.apimanager.annotations.Returner; import com.tecknobit.apimanager.annotations.Structure; -import com.tecknobit.apimanager.formatters.TimeFormatter; +import com.tecknobit.equinox.environment.records.EquinoxItem; import com.tecknobit.novacore.records.NovaItem; import com.tecknobit.novacore.records.release.Release; import jakarta.persistence.*; @@ -30,7 +30,7 @@ @Entity @Structure @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) -public abstract class ReleaseEvent extends NovaItem { +public abstract class ReleaseEvent extends EquinoxItem { /** * {@code RELEASE_EVENT_IDENTIFIER_KEY} the key for the "release_event_id" field @@ -213,7 +213,7 @@ public long getReleaseEventTimestamp() { */ @JsonIgnore public String getReleaseEventDate() { - return TimeFormatter.getStringDate(releaseEventDate); + return timeFormatter.formatAsString(releaseEventDate); } /** diff --git a/core/src/main/java/com/tecknobit/novacore/helpers/Requester.kt b/core/src/main/kotlin/com/tecknobit/novacore/helpers/NovaRequester.kt similarity index 54% rename from core/src/main/java/com/tecknobit/novacore/helpers/Requester.kt rename to core/src/main/kotlin/com/tecknobit/novacore/helpers/NovaRequester.kt index 6b6b84e..aab1094 100644 --- a/core/src/main/java/com/tecknobit/novacore/helpers/Requester.kt +++ b/core/src/main/kotlin/com/tecknobit/novacore/helpers/NovaRequester.kt @@ -3,16 +3,12 @@ package com.tecknobit.novacore.helpers import com.tecknobit.apimanager.annotations.RequestPath import com.tecknobit.apimanager.annotations.Wrapper import com.tecknobit.apimanager.apis.APIRequest -import com.tecknobit.apimanager.apis.APIRequest.* -import com.tecknobit.apimanager.apis.sockets.SocketManager.StandardResponseCode -import com.tecknobit.apimanager.apis.sockets.SocketManager.StandardResponseCode.* -import com.tecknobit.apimanager.formatters.JsonHelper -import com.tecknobit.novacore.InputValidator -import com.tecknobit.novacore.InputValidator.DEFAULT_LANGUAGE +import com.tecknobit.apimanager.apis.APIRequest.Params +import com.tecknobit.equinox.environment.helpers.EquinoxRequester import com.tecknobit.novacore.helpers.Endpoints.* import com.tecknobit.novacore.records.NovaItem.IDENTIFIER_KEY import com.tecknobit.novacore.records.NovaNotification.NOTIFICATIONS_KEY -import com.tecknobit.novacore.records.User.* +import com.tecknobit.novacore.records.NovaUser.* import com.tecknobit.novacore.records.project.JoiningQRCode.CREATE_JOIN_CODE_KEY import com.tecknobit.novacore.records.project.JoiningQRCode.JOIN_CODE_KEY import com.tecknobit.novacore.records.project.Project.LOGO_URL_KEY @@ -26,244 +22,26 @@ import com.tecknobit.novacore.records.release.events.RejectedReleaseEvent.TAGS_K import com.tecknobit.novacore.records.release.events.RejectedTag.COMMENT_KEY import com.tecknobit.novacore.records.release.events.ReleaseEvent.ReleaseTag import com.tecknobit.novacore.records.release.events.ReleaseStandardEvent.RELEASE_EVENT_STATUS_KEY -import kotlinx.coroutines.async -import kotlinx.coroutines.runBlocking +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MultipartBody +import okhttp3.RequestBody.Companion.toRequestBody import org.json.JSONArray import org.json.JSONObject -import org.springframework.core.io.FileSystemResource -import org.springframework.http.HttpEntity -import org.springframework.http.HttpHeaders -import org.springframework.http.MediaType -import org.springframework.util.LinkedMultiValueMap -import org.springframework.util.MultiValueMap -import org.springframework.web.client.RestTemplate import java.io.File -import java.io.IOException -/** - * The **Requester** class is useful to communicate with the Nova's backend - * - * @param host: the host where is running the Nova's backend - * @param userId: the user identifier - * @param userToken: the user token - * - * @author N7ghtm4r3 - Tecknobit - */ -open class Requester ( - public var host: String, - public var userId: String? = null, - public var userToken: String? = null +class NovaRequester( + host: String, + userId: String? = null, + userToken: String? = null +) : EquinoxRequester( + host = host, + userId = userId, + userToken = userToken, + connectionTimeout = 5000, + connectionErrorMessage = DEFAULT_CONNECTION_ERROR_MESSAGE, + enableCertificatesValidation = true ) { - companion object { - - /** - * **RESPONSE_STATUS_KEY** the key for the "status" field - */ - const val RESPONSE_STATUS_KEY: String = "status" - - /** - * **RESPONSE_MESSAGE_KEY** the key for the "response" field - */ - const val RESPONSE_MESSAGE_KEY: String = "response" - - /** - * **SERVER_NOT_REACHABLE** message to send when the server is not available at the moment when the - * request has been sent - */ - const val SERVER_NOT_REACHABLE = "Server is temporarily unavailable" - - } - - /** - * **apiRequest** -> the instance to communicate and make the requests to the backend - */ - protected val apiRequest = APIRequest(5000) - - /** - * **headers** the headers used in the request - */ - protected val headers = Headers() - - /** - * **mustValidateCertificates** flag whether the requests must validate the SSL certificates, this need for example - * when the SSL is a self-signed certificate - */ - protected var mustValidateCertificates = host.startsWith("https") - - init { - changeHost(host) - setUserCredentials(userId, userToken) - } - - /** - * Function to set the user credentials used to make the authenticated requests - * - * @param userId: the user identifier to use - * @param userToken: the user token to use - */ - fun setUserCredentials( - userId: String?, - userToken: String? - ) { - this.userId = userId - this.userToken = userToken - if(userToken != null) - headers.addHeader(TOKEN_KEY, userToken) - } - - /** - * Function to change during the runtime, for example when the local session changed, the host address to make the - * requests - * - * @param host: the new host address to use - */ - fun changeHost( - host: String - ) { - this.host = host + BASE_ENDPOINT - mustValidateCertificates = host.startsWith("https") - } - - /** - * Function to execute the request to sign up in the Nova's system - * - * @param serverSecret: the secret of the personal Pandoro's backend - * @param name: the name of the user - * @param surname: the surname of the user - * @param email: the email of the user - * @param password: the password of the user - * @param language: the language of the user - * - * @return the result of the request as [JSONObject] - * - */ - @RequestPath(path = "/api/v1/users/signUp", method = APIRequest.RequestMethod.POST) - fun signUp( - serverSecret: String, - name: String, - surname: String, - email: String, - password: String, - language: String - ) : JSONObject { - val payload = Params() - payload.addParam(SERVER_SECRET_KEY, serverSecret) - payload.addParam(NAME_KEY, name) - payload.addParam(SURNAME_KEY, surname) - payload.addParam(EMAIL_KEY, email) - payload.addParam(PASSWORD_KEY, password) - payload.addParam(LANGUAGE_KEY, - if(!InputValidator.isLanguageValid(language)) - DEFAULT_LANGUAGE - else - language - ) - return execPost( - endpoint = SIGN_UP_ENDPOINT, - payload = payload - ) - } - - /** - * Function to execute the request to sign in the Nova's system - * - * @param email: the email of the user - * @param password: the password of the user - * - * @return the result of the request as [JSONObject] - * - */ - @RequestPath(path = "/api/v1/users/signIn", method = APIRequest.RequestMethod.POST) - fun signIn( - email: String, - password: String - ) : JSONObject { - val payload = Params() - payload.addParam(EMAIL_KEY, email) - payload.addParam(PASSWORD_KEY, password) - return execPost( - endpoint = SIGN_IN_ENDPOINT, - payload = payload - ) - } - - /** - * Function to execute the request to change the profile pic of the user - * - * @param profilePic: the profile pic chosen by the user to set as the new profile pic - * - * @return the result of the request as [JSONObject] - */ - @RequestPath(path = "/api/v1/users/{id}/changeProfilePic", method = APIRequest.RequestMethod.POST) - open fun changeProfilePic( - profilePic: File - ) : JSONObject { - val body: MultiValueMap = LinkedMultiValueMap() - body.add(PROFILE_PIC_URL_KEY, FileSystemResource(profilePic)) - return execMultipartRequest( - body = body, - endpoint = assembleUsersEndpointPath(CHANGE_PROFILE_PIC_ENDPOINT) - ) - } - - /** - * Function to execute the request to change the email of the user - * - * @param newEmail: the new email of the user - * - * @return the result of the request as [JSONObject] - */ - @RequestPath(path = "/api/v1/users/{id}/changeEmail", method = APIRequest.RequestMethod.PATCH) - fun changeEmail( - newEmail: String - ): JSONObject { - val payload = Params() - payload.addParam(EMAIL_KEY, newEmail) - return execPatch( - endpoint = assembleUsersEndpointPath(CHANGE_EMAIL_ENDPOINT), - payload = payload - ) - } - - /** - * Function to execute the request to change the password of the user - * - * @param newPassword: the new password of the user - * - * @return the result of the request as [JSONObject] - */ - @RequestPath(path = "/api/v1/users/{id}/changePassword", method = APIRequest.RequestMethod.PATCH) - fun changePassword( - newPassword: String - ): JSONObject { - val payload = Params() - payload.addParam(PASSWORD_KEY, newPassword) - return execPatch( - endpoint = assembleUsersEndpointPath(CHANGE_PASSWORD_ENDPOINT), - payload = payload - ) - } - - /** - * Function to execute the request to change the language of the user - * - * @param newLanguage: the new language of the user - * - * @return the result of the request as [JSONObject] - */ - @RequestPath(path = "/api/v1/users/{id}/changeLanguage", method = APIRequest.RequestMethod.PATCH) - fun changeLanguage( - newLanguage: String - ): JSONObject { - val payload = Params() - payload.addParam(LANGUAGE_KEY, newLanguage) - return execPatch( - endpoint = assembleUsersEndpointPath(CHANGE_LANGUAGE_ENDPOINT), - payload = payload - ) - } - /** * Function to execute the request to get the user notifications * @@ -278,33 +56,6 @@ open class Requester ( ) } - /** - * Function to execute the request to delete the account of the user - * - * No-any params required - * - * @return the result of the request as [JSONObject] - */ - @RequestPath(path = "/api/v1/users/{id}", method = APIRequest.RequestMethod.DELETE) - fun deleteAccount(): JSONObject { - return execDelete( - endpoint = assembleUsersEndpointPath() - ) - } - - /** - * Function to assemble the endpoint to make the request to the users controller - * - * @param endpoint: the endpoint path of the url - * - * @return an endpoint to make the request as [String] - */ - protected fun assembleUsersEndpointPath( - endpoint: String = "" - ): String { - return "$USERS_KEY/$userId$endpoint" - } - /** * Function to execute the request to list the projects of the user * @@ -328,13 +79,21 @@ open class Requester ( * @return the result of the request as [JSONObject] */ @RequestPath(path = "/api/v1/{id}/projects", method = APIRequest.RequestMethod.POST) - open fun addProject( + fun addProject( logoPic: File, projectName: String ) : JSONObject { - val body: MultiValueMap = LinkedMultiValueMap() - body.add(LOGO_URL_KEY, FileSystemResource(logoPic)) - body.add(NAME_KEY, projectName) + val body = MultipartBody.Builder().setType(MultipartBody.FORM) + .addFormDataPart( + LOGO_URL_KEY, + logoPic.name, + logoPic.readBytes().toRequestBody("*/*".toMediaType()) + ) + .addFormDataPart( + NAME_KEY, + projectName + ) + .build() return execMultipartRequest( body = body, endpoint = assembleProjectsEndpointPath() @@ -609,19 +368,21 @@ open class Requester ( * @return the result of the request as [JSONObject] */ @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}", method = APIRequest.RequestMethod.POST) - open fun uploadAsset( + fun uploadAsset( projectId: String, releaseId: String, assets: List ) : JSONObject { - val body: MultiValueMap = LinkedMultiValueMap() - val fileSystemResourceAssets = mutableListOf () + val body = MultipartBody.Builder().setType(MultipartBody.FORM) assets.forEach { asset -> - fileSystemResourceAssets.add(FileSystemResource(asset)) + body.addFormDataPart( + ASSETS_UPLOADED_KEY, + asset.name, + asset.readBytes().toRequestBody("*/*".toMediaType()) + ) } - body.put(ASSETS_UPLOADED_KEY, fileSystemResourceAssets.toList()) return execMultipartRequest( - body = body, + body = body.build(), endpoint = assembleReleasesEndpointPath( projectId = projectId, releaseId = releaseId @@ -629,31 +390,6 @@ open class Requester ( ) } - /** - * Function to exec a multipart body request - * - * @param body: the body payload of the request - * @param endpoint: the endpoint path of the url - * - * @return the result of the request as [JSONObject] - */ - private fun execMultipartRequest( - body: MultiValueMap, - endpoint: String - ) : JSONObject { - val headers = HttpHeaders() - headers.contentType = MediaType.MULTIPART_FORM_DATA - headers.add(TOKEN_KEY, userToken) - val requestEntity: HttpEntity = HttpEntity(body, headers) - val restTemplate = RestTemplate() - val response = restTemplate.postForEntity( - host + endpoint, - requestEntity, - String::class.java - ).body - return JSONObject(response) - } - /** * Function to execute the request to approve the last assets uploaded * @@ -743,7 +479,8 @@ open class Requester ( if(reasons != null) payload.addParam(REASONS_KEY, reasons) if(tags != null) { - payload.addParam(TAGS_KEY, formatValuesList(tags.toString() + payload.addParam( + TAGS_KEY, formatValuesList(tags.toString() .replace("[", "") .replace("]", "") )) @@ -905,243 +642,4 @@ open class Requester ( return JSONArray(values.replace(" ", "").split(",")) } - /** - * Function to execute a [APIRequest.RequestMethod.GET] request to the backend - * - * @param endpoint: the endpoint path of the request url - * - * @return the result of the request as [JSONObject] - */ - @Wrapper - private fun execGet( - endpoint: String - ) : JSONObject { - return execRequest( - method = APIRequest.RequestMethod.GET, - endpoint = endpoint - ) - } - - /** - * Function to execute a [APIRequest.RequestMethod.POST] request to the backend - * - * @param endpoint: the endpoint path of the request url - * @param payload: the payload of the request - * - * @return the result of the request as [JSONObject] - */ - @Wrapper - private fun execPost( - endpoint: String, - payload: Params - ) : JSONObject { - return execRequest( - method = APIRequest.RequestMethod.POST, - endpoint = endpoint, - payload = payload - ) - } - - /** - * Function to execute a [APIRequest.RequestMethod.PUT] request to the backend - * - * @param endpoint: the endpoint path of the request url - * @param payload: the payload of the request - * - * @return the result of the request as [JSONObject] - */ - @Wrapper - private fun execPut( - endpoint: String, - payload: Params - ) : JSONObject { - return execRequest( - method = APIRequest.RequestMethod.PUT, - endpoint = endpoint, - payload = payload - ) - } - - /** - * Function to execute a [APIRequest.RequestMethod.PATCH] request to the backend - * - * @param endpoint: the endpoint path of the request url - * @param payload: the payload of the request - * - * @return the result of the request as [JSONObject] - */ - @Wrapper - private fun execPatch( - endpoint: String, - payload: Params - ) : JSONObject { - return execRequest( - method = APIRequest.RequestMethod.PATCH, - endpoint = endpoint, - payload = payload - ) - } - - /** - * Function to execute a [APIRequest.RequestMethod.DELETE] request to the backend - * - * @param endpoint: the endpoint path of the request url - * @param payload: the payload of the request - * - * @return the result of the request as [JSONObject] - */ - @Wrapper - private fun execDelete( - endpoint: String, - payload: Params? = null - ) : JSONObject { - return execRequest( - method = APIRequest.RequestMethod.DELETE, - endpoint = endpoint, - payload = payload - ) - } - - /** - * Function to execute a request to the backend - * - * @param method: the method of the request - * @param endpoint: the endpoint path of the request url - * @param payload: the payload of the request - * - * @return the result of the request as [JSONObject] - */ - private fun execRequest( - method: RequestMethod, - endpoint: String, - payload: Params? = null - ) : JSONObject { - var response: String? = null - var jResponse: JSONObject - if(mustValidateCertificates) - apiRequest.validateSelfSignedCertificate() - runBlocking { - try { - async { - val requestUrl = host + endpoint - try { - if(payload != null) { - apiRequest.sendJSONPayloadedAPIRequest( - requestUrl, - method, - headers, - payload - ) - } else { - apiRequest.sendAPIRequest( - requestUrl, - method, - headers - ) - } - response = apiRequest.response - } catch (e: IOException) { - response = connectionErrorMessage(SERVER_NOT_REACHABLE) - } - }.await() - jResponse = JSONObject(response) - } catch (e: Exception) { - jResponse = JSONObject(connectionErrorMessage(SERVER_NOT_REACHABLE)) - } - } - return jResponse - } - - /** - * Function to set the [RESPONSE_STATUS_KEY] to send when an error during the connection occurred - * - * @param error: the error to use - * - * @return the error message as [String] - */ - protected fun connectionErrorMessage(error: String): String { - return JSONObject() - .put(RESPONSE_STATUS_KEY, GENERIC_RESPONSE) - .put(RESPONSE_MESSAGE_KEY, error) - .toString() - } - - /** - * Function to execute and manage the response of a request - * - * @param request: the request to execute - * @param onSuccess: the action to execute if the request has been successful - * @param onFailure: the action to execute if the request has been failed - * @param onConnectionError: the action to execute if the request has been failed for a connection error - */ - fun sendRequest( - request: () -> JSONObject, - onSuccess: (JsonHelper) -> Unit, - onFailure: (JSONObject) -> Unit, - onConnectionError: ((JsonHelper) -> Unit)? = null - ) { - val response = request.invoke() - when(isSuccessfulResponse(response)) { - SUCCESSFUL -> onSuccess.invoke(JsonHelper(response)) - GENERIC_RESPONSE -> { - if(onConnectionError != null) - onConnectionError.invoke(JsonHelper(response)) - else - onFailure.invoke(response) - } - else -> onFailure.invoke(response) - } - } - - /** - * Function to get whether the request has been successful or not - * - * @param response: the response of the request - * - * @return whether the request has been successful or not as [StandardResponseCode] - */ - protected fun isSuccessfulResponse( - response: JSONObject? - ): StandardResponseCode { - if(response == null || !response.has(RESPONSE_STATUS_KEY)) - return FAILED - return when(response.getString(RESPONSE_STATUS_KEY)) { - SUCCESSFUL.name -> SUCCESSFUL - GENERIC_RESPONSE.name -> GENERIC_RESPONSE - else -> FAILED - } - } - - /** - * The **ListFetcher** interface is useful to manage the requests to refresh a list of items - * - * @author N7ghtm4r3 - Tecknobit - */ - interface ListFetcher { - - /** - * Function to refresh a list of item - * - * No-any params required - */ - fun refreshList() - - } - - /** - * The **ItemFetcher** interface is useful to manage the requests to refresh a single item - * - * @author N7ghtm4r3 - Tecknobit - */ - interface ItemFetcher { - - /** - * Function to refresh a single item - * - * No-any params required - */ - fun refreshItem() - - } - -} \ No newline at end of file +} diff --git a/core/src/main/resources/resources.mantis b/core/src/main/resources/resources.mantis deleted file mode 100644 index 6416143..0000000 --- a/core/src/main/resources/resources.mantis +++ /dev/null @@ -1,21 +0,0 @@ -{ - "en": { - "new_asset_uploaded_key": "New asset uploaded", - "asset_has_been_approved_key": "Asset has been approved", - "beta_timeline_message_key": "Asset has been promoted to Beta version", - "latest_timeline_message_key": "Release promoted as latest!", - "creation_date_key": "Date of creation:", - "alpha_timeline_message_key": "Asset has been promoted to Alpha version", - "new_asset_has_been_uploaded_key": "New asset has been uploaded" - }, - "ignored_resources": {}, - "it": { - "new_asset_uploaded_key": "Nuovo asset caricato", - "asset_has_been_approved_key": "L'asset e' stato approvato", - "beta_timeline_message_key": "L'asset e' stato promosso alla versione Beta", - "latest_timeline_message_key": "Release promosso come ultimo!", - "creation_date_key": "Data creazione:", - "alpha_timeline_message_key": "L'asset e' stato promosso alla versione Alpha", - "new_asset_has_been_uploaded_key": "Un nuovo asset e' stato caricato" - } -} \ No newline at end of file From e3988ed6f5c6d6243d3599bc970cb61bf32ca23d Mon Sep 17 00:00:00 2001 From: N7ghtm4r3 Date: Wed, 18 Sep 2024 21:57:44 +0200 Subject: [PATCH 03/25] Integrated Equinox and auto creation if database does not exist --- .../nova/controllers/NovaUsersController.java | 14 + .../projectmanagers/ProjectsController.java | 8 +- .../projectmanagers/ReleasesController.java | 7 +- .../helpers/services/NovaUsersHelper.java | 12 + .../nova/helpers/services/ProjectsHelper.java | 2 +- .../JoiningQRCodeRepository.java | 2 +- .../projectsutils/ProjectsRepository.java | 1 - .../releaseutils/NotificationsRepository.java | 1 - .../releaseutils/ReleaseEventsRepository.java | 1 - .../releaseutils/ReleaseTagRepository.java | 1 - .../releaseutils/ReleasesRepository.java | 1 - backend/src/main/resources/app.properties | 2 +- .../tecknobit/novacore/InputValidator.java | 329 ------------------ .../novacore/NovaInputValidator.java | 161 +++++++++ .../novacore/helpers/LocalSessionUtils.java | 1 - .../{Endpoints.java => NovaEndpoints.java} | 45 +-- .../novacore/records/NotificationsTarget.java | 2 +- .../tecknobit/novacore/records/NovaItem.java | 72 ---- .../novacore/records/NovaNotification.java | 5 +- .../tecknobit/novacore/records/NovaUser.java | 2 +- .../records/project/JoiningQRCode.java | 6 +- .../novacore/records/project/Project.java | 6 +- .../novacore/records/release/Release.java | 3 +- .../release/events/AssetUploadingEvent.java | 8 +- .../release/events/RejectedReleaseEvent.java | 4 +- .../records/release/events/RejectedTag.java | 6 +- .../records/release/events/ReleaseEvent.java | 3 +- .../release/events/ReleaseStandardEvent.java | 5 +- .../novacore/helpers/NovaRequester.kt | 4 +- 29 files changed, 229 insertions(+), 485 deletions(-) delete mode 100644 core/src/main/java/com/tecknobit/novacore/InputValidator.java create mode 100644 core/src/main/java/com/tecknobit/novacore/NovaInputValidator.java rename core/src/main/java/com/tecknobit/novacore/helpers/{Endpoints.java => NovaEndpoints.java} (52%) delete mode 100644 core/src/main/java/com/tecknobit/novacore/records/NovaItem.java diff --git a/backend/src/main/java/com/tecknobit/nova/controllers/NovaUsersController.java b/backend/src/main/java/com/tecknobit/nova/controllers/NovaUsersController.java index 31ea590..64dce1e 100644 --- a/backend/src/main/java/com/tecknobit/nova/controllers/NovaUsersController.java +++ b/backend/src/main/java/com/tecknobit/nova/controllers/NovaUsersController.java @@ -7,6 +7,7 @@ import com.tecknobit.nova.helpers.services.repositories.releaseutils.NotificationsRepository; import com.tecknobit.novacore.records.NovaNotification; import com.tecknobit.novacore.records.NovaUser; +import org.json.JSONObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Primary; import org.springframework.web.bind.annotation.GetMapping; @@ -49,12 +50,25 @@ public NovaUsersController(NovaUsersHelper usersHelper) { super(usersHelper); } + /** + * {@inheritDoc} + */ @Override @CustomParametersOrder(order = ROLE_KEY) protected Object[] getSignUpCustomParams() { return new Object[]{Vendor}; } + /** + * {@inheritDoc} + */ + @Override + protected JSONObject assembleSignInSuccessResponse(NovaUser user) { + JSONObject response = super.assembleSignInSuccessResponse(user); + response.put(ROLE_KEY, user.getRole()); + return response; + } + /** * Method to get the notifications of the user * diff --git a/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectsController.java b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectsController.java index 3e74677..4a7bcf7 100644 --- a/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectsController.java +++ b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectsController.java @@ -20,9 +20,9 @@ import static com.tecknobit.apimanager.apis.APIRequest.RequestMethod.*; import static com.tecknobit.equinox.environment.records.EquinoxUser.TOKEN_KEY; -import static com.tecknobit.novacore.InputValidator.*; -import static com.tecknobit.novacore.helpers.Endpoints.*; -import static com.tecknobit.novacore.records.NovaItem.IDENTIFIER_KEY; +import static com.tecknobit.novacore.NovaInputValidator.*; +import static com.tecknobit.novacore.helpers.NovaEndpoints.*; +import static com.tecknobit.novacore.records.NovaUser.IDENTIFIER_KEY; import static com.tecknobit.novacore.records.NovaUser.*; import static com.tecknobit.novacore.records.project.JoiningQRCode.*; import static com.tecknobit.novacore.records.project.Project.PROJECT_IDENTIFIER_KEY; @@ -36,7 +36,7 @@ * @see ProjectManager */ @RestController -@RequestMapping(BASE_ENDPOINT) +@RequestMapping(BASE_EQUINOX_ENDPOINT) public class ProjectsController extends ProjectManager { /** diff --git a/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ReleasesController.java b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ReleasesController.java index 8adb18d..4970c5a 100644 --- a/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ReleasesController.java +++ b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ReleasesController.java @@ -20,9 +20,8 @@ import static com.tecknobit.apimanager.apis.APIRequest.RequestMethod.*; import static com.tecknobit.equinox.environment.records.EquinoxUser.TOKEN_KEY; -import static com.tecknobit.novacore.InputValidator.*; -import static com.tecknobit.novacore.helpers.Endpoints.*; -import static com.tecknobit.novacore.records.NovaItem.IDENTIFIER_KEY; +import static com.tecknobit.novacore.NovaInputValidator.*; +import static com.tecknobit.novacore.helpers.NovaEndpoints.*; import static com.tecknobit.novacore.records.NovaUser.PROJECTS_KEY; import static com.tecknobit.novacore.records.project.Project.PROJECT_IDENTIFIER_KEY; import static com.tecknobit.novacore.records.release.Release.*; @@ -44,7 +43,7 @@ * @see ProjectManager */ @RestController -@RequestMapping(BASE_ENDPOINT + "{" + IDENTIFIER_KEY + "}/" + PROJECTS_KEY + "/{" + PROJECT_IDENTIFIER_KEY + "}/" +@RequestMapping(BASE_EQUINOX_ENDPOINT + "{" + IDENTIFIER_KEY + "}/" + PROJECTS_KEY + "/{" + PROJECT_IDENTIFIER_KEY + "}/" + RELEASES_KEY + "/") public class ReleasesController extends ProjectManager { diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/NovaUsersHelper.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/NovaUsersHelper.java index 736d904..bbc5400 100644 --- a/backend/src/main/java/com/tecknobit/nova/helpers/services/NovaUsersHelper.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/services/NovaUsersHelper.java @@ -2,6 +2,7 @@ import com.tecknobit.equinox.annotations.CustomParametersOrder; import com.tecknobit.equinox.environment.helpers.services.EquinoxUsersHelper; +import com.tecknobit.equinox.resourcesutils.ResourcesManager; import com.tecknobit.novacore.records.NovaUser; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Service; @@ -11,10 +12,21 @@ import static com.tecknobit.novacore.records.NovaUser.ROLE_KEY; +/** + * The {@code NovaUsersHelper} class is useful to manage all the Nova users database operations + * + * @author N7ghtm4r3 - Tecknobit + * @see ResourcesManager + * + * @since 1.0.1 + */ @Primary @Service public class NovaUsersHelper extends EquinoxUsersHelper { + /** + * {@inheritDoc} + */ @Override @CustomParametersOrder(order = ROLE_KEY) protected List getQueryValuesKeys() { diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java index 93ef2bf..557995e 100644 --- a/backend/src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java @@ -21,7 +21,7 @@ import java.util.List; import static com.tecknobit.equinox.environment.controllers.EquinoxController.generateIdentifier; -import static com.tecknobit.novacore.records.NovaItem.IDENTIFIER_KEY; +import static com.tecknobit.equinox.environment.records.EquinoxItem.IDENTIFIER_KEY; import static com.tecknobit.novacore.records.NovaUser.NAME_KEY; import static com.tecknobit.novacore.records.NovaUser.PROJECTS_KEY; import static com.tecknobit.novacore.records.project.Project.AUTHOR_KEY; diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/JoiningQRCodeRepository.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/JoiningQRCodeRepository.java index d33fa21..2f04d50 100644 --- a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/JoiningQRCodeRepository.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/JoiningQRCodeRepository.java @@ -9,7 +9,7 @@ import org.springframework.stereotype.Repository; import org.springframework.stereotype.Service; -import static com.tecknobit.novacore.records.NovaItem.IDENTIFIER_KEY; +import static com.tecknobit.equinox.environment.records.EquinoxItem.IDENTIFIER_KEY; import static com.tecknobit.novacore.records.NovaUser.ROLE_KEY; import static com.tecknobit.novacore.records.project.JoiningQRCode.JOINING_QRCODES_TABLE; import static com.tecknobit.novacore.records.project.JoiningQRCode.JOIN_CODE_KEY; diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/ProjectsRepository.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/ProjectsRepository.java index 13fef4e..bc12786 100644 --- a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/ProjectsRepository.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/ProjectsRepository.java @@ -12,7 +12,6 @@ import java.util.List; import static com.tecknobit.equinox.environment.records.EquinoxUser.NAME_KEY; -import static com.tecknobit.novacore.records.NovaItem.IDENTIFIER_KEY; import static com.tecknobit.novacore.records.NovaUser.MEMBER_IDENTIFIER_KEY; import static com.tecknobit.novacore.records.NovaUser.PROJECTS_KEY; import static com.tecknobit.novacore.records.project.Project.*; diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/NotificationsRepository.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/NotificationsRepository.java index 25cc9dc..73d8e51 100644 --- a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/NotificationsRepository.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/NotificationsRepository.java @@ -12,7 +12,6 @@ import java.util.List; -import static com.tecknobit.novacore.records.NovaItem.IDENTIFIER_KEY; import static com.tecknobit.novacore.records.NovaNotification.IS_SENT_KEY; import static com.tecknobit.novacore.records.NovaNotification.NOTIFICATIONS_KEY; import static com.tecknobit.novacore.records.NovaUser.USER_KEY; diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/ReleaseEventsRepository.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/ReleaseEventsRepository.java index 52ca8f8..ca88a32 100644 --- a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/ReleaseEventsRepository.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/ReleaseEventsRepository.java @@ -12,7 +12,6 @@ import org.springframework.stereotype.Repository; import org.springframework.stereotype.Service; -import static com.tecknobit.novacore.records.NovaItem.IDENTIFIER_KEY; import static com.tecknobit.novacore.records.release.Release.RELEASE_IDENTIFIER_KEY; import static com.tecknobit.novacore.records.release.events.AssetUploadingEvent.*; import static com.tecknobit.novacore.records.release.events.AssetUploadingEvent.AssetUploaded.ASSETS_UPLOADED_KEY; diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/ReleaseTagRepository.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/ReleaseTagRepository.java index d5ba211..c0fcf2b 100644 --- a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/ReleaseTagRepository.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/ReleaseTagRepository.java @@ -9,7 +9,6 @@ import org.springframework.stereotype.Repository; import org.springframework.stereotype.Service; -import static com.tecknobit.novacore.records.NovaItem.IDENTIFIER_KEY; import static com.tecknobit.novacore.records.release.events.RejectedTag.*; import static com.tecknobit.novacore.records.release.events.ReleaseEvent.RELEASE_EVENT_KEY; diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/ReleasesRepository.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/ReleasesRepository.java index 7932f92..56dda27 100644 --- a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/ReleasesRepository.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/ReleasesRepository.java @@ -9,7 +9,6 @@ import org.springframework.stereotype.Repository; import org.springframework.stereotype.Service; -import static com.tecknobit.novacore.records.NovaItem.IDENTIFIER_KEY; import static com.tecknobit.novacore.records.project.Project.PROJECT_KEY; import static com.tecknobit.novacore.records.release.Release.*; diff --git a/backend/src/main/resources/app.properties b/backend/src/main/resources/app.properties index 0572e99..496d093 100644 --- a/backend/src/main/resources/app.properties +++ b/backend/src/main/resources/app.properties @@ -1,4 +1,4 @@ -spring.datasource.url=jdbc:mysql://localhost:3306/nova +spring.datasource.url=jdbc:mysql://localhost:3306/nova?createDatabaseIfNotExist=true server.port=1054 spring.datasource.username=root spring.jpa.generate-ddl=true diff --git a/core/src/main/java/com/tecknobit/novacore/InputValidator.java b/core/src/main/java/com/tecknobit/novacore/InputValidator.java deleted file mode 100644 index f3b538d..0000000 --- a/core/src/main/java/com/tecknobit/novacore/InputValidator.java +++ /dev/null @@ -1,329 +0,0 @@ -package com.tecknobit.novacore; - -import org.apache.commons.validator.routines.EmailValidator; -import org.apache.commons.validator.routines.UrlValidator; - -import java.util.HashMap; -import java.util.List; - -/** - * The {@code InputValidator} class is useful to validate the inputs - * - * @author N7ghtm4r3 - Tecknobit - */ -public class InputValidator { - - /** - * {@code WRONG_NAME_MESSAGE} error message used when the name inserted is not valid - */ - public static final String WRONG_NAME_MESSAGE = "Name is not valid"; - - /** - * {@code NAME_MAX_LENGTH} the max valid length for the username - */ - public static final int NAME_MAX_LENGTH = 20; - - /** - * {@code PROJECT_NAME_MAX_LENGTH} the max valid length for the name of a project - */ - public static final int PROJECT_NAME_MAX_LENGTH = 25; - - /** - * {@code WRONG_SURNAME_MESSAGE} error message used when the surname inserted is not valid - */ - public static final String WRONG_SURNAME_MESSAGE = "Surname is not valid"; - - /** - * {@code SURNAME_MAX_LENGTH} the max valid length for the surname - */ - public static final int SURNAME_MAX_LENGTH = 30; - - /** - * {@code WRONG_EMAIL_MESSAGE} error message used when the email inserted is not valid - */ - public static final String WRONG_EMAIL_MESSAGE = "Email is not valid"; - - /** - * {@code EMAIL_MAX_LENGTH} the max valid length for the email - */ - public static final int EMAIL_MAX_LENGTH = 75; - - /** - * {@code WRONG_PASSWORD_MESSAGE} error message used when the password inserted is not valid - */ - public static final String WRONG_PASSWORD_MESSAGE = "Password is not valid"; - - /** - * {@code PASSWORD_MIN_LENGTH} the min valid length for the password - */ - public static final int PASSWORD_MIN_LENGTH = 8; - - /** - * {@code PASSWORD_MAX_LENGTH} the max valid length for the password - */ - public static final int PASSWORD_MAX_LENGTH = 32; - - /** - * {@code WRONG_LANGUAGE_MESSAGE} error message used when the language inserted is not valid - */ - public static final String WRONG_LANGUAGE_MESSAGE = "Language is not supported"; - - /** - * {@code DEFAULT_LANGUAGE} default language used - */ - public static final String DEFAULT_LANGUAGE = "en"; - - /** - * {@code WRONG_MAILING_LIST_MESSAGE} error message used when the mailing list inserted is not valid - */ - public static final String WRONG_MAILING_LIST_MESSAGE = "Mailing list is not valid"; - - /** - * {@code WRONG_RELEASE_VERSION_MESSAGE} error message used when the release version inserted is not valid - */ - public static final String WRONG_RELEASE_VERSION_MESSAGE = "The version for the release is not valid"; - - /** - * {@code RELEASE_VERSION_MAX_LENGTH} the max valid length for the release version - */ - public static final int RELEASE_VERSION_MAX_LENGTH = 10; - - /** - * {@code WRONG_RELEASE_NOTES_MESSAGE} error message used when the release notes inserted are not valid - */ - public static final String WRONG_RELEASE_NOTES_MESSAGE = "The notes for the release are not valid"; - - /** - * {@code RELEASE_NOTES_MAX_LENGTH} the max valid length for the release notes - */ - public static final int RELEASE_NOTES_MAX_LENGTH = 300; - - /** - * {@code WRONG_ASSETS_MESSAGE} error message used when the release assets uploaded are not valid - */ - public static final String WRONG_ASSETS_MESSAGE = "The assets uploaded are not valid"; - - /** - * {@code WRONG_REASONS_MESSAGE} error message used when the rejected reasons inserted are not valid - */ - public static final String WRONG_REASONS_MESSAGE = "The reasons of the rejection are not valid"; - - /** - * {@code REASONS_MAX_LENGTH} the max valid length for the reasons - */ - public static final int REASONS_MAX_LENGTH = 300; - - /** - * {@code WRONG_TAG_COMMENT_MESSAGE} error message used when the tag comment inserted is not valid - */ - public static final String WRONG_TAG_COMMENT_MESSAGE = "The comment for the tag is not valid"; - - /** - * {@code TAG_COMMENT_MAX_LENGTH} the max valid length for the tag comment - */ - public static final int TAG_COMMENT_MAX_LENGTH = 300; - - /** - * {@code emailValidator} helper to validate the emails values - */ - private static final EmailValidator emailValidator = EmailValidator.getInstance(); - - /** - * {@code urlValidator} helper to validate the urls values - */ - private static final UrlValidator urlValidator = UrlValidator.getInstance(); - - /** - * {@code LANGUAGES_SUPPORTED} list of the supported languages - */ - public static final HashMap LANGUAGES_SUPPORTED = new HashMap<>(); - - static { - LANGUAGES_SUPPORTED.put("it", "ITALIAN"); - LANGUAGES_SUPPORTED.put("en", "ENGLISH"); - LANGUAGES_SUPPORTED.put("fr", "FRENCH"); - LANGUAGES_SUPPORTED.put("es", "SPANISH"); - } - - /** - * Constructor to init the {@link InputValidator} class
    - * - * No-any params required - */ - private InputValidator() { - } - - /** - * Method to validate a host - * - * @param host: host value to check the validity - * - * @return whether the host is valid or not as {@code boolean} - */ - public static boolean isHostValid(String host) { - return urlValidator.isValid(host); - } - - /** - * Method to validate a server secret - * - * @param serverSecret: name value to check the validity - * - * @return whether the server secret is valid or not as {@code boolean} - */ - public static boolean isServerSecretValid(String serverSecret) { - return isInputValid(serverSecret); - } - - /** - * Method to validate a name - * - * @param name: name value to check the validity - * - * @return whether the name is valid or not as {@code boolean} - */ - public static boolean isNameValid(String name) { - return isInputValid(name) && name.length() <= NAME_MAX_LENGTH; - } - - /** - * Method to validate a surname - * - * @param surname: surname value to check the validity - * - * @return whether the surname is valid or not as {@code boolean} - */ - public static boolean isSurnameValid(String surname) { - return isInputValid(surname) && surname.length() <= SURNAME_MAX_LENGTH; - } - - /** - * Method to validate an email - * - * @param email: password value to check the validity - * - * @return whether the email is valid or not as {@code boolean} - */ - public static boolean isEmailValid(String email) { - return emailValidator.isValid(email) && email.length() <= EMAIL_MAX_LENGTH; - } - - /** - * Method to validate a password - * - * @param password: password value to check the validity - * - * @return whether the password is valid or not as {@code boolean} - */ - public static boolean isPasswordValid(String password) { - int passwordLength = password.length(); - return isInputValid(password) && passwordLength >= PASSWORD_MIN_LENGTH && passwordLength <= PASSWORD_MAX_LENGTH; - } - - /** - * Method to validate a language - * - * @param language: language value to check the validity - * - * @return whether the language is valid or not as {@code boolean} - */ - public static boolean isLanguageValid(String language) { - return language != null && (LANGUAGES_SUPPORTED.containsKey(language) || LANGUAGES_SUPPORTED.containsValue(language)); - } - - /** - * Method to validate a project name - * - * @param projectName: project name value to check the validity - * - * @return whether the project name is valid or not as {@code boolean} - */ - public static boolean isProjectNameValid(String projectName) { - return isInputValid(projectName) && projectName.length() <= PROJECT_NAME_MAX_LENGTH; - } - - /** - * Method to validate a mailing list - * - * @param mailingList: mailing list value to check the validity - * - * @return whether the mailing list is valid or not as {@code boolean} - */ - public static boolean isMailingListValid(String mailingList) { - mailingList = mailingList.replaceAll(" ", ""); - return isMailingListValid(List.of(mailingList.split(","))); - } - - /** - * Method to validate a mailing list - * - * @param mailingList: mailing list value to check the validity - * - * @return whether the mailing list is valid or not as {@code boolean} - */ - public static boolean isMailingListValid(List mailingList) { - if(mailingList != null && !mailingList.isEmpty()) { - for (String email : mailingList) - if(!isEmailValid(email)) - return false; - return true; - } - return false; - } - - /** - * Method to validate a release version - * - * @param releaseVersion: release version value to check the validity - * - * @return whether the release version is valid or not as {@code boolean} - */ - public static boolean isReleaseVersionValid(String releaseVersion) { - return isInputValid(releaseVersion) && releaseVersion.length() <= RELEASE_VERSION_MAX_LENGTH; - } - - /** - * Method to validate a release notes - * - * @param releaseNotes: release notes value to check the validity - * - * @return whether the release notes are valid or not as {@code boolean} - */ - public static boolean areReleaseNotesValid(String releaseNotes) { - return isInputValid(releaseNotes) && releaseNotes.length() <= RELEASE_NOTES_MAX_LENGTH; - } - - /** - * Method to validate a rejected reasons - * - * @param reasons: rejected reasons value to check the validity - * - * @return whether the rejected reasons are valid or not as {@code boolean} - */ - public static boolean areRejectionReasonsValid(String reasons) { - return isInputValid(reasons) && reasons.length() <= REASONS_MAX_LENGTH; - } - - /** - * Method to validate a tag comment - * - * @param comment: comment value to check the validity - * - * @return whether the comment is valid or not as {@code boolean} - */ - public static boolean isTagCommentValid(String comment) { - return isInputValid(comment) && comment.length() <= TAG_COMMENT_MAX_LENGTH; - } - - /** - * Method to validate an input - * - * @param field: field value to check the validity - * - * @return whether the field is valid or not as {@code boolean} - */ - private static boolean isInputValid(String field) { - return field != null && !field.isEmpty(); - } - -} diff --git a/core/src/main/java/com/tecknobit/novacore/NovaInputValidator.java b/core/src/main/java/com/tecknobit/novacore/NovaInputValidator.java new file mode 100644 index 0000000..5e8ef41 --- /dev/null +++ b/core/src/main/java/com/tecknobit/novacore/NovaInputValidator.java @@ -0,0 +1,161 @@ +package com.tecknobit.novacore; + +import com.tecknobit.equinox.inputs.InputValidator; + +import java.util.List; + +/** + * The {@code NovaInputValidator} class is useful to validate the inputs + * + * @author N7ghtm4r3 - Tecknobit + */ +public class NovaInputValidator extends InputValidator { + + /** + * {@code PROJECT_NAME_MAX_LENGTH} the max valid length for the name of a project + */ + public static final int PROJECT_NAME_MAX_LENGTH = 25; + + /** + * {@code WRONG_MAILING_LIST_MESSAGE} error message used when the mailing list inserted is not valid + */ + public static final String WRONG_MAILING_LIST_MESSAGE = "Mailing list is not valid"; + + /** + * {@code WRONG_RELEASE_VERSION_MESSAGE} error message used when the release version inserted is not valid + */ + public static final String WRONG_RELEASE_VERSION_MESSAGE = "The version for the release is not valid"; + + /** + * {@code RELEASE_VERSION_MAX_LENGTH} the max valid length for the release version + */ + public static final int RELEASE_VERSION_MAX_LENGTH = 10; + + /** + * {@code WRONG_RELEASE_NOTES_MESSAGE} error message used when the release notes inserted are not valid + */ + public static final String WRONG_RELEASE_NOTES_MESSAGE = "The notes for the release are not valid"; + + /** + * {@code RELEASE_NOTES_MAX_LENGTH} the max valid length for the release notes + */ + public static final int RELEASE_NOTES_MAX_LENGTH = 300; + + /** + * {@code WRONG_ASSETS_MESSAGE} error message used when the release assets uploaded are not valid + */ + public static final String WRONG_ASSETS_MESSAGE = "The assets uploaded are not valid"; + + /** + * {@code WRONG_REASONS_MESSAGE} error message used when the rejected reasons inserted are not valid + */ + public static final String WRONG_REASONS_MESSAGE = "The reasons of the rejection are not valid"; + + /** + * {@code REASONS_MAX_LENGTH} the max valid length for the reasons + */ + public static final int REASONS_MAX_LENGTH = 300; + + /** + * {@code WRONG_TAG_COMMENT_MESSAGE} error message used when the tag comment inserted is not valid + */ + public static final String WRONG_TAG_COMMENT_MESSAGE = "The comment for the tag is not valid"; + + /** + * {@code TAG_COMMENT_MAX_LENGTH} the max valid length for the tag comment + */ + public static final int TAG_COMMENT_MAX_LENGTH = 300; + + /** + * Constructor to init the {@link NovaInputValidator} class
    + * + * No-any params required + */ + private NovaInputValidator() { + } + + /** + * Method to validate a project name + * + * @param projectName: project name value to check the validity + * + * @return whether the project name is valid or not as {@code boolean} + */ + public static boolean isProjectNameValid(String projectName) { + return isInputValid(projectName) && projectName.length() <= PROJECT_NAME_MAX_LENGTH; + } + + /** + * Method to validate a mailing list + * + * @param mailingList: mailing list value to check the validity + * + * @return whether the mailing list is valid or not as {@code boolean} + */ + public static boolean isMailingListValid(String mailingList) { + mailingList = mailingList.replaceAll(" ", ""); + return isMailingListValid(List.of(mailingList.split(","))); + } + + /** + * Method to validate a mailing list + * + * @param mailingList: mailing list value to check the validity + * + * @return whether the mailing list is valid or not as {@code boolean} + */ + public static boolean isMailingListValid(List mailingList) { + if(mailingList != null && !mailingList.isEmpty()) { + for (String email : mailingList) + if(!isEmailValid(email)) + return false; + return true; + } + return false; + } + + /** + * Method to validate a release version + * + * @param releaseVersion: release version value to check the validity + * + * @return whether the release version is valid or not as {@code boolean} + */ + public static boolean isReleaseVersionValid(String releaseVersion) { + return isInputValid(releaseVersion) && releaseVersion.length() <= RELEASE_VERSION_MAX_LENGTH; + } + + /** + * Method to validate a release notes + * + * @param releaseNotes: release notes value to check the validity + * + * @return whether the release notes are valid or not as {@code boolean} + */ + public static boolean areReleaseNotesValid(String releaseNotes) { + return isInputValid(releaseNotes) && releaseNotes.length() <= RELEASE_NOTES_MAX_LENGTH; + } + + /** + * Method to validate a rejected reasons + * + * @param reasons: rejected reasons value to check the validity + * + * @return whether the rejected reasons are valid or not as {@code boolean} + */ + public static boolean areRejectionReasonsValid(String reasons) { + return isInputValid(reasons) && reasons.length() <= REASONS_MAX_LENGTH; + } + + /** + * Method to validate a tag comment + * + * @param comment: comment value to check the validity + * + * @return whether the comment is valid or not as {@code boolean} + */ + public static boolean isTagCommentValid(String comment) { + return isInputValid(comment) && comment.length() <= TAG_COMMENT_MAX_LENGTH; + } + +} diff --git a/core/src/main/java/com/tecknobit/novacore/helpers/LocalSessionUtils.java b/core/src/main/java/com/tecknobit/novacore/helpers/LocalSessionUtils.java index 2ede9ae..fb0db31 100644 --- a/core/src/main/java/com/tecknobit/novacore/helpers/LocalSessionUtils.java +++ b/core/src/main/java/com/tecknobit/novacore/helpers/LocalSessionUtils.java @@ -6,7 +6,6 @@ import static com.tecknobit.novacore.helpers.LocalSessionUtils.NovaSession.HOST_ADDRESS_KEY; import static com.tecknobit.novacore.helpers.LocalSessionUtils.NovaSession.IS_ACTIVE_SESSION_KEY; -import static com.tecknobit.novacore.records.NovaItem.IDENTIFIER_KEY; import static com.tecknobit.novacore.records.NovaUser.*; /** diff --git a/core/src/main/java/com/tecknobit/novacore/helpers/Endpoints.java b/core/src/main/java/com/tecknobit/novacore/helpers/NovaEndpoints.java similarity index 52% rename from core/src/main/java/com/tecknobit/novacore/helpers/Endpoints.java rename to core/src/main/java/com/tecknobit/novacore/helpers/NovaEndpoints.java index aafcbc0..14f70ca 100644 --- a/core/src/main/java/com/tecknobit/novacore/helpers/Endpoints.java +++ b/core/src/main/java/com/tecknobit/novacore/helpers/NovaEndpoints.java @@ -1,46 +1,13 @@ package com.tecknobit.novacore.helpers; +import com.tecknobit.equinox.environment.helpers.EquinoxBaseEndpointsSet; + /** - * The {@code Endpoints} class is a container with all the Nova's endpoints + * The {@code NovaEndpoints} class is a container with all the Nova's endpoints * * @author N7ghtm4r3 - Tecknobit */ -public class Endpoints { - - /** - * {@code BASE_ENDPOINT} the base endpoint for the backend service - */ - public static final String BASE_ENDPOINT = "/api/v1/"; - - /** - * {@code SIGN_UP_ENDPOINT} the endpoint to execute the sign-up auth action - */ - public static final String SIGN_UP_ENDPOINT = "users/signUp"; - - /** - * {@code SIGN_IN_ENDPOINT} the endpoint to execute the sign-in auth action - */ - public static final String SIGN_IN_ENDPOINT = "users/signIn"; - - /** - * {@code CHANGE_PROFILE_PIC_ENDPOINT} the endpoint to execute the change of the user profile pic - */ - public static final String CHANGE_PROFILE_PIC_ENDPOINT = "/changeProfilePic"; - - /** - * {@code CHANGE_EMAIL_ENDPOINT} the endpoint to execute the change of the user email - */ - public static final String CHANGE_EMAIL_ENDPOINT = "/changeEmail"; - - /** - * {@code CHANGE_PASSWORD_ENDPOINT} the endpoint to execute the change of the user password - */ - public static final String CHANGE_PASSWORD_ENDPOINT = "/changePassword"; - - /** - * {@code CHANGE_LANGUAGE_ENDPOINT} the endpoint to execute the change of the user language - */ - public static final String CHANGE_LANGUAGE_ENDPOINT = "/changeLanguage"; +public class NovaEndpoints extends EquinoxBaseEndpointsSet { /** * {@code ADD_MEMBERS_ENDPOINT} the endpoint to add members into a project @@ -88,10 +55,10 @@ public class Endpoints { public static final String CREATE_REPORT_ENDPOINT = "/createReport"; /** - * Constructor to init the {@link Endpoints} class
    + * Constructor to init the {@link NovaEndpoints} class
    * No-any params required */ - private Endpoints() { + private NovaEndpoints() { } } diff --git a/core/src/main/java/com/tecknobit/novacore/records/NotificationsTarget.java b/core/src/main/java/com/tecknobit/novacore/records/NotificationsTarget.java index 17ac0b2..ab37a42 100644 --- a/core/src/main/java/com/tecknobit/novacore/records/NotificationsTarget.java +++ b/core/src/main/java/com/tecknobit/novacore/records/NotificationsTarget.java @@ -3,7 +3,7 @@ import java.util.List; /** - * The {@code NotificationsTarget} instance is useful to fetch the notifications of a specific {@link NovaItem}'s target + * The {@code NotificationsTarget} instance is useful to fetch the notifications of a specific {@link EquinoxItem}'s target * * @author N7ghtm4r3 - Tecknobit */ diff --git a/core/src/main/java/com/tecknobit/novacore/records/NovaItem.java b/core/src/main/java/com/tecknobit/novacore/records/NovaItem.java deleted file mode 100644 index 8cb1a81..0000000 --- a/core/src/main/java/com/tecknobit/novacore/records/NovaItem.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.tecknobit.novacore.records; - -import com.tecknobit.apimanager.annotations.Structure; -import com.tecknobit.apimanager.formatters.JsonHelper; -import jakarta.persistence.*; -import org.json.JSONObject; - -import java.io.Serializable; - -/** - * The {@code NovaItem} class is useful to create a Nova's item giving the basis utils to work correctly - * - * @author N7ghtm4r3 - Tecknobit - * - * @see Serializable - */ -@Entity -@Structure -@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) -public abstract class NovaItem implements Serializable { - - /** - * {@code IDENTIFIER_KEY} the key for the "id" field - */ - public static final String IDENTIFIER_KEY = "id"; - - /** - * {@code id} identifier of the item - */ - @Id - @Column(name = IDENTIFIER_KEY) - protected final String id; - - /** - * {@code hItem} helper to work with JSON values - */ - @Transient - protected transient final JsonHelper hItem; - - /** - * Constructor to init the {@link NovaItem} class - * - * @param jItem: item formatted as JSON - * - */ - public NovaItem(JSONObject jItem) { - hItem = new JsonHelper(jItem); - id = hItem.getString(IDENTIFIER_KEY); - } - - /** - * Constructor to init the {@link NovaItem} class - * - * @param id: identifier of the item - * - */ - public NovaItem(String id) { - hItem = null; - this.id = id; - } - - /** - * Method to get {@link #id} instance
    - * No-any params required - * - * @return {@link #id} instance as {@link String} - */ - public String getId() { - return id; - } - -} diff --git a/core/src/main/java/com/tecknobit/novacore/records/NovaNotification.java b/core/src/main/java/com/tecknobit/novacore/records/NovaNotification.java index 7907ecb..6ec618a 100644 --- a/core/src/main/java/com/tecknobit/novacore/records/NovaNotification.java +++ b/core/src/main/java/com/tecknobit/novacore/records/NovaNotification.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.tecknobit.apimanager.annotations.Returner; +import com.tecknobit.equinox.environment.records.EquinoxItem; import jakarta.persistence.*; import org.hibernate.annotations.OnDelete; import org.hibernate.annotations.OnDeleteAction; @@ -23,12 +24,12 @@ * The {@code NovaNotification} class is useful to represent a Nova's notification * * @author N7ghtm4r3 - Tecknobit - * @see NovaItem + * @see EquinoxItem * @see Serializable */ @Entity @Table(name = NOTIFICATIONS_KEY) -public class NovaNotification extends NovaItem { +public class NovaNotification extends EquinoxItem { /** * {@code NOTIFICATIONS_KEY} the key for the "notifications" field diff --git a/core/src/main/java/com/tecknobit/novacore/records/NovaUser.java b/core/src/main/java/com/tecknobit/novacore/records/NovaUser.java index ebd1eb5..1fe5331 100644 --- a/core/src/main/java/com/tecknobit/novacore/records/NovaUser.java +++ b/core/src/main/java/com/tecknobit/novacore/records/NovaUser.java @@ -22,7 +22,7 @@ * The {@code NovaUser} class is useful to represent a Nova's user * * @author N7ghtm4r3 - Tecknobit - * @see NovaItem + * @see EquinoxItem * @see Serializable */ @Entity diff --git a/core/src/main/java/com/tecknobit/novacore/records/project/JoiningQRCode.java b/core/src/main/java/com/tecknobit/novacore/records/project/JoiningQRCode.java index 3c5da7e..84a9e47 100644 --- a/core/src/main/java/com/tecknobit/novacore/records/project/JoiningQRCode.java +++ b/core/src/main/java/com/tecknobit/novacore/records/project/JoiningQRCode.java @@ -1,7 +1,7 @@ package com.tecknobit.novacore.records.project; import com.fasterxml.jackson.annotation.JsonIgnore; -import com.tecknobit.novacore.records.NovaItem; +import com.tecknobit.equinox.environment.records.EquinoxItem; import com.tecknobit.novacore.records.NovaUser.Role; import jakarta.persistence.*; import org.hibernate.annotations.OnDelete; @@ -21,12 +21,12 @@ * The {@code JoiningQRCode} class is useful to represent a Nova's joining QRCode to join in a {@link Project} * * @author N7ghtm4r3 - Tecknobit - * @see NovaItem + * @see EquinoxItem * @see Serializable */ @Entity @Table(name = JoiningQRCode.JOINING_QRCODES_TABLE) -public class JoiningQRCode extends NovaItem { +public class JoiningQRCode extends EquinoxItem { /** * {@code WRONG_NAME_MESSAGE} error message used when the joining qr code is expired diff --git a/core/src/main/java/com/tecknobit/novacore/records/project/Project.java b/core/src/main/java/com/tecknobit/novacore/records/project/Project.java index 8df30ea..a9f0c25 100644 --- a/core/src/main/java/com/tecknobit/novacore/records/project/Project.java +++ b/core/src/main/java/com/tecknobit/novacore/records/project/Project.java @@ -4,8 +4,8 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.tecknobit.apimanager.annotations.Returner; +import com.tecknobit.equinox.environment.records.EquinoxItem; import com.tecknobit.novacore.records.NotificationsTarget; -import com.tecknobit.novacore.records.NovaItem; import com.tecknobit.novacore.records.NovaNotification; import com.tecknobit.novacore.records.NovaUser; import com.tecknobit.novacore.records.release.Release; @@ -29,13 +29,13 @@ * The {@code Project} class is useful to represent a Nova's user * * @author N7ghtm4r3 - Tecknobit - * @see NovaItem + * @see EquinoxItem * @see Serializable * @see NotificationsTarget */ @Entity @Table(name = PROJECTS_KEY) -public class Project extends NovaItem implements NotificationsTarget { +public class Project extends EquinoxItem implements NotificationsTarget { /** * {@code PROJECT_MEMBERS_TABLE} the key for the "project members" table diff --git a/core/src/main/java/com/tecknobit/novacore/records/release/Release.java b/core/src/main/java/com/tecknobit/novacore/records/release/Release.java index eb0294e..2e61b9d 100644 --- a/core/src/main/java/com/tecknobit/novacore/records/release/Release.java +++ b/core/src/main/java/com/tecknobit/novacore/records/release/Release.java @@ -6,7 +6,6 @@ import com.tecknobit.apimanager.annotations.Returner; import com.tecknobit.equinox.environment.records.EquinoxItem; import com.tecknobit.novacore.records.NotificationsTarget; -import com.tecknobit.novacore.records.NovaItem; import com.tecknobit.novacore.records.NovaNotification; import com.tecknobit.novacore.records.NovaUser.Role; import com.tecknobit.novacore.records.project.Project; @@ -34,7 +33,7 @@ * The {@code Release} class is useful to represent a Nova's release * * @author N7ghtm4r3 - Tecknobit - * @see NovaItem + * @see EquinoxItem * @see Serializable * @see NotificationsTarget */ diff --git a/core/src/main/java/com/tecknobit/novacore/records/release/events/AssetUploadingEvent.java b/core/src/main/java/com/tecknobit/novacore/records/release/events/AssetUploadingEvent.java index 4d152ce..3d3b482 100644 --- a/core/src/main/java/com/tecknobit/novacore/records/release/events/AssetUploadingEvent.java +++ b/core/src/main/java/com/tecknobit/novacore/records/release/events/AssetUploadingEvent.java @@ -4,7 +4,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.tecknobit.apimanager.annotations.Returner; -import com.tecknobit.novacore.records.NovaItem; +import com.tecknobit.equinox.environment.records.EquinoxItem; import com.tecknobit.novacore.records.release.Release; import com.tecknobit.novacore.records.release.Release.ReleaseStatus; import jakarta.persistence.*; @@ -26,7 +26,7 @@ * makes change the {@link Release}'s status to {@link ReleaseStatus#Verifying} * * @author N7ghtm4r3 - Tecknobit - * @see NovaItem + * @see EquinoxItem * @see Serializable * @see ReleaseEvent * @see ReleaseStandardEvent @@ -144,12 +144,12 @@ public boolean isCommented() { * The {@code AssetUploaded} class is useful to represent an asset uploaded * * @author N7ghtm4r3 - Tecknobit - * @see NovaItem + * @see EquinoxItem * @see Serializable */ @Entity @Table(name = ASSETS_UPLOADED_KEY) - public static final class AssetUploaded extends NovaItem { + public static final class AssetUploaded extends EquinoxItem { /** * {@code ASSETS_UPLOADED_KEY} the key for the "assets_uploaded" field diff --git a/core/src/main/java/com/tecknobit/novacore/records/release/events/RejectedReleaseEvent.java b/core/src/main/java/com/tecknobit/novacore/records/release/events/RejectedReleaseEvent.java index 56bcb5b..c11dc6b 100644 --- a/core/src/main/java/com/tecknobit/novacore/records/release/events/RejectedReleaseEvent.java +++ b/core/src/main/java/com/tecknobit/novacore/records/release/events/RejectedReleaseEvent.java @@ -1,6 +1,6 @@ package com.tecknobit.novacore.records.release.events; -import com.tecknobit.novacore.records.NovaItem; +import com.tecknobit.equinox.environment.records.EquinoxItem; import com.tecknobit.novacore.records.release.Release; import com.tecknobit.novacore.records.release.Release.ReleaseStatus; import jakarta.persistence.*; @@ -16,7 +16,7 @@ * makes change the {@link Release}'s status to {@link ReleaseStatus#Rejected} * * @author N7ghtm4r3 - Tecknobit - * @see NovaItem + * @see EquinoxItem * @see Serializable * @see ReleaseEvent * @see ReleaseStandardEvent diff --git a/core/src/main/java/com/tecknobit/novacore/records/release/events/RejectedTag.java b/core/src/main/java/com/tecknobit/novacore/records/release/events/RejectedTag.java index 5b75116..abc375c 100644 --- a/core/src/main/java/com/tecknobit/novacore/records/release/events/RejectedTag.java +++ b/core/src/main/java/com/tecknobit/novacore/records/release/events/RejectedTag.java @@ -3,7 +3,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.tecknobit.apimanager.annotations.Returner; -import com.tecknobit.novacore.records.NovaItem; +import com.tecknobit.equinox.environment.records.EquinoxItem; import com.tecknobit.novacore.records.release.events.ReleaseEvent.ReleaseTag; import jakarta.persistence.*; import org.hibernate.annotations.OnDelete; @@ -22,12 +22,12 @@ * The {@code RejectedTag} class is useful represent a rejected tag related to a {@link RejectedReleaseEvent} * * @author N7ghtm4r3 - Tecknobit - * @see NovaItem + * @see EquinoxItem * @see Serializable */ @Entity @Table(name = RejectedTag.REJECTED_TAGS_KEY) -public final class RejectedTag extends NovaItem { +public final class RejectedTag extends EquinoxItem { /** * {@code REJECTED_TAGS_KEY} the key for the "rejected_tags" field diff --git a/core/src/main/java/com/tecknobit/novacore/records/release/events/ReleaseEvent.java b/core/src/main/java/com/tecknobit/novacore/records/release/events/ReleaseEvent.java index e3b8112..d6c0bc8 100644 --- a/core/src/main/java/com/tecknobit/novacore/records/release/events/ReleaseEvent.java +++ b/core/src/main/java/com/tecknobit/novacore/records/release/events/ReleaseEvent.java @@ -6,7 +6,6 @@ import com.tecknobit.apimanager.annotations.Returner; import com.tecknobit.apimanager.annotations.Structure; import com.tecknobit.equinox.environment.records.EquinoxItem; -import com.tecknobit.novacore.records.NovaItem; import com.tecknobit.novacore.records.release.Release; import jakarta.persistence.*; import org.json.JSONArray; @@ -24,7 +23,7 @@ * The {@code ReleaseEvent} class is useful to represent a Nova's release event * * @author N7ghtm4r3 - Tecknobit - * @see NovaItem + * @see EquinoxItem * @see Serializable */ @Entity diff --git a/core/src/main/java/com/tecknobit/novacore/records/release/events/ReleaseStandardEvent.java b/core/src/main/java/com/tecknobit/novacore/records/release/events/ReleaseStandardEvent.java index de02c5b..3eaf0b0 100644 --- a/core/src/main/java/com/tecknobit/novacore/records/release/events/ReleaseStandardEvent.java +++ b/core/src/main/java/com/tecknobit/novacore/records/release/events/ReleaseStandardEvent.java @@ -1,6 +1,5 @@ package com.tecknobit.novacore.records.release.events; - -import com.tecknobit.novacore.records.NovaItem; +import com.tecknobit.equinox.environment.records.EquinoxItem; import com.tecknobit.novacore.records.release.Release; import com.tecknobit.novacore.records.release.Release.ReleaseStatus; import jakarta.persistence.Entity; @@ -17,7 +16,7 @@ * The {@code ReleaseStandardEvent} class is useful to represent a standard Nova's release event * * @author N7ghtm4r3 - Tecknobit - * @see NovaItem + * @see EquinoxItem * @see Serializable * @see ReleaseEvent */ diff --git a/core/src/main/kotlin/com/tecknobit/novacore/helpers/NovaRequester.kt b/core/src/main/kotlin/com/tecknobit/novacore/helpers/NovaRequester.kt index aab1094..50926da 100644 --- a/core/src/main/kotlin/com/tecknobit/novacore/helpers/NovaRequester.kt +++ b/core/src/main/kotlin/com/tecknobit/novacore/helpers/NovaRequester.kt @@ -5,8 +5,8 @@ import com.tecknobit.apimanager.annotations.Wrapper import com.tecknobit.apimanager.apis.APIRequest import com.tecknobit.apimanager.apis.APIRequest.Params import com.tecknobit.equinox.environment.helpers.EquinoxRequester -import com.tecknobit.novacore.helpers.Endpoints.* -import com.tecknobit.novacore.records.NovaItem.IDENTIFIER_KEY +import com.tecknobit.equinox.environment.records.EquinoxItem.IDENTIFIER_KEY +import com.tecknobit.novacore.helpers.NovaEndpoints.* import com.tecknobit.novacore.records.NovaNotification.NOTIFICATIONS_KEY import com.tecknobit.novacore.records.NovaUser.* import com.tecknobit.novacore.records.project.JoiningQRCode.CREATE_JOIN_CODE_KEY From ccf524694edd95d7bc5fba2308884f417cf3bd55 Mon Sep 17 00:00:00 2001 From: N7ghtm4r3 Date: Fri, 20 Sep 2024 15:25:45 +0200 Subject: [PATCH 04/25] Working on NovaUser.Role.Tester role integration --- .../projectmanagers/ProjectManager.java | 4 +- .../projectmanagers/ReleasesController.java | 23 +++---- .../novacore/helpers/LocalSessionUtils.java | 10 +++ .../novacore/helpers/NovaEndpoints.java | 4 +- .../tecknobit/novacore/records/NovaUser.java | 63 ++++++++++++----- .../novacore/records/project/Project.java | 69 ++++++++++++++++--- .../novacore/records/release/Release.java | 4 +- .../release/events/AssetUploadingEvent.java | 2 +- .../novacore/helpers/NovaRequester.kt | 6 +- 9 files changed, 135 insertions(+), 50 deletions(-) diff --git a/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectManager.java b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectManager.java index abb92f3..118d04b 100644 --- a/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectManager.java +++ b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectManager.java @@ -57,7 +57,7 @@ protected boolean amIProjectMember(String userId, String projectId) { */ protected boolean isAuthorizedUser(String userId, String projectId) { Project project = projectsHelper.getProject(userId, projectId); - return isProjectAuthor(project, userId) || me.isVendor(); + return (isProjectAuthor(project, userId) || (me.isVendor() && !me.isTester(currentProject))); } /** @@ -72,7 +72,7 @@ protected boolean isAuthorizedUser(String userId, String projectId) { protected boolean isUserQualified(String userId, String projectId) { Project project = projectsHelper.getProject(userId, projectId); currentProject = project; - return ((project != null)) && me.isCustomer(); + return (((project != null)) && (me.isCustomer() || me.isTester(currentProject))); } /** diff --git a/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ReleasesController.java b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ReleasesController.java index 4970c5a..3e0e8d7 100644 --- a/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ReleasesController.java +++ b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ReleasesController.java @@ -44,7 +44,7 @@ */ @RestController @RequestMapping(BASE_EQUINOX_ENDPOINT + "{" + IDENTIFIER_KEY + "}/" + PROJECTS_KEY + "/{" + PROJECT_IDENTIFIER_KEY + "}/" - + RELEASES_KEY + "/") + + RELEASES_KEY) public class ReleasesController extends ProjectManager { /** @@ -89,19 +89,18 @@ public ReleasesController(ProjectsHelper projectsHelper, ReleasesHelper releases * @return the result of the request as {@link String} */ @PostMapping( - path = ADD_RELEASE_ENDPOINT, headers = { TOKEN_KEY } ) - @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/addRelease", method = POST) + @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases", method = POST) public String addRelease( @PathVariable(IDENTIFIER_KEY) String id, @PathVariable(PROJECT_IDENTIFIER_KEY) String projectId, @RequestHeader(TOKEN_KEY) String token, @RequestBody Map payload ) { - if(isMe(id, token) && amIProjectMember(id, projectId)) { + if(isMe(id, token) && amIProjectMember(id, projectId) && !me.isTester(currentProject)) { loadJsonHelper(payload); String releaseVersion = jsonHelper.getString(RELEASE_VERSION_KEY); releaseVersion = releaseVersion.replaceFirst("^v\\.", ""); @@ -144,7 +143,7 @@ public String addRelease( * @apiNote the notifications related to the release belong to the user will be set as red and deleted */ @GetMapping( - path = "{" + RELEASE_IDENTIFIER_KEY + "}", + path = "/{" + RELEASE_IDENTIFIER_KEY + "}", headers = { TOKEN_KEY } @@ -181,7 +180,7 @@ public T getRelease( * @apiNote this request, if successful, will make change the release status to {@link ReleaseStatus#Verifying} */ @PostMapping( - path = "{" + RELEASE_IDENTIFIER_KEY + "}", + path = "/{" + RELEASE_IDENTIFIER_KEY + "}" + UPLOAD_ASSETS_ENDPOINT, headers = { TOKEN_KEY } @@ -257,7 +256,7 @@ public String uploadAsset( * {@link ReleaseStatus#Rejected} */ @PostMapping( - path = "{" + RELEASE_IDENTIFIER_KEY + "}" + COMMENT_ASSET_ENDPOINT + "{" + ASSET_UPLOADING_EVENT_IDENTIFIER_KEY + "}", + path = "/{" + RELEASE_IDENTIFIER_KEY + "}" + COMMENT_ASSET_ENDPOINT + "{" + ASSET_UPLOADING_EVENT_IDENTIFIER_KEY + "}", headers = { TOKEN_KEY } @@ -347,7 +346,7 @@ public String commentAssets( * @return the result of the request as {@link String} */ @PutMapping( - path = "{" + RELEASE_IDENTIFIER_KEY + "}" + EVENTS_ENDPOINT + "{" + RELEASE_EVENT_IDENTIFIER_KEY + "}" + path = "/{" + RELEASE_IDENTIFIER_KEY + "}" + EVENTS_ENDPOINT + "{" + RELEASE_EVENT_IDENTIFIER_KEY + "}" + TAGS_ENDPOINT + "{" + RELEASE_TAG_IDENTIFIER_KEY + "}", headers = { TOKEN_KEY @@ -409,7 +408,7 @@ public String fillRejectedTag( * @return the result of the request as {@link String} */ @PatchMapping( - path = "{" + RELEASE_IDENTIFIER_KEY + "}", + path = "/{" + RELEASE_IDENTIFIER_KEY + "}", headers = { TOKEN_KEY } @@ -479,7 +478,7 @@ public String promoteRelease( * @return the result of the request as {@link String}, if successful includes the path to reach the report */ @GetMapping( - path = "{" + RELEASE_IDENTIFIER_KEY + "}" + CREATE_REPORT_ENDPOINT, + path = "/{" + RELEASE_IDENTIFIER_KEY + "}" + CREATE_REPORT_ENDPOINT, headers = { TOKEN_KEY } @@ -521,7 +520,7 @@ public String createReport( * @return the result of the request as {@link String} */ @DeleteMapping( - path = "{" + RELEASE_IDENTIFIER_KEY + "}", + path = "/{" + RELEASE_IDENTIFIER_KEY + "}", headers = { TOKEN_KEY } @@ -533,7 +532,7 @@ public String deleteRelease( @PathVariable(RELEASE_IDENTIFIER_KEY) String releaseId, @RequestHeader(TOKEN_KEY) String token ) { - if(isMe(id, token) && amIProjectMember(id, projectId)) { + if(isMe(id, token) && amIProjectMember(id, projectId) && !me.isTester(currentProject)) { Release release = getReleaseIfAuthorized(releaseId); if(release != null) { releasesHelper.deleteRelease(id, currentProject, release); diff --git a/core/src/main/java/com/tecknobit/novacore/helpers/LocalSessionUtils.java b/core/src/main/java/com/tecknobit/novacore/helpers/LocalSessionUtils.java index fb0db31..09148f3 100644 --- a/core/src/main/java/com/tecknobit/novacore/helpers/LocalSessionUtils.java +++ b/core/src/main/java/com/tecknobit/novacore/helpers/LocalSessionUtils.java @@ -440,6 +440,16 @@ public boolean isVendor() { return role == Role.Vendor; } + /** + * Method to get whether the member is a {@link Role#Tester}
    + * No-any params required + * + * @return whether the member is a {@link Role#Tester} as boolean + */ + public boolean isTester() { + return role == Role.Tester; + } + /** * Method to get whether the member is a {@link Role#Customer}
    * No-any params required diff --git a/core/src/main/java/com/tecknobit/novacore/helpers/NovaEndpoints.java b/core/src/main/java/com/tecknobit/novacore/helpers/NovaEndpoints.java index 14f70ca..045e53e 100644 --- a/core/src/main/java/com/tecknobit/novacore/helpers/NovaEndpoints.java +++ b/core/src/main/java/com/tecknobit/novacore/helpers/NovaEndpoints.java @@ -30,9 +30,9 @@ public class NovaEndpoints extends EquinoxBaseEndpointsSet { public static final String LEAVE_ENDPOINT = "/leave"; /** - * {@code ADD_RELEASE_ENDPOINT} the endpoint to add a new release + * {@code UPLOAD_ASSETS_ENDPOINT} the endpoint to upload assets to a release */ - public static final String ADD_RELEASE_ENDPOINT = "/addRelease"; + public static final String UPLOAD_ASSETS_ENDPOINT = "/uploadAssets"; /** * {@code COMMENT_ASSET_ENDPOINT} the endpoint to comment an asset uploading of a release diff --git a/core/src/main/java/com/tecknobit/novacore/records/NovaUser.java b/core/src/main/java/com/tecknobit/novacore/records/NovaUser.java index 1fe5331..7ad0acc 100644 --- a/core/src/main/java/com/tecknobit/novacore/records/NovaUser.java +++ b/core/src/main/java/com/tecknobit/novacore/records/NovaUser.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.tecknobit.apimanager.annotations.Returner; +import com.tecknobit.equinox.environment.records.EquinoxItem; import com.tecknobit.equinox.environment.records.EquinoxUser; import com.tecknobit.novacore.records.project.Project; import jakarta.persistence.*; @@ -39,6 +40,11 @@ public enum Role { */ Vendor, + /** + * {@code Tester} this pseudo-role allow the user to approve or reject the releases + */ + Tester, + /** * {@code Customer} this role allow the user to approve or reject the releases and manage their * creation or deletion @@ -97,11 +103,12 @@ public enum Role { * {@code role} the role of the user on the server * * @apiNote this value cannot change on server, this means when the user - * execute the authentication on the server with a role it will be ever the same + * execute the authentication on the server with a role it will be ever the same, but it can be set as {@link Role#Tester} + * for each project where him/her is member */ @Enumerated(value = STRING) @Column(name = ROLE_KEY) - private final Role role; + private Role role; /** * {@code NovaNotification} the list of the notifications which belong to the user @@ -147,13 +154,13 @@ public NovaUser(JSONObject jUser) { * Constructor to init the {@link NovaUser} class * * @param id: identifier of the user - * @param token:{@code token} the token which the user is allowed to operate on server - * @param name:{@code name} the name of the user - * @param surname:{@code surname} the surname of the user - * @param email:{@code email} the email of the user - * @param password:{@code password} the password of the user - * @param language:{@code language} the language selected by the user - * @param role:{@code role} the role of the user on the server @apiNote this value cannot change on server, this means when the user execute the authentication on the server with a role it will be ever the same + * @param token: the token which the user is allowed to operate on server + * @param name: the name of the user + * @param surname: the surname of the user + * @param email: the email of the user + * @param password: the password of the user + * @param language: the language selected by the user + * @param role: the role of the user on the server */ public NovaUser(String id, String token, String name, String surname, String email, String password, String language, Role role) { @@ -165,16 +172,16 @@ public NovaUser(String id, String token, String name, String surname, String ema * * * @param id: identifier of the user - * @param token:{@code token} the token which the user is allowed to operate on server - * @param name:{@code name} the name of the user - * @param surname:{@code surname} the surname of the user - * @param email:{@code email} the email of the user + * @param token: the token which the user is allowed to operate on server + * @param name: the name of the user + * @param surname: the surname of the user + * @param email: the email of the user * @param profilePicUrl:{@code profilePicUrl} the profile pic of the user formatted as url - * @param password:{@code password} the password of the user - * @param authoredProjects:{@code authoredProjects} list of projects which user is the author @apiNote if the user is a {@link Role#Customer} will be ever empty + * @param password: the password of the user + * @param authoredProjects:{@code authoredProjects} list of projects which user is the author * @param projects:{@code projects} list of projects which user is a member - * @param language:{@code language} the language selected by the user - * @param role:{@code role} the role of the user on the server @apiNote this value cannot change on server, this means when the user execute the authentication on the server with a role it will be ever the same + * @param language: the language selected by the user + * @param role: the role of the user on the server * @param notifications:{@code NovaNotification} the list of the notifications which belong to the user */ public NovaUser(String id, String name, String surname, String email, String profilePicUrl, String token, String password, @@ -197,6 +204,15 @@ public List getProjects() { return projects; } + /** + * Method to set the {@link #role} instance + * + * @param role: the role of the user + */ + public void setRole(Role role) { + this.role = role; + } + /** * Method to get {@link #role} instance
    * No-any params required @@ -228,6 +244,19 @@ public boolean isVendor() { return role == Role.Vendor; } + /** + * Method to get whether the member is a {@link Role#Tester}
    + * No-any params required + * + * @param project: the project to check if the user is a {@link Role#Tester} + * + * @return whether the member is a {@link Role#Tester} as boolean + */ + @JsonIgnore + public boolean isTester(Project project) { + return project.getTesters().contains(id); + } + /** * Method to get whether the member is a {@link Role#Customer}
    * No-any params required diff --git a/core/src/main/java/com/tecknobit/novacore/records/project/Project.java b/core/src/main/java/com/tecknobit/novacore/records/project/Project.java index a9f0c25..0fa4aa0 100644 --- a/core/src/main/java/com/tecknobit/novacore/records/project/Project.java +++ b/core/src/main/java/com/tecknobit/novacore/records/project/Project.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.tecknobit.apimanager.annotations.Returner; +import com.tecknobit.apimanager.formatters.JsonHelper; import com.tecknobit.equinox.environment.records.EquinoxItem; import com.tecknobit.novacore.records.NotificationsTarget; import com.tecknobit.novacore.records.NovaNotification; @@ -19,7 +20,9 @@ import java.io.Serializable; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import static com.tecknobit.novacore.records.NovaNotification.NOTIFICATIONS_KEY; import static com.tecknobit.novacore.records.NovaUser.*; @@ -42,6 +45,11 @@ public class Project extends EquinoxItem implements NotificationsTarget { */ public static final String PROJECT_MEMBERS_TABLE = "project_members"; + /** + * {@code PROJECT_TESTERS_TABLE} the key for the "project testers" table + */ + public static final String PROJECT_TESTERS_TABLE = "project_testers"; + /** * {@code PROJECT_IDENTIFIER_KEY} the key for the "project_id" field */ @@ -72,6 +80,11 @@ public class Project extends EquinoxItem implements NotificationsTarget { */ public static final String PROJECT_MEMBERS_KEY = "projectMembers"; + /** + * {@code PROJECT_TESTERS_KEY} the key for the "testers" field + */ + public static final String PROJECT_TESTERS_KEY = "testers"; + /** * {@code WORKING_PROGRESS_VERSION_KEY} the key for the "working_progress_version" field */ @@ -141,6 +154,14 @@ public class Project extends EquinoxItem implements NotificationsTarget { }) private final List projectMembers; + // TODO: 20/09/2024 TO COMMENT + @ElementCollection + @CollectionTable( + name = PROJECT_TESTERS_TABLE + ) + @Column(name = MEMBER_IDENTIFIER_KEY) + private Set testers; + /** * {@code releases} the releases of the project */ @@ -171,7 +192,7 @@ public class Project extends EquinoxItem implements NotificationsTarget { * @apiNote empty constructor required */ public Project() { - this(null, null, null, null, List.of(), List.of(), List.of()); + this(null, null, null, null, List.of(), new HashSet<>(), List.of(), List.of()); } /** @@ -186,33 +207,49 @@ public Project(JSONObject jProject) { logoUrl = hItem.getString(LOGO_URL_KEY); name = hItem.getString(PROJECT_NAME_KEY); projectMembers = NovaUser.returnUsersList(hItem.getJSONArray(PROJECT_MEMBERS_KEY)); + JSONArray testers = hItem.getJSONArray(PROJECT_TESTERS_KEY, new JSONArray()); releases = Release.returnReleasesList(hItem.getJSONArray(RELEASES_KEY)); joiningQRCodes = null; + markProjectTesters(testers); } /** * Constructor to init the {@link Project} class * - * @param id: identifier of the project - * @param author the author of the project - * @param logoUrl: the logo of the project formatted as url - * @param name: the name of the project - * @param projectMembers: the members of the project - * @param releases: the releases of the project - * @param joiningQRCodes: the joining QR-Codes created to join in this project - * + * @param id : identifier of the project + * @param author the author of the project + * @param logoUrl : the logo of the project formatted as url + * @param name : the name of the project + * @param projectMembers : the members of the project + * @param testers: TODO: TO COMMENT + * @param releases : the releases of the project + * @param joiningQRCodes : the joining QR-Codes created to join in this project * @apiNote this is useful for the server-side, so for the clients will be ever hidden - * */ public Project(String id, NovaUser author, String logoUrl, String name, List projectMembers, - List releases, List joiningQRCodes) { + HashSet testers, List releases, List joiningQRCodes) { super(id); this.author = author; this.logoUrl = logoUrl; this.name = name; this.projectMembers = projectMembers; + this.testers = testers; this.releases = releases; this.joiningQRCodes = joiningQRCodes; + markProjectTesters(testers); + } + + // TODO: 20/09/2024 TO COMMENT + private void markProjectTesters(JSONArray jTesters) { + markProjectTesters(new HashSet<>(JsonHelper.toList(jTesters))); + } + + // TODO: 20/09/2024 TO COMMENT + private void markProjectTesters(HashSet testers) { + this.testers = testers; + for (NovaUser member : projectMembers) + if(testers.contains(member.getId())) + member.setRole(Role.Tester); } /** @@ -256,6 +293,16 @@ public List getProjectMembers() { return projectMembers; } + /** + * Method to get {@link #testers} instance
    + * No-any params required + * + * @return {@link #testers} instance as {@link HashSet} of {@link String} + */ + public Set getTesters() { + return testers; + } + /** * Method to get the {@link #"workingProgressVersion"}
    * No-any params required diff --git a/core/src/main/java/com/tecknobit/novacore/records/release/Release.java b/core/src/main/java/com/tecknobit/novacore/records/release/Release.java index 2e61b9d..dee42b7 100644 --- a/core/src/main/java/com/tecknobit/novacore/records/release/Release.java +++ b/core/src/main/java/com/tecknobit/novacore/records/release/Release.java @@ -24,8 +24,7 @@ import java.util.ArrayList; import java.util.List; -import static com.tecknobit.novacore.records.project.Project.PROJECT_KEY; -import static com.tecknobit.novacore.records.project.Project.PROJECT_MEMBERS_KEY; +import static com.tecknobit.novacore.records.project.Project.*; import static com.tecknobit.novacore.records.release.Release.ReleaseStatus.*; import static com.tecknobit.novacore.records.release.events.ReleaseEvent.RELEASE_EVENT_DATE_KEY; @@ -203,6 +202,7 @@ public String getColor() { @JsonIgnoreProperties({ PROJECT_MEMBERS_KEY, RELEASES_KEY, + PROJECT_TESTERS_KEY, "hibernateLazyInitializer", "handler" }) diff --git a/core/src/main/java/com/tecknobit/novacore/records/release/events/AssetUploadingEvent.java b/core/src/main/java/com/tecknobit/novacore/records/release/events/AssetUploadingEvent.java index 3d3b482..2772a24 100644 --- a/core/src/main/java/com/tecknobit/novacore/records/release/events/AssetUploadingEvent.java +++ b/core/src/main/java/com/tecknobit/novacore/records/release/events/AssetUploadingEvent.java @@ -70,7 +70,7 @@ public class AssetUploadingEvent extends ReleaseStandardEvent { private final List assetsUploaded; /** - * {@code commented} whether these assets have already been commented by the {@link Role#Customer} + * {@code commented} whether these assets have already been commented by the {@link Role#Customer} or {@link Role#Tester} */ @Column( name = COMMENTED_KEY, diff --git a/core/src/main/kotlin/com/tecknobit/novacore/helpers/NovaRequester.kt b/core/src/main/kotlin/com/tecknobit/novacore/helpers/NovaRequester.kt index 50926da..8d406b6 100644 --- a/core/src/main/kotlin/com/tecknobit/novacore/helpers/NovaRequester.kt +++ b/core/src/main/kotlin/com/tecknobit/novacore/helpers/NovaRequester.kt @@ -330,8 +330,7 @@ class NovaRequester( payload.addParam(RELEASE_NOTES_KEY, releaseNotes) return execPost( endpoint = assembleReleasesEndpointPath( - projectId = projectId, - endpoint = ADD_RELEASE_ENDPOINT + projectId = projectId ), payload = payload ) @@ -385,7 +384,8 @@ class NovaRequester( body = body.build(), endpoint = assembleReleasesEndpointPath( projectId = projectId, - releaseId = releaseId + releaseId = releaseId, + endpoint = UPLOAD_ASSETS_ENDPOINT ) ) } From 97046a1670c2caf1f6a71b009e02f75c2f01a278 Mon Sep 17 00:00:00 2001 From: N7ghtm4r3 Date: Fri, 20 Sep 2024 17:15:44 +0200 Subject: [PATCH 05/25] Working on NovaUser.Role.Tester role integration --- .../projectmanagers/ProjectManager.java | 2 +- .../projectmanagers/ProjectsController.java | 55 +++++++++++++++- .../nova/helpers/services/ProjectsHelper.java | 14 +++- .../projectsutils/ProjectsRepository.java | 41 ++++++++++++ .../novacore/helpers/NovaEndpoints.java | 5 ++ .../novacore/records/project/Project.java | 49 ++++++++++---- .../novacore/helpers/NovaRequester.kt | 66 ++++++++++++------- 7 files changed, 193 insertions(+), 39 deletions(-) diff --git a/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectManager.java b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectManager.java index 118d04b..cedf95d 100644 --- a/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectManager.java +++ b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectManager.java @@ -57,7 +57,7 @@ protected boolean amIProjectMember(String userId, String projectId) { */ protected boolean isAuthorizedUser(String userId, String projectId) { Project project = projectsHelper.getProject(userId, projectId); - return (isProjectAuthor(project, userId) || (me.isVendor() && !me.isTester(currentProject))); + return (isProjectAuthor(project, userId) || (currentProject != null && me.isVendor() && !me.isTester(currentProject))); } /** diff --git a/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectsController.java b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectsController.java index 4a7bcf7..fb941fc 100644 --- a/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectsController.java +++ b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectsController.java @@ -15,6 +15,7 @@ import org.springframework.web.multipart.MultipartFile; import java.security.NoSuchAlgorithmException; +import java.sql.SQLException; import java.util.List; import java.util.Map; @@ -318,6 +319,57 @@ public String join( return failedResponse(WRONG_PROCEDURE_MESSAGE); } + /** + * Method to mark a member as {@link Role#Tester} of the project + * + * @param id: the identifier of the user + * @param projectId: the project identifier from remove the member + * @param token: the token of the user + * @param payload: payload of the request + *
    +     *      {@code
    +     *              {
    +     *                  "member_id": "the identifier of the member to remove", -> [String]
    +     *              }
    +     *      }
    +     * 
    + * + * @return the result of the request as {@link String} + */ + @PatchMapping( + path = "/{" + IDENTIFIER_KEY + "}/" + PROJECTS_KEY + "/{" + PROJECT_IDENTIFIER_KEY + "}" + + MARK_MEMBER_AS_TESTER_ENDPOINT, + headers = { + TOKEN_KEY + } + ) + @RequestPath(path = "/api/v1/{id}/projects/{projectId}/markAsTester", method = PATCH) + public String markAsTester( + @PathVariable(IDENTIFIER_KEY) String id, + @PathVariable(PROJECT_IDENTIFIER_KEY) String projectId, + @RequestHeader(TOKEN_KEY) String token, + @RequestBody Map payload + ) { + if(isMe(id, token) && isAuthorizedUser(id, projectId)) { + loadJsonHelper(payload); + String memberId = jsonHelper.getString(MEMBER_IDENTIFIER_KEY); + if(currentProject.hasMemberId(memberId)) { + boolean amITheProjectAuthor = currentProject.amITheProjectAuthor(id); + if(amITheProjectAuthor || !currentProject.amITheProjectAuthor(memberId)) { + try { + projectsHelper.markMemberAsTester(projectId, memberId); + return successResponse(); + } catch (Exception e) { + return failedResponse(WRONG_PROCEDURE_MESSAGE); + } + } else + return failedResponse(WRONG_PROCEDURE_MESSAGE); + } else + return failedResponse(WRONG_PROCEDURE_MESSAGE); + } else + return failedResponse(NOT_AUTHORIZED_OR_WRONG_DETAILS_MESSAGE); + } + /** * Method to remove a member from a project * @@ -351,8 +403,7 @@ public String removeMember( if(isMe(id, token) && isAuthorizedUser(id, projectId)) { loadJsonHelper(payload); String memberId = jsonHelper.getString(MEMBER_IDENTIFIER_KEY); - Project project = projectsHelper.getProject(id, projectId); - if(project.hasMemberId(memberId) && !isProjectAuthor(memberId, projectId)) { + if(currentProject.hasMemberId(memberId) && !isProjectAuthor(memberId, projectId)) { projectsHelper.removeMember(projectId, memberId); return successResponse(); } else diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java index 557995e..c6287e4 100644 --- a/backend/src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java @@ -6,6 +6,7 @@ import com.tecknobit.nova.helpers.services.repositories.projectsutils.ProjectsRepository; import com.tecknobit.nova.helpers.services.repositories.releaseutils.NotificationsRepository; import com.tecknobit.novacore.records.NovaUser; +import com.tecknobit.novacore.records.NovaUser.Role; import com.tecknobit.novacore.records.project.JoiningQRCode; import com.tecknobit.novacore.records.project.Project; import com.tecknobit.novacore.records.release.Release; @@ -121,7 +122,7 @@ public Project getProject(String userId, String projectId) { * @param createJoinQRCode: whether create a textual join code * @return the textual join code, if created, as {@link String} */ - public String createJoiningQrcode(String QRCodeId, String projectId, List membersEmails, NovaUser.Role role, + public String createJoiningQrcode(String QRCodeId, String projectId, List membersEmails, Role role, boolean createJoinQRCode) { String joinCode = null; if(createJoinQRCode) @@ -210,6 +211,16 @@ public void deleteJoiningQrcode(String QRCodeId) { joiningQRCodeRepository.deleteJoiningQRCode(QRCodeId); } + /** + * Method to mark a member as {@link Role#Tester} of the project + * + * @param projectId: the project identifier + * @param memberId: the member identifier to mark as tester + */ + public void markMemberAsTester(String projectId, String memberId) { + projectsRepository.markMemberAsTester(projectId, memberId); + } + /** * Method to remove a member from a project * @param projectId: the project identifier @@ -230,6 +241,7 @@ public void deleteProject(String authorId, Project project) { for (Release release : project.getReleases()) releasesHelper.deleteRelease(null, null, release); projectsRepository.removeAllMembers(projectId); + projectsRepository.removeAllTesters(projectId); List members = project.getProjectMembers(); members.add(project.getAuthor()); for(NovaUser member : members) { diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/ProjectsRepository.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/ProjectsRepository.java index bc12786..71028b1 100644 --- a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/ProjectsRepository.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/ProjectsRepository.java @@ -1,5 +1,6 @@ package com.tecknobit.nova.helpers.services.repositories.projectsutils; +import com.tecknobit.novacore.records.NovaUser.Role; import com.tecknobit.novacore.records.project.Project; import jakarta.transaction.Transactional; import org.springframework.data.jpa.repository.JpaRepository; @@ -124,6 +125,31 @@ void joinMember( @Param(MEMBER_IDENTIFIER_KEY) String memberId ); + /** + * Method to execute the query to mark a member as {@link Role#Tester} + * + * @param projectId: the identifier of the project + * @param memberId: the identifier of the member to mark as tester + */ + @Modifying(clearAutomatically = true) + @Transactional + @Query( + value = "INSERT INTO " + PROJECT_TESTERS_TABLE + + " (" + + PROJECT_IDENTIFIER_KEY + "," + + MEMBER_IDENTIFIER_KEY + + " )" + + " VALUES (" + + ":" + PROJECT_IDENTIFIER_KEY + "," + + ":" + MEMBER_IDENTIFIER_KEY + + ")", + nativeQuery = true + ) + void markMemberAsTester( + @Param(PROJECT_IDENTIFIER_KEY) String projectId, + @Param(MEMBER_IDENTIFIER_KEY) String memberId + ); + /** * Method to execute the query to remove a member from an existing {@link Project} * @@ -157,6 +183,21 @@ void removeAllMembers( @Param(IDENTIFIER_KEY) String projectId ); + /** + * Method to execute the query to remove all testers from a {@link Project} + * + * @param projectId: the identifier of the project + */ + @Modifying(clearAutomatically = true) + @Transactional + @Query( + value = "DELETE FROM " + PROJECT_TESTERS_TABLE + " WHERE " + PROJECT_IDENTIFIER_KEY + "=:" + PROJECT_IDENTIFIER_KEY, + nativeQuery = true + ) + void removeAllTesters( + @Param(PROJECT_IDENTIFIER_KEY) String projectId + ); + /** * Method to execute the query to delete an existing {@link Project} * diff --git a/core/src/main/java/com/tecknobit/novacore/helpers/NovaEndpoints.java b/core/src/main/java/com/tecknobit/novacore/helpers/NovaEndpoints.java index 045e53e..352315e 100644 --- a/core/src/main/java/com/tecknobit/novacore/helpers/NovaEndpoints.java +++ b/core/src/main/java/com/tecknobit/novacore/helpers/NovaEndpoints.java @@ -19,6 +19,11 @@ public class NovaEndpoints extends EquinoxBaseEndpointsSet { */ public static final String JOIN_ENDPOINT = "/join"; + /** + * {@code MARK_MEMBER_AS_TESTER_ENDPOINT} the endpoint to mark a member as tester in a project + */ + public static final String MARK_MEMBER_AS_TESTER_ENDPOINT = "/markAsTester"; + /** * {@code REMOVE_MEMBER_ENDPOINT} the endpoint to remove a member from a project */ diff --git a/core/src/main/java/com/tecknobit/novacore/records/project/Project.java b/core/src/main/java/com/tecknobit/novacore/records/project/Project.java index 0fa4aa0..8d11d08 100644 --- a/core/src/main/java/com/tecknobit/novacore/records/project/Project.java +++ b/core/src/main/java/com/tecknobit/novacore/records/project/Project.java @@ -154,13 +154,28 @@ public class Project extends EquinoxItem implements NotificationsTarget { }) private final List projectMembers; - // TODO: 20/09/2024 TO COMMENT - @ElementCollection - @CollectionTable( - name = PROJECT_TESTERS_TABLE + /** + * {@code testers} the testers of the project + */ + @ManyToMany( + fetch = FetchType.LAZY, + cascade = CascadeType.REMOVE + ) + @JoinTable( + name = PROJECT_TESTERS_TABLE, + joinColumns = {@JoinColumn(name = PROJECT_IDENTIFIER_KEY)}, + inverseJoinColumns = {@JoinColumn(name = MEMBER_IDENTIFIER_KEY)} ) - @Column(name = MEMBER_IDENTIFIER_KEY) - private Set testers; + @JsonIgnoreProperties({ + TOKEN_KEY, + PASSWORD_KEY, + PROJECTS_KEY, + AUTHORED_PROJECTS_KEY, + NOTIFICATIONS_KEY, + "hibernateLazyInitializer", + "handler" + }) + private Set testers; /** * {@code releases} the releases of the project @@ -221,13 +236,13 @@ public Project(JSONObject jProject) { * @param logoUrl : the logo of the project formatted as url * @param name : the name of the project * @param projectMembers : the members of the project - * @param testers: TODO: TO COMMENT + * @param testers: the testers of the project * @param releases : the releases of the project * @param joiningQRCodes : the joining QR-Codes created to join in this project * @apiNote this is useful for the server-side, so for the clients will be ever hidden */ public Project(String id, NovaUser author, String logoUrl, String name, List projectMembers, - HashSet testers, List releases, List joiningQRCodes) { + HashSet testers, List releases, List joiningQRCodes) { super(id); this.author = author; this.logoUrl = logoUrl; @@ -239,16 +254,24 @@ public Project(String id, NovaUser author, String logoUrl, String name, List(JsonHelper.toList(jTesters))); } - // TODO: 20/09/2024 TO COMMENT - private void markProjectTesters(HashSet testers) { + /** + * Method to mark the {@link #projectMembers} of the project as {@link Role#Tester} + * + * @param testers: the list of the members to mark as testers + */ + private void markProjectTesters(HashSet testers) { this.testers = testers; for (NovaUser member : projectMembers) - if(testers.contains(member.getId())) + if(testers.contains(member)) member.setRole(Role.Tester); } @@ -299,7 +322,7 @@ public List getProjectMembers() { * * @return {@link #testers} instance as {@link HashSet} of {@link String} */ - public Set getTesters() { + public Set getTesters() { return testers; } diff --git a/core/src/main/kotlin/com/tecknobit/novacore/helpers/NovaRequester.kt b/core/src/main/kotlin/com/tecknobit/novacore/helpers/NovaRequester.kt index 8d406b6..f4cfc1b 100644 --- a/core/src/main/kotlin/com/tecknobit/novacore/helpers/NovaRequester.kt +++ b/core/src/main/kotlin/com/tecknobit/novacore/helpers/NovaRequester.kt @@ -2,8 +2,8 @@ package com.tecknobit.novacore.helpers import com.tecknobit.apimanager.annotations.RequestPath import com.tecknobit.apimanager.annotations.Wrapper -import com.tecknobit.apimanager.apis.APIRequest import com.tecknobit.apimanager.apis.APIRequest.Params +import com.tecknobit.apimanager.apis.APIRequest.RequestMethod.* import com.tecknobit.equinox.environment.helpers.EquinoxRequester import com.tecknobit.equinox.environment.records.EquinoxItem.IDENTIFIER_KEY import com.tecknobit.novacore.helpers.NovaEndpoints.* @@ -49,7 +49,7 @@ class NovaRequester( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/users/{id}/notifications", method = APIRequest.RequestMethod.GET) + @RequestPath(path = "/api/v1/users/{id}/notifications", method = GET) fun getNotifications(): JSONObject { return execGet( endpoint = assembleUsersEndpointPath("/$NOTIFICATIONS_KEY") @@ -63,7 +63,7 @@ class NovaRequester( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/{id}/projects", method = APIRequest.RequestMethod.GET) + @RequestPath(path = "/api/v1/{id}/projects", method = GET) fun listProjects() : JSONObject { return execGet( endpoint = assembleProjectsEndpointPath() @@ -78,7 +78,7 @@ class NovaRequester( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/{id}/projects", method = APIRequest.RequestMethod.POST) + @RequestPath(path = "/api/v1/{id}/projects", method = POST) fun addProject( logoPic: File, projectName: String @@ -107,7 +107,7 @@ class NovaRequester( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/{id}/projects/{projectId}", method = APIRequest.RequestMethod.GET) + @RequestPath(path = "/api/v1/{id}/projects/{projectId}", method = GET) fun getProject( projectId: String ) : JSONObject { @@ -126,7 +126,7 @@ class NovaRequester( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/{id}/projects/{projectId}/addMembers", method = APIRequest.RequestMethod.PUT) + @RequestPath(path = "/api/v1/{id}/projects/{projectId}/addMembers", method = PUT) fun addMembers( projectId: String, mailingList: String, @@ -155,7 +155,7 @@ class NovaRequester( * @return the result of the request as [JSONObject] * */ - @RequestPath(path = "/api/v1/projects/join", method = APIRequest.RequestMethod.POST) + @RequestPath(path = "/api/v1/projects/join", method = POST) @Wrapper fun joinWithId( id: String, @@ -187,7 +187,7 @@ class NovaRequester( * @return the result of the request as [JSONObject] * */ - @RequestPath(path = "/api/v1/projects/join", method = APIRequest.RequestMethod.POST) + @RequestPath(path = "/api/v1/projects/join", method = POST) @Wrapper fun joinWithCode( joinCode: String, @@ -219,7 +219,7 @@ class NovaRequester( * @return the result of the request as [JSONObject] * */ - @RequestPath(path = "/api/v1/projects/join", method = APIRequest.RequestMethod.POST) + @RequestPath(path = "/api/v1/projects/join", method = POST) private fun join( payload: Params, email: String, @@ -238,6 +238,28 @@ class NovaRequester( ) } + /** + * Function to execute the request to mark a member of the project as tester + * + * @param projectId: the project identifier + * @param memberId: the identifier of the member to mark as tester + * + * @return the result of the request as [JSONObject] + * + */ + @RequestPath(path = "/api/v1/{id}/projects/{projectId}/markAsTester", method = PATCH) + fun markAsTester( + projectId: String, + memberId: String + ) : JSONObject { + val payload = Params() + payload.addParam(MEMBER_IDENTIFIER_KEY, memberId) + return execPatch( + endpoint = assembleProjectsEndpointPath(projectId + MARK_MEMBER_AS_TESTER_ENDPOINT), + payload = payload + ) + } + /** * Function to execute the request to remove a member from a project * @@ -247,7 +269,7 @@ class NovaRequester( * @return the result of the request as [JSONObject] * */ - @RequestPath(path = "/api/v1/{id}/projects/{projectId}/removeMember", method = APIRequest.RequestMethod.DELETE) + @RequestPath(path = "/api/v1/{id}/projects/{projectId}/removeMember", method = PATCH) fun removeMember( projectId: String, memberId: String @@ -268,7 +290,7 @@ class NovaRequester( * @return the result of the request as [JSONObject] * */ - @RequestPath(path = "/api/v1/{id}/projects/{projectId}/leave", method = APIRequest.RequestMethod.DELETE) + @RequestPath(path = "/api/v1/{id}/projects/{projectId}/leave", method = DELETE) fun leaveProject( projectId: String ) : JSONObject { @@ -285,7 +307,7 @@ class NovaRequester( * @return the result of the request as [JSONObject] * */ - @RequestPath(path = "/api/v1/{id}/projects/{projectId}", method = APIRequest.RequestMethod.DELETE) + @RequestPath(path = "/api/v1/{id}/projects/{projectId}", method = DELETE) fun deleteProject( projectId: String ) : JSONObject { @@ -319,7 +341,7 @@ class NovaRequester( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/addRelease", method = APIRequest.RequestMethod.POST) + @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/addRelease", method = POST) fun addRelease( projectId: String, releaseVersion: String, @@ -344,7 +366,7 @@ class NovaRequester( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}", method = APIRequest.RequestMethod.GET) + @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}", method = GET) fun getRelease( projectId: String, releaseId: String @@ -366,7 +388,7 @@ class NovaRequester( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}", method = APIRequest.RequestMethod.POST) + @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}", method = POST) fun uploadAsset( projectId: String, releaseId: String, @@ -402,7 +424,7 @@ class NovaRequester( @Wrapper @RequestPath( path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}/comment/{asset_uploading_event_id}", - method = APIRequest.RequestMethod.POST + method = POST ) fun approveAssets( projectId: String, @@ -431,7 +453,7 @@ class NovaRequester( @Wrapper @RequestPath( path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}/comment/{asset_uploading_event_id}", - method = APIRequest.RequestMethod.POST + method = POST ) fun rejectAssets( projectId: String, @@ -464,7 +486,7 @@ class NovaRequester( */ @RequestPath( path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}/comment/{asset_uploading_event_id}", - method = APIRequest.RequestMethod.POST + method = POST ) private fun commentAssets( projectId: String, @@ -509,7 +531,7 @@ class NovaRequester( */ @RequestPath( path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}/events/{release_event_id}/tags/{release_tag_id}", - method = APIRequest.RequestMethod.PUT + method = PUT ) fun fillRejectedTag( projectId: String, @@ -540,7 +562,7 @@ class NovaRequester( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}", method = APIRequest.RequestMethod.PATCH) + @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}", method = PATCH) fun promoteRelease( projectId: String, releaseId: String, @@ -567,7 +589,7 @@ class NovaRequester( */ @RequestPath( path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}/createReport", - method = APIRequest.RequestMethod.GET + method = GET ) fun createReportRelease( projectId: String, @@ -590,7 +612,7 @@ class NovaRequester( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}", method = APIRequest.RequestMethod.DELETE) + @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}", method = DELETE) fun deleteRelease( projectId: String, releaseId: String From 4d1cdf6373b86356e4acb697ea896d2d363e888b Mon Sep 17 00:00:00 2001 From: N7ghtm4r3 Date: Fri, 20 Sep 2024 20:21:48 +0200 Subject: [PATCH 06/25] Terminated the NovaUser.Role.Tester role integration! --- .../nova/helpers/services/ProjectsHelper.java | 1 + .../projectsutils/ProjectsRepository.java | 18 +++++++++++ backend/src/main/resources/resources.mantis | 32 ++++++++++++++++--- .../novacore/NovaInputValidator.java | 12 +++---- 4 files changed, 53 insertions(+), 10 deletions(-) diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java index c6287e4..97c6e21 100644 --- a/backend/src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java @@ -228,6 +228,7 @@ public void markMemberAsTester(String projectId, String memberId) { */ public void removeMember(String projectId, String memberId) { projectsRepository.removeMember(projectId, memberId); + projectsRepository.removeTester(projectId, memberId); } /** diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/ProjectsRepository.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/ProjectsRepository.java index 71028b1..90c348c 100644 --- a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/ProjectsRepository.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/ProjectsRepository.java @@ -183,6 +183,24 @@ void removeAllMembers( @Param(IDENTIFIER_KEY) String projectId ); + /** + * Method to execute the query to remove a tester from an existing {@link Project} + * + * @param projectId: the identifier of the project + * @param memberId: the identifier of the tester to remove + */ + @Modifying(clearAutomatically = true) + @Transactional + @Query( + value = "DELETE FROM " + PROJECT_TESTERS_TABLE + " WHERE " + PROJECT_IDENTIFIER_KEY + "=:" + + PROJECT_IDENTIFIER_KEY + " AND " + MEMBER_IDENTIFIER_KEY + "=:" + MEMBER_IDENTIFIER_KEY, + nativeQuery = true + ) + void removeTester( + @Param(PROJECT_IDENTIFIER_KEY) String projectId, + @Param(MEMBER_IDENTIFIER_KEY) String memberId + ); + /** * Method to execute the query to remove all testers from a {@link Project} * diff --git a/backend/src/main/resources/resources.mantis b/backend/src/main/resources/resources.mantis index 965bf99..faef4b4 100644 --- a/backend/src/main/resources/resources.mantis +++ b/backend/src/main/resources/resources.mantis @@ -16,7 +16,13 @@ "wrong_surname_key": "Surname is not valid", "wrong_language_key": "Language is not supported", "wrong_email_key": "Email is not valid", - "not_authorized_key": "Not authorized or wrong details" + "not_authorized_key": "Not authorized or wrong details", + "wrong_mailing_list_key": "Mailing list is not valid", + "wrong_release_version_key": "The version for the release is not valid", + "wrong_release_notes_key": "The notes for the release are not valid", + "wrong_release_assets_key": "The assets uploaded are not valid", + "wrong_rejection_reasons_key": "The reasons of the rejection are not valid", + "wrong_comment_tag_key": "The comment for the tag is not valid" }, "ignored_resources": {}, "it": { @@ -36,7 +42,13 @@ "wrong_surname_key": "Cognome non valido", "wrong_language_key": "Lingua non supportata", "wrong_email_key": "Email non valida", - "not_authorized_key": "Non autorizzat o dati errati" + "not_authorized_key": "Non autorizzat o dati errati", + "wrong_mailing_list_key": "La mailing list non è valida", + "wrong_release_version_key": "La versione della release non e' valida", + "wrong_release_notes_key": "Le note per la release non sono valide", + "wrong_release_assets_key": "Gli asset caricati non sono validi", + "wrong_rejection_reasons_key": "I motivi del rifiuto non sono validi", + "wrong_comment_tag_key": "Il commento per il tag non e' valido" }, "fr": { "new_asset_uploaded_key": "Nouvel actif téléchargé", @@ -54,7 +66,13 @@ "wrong_surname_key": "Le nom n'est pas valide", "wrong_language_key": "La langue n'est pas prise en charge", "wrong_email_key": "Le courriel n'est pas valide", - "not_authorized_key": "Non autorisa ou faux datails" + "not_authorized_key": "Détails non autorisés ou erronés", + "wrong_mailing_list_key": "La liste de diffusion n'est pas valide", + "wrong_release_version_key": "La version de la version n'est pas valide", + "wrong_release_notes_key": "Les notes de la version ne sont pas valides", + "wrong_release_assets_key": "Les ressources téléchargées ne sont pas valides", + "wrong_rejection_reasons_key": "Les raisons du rejet ne sont pas valables", + "wrong_comment_tag_key": "Le commentaire pour la balise n'est pas valide" }, "es": { "new_asset_uploaded_key": "Nuevo recurso cargado", @@ -72,6 +90,12 @@ "wrong_surname_key": "El apellido no es valido", "wrong_language_key": "El idioma no es compatible", "wrong_email_key": "El correo electrinico no es valido", - "not_authorized_key": "No autorizados o datos incorrectos" + "not_authorized_key": "No autorizados o datos incorrectos", + "wrong_mailing_list_key": "La lista de correo no es válida", + "wrong_release_version_key": "La versión para el lanzamiento no es válida", + "wrong_release_notes_key": "Las notas de la versión no son válidas", + "wrong_release_assets_key": "Los activos cargados no son válidos", + "wrong_rejection_reasons_key": "Los motivos del rechazo no son válidos", + "wrong_comment_tag_key": "El comentario de la etiqueta no es válido" } } diff --git a/core/src/main/java/com/tecknobit/novacore/NovaInputValidator.java b/core/src/main/java/com/tecknobit/novacore/NovaInputValidator.java index 5e8ef41..8763f31 100644 --- a/core/src/main/java/com/tecknobit/novacore/NovaInputValidator.java +++ b/core/src/main/java/com/tecknobit/novacore/NovaInputValidator.java @@ -19,12 +19,12 @@ public class NovaInputValidator extends InputValidator { /** * {@code WRONG_MAILING_LIST_MESSAGE} error message used when the mailing list inserted is not valid */ - public static final String WRONG_MAILING_LIST_MESSAGE = "Mailing list is not valid"; + public static final String WRONG_MAILING_LIST_MESSAGE = "wrong_mailing_list_key"; /** * {@code WRONG_RELEASE_VERSION_MESSAGE} error message used when the release version inserted is not valid */ - public static final String WRONG_RELEASE_VERSION_MESSAGE = "The version for the release is not valid"; + public static final String WRONG_RELEASE_VERSION_MESSAGE = "wrong_release_version_key"; /** * {@code RELEASE_VERSION_MAX_LENGTH} the max valid length for the release version @@ -34,7 +34,7 @@ public class NovaInputValidator extends InputValidator { /** * {@code WRONG_RELEASE_NOTES_MESSAGE} error message used when the release notes inserted are not valid */ - public static final String WRONG_RELEASE_NOTES_MESSAGE = "The notes for the release are not valid"; + public static final String WRONG_RELEASE_NOTES_MESSAGE = "wrong_release_notes_key"; /** * {@code RELEASE_NOTES_MAX_LENGTH} the max valid length for the release notes @@ -44,12 +44,12 @@ public class NovaInputValidator extends InputValidator { /** * {@code WRONG_ASSETS_MESSAGE} error message used when the release assets uploaded are not valid */ - public static final String WRONG_ASSETS_MESSAGE = "The assets uploaded are not valid"; + public static final String WRONG_ASSETS_MESSAGE = "wrong_release_assets_key"; /** * {@code WRONG_REASONS_MESSAGE} error message used when the rejected reasons inserted are not valid */ - public static final String WRONG_REASONS_MESSAGE = "The reasons of the rejection are not valid"; + public static final String WRONG_REASONS_MESSAGE = "wrong_rejection_reasons_key"; /** * {@code REASONS_MAX_LENGTH} the max valid length for the reasons @@ -59,7 +59,7 @@ public class NovaInputValidator extends InputValidator { /** * {@code WRONG_TAG_COMMENT_MESSAGE} error message used when the tag comment inserted is not valid */ - public static final String WRONG_TAG_COMMENT_MESSAGE = "The comment for the tag is not valid"; + public static final String WRONG_TAG_COMMENT_MESSAGE = "wrong_comment_tag_key"; /** * {@code TAG_COMMENT_MAX_LENGTH} the max valid length for the tag comment From 05d80d6934081b79b8fd057874299380c9af3df8 Mon Sep 17 00:00:00 2001 From: N7ghtm4r3 Date: Sat, 21 Sep 2024 12:51:10 +0200 Subject: [PATCH 07/25] Terminated the integration of the edit feature of Project and Release items --- .../projectmanagers/ProjectsController.java | 40 +++- .../projectmanagers/ReleasesController.java | 110 ++++++++--- .../nova/helpers/services/ProjectsHelper.java | 27 +++ .../nova/helpers/services/ReleasesHelper.java | 22 +++ .../projectsutils/ProjectsRepository.java | 43 +++++ .../releaseutils/ReleasesRepository.java | 43 +++++ core/build.gradle.kts | 2 +- .../novacore/helpers/NovaEndpoints.java | 5 + .../novacore/helpers/NovaRequester.kt | 180 ++++++++++++++++-- 9 files changed, 430 insertions(+), 42 deletions(-) diff --git a/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectsController.java b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectsController.java index fb941fc..3717b2f 100644 --- a/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectsController.java +++ b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ProjectsController.java @@ -15,7 +15,6 @@ import org.springframework.web.multipart.MultipartFile; import java.security.NoSuchAlgorithmException; -import java.sql.SQLException; import java.util.List; import java.util.Map; @@ -157,6 +156,45 @@ public T getProject( return (T) failedResponse(NOT_AUTHORIZED_OR_WRONG_DETAILS_MESSAGE); } + /** + * Method to update a project + * + * @param id: the identifier of the user + * @param token: the token of the user + * @param projectId: the project identifier to update + * + * @return the result of the request as {@link String} + */ + @PostMapping( + path = "/{" + IDENTIFIER_KEY + "}/" + PROJECTS_KEY + "/{" + PROJECT_IDENTIFIER_KEY + "}", + headers = { + TOKEN_KEY + } + ) + @RequestPath(path = "/api/v1/{id}/projects/{projectId}", method = PATCH) + public String editProject( + @PathVariable(IDENTIFIER_KEY) String id, + @PathVariable(PROJECT_IDENTIFIER_KEY) String projectId, + @RequestHeader(TOKEN_KEY) String token, + @ModelAttribute ProjectsHelper.ProjectPayload payload + ) { + if(!isMe(id, token)) + return failedResponse(NOT_AUTHORIZED_OR_WRONG_DETAILS_MESSAGE); + Project project = projectsHelper.getProject(id, projectId); + if(project == null || !project.amITheProjectAuthor(id)) + return failedResponse(WRONG_PROCEDURE_MESSAGE); + try { + MultipartFile logo = payload.logo_url(); + String name = payload.name(); + if(!isProjectNameValid(name)) + return failedResponse(WRONG_PROCEDURE_MESSAGE); + projectsHelper.editProject(name, logo, projectId); + return successResponse(); + } catch (Exception e) { + return failedResponse(WRONG_PROCEDURE_MESSAGE); + } + } + /** * Method to add members in a project * diff --git a/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ReleasesController.java b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ReleasesController.java index 3e0e8d7..152e119 100644 --- a/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ReleasesController.java +++ b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ReleasesController.java @@ -102,34 +102,98 @@ public String addRelease( ) { if(isMe(id, token) && amIProjectMember(id, projectId) && !me.isTester(currentProject)) { loadJsonHelper(payload); - String releaseVersion = jsonHelper.getString(RELEASE_VERSION_KEY); - releaseVersion = releaseVersion.replaceFirst("^v\\.", ""); - if(!releaseVersion.startsWith(" ")) - releaseVersion = " " + releaseVersion; - releaseVersion = "v." + releaseVersion; + String releaseVersion = formatReleaseVersion(); String releaseNotes = jsonHelper.getString(RELEASE_NOTES_KEY); - if(currentProject != null) { - if(isReleaseVersionValid(releaseVersion) && currentProject.hasNotReleaseVersion(releaseVersion)) { - if(areReleaseNotesValid(releaseNotes)) { - String releaseId = generateIdentifier(); - releasesHelper.addRelease( - id, - currentProject, - releaseId, - releaseVersion, - releaseNotes - ); - return successResponse(); - } else - return failedResponse(WRONG_RELEASE_NOTES_MESSAGE); + if(isReleaseVersionValid(releaseVersion) && currentProject.hasNotReleaseVersion(releaseVersion)) { + if(areReleaseNotesValid(releaseNotes)) { + String releaseId = generateIdentifier(); + releasesHelper.addRelease( + id, + currentProject, + releaseId, + releaseVersion, + releaseNotes + ); + return successResponse(); } else - return failedResponse(WRONG_RELEASE_VERSION_MESSAGE); + return failedResponse(WRONG_RELEASE_NOTES_MESSAGE); } else - return failedResponse(NOT_AUTHORIZED_OR_WRONG_DETAILS_MESSAGE); + return failedResponse(WRONG_RELEASE_VERSION_MESSAGE); } else return failedResponse(NOT_AUTHORIZED_OR_WRONG_DETAILS_MESSAGE); } + /** + * Method to add a release + * + * @param id: the identifier of the user + * @param projectId: the project identifier where the release is attached + * @param releaseId: the release identifier of the release to edit + * @param token: the token of the user + * @param payload: payload of the request + *
    +     *      {@code
    +     *              {
    +     *                  "release_version": "the version for the release", -> [String]
    +     *                  "release_notes": "the notes attached to the release" -> [String]
    +     *              }
    +     *      }
    +     * 
    + * + * @return the result of the request as {@link String} + */ + @PatchMapping( + path = "/{" + RELEASE_IDENTIFIER_KEY + "}", + headers = { + TOKEN_KEY + } + ) + @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}", method = PATCH) + public String editRelease( + @PathVariable(IDENTIFIER_KEY) String id, + @PathVariable(PROJECT_IDENTIFIER_KEY) String projectId, + @PathVariable(RELEASE_IDENTIFIER_KEY) String releaseId, + @RequestHeader(TOKEN_KEY) String token, + @RequestBody Map payload + ) { + if(!isMe(id, token) || !amIProjectMember(id, projectId) || me.isTester(currentProject)) + return failedResponse(NOT_AUTHORIZED_OR_WRONG_DETAILS_MESSAGE); + Release release = getReleaseIfAuthorized(releaseId); + if(release == null) + return failedResponse(NOT_AUTHORIZED_OR_WRONG_DETAILS_MESSAGE); + loadJsonHelper(payload); + String releaseVersion = formatReleaseVersion(); + String releaseNotes = jsonHelper.getString(RELEASE_NOTES_KEY); + if(!isReleaseVersionValid(releaseVersion)) + return failedResponse(WRONG_RELEASE_VERSION_MESSAGE); + if(!areReleaseNotesValid(releaseNotes)) + return failedResponse(WRONG_RELEASE_NOTES_MESSAGE); + if(release.getReleaseVersion().equals(releaseVersion)) + releaseVersion = null; + else if(!currentProject.hasNotReleaseVersion(releaseVersion)) + return failedResponse(WRONG_RELEASE_VERSION_MESSAGE); + releasesHelper.editRelease( + releaseId, + releaseVersion, + releaseNotes + ); + return successResponse(); + } + + /** + * Method to format the version of a release
    + * No-any params required + * + * @return the version of a release formatted as {@link String} + */ + private String formatReleaseVersion() { + String releaseVersion = jsonHelper.getString(RELEASE_VERSION_KEY); + releaseVersion = releaseVersion.replaceFirst("^v\\.", ""); + if(!releaseVersion.startsWith(" ")) + releaseVersion = " " + releaseVersion; + return "v." + releaseVersion; + } + /** * Method to get a release * @@ -408,12 +472,12 @@ public String fillRejectedTag( * @return the result of the request as {@link String} */ @PatchMapping( - path = "/{" + RELEASE_IDENTIFIER_KEY + "}", + path = "/{" + RELEASE_IDENTIFIER_KEY + "}" + PROMOTE_RELEASE_ENDPOINT, headers = { TOKEN_KEY } ) - @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}", method = PATCH) + @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}/promote", method = PATCH) public String promoteRelease( @PathVariable(IDENTIFIER_KEY) String id, @PathVariable(PROJECT_IDENTIFIER_KEY) String projectId, diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java index 97c6e21..44c255e 100644 --- a/backend/src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/services/ProjectsHelper.java @@ -101,6 +101,33 @@ public JSONObject addProject(String name, MultipartFile logo, String projectId, .put(AUTHOR_KEY, authorId); } + /** + * Method to edit an existing project + * + * @param name: the name of the project + * @param logo: the logo of the project + * @param projectId: the project identifier + */ + public void editProject(String name, MultipartFile logo, String projectId) throws IOException { + boolean logoEdited = logo != null && !logo.isEmpty(); + String logoUrl = null; + if(logoEdited) { + logoUrl = createLogoResource(logo, projectId); + projectsRepository.editProject( + projectId, + logoUrl, + name + ); + } else { + projectsRepository.editProject( + projectId, + name + ); + } + if(logoEdited) + saveResource(logo, logoUrl); + } + /** * Method to get a project * diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/ReleasesHelper.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/ReleasesHelper.java index 8887582..21c6f60 100644 --- a/backend/src/main/java/com/tecknobit/nova/helpers/services/ReleasesHelper.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/services/ReleasesHelper.java @@ -95,6 +95,28 @@ public void addRelease(String requesterUser, Project project, String releaseId, } } + /** + * Method to edit an existing release + * + * @param releaseId: the identifier of the release + * @param releaseVersion: the version of the release + * @param releaseNotesContent: the notes attached to the release + */ + public void editRelease(String releaseId, String releaseVersion, String releaseNotesContent) { + if(releaseVersion == null) { + releasesRepository.editRelease( + releaseId, + releaseNotesContent + ); + } else { + releasesRepository.editRelease( + releaseId, + releaseVersion, + releaseNotesContent + ); + } + } + /** * Method to get a release * diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/ProjectsRepository.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/ProjectsRepository.java index 90c348c..12923b2 100644 --- a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/ProjectsRepository.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/projectsutils/ProjectsRepository.java @@ -77,6 +77,49 @@ void addProject( @Param(AUTHOR_KEY) String author ); + /** + * Method to execute the query to edit an existing {@link Project} + * + * @param projectId: the identifier of the project + * @param name: the project name + */ + @Modifying(clearAutomatically = true) + @Transactional + @Query( + value = "UPDATE " + PROJECTS_KEY + + " SET " + + NAME_KEY + "=:" + NAME_KEY + + " WHERE " + IDENTIFIER_KEY + "=:" + IDENTIFIER_KEY, + nativeQuery = true + ) + void editProject( + @Param(IDENTIFIER_KEY) String projectId, + @Param(NAME_KEY) String name + ); + + /** + * Method to execute the query to add an existing {@link Project} + * + * @param projectId: the identifier of the project + * @param logoUrl: the logo of the project formatted as url + * @param name: the project name + */ + @Modifying(clearAutomatically = true) + @Transactional + @Query( + value = "UPDATE " + PROJECTS_KEY + + " SET " + + NAME_KEY + "=:" + NAME_KEY + "," + + LOGO_URL_KEY + "=:" + LOGO_URL_KEY + + " WHERE " + IDENTIFIER_KEY + "=:" + IDENTIFIER_KEY, + nativeQuery = true + ) + void editProject( + @Param(IDENTIFIER_KEY) String projectId, + @Param(LOGO_URL_KEY) String logoUrl, + @Param(NAME_KEY) String name + ); + /** * Method to execute the query to get an existing {@link Project} if the user is authorized * diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/ReleasesRepository.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/ReleasesRepository.java index 56dda27..09fe633 100644 --- a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/ReleasesRepository.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/ReleasesRepository.java @@ -59,6 +59,49 @@ void addRelease( @Param(RELEASE_NOTES_KEY) String releaseNotes ); + /** + * Method to execute the query to edit an existing {@link Release} + * + * @param releaseId: the identifier of the release + * @param releaseNotes: the notes attached to the release + */ + @Modifying(clearAutomatically = true) + @Transactional + @Query( + value = "UPDATE " + RELEASES_KEY + + " SET " + + RELEASE_NOTES_KEY + "=:" + RELEASE_NOTES_KEY + + " WHERE " + IDENTIFIER_KEY + "=:" + IDENTIFIER_KEY, + nativeQuery = true + ) + void editRelease( + @Param(IDENTIFIER_KEY) String releaseId, + @Param(RELEASE_NOTES_KEY) String releaseNotes + ); + + /** + * Method to execute the query to edit an existing {@link Release} + * + * @param releaseId: the identifier of the release + * @param releaseVersion: the version of the release + * @param releaseNotes: the notes attached to the release + */ + @Modifying(clearAutomatically = true) + @Transactional + @Query( + value = "UPDATE " + RELEASES_KEY + + " SET " + + RELEASE_VERSION_KEY + "=:" + RELEASE_VERSION_KEY + "," + + RELEASE_NOTES_KEY + "=:" + RELEASE_NOTES_KEY + + " WHERE " + IDENTIFIER_KEY + "=:" + IDENTIFIER_KEY, + nativeQuery = true + ) + void editRelease( + @Param(IDENTIFIER_KEY) String releaseId, + @Param(RELEASE_VERSION_KEY) String releaseVersion, + @Param(RELEASE_NOTES_KEY) String releaseNotes + ); + /** * Method to execute the query to approve an existing {@link Release} * diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 78e720c..2974af3 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -20,7 +20,7 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-data-jpa:3.2.3") implementation("org.springframework:spring-web:6.1.5") implementation("com.fasterxml.jackson.core:jackson-databind:2.15.4") - implementation("com.github.N7ghtm4r3:APIManager:2.2.4") + implementation("com.github.N7ghtm4r3:APIManager:2.2.3") implementation("com.github.N7ghtm4r3:Equinox:1.0.3") implementation("com.squareup.okhttp3:okhttp:4.12.0") implementation("org.json:json:20230227") diff --git a/core/src/main/java/com/tecknobit/novacore/helpers/NovaEndpoints.java b/core/src/main/java/com/tecknobit/novacore/helpers/NovaEndpoints.java index 352315e..6ea387d 100644 --- a/core/src/main/java/com/tecknobit/novacore/helpers/NovaEndpoints.java +++ b/core/src/main/java/com/tecknobit/novacore/helpers/NovaEndpoints.java @@ -44,6 +44,11 @@ public class NovaEndpoints extends EquinoxBaseEndpointsSet { */ public static final String COMMENT_ASSET_ENDPOINT = "/comment/"; + /** + * {@code PROMOTE_RELEASE_ENDPOINT} the endpoint to promote a release + */ + public static final String PROMOTE_RELEASE_ENDPOINT = "/promote"; + /** * {@code EVENTS_ENDPOINT} the endpoint to work with the events of a release */ diff --git a/core/src/main/kotlin/com/tecknobit/novacore/helpers/NovaRequester.kt b/core/src/main/kotlin/com/tecknobit/novacore/helpers/NovaRequester.kt index f4cfc1b..0650767 100644 --- a/core/src/main/kotlin/com/tecknobit/novacore/helpers/NovaRequester.kt +++ b/core/src/main/kotlin/com/tecknobit/novacore/helpers/NovaRequester.kt @@ -11,8 +11,10 @@ import com.tecknobit.novacore.records.NovaNotification.NOTIFICATIONS_KEY import com.tecknobit.novacore.records.NovaUser.* import com.tecknobit.novacore.records.project.JoiningQRCode.CREATE_JOIN_CODE_KEY import com.tecknobit.novacore.records.project.JoiningQRCode.JOIN_CODE_KEY +import com.tecknobit.novacore.records.project.Project import com.tecknobit.novacore.records.project.Project.LOGO_URL_KEY import com.tecknobit.novacore.records.project.Project.PROJECT_MEMBERS_KEY +import com.tecknobit.novacore.records.release.Release import com.tecknobit.novacore.records.release.Release.* import com.tecknobit.novacore.records.release.Release.ReleaseStatus.Approved import com.tecknobit.novacore.records.release.Release.ReleaseStatus.Rejected @@ -32,11 +34,13 @@ import java.io.File class NovaRequester( host: String, userId: String? = null, - userToken: String? = null + userToken: String? = null, + debugMode: Boolean = false ) : EquinoxRequester( host = host, userId = userId, userToken = userToken, + debugMode = debugMode, connectionTimeout = 5000, connectionErrorMessage = DEFAULT_CONNECTION_ERROR_MESSAGE, enableCertificatesValidation = true @@ -83,21 +87,88 @@ class NovaRequester( logoPic: File, projectName: String ) : JSONObject { + val body = createProjectPayload( + logoPic = logoPic, + projectName = projectName + ) + return execMultipartRequest( + body = body, + endpoint = assembleProjectsEndpointPath() + ) + } + + /** + * Function to execute the request to edit an existing project + * + * @param project: the project to edit + * @param logoPic: the project logo + * @param projectName: the name of the project + * + * @return the result of the request as [JSONObject] + */ + @RequestPath(path = "/api/v1/{id}/projects/{project_id}", method = POST) + fun editProject( + project: Project, + logoPic: File?, + projectName: String + ) : JSONObject { + return editProject( + projectId = project.id, + logoPic = logoPic, + projectName = projectName + ) + } + + /** + * Function to execute the request to edit an existing project + * + * @param projectId: the identifier of the project + * @param logoPic: the project logo + * @param projectName: the name of the project + * + * @return the result of the request as [JSONObject] + */ + @RequestPath(path = "/api/v1/{id}/projects/{project_id}", method = POST) + fun editProject( + projectId: String, + logoPic: File?, + projectName: String + ) : JSONObject { + val body = createProjectPayload( + logoPic = logoPic, + projectName = projectName + ) + return execMultipartRequest( + body = body, + endpoint = assembleProjectsEndpointPath(projectId) + ) + } + + /** + * Function to create the payload for the project requests + * + * @param logoPic: the project logo + * @param projectName: the name of the project + * + * @return the payload of the request as [MultipartBody] + */ + private fun createProjectPayload( + logoPic: File?, + projectName: String + ) : MultipartBody { val body = MultipartBody.Builder().setType(MultipartBody.FORM) .addFormDataPart( + NAME_KEY, + projectName + ) + if(logoPic != null) { + body .addFormDataPart( LOGO_URL_KEY, logoPic.name, logoPic.readBytes().toRequestBody("*/*".toMediaType()) ) - .addFormDataPart( - NAME_KEY, - projectName - ) - .build() - return execMultipartRequest( - body = body, - endpoint = assembleProjectsEndpointPath() - ) + } + return body.build() } /** @@ -323,7 +394,7 @@ class NovaRequester( * * @return an endpoint to make the request as [String] */ - protected fun assembleProjectsEndpointPath( + private fun assembleProjectsEndpointPath( endpoint: String = "" ): String { var vEndpoint: String = endpoint @@ -341,15 +412,16 @@ class NovaRequester( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/addRelease", method = POST) + @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases", method = POST) fun addRelease( projectId: String, releaseVersion: String, releaseNotes: String ) : JSONObject { - val payload = Params() - payload.addParam(RELEASE_VERSION_KEY, releaseVersion) - payload.addParam(RELEASE_NOTES_KEY, releaseNotes) + val payload = createReleasePayload( + releaseVersion = releaseVersion, + releaseNotes = releaseNotes + ) return execPost( endpoint = assembleReleasesEndpointPath( projectId = projectId @@ -358,6 +430,79 @@ class NovaRequester( ) } + /** + * Function to execute the request to edit an existing release + * + * @param project: the project where the release is attached + * @param release: the release to edit + * @param releaseVersion: the version for the release + * @param releaseNotes: the notes attached to the release + * + * @return the result of the request as [JSONObject] + */ + @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}", method = PATCH) + fun editRelease( + project: Project, + release: Release, + releaseVersion: String, + releaseNotes: String + ) : JSONObject { + return editRelease( + projectId = project.id, + releaseId = release.id, + releaseVersion = releaseVersion, + releaseNotes = releaseNotes + ) + } + + /** + * Function to execute the request to edit an existing release + * + * @param projectId: the project identifier where the release is attached + * @param releaseId: the release identifier of the release to edit + * @param releaseVersion: the version for the release + * @param releaseNotes: the notes attached to the release + * + * @return the result of the request as [JSONObject] + */ + @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}", method = PATCH) + fun editRelease( + projectId: String, + releaseId: String, + releaseVersion: String, + releaseNotes: String + ) : JSONObject { + val payload = createReleasePayload( + releaseVersion = releaseVersion, + releaseNotes = releaseNotes + ) + return execPatch( + endpoint = assembleReleasesEndpointPath( + projectId = projectId, + releaseId = releaseId + ), + payload = payload + ) + } + + /** + * Function to create the payload for the release requests + * + * @param releaseVersion: the version for the release + * @param releaseNotes: the notes attached to the release + * + * @return the payload of the request as [Params] + */ + private fun createReleasePayload( + releaseVersion: String, + releaseNotes: String + ) : Params { + val payload = Params() + payload.addParam(RELEASE_VERSION_KEY, releaseVersion) + payload.addParam(RELEASE_NOTES_KEY, releaseNotes) + return payload + } + /** * Function to execute the request to get an existing release * @@ -562,7 +707,7 @@ class NovaRequester( * * @return the result of the request as [JSONObject] */ - @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}", method = PATCH) + @RequestPath(path = "/api/v1/{id}/projects/{project_id}/releases/{release_id}/promote", method = PATCH) fun promoteRelease( projectId: String, releaseId: String, @@ -574,6 +719,7 @@ class NovaRequester( endpoint = assembleReleasesEndpointPath( projectId = projectId, releaseId = releaseId, + endpoint = PROMOTE_RELEASE_ENDPOINT ), payload = payload ) @@ -635,7 +781,7 @@ class NovaRequester( * @return an endpoint to make the request as [String] */ - protected fun assembleReleasesEndpointPath( + private fun assembleReleasesEndpointPath( projectId: String, releaseId: String = "", extraId: String = "", From ee8a24caa9dd657436da310fe85c6d847a203ac5 Mon Sep 17 00:00:00 2001 From: N7ghtm4r3 Date: Sat, 21 Sep 2024 16:16:45 +0200 Subject: [PATCH 08/25] Added the possibility to comment the asset fo an AssetUploadingEvent and added the field for the name of the asset uploaded to correctly save in the clients --- .../projectmanagers/ReleasesController.java | 9 ++- .../resources/NovaResourcesManager.java | 1 - .../nova/helpers/services/ReleasesHelper.java | 13 ++-- .../releaseutils/ReleaseEventsRepository.java | 23 ++++-- .../release/events/AssetUploadingEvent.java | 71 ++++++++++++++++--- .../novacore/helpers/NovaRequester.kt | 8 ++- 6 files changed, 100 insertions(+), 25 deletions(-) diff --git a/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ReleasesController.java b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ReleasesController.java index 152e119..57e52b4 100644 --- a/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ReleasesController.java +++ b/backend/src/main/java/com/tecknobit/nova/controllers/projectmanagers/ReleasesController.java @@ -238,6 +238,7 @@ public T getRelease( * @param releaseId: the release identifier where upload the asset * @param token: the token of the user * @param assets: the assets to upload + * @param comment: the comment about the assets uploaded * * @return the result of the request as {@link String} * @@ -255,7 +256,11 @@ public String uploadAsset( @PathVariable(PROJECT_IDENTIFIER_KEY) String projectId, @PathVariable(RELEASE_IDENTIFIER_KEY) String releaseId, @RequestHeader(TOKEN_KEY) String token, - @RequestParam(ASSETS_UPLOADED_KEY) MultipartFile[] assets + @RequestParam(ASSETS_UPLOADED_KEY) MultipartFile[] assets, + @RequestParam( + name = AssetUploadingEvent.COMMENT_KEY, + required = false + ) String comment ) { if(isMe(id, token) && isAuthorizedUser(id, projectId)) { Release release = getReleaseIfAuthorized(releaseId); @@ -263,7 +268,7 @@ public String uploadAsset( switch (release.getStatus()) { case New, Rejected, Alpha, Beta -> { try { - if(releasesHelper.uploadAssets(id, currentProject, releaseId, assets)) + if(releasesHelper.uploadAssets(id, currentProject, releaseId, assets, comment)) return successResponse(); return failedResponse(WRONG_ASSETS_MESSAGE); } catch (IOException e) { diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/resources/NovaResourcesManager.java b/backend/src/main/java/com/tecknobit/nova/helpers/resources/NovaResourcesManager.java index ca29e81..9333b7f 100644 --- a/backend/src/main/java/com/tecknobit/nova/helpers/resources/NovaResourcesManager.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/resources/NovaResourcesManager.java @@ -49,7 +49,6 @@ default String createLogoResource(MultipartFile resource, String resourceId) { * Method to create the pathname for an asset * * @param resource: the resource from create its pathname - * @param resourceId: the resource identifier * @return the pathname created for an asset */ @Wrapper diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/ReleasesHelper.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/ReleasesHelper.java index 21c6f60..509d03a 100644 --- a/backend/src/main/java/com/tecknobit/nova/helpers/services/ReleasesHelper.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/services/ReleasesHelper.java @@ -144,20 +144,24 @@ public void readAllNotifications(String userId, String releaseId) { * @param project: the project where the release is attached * @param releaseId: the release identifier * @param assets: the assets to upload + * @param comment: the comment for the uploaded assets * * @return whether the upload has been successful * * @apiNote will be created the related {@link NovaNotification} for each member, not the author of the request, * of the project */ - public boolean uploadAssets(String requesterUser, Project project, String releaseId, - MultipartFile[] assets) throws IOException { + public boolean uploadAssets(String requesterUser, Project project, String releaseId, MultipartFile[] assets, + String comment) throws IOException { String eventId = generateIdentifier(); + if(comment.isEmpty()) + comment = null; releaseEventsRepository.insertAssetUploading( eventId, System.currentTimeMillis(), releaseId, - Verifying.name() + Verifying.name(), + comment ); for (MultipartFile asset : assets) { if(!asset.isEmpty()) { @@ -166,7 +170,8 @@ public boolean uploadAssets(String requesterUser, Project project, String releas releaseEventsRepository.insertAsset( assetId, assetPath, - eventId + eventId, + asset.getOriginalFilename() ); saveResource(asset, assetPath); } else diff --git a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/ReleaseEventsRepository.java b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/ReleaseEventsRepository.java index ca88a32..823aa8b 100644 --- a/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/ReleaseEventsRepository.java +++ b/backend/src/main/java/com/tecknobit/nova/helpers/services/repositories/releaseutils/ReleaseEventsRepository.java @@ -12,6 +12,7 @@ import org.springframework.stereotype.Repository; import org.springframework.stereotype.Service; +import static com.tecknobit.equinox.environment.records.EquinoxUser.NAME_KEY; import static com.tecknobit.novacore.records.release.Release.RELEASE_IDENTIFIER_KEY; import static com.tecknobit.novacore.records.release.events.AssetUploadingEvent.*; import static com.tecknobit.novacore.records.release.events.AssetUploadingEvent.AssetUploaded.ASSETS_UPLOADED_KEY; @@ -39,6 +40,7 @@ public interface ReleaseEventsRepository extends JpaRepository"comment" flag + */ + public static final String COMMENT_KEY = "comment"; + /** * {@code COMMENTED_KEY} the key for the "commented" flag */ @@ -69,6 +75,16 @@ public class AssetUploadingEvent extends ReleaseStandardEvent { }) private final List assetsUploaded; + /** + * {@code comment} the comment about the assets uploaded + */ + @Column( + name = COMMENT_KEY, + columnDefinition = "TEXT DEFAULT NULL", + insertable = false + ) + private final String comment; + /** * {@code commented} whether these assets have already been commented by the {@link Role#Customer} or {@link Role#Tester} */ @@ -87,7 +103,7 @@ public class AssetUploadingEvent extends ReleaseStandardEvent { * @apiNote empty constructor required */ public AssetUploadingEvent() { - this(null, -1, null, List.of(), false); + this(null, -1, null, List.of(), null , false); } /** @@ -99,23 +115,25 @@ public AssetUploadingEvent() { public AssetUploadingEvent(JSONObject jAssetUploadingEvent) { super(jAssetUploadingEvent); assetsUploaded = AssetUploaded.returnAssetUploadedList(hItem.getJSONArray(ASSETS_UPLOADED_KEY)); + comment = hItem.getString(COMMENT_KEY); commented = hItem.getBoolean(COMMENTED_KEY); } /** * Constructor to init the {@link AssetUploadingEvent} class * - * @param id: the identifier of the event - * @param release: the date when the event occurred - * @param releaseEventDate: the date when the event is occurred - * @param assetsUploaded: list of the assets have been uploaded in the events - * @param commented: whether these assets have already been commented by the {@link Role#Customer} - * + * @param id : the identifier of the event + * @param releaseEventDate : the date when the event is occurred + * @param release : the date when the event occurred + * @param assetsUploaded : list of the assets have been uploaded in the events + * @param comment: the comment about the assets uploaded + * @param commented : whether these assets have already been commented by the {@link Role#Customer} */ public AssetUploadingEvent(String id, long releaseEventDate, Release release, List assetsUploaded, - boolean commented) { + String comment, boolean commented) { super(id, releaseEventDate, release, Verifying); this.assetsUploaded = assetsUploaded; + this.comment = comment; this.commented = commented; } @@ -130,6 +148,16 @@ public List getAssetsUploaded() { return assetsUploaded; } + /** + * Method to get {@link #comment} instance
    + * No-any params required + * + * @return {@link #comment} instance as {@link String} + */ + public String getComment() { + return comment; + } + /** * Method to get {@link #commented} instance
    * No-any params required @@ -187,6 +215,15 @@ public static final class AssetUploaded extends EquinoxItem { @Column(name = ASSET_URL_KEY) private final String url; + /** + * {@code name} the name of the asset uploaded + */ + @Column( + name = NAME_KEY, + columnDefinition = "TEXT DEFAULT NULL" + ) + private final String name; + /** * Constructor to init the {@link AssetUploaded} class
    * @@ -195,7 +232,7 @@ public static final class AssetUploaded extends EquinoxItem { * @apiNote empty constructor required */ public AssetUploaded() { - this(null, null, null); + this(null, null, null, null); } /** @@ -208,6 +245,7 @@ public AssetUploaded(JSONObject jAssetUploaded) { super(jAssetUploaded); assetUploadingEvent = null; url = hItem.getString(ASSET_URL_KEY); + name = hItem.getString(NAME_KEY, id); } /** @@ -216,12 +254,13 @@ public AssetUploaded(JSONObject jAssetUploaded) { * @param id: the identifier of the asset uploaded * @param assetUploadingEvent: event where the asset has been uploaded * @param url: the url which the asset can be downloaded - * + * @param name: the name of the asset uploaded */ - public AssetUploaded(String id, AssetUploadingEvent assetUploadingEvent, String url) { + public AssetUploaded(String id, AssetUploadingEvent assetUploadingEvent, String url, String name) { super(id); this.assetUploadingEvent = assetUploadingEvent; this.url = url; + this.name = name; } /** @@ -246,6 +285,16 @@ public String getUrl() { return url; } + /** + * Method to get {@link #name} instance
    + * No-any params required + * + * @return {@link #name} instance as {@link String} + */ + public String getName() { + return name; + } + /** * Method to assemble and return a {@link List} of assets uploaded * diff --git a/core/src/main/kotlin/com/tecknobit/novacore/helpers/NovaRequester.kt b/core/src/main/kotlin/com/tecknobit/novacore/helpers/NovaRequester.kt index 0650767..9b0a03b 100644 --- a/core/src/main/kotlin/com/tecknobit/novacore/helpers/NovaRequester.kt +++ b/core/src/main/kotlin/com/tecknobit/novacore/helpers/NovaRequester.kt @@ -530,6 +530,7 @@ class NovaRequester( * @param projectId: the project identifier where the release is attached * @param releaseId: the release identifier where upload the assets * @param assets: the list of the assets to upload + * @param comment: the comment about the assets uploaded * * @return the result of the request as [JSONObject] */ @@ -537,7 +538,8 @@ class NovaRequester( fun uploadAsset( projectId: String, releaseId: String, - assets: List + assets: List, + comment: String ) : JSONObject { val body = MultipartBody.Builder().setType(MultipartBody.FORM) assets.forEach { asset -> @@ -546,6 +548,10 @@ class NovaRequester( asset.name, asset.readBytes().toRequestBody("*/*".toMediaType()) ) + body.addFormDataPart( + COMMENT_KEY, + comment + ) } return execMultipartRequest( body = body.build(), From ecf6923b88aae560fd7b20fe44e44aef6f0a7ccb Mon Sep 17 00:00:00 2001 From: N7ghtm4r3 Date: Sat, 21 Sep 2024 19:32:18 +0200 Subject: [PATCH 09/25] Working on the JoiningQRCodeWebPageProvider integration --- .idea/inspectionProfiles/Project_Default.xml | 10 + backend/build.gradle.kts | 9 +- .../JoiningQRCodeWebPageProvider.java | 154 ++++++++++++++ backend/src/main/resources/resources.mantis | 18 +- .../resources/templates/invalid_code.html | 38 ++++ .../main/resources/templates/join_code.html | 201 ++++++++++++++++++ 6 files changed, 422 insertions(+), 8 deletions(-) create mode 100644 backend/src/main/java/com/tecknobit/nova/controllers/JoiningQRCodeWebPageProvider.java create mode 100644 backend/src/main/resources/templates/invalid_code.html create mode 100644 backend/src/main/resources/templates/join_code.html diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 853669c..038aa1c 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -1,6 +1,16 @@