feat: SMTP integration, dynamic app_settings for email, and email verification enforcement for tier upgrades
This commit is contained in:
@@ -63,6 +63,13 @@ router.put('/users/:id/tier', async (req, res) => {
|
||||
}
|
||||
|
||||
try {
|
||||
if (role === 'pro' || role === 'enterprise') {
|
||||
const userCheck = await pgPool.query('SELECT is_email_verified FROM users WHERE id = $1', [id]);
|
||||
if (userCheck.rows.length === 0) return res.status(404).json({ error: 'User not found' });
|
||||
if (!userCheck.rows[0].is_email_verified) {
|
||||
return res.status(400).json({ error: 'Cannot upgrade tier: User email is not verified' });
|
||||
}
|
||||
}
|
||||
const result = await pgPool.query(
|
||||
'UPDATE users SET role = $1 WHERE id = $2 RETURNING id, email, role',
|
||||
[role, id]
|
||||
|
||||
+58
-1
@@ -2,7 +2,9 @@ const express = require('express');
|
||||
const router = express.Router();
|
||||
const bcrypt = require('bcryptjs');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const crypto = require('crypto');
|
||||
const { Pool } = require('pg');
|
||||
const { sendMail } = require('../utils/emailService');
|
||||
|
||||
const pgPool = new Pool({
|
||||
host: process.env.PGHOST || 'postgres',
|
||||
@@ -72,7 +74,7 @@ router.post('/login', async (req, res) => {
|
||||
const { verifyToken } = require('../middleware/auth');
|
||||
router.get('/me', verifyToken, async (req, res) => {
|
||||
try {
|
||||
const userQuery = await pgPool.query('SELECT id, email, role FROM users WHERE id = $1', [req.user.id]);
|
||||
const userQuery = await pgPool.query('SELECT id, email, role, is_email_verified FROM users WHERE id = $1', [req.user.id]);
|
||||
if (userQuery.rows.length === 0) return res.status(404).json({ error: 'User not found' });
|
||||
res.json({ user: userQuery.rows[0] });
|
||||
} catch (err) {
|
||||
@@ -81,6 +83,61 @@ router.get('/me', verifyToken, async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Send Verification Email
|
||||
router.post('/send-verification', verifyToken, async (req, res) => {
|
||||
try {
|
||||
const userQuery = await pgPool.query('SELECT email, is_email_verified FROM users WHERE id = $1', [req.user.id]);
|
||||
if (userQuery.rows.length === 0) return res.status(404).json({ error: 'User not found' });
|
||||
|
||||
const user = userQuery.rows[0];
|
||||
if (user.is_email_verified) {
|
||||
return res.status(400).json({ error: 'Email is already verified' });
|
||||
}
|
||||
|
||||
const token = crypto.randomBytes(32).toString('hex');
|
||||
await pgPool.query('UPDATE users SET email_verification_token = $1 WHERE id = $2', [token, req.user.id]);
|
||||
|
||||
const baseUrl = process.env.FRONTEND_URL || 'https://qr.houseofwebsites.ai';
|
||||
const verifyLink = `${baseUrl}/verify-email?token=${token}`;
|
||||
|
||||
const html = `
|
||||
<h2>Verify Your Email</h2>
|
||||
<p>Thanks for using CK-QR! Please verify your email address to unlock Pro tier upgrades.</p>
|
||||
<a href="${verifyLink}" style="display:inline-block;padding:10px 20px;background:#4f46e5;color:#fff;text-decoration:none;border-radius:5px;">Verify Email</a>
|
||||
<p>Or copy and paste this link: <br> ${verifyLink}</p>
|
||||
`;
|
||||
|
||||
await sendMail(user.email, 'Verify your CK-QR account', html);
|
||||
res.json({ message: 'Verification email sent' });
|
||||
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: 'Failed to send verification email' });
|
||||
}
|
||||
});
|
||||
|
||||
// Verify Email Token
|
||||
router.get('/verify-email/:token', async (req, res) => {
|
||||
const { token } = req.params;
|
||||
if (!token) return res.status(400).json({ error: 'Token is required' });
|
||||
|
||||
try {
|
||||
const result = await pgPool.query(
|
||||
'UPDATE users SET is_email_verified = true, email_verification_token = NULL WHERE email_verification_token = $1 RETURNING id, email',
|
||||
[token]
|
||||
);
|
||||
|
||||
if (result.rows.length === 0) {
|
||||
return res.status(400).json({ error: 'Invalid or expired token' });
|
||||
}
|
||||
|
||||
res.json({ message: 'Email verified successfully!' });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: 'Server error during verification' });
|
||||
}
|
||||
});
|
||||
|
||||
// Logout
|
||||
router.post('/logout', (req, res) => {
|
||||
res.clearCookie('token');
|
||||
|
||||
@@ -1,10 +1,29 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const { Pool } = require('pg');
|
||||
|
||||
const pgPool = new Pool({
|
||||
host: process.env.PGHOST || 'postgres',
|
||||
port: process.env.PGPORT || 5432,
|
||||
user: process.env.PGUSER || 'postgres',
|
||||
password: process.env.PGPASSWORD || 'postgres',
|
||||
database: process.env.PGDATABASE || 'ckqr',
|
||||
});
|
||||
|
||||
// Placeholder for ICICI Payment Gateway initialization
|
||||
router.post('/icici/initiate', async (req, res) => {
|
||||
const { amount, plan, userId } = req.body;
|
||||
|
||||
try {
|
||||
const userCheck = await pgPool.query('SELECT is_email_verified FROM users WHERE id = $1', [userId]);
|
||||
if (userCheck.rows.length > 0 && !userCheck.rows[0].is_email_verified) {
|
||||
return res.status(400).json({ error: 'Please verify your email address before upgrading your plan.' });
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error checking verification status', err);
|
||||
return res.status(500).json({ error: 'Server error' });
|
||||
}
|
||||
|
||||
// Here you would construct the ICICI request payload, compute checksums, etc.
|
||||
// and return the URL or parameters for the frontend to redirect the user to ICICI.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user