-
-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(passport): account mask address #2743
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,9 @@ import { Form, useTransition } from '@remix-run/react' | |
|
||
import { Button, Text } from '@proofzero/design-system' | ||
import { FaChevronDown, FaChevronRight } from 'react-icons/fa' | ||
import { TbShield } from 'react-icons/tb' | ||
|
||
import { EmailAccountType } from '@proofzero/types/account' | ||
|
||
import MultiAvatar from '@proofzero/design-system/src/molecules/avatar/MultiAvatar' | ||
import UserPill from '@proofzero/design-system/src/atoms/pills/UserPill' | ||
|
@@ -10,12 +13,14 @@ import { Disclosure } from '@headlessui/react' | |
import { useState } from 'react' | ||
|
||
import passportLogoURL from '~/assets/PassportIcon.svg' | ||
import { HiOutlineMail } from 'react-icons/hi' | ||
import { TbCrown } from 'react-icons/tb' | ||
import { Modal } from '@proofzero/design-system/src/molecules/modal/Modal' | ||
import warningImg from '~/assets/warning.svg' | ||
import InputText from '~/components/inputs/InputText' | ||
import { startCase } from 'lodash' | ||
import { HiOutlineExternalLink, HiOutlineX } from 'react-icons/hi' | ||
import { EmailMaskedPill } from '@proofzero/design-system/src/atoms/pills/EmailMaskPill' | ||
|
||
export const ConfirmRevocationModal = ({ | ||
title, | ||
|
@@ -129,11 +134,16 @@ const AccountExpandedView = ({ | |
<div className="flex flex-col gap-2 p-2.5 bg-white rounded-lg"> | ||
{connectedAccounts && ( | ||
<section className="flex flex-row gap-2 items-center"> | ||
<img src={account.icon} className="rounded-full w-5 h-5" /> | ||
{account.type === EmailAccountType.Mask ? ( | ||
<TbShield /> | ||
) : ( | ||
<img src={account.icon} className="rounded-full w-5 h-5" /> | ||
)} | ||
|
||
<Text size="sm" weight="semibold" className="text-gray-800 truncate"> | ||
{account.address} | ||
</Text> | ||
{account.type === EmailAccountType.Mask ? <EmailMaskedPill /> : null} | ||
</section> | ||
)} | ||
|
||
|
@@ -171,12 +181,14 @@ export const ClaimsMobileView = ({ scopes }: { scopes: any[] }) => { | |
const RowView = ({ | ||
account, | ||
appAskedFor, | ||
masked = false, | ||
whatsBeingShared, | ||
sourceOfData, | ||
sourceOfDataIcon, | ||
dropdown = true, | ||
}: { | ||
appAskedFor: string | ||
masked: boolean | ||
sourceOfData: string | ||
sourceOfDataIcon: JSX.Element | ||
dropdown?: boolean | ||
|
@@ -203,6 +215,7 @@ export const ClaimsMobileView = ({ scopes }: { scopes: any[] }) => { | |
> | ||
{appAskedFor} | ||
</Text> | ||
{masked && <EmailMaskedPill />} | ||
{whatsBeingShared && ( | ||
<Text | ||
size="sm" | ||
|
@@ -229,6 +242,7 @@ export const ClaimsMobileView = ({ scopes }: { scopes: any[] }) => { | |
> | ||
{appAskedFor} | ||
</Text> | ||
{masked && <EmailMaskedPill />} | ||
{whatsBeingShared && ( | ||
<Text | ||
size="sm" | ||
|
@@ -373,6 +387,7 @@ export const ClaimsMobileView = ({ scopes }: { scopes: any[] }) => { | |
size={20} | ||
text={scWallets ? a.title! : a.address} | ||
avatarURL={a.icon} | ||
masked={a.type === EmailAccountType.Mask} | ||
onClick={() => setSelectedAccount(a)} | ||
className={'pointer-events-auto'} | ||
/> | ||
|
@@ -421,11 +436,10 @@ export const ClaimsMobileView = ({ scopes }: { scopes: any[] }) => { | |
<RowView | ||
key={i} | ||
appAskedFor="Email" | ||
whatsBeingShared={scope.account} | ||
masked={scope.masked} | ||
whatsBeingShared={scope.address} | ||
sourceOfData={scope.account} | ||
sourceOfDataIcon={ | ||
<img src={scope.icon} className="w-5 h-5 rounded-full" /> | ||
} | ||
sourceOfDataIcon={<HiOutlineMail className="w-5 h-5" />} | ||
dropdown={false} | ||
/> | ||
) | ||
|
@@ -491,12 +505,14 @@ export const ClaimsWideView = ({ scopes }: { scopes: any[] }) => { | |
const RowView = ({ | ||
account, | ||
appAskedFor, | ||
masked = false, | ||
whatsBeingShared, | ||
sourceOfData, | ||
sourceOfDataIcon, | ||
dropdown = true, | ||
}: { | ||
appAskedFor: string | ||
masked: boolean | ||
sourceOfData: string | ||
sourceOfDataIcon: JSX.Element | ||
dropdown?: boolean | ||
|
@@ -527,15 +543,19 @@ export const ClaimsWideView = ({ scopes }: { scopes: any[] }) => { | |
> | ||
{appAskedFor} | ||
</Text> | ||
{masked && <EmailMaskedPill />} | ||
</Disclosure.Button> | ||
) : ( | ||
<Text | ||
size="sm" | ||
weight="medium" | ||
className="text-gray-500 truncate" | ||
> | ||
{appAskedFor} | ||
</Text> | ||
<div className="flex space-x-1"> | ||
<Text | ||
size="sm" | ||
weight="medium" | ||
className="text-gray-500 truncate" | ||
> | ||
{appAskedFor} | ||
</Text> | ||
{masked && <EmailMaskedPill />} | ||
</div> | ||
)} | ||
</td> | ||
<td className="px-6 py-3"> | ||
|
@@ -636,6 +656,7 @@ export const ClaimsWideView = ({ scopes }: { scopes: any[] }) => { | |
| { | ||
icon: string | ||
address: string | ||
source: string | ||
type: string | ||
title?: string | ||
} | ||
|
@@ -675,7 +696,9 @@ export const ClaimsWideView = ({ scopes }: { scopes: any[] }) => { | |
Wallet(s) | ||
</Text> | ||
) : ( | ||
<MultiAvatar avatars={accounts.map((a) => a.icon)!} /> | ||
<MultiAvatar | ||
avatars={accounts.filter((a) => a.icon).map((a) => a.icon)} | ||
/> | ||
)} | ||
</td> | ||
<td className="px-6 py-3 flex flex-row items-center gap-2.5"> | ||
|
@@ -706,6 +729,7 @@ export const ClaimsWideView = ({ scopes }: { scopes: any[] }) => { | |
size={20} | ||
text={scWallets ? a.title! : a.address} | ||
avatarURL={a.icon} | ||
masked={a.type === EmailAccountType.Mask} | ||
onClick={() => setSelectedAccount(a)} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There might be a type mismatch here, the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't understand. |
||
className={'pointer-events-auto'} | ||
/> | ||
|
@@ -717,7 +741,8 @@ export const ClaimsWideView = ({ scopes }: { scopes: any[] }) => { | |
source={ | ||
source | ||
? source | ||
: `${startCase(selectedAccount.type)} - ${ | ||
: selectedAccount.source || | ||
`${startCase(selectedAccount.type)} - ${ | ||
selectedAccount.address | ||
}` | ||
} | ||
|
@@ -754,11 +779,10 @@ export const ClaimsWideView = ({ scopes }: { scopes: any[] }) => { | |
<RowView | ||
key={i} | ||
appAskedFor="Email" | ||
whatsBeingShared={scope.account} | ||
sourceOfData={scope.account} | ||
sourceOfDataIcon={ | ||
<img src={scope.icon} className="w-5 h-5 rounded-full" /> | ||
} | ||
masked={scope.masked} | ||
whatsBeingShared={scope.address} | ||
sourceOfData={scope.masked ? scope.source : scope.address} | ||
sourceOfDataIcon={<HiOutlineMail className="w-5 h-5" />} | ||
dropdown={false} | ||
/> | ||
) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -325,9 +325,7 @@ export const action: ActionFunction = async ({ request, context }) => { | |
const scope = (form.get('scopes') as string).split(' ') | ||
/* This stores the selection made from the user in the authorization | ||
screen; gets validated and stored for later retrieval at token generation stage */ | ||
const personaData = JSON.parse( | ||
form.get('personaData') as string | ||
) as PersonaData | ||
let personaData = JSON.parse(form.get('personaData') as string) as PersonaData | ||
|
||
const state = form.get('state') as string | ||
const clientId = form.get('client_id') as string | ||
|
@@ -369,6 +367,15 @@ export const action: ActionFunction = async ({ request, context }) => { | |
context.traceSpan | ||
) | ||
|
||
if (personaData.email) { | ||
const emailAccountCoreClient = getCoreClient({ | ||
context, | ||
jwt, | ||
accountURN: personaData.email, | ||
}) | ||
await emailAccountCoreClient.account.resolveIdentity.query({ jwt }) | ||
} | ||
|
||
const authorizeRes = await coreClient.authorization.authorize.mutate({ | ||
identity: identityURN, | ||
responseType, | ||
|
@@ -397,13 +404,13 @@ export const action: ActionFunction = async ({ request, context }) => { | |
} | ||
|
||
export default function Authorize() { | ||
const loaderData = useLoaderData<LoaderData>() | ||
const { | ||
clientId, | ||
appProfile, | ||
scopeMeta, | ||
state, | ||
redirectOverride, | ||
dataForScopes, | ||
redirectUri, | ||
profile, | ||
prompt, | ||
|
@@ -412,10 +419,11 @@ export default function Authorize() { | |
|
||
const userProfile = profile as UserProfile | ||
|
||
const [dataForScopes, setDataForScopes] = useState(loaderData.dataForScopes) | ||
const { | ||
connectedEmails, | ||
personaData, | ||
requestedScope, | ||
connectedEmails, | ||
connectedAccounts, | ||
connectedSmartContractWallets, | ||
} = dataForScopes as DataForScopes | ||
|
@@ -434,6 +442,54 @@ export default function Authorize() { | |
} | ||
return selected | ||
}) | ||
|
||
const [maskEmail, setMaskEmail] = useState<boolean>(false) | ||
useEffect(() => { | ||
setMaskEmailCallback() | ||
}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should have a dependency array, either an empty one: |
||
|
||
const [loadingMaskEmail, setLoadingMaskEmail] = useState<boolean>(false) | ||
|
||
const setMaskEmailCallback = async () => { | ||
if (!maskEmail) return | ||
|
||
const accountURN = selectedEmail?.value | ||
if (!accountURN) return | ||
if (selectedEmail.mask) return | ||
|
||
setLoadingMaskEmail(true) | ||
|
||
const response = await fetch('/create/account-mask', { | ||
body: JSON.stringify({ clientId, state, accountURN }), | ||
headers: { 'Content-Type': 'application/json' }, | ||
method: 'POST', | ||
}) | ||
|
||
let maskAccount = selectedEmail | ||
const [mask] = await response.json<DropdownSelectListItem[]>() | ||
|
||
setDataForScopes((state) => ({ | ||
...state, | ||
connectedAccounts: connectedAccounts.map((ca) => { | ||
if (ca.value !== accountURN) return ca | ||
return { | ||
...ca, | ||
mask, | ||
} | ||
}), | ||
connectedEmails: connectedEmails.map((ce) => { | ||
if (ce.value !== accountURN) return ce | ||
maskAccount = { | ||
...ce, | ||
mask, | ||
} | ||
return maskAccount | ||
}), | ||
})) | ||
setSelectedEmail(maskAccount) | ||
setLoadingMaskEmail(false) | ||
} | ||
|
||
const [selectedConnectedAccounts, setSelectedConnectedAccounts] = useState< | ||
Array<DropdownSelectListItem> | Array<AuthorizationControlSelection> | ||
>(() => { | ||
|
@@ -510,7 +566,9 @@ export default function Authorize() { | |
} | ||
|
||
if (requestedScope.includes('email') && selectedEmail) { | ||
personaData.email = selectedEmail.value | ||
personaData.email = maskEmail | ||
? selectedEmail.mask?.value | ||
: selectedEmail.value | ||
} | ||
|
||
if ( | ||
|
@@ -521,7 +579,12 @@ export default function Authorize() { | |
personaData.connected_accounts = AuthorizationControlSelection.ALL | ||
} else { | ||
personaData.connected_accounts = selectedConnectedAccounts.map( | ||
(account) => (account as DropdownSelectListItem).value | ||
(account) => { | ||
const item = account as DropdownSelectListItem | ||
if (!maskEmail) return item.value | ||
if (item.value === selectedEmail?.value) return item.mask?.value | ||
return item.value | ||
} | ||
) | ||
} | ||
} | ||
|
@@ -640,10 +703,13 @@ export default function Authorize() { | |
// Substituting subtitle with icon | ||
// on the client side | ||
return { | ||
address: email.address, | ||
type: email.type, | ||
icon: getEmailIcon(email.subtitle!), | ||
title: email.title, | ||
selected: email.selected, | ||
value: email.value, | ||
mask: email.mask, | ||
} | ||
}) ?? [] | ||
} | ||
|
@@ -661,6 +727,9 @@ export default function Authorize() { | |
}} | ||
selectEmailCallback={setSelectedEmail} | ||
selectedEmail={selectedEmail} | ||
maskEmail={maskEmail} | ||
loadingMaskEmail={loadingMaskEmail} | ||
setMaskEmail={setMaskEmail} | ||
connectedAccounts={connectedAccounts ?? []} | ||
selectedConnectedAccounts={selectedConnectedAccounts} | ||
addNewAccountCallback={() => { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't seem to be used in the mobile view