linguabot commited on
Commit
48affd9
·
verified ·
1 Parent(s): dff6e2d

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. routes/auth.js +76 -14
routes/auth.js CHANGED
@@ -2,7 +2,7 @@
2
  const express = require('express');
3
  const router = express.Router();
4
 
5
- // Pre-defined users
6
  const PREDEFINED_USERS = {
7
  'mche0278@student.monash.edu': { name: 'Michelle Chen', email: 'mche0278@student.monash.edu', role: 'student' },
8
  'zfan0011@student.monash.edu': { name: 'Fang Zhou', email: 'zfan0011@student.monash.edu', role: 'student' },
@@ -22,6 +22,14 @@ const PREDEFINED_USERS = {
22
  'hongchang.yu@monash.edu': { name: 'Tristan', email: 'hongchang.yu@monash.edu', role: 'admin' }
23
  };
24
 
 
 
 
 
 
 
 
 
25
  // Middleware to verify token (simplified)
26
  const authenticateToken = (req, res, next) => {
27
  const authHeader = req.headers['authorization'];
@@ -91,7 +99,12 @@ router.post('/online/heartbeat', authenticateToken, async (req, res) => {
91
  router.post('/login', async (req, res) => {
92
  try {
93
  const { email } = req.body;
94
- const user = PREDEFINED_USERS[email];
 
 
 
 
 
95
  if (user) {
96
  const token = `user_${Date.now()}`;
97
  // Persist an access session immediately on login
@@ -99,6 +112,16 @@ router.post('/login', async (req, res) => {
99
  const AccessSession = require('../models/AccessSession');
100
  await new AccessSession({ email: user.email, role: user.role, startAt: new Date(), lastSeen: new Date(), path: '/login' }).save();
101
  } catch (e) {}
 
 
 
 
 
 
 
 
 
 
102
  res.json({ success: true, token, user: { name: user.name, displayName: user.displayName || user.name, email: user.email, role: user.role } });
103
  } else {
104
  const visitorUser = { name: 'Visitor', email, role: 'visitor' };
@@ -107,6 +130,7 @@ router.post('/login', async (req, res) => {
107
  const AccessSession = require('../models/AccessSession');
108
  await new AccessSession({ email: (email || 'visitor@example.com'), role: 'visitor', startAt: new Date(), lastSeen: new Date(), path: '/login' }).save();
109
  } catch (e) {}
 
110
  res.json({ success: true, token, user: visitorUser });
111
  }
112
  } catch (error) {
@@ -130,10 +154,20 @@ router.get('/admin/users', authenticateToken, async (req, res) => {
130
  try {
131
  const now = Date.now();
132
  const ONLINE_WINDOW_MS = 2 * 60 * 1000; // 2 minutes
133
- const users = Object.values(PREDEFINED_USERS).map(u => ({
134
- ...u,
135
- online: !!(ONLINE_USERS[u.email] && (now - ONLINE_USERS[u.email] < ONLINE_WINDOW_MS))
136
- }));
 
 
 
 
 
 
 
 
 
 
137
  res.json({ success: true, users });
138
  } catch (error) {
139
  console.error('Get users error:', error);
@@ -146,8 +180,19 @@ router.post('/admin/users', authenticateToken, async (req, res) => {
146
  try {
147
  const { name, email, role, displayName } = req.body || {};
148
  if (!email || !name) return res.status(400).json({ error: 'Name and email required' });
149
- PREDEFINED_USERS[email] = { name, email, role: role || 'student', ...(displayName ? { displayName } : {}) };
150
- res.json({ success: true, user: PREDEFINED_USERS[email] });
 
 
 
 
 
 
 
 
 
 
 
151
  } catch (error) {
152
  console.error('Add user error:', error);
153
  res.status(500).json({ error: 'Failed to add user' });
@@ -158,12 +203,24 @@ router.post('/admin/users', authenticateToken, async (req, res) => {
158
  router.put('/admin/users/:email', authenticateToken, async (req, res) => {
159
  try {
160
  const email = req.params.email;
161
- if (!PREDEFINED_USERS[email]) return res.status(404).json({ error: 'User not found' });
162
  const { name, role, displayName } = req.body || {};
163
- if (typeof name === 'string' && name.trim()) PREDEFINED_USERS[email].name = name.trim();
164
- if (typeof role === 'string' && role.trim()) PREDEFINED_USERS[email].role = role.trim();
165
- if (typeof displayName === 'string') PREDEFINED_USERS[email].displayName = displayName;
166
- res.json({ success: true, user: PREDEFINED_USERS[email] });
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  } catch (error) {
168
  console.error('Update user error:', error);
169
  res.status(500).json({ error: 'Failed to update user' });
@@ -175,8 +232,13 @@ router.get('/admin/stats', authenticateToken, async (req, res) => {
175
  const SourceText = require('../models/SourceText');
176
  const Submission = require('../models/Submission');
177
  const AccessSession = require('../models/AccessSession');
 
 
 
 
 
178
  const stats = {
179
- totalUsers: Object.keys(PREDEFINED_USERS).length,
180
  practiceExamples: await SourceText.countDocuments({ sourceType: 'practice' }),
181
  totalSubmissions: await Submission.countDocuments(),
182
  activeSessions: await AccessSession.countDocuments({ lastSeen: { $gte: new Date(Date.now() - 15 * 60 * 1000) } })
 
2
  const express = require('express');
3
  const router = express.Router();
4
 
5
+ // Pre-defined users (legacy, kept for backwards compatibility). New code persists to MongoDB.
6
  const PREDEFINED_USERS = {
7
  'mche0278@student.monash.edu': { name: 'Michelle Chen', email: 'mche0278@student.monash.edu', role: 'student' },
8
  'zfan0011@student.monash.edu': { name: 'Fang Zhou', email: 'zfan0011@student.monash.edu', role: 'student' },
 
22
  'hongchang.yu@monash.edu': { name: 'Tristan', email: 'hongchang.yu@monash.edu', role: 'admin' }
23
  };
24
 
25
+ // Persistent users model
26
+ let User;
27
+ try {
28
+ User = require('../models/User');
29
+ } catch (e) {
30
+ User = null;
31
+ }
32
+
33
  // Middleware to verify token (simplified)
34
  const authenticateToken = (req, res, next) => {
35
  const authHeader = req.headers['authorization'];
 
99
  router.post('/login', async (req, res) => {
100
  try {
101
  const { email } = req.body;
102
+ // Try persistent user first
103
+ let dbUser = null;
104
+ if (User && email) {
105
+ try { dbUser = await User.findOne({ email: String(email).toLowerCase().trim() }); } catch {}
106
+ }
107
+ const user = dbUser || PREDEFINED_USERS[email];
108
  if (user) {
109
  const token = `user_${Date.now()}`;
110
  // Persist an access session immediately on login
 
112
  const AccessSession = require('../models/AccessSession');
113
  await new AccessSession({ email: user.email, role: user.role, startAt: new Date(), lastSeen: new Date(), path: '/login' }).save();
114
  } catch (e) {}
115
+ // Upsert user into persistent store to avoid loss
116
+ if (User && user?.email) {
117
+ try {
118
+ await User.findOneAndUpdate(
119
+ { email: String(user.email).toLowerCase().trim() },
120
+ { $set: { name: user.name || user.displayName || '', username: (user.email || '').split('@')[0], email: String(user.email).toLowerCase().trim(), role: user.role || 'student' } },
121
+ { upsert: true, new: true, setDefaultsOnInsert: true }
122
+ );
123
+ } catch {}
124
+ }
125
  res.json({ success: true, token, user: { name: user.name, displayName: user.displayName || user.name, email: user.email, role: user.role } });
126
  } else {
127
  const visitorUser = { name: 'Visitor', email, role: 'visitor' };
 
130
  const AccessSession = require('../models/AccessSession');
131
  await new AccessSession({ email: (email || 'visitor@example.com'), role: 'visitor', startAt: new Date(), lastSeen: new Date(), path: '/login' }).save();
132
  } catch (e) {}
133
+ // Do not persist visitors by default
134
  res.json({ success: true, token, user: visitorUser });
135
  }
136
  } catch (error) {
 
154
  try {
155
  const now = Date.now();
156
  const ONLINE_WINDOW_MS = 2 * 60 * 1000; // 2 minutes
157
+ let users = [];
158
+ if (User) {
159
+ try {
160
+ const docs = await User.find({}).select('name email role').sort({ email: 1 }).lean();
161
+ users = docs.map(u => ({ ...u, online: !!(ONLINE_USERS[u.email] && (now - ONLINE_USERS[u.email] < ONLINE_WINDOW_MS)) }));
162
+ } catch {}
163
+ }
164
+ // Fallback to predefined if DB empty
165
+ if (!users || users.length === 0) {
166
+ users = Object.values(PREDEFINED_USERS).map(u => ({
167
+ ...u,
168
+ online: !!(ONLINE_USERS[u.email] && (now - ONLINE_USERS[u.email] < ONLINE_WINDOW_MS))
169
+ }));
170
+ }
171
  res.json({ success: true, users });
172
  } catch (error) {
173
  console.error('Get users error:', error);
 
180
  try {
181
  const { name, email, role, displayName } = req.body || {};
182
  if (!email || !name) return res.status(400).json({ error: 'Name and email required' });
183
+ let saved = null;
184
+ if (User) {
185
+ try {
186
+ saved = await User.findOneAndUpdate(
187
+ { email: String(email).toLowerCase().trim() },
188
+ { $set: { name: name.trim(), username: String(email).split('@')[0], email: String(email).toLowerCase().trim(), role: (role || 'student').trim() } },
189
+ { upsert: true, new: true, setDefaultsOnInsert: true }
190
+ );
191
+ } catch {}
192
+ }
193
+ // Keep legacy map in sync (non-critical)
194
+ PREDEFINED_USERS[email] = { name, email: String(email).toLowerCase().trim(), role: role || 'student', ...(displayName ? { displayName } : {}) };
195
+ res.json({ success: true, user: saved || PREDEFINED_USERS[email] });
196
  } catch (error) {
197
  console.error('Add user error:', error);
198
  res.status(500).json({ error: 'Failed to add user' });
 
203
  router.put('/admin/users/:email', authenticateToken, async (req, res) => {
204
  try {
205
  const email = req.params.email;
 
206
  const { name, role, displayName } = req.body || {};
207
+ let updated = null;
208
+ if (User) {
209
+ try {
210
+ const update = {};
211
+ if (typeof name === 'string' && name.trim()) update.name = name.trim();
212
+ if (typeof role === 'string' && role.trim()) update.role = role.trim();
213
+ updated = await User.findOneAndUpdate({ email: String(email).toLowerCase().trim() }, { $set: update }, { new: true });
214
+ } catch {}
215
+ }
216
+ // Sync legacy map as best-effort
217
+ if (!PREDEFINED_USERS[email]) PREDEFINED_USERS[email] = { name: name || '', email, role: role || 'student', ...(displayName ? { displayName } : {}) };
218
+ else {
219
+ if (typeof name === 'string' && name.trim()) PREDEFINED_USERS[email].name = name.trim();
220
+ if (typeof role === 'string' && role.trim()) PREDEFINED_USERS[email].role = role.trim();
221
+ if (typeof displayName === 'string') PREDEFINED_USERS[email].displayName = displayName;
222
+ }
223
+ res.json({ success: true, user: updated || PREDEFINED_USERS[email] });
224
  } catch (error) {
225
  console.error('Update user error:', error);
226
  res.status(500).json({ error: 'Failed to update user' });
 
232
  const SourceText = require('../models/SourceText');
233
  const Submission = require('../models/Submission');
234
  const AccessSession = require('../models/AccessSession');
235
+ let totalUsers = 0;
236
+ if (User) {
237
+ try { totalUsers = await User.countDocuments({}); } catch {}
238
+ }
239
+ if (!totalUsers) totalUsers = Object.keys(PREDEFINED_USERS).length;
240
  const stats = {
241
+ totalUsers,
242
  practiceExamples: await SourceText.countDocuments({ sourceType: 'practice' }),
243
  totalSubmissions: await Submission.countDocuments(),
244
  activeSessions: await AccessSession.countDocuments({ lastSeen: { $gte: new Date(Date.now() - 15 * 60 * 1000) } })