first commit: Complete phishing test management panel with Node.js backend and React frontend
This commit is contained in:
111
backend/src/controllers/tracking.controller.js
Normal file
111
backend/src/controllers/tracking.controller.js
Normal file
@@ -0,0 +1,111 @@
|
||||
const { TrackingToken, ClickLog, Company } = require('../models');
|
||||
const { getGeoLocation } = require('../utils/geoip');
|
||||
const { parseUserAgent } = require('../utils/userAgentParser');
|
||||
const telegramService = require('../services/telegram.service');
|
||||
const tokenService = require('../services/token.service');
|
||||
const logger = require('../config/logger');
|
||||
|
||||
exports.trackClick = async (req, res, next) => {
|
||||
try {
|
||||
const { token } = req.params;
|
||||
|
||||
// Find token
|
||||
const trackingToken = await TrackingToken.findOne({
|
||||
where: { token },
|
||||
include: [{ model: Company, as: 'company' }],
|
||||
});
|
||||
|
||||
if (!trackingToken) {
|
||||
logger.warn(`Invalid token accessed: ${token}`);
|
||||
return res.redirect(process.env.BASE_URL || 'https://google.com');
|
||||
}
|
||||
|
||||
// Get IP address
|
||||
const ipAddress = req.headers['x-forwarded-for']?.split(',')[0].trim()
|
||||
|| req.connection.remoteAddress
|
||||
|| req.socket.remoteAddress
|
||||
|| req.ip;
|
||||
|
||||
// Get user agent
|
||||
const userAgent = req.headers['user-agent'] || '';
|
||||
const referer = req.headers['referer'] || req.headers['referrer'] || null;
|
||||
|
||||
// Parse geo location
|
||||
const geoData = getGeoLocation(ipAddress);
|
||||
|
||||
// Parse user agent
|
||||
const uaData = parseUserAgent(userAgent);
|
||||
|
||||
// Create click log
|
||||
const clickLog = await ClickLog.create({
|
||||
token_id: trackingToken.id,
|
||||
ip_address: ipAddress,
|
||||
country: geoData.country,
|
||||
city: geoData.city,
|
||||
latitude: geoData.latitude,
|
||||
longitude: geoData.longitude,
|
||||
user_agent: userAgent,
|
||||
browser: uaData.browser,
|
||||
os: uaData.os,
|
||||
device: uaData.device,
|
||||
referer,
|
||||
});
|
||||
|
||||
// Update token stats
|
||||
const isFirstClick = !trackingToken.clicked;
|
||||
await trackingToken.update({
|
||||
clicked: true,
|
||||
click_count: trackingToken.click_count + 1,
|
||||
first_click_at: isFirstClick ? new Date() : trackingToken.first_click_at,
|
||||
last_click_at: new Date(),
|
||||
});
|
||||
|
||||
// Update company stats
|
||||
await tokenService.updateCompanyStats(trackingToken.company_id);
|
||||
|
||||
// Get updated company for Telegram notification
|
||||
const company = await Company.findByPk(trackingToken.company_id);
|
||||
|
||||
// Send Telegram notification
|
||||
try {
|
||||
const timestamp = new Date().toLocaleString('tr-TR', {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit',
|
||||
});
|
||||
|
||||
await telegramService.sendNotification({
|
||||
companyName: company.name,
|
||||
targetEmail: trackingToken.target_email,
|
||||
employeeName: trackingToken.employee_name,
|
||||
ipAddress,
|
||||
country: geoData.country,
|
||||
city: geoData.city,
|
||||
browser: uaData.browser,
|
||||
os: uaData.os,
|
||||
timestamp,
|
||||
clickCount: trackingToken.click_count + 1,
|
||||
companyTotalClicks: company.total_clicks,
|
||||
companyTotalTokens: company.total_tokens,
|
||||
});
|
||||
|
||||
await clickLog.update({ telegram_sent: true });
|
||||
} catch (telegramError) {
|
||||
logger.error('Telegram notification failed:', telegramError);
|
||||
// Don't fail the request if Telegram fails
|
||||
}
|
||||
|
||||
logger.info(`Click tracked: ${token} from ${ipAddress} (${geoData.city}, ${geoData.country})`);
|
||||
|
||||
// Redirect to landing page
|
||||
res.redirect('/landing.html');
|
||||
} catch (error) {
|
||||
logger.error('Tracking error:', error);
|
||||
// Even on error, redirect to something
|
||||
res.redirect(process.env.BASE_URL || 'https://google.com');
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user