leadmind-ai / server.js
stakmodsco's picture
make leadmind ai fully functional by creatng its backend - Follow Up Deployment
1a36166 verified
```javascript
require('dotenv').config();
const express = require('express');
const mongoose = require('mongoose');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const cors = require('cors');
const { v4: uuidv4 } = require('uuid');
const rateLimit = require('express-rate-limit');
const app = express();
// Middleware
app.use(cors());
app.use(express.json());
// Rate limiting
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100 // limit each IP to 100 requests per windowMs
});
app.use('/api/', limiter);
// Database connection
mongoose.connect(process.env.MONGODB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true
})
.then(() => console.log('Connected to MongoDB'))
.catch(err => console.error('MongoDB connection error:', err));
// Models
const User = mongoose.model('User', new mongoose.Schema({
username: { type: String, required: true, unique: true },
password: { type: String, required: true },
role: { type: String, default: 'user' },
apiKey: { type: String, default: uuidv4 }
}));
const Conversation = mongoose.model('Conversation', new mongoose.Schema({
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
messages: [{
content: String,
sender: { type: String, enum: ['user', 'ai'] },
timestamp: { type: Date, default: Date.now }
}],
status: { type: String, enum: ['active', 'resolved'], default: 'active' },
createdAt: { type: Date, default: Date.now }
}));
const Lead = mongoose.model('Lead', new mongoose.Schema({
name: String,
email: { type: String, required: true, unique: true },
phone: String,
status: { type: String, enum: ['new', 'contacted', 'qualified', 'converted'], default: 'new' },
source: String,
notes: String,
createdAt: { type: Date, default: Date.now }
}));
// Authentication middleware
const authenticate = (req, res, next) => {
const token = req.header('Authorization')?.replace('Bearer ', '');
if (!token) return res.status(401).send('Access denied');
try {
const verified = jwt.verify(token, process.env.JWT_SECRET);
req.user = verified;
next();
} catch (err) {
res.status(400).send('Invalid token');
}
};
// Routes
// Auth routes
app.post('/api/auth/register', async (req, res) => {
try {
const { username, password } = req.body;
const hashedPassword = await bcrypt.hash(password, 10);
const user = new User({ username, password: hashedPassword });
await user.save();
res.status(201).send({ message: 'User created successfully' });
} catch (err) {
res.status(400).send(err.message);
}
});
app.post('/api/auth/login', async (req, res) => {
try {
const { username, password } = req.body;
const user = await User.findOne({ username });
if (!user) return res.status(400).send('Invalid credentials');
const validPass = await bcrypt.compare(password, user.password);
if (!validPass) return res.status(400).send('Invalid credentials');
const token = jwt.sign({ _id: user._id, role: user.role }, process.env.JWT_SECRET, { expiresIn: '1h' });
res.send({ token, apiKey: user.apiKey });
} catch (err) {
res.status(400).send(err.message);
}
});
// Conversation routes
app.get('/api/conversations', authenticate, async (req, res) => {
try {
const conversations = await Conversation.find({ userId: req.user._id }).sort({ createdAt: -1 });
res.send(conversations);
} catch (err) {
res.status(400).send(err.message);
}
});
app.post('/api/conversations', authenticate, async (req, res) => {
try {
const conversation = new Conversation({ userId: req.user._id });
await conversation.save();
res.status(201).send(conversation);
} catch (err) {
res.status(400).send(err.message);
}
});
app.post('/api/conversations/:id/messages', authenticate, async (req, res) => {
try {
const conversation = await Conversation.findOne({
_id: req.params.id,
userId: req.user._id
});
if (!conversation) return res.status(404).send('Conversation not found');
// Process AI response (simplified for demo)
const aiResponse = {
content: `AI response to: "${req.body.content}". This is a simulated response.`,
sender: 'ai'
};
conversation.messages.push({
content: req.body.content,
sender: 'user'
});
conversation.messages.push(aiResponse);
await conversation.save();
res.send(conversation);
} catch (err) {
res.status(400).send(err.message);
}
});
// Lead routes
app.get('/api/leads', authenticate, async (req, res) => {
try {
const leads = await Lead.find().sort({ createdAt: -1 });
res.send(leads);
} catch (err) {
res.status(400).send(err.message);
}
});
app.post('/api/leads', authenticate, async (req, res) => {
try {
const lead = new Lead(req.body);
await lead.save();
res.status(201).send(lead);
} catch (err) {
res.status(400).send(err.message);
}
});
app.put('/api/leads/:id', authenticate, async (req, res) => {
try {
const lead = await Lead.findByIdAndUpdate(req.params.id, req.body, { new: true });
if (!lead) return res.status(404).send('Lead not found');
res.send(lead);
} catch (err) {
res.status(400).send(err.message);
}
});
// API Key authentication
app.post('/api/ai/process', async (req, res) => {
try {
const apiKey = req.header('X-API-Key');
if (!apiKey) return res.status(401).send('API key required');
const user = await User.findOne({ apiKey });
if (!user) return res.status(401).send('Invalid API key');
// Process AI request (simplified for demo)
const response = {
id: uuidv4(),
content: `AI processed: "${req.body.content}". This is a simulated response.`,
timestamp: new Date()
};
res.send(response);
} catch (err) {
res.status(400).send(err.message);
}
});
// Start server
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
```