import { h, mount, field, input, toast, errorBox } from "../ui.js"; import { api, get } from "../api.js"; import { tokenTable, newTokenForm, grantHelp } from "./users.js"; export async function render(el) { const me = await get("/auth/whoami"); const grants = await get("/catalog/grants"); const tokensEl = h("div"); const drawTokens = async () => { const tokens = await get("/me/tokens"); mount(tokensEl, tokenTable(tokens, drawTokens), newTokenForm("/me/tokens", grants, drawTokens)); }; const cur = input({ type: "password", autocomplete: "current-password" }); const pw1 = input({ type: "password", autocomplete: "new-password" }); const pw2 = input({ type: "password", autocomplete: "new-password" }); const err = h("div"); mount(el, h("h1", null, "Account: " + me.user.username), h("div", { class: "panel" }, h("h2", null, "Permissions"), h("div", { class: "grants" }, (me.permissions || []).map((p) => h("div", null, p)))), h("div", { class: "panel" }, h("h2", null, "Change password"), h("div", { class: "form-grid" }, field("Current password", cur), field("New password", pw1, "At least 8 characters."), field("Repeat", pw2)), err, h("div", { class: "actions", style: { marginTop: "8px" } }, h("button", { class: "primary", onclick: async () => { mount(err); if (pw1.value !== pw2.value) { mount(err, h("div", { class: "msg err" }, "The new passwords don't match.")); return; } try { await api("POST", "/me/password", { body: { current_password: cur.value, password: pw1.value } }); toast("Password changed; other sessions were logged out"); cur.value = pw1.value = pw2.value = ""; } catch (e) { mount(err, errorBox(e)); } } }, "Change password"))), h("div", { class: "panel" }, h("h2", null, "My API tokens"), h("p", { class: "muted small" }, "Use a token with the jarl CLI (jarl config set token …) or any HTTP client: Authorization: Bearer ."), tokensEl), grantHelp(grants)); await drawTokens(); }