refactor(ui): inject the session server-side instead of fetching it client-side

The pages are rendered by the server, which already holds the session — so
/fingerprint, /cropper and the landing now embed window.__SESSION__ (JSON,
with '<' escaped) instead of each fetching /auth/session on load:

- /fingerprint gets token, identity, agentUrl and the permitted domains
  (the same cached context the endpoint returned); /cropper gets identity
- landing nav is now server-rendered (Sign in vs user chip + Sign out);
  its client fetch script is deleted
- per-user HTML is sent with Cache-Control: no-store and Vary: Cookie
- express.static runs with index:false so '/' can be session-aware while
  assets stay session-free
- GET /auth/session remains as the documented JSON contract (and the
  canonical place the domain-filter caching is exercised in tests)

Client code shrinks by a fetch + error path per page; 3 new tests
(injection, escaping, landing header) — 43 total.
This commit is contained in:
2026-10-01 03:28:31 +01:00
parent 431a452d52
commit 22735c0709
6 changed files with 137 additions and 60 deletions
+1 -28
View File
@@ -22,9 +22,7 @@
</span>
YOUreka <small>Tools</small>
</a>
<div class="nav-right" id="nav-session">
<a class="linklike" href="/auth/login">Sign in</a>
</div>
<div class="nav-right"><!--session-nav--></div>
</div>
</nav>
@@ -69,30 +67,5 @@
<span>Scan captures run locally via the fpagent agent &mdash; no scanner data leaves this machine except the enrolled artifacts you save.</span>
</div>
</footer>
<script>
// Reflect the current session in the header: Sign in vs user chip + Sign out.
fetch('/auth/session')
.then(function (r) { return r.ok ? r.json() : null; })
.then(function (session) {
var host = document.getElementById('nav-session');
if (!session) return; // keep the Sign in link
var name = (session.firstName || session.phone || '?').trim();
host.textContent = '';
var chip = document.createElement('span');
chip.className = 'user-chip';
var avatar = document.createElement('span');
avatar.className = 'avatar';
avatar.textContent = name.slice(0, 2).toUpperCase(); // textContent, never innerHTML
var label = document.createElement('span');
label.textContent = name;
chip.append(avatar, label);
var signOut = document.createElement('a');
signOut.className = 'linklike';
signOut.href = '/auth/logout';
signOut.textContent = 'Sign out';
host.append(chip, signOut);
})
.catch(function () { /* keep Sign in */ });
</script>
</body>
</html>