- 📚 Added "API Dokumentation" link to the sidebar and header navigation.
- 🔓 Defined `viewApiDocs` gate for public access to API documentation.
- ✅ Added feature tests for API documentation route accessibility and OpenAPI document serving.
- 🌐 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>
- ✅ Implemented handling for `CorruptComponentPayloadException` to prevent logging noise and improve exception management.
- 🛠️ Added IP-based throttling (120 requests/min) for the `/livewire/update` endpoint with middleware integration for better traffic control.
- ✅ Introduced unit tests to validate throttle settings and middleware application.
- 🧪 Enhanced tests for ensuring silent handling of corrupt payload scenarios and reduced log noise.
- ➕ Added Latvian (`lv`) JSON translations and validation/password localization files.
- 🛠️ Updated `lang-country` config to include `lv-LV` and centralized language definitions.
- 🌐 Extended sidebar and navigation with new translatable strings.
- ➕ Introduced 72px width customization for the sidebar layout.
- ✅ Improved timezone mapping in Nostr publishing commands (added `Europe/Riga`).
- 🛠️ Refactored language selector to dynamically source available languages from the config.
- Introduced `recalculateActivity` method in `Meetup` model to centralize activity and event timestamp updates.
- Added `MeetupEventObserver` to trigger activity recalculation on event save/delete.
- Updated `/meetups:update-activity` command to leverage the new model method for cleanup.
- Enhanced tests to cover various `MeetupEvent` scenarios affecting activity states.
- 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`).
- Trust the Forge reverse proxy and force https URLs in production so
generated absolute URLs match the actual TLS termination.
- Reject Nostr profile photo URLs that aren't http(s) or that resolve to
loopback / private (RFC1918) addresses to close an SSRF vector in
FetchNostrProfileJob.
- Tighten image upload validation across meetup, course, and lecturer
create/edit components: explicit mimes whitelist (jpeg, png, webp),
max 5 MiB, and dimension cap of 4000x4000.
- Replace the silent "skip if exists" branch in LnurlAuthController with
updateOrCreate so concurrent callers cannot race on the k1 record.
- Validate github_data on Meetup edit, decoding the JSON, and keep only
the whitelisted keys (top, left, state) with strict type coercion to
prevent storing arbitrary attacker-controlled JSON.
- 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.
🛠️ **Factory:** Created factories for `TwitterAccount`, `EmailCampaign`, `EmailTexts`, and `BookCase`.
✨ **Helper:** Added `NostrHelper` with methods for generating fake/mocked Nostr data.
⬆️ **Dependencies:** Updated multiple Composer dependencies including `laravel/framework`, `astrotomic/laravel-translatable`, and others to their latest versions.
- **Removed:** `docker-compose.yml`, Sail-specific Dockerfiles, and related scripts for PHP 8.3 setup.
- **Updated:** Documentation to reflect a shift from Docker to a direct PHP-based local development workflow.
- **Removed:** `laravel/sail` dependency from `composer.lock`.
- **Implemented:** `#[Locked]` Livewire attribute across components for read-only properties.
- **Added:** Feature tests to ensure locked properties cannot be tampered with.
- **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.
- **Removed:** Unused feature and component tests to clean up the codebase.
- **Added:** `RecurrenceType` enum for handling event recurrence modes.
- **Introduced:** City, Country, and Meetup factories for test data generation.
- **Implemented:** Migration to support recurring event fields in `meetup_events` table.
- **Enhanced:** Livewire meetup events creation with recurrence validation and preview logic.
- **Updated:** PHPUnit test suite configuration and composer dependencies for `pestphp/pest@v4.3`.
- **Refined:** SEO configuration (`favicon`) to standardize icon format.
- 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.
- Extend `TZ_MAP` and `DOMAIN_MAP` with `'at'` and `'ch'` entries pointing to `Europe/Berlin` and `portal.einundzwanzig.space` respectively.
- Adjust locale setting logic to use `'de'` for Austria and Switzerland, ensuring consistent language handling in Nostr publishing flows.
- Introduce `portal.einundzwanzig.space` with locale settings in `DomainMiddleware`.
- Replace verbose if‑chain in `NostrTrait::getUrl()` with a concise match expression.
- Add `DOMAIN_MAP` constant to `PublishUnpublishedItems` and force URL generation to use the correct domain per country.
- Update command flow: set domain before configuring timezone/locale.
- Added a new `lang/pl.json` file with comprehensive Polish translations.
- Enhanced `lang/es.json` with additional Spanish keys and phrases for better coverage.
- 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.
- Updated HTML indentation and alignment across `top-countries`, `activities`, and `top-meetups` components.
- Applied consistent formatting to dynamic content (e.g., map links, charts).
- Corrected key usage in `NostrTrait` for route parameters related to `meetups`.
- 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.