"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const express_1 = __importDefault(require("express")); const zod_1 = require("zod"); const express_rate_limit_1 = __importDefault(require("express-rate-limit")); const ssl_analyzer_service_1 = require("../services/ssl-analyzer.service"); const seo_analyzer_service_1 = require("../services/seo-analyzer.service"); const security_analyzer_service_1 = require("../services/security-analyzer.service"); const auth_middleware_1 = require("../middleware/auth.middleware"); const logger_1 = require("../lib/logger"); const prisma_1 = require("../lib/prisma"); const router = express_1.default.Router(); const sslAnalyzer = new ssl_analyzer_service_1.SSLAnalyzerService(); const seoAnalyzer = new seo_analyzer_service_1.SEOAnalyzerService(); const securityAnalyzer = new security_analyzer_service_1.SecurityAnalyzerService(); const analysisLimiter = (0, express_rate_limit_1.default)({ windowMs: 60 * 60 * 1000, max: 100, message: { success: false, error: 'Analysis rate limit exceeded', message: 'Too many analysis requests. Please try again later.' }, standardHeaders: true, legacyHeaders: false, keyGenerator: (req) => { return req.user ? `user:${req.user.id}` : `ip:${req.ip}`; }, }); const analyzeUrlSchema = zod_1.z.object({ url: zod_1.z.string().url('Invalid URL format'), }); router.post('/ssl', auth_middleware_1.optionalAuth, analysisLimiter, async (req, res) => { try { const { url } = analyzeUrlSchema.parse(req.body); let analyzeUrl = url; if (!analyzeUrl.startsWith('http://') && !analyzeUrl.startsWith('https://')) { analyzeUrl = 'https://' + analyzeUrl; } if (!analyzeUrl.startsWith('https://')) { return res.status(400).json({ success: false, error: 'Invalid URL for SSL analysis', message: 'SSL analysis requires HTTPS URLs' }); } const result = await sslAnalyzer.analyzeSSL(analyzeUrl); logger_1.logger.info(`SSL analysis completed for: ${analyzeUrl}`, { userId: req.user?.id, securityScore: result.securityScore, warningsCount: result.warnings.length }); res.json({ success: true, status: 200, data: { analysis: result, url: analyzeUrl, }, meta: { version: 'v2', analysisType: 'ssl', timestamp: new Date().toISOString(), } }); } catch (error) { logger_1.logger.error('SSL analysis failed:', error); if (error instanceof zod_1.z.ZodError) { return res.status(400).json({ success: false, error: 'Validation error', message: error.errors[0]?.message || 'Invalid input', details: error.errors }); } res.status(500).json({ success: false, error: 'SSL analysis failed', message: error instanceof Error ? error.message : 'Unknown error occurred' }); } }); router.post('/seo', auth_middleware_1.optionalAuth, analysisLimiter, async (req, res) => { try { const { url } = analyzeUrlSchema.parse(req.body); let analyzeUrl = url; if (!analyzeUrl.startsWith('http://') && !analyzeUrl.startsWith('https://')) { analyzeUrl = 'https://' + analyzeUrl; } const result = await seoAnalyzer.analyzeSEO(analyzeUrl); logger_1.logger.info(`SEO analysis completed for: ${analyzeUrl}`, { userId: req.user?.id, score: result.score, robotsStatus: result.flags.robotsTxtStatus, noindex: result.flags.noindex }); res.json({ success: true, status: 200, data: { analysis: result, url: analyzeUrl, }, meta: { version: 'v2', analysisType: 'seo', timestamp: new Date().toISOString(), } }); } catch (error) { logger_1.logger.error('SEO analysis failed:', error); if (error instanceof zod_1.z.ZodError) { return res.status(400).json({ success: false, error: 'Validation error', message: error.errors[0]?.message || 'Invalid input', details: error.errors }); } res.status(500).json({ success: false, error: 'SEO analysis failed', message: error instanceof Error ? error.message : 'Unknown error occurred' }); } }); router.post('/security', auth_middleware_1.optionalAuth, analysisLimiter, async (req, res) => { try { const { url } = analyzeUrlSchema.parse(req.body); let analyzeUrl = url; if (!analyzeUrl.startsWith('http://') && !analyzeUrl.startsWith('https://')) { analyzeUrl = 'https://' + analyzeUrl; } const result = await securityAnalyzer.analyzeSecurity(analyzeUrl); logger_1.logger.info(`Security analysis completed for: ${analyzeUrl}`, { userId: req.user?.id, securityScore: result.securityScore, safeBrowsing: result.safeBrowsing.status, vulnerabilityCount: result.vulnerabilities.length }); res.json({ success: true, status: 200, data: { analysis: result, url: analyzeUrl, }, meta: { version: 'v2', analysisType: 'security', timestamp: new Date().toISOString(), } }); } catch (error) { logger_1.logger.error('Security analysis failed:', error); if (error instanceof zod_1.z.ZodError) { return res.status(400).json({ success: false, error: 'Validation error', message: error.errors[0]?.message || 'Invalid input', details: error.errors }); } res.status(500).json({ success: false, error: 'Security analysis failed', message: error instanceof Error ? error.message : 'Unknown error occurred' }); } }); router.post('/comprehensive', auth_middleware_1.optionalAuth, analysisLimiter, async (req, res) => { try { const { url } = analyzeUrlSchema.parse(req.body); let analyzeUrl = url; if (!analyzeUrl.startsWith('http://') && !analyzeUrl.startsWith('https://')) { analyzeUrl = 'https://' + analyzeUrl; } logger_1.logger.info(`Starting comprehensive analysis for: ${analyzeUrl}`, { userId: req.user?.id }); const [sslResult, seoResult, securityResult] = await Promise.allSettled([ analyzeUrl.startsWith('https://') ? sslAnalyzer.analyzeSSL(analyzeUrl) : Promise.resolve(null), seoAnalyzer.analyzeSEO(analyzeUrl), securityAnalyzer.analyzeSecurity(analyzeUrl), ]); const analysis = { ssl: sslResult.status === 'fulfilled' ? sslResult.value : { error: sslResult.status === 'rejected' ? sslResult.reason?.message : 'SSL analysis failed' }, seo: seoResult.status === 'fulfilled' ? seoResult.value : { error: seoResult.status === 'rejected' ? seoResult.reason?.message : 'SEO analysis failed' }, security: securityResult.status === 'fulfilled' ? securityResult.value : { error: securityResult.status === 'rejected' ? securityResult.reason?.message : 'Security analysis failed' }, }; const scores = [ analysis.ssl && 'securityScore' in analysis.ssl ? analysis.ssl.securityScore : 0, analysis.seo && 'score' in analysis.seo ? analysis.seo.score : 0, analysis.security && 'securityScore' in analysis.security ? analysis.security.securityScore : 0, ].filter(score => score > 0); const overallScore = scores.length > 0 ? Math.round(scores.reduce((a, b) => a + b, 0) / scores.length) : 0; logger_1.logger.info(`Comprehensive analysis completed for: ${analyzeUrl}`, { userId: req.user?.id, overallScore, sslSuccess: sslResult.status === 'fulfilled', seoSuccess: seoResult.status === 'fulfilled', securitySuccess: securityResult.status === 'fulfilled' }); res.json({ success: true, status: 200, data: { analysis, summary: { overallScore, analysesCompleted: scores.length, totalAnalyses: 3, }, url: analyzeUrl, }, meta: { version: 'v2', analysisType: 'comprehensive', timestamp: new Date().toISOString(), } }); } catch (error) { logger_1.logger.error('Comprehensive analysis failed:', error); if (error instanceof zod_1.z.ZodError) { return res.status(400).json({ success: false, error: 'Validation error', message: error.errors[0]?.message || 'Invalid input', details: error.errors }); } res.status(500).json({ success: false, error: 'Comprehensive analysis failed', message: error instanceof Error ? error.message : 'Unknown error occurred' }); } }); router.get('/check/:checkId', auth_middleware_1.optionalAuth, async (req, res) => { try { const { checkId } = req.params; if (!checkId) { return res.status(400).json({ success: false, error: 'Check ID required' }); } const check = await prisma_1.prisma.check.findUnique({ where: { id: checkId }, include: { hops: { orderBy: { hopIndex: 'asc' } }, sslInspections: true, seoFlags: true, securityFlags: true, } }); if (!check) { return res.status(404).json({ success: false, error: 'Check not found', message: 'The requested check does not exist or you do not have access to it' }); } res.json({ success: true, status: 200, data: { check: { id: check.id, inputUrl: check.inputUrl, finalUrl: check.finalUrl, status: check.status, startedAt: check.startedAt, finishedAt: check.finishedAt, totalTimeMs: check.totalTimeMs, }, analysis: { ssl: check.sslInspections, seo: check.seoFlags, security: check.securityFlags, }, hops: check.hops, }, meta: { version: 'v2', checkId: check.id, timestamp: new Date().toISOString(), } }); } catch (error) { logger_1.logger.error('Failed to retrieve check analysis:', error); res.status(500).json({ success: false, error: 'Failed to retrieve analysis', message: error instanceof Error ? error.message : 'Unknown error occurred' }); } }); exports.default = router; //# sourceMappingURL=analysis.routes.js.map