From 0083a01d85c8bec75d690b4f0aca4c3d72bc1205 Mon Sep 17 00:00:00 2001 From: Graphictoria Date: Fri, 6 Jan 2023 20:57:15 -0500 Subject: [PATCH] Catalog changes and punishments. - Updated pagination to 35 assets per page in order to fit with newer card scaling. - Implemented the ability to go to traverse pages in the shop. - Allowed the CPU/Memory usage updater job to run when the site is under maintenance. - User punishments. - Revamped punishment notice page. - Created middleware to redirect to punishment notice page when a punishment is active. - Completed moderation status label on user admin/search pages. - Added routes for punishments. - Fixed user homepage button on user admin page. - Added punishments section on user admin page. - Removed legacy bans. - Prevent banned user thumbnails from being rendered. --- web/app/Console/Kernel.php | 2 +- .../Controllers/Api/CommentsController.php | 1 - .../Http/Controllers/Api/ShopController.php | 2 +- .../Controllers/Api/ThumbnailController.php | 15 ++-- .../Web/Auth/UserModerationController.php | 14 --- .../Controllers/Web/ModerationController.php | 28 ++++++ .../Controllers/Web/ProfileController.php | 3 + web/app/Http/Kernel.php | 10 +-- web/app/Http/Middleware/CheckBan.php | 31 ------- .../Middleware/UserPunishmentMiddleware.php | 52 +++++++++++ web/app/Models/Punishment.php | 84 ++++++++++++++++++ web/app/Models/PunishmentContext.php | 11 +++ web/app/Models/PunishmentType.php | 21 +++++ web/app/Models/User.php | 15 ++++ .../Components/Admin/ModerationStatus.php | 28 ++++++ .../2014_10_12_000000_create_users_table.php | 1 - ..._01_07_011658_create_punishments_table.php | 40 +++++++++ ...7_014022_create_punishment_types_table.php | 35 ++++++++ ...14948_create_punishment_contexts_table.php | 37 ++++++++ web/database/seeders/DatabaseSeeder.php | 3 +- web/database/seeders/PunishmentTypeSeeder.php | 27 ++++++ web/resources/js/components/Shop.js | 52 ++++++++--- .../admin/moderation-status.blade.php | 19 ++++ .../views/web/admin/useradmin.blade.php | 26 ++++-- .../views/web/admin/usersearch.blade.php | 2 +- .../views/web/auth/moderated.blade.php | 86 ++++++++++++------- web/routes/web.php | 20 +++-- 27 files changed, 545 insertions(+), 120 deletions(-) delete mode 100644 web/app/Http/Controllers/Web/Auth/UserModerationController.php create mode 100644 web/app/Http/Controllers/Web/ModerationController.php delete mode 100644 web/app/Http/Middleware/CheckBan.php create mode 100644 web/app/Http/Middleware/UserPunishmentMiddleware.php create mode 100644 web/app/Models/Punishment.php create mode 100644 web/app/Models/PunishmentContext.php create mode 100644 web/app/Models/PunishmentType.php create mode 100644 web/app/View/Components/Admin/ModerationStatus.php create mode 100644 web/database/migrations/2023_01_07_011658_create_punishments_table.php create mode 100644 web/database/migrations/2023_01_07_014022_create_punishment_types_table.php create mode 100644 web/database/migrations/2023_01_07_014948_create_punishment_contexts_table.php create mode 100644 web/database/seeders/PunishmentTypeSeeder.php create mode 100644 web/resources/views/components/admin/moderation-status.blade.php diff --git a/web/app/Console/Kernel.php b/web/app/Console/Kernel.php index 7bd625f..3258384 100644 --- a/web/app/Console/Kernel.php +++ b/web/app/Console/Kernel.php @@ -17,7 +17,7 @@ class Kernel extends ConsoleKernel */ protected function schedule(Schedule $schedule) { - $schedule->job(new UpdateUsageCounters)->everyMinute(); + $schedule->job(new UpdateUsageCounters)->everyMinute()->evenInMaintenanceMode(); } /** diff --git a/web/app/Http/Controllers/Api/CommentsController.php b/web/app/Http/Controllers/Api/CommentsController.php index b1cc2b7..eec55f6 100644 --- a/web/app/Http/Controllers/Api/CommentsController.php +++ b/web/app/Http/Controllers/Api/CommentsController.php @@ -46,7 +46,6 @@ class CommentsController extends Controller ]; foreach($comments as $comment) { - // TODO: XlXi: user profile link $poster = [ 'name' => $comment->user->username, 'thumbnail' => 'https://www.virtubrick.local/images/testing/headshot.png', diff --git a/web/app/Http/Controllers/Api/ShopController.php b/web/app/Http/Controllers/Api/ShopController.php index 5f02ccc..7619bf8 100644 --- a/web/app/Http/Controllers/Api/ShopController.php +++ b/web/app/Http/Controllers/Api/ShopController.php @@ -65,7 +65,7 @@ class ShopController extends Controller $assets = self::getAssets($valid['assetTypeId'], (isset($valid['gearGenreId']) ? $valid['gearGenreId'] : null)); $assets = $assets->orderByDesc('created_at') - ->paginate(30); + ->paginate(35); $data = []; foreach($assets as $asset) { diff --git a/web/app/Http/Controllers/Api/ThumbnailController.php b/web/app/Http/Controllers/Api/ThumbnailController.php index 92e3949..a251606 100644 --- a/web/app/Http/Controllers/Api/ThumbnailController.php +++ b/web/app/Http/Controllers/Api/ThumbnailController.php @@ -31,11 +31,10 @@ class ThumbnailController extends Controller private function userValidationRules() { - // TODO: Fail validation if user is moderated. return [ 'id' => [ 'required', - Rule::exists('App\Models\User', 'id') + Rule::exists('App\Models\User', 'id'), ], 'position' => ['sometimes', 'regex:/(Full|Bust)/i'], 'type' => 'regex:/(3D|2D)/i' @@ -55,7 +54,13 @@ class ThumbnailController extends Controller $valid['type'] = strtolower($valid['type']); if($renderType == 'User') { - if($valid['position'] == null) + if($model->hasActivePunishment() && $model->getPunishment()->isDeletion()) + { + $validator->errors()->add('id', 'User is moderated'); + return ValidationHelper::generateValidatorError($validator); + } + + if(!array_key_exists('position', $valid)) $valid['position'] = 'Full'; $valid['position'] = strtolower($valid['position']); @@ -109,9 +114,9 @@ class ThumbnailController extends Controller return $this->handleRender($request, 'Asset'); } - public function renderUser() + public function renderUser(Request $request) { - return handleRender($request, 'User'); + return $this->handleRender($request, 'User'); } public function tryAsset() diff --git a/web/app/Http/Controllers/Web/Auth/UserModerationController.php b/web/app/Http/Controllers/Web/Auth/UserModerationController.php deleted file mode 100644 index e37a7a6..0000000 --- a/web/app/Http/Controllers/Web/Auth/UserModerationController.php +++ /dev/null @@ -1,14 +0,0 @@ -with('punishment', Auth::user()->getPunishment()); + } + + public function reactivate(Request $request) + { + $punishment = Auth::user()->getPunishment(); + if(!$punishment || !$punishment->expired()) + return redirect()->back(); + + $punishment->active = false; + $punishment->save(); + + return redirect()->back(); + } +} diff --git a/web/app/Http/Controllers/Web/ProfileController.php b/web/app/Http/Controllers/Web/ProfileController.php index f33b60a..c649ea5 100644 --- a/web/app/Http/Controllers/Web/ProfileController.php +++ b/web/app/Http/Controllers/Web/ProfileController.php @@ -11,6 +11,9 @@ class ProfileController extends Controller { protected function index(Request $request, User $user) { + if($user->hasActivePunishment() && $user->getPunishment()->isDeletion()) + abort(404); + return view('web.user.profile')->with([ 'title' => sprintf('Profile of %s', $user->username), 'user' => $user diff --git a/web/app/Http/Kernel.php b/web/app/Http/Kernel.php index 94403a3..e07d5f9 100644 --- a/web/app/Http/Kernel.php +++ b/web/app/Http/Kernel.php @@ -25,7 +25,7 @@ class Kernel extends HttpKernel \Illuminate\View\Middleware\ShareErrorsFromSession::class, \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \App\Http\Middleware\TrimStrings::class, - \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, + \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class ]; /** @@ -43,14 +43,15 @@ class Kernel extends HttpKernel // XlXi: Yeah no, the double session protector was stupid. //\App\Http\Middleware\DoubleSessionProtector::class, // Prevents DDoS attacks. \App\Http\Middleware\DailyReward::class, - \App\Http\Middleware\LastSeenMiddleware::class + \App\Http\Middleware\LastSeenMiddleware::class, + \App\Http\Middleware\UserPunishmentMiddleware::class ], 'api' => [ - \App\Http\Middleware\PreventRequestsDuringMaintenance::class, - // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, + + \App\Http\Middleware\UserPunishmentMiddleware::class ], ]; @@ -74,7 +75,6 @@ class Kernel extends HttpKernel 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 'roleset' => \App\Http\Middleware\Roleset::class, - 'banned' => \App\Http\Middleware\CheckBan::class, 'lastseen' => \App\Http\Middleware\LastSeenMiddleware::class, 'csrf' => \App\Http\Middleware\VerifyCsrfToken::class, ]; diff --git a/web/app/Http/Middleware/CheckBan.php b/web/app/Http/Middleware/CheckBan.php deleted file mode 100644 index df2ad1c..0000000 --- a/web/app/Http/Middleware/CheckBan.php +++ /dev/null @@ -1,31 +0,0 @@ -banId != null) { - if($request->route()->getName() != 'moderation.notice' && $request->route()->getName() != 'logout') { - return redirect() - ->to(route('moderation.notice', [], 302)); - } - } else { - return redirect('/', 302); - } - - return $next($request); - } -} diff --git a/web/app/Http/Middleware/UserPunishmentMiddleware.php b/web/app/Http/Middleware/UserPunishmentMiddleware.php new file mode 100644 index 0000000..2db0ade --- /dev/null +++ b/web/app/Http/Middleware/UserPunishmentMiddleware.php @@ -0,0 +1,52 @@ +route()->getName(), 'punishment.'); + if(Auth::user() && Auth::user()->hasActivePunishment()) + { + if($isPunishmentRoute || $request->route()->getName() == 'auth.logout') + return $next($request); + + if(in_array('api', $request->route()->middleware())) + { + if($request->route()->getName() == 'content') // cdn.virtubrick.net + return $next($request); + + return response(['errors' => [['code' => 0, 'message' => 'User is moderated']]], 403) + ->header('Cache-Control', 'private') + ->header('Content-Type', 'application/json; charset=utf-8'); + } + + // Not an API route. + if(!$isPunishmentRoute) + return redirect()->route('punishment.notice', ['ReturnUrl' => url()->full()]); + } + elseif($isPunishmentRoute) + { + $returnUrl = $request->input('ReturnUrl'); + + if(!$returnUrl) + $returnUrl = '/'; + + return redirect($returnUrl); + } + + return $next($request); + } +} diff --git a/web/app/Models/Punishment.php b/web/app/Models/Punishment.php new file mode 100644 index 0000000..9cc3281 --- /dev/null +++ b/web/app/Models/Punishment.php @@ -0,0 +1,84 @@ + + */ + protected $casts = [ + 'expiration' => 'datetime', + 'created_at' => 'datetime', + 'updated_at' => 'datetime' + ]; + + public function punishment_type() + { + return $this->belongsTo(PunishmentType::class, 'punishment_type_id'); + } + + public function user() + { + return $this->belongsTo(User::class, 'user_id'); + } + + public function moderator() + { + return $this->belongsTo(User::class, 'moderator_id'); + } + + public function pardoner() + { + return $this->belongsTo(User::class, 'pardoner_id'); + } + + public function context() + { + return $this->hasMany(PunishmentContext::class, 'punishment_id'); + } + + public function expired() + { + if($this->user->hasRoleset('Owner')) + return true; + + if(!$this->expiration) + return false; + + return !$this->isDeletion() && Carbon::now()->greaterThan($this->expiration); + } + + public function isDeletion() + { + return $this->punishment_type->time === null; + } + + public function reviewed() + { + return $this->created_at->isoFormat('lll'); + } + + public function expirationStr() + { + if(!$this->expiration) + return 'Never'; + + return $this->created_at->isoFormat('lll'); + } + + public static function activeFor($userId) + { + return self::where('user_id', $userId) + ->where('active', true) + ->orderByDesc('id'); + } +} diff --git a/web/app/Models/PunishmentContext.php b/web/app/Models/PunishmentContext.php new file mode 100644 index 0000000..128b10c --- /dev/null +++ b/web/app/Models/PunishmentContext.php @@ -0,0 +1,11 @@ +id)->exists(); + } + + public function getPunishment() + { + return Punishment::activeFor($this->id)->first(); + } + + public function punishments() + { + return $this->hasMany(Punishment::class, 'user_id'); + } + public function _hasRolesetInternal($roleName) { $roleset = Roleset::where('Name', $roleName)->first(); diff --git a/web/app/View/Components/Admin/ModerationStatus.php b/web/app/View/Components/Admin/ModerationStatus.php new file mode 100644 index 0000000..047eb7b --- /dev/null +++ b/web/app/View/Components/Admin/ModerationStatus.php @@ -0,0 +1,28 @@ +dateTime('email_verified_at')->nullable(); $table->string('password'); $table->rememberToken(); - $table->unsignedBigInteger('banId')->nullable(); $table->string('biography')->nullable(); diff --git a/web/database/migrations/2023_01_07_011658_create_punishments_table.php b/web/database/migrations/2023_01_07_011658_create_punishments_table.php new file mode 100644 index 0000000..036a6bc --- /dev/null +++ b/web/database/migrations/2023_01_07_011658_create_punishments_table.php @@ -0,0 +1,40 @@ +id(); + + $table->unsignedTinyInteger('punishment_type_id'); + $table->boolean('active'); + $table->string('user_note'); + $table->unsignedBigInteger('user_id'); + $table->unsignedBigInteger('moderator_id'); + $table->unsignedBigInteger('pardoner_id')->nullable(); + $table->timestamp('expiration')->nullable(); + + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('punishments'); + } +}; diff --git a/web/database/migrations/2023_01_07_014022_create_punishment_types_table.php b/web/database/migrations/2023_01_07_014022_create_punishment_types_table.php new file mode 100644 index 0000000..fe8a09d --- /dev/null +++ b/web/database/migrations/2023_01_07_014022_create_punishment_types_table.php @@ -0,0 +1,35 @@ +id(); + + $table->string('label'); + $table->integer('time')->nullable(); + + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('punishment_types'); + } +}; diff --git a/web/database/migrations/2023_01_07_014948_create_punishment_contexts_table.php b/web/database/migrations/2023_01_07_014948_create_punishment_contexts_table.php new file mode 100644 index 0000000..7d274e7 --- /dev/null +++ b/web/database/migrations/2023_01_07_014948_create_punishment_contexts_table.php @@ -0,0 +1,37 @@ +id(); + + $table->unsignedBigInteger('punishment_id'); + $table->string('user_note'); + $table->longText('description')->nullable(); + $table->string('content_hash')->nullable()->comment('Will display an image from the CDN.'); + + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('punishment_contexts'); + } +}; diff --git a/web/database/seeders/DatabaseSeeder.php b/web/database/seeders/DatabaseSeeder.php index 92226c6..96d6c36 100644 --- a/web/database/seeders/DatabaseSeeder.php +++ b/web/database/seeders/DatabaseSeeder.php @@ -18,7 +18,8 @@ class DatabaseSeeder extends Seeder WebConfigurationSeeder::class, AssetTypeSeeder::class, UsageCounterSeeder::class, - RolesetSeeder::class + RolesetSeeder::class, + PunishmentTypeSeeder::class //FFlagSeeder::class ]); } diff --git a/web/database/seeders/PunishmentTypeSeeder.php b/web/database/seeders/PunishmentTypeSeeder.php new file mode 100644 index 0000000..66d1d86 --- /dev/null +++ b/web/database/seeders/PunishmentTypeSeeder.php @@ -0,0 +1,27 @@ + 'Reminder', 'time' => 0]); + PunishmentType::create(['label' => 'Warning', 'time' => 0]); + PunishmentType::create(['label' => 'Banned for 1 Day', 'time' => 1]); + PunishmentType::create(['label' => 'Banned for 3 Days', 'time' => 3]); + PunishmentType::create(['label' => 'Banned for 7 Days', 'time' => 7]); + PunishmentType::create(['label' => 'Banned for 14 Days', 'time' => 14]); + PunishmentType::create(['label' => 'Account Deleted']); + } +} diff --git a/web/resources/js/components/Shop.js b/web/resources/js/components/Shop.js index 1b3aca9..91bd98a 100644 --- a/web/resources/js/components/Shop.js +++ b/web/resources/js/components/Shop.js @@ -150,7 +150,9 @@ class ShopCategoryButton extends Component { } handleClick() { - this.props.navigateCategory(this.props.id, this.data); + this.props.setPage(1, true, () => { + this.props.navigateCategory(this.props.id, this.data); + }); } render() { @@ -177,7 +179,7 @@ class ShopCategories extends Component { return (
Category
- +
    { Object.keys(shopCategories).map((categoryName, index) => @@ -185,10 +187,10 @@ class ShopCategories extends Component { { categoryName }
      -
    • +
    • { shopCategories[categoryName].map(({label, assetTypeId, gearGenreId}, index) => -
    • +
    • ) }
    @@ -271,10 +273,13 @@ class Shop extends Component { pageLoaded: true, pageNumber: null, pageCount: null, - error: false + error: false, + dataMem: false }; this.navigateCategory = this.navigateCategory.bind(this); + this.incrementPage = this.incrementPage.bind(this); + this.setPage = this.setPage.bind(this); } getCategoryAssetTypeIds(categoryName) { @@ -304,14 +309,23 @@ class Shop extends Component { return assetType; } - navigateCategory(categoryId, data) { - this.setState({selectedCategoryId: categoryId, pageLoaded: false}); + navigateCategory(categoryId, dataraw) { + if(this.state.pageLoaded == false) return; + + this.setState({selectedCategoryId: categoryId, dataMem: dataraw, pageLoaded: false}); let url = buildGenericApiUrl('api', 'shop/v1/list-json'); + + if (this.state.pageNumber == null || this.state.pageNumber == 1) + this.setState({pageNumber: 1}); + let paramIterator = 0; + let data = {...dataraw, page: this.state.pageNumber}; Object.keys(data).filter(key => { if (key == 'label') return false; + else if (key == 'page' && (data[key] == null || data[key] == 1)) + return false; return true; }).map(key => { url += ((paramIterator++ == 0 ? '?' : '&') + `${key}=${data[key]}`); @@ -321,7 +335,7 @@ class Shop extends Component { .then(res => { const items = res.data; - this.setState({ pageItems: items.data, pageCount: items.pages, pageNumber: 1, pageLoaded: true, error: false }); + this.setState({ pageItems: items.data, pageCount: items.pages, pageLoaded: true, error: false }); }).catch(err => { const data = err.response.data; @@ -334,6 +348,22 @@ class Shop extends Component { }); } + incrementPage(amount) { + this.setPage(this.state.pageNumber + amount); + } + + setPage(page, bypass = false, callback) { + if(!bypass && this.state.pageLoaded == false) return; + + this.setState({pageNumber: page}, () => { + if(callback) + callback(); + + if(!bypass) + this.navigateCategory(this.state.selectedCategoryId, this.state.dataMem); + }); + } + render() { return (
    @@ -351,7 +381,7 @@ class Shop extends Component {
    - +
    @@ -386,7 +416,7 @@ class Shop extends Component { this.state.pageCount > 1 ?
    • - +
    • Page  @@ -394,7 +424,7 @@ class Shop extends Component {  of { this.state.pageCount || '???' }
    • - +
    : diff --git a/web/resources/views/components/admin/moderation-status.blade.php b/web/resources/views/components/admin/moderation-status.blade.php new file mode 100644 index 0000000..340a744 --- /dev/null +++ b/web/resources/views/components/admin/moderation-status.blade.php @@ -0,0 +1,19 @@ +@props([ + 'user' +]) + +@php + $color = 'text-'; + $label = 'Unknown'; + if($user->hasActivePunishment()) + { + $color .= 'danger'; + $label = $user->getPunishment()->punishment_type->label; + } + else + { + $color .= 'success'; + $label = 'OK'; + } +@endphp +

    {{ $label }}

    \ No newline at end of file diff --git a/web/resources/views/web/admin/useradmin.blade.php b/web/resources/views/web/admin/useradmin.blade.php index bf5d69c..4f6a77f 100644 --- a/web/resources/views/web/admin/useradmin.blade.php +++ b/web/resources/views/web/admin/useradmin.blade.php @@ -61,7 +61,7 @@ @endif {{ $user->username }} TODO - OK (TODO) + @@ -74,7 +74,7 @@
    @@ -90,16 +90,24 @@ Moderator Created Expiration + Acknowledged - - 1 - 1 day, perm, etc... - Joe - 1/2/3 4:5 6 - 1/2/3 4:5 6 - + @foreach($user->punishments as $punishment) + + {{ $punishment->id }} + {{ $punishment->punishment_type->label }} + + + + + + {{ $punishment->reviewed() }} + {{ $punishment->expirationStr() }} + {{ $punishment->active ? 'No' : 'Yes' }} + + @endforeach
    diff --git a/web/resources/views/web/admin/usersearch.blade.php b/web/resources/views/web/admin/usersearch.blade.php index 3c8ef6c..0ac3cfb 100644 --- a/web/resources/views/web/admin/usersearch.blade.php +++ b/web/resources/views/web/admin/usersearch.blade.php @@ -56,7 +56,7 @@ {{ $user->id }} {{ Auth::user()->hasRoleset('Owner') ? $user->email : $user->getCensoredEmail() }} -

    OK (TODO)

    + @if($rolesetCount > 0) @php diff --git a/web/resources/views/web/auth/moderated.blade.php b/web/resources/views/web/auth/moderated.blade.php index ef7e70c..027a8fe 100644 --- a/web/resources/views/web/auth/moderated.blade.php +++ b/web/resources/views/web/auth/moderated.blade.php @@ -1,42 +1,62 @@ -@php - $noFooter = true; - $noNav = true; -@endphp - @extends('layouts.app') - -@section('title', 'Moderation Notice') +@section('theme', 'light') +@nonav +@nofooter @section('content')
    - - - MODERATION NOTICE - - -
    -

    Your account has been suspended for violating our Terms of Service.

    -
    -

    Suspention Date: 5/6/2022 9:35 PM

    -

    Note: testing

    -
    +
    +

    {{ $punishment->punishment_type->label }}

    +

    + Your account has been {{ $punishment->isDeletion() ? 'closed ' : 'temporarily restricted' }} for violating our Terms of Service. + @if(!$punishment->isDeletion()) + Your account will be terminated if you do not abide by the rules. + @endif +

    + +
    +

    Reviewed: {{ $punishment->reviewed() }}

    +

    Moderator Note: {{ $punishment->user_note }}

    +
    + + @foreach($punishment->context as $context) +
    +

    Reason: {{ $context->user_note }}

    + @if($context->description) +

    Offensive Item: {{ $context->description }}

    + @endif + @if($context->content_hash) + + @endif
    - - -

    By checking the "I Agree" checkbox below, you agree to abide by {{ config('app.name') }}'s Terms of Service. Your account will be permantently suspended if you continue breaking the Terms of Service.

    -
    -
    - - -
    - -
    + @endforeach + +
    + @if($punishment->expired()) +

    By checking the "I Agree" checkbox below, you agree to abide by {{ config('app.name') }}'s Terms of Service.

    +
    + @csrf +
    + + +
    + +
    + + @elseif(!$punishment->isDeletion()) +

    You will be able to reactivate your account in {{ $punishment->expiration->diffForHumans(['syntax' => Carbon\CarbonInterface::DIFF_ABSOLUTE]) }}.

    + @endif + + Logout -

    You will be able to reactivate your account in 0 Seconds.

    If you believe you have been unfairly moderated, please contact us at contact us at support@virtubrick.net and we'll be happy to help.

    - - +
    +
    @endsection diff --git a/web/routes/web.php b/web/routes/web.php index 2c870de..9b4dc80 100644 --- a/web/routes/web.php +++ b/web/routes/web.php @@ -74,13 +74,11 @@ Route::group(['as' => 'admin.', 'prefix' => 'admin'], function() { }); Route::group(['as' => 'auth.', 'namespace' => 'Auth'], function() { - Route::group(['as' => 'protection.', 'prefix' => 'request-blocked'], function() { - Route::get('/', 'DoubleSessionBlockController@index')->name('index'); - Route::post('/', 'DoubleSessionBlockController@store')->name('bypass'); - }); + //Route::group(['as' => 'protection.', 'prefix' => 'request-blocked'], function() { + // Route::get('/', 'DoubleSessionBlockController@index')->name('index'); + // Route::post('/', 'DoubleSessionBlockController@store')->name('bypass'); + //}); - Route::get('/moderation-notice', 'UserModerationController@index')->middleware(['auth', 'banned'])->name('moderation.notice'); - Route::middleware('guest')->group(function () { Route::group(['as' => 'register.', 'prefix' => 'register'], function() { Route::get('/', 'RegisteredUserController@index')->name('index'); @@ -120,6 +118,12 @@ Route::group(['as' => 'auth.', 'namespace' => 'Auth'], function() { }); }); +Route::group(['as' => 'punishment.', 'prefix' => 'membership'], function() { + Route::middleware('auth')->group(function () { + Route::get('/not-approved', 'ModerationController@notice')->name('notice'); + Route::post('/not-approved', 'ModerationController@reactivate')->name('reactivate'); + }); +}); Route::withoutMiddleware(['csrf'])->group(function () { Route::group(['as' => 'client.'], function() { @@ -129,4 +133,8 @@ Route::withoutMiddleware(['csrf'])->group(function () { Route::post('/PlaceLauncher', 'ClientGameController@placeLauncher')->name('placelauncher'); }); }); +}); + +Route::fallback(function() { + return view('errors.404'); }); \ No newline at end of file