Skip to content
This repository was archived by the owner on Dec 3, 2025. It is now read-only.

Conversation

@AKasprzy
Copy link
Contributor

This should close #41.

Adam Kasprzyk and others added 12 commits July 22, 2025 09:31
…and organization invitations; add related tests and translations.
…ze controllers with constants and improved response structures.
… constants for request cooldowns in controllers.
… constants for request cooldowns in controllers.
@AKasprzy AKasprzy linked an issue Jul 25, 2025 that may be closed by this pull request
@AKasprzy AKasprzy marked this pull request as ready for review July 30, 2025 07:17
@mlencki mlencki requested a review from Copilot July 30, 2025 10:33
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements a comprehensive reporting system that allows users to report other users, organizations, and events. The system includes rate limiting to prevent spam (one report per target per day) and admin endpoints to view reports by type.

  • Adds a polymorphic Report model with database migration and factory
  • Implements API endpoints for creating reports and viewing them by type
  • Includes comprehensive test coverage for all reporting scenarios

Reviewed Changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tests/Feature/ReportTest.php Comprehensive test suite covering report creation, validation, rate limiting, and admin viewing
routes/api.php Adds report creation endpoint and admin routes for viewing reports by type
lang/pl/report.php Polish translation strings for report messages
lang/en/report.php English translation strings for report messages
database/migrations/2025_07_25_082312_create_reports_table.php Creates reports table with polymorphic relationship and unique constraint
database/factories/ReportFactory.php Factory for generating test report data
app/Models/User.php Adds reports relationship to User model
app/Models/Report.php Report model with polymorphic relationship and duplicate checking logic
app/Http/Resources/ReportResource.php API resource for formatting report data
app/Http/Requests/StoreReportRequest.php Validation rules for report creation requests
app/Http/Controllers/ReportController.php Controller handling report creation and admin viewing endpoints

Comment on lines +18 to +23

$table->unique([
"reporter_id",
"reportable_type",
"reportable_id",
"created_at",
Copy link

Copilot AI Jul 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The unique constraint includes 'created_at' which is a timestamp. This will not effectively prevent duplicate reports on the same day since 'created_at' includes time components. The constraint should use a date-based approach or the logic should rely on application-level checking only.

Suggested change
$table->unique([
"reporter_id",
"reportable_type",
"reportable_id",
"created_at",
$table->date("created_date")->virtualAs("DATE(created_at)");
$table->unique([
"reporter_id",
"reportable_type",
"reportable_id",
"created_date",

Copilot uses AI. Check for mistakes.
{
return response()->json([
"data" => ReportResource::collection(
Report::query()->where("reportable_type", User::class)->latest()->get(),
Copy link

Copilot AI Jul 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using get() without pagination could cause performance issues when there are many reports. Consider implementing pagination for these admin endpoints.

Suggested change
Report::query()->where("reportable_type", User::class)->latest()->get(),
Report::query()->where("reportable_type", User::class)->latest()->paginate($request->query('per_page', 15)),

Copilot uses AI. Check for mistakes.
Comment on lines +54 to +74
return response()->json([
"data" => ReportResource::collection(
Report::query()->where("reportable_type", User::class)->latest()->get(),
),
], Status::HTTP_OK);
}

public function organizationReports(): JsonResponse
{
return response()->json([
"data" => ReportResource::collection(
Report::query()->where("reportable_type", Organization::class)->latest()->get(),
),
], Status::HTTP_OK);
}

public function eventReports(): JsonResponse
{
return response()->json([
"data" => ReportResource::collection(
Report::query()->where("reportable_type", Event::class)->latest()->get(),
Copy link

Copilot AI Jul 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using get() without pagination could cause performance issues when there are many reports. Consider implementing pagination for these admin endpoints.

Suggested change
return response()->json([
"data" => ReportResource::collection(
Report::query()->where("reportable_type", User::class)->latest()->get(),
),
], Status::HTTP_OK);
}
public function organizationReports(): JsonResponse
{
return response()->json([
"data" => ReportResource::collection(
Report::query()->where("reportable_type", Organization::class)->latest()->get(),
),
], Status::HTTP_OK);
}
public function eventReports(): JsonResponse
{
return response()->json([
"data" => ReportResource::collection(
Report::query()->where("reportable_type", Event::class)->latest()->get(),
$perPage = request()->query('per_page', 15);
return response()->json([
"data" => ReportResource::collection(
Report::query()->where("reportable_type", User::class)->latest()->paginate($perPage),
),
], Status::HTTP_OK);
}
public function organizationReports(): JsonResponse
{
$perPage = request()->query('per_page', 15);
return response()->json([
"data" => ReportResource::collection(
Report::query()->where("reportable_type", Organization::class)->latest()->paginate($perPage),
),
], Status::HTTP_OK);
}
public function eventReports(): JsonResponse
{
$perPage = request()->query('per_page', 15);
return response()->json([
"data" => ReportResource::collection(
Report::query()->where("reportable_type", Event::class)->latest()->paginate($perPage),

Copilot uses AI. Check for mistakes.
{
return response()->json([
"data" => ReportResource::collection(
Report::query()->where("reportable_type", Event::class)->latest()->get(),
Copy link

Copilot AI Jul 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using get() without pagination could cause performance issues when there are many reports. Consider implementing pagination for these admin endpoints.

Suggested change
Report::query()->where("reportable_type", Event::class)->latest()->get(),
Report::query()->where("reportable_type", Event::class)->latest()->paginate(15),

Copilot uses AI. Check for mistakes.
Comment on lines +18 to +26
public function store(StoreReportRequest $request): JsonResponse
{
$user = $request->user();

$type = match ($request->input("type")) {
"user" => User::class,
"organization" => Organization::class,
"event" => Event::class,
};
Copy link

Copilot AI Jul 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type mapping logic is duplicated in three methods (store, userReports, organizationReports, eventReports). Consider extracting this into a private method or constant to reduce duplication.

Suggested change
public function store(StoreReportRequest $request): JsonResponse
{
$user = $request->user();
$type = match ($request->input("type")) {
"user" => User::class,
"organization" => Organization::class,
"event" => Event::class,
};
private const TYPE_USER = User::class;
private const TYPE_ORGANIZATION = Organization::class;
private const TYPE_EVENT = Event::class;
private function _getTypeMapping(string $type): string
{
return match ($type) {
"user" => self::TYPE_USER,
"organization" => self::TYPE_ORGANIZATION,
"event" => self::TYPE_EVENT,
default => throw new \InvalidArgumentException("Invalid type: $type"),
};
}
public function store(StoreReportRequest $request): JsonResponse
{
$user = $request->user();
$type = $this->_getTypeMapping($request->input("type"));

Copilot uses AI. Check for mistakes.
$alreadyReported = Report::alreadyReportedToday(
$user->id,
$type,
(int)$request->input("id"),
Copy link

Copilot AI Jul 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The controller doesn't validate that the reported entity exists before creating the report. This could lead to reports for non-existent entities.

Copilot uses AI. Check for mistakes.
@EwelinaSkrzypacz
Copy link
Member

Conflicts 👀

…into 41-report-system

# Conflicts:
#	app/Models/User.php
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Report system

4 participants