Skip to content

Commit

Permalink
feat: storing vul report pdf in db
Browse files Browse the repository at this point in the history
  • Loading branch information
TangoBeeAkto committed Jan 10, 2025
1 parent 058a93f commit 23831da
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 7 deletions.
21 changes: 21 additions & 0 deletions apps/dashboard/src/main/java/com/akto/action/ReportAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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

Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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'
Expand Down Expand Up @@ -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 = ""
Expand All @@ -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
Expand All @@ -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) {
Expand Down Expand Up @@ -321,7 +331,9 @@ const VulnerabilityReport = () => {
<Text variant="bodySm">{currentDate}</Text>
</VerticalStack>
<div style={{ display: 'flex', alignItems: 'center' }}>
{/* <Button primary onClick={() => handleDownloadPF()} disabled={!pdfDownloadEnabled}>Download</Button> */}
{
window.USER_NAME?.toLowerCase()?.includes("ababank") ? <Button primary onClick={() => handleDownloadPF()} disabled={!pdfDownloadEnabled}>Download</Button> : <></>
}
<img src='/public/white_logo.svg' alt="Logo" className='top-bar-logo' />
</div>
</HorizontalStack>
Expand Down
1 change: 1 addition & 0 deletions libs/dao/src/main/java/com/akto/DaoInit.java
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,7 @@ public static void createIndices() {
TrafficAlertsDao.instance.createIndicesIfAbsent();
RuntimeMetricsDao.instance.createIndicesIfAbsent();
ApiAuditLogsDao.instance.createIndicesIfAbsent();
VulnerabilityReportPDFDao.instance.createIndicesIfAbsent();
}

}
42 changes: 42 additions & 0 deletions libs/dao/src/main/java/com/akto/dao/VulnerabilityReportPDFDao.java
Original file line number Diff line number Diff line change
@@ -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<VulnerabilityReportPDF> {

public static final VulnerabilityReportPDFDao instance = new VulnerabilityReportPDFDao();

public VulnerabilityReportPDFDao() {}

@Override
public String getCollName() {
return "vulnerability_report_pdf";
}

@Override
public Class<VulnerabilityReportPDF> 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);
}

}
45 changes: 45 additions & 0 deletions libs/dao/src/main/java/com/akto/dto/VulnerabilityReportPDF.java
Original file line number Diff line number Diff line change
@@ -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;
}
}

0 comments on commit 23831da

Please sign in to comment.