SaaS/backend/src/controllers/authController.ts
Aimpress Team bda23a773f 🚀 Initial commit: Aimpress AutomationHub
 Features:
- Modern SaaS automation platform
- Next.js 15 + TypeScript frontend
- Node.js + Express backend
- PostgreSQL database with full schema
- Docker Compose setup
- Admin panel with analytics
- Template marketplace (6 templates)
- Integrations hub (10+ services)
- Authentication & role-based access
- Responsive n8n-style design

🎯 Ready for demo and deployment

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-28 21:58:33 +01:00

173 lines
No EOL
4.8 KiB
TypeScript

import { Request, Response } from 'express';
import { pool } from '../db/connection';
import { hashPassword, comparePassword, generateToken, generateRandomToken } from '../utils/auth';
export const signup = async (req: Request, res: Response) => {
try {
const { email, password, first_name, last_name } = req.body;
if (!email || !password) {
return res.status(400).json({
success: false,
message: 'Email and password are required'
});
}
const existingUser = await pool.query('SELECT id FROM users WHERE email = $1', [email]);
if (existingUser.rows.length > 0) {
return res.status(409).json({
success: false,
message: 'User already exists with this email'
});
}
const passwordHash = await hashPassword(password);
const verificationToken = generateRandomToken();
const result = await pool.query(
`INSERT INTO users (email, password_hash, first_name, last_name, verification_token, is_verified)
VALUES ($1, $2, $3, $4, $5, $6)
RETURNING id, email, first_name, last_name, role, subscription_plan, subscription_status, created_at`,
[email, passwordHash, first_name, last_name, verificationToken, false]
);
const user = result.rows[0];
const token = generateToken({
userId: user.id,
email: user.email,
role: user.role,
subscription_plan: user.subscription_plan
});
res.status(201).json({
success: true,
token,
user: {
id: user.id,
email: user.email,
first_name: user.first_name,
last_name: user.last_name,
role: user.role,
subscription_plan: user.subscription_plan,
subscription_status: user.subscription_status,
is_verified: false,
created_at: user.created_at,
updated_at: user.created_at
}
});
} catch (error) {
console.error('Signup error:', error);
res.status(500).json({
success: false,
message: 'Internal server error'
});
}
};
export const login = async (req: Request, res: Response) => {
try {
const { email, password } = req.body;
if (!email || !password) {
return res.status(400).json({
success: false,
message: 'Email and password are required'
});
}
const result = await pool.query(
'SELECT id, email, password_hash, first_name, last_name, is_verified, role, subscription_plan, subscription_status, created_at, updated_at FROM users WHERE email = $1',
[email]
);
if (result.rows.length === 0) {
return res.status(401).json({
success: false,
message: 'Invalid credentials'
});
}
const user = result.rows[0];
const isValidPassword = await comparePassword(password, user.password_hash);
if (!isValidPassword) {
return res.status(401).json({
success: false,
message: 'Invalid credentials'
});
}
const token = generateToken({
userId: user.id,
email: user.email,
role: user.role,
subscription_plan: user.subscription_plan
});
res.json({
success: true,
token,
user: {
id: user.id,
email: user.email,
first_name: user.first_name,
last_name: user.last_name,
is_verified: user.is_verified,
role: user.role,
subscription_plan: user.subscription_plan,
subscription_status: user.subscription_status,
created_at: user.created_at,
updated_at: user.updated_at
}
});
} catch (error) {
console.error('Login error:', error);
res.status(500).json({
success: false,
message: 'Internal server error'
});
}
};
export const resetPassword = async (req: Request, res: Response) => {
try {
const { email } = req.body;
if (!email) {
return res.status(400).json({
success: false,
message: 'Email is required'
});
}
const user = await pool.query('SELECT id FROM users WHERE email = $1', [email]);
if (user.rows.length === 0) {
return res.json({
success: true,
message: 'If the email exists, a reset link has been sent'
});
}
const resetToken = generateRandomToken();
const resetExpires = new Date(Date.now() + 3600000); // 1 hour
await pool.query(
'UPDATE users SET reset_password_token = $1, reset_password_expires = $2 WHERE email = $3',
[resetToken, resetExpires, email]
);
// TODO: Send email with reset link
console.log(`Reset token for ${email}: ${resetToken}`);
res.json({
success: true,
message: 'If the email exists, a reset link has been sent'
});
} catch (error) {
console.error('Reset password error:', error);
res.status(500).json({
success: false,
message: 'Internal server error'
});
}
};