mirror of
https://github.com/zen-browser/rices.git
synced 2025-07-07 08:55:40 +02:00
feat: enhance slug generation and validation
- Add robust error handling for `generateSlug`, throwing `BadRequestException` on invalid input. - Improve error messages to provide clearer feedback in case of failures.
This commit is contained in:
parent
6609122f8a
commit
2b8909c17f
5 changed files with 81 additions and 12 deletions
|
@ -44,6 +44,7 @@
|
|||
"@supabase/supabase-js": "^2.47.10",
|
||||
"@types/express": "^5.0.0",
|
||||
"@types/jest": "^29.5.14",
|
||||
"@types/leo-profanity": "^1.5.4",
|
||||
"@types/node": "^20.3.1",
|
||||
"@types/supertest": "^6.0.2",
|
||||
"@types/uuid": "^10.0.0",
|
||||
|
@ -53,6 +54,7 @@
|
|||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-prettier": "^5.0.0",
|
||||
"jest": "^29.7.0",
|
||||
"leo-profanity": "^1.7.0",
|
||||
"prettier": "^3.0.0",
|
||||
"source-map-support": "^0.5.21",
|
||||
"supertest": "^7.0.0",
|
||||
|
|
|
@ -35,6 +35,13 @@ export class RicesService {
|
|||
throw new BadRequestException('The request body must be a string.');
|
||||
}
|
||||
|
||||
try {
|
||||
this.validateJsonStructure(content);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
} catch (e) {
|
||||
throw new BadRequestException('Invalid json request');
|
||||
}
|
||||
|
||||
// Validate lengths
|
||||
if (name.length > 75) {
|
||||
throw new BadRequestException(
|
||||
|
@ -49,13 +56,11 @@ export class RicesService {
|
|||
}
|
||||
|
||||
// Parse version and OS from User-Agent
|
||||
const userAgentRegex = /ZenBrowser\/(\d+\.\d+\.\d+) \((.+)\)/;
|
||||
const userAgentRegex = /ZenBrowser\/(\d+\.\d+\.\d.\d+) \((.+)\)/;
|
||||
const match = userAgent.match(userAgentRegex);
|
||||
|
||||
if (!match) {
|
||||
throw new BadRequestException(
|
||||
'Invalid User-Agent format. Expected format: ZenBrowser/<version> (<OS>).',
|
||||
);
|
||||
throw new BadRequestException('Invalid request');
|
||||
}
|
||||
|
||||
const [, version, os] = match;
|
||||
|
@ -80,9 +85,16 @@ export class RicesService {
|
|||
);
|
||||
}
|
||||
|
||||
const slug = `${generateSlug(name)}-${uuidv4()}`;
|
||||
const token = uuidv4();
|
||||
let slug: string;
|
||||
try {
|
||||
slug = `${generateSlug(name)}-${uuidv4()}`;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
} catch (e) {
|
||||
// If generateSlug throws an error, rethrow as a BadRequestException
|
||||
throw new BadRequestException(`Invalid name provided`);
|
||||
}
|
||||
|
||||
const token = uuidv4();
|
||||
const encodedContent = Buffer.from(content).toString('base64');
|
||||
|
||||
const metadata = {
|
||||
|
@ -154,13 +166,18 @@ export class RicesService {
|
|||
}
|
||||
|
||||
// Parse version and OS from User-Agent
|
||||
const userAgentRegex = /ZenBrowser\/(\d+\.\d+\.\d+) \((.+)\)/;
|
||||
const userAgentRegex = /ZenBrowser\/(\d+\.\d+\.\d.\d+) \((.+)\)/;
|
||||
const match = userAgent.match(userAgentRegex);
|
||||
|
||||
if (!match) {
|
||||
throw new BadRequestException(
|
||||
'Invalid User-Agent format. Expected format: ZenBrowser/<version> (<OS>).',
|
||||
);
|
||||
throw new BadRequestException('Invalid request');
|
||||
}
|
||||
|
||||
try {
|
||||
this.validateJsonStructure(content);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
} catch (e) {
|
||||
throw new BadRequestException('Invalid json request');
|
||||
}
|
||||
|
||||
const [, version, os] = match;
|
||||
|
@ -280,4 +297,39 @@ export class RicesService {
|
|||
throw new Error('Failed to remove rice by moderation');
|
||||
}
|
||||
}
|
||||
|
||||
validateJsonStructure(jsonString: string): boolean {
|
||||
const requiredKeys: string[] = [
|
||||
'userChrome',
|
||||
'userContent',
|
||||
'enabledMods',
|
||||
'preferences',
|
||||
'workspaceThemes',
|
||||
];
|
||||
|
||||
let json: Record<string, unknown>;
|
||||
|
||||
// Validate JSON string
|
||||
try {
|
||||
json = JSON.parse(jsonString);
|
||||
} catch {
|
||||
throw new BadRequestException('Invalid JSON string.');
|
||||
}
|
||||
|
||||
// Ensure the parsed JSON is an object
|
||||
if (typeof json !== 'object' || json === null) {
|
||||
throw new BadRequestException('The parsed JSON is not a valid object.');
|
||||
}
|
||||
|
||||
// Check for missing keys
|
||||
const missingKeys = requiredKeys.filter((key) => !(key in json));
|
||||
|
||||
if (missingKeys.length > 0) {
|
||||
throw new BadRequestException(
|
||||
`The JSON is missing the following required keys: ${missingKeys.join(', ')}`,
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import * as leoProfanity from 'leo-profanity';
|
||||
|
||||
export function generateSlug(name: string): string {
|
||||
// Ensure the input is a string and trim whitespace
|
||||
if (typeof name !== 'string') {
|
||||
|
@ -5,6 +7,9 @@ export function generateSlug(name: string): string {
|
|||
}
|
||||
const sanitizedInput = name.trim();
|
||||
|
||||
// Configure the profanity filter
|
||||
leoProfanity.loadDictionary('en'); // Ensure the dictionary is loaded
|
||||
|
||||
// Replace accented characters with their unaccented counterparts
|
||||
const normalized = sanitizedInput
|
||||
.normalize('NFD')
|
||||
|
@ -21,5 +26,15 @@ export function generateSlug(name: string): string {
|
|||
throw new Error('Generated slug is empty');
|
||||
}
|
||||
|
||||
// Split the slug into individual words
|
||||
const words = slug.split('-');
|
||||
|
||||
// Check each word for inappropriate content
|
||||
words.forEach((word) => {
|
||||
if (leoProfanity.check(word)) {
|
||||
throw new Error(`The word "${word}" is inappropriate.`);
|
||||
}
|
||||
});
|
||||
|
||||
return slug;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ POST {{baseUrl}}/rices
|
|||
Content-Type: application/json
|
||||
X-Zen-Rice-Name: cool-zenrice-aurora2
|
||||
X-Zen-Rice-Author: jhon@doe.com
|
||||
User-Agent: ZenBrowser/1.0.0 (EndeavourOS x86_64)
|
||||
User-Agent: ZenBrowser/1.0.0.0 (EndeavourOS x86_64)
|
||||
|
||||
{
|
||||
"userChrome": "",
|
||||
|
|
|
@ -7,7 +7,7 @@ Content-Type: application/json
|
|||
x-zen-rices-token: {{previous_token}}
|
||||
X-Zen-Rice-Name: cool-zenrice-aurora2
|
||||
X-Zen-Rice-Author: jhon@doe.com
|
||||
User-Agent: ZenBrowser/1.0.0 (EndeavourOS x86_64)
|
||||
User-Agent: ZenBrowser/1.0.0.0 (EndeavourOS x86_64)
|
||||
|
||||
{
|
||||
"userChrome": "",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue