mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-10-21 16:05:19 +08:00
fix(api): scope TOTP oversight to the caller's workspace
The second-factor listing was instance-wide and the three mutating endpoints never checked that the target Account belongs to the caller's Workspace, so an owner or admin could see and reset another tenant's account. The listing now resolves the Workspace members and the mutations answer 404 for a foreign account, which does not disclose that it exists. Also fixes the TOTP write path on Postgres: six write points passed timezone-aware datetimes into timestamp-without-time-zone columns, which asyncpg rejects, so every enroll, confirm, revoke and recovery-code consumption raised a 500 there. SQLite tolerated the same values. The panel derives its oversight view from the API authorization instead of the length of the account list, which would have hidden it in a single-member Workspace.
This commit is contained in:
@@ -131,9 +131,11 @@ export default function AccountSettingsPanel({
|
||||
async function loadTotpAccounts() {
|
||||
try {
|
||||
const res = await httpClient.getTotpAccounts();
|
||||
const list = res.accounts || [];
|
||||
setIsManager(list.length > 1);
|
||||
setTotpRows(list);
|
||||
// The role rule lives in the API: owners and admins receive the Workspace
|
||||
// list, everyone else receives 403. Deriving manager state from the list
|
||||
// length would hide oversight in a single-member Workspace.
|
||||
setIsManager(true);
|
||||
setTotpRows(res.accounts || []);
|
||||
} catch {
|
||||
// A non-manager receives 403 here; the panel keeps working on own state.
|
||||
setIsManager(false);
|
||||
|
||||
Reference in New Issue
Block a user