const jwt = require('jsonwebtoken'); const argon2 = require('argon2'); const randomstring = require('randomstring'); const {User} = require('../models'); // Pastikan sesuai dengan struktur project require('dotenv').config(); const nodemailer = require('nodemailer'); const sgMail = require('@sendgrid/mail'); // Fungsi untuk membuat token JWT const generateToken = (user) => { return jwt.sign( { id: user.id, email: user.email, role: user.role }, // id bukan _id untuk Sequelize process.env.JWT_SECRET, { expiresIn: process.env.JWT_EXPIRES_IN || '1d' } ); }; // Menambahkan user baru dengan hashing Argon2 exports.register = async (req, res) => { try { const { name, email, password, alamat, nomorTelepon, role } = req.body; // Cek apakah email sudah terdaftar const existingUser = await User.findOne({ where: { email } }); if (existingUser) return res.status(400).json({ message: 'Email already exists' }); // Hash password menggunakan Argon2 const hashedPassword = await argon2.hash(password); const newUser = await User.create({ name, email, password: hashedPassword, alamat, nomorTelepon, role: 'user' }); res.status(201).json({ message: 'User created successfully', user: newUser }); } catch (error) { res.status(500).json({ message: 'Error creating user', error }); } }; // Login exports.login = async (req, res) => { try { const { email, password } = req.body; // 🔹 Cek apakah user dengan email tersebut ada const user = await User.findOne({ where: { email } }); if (!user) { return res.status(401).json({ message: "Email atau password salah" }); } // 🔹 Verifikasi password const isPasswordValid = await argon2.verify(user.password, password); if (!isPasswordValid) { return res.status(401).json({ message: "Email atau password salah" }); } // 🔹 Buat token JWT const token = jwt.sign( { id: user.id, email: user.email, role: user.role }, process.env.JWT_SECRET, { expiresIn: process.env.JWT_EXPIRES_IN || '1d' } ); console.log("User ID dari backend:", user.id); // 🔹 Kirim response dengan token dan role res.status(200).json({ message: "Login berhasil", token, role: user.role // Ini penting untuk Flutter agar bisa menentukan halaman tujuan }); } catch (error) { res.status(500).json({ message: "Terjadi kesalahan", error }); } }; // Buat transporter Nodemailer dengan Gmail const createGmailTransporter = () => { return nodemailer.createTransport({ service: 'gmail', auth: { user: process.env.EMAIL_FROM, // sibayam52@gmail.com dari .env yang sudah ada pass: process.env.EMAIL_PASS, // Gunakan App Password, bukan password biasa! }, // Pool koneksi untuk menghindari rate limiting pool: true, maxConnections: 3, maxMessages: 50, rateDelta: 1500, rateLimit: 3 }); }; exports.sendResetCodeWithGmail = async (req, res) => { const { email } = req.body; try { // Validasi email if (!email || !email.includes('@')) { return res.status(400).json({ message: 'Email tidak valid' }); } const user = await User.findOne({ where: { email } }); if (!user) return res.status(404).json({ message: 'User tidak ditemukan' }); // Generate 6 digit random code const code = Math.floor(100000 + Math.random() * 900000).toString(); const expiresAt = new Date(Date.now() + 10 * 60 * 1000); await user.update({ resetToken: code, resetTokenExpiry: expiresAt, }); // Nama aplikasi yang konsisten const appName = process.env.SENDGRID_SENDER_NAME || 'SistemPakar SIBAYAM'; // Coba buat transporter setiap kali untuk menghindari koneksi mati const transporter = createGmailTransporter(); // Email sangat sederhana tetapi efektif const mailOptions = { from: `"${appName}" <${process.env.EMAIL_FROM}>`, // Menggunakan EMAIL_FROM dari .env to: email, subject: `[${code}] Kode Verifikasi ${appName}`, // Tanda kode di subject membantu visibilitas html: `
Halo ${user.name || 'Pengguna'},
Anda telah meminta untuk mereset password akun SIBAYAM Anda.
Kode verifikasi Anda:
Kode ini akan kadaluarsa dalam 10 menit.
Jika Anda tidak meminta reset password, abaikan email ini.
Email ini dikirim oleh sistem SIBAYAM. Mohon jangan membalas email ini.
Halo ${user.name || 'Pengguna'},
Password akun SIBAYAM Anda telah berhasil diubah.
✓ Password telah diperbarui
Jika Anda tidak melakukan perubahan ini, segera hubungi tim dukungan kami.
Email ini dikirim oleh sistem SIBAYAM. Mohon jangan membalas email ini.