mirror of
https://github.com/Qortal/chrome-extension.git
synced 2025-03-27 15:55:55 +00:00
166 lines
5.8 KiB
TypeScript
166 lines
5.8 KiB
TypeScript
import { Box, Button, Typography } from '@mui/material'
|
|
import React, { useContext } from 'react'
|
|
import { CustomizedSnackbars } from '../Snackbar/Snackbar';
|
|
import { LoadingButton } from '@mui/lab';
|
|
import { MyContext, getBaseApiReact, pauseAllQueues } from '../../App';
|
|
import { getFee } from '../../background';
|
|
import { decryptResource, getGroupAdimns, validateSecretKey } from '../Group/Group';
|
|
import { base64ToUint8Array } from '../../qdn/encryption/group-encryption';
|
|
import { uint8ArrayToObject } from '../../backgroundFunctions/encryption';
|
|
|
|
export const CreateCommonSecret = ({groupId, secretKey, isOwner, myAddress, secretKeyDetails, userInfo, noSecretKey}) => {
|
|
const { show, setTxList } = useContext(MyContext);
|
|
|
|
const [openSnack, setOpenSnack] = React.useState(false);
|
|
const [infoSnack, setInfoSnack] = React.useState(null);
|
|
const [isLoading, setIsLoading] = React.useState(false)
|
|
|
|
const getPublishesFromAdmins = async (admins: string[]) => {
|
|
// const validApi = await findUsableApi();
|
|
const queryString = admins.map((name) => `name=${name}`).join("&");
|
|
const url = `${getBaseApiReact()}/arbitrary/resources/search?mode=ALL&service=DOCUMENT_PRIVATE&identifier=symmetric-qchat-group-${
|
|
groupId
|
|
}&exactmatchnames=true&limit=0&reverse=true&${queryString}`;
|
|
const response = await fetch(url);
|
|
if(!response.ok){
|
|
throw new Error('network error')
|
|
}
|
|
const adminData = await response.json();
|
|
|
|
const filterId = adminData.filter(
|
|
(data: any) =>
|
|
data.identifier === `symmetric-qchat-group-${groupId}`
|
|
);
|
|
if (filterId?.length === 0) {
|
|
return false;
|
|
}
|
|
const sortedData = filterId.sort((a: any, b: any) => {
|
|
// Get the most recent date for both a and b
|
|
const dateA = a.updated ? new Date(a.updated) : new Date(a.created);
|
|
const dateB = b.updated ? new Date(b.updated) : new Date(b.created);
|
|
|
|
// Sort by most recent
|
|
return dateB.getTime() - dateA.getTime();
|
|
});
|
|
|
|
return sortedData[0];
|
|
};
|
|
const getSecretKey = async (loadingGroupParam?: boolean, secretKeyToPublish?: boolean) => {
|
|
try {
|
|
pauseAllQueues()
|
|
|
|
|
|
|
|
const {names} = await getGroupAdimns(groupId);
|
|
if(!names.length){
|
|
throw new Error('Network error')
|
|
}
|
|
const publish = await getPublishesFromAdmins(names);
|
|
|
|
|
|
if (publish === false) {
|
|
|
|
return false;
|
|
}
|
|
|
|
const res = await fetch(
|
|
`${getBaseApiReact()}/arbitrary/DOCUMENT_PRIVATE/${publish.name}/${
|
|
publish.identifier
|
|
}?encoding=base64`
|
|
);
|
|
const data = await res.text();
|
|
|
|
const decryptedKey: any = await decryptResource(data);
|
|
|
|
const dataint8Array = base64ToUint8Array(decryptedKey.data);
|
|
const decryptedKeyToObject = uint8ArrayToObject(dataint8Array);
|
|
|
|
if (!validateSecretKey(decryptedKeyToObject))
|
|
throw new Error("SecretKey is not valid");
|
|
|
|
if (decryptedKeyToObject) {
|
|
|
|
return decryptedKeyToObject;
|
|
} else {
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
|
|
} finally {
|
|
}
|
|
};
|
|
|
|
const createCommonSecret = async ()=> {
|
|
try {
|
|
const fee = await getFee('ARBITRARY')
|
|
await show({
|
|
message: "Would you like to perform an ARBITRARY transaction?" ,
|
|
publishFee: fee.fee + ' QORT'
|
|
})
|
|
setIsLoading(true)
|
|
|
|
const secretKey2 = await getSecretKey()
|
|
if((!secretKey2 && secretKey2 !== false)) throw new Error('invalid secret key')
|
|
if (secretKey2 && !validateSecretKey(secretKey2)) throw new Error('invalid secret key')
|
|
|
|
const secretKeyToSend = !secretKey2 ? null : secretKey2
|
|
|
|
|
|
chrome?.runtime?.sendMessage({ action: "encryptAndPublishSymmetricKeyGroupChat", payload: {
|
|
groupId: groupId,
|
|
previousData: secretKeyToSend
|
|
} }, (response) => {
|
|
if (!response?.error) {
|
|
setInfoSnack({
|
|
type: "success",
|
|
message: "Successfully re-encrypted secret key. It may take a couple of minutes for the changes to propagate. Refresh the group in 5mins",
|
|
});
|
|
setOpenSnack(true);
|
|
setTxList((prev)=> [{
|
|
...response,
|
|
type: 'created-common-secret',
|
|
label: `Published secret key for group ${groupId}: awaiting confirmation`,
|
|
labelDone: `Published secret key for group ${groupId}: success!`,
|
|
done: false,
|
|
groupId,
|
|
|
|
}, ...prev])
|
|
}
|
|
setIsLoading(false)
|
|
});
|
|
} catch (error) {
|
|
|
|
}
|
|
}
|
|
|
|
|
|
return (
|
|
<Box sx={{
|
|
padding: '25px',
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
gap: '25px',
|
|
maxWidth: '350px',
|
|
background: '#444444'
|
|
}}>
|
|
<LoadingButton loading={isLoading} loadingPosition="start" color="warning" variant='contained' onClick={createCommonSecret}>Re-encyrpt key</LoadingButton>
|
|
{noSecretKey ? (
|
|
<Box>
|
|
<Typography>There is no group secret key. Be the first admin to publish one!</Typography>
|
|
</Box>
|
|
) : isOwner && secretKeyDetails && userInfo?.name && userInfo.name !== secretKeyDetails?.name ? (
|
|
<Box>
|
|
<Typography>The latest group secret key was published by a non-owner. As the owner of the group please re-encrypt the key as a safeguard</Typography>
|
|
</Box>
|
|
): (
|
|
<Box>
|
|
<Typography>The group member list has changed. Please re-encrypt the secret key.</Typography>
|
|
</Box>
|
|
)}
|
|
<CustomizedSnackbars open={openSnack} setOpen={setOpenSnack} info={infoSnack} setInfo={setInfoSnack} />
|
|
</Box>
|
|
|
|
)
|
|
}
|