From c32e4896960bd7bdb02a38c680faa5aca4e2c212 Mon Sep 17 00:00:00 2001 From: Umesh Kumar <166806589+TangoBeeAkto@users.noreply.github.com> Date: Fri, 10 Jan 2025 12:02:45 +0530 Subject: [PATCH 01/10] feat: storing vul report pdf in db --- .../java/com/akto/action/ReportAction.java | 21 +++++++++ .../VulnerabilityReport.jsx | 26 ++++++++--- libs/dao/src/main/java/com/akto/DaoInit.java | 1 + .../akto/dao/VulnerabilityReportPDFDao.java | 42 +++++++++++++++++ .../com/akto/dto/VulnerabilityReportPDF.java | 45 +++++++++++++++++++ 5 files changed, 128 insertions(+), 7 deletions(-) create mode 100644 libs/dao/src/main/java/com/akto/dao/VulnerabilityReportPDFDao.java create mode 100644 libs/dao/src/main/java/com/akto/dto/VulnerabilityReportPDF.java diff --git a/apps/dashboard/src/main/java/com/akto/action/ReportAction.java b/apps/dashboard/src/main/java/com/akto/action/ReportAction.java index 87617004fb..a97748c500 100644 --- a/apps/dashboard/src/main/java/com/akto/action/ReportAction.java +++ b/apps/dashboard/src/main/java/com/akto/action/ReportAction.java @@ -10,6 +10,9 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import com.akto.dao.VulnerabilityReportPDFDao; +import com.akto.dto.VulnerabilityReportPDF; +import com.mongodb.client.model.Filters; import org.apache.struts2.ServletActionContext; import org.bson.types.ObjectId; import org.json.JSONObject; @@ -36,6 +39,19 @@ public class ReportAction extends UserAction { private static final LoggerMaker loggerMaker = new LoggerMaker(ReportAction.class); public String downloadReportPDF() { + if(reportUrl == null || reportUrl.isEmpty()) { + status = "ERROR"; + addActionError("Report URL cannot be empty"); + return ERROR.toUpperCase(); + } + + VulnerabilityReportPDF vulnerabilityReportPDF = VulnerabilityReportPDFDao.instance.findOne(Filters.eq(VulnerabilityReportPDF.VULNERABILITY_REPORT_URL, reportUrl)); + if(vulnerabilityReportPDF != null && (vulnerabilityReportPDF.getVulnerabilityReportPDFBinary() != null || !vulnerabilityReportPDF.getVulnerabilityReportPDFBinary().isEmpty())) { + status = "COMPLETED"; + pdf = vulnerabilityReportPDF.getVulnerabilityReportPDFBinary(); + return SUCCESS.toUpperCase(); + } + if (reportId == null) { // Initiate PDF generation @@ -89,6 +105,11 @@ public String downloadReportPDF() { if (status.equals("COMPLETED")) { loggerMaker.infoAndAddToDb("Pdf download status for report id - " + reportId + " completed. Attaching pdf in response ", LogDb.DASHBOARD); pdf = node.get("base64PDF").textValue(); + VulnerabilityReportPDFDao.instance.insertOne(new VulnerabilityReportPDF( + reportUrl, + pdf, + Context.now() + )); } } catch (Exception e) { loggerMaker.errorAndAddToDb(e, "Error while polling pdf download for report id - " + reportId, LogDb.DASHBOARD); diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx index 13b04d2dfc..b9eac54183 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx +++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx @@ -1,5 +1,5 @@ /* eslint-disable no-loop-func */ -import { Box, Divider, Frame, HorizontalStack, Text, TopBar, VerticalStack } from '@shopify/polaris' +import { Box, Button, Divider, Frame, HorizontalStack, Text, TopBar, VerticalStack } from '@shopify/polaris' import React, { useEffect, useRef } from 'react' import api from '../api' import issuesApi from '@/apps/dashboard/pages/issues/api' @@ -233,7 +233,7 @@ const VulnerabilityReport = () => { const handleDownloadPF = async () => { - const WAIT_DURATION = 2500, MAX_RETRIES = 15 + const WAIT_DURATION = 5000, MAX_RETRIES = 60 const reportUrl = window.location.href let pdfError = "" @@ -242,15 +242,23 @@ const VulnerabilityReport = () => { setPdfDownloadEnabled(false) - const progressToastInterval = setInterval(() => { - func.setToast(true, false, "Report PDF generation in progress. Please wait...") + let reportToastInterval = setInterval(() => { + func.setToast(true, false, "Preparing your report. This might take a moment...") }, 1000) + setTimeout(() => { + clearInterval(reportToastInterval) + reportToastInterval = setInterval(() => { + func.setToast(true, false, "Report PDF generation in progress. Please wait...") + }, 1000) + }, 6000) + try { // Trigger pdf download const startDownloadReponse = await api.downloadReportPDF(null, organizationName, currentDate, reportUrl) const reportId = startDownloadReponse?.reportId status = startDownloadReponse?.status + pdf = startDownloadReponse?.pdf if (reportId !== null && status === "IN_PROGRESS") { // Poll for PDF completion @@ -271,13 +279,15 @@ const VulnerabilityReport = () => { func.setToast(true, false, "Report PDF generation in progress. Please wait...") } } else { - pdfError = "Failed to start PDF download" + if(status !== "COMPLETED") { + pdfError = "Failed to start PDF download" + } } } catch (err) { pdfError = err.message } - clearInterval(progressToastInterval) + clearInterval(reportToastInterval) if (status === "COMPLETED") { if (pdf === undefined) { @@ -321,7 +331,9 @@ const VulnerabilityReport = () => { {currentDate}
- {/* */} + { + window.USER_NAME?.toLowerCase()?.includes("ababank") ? : <> + } Logo
diff --git a/libs/dao/src/main/java/com/akto/DaoInit.java b/libs/dao/src/main/java/com/akto/DaoInit.java index 7e4ea5a2fe..08d97119ce 100644 --- a/libs/dao/src/main/java/com/akto/DaoInit.java +++ b/libs/dao/src/main/java/com/akto/DaoInit.java @@ -409,6 +409,7 @@ public static void createIndices() { TrafficAlertsDao.instance.createIndicesIfAbsent(); RuntimeMetricsDao.instance.createIndicesIfAbsent(); ApiAuditLogsDao.instance.createIndicesIfAbsent(); + VulnerabilityReportPDFDao.instance.createIndicesIfAbsent(); } } diff --git a/libs/dao/src/main/java/com/akto/dao/VulnerabilityReportPDFDao.java b/libs/dao/src/main/java/com/akto/dao/VulnerabilityReportPDFDao.java new file mode 100644 index 0000000000..25558d10e5 --- /dev/null +++ b/libs/dao/src/main/java/com/akto/dao/VulnerabilityReportPDFDao.java @@ -0,0 +1,42 @@ +package com.akto.dao; + +import com.akto.dao.context.Context; +import com.akto.dto.VulnerabilityReportPDF; +import com.mongodb.client.MongoDatabase; + +public class VulnerabilityReportPDFDao extends AccountsContextDao { + + public static final VulnerabilityReportPDFDao instance = new VulnerabilityReportPDFDao(); + + public VulnerabilityReportPDFDao() {} + + @Override + public String getCollName() { + return "vulnerability_report_pdf"; + } + + @Override + public Class getClassT() { + return VulnerabilityReportPDF.class; + } + + + public void createIndicesIfAbsent() { + boolean exists = false; + String dbName = Context.accountId.get()+""; + MongoDatabase db = clients[0].getDatabase(dbName); + for (String col: db.listCollectionNames()){ + if (getCollName().equalsIgnoreCase(col)){ + exists = true; + break; + } + } + + if (!exists) { + db.createCollection(getCollName()); + } + + MCollection.createIndexIfAbsent(getDBName(), getCollName(), new String[] { VulnerabilityReportPDF.VULNERABILITY_REPORT_URL }, false); + } + +} diff --git a/libs/dao/src/main/java/com/akto/dto/VulnerabilityReportPDF.java b/libs/dao/src/main/java/com/akto/dto/VulnerabilityReportPDF.java new file mode 100644 index 0000000000..b638beb6f0 --- /dev/null +++ b/libs/dao/src/main/java/com/akto/dto/VulnerabilityReportPDF.java @@ -0,0 +1,45 @@ +package com.akto.dto; + +public class VulnerabilityReportPDF { + + public static final String VULNERABILITY_REPORT_URL = "vulnerabilityReportUrl"; + private String vulnerabilityReportUrl; + + public static final String VULNERABILITY_REPORT_PDF_BINARY = "vulnerabilityReportPDFBinary"; + private String vulnerabilityReportPDFBinary; + + public static final String LAST_UPDATE_TIME_STAMP = "lastUpdateTimeStamp"; + private int lastUpdateTimestamp; + + public VulnerabilityReportPDF() {} + + public VulnerabilityReportPDF(String vulnerabilityReportUrl, String vulnerabilityReportPDFBinary, int lastUpdateTimestamp) { + this.vulnerabilityReportUrl = vulnerabilityReportUrl; + this.vulnerabilityReportPDFBinary = vulnerabilityReportPDFBinary; + this.lastUpdateTimestamp = lastUpdateTimestamp; + } + + public String getVulnerabilityReportUrl() { + return vulnerabilityReportUrl; + } + + public void setVulnerabilityReportUrl(String vulnerabilityReportUrl) { + this.vulnerabilityReportUrl = vulnerabilityReportUrl; + } + + public String getVulnerabilityReportPDFBinary() { + return vulnerabilityReportPDFBinary; + } + + public void setVulnerabilityReportPDFBinary(String vulnerabilityReportPDFBinary) { + this.vulnerabilityReportPDFBinary = vulnerabilityReportPDFBinary; + } + + public int getLastUpdateTimestamp() { + return lastUpdateTimestamp; + } + + public void setLastUpdateTimestamp(int lastUpdateTimestamp) { + this.lastUpdateTimestamp = lastUpdateTimestamp; + } +} From 84dbc353b375602f7f793c8c9facbdebfa341023 Mon Sep 17 00:00:00 2001 From: Umesh Kumar <166806589+TangoBeeAkto@users.noreply.github.com> Date: Fri, 10 Jan 2025 12:14:13 +0530 Subject: [PATCH 02/10] fix: update environment variable for report PDF download URL --- .../dashboard/src/main/java/com/akto/action/ReportAction.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/dashboard/src/main/java/com/akto/action/ReportAction.java b/apps/dashboard/src/main/java/com/akto/action/ReportAction.java index a97748c500..a894486ec3 100644 --- a/apps/dashboard/src/main/java/com/akto/action/ReportAction.java +++ b/apps/dashboard/src/main/java/com/akto/action/ReportAction.java @@ -73,7 +73,7 @@ public String downloadReportPDF() { session.setAttribute("login", Context.now()); } - String url = System.getenv("PUPPETEER_REPLAY_SERVICE_URL") + "/downloadReportPDF"; + String url = System.getenv("REPORT_PUPPETEER_REPLAY_SERVICE_URL") + "/downloadReportPDF"; JSONObject requestBody = new JSONObject(); requestBody.put("reportId", reportId); requestBody.put("username", user.getName()); @@ -94,7 +94,7 @@ public String downloadReportPDF() { loggerMaker.infoAndAddToDb("Polling pdf download status for report id - " + reportId, LogDb.DASHBOARD); try { - String url = System.getenv("PUPPETEER_REPLAY_SERVICE_URL") + "/downloadReportPDF"; + String url = System.getenv("REPORT_PUPPETEER_REPLAY_SERVICE_URL") + "/downloadReportPDF"; JSONObject requestBody = new JSONObject(); requestBody.put("reportId", reportId); String reqData = requestBody.toString(); From 20897dbdbd297d61c685b9f3e184eec59371494f Mon Sep 17 00:00:00 2001 From: Umesh Kumar <166806589+TangoBeeAkto@users.noreply.github.com> Date: Fri, 10 Jan 2025 12:17:59 +0530 Subject: [PATCH 03/10] feat: allow download button for additional user account --- .../pages/testing/vulnerability_report/VulnerabilityReport.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx index b9eac54183..ddb9e7c758 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx +++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx @@ -332,7 +332,7 @@ const VulnerabilityReport = () => {
{ - window.USER_NAME?.toLowerCase()?.includes("ababank") ? : <> + (window.USER_NAME?.toLowerCase()?.includes("ababank") || window.ACCOUNT_NAME?.toLowerCase()?.includes("advanced bank")) ? : <> } Logo
From 71ca510a014786a638313494f597e47ecaa41e98 Mon Sep 17 00:00:00 2001 From: Umesh Kumar <166806589+TangoBeeAkto@users.noreply.github.com> Date: Fri, 10 Jan 2025 12:48:35 +0530 Subject: [PATCH 04/10] feat: add firstPollRequest parameter for report PDF download --- .../main/java/com/akto/action/ReportAction.java | 17 ++++++++++++----- .../web/src/apps/dashboard/pages/testing/api.js | 4 ++-- .../VulnerabilityReport.jsx | 4 ++-- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/apps/dashboard/src/main/java/com/akto/action/ReportAction.java b/apps/dashboard/src/main/java/com/akto/action/ReportAction.java index a894486ec3..d097268fb7 100644 --- a/apps/dashboard/src/main/java/com/akto/action/ReportAction.java +++ b/apps/dashboard/src/main/java/com/akto/action/ReportAction.java @@ -35,6 +35,7 @@ public class ReportAction extends UserAction { private String reportUrl; private String pdf; private String status; + private boolean firstPollRequest; private static final LoggerMaker loggerMaker = new LoggerMaker(ReportAction.class); @@ -45,11 +46,13 @@ public String downloadReportPDF() { return ERROR.toUpperCase(); } - VulnerabilityReportPDF vulnerabilityReportPDF = VulnerabilityReportPDFDao.instance.findOne(Filters.eq(VulnerabilityReportPDF.VULNERABILITY_REPORT_URL, reportUrl)); - if(vulnerabilityReportPDF != null && (vulnerabilityReportPDF.getVulnerabilityReportPDFBinary() != null || !vulnerabilityReportPDF.getVulnerabilityReportPDFBinary().isEmpty())) { - status = "COMPLETED"; - pdf = vulnerabilityReportPDF.getVulnerabilityReportPDFBinary(); - return SUCCESS.toUpperCase(); + if(firstPollRequest) { + VulnerabilityReportPDF vulnerabilityReportPDF = VulnerabilityReportPDFDao.instance.findOne(Filters.eq(VulnerabilityReportPDF.VULNERABILITY_REPORT_URL, reportUrl)); + if(vulnerabilityReportPDF != null && (vulnerabilityReportPDF.getVulnerabilityReportPDFBinary() != null || !vulnerabilityReportPDF.getVulnerabilityReportPDFBinary().isEmpty())) { + status = "COMPLETED"; + pdf = vulnerabilityReportPDF.getVulnerabilityReportPDFBinary(); + return SUCCESS.toUpperCase(); + } } if (reportId == null) { @@ -167,4 +170,8 @@ public String getStatus() { public void setStatus(String status) { this.status = status; } + + public void setFirstPollRequest(boolean firstPollRequest) { + this.firstPollRequest = firstPollRequest; + } } diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/api.js b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/api.js index 5d9c8b82f4..4e9053a3a4 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/api.js +++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/api.js @@ -425,11 +425,11 @@ export default { data: {} }) }, - downloadReportPDF(reportId, organizationName, reportDate, reportUrl) { + downloadReportPDF(reportId, organizationName, reportDate, reportUrl, firstPollRequest) { return request({ url: '/api/downloadReportPDF', method: 'post', - data: {reportId, organizationName, reportDate, reportUrl} + data: {reportId, organizationName, reportDate, reportUrl, firstPollRequest} }) }, fetchScript() { diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx index ddb9e7c758..35fed5f482 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx +++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx @@ -255,7 +255,7 @@ const VulnerabilityReport = () => { try { // Trigger pdf download - const startDownloadReponse = await api.downloadReportPDF(null, organizationName, currentDate, reportUrl) + const startDownloadReponse = await api.downloadReportPDF(null, organizationName, currentDate, reportUrl, true) const reportId = startDownloadReponse?.reportId status = startDownloadReponse?.status pdf = startDownloadReponse?.pdf @@ -263,7 +263,7 @@ const VulnerabilityReport = () => { if (reportId !== null && status === "IN_PROGRESS") { // Poll for PDF completion for(let i = 0; i < MAX_RETRIES; i++) { - const pdfPollResponse = await api.downloadReportPDF(reportId, organizationName, currentDate, reportUrl) + const pdfPollResponse = await api.downloadReportPDF(reportId, organizationName, currentDate, reportUrl, false) status = pdfPollResponse?.status if (status === "COMPLETED") { From 53b04344812a8d7875f865439d7d1adc3e35a7e6 Mon Sep 17 00:00:00 2001 From: Umesh Kumar <166806589+TangoBeeAkto@users.noreply.github.com> Date: Fri, 10 Jan 2025 14:03:22 +0530 Subject: [PATCH 05/10] refactor: replace VulnerabilityReportPDF with TestReports for PDF handling and remove unused DAO --- .../java/com/akto/action/ReportAction.java | 27 ++++++----- libs/dao/src/main/java/com/akto/DaoInit.java | 1 - .../akto/dao/VulnerabilityReportPDFDao.java | 42 ----------------- .../com/akto/dto/VulnerabilityReportPDF.java | 45 ------------------- 4 files changed, 17 insertions(+), 98 deletions(-) delete mode 100644 libs/dao/src/main/java/com/akto/dao/VulnerabilityReportPDFDao.java delete mode 100644 libs/dao/src/main/java/com/akto/dto/VulnerabilityReportPDF.java diff --git a/apps/dashboard/src/main/java/com/akto/action/ReportAction.java b/apps/dashboard/src/main/java/com/akto/action/ReportAction.java index d097268fb7..bda2c52dca 100644 --- a/apps/dashboard/src/main/java/com/akto/action/ReportAction.java +++ b/apps/dashboard/src/main/java/com/akto/action/ReportAction.java @@ -1,5 +1,6 @@ package com.akto.action; +import java.net.URL; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Executors; @@ -10,9 +11,10 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -import com.akto.dao.VulnerabilityReportPDFDao; -import com.akto.dto.VulnerabilityReportPDF; +import com.akto.dao.testing.sources.TestReportsDao; +import com.akto.dto.testing.sources.TestReports; import com.mongodb.client.model.Filters; +import com.mongodb.client.model.Updates; import org.apache.struts2.ServletActionContext; import org.bson.types.ObjectId; import org.json.JSONObject; @@ -46,11 +48,20 @@ public String downloadReportPDF() { return ERROR.toUpperCase(); } + String reportUrlId; + try { + String path = new URL(reportUrl).getPath(); + String[] segments = path.split("/"); + reportUrlId = segments[segments.length - 1]; + } catch (Exception e) { + reportUrlId = ""; + } + if(firstPollRequest) { - VulnerabilityReportPDF vulnerabilityReportPDF = VulnerabilityReportPDFDao.instance.findOne(Filters.eq(VulnerabilityReportPDF.VULNERABILITY_REPORT_URL, reportUrl)); - if(vulnerabilityReportPDF != null && (vulnerabilityReportPDF.getVulnerabilityReportPDFBinary() != null || !vulnerabilityReportPDF.getVulnerabilityReportPDFBinary().isEmpty())) { + TestReports testReport = TestReportsDao.instance.findOne(Filters.eq("_id", new ObjectId(reportUrlId))); + if(testReport != null && (testReport.getPdfReportString() != null && !testReport.getPdfReportString().isEmpty())) { status = "COMPLETED"; - pdf = vulnerabilityReportPDF.getVulnerabilityReportPDFBinary(); + pdf = testReport.getPdfReportString(); return SUCCESS.toUpperCase(); } } @@ -108,11 +119,7 @@ public String downloadReportPDF() { if (status.equals("COMPLETED")) { loggerMaker.infoAndAddToDb("Pdf download status for report id - " + reportId + " completed. Attaching pdf in response ", LogDb.DASHBOARD); pdf = node.get("base64PDF").textValue(); - VulnerabilityReportPDFDao.instance.insertOne(new VulnerabilityReportPDF( - reportUrl, - pdf, - Context.now() - )); + TestReportsDao.instance.updateOne(Filters.eq("_id", new ObjectId(reportUrlId)), Updates.set(TestReports.PDF_REPORT_STRING, pdf)); } } catch (Exception e) { loggerMaker.errorAndAddToDb(e, "Error while polling pdf download for report id - " + reportId, LogDb.DASHBOARD); diff --git a/libs/dao/src/main/java/com/akto/DaoInit.java b/libs/dao/src/main/java/com/akto/DaoInit.java index 08d97119ce..7e4ea5a2fe 100644 --- a/libs/dao/src/main/java/com/akto/DaoInit.java +++ b/libs/dao/src/main/java/com/akto/DaoInit.java @@ -409,7 +409,6 @@ public static void createIndices() { TrafficAlertsDao.instance.createIndicesIfAbsent(); RuntimeMetricsDao.instance.createIndicesIfAbsent(); ApiAuditLogsDao.instance.createIndicesIfAbsent(); - VulnerabilityReportPDFDao.instance.createIndicesIfAbsent(); } } diff --git a/libs/dao/src/main/java/com/akto/dao/VulnerabilityReportPDFDao.java b/libs/dao/src/main/java/com/akto/dao/VulnerabilityReportPDFDao.java deleted file mode 100644 index 25558d10e5..0000000000 --- a/libs/dao/src/main/java/com/akto/dao/VulnerabilityReportPDFDao.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.akto.dao; - -import com.akto.dao.context.Context; -import com.akto.dto.VulnerabilityReportPDF; -import com.mongodb.client.MongoDatabase; - -public class VulnerabilityReportPDFDao extends AccountsContextDao { - - public static final VulnerabilityReportPDFDao instance = new VulnerabilityReportPDFDao(); - - public VulnerabilityReportPDFDao() {} - - @Override - public String getCollName() { - return "vulnerability_report_pdf"; - } - - @Override - public Class getClassT() { - return VulnerabilityReportPDF.class; - } - - - public void createIndicesIfAbsent() { - boolean exists = false; - String dbName = Context.accountId.get()+""; - MongoDatabase db = clients[0].getDatabase(dbName); - for (String col: db.listCollectionNames()){ - if (getCollName().equalsIgnoreCase(col)){ - exists = true; - break; - } - } - - if (!exists) { - db.createCollection(getCollName()); - } - - MCollection.createIndexIfAbsent(getDBName(), getCollName(), new String[] { VulnerabilityReportPDF.VULNERABILITY_REPORT_URL }, false); - } - -} diff --git a/libs/dao/src/main/java/com/akto/dto/VulnerabilityReportPDF.java b/libs/dao/src/main/java/com/akto/dto/VulnerabilityReportPDF.java deleted file mode 100644 index b638beb6f0..0000000000 --- a/libs/dao/src/main/java/com/akto/dto/VulnerabilityReportPDF.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.akto.dto; - -public class VulnerabilityReportPDF { - - public static final String VULNERABILITY_REPORT_URL = "vulnerabilityReportUrl"; - private String vulnerabilityReportUrl; - - public static final String VULNERABILITY_REPORT_PDF_BINARY = "vulnerabilityReportPDFBinary"; - private String vulnerabilityReportPDFBinary; - - public static final String LAST_UPDATE_TIME_STAMP = "lastUpdateTimeStamp"; - private int lastUpdateTimestamp; - - public VulnerabilityReportPDF() {} - - public VulnerabilityReportPDF(String vulnerabilityReportUrl, String vulnerabilityReportPDFBinary, int lastUpdateTimestamp) { - this.vulnerabilityReportUrl = vulnerabilityReportUrl; - this.vulnerabilityReportPDFBinary = vulnerabilityReportPDFBinary; - this.lastUpdateTimestamp = lastUpdateTimestamp; - } - - public String getVulnerabilityReportUrl() { - return vulnerabilityReportUrl; - } - - public void setVulnerabilityReportUrl(String vulnerabilityReportUrl) { - this.vulnerabilityReportUrl = vulnerabilityReportUrl; - } - - public String getVulnerabilityReportPDFBinary() { - return vulnerabilityReportPDFBinary; - } - - public void setVulnerabilityReportPDFBinary(String vulnerabilityReportPDFBinary) { - this.vulnerabilityReportPDFBinary = vulnerabilityReportPDFBinary; - } - - public int getLastUpdateTimestamp() { - return lastUpdateTimestamp; - } - - public void setLastUpdateTimestamp(int lastUpdateTimestamp) { - this.lastUpdateTimestamp = lastUpdateTimestamp; - } -} From 015cffb97fbf84260b657aad3d0216dcc04a225f Mon Sep 17 00:00:00 2001 From: Umesh Kumar <166806589+TangoBeeAkto@users.noreply.github.com> Date: Fri, 10 Jan 2025 14:32:11 +0530 Subject: [PATCH 06/10] fix: validate report URL ID and update environment variable for PDF download service --- .../java/com/akto/action/ReportAction.java | 20 ++++++++++++++----- .../VulnerabilityReport.jsx | 2 +- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/apps/dashboard/src/main/java/com/akto/action/ReportAction.java b/apps/dashboard/src/main/java/com/akto/action/ReportAction.java index bda2c52dca..5bbd28825e 100644 --- a/apps/dashboard/src/main/java/com/akto/action/ReportAction.java +++ b/apps/dashboard/src/main/java/com/akto/action/ReportAction.java @@ -54,11 +54,21 @@ public String downloadReportPDF() { String[] segments = path.split("/"); reportUrlId = segments[segments.length - 1]; } catch (Exception e) { - reportUrlId = ""; + status = "ERROR"; + addActionError("Report URL cannot be empty"); + return ERROR.toUpperCase(); + } + + if(!ObjectId.isValid(reportUrlId)) { + status = "ERROR"; + addActionError("Report URL is invalid"); + return ERROR.toUpperCase(); } + ObjectId reportUrlIdObj = new ObjectId(reportUrlId); + if(firstPollRequest) { - TestReports testReport = TestReportsDao.instance.findOne(Filters.eq("_id", new ObjectId(reportUrlId))); + TestReports testReport = TestReportsDao.instance.findOne(Filters.eq("_id", reportUrlIdObj)); if(testReport != null && (testReport.getPdfReportString() != null && !testReport.getPdfReportString().isEmpty())) { status = "COMPLETED"; pdf = testReport.getPdfReportString(); @@ -87,7 +97,7 @@ public String downloadReportPDF() { session.setAttribute("login", Context.now()); } - String url = System.getenv("REPORT_PUPPETEER_REPLAY_SERVICE_URL") + "/downloadReportPDF"; + String url = System.getenv("PUPPETEER_REPLAY_SERVICE_URL") + "/downloadReportPDF"; JSONObject requestBody = new JSONObject(); requestBody.put("reportId", reportId); requestBody.put("username", user.getName()); @@ -108,7 +118,7 @@ public String downloadReportPDF() { loggerMaker.infoAndAddToDb("Polling pdf download status for report id - " + reportId, LogDb.DASHBOARD); try { - String url = System.getenv("REPORT_PUPPETEER_REPLAY_SERVICE_URL") + "/downloadReportPDF"; + String url = System.getenv("PUPPETEER_REPLAY_SERVICE_URL") + "/downloadReportPDF"; JSONObject requestBody = new JSONObject(); requestBody.put("reportId", reportId); String reqData = requestBody.toString(); @@ -119,7 +129,7 @@ public String downloadReportPDF() { if (status.equals("COMPLETED")) { loggerMaker.infoAndAddToDb("Pdf download status for report id - " + reportId + " completed. Attaching pdf in response ", LogDb.DASHBOARD); pdf = node.get("base64PDF").textValue(); - TestReportsDao.instance.updateOne(Filters.eq("_id", new ObjectId(reportUrlId)), Updates.set(TestReports.PDF_REPORT_STRING, pdf)); + TestReportsDao.instance.updateOne(Filters.eq("_id", reportUrlIdObj), Updates.set(TestReports.PDF_REPORT_STRING, pdf)); } } catch (Exception e) { loggerMaker.errorAndAddToDb(e, "Error while polling pdf download for report id - " + reportId, LogDb.DASHBOARD); diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx index 35fed5f482..775094ef5c 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx +++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx @@ -332,7 +332,7 @@ const VulnerabilityReport = () => {
{ - (window.USER_NAME?.toLowerCase()?.includes("ababank") || window.ACCOUNT_NAME?.toLowerCase()?.includes("advanced bank")) ? : <> + (window.USER_NAME?.toLowerCase()?.includes("@akto.io") || window.ACCOUNT_NAME?.toLowerCase()?.includes("advanced bank")) ? : <> } Logo
From 052e4ca3677ccbfe4c81ea63909bdef5be044ef4 Mon Sep 17 00:00:00 2001 From: Umesh Kumar <166806589+TangoBeeAkto@users.noreply.github.com> Date: Fri, 10 Jan 2025 15:13:00 +0530 Subject: [PATCH 07/10] fix: improve report PDF generation toast handling and prevent duplicate messages --- .../vulnerability_report/VulnerabilityReport.jsx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx index 775094ef5c..b3d20ba660 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx +++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx @@ -246,11 +246,15 @@ const VulnerabilityReport = () => { func.setToast(true, false, "Preparing your report. This might take a moment...") }, 1000) + let generationStarted = false setTimeout(() => { clearInterval(reportToastInterval) - reportToastInterval = setInterval(() => { - func.setToast(true, false, "Report PDF generation in progress. Please wait...") - }, 1000) + generationStarted = true + if(status === "IN_PROGRESS") { + reportToastInterval = setInterval(() => { + func.setToast(true, false, "Report PDF generation in progress. Please wait...") + }, 1000) + } }, 6000) try { @@ -276,7 +280,9 @@ const VulnerabilityReport = () => { await func.sleep(WAIT_DURATION) - func.setToast(true, false, "Report PDF generation in progress. Please wait...") + if(generationStarted) { + func.setToast(generationStarted, false, "Report PDF generation in progress. Please wait...") + } } } else { if(status !== "COMPLETED") { From cb428aca242ce09065034335f669f7136b5ac2eb Mon Sep 17 00:00:00 2001 From: Umesh Kumar <166806589+TangoBeeAkto@users.noreply.github.com> Date: Fri, 10 Jan 2025 15:18:49 +0530 Subject: [PATCH 08/10] fix: toast message handling --- .../testing/vulnerability_report/VulnerabilityReport.jsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx index b3d20ba660..07082a8c4b 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx +++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx @@ -280,9 +280,7 @@ const VulnerabilityReport = () => { await func.sleep(WAIT_DURATION) - if(generationStarted) { - func.setToast(generationStarted, false, "Report PDF generation in progress. Please wait...") - } + func.setToast(generationStarted, false, "Report PDF generation in progress. Please wait...") } } else { if(status !== "COMPLETED") { From b13baaf9ccf399791b7881de7fab9cd704bccda4 Mon Sep 17 00:00:00 2001 From: Umesh Kumar <166806589+TangoBeeAkto@users.noreply.github.com> Date: Mon, 13 Jan 2025 17:13:11 +0530 Subject: [PATCH 09/10] fix: add error message for PDF download failure due to large size --- .../testing/vulnerability_report/VulnerabilityReport.jsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx index 07082a8c4b..320f9c7cb4 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx +++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx @@ -281,6 +281,10 @@ const VulnerabilityReport = () => { await func.sleep(WAIT_DURATION) func.setToast(generationStarted, false, "Report PDF generation in progress. Please wait...") + + if(i === MAX_RETRIES - 1) { + } + pdfError = "Failed to download PDF. The size might be too large. Filter out unnecessary issues and try again." } } else { if(status !== "COMPLETED") { From 87bc3bba4d1e8d268f98d0519896992f9b82ba19 Mon Sep 17 00:00:00 2001 From: Umesh Kumar <166806589+TangoBeeAkto@users.noreply.github.com> Date: Mon, 13 Jan 2025 18:24:55 +0530 Subject: [PATCH 10/10] fix: enhance error handling for PDF download and update toast messages --- .../java/com/akto/action/ReportAction.java | 20 +++++++++++++++++-- .../VulnerabilityReport.jsx | 8 ++++---- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/apps/dashboard/src/main/java/com/akto/action/ReportAction.java b/apps/dashboard/src/main/java/com/akto/action/ReportAction.java index 5bbd28825e..609ed8a46a 100644 --- a/apps/dashboard/src/main/java/com/akto/action/ReportAction.java +++ b/apps/dashboard/src/main/java/com/akto/action/ReportAction.java @@ -13,6 +13,7 @@ import com.akto.dao.testing.sources.TestReportsDao; import com.akto.dto.testing.sources.TestReports; +import com.mongodb.MongoCommandException; import com.mongodb.client.model.Filters; import com.mongodb.client.model.Updates; import org.apache.struts2.ServletActionContext; @@ -40,7 +41,7 @@ public class ReportAction extends UserAction { private boolean firstPollRequest; private static final LoggerMaker loggerMaker = new LoggerMaker(ReportAction.class); - + public String downloadReportPDF() { if(reportUrl == null || reportUrl.isEmpty()) { status = "ERROR"; @@ -129,7 +130,22 @@ public String downloadReportPDF() { if (status.equals("COMPLETED")) { loggerMaker.infoAndAddToDb("Pdf download status for report id - " + reportId + " completed. Attaching pdf in response ", LogDb.DASHBOARD); pdf = node.get("base64PDF").textValue(); - TestReportsDao.instance.updateOne(Filters.eq("_id", reportUrlIdObj), Updates.set(TestReports.PDF_REPORT_STRING, pdf)); + try { + TestReportsDao.instance.updateOne(Filters.eq("_id", reportUrlIdObj), Updates.set(TestReports.PDF_REPORT_STRING, pdf)); + } catch(Exception e) { + loggerMaker.errorAndAddToDb("Error: " + e.getMessage() + ", while updating report binary for reportId: " + reportId, LogDb.DASHBOARD); + if (e instanceof MongoCommandException) { + MongoCommandException mongoException = (MongoCommandException) e; + if (mongoException.getCode() == 17420) { + addActionError("The report is too large to save. Please reduce its size and try again."); + } else { + addActionError("A database error occurred while saving the report. Try again later."); + } + } else { + addActionError("An error occurred while updating the report in DB. Please try again."); + } + status = "ERROR"; + } } } catch (Exception e) { loggerMaker.errorAndAddToDb(e, "Error while polling pdf download for report id - " + reportId, LogDb.DASHBOARD); diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx index 320f9c7cb4..fb68a80bfe 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx +++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/vulnerability_report/VulnerabilityReport.jsx @@ -283,8 +283,8 @@ const VulnerabilityReport = () => { func.setToast(generationStarted, false, "Report PDF generation in progress. Please wait...") if(i === MAX_RETRIES - 1) { + pdfError = "Failed to download PDF. The size might be too large. Filter out unnecessary issues and try again." } - pdfError = "Failed to download PDF. The size might be too large. Filter out unnecessary issues and try again." } } else { if(status !== "COMPLETED") { @@ -292,7 +292,7 @@ const VulnerabilityReport = () => { } } } catch (err) { - pdfError = err.message + pdfError = err?.response?.data?.actionErrors?.[0] || err.message } clearInterval(reportToastInterval) @@ -318,13 +318,13 @@ const VulnerabilityReport = () => { link.click(); func.setToast(true, false, "Report PDF downloaded.") } catch (err) { - pdfError = err.message + pdfError = err?.response?.data?.actionErrors?.[0] || err.message } } } if (pdfError !== "") { - func.setToast(true, true, `Error while downloading PDF. Please try again. \nError: ${pdfError}`) + func.setToast(true, true, `Error: ${pdfError}`) } setPdfDownloadEnabled(true)