File size: 6,005 Bytes
1a36166
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
```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}`));
```