Skip to content

Commit

Permalink
Merge pull request #211 from wwWallet/insufficient-creds
Browse files Browse the repository at this point in the history
handling "HandleOutboundRequestError" type of errors
  • Loading branch information
kkmanos authored Mar 29, 2024
2 parents c10e145 + 4bdcbc7 commit 390541a
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 7 deletions.
10 changes: 9 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const PrivateRoute = React.lazy(() => import('./components/PrivateRoute'));
const CredentialDetail = React.lazy(() => import('./pages/Home/CredentialDetail'));
const SelectCredentialsPopup = React.lazy(() => import('./components/Popups/SelectCredentials'));
const PinInputPopup = React.lazy(() => import('./components/Popups/PinInput'));
const MessagePopup = React.lazy(() => import('./components/Popups/MessagePopup'));
const VerificationResult = React.lazy(() => import('./pages/VerificationResult/VerificationResult'));


Expand Down Expand Up @@ -51,7 +52,11 @@ function App() {
conformantCredentialsMap,
showPinInputPopup,
setShowPinInputPopup,
verifierDomainName
verifierDomainName,
showMessagePopup,
setMessagePopup,
textMessagePopup,
typeMessagePopup,
} = useCheckURL(url);

useEffect(() => {
Expand Down Expand Up @@ -99,6 +104,9 @@ function App() {
{showPinInputPopup &&
<PinInputPopup showPopup={showPinInputPopup} setShowPopup={setShowPinInputPopup} />
}
{showMessagePopup &&
<MessagePopup type={typeMessagePopup} message={textMessagePopup} onClose={() => setMessagePopup(false)} />
}
</HandlerNotification>
</Suspense>
</Router>
Expand Down
49 changes: 49 additions & 0 deletions src/components/Popups/MessagePopup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// MessagePopup.js
import React from 'react';
import { FaCheckCircle, FaExclamationCircle } from 'react-icons/fa';
import { useTranslation } from 'react-i18next';

const MessagePopup = ({ type, message, onClose }) => {
const { title, description } = message || {};
const { t } = useTranslation();

const IconComponent = type === 'error' ? FaExclamationCircle : FaCheckCircle;

const titleColor = type === 'error' ? 'text-red-500' : 'text-green-600';

return (
<div className="fixed inset-0 flex items-center justify-center z-50">
<div className="absolute inset-0 bg-black opacity-50" onClick={() => onClose()}></div>

<div className="bg-white p-4 rounded-lg shadow-lg w-full lg:w-[33.33%] sm:w-[66.67%] z-10 relative m-4">
<div className="flex items-start justify-between border-b rounded-t dark:border-gray-600">

<h2 className={`text-lg font-bold mb-2 flex items-center ${titleColor}`}>
<IconComponent size={20} className="inline mr-1" />
{title}
</h2>
<button type="button" className="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ml-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white" onClick={() => onClose()}>
<svg className="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
<path stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" />
</svg>
</button>
</div>
<hr className="mb-2 border-t border-custom-blue/80" />
<p className="mb-2 mt-4">
{description}
</p>
<div className="flex justify-end space-x-2 pt-4">
<button
type="button"
className="px-4 py-2 text-white bg-gray-500 hover:bg-gray-600 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-gray-300 dark:hover:bg-gray-400"
onClick={onClose}
>
{t('messagePopup.close')}
</button>
</div>
</div>
</div>
);
};

export default MessagePopup;
29 changes: 23 additions & 6 deletions src/components/useCheckURL.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { useEffect, useState, Dispatch, SetStateAction } from 'react';
import { useApi } from '../api';
import { useLocalStorageKeystore } from '../services/LocalStorageKeystore';
import { useTranslation } from 'react-i18next';

export enum HandleOutboundRequestError {
INSUFFICIENT_CREDENTIALS = "INSUFFICIENT_CREDENTIALS",
}

function useCheckURL(urlToCheck: string): {
showSelectCredentialsPopup: boolean,
Expand All @@ -10,7 +14,11 @@ function useCheckURL(urlToCheck: string): {
conformantCredentialsMap: any,
showPinInputPopup: boolean,
setShowPinInputPopup: Dispatch<SetStateAction<boolean>>,
verifierDomainName: string
verifierDomainName: string,
showMessagePopup: boolean;
setMessagePopup: Dispatch<SetStateAction<boolean>>;
textMessagePopup: { title: string, description: string };
typeMessagePopup: string;
} {
const api = useApi();
const isLoggedIn: boolean = api.isLoggedIn();
Expand All @@ -19,8 +27,11 @@ function useCheckURL(urlToCheck: string): {
const [selectionMap, setSelectionMap] = useState<string | null>(null);
const [conformantCredentialsMap, setConformantCredentialsMap] = useState(null);
const [verifierDomainName, setVerifierDomainName] = useState("");

const [showMessagePopup, setMessagePopup] = useState<boolean>(false);
const [textMessagePopup, setTextMessagePopup] = useState<{ title: string, description: string }>({ title: "", description: "" });
const [typeMessagePopup, setTypeMessagePopup] = useState<string>("");
const keystore = useLocalStorageKeystore();
const { t } = useTranslation();

useEffect(() => {

Expand All @@ -29,8 +40,14 @@ function useCheckURL(urlToCheck: string): {
const wwwallet_camera_was_used = new URL(url).searchParams.get('wwwallet_camera_was_used');

const res = await api.post('/communication/handle', { url, camera_was_used: (wwwallet_camera_was_used != null && wwwallet_camera_was_used === 'true') });
const { redirect_to, conformantCredentialsMap, verifierDomainName, preauth, ask_for_pin } = res.data;

const { redirect_to, conformantCredentialsMap, verifierDomainName, preauth, ask_for_pin, error } = res.data;
if (error && error == HandleOutboundRequestError.INSUFFICIENT_CREDENTIALS) {
console.error(`${HandleOutboundRequestError.INSUFFICIENT_CREDENTIALS}`);
setTextMessagePopup({ title: `${t('messagePopup.insufficientCredentials.title')}`, description: `${t('messagePopup.insufficientCredentials.description')}` });
setTypeMessagePopup('error');
setMessagePopup(true);
return false;
}
if (preauth && preauth == true) {
if (ask_for_pin) {
setShowPinInputPopup(true);
Expand Down Expand Up @@ -65,7 +82,7 @@ function useCheckURL(urlToCheck: string): {

if (urlToCheck && isLoggedIn && window.location.pathname === "/cb") {
(async () => {
await communicationHandler(urlToCheck);
await communicationHandler(urlToCheck);
})();
}

Expand All @@ -89,7 +106,7 @@ function useCheckURL(urlToCheck: string): {
}
}, [api, keystore, selectionMap]);

return {showSelectCredentialsPopup, setShowSelectCredentialsPopup, setSelectionMap, conformantCredentialsMap, showPinInputPopup, setShowPinInputPopup, verifierDomainName };
return { showSelectCredentialsPopup, setShowSelectCredentialsPopup, setSelectionMap, conformantCredentialsMap, showPinInputPopup, setShowPinInputPopup, verifierDomainName, showMessagePopup, setMessagePopup, textMessagePopup, typeMessagePopup };
}

export default useCheckURL;
7 changes: 7 additions & 0 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@
"weakPasswordError": "Weak password",
"welcomeMessage": "Welcome to <highlight>wwWallet</highlight>"
},
"messagePopup": {
"close": "Close",
"insufficientCredentials": {
"title": "Insufficient Credentials",
"description": "One or more of the credentials you want to present do not exist for selection."
}
},
"notFound": {
"homeButton": "Back to Home",
"message": "Sorry, the page you're looking for cannot be accessed",
Expand Down

0 comments on commit 390541a

Please sign in to comment.