// Add-User modal (#10). Sits next to the invite modal in the members view, but // instead of emailing an invite it creates a user account directly with an // admin-set password and assigns them to this workspace + role. For // admin-provisioning on instances with no outbound email (where invites never // deliver). Mirrors workspace-members-invite-modal.js's structure. // // workspace: { id, name } // opts.onSuccess: (result) => void - fires on 201 (server response body) // opts.mapError: (err) => string - translates server error to display text import { api } from '../api.js'; import { t } from '../i18n.js'; const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; // Crockford-ish readable random password: avoids ambiguous chars (0/O, 1/l/I). function generatePassword(len = 16) { const alphabet = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789'; const arr = new Uint32Array(len); crypto.getRandomValues(arr); let out = ''; for (let i = 0; i < len; i++) out += alphabet[arr[i] % alphabet.length]; return out; } export function openAddUserModal(workspace, opts = {}) { const { onSuccess, mapError } = opts; const overlay = document.createElement('div'); overlay.className = 'modal-overlay'; overlay.innerHTML = `