Files
HIPCTF2/docs/guides/authenticated-shell.md
T
2026-07-21 23:22:03 +00:00

90 lines
4.1 KiB
Markdown

---
type: guide
title: Authenticated Shell
description: How a signed-in user experiences the post-login shell, including authenticated event streaming.
tags: [guide, shell, header, sse, navigation, tester]
timestamp: 2026-07-21T23:25:00Z
---
# When this view is available
The authenticated shell is the post-login UI rendered by `HomeComponent`
(`frontend/src/app/features/home/home.component.ts`). It is gated by the client
`authGuard` and the JWT-protected `/api/v1/events/status` stream.
A user who is not signed in, or whose session has expired, is sent to `/login`
before the shell mounts.
# How to access (tester steps)
1. Ensure the instance is initialized. If not, follow [First-Run Bootstrap](/guides/bootstrap.md).
2. Sign in via `/login` as an admin or player.
3. Confirm the browser lands on `/challenges` and renders the shell.
# Expected behavior
## Header
| Element | Selector | Expected |
|---|---|---|
| Page title | `[data-testid="shell-title"]` | Shows the bootstrap `pageTitle`; clicking navigates to `/challenges`. |
| Active section | `[data-testid="shell-active-section"]` | Shows `Challenges`, `Scoreboard`, `Blog`, or `Admin` based on the URL. |
| Event LED | `[data-testid="shell-led"]` | Uses `led-running`, `led-countdown`, `led-stopped`, or `led-unconfigured`. |
| Countdown | `[data-testid="shell-countdown"]` | Displays `DD:HH:mm`, `Event ended`, or empty for an unconfigured event. |
| User menu | `[data-testid="user-menu-trigger"]` | Toggles rank, change-password, optional admin, and logout entries. |
## Quick tabs
The tab strip `[data-testid="quick-tabs"]` contains `Challenges`, `Scoreboard`, and
`Blog`. Clicking a tab navigates to its matching route; the active tab is marked
with the active class.
# Live event window
1. `HomeComponent.ngOnInit()` starts `EventStatusStore` with
`AuthenticatedEventSourceService.open('/api/v1/events/status')`.
2. The transport uses `fetch`, sends `Accept: text/event-stream`, includes
`Authorization: Bearer <access-token>` when available, and sends credentials.
3. It parses SSE `event:` and `data:` lines, buffers frames until a message listener
is registered, and dispatches `MessageEvent` payloads.
4. The store applies each state frame and advances countdown values with a local
one-second tick between server pushes.
5. Leaving the shell closes the source, aborts the fetch, and clears the tick.
A failed HTTP response, missing stream body, or streaming failure dispatches an
error event. The shell retains the last event state until a later connection succeeds.
# Architecture map
| File | Responsibility |
|---|---|
| `frontend/src/app/features/home/home.component.ts` | Hosts the shell and starts/stops the authenticated event stream. |
| `frontend/src/app/core/services/authenticated-event-source.service.ts` | Fetch-based authenticated SSE transport with abort and frame parsing. |
| `frontend/src/app/core/services/event-status.store.ts` | Applies event frames and derives the live countdown. |
| `frontend/src/app/features/shell/header/shell-header.component.ts` | Renders event LED, countdown, navigation, and user menu. |
| `frontend/src/app/features/shell/tabs/quick-tabs.component.ts` | Renders the main navigation tabs. |
| `tests/frontend/authenticated-event-source.spec.ts` | Verifies authorization headers, SSE frame delivery, and anonymous header omission. |
# Tester flows
## Live event window
1. Configure a future start time and confirm the countdown LED and text appear.
2. Move the start time into the past and the end time into the future; confirm the
LED changes to running and the countdown counts toward the end.
3. Move the end time into the past; confirm `Event ended` and the stopped LED.
4. Remove either setting; confirm the unconfigured LED and empty countdown.
## Navigation and logout
1. Click each quick tab and confirm the matching route and active styling.
2. Open the user menu and click **Logout**.
3. Confirm navigation to `/login` and that the event stream is closed.
# See also
- [Event Window](/guides/event-window.md)
- [System Endpoints](/api/system.md)
- [Frontend Structure](/architecture/frontend-structure.md)
- [Change Password](/guides/change-password.md)