Files
speckle-server/packages/server/modules/shared/helpers/sanitization.ts
T
Kristaps Fabians Geikins 1d2a594f0a chore: upgrade TS 5.2 -> 5.7.3 & ESLint to 9.20.1 (#4032)
* chore: upgrade TS 5.2 -> 5.7.3

* vite dts fix

* lint fix

* resolutions fix

* ui comp build fix

* precommit fix?

* latest eslint version

* autoloader fix

* undo unnecessary viewer change

* eslint fixes fe2 + trying disabled type linting

* lint fixes
2025-02-20 14:18:18 +02:00

56 lines
1.5 KiB
TypeScript

import { MaybeNullOrUndefined, Nullable } from '@speckle/shared'
import { BaseError } from '@/modules/shared/errors'
const base64ImagePattern = /^data:image\/[a-zA-Z+.-]+;base64,[a-zA-Z0-9+/]+=*$/
class InvalidUrlError extends BaseError {
static code = 'INVALID_URL_ERROR'
static defaultMessage = 'Invalid URL'
static statusCode = 400
}
const validateImageUrl = (url: string): string => {
// Parse the URL to ensure it's valid
let parsedUrl: URL
try {
parsedUrl = new URL(url)
} catch {
throw new InvalidUrlError('Invalid URL')
}
// Only allow http: and https: protocols
if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {
throw new InvalidUrlError('Invalid protocol')
}
// Check the file extension to ensure it's an image
const allowedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'svg', 'webp']
const extension = parsedUrl.pathname.split('.').pop()?.toLowerCase() || 'invalid'
if (!allowedExtensions.includes(extension)) {
throw new InvalidUrlError('Invalid file type')
}
// If all checks pass, return the sanitized URL
return parsedUrl.href
}
/**
* Ensure that image refers to a valid image URL or a base64 data string
*/
export const sanitizeImageUrl = (
image: MaybeNullOrUndefined<string>
): Nullable<string> => {
if (!image?.length) return null
// If the image is a base64 string, return it as is
if (base64ImagePattern.test(image)) return image
try {
return validateImageUrl(image)
} catch {
// invalid url
}
return null
}