REDROOM
PHP 8.2.30
Path:
Logout
Edit File
Size: 15.34 KB
Close
//home/byroehnu/easepay.easetack.com/controllers/advancedAuthController.js
Text
Base64
const bcrypt = require('bcryptjs'); const jwt = require('jsonwebtoken'); const crypto = require('crypto'); const { prisma } = require('../config/prisma'); // Generate JWT token with extended expiry for auto-login const generateToken = (id, extended = false) => { const expiresIn = extended ? '30d' : (process.env.JWT_EXPIRES_IN || '7d'); return jwt.sign({ id }, process.env.JWT_SECRET, { expiresIn }); }; // Generate session token const generateSessionToken = () => { return crypto.randomBytes(32).toString('hex'); }; // Hash PIN securely const hashPIN = async (pin) => { const salt = await bcrypt.genSalt(12); return bcrypt.hash(pin, salt); }; // Setup PIN for user const setupPIN = async (req, res) => { try { const { pin, confirmPin } = req.body; const userId = req.user.id; // Validation if (!pin || !confirmPin) { return res.status(400).json({ success: false, message: 'Please provide PIN and confirmation' }); } if (pin !== confirmPin) { return res.status(400).json({ success: false, message: 'PINs do not match' }); } if (!/^\d{4,6}$/.test(pin)) { return res.status(400).json({ success: false, message: 'PIN must be 4-6 digits' }); } // Hash and save PIN const hashedPin = await hashPIN(pin); await prisma.user.update({ where: { id: userId }, data: { pin: hashedPin, pinSetAt: new Date() } }); console.log(`✅ PIN setup completed for user ${userId}`); res.status(200).json({ success: true, message: 'PIN setup successful' }); } catch (error) { console.error('Setup PIN error:', error); res.status(500).json({ success: false, message: 'Failed to setup PIN' }); } }; // PIN-based login const loginWithPIN = async (req, res) => { try { const { phone, pin, deviceId, deviceType } = req.body; if (!phone || !pin) { return res.status(400).json({ success: false, message: 'Please provide phone number and PIN' }); } console.log(`🔐 PIN login attempt for ${phone}`); // Find user const user = await prisma.user.findUnique({ where: { phone }, select: { id: true, phone: true, pin: true, firstName: true, lastName: true, email: true, role: true, isActive: true, phoneVerified: true, loginAttempts: true, lockedUntil: true } }); if (!user) { return res.status(404).json({ success: false, message: 'User not found' }); } // Check if account is locked if (user.lockedUntil && new Date() < user.lockedUntil) { return res.status(423).json({ success: false, message: 'Account temporarily locked. Try again later.' }); } // Check if user is active if (!user.isActive) { return res.status(401).json({ success: false, message: 'Account has been deactivated' }); } // Check if PIN is set if (!user.pin) { return res.status(400).json({ success: false, message: 'PIN not set. Please login with OTP first.' }); } // Verify PIN const isPinValid = await bcrypt.compare(pin, user.pin); if (!isPinValid) { // Increment login attempts const loginAttempts = (user.loginAttempts || 0) + 1; const updateData = { loginAttempts }; // Lock account after 5 failed attempts if (loginAttempts >= 5) { updateData.lockedUntil = new Date(Date.now() + 30 * 60 * 1000); // 30 minutes } await prisma.user.update({ where: { id: user.id }, data: updateData }); return res.status(401).json({ success: false, message: 'Invalid PIN', attemptsRemaining: Math.max(0, 5 - loginAttempts) }); } // Successful login - reset attempts and update session const sessionToken = generateSessionToken(); const sessionExpiresAt = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000); // 30 days await prisma.user.update({ where: { id: user.id }, data: { loginAttempts: 0, lockedUntil: null, lastLoginAt: new Date(), sessionToken, sessionExpiresAt } }); // Register/update device if provided if (deviceId && deviceType) { await prisma.deviceToken.upsert({ where: { userId_deviceId: { userId: user.id, deviceId } }, update: { lastUsedAt: new Date(), isActive: true }, create: { userId: user.id, deviceId, deviceType, lastUsedAt: new Date() } }); } // Generate tokens const token = generateToken(user.id, true); console.log(`✅ PIN login successful for ${phone}`); res.status(200).json({ success: true, message: 'Login successful', token, sessionToken, user: { id: user.id, phone: user.phone, firstName: user.firstName, lastName: user.lastName, email: user.email, role: user.role, phoneVerified: user.phoneVerified } }); } catch (error) { console.error('PIN login error:', error); res.status(500).json({ success: false, message: 'Login failed' }); } }; // Enable biometric authentication const enableBiometric = async (req, res) => { try { const { deviceId, biometricHash, deviceType } = req.body; const userId = req.user.id; if (!deviceId || !biometricHash) { return res.status(400).json({ success: false, message: 'Device ID and biometric hash are required' }); } // Update user biometric settings await prisma.user.update({ where: { id: userId }, data: { biometricEnabled: true, biometricHash } }); // Register device with biometric capability await prisma.deviceToken.upsert({ where: { userId_deviceId: { userId, deviceId } }, update: { biometricId: biometricHash, deviceType: deviceType || 'mobile', lastUsedAt: new Date() }, create: { userId, deviceId, deviceType: deviceType || 'mobile', biometricId: biometricHash } }); console.log(`✅ Biometric enabled for user ${userId} on device ${deviceId}`); res.status(200).json({ success: true, message: 'Biometric authentication enabled' }); } catch (error) { console.error('Enable biometric error:', error); res.status(500).json({ success: false, message: 'Failed to enable biometric authentication' }); } }; // Biometric login const loginWithBiometric = async (req, res) => { try { const { phone, biometricHash, deviceId } = req.body; if (!phone || !biometricHash || !deviceId) { return res.status(400).json({ success: false, message: 'Phone, biometric data, and device ID are required' }); } console.log(`👆 Biometric login attempt for ${phone} on device ${deviceId}`); // Find user with biometric enabled const user = await prisma.user.findUnique({ where: { phone }, select: { id: true, phone: true, firstName: true, lastName: true, email: true, role: true, isActive: true, phoneVerified: true, biometricEnabled: true, biometricHash: true } }); if (!user) { return res.status(404).json({ success: false, message: 'User not found' }); } if (!user.isActive) { return res.status(401).json({ success: false, message: 'Account has been deactivated' }); } if (!user.biometricEnabled) { return res.status(400).json({ success: false, message: 'Biometric authentication not enabled' }); } // Verify device is registered const device = await prisma.deviceToken.findUnique({ where: { userId_deviceId: { userId: user.id, deviceId } } }); if (!device || !device.biometricId) { return res.status(401).json({ success: false, message: 'Device not registered for biometric authentication' }); } // In a real app, you'd verify the biometric hash against stored templates // For this demo, we'll check if it matches the stored hash if (device.biometricId !== biometricHash) { return res.status(401).json({ success: false, message: 'Biometric authentication failed' }); } // Successful biometric login const sessionToken = generateSessionToken(); const sessionExpiresAt = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000); await prisma.user.update({ where: { id: user.id }, data: { lastLoginAt: new Date(), sessionToken, sessionExpiresAt } }); await prisma.deviceToken.update({ where: { userId_deviceId: { userId: user.id, deviceId } }, data: { lastUsedAt: new Date() } }); const token = generateToken(user.id, true); console.log(`✅ Biometric login successful for ${phone}`); res.status(200).json({ success: true, message: 'Biometric login successful', token, sessionToken, user: { id: user.id, phone: user.phone, firstName: user.firstName, lastName: user.lastName, email: user.email, role: user.role, phoneVerified: user.phoneVerified } }); } catch (error) { console.error('Biometric login error:', error); res.status(500).json({ success: false, message: 'Biometric login failed' }); } }; // Auto-login with session token const autoLogin = async (req, res) => { try { const { sessionToken, deviceId } = req.body; if (!sessionToken) { return res.status(400).json({ success: false, message: 'Session token is required' }); } console.log(`🔄 Auto-login attempt with session token`); // Find user with valid session const user = await prisma.user.findFirst({ where: { sessionToken, sessionExpiresAt: { gt: new Date() }, isActive: true, autoLoginEnabled: true }, select: { id: true, phone: true, firstName: true, lastName: true, email: true, role: true, phoneVerified: true, sessionExpiresAt: true } }); if (!user) { return res.status(401).json({ success: false, message: 'Invalid or expired session' }); } // Update last login and device usage await prisma.user.update({ where: { id: user.id }, data: { lastLoginAt: new Date() } }); if (deviceId) { await prisma.deviceToken.updateMany({ where: { userId: user.id, deviceId }, data: { lastUsedAt: new Date() } }); } const token = generateToken(user.id, true); console.log(`✅ Auto-login successful for user ${user.id}`); res.status(200).json({ success: true, message: 'Auto-login successful', token, user: { id: user.id, phone: user.phone, firstName: user.firstName, lastName: user.lastName, email: user.email, role: user.role, phoneVerified: user.phoneVerified } }); } catch (error) { console.error('Auto-login error:', error); res.status(500).json({ success: false, message: 'Auto-login failed' }); } }; // Get user security settings const getSecuritySettings = async (req, res) => { try { const userId = req.user.id; const user = await prisma.user.findUnique({ where: { id: userId }, select: { pin: true, biometricEnabled: true, autoLoginEnabled: true, requirePinForTransactions: true, pinSetAt: true, deviceTokens: { select: { deviceId: true, deviceName: true, deviceType: true, biometricId: true, isActive: true, lastUsedAt: true } } } }); res.status(200).json({ success: true, settings: { hasPIN: !!user.pin, biometricEnabled: user.biometricEnabled, autoLoginEnabled: user.autoLoginEnabled, requirePinForTransactions: user.requirePinForTransactions, pinSetAt: user.pinSetAt, registeredDevices: user.deviceTokens.length, devices: user.deviceTokens } }); } catch (error) { console.error('Get security settings error:', error); res.status(500).json({ success: false, message: 'Failed to get security settings' }); } }; // Update security settings const updateSecuritySettings = async (req, res) => { try { const userId = req.user.id; const { autoLoginEnabled, requirePinForTransactions } = req.body; const updateData = {}; if (typeof autoLoginEnabled === 'boolean') { updateData.autoLoginEnabled = autoLoginEnabled; } if (typeof requirePinForTransactions === 'boolean') { updateData.requirePinForTransactions = requirePinForTransactions; } await prisma.user.update({ where: { id: userId }, data: updateData }); res.status(200).json({ success: true, message: 'Security settings updated successfully' }); } catch (error) { console.error('Update security settings error:', error); res.status(500).json({ success: false, message: 'Failed to update security settings' }); } }; // Logout and invalidate session const logout = async (req, res) => { try { const userId = req.user.id; const { deviceId } = req.body; // Clear session token await prisma.user.update({ where: { id: userId }, data: { sessionToken: null, sessionExpiresAt: null } }); // Deactivate device if specified if (deviceId) { await prisma.deviceToken.updateMany({ where: { userId, deviceId }, data: { isActive: false } }); } res.status(200).json({ success: true, message: 'Logout successful' }); } catch (error) { console.error('Logout error:', error); res.status(500).json({ success: false, message: 'Logout failed' }); } }; module.exports = { setupPIN, loginWithPIN, enableBiometric, loginWithBiometric, autoLogin, getSecuritySettings, updateSecuritySettings, logout };
Save
Close
Exit & Reset
Text mode: syntax highlighting auto-detects file type.
Directory Contents
Dirs: 1 × Files: 17
Delete Selected
Select All
Select None
Sort:
Name
Size
Modified
Enable drag-to-move
Name
Size
Perms
Modified
Actions
controllers
DIR
-
drwxr-xr-x
2026-03-20 23:25:48
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
.htaccess
127 B
lr--r--r--
2026-03-14 01:49:22
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
advancedAuthController.js
15.34 KB
lrw-r--r--
2026-02-19 22:06:47
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
authController.js
30.77 KB
lrw-r--r--
2026-03-04 06:33:18
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
authController_copy.js
62.98 KB
lrw-r--r--
2026-03-01 23:46:52
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
businessController.js
10.79 KB
lrw-r--r--
2026-02-07 16:28:16
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
businessProfileController.js
14.17 KB
lrw-r--r--
2026-02-27 04:02:38
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
creditScoreController.js
6.32 KB
lrw-r--r--
2026-02-06 17:10:19
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
dashboardController.js
15.13 KB
lrw-r--r--
2026-03-01 05:05:51
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
expenseController.js
8.50 KB
lrw-r--r--
2026-03-01 05:05:52
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
inventoryController.js
12.15 KB
lrw-r--r--
2026-02-27 04:02:38
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
invoiceController.js
25.39 KB
lrw-r--r--
2026-03-01 05:05:51
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
reportController.js
17.61 KB
lrw-r--r--
2026-03-01 05:05:51
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
saleController.js
6.45 KB
lrw-r--r--
2026-03-01 05:05:51
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
settingsController.js
2.33 KB
lrw-r--r--
2026-03-01 05:05:51
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
subscriptionController.js
12.78 KB
lrw-r--r--
2026-02-21 08:13:30
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
taxController.js
9.96 KB
lrw-r--r--
2026-03-01 05:05:51
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
webhookController.js
8.51 KB
lrw-r--r--
2026-02-20 19:31:28
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
Zip Selected
If ZipArchive is unavailable, a
.tar
will be created (no compression).