Commit Graph
15 Commits
Author SHA1 Message Date
openhands c5db7f5156 fix: production hardening — migration script, security fixes, structured logging, API docs, component splitting
- Create apply-migrations.ts and jobs-worker.ts scripts (package.json references)
- Convert badge leaderboard from $queryRawUnsafe to $queryRaw with Prisma.sql templates
- Fix OAuth email binding: add oauth_require_link site setting, skip 2FA-protected accounts
- Add per-user 2FA rate limiting (5/30s) to prevent TOTP brute-force
- Add structured JSON logger with levels (debug/info/warn/error)
- Split 341-line HomePage into GuestView + UserView components
- Add OpenAPI v3.1 spec at /api/openapi.json
- Add LOG_LEVEL env var, regenerate Prisma client
- Add mysql2 dependency for migration scripts
- All 58 tests pass, typecheck clean
2026-07-08 13:06:02 +02:00
openhands f381aa987f Fix dropdown visibility and add missing translations 2026-07-04 20:18:30 +02:00
openhands 7e5813bd97 Fix client loading as atomcms normal 2026-07-03 15:16:47 +02:00
remco d588ae5f0f style: polish enter button with gradient, inner highlight, arrow icon, and premium hover effects 2026-07-01 18:03:52 +02:00
remco d7138f3a32 fix: make enter button use theme primary color 2026-07-01 17:33:14 +02:00
remco 121459db22 fix: redesign avatar backdrop on home page for professional look
- Improve login card backdrop with cover background, multi-point gradient overlay, and decorative primary glow
- Redesign authenticated user hero section with layered background, dual decorative glows, glass-morphism enter button, and avatar positioned naturally at bottom
- Replace plain bg-black/30 overlay with rich gradient depth
2026-07-01 17:31:28 +02:00
remco 1de72863db latest changes 2026-07-01 15:06:52 +02:00
Simo 4dfe698009 Close remaining web gaps: rich profile, login history, lightbox/slider, flash client, admin chatlog/DJ/chart/WYSIWYG, niche API
- Rich profile (/u/[username]): wallet (credits/duckets/diamonds), friends
  grid (messenger_friendships), and owned rooms sections.
- Login history: new website_login_logs table (model + migration 0007),
  recorded on every successful sign-in (ip + user-agent), surfaced on a new
  /settings/sessions page (with failed-attempt list from failed_logins).
- Photos lightbox + home article slider (client components, no Swiper dep).
- /client/flash launcher (SSO ticket like the Nitro page).
- Admin: private chatlogs section in /admin/logs, /admin/radio/moderation
  (shout moderation), a "users by rank" inline bar chart on the dashboard,
  and a TinyMCE rich-text editor on the article admin forms.
- Niche API: /api/values/[id], /api/guilds(+/[id]), /api/radio/auto-play.

Verified live (prod, amx_test): login recorded → /settings/sessions shows
it with device; profile renders wallet/friends/rooms; dashboard chart +
private-chat logs + /client/flash + /api/guilds all OK. Reverted test data.
tsc 0, vitest 49/49, next build 0.
2026-06-29 18:26:34 +02:00
Simo f7b3845131 Close the web-feasible 100% gaps: REST write/token API, tickets, draw-badge, /me, sanitisation, dusk, radio SSE
Final parity push (web-tier only):
- REST API write + token auth: POST /api/tokens (issue a personal_access_token
  for the session user), Bearer auth via src/lib/api-auth.ts, POST
  /api/articles/[slug]/comment, GET/DELETE /api/me/tokens, full tickets API
  (/api/tickets +[id] +[id]/reply), radio current-dj/points/points-leaderboard/
  embed-config + POST shouts, and a real-time /api/radio/stream (SSE). 31 public
  API routes total.
- Pages: /draw-badge (buy a custom profile badge → credits + RCON), /me
  dashboard (stats + online friends + referral claim). Wired into the nav.
- HTML sanitisation (sanitize-html) — the HTMLPurifier equivalent — applied to
  writeable boxes + article bodies before dangerouslySetInnerHTML.
- "Dusk" dark theme preset + a default-dark site option honoured by the
  no-flash boot script.

Verified live (prod, amx_test): token issue → Bearer endpoint 200, no-token
401; /api/me/tokens lists it; current-dj/leaderboard JSON; /me + /draw-badge
200; reverted the test user + tokens. tsc 0, vitest 49/49, next build 0.
2026-06-29 18:15:01 +02:00
Simo 0cd4d06ff6 Fill the remaining gaps: badge upload, radio tools, VPN, writeable boxes
Built the admin tools previously listed as missing:
- Badge upload (/admin/badges): uploads a <code>.gif into the emulator's
  badge dir via BADGE_UPLOAD_DIR (node:fs); validated code/type/size,
  logged. Made configurable rather than skipped.
- Radio tools: /admin/radio/api-keys (CRUD, server-generated keys),
  /admin/radio/autodj (Auto-DJ playlist CRUD), /admin/radio/embed (embed
  snippet generator), /admin/radio/points (points settings),
  /admin/radio/monitoring (live stream/now-playing/listeners status).
  radio_api_keys + radio_auto_dj_playlist already had real columns.
- /admin/vpn: VPN/proxy detection config (block toggle + provider + key),
  complementing /admin/ip's raw blacklist.
- Writeable boxes: new website_writeable_boxes table (model + migration
  0006) + /admin/writeable-boxes CRUD; active boxes render on the public
  home page. env: BADGE_UPLOAD_DIR.

Verified live (prod, amx_test): all 8 pages render with real data; a test
writeable box appeared on the public home and was reverted. tsc 0,
vitest 49/49, next build 0 (7 new admin routes).
2026-06-28 21:04:34 +02:00
Simo e004dfedaf i18n: translate all public page bodies (EN + IT)
Internationalised the ~44 public pages with next-intl (the shell was
already translated). Each page now pulls its copy from a "pages.<slug>"
namespace via getTranslations (server) / useTranslations (client); the
EN + IT catalogs were authored by parallel agents and merged centrally,
with natural Italian (ICU plurals) and it backfilled from en for any
gap. request.ts gained getMessageFallback/onError so a missing key
degrades to the English value, never a raw key.

Behaviour unchanged (only display text moved to t() calls; queries,
actions, fields, ContentCard structure preserved). Verified on the prod
server: with NEXT_LOCALE=it, home/community/staff/news/shop/rankings all
render Italian copy, no raw-key leakage; English unchanged. The nav
language switcher toggles EN/IT live. tsc 0, vitest 49/49, next build 0.

Admin pages intentionally left in English (staff tooling).
2026-06-28 20:40:06 +02:00
Simo e9ea19795a Adapt + improve all public pages to the atom design system
Extended the same design-system treatment to the public site, faithful
to AtomCMS's "atom" theme. New src/components/public/ui.tsx provides the
signature atom building blocks + a scoped CSS layer:
- ContentCard: surface card with a primary-tinted header (icon circle +
  title + subtitle) and padded body — the atom content-card, used as
  every page's header and section wrapper.
- StatBlock / stat-grid, EmptyState, OnlineBadge (online/offline pill),
  RankBadge (medals for the top 3), and responsive .card-grid helpers.

Swept ~45 public pages (home/community/rankings hand-built as the
reference; the rest via parallel agents that read the schema and
preserved every query, server action, auth gate and field name):
heroes → ContentCard headers, lists → card-grids in ContentCards,
"no X" → EmptyState, status → OnlineBadge/RankBadge. The leaderboard
gained Credits/Diamonds/Duckets tabs (usersCurrency).

Behaviour unchanged. Verified on the prod server against amx_test: 15+
public pages render the content-cards/grids with real data, no errors;
computed styles confirm the tinted header, icon circle, medal + online
pills. Fixed an undefined --color-golden ref. tsc 0, vitest 49/49,
next build 0.
2026-06-28 19:28:36 +02:00
Simo 9a79acebe7 Add atom-theme visual design (header/footer, theme system, restyled pages)
Faithful port of AtomCMS's "atom" theme look (light, Habbo-retro, golden
#eeb425 / amber #f59e0b accents, white cards, 12px radii, Nunito-first stack):
- globals.css: full token set + components (.site-header/.nav-item, .btn-*,
  .card, .hero, currency pills, article cards, inputs, tables, footer).
- SiteHeader (brand + nav + currency pills + auth box, staff-aware) + SiteFooter;
  layout wraps header/content/footer. Removed the bare SiteNav.
- Restyled home (hero + article cards), login (centered card).
- siteSettings now falls back to DEFAULTS on missing key OR DB error, so pages
  render without a DB; DATABASE_CONNECT_TIMEOUT_MS env + pool acquireTimeout make
  the no-DB fallback fast.

Verified in a real browser (computed styles): header white/sticky, golden logo
gradient, uppercase nav, amber primary button @12px radius, golden outline,
hero gradient — all correct. tsc exit 0, vitest 48/48, next build exit 0.
2026-06-28 13:13:00 +02:00
Simo 6e34d485d4 Add data-driven public pages (home, news, profile)
Real App Router pages reading the converted Prisma models:
- home: latest 4 articles (websiteArticles) + hotel_name from settings
- /news + /news/[slug]: article index and detail
- /u/[username]: profile (avatar via imager helper, motto, rank, credits, online)
- shared SiteNav (reads session via auth() + hotel_name), globals.css
- src/lib/format.ts: avatarImageUrl + excerpt helpers (unit-tested)

Verified: tsc exit 0, vitest 43/43, next build exit 0 (7 routes). Pages render
against a live DB (deferred until DATABASE_URL is provided). i18n to be layered
on next.
2026-06-27 16:42:59 +02:00
Simo 443d908909 Scaffold Next.js 16 app + wire NextAuth Credentials to auth core
Minimal but real App Router app that builds (next build exit 0):
- src/lib/auth.ts: NextAuth v5 Credentials provider calling checkLogin()
  (argon2id/bcrypt + md5->argon2id upgrade gated by CONVERT_PASSWORDS), JWT
  session, /api/auth/[...nextauth] route handler.
- src/app: root layout, home (force-dynamic, reads hotel_name via siteSettings),
  /login client form (signIn).
- next.config.ts: pinned turbopack.root, serverExternalPackages for the Prisma
  MariaDB adapter; tsconfig set up for Next.

Routes: / (dynamic), /login, /api/auth. Verified: next build exit 0, 28 tests.
Still needs DB+APP_KEY to run auth end-to-end. i18n/middleware/pages to follow.
2026-06-27 16:11:52 +02:00