clay-server 2.27.0-beta.9 → 2.27.0
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/README.md +10 -0
- package/lib/daemon-projects.js +164 -0
- package/lib/daemon.js +13 -126
- package/lib/mates-identity.js +132 -0
- package/lib/mates-knowledge.js +113 -0
- package/lib/mates-prompts.js +398 -0
- package/lib/mates.js +40 -599
- package/lib/project-connection.js +2 -0
- package/lib/project-http.js +4 -2
- package/lib/project-loop.js +110 -48
- package/lib/project-mate-interaction.js +4 -0
- package/lib/project-notifications.js +210 -0
- package/lib/project-sessions.js +5 -2
- package/lib/project-user-message.js +2 -1
- package/lib/project.js +26 -2
- package/lib/public/app.js +1193 -8517
- package/lib/public/css/command-palette.css +14 -0
- package/lib/public/css/loop.css +301 -0
- package/lib/public/css/notifications-center.css +190 -0
- package/lib/public/css/rewind.css +6 -0
- package/lib/public/index.html +89 -35
- package/lib/public/modules/app-connection.js +160 -0
- package/lib/public/modules/app-cursors.js +473 -0
- package/lib/public/modules/app-debate-ui.js +389 -0
- package/lib/public/modules/app-dm.js +627 -0
- package/lib/public/modules/app-favicon.js +212 -0
- package/lib/public/modules/app-header.js +229 -0
- package/lib/public/modules/app-home-hub.js +600 -0
- package/lib/public/modules/app-loop-ui.js +589 -0
- package/lib/public/modules/app-loop-wizard.js +439 -0
- package/lib/public/modules/app-messages.js +1560 -0
- package/lib/public/modules/app-misc.js +299 -0
- package/lib/public/modules/app-notifications.js +372 -0
- package/lib/public/modules/app-panels.js +888 -0
- package/lib/public/modules/app-projects.js +798 -0
- package/lib/public/modules/app-rate-limit.js +451 -0
- package/lib/public/modules/app-rendering.js +597 -0
- package/lib/public/modules/app-skills-install.js +234 -0
- package/lib/public/modules/command-palette.js +27 -4
- package/lib/public/modules/input.js +31 -20
- package/lib/public/modules/scheduler-config.js +1532 -0
- package/lib/public/modules/scheduler-history.js +79 -0
- package/lib/public/modules/scheduler.js +33 -1554
- package/lib/public/modules/session-search.js +13 -1
- package/lib/public/modules/sidebar-mates.js +812 -0
- package/lib/public/modules/sidebar-mobile.js +1269 -0
- package/lib/public/modules/sidebar-projects.js +1449 -0
- package/lib/public/modules/sidebar-sessions.js +986 -0
- package/lib/public/modules/sidebar.js +232 -4591
- package/lib/public/modules/store.js +27 -0
- package/lib/public/modules/ws-ref.js +7 -0
- package/lib/public/style.css +1 -0
- package/lib/sdk-bridge.js +96 -717
- package/lib/sdk-message-processor.js +587 -0
- package/lib/sdk-message-queue.js +42 -0
- package/lib/sdk-skill-discovery.js +131 -0
- package/lib/server-admin.js +712 -0
- package/lib/server-auth.js +737 -0
- package/lib/server-dm.js +221 -0
- package/lib/server-mates.js +281 -0
- package/lib/server-palette.js +110 -0
- package/lib/server-settings.js +479 -0
- package/lib/server-skills.js +280 -0
- package/lib/server.js +246 -2755
- package/lib/sessions.js +11 -4
- package/lib/users-auth.js +146 -0
- package/lib/users-permissions.js +118 -0
- package/lib/users-preferences.js +210 -0
- package/lib/users.js +48 -398
- package/lib/ws-schema.js +498 -0
- package/package.json +1 -1
package/lib/users.js
CHANGED
|
@@ -3,32 +3,12 @@ var path = require("path");
|
|
|
3
3
|
var crypto = require("crypto");
|
|
4
4
|
var { execSync } = require("child_process");
|
|
5
5
|
var { CONFIG_DIR } = require("./config");
|
|
6
|
+
var { attachAuth } = require("./users-auth");
|
|
7
|
+
var { DEFAULT_PERMISSIONS, ALL_PERMISSIONS, attachPermissions } = require("./users-permissions");
|
|
8
|
+
var { attachPreferences } = require("./users-preferences");
|
|
6
9
|
|
|
7
10
|
var USERS_FILE = path.join(CONFIG_DIR, "users.json");
|
|
8
11
|
|
|
9
|
-
// --- Per-user RBAC permissions (default values for regular users) ---
|
|
10
|
-
var DEFAULT_PERMISSIONS = {
|
|
11
|
-
terminal: false,
|
|
12
|
-
fileBrowser: true,
|
|
13
|
-
createProject: true,
|
|
14
|
-
deleteProject: false,
|
|
15
|
-
skills: true,
|
|
16
|
-
sessionDelete: false,
|
|
17
|
-
scheduledTasks: false,
|
|
18
|
-
projectSettings: false,
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
var ALL_PERMISSIONS = {
|
|
22
|
-
terminal: true,
|
|
23
|
-
fileBrowser: true,
|
|
24
|
-
createProject: true,
|
|
25
|
-
deleteProject: true,
|
|
26
|
-
skills: true,
|
|
27
|
-
sessionDelete: true,
|
|
28
|
-
scheduledTasks: true,
|
|
29
|
-
projectSettings: true,
|
|
30
|
-
};
|
|
31
|
-
|
|
32
12
|
// --- Default data ---
|
|
33
13
|
|
|
34
14
|
function defaultData() {
|
|
@@ -66,88 +46,12 @@ function saveUsers(data) {
|
|
|
66
46
|
fs.renameSync(tmpPath, USERS_FILE);
|
|
67
47
|
}
|
|
68
48
|
|
|
69
|
-
// --- Multi-user mode ---
|
|
70
|
-
|
|
71
|
-
function isMultiUser() {
|
|
72
|
-
var data = loadUsers();
|
|
73
|
-
return !!data.multiUser;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function enableMultiUser() {
|
|
77
|
-
var data = loadUsers();
|
|
78
|
-
if (data.multiUser) {
|
|
79
|
-
// Already enabled — check if admin exists
|
|
80
|
-
var admin = findAdmin(data);
|
|
81
|
-
if (admin) {
|
|
82
|
-
return { alreadyEnabled: true, hasAdmin: true, setupCode: null };
|
|
83
|
-
}
|
|
84
|
-
// Multi-user enabled but no admin — regenerate setup code
|
|
85
|
-
var code = generateSetupCode();
|
|
86
|
-
data.setupCode = code;
|
|
87
|
-
saveUsers(data);
|
|
88
|
-
return { alreadyEnabled: true, hasAdmin: false, setupCode: code };
|
|
89
|
-
}
|
|
90
|
-
var code = generateSetupCode();
|
|
91
|
-
data.multiUser = true;
|
|
92
|
-
data.setupCode = code;
|
|
93
|
-
saveUsers(data);
|
|
94
|
-
return { alreadyEnabled: false, hasAdmin: false, setupCode: code };
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function disableMultiUser() {
|
|
98
|
-
var data = loadUsers();
|
|
99
|
-
data.multiUser = false;
|
|
100
|
-
data.setupCode = null;
|
|
101
|
-
saveUsers(data);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// --- Setup code ---
|
|
105
|
-
|
|
106
|
-
function generateSetupCode() {
|
|
107
|
-
var chars = "abcdefghijkmnpqrstuvwxyz23456789"; // no ambiguous chars
|
|
108
|
-
var code = "";
|
|
109
|
-
var bytes = crypto.randomBytes(6);
|
|
110
|
-
for (var i = 0; i < 6; i++) {
|
|
111
|
-
code += chars[bytes[i] % chars.length];
|
|
112
|
-
}
|
|
113
|
-
return code;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function getSetupCode() {
|
|
117
|
-
var data = loadUsers();
|
|
118
|
-
if (data.setupCode) return data.setupCode;
|
|
119
|
-
// Defensive: if multi-user is on, no admin, and no code, auto-generate one
|
|
120
|
-
if (data.multiUser && !findAdmin(data)) {
|
|
121
|
-
var code = generateSetupCode();
|
|
122
|
-
data.setupCode = code;
|
|
123
|
-
saveUsers(data);
|
|
124
|
-
return code;
|
|
125
|
-
}
|
|
126
|
-
return null;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function clearSetupCode() {
|
|
130
|
-
var data = loadUsers();
|
|
131
|
-
data.setupCode = null;
|
|
132
|
-
saveUsers(data);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function validateSetupCode(code) {
|
|
136
|
-
var data = loadUsers();
|
|
137
|
-
if (!data.setupCode) return false;
|
|
138
|
-
return data.setupCode === code;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
49
|
// --- User CRUD ---
|
|
142
50
|
|
|
143
51
|
function generateUserId() {
|
|
144
52
|
return crypto.randomUUID();
|
|
145
53
|
}
|
|
146
54
|
|
|
147
|
-
function hashPin(pin) {
|
|
148
|
-
return crypto.createHash("sha256").update("clay-user:" + pin).digest("hex");
|
|
149
|
-
}
|
|
150
|
-
|
|
151
55
|
function createUser(opts) {
|
|
152
56
|
var data = loadUsers();
|
|
153
57
|
// Check username uniqueness
|
|
@@ -169,7 +73,7 @@ function createUser(opts) {
|
|
|
169
73
|
username: opts.username,
|
|
170
74
|
email: opts.email || null,
|
|
171
75
|
displayName: opts.displayName || opts.username,
|
|
172
|
-
pinHash: hashPin(opts.pin),
|
|
76
|
+
pinHash: auth.hashPin(opts.pin),
|
|
173
77
|
role: opts.role || "user",
|
|
174
78
|
mustChangePin: !!opts.mustChangePin,
|
|
175
79
|
createdAt: Date.now(),
|
|
@@ -244,14 +148,6 @@ function findUserByEmail(email) {
|
|
|
244
148
|
return null;
|
|
245
149
|
}
|
|
246
150
|
|
|
247
|
-
function authenticateUser(username, pin) {
|
|
248
|
-
var user = findUserByUsername(username);
|
|
249
|
-
if (!user) return null;
|
|
250
|
-
var pinH = hashPin(pin);
|
|
251
|
-
if (user.pinHash !== pinH) return null;
|
|
252
|
-
return user;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
151
|
function getAllUsers() {
|
|
256
152
|
var data = loadUsers();
|
|
257
153
|
return data.users.map(function (u) {
|
|
@@ -300,7 +196,7 @@ function updateUserPin(userId, newPin) {
|
|
|
300
196
|
var data = loadUsers();
|
|
301
197
|
for (var i = 0; i < data.users.length; i++) {
|
|
302
198
|
if (data.users[i].id === userId) {
|
|
303
|
-
data.users[i].pinHash = hashPin(newPin);
|
|
199
|
+
data.users[i].pinHash = auth.hashPin(newPin);
|
|
304
200
|
data.users[i].mustChangePin = false;
|
|
305
201
|
saveUsers(data);
|
|
306
202
|
return { ok: true };
|
|
@@ -309,19 +205,9 @@ function updateUserPin(userId, newPin) {
|
|
|
309
205
|
return { error: "User not found" };
|
|
310
206
|
}
|
|
311
207
|
|
|
312
|
-
// Generate a random 6-digit PIN
|
|
313
|
-
function generatePin() {
|
|
314
|
-
var digits = "";
|
|
315
|
-
var bytes = crypto.randomBytes(6);
|
|
316
|
-
for (var i = 0; i < 6; i++) {
|
|
317
|
-
digits += (bytes[i] % 10).toString();
|
|
318
|
-
}
|
|
319
|
-
return digits;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
208
|
// Admin creates a user with a temporary PIN (must be changed on first login)
|
|
323
209
|
function createUserByAdmin(opts) {
|
|
324
|
-
var tempPin = generatePin();
|
|
210
|
+
var tempPin = auth.generatePin();
|
|
325
211
|
var result = createUser({
|
|
326
212
|
username: opts.username,
|
|
327
213
|
displayName: opts.displayName || opts.username,
|
|
@@ -373,23 +259,6 @@ function updateLinuxUser(userId, linuxUsername) {
|
|
|
373
259
|
return { error: "User not found" };
|
|
374
260
|
}
|
|
375
261
|
|
|
376
|
-
// --- Auth tokens ---
|
|
377
|
-
|
|
378
|
-
function generateUserAuthToken(userId) {
|
|
379
|
-
var token = crypto.randomBytes(32).toString("hex");
|
|
380
|
-
return userId + ":" + token;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
function parseAuthCookie(cookieValue) {
|
|
384
|
-
if (!cookieValue) return null;
|
|
385
|
-
var idx = cookieValue.indexOf(":");
|
|
386
|
-
if (idx < 0) return null;
|
|
387
|
-
return {
|
|
388
|
-
userId: cookieValue.substring(0, idx),
|
|
389
|
-
token: cookieValue.substring(idx + 1),
|
|
390
|
-
};
|
|
391
|
-
}
|
|
392
|
-
|
|
393
262
|
// --- Invite links ---
|
|
394
263
|
|
|
395
264
|
function createInvite(createdByUserId, targetEmail) {
|
|
@@ -507,256 +376,47 @@ function removeExpiredInvites() {
|
|
|
507
376
|
if (data.invites.length !== before) saveUsers(data);
|
|
508
377
|
}
|
|
509
378
|
|
|
510
|
-
// ---
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
// --- DM Hidden (dismissed from strip) ---
|
|
553
|
-
|
|
554
|
-
function getDmHidden(userId) {
|
|
555
|
-
var data = loadUsers();
|
|
556
|
-
for (var i = 0; i < data.users.length; i++) {
|
|
557
|
-
if (data.users[i].id === userId) {
|
|
558
|
-
return data.users[i].dmHidden || [];
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
return [];
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
function addDmHidden(userId, targetUserId) {
|
|
565
|
-
var data = loadUsers();
|
|
566
|
-
for (var i = 0; i < data.users.length; i++) {
|
|
567
|
-
if (data.users[i].id === userId) {
|
|
568
|
-
if (!data.users[i].dmHidden) data.users[i].dmHidden = [];
|
|
569
|
-
if (data.users[i].dmHidden.indexOf(targetUserId) === -1) {
|
|
570
|
-
data.users[i].dmHidden.push(targetUserId);
|
|
571
|
-
saveUsers(data);
|
|
572
|
-
}
|
|
573
|
-
return data.users[i].dmHidden;
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
return [];
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
function removeDmHidden(userId, targetUserId) {
|
|
580
|
-
var data = loadUsers();
|
|
581
|
-
for (var i = 0; i < data.users.length; i++) {
|
|
582
|
-
if (data.users[i].id === userId) {
|
|
583
|
-
if (!data.users[i].dmHidden) data.users[i].dmHidden = [];
|
|
584
|
-
data.users[i].dmHidden = data.users[i].dmHidden.filter(function (id) {
|
|
585
|
-
return id !== targetUserId;
|
|
586
|
-
});
|
|
587
|
-
saveUsers(data);
|
|
588
|
-
return data.users[i].dmHidden;
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
return [];
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
// --- Deleted built-in mate keys tracking ---
|
|
595
|
-
|
|
596
|
-
function getDeletedBuiltinKeys(userId) {
|
|
597
|
-
var data = loadUsers();
|
|
598
|
-
for (var i = 0; i < data.users.length; i++) {
|
|
599
|
-
if (data.users[i].id === userId) {
|
|
600
|
-
return data.users[i].deletedBuiltinKeys || [];
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
return [];
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
function addDeletedBuiltinKey(userId, key) {
|
|
607
|
-
var data = loadUsers();
|
|
608
|
-
for (var i = 0; i < data.users.length; i++) {
|
|
609
|
-
if (data.users[i].id === userId) {
|
|
610
|
-
if (!data.users[i].deletedBuiltinKeys) data.users[i].deletedBuiltinKeys = [];
|
|
611
|
-
if (data.users[i].deletedBuiltinKeys.indexOf(key) === -1) {
|
|
612
|
-
data.users[i].deletedBuiltinKeys.push(key);
|
|
613
|
-
saveUsers(data);
|
|
614
|
-
}
|
|
615
|
-
return;
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
function removeDeletedBuiltinKey(userId, key) {
|
|
621
|
-
var data = loadUsers();
|
|
622
|
-
for (var i = 0; i < data.users.length; i++) {
|
|
623
|
-
if (data.users[i].id === userId) {
|
|
624
|
-
if (!data.users[i].deletedBuiltinKeys) return;
|
|
625
|
-
data.users[i].deletedBuiltinKeys = data.users[i].deletedBuiltinKeys.filter(function (k) {
|
|
626
|
-
return k !== key;
|
|
627
|
-
});
|
|
628
|
-
saveUsers(data);
|
|
629
|
-
return;
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
// --- RBAC permissions ---
|
|
635
|
-
|
|
636
|
-
function getEffectivePermissions(user, osUsersMode) {
|
|
637
|
-
// OS-mode users with linuxUser are exempt from RBAC (OS handles isolation)
|
|
638
|
-
if (osUsersMode && user && user.linuxUser) return ALL_PERMISSIONS;
|
|
639
|
-
// Admin always has full permissions
|
|
640
|
-
if (user && user.role === "admin") return ALL_PERMISSIONS;
|
|
641
|
-
// Merge stored permissions with defaults (handles missing keys for forward-compat)
|
|
642
|
-
var stored = (user && user.permissions) || {};
|
|
643
|
-
var result = {};
|
|
644
|
-
var keys = Object.keys(DEFAULT_PERMISSIONS);
|
|
645
|
-
for (var i = 0; i < keys.length; i++) {
|
|
646
|
-
var k = keys[i];
|
|
647
|
-
result[k] = stored[k] !== undefined ? stored[k] : DEFAULT_PERMISSIONS[k];
|
|
648
|
-
}
|
|
649
|
-
return result;
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
function updateUserPermissions(userId, permissions) {
|
|
653
|
-
var data = loadUsers();
|
|
654
|
-
for (var i = 0; i < data.users.length; i++) {
|
|
655
|
-
if (data.users[i].id === userId) {
|
|
656
|
-
// Validate: only allow known permission keys with boolean values
|
|
657
|
-
var clean = {};
|
|
658
|
-
var keys = Object.keys(DEFAULT_PERMISSIONS);
|
|
659
|
-
for (var j = 0; j < keys.length; j++) {
|
|
660
|
-
var k = keys[j];
|
|
661
|
-
clean[k] = permissions[k] === true;
|
|
662
|
-
}
|
|
663
|
-
data.users[i].permissions = clean;
|
|
664
|
-
saveUsers(data);
|
|
665
|
-
return { ok: true, permissions: clean };
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
return { error: "User not found" };
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
// --- Project access helpers ---
|
|
672
|
-
|
|
673
|
-
function canAccessProject(userId, project) {
|
|
674
|
-
if (!project) return false;
|
|
675
|
-
// Public projects are accessible to all authenticated users
|
|
676
|
-
if (!project.visibility || project.visibility === "public") return true;
|
|
677
|
-
// Admin always has access
|
|
678
|
-
var user = findUserById(userId);
|
|
679
|
-
if (user && user.role === "admin") return true;
|
|
680
|
-
// Owner always has access to their own project
|
|
681
|
-
if (project.ownerId && project.ownerId === userId) return true;
|
|
682
|
-
// Private project — check allowedUsers
|
|
683
|
-
var allowed = project.allowedUsers || [];
|
|
684
|
-
return allowed.indexOf(userId) >= 0;
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
function getAccessibleProjects(userId, projects) {
|
|
688
|
-
if (!projects) return [];
|
|
689
|
-
return projects.filter(function (p) {
|
|
690
|
-
return canAccessProject(userId, p);
|
|
691
|
-
});
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
// --- Session visibility helpers ---
|
|
695
|
-
|
|
696
|
-
function canAccessSession(userId, session, project) {
|
|
697
|
-
// Must have project access first
|
|
698
|
-
if (!canAccessProject(userId, project)) return false;
|
|
699
|
-
// Sessions without ownerId are legacy — only admin can see them
|
|
700
|
-
if (!session.ownerId) {
|
|
701
|
-
var user = findUserById(userId);
|
|
702
|
-
return !!(user && user.role === "admin");
|
|
703
|
-
}
|
|
704
|
-
// Owner can always see their own sessions
|
|
705
|
-
if (session.ownerId === userId) return true;
|
|
706
|
-
// Shared sessions are visible to all project members (default)
|
|
707
|
-
if (!session.sessionVisibility || session.sessionVisibility === "shared") return true;
|
|
708
|
-
// Private sessions are only visible to the owner
|
|
709
|
-
return false;
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
// --- Per-user chat layout setting ---
|
|
713
|
-
|
|
714
|
-
function getChatLayout(userId) {
|
|
715
|
-
var data = loadUsers();
|
|
716
|
-
for (var i = 0; i < data.users.length; i++) {
|
|
717
|
-
if (data.users[i].id === userId) {
|
|
718
|
-
return data.users[i].chatLayout || "channel";
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
return "channel";
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
function setChatLayout(userId, layout) {
|
|
725
|
-
var val = (layout === "bubble") ? "bubble" : "channel";
|
|
726
|
-
var data = loadUsers();
|
|
727
|
-
for (var i = 0; i < data.users.length; i++) {
|
|
728
|
-
if (data.users[i].id === userId) {
|
|
729
|
-
data.users[i].chatLayout = val;
|
|
730
|
-
saveUsers(data);
|
|
731
|
-
return { ok: true, chatLayout: val };
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
return { error: "User not found" };
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
// --- Per-user auto-continue setting ---
|
|
738
|
-
|
|
739
|
-
function getAutoContinue(userId) {
|
|
740
|
-
var data = loadUsers();
|
|
741
|
-
for (var i = 0; i < data.users.length; i++) {
|
|
742
|
-
if (data.users[i].id === userId) {
|
|
743
|
-
return !!data.users[i].autoContinueOnRateLimit;
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
return false;
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
function setAutoContinue(userId, enabled) {
|
|
750
|
-
var data = loadUsers();
|
|
751
|
-
for (var i = 0; i < data.users.length; i++) {
|
|
752
|
-
if (data.users[i].id === userId) {
|
|
753
|
-
data.users[i].autoContinueOnRateLimit = !!enabled;
|
|
754
|
-
saveUsers(data);
|
|
755
|
-
return { ok: true, autoContinueOnRateLimit: !!enabled };
|
|
756
|
-
}
|
|
757
|
-
}
|
|
758
|
-
return { error: "User not found" };
|
|
759
|
-
}
|
|
379
|
+
// --- Wire extracted modules ---
|
|
380
|
+
|
|
381
|
+
var auth = attachAuth({ loadUsers: loadUsers, saveUsers: saveUsers, findAdmin: findAdmin });
|
|
382
|
+
var permissions = attachPermissions({ loadUsers: loadUsers, saveUsers: saveUsers, findUserById: findUserById });
|
|
383
|
+
var preferences = attachPreferences({ loadUsers: loadUsers, saveUsers: saveUsers });
|
|
384
|
+
|
|
385
|
+
// Alias auth functions
|
|
386
|
+
var isMultiUser = auth.isMultiUser;
|
|
387
|
+
var enableMultiUser = auth.enableMultiUser;
|
|
388
|
+
var disableMultiUser = auth.disableMultiUser;
|
|
389
|
+
var getSetupCode = auth.getSetupCode;
|
|
390
|
+
var clearSetupCode = auth.clearSetupCode;
|
|
391
|
+
var validateSetupCode = auth.validateSetupCode;
|
|
392
|
+
var hashPin = auth.hashPin;
|
|
393
|
+
var generatePin = auth.generatePin;
|
|
394
|
+
var authenticateUser = auth.authenticateUser;
|
|
395
|
+
var generateUserAuthToken = auth.generateUserAuthToken;
|
|
396
|
+
var parseAuthCookie = auth.parseAuthCookie;
|
|
397
|
+
|
|
398
|
+
// Alias permissions functions
|
|
399
|
+
var getEffectivePermissions = permissions.getEffectivePermissions;
|
|
400
|
+
var updateUserPermissions = permissions.updateUserPermissions;
|
|
401
|
+
var canAccessProject = permissions.canAccessProject;
|
|
402
|
+
var getAccessibleProjects = permissions.getAccessibleProjects;
|
|
403
|
+
var canAccessSession = permissions.canAccessSession;
|
|
404
|
+
|
|
405
|
+
// Alias preferences functions
|
|
406
|
+
var getDmFavorites = preferences.getDmFavorites;
|
|
407
|
+
var addDmFavorite = preferences.addDmFavorite;
|
|
408
|
+
var removeDmFavorite = preferences.removeDmFavorite;
|
|
409
|
+
var getDmHidden = preferences.getDmHidden;
|
|
410
|
+
var addDmHidden = preferences.addDmHidden;
|
|
411
|
+
var removeDmHidden = preferences.removeDmHidden;
|
|
412
|
+
var getDeletedBuiltinKeys = preferences.getDeletedBuiltinKeys;
|
|
413
|
+
var addDeletedBuiltinKey = preferences.addDeletedBuiltinKey;
|
|
414
|
+
var removeDeletedBuiltinKey = preferences.removeDeletedBuiltinKey;
|
|
415
|
+
var getChatLayout = preferences.getChatLayout;
|
|
416
|
+
var setChatLayout = preferences.setChatLayout;
|
|
417
|
+
var getAutoContinue = preferences.getAutoContinue;
|
|
418
|
+
var setAutoContinue = preferences.setAutoContinue;
|
|
419
|
+
var setMateOnboarded = preferences.setMateOnboarded;
|
|
760
420
|
|
|
761
421
|
module.exports = {
|
|
762
422
|
USERS_FILE: USERS_FILE,
|
|
@@ -810,17 +470,7 @@ module.exports = {
|
|
|
810
470
|
removeDmHidden: removeDmHidden,
|
|
811
471
|
getChatLayout: getChatLayout,
|
|
812
472
|
setChatLayout: setChatLayout,
|
|
813
|
-
setMateOnboarded:
|
|
814
|
-
var data = loadUsers();
|
|
815
|
-
for (var i = 0; i < data.users.length; i++) {
|
|
816
|
-
if (data.users[i].id === userId) {
|
|
817
|
-
data.users[i].mateOnboardingShown = true;
|
|
818
|
-
saveUsers(data);
|
|
819
|
-
return { ok: true };
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
return { error: "User not found" };
|
|
823
|
-
},
|
|
473
|
+
setMateOnboarded: setMateOnboarded,
|
|
824
474
|
getAutoContinue: getAutoContinue,
|
|
825
475
|
setAutoContinue: setAutoContinue,
|
|
826
476
|
getDeletedBuiltinKeys: getDeletedBuiltinKeys,
|