import express from 'express'; import sqlite3 from 'sqlite3'; import { open } from 'sqlite'; import bcrypt from 'bcrypt'; import nodemailer from 'nodemailer'; import dotenv from 'dotenv'; import fs, { stat } from 'fs'; import jwt from 'jsonwebtoken'; dotenv.config(); const transporter = nodemailer.createTransport({ host: process.env.SMTP_HOST, port: process.env.SMTP_PORT, secure: process.env.SMTP_SECURE === 'true', // false for 587, true for 465 auth: { user: process.env.EMAIL_USER, pass: process.env.EMAIL_PASS, }, }); function sendMail(to, subject, html) { const mailOptions = { from: process.env.EMAIL_USER, to: to, subject: subject, html: html }; return transporter.sendMail(mailOptions) .then(() => console.log('Email sent successfully')) .catch(error => console.error('Error sending email:', error)); } // Middleware for checking the token const verifyToken = (req, res, next) => { // Get the token from the headers const token = req.headers.authorization?.replace("Bearer ", ""); // Check if the token is missing if (!token) { return res.status(403).json({ error: "Acces unauthorized, token required" }); } try { // Decode the token and set the user information in the request req.user = jwt.verify(token, jwtSecret); // The token is valid and the user is authorized to access the route next(); } catch (error) { return res.status(401).json({ error: "Acces unauthorized, invalid token" }); } }; const db = await open({ filename: './db/database.db', driver: sqlite3.Database }); function initializeDatabase() { db.exec(` CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL UNIQUE, email TEXT NOT NULL UNIQUE, password TEXT NOT NULL, admin BOOLEAN DEFAULT 0, historyToDefault INTEGER DEFAULT 0 ); `); db.exec(` CREATE TABLE IF NOT EXISTS verify ( id INTEGER PRIMARY KEY, token TEXT NOT NULL UNIQUE, username TEXT NOT NULL UNIQUE, email TEXT NOT NULL UNIQUE, password TEXT NOT NULL, createdAt DATETIME DEFAULT CURRENT_TIMESTAMP ); `); } initializeDatabase(); const app = express(); const port = 20909; app.use(express.json()); app.use(express.static('public')); app.get('/login', (req, res) => { res.sendFile('index.html', { root: 'public' }); } ); app.get('/register', (req, res) => { res.sendFile('register.html', { root: 'public' }); } ); app.get('/', (req, res) => { // redirect to login page res.redirect('/login'); } ); app.post('/api/login', async (req, res) => { const { username, password } = req.body; if (!username || !password) { return res.status(400).json({ message: 'Username and password are required' }); } try { const user = await db.get('SELECT * FROM users WHERE username = ? OR email = ?', [username, username]); if (!user) { return res.status(401).json({ message: 'Invalid username or password' }); } // Check password (replace with real password check logic) const isPasswordValid = bcrypt.compareSync(password, user.password); if (!isPasswordValid) { return res.status(401).json({ message: 'Invalid username or password' }); } res.status(200).json({ message: 'Login successful' }); } catch (err) { console.error('Database error:', err); res.status(500).json({ message: 'Internal server error' }); } } ); app.post('/api/register', async (req, res) => { const { username, email, password } = req.body; if (!username || !email || !password) { return res.status(400).json({ message: 'Username, email, and password are required' }); } const hashedPassword = bcrypt.hashSync(password, 10); try { // Check if user already exists in users table const user = await db.get('SELECT * FROM users WHERE username = ? OR email = ?', [username, email]); if (user) { return res.status(409).json({ message: 'Username or email already exists' }); } // Check if user is already in verify table const verify = await db.get('SELECT * FROM verify WHERE username = ? OR email = ?', [username, email]); if (verify) { // If token is still valid if (Date.now() - new Date(verify.createdAt).getTime() < 24 * 60 * 60 * 1000) { return res.status(409).json({ message: 'Verification already sent, please check your email' }); } else { // If token is expired, delete it await db.run('DELETE FROM verify WHERE id = ?', [verify.id]); } } // Insert new verification token const verificationToken = Math.random().toString(36).substring(2, 15); await db.run('INSERT INTO verify (token, username, email, password) VALUES (?, ?, ?, ?)', [verificationToken, username, email, hashedPassword]); // read the email template const emailTemplate = fs.readFileSync('mailFile/mail.html', 'utf8'); const emailContent = emailTemplate.replace('{{verification_link}}', `${process.env.URL}/verify?token=${verificationToken}`); sendMail(email, 'Welcome to Our Service', emailContent); return res.status(201).json({ message: 'email send' }); } catch (err) { await db.run('DELETE FROM verify WHERE username = ? OR email = ?', [username, email]); console.error('Database error:', err); return res.status(500).json({ message: 'Internal server error' }); } }); app.get('/verify', (req, res) => { const { token } = req.query; if (!token) { return res.status(400).json({ message: 'Token is required' }); } res.sendFile('verify.html', { root: 'public' }); } ); app.post('/api/verify', async (req, res) => { const { token } = req.body; if (!token) { return res.status(400).json({ message: 'Token is required' }); } try { const verify = await db.get('SELECT * FROM verify WHERE token = ?', [token]); if (!verify) { return res.status(404).json({ message: 'Invalid or expired token' }); } // Check if the token is still valid (24 hours) if (Date.now() - new Date(verify.createdAt).getTime() > 24 * 60 * 60 * 1000) { return res.status(410).json({ message: 'Token has expired' }); } // Insert user into users table await db.run('INSERT INTO users (username, email, password) VALUES (?, ?, ?)', [verify.username, verify.email, verify.password]) await db.run('DELETE FROM verify WHERE id = ?', [verify.id]); res.status(200).json({ message: 'Account verified successfully' }); } catch (err) { console.error('Database error:', err); return res.status(500).json({ message: 'Internal server error' }); } } ); app.listen(port, "127.0.0.1", () => { console.log(`Server is running on localhost:${port}`); } );