From cbcc1f025ae291a7d84b9b4d5aea5fc5a6d1921c Mon Sep 17 00:00:00 2001 From: Miguel N Date: Tue, 20 Jul 2021 22:35:49 +0100 Subject: [PATCH] Refactored ban system Implemented a Reddit-like account suspension system (similar to subreddit bans). This makes it easier to ban users from the app, and the code has also been cleaned up. The interface was also revamped. --- app/Ban.php | 4 +- app/Console/Kernel.php | 4 +- app/Http/Controllers/BanController.php | 38 ++++----------- app/Http/Controllers/ProfileController.php | 12 +++++ app/Http/Requests/BanUserRequest.php | 11 ++++- ...leanBans.php => ProcessDueSuspensions.php} | 8 ++-- config/adminlte.php | 16 +++++++ .../2021_07_20_094139_change_bans_table.php | 36 ++++++++++++++ resources/lang/en/messages.php | 11 ++--- .../user/profile/displayprofile.blade.php | 47 ++++++++++--------- 10 files changed, 118 insertions(+), 69 deletions(-) rename app/Jobs/{CleanBans.php => ProcessDueSuspensions.php} (86%) create mode 100644 database/migrations/2021_07_20_094139_change_bans_table.php diff --git a/app/Ban.php b/app/Ban.php index e08b336..f4c2dfb 100755 --- a/app/Ban.php +++ b/app/Ban.php @@ -30,13 +30,13 @@ class Ban extends Model 'userID', 'reason', 'bannedUntil', - 'userAgent', + 'isPermanent', 'authorUserID', ]; public $dates = [ - 'bannedUntil', + 'suspendedUntil', ]; public function user() diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 28273ca..b50fa90 100755 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -21,7 +21,7 @@ namespace App\Console; -use App\Jobs\CleanBans; +use App\Jobs\ProcessDueSuspensions; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; @@ -50,7 +50,7 @@ class Kernel extends ConsoleKernel ->daily(); // Production value: Every day - $schedule->job(new CleanBans) + $schedule->job(new ProcessDueSuspensions) ->daily(); // Production value: Every day } diff --git a/app/Http/Controllers/BanController.php b/app/Http/Controllers/BanController.php index 8c8acf4..7865d5c 100755 --- a/app/Http/Controllers/BanController.php +++ b/app/Http/Controllers/BanController.php @@ -34,48 +34,26 @@ class BanController extends Controller { $this->authorize('create', [Ban::class, $user]); - // FIXME: Needs refactoring to a simpler format, e.g. parse the user's given date directly. if (is_null($user->bans)) { + + $duration = $request->duration; $reason = $request->reason; - $duration = strtolower($request->durationOperator); - $durationOperand = $request->durationOperand; + $type = $request->suspensionType; // ON: Temporary | OFF: Permanent - $expiryDate = now(); - - if (! empty($duration)) { - switch ($duration) { - case 'days': - $expiryDate->addDays($durationOperand); - break; - - case 'weeks': - $expiryDate->addWeeks($durationOperand); - break; - - case 'months': - $expiryDate->addMonths($durationOperand); - break; - - case 'years': - $expiryDate->addYears($durationOperand); - break; - } - } else { - // Essentially permanent - $expiryDate->addYears(40); + if ($type == "on") { + $expiryDate = now()->addDays($duration); } $ban = Ban::create([ 'userID' => $user->id, 'reason' => $reason, - 'bannedUntil' => $expiryDate->format('Y-m-d H:i:s'), - 'userAgent' => 'Unknown', + 'bannedUntil' => ($type == "on") ? $expiryDate->format('Y-m-d H:i:s') : null, 'authorUserID' => Auth::user()->id, + 'isPermanent' => ($type == "off") ? true : false ]); - event(new UserBannedEvent($user, $ban)); - $request->session()->flash('success', __('Account suspended. Suspension ID #:susId', ['susId', $ban->id])); + $request->session()->flash('success', __('Account suspended.')); } else { $request->session()->flash('error', __('Account already suspended!')); } diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php index ca663b5..aba3e8b 100755 --- a/app/Http/Controllers/ProfileController.php +++ b/app/Http/Controllers/ProfileController.php @@ -71,6 +71,17 @@ class ProfileController extends Controller } } + $suspensionInfo = null; + if ($user->isBanned()) + { + $suspensionInfo = [ + + 'isPermanent' => $user->bans->isPermanent, + 'reason' => $user->bans->reason, + 'bannedUntil' => $user->bans->bannedUntil + ]; + } + if (Auth::user()->is($user) || Auth::user()->can('profiles.view.others')) { return view('dashboard.user.profile.displayprofile') ->with([ @@ -82,6 +93,7 @@ class ProfileController extends Controller 'since' => $createdDate->englishMonth.' '.$createdDate->year, 'ipInfo' => IP::lookup($user->originalIP), 'roles' => $roleList, + 'suspensionInfo' => $suspensionInfo ]); } else { abort(403, __('You cannot view someone else\'s profile.')); diff --git a/app/Http/Requests/BanUserRequest.php b/app/Http/Requests/BanUserRequest.php index 6c0469b..943bd90 100755 --- a/app/Http/Requests/BanUserRequest.php +++ b/app/Http/Requests/BanUserRequest.php @@ -45,8 +45,15 @@ class BanUserRequest extends FormRequest { return [ 'reason' => 'required|string', - 'durationOperand' => 'nullable|string', - 'durationOperator' => 'nullable|string', + 'suspensionType' => 'required|string', + 'duration' => 'required_if:suspensionType,on|nullable|integer', + ]; + } + + public function messages() + { + return [ + 'duration.required_if' => __('You must provide a duration if the suspension is temporary.') ]; } } diff --git a/app/Jobs/CleanBans.php b/app/Jobs/ProcessDueSuspensions.php similarity index 86% rename from app/Jobs/CleanBans.php rename to app/Jobs/ProcessDueSuspensions.php index 5a25994..c3d040d 100755 --- a/app/Jobs/CleanBans.php +++ b/app/Jobs/ProcessDueSuspensions.php @@ -30,7 +30,7 @@ use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\Log; -class CleanBans implements ShouldQueue +class ProcessDueSuspensions implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; @@ -52,15 +52,15 @@ class CleanBans implements ShouldQueue */ public function handle() { - Log::debug('Running automatic ban cleaner...'); + Log::debug('Running automatic suspension cleaner...'); $bans = Ban::all(); if (! is_null($bans)) { foreach ($this->bans as $ban) { $bannedUntil = Carbon::parse($ban->bannedUntil); - if ($bannedUntil->equalTo(now())) { - Log::debug('Deleted ban '.$ban->id.' belonging to '.$ban->user->name); + if ($bannedUntil->isToday()) { + Log::debug('Lifted expired suspension ID '.$ban->id.' for '.$ban->user->name); $ban->delete(); } } diff --git a/config/adminlte.php b/config/adminlte.php index 9e19fb8..6df80ce 100755 --- a/config/adminlte.php +++ b/config/adminlte.php @@ -611,5 +611,21 @@ return [ ], ], + [ + 'name' => 'BootstrapSwitch', + 'active' => true, + 'files' => [ + [ + 'type' => 'js', + 'asset' => false, + 'location' => 'https://cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/js/bootstrap4-toggle.min.js' + ], + [ + 'type' => 'css', + 'asset' => false, + 'location' => 'https://cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/css/bootstrap4-toggle.min.css' + ] + ] + ] ], ]; diff --git a/database/migrations/2021_07_20_094139_change_bans_table.php b/database/migrations/2021_07_20_094139_change_bans_table.php new file mode 100644 index 0000000..422ba10 --- /dev/null +++ b/database/migrations/2021_07_20_094139_change_bans_table.php @@ -0,0 +1,36 @@ +dropColumn('userAgent'); + $table->boolean('isPermanent')->default(false); + + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('bans', function (Blueprint $table) { + $table->dropColumn('isPermanent'); + $table->string('userAgent')->after('bannedUntil'); + }); + } +} diff --git a/resources/lang/en/messages.php b/resources/lang/en/messages.php index edcc8af..87f4b9c 100755 --- a/resources/lang/en/messages.php +++ b/resources/lang/en/messages.php @@ -411,14 +411,13 @@ return [ 'title' => ':name\'s profile', 'profile' => 'Profile', 'users' => 'Users', - 'account_banned' => 'Account banned', - 'account_banned_exp' => 'This user has been banned by the moderators.', - 'ban_confirm' => 'Please confirm that you want to ban this user account. You\'ll need to add a reason and expiration date to confirm this. Bans don\'t transfer to connected Minecraft networks (yet).', - 'leave_empty' => 'Leave empty for a permanent ban', + 'account_banned' => 'Account suspended', + 'account_banned_exp' => 'This user has been suspended by the admins.', + 'ban_confirm' => 'Please confirm that you want to suspend this account. You\'ll need to add a reason and expiration date to confirm this.', 'duration' => 'Duration', - 'p_duration' => 'Punishment duration', + 'p_duration' => 'Suspension duration', 'p_duration_exp' => 'e.g. Spamming', - 'ban' => 'Ban', + 'ban' => 'Suspend', 'terminate_notice' => 'You are about to terminate a staff member', 'terminate_notice_warning' => 'Terminating a staff member will remove their privileges on the team management site and Network. diff --git a/resources/views/dashboard/user/profile/displayprofile.blade.php b/resources/views/dashboard/user/profile/displayprofile.blade.php index a882abb..2d796a9 100755 --- a/resources/views/dashboard/user/profile/displayprofile.blade.php +++ b/resources/views/dashboard/user/profile/displayprofile.blade.php @@ -18,16 +18,16 @@ @section('content') - @if ($profile->user->isBanned()) + @if (is_array($suspensionInfo))
- {{__('messages.profile.account_banned')}} + {{__('messages.profile.account_banned')}} {{ ($suspensionInfo['isPermanent']) ? __('permanently.') : __('until :date.', ['date' => $suspensionInfo['bannedUntil']]) }}

{{__('messages.profile.account_banned_exp')}}

- {{$profile->user->bans->reason}} + {{$suspensionInfo['reason']}}

@@ -43,32 +43,33 @@
@csrf - - +
-
- -
- - -
-

{{__('messages.profile.leave_empty')}}

- + +
+ + +
+ +

{{ __('Temporary suspensions will be automatically lifted. The suspension note is visible to all users. Suspended users will not be able to login or register.') }}

+
+ - - - + @@ -334,13 +335,13 @@
@if (!$profile->user->isBanned()) -
+
@else
@method('DELETE') @csrf - +
@endif