Files
balikci/backend/src/services/token.service.js
salvacybersec f86cda2978 Domain support
2025-11-10 20:01:41 +03:00

153 lines
4.2 KiB
JavaScript

const { TrackingToken, Company, MailTemplate } = require('../models');
const { generateTrackingToken } = require('../utils/tokenGenerator');
const mailService = require('./mail.service');
const logger = require('../config/logger');
class TokenService {
async createToken(data) {
const { company_id, target_email, employee_name, template_type, from_name } = data;
// Generate unique token
let token = generateTrackingToken();
let isUnique = false;
let attempts = 0;
// Ensure token is unique
while (!isUnique && attempts < 5) {
const existing = await TrackingToken.findOne({ where: { token } });
if (!existing) {
isUnique = true;
} else {
token = generateTrackingToken();
attempts++;
}
}
if (!isUnique) {
throw new Error('Failed to generate unique token');
}
// Get company and template
const company = await Company.findByPk(company_id);
if (!company) {
throw new Error('Company not found');
}
const template = await MailTemplate.findOne({ where: { template_type } });
if (!template) {
throw new Error('Mail template not found');
}
// Create tracking token
const trackingToken = await TrackingToken.create({
token,
company_id,
target_email,
employee_name,
template_type,
from_name: from_name || null,
mail_subject: template.subject_template.replace('{{company_name}}', company.name),
});
// Update company stats
await company.increment('total_tokens');
logger.info(`Token created: ${token} for ${target_email}`);
return trackingToken;
}
async sendMail(tokenId) {
const token = await TrackingToken.findByPk(tokenId, {
include: [{ model: Company, as: 'company' }],
});
if (!token) {
throw new Error('Token not found');
}
if (token.mail_sent) {
throw new Error('Mail already sent for this token');
}
// Get mail template
const template = await MailTemplate.findOne({
where: { template_type: token.template_type },
});
if (!template) {
throw new Error('Mail template not found');
}
// Get base URL from settings or env
const { Settings } = require('../models');
const baseUrlSetting = await Settings.findOne({ where: { key: 'base_url' } });
const baseUrl = baseUrlSetting?.value || process.env.BASE_URL || 'http://localhost:3000';
// Prepare template data
const trackingUrl = `${baseUrl}/t/${token.token}`;
const currentDate = new Date().toLocaleDateString('tr-TR', {
year: 'numeric',
month: 'long',
day: 'numeric',
});
const currentYear = new Date().getFullYear();
const templateData = {
company_name: token.company.name,
employee_name: token.employee_name,
tracking_url: trackingUrl,
current_date: currentDate,
current_year: currentYear,
};
// Render mail body
const htmlBody = mailService.renderTemplate(template.body_html, templateData);
const subject = mailService.renderTemplate(template.subject_template, templateData);
// Send mail with custom from_name if provided
await mailService.sendMail(token.target_email, subject, htmlBody, token.from_name);
// Update token
await token.update({
mail_sent: true,
sent_at: new Date(),
});
logger.info(`Mail sent for token: ${token.token} to ${token.target_email}`);
return token;
}
async updateCompanyStats(companyId) {
const company = await Company.findByPk(companyId);
if (!company) return;
// Count tokens
const totalTokens = await TrackingToken.count({
where: { company_id: companyId },
});
const clickedTokens = await TrackingToken.count({
where: { company_id: companyId, clicked: true },
});
const totalClicks = await TrackingToken.sum('click_count', {
where: { company_id: companyId },
});
const clickRate = totalTokens > 0 ? ((clickedTokens / totalTokens) * 100).toFixed(2) : 0;
await company.update({
total_tokens: totalTokens,
total_clicks: totalClicks || 0,
click_rate: clickRate,
});
logger.info(`Company stats updated for: ${company.name}`);
}
}
module.exports = new TokenService();