ui(pool): pick an account's users from its own Edit
Each account row in the Account pool card has a pencil: tick the users whose sessions run on it (one moves off any other account, unticking sends one back to the balancer). PUT /api/accounts/:name/users saves the set in one transaction, audits each change and switches a Claude login into each added user's home at once. The card-level switch button and pinned list are gone.
This commit is contained in:
@@ -11,6 +11,8 @@
|
||||
* written into the user's home right away (`applyPin`), over the pool login
|
||||
* their running panes use, so those move to it without a restart.
|
||||
*
|
||||
* `setAccountUsers` is the Users page's Edit of one account: who runs on it.
|
||||
*
|
||||
* Server mode only: in local mode there are no users and nothing is pinned.
|
||||
* Removing the account drops its pins (`dropAccount`); deleting the user drops
|
||||
* theirs (ON DELETE CASCADE, and `auth.deleteUser`).
|
||||
@@ -81,6 +83,41 @@ function setPin(userId, tool, account) {
|
||||
return { userId: user.id, username: user.username, account: name };
|
||||
}
|
||||
|
||||
/**
|
||||
* The Users page's Edit of one account: exactly `userIds` run on `account`
|
||||
* afterwards. A user pinned to another account of the tool moves here; one
|
||||
* pinned here but left out goes back to the balancer. One transaction.
|
||||
* Returns `{added, removed}` (each `[{userId, username}]`).
|
||||
*/
|
||||
function setAccountUsers(tool, account, userIds) {
|
||||
validTool(tool);
|
||||
const name = String(account ?? "");
|
||||
if (!poolOf(tool).hasAccount(name)) {
|
||||
throw err("ENOACCOUNT", `no ${tool} account ${name} in the pool`);
|
||||
}
|
||||
if (!Array.isArray(userIds) || !userIds.every(Number.isInteger)) {
|
||||
throw err("EBADUSER", "userIds: an array of user ids");
|
||||
}
|
||||
const want = [...new Set(userIds)];
|
||||
const users = want.map((id) => {
|
||||
const u = db().prepare("SELECT id, username FROM users WHERE id = ?").get(id);
|
||||
if (!u) throw err("ENOUSER", `no user ${id}`);
|
||||
return u;
|
||||
});
|
||||
const before = listPins(tool);
|
||||
const here = new Set(before.filter((p) => p.account === name).map((p) => p.userId));
|
||||
const added = users.filter((u) => !here.has(u.id));
|
||||
const removed = before.filter((p) => p.account === name && !want.includes(p.userId));
|
||||
db().transaction(() => {
|
||||
for (const u of added) setPin(u.id, tool, name);
|
||||
for (const p of removed) setPin(p.userId, tool, null);
|
||||
})();
|
||||
return {
|
||||
added: added.map((u) => ({ userId: u.id, username: u.username })),
|
||||
removed: removed.map((p) => ({ userId: p.userId, username: p.username })),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a pin take effect now where it can: a Claude login is written into
|
||||
* the user's home at once (claude-pool `switchHome`), so their running panes
|
||||
@@ -104,4 +141,4 @@ function dropAccount(tool, account) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { TOOLS, pinFor, listPins, setPin, applyPin, dropAccount };
|
||||
module.exports = { TOOLS, pinFor, listPins, setPin, setAccountUsers, applyPin, dropAccount };
|
||||
|
||||
Reference in New Issue
Block a user