From b4845dd4357ed999b6a842095bb4a70f5abe1839 Mon Sep 17 00:00:00 2001 From: yznahmad Date: Mon, 11 Aug 2025 23:56:36 +0300 Subject: [PATCH] 10 Descriptive message about your chansssges100 --- .../app/api/user/actions/settings/route.ts | 19 +++--- .../dashboard/settings/generalSettings.tsx | 61 ++++++++++++------- webapp/src/components/dashboard/sidebar.tsx | 12 +++- webapp/src/messages/ar.json | 3 +- webapp/src/messages/en.json | 3 +- 5 files changed, 67 insertions(+), 31 deletions(-) diff --git a/webapp/src/app/api/user/actions/settings/route.ts b/webapp/src/app/api/user/actions/settings/route.ts index da22208..f99d356 100644 --- a/webapp/src/app/api/user/actions/settings/route.ts +++ b/webapp/src/app/api/user/actions/settings/route.ts @@ -58,11 +58,14 @@ export async function PUT(req:Request) // Validate logo if provided if (logo && typeof logo === 'string') { - // Check if it's a valid SVG - if (!logo.includes('')) { + const isSvg = logo.includes(''); + const isPng = logo.startsWith('data:image/png;base64,'); + + // Check if it's a valid SVG or PNG data URL + if (!isSvg && !isPng) { return NextResponse.json({ success: false, - message: "invalidSVGFile", + message: "invalidLogoFile", }, { status: 400, headers: { @@ -71,10 +74,12 @@ export async function PUT(req:Request) }) } - // Remove any script tags for security - const cleanLogo = logo.replace(/]*>.*?<\/script>/gi, ''); - // Update the logo variable with cleaned content - logo = cleanLogo; + // For SVG files, remove any script tags for security + if (isSvg) { + const cleanLogo = logo.replace(/]*>.*?<\/script>/gi, ''); + logo = cleanLogo; + } + // PNG data URLs are already safe as they're base64 encoded } // update the doc let updated_doc = await userModel.updateMany({} , { diff --git a/webapp/src/components/dashboard/settings/generalSettings.tsx b/webapp/src/components/dashboard/settings/generalSettings.tsx index 40e0eba..ef0c503 100644 --- a/webapp/src/components/dashboard/settings/generalSettings.tsx +++ b/webapp/src/components/dashboard/settings/generalSettings.tsx @@ -35,8 +35,8 @@ export default function GeneralSettings() { value: true, label: t('show') }, { value: false, label: t('dontShow') }, ] - // extract svg from svg file - const readFile = (file : Blob) => { + // extract content from svg or png file + const readFile = (file : Blob, fileType: string) => { // this function return a promise return new Promise((resolve, reject) => { // read the file @@ -50,37 +50,48 @@ export default function GeneralSettings() reader.onerror = (error) => { reject(error); }; - // read the file as a text thene fire onload listener - reader.readAsText(file); + // read the file based on type + if (fileType === 'svg') { + reader.readAsText(file); + } else { + reader.readAsDataURL(file); + } }); }; // handle the changes in the file input const handleFileChange = async (event : any , setFieldValue : any) => { const file = event.target.files[0]; if (file) { - // Validate file type - if (!file.type.includes('svg') && !file.name.toLowerCase().endsWith('.svg')) { - alert(t('onlySVGFilesAllowed') || 'Only SVG files are allowed'); + // Validate file type - allow both SVG and PNG + const isSvg = file.type.includes('svg') || file.name.toLowerCase().endsWith('.svg'); + const isPng = file.type.includes('png') || file.name.toLowerCase().endsWith('.png'); + + if (!isSvg && !isPng) { + alert(t('onlySVGAndPNGFilesAllowed') || 'Only SVG and PNG files are allowed'); event.target.value = ''; // Clear the input return; } try { + const fileType = isSvg ? 'svg' : 'png'; // get the file content - const content = await readFile(file) as string; + const content = await readFile(file, fileType) as string; - // Validate SVG content - if (!content.includes('')) { - alert(t('invalidSVGFile') || 'Invalid SVG file format'); - event.target.value = ''; // Clear the input - return; + if (fileType === 'svg') { + // Validate SVG content + if (!content.includes('')) { + alert(t('invalidSVGFile') || 'Invalid SVG file format'); + event.target.value = ''; // Clear the input + return; + } + + // Additional security check - remove any script tags + const cleanContent = content.replace(/]*>.*?<\/script>/gi, ''); + setFieldValue('logo' , cleanContent); + } else { + // For PNG files, store the data URL directly + setFieldValue('logo' , content); } - - // Additional security check - remove any script tags - const cleanContent = content.replace(/]*>.*?<\/script>/gi, ''); - - // set the field value with with new file content - setFieldValue('logo' , cleanContent) } catch (error) { console.error('Error reading file:', error); alert(t('errorReadingFile') || 'Error reading file'); @@ -343,13 +354,21 @@ export default function GeneralSettings() dark:border-primary-dark rounded-md overflow-hidden flex items-center justify-center `}> -
+ {values.logo && values.logo.startsWith('data:image/png') ? ( + Logo + ) : ( +
+ )} { handleFileChange(e , setFieldValue) })} - accept=".svg" + accept=".svg,.png" disabled={!edite} className="invisible w-0 h-0 hidden" type="file" diff --git a/webapp/src/components/dashboard/sidebar.tsx b/webapp/src/components/dashboard/sidebar.tsx index e398bf2..ca4c6a1 100644 --- a/webapp/src/components/dashboard/sidebar.tsx +++ b/webapp/src/components/dashboard/sidebar.tsx @@ -46,7 +46,17 @@ export default function Sidebar () {