Replaces the custom-scheme auto-redirect (which triggers Chrome's
confirmation prompt) with a verified Android App Link handoff:
- public/.well-known/assetlinks.json for space.einundzwanzig.mobile
(debug cert fingerprint; add the release cert before store builds)
- GET /app/auth handoff: opens the app directly when the App Link is
verified; renders a button-based fallback page otherwise
- POST /api/mobile/token: trades a NIP-55-signed login event for a
Sanctum token — used when Amber's callback opens the app directly
- complete/confirm/signedCallback now redirect to the handoff URL
Amber drops the query string when it rebuilds the callback URL and
appends the signed event directly to the path. The mobile login page now
hands out path-based callback URLs (/auth/mobile/signed/{k1}/) so the
event arrives as the remainder of the path.
The new callback runs in the web middleware group: the signer opens it
in the system browser, which shares cookies with the in-app browser
session, so the flow completes immediately — a bridge page issues the
token and fires the einundzwanzig:// deep link. The LoginKey row is
still written as a fallback for the polling login page.
The Einundzwanzig mobile app opens /auth/mobile in an in-app browser.
After a Lightning (LNURL) or Nostr login the flow issues a personal
access token and hands it back via the einundzwanzig://auth deep link.
- New auth.mobile-login Livewire view: Lightning QR (shared k1) plus
Nostr signing via NIP-55 Android signers (Amber) with server callback,
and a confirmation screen for already authenticated sessions
- MobileAuthController: NIP-55 callback verification, completion route
issuing the token (replacing same-device tokens), redirect whitelist
- Nostr login event verification and npub user resolution extracted to
App\Support\NostrLogin, now shared with the interactive login
- GET /api/user (auth:sanctum) returns the token owner's profile
- ➕ Introduced `store`, `update`, `mine`, and `mineShow` endpoints for `Meetups`, `Cities`, `Venues`, and `Lecturers` with validation and authorization.
- 🔒 Added `Policies` for `Meetups`, `Cities`, `Venues`, and `Lecturers` leveraging `ChecksCreatorOwnership` for ownership checks.
- 🌐 Created `Resources` for structured API responses: `MeetupResource`, `CityResource`, `VenueResource`, and `LecturerResource`.
- ✅ Added dedicated `Request` classes for input validation: `Store` and `Update` variants for all models.
- 🛠️ Updated controllers to support new functionalities with localized error messages and proper HTTP responses.
- 🌐 Added API documentation annotations for multiple controllers (Meetups, Cities, Countries, Courses, Highscores, Venues), improving public and developer-facing endpoint clarity.
- ➕ Integrated and configured the `dedoc/scramble` package for automated OpenAPI documentation generation.
- 🔒 Excluded internal routes and actions from API documentation using `ExcludeRouteFromDocs` attributes.
- 🌍 Added new localization keys for API Token features across multiple languages (`lv`, `es`, etc.).
- 🛠️ Introduced `Group`, `Response`, and `QueryParameter` attributes for better request descriptions and structured documentation.
- 🚀 Enhanced functionality for listing operations in controllers with filters and query parameters like `search` and `selected`.
Adds a "API Tokens" settings page so an authenticated user can create and
revoke Sanctum personal access tokens for the new authenticated write
endpoints — using the official Sanctum API ($user->createToken() / tokens()).
- New Volt component settings/api-tokens (create token, one-time plain-text
reveal with copy-to-clipboard, list + revoke own tokens).
- Registered route settings.api-tokens (country-prefixed, auth group) and
added a nav entry in the settings layout.
- SEO definition for the new page.
- Pest feature tests (create/reveal-once, validation, revoke, ownership
scoping) and a Pest browser screenshot test.
Implements Sanctum-authenticated write endpoints so a lecturer can create
and update their own courses and dated course events programmatically
(e.g. to keep the portal's course events in sync with an external system).
- CourseController@store / @update implemented (validation mirrors the
Livewire course create form; create requires is_lecturer, update is
restricted to the owner or a super-admin).
- New CourseEventController with index/store/update. index returns only the
authenticated user's own events (optional ?course_id= filter) for
idempotent syncing; validation mirrors the Livewire course event form.
- Public `courses` API resource narrowed to index/show; all writes moved
behind an `auth:sanctum` route group (the previous store/update/destroy
actions were empty no-ops).
- Pest feature test covering auth (401), authorization (403/is_lecturer/
ownership), creation (201), validation (422) and ownership-scoped listing.
Ported from Einundzwanzig-Podcast/einundzwanzig-portal#25, adapted to this
repo's conventions (inline authorization instead of policies, Pest tests,
validation mirroring the current Livewire forms) while keeping the same
endpoint outputs.
Co-authored-by: schnuartz-ai <schnuartz@gmail.com>
- Added `is_active` and `last_event_at` fields to meetups with migration.
- Enhanced UI: Display `Aktiv`/`Inaktiv` badges and last event dates across dashboard, tables, and maps.
- Introduced `/meetups:update-activity` command to manage activity flags and timestamps.
- Validated latitude/longitude to prevent `0,0` inputs in city creation and updates.
- Updated factories and tests to include meetup activity states (`active`, `inactive`).
- Add 60 req/min throttle to the public API group and a stricter 10 req/min
throttle to POST /highscores.
- Replace mass-assigned $guarded=[] with explicit $fillable on User, Meetup,
Course, Lecturer, and SelfHostedService. created_by stays out of the
whitelist; the existing creating() hooks continue to populate it.
- Require authenticated user on Api/MeetupController::index instead of
trusting the user_id query parameter (IDOR).
- Constrain the /img and /img-public route paths to a safe character set
and reject any path containing ".." in ImageController.
- Add rel="noopener noreferrer" to every target="_blank" link on the meetup
and course landing pages.
- Remove unauthenticated /test route that dispatched FetchNostrProfileJob
for a hardcoded user (routes/web.php).
- Enforce created_by ownership check in meetup and lecturer Livewire edit
components; mirror the existing services/edit pattern.
- Replace blind-trust nostrLoggedIn handler with NIP-42-style signed event
verification: server-issued challenge stored in session, client signs a
kind:22242 event, server verifies signature via swentel/nostr-php and
derives npub. Challenge is single-use with 5-minute TTL.
- Validate the ?my[] parameter on the calendar download endpoint as an
array of integers and intersect with the authenticated user's meetups.
Hier ist ein Beispiel wie man eine route von Laravel Nightwatch exkludiert:
// Never sample a route
Route::get('/users', [UserController::class, 'index'])
->middleware(Sample::never());
Das selbe mache bitte in unserem Projekt für folgende routes:
/{country}/meetup/stream-calendar
/{country}/meetup/{meetup}/event/{event}
/stream-calendar
- **Added:** Endpoints for submitting highscores (`highscores.store`) and retrieving the leaderboard (`highscores.index`).
- **Implemented:** Validation rules via `StoreHighscoreRequest` to ensure highscore integrity.
- **Included:** `Highscore` model, migration, and factory for data handling and seeding.
- **Enhanced:** Comprehensive feature tests covering submission, updating, retrieval, and payload validation.
- Replaced `state` and `computed` with `Livewire\Component` implementations in `language/selector.blade.php` for enhanced maintainability.
- Adjusted `login.blade.php` syntax for dynamic href generation and removed commented-out sign-up link.
- Added unique `wire:key` attributes to iterable elements for enhanced performance and reactivity.
- Simplified controller routing and corrected indentation in `web.php`, improving clarity.
- Added `LnurlAuthController` to handle LNURL authentication flow with signature verification, user creation, and session expiry checks.
- Integrated authentication error polling in `nostrLogin.js`.
- Added `LoginKeyFactory` for testing and database seed purposes.
- Created feature tests (`LnurlAuthTest`) to validate LNURL callback, error responses, and session handling.
- Extended `login.blade.php` with dynamic error handling and reset logic for expired sessions.
- 🛠️ Updated Laravel Boost MCP server command from `vendor/bin/sail` to `docker` with proper arguments
- 🌐 Added comprehensive routing structure including country-specific groups, dashboard redirects, and meetup/calendar routes
- 📝 Included new test routes, error handling, and image serving capabilities
- 🔧 Enhanced authentication middleware usage with country prefixes for various resource routes
- 🚫 Commented out legacy book rental routes while maintaining flexibility for future activation
- 🔄 Implemented fallback 404 handling with rate limiting and included auth routes from separate file
- Introduced a new route `meetup/ical` in `api.php` to handle iCal data export.
- Added `ical` method to `MeetupController` returning a 404 response for now.
- Introduced `all-meetups` route (`meetups.index-all`) for accessing meetups globally.
- Updated sidebar with a new navigation item for global meetups, including icon and dynamic badge count.
- Enhanced backend logic to handle country-specific and global meetup filtering based on the current route.
- Introduced `FetchNostrProfileJob` for retrieving and updating user Nostr profiles.
- Added Hungarian translations (`auth.php`, `passwords.php`, `validation.php`, and others) for improved localization.
- Integrated Laravel Horizon for enhanced queue management (`HorizonServiceProvider` added, `composer.json` updated).
- Updated German and Spanish language files to fix duplicate keys.
- Minor route addition for testing Nostr profile job dispatch.
- Introduced `meetups.map-world` route for global meetup map view.
- Updated `meetups.map` route to include dynamic filtering based on country.
- Enhanced sidebar with icons and flags for improved navigation clarity.
- Added `label` attributes to timezone and country choosers for improved accessibility.
- Renamed `meetups.landingpage-event` route to `meetups.landingpage-event-old` for clarity and potential deprecation.
- Removed redundant `heading` attribute from sidebar's navlist group for cleaner rendering.
- Added Laravel Nightwatch for advanced monitoring and user sampling.
- Customized Livewire update route with rate-limiting middleware.
- Introduced a global fallback route with 404 response and sampling middleware.
- Enabled event listening for health diagnosis with Nightwatch sampling adjustments.
- Refined lazy loading prevention in local environments.
- Updated settings route links to include `country` parameter dynamically resolved from session.
- Improved relational queries by adding `city.country` to meetups map and `coursesEvents.course` to lecturers data.
- Added `DomainMiddleware` to dynamically set locale, language-country session, and app name based on domain.
- Updated views and components to leverage `lang_country` session for language and region-specific content.
- Enhanced country parameter retrieval with `config('app.domain_country')` as fallback.
- Refined language filtering by scanning available language files dynamically.
- Added language-specific assets and translations (`nl.json`, `es.json`) with improved language-region associations.
- Updated `app-logo-icon` to display region-specific images or default SVGs.
- Improved views with cleaner, dynamic rendering and session-aware functionalities.
- Updated multiple views to conditionally render actions based on authentication state for a better user experience.
- Added login links where actions require authentication.
- Added `publicDisk` configuration to `filesystems.php`.
- Expanded locale translations in `es.json` and `de.json`.
- Implemented RSS, Atom, and JSON feed views.
- Added `feed.php` configuration for feed generation.
- Introduced `ImageController` for image handling.
- Updated application routing to include `api.php`.