feat: get number of follows on public profile
Laravel CI-CD / Tests Unitaires (push) Successful in 1m31s Details
Laravel CI-CD / Deploy with Kamal (push) Successful in 1m44s Details

This commit is contained in:
Leon Morival 2026-05-28 20:52:48 +02:00
parent 1db50bc69a
commit c9dafc0f05
4 changed files with 27 additions and 0 deletions

View File

@ -64,6 +64,8 @@ class FollowController extends Controller
public function followers(Request $request, User $user): AnonymousResourceCollection public function followers(Request $request, User $user): AnonymousResourceCollection
{ {
abort_unless($request->user()->id === $user->id, 403);
$perPage = max(1, min($request->integer('per_page', 15), 100)); $perPage = max(1, min($request->integer('per_page', 15), 100));
$followers = $user->followers() $followers = $user->followers()
@ -75,6 +77,8 @@ class FollowController extends Controller
public function following(Request $request, User $user): AnonymousResourceCollection public function following(Request $request, User $user): AnonymousResourceCollection
{ {
abort_unless($request->user()->id === $user->id, 403);
$perPage = max(1, min($request->integer('per_page', 15), 100)); $perPage = max(1, min($request->integer('per_page', 15), 100));
$following = $user->following() $following = $user->following()

View File

@ -2,6 +2,7 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Enums\FollowStatus;
use App\Enums\MealPostVisibility; use App\Enums\MealPostVisibility;
use App\Http\Resources\MealPostsResource; use App\Http\Resources\MealPostsResource;
use App\Models\User; use App\Models\User;
@ -39,6 +40,12 @@ class PublicUserProfileController extends Controller
->where('visibility', MealPostVisibility::Public->value) ->where('visibility', MealPostVisibility::Public->value)
->whereNull('hidden_at') ->whereNull('hidden_at')
->count(), ->count(),
'followersCount' => $user->followers()
->wherePivot('status', FollowStatus::Accepted)
->count(),
'followingCount' => $user->following()
->wherePivot('status', FollowStatus::Accepted)
->count(),
], ],
'meals' => MealPostsResource::collection($meals)->resolve($request), 'meals' => MealPostsResource::collection($meals)->resolve($request),
], ],

View File

@ -7,6 +7,9 @@ use App\Listeners\GrantCreditsFromStripeWebhook;
use App\Mail\ResetPasswordMail; use App\Mail\ResetPasswordMail;
use App\Mail\VerifyAccount; use App\Mail\VerifyAccount;
use App\Models\User; use App\Models\User;
use Dedoc\Scramble\Scramble;
use Dedoc\Scramble\Support\Generator\OpenApi;
use Dedoc\Scramble\Support\Generator\SecurityScheme;
use Illuminate\Auth\Notifications\ResetPassword; use Illuminate\Auth\Notifications\ResetPassword;
use Illuminate\Auth\Notifications\VerifyEmail; use Illuminate\Auth\Notifications\VerifyEmail;
use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Cache\RateLimiting\Limit;
@ -45,6 +48,12 @@ class AppServiceProvider extends ServiceProvider
{ {
$this->configureRateLimiting(); $this->configureRateLimiting();
Scramble::afterOpenApiGenerated(function (OpenApi $openApi) {
$openApi->secure(
SecurityScheme::http('bearer')
);
});
if ($this->app->environment('production')) { if ($this->app->environment('production')) {
URL::forceScheme('https'); URL::forceScheme('https');
} }

View File

@ -3,6 +3,7 @@
use App\Http\Controllers\AuthController; use App\Http\Controllers\AuthController;
use App\Http\Controllers\BillingController; use App\Http\Controllers\BillingController;
use App\Http\Controllers\DeviceTokenController; use App\Http\Controllers\DeviceTokenController;
use App\Http\Controllers\FollowController;
use App\Http\Controllers\LegalDocumentController; use App\Http\Controllers\LegalDocumentController;
use App\Http\Controllers\MealImageAnalysisController; use App\Http\Controllers\MealImageAnalysisController;
use App\Http\Controllers\MealPostController; use App\Http\Controllers\MealPostController;
@ -79,6 +80,12 @@ Route::middleware(['auth:sanctum', 'verified', 'not_suspended'])->group(function
// Meals // Meals
Route::middleware(['auth:sanctum', 'verified', 'not_suspended'])->group(function (): void { Route::middleware(['auth:sanctum', 'verified', 'not_suspended'])->group(function (): void {
Route::get('users/{user}', [PublicUserProfileController::class, 'show'])->name('users.show'); Route::get('users/{user}', [PublicUserProfileController::class, 'show'])->name('users.show');
Route::post('users/{user}/follow', [FollowController::class, 'follow'])->middleware('throttle:engagement')->name('users.follow');
Route::delete('users/{user}/follow', [FollowController::class, 'unfollow'])->middleware('throttle:engagement')->name('users.unfollow');
Route::post('users/{user}/accept', [FollowController::class, 'accept'])->middleware('throttle:engagement')->name('users.accept');
Route::post('users/{user}/reject', [FollowController::class, 'reject'])->middleware('throttle:engagement')->name('users.reject');
Route::get('users/{user}/followers', [FollowController::class, 'followers'])->name('users.followers');
Route::get('users/{user}/following', [FollowController::class, 'following'])->name('users.following');
Route::post('users/{user}/reports', [ReportController::class, 'storeUser']) Route::post('users/{user}/reports', [ReportController::class, 'storeUser'])
->middleware('throttle:reports') ->middleware('throttle:reports')
->name('users.reports.store'); ->name('users.reports.store');