From 2a7f478d1a633bde5f196786204be5c785534e13 Mon Sep 17 00:00:00 2001 From: Kenji Tanaka Date: Fri, 8 Mar 2024 08:49:41 -0500 Subject: [PATCH 1/3] :wrench: chore(Deliverables): Validate id for crp outcomes in save process --- .../cgiar/ccafs/marlo/action/projects/DeliverableAction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/marlo-web/src/main/java/org/cgiar/ccafs/marlo/action/projects/DeliverableAction.java b/marlo-web/src/main/java/org/cgiar/ccafs/marlo/action/projects/DeliverableAction.java index 431a8ea92f..c6472fa300 100644 --- a/marlo-web/src/main/java/org/cgiar/ccafs/marlo/action/projects/DeliverableAction.java +++ b/marlo-web/src/main/java/org/cgiar/ccafs/marlo/action/projects/DeliverableAction.java @@ -2812,7 +2812,7 @@ public void saveCrpOutcomes(Deliverable deliverable, Phase phase) { && deliverableOutcome.getCrpProgramOutcome().getId() != null) { CrpProgramOutcome outcome = crpProgramOutcomeManager.getCrpProgramOutcomeById(deliverableOutcome.getCrpProgramOutcome().getId()); - if (outcome != null) { + if (outcome != null && outcome.getId() != null) { deliverableOutcomeSave.setCrpProgramOutcome(outcome); } From cced643aec5f7c782d4e28f127062b4c1adca89f Mon Sep 17 00:00:00 2001 From: Kenji Tanaka Date: Fri, 8 Mar 2024 09:02:08 -0500 Subject: [PATCH 2/3] :wrench: chore(migration): Create TIP security specificity --- .../main/java/org/cgiar/ccafs/marlo/config/APConstants.java | 1 + .../main/java/org/cgiar/ccafs/marlo/config/APConstants.java | 1 + .../V2_6_0_20240307_1430__CreateTIPSecuritySpecificity.sql | 6 ++++++ 3 files changed, 8 insertions(+) create mode 100644 marlo-web/src/main/resources/database/migrations/V2_6_0_20240307_1430__CreateTIPSecuritySpecificity.sql diff --git a/marlo-data/src/main/java/org/cgiar/ccafs/marlo/config/APConstants.java b/marlo-data/src/main/java/org/cgiar/ccafs/marlo/config/APConstants.java index ddcf405fb7..3fa466befd 100644 --- a/marlo-data/src/main/java/org/cgiar/ccafs/marlo/config/APConstants.java +++ b/marlo-data/src/main/java/org/cgiar/ccafs/marlo/config/APConstants.java @@ -152,6 +152,7 @@ public final class APConstants { public static final String HIGHLIGHT_COMMENTS_ACTIVE = "highlight_comments_active"; public static final String SHFRM_CONTRIBUTION_ACTIVE = "shfrm_contribution_active"; public static final String TIP_SECTION_ACTIVE = "tip_section_active"; + public static final String TIP_SECURITY_ACTIVE = "tip_security_active"; public static final String IS_EXPECTED_DELIVERABLE_REPORT_All_YEARS_VISIBLE = "is_expected_deliverable_report_all_years_visible"; diff --git a/marlo-web/src/main/java/org/cgiar/ccafs/marlo/config/APConstants.java b/marlo-web/src/main/java/org/cgiar/ccafs/marlo/config/APConstants.java index 29095bf093..08ed0a97e2 100644 --- a/marlo-web/src/main/java/org/cgiar/ccafs/marlo/config/APConstants.java +++ b/marlo-web/src/main/java/org/cgiar/ccafs/marlo/config/APConstants.java @@ -162,6 +162,7 @@ public final class APConstants { public static final String HIGHLIGHT_COMMENTS_ACTIVE = "highlight_comments_active"; public static final String SHFRM_CONTRIBUTION_ACTIVE = "shfrm_contribution_active"; public static final String TIP_SECTION_ACTIVE = "tip_section_active"; + public static final String TIP_SECURITY_ACTIVE = "tip_security_active"; public static final String IS_EXPECTED_DELIVERABLE_REPORT_All_YEARS_VISIBLE = "is_expected_deliverable_report_all_years_visible"; diff --git a/marlo-web/src/main/resources/database/migrations/V2_6_0_20240307_1430__CreateTIPSecuritySpecificity.sql b/marlo-web/src/main/resources/database/migrations/V2_6_0_20240307_1430__CreateTIPSecuritySpecificity.sql new file mode 100644 index 0000000000..b72e75e29e --- /dev/null +++ b/marlo-web/src/main/resources/database/migrations/V2_6_0_20240307_1430__CreateTIPSecuritySpecificity.sql @@ -0,0 +1,6 @@ +INSERT INTO parameters (global_unit_type_id, `key`, `description`, `format`, default_value, category) +VALUES ( '1', 'tip_security_active', 'Enable TIP security', '1', 'false', '2'); +INSERT INTO parameters (global_unit_type_id, `key`, `description`, `format`, default_value, category) +VALUES ( '3', 'tip_security_active', 'Enable TIP security', '1', 'false', '2'); +INSERT INTO parameters (global_unit_type_id, `key`, `description`, `format`, default_value, category) +VALUES ( '4', 'tip_security_active', 'Enable TIP security', '1', 'false', '2'); \ No newline at end of file From 634ba80cb708c001ab5c6e6ffcb0655c4b91e993 Mon Sep 17 00:00:00 2001 From: Kenji Tanaka Date: Fri, 8 Mar 2024 15:27:17 -0500 Subject: [PATCH 3/3] :sparkles: feat(TIP integration): Implement AES encryption for TIP URL --- .../cgiar/ccafs/marlo/utils/AESConvert.java | 87 +++++++++++++++++++ .../tip/TipDinamicUrlGenerationAction.java | 8 +- 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 marlo-utils/src/main/java/org/cgiar/ccafs/marlo/utils/AESConvert.java diff --git a/marlo-utils/src/main/java/org/cgiar/ccafs/marlo/utils/AESConvert.java b/marlo-utils/src/main/java/org/cgiar/ccafs/marlo/utils/AESConvert.java new file mode 100644 index 0000000000..bbdb89eef3 --- /dev/null +++ b/marlo-utils/src/main/java/org/cgiar/ccafs/marlo/utils/AESConvert.java @@ -0,0 +1,87 @@ +/***************************************************************** + * This file is part of Managing Agricultural Research for Learning & + * Outcomes Platform (MARLO). + * MARLO is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * MARLO is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with MARLO. If not, see . + *****************************************************************/ +package org.cgiar.ccafs.marlo.utils; + +import java.io.ByteArrayOutputStream; +import java.security.MessageDigest; +import java.util.Base64; +import java.util.zip.GZIPOutputStream; + +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class AESConvert { + + private static Logger LOG = LoggerFactory.getLogger(AESConvert.class); + + public static String stringToAES(String value) { + MessageDigest md; + try { + // Generate a secret key + KeyGenerator keygen = KeyGenerator.getInstance("AES"); + keygen.init(256); // Use a 256-bit key (AES-256) + SecretKey secretKey = keygen.generateKey(); + + // Convert the secret key to byte array + byte[] secretKeyBytes = secretKey.getEncoded(); + + // Convert the text to compress into bytes + String originalText = "Sample text to compress and encrypt using AES"; + byte[] originalBytes = originalText.getBytes(); + + // Compress the text + ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + GZIPOutputStream gzipStream = new GZIPOutputStream(byteStream); + gzipStream.write(originalBytes); + gzipStream.close(); + byte[] compressedBytes = byteStream.toByteArray(); + + // Encrypt the compressed text using AES + Cipher cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(secretKeyBytes, "AES")); + byte[] encryptedBytes = cipher.doFinal(compressedBytes); + + // Encode the encrypted bytes to Base64 for easier storage or transmission + String encryptedText = Base64.getEncoder().encodeToString(encryptedBytes); + + // Decode the encrypted text into bytes + byte[] decodedEncryptedBytes = Base64.getDecoder().decode(encryptedText); + + // Decrypt the encrypted text using AES + cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(secretKeyBytes, "AES")); + byte[] decryptedBytes = cipher.doFinal(decodedEncryptedBytes); + + // Decompress the decrypted text + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + outputStream.write(decryptedBytes); + outputStream.close(); + + // Convert the decompressed text to a string + String decompressedText = new String(outputStream.toByteArray()); + + return encryptedText; + + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/marlo-web/src/main/java/org/cgiar/ccafs/marlo/action/json/tip/TipDinamicUrlGenerationAction.java b/marlo-web/src/main/java/org/cgiar/ccafs/marlo/action/json/tip/TipDinamicUrlGenerationAction.java index 0e7ad618c3..e2e4e1492a 100644 --- a/marlo-web/src/main/java/org/cgiar/ccafs/marlo/action/json/tip/TipDinamicUrlGenerationAction.java +++ b/marlo-web/src/main/java/org/cgiar/ccafs/marlo/action/json/tip/TipDinamicUrlGenerationAction.java @@ -16,8 +16,10 @@ package org.cgiar.ccafs.marlo.action.json.tip; import org.cgiar.ccafs.marlo.action.BaseAction; +import org.cgiar.ccafs.marlo.config.APConstants; import org.cgiar.ccafs.marlo.data.manager.TipParametersManager; import org.cgiar.ccafs.marlo.data.model.TipParameters; +import org.cgiar.ccafs.marlo.utils.AESConvert; import java.util.List; @@ -67,7 +69,11 @@ public String createDinamicURL() { loginService = tipParameters.get(0).getTipLoginService(); } } - tipURL = loginService + "/" + token + "/staff/" + userEmail; + if (this.hasSpecificities(APConstants.TIP_SECURITY_ACTIVE)) { + tipURL = loginService + "/" + (AESConvert.stringToAES(token + "/staff/" + userEmail)); + } else { + tipURL = loginService + "/" + token + "/staff/" + userEmail; + } } else { // Not CGIAR User if (tipParameters != null && tipParameters.get(0) != null && tipParameters.get(0).getTipBaseUrl() != null) {