Permissions view - Restore the System Accounts listing path and audit related tabs. - Lock the framework system_users deny rules (is_system_managed) and system-principal global rules; show them read-only. System vs service accounts - Only account_type='system' is immutable. service-bot is no longer a system principal; ensureInternalAccounts repairs existing rows. - GET /users now surfaces system/service accounts (gated by read/system_users, read/service_users) and Type is the first column. Service accounts - UI to create/edit/delete service accounts (API-only, no login). - Admin API-key management: GET/POST/DELETE /users/:id/keys, restricted to service accounts, scope-capped to the account's own permissions, with a key-management card on the user detail page. Password policy - Admins never set passwords. Creating a user account auto-generates a strong password (shown once) and forces a change on first login; admin "Reset password" does the same. - Forced change flow: login returns password_change_required + challenge token; POST /auth/change-password validates strength, clears the flag, issues the session. Enforced after password and MFA. - Strength: length 12-128, reject common passwords and email/name. UI - Lock indicators in action columns use a shared LockBtn (tooltip, aligned with other action buttons). - Account-type selection in create is a segmented button selector.
10 lines
407 B
TypeScript
10 lines
407 B
TypeScript
import { randomBytes } from 'node:crypto';
|
|
|
|
// Unambiguous alphabet (no 0/O/1/l/I) so generated passwords are easy to read
|
|
// and copy. 20 chars over 54 symbols is ~115 bits of entropy.
|
|
const ALPHA = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789';
|
|
|
|
export function generatePassword(length = 20): string {
|
|
return Array.from(randomBytes(length)).map((b) => ALPHA[b % ALPHA.length]).join('');
|
|
}
|