From 66fbbfc7e8e2b854598834055ed3f54ff935118f Mon Sep 17 00:00:00 2001 From: Ark2307 <kr.aryan2307@gmail.com> Date: Fri, 20 Sep 2024 12:28:12 +0530 Subject: [PATCH 1/4] Fixing in groups --- .../com/akto/action/ApiCollectionsAction.java | 51 ++++++++++++++----- .../utils/notifications/TrafficUpdates.java | 2 +- apps/dashboard/src/main/resources/struts.xml | 20 ++++++++ .../api_collections/ApiCollections.jsx | 21 +++++--- .../pages/observe/api_collections/api.js | 7 +++ .../java/com/akto/dao/ApiCollectionsDao.java | 8 ++- 6 files changed, 85 insertions(+), 24 deletions(-) diff --git a/apps/dashboard/src/main/java/com/akto/action/ApiCollectionsAction.java b/apps/dashboard/src/main/java/com/akto/action/ApiCollectionsAction.java index 8192330b8c..f16308f4a2 100644 --- a/apps/dashboard/src/main/java/com/akto/action/ApiCollectionsAction.java +++ b/apps/dashboard/src/main/java/com/akto/action/ApiCollectionsAction.java @@ -26,9 +26,6 @@ import com.akto.dto.CollectionConditions.ConditionUtils; import com.akto.dto.billing.Organization; import com.akto.dto.type.SingleTypeInfo; -import com.akto.dto.usage.MetricTypes; -import com.akto.dto.usage.UsageMetric; -import com.akto.listener.InitializerListener; import com.akto.listener.RuntimeListener; import com.akto.log.LoggerMaker; import com.akto.log.LoggerMaker.LogDb; @@ -78,10 +75,10 @@ public void setApiList(List<ApiInfoKey> apiList) { boolean redacted; - public List<ApiCollection> fillApiCollectionsUrlCount(List<ApiCollection> apiCollections) { + public List<ApiCollection> fillApiCollectionsUrlCount(List<ApiCollection> apiCollections, Bson filter) { int tsRandom = Context.now(); loggerMaker.infoAndAddToDb("fillApiCollectionsUrlCount started: " + tsRandom, LoggerMaker.LogDb.DASHBOARD); - Map<Integer, Integer> countMap = ApiCollectionsDao.instance.buildEndpointsCountToApiCollectionMap(); + Map<Integer, Integer> countMap = ApiCollectionsDao.instance.buildEndpointsCountToApiCollectionMap(filter); loggerMaker.infoAndAddToDb("fillApiCollectionsUrlCount buildEndpointsCountToApiCollectionMap done: " + tsRandom, LoggerMaker.LogDb.DASHBOARD); for (ApiCollection apiCollection: apiCollections) { @@ -93,11 +90,7 @@ public List<ApiCollection> fillApiCollectionsUrlCount(List<ApiCollection> apiCol apiCollection.setUrlsCount(count); } else if(ApiCollection.Type.API_GROUP.equals(apiCollection.getType())){ if (count == null) { - List<Bson> filters = SingleTypeInfoDao.filterForHostHostHeaderRaw(); - filters.add(Filters.in(SingleTypeInfo._COLLECTION_IDS, apiCollectionId)); - count = (int) SingleTypeInfoDao.instance.count( - Filters.and(filters) - ); + count = fallbackCount; } apiCollection.setUrlsCount(count); } else { @@ -116,9 +109,35 @@ public List<ApiCollection> fillApiCollectionsUrlCount(List<ApiCollection> apiCol return apiCollections; } + private Map<Integer, Integer> deactivatedHostnameCountMap; + + public String getCountForHostnameDeactivatedCollections(){ + this.deactivatedHostnameCountMap = new HashMap<>(); + if(deactivatedCollections == null || deactivatedCollections.isEmpty()){ + return SUCCESS.toUpperCase(); + } + Bson filter = Filters.and(Filters.exists(ApiCollection.HOST_NAME), Filters.in(Constants.ID, deactivatedCollections)); + List<ApiCollection> hCollections = ApiCollectionsDao.instance.findAll(filter, Projections.include(Constants.ID)); + List<Integer> deactivatedIds = new ArrayList<>(); + for(ApiCollection collection : hCollections){ + if(deactivatedCollections.contains(collection.getId())){ + deactivatedIds.add(collection.getId()); + } + } + + if(deactivatedIds.isEmpty()){ + return SUCCESS.toUpperCase(); + } + + this.deactivatedHostnameCountMap = ApiCollectionsDao.instance.buildEndpointsCountToApiCollectionMap( + Filters.in(SingleTypeInfo._COLLECTION_IDS, deactivatedIds) + ); + return SUCCESS.toUpperCase(); + } + public String fetchAllCollections() { this.apiCollections = ApiCollectionsDao.instance.findAll(new BasicDBObject()); - this.apiCollections = fillApiCollectionsUrlCount(this.apiCollections); + this.apiCollections = fillApiCollectionsUrlCount(this.apiCollections, Filters.empty()); return Action.SUCCESS.toUpperCase(); } @@ -178,7 +197,7 @@ public String fetchAllCollectionsBasic() { } } - this.apiCollections = fillApiCollectionsUrlCount(this.apiCollections); + this.apiCollections = fillApiCollectionsUrlCount(this.apiCollections, Filters.nin(SingleTypeInfo._API_COLLECTION_ID, deactivatedCollections)); return Action.SUCCESS.toUpperCase(); } @@ -599,7 +618,7 @@ private List<ApiCollection> filterCollections(List<ApiCollection> apiCollections public String deactivateCollections() { this.apiCollections = filterCollections(this.apiCollections, false); - this.apiCollections = fillApiCollectionsUrlCount(this.apiCollections); + this.apiCollections = fillApiCollectionsUrlCount(this.apiCollections,Filters.empty()); int deltaUsage = (-1) * this.apiCollections.stream().mapToInt(apiCollection -> apiCollection.getUrlsCount()).sum(); List<Integer> apiCollectionIds = reduceApiCollectionToId(this.apiCollections); ApiCollectionsDao.instance.updateMany(Filters.in(Constants.ID, apiCollectionIds), @@ -613,7 +632,7 @@ public String activateCollections() { if (this.apiCollections.isEmpty()) { return Action.SUCCESS.toUpperCase(); } - this.apiCollections = fillApiCollectionsUrlCount(this.apiCollections); + this.apiCollections = fillApiCollectionsUrlCount(this.apiCollections,Filters.empty()); int accountId = Context.accountId.get(); FeatureAccess featureAccess = UsageMetricUtils.getFeatureAccess(accountId, MetricTypes.ACTIVE_ENDPOINTS); @@ -788,4 +807,8 @@ public void setStartTimestamp(int startTimestamp) { public void setEndTimestamp(int endTimestamp) { this.endTimestamp = endTimestamp; } + + public Map<Integer, Integer> getDeactivatedHostnameCountMap() { + return deactivatedHostnameCountMap; + } } diff --git a/apps/dashboard/src/main/java/com/akto/utils/notifications/TrafficUpdates.java b/apps/dashboard/src/main/java/com/akto/utils/notifications/TrafficUpdates.java index d37795d41a..9754a5d327 100644 --- a/apps/dashboard/src/main/java/com/akto/utils/notifications/TrafficUpdates.java +++ b/apps/dashboard/src/main/java/com/akto/utils/notifications/TrafficUpdates.java @@ -64,7 +64,7 @@ public void sendAlerts(String webhookUrl, String metricsUrl, int thresholdSecond public List<TrafficMetricsAlert> filterTrafficMetricsAlertsList(List<TrafficMetricsAlert> trafficMetricsAlertList) { List<ApiCollection> apiCollections = ApiCollectionsDao.instance.getMetaAll(); - Map<Integer, Integer> countMap = ApiCollectionsDao.instance.buildEndpointsCountToApiCollectionMap(); + Map<Integer, Integer> countMap = ApiCollectionsDao.instance.buildEndpointsCountToApiCollectionMap(Filters.empty()); Set<String> allowedHosts = new HashSet<>(); for (ApiCollection apiCollection: apiCollections) { int apiCollectionId = apiCollection.getId(); diff --git a/apps/dashboard/src/main/resources/struts.xml b/apps/dashboard/src/main/resources/struts.xml index 4bc9b0107c..ebbe01d95e 100644 --- a/apps/dashboard/src/main/resources/struts.xml +++ b/apps/dashboard/src/main/resources/struts.xml @@ -1472,6 +1472,26 @@ <result name="ERROR" type="httpheader"> <param name="status">401</param> </result> + </action> + + <action name="api/getCountForHostnameDeactivatedCollections" class="com.akto.action.ApiCollectionsAction" method="getCountForHostnameDeactivatedCollections"> + <interceptor-ref name="json"/> + <interceptor-ref name="defaultStack" /> + <interceptor-ref name="roleAccessInterceptor"> + <param name="featureLabel">API_COLLECTIONS</param> + <param name="accessType">READ</param> + </interceptor-ref> + <result name="FORBIDDEN" type="json"> + <param name="statusCode">403</param> + <param name="ignoreHierarchy">false</param> + <param name="includeProperties">^actionErrors.*</param> + </result> + <result name="SUCCESS" type="json"> + <param name="root">deactivatedHostnameCountMap</param> + </result> + <result name="ERROR" type="httpheader"> + <param name="status">401</param> + </result> </action> <action name="api/getSensitiveInfoForCollections" class="com.akto.action.ApiCollectionsAction" method="fetchSensitiveInfoInCollections"> diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api_collections/ApiCollections.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api_collections/ApiCollections.jsx index 73e8f13b28..6cacc5ca8e 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api_collections/ApiCollections.jsx +++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api_collections/ApiCollections.jsx @@ -295,6 +295,7 @@ function ApiCollections() { let apiPromises = [ api.getCoverageInfoForCollections(), api.getLastTrafficSeen(), + collectionApi.fetchCountForHostnameDeactivatedCollections() ]; if(shouldCallHeavyApis){ apiPromises = [ @@ -307,30 +308,31 @@ function ApiCollections() { let coverageInfo = results[0].status === 'fulfilled' ? results[0].value : {}; // let coverageInfo = dummyData.coverageMap let trafficInfo = results[1].status === 'fulfilled' ? results[1].value : {}; + let deactivatedCountInfo = results[2].status === 'fulfilled' ? results[2].value : {}; let riskScoreObj = lastFetchedResp let sensitiveInfo = lastFetchedSensitiveResp let severityObj = lastFetchedSeverityResp if(shouldCallHeavyApis){ - if(results[2]?.status === "fulfilled"){ - const res = results[2].value + if(results[3]?.status === "fulfilled"){ + const res = results[3].value riskScoreObj = { criticalUrls: res.criticalEndpointsCount, riskScoreMap: res.riskScoreOfCollectionsMap } } - if(results[3]?.status === "fulfilled"){ - const res = results[3].value + if(results[4]?.status === "fulfilled"){ + const res = results[4].value sensitiveInfo ={ sensitiveUrls: res.sensitiveUrlsInResponse, sensitiveInfoMap: res.sensitiveSubtypesInCollection } } - if(results[4]?.status === "fulfilled"){ - const res = results[4].value + if(results[5]?.status === "fulfilled"){ + const res = results[5].value severityObj = res } @@ -349,7 +351,12 @@ function ApiCollections() { setNormalData(dataObj.normal) // Separate active and deactivated collections - const deactivatedCollections = dataObj.prettify.filter(c => c.deactivated); + const deactivatedCollections = dataObj.prettify.filter(c => c.deactivated).map((c)=>{ + if(c.type !== "API_GROUP" && deactivatedCountInfo.hasOwnProperty(c.id)){ + c.urlsCount = deactivatedCountInfo[c.id] + } + return c + }); // Calculate summary data only for active collections const summary = transform.getSummaryData(dataObj.normal) diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api_collections/api.js b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api_collections/api.js index 9eea7c81d1..f2748e29a1 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api_collections/api.js +++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api_collections/api.js @@ -14,5 +14,12 @@ export default { method: 'post', data: { apiCollections: items } }) + }, + fetchCountForHostnameDeactivatedCollections(){ + return request({ + url: '/api/getCountForHostnameDeactivatedCollections', + method: 'post', + data: {} + }) } } \ No newline at end of file diff --git a/libs/dao/src/main/java/com/akto/dao/ApiCollectionsDao.java b/libs/dao/src/main/java/com/akto/dao/ApiCollectionsDao.java index 5f3c918926..cb8154a1bf 100644 --- a/libs/dao/src/main/java/com/akto/dao/ApiCollectionsDao.java +++ b/libs/dao/src/main/java/com/akto/dao/ApiCollectionsDao.java @@ -137,11 +137,15 @@ public List<Integer> fetchNonTrafficApiCollectionsIds() { return apiCollectionIds; } - public Map<Integer, Integer> buildEndpointsCountToApiCollectionMap() { + public Map<Integer, Integer> buildEndpointsCountToApiCollectionMap(Bson filter) { Map<Integer, Integer> countMap = new HashMap<>(); List<Bson> pipeline = new ArrayList<>(); - pipeline.add(Aggregates.match(SingleTypeInfoDao.filterForHostHeader(0, false))); + pipeline.add(Aggregates.match(Filters.and( + SingleTypeInfoDao.filterForHostHeader(0, false), + filter + ) + )); BasicDBObject groupedId = new BasicDBObject(SingleTypeInfo._COLLECTION_IDS, "$" + SingleTypeInfo._COLLECTION_IDS); pipeline.add(Aggregates.unwind("$" + SingleTypeInfo._COLLECTION_IDS)); pipeline.add(Aggregates.group(groupedId, Accumulators.sum("count",1))); From 80395f9f80d2c8fe2b6b0599f972800d8a11dd59 Mon Sep 17 00:00:00 2001 From: Ark2307 <kr.aryan2307@gmail.com> Date: Fri, 20 Sep 2024 16:03:41 +0530 Subject: [PATCH 2/4] Fixing fields for groups --- .../pages/observe/api_collections/ApiCollections.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api_collections/ApiCollections.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api_collections/ApiCollections.jsx index 6cacc5ca8e..afd5c95166 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api_collections/ApiCollections.jsx +++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api_collections/ApiCollections.jsx @@ -175,12 +175,12 @@ const convertToNewData = (collectionsArr, sensitiveInfoMap, severityInfoMap, cov return{ ...c, displayNameComp: (<Box maxWidth="20vw"><TooltipText tooltip={c.displayName} text={c.displayName} textProps={{fontWeight: 'medium'}}/></Box>), - testedEndpoints: coverageMap[c.id] ? coverageMap[c.id] : 0, + testedEndpoints: c.urlsCount === 0 ? 0 : (coverageMap[c.id] ? coverageMap[c.id] : 0), sensitiveInRespTypes: sensitiveInfoMap[c.id] ? sensitiveInfoMap[c.id] : [], severityInfo: severityInfoMap[c.id] ? severityInfoMap[c.id] : {}, detected: func.prettifyEpoch(trafficInfoMap[c.id] || 0), - detectedTimestamp: trafficInfoMap[c.id] || 0, - riskScore: riskScoreMap[c.id] ? riskScoreMap[c.id] : 0, + detectedTimestamp: c.urlsCount === 0 ? 0 : (trafficInfoMap[c.id] || 0), + riskScore: c.urlsCount === 0 ? 0 : (riskScoreMap[c.id] ? riskScoreMap[c.id] : 0), discovered: func.prettifyEpoch(c.startTs || 0), } }) @@ -352,7 +352,7 @@ function ApiCollections() { // Separate active and deactivated collections const deactivatedCollections = dataObj.prettify.filter(c => c.deactivated).map((c)=>{ - if(c.type !== "API_GROUP" && deactivatedCountInfo.hasOwnProperty(c.id)){ + if(deactivatedCountInfo.hasOwnProperty(c.id)){ c.urlsCount = deactivatedCountInfo[c.id] } return c From 3442d6ff28b634544dd3415861eac7ca1bbf4fda Mon Sep 17 00:00:00 2001 From: Ark2307 <kr.aryan2307@gmail.com> Date: Fri, 20 Sep 2024 16:24:56 +0530 Subject: [PATCH 3/4] increasing limit for recent endpoints --- libs/dao/src/main/java/com/akto/dao/SingleTypeInfoDao.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/dao/src/main/java/com/akto/dao/SingleTypeInfoDao.java b/libs/dao/src/main/java/com/akto/dao/SingleTypeInfoDao.java index b8a5ac7af5..9b92fdceb0 100644 --- a/libs/dao/src/main/java/com/akto/dao/SingleTypeInfoDao.java +++ b/libs/dao/src/main/java/com/akto/dao/SingleTypeInfoDao.java @@ -719,7 +719,7 @@ public List<BasicDBObject> fetchRecentEndpoints(int startTimestamp, int endTimes Filters.nin(SingleTypeInfo._API_COLLECTION_ID, nonHostApiCollectionIds), hostFilterQ ); - List<SingleTypeInfo> latestHosts = SingleTypeInfoDao.instance.findAll(filterQWithTs, 0, 1_000, Sorts.descending("timestamp"), Projections.exclude("values")); + List<SingleTypeInfo> latestHosts = SingleTypeInfoDao.instance.findAll(filterQWithTs, 0, 20_000, Sorts.descending("timestamp"), Projections.exclude("values")); for(SingleTypeInfo sti: latestHosts) { BasicDBObject id = new BasicDBObject("apiCollectionId", sti.getApiCollectionId()) From 1ec7c980803fbbe6c4db072874f7c8900715eb53 Mon Sep 17 00:00:00 2001 From: Ark2307 <kr.aryan2307@gmail.com> Date: Fri, 20 Sep 2024 18:09:16 +0530 Subject: [PATCH 4/4] Optimising api changes page --- .../akto/action/observe/InventoryAction.java | 19 ++++++- apps/dashboard/src/main/resources/struts.xml | 21 +++++++ .../src/apps/dashboard/pages/observe/api.js | 9 +++ .../observe/api_collections/ApiChanges.jsx | 55 +++++++++++-------- .../main/java/com/akto/dao/ApiInfoDao.java | 3 + 5 files changed, 83 insertions(+), 24 deletions(-) diff --git a/apps/dashboard/src/main/java/com/akto/action/observe/InventoryAction.java b/apps/dashboard/src/main/java/com/akto/action/observe/InventoryAction.java index 83dc5d355c..98b52c2805 100644 --- a/apps/dashboard/src/main/java/com/akto/action/observe/InventoryAction.java +++ b/apps/dashboard/src/main/java/com/akto/action/observe/InventoryAction.java @@ -419,10 +419,25 @@ public String fetchSensitiveParamsForEndpoints() { return Action.SUCCESS.toUpperCase(); } + public String loadRecentApiInfos(){ + Bson filter = Filters.and( + Filters.nin(ApiInfo.ID_API_COLLECTION_ID,deactivatedCollections), + Filters.gte(ApiInfo.DISCOVERED_TIMESTAMP, startTimestamp), + Filters.lte(ApiInfo.DISCOVERED_TIMESTAMP, endTimestamp) + ); + List<ApiInfo> apiInfos = ApiInfoDao.instance.findAll(filter); + for(ApiInfo info: apiInfos){ + info.calculateActualAuth(); + } + response = new BasicDBObject(); + response.put("apiInfoList", apiInfos); + return Action.SUCCESS.toUpperCase(); + } + public String loadRecentEndpoints() { List<BasicDBObject> list = fetchRecentEndpoints(startTimestamp, endTimestamp); - attachTagsInAPIList(list); - attachAPIInfoListInResponse(list, -1); + response = new BasicDBObject(); + response.put("endpoints", list); return Action.SUCCESS.toUpperCase(); } diff --git a/apps/dashboard/src/main/resources/struts.xml b/apps/dashboard/src/main/resources/struts.xml index ebbe01d95e..b4066b54dd 100644 --- a/apps/dashboard/src/main/resources/struts.xml +++ b/apps/dashboard/src/main/resources/struts.xml @@ -865,6 +865,27 @@ </result> </action> + <action name="api/loadRecentApiInfos" class="com.akto.action.observe.InventoryAction" method="loadRecentApiInfos"> + <interceptor-ref name="json"/> + <interceptor-ref name="defaultStack" /> + <interceptor-ref name="roleAccessInterceptor"> + <param name="featureLabel">API_COLLECTIONS</param> + <param name="accessType">READ</param> + </interceptor-ref> + + <result name="FORBIDDEN" type="json"> + <param name="statusCode">403</param> + <param name="ignoreHierarchy">false</param> + <param name="includeProperties">^actionErrors.*</param> + </result> + <result name="SUCCESS" type="json"> + <param name="root">response</param> + </result> + <result name="ERROR" type="httpheader"> + <param name="status">401</param> + </result> + </action> + <action name="api/fetchNewParametersTrend" class="com.akto.action.observe.InventoryAction" method="fetchNewParametersTrend"> <interceptor-ref name="json"/> <interceptor-ref name="defaultStack" /> diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api.js b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api.js index df4e73204d..8ec8b84c5b 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api.js +++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api.js @@ -329,6 +329,15 @@ export default { }) return resp }, + + async loadRecentApiInfos (startTimestamp, endTimestamp) { + const resp = await request({ + url: '/api/loadRecentApiInfos', + method: 'post', + data: { startTimestamp, endTimestamp } + }) + return resp + }, async fetchSensitiveParamsForEndpoints (urls) { const resp = await request({ url: '/api/fetchSensitiveParamsForEndpoints', diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api_collections/ApiChanges.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api_collections/ApiChanges.jsx index d99ffc5c8d..ff59d24502 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api_collections/ApiChanges.jsx +++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api_collections/ApiChanges.jsx @@ -61,29 +61,40 @@ function ApiChanges() { }) } + async function fetchData() { + let apiCollection, apiCollectionUrls, apiInfoList; + let apiPromises = [ + api.loadRecentEndpoints(startTimestamp, endTimestamp), + api.loadRecentApiInfos(startTimestamp, endTimestamp), + api.fetchNewParametersTrend(startTimestamp, endTimestamp) + ]; + let results = await Promise.allSettled(apiPromises); + let endpointsFromStiResp = results[0].status === 'fulfilled' ? results[0].value : {"endpoints": []} + let endpointsFromApiInfos = results[1].status === 'fulfilled' ? results[1].value : {"apiInfoList" : []} + let parametersResp = results[2].status === 'fulfilled' ? results[2].value : {} + + apiCollection = endpointsFromStiResp.endpoints.map(x => { return { ...x._id, startTs: x.startTs } }) + apiCollectionUrls = endpointsFromStiResp.endpoints.map(x => x._id.url) + apiInfoList = endpointsFromApiInfos.apiInfoList + + await api.fetchSensitiveParamsForEndpoints(apiCollectionUrls).then(allSensitiveFields => { + let sensitiveParams = allSensitiveFields.data.endpoints + setSensitiveParams([...sensitiveParams]); + apiCollection = transform.fillSensitiveParams(sensitiveParams, apiCollection); + }) + + let data = func.mergeApiInfoAndApiCollection(apiCollection, apiInfoList, collectionsMap); + const prettifiedData = transform.prettifyEndpointsData(data) + setNewEndpoints({prettify: prettifiedData, normal: data}); + + const trendObj = transform.findNewParametersCountTrend(parametersResp, startTimestamp, endTimestamp) + setNewParametersCount(trendObj.count) + setParametersTrend(trendObj.trend) + + setLoading(false); + } + useEffect(() => { - async function fetchData() { - let apiCollection, apiCollectionUrls, apiInfoList; - await api.loadRecentEndpoints(startTimestamp, endTimestamp).then((res) => { - apiCollection = res.data.endpoints.map(x => { return { ...x._id, startTs: x.startTs } }) - apiCollectionUrls = res.data.endpoints.map(x => x._id.url) - apiInfoList = res.data.apiInfoList - }) - await api.fetchSensitiveParamsForEndpoints(apiCollectionUrls).then(allSensitiveFields => { - let sensitiveParams = allSensitiveFields.data.endpoints - setSensitiveParams([...sensitiveParams]); - apiCollection = transform.fillSensitiveParams(sensitiveParams, apiCollection); - }) - let data = func.mergeApiInfoAndApiCollection(apiCollection, apiInfoList, collectionsMap); - const prettifiedData = transform.prettifyEndpointsData(data) - setNewEndpoints({prettify: prettifiedData, normal: data}); - await api.fetchNewParametersTrend(startTimestamp, endTimestamp).then((resp) => { - const trendObj = transform.findNewParametersCountTrend(resp, startTimestamp, endTimestamp) - setNewParametersCount(trendObj.count) - setParametersTrend(trendObj.trend) - }) - setLoading(false); - } if (allCollections.length > 0) { fetchData(); } diff --git a/libs/dao/src/main/java/com/akto/dao/ApiInfoDao.java b/libs/dao/src/main/java/com/akto/dao/ApiInfoDao.java index b402cfdb0c..17fbf5269b 100644 --- a/libs/dao/src/main/java/com/akto/dao/ApiInfoDao.java +++ b/libs/dao/src/main/java/com/akto/dao/ApiInfoDao.java @@ -80,6 +80,9 @@ public void createIndicesIfAbsent() { MCollection.createIndexIfAbsent(getDBName(), getCollName(), new String[] { ApiInfo.RISK_SCORE, ApiInfo.ID_API_COLLECTION_ID }, false); + + MCollection.createIndexIfAbsent(getDBName(), getCollName(), + new String[] {ApiInfo.DISCOVERED_TIMESTAMP }, false); }