Files
HIPCTF2/docs/guides/authenticated-shell.md
T
2026-07-22 09:37:07 +00:00

6.3 KiB
Raw Blame History

type, title, description, tags, timestamp
type title description tags timestamp
guide Authenticated Shell How a signed-in user experiences the post-login shell, including authenticated event streaming.
guide
shell
header
sse
navigation
tester
2026-07-22T09:35: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.
  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"] A 10×10 circular dot whose color reflects the current event state. See Event LED colors below.
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.

Event LED colors

The LED is rendered by ShellHeaderComponent as a <span class="led"> with one of four state classes attached via [class.led-<state>] and a [style.background-color] bound directly from a pure TypeScript helper.

Event state CSS class Color token ([style.background-color] value) Approx. hex Visual
countdown led led-countdown var(--color-warning) #f59e0b Yellow filled dot
running led led-running var(--color-success) #10b981 Green filled dot
stopped led led-stopped var(--color-danger) #ef4444 Red filled dot
unconfigured led led-unconfigured var(--color-secondary) #64748b Neutral gray filled dot

The mapping is defined in frontend/src/app/core/services/event-status.pure.ts as the constant LED_COLOR_BY_STATE and exposed through the helper ledBackgroundColor(state). ShellHeaderComponent exposes it on the DOM via a computed signal called ledColor(), so the active theme token resolves at runtime and the LED is never painted with transparent.

The base .led rule paints a 10×10 circular inline-block, so the LED is always the same size and shape — only the background color changes between states. The element also carries aria-label="Event status: <state>" for assistive tech.

What the tester should see

  • The 10×10 LED is visible (not transparent, not invisible) in every state.
  • The LED color matches the table above for the active EventState.
  • Switching the event window (countdown → running → stopped → unconfigured) flips the dot color in real time.
  • The aria-label updates to Event status: <state> and never relies on color alone.

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; owns the component-scoped LED shape and state color rules.
frontend/src/styles.css Defines the shared theme color tokens consumed by the shell LED.
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