This is an automated email from the ASF dual-hosted git repository.

dhavalshah9131 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git

commit 69911e5258d8b611e1410698c42e9ef59c907caa
Author: Mugdha Varadkar <mug...@apache.org>
AuthorDate: Thu Nov 9 13:38:35 2023 +0530

    RANGER-4187: Not able to search using multiple user filter in access audit 
tab
---
 .../react-typeahead/tokenizer/index.js             |  25 ++++-
 .../main/webapp/react-webapp/src/utils/XAUtils.js  | 119 ++++++++++++++++-----
 .../src/views/AuditEvent/AccessLogs.jsx            |  87 ++++++++++-----
 3 files changed, 174 insertions(+), 57 deletions(-)

diff --git 
a/security-admin/src/main/webapp/react-webapp/src/components/structured-filter/react-typeahead/tokenizer/index.js
 
b/security-admin/src/main/webapp/react-webapp/src/components/structured-filter/react-typeahead/tokenizer/index.js
index 82f73024a..c17a3ff5e 100644
--- 
a/security-admin/src/main/webapp/react-webapp/src/components/structured-filter/react-typeahead/tokenizer/index.js
+++ 
b/security-admin/src/main/webapp/react-webapp/src/components/structured-filter/react-typeahead/tokenizer/index.js
@@ -23,7 +23,7 @@ import KeyEvent from "../keyevent";
 import Typeahead from "../typeahead";
 import createReactClass from "create-react-class";
 import PropTypes from "prop-types";
-import { find, map, some, trim } from "lodash";
+import { find, filter, map, some, trim, includes } from "lodash";
 var classNames = require("classnames");
 /**
  * A typeahead that, when an option is selected, instead of simply filling
@@ -74,7 +74,7 @@ var TypeaheadTokenizer = createReactClass({
       !!this.props.customClasses.token;
     var classList = classNames(tokenClasses);
     var result = this.state.selected.map(function (selected, index) {
-      let mykey = selected.category + selected.value;
+      let mykey = selected.category + selected.value + index;
       let categoryLabel = this._getFilterCategoryLabel(selected.category);
       let categoryValue = this._getFilterCategoryLabelForOption(
         selected.category,
@@ -113,7 +113,15 @@ var TypeaheadTokenizer = createReactClass({
     if (this.state.category == "") {
       var categories = [];
       let selectedCategory = [];
-      selectedCategory = map(this.state.selected, "category");
+      let bypassCategory = map(
+        filter(this.props.options, ["addMultiple", true]),
+        "category"
+      );
+      selectedCategory = this.state.selected
+        .map((item) => {
+          if (!bypassCategory.includes(item.category)) return item.category;
+        })
+        .filter(Boolean);
       for (var i = 0; i < this.props.options.length; i++) {
         selectedCategory.indexOf(this.props.options[i].category) === -1 &&
           categories.push(this.props.options[i].category);
@@ -245,7 +253,16 @@ var TypeaheadTokenizer = createReactClass({
   _getOptionsLabel: function () {
     var currentHeader = this._getHeader();
     var optionsLabel = [];
-    let selectedCategory = map(this.state.selected, "category");
+    let selectedCategory = [];
+    let bypassCategory = map(
+      filter(this.props.options, ["addMultiple", true]),
+      "category"
+    );
+    selectedCategory = this.state.selected
+      .map((item) => {
+        if (!bypassCategory.includes(item.category)) return item.category;
+      })
+      .filter(Boolean);
     if (currentHeader == "Category") {
       for (var i = 0; i < this.props.options.length; i++) {
         selectedCategory.indexOf(this.props.options[i].category) === -1 &&
diff --git a/security-admin/src/main/webapp/react-webapp/src/utils/XAUtils.js 
b/security-admin/src/main/webapp/react-webapp/src/utils/XAUtils.js
index ebf1b3fc2..9f6706261 100644
--- a/security-admin/src/main/webapp/react-webapp/src/utils/XAUtils.js
+++ b/security-admin/src/main/webapp/react-webapp/src/utils/XAUtils.js
@@ -41,7 +41,8 @@ import {
   isNull,
   some,
   has,
-  sortBy
+  sortBy,
+  isArray
 } from "lodash";
 import { matchRoutes } from "react-router-dom";
 import dateFormat from "dateformat";
@@ -1141,28 +1142,49 @@ export const fetchSearchFilterParams = (
   let defaultSearchFilterParam = [];
 
   // Get search filter params from current search params
-  const currentParams = Object.fromEntries([...searchParams]);
-  for (const param in currentParams) {
+  for (const [key, value] of searchParams.entries()) {
     let searchFilterObj = find(searchFilterOptions, {
-      urlLabel: param
+      urlLabel: key
     });
 
     if (!isUndefined(searchFilterObj)) {
       let category = searchFilterObj.category;
-      let value = currentParams[param];
+      let categoryValue = value;
+
+      if (searchFilterObj?.addMultiple) {
+        let oldValue = searchFilterParam[category];
+        let newValue = value;
+        if (oldValue) {
+          if (isArray(oldValue)) {
+            searchFilterParam[category].push(newValue);
+            searchParam[key].push(newValue);
+          } else {
+            searchFilterParam[category] = [oldValue, newValue];
+            searchParam[key] = [oldValue, newValue];
+          }
+        } else {
+          searchFilterParam[category] = newValue;
+          searchParam[key] = newValue;
+        }
+      } else {
+        if (searchFilterObj.type == "textoptions") {
+          let textOptionObj = find(searchFilterObj.options(), {
+            label: categoryValue
+          });
+          categoryValue = !isUndefined(textOptionObj)
+            ? textOptionObj.value
+            : categoryValue;
+        }
 
-      if (searchFilterObj.type == "textoptions") {
-        let textOptionObj = find(searchFilterObj.options(), {
-          label: value
-        });
-        value = !isUndefined(textOptionObj) ? textOptionObj.value : value;
+        searchFilterParam[category] = categoryValue;
+        searchParam[key] = value;
       }
-
-      searchFilterParam[category] = value;
       defaultSearchFilterParam.push({
         category: category,
-        value: value
+        value: categoryValue
       });
+    } else {
+      searchParam[key] = value;
     }
   }
 
@@ -1182,26 +1204,49 @@ export const fetchSearchFilterParams = (
           let category = searchFilterObj.category;
           let value = localStorageParams[localParam];
 
-          if (searchFilterObj.type == "textoptions") {
-            let textOptionObj = find(searchFilterObj.options(), {
-              label: value
+          if (searchFilterObj?.addMultiple) {
+            if (isArray(value)) {
+              for (const val of value) {
+                searchFilterParam[category] = value;
+                defaultSearchFilterParam.push({
+                  category: category,
+                  value: val
+                });
+                searchParam[localParam] = value;
+              }
+            } else {
+              searchFilterParam[category] = value;
+              defaultSearchFilterParam.push({
+                category: category,
+                value: value
+              });
+              searchParam[localParam] = value;
+            }
+          } else {
+            if (searchFilterObj.type == "textoptions") {
+              let textOptionObj = find(searchFilterObj.options(), {
+                label: value
+              });
+              value = !isUndefined(textOptionObj) ? textOptionObj.value : 
value;
+            }
+
+            searchFilterParam[category] = value;
+            defaultSearchFilterParam.push({
+              category: category,
+              value: value
             });
-            value = !isUndefined(textOptionObj) ? textOptionObj.value : value;
+            searchParam[localParam] = localStorageParams[localParam];
           }
-
-          searchFilterParam[category] = value;
-          defaultSearchFilterParam.push({
-            category: category,
-            value: value
-          });
+        } else {
           searchParam[localParam] = localStorageParams[localParam];
         }
       }
     }
   }
+
   finalSearchFilterData["searchFilterParam"] = searchFilterParam;
   finalSearchFilterData["defaultSearchFilterParam"] = defaultSearchFilterParam;
-  finalSearchFilterData["searchParam"] = { ...currentParams, ...searchParam };
+  finalSearchFilterData["searchParam"] = searchParam;
 
   return finalSearchFilterData;
 };
@@ -1217,7 +1262,21 @@ export const parseSearchFilter = (filter, 
searchFilterOptions) => {
     });
 
     if (searchFilterObj !== undefined) {
-      searchFilterParam[obj.category] = obj.value;
+      if (searchFilterObj?.addMultiple) {
+        let oldValue = searchFilterParam[obj.category];
+        let newValue = obj.value;
+        if (oldValue) {
+          if (isArray(oldValue)) {
+            searchFilterParam[obj.category].push(newValue);
+          } else {
+            searchFilterParam[obj.category] = [oldValue, newValue];
+          }
+        } else {
+          searchFilterParam[obj.category] = newValue;
+        }
+      } else {
+        searchFilterParam[obj.category] = obj.value;
+      }
 
       let urlLabelParam = searchFilterObj.urlLabel;
 
@@ -1228,7 +1287,12 @@ export const parseSearchFilter = (filter, 
searchFilterOptions) => {
         searchParam[urlLabelParam] =
           textOptionObj !== undefined ? textOptionObj.label : obj.value;
       } else {
-        searchParam[urlLabelParam] = obj.value;
+        if (searchFilterObj?.addMultiple) {
+          searchParam[urlLabelParam] =
+            searchFilterParam[searchFilterObj.category];
+        } else {
+          searchParam[urlLabelParam] = obj.value;
+        }
       }
     }
   });
@@ -1352,9 +1416,8 @@ export const updateTagActive = (isTagView) => {
 };
 
 export const handleLogout = async (checkKnoxSSOVal, navigate) => {
-  let logoutResp = {};
   try {
-    logoutResp = await fetchApi({
+    await fetchApi({
       url: "logout",
       baseURL: "",
       headers: {
diff --git 
a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AccessLogs.jsx
 
b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AccessLogs.jsx
index 7ec8503e7..141b06cdb 100644
--- 
a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AccessLogs.jsx
+++ 
b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AccessLogs.jsx
@@ -18,7 +18,7 @@
  */
 
 import React, { useState, useCallback, useEffect, useRef } from "react";
-import { useSearchParams, useOutletContext } from "react-router-dom";
+import { useSearchParams, useOutletContext, Link } from "react-router-dom";
 import { Badge, Button, Row, Col, Table, Modal } from "react-bootstrap";
 import XATableLayout from "Components/XATableLayout";
 import dateFormat from "dateformat";
@@ -40,10 +40,12 @@ import {
   toString,
   toUpper,
   has,
-  filter
+  filter,
+  find,
+  isArray
 } from "lodash";
 import { toast } from "react-toastify";
-import { Link } from "react-router-dom";
+import qs from "qs";
 import { AccessMoreLess } from "Components/CommonComponents";
 import { PolicyViewDetails } from "./AdminLogs/PolicyViewDetails";
 import StructuredFilter from 
"../../components/structured-filter/react-typeahead/tokenizer";
@@ -120,10 +122,13 @@ function Access() {
       });
     }
 
-    // Updating the states for search params, search filter, default search 
filter and localStorage
-    if (localStorage?.excludeServiceUser) {
+    // Add excludeServiceUser if not present in the search param with default 
state value of checked
+    if (!has(searchParam, "excludeServiceUser")) {
       searchParam["excludeServiceUser"] = checked;
     }
+    localStorage.setItem("excludeServiceUser", checked);
+
+    // Updating the states for search params, search filter, default search 
filter and localStorage
     setSearchParams(searchParam, { replace: true });
     setSearchFilterParams(searchFilterParam);
     setDefaultSearchFilterParams(defaultSearchFilterParam);
@@ -135,17 +140,16 @@ function Access() {
       let { searchFilterParam, defaultSearchFilterParam, searchParam } =
         fetchSearchFilterParams("bigData", searchParams, searchFilterOptions);
 
-      // Updating the states for search params, search filter, default search 
filter and localStorage
-      if (localStorage?.excludeServiceUser || searchParam?.excludeServiceUser) 
{
-        if (searchParam?.excludeServiceUser) {
-          setChecked(searchParam?.excludeServiceUser == "true" ? true : false);
-          localStorage.setItem(
-            "excludeServiceUser",
-            searchParam?.excludeServiceUser
-          );
-        }
-        searchParam["excludeServiceUser"] = localStorage?.excludeServiceUser;
+      // Update excludeServiceUser in the search param and in the localStorage
+      if (searchParam?.excludeServiceUser) {
+        setChecked(searchParam?.excludeServiceUser == "true" ? true : false);
+        localStorage.setItem(
+          "excludeServiceUser",
+          searchParam?.excludeServiceUser
+        );
       }
+
+      // Updating the states for search params, search filter, default search 
filter and localStorage
       setSearchParams(searchParam, { replace: true });
       if (
         JSON.stringify(searchFilterParams) !== 
JSON.stringify(searchFilterParam)
@@ -154,6 +158,7 @@ function Access() {
       }
       setDefaultSearchFilterParams(defaultSearchFilterParam);
       localStorage.setItem("bigData", JSON.stringify(searchParam));
+
       setContentLoader(false);
     }
   }, [searchParams, servicesAvailable]);
@@ -186,7 +191,10 @@ function Access() {
           try {
             logsResp = await fetchApi({
               url: "assets/accessAudit",
-              params: params
+              params: params,
+              paramsSerializer: function (params) {
+                return qs.stringify(params, { arrayFormat: "repeat" });
+              }
             });
             logs = logsResp.data.vXAccessAudits;
             totalCount = logsResp.data.totalCount;
@@ -223,13 +231,39 @@ function Access() {
   };
 
   const toggleChange = (chkVal) => {
-    let currentParams = Object.fromEntries([...searchParams]);
-    currentParams["excludeServiceUser"] = chkVal?.target?.checked;
-    localStorage.setItem(
-      "excludeServiceUser",
-      JSON.stringify(chkVal?.target?.checked)
-    );
-    setSearchParams(currentParams, { replace: true });
+    let checkBoxValue = chkVal?.target?.checked;
+    let searchParam = {};
+
+    for (const [key, value] of searchParams.entries()) {
+      let searchFilterObj = find(searchFilterOptions, {
+        urlLabel: key
+      });
+
+      if (!isUndefined(searchFilterObj)) {
+        if (searchFilterObj?.addMultiple) {
+          let oldValue = searchParam[key];
+          let newValue = value;
+          if (oldValue) {
+            if (isArray(oldValue)) {
+              searchParam[key].push(newValue);
+            } else {
+              searchParam[key] = [oldValue, newValue];
+            }
+          } else {
+            searchParam[key] = newValue;
+          }
+        } else {
+          searchParam[key] = value;
+        }
+      } else {
+        searchParam[key] = value;
+      }
+    }
+
+    searchParam["excludeServiceUser"] = checkBoxValue;
+    localStorage.setItem("excludeServiceUser", checkBoxValue);
+
+    setSearchParams(searchParam, { replace: true });
     setAccessLogs([]);
     setChecked(chkVal?.target?.checked);
     setLoader(true);
@@ -238,6 +272,7 @@ function Access() {
 
   const handleClosePolicyId = () => setPolicyViewModal(false);
   const handleClose = () => setShowRowModal(false);
+
   const rowModal = (row) => {
     setShowRowModal(true);
     setRowData(row.original);
@@ -770,7 +805,7 @@ function Access() {
       category: "eventId",
       label: "Audit ID",
       urlLabel: "eventId",
-      type: "number"
+      type: "text"
     },
     {
       category: "clientIP",
@@ -794,7 +829,8 @@ function Access() {
       category: "excludeUser",
       label: "Exclude User",
       urlLabel: "excludeUser",
-      type: "number"
+      addMultiple: true,
+      type: "text"
     },
     {
       category: "policyId",
@@ -857,6 +893,7 @@ function Access() {
       category: "requestUser",
       label: "User",
       urlLabel: "user",
+      addMultiple: true,
       type: "text"
     },
     {

Reply via email to