ipx-web: the page in its own container, behind Caddy (#203)
web/build.mjs builds a static site, web/dist, with the icons and typeface beside the pages; Dockerfile.web serves it with Caddy, which passes /api and /media to ipx on the same origin, so cookies, live updates and Cloudflare Access work as before. ipx serves no page any more: build.rs and every include_str! of the web files are gone, and its image is built without node. What ipx did to the page as it served it is kept another way. Caddy asks ipx before serving a page (forward_auth): /api/page-check sends a browser not signed in to /login and a non-admin away from /admin, and refuses them /admin.js; /api/login-check sends someone Access vouches for past the form; a page asked for with ?token= goes to /api/signin, which sets the cookie. The theme and the admin link, once written into the page per person, are set by web/boot.js in <head> from the theme cookie and the last visit, before the first frame, and /api/me brings the version and the account's theme from before. Caddy strips the Cf-Access-* headers from every peer but TUNNEL_PEER, the address cloudflared's requests come from, which is the boundary trusted_proxies drew; ipx then trusts only Caddy's address. The browser suite runs Caddy in front of its daemon, so it tests what production would run. Not deployed: production's cutover is on #203. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -90,15 +90,19 @@ test('each browser keeps its own theme, in a cookie, not on the account', async
|
||||
expect(cookie?.value).toBe('flatremix.light');
|
||||
expect(patched, 'nothing sent to the account').toBe(false);
|
||||
|
||||
// This browser: the server reads the cookie and draws the page in it from the first frame.
|
||||
const res = await page.reload();
|
||||
expect(await res.text()).toContain('data-theme=flatremix data-choice=light data-mode=light');
|
||||
// This browser: boot.js reads the cookie in <head> and draws the page in it from the first
|
||||
// frame, before the app's script has run (#203).
|
||||
const firstFrame = () => document.documentElement.dataset;
|
||||
await page.reload({ waitUntil: 'commit' });
|
||||
await page.waitForFunction(() => document.body);
|
||||
expect(await page.evaluate(firstFrame)).toMatchObject({ theme: 'flatremix', choice: 'light', mode: 'light' });
|
||||
|
||||
// Another browser, the same account: not this one's theme.
|
||||
const other = await browser.newContext();
|
||||
const p2 = await other.newPage();
|
||||
const res2 = await p2.goto(`/?token=${TOKEN}`);
|
||||
expect(await res2.text()).not.toContain('data-theme=flatremix');
|
||||
await p2.goto(`/?token=${TOKEN}`);
|
||||
await expect(p2.locator('#feedlist')).toBeVisible();
|
||||
expect((await p2.evaluate(firstFrame)).theme).not.toBe('flatremix');
|
||||
await other.close();
|
||||
});
|
||||
|
||||
@@ -583,8 +587,9 @@ test('a second person has their own feeds and their own read state', async ({ br
|
||||
await expect(page.locator('#modalCard')).toContainText('Subscriptions');
|
||||
await expect(page.locator('#modalCard')).toContainText('Only an admin changes this');
|
||||
await page.locator('#modalCard .cardx').click();
|
||||
await expect(page.locator('#admin')).toHaveCount(0);
|
||||
expect(await (await page.request.get('/')).text()).not.toContain('href=/admin');
|
||||
// The page is the same for everyone now (#203): the link is there, and hidden from anyone /api/me
|
||||
// does not call an admin.
|
||||
await expect(page.locator('#admin')).toBeHidden();
|
||||
// Asking for it anyway goes back to the app, and its script is refused.
|
||||
await page.goto('/admin');
|
||||
await expect(page).toHaveURL(/:8791\/$/);
|
||||
|
||||
@@ -35,7 +35,8 @@ enabled = false
|
||||
|
||||
[web]
|
||||
enabled = true
|
||||
bind = "127.0.0.1:8791"
|
||||
# Behind Caddy, which serves the pages on 8791 and passes the API here (#203).
|
||||
bind = "127.0.0.1:8796"
|
||||
token = "${TOKEN}"
|
||||
# The proxy path, for tests that send the header themselves: the daemon sees them at 127.0.0.1.
|
||||
trusted_header = "X-Test-User"
|
||||
|
||||
Reference in New Issue
Block a user