const express = require('express'); const { OAuth2Client } = require('google-auth-library'); const { generateToken, authenticateToken } = require('../middleware/auth'); const { executeQuery } = require('../config/database'); const { isEmailAuthorized } = require('../middleware/emailAuth'); const router = express.Router(); const client = new OAuth2Client(process.env.GOOGLE_CLIENT_ID); // Google OAuth login router.post('/google', async (req, res) => { try { const { token } = req.body; console.log('🔍 Login attempt with token:', token ? 'Present' : 'Missing'); if (!token) { console.log('❌ No token provided'); return res.status(400).json({ error: 'Token is required' }); } // Verify Google token console.log('🔐 Verifying Google token...'); const ticket = await client.verifyIdToken({ idToken: token, audience: process.env.GOOGLE_CLIENT_ID, }); const payload = ticket.getPayload(); const googleId = payload['sub']; const email = payload['email']; const name = payload['name']; const picture = payload['picture']; console.log(`👤 Google token verified for: ${email}`); // Check if email is authorized const authorized = isEmailAuthorized(email); console.log(`🔒 Email authorization check for ${email}: ${authorized ? 'ALLOWED' : 'DENIED'}`); if (!authorized) { console.log(`❌ Access denied for ${email}`); return res.status(403).json({ error: 'Access denied', message: 'Your email address is not authorized to access this application' }); } // Check if user exists in database (optional - auth works without DB) let user; try { // Only try database operations if DB is configured if (process.env.DB_SERVER) { const userResult = await executeQuery( 'SELECT * FROM Users WHERE email = @email', { email } ); if (userResult.recordset.length > 0) { // User exists, update last login user = userResult.recordset[0]; await executeQuery( 'UPDATE Users SET last_login = GETDATE(), picture = @picture WHERE id = @id', { picture, id: user.id } ); } else { // Create new user const insertResult = await executeQuery( `INSERT INTO Users (google_id, email, name, picture, created_at, last_login) OUTPUT INSERTED.* VALUES (@googleId, @email, @name, @picture, GETDATE(), GETDATE())`, { googleId, email, name, picture } ); user = insertResult.recordset[0]; } console.log('✅ Database operations completed successfully'); } else { console.log('⚠️ No database configured, using fallback user object'); throw new Error('No database configured'); } } catch (dbError) { console.error('Database error during authentication:', dbError.message); // Fallback: create user object without database user = { id: googleId, email, name, picture, google_id: googleId, }; console.log('✅ Using fallback user object (no database)'); } // Generate JWT token const jwtToken = generateToken(user); res.json({ success: true, token: jwtToken, user: { id: user.id, email: user.email, name: user.name, picture: user.picture, }, }); } catch (error) { console.error('Google authentication error:', error); res.status(401).json({ error: 'Invalid Google token' }); } }); // Verify JWT token router.get('/verify', authenticateToken, async (req, res) => { try { // Token is already verified by middleware res.json({ success: true, user: req.user, }); } catch (error) { console.error('Token verification error:', error); res.status(401).json({ error: 'Invalid token' }); } }); // Logout (client-side token removal) router.post('/logout', authenticateToken, (req, res) => { res.json({ success: true, message: 'Logged out successfully' }); }); module.exports = router;