meissosisai commited on
Commit
3ad0250
·
1 Parent(s): a314cc1

Critical Fix: Resolve 401 'Subject not found' loop, stabilize HF Space persistence, and improve session recovery

Browse files
backend/controllers/users.js CHANGED
@@ -51,6 +51,11 @@ exports.updatePreferences = asyncHandler(async (req, res, next) => {
51
  exports.getProfile = asyncHandler(async (req, res, next) => {
52
  const user = await User.findById(req.user.id);
53
 
 
 
 
 
 
54
  const profile = {
55
  name: user.name,
56
  role: user.role,
 
51
  exports.getProfile = asyncHandler(async (req, res, next) => {
52
  const user = await User.findById(req.user.id);
53
 
54
+ if (!user) {
55
+ res.clearCookie('token');
56
+ return next(new ErrorResponse('Not authorized', 401));
57
+ }
58
+
59
  const profile = {
60
  name: user.name,
61
  role: user.role,
backend/middleware/auth.js CHANGED
@@ -25,11 +25,13 @@ exports.protect = asyncHandler(async (req, res, next) => {
25
  req.user = await User.findById(decoded.id);
26
 
27
  if (!req.user) {
28
- return next(new ErrorResponse('Not authorized: Subject not found in archive', 401));
 
29
  }
30
  next();
31
  } catch (err) {
32
  console.log(`AUTH_FAILURE: Token verification failed (${err.message})`);
 
33
  return next(new ErrorResponse('Not authorized: Link signature invalid', 401));
34
  }
35
  });
 
25
  req.user = await User.findById(decoded.id);
26
 
27
  if (!req.user) {
28
+ res.clearCookie('token');
29
+ return next(new ErrorResponse('Not authorized: Subject not found in archive. Please log in again.', 401));
30
  }
31
  next();
32
  } catch (err) {
33
  console.log(`AUTH_FAILURE: Token verification failed (${err.message})`);
34
+ res.clearCookie('token');
35
  return next(new ErrorResponse('Not authorized: Link signature invalid', 401));
36
  }
37
  });
backend/models/Announcement.js CHANGED
@@ -1,14 +1,22 @@
1
  const { db } = require('../db');
2
 
3
  class Announcement {
4
- static async findOne(query) {
5
  return {
6
- sort: (sortQuery) => new Promise((resolve, reject) => {
7
- db.announcements.find(query).sort(sortQuery).limit(1).exec((err, docs) => {
8
- if (err) reject(err);
9
- else resolve(docs[0] || null);
10
- });
11
- })
 
 
 
 
 
 
 
 
12
  };
13
  }
14
 
@@ -23,4 +31,4 @@ class Announcement {
23
  }
24
  }
25
 
26
- module.exports = Announcement;
 
1
  const { db } = require('../db');
2
 
3
  class Announcement {
4
+ static findOne(query) {
5
  return {
6
+ sort: function(sortQuery) {
7
+ this._sort = sortQuery;
8
+ return this;
9
+ },
10
+ then: function(resolve, reject) {
11
+ return new Promise((res, rej) => {
12
+ let q = db.announcements.find(query);
13
+ if (this._sort) q = q.sort(this._sort);
14
+ q.limit(1).exec((err, docs) => {
15
+ if (err) rej(err);
16
+ else res(docs[0] || null);
17
+ });
18
+ }).then(resolve, reject);
19
+ }
20
  };
21
  }
22
 
 
31
  }
32
  }
33
 
34
+ module.exports = Announcement;
backend/models/Message.js CHANGED
@@ -1,23 +1,29 @@
1
  const { db } = require('../db');
2
 
3
  class Message {
4
- static async find(query) {
5
- return {
6
- sort: (sortQuery) => ({
7
- limit: (limitNum) => new Promise((resolve, reject) => {
8
- db.messages.find(query).sort(sortQuery).limit(limitNum).exec((err, docs) => {
9
- if (err) reject(err);
10
- else resolve(docs);
 
 
 
 
 
 
 
 
 
 
 
11
  });
12
- }),
13
- exec: () => new Promise((resolve, reject) => {
14
- db.messages.find(query).sort(sortQuery).exec((err, docs) => {
15
- if (err) reject(err);
16
- else resolve(docs);
17
- });
18
- })
19
- })
20
  };
 
21
  }
22
 
23
  static async create(msgData) {
@@ -40,4 +46,4 @@ class Message {
40
  }
41
  }
42
 
43
- module.exports = Message;
 
1
  const { db } = require('../db');
2
 
3
  class Message {
4
+ static find(query) {
5
+ const chain = {
6
+ sort: function(sortQuery) {
7
+ this._sort = sortQuery;
8
+ return this;
9
+ },
10
+ limit: function(limitNum) {
11
+ this._limit = limitNum;
12
+ return this;
13
+ },
14
+ then: function(resolve, reject) {
15
+ return new Promise((res, rej) => {
16
+ let q = db.messages.find(query);
17
+ if (this._sort) q = q.sort(this._sort);
18
+ if (this._limit) q = q.limit(this._limit);
19
+ q.exec((err, docs) => {
20
+ if (err) rej(err);
21
+ else res(docs);
22
  });
23
+ }).then(resolve, reject);
24
+ }
 
 
 
 
 
 
25
  };
26
+ return chain;
27
  }
28
 
29
  static async create(msgData) {
 
46
  }
47
  }
48
 
49
+ module.exports = Message;
backend/models/User.js CHANGED
@@ -8,13 +8,24 @@ class User {
8
  Object.assign(this, userData);
9
  }
10
 
11
- static async findOne(query) {
12
- return new Promise((resolve, reject) => {
13
- db.users.findOne(query, (err, doc) => {
14
- if (err) reject(err);
15
- else resolve(doc ? new User(doc) : null);
16
- });
17
- });
 
 
 
 
 
 
 
 
 
 
 
18
  }
19
 
20
  static async findById(id) {
@@ -35,7 +46,6 @@ class User {
35
  userData.createdAt = userData.createdAt || new Date();
36
  userData.role = userData.role || 'user';
37
 
38
- // Ownership check
39
  const owners = ['johanvoncd7@gmail.com', 'codexai@mightysmp.online'];
40
  if (owners.includes(userData.email)) {
41
  userData.role = 'owner';
@@ -86,24 +96,6 @@ class User {
86
  });
87
  });
88
  }
89
-
90
- // Chainable .select implementation for compatibility
91
- static findOne(query) {
92
- return {
93
- select: (fields) => new Promise((resolve, reject) => {
94
- db.users.findOne(query, (err, doc) => {
95
- if (err) reject(err);
96
- else resolve(doc ? new User(doc) : null);
97
- });
98
- }),
99
- then: (resolve, reject) => {
100
- db.users.findOne(query, (err, doc) => {
101
- if (err) { if (reject) reject(err); }
102
- else resolve(doc ? new User(doc) : null);
103
- });
104
- }
105
- };
106
- }
107
  }
108
 
109
  module.exports = User;
 
8
  Object.assign(this, userData);
9
  }
10
 
11
+ static findOne(query) {
12
+ const chain = {
13
+ select: function(fields) {
14
+ return this;
15
+ },
16
+ then: function(resolve, reject) {
17
+ return new Promise((res, rej) => {
18
+ db.users.findOne(query, (err, doc) => {
19
+ if (err) rej(err);
20
+ else res(doc ? new User(doc) : null);
21
+ });
22
+ }).then(resolve, reject);
23
+ },
24
+ catch: function(reject) {
25
+ return this.then(null, reject);
26
+ }
27
+ };
28
+ return chain;
29
  }
30
 
31
  static async findById(id) {
 
46
  userData.createdAt = userData.createdAt || new Date();
47
  userData.role = userData.role || 'user';
48
 
 
49
  const owners = ['johanvoncd7@gmail.com', 'codexai@mightysmp.online'];
50
  if (owners.includes(userData.email)) {
51
  userData.role = 'owner';
 
96
  });
97
  });
98
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  }
100
 
101
  module.exports = User;
backend/public/chat.html CHANGED
@@ -307,6 +307,13 @@
307
  input.value = ''; input.style.height = 'auto';
308
  try {
309
  const res = await fetch(`${API_BASE}/api/ai/chat`, { method: 'POST', headers: { 'Authorization': `Bearer ${token}` }, body: fd });
 
 
 
 
 
 
 
310
  const reader = res.body.getReader(); const decoder = new TextDecoder();
311
  let aiNode = appendMessage('ai', '', activeModel); let fullText = "";
312
  while (true) {
 
307
  input.value = ''; input.style.height = 'auto';
308
  try {
309
  const res = await fetch(`${API_BASE}/api/ai/chat`, { method: 'POST', headers: { 'Authorization': `Bearer ${token}` }, body: fd });
310
+
311
+ if (res.status === 401) {
312
+ localStorage.removeItem('token');
313
+ window.location.href = '/auth?error=SESSION_EXPIRED';
314
+ return;
315
+ }
316
+
317
  const reader = res.body.getReader(); const decoder = new TextDecoder();
318
  let aiNode = appendMessage('ai', '', activeModel); let fullText = "";
319
  while (true) {
backend/services/persistenceService.js CHANGED
@@ -26,7 +26,13 @@ exports.syncToCloud = async () => {
26
  try {
27
  execSync(`git add backend/data/*.db`, { cwd: rootDir });
28
  execSync(`git ${gitIdent} commit -m "Neural Archive Sync: [$(date)]"`, { cwd: rootDir });
29
- execSync(`git push "${remoteUrl}" main`, { cwd: rootDir });
 
 
 
 
 
 
30
  console.log('[PERSISTENCE] Cloud Sync: SUCCESS ✅');
31
  } catch (gitErr) {
32
  if (gitErr.message.includes('nothing to commit')) {
 
26
  try {
27
  execSync(`git add backend/data/*.db`, { cwd: rootDir });
28
  execSync(`git ${gitIdent} commit -m "Neural Archive Sync: [$(date)]"`, { cwd: rootDir });
29
+
30
+ if (process.env.SPACE_ID || process.env.HF_TOKEN) {
31
+ console.log('[PERSISTENCE] HF_SPACE detected. Skipping remote push to prevent restart loop.');
32
+ } else {
33
+ execSync(`git push "${remoteUrl}" main`, { cwd: rootDir });
34
+ }
35
+
36
  console.log('[PERSISTENCE] Cloud Sync: SUCCESS ✅');
37
  } catch (gitErr) {
38
  if (gitErr.message.includes('nothing to commit')) {