Skip to content

Commit 245a5d6

Browse files
SQLITECLOUD update
1 parent 6ae63eb commit 245a5d6

10 files changed

Lines changed: 551 additions & 35 deletions

File tree

backend/.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ GROQ_MODEL=openai/gpt-oss-120b
44
LLM_TIMEOUT_MS=30000
55

66
DB_PROVIDER=sqlitecloud
7-
SQLITECLOUD_URL=sqlitecloud://cn2gr5hvdk.g2.sqlite.cloud:8860/auth.sqlitecloud?apikey=V2ktpR7JkdaZTnRXp2MAGcjhOzi9adtOSjzkaGAcf4k
7+
SQLITECLOUD_URL=sqlitecloud://cn2gr5hvdk.g2.sqlite.cloud:8860/userDATA?apikey=V2ktpR7JkdaZTnRXp2MAGcjhOzi9adtOSjzkaGAcf4k

backend/index.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const {
1111

1212
const { initDbIfNeeded } = require('./services/dbInit');
1313
const { initCatalogSchema } = require('./services/careerCatalog');
14+
const { getUserDataDb } = require('./services/userDataStore');
1415

1516
const authRoutes = require('./routes/auth');
1617
const profileRoutes = require('./routes/profile');
@@ -76,6 +77,16 @@ async function initializeMainDb() {
7677

7778
await initCatalogSchema();
7879
console.log('📚 Catalog schema ready');
80+
81+
try {
82+
const userDataDb = await getUserDataDb();
83+
if (userDataDb) {
84+
console.log('🗂️ userDATA schema ready');
85+
}
86+
} catch (userDataErr) {
87+
console.warn('⚠️ userDATA initialization warning:', userDataErr.message);
88+
}
89+
7990
startServer();
8091
} catch (e) {
8192
console.error('❌ DB init failed:', e.message);

backend/routes/auth.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const jwt = require('jsonwebtoken');
66
const router = express.Router();
77
const { JWT_SECRET, ADMIN_EMAIL } = require('../config');
88
const { requireAuth } = require('../middleware/auth');
9+
const { mirrorUserAccount } = require('../services/userDataStore');
910

1011
function hasColumn(tableName, columnName) {
1112
return new Promise((resolve) => {
@@ -165,6 +166,15 @@ router.post('/register', async (req, res) => {
165166
throw new Error('Đăng ký thất bại: dữ liệu email lưu không khớp');
166167
}
167168

169+
await mirrorUserAccount({
170+
appUserId: result.lastID,
171+
username: loginName,
172+
email: normalizedEmail,
173+
passwordHash,
174+
userType,
175+
source: 'auth_register'
176+
});
177+
168178
const token = jwt.sign({
169179
user_id: result.lastID,
170180
username: loginName,
@@ -220,6 +230,19 @@ router.post('/login', async (req, res) => {
220230

221231
const resolvedUsername = (usernameExists ? user.username : null) || getEmailLocalPart(user.email) || user.email;
222232

233+
try {
234+
await mirrorUserAccount({
235+
appUserId: user.id,
236+
username: resolvedUsername,
237+
email: user.email,
238+
passwordHash: user.password_hash || '',
239+
userType: user.user_type,
240+
source: 'auth_login'
241+
});
242+
} catch (mirrorError) {
243+
console.warn('Login mirror warning:', mirrorError.message);
244+
}
245+
223246
const token = jwt.sign({
224247
user_id: user.id,
225248
username: resolvedUsername,

backend/routes/chat.js

Lines changed: 69 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ const {
1212
} = require('../services/questionEngine');
1313
const llmScorer = require('../services/llmScorer');
1414
const { isEnabled: isLlmEnabled } = llmScorer;
15+
const {
16+
mirrorChatMessage,
17+
mirrorCareerProbabilities,
18+
deleteMirroredConversationData,
19+
deleteMirroredUserHistory
20+
} = require('../services/userDataStore');
1521

1622
const MEMORY_MESSAGES = [];
1723
const MIN_CONF_SCORE = 1;
@@ -664,24 +670,38 @@ router.put('/conversation/:conversationId', requireAuth, async (req, res) => {
664670
);
665671
});
666672

667-
router.delete('/history/:userId', requireAuth, (req, res) => {
673+
router.delete('/history/:userId', requireAuth, async (req, res) => {
668674
const { userId } = req.params;
669675
if (req.user.user_type !== 'admin' && String(req.user.user_id) !== String(userId)) {
670676
return res.status(403).json({ success: false, error: 'Forbidden' });
671677
}
672678
const delMessages = 'DELETE FROM chat_messages WHERE user_id = ?';
673679
const delRecs = 'DELETE FROM recommendations WHERE user_id = ?';
680+
const delState = 'DELETE FROM conversation_state WHERE user_id = ?';
674681
const delConversations = 'DELETE FROM conversations WHERE user_id = ?';
675-
global.db.serialize(() => {
676-
global.db.run(delMessages, [userId]);
677-
global.db.run(delRecs, [userId], function (err) {
678-
if (err) return res.status(500).json({ success: false, error: err.message });
679-
global.db.run(delConversations, [userId], (err2) => {
680-
if (err2) return res.status(500).json({ success: false, error: err2.message });
681-
res.json({ success: true, data: { deleted: true } });
682+
try {
683+
await new Promise((resolve, reject) => {
684+
global.db.serialize(() => {
685+
global.db.run(delMessages, [userId]);
686+
global.db.run(delRecs, [userId]);
687+
global.db.run(delState, [userId]);
688+
global.db.run(delConversations, [userId], (err) => {
689+
if (err) return reject(err);
690+
resolve();
691+
});
682692
});
683693
});
684-
});
694+
695+
try {
696+
await deleteMirroredUserHistory({ appUserId: Number(userId) || userId });
697+
} catch (mirrorError) {
698+
console.warn('[CHAT DEBUG] deleteMirroredUserHistory warning:', mirrorError.message);
699+
}
700+
701+
res.json({ success: true, data: { deleted: true } });
702+
} catch (error) {
703+
res.status(500).json({ success: false, error: error.message });
704+
}
685705
});
686706

687707
router.get('/messages/:conversationId', requireAuth, (req, res) => {
@@ -739,12 +759,24 @@ router.delete('/conversation/:conversationId', requireAuth, (req, res) => {
739759

740760
const deleteMessages = 'DELETE FROM chat_messages WHERE conversation_id = ?';
741761
const deleteRecs = 'DELETE FROM recommendations WHERE conversation_id = ?';
762+
const deleteState = 'DELETE FROM conversation_state WHERE conversation_id = ?';
742763
const deleteConv = 'DELETE FROM conversations WHERE id = ?';
743764
global.db.serialize(() => {
744765
global.db.run(deleteMessages, [conversationId]);
745766
global.db.run(deleteRecs, [conversationId]);
746-
global.db.run(deleteConv, [conversationId], function (err2) {
767+
global.db.run(deleteState, [conversationId]);
768+
global.db.run(deleteConv, [conversationId], async function (err2) {
747769
if (err2) return res.status(500).json({ success: false, error: err2.message });
770+
771+
try {
772+
await deleteMirroredConversationData({
773+
appUserId: row?.user_id || null,
774+
conversationId
775+
});
776+
} catch (mirrorError) {
777+
console.warn('[CHAT DEBUG] deleteMirroredConversationData warning:', mirrorError.message);
778+
}
779+
748780
res.json({ success: true, data: { deleted: true } });
749781
});
750782
});
@@ -776,9 +808,25 @@ async function saveMessage(convId, userId, sender, message, nodeId) {
776808
reject(err);
777809
} else {
778810
console.log('[CHAT DEBUG] saveMessage SUCCESS - messageId:', this.lastID);
779-
resolve(this.lastID);
811+
const insertedId = this.lastID;
812+
resolve(insertedId);
780813
}
781814
});
815+
}).then(async (messageId) => {
816+
try {
817+
await mirrorChatMessage({
818+
appUserId: userId,
819+
conversationId: convId,
820+
messageId,
821+
sender,
822+
message,
823+
nodeId,
824+
createdAt: new Date().toISOString()
825+
});
826+
} catch (mirrorError) {
827+
console.warn('[CHAT DEBUG] mirrorChatMessage warning:', mirrorError.message);
828+
}
829+
return messageId;
782830
});
783831
}
784832

@@ -881,6 +929,16 @@ async function saveRecommendations(convId, userId, recommendations) {
881929
);
882930
});
883931
}
932+
933+
try {
934+
await mirrorCareerProbabilities({
935+
appUserId: userId,
936+
conversationId: convId,
937+
recommendations
938+
});
939+
} catch (mirrorError) {
940+
console.warn('[CHAT DEBUG] mirrorCareerProbabilities warning:', mirrorError.message);
941+
}
884942
}
885943

886944
async function logEvent(eventType, userId, metadata) {

backend/routes/profile.js

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
const express = require('express');
44
const router = express.Router();
55
const { requireAuth } = require('../middleware/auth');
6+
const { mirrorUserAccount } = require('../services/userDataStore');
67

78
function normalizeUserType(value) {
89
const normalized = String(value || '').trim().toLowerCase();
@@ -57,10 +58,37 @@ router.put('/:id', requireAuth, (req, res) => {
5758
global.db.run(
5859
'UPDATE users SET user_type = ? WHERE id = ?',
5960
[normalizedEducationLevel, targetId],
60-
(userErr) => {
61+
async (userErr) => {
6162
if (userErr) {
6263
return res.status(500).json({ success: false, error: userErr.message });
6364
}
65+
66+
try {
67+
const userRow = await new Promise((resolve) => {
68+
global.db.get(
69+
'SELECT id, email, username, password_hash, user_type FROM users WHERE id = ? LIMIT 1',
70+
[targetId],
71+
(getErr, row) => {
72+
if (getErr) return resolve(null);
73+
resolve(row || null);
74+
}
75+
);
76+
});
77+
78+
if (userRow?.email) {
79+
await mirrorUserAccount({
80+
appUserId: userRow.id,
81+
username: userRow.username || userRow.email,
82+
email: userRow.email,
83+
passwordHash: userRow.password_hash || '',
84+
userType: userRow.user_type || normalizedEducationLevel,
85+
source: 'profile_update'
86+
});
87+
}
88+
} catch (mirrorError) {
89+
console.warn('Profile mirror warning:', mirrorError.message);
90+
}
91+
6492
res.json({ success: true, data: { updated: true, user_type: normalizedEducationLevel } });
6593
}
6694
);

0 commit comments

Comments
 (0)