diff --git a/apps/dashboard/src/main/java/com/akto/action/BurpJarAction.java b/apps/dashboard/src/main/java/com/akto/action/BurpJarAction.java index 537382cf0d..26a92426f7 100644 --- a/apps/dashboard/src/main/java/com/akto/action/BurpJarAction.java +++ b/apps/dashboard/src/main/java/com/akto/action/BurpJarAction.java @@ -64,6 +64,7 @@ public String fetchBurpCredentials() { apiToken = ApiTokensDao.instance.findOne( Filters.and( Filters.eq(ApiToken.USER_NAME, getSUser().getLogin()), + Filters.eq(ApiToken.ACCOUNT_ID, Context.accountId.get()), Filters.eq(ApiToken.UTILITY, ApiToken.Utility.BURP) ) ); diff --git a/apps/dashboard/src/main/java/com/akto/action/testing/StartTestAction.java b/apps/dashboard/src/main/java/com/akto/action/testing/StartTestAction.java index f4f7aefd2d..59dff5577d 100644 --- a/apps/dashboard/src/main/java/com/akto/action/testing/StartTestAction.java +++ b/apps/dashboard/src/main/java/com/akto/action/testing/StartTestAction.java @@ -26,6 +26,9 @@ import com.akto.util.Constants; import com.akto.util.enums.GlobalEnums.TestErrorSource; import com.akto.utils.Utils; +import com.google.gson.Gson; +import com.google.gson.JsonParser; +import com.mongodb.BasicDBList; import com.mongodb.BasicDBObject; import com.mongodb.client.model.Filters; import com.mongodb.client.model.Projections; @@ -71,6 +74,7 @@ public class StartTestAction extends UserAction { private Map allTestsCountMap = new HashMap<>(); private Map issuesSummaryInfoMap = new HashMap<>(); private String testRoleId; + private static final Gson gson = new Gson(); private static List getTestingRunListFromSummary(Bson filters) { Bson projections = Projections.fields( @@ -480,23 +484,46 @@ public String fetchVulnerableTestRunResults() { List testingRunResultList = TestingRunResultDao.instance.findAll(filters, skip, 50, null); Map sampleDataVsCurlMap = new HashMap<>(); for (TestingRunResult runResult: testingRunResultList) { - List testResults = new ArrayList<>(); - // todo: fix + WorkflowTest workflowTest = runResult.getWorkflowTest(); for (GenericTestResult tr : runResult.getTestResults()) { - TestResult testResult = (TestResult) tr; - if (testResult.isVulnerable()) { - testResults.add(testResult); - sampleDataVsCurlMap.put(testResult.getMessage(), - ExportSampleDataAction.getCurl(testResult.getMessage())); - sampleDataVsCurlMap.put(testResult.getOriginalMessage(), - ExportSampleDataAction.getCurl(testResult.getOriginalMessage())); + if (tr.isVulnerable()) { + if (tr instanceof TestResult) { + TestResult testResult = (TestResult) tr; + sampleDataVsCurlMap.put(testResult.getMessage(), + ExportSampleDataAction.getCurl(testResult.getMessage())); + sampleDataVsCurlMap.put(testResult.getOriginalMessage(), + ExportSampleDataAction.getCurl(testResult.getOriginalMessage())); + } else if (tr instanceof MultiExecTestResult){ + MultiExecTestResult testResult = (MultiExecTestResult) tr; + Map nodeResultMap = testResult.getNodeResultMap(); + for (String order : nodeResultMap.keySet()) { + WorkflowTestResult.NodeResult nodeResult = nodeResultMap.get(order); + String nodeResultLastMessage = getNodeResultLastMessage(nodeResult.getMessage()); + if (nodeResultLastMessage != null) { + nodeResult.setMessage(nodeResultLastMessage); + sampleDataVsCurlMap.put(nodeResultLastMessage, + ExportSampleDataAction.getCurl(nodeResultLastMessage)); + } + } + } + } + } + if (workflowTest != null) { + Map nodeDetailsMap = workflowTest.getMapNodeIdToWorkflowNodeDetails(); + for (String nodeName: nodeDetailsMap.keySet()) { + if (nodeDetailsMap.get(nodeName) instanceof YamlNodeDetails) { + YamlNodeDetails details = (YamlNodeDetails) nodeDetailsMap.get(nodeName); + sampleDataVsCurlMap.put(details.getOriginalMessage(), + ExportSampleDataAction.getCurl(details.getOriginalMessage())); + } + } } - runResult.setTestResults(testResults); } this.testingRunResults = testingRunResultList; this.sampleDataVsCurlMap = sampleDataVsCurlMap; } catch (Exception e) { + loggerMaker.errorAndAddToDb("Error while executing test run summary" + e.getMessage(), LogDb.DASHBOARD); addActionError("Invalid test summary id"); return ERROR.toUpperCase(); } @@ -504,6 +531,15 @@ public String fetchVulnerableTestRunResults() { return SUCCESS.toUpperCase(); } + private String getNodeResultLastMessage(String message) { + if (StringUtils.isEmpty(message) || "[]".equals(message)) { + return null; + } + List listOfMessage = gson.fromJson(message, List.class); + Object vulnerableMessage = listOfMessage.get(listOfMessage.size() - 1); + return gson.toJson(vulnerableMessage); + } + private String testingRunResultHexId; private TestingRunResult testingRunResult; diff --git a/apps/dashboard/web/pages/login.jsp b/apps/dashboard/web/pages/login.jsp index 4b2700e25f..bcb41d34c0 100644 --- a/apps/dashboard/web/pages/login.jsp +++ b/apps/dashboard/web/pages/login.jsp @@ -131,19 +131,9 @@ // the user will always see the old login screen script.type = "text/javascript" if (window.RELEASE_VERSION_GLOBAL == '' || window.RELEASE_VERSION_GLOBAL == 'akto-release-version') {// Case when akto version is not available - if (window.AKTO_UI_MODE == 'VERSION_2') { - script.src = "/polaris_web/web/dist/main.js"; - } else { - script.src = "/dist/main.js"; - } - } else if (window.RELEASE_VERSION == '' || window.RELEASE_VERSION == 'akto-release-version') { - script.src = "https://d1hvi6xs55woen.cloudfront.net/web/" + window.RELEASE_VERSION_GLOBAL + "/dist/main.js";; + script.src = "/polaris_web/web/dist/main.js"; } else { - if (window.AKTO_UI_MODE == 'VERSION_2') { - script.src = "https://d1hvi6xs55woen.cloudfront.net/polaris_web/" + window.RELEASE_VERSION + "/dist/main.js"; - } else { - script.src = "https://d1hvi6xs55woen.cloudfront.net/web/" + window.RELEASE_VERSION + "/dist/main.js"; - } + script.src = "https://d1hvi6xs55woen.cloudfront.net/polaris_web/" + window.RELEASE_VERSION_GLOBAL + "/dist/main.js";; } document.body.appendChild(script); diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/components/layouts/PasswordTextField.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/components/layouts/PasswordTextField.jsx index 4e5d46be7e..b856667e76 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/components/layouts/PasswordTextField.jsx +++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/components/layouts/PasswordTextField.jsx @@ -26,6 +26,7 @@ function PasswordTextField(props) { return ( ) } diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api_collections/ApiEndpoints.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api_collections/ApiEndpoints.jsx index ea0bc59410..9fa0ae3923 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api_collections/ApiEndpoints.jsx +++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api_collections/ApiEndpoints.jsx @@ -31,11 +31,13 @@ const headings = [ text: "Endpoint", value: "endpointComp", title: "Api endpoints", + textValue: "endpoint" }, { text: "Risk score", title: "Risk score", value: "riskScoreComp", + textValue: "riskScore" }, { text: "Hostname", @@ -56,20 +58,22 @@ const headings = [ title: 'Auth type', value: 'auth_type', showFilter: true, - type: CellType.TEXT, + textValue: 'authTypeTag' }, { text: 'Sensitive Params', title: 'Sensitive params', value: 'sensitiveTagsComp', filterKey: 'sensitiveTags', - showFilter: true + showFilter: true, + textValue: "sensitiveDataTags" }, { text: 'Last Seen', title: 'Last seen', value: 'last_seen', isText: true, + type: CellType.TEXT } ] @@ -77,7 +81,8 @@ let headers = JSON.parse(JSON.stringify(headings)) headers.push({ text: 'Method', filterKey: 'method', - showFilter: true + showFilter: true, + textValue: 'method', }) @@ -322,7 +327,7 @@ function ApiEndpoints() { function exportCsv() { if (!loading) { - let headerTextToValueMap = Object.fromEntries(headers.map(x => [x.text, x.value]).filter(x => x[0].length > 0)); + let headerTextToValueMap = Object.fromEntries(headers.map(x => [x.text, x.type === CellType.TEXT ? x.value : x.textValue]).filter(x => x[0].length > 0)); let csv = Object.keys(headerTextToValueMap).join(",") + "\r\n" const allEndpoints = endpointData['All'] diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/transform.js b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/transform.js index df784edc6a..0574c6a1f8 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/transform.js +++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/transform.js @@ -487,7 +487,8 @@ const transform = { sensitiveTagsComp: this.prettifySubtypes(url.sensitiveTags), riskScoreComp: {score.toString()}, riskScore: score, - isNew: this.isNewEndpoint(url.lastSeenTs) + isNew: this.isNewEndpoint(url.lastSeenTs), + sensitiveDataTags: url?.sensitiveTags.join(" "), } }) diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/ExportHtml/ExportHtml.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/ExportHtml/ExportHtml.jsx index 0b2f4ff5e2..3987a64197 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/ExportHtml/ExportHtml.jsx +++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/ExportHtml/ExportHtml.jsx @@ -3,51 +3,20 @@ import { useParams } from 'react-router-dom' import issuesApi from '../../issues/api'; import api from '../api'; import PersistStore from '../../../../main/PersistStore'; -import { Avatar, Box, Frame, HorizontalGrid, HorizontalStack, LegacyCard, Text, TopBar, VerticalStack, Icon} from '@shopify/polaris' -import {FlagMajor, CollectionsMajor, ResourcesMajor, InfoMinor, CreditCardSecureMajor, FraudProtectMajor} from "@shopify/polaris-icons" +import { Avatar, Box, Frame, HorizontalGrid, HorizontalStack, LegacyCard, Text, TopBar, VerticalStack, Icon } from '@shopify/polaris' +import { FlagMajor, CollectionsMajor, ResourcesMajor, InfoMinor, CreditCardSecureMajor, FraudProtectMajor } from "@shopify/polaris-icons" import './styles.css' import transform from '../transform'; function ExportHtml() { - const params = useParams() ; + const params = useParams(); const testingRunSummaryId = params.summaryId const issuesFilter = params.issuesFilter - const moreInfoSections = [ - { - icon: InfoMinor, - title: "Description", - content: "" - }, - { - icon: FlagMajor, - title: "Impact", - content: "" - }, - { - icon: CollectionsMajor, - title: "Tags", - content: "" - }, - { - icon: CreditCardSecureMajor, - title: "CWE", - content: "" - }, - { - icon: FraudProtectMajor, - title: "CVE", - content: "" - }, - { - icon: ResourcesMajor, - title: "References", - content: "" - } - ] - - const [vulnerableResultsMap, setVulnerableResultsMap] = useState([]) ; + let moreInfoSections = transform.getInfoSectionsHeaders().filter(item => item.title !== 'Jira') + + const [vulnerableResultsMap, setVulnerableResultsMap] = useState([]); const [dataToCurlObj, setDataToCurlObj] = useState({}); - const [severitiesCount,setSeveritiesCount] = useState({HIGH: 0, MEDIUM: 0, LOW: 0}) ; + const [severitiesCount, setSeveritiesCount] = useState({ HIGH: 0, MEDIUM: 0, LOW: 0 }); const collectionsMap = PersistStore(state => state.collectionsMap) const subCategoryMap = PersistStore(state => state.subCategoryMap) @@ -66,15 +35,15 @@ function ExportHtml() { let severity = subCategory?.superCategory?.severity?._name let severityIndex = 0; switch (severity) { - case 'HIGH': + case 'HIGH': ++high severityIndex = 2 break; - case 'MEDIUM': + case 'MEDIUM': ++medium severityIndex = 1 break; - case 'LOW': + case 'LOW': ++low severityIndex = 0 break; @@ -95,7 +64,7 @@ function ExportHtml() { vulnerabilities['severityIndex'] = severityIndex categoryVsVulMap[subtype] = vulnerabilities }) - setSeveritiesCount({HIGH: high, MEDIUM: medium, LOW: low}); + setSeveritiesCount({ HIGH: high, MEDIUM: medium, LOW: low }); let localCopy = vulnerableResultsMap Object.keys(categoryVsVulMap).forEach((category) => { let obj = categoryVsVulMap[category] @@ -112,17 +81,17 @@ function ExportHtml() { } const fetchVulnerableData = async () => { - let resultsCount = 0 ; + let resultsCount = 0; let vulnerableTestingRunResults = [] let sampleDataVsCurlMap = {} if (testingRunSummaryId) { - while(true){ + while (true) { let testingRunCountsFromDB = 0 - await api.fetchVulnerableTestingRunResults(testingRunSummaryId,resultsCount).then((resp)=>{ + await api.fetchVulnerableTestingRunResults(testingRunSummaryId, resultsCount).then((resp) => { vulnerableTestingRunResults = [...vulnerableTestingRunResults, ...resp.testingRunResults] testingRunCountsFromDB = resp.testingRunResults.length - sampleDataVsCurlMap = {...sampleDataVsCurlMap, ...resp.sampleDataVsCurlMap} + sampleDataVsCurlMap = { ...sampleDataVsCurlMap, ...resp.sampleDataVsCurlMap } }) resultsCount += 50 if (testingRunCountsFromDB < 50) { @@ -137,7 +106,7 @@ function ExportHtml() { await issuesApi.fetchVulnerableTestingRunResultsFromIssues(filters, resultsCount).then(resp => { vulnerableTestingRunResults = [...vulnerableTestingRunResults, ...resp.testingRunResults] testingRunCountsFromDB = resp.totalIssuesCount - sampleDataVsCurlMap = {...sampleDataVsCurlMap, ...resp.sampleDataVsCurlMap} + sampleDataVsCurlMap = { ...sampleDataVsCurlMap, ...resp.sampleDataVsCurlMap } }) resultsCount += 50 if (testingRunCountsFromDB < 50 || resultsCount >= 1000) { @@ -150,18 +119,18 @@ function ExportHtml() { createVulnerabilityMap(vulnerableTestingRunResults) } - useEffect(()=>{ + useEffect(() => { fetchVulnerableData() - },[]) + }, []) const headerComp = (
- + - Akto Vulnerabilities Report + Akto Vulnerabilities Report
@@ -170,15 +139,15 @@ function ExportHtml() { ) - const getColor = (item) =>{ - switch(item.category.severityIndex){ + const getColor = (item) => { + switch (item.category.severityIndex) { case 0: return "bg-caution" - case 1 : + case 1: return "bg-warning" - case 2 : + case 2: return "bg-critical" default: @@ -191,20 +160,20 @@ function ExportHtml() { } - const cardTitleComponent = (item) =>{ - return( + const cardTitleComponent = (item) => { + return ( - - - Vulnerability + + + Vulnerability + - - - - {item?.category.testName} + + + {item?.category.testName} + - ) @@ -212,14 +181,14 @@ function ExportHtml() { return ( -
+
Summary of alerts -
+
@@ -228,7 +197,7 @@ function ExportHtml() {
-
+
@@ -238,9 +207,9 @@ function ExportHtml() {
- {Object.keys(severitiesCount)?.map((element, index)=>( + {Object.keys(severitiesCount)?.map((element, index) => ( -
+
@@ -249,7 +218,7 @@ function ExportHtml() {
-
+
@@ -266,7 +235,7 @@ function ExportHtml() { Vulnerabilities details - {vulnerableResultsMap?.map((item,index)=>( + {vulnerableResultsMap?.map((item, index) => ( { if (str && str.length > 3000) { return str.substr(0, 3000) + ' .........'; @@ -300,102 +268,219 @@ function MoreInformationComponent(props) { return props.dataToCurlObj[message] } + const getResponse = (message) => { + let messageJson = JSON.parse(message) + if (messageJson['response']) { + return JSON.stringify(messageJson['response']) + } + return JSON.stringify({ "statusCode": messageJson['statusCode'], "body": messageJson['responsePayload'], "headers": messageJson['responseHeaders'] }) + } + + return ( +
+
+ {Object.keys(props.testingRun.workflowTest.mapNodeIdToWorkflowNodeDetails).map((stepId, index) => { + let step = props.testingRun.workflowTest.mapNodeIdToWorkflowNodeDetails[stepId] + let nodeResultMap = props.testingRun.testResults[0].nodeResultMap[stepId] + if (nodeResultMap.message !== '[]') { + let attempt = nodeResultMap.message + return ( +
+
+ + + Vulnerable endpoint: + + + {step.apiInfoKey.url} + + + + + + Collection name: {" "} + + + {props.collectionsMap[step.apiInfoKey.apiCollectionId]} + + + +
+
+
+ + Original request + + + Attempt + +
+
+ + {getTruncatedString(getOriginalCurl(step.originalMessage))} + + + {getTruncatedString(getOriginalCurl(attempt))} + +
+
+ + Original Response + + + Attempt Response + +
+
+ + {getTruncatedString(getResponse(step.originalMessage))} + + + {getTruncatedString(getResponse(attempt))} + +
+
+
+ + ) + } + })} + +
+
+ ) + +} + + +function VulnerableEndpointDetails(props) { + const getTruncatedString = (str) => { + if (str && str.length > 3000) { + return str.substr(0, 3000) + ' .........'; + } + return str; + } + + const getOriginalCurl = (message) => { + return props.dataToCurlObj[message] + } const getResponse = (message) => { let messageJson = JSON.parse(message) if (messageJson['response']) { return JSON.stringify(messageJson['response']) } - return JSON.stringify({"statusCode":messageJson['statusCode'], "body": messageJson['responsePayload'], "headers": messageJson['responseHeaders']}) + return JSON.stringify({ "statusCode": messageJson['statusCode'], "body": messageJson['responsePayload'], "headers": messageJson['responseHeaders'] }) } + return ( - - - - { - props.sections?.map((section, index) => { - return ( - - -
- {section?.icon && } -
- - {section.title || "Heading"} - -
- {section.content} -
-
) - }) - } -
- - {props.item?.category?.vulnerableTestingRunResults?.map((testingRun, index)=> ( -
-
- - - Vulnerable endpoint: - - - { testingRun.apiInfoKey.url } - - - - - - Collection name: {" "} - - - { props.collectionsMap[testingRun.apiInfoKey.apiCollectionId]} - - - +
+
+ + + Vulnerable endpoint: + + + {props.testingRun.apiInfoKey.url} + + + + + + Collection name: {" "} + + + {props.collectionsMap[props.testingRun.apiInfoKey.apiCollectionId]} + + + +
+ {props.testingRun?.testResults?.map((testRun, index1) => ( +
+
+ + Original request + + + Attempt + +
+
+ + {getTruncatedString(getOriginalCurl(testRun.originalMessage))} + + + {getTruncatedString(getOriginalCurl(testRun.message))} + +
+
+ + Original Response + + + Attempt Response + +
+
+ + {getTruncatedString(getResponse(testRun.originalMessage))} + + + {getTruncatedString(getResponse(testRun.message))} +
- {testingRun?.testResults?.map((testRun, index1) => ( -
-
- - Original request - - - Attempt - -
-
- - { getTruncatedString(getOriginalCurl(testRun.originalMessage)) } - - - { getTruncatedString(getOriginalCurl(testRun.message)) } - -
-
- - Original Response - - - Attempt Response - -
-
- - { getTruncatedString(getResponse(testRun.originalMessage)) } - - - { getTruncatedString(getResponse(testRun.message)) } - -
-
- ))}
))} - - - +
+ ) + +} + +function MoreInformationComponent(props) { + + return ( + + + + { + props.sections?.map((section, index) => { + return ( + + +
+ {section?.icon && } +
+ + {section.title || "Heading"} + +
+ {section.content} +
+
) + }) + } +
+ + {props.item?.category?.vulnerableTestingRunResults?.map((testingRun, index) => ( + testingRun.workflowTest ? : + ))} + +
+
) - } - +} + export default ExportHtml \ No newline at end of file diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/transform.js b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/transform.js index d18c9512ce..3d8aea4b1c 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/transform.js +++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/transform.js @@ -343,7 +343,7 @@ const transform = { fillMoreInformation(category, moreInfoSections, affectedEndpoints, jiraIssueUrl, createJiraTicket) { var key = /[^/]*$/.exec(jiraIssueUrl)[0]; - const jiraComponent = jiraIssueUrl.length > 0 ? ( + const jiraComponent = jiraIssueUrl?.length > 0 ? ( diff --git a/apps/dashboard/web/polaris_web/web/src/apps/main/App.js b/apps/dashboard/web/polaris_web/web/src/apps/main/App.js index 5f2ca1b9bc..cc880569f3 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/main/App.js +++ b/apps/dashboard/web/polaris_web/web/src/apps/main/App.js @@ -9,8 +9,6 @@ import SensitiveDataExposure from "../dashboard/pages/observe/SensitiveDataExpos import SingleRequest from "../dashboard/pages/observe/SingleRequest/SingleRequest"; import PageObserve from "../dashboard/pages/observe/PageObserve" import PageTesting from "../dashboard/pages/testing/PageTesting"; -import { AppProvider } from "@shopify/polaris" -import SignUp from "../signup/pages/SignUp" import { createBrowserRouter, RouterProvider, @@ -60,6 +58,7 @@ import HomeDashboard from "../dashboard/pages/dashboard/HomeDashboard"; import TestLibrary from "../dashboard/pages/settings/test_library/TestLibrary"; import { useStiggContext } from '@stigg/react-sdk'; import DependencyTable from "../dashboard/pages/testing/DependencyTable/DependencyTable"; +import SignupPage from "../signup/pages/SignupPage"; // if you add a component in a new path, please verify the search implementation in function -> 'getSearchItemsArr' in func.js @@ -285,13 +284,17 @@ const router = createBrowserRouter([ ], errorElement: }, -{ - path: "/login", - element: , -}, -{ - path: "/", - element: , + { + path: "/login", + element: , + }, + { + path: "/", + element: , + }, + { + path: "/signup", + element: , }, ]) diff --git a/apps/dashboard/web/polaris_web/web/src/apps/signup/api.js b/apps/dashboard/web/polaris_web/web/src/apps/signup/api.js index 2b27f933fb..93e8e1e335 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/signup/api.js +++ b/apps/dashboard/web/polaris_web/web/src/apps/signup/api.js @@ -53,5 +53,14 @@ export default { newAccountName } }) + }, + signupUser: function(email, password, invitationCode){ + return request({ + url: '/signup-email', + method: 'post', + data: { + email, password, invitationCode + } + }) } } \ No newline at end of file diff --git a/apps/dashboard/web/polaris_web/web/src/apps/signup/components/ProductPreview.jsx b/apps/dashboard/web/polaris_web/web/src/apps/signup/components/ProductPreview.jsx deleted file mode 100644 index 995a97c76c..0000000000 --- a/apps/dashboard/web/polaris_web/web/src/apps/signup/components/ProductPreview.jsx +++ /dev/null @@ -1,51 +0,0 @@ -import { useState } from "react" - -import {Box, Text, Icon, HorizontalStack, VerticalStack} from "@shopify/polaris" -import {ChevronLeftMinor, ChevronRightMinor} from "@shopify/polaris-icons" - -import ProductPreviewImages from "../util/productPreviewImages.js" - - -const ProductPreview = () => { - const [selectedIndex, setSelectedIndex ] = useState(0) - - const handleLeftProductPreviewNavigation = () => { - if (selectedIndex > 0) { - setSelectedIndex(selectedIndex - 1) - } - } - - const handleRightProductPreviewNavigation = () => { - if (selectedIndex < ProductPreviewImages.length - 1) { - setSelectedIndex(selectedIndex + 1) - } - } - - return ( - -
- - - - -
- -
- {selectedIndex + 1} / {ProductPreviewImages.length} -
- -
-
-
-
-
- ) -} - -export default ProductPreview \ No newline at end of file diff --git a/apps/dashboard/web/polaris_web/web/src/apps/signup/components/SSOTextfield.jsx b/apps/dashboard/web/polaris_web/web/src/apps/signup/components/SSOTextfield.jsx new file mode 100644 index 0000000000..50c4fdde39 --- /dev/null +++ b/apps/dashboard/web/polaris_web/web/src/apps/signup/components/SSOTextfield.jsx @@ -0,0 +1,15 @@ +import { Avatar, Button, HorizontalStack, Text } from '@shopify/polaris' +import React from 'react' + +function SSOTextfield({onClickFunc, logo , text}) { + return ( + + ) +} + +export default SSOTextfield \ No newline at end of file diff --git a/apps/dashboard/web/polaris_web/web/src/apps/signup/components/SignUp.jsx b/apps/dashboard/web/polaris_web/web/src/apps/signup/components/SignUp.jsx new file mode 100644 index 0000000000..65a6a8d484 --- /dev/null +++ b/apps/dashboard/web/polaris_web/web/src/apps/signup/components/SignUp.jsx @@ -0,0 +1,185 @@ +import { Avatar, Box, Button, Form, Frame, HorizontalStack, Page, Text, TextField, Toast, VerticalStack } from '@shopify/polaris' +import React, { useEffect, useState } from 'react' +import SSOTextfield from './SSOTextfield' +import PasswordTextField from '../../dashboard/components/layouts/PasswordTextField' +import { useLocation, useNavigate } from "react-router-dom" +import api from '../api' +import func from '@/util/func' +import "../styles.css" + +function SignUp() { + + const location = useLocation() + + const [ssoList, setSsoList] = useState([]) + const [email, setEmail] = useState("") + const [password, setPassword] = useState("") + const [loginActive, setLoginActive] = useState(location.pathname.includes("login")) + const [loading, setLoading] = useState(false) + + const oktaUrl = window.OKTA_AUTH_URL + const azureUrl = window.AZURE_REQUEST_URL + const githubId = window.GITHUB_CLIENT_ID + + const githubAuthObj = { + logo: '/public/github_icon.svg', + text: 'Continue with Github SSO', + onClickFunc: () => { window.location.href = ("https://github.com/login/oauth/authorize?client_id=" + githubId); } + } + + const azureAuthObj = { + logo: '/public/azure_logo.svg', + text: 'Continue with Azure SSO', + onClickFunc: () => { window.location.href = azureUrl } + } + + const oktaAuthObj = { + logo: '/public/okta_logo.svg', + text: 'Continue with Okta SSO', + onClickFunc: () => { window.location.href = oktaUrl } + } + + useEffect(() => { + let copySsoList = [] + if (githubId !== undefined && githubId.length > 0) { + copySsoList.push(githubAuthObj) + } + + if (oktaUrl !== undefined && oktaUrl.length > 0) { + copySsoList.push(oktaAuthObj) + } + + if (azureUrl !== undefined && azureUrl > 0) { + copySsoList.push(azureAuthObj) + } + + setSsoList(copySsoList) + + if (window.IS_SAAS && window.IS_SAAS === "true") { + window.location.href = "/"; + } + }, []) + + const ssoCard = ( + ssoList.length === 0 ? null : + + { + ssoList.map((sso, index) => { + return ( + + + +
+ or +
+
+
+ ) + }) + } +
+ ) + + const loginFunc = async() => { + setLoading(true) + if(loginActive){ + try { + await api.login(email, password) + } catch { + func.setToast(true, true, "Email or password incorrect. Please login again.") + } + }else{ + try { + api.signupUser(email, password, window.SIGNUP_INVITATION_CODE).then((resp)=> { + if (resp && resp.indexOf("<")== -1) { + func.setToast(true, true, "Signup error " + resp) + }else{ + navigate('/dashboard/onboarding') + } + }) + } catch (error) { + func.setToast(true, true, "Signup error " + error) + } + } + setLoading(false) + } + + const loginObject = { + headingText: "Welcome back", + buttonText: "Sign in", + linkText: "Sign up", + descriptionText: "Need to create a new organization?", + targetUrl: '/signup' + } + + const signupObject = { + headingText: "Create new account", + buttonText: "Sign up", + linkText: "Sign in", + descriptionText: "Already using Akto?", + targetUrl: '/login' + } + + const activeObject = loginActive ? loginObject : signupObject + const navigate = useNavigate() + + const signupEmailCard = ( + +
+ +
+ +
+
+ setPassword(val)} onFunc={true} field={password} label="Password" monospaced={true}/> +
+ +
+
+ + {activeObject.descriptionText} + + +
+ ) + return ( +
+ + + +
+ + + + +
+ +
+
+ + {activeObject.headingText} + + {ssoCard} + {signupEmailCard} + + + +
+
+ + +
+ + +
+ +
+
+
+ + +
+ ) +} + +export default SignUp \ No newline at end of file diff --git a/apps/dashboard/web/polaris_web/web/src/apps/signup/components/SignUpCard.jsx b/apps/dashboard/web/polaris_web/web/src/apps/signup/components/SignUpCard.jsx deleted file mode 100644 index 00544a4fdf..0000000000 --- a/apps/dashboard/web/polaris_web/web/src/apps/signup/components/SignUpCard.jsx +++ /dev/null @@ -1,111 +0,0 @@ -import { useState } from "react" -import { useNavigate } from "react-router-dom" -import api from "../api" - -import { TextField, Button, Box, Text, HorizontalStack, Divider, VerticalStack, Toast, Frame } from "@shopify/polaris" - -import AktoLogo from "../images/akto_logo.png" -import AktoLogoText from "../images/akto_logo_text.png" -import GoogleIcon from "../images/google.png" -import Store from "../../dashboard/store" - -const SignUpCard = () => { - const [email, setEmail] = useState('') - const [password, setPassword] = useState('') - - const toastConfig = Store(state => state.toastConfig) - const setToastConfig = Store(state => state.setToastConfig) - const storeUsername = Store(state => state.storeUsername) - - const isLocalDeploy = window.DASHBOARD_MODE && window.DASHBOARD_MODE.toLowerCase() === 'local_deploy' - - const setLoginErrorToast = () => { - setToastConfig({ - isActive: true, - isError: true, - message: "Please, Log in Again" - }) - } - - const disableLoginErrorToast = () => { - setToastConfig({ - isActive: false, - isError: false, - message: "" - }) - } - - const loginToastMarkup = toastConfig.isActive ? ( - - ) : null; - - const handleEmailChange = (inputEmail) => { - setEmail(inputEmail) - } - - const handlePasswordChange = (inputPassword) => { - setPassword(inputPassword) - } - - const handleContinueWithEmail = async () => { - try { - await api.login(email, password) - } catch { - setLoginErrorToast() - } - } - - return ( - -
- - - - - -
- Getting started - Start free, no credit card required -
- - - or - - - - - - - - - - - -
-
- - {loginToastMarkup} - -
-
-
- ) -} - -export default SignUpCard diff --git a/apps/dashboard/web/polaris_web/web/src/apps/signup/images/akto_logo.png b/apps/dashboard/web/polaris_web/web/src/apps/signup/images/akto_logo.png deleted file mode 100644 index 1aecd11c4c..0000000000 Binary files a/apps/dashboard/web/polaris_web/web/src/apps/signup/images/akto_logo.png and /dev/null differ diff --git a/apps/dashboard/web/polaris_web/web/src/apps/signup/images/akto_logo_text.png b/apps/dashboard/web/polaris_web/web/src/apps/signup/images/akto_logo_text.png deleted file mode 100644 index 301ac2fc8d..0000000000 Binary files a/apps/dashboard/web/polaris_web/web/src/apps/signup/images/akto_logo_text.png and /dev/null differ diff --git a/apps/dashboard/web/polaris_web/web/src/apps/signup/images/google.png b/apps/dashboard/web/polaris_web/web/src/apps/signup/images/google.png deleted file mode 100644 index 6545765bda..0000000000 Binary files a/apps/dashboard/web/polaris_web/web/src/apps/signup/images/google.png and /dev/null differ diff --git a/apps/dashboard/web/polaris_web/web/src/apps/signup/images/product-preview-images/product-preview-1.png b/apps/dashboard/web/polaris_web/web/src/apps/signup/images/product-preview-images/product-preview-1.png deleted file mode 100644 index f9eeeef542..0000000000 Binary files a/apps/dashboard/web/polaris_web/web/src/apps/signup/images/product-preview-images/product-preview-1.png and /dev/null differ diff --git a/apps/dashboard/web/polaris_web/web/src/apps/signup/images/product-preview-images/product-preview-2.png b/apps/dashboard/web/polaris_web/web/src/apps/signup/images/product-preview-images/product-preview-2.png deleted file mode 100644 index ce8b4ab5c7..0000000000 Binary files a/apps/dashboard/web/polaris_web/web/src/apps/signup/images/product-preview-images/product-preview-2.png and /dev/null differ diff --git a/apps/dashboard/web/polaris_web/web/src/apps/signup/pages/SignUp.jsx b/apps/dashboard/web/polaris_web/web/src/apps/signup/pages/SignUp.jsx deleted file mode 100644 index bb4f43548f..0000000000 --- a/apps/dashboard/web/polaris_web/web/src/apps/signup/pages/SignUp.jsx +++ /dev/null @@ -1,14 +0,0 @@ -import SignUpCard from "../components/SignUpCard" -import ProductPreview from "../components/ProductPreview" -import { Frame } from "@shopify/polaris" - -const SignUp = () => { - return ( -
- - -
- ) -} - -export default SignUp \ No newline at end of file diff --git a/apps/dashboard/web/polaris_web/web/src/apps/signup/pages/SignupPage.jsx b/apps/dashboard/web/polaris_web/web/src/apps/signup/pages/SignupPage.jsx new file mode 100644 index 0000000000..f0e9077dc6 --- /dev/null +++ b/apps/dashboard/web/polaris_web/web/src/apps/signup/pages/SignupPage.jsx @@ -0,0 +1,36 @@ +import React from 'react' +import SignUp from "../components/SignUp" +import { Box, Text, VerticalStack } from '@shopify/polaris' + +function SignupPage() { + + const imageStyle = { + width: '953px', + borderRadius: '12px', + border: '6px solid', + marginTop: '90px' + } + return ( +
+
+ + + + {`"It's truly a game-changer and we highly recommend Akto to anyone looking to effortlessly secure their API endpoints."`} + + + — Security team + Enterprise SaaS customer + + ss + + +
+
+ +
+
+ ) +} + +export default SignupPage \ No newline at end of file diff --git a/apps/dashboard/web/polaris_web/web/src/apps/signup/styles.css b/apps/dashboard/web/polaris_web/web/src/apps/signup/styles.css new file mode 100644 index 0000000000..7e91daa3b7 --- /dev/null +++ b/apps/dashboard/web/polaris_web/web/src/apps/signup/styles.css @@ -0,0 +1,12 @@ +.akto-logo .Polaris-Avatar__Image{ + height: unset !important; +} + +.akto-logo .Polaris-Avatar__size2xl--experimental { + width: 117px !important; + height: 38px !important; +} + +.login-page .Polaris-Frame__Main{ + background: var(--white) !important; +} \ No newline at end of file diff --git a/apps/dashboard/web/polaris_web/web/src/apps/signup/util/productPreviewImages.js b/apps/dashboard/web/polaris_web/web/src/apps/signup/util/productPreviewImages.js deleted file mode 100644 index 8c848bb409..0000000000 --- a/apps/dashboard/web/polaris_web/web/src/apps/signup/util/productPreviewImages.js +++ /dev/null @@ -1,7 +0,0 @@ -import PP1 from "../images/product-preview-images/product-preview-1.png" -import PP2 from "../images/product-preview-images/product-preview-2.png" - -export default [ - PP1, - PP2, -] \ No newline at end of file diff --git a/apps/dashboard/web/polaris_web/web/src/util/func.js b/apps/dashboard/web/polaris_web/web/src/util/func.js index ca88abfced..544eab0d7a 100644 --- a/apps/dashboard/web/polaris_web/web/src/util/func.js +++ b/apps/dashboard/web/polaris_web/web/src/util/func.js @@ -730,6 +730,7 @@ mergeApiInfoAndApiCollection(listEndpoints, apiInfoList, idToName) { } let authType = apiInfoMap[key] ? apiInfoMap[key]["actualAuthType"].join(", ") : "" + let authTypeTag = authType.replace(",", ""); let score = apiInfoMap[key] ? apiInfoMap[key]?.severityScore : 0 let isSensitive = apiInfoMap[key] ? apiInfoMap[key]?.isSensitive : false @@ -755,6 +756,7 @@ mergeApiInfoAndApiCollection(listEndpoints, apiInfoList, idToName) { apiCollectionName: idToName ? (idToName[x.apiCollectionId] || '-') : '-', auth_type: (authType || "").toLowerCase(), sensitiveTags: [...this.convertSensitiveTags(x.sensitive)], + authTypeTag: (authTypeTag || "").toLowerCase(), collectionIds: apiInfoMap[key] ? apiInfoMap[key]?.collectionIds.filter(x => { return Object.keys(apiGroupsMap).includes(x) || Object.keys(apiGroupsMap).includes(x.toString()) }).map( x => { diff --git a/apps/dashboard/web/public/logo_google.svg b/apps/dashboard/web/public/logo_google.svg new file mode 100644 index 0000000000..f919587bcd --- /dev/null +++ b/apps/dashboard/web/public/logo_google.svg @@ -0,0 +1 @@ + diff --git a/apps/dashboard/web/public/productss.png b/apps/dashboard/web/public/productss.png new file mode 100644 index 0000000000..ab02ae4083 Binary files /dev/null and b/apps/dashboard/web/public/productss.png differ diff --git a/apps/testing/src/main/java/com/akto/testing/Main.java b/apps/testing/src/main/java/com/akto/testing/Main.java index 39f8c6c25f..ff45c8d27d 100644 --- a/apps/testing/src/main/java/com/akto/testing/Main.java +++ b/apps/testing/src/main/java/com/akto/testing/Main.java @@ -28,6 +28,8 @@ import com.akto.util.EmailAccountName; import com.mongodb.ConnectionString; import com.mongodb.client.model.Filters; +import com.mongodb.client.model.FindOneAndUpdateOptions; +import com.mongodb.client.model.ReturnDocument; import com.mongodb.client.model.Updates; import org.bson.conversions.Bson; import org.bson.types.ObjectId; @@ -50,27 +52,20 @@ public class Main { public static final boolean SKIP_SSRF_CHECK = "true".equalsIgnoreCase(System.getenv("SKIP_SSRF_CHECK")); public static final boolean IS_SAAS = "true".equalsIgnoreCase(System.getenv("IS_SAAS")); - private static ObjectId createTRRSummaryIfAbsent(TestingRun testingRun, int start){ - ObjectId summaryId = new ObjectId(); - try { - ObjectId testingRunId = new ObjectId(testingRun.getHexId()); - TestingRunResultSummary testingRunResultSummary = TestingRunResultSummariesDao.instance.findOne( + private static TestingRunResultSummary createTRRSummaryIfAbsent(TestingRun testingRun, int start){ + ObjectId testingRunId = new ObjectId(testingRun.getHexId()); + + return TestingRunResultSummariesDao.instance.getMCollection().findOneAndUpdate( Filters.and( - Filters.eq(TestingRunResultSummary.TESTING_RUN_ID, testingRunId), - Filters.eq(TestingRunResultSummary.STATE,TestingRun.State.SCHEDULED) - ) - ); - summaryId = testingRunResultSummary.getId(); - TestingRunResultSummariesDao.instance.updateOne( - Filters.eq(TestingRunResultSummary.ID, summaryId), - Updates.set(TestingRunResultSummary.STATE, TestingRun.State.RUNNING)); - } catch (Exception e){ - TestingRunResultSummary summary = new TestingRunResultSummary(start, 0, new HashMap<>(), - 0, testingRun.getId(), testingRun.getId().toHexString(), 0, 0); - - summaryId = TestingRunResultSummariesDao.instance.insertOne(summary).getInsertedId().asObjectId().getValue(); - } - return summaryId; + Filters.eq(TestingRunResultSummary.TESTING_RUN_ID, testingRunId), + Filters.eq(TestingRunResultSummary.STATE,TestingRun.State.SCHEDULED) + ), + Updates.combine( + Updates.set(TestingRunResultSummary.STATE, TestingRun.State.RUNNING), + Updates.setOnInsert(TestingRunResultSummary.START_TIMESTAMP, start) + ), + new FindOneAndUpdateOptions().upsert(true).returnDocument(ReturnDocument.AFTER) + ); } private static void setupRateLimitWatcher () { @@ -104,7 +99,7 @@ private static TestingRun findPendingTestingRun() { ); Bson filter2 = Filters.and( Filters.eq(TestingRun.STATE, TestingRun.State.RUNNING), - Filters.lte(TestingRun.SCHEDULE_TIMESTAMP, delta) + Filters.lte(TestingRun.PICKED_UP_TIMESTAMP, delta) ); Bson update = Updates.combine( @@ -112,21 +107,24 @@ private static TestingRun findPendingTestingRun() { Updates.set(TestingRun.STATE, TestingRun.State.RUNNING) ); + // returns the previous state of testing run before the update return TestingRunDao.instance.getMCollection().findOneAndUpdate( Filters.or(filter1,filter2), update); } private static TestingRunResultSummary findPendingTestingRunResultSummary() { - int delta = Context.now() - 20*60; + int now = Context.now(); + int delta = now - 20*60; Bson filter1 = Filters.and( Filters.eq(TestingRun.STATE, TestingRun.State.SCHEDULED), - Filters.lte(TestingRunResultSummary.START_TIMESTAMP, Context.now()), + Filters.lte(TestingRunResultSummary.START_TIMESTAMP, now), Filters.gt(TestingRunResultSummary.START_TIMESTAMP, delta) ); Bson filter2 = Filters.and( Filters.eq(TestingRun.STATE, TestingRun.State.RUNNING), + Filters.lte(TestingRunResultSummary.START_TIMESTAMP, now - 5*60), Filters.gt(TestingRunResultSummary.START_TIMESTAMP, delta) ); @@ -196,6 +194,7 @@ public static void main(String[] args) throws InterruptedException { int start = Context.now(); TestingRunResultSummary trrs = findPendingTestingRunResultSummary(); + boolean isSummaryRunning = trrs != null && trrs.getState().equals(State.RUNNING); TestingRun testingRun; ObjectId summaryId = null; if (trrs == null) { @@ -209,6 +208,8 @@ public static void main(String[] args) throws InterruptedException { return; } + boolean isTestingRunRunning = testingRun.getState().equals(State.RUNNING); + int accountId = account.getId(); if (UsageMetricUtils.checkTestRunsOverage(accountId)) { int lastSent = logSentMap.getOrDefault(accountId, 0); @@ -231,10 +232,10 @@ public static void main(String[] args) throws InterruptedException { try { setTestingRunConfig(testingRun, trrs); - if (summaryId == null) { - if (testingRun.getState().equals(TestingRun.State.RUNNING)) { - Map objectIdTestingRunResultSummaryMap = TestingRunResultSummariesDao.instance.fetchLatestTestingRunResultSummaries(Collections.singletonList(testingRun.getId())); - TestingRunResultSummary testingRunResultSummary = objectIdTestingRunResultSummaryMap.get(testingRun.getId()); + if (isSummaryRunning || isTestingRunRunning) { + Map objectIdTestingRunResultSummaryMap = TestingRunResultSummariesDao.instance.fetchLatestTestingRunResultSummaries(Collections.singletonList(testingRun.getId())); + TestingRunResultSummary testingRunResultSummary = objectIdTestingRunResultSummaryMap.get(testingRun.getId()); + if (testingRunResultSummary != null) { List testingRunResults = TestingRunResultDao.instance.fetchLatestTestingRunResult(Filters.eq(TestingRunResult.TEST_RUN_RESULT_SUMMARY_ID, testingRunResultSummary.getId()), 1); if (testingRunResults != null && !testingRunResults.isEmpty()) { TestingRunResult testingRunResult = testingRunResults.get(0); @@ -245,22 +246,57 @@ public static void main(String[] args) throws InterruptedException { } else { loggerMaker.infoAndAddToDb("Test run was executed long ago, TRR_ID:" + testingRunResult.getHexId() + ", TRRS_ID:" + testingRunResultSummary.getHexId() + " TR_ID:" + testingRun.getHexId(), LogDb.TESTING); - TestingRunResultSummariesDao.instance.updateOne(Filters.eq(TestingRunResultSummary.ID, testingRunResultSummary.getId()), Updates.set(TestingRunResultSummary.STATE, TestingRun.State.FAILED)); + TestingRunResultSummary summary = TestingRunResultSummariesDao.instance.updateOneNoUpsert( + Filters.and( + Filters.eq(TestingRunResultSummary.ID, testingRunResultSummary.getId()), + Filters.eq(TestingRunResultSummary.STATE, State.RUNNING) + ), + Updates.set(TestingRunResultSummary.STATE, State.FAILED) + ); + if (summary == null) { + loggerMaker.infoAndAddToDb("Skipping because some other thread picked it up, TRRS_ID:" + testingRunResultSummary.getHexId() + " TR_ID:" + testingRun.getHexId(), LogDb.TESTING); + return; + } + TestingRunResultSummary runResultSummary = TestingRunResultSummariesDao.instance.findOne(Filters.eq(TestingRunResultSummary.ID, testingRunResultSummary.getId())); GithubUtils.publishGithubComments(runResultSummary); } } else { loggerMaker.infoAndAddToDb("No executions made for this test, will need to restart it, TRRS_ID:" + testingRunResultSummary.getHexId() + " TR_ID:" + testingRun.getHexId(), LogDb.TESTING); - TestingRunResultSummariesDao.instance.updateOne(Filters.eq(TestingRunResultSummary.ID, testingRunResultSummary.getId()), Updates.set(TestingRunResultSummary.STATE, TestingRun.State.FAILED)); - TestingRunResultSummary runResultSummary = TestingRunResultSummariesDao.instance.findOne(Filters.eq(TestingRunResultSummary.ID, testingRunResultSummary.getId())); - GithubUtils.publishGithubComments(runResultSummary); + TestingRunResultSummary summary = TestingRunResultSummariesDao.instance.updateOneNoUpsert( + Filters.and( + Filters.eq(TestingRunResultSummary.ID, testingRunResultSummary.getId()), + Filters.eq(TestingRunResultSummary.STATE, State.RUNNING) + ), + Updates.set(TestingRunResultSummary.STATE, State.FAILED) + ); + if (summary == null) { + loggerMaker.infoAndAddToDb("Skipping because some other thread picked it up, TRRS_ID:" + testingRunResultSummary.getHexId() + " TR_ID:" + testingRun.getHexId(), LogDb.TESTING); + return; + } + } + + // insert new summary based on old summary + if (summaryId != null) { + trrs.setId(new ObjectId()); + trrs.setStartTimestamp(start); + trrs.setState(State.RUNNING); + TestingRunResultSummariesDao.instance.insertOne(trrs); + summaryId = trrs.getId(); + } else { + trrs = createTRRSummaryIfAbsent(testingRun, start); + summaryId = trrs.getId(); } } + } - summaryId = createTRRSummaryIfAbsent(testingRun, start); + if (summaryId == null) { + trrs = createTRRSummaryIfAbsent(testingRun, start); + summaryId = trrs.getId(); } + TestExecutor testExecutor = new TestExecutor(); - if (trrs != null && trrs.getState() == State.SCHEDULED) { + if (trrs.getState() == State.SCHEDULED) { if (trrs.getMetadata()!= null && trrs.getMetadata().containsKey("pull_request_id") && trrs.getMetadata().containsKey("commit_sha_head") ) { //case of github status push GithubUtils.publishGithubStatus(trrs); @@ -270,7 +306,7 @@ public static void main(String[] args) throws InterruptedException { testExecutor.init(testingRun, summaryId); raiseMixpanelEvent(summaryId, testingRun); } catch (Exception e) { - loggerMaker.errorAndAddToDb("Error in init " + e, LogDb.TESTING); + loggerMaker.errorAndAddToDb(e, "Error in init " + e); } Bson completedUpdate = Updates.combine( Updates.set(TestingRun.STATE, TestingRun.State.COMPLETED),