| | |
| | |
| | |
| | |
| |
|
| | const logger = require('../utils/logger') |
| | const { CLIENT_DEFINITIONS, getAllClientDefinitions } = require('./clientDefinitions') |
| | const ClaudeCodeValidator = require('./clients/claudeCodeValidator') |
| | const GeminiCliValidator = require('./clients/geminiCliValidator') |
| | const CodexCliValidator = require('./clients/codexCliValidator') |
| | const DroidCliValidator = require('./clients/droidCliValidator') |
| |
|
| | |
| | |
| | |
| | class ClientValidator { |
| | |
| | |
| | |
| | |
| | |
| | static getValidator(clientId) { |
| | switch (clientId) { |
| | case 'claude_code': |
| | return ClaudeCodeValidator |
| | case 'gemini_cli': |
| | return GeminiCliValidator |
| | case 'codex_cli': |
| | return CodexCliValidator |
| | case 'droid_cli': |
| | return DroidCliValidator |
| | default: |
| | logger.warn(`Unknown client ID: ${clientId}`) |
| | return null |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | static getSupportedClients() { |
| | return ['claude_code', 'gemini_cli', 'codex_cli', 'droid_cli'] |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | static validateClient(clientId, req) { |
| | const validator = this.getValidator(clientId) |
| |
|
| | if (!validator) { |
| | logger.warn(`No validator found for client: ${clientId}`) |
| | return false |
| | } |
| |
|
| | try { |
| | return validator.validate(req) |
| | } catch (error) { |
| | logger.error(`Error validating client ${clientId}:`, error) |
| | return false |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | static validateRequest(allowedClients, req) { |
| | const userAgent = req.headers['user-agent'] || '' |
| | const clientIP = req.ip || req.connection?.remoteAddress || 'unknown' |
| |
|
| | |
| | logger.api(`🔍 Starting client validation for User-Agent: "${userAgent}"`) |
| | logger.api(` Allowed clients: ${allowedClients.join(', ')}`) |
| | logger.api(` Request from IP: ${clientIP}`) |
| |
|
| | |
| | for (const clientId of allowedClients) { |
| | const validator = this.getValidator(clientId) |
| |
|
| | if (!validator) { |
| | logger.warn(`Skipping unknown client ID: ${clientId}`) |
| | continue |
| | } |
| |
|
| | logger.debug(`Checking against ${validator.getName()}...`) |
| |
|
| | try { |
| | if (validator.validate(req)) { |
| | |
| | logger.api(`✅ Client validated: ${validator.getName()} (${clientId})`) |
| | logger.api(` Matched User-Agent: "${userAgent}"`) |
| |
|
| | return { |
| | allowed: true, |
| | matchedClient: clientId, |
| | clientName: validator.getName(), |
| | clientInfo: Object.values(CLIENT_DEFINITIONS).find((def) => def.id === clientId) |
| | } |
| | } |
| | } catch (error) { |
| | logger.error(`Error during validation for ${clientId}:`, error) |
| | continue |
| | } |
| | } |
| |
|
| | |
| | logger.api(`❌ No matching client found for User-Agent: "${userAgent}"`) |
| | return { |
| | allowed: false, |
| | matchedClient: null, |
| | reason: 'No matching client found' |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | static getClientInfo(clientId) { |
| | const validator = this.getValidator(clientId) |
| | if (!validator) { |
| | return null |
| | } |
| |
|
| | return validator.getInfo() |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | static getAvailableClients() { |
| | |
| | return getAllClientDefinitions() |
| | } |
| | } |
| |
|
| | module.exports = ClientValidator |
| |
|