Compare commits
No commits in common. "bbe82ec9a38c1406fde6c6bd84791f403df0386d" and "d76f8e1e296fa157f54f87fd2a4b2a79a414f1e3" have entirely different histories.
bbe82ec9a3
...
d76f8e1e29
@ -58,14 +58,11 @@ export async function PUT(req:Request)
|
||||
|
||||
// Validate logo if provided
|
||||
if (logo && typeof logo === 'string') {
|
||||
const isSvg = logo.includes('<svg') && logo.includes('</svg>');
|
||||
const isPng = logo.startsWith('data:image/png;base64,');
|
||||
|
||||
// Check if it's a valid SVG or PNG data URL
|
||||
if (!isSvg && !isPng) {
|
||||
// Check if it's a valid SVG
|
||||
if (!logo.includes('<svg') || !logo.includes('</svg>')) {
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
message: "invalidLogoFile",
|
||||
message: "invalidSVGFile",
|
||||
}, {
|
||||
status: 400,
|
||||
headers: {
|
||||
@ -74,13 +71,11 @@ export async function PUT(req:Request)
|
||||
})
|
||||
}
|
||||
|
||||
// For SVG files, remove any script tags for security
|
||||
if (isSvg) {
|
||||
// Remove any script tags for security
|
||||
const cleanLogo = logo.replace(/<script[^>]*>.*?<\/script>/gi, '');
|
||||
// Update the logo variable with cleaned content
|
||||
logo = cleanLogo;
|
||||
}
|
||||
// PNG data URLs are already safe as they're base64 encoded
|
||||
}
|
||||
// update the doc
|
||||
let updated_doc = await userModel.updateMany({} , {
|
||||
$set: {
|
||||
|
||||
@ -35,8 +35,8 @@ export default function GeneralSettings()
|
||||
{ value: true, label: t('show') },
|
||||
{ value: false, label: t('dontShow') },
|
||||
]
|
||||
// extract content from svg or png file
|
||||
const readFile = (file : Blob, fileType: string) => {
|
||||
// extract svg from svg file
|
||||
const readFile = (file : Blob) => {
|
||||
// this function return a promise
|
||||
return new Promise((resolve, reject) => {
|
||||
// read the file
|
||||
@ -50,34 +50,25 @@ export default function GeneralSettings()
|
||||
reader.onerror = (error) => {
|
||||
reject(error);
|
||||
};
|
||||
// read the file based on type
|
||||
if (fileType === 'svg') {
|
||||
// read the file as a text thene fire onload listener
|
||||
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 - 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');
|
||||
// Validate file type
|
||||
if (!file.type.includes('svg') && !file.name.toLowerCase().endsWith('.svg')) {
|
||||
alert(t('onlySVGFilesAllowed') || 'Only SVG 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, fileType) as string;
|
||||
const content = await readFile(file) as string;
|
||||
|
||||
if (fileType === 'svg') {
|
||||
// Validate SVG content
|
||||
if (!content.includes('<svg') || !content.includes('</svg>')) {
|
||||
alert(t('invalidSVGFile') || 'Invalid SVG file format');
|
||||
@ -87,11 +78,9 @@ export default function GeneralSettings()
|
||||
|
||||
// Additional security check - remove any script tags
|
||||
const cleanContent = content.replace(/<script[^>]*>.*?<\/script>/gi, '');
|
||||
setFieldValue('logo' , cleanContent);
|
||||
} else {
|
||||
// For PNG files, store the data URL directly
|
||||
setFieldValue('logo' , content);
|
||||
}
|
||||
|
||||
// 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');
|
||||
@ -354,21 +343,13 @@ 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') ? (
|
||||
<img
|
||||
src={values.logo}
|
||||
alt="Logo"
|
||||
className="max-w-[100px] max-h-[100px] object-contain"
|
||||
/>
|
||||
) : (
|
||||
<div className="overflow-hidden [&_svg]:max-w-[100px] [&_svg]:max-h-[100px]" dangerouslySetInnerHTML={{ __html: values.logo }} />
|
||||
)}
|
||||
</label>
|
||||
<input
|
||||
onChange={((e) => {
|
||||
handleFileChange(e , setFieldValue)
|
||||
})}
|
||||
accept=".svg,.png"
|
||||
accept=".svg"
|
||||
disabled={!edite}
|
||||
className="invisible w-0 h-0 hidden"
|
||||
type="file"
|
||||
|
||||
@ -46,17 +46,7 @@ export default function Sidebar () {
|
||||
<nav className={`fixed top-0 ltr:left-0 rtl:right-0 lg:relative shadow-[5px_0_25px_0_rgba(94,92,154,0.1)] z-[99] h-screen bg-primary-dark dark:bg-primary-dark duration-300 ${sidebarState ? 'min-w-[260px] max-w-[260px] ' : 'ltr:translate-x-[-260px] rtl:translate-x-[260px] w-0'}`}>
|
||||
<header className="w-full max-h-[64px] flex justify-between items-center px-[18px] py-[14px] [&_*]:text-text-light bg-secondary-dark">
|
||||
<div className="flex justify-center items-center flex gap-[15px]">
|
||||
<div className={`w-12 h-16 flex items-center justify-center relative ${appGeneralSettings.showLogo ? '' : 'hidden'}`}>
|
||||
{appGeneralSettings.logo && appGeneralSettings.logo.startsWith('data:image/png') ? (
|
||||
<img
|
||||
src={appGeneralSettings.logo}
|
||||
alt="Logo"
|
||||
className="max-w-full max-h-full object-contain"
|
||||
/>
|
||||
) : (
|
||||
<div dangerouslySetInnerHTML={{ __html: appGeneralSettings.logo || '' }} />
|
||||
)}
|
||||
</div>
|
||||
<div className={`w-12 h-16 flex items-center justify-center relative ${appGeneralSettings.showLogo ? '' : 'hidden'}`} dangerouslySetInnerHTML={{ __html: appGeneralSettings.logo || '' }} />
|
||||
<h1 className="text-[25px] font-light">{local == 'ar' ? appGeneralSettings.appName : appGeneralSettings.appNameEN}</h1>
|
||||
</div>
|
||||
<button onClick={() => {dispatch(toggleSidebar())}} className="rounded-full rtl:rotate-180 hover:bg-primary/5 p-[6px]">
|
||||
|
||||
@ -365,9 +365,8 @@
|
||||
"save": "الحفظ",
|
||||
"ignore": "تجاهل",
|
||||
"appNameEN": "اسم التطبيق ( en )",
|
||||
"onlySVGAndPNGFilesAllowed": "يُسمح فقط بملفات SVG و PNG",
|
||||
"onlySVGFilesAllowed": "يُسمح فقط بملفات SVG",
|
||||
"invalidSVGFile": "تنسيق ملف SVG غير صالح",
|
||||
"invalidLogoFile": "تنسيق ملف الشعار غير صالح. يُسمح فقط بملفات SVG و PNG",
|
||||
"errorReadingFile": "خطأ في قراءة الملف"
|
||||
},
|
||||
"statistics": {
|
||||
|
||||
@ -369,9 +369,8 @@
|
||||
"edite": "Edite",
|
||||
"save": "Save",
|
||||
"ignore": "Ignore",
|
||||
"onlySVGAndPNGFilesAllowed": "Only SVG and PNG files are allowed",
|
||||
"onlySVGFilesAllowed": "Only SVG files are allowed",
|
||||
"invalidSVGFile": "Invalid SVG file format",
|
||||
"invalidLogoFile": "Invalid logo file format. Only SVG and PNG files are allowed",
|
||||
"errorReadingFile": "Error reading file"
|
||||
},
|
||||
"statistics": {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user