Skip to content
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

implement permissions #60

Merged
merged 4 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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[]
>([]);

mehdi-torabiv marked this conversation as resolved.
Show resolved Hide resolved
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.
mehdi-torabiv marked this conversation as resolved.
Show resolved Hide resolved
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[]'.
mehdi-torabiv marked this conversation as resolved.
Show resolved Hide resolved
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
Loading