From b6d4210cb1b466e01abfb29f0277701dbbbb89fa Mon Sep 17 00:00:00 2001 From: tipusinghaw Date: Fri, 1 Sep 2023 23:28:16 +0530 Subject: [PATCH 01/25] fix: fixed-fido-supabase error Signed-off-by: tipusinghaw --- src/api/Auth.ts | 2 +- .../Authentication/SignInUserPasskey.tsx | 1 - .../Authentication/SignUpUserPasskey.tsx | 28 +++++++------------ 3 files changed, 11 insertions(+), 20 deletions(-) diff --git a/src/api/Auth.ts b/src/api/Auth.ts index f60eadb10..a26bc81bf 100644 --- a/src/api/Auth.ts +++ b/src/api/Auth.ts @@ -11,7 +11,7 @@ export interface UserSignUpData { email: string, } export interface AddPasswordDetails { - password:string + password?:string isPasskey:boolean firstName: string|null lastName: string|null diff --git a/src/components/Authentication/SignInUserPasskey.tsx b/src/components/Authentication/SignInUserPasskey.tsx index 97a6da657..8d04a78ba 100644 --- a/src/components/Authentication/SignInUserPasskey.tsx +++ b/src/components/Authentication/SignInUserPasskey.tsx @@ -100,7 +100,6 @@ const SignInUserPasskey = (signInUserProps: signInUserProps) => { if (data?.data.verified) { const payload: UserSignInData = { email: email, - password: passwordEncryption('Password@1'), isPasskey: true }; diff --git a/src/components/Authentication/SignUpUserPasskey.tsx b/src/components/Authentication/SignUpUserPasskey.tsx index c9130fb58..3aeaba1d2 100644 --- a/src/components/Authentication/SignUpUserPasskey.tsx +++ b/src/components/Authentication/SignUpUserPasskey.tsx @@ -4,7 +4,7 @@ import { Alert, Button } from 'flowbite-react'; import type { AxiosError, AxiosResponse } from 'axios'; import type { IdeviceBody, RegistrationOptionInterface } from '../Profile/interfaces/index.js'; import { addDeviceDetails, generateRegistrationOption, verifyRegistration } from '../../api/Fido.js'; -import { addPasswordDetails, getFromLocalStorage, passwordEncryption, sendVerificationMail } from '../../api/Auth.js'; +import { AddPasswordDetails, addPasswordDetails, getFromLocalStorage, passwordEncryption, sendVerificationMail } from '../../api/Auth.js'; import { apiStatusCodes, storageKeys } from '../../config/CommonConstant.js'; import { useEffect, useState } from 'react'; @@ -57,14 +57,16 @@ const SignUpUserPasskey = ({ firstName, lastName }: { firstName: string; lastNam } } - const submit = async (passwordDetails: passwordValues, fidoFlag: boolean) => { + const submit = async (fidoFlag: boolean, passwordDetails?: passwordValues,) => { const userEmail = await getFromLocalStorage(storageKeys.USER_EMAIL) - const payload = { - password: passwordEncryption(passwordDetails?.password), - isPasskey: false, + let payload: AddPasswordDetails = { + isPasskey: fidoFlag, firstName: firstName, - lastName: lastName - } + lastName: lastName, + }; + if (!fidoFlag) { + payload.password = passwordDetails?.password; + } setLoading(true) const userRsp = await addPasswordDetails(payload, userEmail) @@ -148,17 +150,7 @@ const SignUpUserPasskey = ({ firstName, lastName }: { firstName: string; lastNam const deviceDetailsResp = await addDeviceDetails(deviceBody) const { data } = deviceDetailsResp as AxiosResponse if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - // const password = secureRandomPassword.randomPassword({ - // characters: secureRandomPassword.lower + secureRandomPassword.upper + secureRandomPassword.digits, - // length: 12, - // }); - const fidoPassword = { - password: 'Password@1', - // confirmPassword: `${password}@1` - confirmPassword: 'Password@1' - } - - submit(fidoPassword, true) + submit(true) } else { setAddFailur(deviceDetailsResp as string) } From 3b2647ac788fff4fe61c40c682d16f75e0c00a48 Mon Sep 17 00:00:00 2001 From: tipusinghaw Date: Thu, 7 Sep 2023 15:07:32 +0530 Subject: [PATCH 02/25] feat: implemented passkey add device Signed-off-by: tipusinghaw --- package-lock.json | 234 ++++++++- package.json | 3 +- src/api/Auth.ts | 24 + src/assets/passkeyAddDevice.svg | 127 +++++ src/commonComponents/PasseyAddDevicePopup.tsx | 195 +++++++ .../Authentication/ResetPassword.tsx | 82 ++- .../Authentication/SignUpUserPasskey.tsx | 61 ++- src/components/Profile/AddPasskey.tsx | 486 +++++++++--------- src/components/Profile/interfaces/index.ts | 3 + src/config/apiRoutes.ts | 3 +- 10 files changed, 950 insertions(+), 268 deletions(-) create mode 100644 src/assets/passkeyAddDevice.svg create mode 100644 src/commonComponents/PasseyAddDevicePopup.tsx diff --git a/package-lock.json b/package-lock.json index 98810efde..61136c553 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49,6 +49,7 @@ "socket.io-client": "^4.6.2", "tailwind-scrollbar": "^3.0.4", "tailwindcss": "^3.3.3", + "uuidv4": "^6.2.13", "yup": "^1.2.0" }, "devDependencies": { @@ -1352,6 +1353,15 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-drE6uz7QBKq1fYqqoFKTDRdFCPHd5TCub75BM+D+cMx7NU9hUz7SESLfC2fSCXVFMO5Yj8sOWHuGqPgjc+fz0Q==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/mdast": { "version": "3.0.12", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.12.tgz", @@ -1456,6 +1466,11 @@ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.7.tgz", "integrity": "sha512-cputDpIbFgLUaGQn6Vqg3/YsJwxUwHLO13v3i5ouxT4lat0khip9AEWxtERujXV9wxIB1EyF97BSJFt6vpdI8g==" }, + "node_modules/@types/uuid": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", + "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==" + }, "node_modules/@types/websocket": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/websocket/-/websocket-1.0.5.tgz", @@ -2369,6 +2384,11 @@ "ieee754": "^1.2.1" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "node_modules/bufferutil": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.7.tgz", @@ -3085,6 +3105,14 @@ "resolved": "https://registry.npmjs.org/easy-bem/-/easy-bem-1.1.1.tgz", "integrity": "sha512-GJRqdiy2h+EXy6a8E6R+ubmqUM08BK0FWNq41k24fup6045biQ8NXxoXimiwegMQvFFV3t1emADdGNL1TlS61A==" }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/electron-to-chromium": { "version": "1.4.484", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.484.tgz", @@ -5399,6 +5427,46 @@ "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.3.1.tgz", "integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==" }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -5512,16 +5580,46 @@ "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==" }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, "node_modules/lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "node_modules/log-symbols": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", @@ -10741,9 +10839,9 @@ } }, "node_modules/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -11806,6 +11904,23 @@ "base64-arraybuffer": "^1.0.2" } }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/uuidv4": { + "version": "6.2.13", + "resolved": "https://registry.npmjs.org/uuidv4/-/uuidv4-6.2.13.tgz", + "integrity": "sha512-AXyzMjazYB3ovL3q051VLH06Ixj//Knx7QnUSi1T//Ie3io6CpsPu9nVMOx5MoLWh6xV0B9J0hIaxungxXUbPQ==", + "dependencies": { + "@types/uuid": "8.3.4", + "uuid": "8.3.2" + } + }, "node_modules/uvu": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz", @@ -13268,6 +13383,15 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "@types/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-drE6uz7QBKq1fYqqoFKTDRdFCPHd5TCub75BM+D+cMx7NU9hUz7SESLfC2fSCXVFMO5Yj8sOWHuGqPgjc+fz0Q==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/mdast": { "version": "3.0.12", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.12.tgz", @@ -13374,6 +13498,11 @@ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.7.tgz", "integrity": "sha512-cputDpIbFgLUaGQn6Vqg3/YsJwxUwHLO13v3i5ouxT4lat0khip9AEWxtERujXV9wxIB1EyF97BSJFt6vpdI8g==" }, + "@types/uuid": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", + "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==" + }, "@types/websocket": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/websocket/-/websocket-1.0.5.tgz", @@ -13991,6 +14120,11 @@ "ieee754": "^1.2.1" } }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "bufferutil": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.7.tgz", @@ -14463,6 +14597,14 @@ "resolved": "https://registry.npmjs.org/easy-bem/-/easy-bem-1.1.1.tgz", "integrity": "sha512-GJRqdiy2h+EXy6a8E6R+ubmqUM08BK0FWNq41k24fup6045biQ8NXxoXimiwegMQvFFV3t1emADdGNL1TlS61A==" }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "electron-to-chromium": { "version": "1.4.484", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.484.tgz", @@ -16108,6 +16250,42 @@ "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.3.1.tgz", "integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==" }, + "jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + } + }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -16196,16 +16374,46 @@ "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==" }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, "lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "log-symbols": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", @@ -19565,9 +19773,9 @@ } }, "semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" }, @@ -20345,6 +20553,20 @@ "base64-arraybuffer": "^1.0.2" } }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, + "uuidv4": { + "version": "6.2.13", + "resolved": "https://registry.npmjs.org/uuidv4/-/uuidv4-6.2.13.tgz", + "integrity": "sha512-AXyzMjazYB3ovL3q051VLH06Ixj//Knx7QnUSi1T//Ie3io6CpsPu9nVMOx5MoLWh6xV0B9J0hIaxungxXUbPQ==", + "requires": { + "@types/uuid": "8.3.4", + "uuid": "8.3.2" + } + }, "uvu": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz", diff --git a/package.json b/package.json index e4af0800f..68e9bae08 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "socket.io-client": "^4.6.2", "tailwind-scrollbar": "^3.0.4", "tailwindcss": "^3.3.3", + "uuidv4": "^6.2.13", "yup": "^1.2.0" }, "devDependencies": { @@ -90,4 +91,4 @@ "eslint-plugin-tsdoc": "^0.2.17", "postcss": "^8.4.25" } -} \ No newline at end of file +} diff --git a/src/api/Auth.ts b/src/api/Auth.ts index a26bc81bf..78a7a7017 100644 --- a/src/api/Auth.ts +++ b/src/api/Auth.ts @@ -6,6 +6,7 @@ import CryptoJS from "crypto-js" import { apiRoutes } from '../config/apiRoutes' import { envConfig } from '../config/envConfig' import { storageKeys } from '../config/CommonConstant' +import type { AddPassword } from '../components/Profile/interfaces' export interface UserSignUpData { email: string, @@ -152,6 +153,29 @@ export const addPasswordDetails = async(payload: AddPasswordDetails, email:strin } +export const addPasskeyUserDetails = async(payload: AddPassword, email:string) => { + const token = await getFromLocalStorage(storageKeys.TOKEN) + const details ={ + url: `${apiRoutes.auth.passkeyUserDetails}${email}`, + payload, + config: { headers: { + 'Content-type': 'application/json', + 'Authorization': `Bearer ${token}`, + }, } + } + try{ + const response = await axiosPost(details) + return response + } + catch(error){ + const err = error as Error + return err?.message + } + + +} + + export const passwordEncryption = (password: string): string => { const CRYPTO_PRIVATE_KEY: string = `${envConfig.PUBLIC_CRYPTO_PRIVATE_KEY}` const encryptedPassword: string = CryptoJS.AES.encrypt(JSON.stringify(password), CRYPTO_PRIVATE_KEY).toString() diff --git a/src/assets/passkeyAddDevice.svg b/src/assets/passkeyAddDevice.svg new file mode 100644 index 000000000..eb46e93cd --- /dev/null +++ b/src/assets/passkeyAddDevice.svg @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/commonComponents/PasseyAddDevicePopup.tsx b/src/commonComponents/PasseyAddDevicePopup.tsx new file mode 100644 index 000000000..869282e9e --- /dev/null +++ b/src/commonComponents/PasseyAddDevicePopup.tsx @@ -0,0 +1,195 @@ +import * as yup from 'yup'; +import { Button, Label, Modal } from 'flowbite-react'; +import { + Field, + Form, + Formik, +} from 'formik'; +import { useState } from 'react'; +import { Alert } from 'flowbite-react'; +import type { AxiosResponse } from 'axios'; +import { addPasskeyUserDetails, getFromLocalStorage, passwordEncryption } from '../api/Auth'; +import { apiStatusCodes, storageKeys } from '../config/CommonConstant'; +import { getSupabaseClient } from '../supabase'; +import passkeyAddDevice from '../assets/passkeyAddDevice.svg'; + +interface passwordValue { + Password: string; +} + +const PasskeyAddDevice = (props: { + setOpenModel(arg0: boolean): unknown; openModal: boolean; closeModal: (flag: boolean) => void; registerWithPasskey: (flag: boolean) => Promise +} +) => { + const [fidoUserError, setFidoUserError] = useState(null) + const [nextflag, setNextFlag] = useState(false) + const [success, setSuccess] = useState(null) + const [passwordVisible, setPasswordVisible] = useState(false); + + const savePassword = async (values: passwordValue) => { + try { + const storedEmail = await getFromLocalStorage(storageKeys.LOGIN_USER_EMAIL); + const { data, error } = await getSupabaseClient().auth.signInWithPassword({ + email: storedEmail, + password: values.Password, + }); + if (error) { + setFidoUserError(error?.message) + + } else { + if (data) { + const payload = { + password: passwordEncryption(values.Password) + } + const passkeyUserDetailsResp = await addPasskeyUserDetails(payload, storedEmail) + const { data } = passkeyUserDetailsResp as AxiosResponse + if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { + setSuccess('User details updated successfully') + setNextFlag(true) + } else { + setFidoUserError(passkeyUserDetailsResp as string) + } + } + } + } catch (error) { + console.error('An unexpected error occurred:', error.message); + setFidoUserError('An unexpected error occurred') + } + }; + + return ( + { + props.setOpenModel(false) + } + }> + Add Passkey + +
+ { + (success || fidoUserError) && +
+ { + setSuccess(null) + setFidoUserError(null) + } + } + > + +

+ {success || fidoUserError} +

+
+
+
+ } + {!nextflag && (
+

+ Enter Password +

+
)} + + {!nextflag && ( savePassword(values)} + > + {(formikHandlers): JSX.Element => ( +
+
+
+
+
+ + +
+ { + (formikHandlers?.errors?.Password && formikHandlers?.touched?.Password) && + {formikHandlers?.errors?.Password} + } +
+ +
+ )} +
)} + + {nextflag && ( +
+
+ SVG Image +
+
+ +
+
)} +
+
+
+ ); +}; + +export default PasskeyAddDevice; \ No newline at end of file diff --git a/src/components/Authentication/ResetPassword.tsx b/src/components/Authentication/ResetPassword.tsx index ac5559dff..feca92385 100644 --- a/src/components/Authentication/ResetPassword.tsx +++ b/src/components/Authentication/ResetPassword.tsx @@ -8,13 +8,15 @@ import { Form, Formik } from 'formik'; -import { passwordRegex } from '../../config/CommonConstant.js'; -import { useState } from 'react'; +import { apiStatusCodes, passwordRegex, storageKeys } from '../../config/CommonConstant.js'; +import { useEffect, useState } from 'react'; import { getSupabaseClient } from '../../supabase'; import { pathRoutes } from '../../config/pathRoutes.js'; import FooterBar from './FooterBar.js'; import NavBar from './NavBar.js'; +import { addPasskeyUserDetails, getFromLocalStorage, passwordEncryption, setToLocalStorage } from '../../api/Auth.js'; +import type { AxiosResponse } from 'axios'; interface passwordValues { password: string, @@ -29,20 +31,74 @@ const ResetPassword = () => { const [message, setMessage] = useState('') const [passwordVisible, setPasswordVisible] = useState(false); const [confirmPasswordVisible, setConfirmPasswordVisible] = useState(false); + const [userToken, setUserToken] = useState(''); + + useEffect(() => { + const setAccessToken = async () => { + const hashPart = window.location.href.split("#")[1]; + const paramsArray = hashPart.split("&"); + let accessToken; + for (const param of paramsArray) { + const [key, value] = param.split("="); + if (key === "access_token") { + accessToken = value; + break; + } + } + if (accessToken) { + setUserToken(accessToken); + } else { + + } + + }; + setAccessToken(); + }, []); const submit = async (passwordDetails: passwordValues) => { - - setLoading(true) - - const { data, error } = await getSupabaseClient().auth.updateUser({ password: passwordDetails?.password }); - - setLoading(false) - if (!error) { + try { + await setToLocalStorage(storageKeys.TOKEN, userToken); + setLoading(true); + + const { data, error } = await getSupabaseClient().auth.updateUser({ password: passwordDetails?.password }); + + if (data?.user?.email) { + await updatePasswordDetails(passwordEncryption(passwordDetails?.password), data.user.email); + } + + if (!error) { + setLoading(false); window.location.href = `${pathRoutes.auth.sinIn}?isPasswordSet=true` - } else { - setErrMsg(error.message) + } else { + setLoading(false); + setErrMsg(error.message); + } + } catch (error) { + console.error('An error occurred:', error); + setErrMsg('An error occurred while updating password in supabase.'); } - } + }; + + + const updatePasswordDetails = async (password: string, email: string) => { + try { + const payload = { + password: password + } + const passkeyUserDetailsResp = await addPasskeyUserDetails(payload, email); + const { data } = passkeyUserDetailsResp as AxiosResponse; + + if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { + setLoading(false); + } else { + setErrMsg(passkeyUserDetailsResp as string); + } + } catch (error) { + console.error('An error occurred:', error); + setErrMsg('An error occurred while updating password details.'); + } + }; + return (
@@ -190,7 +246,7 @@ const ResetPassword = () => { />
- +
+ +
+

+ © 2019 - {new Date().getFullYear()} - + CREDEBL + | All rights reserved. +

+ +
+
} { @@ -328,4 +379,4 @@ const SignUpUserPasskey = ({ firstName, lastName }: { firstName: string; lastNam ); }; -export default SignUpUserPasskey; +export default SignUpUserPasskey; \ No newline at end of file diff --git a/src/components/Profile/AddPasskey.tsx b/src/components/Profile/AddPasskey.tsx index 615420515..7dc6506b9 100644 --- a/src/components/Profile/AddPasskey.tsx +++ b/src/components/Profile/AddPasskey.tsx @@ -1,276 +1,278 @@ - import { useEffect, useState } from 'react'; - import { startRegistration } from '@simplewebauthn/browser' - import type { AxiosError, AxiosResponse } from 'axios'; - import { addDeviceDetails, generateRegistrationOption, getUserDeviceDetails, verifyRegistration } from '../../api/Fido'; - import DeviceDetails from '../../commonComponents/DeviceDetailsCard'; - import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; - import { getFromLocalStorage, getUserProfile } from '../../api/Auth'; - import BreadCrumbs from '../BreadCrumbs'; - import { Alert } from 'flowbite-react'; - import type { IDeviceData, IdeviceBody, RegistrationOptionInterface, UserProfile, verifyRegistrationObjInterface } from './interfaces'; - import DisplayUserProfile from './DisplayUserProfile'; - import EditUserProfile from './EditUserProfile'; +import { useEffect, useState } from 'react'; +import { startRegistration } from '@simplewebauthn/browser' +import type { AxiosError, AxiosResponse } from 'axios'; +import { addDeviceDetails, generateRegistrationOption, getUserDeviceDetails, verifyRegistration } from '../../api/Fido'; +import DeviceDetails from '../../commonComponents/DeviceDetailsCard'; +import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; +import { getFromLocalStorage, getUserProfile } from '../../api/Auth'; +import BreadCrumbs from '../BreadCrumbs'; +import { Alert } from 'flowbite-react'; +import type { IDeviceData, IdeviceBody, RegistrationOptionInterface, UserProfile, verifyRegistrationObjInterface } from './interfaces'; +import DisplayUserProfile from './DisplayUserProfile'; import UpdateUserProfile from './EditUserProfile'; import CustomSpinner from '../CustomSpinner'; - - const AddPasskey = () => { - const [fidoError, setFidoError] = useState("") - const [fidoLoader, setFidoLoader] = useState(false) - const [OrgUserEmail, setOrgUserEmail] = useState('') - const [deviceList, setDeviceList] = useState([]) - const [addSuccess, setAddSuccess] = useState(null) - const [addfailure, setAddFailur] = useState(null) - const [isEditProfileOpen, setIsEditProfileOpen] = useState(false); - const [prePopulatedUserProfile, setPrePopulatedUserProfile] = useState(null); - - - const fetchUserProfile = async () => { - try { - const token = await getFromLocalStorage(storageKeys.TOKEN); - const userDetailsResponse = await getUserProfile(token); - const { data } = userDetailsResponse as AxiosResponse; - - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - setPrePopulatedUserProfile(data?.data); - } - } catch (error) { - } - }; - - const toggleEditProfile = async () => { - await fetchUserProfile() - setIsEditProfileOpen(!isEditProfileOpen); - }; - - const showFidoError = (error: unknown): void => { - const err = error as AxiosError - if (err.message.includes("The operation either timed out or was not allowed")) { - const [errorMsg] = err.message.split('.') - setFidoError(errorMsg) - setTimeout(() => { - setFidoError("") - }, 5000) - } else { - setFidoError(err.message) - setTimeout(() => { - setFidoError("") - }, 5000) +import PasskeyAddDevice from '../../commonComponents/PasseyAddDevicePopup'; + +const AddPasskey = () => { + const [fidoError, setFidoError] = useState("") + const [fidoLoader, setFidoLoader] = useState(false) + const [OrgUserEmail, setOrgUserEmail] = useState('') + const [deviceList, setDeviceList] = useState([]) + const [addSuccess, setAddSuccess] = useState(null) + const [addfailure, setAddFailur] = useState(null) + const [isEditProfileOpen, setIsEditProfileOpen] = useState(false); + const [prePopulatedUserProfile, setPrePopulatedUserProfile] = useState(null); + + + const [openModel, setOpenModel] = useState(false) + + const props = { openModel, setOpenModel }; + const fetchUserProfile = async () => { + try { + const token = await getFromLocalStorage(storageKeys.TOKEN); + const userDetailsResponse = await getUserProfile(token); + const { data } = userDetailsResponse as AxiosResponse; + + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + setPrePopulatedUserProfile(data?.data); } + } catch (error) { } + }; + const toggleEditProfile = async () => { + await fetchUserProfile() + setIsEditProfileOpen(!isEditProfileOpen); + }; - const addDevice = async (): Promise => { - try { - registerWithPasskey(true) - } catch (error) { - setFidoLoader(false) - } + const showFidoError = (error: unknown): void => { + const err = error as AxiosError + if (err.message.includes("The operation either timed out or was not allowed")) { + const [errorMsg] = err.message.split('.') + setFidoError(errorMsg) + } else { + setFidoError(err.message) } + } - const setProfile = async () => { - const UserEmail = await getFromLocalStorage(storageKeys.USER_EMAIL) - setOrgUserEmail(UserEmail) - return UserEmail + const addDevice = async (): Promise => { + try { + setOpenModel(true) + } catch (error) { + setFidoLoader(false) } - - useEffect(() => { - fetchUserProfile(); + } + const setProfile = async () => { + const UserEmail = await getFromLocalStorage(storageKeys.USER_EMAIL) + setOrgUserEmail(UserEmail) + return UserEmail + } + + useEffect(() => { + fetchUserProfile(); }, []); - const registerWithPasskey = async (flag: boolean): Promise => { - try { - const RegistrationOption: RegistrationOptionInterface = { - userName: OrgUserEmail, - deviceFlag: flag - } - // Generate Registration Option - const generateRegistrationResponse = await generateRegistrationOption(RegistrationOption) - const { data } = generateRegistrationResponse as AxiosResponse - const opts = data?.data - const challangeId = data?.data?.challenge - if (opts) { - opts.authenticatorSelection = { - residentKey: "preferred", - requireResidentKey: false, - userVerification: "preferred" - } - } - const attResp = await startRegistration(opts) - - const verifyRegistrationObj = { - ...attResp, - challangeId + const registerWithPasskey = async (flag: boolean): Promise => { + try { + const RegistrationOption: RegistrationOptionInterface = { + userName: OrgUserEmail, + deviceFlag: flag + } + // Generate Registration Option + const generateRegistrationResponse = await generateRegistrationOption(RegistrationOption) + const { data } = generateRegistrationResponse as AxiosResponse + const opts = data?.data + const challangeId = data?.data?.challenge + if (opts) { + opts.authenticatorSelection = { + residentKey: "preferred", + requireResidentKey: false, + userVerification: "preferred" } + } + setOpenModel(false) + const attResp = await startRegistration(opts) - await verifyRegistrationMethod(verifyRegistrationObj, OrgUserEmail); - } catch (error) { - showFidoError(error) + const verifyRegistrationObj = { + ...attResp, + challangeId } + console.log("verifyRegistrationObj::::", verifyRegistrationObj) + await verifyRegistrationMethod(verifyRegistrationObj, OrgUserEmail); + } catch (error) { + showFidoError(error) } + } - const verifyRegistrationMethod = async (verifyRegistrationObj, OrgUserEmail: string) => { - try { - const verificationRegisterResp = await verifyRegistration(verifyRegistrationObj, OrgUserEmail) - const { data } = verificationRegisterResp as AxiosResponse - const credentialID = data?.data?.newDevice?.credentialID + const verifyRegistrationMethod = async (verifyRegistrationObj, OrgUserEmail: string) => { + try { + const verificationRegisterResp = await verifyRegistration(verifyRegistrationObj, OrgUserEmail) + const { data } = verificationRegisterResp as AxiosResponse + const credentialID = data?.data?.newDevice?.credentialID - if (data?.data?.verified) { - let platformDeviceName = '' + if (data?.data?.verified) { + let platformDeviceName = '' - if (verifyRegistrationObj?.authenticatorAttachment === "cross-platform") { - platformDeviceName = 'Passkey' - } else { - platformDeviceName = navigator.platform - } + if (verifyRegistrationObj?.authenticatorAttachment === "cross-platform") { + platformDeviceName = 'Passkey' + } else { + platformDeviceName = navigator.platform + } - const deviceBody: IdeviceBody = { - userName: OrgUserEmail, - credentialId: credentialID, - deviceFriendlyName: platformDeviceName - } - await addDeviceDetailsMethod(deviceBody) + const deviceBody: IdeviceBody = { + userName: OrgUserEmail, + credentialId: credentialID, + deviceFriendlyName: platformDeviceName } - } catch (error) { - showFidoError(error) + await addDeviceDetailsMethod(deviceBody) } + } catch (error) { + showFidoError(error) } - - const addDeviceDetailsMethod = async (deviceBody: IdeviceBody) => { - try { - const deviceDetailsResp = await addDeviceDetails(deviceBody) - const { data } = deviceDetailsResp as AxiosResponse - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - setAddSuccess("Device added successfully") - userDeviceDetails() - } else { - setAddFailur(deviceDetailsResp as string) - } - setTimeout(() => { - setAddSuccess('') - setAddFailur('') - }, 3000); - } catch (error) { - showFidoError(error) + } + + const addDeviceDetailsMethod = async (deviceBody: IdeviceBody) => { + try { + const deviceDetailsResp = await addDeviceDetails(deviceBody) + const { data } = deviceDetailsResp as AxiosResponse + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + setAddSuccess("Device added successfully") + userDeviceDetails() + } else { + setAddFailur(deviceDetailsResp as string) } + } catch (error) { + showFidoError(error) } - - //userDeviceDetails on page reload - const userDeviceDetails = async (): Promise => { - try { - const config = { headers: {} } - setFidoLoader(true) - - const userDeviceDetailsResp = await getUserDeviceDetails(OrgUserEmail) - setFidoLoader(false) - - if (userDeviceDetailsResp) { - const deviceDetails = Object.keys(userDeviceDetailsResp?.data?.data)?.length > 0 ? - userDeviceDetailsResp?.data?.data.map((data) => { - data.lastChangedDateTime = data.lastChangedDateTime ? data.lastChangedDateTime : "-" - return data - }) - : [] - setDeviceList(deviceDetails) - } - } catch (error) { - setFidoLoader(false) + } + + //userDeviceDetails on page reload + const userDeviceDetails = async (): Promise => { + try { + const config = { headers: {} } + setFidoLoader(true) + + const userDeviceDetailsResp = await getUserDeviceDetails(OrgUserEmail) + setFidoLoader(false) + + if (userDeviceDetailsResp) { + const deviceDetails = Object.keys(userDeviceDetailsResp?.data?.data)?.length > 0 ? + userDeviceDetailsResp?.data?.data.map((data) => { + data.lastChangedDateTime = data.lastChangedDateTime ? data.lastChangedDateTime : "-" + return data + }) + : [] + setDeviceList(deviceDetails) } + } catch (error) { + setFidoLoader(false) } + } + + useEffect(() => { + if (OrgUserEmail) { + userDeviceDetails(); + } else { + setProfile(); + } + }, [OrgUserEmail]); + + const updatePrePopulatedUserProfile = (updatedProfile: UserProfile) => { + setPrePopulatedUserProfile(updatedProfile); + }; + + return ( + +
+ +

+ User's Profile +

+ + {fidoLoader + ?
+ + +
+ : + +
+ + {/* first section */} +
+ + {!isEditProfileOpen && prePopulatedUserProfile && ( + + )} + + {isEditProfileOpen && prePopulatedUserProfile && ( + + )} - useEffect(() => { - if (OrgUserEmail) { - userDeviceDetails(); - } else { - setProfile(); - } - }, [OrgUserEmail]); - - const updatePrePopulatedUserProfile = (updatedProfile: UserProfile) => { - setPrePopulatedUserProfile(updatedProfile); - }; - - return ( - -
- -

- User's Profile -

- - {fidoLoader - ?
- -
- : - -
- - {/* first section */} -
- - {!isEditProfileOpen && prePopulatedUserProfile && ( - - )} - - {isEditProfileOpen && prePopulatedUserProfile && ( - - )} - -
- - {/* second section */} -
-
- -
- {deviceList && deviceList.length > 0 && - deviceList.map((element, key) => ( - - ))} -
- -
- - {/* */} - { - (addSuccess || addfailure || fidoError) && -
- setAddSuccess(null)} - > - -

- {addSuccess || addfailure || fidoError} -

-
-
-
- } -
+ + {/* second section */} +
+
+ +
+ {deviceList && deviceList.length > 0 && + deviceList.map((element, key) => ( + + ))}
+
+ + + { + (addSuccess || addfailure || fidoError) && +
+ { + setAddSuccess(null) + setFidoError('') + setAddFailur('') + }} + > + +

+ {addSuccess || addfailure || fidoError} +

+
+
+
+ } +
- } -
- ); - }; - export default AddPasskey; + +
+ } +
+ ); +}; + +export default AddPasskey; diff --git a/src/components/Profile/interfaces/index.ts b/src/components/Profile/interfaces/index.ts index 74df7fa80..799a152b5 100644 --- a/src/components/Profile/interfaces/index.ts +++ b/src/components/Profile/interfaces/index.ts @@ -4,6 +4,9 @@ export interface RegistrationOptionInterface { } +export interface AddPassword { + password: string, +} export interface verifyRegistrationObjInterface { id: string; rawId: string; diff --git a/src/config/apiRoutes.ts b/src/config/apiRoutes.ts index da347f155..06d0393a2 100644 --- a/src/config/apiRoutes.ts +++ b/src/config/apiRoutes.ts @@ -7,7 +7,8 @@ export const apiRoutes = { verifyEmail:'/users/verify', userProfile: 'users/profile', checkUser:'/users/check-user/', - addDetails:'/users/add/' + addDetails:'/users/add/', + passkeyUserDetails:'/users/password/' }, users:{ invitations: '/users/invitations', From 5611880318014a72800dc07459271a8a20e9f4c5 Mon Sep 17 00:00:00 2001 From: tipusinghaw Date: Thu, 7 Sep 2023 15:50:38 +0530 Subject: [PATCH 03/25] fix: removed duplicate code Signed-off-by: tipusinghaw --- src/commonComponents/PasseyAddDevicePopup.tsx | 13 ++-- .../Authentication/ResetPassword.tsx | 4 +- .../Authentication/SignUpUserPasskey.tsx | 63 ++----------------- 3 files changed, 14 insertions(+), 66 deletions(-) diff --git a/src/commonComponents/PasseyAddDevicePopup.tsx b/src/commonComponents/PasseyAddDevicePopup.tsx index 869282e9e..45ad109ad 100644 --- a/src/commonComponents/PasseyAddDevicePopup.tsx +++ b/src/commonComponents/PasseyAddDevicePopup.tsx @@ -1,19 +1,18 @@ import * as yup from 'yup'; -import { Button, Label, Modal } from 'flowbite-react'; +import { Button, Label, Modal, Alert } from 'flowbite-react'; import { Field, Form, Formik, } from 'formik'; import { useState } from 'react'; -import { Alert } from 'flowbite-react'; import type { AxiosResponse } from 'axios'; import { addPasskeyUserDetails, getFromLocalStorage, passwordEncryption } from '../api/Auth'; import { apiStatusCodes, storageKeys } from '../config/CommonConstant'; import { getSupabaseClient } from '../supabase'; import passkeyAddDevice from '../assets/passkeyAddDevice.svg'; -interface passwordValue { +interface PasswordValue { Password: string; } @@ -26,7 +25,7 @@ const PasskeyAddDevice = (props: { const [success, setSuccess] = useState(null) const [passwordVisible, setPasswordVisible] = useState(false); - const savePassword = async (values: passwordValue) => { + const savePassword = async (values: PasswordValue) => { try { const storedEmail = await getFromLocalStorage(storageKeys.LOGIN_USER_EMAIL); const { data, error } = await getSupabaseClient().auth.signInWithPassword({ @@ -37,7 +36,6 @@ const PasskeyAddDevice = (props: { setFidoUserError(error?.message) } else { - if (data) { const payload = { password: passwordEncryption(values.Password) } @@ -49,7 +47,7 @@ const PasskeyAddDevice = (props: { } else { setFidoUserError(passkeyUserDetailsResp as string) } - } + } } catch (error) { console.error('An unexpected error occurred:', error.message); @@ -102,7 +100,7 @@ const PasskeyAddDevice = (props: { validateOnBlur validateOnChange enableReinitialize - onSubmit={(values: passwordValue) => savePassword(values)} + onSubmit={(values: PasswordValue) => savePassword(values)} > {(formikHandlers): JSX.Element => (
@@ -120,6 +118,7 @@ const PasskeyAddDevice = (props: { />
@@ -174,7 +173,7 @@ const ViewSchemas = () => { {loading ? (
- +
) : (
@@ -209,19 +208,19 @@ const ViewSchemas = () => {

- Name: {schemaDetails?.schemaName} + Name: {schemaDetails?.schema?.name}

- Version: {schemaDetails?.version} + Version: {schemaDetails?.schema?.version}

Schema ID: {schemaDetails?.schemaId}

- Issuer DID: {schemaDetails?.issuerDid} + Issuer DID: {schemaDetails?.schema?.issuerId}

@@ -230,9 +229,9 @@ const ViewSchemas = () => {
Attributes: - {schemaDetails?.attributes && schemaDetails?.attributes?.length > 0 && - schemaDetails?.attributes.map((element: string) => ( - {element?.attributeName} + {schemaDetails?.schema?.attrNames && schemaDetails?.schema?.attrNames?.length > 0 && + schemaDetails?.schema?.attrNames.map((element: string) => ( + {element} ))}
@@ -383,9 +382,9 @@ const ViewSchemas = () => { Credential Definitions - {credDeffloader ? (
- - + {loading ? (
+ +
) : credDeffList && credDeffList.length > 0 ? (
@@ -422,4 +421,5 @@ const ViewSchemas = () => { } -export default ViewSchemas \ No newline at end of file +export default ViewSchemas + From 7f3a3f24c50390e2cbbe4d2d7f4a74ab2ad582d5 Mon Sep 17 00:00:00 2001 From: "@nishad.shirsat" Date: Mon, 11 Sep 2023 12:17:53 +0530 Subject: [PATCH 09/25] worked on user role management for org dashboard and users invitations Signed-off-by: @nishad.shirsat --- src/components/EmptyListComponent/index.tsx | 18 +++--- src/components/RoleViewButton/index.tsx | 60 +++++++++++++++++++ src/components/organization/Dashboard.tsx | 25 ++++++-- src/components/organization/OrgDropDown.tsx | 24 ++++---- .../organization/OrganizationsList.tsx | 44 ++++++++------ .../organization/invitations/Invitations.tsx | 28 +++++---- src/components/organization/users/Members.tsx | 27 ++++++--- src/utils/enums/features.ts | 6 ++ src/utils/enums/roles.ts | 8 +++ 9 files changed, 177 insertions(+), 63 deletions(-) create mode 100644 src/components/RoleViewButton/index.tsx create mode 100644 src/utils/enums/features.ts create mode 100644 src/utils/enums/roles.ts diff --git a/src/components/EmptyListComponent/index.tsx b/src/components/EmptyListComponent/index.tsx index c9989430d..a3b29005e 100644 --- a/src/components/EmptyListComponent/index.tsx +++ b/src/components/EmptyListComponent/index.tsx @@ -1,12 +1,13 @@ import type { ReactElement } from "react"; +import RoleViewButton from "../RoleViewButton"; -export const EmptyListMessage = ({ message, description, buttonContent, svgComponent, onClick } +export const EmptyListMessage = ({ message, description, buttonContent, svgComponent, onClick, feature } : { message: string, description: string, buttonContent?: string, svgComponent?: ReactElement, - + feature?: string onClick?: () => void, }) => { return ( @@ -15,12 +16,13 @@ export const EmptyListMessage = ({ message, description, buttonContent, svgCompo

{description}

{ buttonContent - && + && + }
diff --git a/src/components/RoleViewButton/index.tsx b/src/components/RoleViewButton/index.tsx new file mode 100644 index 000000000..4ed94b180 --- /dev/null +++ b/src/components/RoleViewButton/index.tsx @@ -0,0 +1,60 @@ +import { ReactElement, useEffect, useState } from 'react'; + +import { Button } from 'flowbite-react'; +import { Features } from '../../utils/enums/features'; +import { Roles } from '../../utils/enums/roles'; +import { getFromLocalStorage } from '../../api/Auth'; +import { storageKeys } from '../../config/CommonConstant'; + +interface RoleViewButtonProps { + buttonTitle?: string, + svgComponent?: ReactElement, + onClickEvent?: () => void, + feature: string +} + + +const RoleViewButton = ({ buttonTitle, svgComponent, onClickEvent, feature }: RoleViewButtonProps) => { + + const [userRoles, setUserRoles] = useState([]) + + const getUserRoles = async () => { + const orgRoles = await getFromLocalStorage(storageKeys.ORG_ROLES) + const roles = orgRoles.split(',') + setUserRoles(roles) + } + + useEffect(() => { + getUserRoles() + }, []) + + const isRoleAccess = (): boolean => { + + if(feature === Features.CRETAE_ORG){ + return true + } else if (userRoles.includes(Roles.OWNER) || userRoles.includes(Roles.ADMIN)) { + return true + } else { + return false + } + + } + + return ( + <> + { + isRoleAccess() + && + } + + ) + +} + +export default RoleViewButton \ No newline at end of file diff --git a/src/components/organization/Dashboard.tsx b/src/components/organization/Dashboard.tsx index d9a3d554c..3505dbf13 100644 --- a/src/components/organization/Dashboard.tsx +++ b/src/components/organization/Dashboard.tsx @@ -12,6 +12,7 @@ import CustomSpinner from '../CustomSpinner'; import EditOrgdetailsModal from './EditOrgdetailsModal'; import Invitation_Card from '../../assets/Invitation_Card.svg'; import OrganizationDetails from './OrganizationDetails'; +import { Roles } from '../../utils/enums/roles'; import Schema_Card from '../../assets/Schema_Card.svg'; import User_Card from '../../assets/User_Card.svg'; import WalletSpinup from './WalletSpinup'; @@ -28,6 +29,7 @@ const Dashboard = () => { const [failure, setFailure] = useState(null) const [loading, setLoading] = useState(true) + const [userRoles, setUserRoles] = useState([]) const [openModal, setOpenModal] = useState(false); const props = { openModal, setOpenModal }; @@ -42,6 +44,16 @@ const Dashboard = () => { setOrgData(updatedData); }; + const getUserRoles = async () => { + const orgRoles = await getFromLocalStorage(storageKeys.ORG_ROLES) + const roles = orgRoles.split(',') + setUserRoles(roles) + } + + useEffect(() => { + getUserRoles() + },[]) + const fetchOrganizationDetails = async () => { @@ -147,9 +159,10 @@ const Dashboard = () => {
-
-
- + } {
) : walletStatus === true ? () - : ( setWalletSpinupStatus(flag)} />) + : ((userRoles.includes(Roles.OWNER) || userRoles.includes(Roles.ADMIN)) + && setWalletSpinupStatus(flag)} />) + } diff --git a/src/components/organization/OrgDropDown.tsx b/src/components/organization/OrgDropDown.tsx index fbc072c74..5c1fb7c1c 100644 --- a/src/components/organization/OrgDropDown.tsx +++ b/src/components/organization/OrgDropDown.tsx @@ -28,11 +28,20 @@ const OrgDropDown = () => { } }; - const goToOrgDashboard = async (orgId: number, roles: string[]) => { - await setToLocalStorage(storageKeys.ORG_ID, orgId.toString()); + const goToOrgDashboard = async (org: Organisation) => { + + await setOrgRoleDetails(org) window.location.href = pathRoutes.organizations.dashboard; }; + const setOrgRoleDetails = async (org: Organisation) => { + + await setToLocalStorage(storageKeys.ORG_ID, org.id.toString()); + const roles: string[] = org?.userOrgRoles.map(role => role.orgRole.name) + + await setToLocalStorage(storageKeys.ORG_ROLES, roles.toString()); + } + const setActiveOrg = async (organizations: Organisation[]) => { let activeOrg: Organisation | null = null @@ -48,15 +57,8 @@ const OrgDropDown = () => { } if (activeOrg) { - - await setToLocalStorage(storageKeys.ORG_ID, activeOrg.id.toString()); - const roles: string[] = activeOrg?.userOrgRoles.map(role => role.orgRole.name) - activeOrg.roles = roles - - await setToLocalStorage(storageKeys.ORG_ROLES, roles.toString()); + await setOrgRoleDetails(activeOrg) } - - } const redirectToCreateOrgModal = () => { @@ -107,7 +109,7 @@ const OrgDropDown = () => { const roles: string[] = org.userOrgRoles.map(role => role.orgRole.name) org.roles = roles return ( -
  • goToOrgDashboard(org?.id, org?.roles)}> +
  • goToOrgDashboard(org)}> { setSearchText(e.target.value); } - const redirectOrgDashboard = (orgId: number) => { - setToLocalStorage(storageKeys.ORG_ID, orgId.toString()) - window.location.href = pathRoutes.organizations.dashboard + const redirectOrgDashboard = async (activeOrg: Organisation) => { + + await setToLocalStorage(storageKeys.ORG_ID, activeOrg.id.toString()); + const roles: string[] = activeOrg?.userOrgRoles.map(role => role.orgRole.name) + activeOrg.roles = roles + + await setToLocalStorage(storageKeys.ORG_ROLES, roles.toString()); + window.location.href = pathRoutes.organizations.dashboard } @@ -132,18 +139,18 @@ const OrganizationsList = () => { - + + + + +
  • + } + onClickEvent={createOrganizationModel} + />
    { : organizationsList && organizationsList?.length > 0 ? (
    { organizationsList.map((org) => ( - redirectOrgDashboard(org.id)} className='transform transition duration-500 hover:scale-105 hover:bg-gray-50 cursor-pointer'> + redirectOrgDashboard(org)} className='transform transition duration-500 hover:scale-105 hover:bg-gray-50 cursor-pointer'>
    {(org.logoUrl) ? : } @@ -214,6 +221,7 @@ const OrganizationsList = () => { description={'Get started by creating a new Organization'} buttonContent={'Create Organization'} onClick={createOrganizationModel} + feature={Features.CRETAE_ORG} svgComponent={ } />) diff --git a/src/components/organization/invitations/Invitations.tsx b/src/components/organization/invitations/Invitations.tsx index 1b8f5bfd3..b350258fa 100644 --- a/src/components/organization/invitations/Invitations.tsx +++ b/src/components/organization/invitations/Invitations.tsx @@ -1,20 +1,22 @@ 'use client'; -import { Button, Pagination } from 'flowbite-react'; import { ChangeEvent, useEffect, useState } from 'react'; +import { apiStatusCodes, storageKeys } from '../../../config/CommonConstant'; import { AlertComponent } from '../../AlertComponent'; import type { AxiosResponse } from 'axios'; +import CustomSpinner from '../../CustomSpinner'; import { EmptyListMessage } from '../../EmptyListComponent'; +import { Features } from '../../../utils/enums/features'; import type { Invitation } from '../interfaces/invitations'; import type { OrgRole } from '../interfaces' +import { Pagination } from 'flowbite-react'; +import RoleViewButton from '../../RoleViewButton'; import SearchInput from '../../SearchInput'; import SendInvitationModal from './SendInvitationModal'; import { TextTittlecase } from '../../../utils/TextTransform'; -import { apiStatusCodes } from '../../../config/CommonConstant'; +import { getFromLocalStorage } from '../../../api/Auth'; import { getOrganizationInvitations } from '../../../api/invitations'; -import { getOrganizations } from '../../../api/organization'; -import CustomSpinner from '../../CustomSpinner'; const initialPageState = { pageNumber: 1, @@ -29,6 +31,7 @@ const Invitations = () => { const [message, setMessage] = useState(null) const [error, setError] = useState(null) const [currentPage, setCurrentPage] = useState(initialPageState); + const [userRoles, setUserRoles] = useState([]) const timestamp = Date.now(); const onPageChange = (page: number) => { @@ -87,6 +90,7 @@ const Invitations = () => { return () => clearTimeout(getData) }, [searchText, openModal, currentPage.pageNumber]) + //onCHnage of Search input text const searchInputChange = (e: ChangeEvent) => { setSearchText(e.target.value); @@ -106,16 +110,15 @@ const Invitations = () => { - + } + onClickEvent={createInvitationsModel} + />
    { message={'No Invitations'} description={'Get started by inviting a users'} buttonContent={'Invite'} + feature={Features.SEND_INVITATION} onClick={createInvitationsModel} svgComponent={ diff --git a/src/components/organization/users/Members.tsx b/src/components/organization/users/Members.tsx index f64b120c0..7e831c5c2 100644 --- a/src/components/organization/users/Members.tsx +++ b/src/components/organization/users/Members.tsx @@ -1,16 +1,18 @@ 'use client'; import { ChangeEvent, useEffect, useState } from 'react'; -import { Pagination } from 'flowbite-react'; -import { getOrganizationUsers, getOrganizations } from '../../../api/organization'; +import { apiStatusCodes, storageKeys } from '../../../config/CommonConstant'; import { AlertComponent } from '../../AlertComponent'; import type { AxiosResponse } from 'axios'; +import CustomSpinner from '../../CustomSpinner'; import EditUserRoleModal from './EditUserRolesModal'; +import { Pagination } from 'flowbite-react'; +import {Roles} from '../../../utils/enums/roles' import SearchInput from '../../SearchInput'; import type { User } from '../interfaces/users'; -import { apiStatusCodes } from '../../../config/CommonConstant'; -import CustomSpinner from '../../CustomSpinner'; +import { getFromLocalStorage } from '../../../api/Auth'; +import { getOrganizationUsers } from '../../../api/organization'; const initialPageState = { pageNumber: 1, @@ -24,6 +26,7 @@ const Members = () => { const [loading, setLoading] = useState(false) const [message, setMessage] = useState(null) const [error, setError] = useState(null) + const [userRoles, setUserRoles] = useState([]) const [currentPage, setCurrentPage] = useState(initialPageState); const timestamp = Date.now(); @@ -39,10 +42,6 @@ const Members = () => { const [selectedUser, setSelectedUser] = useState(null) const props = { openModal, setOpenModal }; - const createOrganizationModel = () => { - props.setOpenModal(true) - } - //Fetch the user organization list const getAllUsers = async () => { setLoading(true) @@ -95,6 +94,16 @@ const Members = () => { return () => clearTimeout(getData) }, [searchText, openModal, currentPage.pageNumber]) + const getUserRoles = async () => { + const orgRoles = await getFromLocalStorage(storageKeys.ORG_ROLES) + const roles = orgRoles.split(',') + setUserRoles(roles) + } + + useEffect(() => { + getUserRoles() + },[]) + //onCHnage of Search input text const searchInputChange = (e: ChangeEvent) => { setSearchText(e.target.value); @@ -193,7 +202,7 @@ const Members = () => { { - !user.roles.includes('owner') + !user.roles.includes(Roles.OWNER) && (userRoles.includes(Roles.OWNER) || userRoles.includes(Roles.ADMIN)) ?

    editUserRole(user)} className="cursor-pointer mr-2 flex items-center text-sm font-medium text-gray-500 dark:text-gray-400" diff --git a/src/utils/enums/features.ts b/src/utils/enums/features.ts new file mode 100644 index 000000000..bd1fe8aee --- /dev/null +++ b/src/utils/enums/features.ts @@ -0,0 +1,6 @@ + + +export enum Features { + SEND_INVITATION = 'send_invitations', + CRETAE_ORG = 'create_org' +} \ No newline at end of file diff --git a/src/utils/enums/roles.ts b/src/utils/enums/roles.ts new file mode 100644 index 000000000..1e92dec3b --- /dev/null +++ b/src/utils/enums/roles.ts @@ -0,0 +1,8 @@ + +export enum Roles { + OWNER = 'owner', + ADMIN = 'admin', + ISSUER = 'issuer', + VERIFIER = 'verifier', + MEMBER = 'member' +}; From 1d11fae79ea32031ae20b029a25b863b66b515d7 Mon Sep 17 00:00:00 2001 From: tipusinghaw Date: Mon, 11 Sep 2023 12:28:22 +0530 Subject: [PATCH 10/25] feat: implemented disable revoke button if only one passkey left Signed-off-by: tipusinghaw --- src/api/Auth.ts | 2 +- src/commonComponents/DeviceDetailsCard.tsx | 18 ++++++++++-------- src/commonComponents/PasseyAddDevicePopup.tsx | 7 ++++--- .../Authentication/SignInUserPasskey.tsx | 3 +-- src/components/Profile/AddPasskey.tsx | 17 ++++++++++++----- src/config/apiRoutes.ts | 5 +++-- 6 files changed, 31 insertions(+), 21 deletions(-) diff --git a/src/api/Auth.ts b/src/api/Auth.ts index 22d69312a..d6dd14c0d 100644 --- a/src/api/Auth.ts +++ b/src/api/Auth.ts @@ -136,7 +136,7 @@ export const checkUserExist = async(payload: string) => { } export const addPasswordDetails = async(payload: AddPasswordDetails, email:string) => { - // Api call to add password details + // Api call to add password const details ={ url: `${apiRoutes.auth.addDetails}${email}`, payload, diff --git a/src/commonComponents/DeviceDetailsCard.tsx b/src/commonComponents/DeviceDetailsCard.tsx index 7ae032d15..97ac3e5e2 100644 --- a/src/commonComponents/DeviceDetailsCard.tsx +++ b/src/commonComponents/DeviceDetailsCard.tsx @@ -7,8 +7,9 @@ import type { AxiosResponse } from "axios"; import { apiStatusCodes } from "../config/CommonConstant"; import BreadCrumbs from "../components/BreadCrumbs"; import editIcon from '/images/edit.svg'; +import React from "react"; -const DeviceDetails = (props: { deviceFriendlyName: string, createDateTime: string, credentialID: string, refreshList: () => void }) => { +const DeviceDetails = (props: { deviceFriendlyName: string, createDateTime: string, credentialID: string, refreshList: () => void, disableRevoke: boolean }) => { const [openModal, setOpenModal] = useState(false); const [openEditModel, setOpenEditModel] = useState(false) const [editSuccess, setEditSuccess] = useState(null) @@ -48,18 +49,17 @@ const DeviceDetails = (props: { deviceFriendlyName: string, createDateTime: stri const { data } = editDeviceDetailsResponse as AxiosResponse if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { await setEditSuccess(data?.message) - - + + } else { setEditFailur(editDeviceDetailsResponse as string) } setTimeout(() => { - setEditSuccess('') - setEditFailur('') props.refreshList() - }, 3000); + }, 4000); + } - + return ( <>

      @@ -103,7 +103,9 @@ const DeviceDetails = (props: { deviceFriendlyName: string, createDateTime: stri

    - @@ -181,7 +182,7 @@ const PasskeyAddDevice = (props: { id="loginwithpasskey" isProcessing={''} onClick={() => props.registerWithPasskey(true)} - className="text-base font-medium text-center text-white bg-primary-700 rounded-lg hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 sm:w-auto dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800" + className="text-base hover:!bg-primary-800 font-medium text-center text-white bg-primary-700 rounded-lg hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 sm:w-auto dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800" > Create Passkey diff --git a/src/components/Authentication/SignInUserPasskey.tsx b/src/components/Authentication/SignInUserPasskey.tsx index 9681911b6..94e1921fb 100644 --- a/src/components/Authentication/SignInUserPasskey.tsx +++ b/src/components/Authentication/SignInUserPasskey.tsx @@ -97,7 +97,6 @@ const SignInUserPasskey = (signInUserProps: signInUserProps) => { }; const verificationResp = await verifyAuthenticationMethod(verifyAuthenticationObj, { userName: email }); const { data } = verificationResp as AxiosResponse - if (data?.data.verified) { const payload: UserSignInData = { email: email, @@ -234,7 +233,7 @@ const SignInUserPasskey = (signInUserProps: signInUserProps) => {
    - + --> + + - Initiate Issuance + Issue
    diff --git a/src/commonComponents/DeviceDetailsCard.tsx b/src/commonComponents/DeviceDetailsCard.tsx index 44236244b..77c2ae0a3 100644 --- a/src/commonComponents/DeviceDetailsCard.tsx +++ b/src/commonComponents/DeviceDetailsCard.tsx @@ -8,6 +8,7 @@ import { apiStatusCodes } from "../config/CommonConstant"; import BreadCrumbs from "../components/BreadCrumbs"; import editIcon from '/images/edit.svg'; import { dateConversion } from "../utils/DateConversion"; +import DateTooltip from "../components/Tooltip"; const DeviceDetails = (props: { deviceFriendlyName: string, createDateTime: string, credentialID: string, refreshList: () => void }) => { const [openModal, setOpenModal] = useState(false); @@ -97,8 +98,9 @@ const DeviceDetails = (props: { deviceFriendlyName: string, createDateTime: stri

    - {dateConversion(new Date(props.createDateTime).toLocaleDateString('en-GB'))} -

    + + {dateConversion(new Date(props.createDateTime).toLocaleDateString('en-GB'))} +

    {props.credentialID}

    diff --git a/src/commonComponents/SchemaCard.tsx b/src/commonComponents/SchemaCard.tsx index ad3b93e00..e141741de 100644 --- a/src/commonComponents/SchemaCard.tsx +++ b/src/commonComponents/SchemaCard.tsx @@ -1,5 +1,6 @@ import { Card } from 'flowbite-react'; import { dateConversion } from '../utils/DateConversion'; +import DateTooltip from '../components/Tooltip'; const SchemaCard = (props: {className:string, schemaName: string, version: string, schemaId: string, issuerDid: string, attributes: [], created: string, onClickCallback: (schemaId: string, attributes: string[], issuerDid:string, created:string) => void; }) => { return ( @@ -17,8 +18,9 @@ const SchemaCard = (props: {className:string, schemaName: string, version: strin

    - Created: {dateConversion(props.created)} -

    + + Created: {dateConversion(props.created)} +

    diff --git a/src/components/Issuance/ConnectionList.tsx b/src/components/Issuance/ConnectionList.tsx index 599d1cee3..d054c1a63 100644 --- a/src/components/Issuance/ConnectionList.tsx +++ b/src/components/Issuance/ConnectionList.tsx @@ -8,6 +8,8 @@ import type { TableData } from "../../commonComponents/datatable/interface"; import { apiStatusCodes } from "../../config/CommonConstant"; import { AlertComponent } from "../AlertComponent"; import { dateConversion } from "../../utils/DateConversion"; +import DateTooltip from "../Tooltip"; +import React from "react"; const ConnectionList = (props: { selectConnection: (connections: TableData[]) => void; }) => { @@ -38,7 +40,7 @@ const ConnectionList = (props: { selectConnection: (connections: TableData[]) => const createdOn = ele?.createdAt ? ele?.createdAt : 'Not available' return { data: [{ - data:
    + data:
    ) => { const inputElement = event.target as HTMLInputElement; selectConnection(userName, connectionId, inputElement.checked) @@ -46,7 +48,9 @@ const ConnectionList = (props: { selectConnection: (connections: TableData[]) => value="" className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded-lg focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600 cursor-pointer" />
    }, - { data: userName }, { data: connectionId }, {data:dateConversion(createdOn)}, + { data: userName }, + { data: connectionId }, + {data: {dateConversion(createdOn)} }, ] } }) @@ -104,8 +108,8 @@ const ConnectionList = (props: { selectConnection: (connections: TableData[]) => }, [selectedConnectionList]) return ( -
    -
    +
    +

    Connection List

    @@ -117,7 +121,7 @@ const ConnectionList = (props: { selectConnection: (connections: TableData[]) => setError(null) }} /> -
    diff --git a/src/components/Issuance/CredDefSelection.tsx b/src/components/Issuance/CredDefSelection.tsx index 84212fb6e..4e49ca23f 100644 --- a/src/components/Issuance/CredDefSelection.tsx +++ b/src/components/Issuance/CredDefSelection.tsx @@ -17,6 +17,7 @@ import { dateConversion } from "../../utils/DateConversion"; import { getCredentialDefinitions } from "../../api/issuance"; import { getSchemaById } from "../../api/Schema"; import { pathRoutes } from "../../config/pathRoutes"; +import DateTooltip from "../Tooltip"; const CredDefSelection = () => { const [schemaState, setSchemaState] = useState({ schemaName: '', version: '' }) @@ -72,7 +73,8 @@ const CredDefSelection = () => { if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { const credDefs = data?.data?.data.map((ele: CredDefData) => { return { - clickId: ele.credentialDefinitionId, data: [{ data: ele.tag ? ele.tag : 'Not available' }, { data: ele?.createDateTime ? dateConversion(ele?.createDateTime): 'Not available' }, + clickId: ele.credentialDefinitionId, data: [{ data: ele.tag ? ele.tag : 'Not available' }, + { data: ele?.createDateTime ? {dateConversion(ele?.createDateTime)} : 'Not available' }, { data: ele.revocable === true ? Yes : No } ] } diff --git a/src/components/Issuance/IssuedCrdentials.tsx b/src/components/Issuance/IssuedCrdentials.tsx index b6248cf7c..4c63f633c 100644 --- a/src/components/Issuance/IssuedCrdentials.tsx +++ b/src/components/Issuance/IssuedCrdentials.tsx @@ -17,6 +17,7 @@ import type { TableData } from '../../commonComponents/datatable/interface'; import { dateConversion } from '../../utils/DateConversion'; import { getIssuedCredentials } from '../../api/issuance'; import { pathRoutes } from '../../config/pathRoutes'; +import DateTooltip from '../Tooltip'; interface IssuedCredential { metadata: { [x: string]: { schemaId: string } }; @@ -56,7 +57,7 @@ const CredentialList = () => { : 'Not available', }, { data: schemaName }, - { data: dateConversion(issuedCredential.updatedAt) }, + { data: {dateConversion(issuedCredential.updatedAt)} }, { data: ( { + + const formattedDate = date ? moment(date).format("MMM DD, YYYY, h:mm A z") : ''; + + return ( + + { + children + } + + ) +} + +export default DateTooltip \ No newline at end of file diff --git a/src/components/User/UserDashBoard.tsx b/src/components/User/UserDashBoard.tsx index 737204bf4..9bbe9ce17 100644 --- a/src/components/User/UserDashBoard.tsx +++ b/src/components/User/UserDashBoard.tsx @@ -13,6 +13,7 @@ import { getUserInvitations } from "../../api/invitations"; import { pathRoutes } from "../../config/pathRoutes"; import { setToLocalStorage } from "../../api/Auth"; import { dateConversion } from "../../utils/DateConversion"; +import DateTooltip from "../Tooltip"; const initialPageState = { pageNumber: 1, @@ -256,7 +257,10 @@ const UserDashBoard = () => {

    {activity.action} diff --git a/src/components/Verification/ConnectionList.tsx b/src/components/Verification/ConnectionList.tsx index 212e006fa..c9995b8f1 100644 --- a/src/components/Verification/ConnectionList.tsx +++ b/src/components/Verification/ConnectionList.tsx @@ -8,6 +8,8 @@ import type { TableData } from "../../commonComponents/datatable/interface"; import { apiStatusCodes } from "../../config/CommonConstant"; import { AlertComponent } from "../AlertComponent"; import { dateConversion } from "../../utils/DateConversion"; +import DateTooltip from "../Tooltip"; +import React from "react"; const ConnectionList = (props: { selectConnection: (connections: TableData[]) => void; }) => { const [connectionList, setConnectionList] = useState([]) @@ -18,10 +20,10 @@ const ConnectionList = (props: { selectConnection: (connections: TableData[]) => const [error, setError] = useState(null) useEffect(() => { - getConnections() + getConnectionsVerification() }, []) - const getConnections = async () => { + const getConnectionsVerification = async () => { setLoading(true) const response = await getConnectionsByOrg(); const { data } = response as AxiosResponse @@ -33,7 +35,7 @@ const ConnectionList = (props: { selectConnection: (connections: TableData[]) => const createdOn = ele?.createdAt ? ele?.createdAt : 'Not available' return { data: [{ - data:
    + data:
    ) => { const inputElement = event.target as HTMLInputElement; selectConnection(userName, connectionId, inputElement.checked) @@ -42,7 +44,9 @@ const ConnectionList = (props: { selectConnection: (connections: TableData[]) => className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded-lg focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600 cursor-pointer" />
    }, - { data: userName }, { data: connectionId }, {data:dateConversion(createdOn)}, + { data: userName }, + { data: connectionId }, + {data: {dateConversion(createdOn)} }, ] } }) @@ -54,8 +58,8 @@ const ConnectionList = (props: { selectConnection: (connections: TableData[]) => setLoading(false) } - - const header = [ + + const verification_header = [ { columnName: '', width: 'w-0.5' }, { columnName: 'User' }, { columnName: 'Connection ID' }, @@ -85,22 +89,23 @@ const ConnectionList = (props: { selectConnection: (connections: TableData[]) => }, [selectedConnectionList]) return ( -
    -
    +
    +

    Connection List

    - { setError(null) }} /> -
    - +
    ) diff --git a/src/components/Verification/VerificationCredentialList.tsx b/src/components/Verification/VerificationCredentialList.tsx index bd187dfd2..26dcf9d66 100644 --- a/src/components/Verification/VerificationCredentialList.tsx +++ b/src/components/Verification/VerificationCredentialList.tsx @@ -27,6 +27,7 @@ import { dateConversion } from '../../utils/DateConversion'; import { pathRoutes } from '../../config/pathRoutes'; import { removeFromLocalStorage } from '../../api/Auth'; import CustomSpinner from '../CustomSpinner'; +import DateTooltip from '../Tooltip'; const VerificationCredentialList = () => { const [loading, setLoading] = useState(true); @@ -76,7 +77,7 @@ const VerificationCredentialList = () => { ? requestProof?.connectionId : 'Not available', }, - { data: dateConversion(requestProof?.updatedAt) }, + { data: {dateConversion(requestProof.updatedAt)} }, { data: ( { @@ -173,8 +174,11 @@ const OrganizationDetails = ({ orgData }: { orgData: Organisation | null }) => {

    - {agentData?.createDateTime ? dateConversion(agentData?.createDateTime) : dateConversion(new Date().toISOString())} - + { + agentData?.createDateTime ? + { dateConversion(agentData?.createDateTime) } : + { dateConversion(new Date().toISOString()) } + }

    diff --git a/src/components/organization/OrganizationsList.tsx b/src/components/organization/OrganizationsList.tsx index d256ac6d9..199d5368b 100644 --- a/src/components/organization/OrganizationsList.tsx +++ b/src/components/organization/OrganizationsList.tsx @@ -16,6 +16,7 @@ import { pathRoutes } from '../../config/pathRoutes'; import { setToLocalStorage } from '../../api/Auth'; import { EmptyListMessage } from '../EmptyListComponent'; import CustomSpinner from '../CustomSpinner'; +import React from 'react'; const initialPageState = { pageNumber: 1, @@ -169,7 +170,7 @@ const OrganizationsList = () => { : organizationsList && organizationsList?.length > 0 ? (
    { organizationsList.map((org) => ( - redirectOrgDashboard(org.id)} className='transform transition duration-500 hover:scale-105 hover:bg-gray-50 cursor-pointer'> + redirectOrgDashboard(org.id)} className='transform transition duration-500 hover:scale-105 hover:bg-gray-50 cursor-pointer overflow-hidden overflow-ellipsis' style={{ maxHeight: '100%', maxWidth: '100%', overflow: 'auto' }}>
    {(org.logoUrl) ? : } diff --git a/src/components/organization/invitations/Invitations.tsx b/src/components/organization/invitations/Invitations.tsx index 05e01b003..4e3fceac6 100644 --- a/src/components/organization/invitations/Invitations.tsx +++ b/src/components/organization/invitations/Invitations.tsx @@ -16,6 +16,7 @@ import { getOrganizationInvitations } from '../../../api/invitations'; import { getOrganizations } from '../../../api/organization'; import CustomSpinner from '../../CustomSpinner'; import { dateConversion } from '../../../utils/DateConversion'; +import DateTooltip from '../../Tooltip'; const initialPageState = { pageNumber: 1, @@ -220,9 +221,9 @@ const Invitations = () => {

    - Invited On: {dateConversion(invitation.createDateTime)} -

    - + Invited On: {dateConversion(invitation.createDateTime)} +

    +
    )) From fec24a1d053ced24112f73398083fc69611d15b0 Mon Sep 17 00:00:00 2001 From: pranalidhanavade Date: Tue, 12 Sep 2023 20:16:28 +0530 Subject: [PATCH 13/25] feat:added terms conditions and privacy policy Signed-off-by: pranalidhanavade --- src/pages/index.astro | 12 +-- src/pages/privacy-policy.md | 93 ++++++++++++++++++++++ src/pages/terms-and-conditions.md | 124 ++++++++++++++++++++++++++++++ src/styles/markdown.css | 30 ++++++++ 4 files changed, 253 insertions(+), 6 deletions(-) create mode 100644 src/pages/privacy-policy.md create mode 100644 src/pages/terms-and-conditions.md create mode 100644 src/styles/markdown.css diff --git a/src/pages/index.astro b/src/pages/index.astro index 6ae21b513..9c4eafae8 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1056,13 +1056,13 @@ import { pathRoutes } from '../config/pathRoutes'; >Blockster Labs Private Limited. All Rights Reserved. -
    -

    - • Terms and Conditions -

    -

    +

    diff --git a/src/pages/privacy-policy.md b/src/pages/privacy-policy.md new file mode 100644 index 000000000..91322d3f2 --- /dev/null +++ b/src/pages/privacy-policy.md @@ -0,0 +1,93 @@ +# PRIVACY POLICY + +Effective Date: 12/09/2023 + +## 1. Responsible Entity's Name and Contact Information +Responsible for the processing of data on ADEYA Mobile Wallet App: Blockster Labs Pvt Ltd Company; A Company established under provisions of Companies Act 1956 of Government of India, and as amended further from time to time and having its registered office at 409, Navale ICON, Off. Mumbai-Bangalore Highway, Narhe, Pune, Maharashtra, 411021 India +Email: privacy@blockster.global + +Note: A data control officer has not been mandated by the Responsible Entity. If you have queries or wish to assert any of your legal rights regarding data protection, kindly get in touch with the Responsible Entity immediately. + +## 2. Information on the Processing of Personal Data +ADEYA Mobile Wallet App is designed to prioritize user privacy. As a basic principle, no data is processed by Blockster Labs Pvt Ltd Company when the app is used. All data is securely stored only on the user's end device, and Blockster Labs Pvt Ltd Company does not have access to this data. + +However, the app is associated with a digital mailbox service ("Mediation Agent") operated by Blockster Labs Pvt Ltd Company. The installation ID of the user is saved and processed for the purpose of the mailbox service. This allows incoming messages to be properly assigned to the respective user. The incoming messages are encrypted and sent to the mailbox service, which then forwards them to the user's app. The recipient of the message receives a dedicated code from the mailbox service, which is linked to the installation ID. + +The Responsible Entity cannot identify individual users or access the content of the messages since they are encrypted and decrypted only on the user's end device. Once the messages have been properly sent to the app, the mailbox service deletes them. The messages are held on the mailbox service until they can be delivered if the user's app isn't accessible. + +To enhance the user experience and improve app functionality, automated crash reports may be generated in the event of errors or application crashes. These reports may include information such as the cause of the crash, error reports, and additional data like the date and time of the crash, device model number, installed operating system version, language settings, and the user's country. + + +## 3. Legal Basis of the Processing +The processing of the installation ID is based on contractual purposes (Article 6(1)(b) of the General Data Protection Regulation - GDPR). The installation ID is automatically provided by Blockster Labs Pvt Ltd Company for the functioning of the mailbox service. Without processing the installation ID, Blockster Labs Pvt Ltd Company cannot assign or deliver incoming messages to individual users. The processing is necessary to fulfill the purpose of the contract, which involves the exchange of identity information. + +Error analysis and other analyses are carried out in the legitimate interests of Blockster Labs Pvt Ltd Company (Article 6(1)(f) GDPR). These analyses aim to ensure app functionality and improvement. No automated decision-making is involved in these processes. + +## 4. Recipients and Categories of Recipients +In general, data transfer to third parties (other than Blockster Labs Pvt Ltd Company) does not occur and is not planned. However, data transfer may occur in specific cases when legally obligated or with user consent. Such cases may include: +- Public authorities and institutions (e.g., tax authorities, prosecution authorities, family courts, land registry offices) if legally or officially required for any purposes that is the interest of justice and so called upon by the appropriate legal authorities using the due course of procedure laid down by current provisions of law. +- Auditors +- Service providers engaged in order-processing relationships + +## 5. Data Transfer to Third Countries +Data transfers to third countries do not occur. + +## 6. Storage Duration +Blockster Labs Pvt Ltd Company processes and stores personal data as long as it is required to fulfill contractual obligations and protect our rights. The Installation ID associated with your personal data is also deleted when you uninstall the app from your device. + +## 7. Information about data subjects' rights + +As an affected person, the User has the following rights regarding how their personal data is processed: + +Right of access (Article 15 GDPR) +Right to rectification (Article 16 GDPR) +Right to erasure (“right to be forgotten”) (Article 17 GDPR) +Right to restriction of processing (Article 18 GDPR) +Right to data portability (Article 20 GDPR) +Right to object (Article 21 GDPR) +Right to withdraw consent (Article 7 Para. 3 GDPR) +Right to lodge a complaint with a supervisory authority (Article 77 GDPR) +‍ +The User may reach out to us using the details listed in No. 1 to exercise these rights. + +7.1 Right of access (Article 15 GDPR) +The Right of Access means that the User has the right to request confirmation from the Responsible Entity as to whether their personal data is being processed. If the processing is taking place, the User also has the right to obtain information about their personal data and the details listed in Article 15 Para. 1 of the GDPR. + +7.2 Right to rectification (Article 16 GDPR) +The Right to Rectification means that the User has the right to request the correction of inaccurate personal data concerning them without undue delay. They also have the right to have incomplete personal data completed. + +7.3 Right to erasure ("right to be forgotten") (Article 17 GDPR) +The Right to Erasure means that the User fundamentally has the right to request the deletion of their personal data without undue delay. The Responsible Entity is obligated to delete the personal data promptly if one of the reasons listed in Article 17 Para. 1 of the GDPR applies. For example, this can be the case if the personal data is no longer necessary for the purposes for which it was collected or processed (Art. 17 Para. 1 specified in a) GDPR). + +If the Responsible Entity has made the personal data public and is required to erase it, they are also obligated to take reasonable measures, considering available technology and implementation costs, to inform other data processing responsible entities that are processing the personal data about the User's request for erasure. This includes deleting any links to, copies of, or replications of the personal data. + +However, the Right to Erasure ("right to be forgotten") does not apply in certain circumstances, as stated in Article 17 Para. 3 of the GDPR. For example, the right may not apply if the processing of personal data is necessary for compliance with a legal obligation or for the establishment, exercise, or defence of legal claims. + +7.4 Right to restriction of processing (Article 18 GDPR) +The Right to Restriction of Processing means that the User has the right to request the restriction of processing their personal data under certain conditions listed in Article 18 Para. 1 of the GDPR. For instance, if the User disputes the accuracy of their personal data, they can request the restriction of processing while the Responsible Entity verifies the accuracy of the data. + +7.5 Right to data portability (Article 20 GDPR) +The Right to Data Portability grants the User the right to receive their personal data, which they have provided to the Responsible Entity, in a structured, commonly used, and machine-readable format. The User also has the right to transmit this data to another responsible entity without hindrance, provided that the processing is based on consent or a contract and is carried out by automated means. + +Additionally, when exercising the right to data portability, the User has the right to have their personal data transmitted directly from the Responsible Entity to another responsible entity if technically feasible. + +7.6 Right to object (Article 21 GDPR) +As soon as possible after the initial contact, we let the User know about their right to object. The Right to Object applies in the following cases: + +7.6.1 Right to object on grounds relating to the data subject's specific circumstances +The User has the right to object at any time to the processing of their personal data based on their individual circumstances or for reasons of public interest. Profiling based on these laws is likewise subject to this right. Unless the Responsible Entity can show compelling legitimate grounds for the processing that outweigh the User's interests, rights, and freedoms, or if the processing is required for the establishment, exercise, or defence of legal claims, the Responsible Entity will stop processing personal data if the User objects due to their unique situation. + +7.6.2 Right to object to direct marketing +If the User's personal data is processed for direct marketing purposes, they have the right to object to the processing of their personal data for such marketing. This right also applies to profiling related to direct marketing. If the User objects to the processing of their personal data for direct marketing purposes, the Responsible Entity will cease processing their personal data for those purposes. + +7.7 Right to withdraw consent +If the processing of personal data is based on the User's consent, they have the right to withdraw their consent at any time. The withdrawal of consent does not affect the lawfulness of the processing based on consent before its withdrawal. Before providing consent, the User must be made aware of their right to do so. + +7.8 Right to complain to a supervisory authority +The User has the right to lodge a complaint with a supervisory authority if they believe that the processing of their personal data infringes the provisions of the GDPR. The relevant supervisory authority for the Responsible Entity is the data protection supervisory officer of Government of India. + +## 8. Version and changes to this data protection information +The most recent update to this data protection information was made in September 2023. This data protection information might need to be updated as a result of technical developments, adjustments to the app's functioning, and/or changing regulatory and governmental regulations. The app always has the most recent version of the data protection information. + + + diff --git a/src/pages/terms-and-conditions.md b/src/pages/terms-and-conditions.md new file mode 100644 index 000000000..1eff0195e --- /dev/null +++ b/src/pages/terms-and-conditions.md @@ -0,0 +1,124 @@ + +# TERMS AND CONDITIONS + +## 1. Validity of the General Terms and Conditions + +1.1 The usage of the "ADEYA" Self-sovereign Identity Edge Wallet (the "ADEYA App") is subject to these general terms and conditions (the "GTC"). The ADEYA App offers constant access to and viewing of the GTC. + +1.2 The terms of these GTC apply to the use of the ADEYA App and associated services as well as the provision of all services and advantages linked to the ADEYA App. + +1.3 Blockster Labs Pvt Ltd Company provides users with access to self-sovereign identification networks through the ADEYA App in accordance with the terms of these GTC. + +1.4 Other general terms and conditions, such as the user's, do not apply, despite the user's wants. Only if Blockster Labs Pvt Ltd Company expressly agrees to the user's general terms and conditions does the user presume their validity. + +1.5 The legality of the remaining sections of these GTC shall not be impacted if any provision is or becomes illegal by influx of law or due to passage of time. The user and Blockster Labs Pvt Ltd Company agree to discuss the grounds for the invalidity of the provision to come up with a replacement provision that closely resembles its goals. + +1.6 In the case of contractual discrepancy or variations, the same rule (Section 1.5) applies. + +## 2. The ADEYA App's Purpose and Object of Performance + +2.1 The ADEYA App is a state-of-the-art SSI-based mobile wallet application designed to securely store user credentials using cryptography. It allows users to safeguard their verifiable credentials and embrace the convenience of an identity wallet on their smartphones without compromising privacy. Blockster Labs Pvt Ltd Company develops the ADEYA App. + +2.2 The ADEYA App is intended for the digital identification and authentication of natural persons. Users can obtain and store identity information about themselves from other participants and share it if required. The identity information may include legitimation data, creditworthiness data, payment transaction data, registration data, and other text-based information. + +2.3 The ADEYA App connects to self-sovereign identity networks, enabling peer-to-peer connections with other participants. Users can exchange encrypted messages and receive other participants' identity information ("verifiable credentials"). They can also respond to identity requests from participants by sharing the relevant stored identity information. The ADEYA App is also connected to a digital mailbox service ("Mediation Agent") operated by Blockster Labs Pvt Ltd Company, ensuring secure message delivery. + + +## 3. The ADEYA App's Application and functionality + +3.1 Application and Launch: +When the user starts the "ADEYA" App on their mobile phone, they are prompted to secure access to the app by entering a six-digit PIN code. + +3.2 Tab Menu: +The "ADEYA" app's primary features are available through the tab navigation at the bottom of the app. There are two tabs on the tab menu: "Credentials" and "Home." The "Home" tab is the one that initially appears when the programme is opened. Identity information that is saved in the app is shown as separate card icons under the "Credentials" page. A card symbol can be touched to display extensive information about the issuer and the identifying attributes that have been recorded under "Info." Information regarding the use of the identification traits, including specifics of shared information, is displayed in the "Activities" section. The first card in the "Credentials" page that the user sees after receiving new identification information gives them the choice to accept or reject it. + +3.3 Scan Button: +The Scan button, which can be found in the bottom right of the app, gives users access to a QR Code scanner. With the use of this scanner, users may see and accept QR Code-based connection requests from other users. For this feature to work, the app needs access to the phone's camera. + +3.4. App Settings: +The "ADEYA" App has a number of customization choices that are available from the toolbar by selecting the gear icon. The configuration options include: + +- Language: Users have the option of changing the app's language. +- Utilise Biometrics: To increase security on their mobile phone, users can enable biometric authentication, such as fingerprint or face recognition. + +3.5. Functionality: +- Establish Connections: Users can connect with one another by exchanging QR codes with other users. Users can learn more about the contact request's sender by scanning the QR code. Requests for contact might be approved or denied. A peer-to-peer connection is made after accepting a contact request. Under the "Contacts" icon in the menu, any connections that have already been made with other participants are shown. When a specific connection is chosen, all identification data transmitted to or received from that participant is shown. + +- Sharing identification Information: Through already established peer-to-peer connections, participants can make identification queries to the user. The notification icon shows all identity requests. Existing identification attributes that are saved in the app are used to pre-fill the desired attributes. If suitable alternatives are available, users have the opportunity to manually edit this information. The "ADEYA" App's only job is to make it easier for participants to exchange information. An identification request can be refused if a user decides not to reply to it, in which case the asking participant won't receive any information. The submitted information is accessible either under the relevant card in the "Credentials" page when identification inquiries are successfully complied with. +- Support for numerous Hyperledger Indy networks: The "ADEYA" software now supports the mainnet of Sovrin, the BCovrin Ledger, as well as the Indicio network. + +You accept and agree to the functionality as mentioned above, as well as any other terms and conditions that the app developer may have stated, by using the "ADEYA" App. + +## 4. Application/Registration + +No login or registration with Blockster Labs Pvt Ltd Company is required to use the ADEYA App. + +## 5. The "ADEYA" App's availability and changes, as well as services related to it: + +5.1 After the "ADEYA" App has been installed, the user may use it and any connected Blockster Labs Pvt Ltd services in accordance with the terms and conditions set out in this agreement. + +5.2 The "ADEYA" App and the services and advantages connected to it are continuously made available by Blockster Labs Pvt Ltd. However, the "ADEYA" App and the services and advantages connected to it are not guaranteed, obligated to be available at all the time, or subject to responsibility by Blockster Labs Pvt Ltd Company. + +5.3 Additionally, Blockster Labs Pvt Ltd corporation is free to suspend or stop using the "ADEYA" App, as well as the features and services connected to it, at any time, regardless of outside factors beyond its control. Blockster Labs Pvt Ltd company has all discretion over the timing, scope, and length of any suspensions it imposes and whether to execute any necessary maintenance or repairs. These decisions are not subject to judicial scrutiny. + +5.4 The Blockster Labs Pvt Ltd company reserves the right to prohibit and/or ban the use of the "ADEYA" App at any time and to stop offering services associated with the "ADEYA" App. Such activities are not subject to justification and may be carried out at the sole discretion of Blockster Labs Pvt Ltd Company, including in a way that is not susceptible to judicial scrutiny. + +5.5 The "ADEYA" App may undergo modifications at any moment, at the sole discretion of the Blockster Labs Pvt Ltd, including but not limited to the type and extent of changes. The company is under no obligation to notify users of such changes. + +## 6. Consent to the use of data and information of the user + +6.1 By selecting the appropriate field during the installation of the "ADEYA" App, the user confirms his consent to the entirety of these GTC, and specifically to the following points: + +A user's identification data will initially only be saved on the "ADEYA" App and won't be shared with other parties until the user expressly agrees to it. +The user agrees that some personal data may be collected and processed by the "ADEYA" App in order for it to operate properly and provide the services it offers. This data may include the user's name, contact information, device information, and any other facts the user freely submits inside the app. +The user grants Blockster Labs Pvt Ltd permission to gather and analyse anonymous user data and statistics about the "ADEYA" App in order to enhance its functionality, performance, and user experience. This information will be handled in compliance with the relevant data protection laws and rules applicable to India which may be further amended from time to time. +The user is aware of and accepts that the "ADEYA" App secures and protects user credentials and data using cryptography and encryption techniques. The user understands that no security solution is perfect and that Blockster Labs Pvt Ltd cannot completely guarantee the protection of user data. The user is in charge of adopting the necessary safety measures to protect their device and access to the app. +The user acknowledges and accepts that when they access or use the "ADEYA" App, Blockster Labs Pvt Ltd may use cookies or other similar technologies to gather certain information. IP addresses, unique device identifiers, surfing habits, and other relevant data may be included in this information. +The user is aware of and consents to the processing of their personal data by Blockster Labs Pvt Ltd in compliance with all applicable data protection laws and regulations, including the General Data Protection Regulation (GDPR) and other pertinent privacy legislation. +By uninstalling the "ADEYA" App and ceasing to use it, the user has the right to withdraw their consent to the collection, processing, and storage of their personal information at any time. The user is aware, however, that such a withdrawal of permission may prevent them from using certain of the app's features or services. + +## 7. Intellectual Property Rights +7.1 The "ADEYA" App (including but not limited to its design, layout, graphics, text, and other content, as well as any software, algorithms, and underlying technologies), is protected by intellectual property rights and is owned or licenced by the Blockster Labs Pvt Ltd Company. The "ADEYA" App can be used by the user for personal and non-commercial reasons, but only with a limited, non-exclusive, and non-transferable right. +7.2 The user acknowledges that they will not, without Blockster Labs Pvt Ltd Company written approval, reproduce, edit, distribute, display, perform, publish, licence, create derivative works from, or sell any portion of the "ADEYA" App. +7.3 Any copyright, trademark, or other property rights notices included in or accompanying the "ADEYA" App may not be removed, altered, or obscured by the user. + +## 8. Limitation of Liability +8.1 Users acknowledge that they are using the "ADEYA" App at their own risk. Blockster Labs Pvt Ltd disclaims all responsibility for any harm that may result from using the "ADEYA" App, including but not limited to any direct, indirect, incidental, consequential, or punitive damages. + +8.2 Blockster Labs Pvt Ltd disclaims all responsibility for any delays, interruptions, errors, or omissions in the "ADEYA" App's operation or any component thereof, as well as for any failure to perform, whether brought on by divine intervention, technical issues, unauthorised access, theft, or other causes outside of Blockster Labs Pvt Ltd control. + +8.3 With regard to the accuracy, dependability, or fitness of the "ADEYA" App for any given purpose, the company makes no representations or guarantees of any kind, either stated or implied. On an "as-is" and "as available" basis, the app is made available. + +8.4 The user understands that the company Blockster Labs Pvt Ltd cannot ensure the continuous or error-free operation of the "ADEYA" App and that any dependence on its functionality is done at the user's own risk. + +8.5 Blockster Labs Pvt Ltd responsibility is restricted to the fullest extent permissible by law in places where the exclusion or limitation of liability for consequential or incidental damages is not permitted. + +## 9. Termination +9.1 Blockster Labs Pvt Ltd retains the right to deny or restrict a user's access to the "ADEYA" App at any time and for any reason, including but not limited to a violation of these general terms and conditions, without prior warning or responsibility. + +9.2 The user has the option to stop using the "ADEYA" App whenever they choose by uninstalling it and doing so. + +9.3 If the agreement is terminated, the user's right to use the "ADEYA" App will end immediately, and they must uninstall it as soon as possible and remove any copies of it from their devices. + +## 10. Governing Law and Dispute Resolution + +10.1 The Indian laws will be applicable to the present contract without regard to its rules on conflicts of laws and the same shall govern these general terms and conditions and be followed in interpreting them. + +10.2 In case of any dispute arising out of the said agreement of general terms and conditions the same shall be resolved as far as possible amicably but in case the same cannot be resolved amicably then the dispute shall be referred to a Sole Arbitrator appointed by Blockster Labs Pvt Ltd and the same shall be governed by provisions of Arbitration and Conciliation Act, 1996 and further amended from time to time. The seat and place of Arbitration shall be Pune and language of Arbitration proceedings shall be English. + +10.3 Further, the Courts of Pune shall have exclusive jurisdiction to decide the dispute which may so arise in case the Arbitration proceedings cannot decide the dispute between the parties to the present agreement. + +## 11. Severability +11.1 The remaining terms of these general terms and conditions shall remain in full force and effect in the event that any provision is judged to be invalid, unlawful, or unenforceable. + +## 12. Entire Agreement +12.1 These general terms and conditions replace all prior or contemporaneous oral or written agreements, communications, or understandings with respect to the subject matter hereof and represent the complete agreement between the user and Blockster Labs Pvt Ltd with regard to the use of the "ADEYA" App. + +## 13. Contact Information +13.1 Users can get in touch with Blockster Labs at info@blockster.global if they have any questions, issues, or suggestions about these GTC or the "ADEYA" App. + +01-SEP-2023 is the date on which these general terms and conditions take effect. + + + + diff --git a/src/styles/markdown.css b/src/styles/markdown.css new file mode 100644 index 000000000..172a9a036 --- /dev/null +++ b/src/styles/markdown.css @@ -0,0 +1,30 @@ +body { + background-color: #ffffff; + font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji", Inter var, ui-sans-serif, system-ui, -apple-system, system-ui, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji; + ; + margin-left: 10rem; + margin-right: 10rem; + text-align: justify; + margin-top: 2rem; + line-height: 2rem; +} + +h1 { + font-size: 25px; + color: black; + font-weight: 800; + margin-bottom: 1rem; + +} + +h2 { + margin-top: 2rem; + font-size: 20px; + color: black; + font-weight: 800; + margin-bottom: 1rem; +} + +button { + background-color: red !important; +} \ No newline at end of file From d080116b1e5ae01e9e0518865511a6a7fd7134fd Mon Sep 17 00:00:00 2001 From: pranalidhanavade Date: Wed, 13 Sep 2023 15:51:31 +0530 Subject: [PATCH 14/25] feat:added terms conditions and privacy policy pages Signed-off-by: pranalidhanavade --- src/app/FooterStacked.astro | 4 ++-- src/app/LayoutStacked.astro | 1 + src/components/CopyrightNotice.astro | 2 +- src/pages/privacy-policy.md | 7 ++++++- src/pages/terms-and-conditions.md | 4 +++- src/styles/markdown.css | 23 +++++++++++++---------- 6 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/app/FooterStacked.astro b/src/app/FooterStacked.astro index 6f08ba693..3ecd3a26c 100644 --- a/src/app/FooterStacked.astro +++ b/src/app/FooterStacked.astro @@ -7,7 +7,7 @@ import CopyrightNotice from '../components/CopyrightNotice.astro'; > -
      + diff --git a/src/app/LayoutStacked.astro b/src/app/LayoutStacked.astro index dbd173f1b..f47f40efa 100644 --- a/src/app/LayoutStacked.astro +++ b/src/app/LayoutStacked.astro @@ -2,6 +2,7 @@ import FooterStacked from './FooterStacked.astro'; import LayoutCommon from './LayoutCommon.astro'; import NavBarStacked from './NavBarStacked.astro'; +import '../styles/markdown.css' --- diff --git a/src/components/CopyrightNotice.astro b/src/components/CopyrightNotice.astro index 054afc462..5cc7b643e 100644 --- a/src/components/CopyrightNotice.astro +++ b/src/components/CopyrightNotice.astro @@ -1,6 +1,6 @@

      © 2019 - {new Date().getFullYear()} — CREDEBL Blockster Labs Private Limited | All rights reserved.

      diff --git a/src/pages/privacy-policy.md b/src/pages/privacy-policy.md index 91322d3f2..e9561e875 100644 --- a/src/pages/privacy-policy.md +++ b/src/pages/privacy-policy.md @@ -1,6 +1,10 @@ +--- +layout: ../app/LayoutStacked.astro +--- + # PRIVACY POLICY -Effective Date: 12/09/2023 +Effective Date: 1/09/2023 ## 1. Responsible Entity's Name and Contact Information Responsible for the processing of data on ADEYA Mobile Wallet App: Blockster Labs Pvt Ltd Company; A Company established under provisions of Companies Act 1956 of Government of India, and as amended further from time to time and having its registered office at 409, Navale ICON, Off. Mumbai-Bangalore Highway, Narhe, Pune, Maharashtra, 411021 India @@ -90,4 +94,5 @@ The User has the right to lodge a complaint with a supervisory authority if they The most recent update to this data protection information was made in September 2023. This data protection information might need to be updated as a result of technical developments, adjustments to the app's functioning, and/or changing regulatory and governmental regulations. The app always has the most recent version of the data protection information. + diff --git a/src/pages/terms-and-conditions.md b/src/pages/terms-and-conditions.md index 1eff0195e..2348082a1 100644 --- a/src/pages/terms-and-conditions.md +++ b/src/pages/terms-and-conditions.md @@ -1,4 +1,6 @@ - +--- +layout: ../app/LayoutStacked.astro +--- # TERMS AND CONDITIONS ## 1. Validity of the General Terms and Conditions diff --git a/src/styles/markdown.css b/src/styles/markdown.css index 172a9a036..fc472a1a6 100644 --- a/src/styles/markdown.css +++ b/src/styles/markdown.css @@ -1,15 +1,15 @@ body { background-color: #ffffff; - font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji", Inter var, ui-sans-serif, system-ui, -apple-system, system-ui, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji; + font-family: ui-sans-serif, system-ui, "Segoe UI", "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji", ui-sans-serif, system-ui, system-ui, Helvetica ,Arial, sans-serif,Color, Symbol; ; - margin-left: 10rem; - margin-right: 10rem; + /* margin-left: 10rem; + margin-right: 10rem; */ text-align: justify; - margin-top: 2rem; + /* margin-top: 2rem; */ line-height: 2rem; } -h1 { + h1{ font-size: 25px; color: black; font-weight: 800; @@ -17,14 +17,17 @@ h1 { } -h2 { + h2 { margin-top: 2rem; font-size: 20px; color: black; font-weight: 800; margin-bottom: 1rem; -} +} + p{ + margin-bottom: 1rem; + } -button { - background-color: red !important; -} \ No newline at end of file + .markdown-container ul{ + list-style: disc; + } \ No newline at end of file From 336a157013c8c0eca0eb3dcd51b6f7a4a1af3514 Mon Sep 17 00:00:00 2001 From: pranalidhanavade Date: Wed, 13 Sep 2023 16:14:55 +0530 Subject: [PATCH 15/25] feat:added terms conditions and privacy policy pages Signed-off-by: pranalidhanavade --- src/styles/markdown.css | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/styles/markdown.css b/src/styles/markdown.css index fc472a1a6..77a5de0df 100644 --- a/src/styles/markdown.css +++ b/src/styles/markdown.css @@ -2,10 +2,8 @@ body { background-color: #ffffff; font-family: ui-sans-serif, system-ui, "Segoe UI", "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji", ui-sans-serif, system-ui, system-ui, Helvetica ,Arial, sans-serif,Color, Symbol; ; - /* margin-left: 10rem; - margin-right: 10rem; */ + text-align: justify; - /* margin-top: 2rem; */ line-height: 2rem; } From c94c979a56c6292cf484267bff9b5a943dc95c8e Mon Sep 17 00:00:00 2001 From: MoulikaKulkarni Date: Wed, 13 Sep 2023 17:08:59 +0530 Subject: [PATCH 16/25] fix: date-tooltip Signed-off-by: MoulikaKulkarni --- src/components/Tooltip/index.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/Tooltip/index.tsx b/src/components/Tooltip/index.tsx index ecb244868..28092d8ef 100644 --- a/src/components/Tooltip/index.tsx +++ b/src/components/Tooltip/index.tsx @@ -2,16 +2,20 @@ import { Tooltip } from 'flowbite-react'; import moment from 'moment'; import { dateConversion } from '../../utils/DateConversion'; import type { ChildrenType } from 'react-tooltip'; +import { useEffect } from 'react'; interface DateProps { - date?: Date + date: string id?: string children?: any } const DateTooltip = ({date, children}: DateProps) => { - const formattedDate = date ? moment(date).format("MMM DD, YYYY, h:mm A z") : ''; + + const updatedDate = new Date(date); + const formattedDate = date ? moment(updatedDate).format("MMM DD, YYYY, h:mm A z") : ''; + return ( Date: Wed, 13 Sep 2023 17:17:49 +0530 Subject: [PATCH 17/25] fix: date-tooltip Signed-off-by: MoulikaKulkarni --- src/components/Tooltip/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/Tooltip/index.tsx b/src/components/Tooltip/index.tsx index 28092d8ef..912a20ba3 100644 --- a/src/components/Tooltip/index.tsx +++ b/src/components/Tooltip/index.tsx @@ -2,7 +2,6 @@ import { Tooltip } from 'flowbite-react'; import moment from 'moment'; import { dateConversion } from '../../utils/DateConversion'; import type { ChildrenType } from 'react-tooltip'; -import { useEffect } from 'react'; interface DateProps { date: string From 1e8f7dfdd30dc8522da942d44735bfe7ba5667ce Mon Sep 17 00:00:00 2001 From: MoulikaKulkarni Date: Wed, 13 Sep 2023 17:42:18 +0530 Subject: [PATCH 18/25] fix: date-tooltip Signed-off-by: MoulikaKulkarni --- package-lock.json | 180 --------------------- src/commonComponents/DeviceDetailsCard.tsx | 4 +- 2 files changed, 1 insertion(+), 183 deletions(-) diff --git a/package-lock.json b/package-lock.json index 61136c553..56b58d11b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1353,15 +1353,6 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, - "node_modules/@types/jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-drE6uz7QBKq1fYqqoFKTDRdFCPHd5TCub75BM+D+cMx7NU9hUz7SESLfC2fSCXVFMO5Yj8sOWHuGqPgjc+fz0Q==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/mdast": { "version": "3.0.12", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.12.tgz", @@ -2384,11 +2375,6 @@ "ieee754": "^1.2.1" } }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" - }, "node_modules/bufferutil": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.7.tgz", @@ -3105,14 +3091,6 @@ "resolved": "https://registry.npmjs.org/easy-bem/-/easy-bem-1.1.1.tgz", "integrity": "sha512-GJRqdiy2h+EXy6a8E6R+ubmqUM08BK0FWNq41k24fup6045biQ8NXxoXimiwegMQvFFV3t1emADdGNL1TlS61A==" }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, "node_modules/electron-to-chromium": { "version": "1.4.484", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.484.tgz", @@ -5427,46 +5405,6 @@ "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.3.1.tgz", "integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==" }, - "node_modules/jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", - "dependencies": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=12", - "npm": ">=6" - } - }, - "node_modules/jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -5580,46 +5518,16 @@ "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==" }, - "node_modules/lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" - }, - "node_modules/lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" - }, - "node_modules/lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" - }, - "node_modules/lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" - }, "node_modules/lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" }, - "node_modules/lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" - }, "node_modules/log-symbols": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", @@ -13383,15 +13291,6 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, - "@types/jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-drE6uz7QBKq1fYqqoFKTDRdFCPHd5TCub75BM+D+cMx7NU9hUz7SESLfC2fSCXVFMO5Yj8sOWHuGqPgjc+fz0Q==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, "@types/mdast": { "version": "3.0.12", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.12.tgz", @@ -14120,11 +14019,6 @@ "ieee754": "^1.2.1" } }, - "buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" - }, "bufferutil": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.7.tgz", @@ -14597,14 +14491,6 @@ "resolved": "https://registry.npmjs.org/easy-bem/-/easy-bem-1.1.1.tgz", "integrity": "sha512-GJRqdiy2h+EXy6a8E6R+ubmqUM08BK0FWNq41k24fup6045biQ8NXxoXimiwegMQvFFV3t1emADdGNL1TlS61A==" }, - "ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, "electron-to-chromium": { "version": "1.4.484", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.484.tgz", @@ -16250,42 +16136,6 @@ "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.3.1.tgz", "integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==" }, - "jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", - "requires": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^7.5.4" - } - }, - "jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "requires": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -16374,46 +16224,16 @@ "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==" }, - "lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" - }, - "lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" - }, - "lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" - }, - "lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" - }, "lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" }, - "lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" - }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, - "lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" - }, "log-symbols": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", diff --git a/src/commonComponents/DeviceDetailsCard.tsx b/src/commonComponents/DeviceDetailsCard.tsx index afe84ccde..738cff853 100644 --- a/src/commonComponents/DeviceDetailsCard.tsx +++ b/src/commonComponents/DeviceDetailsCard.tsx @@ -98,9 +98,7 @@ const DeviceDetails = (props: { deviceFriendlyName: string, createDateTime: stri

    - - {dateConversion(new Date(props.createDateTime).toLocaleDateString('en-GB'))} -

    + {dateConversion(props?.createDateTime)}

    {props.credentialID}

    From 2da65f128ebb1cbf79ad72a441c0a7d78a5f5e36 Mon Sep 17 00:00:00 2001 From: MoulikaKulkarni Date: Wed, 13 Sep 2023 17:51:30 +0530 Subject: [PATCH 19/25] fix: date-tooltip Signed-off-by: MoulikaKulkarni --- src/commonComponents/DeviceDetailsCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commonComponents/DeviceDetailsCard.tsx b/src/commonComponents/DeviceDetailsCard.tsx index 738cff853..7999bd8ed 100644 --- a/src/commonComponents/DeviceDetailsCard.tsx +++ b/src/commonComponents/DeviceDetailsCard.tsx @@ -58,7 +58,7 @@ const DeviceDetails = (props: { deviceFriendlyName: string, createDateTime: stri } setTimeout(() => { props.refreshList() - }, 4000); + }, 6000); } From 4b8bad6ecc969186d917182209a615e3e61904ac Mon Sep 17 00:00:00 2001 From: Nishad Shirsat <103021375+nishad-ayanworks@users.noreply.github.com> Date: Thu, 14 Sep 2023 11:55:31 +0530 Subject: [PATCH 20/25] refactor: user role management for schema, cred-def, issuence and verification feature (#255) * worked on the user role management for schema and cred-def feature Signed-off-by: @nishad.shirsat * removed unnecessary code from files Signed-off-by: @nishad.shirsat * Worked on the user role manage for issuance Signed-off-by: @nishad.shirsat * Worked on the user role manage for verification Signed-off-by: @nishad.shirsat * Modified if condition in role view button Signed-off-by: @nishad.shirsat --------- Signed-off-by: @nishad.shirsat --- .../CredentialDefinitionCard.tsx | 28 ++++++++-- src/components/Issuance/IssuedCrdentials.tsx | 51 ++++++++----------- .../Resources/Schema/SchemasList.tsx | 50 +++++++++--------- .../Resources/Schema/ViewSchema.tsx | 47 +++++++++++++---- src/components/RoleViewButton/index.tsx | 18 ++++++- .../VerificationCredentialList.tsx | 48 ++++++++--------- src/utils/enums/features.ts | 5 +- 7 files changed, 152 insertions(+), 95 deletions(-) diff --git a/src/commonComponents/CredentialDefinitionCard.tsx b/src/commonComponents/CredentialDefinitionCard.tsx index d99d9f22a..e4514c174 100644 --- a/src/commonComponents/CredentialDefinitionCard.tsx +++ b/src/commonComponents/CredentialDefinitionCard.tsx @@ -1,17 +1,33 @@ import { Button, Card } from 'flowbite-react'; -const CredDeffCard = (props: { credDeffName: string, credentialDefinitionId: string, schemaId: string, revocable: boolean, onClickCallback: (schemaId: string, credentialDefinitionId: string) => void; }) => { - return ( - { +import { Roles } from '../utils/enums/roles'; + +const CredDeffCard = (props: { credDeffName: string, userRoles?:string[], credentialDefinitionId: string, schemaId: string, revocable: boolean, onClickCallback: (schemaId: string, credentialDefinitionId: string) => void; }) => { + + const redirectToIssuance = () => { + if (props?.userRoles?.includes(Roles.OWNER) + || props?.userRoles?.includes(Roles.ADMIN) + || props?.userRoles?.includes(Roles.ISSUER)) { props.onClickCallback(props.schemaId, props.credentialDefinitionId) - }} className=' cursor-pointer overflow-hidden overflow-ellipsis' style={{ maxHeight: '100%', maxWidth: '100%', overflow: 'auto' }}> + + } + } + + return ( +
    {/* This will take up 2/3 of the available width on larger screens */}
    {props.credDeffName}
    -
    + { + props.userRoles + && (props.userRoles.includes(Roles.OWNER) + || props.userRoles.includes(Roles.ADMIN) + || props.userRoles.includes(Roles.ISSUER) + ) + &&
    + } +

    diff --git a/src/components/Issuance/IssuedCrdentials.tsx b/src/components/Issuance/IssuedCrdentials.tsx index 4c63f633c..b6676bb03 100644 --- a/src/components/Issuance/IssuedCrdentials.tsx +++ b/src/components/Issuance/IssuedCrdentials.tsx @@ -1,7 +1,7 @@ 'use client'; import { ChangeEvent, useEffect, useState } from 'react'; -import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; +import { IssueCredential, IssueCredentialUserText } from '../../common/enums'; import { AlertComponent } from '../AlertComponent'; import type { AxiosResponse } from 'axios'; @@ -9,15 +9,17 @@ import BreadCrumbs from '../BreadCrumbs'; import { Button } from 'flowbite-react'; import CustomSpinner from '../CustomSpinner'; import DataTable from '../../commonComponents/datatable'; +import DateTooltip from '../Tooltip'; import { EmptyListMessage } from '../EmptyListComponent'; -import { IssueCredential, IssueCredentialUserText } from '../../common/enums'; +import { Features } from '../../utils/enums/features'; import React from 'react'; +import RoleViewButton from '../RoleViewButton'; import SearchInput from '../SearchInput'; import type { TableData } from '../../commonComponents/datatable/interface'; +import { apiStatusCodes } from '../../config/CommonConstant'; import { dateConversion } from '../../utils/DateConversion'; import { getIssuedCredentials } from '../../api/issuance'; import { pathRoutes } from '../../config/pathRoutes'; -import DateTooltip from '../Tooltip'; interface IssuedCredential { metadata: { [x: string]: { schemaId: string } }; @@ -147,32 +149,23 @@ const CredentialList = () => {

    -
    -
    - -
    +
    +
    + + + + + + } + onClickEvent={schemeSelection} + /> + +
    void; }) => { const [schemaList, setSchemaList] = useState([]) @@ -136,8 +139,8 @@ const SchemaList = (props: { schemaSelectionCallback: (schemaId: string, schemaD - {options.map((opt) => (
    -
    - + />
    @@ -182,8 +186,8 @@ const SchemaList = (props: { schemaSelectionCallback: (schemaId: string, schemaD } {loading ? (
    - - + +
    ) : schemaList && schemaList.length > 0 ? ( @@ -199,7 +203,7 @@ const SchemaList = (props: { schemaSelectionCallback: (schemaId: string, schemaD
    - {schemaList.length> 0 &&( 0 && ( { setSchemaListAPIParameter(prevState => ({ @@ -213,8 +217,8 @@ const SchemaList = (props: { schemaSelectionCallback: (schemaId: string, schemaD
    ) : ( + buttonContent={'Create'} + svgComponent={ } onClick={() => { diff --git a/src/components/Resources/Schema/ViewSchema.tsx b/src/components/Resources/Schema/ViewSchema.tsx index 3f6851d21..495fd22ad 100644 --- a/src/components/Resources/Schema/ViewSchema.tsx +++ b/src/components/Resources/Schema/ViewSchema.tsx @@ -1,20 +1,23 @@ +import * as yup from 'yup'; import { Alert, Button, Card, Label, Pagination } from 'flowbite-react'; import { Field, Form, Formik } from 'formik'; -import { useEffect, useState } from 'react'; -import BreadCrumbs from '../../BreadCrumbs'; -import * as yup from 'yup'; import { apiStatusCodes, storageKeys } from '../../../config/CommonConstant'; -import CredDeffCard from '../../../commonComponents/CredentialDefinitionCard'; import { createCredentialDefinition, getCredDeffById, getSchemaById } from '../../../api/Schema'; +import { getFromLocalStorage, setToLocalStorage } from '../../../api/Auth'; +import { useEffect, useState } from 'react'; + import type { AxiosResponse } from 'axios'; +import BreadCrumbs from '../../BreadCrumbs'; +import CredDeffCard from '../../../commonComponents/CredentialDefinitionCard'; import type { CredDeffFieldNameType } from './interfaces'; -import { getFromLocalStorage, setToLocalStorage } from '../../../api/Auth'; +import CustomSpinner from '../../CustomSpinner'; import { EmptyListMessage } from '../../EmptyListComponent'; +import React from 'react'; +import { Roles } from '../../../utils/enums/roles'; +import SchemaCard from '../../../commonComponents/SchemaCard'; import { nanoid } from 'nanoid'; import { pathRoutes } from '../../../config/pathRoutes'; -import CustomSpinner from '../../CustomSpinner'; -import React from 'react'; interface Values { tagName: string; @@ -51,6 +54,9 @@ const ViewSchemas = () => { const [orgId, setOrgId] = useState(0) const [credDefAuto, setCredDefAuto] = useState('') + const [userRoles, setUserRoles] = useState([]) + + const getSchemaDetails = async (id: string, organizationId: number) => { try { setLoading(true); @@ -109,6 +115,16 @@ const ViewSchemas = () => { fetchData(); }, []); + const getUserRoles = async () => { + const orgRoles = await getFromLocalStorage(storageKeys.ORG_ROLES) + const roles = orgRoles.split(',') + setUserRoles(roles) + } + + useEffect(() => { + getUserRoles() + },[]) + const submit = async (values: Values) => { setCreateLoader(true) @@ -241,7 +257,11 @@ const ViewSchemas = () => {
    )} - + { + (userRoles.includes(Roles.OWNER) + || userRoles.includes(Roles.ADMIN)) + + &&
    Create Credential Definition @@ -364,6 +384,8 @@ const ViewSchemas = () => {
    + + }
    <> @@ -392,7 +414,14 @@ const ViewSchemas = () => { {credDeffList && credDeffList.length > 0 && credDeffList.map((element, key) => (
    - +
    )) } diff --git a/src/components/RoleViewButton/index.tsx b/src/components/RoleViewButton/index.tsx index 4ed94b180..1c2f0616b 100644 --- a/src/components/RoleViewButton/index.tsx +++ b/src/components/RoleViewButton/index.tsx @@ -32,7 +32,23 @@ const RoleViewButton = ({ buttonTitle, svgComponent, onClickEvent, feature }: Ro if(feature === Features.CRETAE_ORG){ return true - } else if (userRoles.includes(Roles.OWNER) || userRoles.includes(Roles.ADMIN)) { + } else if (feature === Features.ISSUENCE) { + if (userRoles.includes(Roles.OWNER) + || userRoles.includes(Roles.ADMIN) + || userRoles.includes(Roles.ISSUER) + ) { + return true + } + return false + }else if (feature === Features.VERIFICATION) { + if (userRoles.includes(Roles.OWNER) + || userRoles.includes(Roles.ADMIN) + || userRoles.includes(Roles.VERIFIER) + ) { + return true + } + return false + }else if (userRoles.includes(Roles.OWNER) || userRoles.includes(Roles.ADMIN)) { return true } else { return false diff --git a/src/components/Verification/VerificationCredentialList.tsx b/src/components/Verification/VerificationCredentialList.tsx index 26dcf9d66..7be364f3a 100644 --- a/src/components/Verification/VerificationCredentialList.tsx +++ b/src/components/Verification/VerificationCredentialList.tsx @@ -1,7 +1,11 @@ 'use client'; -import { Alert, Button, Pagination } from 'flowbite-react'; +import { Alert, Button } from 'flowbite-react'; import { ChangeEvent, useEffect, useState } from 'react'; +import { + ProofRequestState, + ProofRequestStateUserText, +} from '../../common/enums'; import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; import { getProofAttributes, @@ -12,22 +16,20 @@ import { import { AlertComponent } from '../AlertComponent'; import type { AxiosResponse } from 'axios'; import BreadCrumbs from '../BreadCrumbs'; +import CustomSpinner from '../CustomSpinner'; import DataTable from '../../commonComponents/datatable'; +import DateTooltip from '../Tooltip'; import { EmptyListMessage } from '../EmptyListComponent'; +import { Features } from '../../utils/enums/features'; import ProofRequest from './ProofRequestPopup'; -import { - ProofRequestState, - ProofRequestStateUserText, -} from '../../common/enums'; import React from 'react'; import type { RequestProof } from './interface'; +import RoleViewButton from '../RoleViewButton'; import SearchInput from '../SearchInput'; import type { TableData } from '../../commonComponents/datatable/interface'; import { dateConversion } from '../../utils/DateConversion'; import { pathRoutes } from '../../config/pathRoutes'; import { removeFromLocalStorage } from '../../api/Auth'; -import CustomSpinner from '../CustomSpinner'; -import DateTooltip from '../Tooltip'; const VerificationCredentialList = () => { const [loading, setLoading] = useState(true); @@ -273,27 +275,19 @@ const VerificationCredentialList = () => {

    -
    -
    - + } + onClickEvent={schemeSelection} + />
    { (proofReqSuccess || errMsg) && ( diff --git a/src/utils/enums/features.ts b/src/utils/enums/features.ts index bd1fe8aee..cc574a15e 100644 --- a/src/utils/enums/features.ts +++ b/src/utils/enums/features.ts @@ -2,5 +2,8 @@ export enum Features { SEND_INVITATION = 'send_invitations', - CRETAE_ORG = 'create_org' + CRETAE_ORG = 'create_org', + CRETAE_SCHEMA = 'create_schema', + ISSUENCE = 'issuence', + VERIFICATION = 'verification' } \ No newline at end of file From d34a6a77eb7922c86d6c620f27cfecd3c3d5783c Mon Sep 17 00:00:00 2001 From: pranalidhanavade Date: Thu, 14 Sep 2023 20:19:21 +0530 Subject: [PATCH 21/25] fix:alignment fixes on editorganizationmodal page and verification page Signed-off-by: pranalidhanavade --- src/components/Resources/Schema/Create.tsx | 4 ++-- src/components/Verification/Verification.tsx | 9 ++++++++- src/components/organization/EditOrgdetailsModal.tsx | 2 +- src/config/pathRoutes.ts | 2 +- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/components/Resources/Schema/Create.tsx b/src/components/Resources/Schema/Create.tsx index 9283b109d..5660dbc33 100644 --- a/src/components/Resources/Schema/Create.tsx +++ b/src/components/Resources/Schema/Create.tsx @@ -191,8 +191,8 @@ const CreateSchema = () => { return ( <> -
    - Attributes * +
    + Attributes *
    {attribute.map((element: any, index: number) => ( diff --git a/src/components/Verification/Verification.tsx b/src/components/Verification/Verification.tsx index ddd9919e8..0ac50352b 100644 --- a/src/components/Verification/Verification.tsx +++ b/src/components/Verification/Verification.tsx @@ -10,6 +10,7 @@ import DataTable from "../../commonComponents/datatable"; import type { TableData } from "../../commonComponents/datatable/interface"; import { verifyCredential } from "../../api/verification"; import { pathRoutes } from "../../config/pathRoutes"; +import CustomSpinner from "../CustomSpinner"; interface SchemaDetails { schemaName: string, @@ -41,7 +42,7 @@ const VerificationCred = () => { const [schemaDetails, setSchemaDetails] = useState({ schemaName: '', version: '', schemaId: '', credDefId: '' }) - const [loading, setLoading] = useState(false) + const [loading, setLoading] = useState(true) const [schemaAttributes, setSchemaAttributes] = useState([]); const [selectedUsersData, setSelectedUsersData] = useState>([]); const [requestLoader, setRequestLoader] = useState(false) @@ -220,6 +221,11 @@ const VerificationCred = () => { Verification
    + {loading ? +
    + +
    + :
    @@ -242,6 +248,7 @@ const VerificationCred = () => {

    + } { (proofReqSuccess || errMsg) &&
    diff --git a/src/components/organization/EditOrgdetailsModal.tsx b/src/components/organization/EditOrgdetailsModal.tsx index 57d742a48..e7312d0cc 100644 --- a/src/components/organization/EditOrgdetailsModal.tsx +++ b/src/components/organization/EditOrgdetailsModal.tsx @@ -176,7 +176,7 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps)=> { props?.onEditSucess() } props.setOpenModal(false) - + window.location.reload(); } else { setErrMsg(resUpdateOrg as string) } diff --git a/src/config/pathRoutes.ts b/src/config/pathRoutes.ts index b6a0dca75..8fdcacada 100644 --- a/src/config/pathRoutes.ts +++ b/src/config/pathRoutes.ts @@ -59,7 +59,7 @@ export const pathRoutes = { schemas:'/organizations/schemas' }, verification:{ - credDef:'/organizations/credentials-issued/schemas/cred-defs', + credDef:'/organizations/verification/schemas/cred-defs', schemas:'/organizations/verification/schemas', verification:'/organizations/verification/schemas/cred-defs/connections', }, From d4214d925f2417acedd665b0ea88df12f41036e7 Mon Sep 17 00:00:00 2001 From: MoulikaKulkarni Date: Fri, 15 Sep 2023 16:17:08 +0530 Subject: [PATCH 22/25] feat: public view Signed-off-by: MoulikaKulkarni --- src/components/organization/Dashboard.tsx | 7 +++++++ src/components/organization/interfaces/index.ts | 1 + 2 files changed, 8 insertions(+) diff --git a/src/components/organization/Dashboard.tsx b/src/components/organization/Dashboard.tsx index 3505dbf13..51e241501 100644 --- a/src/components/organization/Dashboard.tsx +++ b/src/components/organization/Dashboard.tsx @@ -157,6 +157,13 @@ const Dashboard = () => { {orgData?.description}

    +

    + Public view : + + {orgData?.publicProfile ? " Public" : "Private"} + +

    +
    { diff --git a/src/components/organization/interfaces/index.ts b/src/components/organization/interfaces/index.ts index 0e1cfb184..3dd8dd250 100644 --- a/src/components/organization/interfaces/index.ts +++ b/src/components/organization/interfaces/index.ts @@ -19,6 +19,7 @@ export interface Organisation { roles: string[] userOrgRoles: UserOrgRole[] org_agents: OrgAgent[] + publicProfile: boolean } export interface OrgRole { From ae287aaf51e4e22fb84f2e53401ae1f6a39e3c1f Mon Sep 17 00:00:00 2001 From: MoulikaKulkarni Date: Fri, 15 Sep 2023 18:30:53 +0530 Subject: [PATCH 23/25] fix: view schema responsiveness Signed-off-by: MoulikaKulkarni --- src/components/Resources/Schema/ViewSchema.tsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/components/Resources/Schema/ViewSchema.tsx b/src/components/Resources/Schema/ViewSchema.tsx index 495fd22ad..669857437 100644 --- a/src/components/Resources/Schema/ViewSchema.tsx +++ b/src/components/Resources/Schema/ViewSchema.tsx @@ -186,19 +186,20 @@ const ViewSchemas = () => { className="p-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800" >
    - + {loading ? (
    ) : ( -
    -
    +
    +
    +
    Schema Details
    -
    - +
    { (userRoles.includes(Roles.OWNER) || userRoles.includes(Roles.ADMIN)) - && + &&
    Create Credential Definition From 588491bb92e95934e918ff85b22a4159ed55dad7 Mon Sep 17 00:00:00 2001 From: tipusinghaw Date: Mon, 18 Sep 2023 12:34:39 +0530 Subject: [PATCH 24/25] fix: passkey add device loader issue Signed-off-by: tipusinghaw --- src/components/Authentication/SignInUserPasskey.tsx | 1 + src/components/Profile/AddPasskey.tsx | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/Authentication/SignInUserPasskey.tsx b/src/components/Authentication/SignInUserPasskey.tsx index 94e1921fb..37286be51 100644 --- a/src/components/Authentication/SignInUserPasskey.tsx +++ b/src/components/Authentication/SignInUserPasskey.tsx @@ -95,6 +95,7 @@ const SignInUserPasskey = (signInUserProps: signInUserProps) => { ...attResp, challangeId }; + setFidoLoader(false) const verificationResp = await verifyAuthenticationMethod(verifyAuthenticationObj, { userName: email }); const { data } = verificationResp as AxiosResponse if (data?.data.verified) { diff --git a/src/components/Profile/AddPasskey.tsx b/src/components/Profile/AddPasskey.tsx index 25a7ed872..5087abb3c 100644 --- a/src/components/Profile/AddPasskey.tsx +++ b/src/components/Profile/AddPasskey.tsx @@ -140,8 +140,10 @@ const AddPasskey = () => { const { data } = deviceDetailsResp as AxiosResponse if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { setAddSuccess("Device added successfully") - userDeviceDetails() - window.location.href = `${apiRoutes.auth.profile}` + setTimeout(() => { + userDeviceDetails() + window.location.href = `${apiRoutes.auth.profile}` + }, 4000) } else { setAddFailur(deviceDetailsResp as string) } From 68d9b6602c25764472f1e9c4f546688b21ff085e Mon Sep 17 00:00:00 2001 From: tipusinghaw Date: Mon, 18 Sep 2023 14:58:24 +0530 Subject: [PATCH 25/25] fix: add device alert message issue Signed-off-by: tipusinghaw --- src/components/Profile/AddPasskey.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/Profile/AddPasskey.tsx b/src/components/Profile/AddPasskey.tsx index 5087abb3c..ffa9c9de8 100644 --- a/src/components/Profile/AddPasskey.tsx +++ b/src/components/Profile/AddPasskey.tsx @@ -141,7 +141,8 @@ const AddPasskey = () => { if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { setAddSuccess("Device added successfully") setTimeout(() => { - userDeviceDetails() + // userDeviceDetails() // required + setAddSuccess('') window.location.href = `${apiRoutes.auth.profile}` }, 4000) } else {