const bcrypt = require('bcryptjs'); const jwt = require('jsonwebtoken'); const prisma = require('../lib/prisma'); const register = async (req, res) => { const { name, email, password } = req.body; if (!name || !email || !password) { return res.status(400).json({ error: 'Name, email and password are required' }); } try { const existing = await prisma.user.findUnique({ where: { email } }); if (existing) return res.status(409).json({ error: 'Email already registered' }); const hashedPassword = await bcrypt.hash(password, 12); const user = await prisma.user.create({ data: { name, email, hashedPassword }, }); const token = jwt.sign( { userId: user.id, email: user.email, name: user.name, role: user.role }, process.env.JWT_SECRET, { expiresIn: '7d' } ); res.status(201).json({ token, user: { id: user.id, name: user.name, email: user.email, role: user.role }, }); } catch (err) { console.error(err); res.status(500).json({ error: 'Server error' }); } }; const login = async (req, res) => { const { email, password } = req.body; if (!email || !password) { return res.status(400).json({ error: 'Email and password are required' }); } try { const user = await prisma.user.findUnique({ where: { email } }); if (!user) return res.status(401).json({ error: 'Invalid credentials' }); if (!user.hashedPassword) { return res.status(401).json({ error: 'This account was registered using Google. Please sign in with Google.' }); } const valid = await bcrypt.compare(password, user.hashedPassword); if (!valid) return res.status(401).json({ error: 'Invalid credentials' }); const token = jwt.sign( { userId: user.id, email: user.email, name: user.name, role: user.role }, process.env.JWT_SECRET, { expiresIn: '7d' } ); res.json({ token, user: { id: user.id, name: user.name, email: user.email, role: user.role }, }); } catch (err) { console.error(err); res.status(500).json({ error: 'Server error' }); } }; const google = async (req, res) => { const { credential } = req.body; if (!credential) { return res.status(400).json({ error: 'Google credential is required' }); } try { // Verify token with Google's tokeninfo endpoint const response = await fetch(`https://oauth2.googleapis.com/tokeninfo?id_token=${credential}`); if (!response.ok) { return res.status(400).json({ error: 'Invalid Google credential' }); } const payload = await response.json(); // Verify email is verified if (payload.email_verified !== 'true' && payload.email_verified !== true) { return res.status(400).json({ error: 'Google email is not verified' }); } const { email, name } = payload; // Check if user already exists let user = await prisma.user.findUnique({ where: { email } }); if (!user) { // Create a user without a password user = await prisma.user.create({ data: { name: name || email.split('@')[0], email, hashedPassword: null, }, }); } // Generate JWT token const token = jwt.sign( { userId: user.id, email: user.email, name: user.name, role: user.role }, process.env.JWT_SECRET, { expiresIn: '7d' } ); res.json({ token, user: { id: user.id, name: user.name, email: user.email, role: user.role }, }); } catch (err) { console.error('Google Auth Error:', err); res.status(500).json({ error: 'Server error during Google authentication' }); } }; const getMe = async (req, res) => { try { const user = await prisma.user.findUnique({ where: { id: req.user.userId }, select: { id: true, name: true, email: true, role: true, createdAt: true }, }); if (!user) return res.status(404).json({ error: 'User not found' }); // Check if onboarding is done const workspace = await prisma.teamMember.findFirst({ where: { userId: user.id }, include: { workspace: true }, }); res.json({ user, workspace: workspace?.workspace || null }); } catch (err) { console.error(err); res.status(500).json({ error: 'Server error' }); } }; module.exports = { register, login, google, getMe, };