🆙 Final fix delete storage link to fix news_images and logs 🆙

This commit is contained in:
Remco
2026-01-07 20:29:24 +01:00
parent 65ea6c167f
commit acf2d7e661
447 changed files with 208 additions and 66965 deletions
@@ -1,29 +0,0 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Resources\OnlineUserCountResource;
use App\Http\Resources\OnlineUsersResource;
use App\Http\Resources\UserResource;
use App\Services\User\UserApiService;
class HotelApiController extends Controller
{
public function __construct(private readonly UserApiService $userApiService) {}
public function fetchUser(string $username, array $columns = ['username', 'motto', 'look']): UserResource
{
return new UserResource($this->userApiService->fetchUser($username, $columns));
}
public function onlineUsers($columns = ['username', 'motto', 'look'], bool $randomOrder = true): OnlineUsersResource
{
return new OnlineUsersResource($this->userApiService->onlineUsers($columns, $randomOrder));
}
public function onlineUserCount(): OnlineUserCountResource
{
return new OnlineUserCountResource($this->userApiService->onlineUserCount());
}
}
@@ -1,46 +0,0 @@
<?php
namespace App\Http\Controllers\Articles;
use App\Http\Controllers\Controller;
use App\Models\Articles\WebsiteArticle;
use App\Services\Articles\ArticleService;
use App\Services\Articles\ReactionService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
class ArticleController extends Controller
{
public function __construct(
private readonly ArticleService $articlesService,
private readonly ReactionService $reactionService,
) {}
public function index(): View
{
$articles = $this->articlesService->getArticles(true);
return view('community.articles', [
'articles' => $articles,
]);
}
public function show(WebsiteArticle $article): View
{
return view('community.article', [
'article' => $article,
'otherArticles' => WebsiteArticle::whereNot('slug', $article->slug)->latest('id')->take(15)->get(),
'myReactions' => Auth::check() ? $article->reactions->where('user_id', Auth::id())->pluck('reaction') : [],
'articleReactions' => collect($article->reactions)->groupBy('reaction', true),
]);
}
public function toggleReaction(WebsiteArticle $article, Request $request): JsonResponse
{
$response = $this->reactionService->toggleReaction($article, Auth::user(), $request);
return response()->json($response);
}
}
@@ -1,29 +0,0 @@
<?php
namespace App\Http\Controllers\Articles;
use App\Http\Controllers\Controller;
use App\Http\Requests\ArticleCommentFormRequest;
use App\Models\Articles\WebsiteArticle;
use App\Models\Articles\WebsiteArticleComment;
use App\Services\Articles\CommentService;
use Illuminate\Http\RedirectResponse;
class WebsiteArticleCommentsController extends Controller
{
public function __construct(public readonly CommentService $commentService) {}
public function store(WebsiteArticle $article, ArticleCommentFormRequest $request): RedirectResponse
{
$this->commentService->store($request->get('comment'), $article);
return back()->with('success', __('You comment has been posted!'));
}
public function destroy(WebsiteArticleComment $comment): RedirectResponse
{
$this->commentService->destroy($comment);
return back()->with('success', __('You comment has been deleted!'));
}
}
@@ -1,124 +0,0 @@
<?php
namespace App\Http\Controllers\Badge;
use App\Actions\SendCurrency;
use App\Enums\CurrencyTypes;
use App\Http\Controllers\Controller;
use App\Models\WebsiteDrawBadge;
use App\Services\SettingsService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class BadgeController extends Controller
{
private const int BADGE_WIDTH = 40;
private const int BADGE_HEIGHT = 40;
private const int MAX_BADGE_SIZE_BYTES = 40960;
public function show(SettingsService $settingsService)
{
$cost = (int) $settingsService->getOrDefault('drawbadge_currency_value', 150);
$currencyType = $settingsService->getOrDefault('drawbadge_currency_type', 'credits');
$badgesPath = $settingsService->getOrDefault('badge_path_filesystem');
$folderError = false;
$errorMessage = '';
if ($badgesPath === '' || $badgesPath === '0') {
$folderError = true;
$errorMessage = 'Badges path not configured.';
} elseif (! file_exists($badgesPath)) {
$folderError = true;
$errorMessage = 'Badges path not configured.';
} elseif (! is_writable($badgesPath)) {
$folderError = true;
$errorMessage = 'Badges folder does not have write access.';
}
return view('draw-badge', ['cost' => $cost, 'currencyType' => $currencyType, 'folderError' => $folderError, 'errorMessage' => $errorMessage]);
}
public function buy(Request $request, SendCurrency $sendCurrency, SettingsService $settingsService)
{
$user = Auth::user();
$cost = (int) $settingsService->getOrDefault('drawbadge_currency_value', 150);
$currencyType = $settingsService->getOrDefault('drawbadge_currency_type', 'credits');
$currentAmount = match ($currencyType) {
'credits' => $user->credits ?? 0,
'duckets' => $user->currencies()->where('type', CurrencyTypes::Duckets)->value('amount') ?? 0,
'diamonds' => $user->currencies()->where('type', CurrencyTypes::Diamonds)->value('amount') ?? 0,
'points' => $user->currencies()->where('type', CurrencyTypes::Points)->value('amount') ?? 0,
default => 0,
};
if ($currentAmount < $cost) {
return response()->json(['success' => false, 'message' => 'Insufficient ' . $currencyType . '.'], 400);
}
$result = $sendCurrency->execute($user, $currencyType, -$cost);
if ($result === false) {
return response()->json(['success' => false, 'message' => 'Failed to deduct ' . $currencyType . '.'], 500);
}
$badgeData = $request->input('badge_data');
if (! $badgeData) {
return response()->json(['success' => false, 'message' => 'No badge data provided.'], 400);
}
$badgeData = preg_replace('#^data:image/\w+;base64,#i', '', (string) $badgeData);
$decoded = base64_decode((string) $badgeData, true);
if ($decoded === false) {
return response()->json(['success' => false, 'message' => 'Invalid base64 data.'], 400);
}
$info = @getimagesizefromstring($decoded);
if (
$info === false ||
$info['mime'] !== 'image/gif' ||
$info[0] !== self::BADGE_WIDTH ||
$info[1] !== self::BADGE_HEIGHT
) {
return response()->json(['success' => false, 'message' => 'Invalid GIF image or incorrect dimensions.'], 400);
}
if (strlen($decoded) > self::MAX_BADGE_SIZE_BYTES) {
return response()->json(['success' => false, 'message' => 'Image file too large.'], 400);
}
$image = @imagecreatefromstring($decoded);
if ($image === false) {
return response()->json(['success' => false, 'message' => 'Failed to process image.'], 400);
}
$badgesPath = $settingsService->getOrDefault('badge_path_filesystem');
if ($badgesPath === '' || $badgesPath === '0') {
return response()->json(['success' => false, 'message' => 'Badges path not configured.'], 500);
}
$filename = $user->id . '_' . time() . '.gif';
$fullPath = rtrim($badgesPath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $filename;
if (! imagegif($image, $fullPath)) {
return response()->json(['success' => false, 'message' => 'Failed to save badge file.'], 500);
}
$baseUrl = $settingsService->getOrDefault('badges_path', '/badges/');
$badgeUrl = rtrim($baseUrl, '/') . '/' . $filename;
WebsiteDrawBadge::create([
'user_id' => $user->id,
'badge_path' => $fullPath,
'badge_url' => $badgeUrl,
'badge_name' => $request->input('badge_name'),
'badge_desc' => $request->input('badge_description'),
]);
return response()->json(['success' => true, 'badge_path_filesystem' => $fullPath]);
}
}
@@ -1,21 +0,0 @@
<?php
namespace App\Http\Controllers\Client;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
class FlashController extends Controller
{
public function __invoke(): View
{
Auth::user()->update([
'ip_current' => request()->ip(),
]);
return view('client.flash', [
'sso' => Auth::user()->ssoTicket(),
]);
}
}
@@ -1,21 +0,0 @@
<?php
namespace App\Http\Controllers\Client;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
class NitroController extends Controller
{
public function __invoke(): View
{
Auth::user()->update([
'ip_current' => request()->ip(),
]);
return view('client.nitro', [
'sso' => Auth::user()->ssoTicket(),
]);
}
}
@@ -1,56 +0,0 @@
<?php
namespace App\Http\Controllers\Community;
use App\Http\Controllers\Controller;
use App\Models\Game\Player\UserCurrency;
use App\Models\Game\Player\UserSetting;
use App\Models\User;
use App\Services\Community\StaffService;
use Illuminate\View\View;
class LeaderboardController extends Controller
{
protected array $staffIds = [];
public function __construct(private readonly StaffService $staffService)
{
$this->staffIds = $this->staffService->fetchEmployeeIds();
}
public function __invoke(): View
{
$topCredits = User::query()
->whereNotIn('id', $this->staffIds)
->orderByDesc('credits')
->take(9)
->get();
$getUserCurrency = fn ($type) => UserCurrency::query()
->whereNotIn('user_id', $this->staffIds)
->where('type', $type)
->orderByDesc('amount')
->take(9)
->with('user:id,username,look')
->get();
return view('leaderboard', [
'credits' => $topCredits,
'duckets' => $getUserCurrency(0),
'diamonds' => $getUserCurrency(5),
'mostOnline' => $this->retrieveSettings('online_time'),
'respectsReceived' => $this->retrieveSettings('respects_received'),
'achievementScores' => $this->retrieveSettings('achievement_score'),
]);
}
private function retrieveSettings($column)
{
return UserSetting::select('user_id', $column)
->whereNotIn('user_id', $this->staffIds)
->orderByDesc($column)
->take(9)
->with('user:id,username,look')
->get();
}
}
@@ -1,19 +0,0 @@
<?php
namespace App\Http\Controllers\Community;
use App\Http\Controllers\Controller;
use App\Services\Community\CameraService;
use Illuminate\View\View;
class PhotosController extends Controller
{
public function __construct(private readonly CameraService $cameraService) {}
public function __invoke(): View
{
return view('community.photos', [
'photos' => $this->cameraService->fetchPhotos(true),
]);
}
}
@@ -1,17 +0,0 @@
<?php
namespace App\Http\Controllers\Community;
use App\Http\Controllers\Controller;
use App\Models\Game\Room;
use Illuminate\View\View;
class RoomController extends Controller
{
public function __invoke(Room $room): View
{
return view('room.index', [
'room' => $room->load('owner:id,username,look'),
]);
}
}
@@ -1,47 +0,0 @@
<?php
namespace App\Http\Controllers\Community\Staff;
use App\Http\Controllers\Controller;
use App\Http\Requests\StaffApplicationFormRequest;
use App\Models\Community\Staff\WebsiteOpenPosition;
use App\Services\Community\StaffApplicationService;
use Illuminate\Http\RedirectResponse;
class StaffApplicationsController extends Controller
{
public function __construct(private readonly StaffApplicationService $staffApplicationService) {}
public function index()
{
return view('community.staff-applications', [
'positions' => $this->staffApplicationService->fetchOpenPositions(),
]);
}
public function show(WebsiteOpenPosition $position)
{
return view('community.staff-applications-apply', [
'position' => $position->load('permission'),
]);
}
public function store(WebsiteOpenPosition $position, StaffApplicationFormRequest $request): RedirectResponse
{
if ($this->staffApplicationService->hasUserAppliedForPosition($request->user(), $position->permission->id)) {
return back()->withErrors([
'message' => __('You have already applied for this position.'),
]);
}
if (! $this->staffApplicationService->isPositionOpenForApplication($position)) {
return back()->withErrors([
'message' => __('You cannot apply for this position.'),
]);
}
$this->staffApplicationService->storeApplication($request->user(), $position->permission->id, $request->input('content'));
return to_route('staff-applications.index')->with('success', __('Your application has been submitted!'));
}
}
@@ -1,21 +0,0 @@
<?php
namespace App\Http\Controllers\Community\Staff;
use App\Http\Controllers\Controller;
use App\Services\Community\StaffService;
use Illuminate\View\View;
class StaffController extends Controller
{
public function __construct(private readonly StaffService $staffService) {}
public function __invoke(): View
{
$employees = $this->staffService->fetchStaffPositions();
return view('community.staff', [
'employees' => $employees,
]);
}
}
@@ -1,21 +0,0 @@
<?php
namespace App\Http\Controllers\Community\Staff;
use App\Http\Controllers\Controller;
use App\Services\Community\TeamService;
use Illuminate\View\View;
class WebsiteTeamsController extends Controller
{
public function __construct(private readonly TeamService $teamService) {}
public function __invoke(): View
{
$employees = $this->teamService->fetchTeams();
return view('community.teams', [
'employees' => $employees,
]);
}
}
@@ -1,81 +0,0 @@
<?php
namespace App\Http\Controllers\Community;
use App\Http\Controllers\Controller;
use App\Http\Requests\RareSearchFormRequest;
use App\Models\Community\RareValue\WebsiteRareValue;
use App\Models\Community\RareValue\WebsiteRareValueCategory;
use App\Models\Game\Furniture\Item;
use App\Services\Community\RareValues\RareValueCategoriesService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Cache;
use Illuminate\View\View;
class WebsiteRareValuesController extends Controller
{
public function __construct(private readonly RareValueCategoriesService $valueCategoriesService) {}
public function index(): View
{
return view('rare-values', [
'categories' => $this->valueCategoriesService->fetchCategoriesByPriority(),
'categoriesNav' => $this->valueCategoriesService->fetchAllCategories(),
]);
}
public function category(int $id): View|RedirectResponse
{
$category = $this->valueCategoriesService->fetchCategoryById($id);
if (! $category instanceof \App\Models\Community\RareValue\WebsiteRareValueCategory) {
return back()->withErrors([
'message' => __('The entered category does not exist'),
]);
}
return view('rare-values', [
'categories' => $category,
'categoriesNav' => $this->valueCategoriesService->fetchAllCategories(),
]);
}
public function search(RareSearchFormRequest $request): View|RedirectResponse
{
$searchTerm = $request->input('search');
$categories = $this->valueCategoriesService->searchCategories($searchTerm);
if ($categories->isEmpty()) {
return back()->withErrors([
'message' => __('It seems like there were no rares matching your search input'),
]);
}
return view('rare-values', [
'categories' => $categories,
'categoriesNav' => WebsiteRareValueCategory::has('furniture')->get(),
]);
}
public function value(WebsiteRareValue $value): View
{
$items = Item::with(['user:id,username,look'])
->where('item_id', $value->item_id)
->get();
$itemsPerUser = $items->groupBy('user_id')->map(fn ($group) => [
'user' => $group->first()->user,
'item_count' => $group->count(),
]);
if ((bool) setting('enable_caching')) {
Cache::remember('allItems_' . $value->id, setting('cache_timer'), fn () => $items);
}
return view('value', [
'value' => $value,
'items' => $itemsPerUser,
]);
}
}
@@ -1,12 +0,0 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController
{
use AuthorizesRequests, ValidatesRequests;
}
@@ -1,16 +0,0 @@
<?php
namespace App\Http\Controllers\Help;
use App\Http\Controllers\Controller;
use App\Models\Help\WebsiteHelpCenterCategory;
class HelpCenterController extends Controller
{
public function __invoke()
{
return view('help-center.index', [
'categories' => WebsiteHelpCenterCategory::orderBy('position')->get(),
]);
}
}
@@ -1,120 +0,0 @@
<?php
namespace App\Http\Controllers\Help;
use App\Http\Controllers\Controller;
use App\Http\Requests\WebsiteTicketFormRequest;
use App\Models\Help\WebsiteHelpCenterCategory;
use App\Models\Help\WebsiteHelpCenterTicket;
use Illuminate\Support\Facades\Auth;
class TicketController extends Controller
{
public function index()
{
if (hasPermission('manage_website_tickets') === '' || hasPermission('manage_website_tickets') === '0') {
return back()->with([
'message' => __('You cannot access this page'),
]);
}
return view('help-center.tickets.index', [
'tickets' => WebsiteHelpCenterTicket::orderBy('open')->with('user:id,username')->paginate(15),
]);
}
public function create()
{
return view('help-center.tickets.create', [
'categories' => WebsiteHelpCenterCategory::get(),
'openTickets' => WebsiteHelpCenterTicket::where('open', true)->where('user_id', Auth::id())->get(),
]);
}
public function store(WebsiteTicketFormRequest $request)
{
Auth::user()->tickets()->create($request->validated());
return back()->with('success', __('Ticket submitted!'));
}
public function edit(WebsiteHelpCenterTicket $ticket)
{
if (! $ticket->canManageTicket()) {
return back()->with([
'message' => __('You cannot manage others tickets.'),
]);
}
$ticket->load([
'user:id,username,look',
'category',
'replies.user:id,username,look',
]);
return view('help-center.tickets.edit', [
'ticket' => $ticket,
'categories' => WebsiteHelpCenterCategory::get(),
'openTickets' => WebsiteHelpCenterTicket::where('open', true)->where('id', '!=', $ticket->id)->where('user_id', Auth::id())->get(),
]);
}
public function update(WebsiteHelpCenterTicket $ticket, WebsiteTicketFormRequest $request)
{
if (! $ticket->canManageTicket()) {
return back()->with([
'message' => __('You cannot manage others tickets.'),
]);
}
$ticket->update($request->validated());
return to_route('help-center.ticket.show', $ticket)->with('success', __('Ticket updated!'));
}
public function show(WebsiteHelpCenterTicket $ticket)
{
if (! $ticket->canManageTicket()) {
return back()->with([
'message' => __('You cannot view others tickets.'),
]);
}
$ticket->load([
'user:id,username,look',
'category',
'replies.user:id,username,look',
]);
return view('help-center.tickets.show', [
'ticket' => $ticket,
'openTickets' => WebsiteHelpCenterTicket::where('open', true)->where('id', '!=', $ticket->id)->where('user_id', Auth::id())->get(),
]);
}
public function destroy(WebsiteHelpCenterTicket $ticket)
{
if (! $ticket->canDeleteTicket()) {
return back()->with([
'message' => __('You cannot delete others tickets.'),
]);
}
$ticket->delete();
return to_route('me.show')->with('success', __('The ticket has been deleted!'));
}
public function toggleTicketStatus(WebsiteHelpCenterTicket $ticket)
{
if (! $ticket->canManageTicket()) {
return back()->with([
'message' => __('You manage others tickets.'),
]);
}
$ticket->open ? $ticket->update(['open' => false]) : $ticket->update(['open' => true]);
return back()->with('success', __('The ticket status has been changed!'));
}
}
@@ -1,47 +0,0 @@
<?php
namespace App\Http\Controllers\Help;
use App\Http\Controllers\Controller;
use App\Http\Requests\WebsiteTicketReplyFormRequest;
use App\Models\Help\WebsiteHelpCenterTicket;
use App\Models\Help\WebsiteHelpCenterTicketReply;
class TicketReplyController extends Controller
{
public function store(WebsiteHelpCenterTicket $ticket, WebsiteTicketReplyFormRequest $request)
{
if (! $ticket->isOpen()) {
return back()->with([
'message' => __('You cannot reply to the ticket as it has been closed.'),
]);
}
if (! $ticket->canManageTicket()) {
return back()->with([
'message' => __('You cannot reply to others tickets.'),
]);
}
$data = $request->validated();
$ticket->replies()->create([
'user_id' => $request->user()->id,
'content' => $data['content'],
]);
return back()->with('success', __('The reply has been submitted!'));
}
public function destroy(WebsiteHelpCenterTicketReply $reply)
{
if (! $reply->canDeleteReply()) {
return back()->with([
'message' => __('You do not have permission to delete this reply.'),
]);
}
$reply->delete();
return back()->with('success', __('The reply has been deleted!'));
}
}
@@ -1,17 +0,0 @@
<?php
namespace App\Http\Controllers\Help;
use App\Http\Controllers\Controller;
use App\Models\Help\WebsiteRuleCategory;
use Illuminate\View\View;
class WebsiteRulesController extends Controller
{
public function __invoke(): View
{
return view('rules', [
'categories' => WebsiteRuleCategory::with('rules')->get(),
]);
}
}
@@ -1,27 +0,0 @@
<?php
namespace App\Http\Controllers\Miscellaneous;
use App\Http\Controllers\Controller;
use App\Models\Articles\WebsiteArticle;
use App\Models\Miscellaneous\CameraWeb;
use Illuminate\View\View;
class HomeController extends Controller
{
public function __invoke(): View
{
return view('index', [
'articles' => WebsiteArticle::latest('id')
->take(4)
->has('user')
->with('user:id,username,look')
->get(),
'photos' => CameraWeb::latest('id')
->take(4)
->where('visible', true)
->with('user:id,username,look')
->get(),
]);
}
}
@@ -1,119 +0,0 @@
<?php
namespace App\Http\Controllers\Miscellaneous;
use App\Http\Controllers\Controller;
use App\Models\Miscellaneous\WebsiteInstallation;
use App\Models\Miscellaneous\WebsiteSetting;
use App\Rules\ValidateInstallationKeyRule;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
class InstallationController extends Controller
{
public function index()
{
return view('installation.index');
}
public function storeInstallationKey(Request $request)
{
$request->validate([
'installation_key' => ['required', 'string', 'max:255', new ValidateInstallationKeyRule],
]);
WebsiteInstallation::first()->update([
'step' => 1,
'user_ip' => $request->ip(),
]);
return to_route('installation.show-step', 1);
}
public function showStep($currentStep)
{
$settings = $this->getSettingsForStep((int) $currentStep);
return view('installation.step-' . $currentStep, [
'settings' => $settings,
]);
}
public function saveStepSettings(Request $request)
{
$this->updateSettings($request);
WebsiteInstallation::increment('step');
return to_route('installation.show-step', WebsiteInstallation::first()->step);
}
public function previousStep()
{
WebsiteInstallation::decrement('step');
return to_route('installation.show-step', WebsiteInstallation::first()->step);
}
public function restartInstallation()
{
WebsiteInstallation::first()->update([
'step' => 0,
'installation_key' => Str::uuid(),
'user_ip' => null,
]);
WebsiteSetting::where('key', 'theme')->update([
'value' => 'atom',
]);
return to_route('installation.index');
}
public function completeInstallation()
{
WebsiteInstallation::latest()->first()->update([
'completed' => true,
]);
if (Cache::has('website_permissions')) {
Cache::forget('website_permissions');
}
if (Cache::has('website_settings')) {
Cache::forget('website_settings');
}
return to_route('welcome');
}
private function updateSettings(Request $request)
{
foreach ($request->except('_token') as $key => $value) {
WebsiteSetting::where('key', '=', $key)->update([
'value' => $value ?? '',
]);
}
}
private function getSettingsForStep(int $step)
{
$settingsData = array_chunk(WebsiteSetting::all()->pluck('key')->toArray(), ceil(WebsiteSetting::count() / 4));
$settings = match ($step) {
1 => $settingsData[0] ?? [],
2 => $settingsData[1] ?? [],
3 => $settingsData[2] ?? [],
4 => $settingsData[3] ?? [],
5 => [], // Completion step has no settings
default => throw new Exception('Step does not exist'),
};
return WebsiteSetting::query()
->whereIn('key', $settings)
->select(['key', 'value', 'comment'])
->get();
}
}
@@ -1,24 +0,0 @@
<?php
namespace App\Http\Controllers\Miscellaneous;
use App\Http\Controllers\Controller;
use App\Models\Miscellaneous\WebsiteLanguage;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Session;
class LocaleController extends Controller
{
public function __invoke(string $locale): RedirectResponse
{
if (! WebsiteLanguage::where('country_code', $locale)->exists()) {
return back()->withErrors(['message' => __('The language selected is not supported')]);
}
App::setLocale($locale);
Session::put('locale', $locale);
return back();
}
}
@@ -1,40 +0,0 @@
<?php
namespace App\Http\Controllers\Miscellaneous;
use App\Http\Controllers\Controller;
use App\Models\Miscellaneous\WebsiteSetting;
use Illuminate\Http\Request;
class LogoGeneratorController extends Controller
{
public function index()
{
if (hasPermission('generate_logo') === '' || hasPermission('generate_logo') === '0') {
return to_route('me.show')->with([
'message' => __('You do not have permission to do this.'),
]);
}
return view('logo-generator');
}
public function store(Request $request)
{
$request->validate(['logo' => ['required', 'image']]);
$file = $request->file('logo');
$filename = $file->getClientOriginalName();
$path = '/assets/images/generated-logos';
$file->move(public_path($path), $filename);
$setting = WebsiteSetting::where('key', 'cms_logo')->first();
$setting->update([
'value' => sprintf('%s/%s', $path, $filename),
]);
return response()->json(['success' => true, 'message' => 'Logo updated!']);
}
}
@@ -1,17 +0,0 @@
<?php
namespace App\Http\Controllers\Miscellaneous;
use App\Http\Controllers\Controller;
use App\Models\Miscellaneous\WebsiteMaintenanceTask;
use Illuminate\View\View;
class MaintenanceController extends Controller
{
public function __invoke(): View
{
return view('maintenance', [
'tasks' => WebsiteMaintenanceTask::with('user:id,username,look')->simplePaginate(5),
]);
}
}
@@ -1,145 +0,0 @@
<?php
namespace App\Http\Controllers\Shop;
use App\Http\Controllers\Controller;
use App\Http\Requests\AccountTopupFormRequest;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Srmklive\PayPal\Services\PayPal as PayPalClient;
use Symfony\Component\HttpFoundation\Response;
class PaypalController extends Controller
{
private const string STATUS_CANCELLED = 'CANCELLED';
private const string STATUS_COMPLETED = 'COMPLETED';
public function __construct(private PayPalClient $provider)
{
$this->provider = new PayPalClient;
$this->provider->setApiCredentials(config('habbo.paypal'));
$this->provider->getAccessToken();
}
public function process(AccountTopupFormRequest $request): Response|RedirectResponse
{
$amount = $request->integer('amount');
$orderData = [
'intent' => 'CAPTURE',
'application_context' => [
'return_url' => route('paypal.successful-transaction'),
'cancel_url' => route('paypal.cancelled-transaction'),
'brand_name' => setting('hotel_name'),
'landing_page' => 'BILLING',
'shipping_preference' => 'NO_SHIPPING',
'user_action' => 'CONTINUE',
],
'purchase_units' => [
0 => [
'amount' => [
'currency_code' => config('habbo.paypal.currency'),
'value' => (string) $amount,
],
],
],
];
$response = $this->provider->createOrder($orderData);
if (isset($response['id']) === false) {
Log::error('Error creating order', ['response' => $response]);
return to_route('shop.index')->withErrors(
['message' => $response['message'] ?? __('Something went wrong')],
);
}
foreach ($response['links'] as $links) {
if ($links['rel'] === 'approve') {
$request->user()->transactions()->create([
'transaction_id' => $response['id'],
'amount' => 0,
]);
return redirect()->away($links['href']);
}
}
return to_route('shop.index')->withErrors(
['message' => $response['message'] ?? __('Something went wrong')],
);
}
public function successful(Request $request): Response
{
$request->validate([
'token' => ['required'],
]);
$user = $request->user();
$transaction = $user->transactions()->where('transaction_id', $request['token'])->first();
if ($transaction === null) {
return to_route('shop.index')->withErrors(['message' => __('Something went wrong, please try again later')]);
}
$response = $this->provider->capturePaymentOrder($request['token']);
$paymentDetails = $response['purchase_units'][0]['payments']['captures'][0];
if (! isset($response['status'], $paymentDetails)) {
Log::error('Invalid response from PayPal', ['response' => $response]);
return to_route('shop.index')->withErrors(['message' => __('Something went wrong, please try again later')]);
}
if (($response['status'] ?? null) === null) {
$details = $response['error']['details'][0];
$transaction->update([
'status' => $response['name'],
'description' => sprintf('%s - %s', $details['issue'], $details['description']),
'amount' => 0,
]);
return to_route('shop.index')->withErrors(['message' => __('Something went wrong, please check your paypal account to make sure nothing was deducted and try again')]);
}
$paymentDetails = $response['purchase_units'][0]['payments']['captures'][0];
$transaction->update([
'status' => $paymentDetails['status'],
'amount' => $paymentDetails['amount']['value'],
'currency' => $paymentDetails['amount']['currency_code'],
]);
if ($response['status'] !== self::STATUS_COMPLETED) {
return to_route('shop.index')->withErrors(
['message' => $response['message'] ?? __('Something went wrong')],
);
}
$user->increment('website_balance', $paymentDetails['amount']['value']);
return to_route('shop.index')->with('success', __('Transaction successful'));
}
public function cancelled(Request $request): Response
{
$request->validate([
'token' => ['required'],
]);
$transaction = $request->user()->transactions()->where('transaction_id', $request['token'])->first();
if ($transaction !== null) {
$transaction->update([
'status' => self::STATUS_CANCELLED,
'description' => 'The user cancelled the transaction',
]);
}
return to_route('shop.index')->withErrors(
['message' => __('You have canceled the transaction')],
);
}
}
@@ -1,142 +0,0 @@
<?php
namespace App\Http\Controllers\Shop;
use App\Actions\SendCurrency;
use App\Actions\SendFurniture;
use App\Http\Controllers\Controller;
use App\Models\Shop\WebsiteShopArticle;
use App\Models\Shop\WebsiteShopCategory;
use App\Models\User;
use App\Services\RconService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class ShopController extends Controller
{
public function __construct(private readonly RconService $rconService) {}
public function __invoke(?WebsiteShopCategory $category)
{
$packages = WebsiteShopArticle::orderBy('position');
if ($category && $category->exists) {
$packages = $category->articles()->orderBy('position');
}
return view('shop.shop', [
'articles' => $packages->with(['rank:id,rank_name', 'features'])->get(),
'categories' => WebsiteShopCategory::whereHas('articles')->get(),
]);
}
private function giveBadges(User $user, string $badges)
{
$badgeList = explode(';', $badges);
$ownedBadges = $user->badges()->pluck('badge_code')->toArray();
foreach ($badgeList as $badge) {
if (in_array($badge, $ownedBadges)) {
continue;
}
if ($this->rconService->isConnected) {
$this->rconService->giveBadge($user, $badge);
continue;
}
$user->badges()->updateOrCreate([
'user_id' => $user->id,
'badge_code' => $badge,
]);
}
}
public function purchase(WebsiteShopArticle $package, Request $request, SendCurrency $sendCurrency): Response
{
$user = Auth::user();
if ($request->has('receiver')) {
if (! $package->is_giftable) {
return to_route('shop.index')->withErrors(
['message' => __('This package is not giftable')],
);
}
$user = User::where('username', $request->input('receiver'))->first();
if (! $user) {
return to_route('shop.index')->withErrors(
['message' => __('Recipient not found')],
);
}
}
if ($package->give_rank && $user->rank >= $package->give_rank) {
$message = __('You are already this or a higher rank');
if ($user->username !== Auth::user()->username) {
$message = __('The recipient is already this or a higher rank');
}
return to_route('shop.index')->withErrors(
['message' => $message],
);
}
if (! $this->rconService->isConnected && $user->online === '1') {
return to_route('shop.index')->withErrors(
['message' => __('Please logout before purchasing a package')],
);
}
if (Auth::user()->website_balance < $package->price()) {
return to_route('shop.index')->withErrors(
['message' => __('You need to top-up your account with another $:amount to purchase this package', ['amount' => ($package->price() - Auth::user()->website_balance)])],
);
}
Auth::user()?->decrement('website_balance', $package->price());
$sendCurrency->execute($user, 'credits', $package->credits);
$sendCurrency->execute($user, 'duckets', $package->duckets);
$sendCurrency->execute($user, 'diamonds', $package->diamonds);
if ($package->give_rank) {
if ($this->rconService->isConnected) {
$this->rconService->setRank($user, $package->give_rank);
$this->rconService->disconnectUser($user);
} else {
$user->update([
'rank' => $package->give_rank,
]);
}
}
if ($package->badges) {
$this->giveBadges($user, $package->badges);
}
if ($package->furniture) {
$this->handleFurniture(json_decode($package->furniture, true));
}
$message = __('You have successfully purchased the package :name', ['name' => $package->name]);
if ($user->username !== Auth::user()->username) {
$message = __('You have successfully purchased the package :name for :username', ['name' => $package->name, 'username' => $user->username]);
}
return to_route('shop.index')->with('success', $message);
}
public function handleFurniture(array $furniture)
{
$sendFurniture = app(SendFurniture::class);
$sendFurniture->execute(Auth::user(), $furniture);
}
}
@@ -1,44 +0,0 @@
<?php
namespace App\Http\Controllers\Shop;
use App\Http\Controllers\Controller;
use App\Http\Requests\ShopVoucherFormRequest;
use App\Models\Shop\WebsiteShopVoucher;
class ShopVoucherController extends Controller
{
public function __invoke(ShopVoucherFormRequest $request)
{
$user = $request->user();
$voucher = WebsiteShopVoucher::where('code', $request->string('code'))->first();
if (is_null($voucher) || ($voucher->expires_at && $voucher->expires_at->lte(now()))) {
return back()->withErrors([
'message' => __('No active voucher with the given code was found'),
]);
}
if ($user->usedShopVouchers()->where('voucher_id', $voucher->id)->exists()) {
return back()->withErrors([
'message' => __('You can only use each shop voucher once'),
]);
}
$user->usedShopVouchers()->create([
'voucher_id' => $voucher->id,
]);
$user->increment('website_balance', $voucher->amount);
$voucher->increment('use_count');
if ($voucher->max_uses && $voucher->use_count >= $voucher->max_uses) {
$voucher->update([
'expires_at' => now(),
]);
}
return back()->with('success', __('Your balance has been increased by $:amount', ['amount' => $voucher->amount]));
}
}
@@ -1,69 +0,0 @@
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Http\Requests\AccountSettingsFormRequest;
use App\Services\RconService;
use App\Services\User\SessionService;
use App\Services\User\UserService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
class AccountSettingsController extends Controller
{
public function __construct(private readonly SessionService $sessionService, private readonly UserService $userService, private readonly RconService $rconService) {}
public function edit(): View
{
return view('user.settings.account', [
'user' => Auth::user()->load('settings:allow_name_change'),
]);
}
public function sessionLogs(Request $request): View
{
$sessions = $this->sessionService->fetchSessionLogs($request);
return view('user.settings.session-logs', [
'logs' => $sessions,
]);
}
public function update(AccountSettingsFormRequest $request): RedirectResponse
{
$user = Auth::user();
if ($user === null) {
return back()->withErrors('User not found');
}
// $allowedNameChange = $user->settings?->allow_name_change && $user->username !== $request->input('username');
if (! $this->rconService->isConnected() && Auth::user()->online === '1') {
return back()->withErrors('You must be offline to change your account settings');
}
/** if ($allowedNameChange) {
$this->rconService->disconnectUser($user);
$this->userService->updateField($user, 'username', $request->input('username'));
} **/
if ($user->mail !== $request->input('mail')) {
$this->userService->updateField($user, 'mail', $request->input('mail'));
}
if ($user->motto !== $request->input('motto')) {
$this->rconService->setMotto($user, $request->input('motto'));
$this->userService->updateField($user, 'motto', $request->input('motto'));
}
return to_route('settings.account.show')->with('success', __('Your account settings has been updated'));
}
public function twoFactor(): View
{
return view('user.settings.two-factor');
}
}
@@ -1,23 +0,0 @@
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Models\User\Ban;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
class BannedController extends Controller
{
public function __invoke(): View
{
$ipBan = Ban::where('ip', '=', request()->ip())
->where('ban_expire', '>', time())
->orderByDesc('id')
->first();
return view('banned', [
'ban' => $ipBan ?? Auth::user()->ban,
]);
}
}
@@ -1,78 +0,0 @@
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Models\PasswordResetToken;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Mail;
class ForgotPasswordController extends Controller
{
public function __invoke()
{
return view('auth.passwords.forget');
}
public function submitForgetPassword(Request $request)
{
$request->validate([
'mail' => ['required', 'email'],
]);
// Do not tell the user that this email does not exist to prevent possible attacks
if (User::where('mail', $request->mail)->exists()) {
$token = Str::uuid();
PasswordResetToken::create([
'email' => $request->mail,
'token' => $token,
]);
Mail::send('email.forgetPassword', ['token' => $token], function ($message) use ($request): void {
$message->to($request->mail);
$message->subject('Reset Password');
});
}
return back()->with('success', __('We have e-mailed your password reset link!'));
}
public function showResetPassword(Request $request, string $token)
{
$prt = PasswordResetToken::select('token', 'created_at')->where('token', $token)->first();
if ($prt === null) {
return to_route('forgot.password.get')->withErrors('message', __('This token has expired!'));
}
$tokenExpiration = \Illuminate\Support\Facades\Date::now()->subMinutes(config('habbo.password_reset_token_time'));
if ($prt->created_at->gte($tokenExpiration)) { // gte = greater than or equals
$prt->delete();
return to_route('forgot.password.get')->withErrors('message', __('This token has expired!'));
}
return view('auth.passwords.reset', [
'token' => $token,
]);
}
public function submitResetPassword(Request $request, string $token)
{
$request->validate([
'password' => ['required', 'min:8', 'confirmed'],
'password_confirmation' => ['required'],
]);
$prt = PasswordResetToken::select('email', 'token')->where('token', $token)->first();
if ($prt === null) {
return to_route('forgot.password.get')->withErrors('message', __('This token has expired!'));
}
$prt->user->changePassword($request->password);
$prt->delete();
return to_route('login')->with('success', __('Your password has been successfully reset!'));
}
}
@@ -1,54 +0,0 @@
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Http\Requests\GuestbookFormRequest;
use App\Models\User;
use App\Models\User\WebsiteUserGuestbook;
use Illuminate\Support\Facades\Auth;
class GuestbookController extends Controller
{
public function store(User $user, GuestbookFormRequest $request)
{
$this->validateGuestbookPost($user, $request);
$user->profileGuestbook()->create([
'user_id' => Auth::id(),
'message' => $request->input('message'),
]);
return back()->with('success', __('Your message has been posted.'));
}
public function destroy(User $user, WebsiteUserGuestbook $guestbook)
{
if ($guestbook->user_id !== Auth::id() && $guestbook->profile_id !== $user->id && Auth::user()->rank < (int) setting('min_staff_rank')) {
return back()->withErrors([
'message' => __('Do do not have permission to delete this message'),
]);
}
$guestbook->delete();
return back()->with('success', __('Your message has been deleted.'));
}
private function validateGuestbookPost(User $user, GuestbookFormRequest $request)
{
if ($user->id === $request->user()->id) {
return $this->redirectWithError(__('You cannot post a message on your own profile.'));
}
$maxAllowedPostCount = in_array(setting('max_guestbook_posts_per_profile'), ['', '0'], true) ? 3 : (int) setting('max_guestbook_posts_per_profile');
if ($user->profileGuestbook()->where('user_id', $request->user()->id)->count() >= $maxAllowedPostCount) {
return $this->redirectWithError(__('You have already posted :count messages on this profile.', ['count' => $maxAllowedPostCount]));
}
}
private function redirectWithError($message)
{
return back()->withErrors(['message' => $message]);
}
}
@@ -1,21 +0,0 @@
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Models\Articles\WebsiteArticle;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
class MeController extends Controller
{
public function __invoke(): View
{
return view('user.me', [
'onlineFriends' => Auth::user()?->getOnlineFriends(),
'user' => Auth::user()?->load('permission:id,rank_name'),
'articles' => WebsiteArticle::whereHas('user')->with('user:id,username,look')->latest()->take(5)->get(),
]);
}
}
@@ -1,27 +0,0 @@
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Http\Requests\PasswordSettingsFormRequest;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\View\View;
class PasswordSettingsController extends Controller
{
public function edit(): View
{
return view('user.settings.password');
}
public function update(PasswordSettingsFormRequest $request): RedirectResponse
{
Auth::user()->update([
'password' => Hash::make($request->input('password')),
]);
return to_route('settings.password.show')->with('success', __('Your password has been changed!'));
}
}
@@ -1,65 +0,0 @@
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Models\Game\Guild\GuildMember;
use App\Models\Game\Player\MessengerFriendship;
use App\Models\User;
class ProfileController extends Controller
{
public function __invoke(User $user)
{
$user = $this->loadUserRelations($user);
$friends = $this->getUserFriends($user->id);
$groups = $this->getUserGroups($user->id);
return view('user.profile', [
'user' => $user,
'friends' => $friends,
'groups' => $groups,
'guestbook' => $user->profileGuestbook()->with('user')->latest()->limit(5)->get(),
'photos' => $user->photos()->limit(3)->get(),
]);
}
private function loadUserRelations(User $user): User
{
return $user->load([
'badges' => function ($badges): void {
$badges->where('slot_id', '>', '0')
->orderBy('slot_id')
->take(5);
},
'rooms' => function ($rooms): void {
$rooms->select('id', 'owner_id', 'name', 'users')
->orderByDesc('users')
->orderBy('id');
},
]);
}
private function getUserFriends(int $userId)
{
return MessengerFriendship::select('user_two_id')
->where('user_one_id', '=', $userId)
->whereHas('user')
->with('user:id,username,look')
->inRandomOrder()
->take(12)
->get();
}
private function getUserGroups(int $userId)
{
return GuildMember::query()
->select(['guilds_members.id', 'guilds_members.guild_id', 'guilds_members.user_id', 'guilds.name', 'guilds.badge'])
->where('guilds_members.user_id', '=', $userId)
->join('guilds', 'guilds_members.guild_id', '=', 'guilds.id')
->inRandomOrder()
->take(6)
->get();
}
}
@@ -1,33 +0,0 @@
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Services\RconService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Auth;
class ReferralController extends Controller
{
public function __invoke(RconService $rcon): RedirectResponse
{
$user = Auth::user();
if (! $user->referrals || $user->referrals->referrals_total < setting('referrals_needed')) {
return back()->withErrors([
'message' => __('You do not have enough referrals to claim your reward'),
]);
}
// Decrease the total amount of referrals with the amount needed to claim reward
$user->referrals->decrement('referrals_total', setting('referrals_needed'));
$rcon->giveDiamonds($user, setting('referral_reward_amount'));
// Log the claim
$user->claimedReferralLog()->create([
'ip_address' => request()->ip(),
]);
return back()->with('success', __('Woah! You have successfully claimed your reward - Keep up the good work!'));
}
}
@@ -1,42 +0,0 @@
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
use Laravel\Fortify\Actions\DisableTwoFactorAuthentication;
use Laravel\Fortify\Actions\EnableTwoFactorAuthentication;
class TwoFactorAuthenticationController extends Controller
{
public function index(): View
{
return view('user.settings.two-factor');
}
public function store(Request $request, EnableTwoFactorAuthentication $enable): RedirectResponse
{
$enable($request->user());
return to_route('settings.two-factor')->with('success', __('Two-factor authentication has been enabled. Please scan the QR code to continue.'));
}
public function verify(Request $request): RedirectResponse
{
$confirmed = $request->user()->confirmTwoFactorAuthentication($request->input('code'));
if (! $confirmed) {
return back()->withErrors('Invalid Two Factor Authentication code');
}
return to_route('settings.two-factor')->with('success', __('Two-factor authentication has been confirmed.'));
}
public function destroy(Request $request, DisableTwoFactorAuthentication $disable): RedirectResponse
{
$disable($request->user());
return to_route('settings.two-factor')->with('success', __('Two-factor authentication has been disabled.'));
}
}
@@ -1,18 +0,0 @@
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Models\User;
class UserReferralController extends Controller
{
public function __invoke(string $referralCode)
{
User::where('referral_code', '=', $referralCode)->firstOrFail();
return view('auth.register', [
'referral_code' => $referralCode,
]);
}
}
-110
View File
@@ -1,110 +0,0 @@
<?php
namespace App\Http;
use App\Http\Middleware\Authenticate;
use App\Http\Middleware\BannedMiddleware;
use App\Http\Middleware\EncryptCookies;
use App\Http\Middleware\FindRetrosMiddleware;
use App\Http\Middleware\ForceStaffTwoFactorMiddleware;
use App\Http\Middleware\InstallationMiddleware;
use App\Http\Middleware\LocalizationMiddleware;
use App\Http\Middleware\LogViewerMiddleware;
use App\Http\Middleware\MaintenanceMiddleware;
use App\Http\Middleware\PreventRequestsDuringMaintenance;
use App\Http\Middleware\RealClientIpMiddleware;
use App\Http\Middleware\RedirectIfAuthenticated;
use App\Http\Middleware\SetThemeMiddleware;
use App\Http\Middleware\TrimStrings;
use App\Http\Middleware\TrustProxies;
use App\Http\Middleware\VerifyCsrfToken;
use App\Http\Middleware\VPNCheckerMiddleware;
use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth;
use Illuminate\Auth\Middleware\Authorize;
use Illuminate\Auth\Middleware\EnsureEmailIsVerified;
use Illuminate\Auth\Middleware\RequirePassword;
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull;
use Illuminate\Foundation\Http\Middleware\ValidatePostSize;
use Illuminate\Http\Middleware\HandleCors;
use Illuminate\Http\Middleware\SetCacheHeaders;
use Illuminate\Routing\Middleware\SubstituteBindings;
use Illuminate\Routing\Middleware\ThrottleRequests;
use Illuminate\Routing\Middleware\ValidateSignature;
use Illuminate\Session\Middleware\AuthenticateSession;
use Illuminate\Session\Middleware\StartSession;
use Illuminate\View\Middleware\ShareErrorsFromSession;
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* @var array<int, class-string|string>
*/
protected $middleware = [
// \App\Http\Middleware\TrustHosts::class,
RealClientIpMiddleware::class,
TrustProxies::class,
HandleCors::class,
PreventRequestsDuringMaintenance::class,
ValidatePostSize::class,
TrimStrings::class,
ConvertEmptyStringsToNull::class,
SetThemeMiddleware::class,
InstallationMiddleware::class,
];
/**
* The application's route middleware groups.
*
* @var array<string, array<int, class-string|string>>
*/
protected $middlewareGroups = [
'web' => [
EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartSession::class,
ShareErrorsFromSession::class,
VerifyCsrfToken::class,
SubstituteBindings::class,
LocalizationMiddleware::class,
],
'api' => [
EnsureFrontendRequestsAreStateful::class,
ThrottleRequests::class . ':api',
SubstituteBindings::class,
],
];
/**
* The application's middleware aliases.
*
* Aliases may be used to conveniently assign middleware to routes and groups.
*
* @var array<string, class-string|string>
*/
protected $middlewareAliases = [
'auth' => Authenticate::class,
'auth.basic' => AuthenticateWithBasicAuth::class,
'auth.session' => AuthenticateSession::class,
'cache.headers' => SetCacheHeaders::class,
'can' => Authorize::class,
'guest' => RedirectIfAuthenticated::class,
'password.confirm' => RequirePassword::class,
'signed' => ValidateSignature::class,
'throttle' => ThrottleRequests::class,
'verified' => EnsureEmailIsVerified::class,
'maintenance' => MaintenanceMiddleware::class,
'check.ban' => BannedMiddleware::class,
'findretros.redirect' => FindRetrosMiddleware::class,
'vpn.checker' => VPNCheckerMiddleware::class,
'log.viewer' => LogViewerMiddleware::class,
'force.staff.2fa' => ForceStaffTwoFactorMiddleware::class,
];
}
@@ -1,18 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Http\Request;
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*/
#[\Override]
protected function redirectTo(Request $request): ?string
{
return $request->expectsJson() ? null : route('login');
}
}
@@ -1,48 +0,0 @@
<?php
namespace App\Http\Middleware;
use App\Models\User\Ban;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class BannedMiddleware
{
public function handle(Request $request, Closure $next): Response
{
$authenticated = Auth::check();
$ipBan = Ban::where('ip', '=', $request->ip())
->where('ban_expire', '>', time())
->whereIn('type', ['ip', 'machine'])
->orderByDesc('id')
->exists();
if ($request->is('logout')) {
return $next($request);
}
if (! $authenticated && ! $ipBan && $request->is('banned')) {
return to_route('login');
}
if ($ipBan && ! $request->is('banned')) {
return to_route('banned.show');
}
if ($authenticated) {
$accountBan = $request->user()?->ban;
if ($accountBan && ! $request->is('banned')) {
return to_route('banned.show');
}
if (! $ipBan && ! $accountBan && $request->is('banned')) {
return to_route('me.show');
}
}
return $next($request);
}
}
@@ -1,17 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
class EncryptCookies extends Middleware
{
/**
* The names of the cookies that should not be encrypted.
*
* @var array<int, string>
*/
protected $except = [
//
];
}
@@ -1,23 +0,0 @@
<?php
namespace App\Http\Middleware;
use App\Services\FindRetrosService;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
/* Credits to Kani for this */
class FindRetrosMiddleware
{
public function handle(Request $request, Closure $next): Response
{
$findRetrosService = new FindRetrosService;
if (config('habbo.findretros.enabled') && ! $findRetrosService->checkHasVoted()) {
return redirect($findRetrosService->getRedirectUri());
}
return $next($request);
}
}
@@ -1,30 +0,0 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class ForceStaffTwoFactorMiddleware
{
public function handle(Request $request, Closure $next): Response
{
if (! Auth::check() || ! setting('force_staff_2fa')) {
return $next($request);
}
$user = $request->user();
$urls = [
'user/settings/two-factor',
'user/settings/2fa-verify',
];
if (($user->rank >= setting('min_staff_rank') && ! $user->two_factor_confirmed) && ! in_array(request()->path(), $urls)) {
return to_route('settings.two-factor');
}
return $next($request);
}
}
@@ -1,159 +0,0 @@
<?php
namespace App\Http\Middleware;
use App\Exceptions\MigrationFailedException;
use App\Models\Miscellaneous\WebsiteInstallation;
use Closure;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;
class InstallationMiddleware
{
public function handle(Request $request, Closure $next)
{
if (Cache::get('app_installed')) {
return $next($request);
}
$this->ensureInstallationTableExists();
$installation = $this->getInstallation();
if ($installation && $installation->completed && $request->is('installation*')) {
Cache::rememberForever('app_installed', fn () => true);
return to_route('welcome');
}
$isInstallationStepHandled = $this->handleInstallationSteps($request, $installation);
if (! $isInstallationStepHandled) {
return $this->redirectIfNotCompleted($installation);
}
return $next($request);
}
private function ensureInstallationTableExists()
{
if (! Schema::hasTable('website_installation')) {
Artisan::call('migrate', ['--path' => 'database/migrations/' . findMigration('website_installation')]);
if (! Schema::hasTable('website_installation')) {
throw new MigrationFailedException('website_installation');
}
}
if (! Schema::hasTable('sessions')) {
Artisan::call('migrate', ['--path' => 'database/migrations/' . findMigration('sessions')]);
}
}
private function getInstallation()
{
try {
$installation = WebsiteInstallation::query()->first();
if (! $installation) {
return WebsiteInstallation::create([
'step' => 0,
'completed' => false,
'installation_key' => Str::uuid(),
'user_ip' => request()?->ip(),
]);
}
return $installation;
} catch (Exception $e) {
Log::error('Error fetching or creating WebsiteInstallation: ' . $e->getMessage());
abort(500, 'An error occurred while setting up the installation.');
}
}
private function handleInstallationSteps(Request $request, WebsiteInstallation $installation)
{
if ($installation->completed) {
return true;
}
if ($this->isWelcomeStep($request, $installation)) {
return true;
}
if ($this->isRedirectToWelcome($request, $installation)) {
return false;
}
if ($this->isInvalidAccess($request, $installation)) {
abort(403);
}
if ($this->isInvalidStep($request)) {
return false;
}
return ! $this->isMismatchedStep($request, $installation);
}
private function isWelcomeStep(Request $request, WebsiteInstallation $installation)
{
return $installation->step === 0 && $request->getRequestUri() === '/installation';
}
private function isRedirectToWelcome(Request $request, WebsiteInstallation $installation)
{
return $installation->step === 0 && $request->getRequestUri() !== '/installation' && $request->method() !== 'POST';
}
private function isInvalidAccess(Request $request, WebsiteInstallation $installation)
{
return $installation->step > 0 && $request->ip() !== $installation->user_ip;
}
private function isInvalidStep(Request $request)
{
return ! $this->isValidStep($request) && $this->isNonPostRequest($request);
}
private function isMismatchedStep(Request $request, WebsiteInstallation $installation)
{
return $this->getCurrentStep($request) !== $installation->step && $this->isNonPostRequest($request);
}
private function isValidStep(Request $request)
{
$step = $this->getCurrentStep($request);
return filter_var($step, FILTER_VALIDATE_INT) !== false;
}
private function isNonPostRequest(Request $request)
{
return $request->method() !== 'POST' || $request->is('restart-installation');
}
private function getCurrentStep(Request $request)
{
return (int) Str::after($request->path(), 'step/');
}
private function redirectToStep(int $step)
{
return to_route('installation.show-step', $step);
}
protected function redirectIfNotCompleted(WebsiteInstallation $installation)
{
if ($installation->step === 0) {
return to_route('installation.index');
}
return $this->redirectToStep($installation->step ?: 1);
}
}
@@ -1,50 +0,0 @@
<?php
namespace App\Http\Middleware;
use App\Models\Miscellaneous\WebsiteLanguage;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Session;
use Symfony\Component\HttpFoundation\Response;
class LocalizationMiddleware
{
public function handle(Request $request, Closure $next): Response
{
// Controleer of de instellingen bestaan en of de taal al in de sessie staat
if (Schema::hasTable('website_settings') && Session::has('locale')) {
App::setLocale(Session::get('locale'));
return $next($request);
}
$countryCode = config('habbo.site.default_language');
// GEWIJZIGD: isset() werkt niet op Request::server() in PHP 8. Gebruik null !== in plaats daarvan.
if (null !== \Illuminate\Support\Facades\Request::server('HTTP_CF_IPCOUNTRY')) {
$countryCode = strtolower((string) \Illuminate\Support\Facades\Request::server('HTTP_CF_IPCOUNTRY'));
}
elseif (null !== \Illuminate\Support\Facades\Request::server('HTTP_ACCEPT_LANGUAGE')) {
$countryCode = strtolower(substr((string) \Illuminate\Support\Facades\Request::server('HTTP_ACCEPT_LANGUAGE'), 0, 2));
}
// Als de taal niet in de database staat, gebruik de standaardtaal
if (Schema::hasTable('website_languages') && WebsiteLanguage::where('country_code', '=', $countryCode)->doesntExist()) {
$defaultCountry = config('habbo.site.default_language');
App::setLocale($defaultCountry);
Session::put('locale', $defaultCountry);
return $next($request);
}
// Zet de gedetecteerde taal
App::setLocale($countryCode);
Session::put('locale', $countryCode);
return $next($request);
}
}
@@ -1,24 +0,0 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class LogViewerMiddleware
{
public function handle(Request $request, Closure $next): Response
{
if (! Auth::check()) {
return to_route('login');
}
if (hasPermission('view_server_logs') === '' || hasPermission('view_server_logs') === '0') {
abort(403);
}
return $next($request);
}
}
@@ -1,58 +0,0 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class MaintenanceMiddleware
{
public function handle(Request $request, Closure $next): Response
{
$isPostRequest = $request->method() === 'POST';
$isMaintenanceRequest = $request->is('maintenance');
$maintenanceEnabled = setting('maintenance_enabled');
$fortify2faRoutes = [
'two-factor.login',
'two-factor.confirm',
];
if ($maintenanceEnabled && $isPostRequest && ! Auth::check()) {
return $next($request);
}
$isFortify2faRoute = in_array($request->route()?->getName(), $fortify2faRoutes, true);
if ($maintenanceEnabled && $isFortify2faRoute) {
return $next($request);
}
if (Auth::check() && Auth::user()->rank >= setting('min_maintenance_login_rank')) {
if ($isMaintenanceRequest) {
return to_route('me.show');
}
return $next($request);
}
if (Auth::check() && Auth::user()->rank >= setting('min_maintenance_login_rank') && $isMaintenanceRequest) {
return to_route('me.show');
}
if ($maintenanceEnabled && ! $isMaintenanceRequest && ! $isPostRequest) {
return to_route('maintenance.show');
}
if (! $maintenanceEnabled && $isMaintenanceRequest && ! $isPostRequest) {
return to_route('welcome');
}
if ($maintenanceEnabled && ! $isMaintenanceRequest && Auth::check() && Auth::user()->rank < setting('min_maintenance_login_rank')) {
return to_route('maintenance.show');
}
return $next($request);
}
}
@@ -1,17 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance as Middleware;
class PreventRequestsDuringMaintenance extends Middleware
{
/**
* The URIs that should be reachable while maintenance mode is enabled.
*
* @var array<int, string>
*/
protected $except = [
//
];
}
@@ -1,47 +0,0 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class RealClientIpMiddleware
{
public function handle(Request $request, Closure $next)
{
$proxyHeaders = [
'HTTP_CF_CONNECTING_IP',
'HTTP_X_FORWARDED_FOR',
'HTTP_X_REAL_IP',
'HTTP_CLIENT_IP',
'HTTP_TRUE_CLIENT_IP',
];
foreach ($proxyHeaders as $header) {
if (! empty(\Illuminate\Support\Facades\Request::server($header))) {
$ip = \Illuminate\Support\Facades\Request::server($header);
if (str_contains((string) $ip, ',')) {
[$ip] = explode(',', (string) $ip);
}
$ip = trim((string) $ip);
if (filter_var($ip, FILTER_VALIDATE_IP)) {
// Set the real IP as REMOTE_ADDR
$request->server->set('REMOTE_ADDR', $ip);
break;
}
}
}
// Special handling for REMOTE_ADDR with multiple IPs
$remoteAddr = \Illuminate\Support\Facades\Request::server('REMOTE_ADDR') ?? '';
if (! empty($remoteAddr) && str_contains((string) $remoteAddr, ',')) {
[$ip] = explode(',', (string) $remoteAddr);
$ip = trim($ip);
if (filter_var($ip, FILTER_VALIDATE_IP)) {
$request->server->set('REMOTE_ADDR', $ip);
}
}
return $next($request);
}
}
@@ -1,35 +0,0 @@
<?php
namespace App\Http\Middleware;
use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* @param Closure(Request):((\Illuminate\Http\Response|RedirectResponse)) $next
*/
public function handle(Request $request, Closure $next, string ...$guards): Response
{
$guards = $guards === [] ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
if ($request->expectsJson()) {
return response()->json();
}
return redirect(RouteServiceProvider::HOME);
}
}
return $next($request);
}
}
@@ -1,22 +0,0 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Qirolab\Theme\Theme;
use Symfony\Component\HttpFoundation\Response;
class SetThemeMiddleware
{
public function handle(Request $request, Closure $next): Response
{
if (setting('theme') === '' || setting('theme' === '1')) {
Theme::set('atom');
} else {
Theme::set(setting('theme'));
}
return $next($request);
}
}
@@ -1,19 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
class TrimStrings extends Middleware
{
/**
* The names of the attributes that should not be trimmed.
*
* @var array<int, string>
*/
protected $except = [
'current_password',
'password',
'password_confirmation',
];
}
@@ -1,21 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Middleware\TrustHosts as Middleware;
class TrustHosts extends Middleware
{
/**
* Get the host patterns that should be trusted.
*
* @return array<int, string|null>
*/
#[\Override]
public function hosts(): array
{
return [
$this->allSubdomainsOfApplicationUrl(),
];
}
}
@@ -1,28 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Middleware\TrustProxies as Middleware;
use Illuminate\Http\Request;
class TrustProxies extends Middleware
{
/**
* The trusted proxies for this application.
*
* @var array<int, string>|string|null
*/
protected $proxies;
/**
* The headers that should be used to detect proxies.
*
* @var int
*/
protected $headers =
Request::HEADER_X_FORWARDED_FOR |
Request::HEADER_X_FORWARDED_HOST |
Request::HEADER_X_FORWARDED_PORT |
Request::HEADER_X_FORWARDED_PROTO |
Request::HEADER_X_FORWARDED_AWS_ELB;
}
@@ -1,81 +0,0 @@
<?php
namespace App\Http\Middleware;
use App\Models\Miscellaneous\WebsiteIpBlacklist;
use App\Models\Miscellaneous\WebsiteIpWhitelist;
use App\Services\IpLookupService;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class VPNCheckerMiddleware
{
public function handle(Request $request, Closure $next): Response
{
// Skip check if vpn checker is disabled
if (setting('vpn_block_enabled') === '0' || setting('ipdata_api_key') === 'ADD-API-KEY-HERE') {
return $next($request);
}
// Skip check if the rank is allowed to bypass the checker
if (hasPermission('bypass_vpn') !== '' && hasPermission('bypass_vpn') !== '0') {
return $next($request);
}
// Skip check if the IP is in the whitelist table
if (WebsiteIpWhitelist::where('ip_address', $request->ip())->exists()) {
return $next($request);
}
// Restrict user if IP is blacklisted
if (WebsiteIpBlacklist::where('ip_address', $request->ip())->exists()) {
return to_route('me.show')->withErrors([
'message' => __('Your IP have been restricted - If you think this is a mistake, you can contact us on our Discord.'),
]);
}
// Instantiate the necessary things to look up the visitor IP
$ipService = new IpLookupService(setting('ipdata_api_key'));
$userIp = $request->ip();
$apiResponse = $ipService->ipLookup($userIp);
$asn = $apiResponse['asn']['asn'] ?? '';
$asnWhitelisted = WebsiteIpWhitelist::where('asn', $asn)
->where('whitelist_asn', '=', '1')
->exists();
if ($asnWhitelisted) {
return $next($request);
}
// Fetch all blacklisted ASNs
$asnBlacklisted = WebsiteIpBlacklist::where('asn', $asn)
->where('blacklist_asn', '=', '1')
->exists();
// Restrict the user if their ASN is within the blacklist table
if ($asnBlacklisted) {
return to_route('me.show')->withErrors([
'message' => __('Your IP have been restricted - If you think this is a mistake, you can contact us on our Discord.'),
]);
}
if (isset($apiResponse['threat']) && is_array($apiResponse['threat'])) {
$filteredThreats = array_diff_key($apiResponse['threat'], array_flip(['blocklists', 'is_icloud_relay', 'is_datacenter', 'is_tor', 'is_proxy']));
if (in_array(true, $filteredThreats, true)) {
WebsiteIpBlacklist::create([
'ip_address' => $userIp,
'asn' => null,
]);
return to_route('me.show')->withErrors([
'message' => __('Your IP has been restricted - If you think this is a mistake, you can contact us on our Discord.'),
]);
}
}
return $next($request);
}
}
@@ -1,22 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Routing\Middleware\ValidateSignature as Middleware;
class ValidateSignature extends Middleware
{
/**
* The names of the query string parameters that should be ignored.
*
* @var array<int, string>
*/
protected $except = [
// 'fbclid',
// 'utm_campaign',
// 'utm_content',
// 'utm_medium',
// 'utm_source',
// 'utm_term',
];
}
@@ -1,17 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* The URIs that should be excluded from CSRF verification.
*
* @var array<int, string>
*/
protected $except = [
//
];
}
@@ -1,28 +0,0 @@
<?php
namespace App\Http\Requests;
use App\Rules\GoogleRecaptchaRule;
use App\Rules\WebsiteWordfilterRule;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use RyanChandler\LaravelCloudflareTurnstile\Rules\Turnstile;
class AccountSettingsFormRequest extends FormRequest
{
public function rules(): array
{
return [
'username' => ['sometimes', 'string', sprintf('regex:%s', setting('username_regex')), 'min:3', 'max:25', Rule::unique('users')->ignore($this->user()->id), new WebsiteWordfilterRule],
'mail' => ['required', 'email', Rule::unique('users')->ignore($this->user()->id), new WebsiteWordfilterRule],
'motto' => ['nullable', 'string', 'max:127', new WebsiteWordfilterRule],
'g-recaptcha-response' => [new GoogleRecaptchaRule],
'cf-turnstile-response' => [app(Turnstile::class)],
];
}
public function authorize(): bool
{
return true;
}
}
@@ -1,15 +0,0 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class AccountTopupFormRequest extends FormRequest
{
public function rules(): array
{
return [
'amount' => ['required', 'integer', 'min:1', 'max:250'],
];
}
}
@@ -1,21 +0,0 @@
<?php
namespace App\Http\Requests;
use App\Rules\WebsiteWordfilterRule;
use Illuminate\Foundation\Http\FormRequest;
class ArticleCommentFormRequest extends FormRequest
{
public function rules(): array
{
return [
'comment' => ['required', 'string', 'min:2', 'max:255', new WebsiteWordfilterRule],
];
}
public function authorize(): bool
{
return true;
}
}
@@ -1,16 +0,0 @@
<?php
namespace App\Http\Requests;
use App\Rules\WebsiteWordfilterRule;
use Illuminate\Foundation\Http\FormRequest;
class GuestbookFormRequest extends FormRequest
{
public function rules(): array
{
return [
'message' => ['required', 'string', 'max:32', new WebsiteWordfilterRule],
];
}
}
@@ -1,24 +0,0 @@
<?php
namespace App\Http\Requests;
use App\Actions\Fortify\Rules\PasswordValidationRules;
use App\Rules\CurrentPasswordRule;
use App\Rules\GoogleRecaptchaRule;
use Illuminate\Foundation\Http\FormRequest;
use RyanChandler\LaravelCloudflareTurnstile\Rules\Turnstile;
class PasswordSettingsFormRequest extends FormRequest
{
use PasswordValidationRules;
public function rules(): array
{
return [
'current_password' => ['required', 'string', new CurrentPasswordRule],
'password' => $this->passwordRules(),
'g-recaptcha-response' => [new GoogleRecaptchaRule],
'cf-turnstile-response' => [app(Turnstile::class)],
];
}
}
@@ -1,20 +0,0 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class RareSearchFormRequest extends FormRequest
{
public function rules(): array
{
return [
'search' => ['required', 'string', 'min:1', 'max:255'],
];
}
public function authorize(): bool
{
return true;
}
}
@@ -1,38 +0,0 @@
<?php
namespace App\Http\Requests;
use App\Rules\GoogleRecaptchaRule;
use Illuminate\Foundation\Http\FormRequest;
use RyanChandler\LaravelCloudflareTurnstile\Rules\Turnstile;
class RegisterFormRequest extends FormRequest
{
protected $errorBag = 'register';
public function rules(): array
{
return [
'username' => ['required', 'string', sprintf('regex:%s', setting('username_regex')), 'max:25', Rule::unique('users')],
'mail' => ['required', 'string', 'email', 'max:255', Rule::unique('users')],
'password' => ['required', 'string', 'confirmed', 'min:8'],
'terms' => ['required', 'accepted'],
'g-recaptcha-response' => [new GoogleRecaptchaRule],
'cf-turnstile-response' => [app(Turnstile::class)],
];
}
public function authorize(): bool
{
return true;
}
#[\Override]
public function messages(): array
{
return [
'g-recaptcha-response.required' => __('The Google recaptcha must be completed'),
'g-recaptcha-response.string' => __('The google recaptcha was submitted with an invalid type'),
];
}
}
@@ -1,19 +0,0 @@
<?php
namespace App\Http\Requests;
use App\Rules\GoogleRecaptchaRule;
use Illuminate\Foundation\Http\FormRequest;
use RyanChandler\LaravelCloudflareTurnstile\Rules\Turnstile;
class ShopVoucherFormRequest extends FormRequest
{
public function rules(): array
{
return [
'code' => ['required', 'string'],
'g-recaptcha-response' => [new GoogleRecaptchaRule],
'cf-turnstile-response' => [app(Turnstile::class)],
];
}
}
@@ -1,19 +0,0 @@
<?php
namespace App\Http\Requests;
use App\Rules\GoogleRecaptchaRule;
use Illuminate\Foundation\Http\FormRequest;
use RyanChandler\LaravelCloudflareTurnstile\Rules\Turnstile;
class StaffApplicationFormRequest extends FormRequest
{
public function rules(): array
{
return [
'content' => ['required', 'string'],
'g-recaptcha-response' => [new GoogleRecaptchaRule],
'cf-turnstile-response' => [app(Turnstile::class)],
];
}
}
@@ -1,18 +0,0 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class WebsiteTicketFormRequest extends FormRequest
{
public function rules(): array
{
return [
'category_id' => ['required', 'integer', Rule::exists('website_help_center_categories', 'id')],
'title' => ['required', 'string', 'min:10', 'max:255'],
'content' => ['required', 'string', 'min:10', 'max:65000'],
];
}
}
@@ -1,15 +0,0 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class WebsiteTicketReplyFormRequest extends FormRequest
{
public function rules(): array
{
return [
'content' => ['required', 'string', 'min:10', 'max:65000'],
];
}
}
@@ -1,23 +0,0 @@
<?php
namespace App\Http\Resources;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Http\Resources\Json\JsonResource;
use JsonSerializable;
class OnlineUserCountResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array|Arrayable|JsonSerializable
*/
#[\Override]
public function toArray($request): array
{
return [
'onlineCount' => $this->resource,
];
}
}
@@ -1,24 +0,0 @@
<?php
namespace App\Http\Resources;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use JsonSerializable;
class OnlineUsersResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array|Arrayable|JsonSerializable
*/
#[\Override]
public function toArray(Request $request): array
{
return [
'data' => $this->paginate(10),
];
}
}
@@ -1,23 +0,0 @@
<?php
namespace App\Http\Resources;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Http\Resources\Json\JsonResource;
use JsonSerializable;
class UserResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array|Arrayable|JsonSerializable
*/
#[\Override]
public function toArray($request): array
{
return [
'data' => $this->resource ?: 'No user found',
];
}
}