Add removeFromMine functionality to Meetups API for removing meetups from a user's "My Meetups" list

- 🔒 Introduce `removeFromMine` policy for authenticated users to remove meetups.
- ✏️ Add `removeFromMine` method in `MeetupController` with idempotent handling.
-  Add `removeMember` utility in `Meetup` model for managing pivot relationships.
- 🧪 Add feature tests for `removeFromMine`, covering idempotency, permissions, and unknown slugs.
- 🌐 Register `removeFromMine` route in API and link it to `MeetupController`.
This commit is contained in:
HolgerHatGarKeineNode
2026-06-15 21:28:01 +02:00
parent 4b6cf95932
commit e55967e9ac
5 changed files with 99 additions and 0 deletions
@@ -144,6 +144,24 @@ class MeetupController extends Controller
: \Symfony\Component\HttpFoundation\Response::HTTP_OK);
}
/**
* Meetup aus „Meine Meetups" entfernen
*
* Entfernt ein Meetup aus der „Meine Meetups"-Liste des authentifizierten Nutzers
* (löst die meetup_user-Pivot-Mitgliedschaft). Die Stammdaten des Meetups bleiben
* erhalten Gegenstück zu addToMine(). Idempotent: war das Meetup nicht (mehr)
* zugeordnet, bleibt die Antwort 200 OK.
*/
#[Response(status: 401, description: 'Nicht authentifiziert.')]
public function removeFromMine(Request $request, Meetup $meetup): MeetupResource
{
Gate::authorize('removeFromMine', $meetup);
$meetup->removeMember($request->user());
return MeetupResource::make($meetup);
}
/**
* Eigenes Meetup anzeigen
*
+11
View File
@@ -202,6 +202,17 @@ class Meetup extends Model implements HasMedia
return ! $wasMember;
}
/**
* Den Nutzer wieder aus „Meine Meetups" entfernen (löst die meetup_user-Pivot).
* Idempotent: war der Nutzer kein Mitglied, passiert nichts. Gibt true zurück,
* wenn tatsächlich eine Zuordnung gelöst wurde (false = war kein Mitglied).
* Gegenstück zu {@see addMember()}; die Stammdaten bleiben unberührt.
*/
public function removeMember(User $user): bool
{
return $this->users()->detach($user->getKey()) > 0;
}
/**
* RateLimiter-Key für Meetup-Stammdaten-Updates über das Portal-Frontend.
*/
+11
View File
@@ -47,6 +47,17 @@ class MeetupPolicy
return true;
}
/**
* Ein Meetup wieder aus „Meine Meetups" entfernen (löst die meetup_user-Pivot
* des Nutzers). Spiegelt die offene Semantik von addToMine(): jeder
* authentifizierte Nutzer darf seine eigene Zuordnung lösen. Die Stammdaten
* bleiben dem Ersteller vorbehalten (siehe update()).
*/
public function removeFromMine(User $user, Meetup $meetup): bool
{
return true;
}
public function update(User $user, Meetup $meetup): bool
{
return $this->owns($user, $meetup);