Manage conflicts

This commit is contained in:
Nicola Benaglia 2025-05-24 14:53:46 +02:00
parent a778aa7a0f
commit 506d65dc08
2 changed files with 114 additions and 7114 deletions

View File

@ -38,7 +38,11 @@ import {
getPublicKey, getPublicKey,
transferAsset, transferAsset,
} from '../background/background.ts'; } from '../background/background.ts';
import { getNameInfo, uint8ArrayToObject } from '../encryption/encryption.ts'; import {
getAllUserNames,
getNameInfo,
uint8ArrayToObject,
} from '../encryption/encryption.ts';
import { showSaveFilePicker } from '../hooks/useQortalMessageListener.tsx'; import { showSaveFilePicker } from '../hooks/useQortalMessageListener.tsx';
import { getPublishesFromAdminsAdminSpace } from '../components/Chat/AdminSpaceInner.tsx'; import { getPublishesFromAdminsAdminSpace } from '../components/Chat/AdminSpaceInner.tsx';
import { extractComponents } from '../components/Chat/MessageDisplay.tsx'; import { extractComponents } from '../components/Chat/MessageDisplay.tsx';
@ -1315,7 +1319,7 @@ export const publishQDNResource = async (
if (appFee && appFee > 0 && appFeeRecipient) { if (appFee && appFee > 0 && appFeeRecipient) {
hasAppFee = true; hasAppFee = true;
} }
const registeredName = await getNameInfo(); const registeredName = data?.name || (await getNameInfo());
const name = registeredName; const name = registeredName;
if (!name) { if (!name) {
throw new Error( throw new Error(
@ -1331,7 +1335,7 @@ export const publishQDNResource = async (
const title = data.title; const title = data.title;
const description = data.description; const description = data.description;
const category = data.category; const category = data.category;
const file = data?.file || data?.blob;
const tags = data?.tags || []; const tags = data?.tags || [];
const result = {}; const result = {};
@ -1346,9 +1350,7 @@ export const publishQDNResource = async (
if (data.identifier == null) { if (data.identifier == null) {
identifier = 'default'; identifier = 'default';
} }
if (data?.file || data?.blob) {
data64 = await fileToBase64(data?.file || data?.blob);
}
if ( if (
data.encrypt && data.encrypt &&
(!data.publicKeys || (!data.publicKeys ||
@ -1367,6 +1369,9 @@ export const publishQDNResource = async (
const parsedData = resKeyPair; const parsedData = resKeyPair;
const privateKey = parsedData.privateKey; const privateKey = parsedData.privateKey;
const userPublicKey = parsedData.publicKey; const userPublicKey = parsedData.publicKey;
if (data?.file || data?.blob) {
data64 = await fileToBase64(data?.file || data?.blob);
}
const encryptDataResponse = encryptDataGroup({ const encryptDataResponse = encryptDataGroup({
data64, data64,
publicKeys: data.publicKeys, publicKeys: data.publicKeys,
@ -1410,6 +1415,7 @@ export const publishQDNResource = async (
}), }),
text2: `service: ${service}`, text2: `service: ${service}`,
text3: `identifier: ${identifier || null}`, text3: `identifier: ${identifier || null}`,
text4: `name: ${registeredName}`,
fee: fee.fee, fee: fee.fee,
...handleDynamicValues, ...handleDynamicValues,
}, },
@ -1420,11 +1426,10 @@ export const publishQDNResource = async (
try { try {
const resPublish = await publishData({ const resPublish = await publishData({
registeredName: encodeURIComponent(name), registeredName: encodeURIComponent(name),
file: data64, data: data64 ? data64 : file,
service: service, service: service,
identifier: encodeURIComponent(identifier), identifier: encodeURIComponent(identifier),
uploadType: 'file', uploadType: data64 ? 'base64' : 'file',
isBase64: true,
filename: filename, filename: filename,
title, title,
description, description,
@ -1558,6 +1563,7 @@ export const publishMultipleQDNResources = async (
const fee = await getFee('ARBITRARY'); const fee = await getFee('ARBITRARY');
const registeredName = await getNameInfo(); const registeredName = await getNameInfo();
const name = registeredName; const name = registeredName;
if (!name) { if (!name) {
@ -1568,6 +1574,14 @@ export const publishMultipleQDNResources = async (
); );
} }
const userNames = await getAllUserNames();
data.resources?.forEach((item) => {
if (item?.name && !userNames?.includes(item.name))
throw new Error(
`The name ${item.name}, does not belong to the publisher.`
);
});
const appFee = data?.appFee ? +data.appFee : undefined; const appFee = data?.appFee ? +data.appFee : undefined;
const appFeeRecipient = data?.appFeeRecipient; const appFeeRecipient = data?.appFeeRecipient;
let hasAppFee = false; let hasAppFee = false;
@ -1638,7 +1652,7 @@ export const publishMultipleQDNResources = async (
<div class="resource-detail"><span>Service:</span> ${ <div class="resource-detail"><span>Service:</span> ${
resource.service resource.service
}</div> }</div>
<div class="resource-detail"><span>Name:</span> ${name}</div> <div class="resource-detail"><span>Name:</span> ${resource?.name || name}</div>
<div class="resource-detail"><span>Identifier:</span> ${ <div class="resource-detail"><span>Identifier:</span> ${
resource.identifier resource.identifier
}</div> }</div>
@ -1695,6 +1709,7 @@ export const publishMultipleQDNResources = async (
reason: errorMsg, reason: errorMsg,
identifier: resource.identifier, identifier: resource.identifier,
service: resource.service, service: resource.service,
name: resource?.name || name,
}); });
continue; continue;
} }
@ -1709,12 +1724,13 @@ export const publishMultipleQDNResources = async (
reason: errorMsg, reason: errorMsg,
identifier: resource.identifier, identifier: resource.identifier,
service: resource.service, service: resource.service,
name: resource?.name || name,
}); });
continue; continue;
} }
const service = resource.service; const service = resource.service;
let identifier = resource.identifier; let identifier = resource.identifier;
let data64 = resource?.data64 || resource?.base64; let rawData = resource?.data64 || resource?.base64;
const filename = resource.filename; const filename = resource.filename;
const title = resource.title; const title = resource.title;
const description = resource.description; const description = resource.description;
@ -1741,26 +1757,31 @@ export const publishMultipleQDNResources = async (
reason: errorMsg, reason: errorMsg,
identifier: resource.identifier, identifier: resource.identifier,
service: resource.service, service: resource.service,
name: resource?.name || name,
}); });
continue; continue;
} }
if (resource.file) { if (resource.file) {
data64 = await fileToBase64(resource.file); rawData = resource.file;
} }
if (resourceEncrypt) { if (resourceEncrypt) {
try { try {
if (resource?.file) {
rawData = await fileToBase64(resource.file);
}
const resKeyPair = await getKeyPair(); const resKeyPair = await getKeyPair();
const parsedData = resKeyPair; const parsedData = resKeyPair;
const privateKey = parsedData.privateKey; const privateKey = parsedData.privateKey;
const userPublicKey = parsedData.publicKey; const userPublicKey = parsedData.publicKey;
const encryptDataResponse = encryptDataGroup({ const encryptDataResponse = encryptDataGroup({
data64, data64: rawData,
publicKeys: data.publicKeys, publicKeys: data.publicKeys,
privateKey, privateKey,
userPublicKey, userPublicKey,
}); });
if (encryptDataResponse) { if (encryptDataResponse) {
data64 = encryptDataResponse; rawData = encryptDataResponse;
} }
} catch (error) { } catch (error) {
const errorMsg = const errorMsg =
@ -1772,32 +1793,37 @@ export const publishMultipleQDNResources = async (
reason: errorMsg, reason: errorMsg,
identifier: resource.identifier, identifier: resource.identifier,
service: resource.service, service: resource.service,
name: resource?.name || name,
}); });
continue; continue;
} }
} }
try { try {
const dataType =
resource?.base64 || resource?.data64 || resourceEncrypt
? 'base64'
: 'file';
console.log('dataType', dataType);
await retryTransaction( await retryTransaction(
publishData, publishData,
[ [
{ {
registeredName: encodeURIComponent(name), apiVersion: 2,
file: data64,
service: service,
identifier: encodeURIComponent(identifier),
uploadType: 'file',
isBase64: true,
filename: filename,
title,
description,
category, category,
data: rawData,
description,
filename: filename,
identifier: encodeURIComponent(identifier),
registeredName: encodeURIComponent(resource?.name || name),
service: service,
tag1, tag1,
tag2, tag2,
tag3, tag3,
tag4, tag4,
tag5, tag5,
apiVersion: 2, title,
uploadType: dataType,
withFee: true, withFee: true,
}, },
], ],
@ -1818,6 +1844,7 @@ export const publishMultipleQDNResources = async (
reason: errorMsg, reason: errorMsg,
identifier: resource.identifier, identifier: resource.identifier,
service: resource.service, service: resource.service,
name: resource?.name || name,
}); });
} }
} catch (error) { } catch (error) {
@ -1829,6 +1856,7 @@ export const publishMultipleQDNResources = async (
}), }),
identifier: resource.identifier, identifier: resource.identifier,
service: resource.service, service: resource.service,
name: resource?.name || name,
}); });
} }
} }
@ -2324,6 +2352,44 @@ export const joinGroup = async (data, isFromExtension) => {
export const saveFile = async (data, sender, isFromExtension, snackMethods) => { export const saveFile = async (data, sender, isFromExtension, snackMethods) => {
try { try {
if (!data?.filename) throw new Error('Missing filename');
if (data?.location) {
const requiredFieldsLocation = ['service', 'name'];
const missingFieldsLocation: string[] = [];
requiredFieldsLocation.forEach((field) => {
if (!data?.location[field]) {
missingFieldsLocation.push(field);
}
});
if (missingFieldsLocation.length > 0) {
const missingFieldsString = missingFieldsLocation.join(', ');
const errorMsg = `Missing fields: ${missingFieldsString}`;
throw new Error(errorMsg);
}
const resPermission = await getUserPermission(
{
text1: 'Would you like to download:',
highlightedText: `${data?.filename}`,
},
isFromExtension
);
const { accepted } = resPermission;
if (!accepted) throw new Error('User declined to save file');
const a = document.createElement('a');
let locationUrl = `/arbitrary/${data.location.service}/${data.location.name}`;
if (data.location.identifier) {
locationUrl = locationUrl + `/${data.location.identifier}`;
}
const endpoint = await createEndpoint(
locationUrl + `?attachment=true&attachmentFilename=${data?.filename}`
);
a.href = endpoint;
a.download = data.filename;
document.body.appendChild(a);
a.click();
a.remove();
return true;
}
const requiredFields = ['filename', 'blob']; const requiredFields = ['filename', 'blob'];
const missingFields: string[] = []; const missingFields: string[] = [];
requiredFields.forEach((field) => { requiredFields.forEach((field) => {
@ -2341,6 +2407,8 @@ export const saveFile = async (data, sender, isFromExtension, snackMethods) => {
} }
const filename = data.filename; const filename = data.filename;
const blob = data.blob; const blob = data.blob;
const mimeType = blob.type || data.mimeType;
const resPermission = await getUserPermission( const resPermission = await getUserPermission(
{ {
text1: i18n.t('question:download_file', { text1: i18n.t('question:download_file', {
@ -2351,6 +2419,17 @@ export const saveFile = async (data, sender, isFromExtension, snackMethods) => {
isFromExtension isFromExtension
); );
const { accepted } = resPermission; const { accepted } = resPermission;
if (!accepted) throw new Error('User declined to save file'); // TODO translate
showSaveFilePicker(
{
filename,
mimeType,
blob,
},
snackMethods
);
return true;
if (accepted) { if (accepted) {
const mimeType = blob.type || data.mimeType; const mimeType = blob.type || data.mimeType;
@ -5396,11 +5475,10 @@ export const updateNameRequest = async (data, isFromExtension) => {
const fee = await getFee('UPDATE_NAME'); const fee = await getFee('UPDATE_NAME');
const resPermission = await getUserPermission( const resPermission = await getUserPermission(
{ {
text1: i18n.t('question:permission.register_name', { text1: `Do you give this application permission to update this name?`, // TODO translate
postProcess: 'capitalizeFirstChar', text2: `previous name: ${oldName}`,
}), text3: `new name: ${newName}`,
highlightedText: data.newName, text4: data?.description,
text2: data?.description,
fee: fee.fee, fee: fee.fee,
}, },
isFromExtension isFromExtension
@ -6012,7 +6090,7 @@ export const createGroupRequest = async (data, isFromExtension) => {
]; ];
const missingFields: string[] = []; const missingFields: string[] = [];
requiredFields.forEach((field) => { requiredFields.forEach((field) => {
if (data[field] !== undefined && data[field] !== null) { if (data[field] === undefined || data[field] === null) {
missingFields.push(field); missingFields.push(field);
} }
}); });
@ -6076,7 +6154,7 @@ export const updateGroupRequest = async (data, isFromExtension) => {
]; ];
const missingFields: string[] = []; const missingFields: string[] = [];
requiredFields.forEach((field) => { requiredFields.forEach((field) => {
if (data[field] !== undefined && data[field] !== null) { if (data[field] === undefined || data[field] === null) {
missingFields.push(field); missingFields.push(field);
} }
}); });
@ -6250,7 +6328,7 @@ export const sellNameRequest = async (data, isFromExtension) => {
const requiredFields = ['salePrice', 'nameForSale']; const requiredFields = ['salePrice', 'nameForSale'];
const missingFields: string[] = []; const missingFields: string[] = [];
requiredFields.forEach((field) => { requiredFields.forEach((field) => {
if (data[field] !== undefined && data[field] !== null) { if (data[field] === undefined || data[field] === null) {
missingFields.push(field); missingFields.push(field);
} }
}); });
@ -6320,7 +6398,7 @@ export const cancelSellNameRequest = async (data, isFromExtension) => {
const requiredFields = ['nameForSale']; const requiredFields = ['nameForSale'];
const missingFields: string[] = []; const missingFields: string[] = [];
requiredFields.forEach((field) => { requiredFields.forEach((field) => {
if (data[field] !== undefined && data[field] !== null) { if (data[field] === undefined || data[field] === null) {
missingFields.push(field); missingFields.push(field);
} }
}); });
@ -6377,7 +6455,7 @@ export const buyNameRequest = async (data, isFromExtension) => {
const requiredFields = ['nameForSale']; const requiredFields = ['nameForSale'];
const missingFields: string[] = []; const missingFields: string[] = [];
requiredFields.forEach((field) => { requiredFields.forEach((field) => {
if (data[field] !== undefined && data[field] !== null) { if (data[field] === undefined || data[field] === null) {
missingFields.push(field); missingFields.push(field);
} }
}); });
@ -6908,12 +6986,11 @@ export const multiPaymentWithPrivateData = async (data, isFromExtension) => {
[ [
{ {
registeredName: encodeURIComponent(name), registeredName: encodeURIComponent(name),
file: encryptDataResponse, data: encryptDataResponse,
service: transaction.service, service: transaction.service,
identifier: encodeURIComponent(transaction.identifier), identifier: encodeURIComponent(transaction.identifier),
uploadType: 'file', uploadType: 'base64',
description: transaction?.description, description: transaction?.description,
isBase64: true,
apiVersion: 2, apiVersion: 2,
withFee: true, withFee: true,
}, },

File diff suppressed because it is too large Load Diff