Skip to content

Commit

Permalink
implement permissions
Browse files Browse the repository at this point in the history
  • Loading branch information
mehdi-torabiv committed Aug 28, 2024
1 parent 381f919 commit 2857603
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 202 deletions.
19 changes: 10 additions & 9 deletions src/components/shared/CustomTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ const CustomTable: React.FC<CustomTableProps<AccessData>> = ({
ycolumns,
handleGrantOrRevokeAccess,
}) => {
console.log('xcolumns:', xcolumns);
console.log('ycolumns:', ycolumns);

const groupedApplications = ycolumns.reduce(
(acc, application) => {
if (!acc[application.applicationName]) {
Expand Down Expand Up @@ -89,12 +86,16 @@ const CustomTable: React.FC<CustomTableProps<AccessData>> = ({
);
return (
<TableCell key={colIndex} align="center">
<AccessControlButton
hasAccess={application?.hasPermission || false}
onToggleAccess={() =>
handleToggleAccess(application!, platform)
}
/>
{application ? (
<AccessControlButton
hasAccess={application.hasPermission}
onToggleAccess={() =>
handleToggleAccess(application, platform)
}
/>
) : (
<Typography variant="body2">No Data</Typography>
)}
</TableCell>
);
})}
Expand Down
285 changes: 141 additions & 144 deletions src/pages/Permissions/Permissions.tsx
Original file line number Diff line number Diff line change
@@ -1,175 +1,172 @@
/* eslint-disable react-hooks/exhaustive-deps */
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
useAccount,
useReadContract,
useReadContracts,
useWriteContract,
} from 'wagmi';
import { Abi, Address } from 'viem';
import { useEffect, useState } from 'react';
/* eslint-disable @typescript-eslint/no-explicit-any */
import { useEffect, useMemo, useState } from 'react';
import { useReadContract, useReadContracts, useWriteContract } from 'wagmi';
import { Address, Abi } from 'viem';
import { Backdrop, CircularProgress, Stack, Typography } from '@mui/material';
import { useGetAttestations } from '../../services/eas/query';
import sepoliaChainAppConctract from '../../utils/contracts/app/sepoliaChain.json';
import sepoliaChainOidonctract from '../../utils/contracts/oid/sepoliaChain.json';
import useSessionSigs from '../../hooks/useSessionSigs';
import useLit from '../../hooks/LitProvider';
import { useSigner } from '../../utils/eas-wagmi-utils';
import { decryptAttestation, getAttestations } from '../../libs/oci';
import CustomTable from '../../components/shared/CustomTable';

interface IProvider {
uid: string;
provider: string;
id: string;
}
import { decodeAttestationData, IAttestation } from '../../libs/oci';
import CustomTable, {
Platform,
AccessData,
} from '../../components/shared/CustomTable';

export function Permissions() {
const signer = useSigner();
const { litNodeClient } = useLit();
const { sessionSigs, createSessionSigs } = useSessionSigs();

const { isConnected, address, chainId } = useAccount();
const [applicationsArgs, setApplicationsArgs] = useState<[number, number]>([
0, 10,
]);
const { writeContract } = useWriteContract();

const [providers, setProviders] = useState<IProvider[]>([]);
const [uids, setUids] = useState<string[]>([]);

const { data: applications } = useReadContract({
abi: sepoliaChainAppConctract.appContractABI,
address: sepoliaChainAppConctract.appContractAddress as Address,
functionName: 'getApplications',
args: applicationsArgs,
});
const { writeContract, isPending: isWriting } = useWriteContract();
const { data: attestationsResponse, isLoading: isLoadingAttestations } =
useGetAttestations();
const [applicationsArgs] = useState<[number, number]>([0, 10]);
const [attestations, setAttestations] = useState<
(IAttestation & { provider?: string; id?: string })[]
>([]);
const [permissionsWithUidsAndApps, setPermissionsWithUidsAndApps] = useState<
AccessData[]
>([]);

const { data: applications, isLoading: isLoadingApplications } =
useReadContract({
abi: sepoliaChainAppConctract.appContractABI,
address: sepoliaChainAppConctract.appContractAddress as Address,
functionName: 'getApplications',
args: applicationsArgs,
});

useEffect(() => {
if (!isConnected) throw new Error('Wallet not connected');
}, [isConnected, applications]);

const contractCalls = uids.flatMap((uid) =>
applications.map((application) => ({
abi: sepoliaChainOidonctract.oidContractAbi as Abi,
address: sepoliaChainOidonctract.oidContractAddress as Address,
functionName: 'hasPermission',
args: [uid, application.account],
}))
);

const { data: hasPermissionsOnApp } = useReadContracts({
contracts: contractCalls,
});

console.log({ hasPermissionsOnApp });
const processAttestations = () => {
if (!attestationsResponse) {
return;
}

const permissionsWithUidsAndApps =
hasPermissionsOnApp
?.map((permissionResult, index) => {
const uidIndex = Math.floor(index / applications.length);
const appIndex = index % applications.length;
const attestationsData = attestationsResponse.map((attestation) => {
const decodedData = decodeAttestationData(attestation.data);

if (!permissionResult || typeof permissionResult.result !== 'boolean') {
console.error(
`Unexpected result format for UID: ${uids[uidIndex]} and account: ${applications[appIndex].account}`,
permissionResult
);
return null;
}
const providerData = decodedData.find(
(data) => data.name === 'provider'
);

return {
uid: uids[uidIndex],
account: applications[appIndex].account,
applicationName: applications[appIndex].name,
hasPermission: permissionResult.result as boolean,
...attestation,
provider:
typeof providerData?.value.value === 'string'
? providerData.value.value
: undefined,
decodedData,
};
})
.filter(Boolean) || [];
});

console.log({ permissionsWithUidsAndApps });
setAttestations(attestationsData);
};

// const { data: hasPermission } = useReadContract({
// abi: sepoliaChainOidonctract.oidContractAbi,
// address: sepoliaChainOidonctract.oidContractAddress as Address,
// functionName: 'hasPermission',
// args: [uid, account],
// });
processAttestations();
}, [attestationsResponse]);

// useEffect(() => {
// if (!isConnected) throw new Error('Wallet not connected');
const contractCalls = useMemo(
() =>
attestations.flatMap(
(attestation) =>
applications?.map((application) => ({

Check failure on line 68 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 18/ubuntu-latest

Property 'map' does not exist on type '{}'.

Check failure on line 68 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 18/ubuntu-latest

Parameter 'application' implicitly has an 'any' type.

Check failure on line 68 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 17/ubuntu-latest

Property 'map' does not exist on type '{}'.

Check failure on line 68 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 17/ubuntu-latest

Parameter 'application' implicitly has an 'any' type.

Check failure on line 68 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 18/ubuntu-latest

Property 'map' does not exist on type '{}'.

Check failure on line 68 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 18/ubuntu-latest

Parameter 'application' implicitly has an 'any' type.

Check failure on line 68 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 17/ubuntu-latest

Property 'map' does not exist on type '{}'.

Check failure on line 68 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 17/ubuntu-latest

Parameter 'application' implicitly has an 'any' type.
abi: sepoliaChainOidonctract.oidContractAbi as Abi,
address: sepoliaChainOidonctract.oidContractAddress as Address,
functionName: 'hasPermission',
args: [attestation.id, application.account],
})) || []
),
[attestations, applications]
);

// console.log({ hasPermission });
// }, [hasPermission]);
const { data: hasPermissionsOnApp, isLoading: isLoadingPermissions } =
useReadContracts({
contracts: contractCalls,
});

useEffect(() => {
if (isConnected && signer && chainId && litNodeClient) {
createSessionSigs({ signer, chainId, litNodeClient });
if (hasPermissionsOnApp) {
const uids = attestations.map((attestation) => attestation.id);

const permissions =
hasPermissionsOnApp
?.map((permissionResult, index) => {

Check failure on line 89 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 18/ubuntu-latest

Parameter 'permissionResult' implicitly has an 'any' type.

Check failure on line 89 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 18/ubuntu-latest

Parameter 'index' implicitly has an 'any' type.

Check failure on line 89 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 17/ubuntu-latest

Parameter 'permissionResult' implicitly has an 'any' type.

Check failure on line 89 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 17/ubuntu-latest

Parameter 'index' implicitly has an 'any' type.

Check failure on line 89 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 18/ubuntu-latest

Parameter 'permissionResult' implicitly has an 'any' type.

Check failure on line 89 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 18/ubuntu-latest

Parameter 'index' implicitly has an 'any' type.

Check failure on line 89 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 17/ubuntu-latest

Parameter 'permissionResult' implicitly has an 'any' type.

Check failure on line 89 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 17/ubuntu-latest

Parameter 'index' implicitly has an 'any' type.
const uidIndex = Math.floor(index / applications.length);

Check failure on line 90 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 18/ubuntu-latest

'applications' is of type 'unknown'.

Check failure on line 90 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 17/ubuntu-latest

'applications' is of type 'unknown'.

Check failure on line 90 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 18/ubuntu-latest

'applications' is of type 'unknown'.

Check failure on line 90 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 17/ubuntu-latest

'applications' is of type 'unknown'.
const appIndex = index % applications.length;

Check failure on line 91 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 18/ubuntu-latest

'applications' is of type 'unknown'.

Check failure on line 91 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 17/ubuntu-latest

'applications' is of type 'unknown'.

Check failure on line 91 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 18/ubuntu-latest

'applications' is of type 'unknown'.

Check failure on line 91 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 17/ubuntu-latest

'applications' is of type 'unknown'.

if (
!permissionResult ||
typeof permissionResult.result !== 'boolean'
) {
console.error(
`Unexpected result format for UID: ${uids[uidIndex]} and account: ${applications[appIndex].account}`,

Check failure on line 98 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 18/ubuntu-latest

'applications' is of type 'unknown'.

Check failure on line 98 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 17/ubuntu-latest

'applications' is of type 'unknown'.

Check failure on line 98 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 18/ubuntu-latest

'applications' is of type 'unknown'.

Check failure on line 98 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 17/ubuntu-latest

'applications' is of type 'unknown'.
permissionResult
);
return null;
}

return {
uid: uids[uidIndex],
account: applications[appIndex].account,

Check failure on line 106 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 18/ubuntu-latest

'applications' is of type 'unknown'.

Check failure on line 106 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 17/ubuntu-latest

'applications' is of type 'unknown'.

Check failure on line 106 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 18/ubuntu-latest

'applications' is of type 'unknown'.

Check failure on line 106 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 17/ubuntu-latest

'applications' is of type 'unknown'.
applicationName: applications[appIndex].name,

Check failure on line 107 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 18/ubuntu-latest

'applications' is of type 'unknown'.

Check failure on line 107 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 17/ubuntu-latest

'applications' is of type 'unknown'.

Check failure on line 107 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 18/ubuntu-latest

'applications' is of type 'unknown'.

Check failure on line 107 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 17/ubuntu-latest

'applications' is of type 'unknown'.
hasPermission: permissionResult.result as boolean,
};
})
.filter(Boolean) || [];

setPermissionsWithUidsAndApps(permissions);
}
}, [signer, isConnected, litNodeClient, chainId, createSessionSigs]);

const fetchAttestations = async () => {
if (!address) throw new Error('No address found');
}, [hasPermissionsOnApp, attestations, applications]);

const attestations = await getAttestations(address as `0x${string}`);
const providers: Platform[] = attestations.map((attestation) => ({

Check failure on line 117 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 18/ubuntu-latest

Type '{ id: string | undefined; provider: string; uid: string | undefined; }[]' is not assignable to type 'Platform[]'.

Check failure on line 117 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 17/ubuntu-latest

Type '{ id: string | undefined; provider: string; uid: string | undefined; }[]' is not assignable to type 'Platform[]'.

Check failure on line 117 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 18/ubuntu-latest

Type '{ id: string | undefined; provider: string; uid: string | undefined; }[]' is not assignable to type 'Platform[]'.

Check failure on line 117 in src/pages/Permissions/Permissions.tsx

View workflow job for this annotation

GitHub Actions / test/node 17/ubuntu-latest

Type '{ id: string | undefined; provider: string; uid: string | undefined; }[]' is not assignable to type 'Platform[]'.
id: attestation.id,
provider: attestation.provider || 'Unknown',
uid: attestation.id,
}));

const filteredUids = attestations
.filter((attestation) => attestation.revocationTime === 0n)
.map((attestation) => attestation.uid);

setUids(filteredUids);

return attestations.filter(
(attestation) => attestation.revocationTime === 0n
);
const handleGrantOrRevokeAccess = (application: any, platform: any) => {
writeContract({
abi: sepoliaChainOidonctract.oidContractAbi as Abi,
address: sepoliaChainOidonctract.oidContractAddress as Address,
functionName: application.hasPermission
? 'revokePermission'
: 'grantPermission',
args: [platform.uid, application.account],
});
};

useEffect(() => {
const decrypt = async () => {
try {
if (!sessionSigs || !litNodeClient)
throw new Error('No sessionSigs found');

const attestations = await fetchAttestations();

const decryptedProviders = (await Promise.all(
attestations.map((attestation) =>
decryptAttestation(litNodeClient, attestation, sessionSigs)
.then((result) => ({
...result,
uid: attestation.uid,
}))
.catch(() => null)
)
).then((results) =>
results.filter((value) => value !== null)
)) as IProvider[];

setProviders(decryptedProviders);
} catch (e) {
console.log(e);
}
};

decrypt();
}, [sessionSigs, litNodeClient]);

console.log({ providers });
const isLoading =
isWriting ||
isLoadingAttestations ||
isLoadingApplications ||
isLoadingPermissions;

return (
<div>
<div>Permissions</div>
<Backdrop
open={isLoading}
sx={{
zIndex: (theme) => theme.zIndex.drawer + 1,
background: '#fff',
color: 'black',
}}
>
<Stack
sx={{
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
}}
>
<CircularProgress color="inherit" />
<Typography variant="h6" gutterBottom style={{ marginLeft: '15px' }}>
Loading...
</Typography>
</Stack>
</Backdrop>
<Typography variant="h6" gutterBottom>
Permissions
</Typography>
<CustomTable
xcolumns={providers}
ycolumns={permissionsWithUidsAndApps}
handleGrantOrRevokeAccess={(application, platform) => {
writeContract({
abi: sepoliaChainOidonctract.oidContractAbi as Abi,
address: sepoliaChainOidonctract.oidContractAddress as Address,
functionName: application.hasPermission
? 'revokePermission'
: 'grantPermission',
args: [platform.uid, application.account],
});
}}
handleGrantOrRevokeAccess={handleGrantOrRevokeAccess}
/>
</div>
);
Expand Down
Loading

0 comments on commit 2857603

Please sign in to comment.