AravindS2006 commited on
Commit
77e3edd
·
verified ·
1 Parent(s): 2703c75

Create server.js

Browse files
Files changed (1) hide show
  1. server.js +267 -0
server.js ADDED
@@ -0,0 +1,267 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // server.js (Node.js backend)
2
+
3
+ const express = require('express');
4
+ const multer = require('multer');
5
+ const cors = require('cors');
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+ const bcrypt = require('bcrypt');
9
+ const jwt = require('jsonwebtoken');
10
+
11
+ const app = express();
12
+ const port = process.env.PORT || 3000;
13
+ const secretKey = 'your-secret-key'; // Replace with a strong, randomly generated secret key
14
+ const usersFilePath = 'users.json'; // File to store user data
15
+
16
+ // --- Middleware ---
17
+ app.use(cors({
18
+ origin: 'http://localhost:8080' // Replace with your frontend's origin (e.g., your domain)
19
+ })); // Enable CORS for your frontend origin
20
+ app.use(express.json());
21
+ app.use(express.static('public'));
22
+
23
+ // --- File Upload Configuration ---
24
+ const storage = multer.diskStorage({
25
+ destination: (req, file, cb) => {
26
+ const uploadPath = 'uploads/';
27
+ fs.mkdirSync(uploadPath, { recursive: true });
28
+ cb(null, uploadPath);
29
+ },
30
+ filename: (req, file, cb) => {
31
+ const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
32
+ const ext = path.extname(file.originalname);
33
+ cb(null, file.fieldname + '-' + uniqueSuffix + ext);
34
+ }
35
+ });
36
+
37
+ const upload = multer({ storage: storage });
38
+
39
+ // --- Load Users from File (Database Simulation) ---
40
+ let users = [];
41
+ function loadUsers() {
42
+ try {
43
+ const data = fs.readFileSync(usersFilePath, 'utf8');
44
+ users = JSON.parse(data);
45
+ } catch (error) {
46
+ console.log('No existing users file found or error loading users. Starting with an empty user list.');
47
+ users = []; // Start with an empty array if the file doesn't exist or has an error
48
+ }
49
+ }
50
+
51
+ function saveUsers() {
52
+ try {
53
+ fs.writeFileSync(usersFilePath, JSON.stringify(users, null, 2), 'utf8'); // Pretty print the JSON
54
+ console.log('Users saved to file.');
55
+ } catch (error) {
56
+ console.error('Error saving users to file:', error);
57
+ }
58
+ }
59
+
60
+ loadUsers(); // Load users when the server starts
61
+
62
+ // --- Helper Functions ---
63
+
64
+ function generateToken(user) {
65
+ const payload = {
66
+ userId: user.id,
67
+ email: user.email,
68
+ name: user.name
69
+ };
70
+ const options = {
71
+ expiresIn: '1h'
72
+ };
73
+ return jwt.sign(payload, secretKey, options);
74
+ }
75
+
76
+ // --- API Endpoints ---
77
+
78
+ // 1. Registration
79
+ app.post('/register', async (req, res) => {
80
+ try {
81
+ const { name, email, password, age, medicalHistory } = req.body;
82
+
83
+ // Input validation (enhanced)
84
+ if (!name || name.length < 2) {
85
+ return res.status(400).json({ message: 'Name must be at least 2 characters long.' });
86
+ }
87
+ if (!email || !email.includes('@')) {
88
+ return res.status(400).json({ message: 'Invalid email format.' });
89
+ }
90
+ if (!password || password.length < 6) {
91
+ return res.status(400).json({ message: 'Password must be at least 6 characters long.' });
92
+ }
93
+
94
+ // Check if the email is already registered
95
+ if (users.find(user => user.email === email)) {
96
+ return res.status(400).json({ message: 'Email already exists.' });
97
+ }
98
+
99
+ // Hash the password
100
+ const hashedPassword = await bcrypt.hash(password, 10);
101
+
102
+ // Create a new user object
103
+ const newUser = {
104
+ id: users.length > 0 ? users[users.length - 1].id + 1 : 1, // Simple ID generation
105
+ name,
106
+ email,
107
+ password: hashedPassword,
108
+ age,
109
+ medicalHistory,
110
+ analysisHistory: [] // Initialize analysis history
111
+ };
112
+
113
+ // Add the new user to the users array
114
+ users.push(newUser);
115
+ saveUsers(); // Save the updated user list to the file
116
+
117
+ res.status(201).json({ message: 'User registered successfully.' });
118
+
119
+ } catch (error) {
120
+ console.error('Registration error:', error);
121
+ res.status(500).json({ message: 'Registration failed. Please try again later.' });
122
+ }
123
+ });
124
+
125
+ // 2. Login
126
+ app.post('/login', async (req, res) => {
127
+ try {
128
+ const { email, password } = req.body;
129
+
130
+ // Find the user by email
131
+ const user = users.find(user => user.email === email);
132
+
133
+ // Check if the user exists
134
+ if (!user) {
135
+ return res.status(401).json({ message: 'Invalid credentials.' });
136
+ }
137
+
138
+ // Compare the provided password with the hashed password
139
+ const passwordMatch = await bcrypt.compare(password, user.password);
140
+
141
+ // Check if the passwords match
142
+ if (!passwordMatch) {
143
+ return res.status(401).json({ message: 'Invalid credentials.' });
144
+ }
145
+
146
+ // Generate a JWT
147
+ const token = generateToken(user);
148
+
149
+ // Respond with the token
150
+ res.status(200).json({ token: token, message: 'Login successful' });
151
+
152
+ } catch (error) {
153
+ console.error('Login error:', error);
154
+ res.status(500).json({ message: 'Login failed.' });
155
+ }
156
+ });
157
+
158
+ // 3. Authentication Middleware
159
+ function authenticateToken(req, res, next) {
160
+ const authHeader = req.headers['authorization'];
161
+ const token = authHeader && authHeader.split(' ')[1];
162
+
163
+ if (!token) {
164
+ return res.status(401).json({ message: 'Unauthorized: No token provided.' });
165
+ }
166
+
167
+ jwt.verify(token, secretKey, (err, user) => {
168
+ if (err) {
169
+ console.error('Token verification error:', err);
170
+ return res.status(403).json({ message: 'Forbidden: Invalid token.' });
171
+ }
172
+ req.user = user;
173
+ next();
174
+ });
175
+ }
176
+
177
+ // 4. Get User Data (Protected Route)
178
+ app.get('/user', authenticateToken, (req, res) => {
179
+ try {
180
+ const userId = req.user.userId;
181
+ const user = users.find(user => user.id === userId);
182
+
183
+ if (!user) {
184
+ return res.status(404).json({ message: 'User not found.' });
185
+ }
186
+
187
+ // Return user data (excluding the password)
188
+ const userData = {
189
+ name: user.name,
190
+ email: user.email,
191
+ age: user.age,
192
+ medicalHistory: user.medicalHistory,
193
+ analysisHistory: user.analysisHistory || [] // Get analysis history
194
+ };
195
+
196
+ res.status(200).json(userData);
197
+
198
+ } catch (error) {
199
+ console.error('Error fetching user data:', error);
200
+ res.status(500).json({ message: 'Failed to fetch user data.' });
201
+ }
202
+ });
203
+
204
+ // 5. Image Analysis
205
+ app.post('/analyze', authenticateToken, upload.single('image'), async (req, res) => {
206
+ try {
207
+ if (!req.file) {
208
+ return res.status(400).json({ message: 'No image uploaded.' });
209
+ }
210
+
211
+ const imagePath = req.file.path;
212
+ const userId = req.user.userId;
213
+
214
+ // --- Placeholder for Model Prediction ---
215
+ const glaucomaProbability = Math.random();
216
+ const otherDiseases = {
217
+ 'Diabetic Retinopathy': Math.random(),
218
+ 'Macular Degeneration': Math.random()
219
+ };
220
+
221
+ const analysisDescription = glaucomaProbability > 0.7 ? 'Possible signs of glaucoma detected. Consult an ophthalmologist.' : 'No significant signs of glaucoma detected.';
222
+
223
+ // --- Store Analysis History ---
224
+ const userIndex = users.findIndex(user => user.id === userId);
225
+ if (userIndex !== -1) {
226
+ users[userIndex].analysisHistory.push({
227
+ date: new Date(),
228
+ imagePath: imagePath,
229
+ glaucoma_probability: glaucomaProbability,
230
+ analysis_description: analysisDescription,
231
+ other_diseases: otherDiseases
232
+ });
233
+ saveUsers(); // Save the updated user list to the file
234
+ } else {
235
+ console.warn(`User with ID ${userId} not found for analysis history update.`);
236
+ }
237
+
238
+ // --- Respond with the analysis results ---
239
+ res.status(200).json({
240
+ glaucoma_probability: glaucomaProbability,
241
+ analysis_description: analysisDescription,
242
+ other_diseases: otherDiseases,
243
+ image_path: imagePath // Send the image path back to the client
244
+ });
245
+
246
+ } catch (error) {
247
+ console.error('Analysis error:', error);
248
+ res.status(500).json({ message: 'Image analysis failed. Please try again later.' });
249
+ }
250
+ });
251
+
252
+ // 6. Contact Form (Placeholder)
253
+ app.post('/contact', (req, res) => {
254
+ const { name, email, message } = req.body;
255
+
256
+ if (!name || !email || !message) {
257
+ return res.status(400).json({ message: 'All fields are required.' });
258
+ }
259
+
260
+ console.log('Contact form submission:', { name, email, message });
261
+ res.status(200).json({ message: 'Your message has been sent (simulated).' });
262
+ });
263
+
264
+ // --- Start the Server ---
265
+ app.listen(port, () => {
266
+ console.log(`Server listening on port ${port}`);
267
+ });