Files
url_tracker_tool/apps/api/dist/routes/analysis.routes.js
Andrei 58f8093689 Rebrand from 'Redirect Intelligence v2' to 'URL Tracker Tool V2' throughout UI
- Updated all component headers and documentation
- Changed navbar and footer branding
- Updated homepage hero badge
- Modified page title in index.html
- Simplified footer text to 'Built with ❤️'
- Consistent V2 capitalization across all references
2025-08-19 19:12:23 +00:00

316 lines
12 KiB
JavaScript

"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