diff --git a/backend/src/controllers/ollama.controller.js b/backend/src/controllers/ollama.controller.js index 6670d70..4b5c0b7 100644 --- a/backend/src/controllers/ollama.controller.js +++ b/backend/src/controllers/ollama.controller.js @@ -2,6 +2,25 @@ const ollamaService = require('../services/ollama.service'); const { Settings, MailTemplate } = require('../models'); const logger = require('../utils/logger'); +/** + * Get available template themes + */ +exports.getThemes = async (req, res, next) => { + try { + const themes = ollamaService.getAvailableThemes(); + + res.json({ + success: true, + data: { + themes, + }, + }); + } catch (error) { + logger.error('Failed to get themes:', error); + next(error); + } +}; + /** * Test Ollama connection */ @@ -96,7 +115,7 @@ exports.updateSettings = async (req, res, next) => { */ exports.generateTemplate = async (req, res, next) => { try { - const { company_name, scenario, employee_info, custom_prompt, template_name, template_type } = req.body; + const { company_name, scenario, employee_info, custom_prompt, template_name, template_type, generate_html, template_theme } = req.body; // Validation if (!company_name || !scenario) { @@ -106,7 +125,7 @@ exports.generateTemplate = async (req, res, next) => { }); } - logger.info(`AI template generation requested for: ${company_name} - ${scenario}`); + logger.info(`AI template generation requested for: ${company_name} - ${scenario} (HTML: ${generate_html ? 'yes' : 'no'}, Theme: ${template_theme || 'red'})`); // Generate template using Ollama const templateData = await ollamaService.generateMailTemplate({ @@ -114,6 +133,8 @@ exports.generateTemplate = async (req, res, next) => { scenario, employee_info, custom_prompt, + generate_html: generate_html || false, + template_theme: template_theme || 'red', }); // Save to database if template_name is provided diff --git a/backend/src/routes/ollama.routes.js b/backend/src/routes/ollama.routes.js index 80a6d67..6adfe8c 100644 --- a/backend/src/routes/ollama.routes.js +++ b/backend/src/routes/ollama.routes.js @@ -6,6 +6,9 @@ const { requireAuth } = require('../middlewares/auth'); // All routes require authentication router.use(requireAuth); +// Get available template themes +router.get('/themes', ollamaController.getThemes); + // Test Ollama connection router.get('/test', ollamaController.testConnection); diff --git a/backend/src/services/ollama.service.js b/backend/src/services/ollama.service.js index d4e626c..dae07ba 100644 --- a/backend/src/services/ollama.service.js +++ b/backend/src/services/ollama.service.js @@ -9,32 +9,29 @@ class OllamaService { this.initialized = false; } - /** - * Initialize Ollama service with settings from database - */ async initialize() { + if (this.initialized && this.serverUrl && this.model) { + return; + } + try { - const serverUrlSetting = await Settings.findOne({ - where: { key: 'ollama_server_url' }, - }); - const modelSetting = await Settings.findOne({ - where: { key: 'ollama_model' }, + const settings = await Settings.findAll(); + const settingsMap = {}; + settings.forEach(s => { + settingsMap[s.key] = s.value; }); - this.serverUrl = serverUrlSetting?.value || process.env.OLLAMA_URL || 'http://localhost:11434'; - this.model = modelSetting?.value || process.env.OLLAMA_MODEL || 'llama3.2'; - + this.serverUrl = settingsMap['ollama_server_url'] || 'http://localhost:11434'; + this.model = settingsMap['ollama_model'] || 'llama3.2:latest'; this.initialized = true; - logger.info(`Ollama service initialized: ${this.serverUrl} with model ${this.model}`); + + logger.info(`Ollama initialized: ${this.serverUrl}, model: ${this.model}`); } catch (error) { - logger.error('Failed to initialize Ollama service:', error); - throw error; + logger.error('Failed to initialize Ollama:', error.message); + throw new Error('Ollama ayarları yüklenemedi'); } } - /** - * Test Ollama connection - */ async testConnection() { if (!this.initialized) { await this.initialize(); @@ -45,24 +42,22 @@ class OllamaService { timeout: 5000, }); + const models = response.data.models || []; + return { success: true, - models: response.data.models || [], message: 'Ollama bağlantısı başarılı', + models: models, }; } catch (error) { logger.error('Ollama connection test failed:', error.message); return { success: false, - error: error.message, - message: 'Ollama sunucusuna bağlanılamadı', + message: 'Ollama bağlantısı başarısız: ' + error.message, }; } } - /** - * List available models - */ async listModels() { if (!this.initialized) { await this.initialize(); @@ -80,23 +75,19 @@ class OllamaService { } } - /** - * Generate mail template using Ollama - * @param {Object} params - Template generation parameters - * @param {string} params.company_name - Target company name - * @param {string} params.scenario - Phishing scenario type - * @param {string} params.employee_info - Employee information (optional) - * @param {string} params.custom_prompt - Custom instructions (optional) - */ async generateMailTemplate(params) { if (!this.initialized) { await this.initialize(); } - const { company_name, scenario, employee_info, custom_prompt } = params; + const { company_name, scenario, employee_info, custom_prompt, generate_html = false } = params; - // Build the prompt - const systemPrompt = `Sen profesyonel bir siber güvenlik uzmanısın ve şirketler için phishing farkındalık testi mail şablonları oluşturuyorsun. + // Build the prompt based on mode + let systemPrompt, userPrompt; + + if (generate_html) { + // Full HTML generation mode + systemPrompt = `Sen profesyonel bir siber güvenlik uzmanısın ve şirketler için phishing farkındalık testi mail şablonları oluşturuyorsun. GÖREV: Gerçekçi, ikna edici ve profesyonel phishing test mailleri oluştur. @@ -106,42 +97,75 @@ KURALLAR: 3. İkna edici ve inandırıcı olmalı 4. Türkçe dil bilgisi ve imla kurallarına uygun olmalı 5. Kullanıcıyı aciliyet hissi ile harekete geçirmeli -6. Şirket logosu/branding için placeholder kullan ZORUNLU PLACEHOLDER'LAR: - {{company_name}} - Şirket adı -- {{employee_name}} - Çalışan adı (varsa "Sayın {{employee_name}}", yoksa "Sayın Yetkili") -- {{tracking_url}} - Tıklama linki (button veya link olarak) +- {{employee_name}} - Çalışan adı +- {{tracking_url}} - Tıklama linki -YANIT FORMATI: Sadece ve sadece JSON, hiçbir ek açıklama yok!`; +YANIT FORMATI: Sadece JSON!`; - let userPrompt = `Aşağıdaki bilgilere göre profesyonel bir phishing test mail şablonu oluştur: + userPrompt = `Aşağıdaki bilgilere göre profesyonel bir phishing test mail şablonu oluştur: 📌 HEDEF ŞİRKET: ${company_name} 📌 SENARYO: ${scenario}`; - if (employee_info) { + if (employee_info) userPrompt += `\n📌 HEDEF KİTLE: ${employee_info}`; + if (custom_prompt) userPrompt += `\n📌 ÖZEL TALİMATLAR: ${custom_prompt}`; + userPrompt += ` -📌 HEDEF KİTLE: ${employee_info}`; - } - if (custom_prompt) { - userPrompt += ` -📌 ÖZEL TALİMATLAR: ${custom_prompt}`; - } - - userPrompt += ` - -JSON YANIT FORMATI (AYNEN BU YAPIDA): +JSON YANIT FORMATI: { - "subject": "İkna edici mail konusu buraya (max 70 karakter)", - "body": "
Sayın {{employee_name}},
Mail içeriği buraya - ikna edici ve aciliyet vurgulu
Butona tıklat" + "subject": "İkna edici mail konusu (max 70 karakter)", + "body": "Sayın {{employee_name}},
İçerik
Tıklayın" } -⚠️ SADECE JSON DÖNDÜR! Açıklama, not, yorum YAZMA! -⚠️ Body içinde CSS stillendir, responsive yap! -⚠️ Konuyu çekici ve acil yap! -⚠️ HTML'i tam ve geçerli oluştur!`; +⚠️ SADECE JSON DÖNDÜR!`; + + } else { + // Text-only generation mode (RECOMMENDED) + systemPrompt = `Sen profesyonel bir siber güvenlik uzmanısın ve phishing test mail içerikleri yazıyorsun. + +GÖREV: İkna edici, gerçekçi ve profesyonel mail içerikleri yaz. + +KURALLAR: +1. Gerçek şirket maillerine benzer dil ve ton kullan +2. İkna edici ve inandırıcı ol +3. Türkçe dil bilgisi ve imla kurallarına uygun yaz +4. Kullanıcıyı aciliyet hissi ile harekete geçir +5. SADECE METİN İÇERİĞİ yaz, HTML TAG'LERİ KULLANMA! + +ZORUNLU PLACEHOLDER'LAR: +- {{company_name}} - Şirket adı +- {{employee_name}} - Çalışan adı +- {{tracking_url}} - Link metni (örn: "buraya tıklayın", "hesabınızı doğrulayın") + +YANIT FORMATI: Sadece JSON!`; + + userPrompt = `Aşağıdaki bilgilere göre profesyonel bir phishing test mail içeriği yaz: + +📌 HEDEF ŞİRKET: ${company_name} +📌 SENARYO: ${scenario}`; + + if (employee_info) userPrompt += `\n📌 HEDEF KİTLE: ${employee_info}`; + if (custom_prompt) userPrompt += `\n📌 ÖZEL TALİMATLAR: ${custom_prompt}`; + + userPrompt += ` + +JSON YANIT FORMATI: +{ + "subject": "İkna edici mail konusu (max 70 karakter)", + "body": "Mail içeriği buraya. Sayın {{employee_name}}, [mesajın içeriği]. Link metni için {{tracking_url}} placeholder'ını kullan. İmza kısmı." +} + +⚠️ ÖNEMLİ: +- Body içinde HTML TAG kullanma (,
${p.replace(/\{\{tracking_url\}\}/g, 'Buraya Tıklayın')}
`; + } + return `${p}
`; + }) + .join('\n'); + + return ` + + + + +