Update MeetupController to use pivot memberships for "My Meetups" in both listing and detail views

- ✏️ Adjust `mine` method to fetch meetups based on dashboard selections (`meetup_user` pivot).
- ✏️ Add `viewMine` policy to control access to individual meetups for pivot members.
- 🧪 Update feature tests to reflect pivot-based logic for "My Meetups."
This commit is contained in:
HolgerHatGarKeineNode
2026-06-13 22:42:33 +02:00
parent b6f5d57530
commit 8d7b1515d8
3 changed files with 39 additions and 14 deletions
@@ -106,14 +106,15 @@ class MeetupController extends Controller
/**
* Eigene Meetups auflisten
*
* Liefert alle vom authentifizierten Nutzer erstellten Meetups, alphabetisch sortiert.
* Liefert die im Dashboard ausgewählten Meetups des authentifizierten Nutzers
* (meetup_user-Pivot, „Meine Meetups"), alphabetisch sortiert.
*/
public function mine(Request $request): AnonymousResourceCollection
{
Gate::authorize('viewAny', Meetup::class);
$meetups = Meetup::query()
->where('created_by', $request->user()->id)
$meetups = $request->user()
->meetups()
->orderBy('name')
->get();
@@ -123,12 +124,12 @@ class MeetupController extends Controller
/**
* Eigenes Meetup anzeigen
*
* Zeigt ein einzelnes, vom authentifizierten Nutzer erstelltes Meetup.
* Zeigt ein einzelnes der im Dashboard ausgewählten Meetups (meetup_user-Pivot).
*/
#[Response(status: 403, description: 'Nur der Ersteller oder ein Super-Admin darf das Meetup sehen.')]
#[Response(status: 403, description: 'Nur der Ersteller oder ein Mitglied (meetup_user-Pivot) darf das Meetup sehen.')]
public function mineShow(Meetup $meetup): MeetupResource
{
Gate::authorize('view', $meetup);
Gate::authorize('viewMine', $meetup);
return MeetupResource::make($meetup);
}
+11
View File
@@ -20,6 +20,17 @@ class MeetupPolicy
return $this->owns($user, $meetup);
}
/**
* Sichtbarkeit der „Meine Meetups"-Detailansicht: Neben dem Ersteller darf
* jedes Mitglied der meetup_user-Pivot („Meine Meetups" im Dashboard) das
* abonnierte Meetup über die REST-API ansehen. Spiegelt die Listen-Semantik
* von MeetupController::mine(), die ebenfalls die Pivot-Mitgliedschaft nutzt.
*/
public function viewMine(User $user, Meetup $meetup): bool
{
return $this->owns($user, $meetup) || $meetup->hasMember($user);
}
public function create(User $user): bool
{
return true;
+21 -8
View File
@@ -70,23 +70,36 @@ it('forbids updating as a pivot member who is not the creator', function () {
])->assertForbidden();
});
it('returns only own in mine index', function () {
it('returns the dashboard-selected meetups in mine index', function () {
Sanctum::actingAs($user = User::factory()->create());
$other = User::factory()->create();
Meetup::factory()->count(2)->create(['created_by' => $user->id]);
Meetup::factory()->create(['created_by' => $other->id]);
$selected = Meetup::factory()->count(2)->create();
$unselected = Meetup::factory()->create();
$user->meetups()->attach($selected);
$response = $this->getJson('/api/my-meetups');
$response->assertSuccessful();
expect($response->json('data'))->toHaveCount(2);
collect($response->json('data'))->each(
fn ($meetup) => expect($meetup['created_by'])->toBe($user->id)
);
$ids = collect($response->json('data'))->pluck('id')->all();
expect($ids)
->toContain(...$selected->pluck('id')->all())
->not->toContain($unselected->id);
});
it('forbids viewing someone elses in mine show', function () {
it('lets a pivot member view in mine show', function () {
Sanctum::actingAs($user = User::factory()->create());
$meetup = Meetup::factory()->create();
$user->meetups()->attach($meetup);
$this->getJson('/api/my-meetups/'.$meetup->id)
->assertSuccessful()
->assertJsonPath('data.id', $meetup->id);
});
it('forbids viewing a meetup the user has not selected in mine show', function () {
$owner = User::factory()->create();
$meetup = Meetup::factory()->create(['created_by' => $owner->id]);