events()->pluck('id'); $matches = PersonIdentityMatch::pending() ->whereHas('person', fn ($q) => $q->whereIn('event_id', $eventIds)) ->with(['person.crowdType', 'person.event', 'matchedUser']) ->orderBy('created_at', 'desc') ->paginate(25); return PersonIdentityMatchResource::collection($matches); } public function showForPerson(Organisation $organisation, Person $person): PersonIdentityMatchResource { Gate::authorize('view', [$person, $person->event]); $match = $person->pendingIdentityMatch() ->with('matchedUser') ->firstOrFail(); return new PersonIdentityMatchResource($match); } public function confirm(Request $request, Organisation $organisation, PersonIdentityMatch $personIdentityMatch): JsonResponse { // Verify match belongs to this organisation if ($personIdentityMatch->person->event->organisation_id !== $organisation->id) { return $this->notFound('Match not found.'); } Gate::authorize('confirm', $personIdentityMatch); try { $this->identityService->confirmMatch($personIdentityMatch, $request->user()); } catch (\DomainException $e) { return $this->error($e->getMessage(), 422); } $personIdentityMatch->refresh()->load(['person.crowdType', 'person.event', 'matchedUser', 'resolvedBy']); return $this->success(new PersonIdentityMatchResource($personIdentityMatch)); } public function dismiss(Request $request, Organisation $organisation, PersonIdentityMatch $personIdentityMatch): JsonResponse { // Verify match belongs to this organisation if ($personIdentityMatch->person->event->organisation_id !== $organisation->id) { return $this->notFound('Match not found.'); } Gate::authorize('dismiss', $personIdentityMatch); try { $this->identityService->dismissMatch($personIdentityMatch, $request->user()); } catch (\DomainException $e) { return $this->error($e->getMessage(), 422); } $personIdentityMatch->refresh()->load(['person.crowdType', 'person.event', 'matchedUser', 'resolvedBy']); return $this->success(new PersonIdentityMatchResource($personIdentityMatch)); } public function bulkConfirm(BulkConfirmIdentityMatchesRequest $request, Organisation $organisation): JsonResponse { Gate::authorize('bulkConfirm', [PersonIdentityMatch::class, $organisation]); $orgEventIds = $organisation->events()->pluck('id'); $matches = PersonIdentityMatch::whereIn('id', $request->validated('match_ids')) ->whereHas('person', fn ($q) => $q->whereIn('event_id', $orgEventIds)) ->with('person') ->get() ->keyBy('id'); $confirmed = 0; $errors = []; foreach ($request->validated('match_ids') as $matchId) { $match = $matches->get($matchId); if ($match === null) { $errors[] = ['match_id' => $matchId, 'error' => 'Match not found.']; continue; } $response = Gate::inspect('update', [$match->person, $match->person->event]); if ($response->denied()) { $errors[] = ['match_id' => $matchId, 'error' => 'Unauthorized.']; continue; } try { $this->identityService->confirmMatch($match, $request->user()); $confirmed++; } catch (\DomainException $e) { $errors[] = ['match_id' => $matchId, 'error' => $e->getMessage()]; } } return response()->json([ 'confirmed' => $confirmed, 'errors' => $errors, ]); } }