Bundles the console work from the current branch: the header account control, database-backed roles and permissions, and signing out across the applications that share this sign-in. The account control replaces a separate identity chip and a separate sign-out button, which meant the header carried two controls describing one fact. web/account.js is mounted into every page by a placeholder and owns the keyboard handling, the outside-click behaviour and the sign-out form once. It also fills the trigger's name, which the previous markup left empty. Signing out revokes the hosted-login bearer sessions this installation issued, then redirects to the provider's end_session_endpoint when the discovery document advertises one. Applications that authenticate against this installation therefore lose their session too; one pointed straight at an identity provider is out of its reach and is unchanged. Roles and permissions become rows rather than a closed enum, so a tenant can extend the catalog without a migration, and a role can no longer be granted a capability that is not in it. requireSameOrigin now compares against the origin the request arrived on instead of the configured base URL, which defaulted to http://localhost:8080 and so rejected every write in a deployment that never set it. Two bugs found while verifying in a browser: - A profile picture never rendered. avatarURL built an absolute URL from the configured base URL, and the page's own img-src 'self' blocked it. The console's own pages now take a root-relative path; only /connect/userinfo, read from another origin, needs an absolute one, and it follows the request. - absoluteURL preferred the configuration over the request while its comment claimed the opposite, which also misdirected the logout redirect. Card layout: the footer was one two-column row shared between a label and a forty-character identifier, so the identifier took the width and crushed its label into three stacked words. Each pair is a line now, the value truncates with the full text in the title, and cards align their footers across a row.
81 lines
No EOL
3.5 KiB
HTML
81 lines
No EOL
3.5 KiB
HTML
<!doctype html>
|
||
<html lang="en" data-theme="tokyo" data-mode="dark">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<meta name="color-scheme" content="dark light">
|
||
<title>Go Loose · Profile</title>
|
||
<link rel="stylesheet" href="/assets/style.css">
|
||
<link rel="stylesheet" href="__GO_LOOSE_THEME_ORIGIN__/rt/v1/contract.css" data-theme-contract>
|
||
</head>
|
||
<body class="profile-page">
|
||
<div class="noise"></div>
|
||
<header>
|
||
<a class="brand" href="/"><span class="brand-mark">GL</span><span>Go Loose</span></a>
|
||
<nav>
|
||
<a href="/">Console</a>
|
||
<a href="/docs">API docs</a>
|
||
<a href="/roles">Roles</a>
|
||
<bananas-theme-selector id="theme"></bananas-theme-selector>
|
||
<bananas-appearance-toggle id="mode"></bananas-appearance-toggle>
|
||
<div data-account-menu></div>
|
||
</nav>
|
||
</header>
|
||
|
||
<main>
|
||
<section class="hero profile-hero">
|
||
<div>
|
||
<p class="eyebrow">YOUR ACCOUNT</p>
|
||
<h1>Profile<span>.</span></h1>
|
||
<p class="lede">Your name, picture, and the tenant roles you hold. Applications such as go-tell read the picture link and your role through the login endpoints.</p>
|
||
</div>
|
||
</section>
|
||
|
||
<div id="notice" class="notice" hidden></div>
|
||
|
||
<section class="profile-grid">
|
||
<article class="card profile-card">
|
||
<h2>Profile picture</h2>
|
||
<div class="avatar-preview">
|
||
<img id="avatar-image" alt="" width="112" height="112" hidden>
|
||
<span id="avatar-fallback" class="avatar-initials">–</span>
|
||
</div>
|
||
<form id="avatar-form">
|
||
<label>Choose a picture <small>(JPEG, PNG, or GIF, up to 2 MiB)</small><input type="file" id="avatar-file" accept="image/jpeg,image/png,image/gif"></label>
|
||
<div class="profile-actions">
|
||
<button type="submit" id="avatar-save" disabled>Upload picture</button>
|
||
<button type="button" class="ghost" id="avatar-remove" hidden>Remove picture</button>
|
||
</div>
|
||
</form>
|
||
<label class="muted">Picture link <small>(embed it with a plain image tag)</small>
|
||
<div class="secret"><code id="avatar-url">No picture uploaded</code><button id="copy-avatar" type="button" hidden>Copy</button></div>
|
||
</label>
|
||
</article>
|
||
|
||
<article class="card profile-card">
|
||
<h2>Account</h2>
|
||
<form id="profile-form">
|
||
<label>Display name<input name="display_name" id="display-name" maxlength="200" required></label>
|
||
<label>Email<input id="email" readonly></label>
|
||
<dl class="facts">
|
||
<div><dt>System administrator</dt><dd id="system-admin">—</dd></div>
|
||
<div><dt>Member since</dt><dd id="created-at">—</dd></div>
|
||
<div><dt>Last login</dt><dd id="last-login">—</dd></div>
|
||
<div><dt>Name managed by</dt><dd id="name-source">—</dd></div>
|
||
</dl>
|
||
<button type="submit">Save profile</button>
|
||
</form>
|
||
</article>
|
||
|
||
<article class="card profile-card profile-wide">
|
||
<h2>Tenant roles</h2>
|
||
<div class="table-wrap"><table><thead><tr><th>Tenant</th><th>Slug</th><th>Role</th><th>Capabilities</th></tr></thead><tbody id="membership-list"></tbody></table></div>
|
||
</article>
|
||
</section>
|
||
</main>
|
||
|
||
<script src="/assets/account.js" defer></script>
|
||
<script src="/assets/profile.js" defer></script>
|
||
<script type="module" src="__GO_LOOSE_THEME_ORIGIN__/rt/v1/components.js" data-bananas-components></script>
|
||
</body>
|
||
</html> |