* feat: enhance image upload validation across the application
* Patch improvements.
* refactor: streamline avatar upload error handling in updateProfile handler
* refactor: extract image validation logic into a separate module for reuse in BannerUploader and ImageUploader
* fix: reset file input value on validation failure in image uploaders
* fix: update localization key for image file upload error message
* fix: update HTML content validation in image uploader to check for additional byte
* Code Quality improvements
* add : unit tests.
* fix : fixing some more issues.
* fix : some import fixes
* fix : fixing type-check issues
* fix : some more import fixes.
* fix : removing Duplicate max-file-size constant
* refactor: enhance base64 validation with regex pattern
* refactor: centralize MAX_IMAGE_FILE_SIZE and fix SVG checks.
* fix : some toast fixes.
* fixing the size of the banner.
* fix: update accepted image formats in BannerUploader and ImageUploader components
* fix
* coderabbit suggestions addressed.
* addressed coderrabit comment
* refactor: implement generic i18n error messages with interpolation
- Add generic 'unsupported_file_type' translation key with {{type}} interpolation
- Replace hardcoded file type error messages with reusable i18n pattern
- Update imageValidation interfaces to support errorKey and errorParams
- Refactor server-side and client-side validation to use new pattern
- Remove individual translation keys for each file type (PDF, HTML, Script, ZIP, Executable)
- Add new translation keys for other validation errors (SVG, base64, empty data, etc.)
- Type-safe error handling with proper interpolation support
Benefits:
- Single reusable translation pattern reduces duplication
- Easier to maintain and localize
- Consistent error messaging across file types
* feat: add MAX_BANNER_SIZE constant and update file size validation
- Add MAX_BANNER_SIZE constant (5MB) to shared constants file
- Update BannerUploader to use shared constant instead of inline value
- Update ImageUploader to handle new errorKey/errorParams pattern
- Maintain backward compatibility with existing error handling
Note: Pre-existing linting warnings in constants.ts and BannerUploader.tsx
are unrelated to these changes and were present before this refactor.
* adressed volnei's suggestions.
* test: update image validation tests for new errorKey/errorParams pattern
- Update all dangerous file type tests to expect errorKey and errorParams instead of hardcoded error messages
- Add comprehensive tests for new error format validation pattern
- Add tests for backward compatibility with error field
- Add tests for MAX_BANNER_SIZE constant integration
- Verify that unsupported file types now return generic 'unsupported_file_type' key with type interpolation
- Ensure all existing functionality continues to work with enhanced error handling
All 42 tests passing ✅
* test: update server-side image validation tests for new error format
- Update all dangerous file type tests to expect errorKey and errorParams
- Change hardcoded error messages to i18n keys (unsupported_file_type, svg_contains_dangerous_content, etc.)
- Update edge case tests to use new error keys (empty_image_data, invalid_base64_format, unrecognized_image_format)
- Add comprehensive tests for new error format validation pattern
- Add tests for backward compatibility with error field
- Verify that unsupported file types return generic 'unsupported_file_type' key with type interpolation
All 26 server-side tests passing ✅
Complements client-side test updates for complete test coverage
---------
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: unknown <adhabal2002@gmail.com>
72 lines
2.0 KiB
TypeScript
72 lines
2.0 KiB
TypeScript
/**
|
|
* Shared image validation constants and utilities
|
|
* Used by both server-side and client-side validation modules
|
|
*/
|
|
|
|
/**
|
|
* Magic numbers (file signatures) for different file types
|
|
*/
|
|
export const FILE_SIGNATURES = {
|
|
PNG: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a],
|
|
JPEG_FF_D8_FF: [0xff, 0xd8, 0xff],
|
|
GIF87a: [0x47, 0x49, 0x46, 0x38, 0x37, 0x61],
|
|
GIF89a: [0x47, 0x49, 0x46, 0x38, 0x39, 0x61],
|
|
WEBP: [0x52, 0x49, 0x46, 0x46],
|
|
WEBP_SIGNATURE: [0x57, 0x45, 0x42, 0x50],
|
|
BMP: [0x42, 0x4d],
|
|
ICO: [0x00, 0x00, 0x01, 0x00],
|
|
SVG: [0x3c, 0x3f, 0x78, 0x6d, 0x6c],
|
|
SVG_DIRECT: [0x3c, 0x73, 0x76, 0x67],
|
|
|
|
PDF: [0x25, 0x50, 0x44, 0x46],
|
|
HTML: [0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45],
|
|
HTML_TAG: [0x3c, 0x68, 0x74, 0x6d, 0x6c],
|
|
SCRIPT_TAG: [0x3c, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74],
|
|
ZIP: [0x50, 0x4b, 0x03, 0x04],
|
|
EXECUTABLE: [0x4d, 0x5a],
|
|
} as const;
|
|
|
|
/**
|
|
* Check if bytes match a signature
|
|
*/
|
|
export function matchesSignature(data: Uint8Array, signature: readonly number[]): boolean {
|
|
if (data.length < signature.length) return false;
|
|
return signature.every((byte, index) => data[index] === byte);
|
|
}
|
|
|
|
/**
|
|
* SVG content validation patterns
|
|
*/
|
|
export const DANGEROUS_SVG_PATTERNS = [
|
|
"<script",
|
|
"javascript:",
|
|
"onload=",
|
|
"onclick=",
|
|
"onmouseover=",
|
|
"onmouseout=",
|
|
"onfocus=",
|
|
"onblur=",
|
|
] as const;
|
|
|
|
/**
|
|
* Validate SVG content for dangerous patterns
|
|
*/
|
|
export function containsDangerousSVGContent(content: string): boolean {
|
|
return DANGEROUS_SVG_PATTERNS.some((pattern) => content.includes(pattern));
|
|
}
|
|
|
|
/**
|
|
* Base64 regex pattern that matches valid base64 strings
|
|
* - Matches complete base64 groups of 4 characters
|
|
* - Handles proper padding with = characters
|
|
* - Supports both padded and unpadded forms correctly
|
|
*/
|
|
const BASE64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}(?:==)?|[A-Za-z0-9+/]{3}=)?$/;
|
|
|
|
/**
|
|
* Validate base64 string format using strict regex
|
|
*/
|
|
export function isValidBase64(str: string): boolean {
|
|
return BASE64_REGEX.test(str);
|
|
}
|