isAdmin()) { return true; } return null; } /** * Any authenticated user with a mature account may award any artwork * that isn't their own. * Returns false (→ 403 or 404 based on caller) when the check fails. */ public function award(User $user, Artwork $artwork): Response { if (! config('artwork_medals.enabled', true)) { return Response::deny('Artwork medals are currently disabled.'); } if (! $artwork->is_public || ! $artwork->is_approved) { return Response::deny('This artwork is not eligible for medals.'); } if ($artwork->deleted_at !== null) { return Response::deny('This artwork is no longer available for medals.'); } if ($artwork->published_at === null || $artwork->published_at->isFuture()) { return Response::deny('This artwork is not published yet.'); } if ($artwork->user_id === $user->id) { return Response::deny('You cannot medal your own artwork.'); } return $this->accountIsMature($user); } /** * The user may change a medal they already placed. */ public function change(User $user, ArtworkAward $award): bool { return $user->id === $award->user_id; } /** * The user may remove a medal they already placed. */ public function remove(User $user, ArtworkAward $award): bool { return $user->id === $award->user_id; } // ------------------------------------------------------------------------- private function accountIsMature(User $user): Response { if ((bool) config('artwork_medals.require_verified_email', true)) { $isVerified = method_exists($user, 'hasVerifiedEmail') ? $user->hasVerifiedEmail() : ! empty($user->email_verified_at); if (! $isVerified) { return Response::deny('Verify your email address before giving medals.'); } } if (! $user->created_at) { return Response::allow(); // cannot verify — allow } $minimumAgeHours = (int) config('artwork_medals.minimum_account_age_hours', 24); if ($user->created_at->diffInHours(now()) < $minimumAgeHours) { return Response::deny("Your account must be at least {$minimumAgeHours} hours old before giving medals."); } return Response::allow(); } }