Files
thrilltrack-explorer/src/lib/validation.ts
gpt-engineer-app[bot] 64c29348ce Add disallowed usernames
2025-09-28 17:57:48 +00:00

59 lines
2.4 KiB
TypeScript

import { z } from 'zod';
// Reserved usernames for security and system purposes
const FORBIDDEN_USERNAMES = new Set([
// System/Admin accounts
'admin', 'administrator', 'moderator', 'mod', 'owner', 'root', 'system', 'support',
'staff', 'team', 'official', 'verified', 'bot', 'api', 'service',
// Company/Brand protection
'thrillwiki', 'lovable', 'supabase', 'cloudflare',
// Common system routes/pages
'www', 'mail', 'email', 'ftp', 'blog', 'forum', 'shop', 'store', 'app', 'mobile',
'help', 'support', 'contact', 'about', 'terms', 'privacy', 'security', 'legal',
'login', 'signup', 'register', 'signin', 'signout', 'logout', 'auth', 'oauth',
'profile', 'profiles', 'user', 'users', 'account', 'accounts', 'settings',
'dashboard', 'console', 'panel', 'manage', 'management',
// Technical terms
'null', 'undefined', 'true', 'false', 'delete', 'remove', 'test', 'demo',
'localhost', 'example', 'temp', 'temporary', 'guest', 'anonymous', 'anon',
// Offensive prevention (basic)
'fuck', 'shit', 'damn', 'hell', 'ass', 'bitch', 'bastard', 'crap',
'nazi', 'hitler', 'stalin', 'terrorist', 'kill', 'death', 'murder',
// Impersonation prevention
'ceo', 'president', 'manager', 'director', 'executive', 'founder'
]);
export const usernameSchema = z
.string()
.min(3, 'Username must be at least 3 characters')
.max(30, 'Username must be less than 30 characters')
.regex(/^[a-zA-Z0-9_-]+$/, 'Username can only contain letters, numbers, underscores, and hyphens')
.regex(/^[a-zA-Z0-9]/, 'Username must start with a letter or number')
.transform(val => val.toLowerCase())
.refine(val => !FORBIDDEN_USERNAMES.has(val), 'This username is not allowed');
// Display name validation with content filtering
export const displayNameSchema = z
.string()
.max(100, 'Display name must be less than 100 characters')
.refine(val => {
if (!val) return true;
const lowerVal = val.toLowerCase();
// Check for basic offensive content in display names
const offensiveTerms = ['nazi', 'hitler', 'terrorist', 'kill', 'murder', 'fuck', 'shit'];
return !offensiveTerms.some(term => lowerVal.includes(term));
}, 'Display name contains inappropriate content')
.optional();
export const profileEditSchema = z.object({
username: usernameSchema,
display_name: displayNameSchema,
bio: z.string().max(500, 'Bio must be less than 500 characters').optional(),
});
export type ProfileEditForm = z.infer<typeof profileEditSchema>;