From 163d69ccca1a5bd704da33a0133d80595a221dc7 Mon Sep 17 00:00:00 2001
From: Arnab Dutta <arnab.bdutta@gmail.com>
Date: Thu, 5 Sep 2024 23:45:27 +0530
Subject: [PATCH 1/3] fix: high CPU usage on opening tarp #9390

Signed-off-by: Arnab Dutta <arnab.bdutta@gmail.com>
---
 .../jans-tarp/src/options/authFlowInputs.tsx  |  3 +-
 demos/jans-tarp/src/options/oidcClients.tsx   | 29 +++++++---
 demos/jans-tarp/src/options/options.tsx       | 54 ++++++++++++-------
 demos/jans-tarp/src/options/userDetails.tsx   | 11 ++--
 4 files changed, 64 insertions(+), 33 deletions(-)

diff --git a/demos/jans-tarp/src/options/authFlowInputs.tsx b/demos/jans-tarp/src/options/authFlowInputs.tsx
index 49f10a917cf..9c9c6018248 100644
--- a/demos/jans-tarp/src/options/authFlowInputs.tsx
+++ b/demos/jans-tarp/src/options/authFlowInputs.tsx
@@ -25,7 +25,7 @@ const createOption = (label: string) => ({
   name: label,
 });
 const filter = createFilterOptions();
-export default function AuthFlowInputs({ isOpen, handleDialog, client }) {
+export default function AuthFlowInputs({ isOpen, handleDialog, client, notifyOnDataChange }) {
   const [open, setOpen] = React.useState(isOpen);
   const [errorMessage, setErrorMessage] = React.useState("")
   const [additionalParamError, setAdditionalParamError] = React.useState("")
@@ -181,6 +181,7 @@ export default function AuthFlowInputs({ isOpen, handleDialog, client }) {
           console.log("userDetails: " + JSON.stringify(userInfoResponse.data));
           handleClose();
         });
+        notifyOnDataChange();
       }
     }
   }
diff --git a/demos/jans-tarp/src/options/oidcClients.tsx b/demos/jans-tarp/src/options/oidcClients.tsx
index 39974482a43..eaa9ff7f158 100644
--- a/demos/jans-tarp/src/options/oidcClients.tsx
+++ b/demos/jans-tarp/src/options/oidcClients.tsx
@@ -70,8 +70,8 @@ function createData(
     };
 }
 
-function Row(props: { row: ReturnType<typeof createData> }) {
-    const { row } = props;
+function Row(props: { row: ReturnType<typeof createData>, notifyOnDataChange }) {
+    const { row, notifyOnDataChange } = props;
     const [open, setOpen] = React.useState(false);
     const lifetime = Math.floor((row.expireAt - moment().toDate().getTime()) / 1000);
 
@@ -88,11 +88,16 @@ function Row(props: { row: ReturnType<typeof createData> }) {
                 chrome.storage.local.set({ oidcClients: clientArr.filter(obj => obj.clientId !== row.clientId) });
             }
         });
+        handleNotifyOnDataChange();
     }
 
+    const handleNotifyOnDataChange = () => {
+        notifyOnDataChange();
+    };
+
     return (
         <React.Fragment>
-            <AuthFlowInputs isOpen={open} handleDialog={handleDialog} client={row} />
+            <AuthFlowInputs isOpen={open} handleDialog={handleDialog} client={row} notifyOnDataChange={handleNotifyOnDataChange}/>
             <TableRow sx={{ '& > *': { borderBottom: 'unset' } }}>
                 <TableCell>
                     <Tooltip title="Delete Client from jans-tarp">
@@ -113,7 +118,12 @@ function Row(props: { row: ReturnType<typeof createData> }) {
                     <Grid item xs={8}>
                         <Tooltip title="Trigger authentication flow">
                             <IconButton aria-label="Trigger Auth Flow">
-                                <OfflineBoltIcon sx={{ color: green[500] }} onClick={() => setOpen(true)} />
+                                <OfflineBoltIcon
+                                    sx={{ color: green[500] }}
+                                    onClick={() => {
+                                        setOpen(true);
+                                        notifyOnDataChange();
+                                    }} />
                             </IconButton>
                         </Tooltip>
                     </Grid>
@@ -123,17 +133,22 @@ function Row(props: { row: ReturnType<typeof createData> }) {
     );
 }
 
-export default function OIDCClients(data) {
+export default function OIDCClients({ data, notifyOnDataChange }) {
     const [modelOpen, setModelOpen] = React.useState(false);
     const [drawerOpen, setDrawerOpen] = React.useState(false);
     const handleDialog = (isOpen) => {
         setModelOpen(isOpen);
+        notifyOnDataChange();
     };
 
     const handleDrawer = (isOpen) => {
         setDrawerOpen(isOpen);
     };
 
+    const handleNotifyOnDataChange = () => {
+        notifyOnDataChange();
+    };
+
     return (
         <Container maxWidth="lg">
             <RegisterClient isOpen={modelOpen} handleDialog={handleDialog} />
@@ -157,9 +172,9 @@ export default function OIDCClients(data) {
                             </TableRow>
                         </TableHead>
                         <TableBody>
-                            {(data.data === undefined || data.data.length == 0) ?
+                            {(data === undefined || data.length == 0) ?
                                 <TableCell colSpan={6}><Alert severity="warning">No Records to show.</Alert></TableCell> :
-                                data.data.map((row) => (<Row key={row.clientId} row={row} />))
+                                data.map((row) => (<Row key={row.clientId} row={row} notifyOnDataChange={handleNotifyOnDataChange} />))
                             }
                         </TableBody>
                     </Table>
diff --git a/demos/jans-tarp/src/options/options.tsx b/demos/jans-tarp/src/options/options.tsx
index f34c5c87e0c..cc76c137fc2 100644
--- a/demos/jans-tarp/src/options/options.tsx
+++ b/demos/jans-tarp/src/options/options.tsx
@@ -8,36 +8,50 @@ const Options = () => {
 
   const [optionType, setOptionType] = useState("");
   const [data, setdata] = useState({});
+  const [dataChanged, setDataChanged] = useState(false);
 
-  chrome.storage.local.get(["oidcClients"], (oidcClientResults) => {
-
-    if (!isEmpty(oidcClientResults) && Object.keys(oidcClientResults).length !== 0) {
-
-      chrome.storage.local.get(["loginDetails"], (loginDetailsResult) => {
-        if (!isEmpty(loginDetailsResult) && Object.keys(loginDetailsResult).length !== 0) {
-          setOptionType('loginPage');
-          setdata(loginDetailsResult);
-        } else {
-          setOptionType('oidcClientPage');
-          setdata(oidcClientResults);
-        }
-      });
-    } else {
-      setOptionType('oidcClientPage');
-      setdata({});
-    }
-  });
+  useEffect(() => {
+    chrome.storage.local.get(["oidcClients"], (oidcClientResults) => {
+
+      if (!isEmpty(oidcClientResults) && Object.keys(oidcClientResults).length !== 0) {
+
+        chrome.storage.local.get(["loginDetails"], (loginDetailsResult) => {
+          if (!isEmpty(loginDetailsResult) && Object.keys(loginDetailsResult).length !== 0) {
+            setOptionType('loginPage');
+            setdata(loginDetailsResult);
+          } else {
+            setOptionType('oidcClientPage');
+            setdata(oidcClientResults);
+          }
+        });
+      } else {
+        setOptionType('oidcClientPage');
+        setdata({});
+      }
+      setDataChanged(false);
+    })
+  }, [dataChanged]);
 
   function isEmpty(value) {
     return (value == null || value.length === 0);
   }
 
+  function handleDataChange() {
+    setDataChanged(true);
+  }
+
   function renderPage({ optionType, data }) {
     switch (optionType) {
       case 'oidcClientPage':
-        return <OIDCClients data={data.oidcClients}/>
+        return <OIDCClients
+          data={data.oidcClients}
+          notifyOnDataChange={handleDataChange}
+        />
       case 'loginPage':
-        return <UserDetails data={data.loginDetails} />
+        return <UserDetails
+          data={data.loginDetails}
+          notifyOnDataChange={handleDataChange}
+        />
       default:
         return null
     }
diff --git a/demos/jans-tarp/src/options/userDetails.tsx b/demos/jans-tarp/src/options/userDetails.tsx
index 10ef4d99220..cb430fd8ad4 100644
--- a/demos/jans-tarp/src/options/userDetails.tsx
+++ b/demos/jans-tarp/src/options/userDetails.tsx
@@ -4,7 +4,7 @@ import './options.css'
 import './alerts.css';
 import { WindmillSpinner } from 'react-spinner-overlay'
 
-const UserDetails = (data) => {
+const UserDetails = ({data, notifyOnDataChange}) => {
     const [loading, setLoading] = useState(false);
     const [showMoreIdToken, setShowMoreIdToken] = useState(false);
     const [showMoreAT, setShowMoreAT] = useState(false);
@@ -51,6 +51,7 @@ const UserDetails = (data) => {
 
         }
         setLoading(false);
+        notifyOnDataChange("true");
     }
 
     return (
@@ -61,23 +62,23 @@ const UserDetails = (data) => {
             </div>
             <legend><span className="number">O</span> User Details:</legend>
             <hr />
-            {data.data.displayToken ?
+            {data.displayToken ?
                 <>
                     <div className="alert alert-success alert-dismissable fade in">
                         <strong>Access Token</strong>
-                        <p>{showMoreAT ? (!!data.data ? data.data?.access_token : '') : (!!data.data ? data.data?.access_token.substring(0, 250).concat(' ...') : '')}</p>
+                        <p>{showMoreAT ? (!!data ? data?.access_token : '') : (!!data ? data?.access_token.substring(0, 250).concat(' ...') : '')}</p>
                         <a href="#" onClick={() => setShowMoreAT(!showMoreAT)}>{showMoreAT ? "Show less" : "Show more"}</a>
                     </div>
                     <div className="alert alert-success alert-dismissable fade in">
                         <strong>Id Token</strong>
-                        <p>{showMoreIdToken ? (!!data.data ? data.data?.id_token : '') : (!!data.data ? data.data?.id_token.substring(0, 250).concat(' ...') : '')}</p>
+                        <p>{showMoreIdToken ? (!!data ? data?.id_token : '') : (!!data ? data?.id_token.substring(0, 250).concat(' ...') : '')}</p>
                         <a href="#" onClick={() => setShowMoreIdToken(!showMoreIdToken)}>{showMoreIdToken ? "Show less" : "Show more"}</a>
                     </div>
                 </>
                 : ''}
             <div className="alert alert-success alert-dismissable fade in">
                 <strong>User Details</strong>
-                <p>{showMoreUI ? (!!data.data ? data.data?.userDetails : '') : (!!data.data ? data.data?.userDetails.substring(0, 250).concat(' ...') : '')}</p>
+                <p>{showMoreUI ? (!!data ? data?.userDetails : '') : (!!data ? data?.userDetails.substring(0, 250).concat(' ...') : '')}</p>
                 <a href="#" onClick={() => setShowMoreUI(!showMoreUI)}>{showMoreUI ? "Show less" : "Show more"}</a>
             </div>
             <hr />

From 2b6bc83628cee544dc840efa6f2c9dfe5c63aa16 Mon Sep 17 00:00:00 2001
From: Arnab Dutta <arnab.bdutta@gmail.com>
Date: Fri, 6 Sep 2024 13:12:36 +0530
Subject: [PATCH 2/3] feat: resolving review comments

Signed-off-by: Arnab Dutta <arnab.bdutta@gmail.com>
---
 demos/jans-tarp/src/options/oidcClients.tsx | 16 ++++------------
 demos/jans-tarp/src/options/userDetails.tsx |  2 +-
 2 files changed, 5 insertions(+), 13 deletions(-)

diff --git a/demos/jans-tarp/src/options/oidcClients.tsx b/demos/jans-tarp/src/options/oidcClients.tsx
index eaa9ff7f158..d18ea9a298c 100644
--- a/demos/jans-tarp/src/options/oidcClients.tsx
+++ b/demos/jans-tarp/src/options/oidcClients.tsx
@@ -88,16 +88,12 @@ function Row(props: { row: ReturnType<typeof createData>, notifyOnDataChange })
                 chrome.storage.local.set({ oidcClients: clientArr.filter(obj => obj.clientId !== row.clientId) });
             }
         });
-        handleNotifyOnDataChange();
-    }
-
-    const handleNotifyOnDataChange = () => {
         notifyOnDataChange();
-    };
+    }
 
     return (
         <React.Fragment>
-            <AuthFlowInputs isOpen={open} handleDialog={handleDialog} client={row} notifyOnDataChange={handleNotifyOnDataChange}/>
+            <AuthFlowInputs isOpen={open} handleDialog={handleDialog} client={row} notifyOnDataChange={notifyOnDataChange}/>
             <TableRow sx={{ '& > *': { borderBottom: 'unset' } }}>
                 <TableCell>
                     <Tooltip title="Delete Client from jans-tarp">
@@ -145,10 +141,6 @@ export default function OIDCClients({ data, notifyOnDataChange }) {
         setDrawerOpen(isOpen);
     };
 
-    const handleNotifyOnDataChange = () => {
-        notifyOnDataChange();
-    };
-
     return (
         <Container maxWidth="lg">
             <RegisterClient isOpen={modelOpen} handleDialog={handleDialog} />
@@ -172,9 +164,9 @@ export default function OIDCClients({ data, notifyOnDataChange }) {
                             </TableRow>
                         </TableHead>
                         <TableBody>
-                            {(data === undefined || data.length == 0) ?
+                            {(data === undefined || data?.length == 0) ?
                                 <TableCell colSpan={6}><Alert severity="warning">No Records to show.</Alert></TableCell> :
-                                data.map((row) => (<Row key={row.clientId} row={row} notifyOnDataChange={handleNotifyOnDataChange} />))
+                                data.map((row) => (<Row key={row?.clientId} row={row} notifyOnDataChange={notifyOnDataChange} />))
                             }
                         </TableBody>
                     </Table>
diff --git a/demos/jans-tarp/src/options/userDetails.tsx b/demos/jans-tarp/src/options/userDetails.tsx
index cb430fd8ad4..3aea22ce430 100644
--- a/demos/jans-tarp/src/options/userDetails.tsx
+++ b/demos/jans-tarp/src/options/userDetails.tsx
@@ -62,7 +62,7 @@ const UserDetails = ({data, notifyOnDataChange}) => {
             </div>
             <legend><span className="number">O</span> User Details:</legend>
             <hr />
-            {data.displayToken ?
+            {data?.displayToken ?
                 <>
                     <div className="alert alert-success alert-dismissable fade in">
                         <strong>Access Token</strong>

From 0dd943f5bbaee1dce28c0fd9b21c0bd2fa62ca16 Mon Sep 17 00:00:00 2001
From: Arnab Dutta <arnab.bdutta@gmail.com>
Date: Fri, 6 Sep 2024 13:23:21 +0530
Subject: [PATCH 3/3] feat: correct comments

Signed-off-by: Arnab Dutta <arnab.bdutta@gmail.com>
---
 demos/jans-tarp/src/options/registerClient.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/demos/jans-tarp/src/options/registerClient.tsx b/demos/jans-tarp/src/options/registerClient.tsx
index 2cc012af3f4..07e4e35de35 100644
--- a/demos/jans-tarp/src/options/registerClient.tsx
+++ b/demos/jans-tarp/src/options/registerClient.tsx
@@ -140,7 +140,7 @@ export default function RegisterClient({ isOpen, handleDialog }) {
 
       if (openidConfig != undefined) {
         chrome.storage.local.set({ opConfiguration: openidConfig.data }).then(() => {
-          console.log("openapiConfig is set to " + openidConfig);
+          console.log("OP Configuration: " + JSON.stringify(openidConfig));
         });
 
         const registrationUrl = openidConfig.data.registration_endpoint;