@yeaft/webchat-agent 1.0.657 → 1.0.659
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/local-runtime/server/database.js +1 -0
- package/local-runtime/server/db/connection.js +17 -0
- package/local-runtime/server/db/user-preferences-db.js +15 -0
- package/local-runtime/server/routes/user-routes.js +39 -1
- package/local-runtime/version.json +1 -1
- package/local-runtime/web/app.bundle.js +188 -151
- package/local-runtime/web/app.bundle.js.gz +0 -0
- package/local-runtime/web/index.html +2 -2
- package/local-runtime/web/style.bundle.css +1 -1
- package/local-runtime/web/style.bundle.css.gz +0 -0
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Re-export entry point — preserves all existing import paths.
|
|
2
2
|
// Actual implementations are in server/db/*.js sub-modules.
|
|
3
3
|
export { userDb } from './db/user-db.js';
|
|
4
|
+
export { userPreferencesDb } from './db/user-preferences-db.js';
|
|
4
5
|
export { invitationDb } from './db/invitation-db.js';
|
|
5
6
|
export { sessionDb } from './db/session-db.js';
|
|
6
7
|
export { yeaftSessionDb } from './db/yeaft-session-db.js';
|
|
@@ -38,6 +38,12 @@ db.exec(`
|
|
|
38
38
|
deletion_id TEXT UNIQUE
|
|
39
39
|
);
|
|
40
40
|
|
|
41
|
+
CREATE TABLE IF NOT EXISTS user_preferences (
|
|
42
|
+
user_id TEXT PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
|
|
43
|
+
sidebar_projects_ratio REAL NOT NULL DEFAULT 0.5
|
|
44
|
+
CHECK (sidebar_projects_ratio >= 0.15 AND sidebar_projects_ratio <= 0.85)
|
|
45
|
+
);
|
|
46
|
+
|
|
41
47
|
-- Finalized deletion survives removal of the users row. This prevents a
|
|
42
48
|
-- configured credential from becoming authoritative again on restart.
|
|
43
49
|
CREATE TABLE IF NOT EXISTS user_deletion_tombstones (
|
|
@@ -900,6 +906,17 @@ export const stmts = {
|
|
|
900
906
|
UPDATE users SET aad_oid = ? WHERE id = ?
|
|
901
907
|
`),
|
|
902
908
|
|
|
909
|
+
getUserPreferences: db.prepare(`
|
|
910
|
+
SELECT sidebar_projects_ratio FROM user_preferences WHERE user_id = ?
|
|
911
|
+
`),
|
|
912
|
+
|
|
913
|
+
upsertUserPreferences: db.prepare(`
|
|
914
|
+
INSERT INTO user_preferences (user_id, sidebar_projects_ratio)
|
|
915
|
+
VALUES (?, ?)
|
|
916
|
+
ON CONFLICT(user_id) DO UPDATE SET
|
|
917
|
+
sidebar_projects_ratio = excluded.sidebar_projects_ratio
|
|
918
|
+
`),
|
|
919
|
+
|
|
903
920
|
// Invitation 操作
|
|
904
921
|
insertInvitation: db.prepare(`
|
|
905
922
|
INSERT INTO invitations (id, created_by, created_at, expires_at, role)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { stmts } from './connection.js';
|
|
2
|
+
|
|
3
|
+
/** Server-owned browser preferences, scoped to an authenticated user's DB id. */
|
|
4
|
+
export const userPreferencesDb = {
|
|
5
|
+
get(userId) {
|
|
6
|
+
const row = stmts.getUserPreferences.get(userId);
|
|
7
|
+
return { sidebarProjectsRatio: row?.sidebar_projects_ratio ?? 0.5 };
|
|
8
|
+
},
|
|
9
|
+
|
|
10
|
+
// The HTTP boundary validates the ratio; the schema also enforces its range.
|
|
11
|
+
update(userId, sidebarProjectsRatio) {
|
|
12
|
+
stmts.upsertUserPreferences.run(userId, sidebarProjectsRatio);
|
|
13
|
+
return this.get(userId);
|
|
14
|
+
},
|
|
15
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CONFIG } from '../config.js';
|
|
2
2
|
import { hashPassword } from '../auth.js';
|
|
3
|
-
import { userDb, sessionDb } from '../database.js';
|
|
3
|
+
import { userDb, userPreferencesDb, sessionDb } from '../database.js';
|
|
4
4
|
import {
|
|
5
5
|
activeSessions, pendingVerifications, pendingTotpVerifications, pendingTotpSetup,
|
|
6
6
|
revokedTokens
|
|
@@ -83,6 +83,44 @@ export function registerUserRoutes(app, {
|
|
|
83
83
|
}
|
|
84
84
|
});
|
|
85
85
|
|
|
86
|
+
app.get('/api/user/preferences', requireAuth, (req, res) => {
|
|
87
|
+
try {
|
|
88
|
+
const user = loadCurrentUser(req);
|
|
89
|
+
if (!user) {
|
|
90
|
+
return res.status(404).json({ error: 'User not found' });
|
|
91
|
+
}
|
|
92
|
+
res.set('Cache-Control', 'private, no-store').json(userPreferencesDb.get(user.id));
|
|
93
|
+
} catch (err) {
|
|
94
|
+
console.error('Get preferences error:', err);
|
|
95
|
+
res.status(500).json({ error: 'Failed to get preferences' });
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
app.patch('/api/user/preferences', requireAuth, (req, res) => {
|
|
100
|
+
try {
|
|
101
|
+
const user = loadCurrentUser(req);
|
|
102
|
+
if (!user) {
|
|
103
|
+
return res.status(404).json({ error: 'User not found' });
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const body = req.body;
|
|
107
|
+
if (!body || typeof body !== 'object' || Array.isArray(body)
|
|
108
|
+
|| Object.keys(body).some(key => key !== 'sidebarProjectsRatio')
|
|
109
|
+
|| typeof body.sidebarProjectsRatio !== 'number'
|
|
110
|
+
|| !Number.isFinite(body.sidebarProjectsRatio)
|
|
111
|
+
|| body.sidebarProjectsRatio < 0.15 || body.sidebarProjectsRatio > 0.85) {
|
|
112
|
+
return res.status(400).json({
|
|
113
|
+
error: 'Expected only sidebarProjectsRatio, a finite number between 0.15 and 0.85',
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
res.set('Cache-Control', 'private, no-store').json(userPreferencesDb.update(user.id, body.sidebarProjectsRatio));
|
|
118
|
+
} catch (err) {
|
|
119
|
+
console.error('Update preferences error:', err);
|
|
120
|
+
res.status(500).json({ error: 'Failed to update preferences' });
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
86
124
|
// Update my profile (password and/or email)
|
|
87
125
|
app.put('/api/user/profile', requireAuth, async (req, res) => {
|
|
88
126
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"1.0.
|
|
1
|
+
{"version":"1.0.659"}
|