Skip to content

feat: add admin panel - #3

Open
duszmox wants to merge 39 commits into
mainfrom
deploy
Open

feat: add admin panel#3
duszmox wants to merge 39 commits into
mainfrom
deploy

Conversation

@duszmox

@duszmox duszmox commented Aug 25, 2026

Copy link
Copy Markdown

No description provided.

duszmox added 28 commits August 23, 2026 14:24
- Add OIDC login/callback/logout flow with DB-backed sessions (BSS-006)
- Add viewer policy and admin/leadership route guards (BSS-007)
- Add Authentik member cache sync job and mapping (BSS-008)
- Add shared slug history, immutable audit log, and optimistic locking (BSS-009)
- Add background job runner with locking, health, and sync alerts (BSS-010)
- Add media/YouTube URL validators for publish and draft flows (BSS-011)
- Add auth_sessions migration and svc-bss-sync OOB config docs
- Add catalog (names/tags/staff-roles), events, and videos domain modules with lifecycle, purge, and highlight-invalidation logic
- Add related-videos, view-counter, search, and homepage (live/highlight/about/state) services
- Add migrations for nullable event start_date, partial live-overlap exclusion constraint, and pg_trgm/bss_norm search support
- Add integration test suites for all new domains
- Update docs/implementation-progress.md for phase 2 gate results
- Add public app shell with Hungarian 404/error/loading states, navbar with login/logout and viewer-aware session state
- Implement slug-based routing with legacy slug redirects for videos, events, and members
- Build video list/detail pages with filters, native player, view counting, and related videos
- Build event list/detail pages and public member list/profile/archived/contributors pages
- Add homepage with live/highlight sections, global search page and API, and about/courses redirect pages
- Cover all new pages and routes with integration tests

Cards BSS-019 – BSS-026 done, phase gate green.
- Add admin shell (sidebar, tables, forms, alerts) and routes for events, videos, members, homepage, catalog, audit, and trash
- Add admin server domain logic and HTTP API routes with access guards
- Add integration tests covering admin access, catalog, event, video, homepage, member, and trash/audit routes
- Update implementation progress doc for phase 4 completion
- Add idempotent seed JSON importer and validation schema, plus `pnpm db:seed` CLI
- Add sitemap/robots generation and security headers (CSP, X-Frame-Options, etc.)
- Add per-page SEO metadata (title/description/canonical/OG) across public routes
- Polish admin forms with character-limit hints and noindex on admin pages
- Add end-to-end acceptance chain, seed importer, and security header tests
- Rewrite README and update docs with install/demo walkthrough and phase status
- Allow overriding Authentik/app base URLs via BSS_AUTHENTIK_BASE_URL and BSS_APP_BASE_URL for LAN dev setups
- Add matching OIDC redirect URI when app base URL differs from localhost/127.0.0.1
- Accept RFC1918 private-network http issuer URLs in oob-schema validation, not just localhost/127.0.0.1
- Regenerate routeTree.gen.ts with router Register typing
- Add BSS navbar logo SVGs (desktop + mobile) and swap them in via responsive `<picture>`
- Add consistent hover/focus/active styles (ctrl-btn, solid-btn, hover-lift, nav-link) across nav, admin, and content links/buttons
- Mark active nav/tab links with aria-current for accessibility
- Fix ThemeToggle to read the stored theme after hydration instead of resetting to auto, avoiding an SSR/client mismatch
- Work around a router-ssr-query-core bug that logged a spurious "query stream" error on every page load
- Add UserMenu popover (avatar, admin link, logout) replacing the plain logout button
- Add Thumbnail component with fixed 16:9 frame and skeleton placeholder, used across home/events/videos/search
- Add pending-state skeletons for homepage, event list, and video list routes
- Fall back to the latest visible video thumbnail for events without their own cover image
- Add card border, skeleton, and popover theme variables; polish dark-mode nav colors
- Fix YouTube oEmbed endpoint URL casing to lowercase `oembed` (config, live schedule, admin homepage routes, tests)
- Add shared `parsePaginationNumber`/`parseSearchPage` helpers and use them across admin audit, events, videos, and trash routes to handle string/number page params consistently
- Add AdminSearchSelect combobox for filtering long option lists (events, staff, roles, related videos)
- Add client-side media URL validation with save-time confirmation for disallowed hosts
- Split "Felhasznált zenék" into a structured artist/title list editor with free-text fallback
- Add accent-insensitive text-search helper used by the new select component
- Link published videos to their public page from the admin list and editor
- Add unit tests for media-url, song-list, and text-search helpers
- Swap native `<select>` filters/pickers for `AdminSearchSelect` across audit, events, videos, homepage, and catalog merge admin pages; add shared status/visibility option constants
- Add `src/lib/youtube-url.ts` for client-side YouTube URL parsing and extract `allowedMediaHosts` into `src/server/media/allowed-hosts.ts`
- Show live validation warnings for event thumbnail and live-stream URLs while typing, ahead of server-side checks
- Translate the product specification (docs/product-specification.md) from Hungarian to English
- Translate inline code comments and JSDoc across components, routes, lib, and server modules to English
- No functional or behavioral changes
- Homepage hero now plays the featured video inline via VideoDetailPlayer instead of a static card; title links through to the video page
- Highlight state shows six side videos (was five) since the hero no longer needs a separate thumbnail slot
- Footer renders real partner logos and social links (Facebook/YouTube/Instagram) with SVG assets instead of empty alt-only placeholders
- Move page background (color + dot pattern) from body to root element and add public/background.svg
- Update product spec and implementation progress docs, adjust homepage integration tests
- Replace native video controls with a branded player (play/pause, seek, volume, mute, fullscreen, HUD auto-hide) and keyboard shortcuts (space/k, j/l, arrows, m, f, 0-9, home/end)
- Support iOS Safari and other WebKit fullscreen APIs
- Make the video detail page responsive (title, meta, related videos grid) and widen the player container
- Add a `site-width` utility class for consistent page gutters and use it across public pages instead of ad-hoc `mx-auto w-[90dvw]`/`w-[95dvw]` classes
- Switch admin editor pages (events, videos, catalog, homepage, trash, members, audit) from fixed `max-w-*` to full-width layout
- Replace native `<select>` filters and the checkbox tag dropdown on `/videos` with `AdminSearchSelect`
- Add visibility icons to admin video views
- Track saved editor state after partial saves
- Add a search form to the search results page
- Fix the AdminSearchSelect declaration
- Preserve trigger scale during active interaction
- Add public-page links from the admin event list and editor
- Open published event pages in a new tab
- Save reorder, add, and remove changes immediately
- Roll back the local selection when saving fails
- Add reorder API handling with save feedback and audit logging
- Show visibility icons in admin selects and labels
- Improve role deletion guidance and page styling
Remove 134 comments referencing spec chapters and BSS plan cards
(BSS-xxx, spec x.y, specification). Follow-up to implementation-plan
deletion; retains functional docs (373 general impl notes remain).
- Derive video assets from encoding and quality metadata
- Add HQ/LQ playback switching and media validation
- Update schema, migrations, docs, seeds, and tests
- Remove media allowlist from OOB configuration
- Use shared default media settings across validation and routes
- Add a default avatar for members without profile images
- Collapse long video pagination lists with ellipses
- Fix contributor pagination links and add coverage
- Standardize member profile spacing and image alignment
- Center archived member cards
- Reuse shared page query parsing
@duszmox
duszmox marked this pull request as ready for review August 29, 2026 10:59
@duszmox
duszmox requested review from TGyAkos and a lite review from Copilot August 29, 2026 10:59

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The view-count API currently returns incorrect counted values and the lock manager swallows connection errors, both of which can cause incorrect behavior in production.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds a production-ready admin surface and supporting infrastructure (auth/viewer resolution, server-side APIs, homepage/admin data plumbing), alongside a new Vitest test setup and Docker-based runtime/dev tooling to support the expanded backend.

Changes:

  • Introduces admin-area routing, access guards, and multiple server endpoints/utilities (viewer state, homepage admin data, webhook client management, view counter, health checks, sitemap/robots, security headers).
  • Adds extensive unit + integration test coverage with a multi-project Vitest config and helper utilities (DB isolation, fetch mocking, OOB config fixtures).
  • Adds deployment/developer ops artifacts (Dockerfile, compose files, scripts, ESLint/Prettier ignore updates, workspace settings).
File summaries
File Description
vitest.config.ts Adds Vitest multi-project config (unit/integration).
vite.config.ts Adjusts Vite plugin configuration.
tsconfig.json Reformats TS include list.
tests/unit/video-time.test.ts Unit tests for video start-time parsing.
tests/unit/video-media.test.ts Unit tests for derived media asset URLs.
tests/unit/text-search.test.ts Unit tests for accent-insensitive search matching.
tests/unit/song-list.test.ts Unit tests for song list parsing/serialization.
tests/unit/security-headers.test.ts Unit tests for CSP/security headers and robots.txt.
tests/unit/pagination.test.ts Unit tests for pagination parsing + display items.
tests/unit/openapi.test.ts Unit tests for generated OpenAPI YAML correctness.
tests/unit/oob-config.test.ts Unit tests for OOB config schema validation.
tests/unit/oob-config-load.test.ts Unit tests for OOB config file loading/errors.
tests/unit/media-url.test.ts Unit tests for media + YouTube URL warnings.
tests/unit/http-mock.test.ts Unit tests for fetch mocking helper.
tests/unit/clock.test.ts Unit tests for SystemClock/FakeClock.
tests/unit/academic-semester.test.ts Unit tests for academic semester parsing/formatting.
tests/integration/smoke.db.test.ts Integration smoke tests against real PostgreSQL.
tests/integration/seo-sitemap.test.ts Integration tests for sitemap visibility rules + XML.
tests/integration/health.test.ts Integration tests for health endpoints behavior.
tests/integration/about-courses.test.ts Integration tests for courses redirect + about videos.
tests/helpers/test-db.ts Test DB creation + migration helpers for integration tests.
tests/helpers/oob-config.ts Helper to build/override OOB config fixtures.
tests/helpers/http-mock.ts Fetch mock implementation for tests.
src/server/views/counter.ts View session token + per-session view counting logic.
src/server/videos/visibility.ts Visibility condition + predicate shared across queries.
src/server/videos/purge.ts Daily purge job for expired trashed videos.
src/server/videos/highlight-invalidation.ts Clears homepage/about references to a given video.
src/server/shared/text.ts Shared text validation utilities and error type.
src/server/shared/pg-error.ts Extracts PostgreSQL error info + unique-violation helper.
src/server/shared/pagination.ts Parses pagination params consistently (URL serializer quirks).
src/server/shared/db-executor.ts Defines shared Drizzle executor type.
src/server/pages/viewer.ts Resolves viewer state from request (cookies + session).
src/server/pages/viewer-fn.ts ServerFn to fetch viewer navbar state (profile display).
src/server/pages/slug-route.ts Public slug resolution (current + redirect) with visibility.
src/server/pages/sitemap.ts Builds sitemap entries + renders sitemap XML.
src/server/pages/member-archive-fn.ts ServerFn for member archive pagination.
src/server/pages/homepage.ts Homepage DTO assembly and thumbnail fallback logic.
src/server/pages/courses-redirect.ts Server-side redirect rules for /courses.
src/server/pages/admin/access.ts Admin/leadership area access classification via guards.
src/server/pages/admin/access-fn.ts ServerFns to query admin/leadership access state.
src/server/media/youtube.ts Server-side YouTube validation (oEmbed) + embed URL builder.
src/server/media/allowed-hosts.ts Exposes allowed media hosts from client-safe defaults.
src/server/jobs/locks.ts PostgreSQL advisory lock manager for background jobs.
src/server/jobs/health.ts Liveness/readiness response helpers (no secret leakage).
src/server/http/security-headers.ts CSP, baseline security headers, robots.txt generator.
src/server/homepage/highlight.ts Leadership-only highlight video setter + audit logging.
src/server/homepage/about.ts Leadership-only About videos setter + filtered getter.
src/server/config/load.ts Loads + caches OOB config with explicit error types.
src/server/catalog/names.ts Normalization + accent folding helpers for catalog names.
src/server/auth/viewer.ts Viewer level model + resolution from groups/session.
src/server/auth/session-cookies.ts Cookie parsing/serialization + session/OIDC txn signing.
src/server/auth/policy.ts Permission predicates (member/leadership/admin area).
src/server/auth/guards.ts Guard errors + requireAdmin/requireLeadership helpers.
src/server/api/view-routes.ts API route handler for view counting + cookie issuance.
src/server/api/search-routes.ts API search handler with origin enforcement + typed output.
src/server/api/http.ts Shared API helpers (origin, returnTo sanitizer, HTML error pages).
src/server/api/admin/webhook-client-routes.ts Admin routes for webhook client CRUD/rotate/revoke + audit.
src/server/admin/trash-admin.ts Admin trash listing + remaining-days computation.
src/server/admin/homepage-admin.ts Admin homepage data aggregation (live/highlight/about).
src/server.ts Server request router (SSR, API, sitemap, robots, redirect, headers).
src/routes/videos/$videoId.tsx Removes placeholder video route page.
src/routes/members/contributors.tsx Adds contributors archive page with pagination.
src/routes/demo/tanstack-query.tsx Removes demo TanStack Query route.
src/routes/admin/videos/new.tsx Adds admin UI to create a draft video.
src/routes/admin/index.tsx Redirects /admin/ to /admin/videos.
src/routes/admin/events/new.tsx Adds admin UI to create a draft event.
src/routes/admin.tsx Adds admin layout route with access checks + sidebar.
src/routes/__root.tsx Updates app shell metadata, adds global viewer prefetch, error/notfound UI.
src/router.tsx Adds default pending component + SSR query-stream hydration workaround.
src/lib/youtube-url.ts Client-safe YouTube URL parsing + warning helper.
src/lib/webhook.ts Exposes webhook path constant for UI/reference.
src/lib/video-time.ts Parses video start-time inputs (seconds / hms).
src/lib/video-media.ts Derives media asset URLs from encoding/base filename.
src/lib/utils.ts Normalizes formatting/import style for cn helper.
src/lib/text-search.ts Client list filtering with diacritic-insensitive matching.
src/lib/song-list.ts Structured song list parsing/serialization utilities.
src/lib/pagination.ts Pagination item generation with ellipsis rules.
src/lib/media-url.ts Client-side media URL host/protocol validation warnings.
src/lib/format-date.ts Hungarian date/time formatting helpers.
src/lib/clock.ts Clock abstraction with fake/system implementations.
src/lib/admin-labels.ts Admin UI labels/options for status/visibility/membership.
src/lib/admin-api.ts Typed JSON POST helper for admin API calls.
src/lib/activity.ts Groups activity rows by role or year.
src/lib/academic-semester.ts Client-safe academic semester display formatting.
src/components/ui/button.tsx Re-formats button component imports/strings.
src/components/Thumbnail.tsx Adds thumbnail component with skeleton + cached-load handling.
src/components/ThemeToggle.tsx Fixes theme hydration behavior and updates labels/styles.
src/components/MemberCard.tsx Updates placeholder avatar asset reference.
src/components/Footer.tsx Implements footer partners + social links with icons.
src/components/EventCard.tsx Simplifies placeholder component signature.
src/components/admin/VideoVisibility.tsx Renders visibility icon+label for admin UI.
src/components/admin/ResponsiveTable.tsx Adds responsive table/card view for admin lists.
src/components/admin/form.tsx Adds reusable admin form controls/buttons.
src/components/admin/Alerts.tsx Adds admin banners/messages/warnings components.
src/components/admin/AdminSidebar.tsx Adds admin sidebar navigation with leadership filtering.
scripts/webhook-client.ts CLI for managing webhook clients directly in DB.
scripts/import-seed.ts CLI for importing seed data using OOB config.
scripts/generate-openapi.ts CLI to generate + write OpenAPI YAML.
scripts/check-oob.ts CLI to validate OOB config file.
scripts/bootstrap-local.ts CLI to create local infra files + print next steps.
public/social/youtube.svg Adds YouTube social icon asset.
public/social/instagram.svg Adds Instagram social icon asset.
public/social/facebook.svg Adds Facebook social icon asset.
public/manifest.json Updates PWA manifest name/icons to BSS branding.
public/icons/play.svg Adds play icon.
public/icons/pause.svg Adds pause icon.
public/icons/gear.svg Adds gear icon.
public/icons/fullscreen-exit.svg Adds fullscreen-exit icon.
public/icons/fullscreen-enter.svg Adds fullscreen-enter icon.
public/icons/check.svg Adds check icon.
prettier.config.js Normalizes Prettier config formatting.
pnpm-workspace.yaml Allows builds for esbuild/unrs-resolver.
mise.toml Adds mise config to pin pnpm tool version.
eslint.config.js Extends ignore patterns for build outputs and artifacts.
drizzle/20260828171858_academic_semester/migration.sql Drops legacy joined_semester_raw column.
drizzle/20260828170020_member_webhooks/migration.sql Adds webhook client/delivery tables and member cache changes.
drizzle/20260828154802_elite_stardust/migration.sql Migrates video quality to hasHq/hasLq flags.
drizzle/20260828152718_late_dust/migration.sql Adds encoding group/base filename extraction + drops old URL cols.
drizzle/20260823193237_organic_ego/migration.sql Adds trigram + normalization function for accent-insensitive search.
drizzle/20260823191647_melted_mojo/migration.sql Adds/repairs live stream overlap exclusion constraint.
drizzle/20260823184625_salty_jocasta/migration.sql Makes event start_date nullable.
drizzle/20260823170852_audit_immutability/migration.sql Adds trigger preventing audit log mutation.
drizzle/20260823164832_married_vivisector/migration.sql Adds member sync run table + indexes.
drizzle/20260823151053_solid_stingray/migration.sql Adds auth_sessions table + expiry index.
docs/examples/seed.example.json Adds example seed JSON format.
docs/examples/oob-config.example.json Adds example OOB config JSON format.
Dockerfile Adds multi-stage Docker build/runtime setup.
docker-compose.yml Adds production compose (app + db + authentik + migrate tool).
docker-compose.dev.yml Updates dev compose (healthchecks, authentik env/blueprints).
.prettierignore Ignores build outputs and generated OpenAPI YAML.
.gitignore Ignores OOB and env variants + macOS ._*.
.env.example Adds TEST_DATABASE_URL for integration tests.
.cta.json Reformats chosen add-ons array.
Review details
  • Files reviewed: 26/271 changed files
  • Comments generated: 4
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/server/api/view-routes.ts
Comment thread src/server/jobs/locks.ts
Comment thread src/server/pages/sitemap.ts
Comment thread src/server/pages/slug-route.ts

@TGyAkos TGyAkos left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM well done

}
}

// to publicly unreachable content.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be made clearer

Comment thread src/server/shared/slug.ts
Comment on lines +8 to +33
const HUNGARIAN_ACCENTS: Record<string, string> = {
á: 'a',
é: 'e',
í: 'i',
ó: 'o',
ö: 'o',
ő: 'o',
ú: 'u',
ü: 'u',
ű: 'u',
Á: 'a',
É: 'e',
Í: 'i',
Ó: 'o',
Ö: 'o',
Ő: 'o',
Ú: 'u',
Ü: 'u',
Ű: 'u',
}

export function slugify(title: string): string {
const folded = title.replace(
/[áéíóöőúüűÁÉÍÓÖŐÚÜŰ]/g,
(char) => HUNGARIAN_ACCENTS[char] ?? char,
)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same logic is used in server/catalog/names.ts could be reused, it doesn't really matter

@@ -0,0 +1,48 @@
const MEDIA_HOST = 'https://v.bsstudio.hu'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be set from the oob?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants