🆙 Add fixed cms 🆙

This commit is contained in:
Remco
2026-02-02 19:30:21 +01:00
parent b1a2cab62d
commit b67e0ec2b9
3982 changed files with 193682 additions and 0 deletions
@@ -0,0 +1,17 @@
<?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.
*/
protected function redirectTo(Request $request): ?string
{
return $request->expectsJson() ? null : route('login');
}
}
@@ -0,0 +1,48 @@
<?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);
}
}
@@ -0,0 +1,17 @@
<?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 = [
//
];
}
@@ -0,0 +1,23 @@
<?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);
}
}
@@ -0,0 +1,30 @@
<?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);
}
}
@@ -0,0 +1,176 @@
<?php
namespace App\Http\Middleware;
use App\Exceptions\MigrationFailedException;
use App\Models\Miscellaneous\WebsiteInstallation;
use App\Services\InstallationService;
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 (app(InstallationService::class)->isComplete()) {
if ($request->is('installation*')) {
return to_route('welcome');
}
return $next($request);
}
$this->ensureInstallationTableExists();
$installation = $this->getInstallation();
$isInstallationStepHandled = $this->handleInstallationSteps($request, $installation);
if (! $isInstallationStepHandled) {
return $this->redirectIfNotCompleted($installation);
}
return $next($request);
}
private function ensureInstallationTableExists(): void
{
if (! Schema::hasTable('website_installation')) {
Artisan::call('migrate', ['--path' => 'database/migrations/' . findMigration('website_installation')]);
// Migration executed, proceed
}
if (! Schema::hasTable('sessions')) {
Artisan::call('migrate', ['--path' => 'database/migrations/' . findMigration('sessions')]);
}
}
private function getInstallation()
{
try {
$cacheKey = 'installation_record';
$cachedInstallation = Cache::get($cacheKey);
if ($cachedInstallation) {
$installation = new WebsiteInstallation;
$installation->fill((array) $cachedInstallation);
return $installation;
}
$installation = WebsiteInstallation::query()->first();
if (! $installation) {
$installation = WebsiteInstallation::create([
'step' => 0,
'completed' => false,
'installation_key' => Str::uuid(),
'user_ip' => request()->ip(),
]);
}
if ($installation->completed) {
Cache::rememberForever($cacheKey, fn () => $installation->toArray());
}
return $installation;
} catch (Exception $e) {
Log::error('Error fetching or creating WebsiteInstallation: ' . $e->getMessage());
abort(500, 'An error occurred while setting up 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;
}
if ($this->isMismatchedStep($request, $installation)) {
return false;
}
return true;
}
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);
}
}
@@ -0,0 +1,48 @@
<?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
{
if (Schema::hasTable('website_settings')) {
if (Session::has('locale')) {
App::setLocale(Session::get('locale'));
return $next($request);
}
}
$countryCode = config('habbo.site.default_language');
if (isset($_SERVER['HTTP_CF_IPCOUNTRY'])) {
$countryCode = strtolower((string) $_SERVER['HTTP_CF_IPCOUNTRY']);
} elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
$countryCode = strtolower(substr((string) $_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2));
}
// If the language does not exist in the database
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);
}
App::setLocale($countryCode);
Session::put('locale', $countryCode);
return $next($request);
}
}
@@ -0,0 +1,24 @@
<?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')) {
abort(403);
}
return $next($request);
}
}
@@ -0,0 +1,65 @@
<?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);
}
$route = $request->route();
/** @var string|null $routeName */
if ($route) {
$routeName = $route->getName();
} else {
$routeName = null;
}
$isFortify2faRoute = in_array($routeName, $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);
}
}
@@ -0,0 +1,17 @@
<?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 = [
//
];
}
@@ -0,0 +1,47 @@
<?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($_SERVER[$header])) {
$ip = $_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 = $_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);
}
}
@@ -0,0 +1,35 @@
<?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 = empty($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);
}
}
@@ -0,0 +1,22 @@
<?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);
}
}
@@ -0,0 +1,19 @@
<?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',
];
}
@@ -0,0 +1,20 @@
<?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>
*/
public function hosts(): array
{
return [
$this->allSubdomainsOfApplicationUrl(),
];
}
}
@@ -0,0 +1,28 @@
<?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;
}
@@ -0,0 +1,81 @@
<?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')) {
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, array_values($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);
}
}
@@ -0,0 +1,22 @@
<?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',
];
}
@@ -0,0 +1,17 @@
<?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 = [
//
];
}