diff --git a/src/i18n/index.ts b/src/i18n/index.ts index c91bd2e..e48618c 100644 --- a/src/i18n/index.ts +++ b/src/i18n/index.ts @@ -47,6 +47,10 @@ export class I18nService { let value: string | TranslationData = translations; for (const key of keys) { + if (typeof value === 'string') { + // If we hit a string before traversing all keys, the path is invalid + break; + } value = value?.[key]; if (value === undefined) { // Fallback to default locale if key not found diff --git a/src/routes/admin.ts b/src/routes/admin.ts index 4a55a8d..3bb7cc8 100644 --- a/src/routes/admin.ts +++ b/src/routes/admin.ts @@ -74,7 +74,16 @@ type AuthMiddleware = (req: Request, res: Response, next: NextFunction) => void; export default ( locationModel: Location, profanityWordModel: ProfanityWord, - profanityFilter: ProfanityFilterService, + profanityFilter: ProfanityFilterService | { + containsProfanity(): boolean; + analyzeProfanity(text: string): any; + filterProfanity(text: string): string; + addCustomWord(word: string, severity: string, category: string, createdBy?: string): Promise; + removeCustomWord(wordId: number): Promise; + updateCustomWord(wordId: number, updates: any): Promise; + getCustomWords(): Promise; + loadCustomWords(): Promise; + }, authenticateAdmin: AuthMiddleware ): Router => { const router = express.Router(); diff --git a/src/routes/locations.ts b/src/routes/locations.ts index 6c97fff..61fc2d2 100644 --- a/src/routes/locations.ts +++ b/src/routes/locations.ts @@ -14,7 +14,11 @@ interface LocationPostRequest extends Request { } -export default (locationModel: Location, profanityFilter: ProfanityFilterService): Router => { +export default (locationModel: Location, profanityFilter: ProfanityFilterService | { + containsProfanity(): boolean; + analyzeProfanity(text: string): any; + filterProfanity(text: string): string; +}): Router => { const router = express.Router(); // Rate limiting for location submissions to prevent abuse @@ -220,7 +224,7 @@ export default (locationModel: Location, profanityFilter: ProfanityFilterService details: { severity: analysis.severity, wordCount: analysis.count, - detectedCategories: [...new Set(analysis.matches.map(m => m.category))] + detectedCategories: [...new Set(analysis.matches.map((m: any) => m.category))] } }); return; diff --git a/src/server.ts b/src/server.ts index 587d9bf..89e24a6 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,3 +1,4 @@ +/// import dotenv from 'dotenv'; import express, { Request, Response, NextFunction, Application } from 'express'; import cors from 'cors'; @@ -88,23 +89,15 @@ function createFallbackFilter(): FallbackFilter { filterProfanity: (text: string): string => text || '', // Database management methods used by admin routes - addCustomWord: async (word: string, severity: string, category: string, createdBy?: string) => ({ - id: null, - word: word || null, - severity: severity || null, - category: category || null, - createdBy: createdBy || null, - success: false, - error: 'Profanity filter not available - please check server configuration' - }), - removeCustomWord: async () => ({ - success: false, - error: 'Profanity filter not available - please check server configuration' - }), - updateCustomWord: async () => ({ - success: false, - error: 'Profanity filter not available - please check server configuration' - }), + addCustomWord: async (): Promise => { + throw new Error('Profanity filter not available - please check server configuration'); + }, + removeCustomWord: async (): Promise<{ deleted: boolean; changes: number }> => { + throw new Error('Profanity filter not available - please check server configuration'); + }, + updateCustomWord: async (): Promise => { + throw new Error('Profanity filter not available - please check server configuration'); + }, getCustomWords: async (): Promise => [], loadCustomWords: async (): Promise => {},