You've already forked Epicnabbo-Catalogus-Updated-Daily
🆙 Final fix delete storage link to fix news_images and logs 🆙
This commit is contained in:
-58
@@ -1,58 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Fortify\Controllers;
|
||||
|
||||
use Illuminate\Contracts\Auth\StatefulGuard;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Laravel\Fortify\Events\RecoveryCodeReplaced;
|
||||
use Laravel\Fortify\Http\Requests\TwoFactorLoginRequest;
|
||||
use Laravel\Fortify\Http\Responses\TwoFactorLoginResponse;
|
||||
|
||||
class TwoFactorAuthenticatedSessionController extends Controller
|
||||
{
|
||||
/**
|
||||
* The guard implementation.
|
||||
*
|
||||
* @var StatefulGuard
|
||||
*/
|
||||
protected $guard;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(StatefulGuard $guard)
|
||||
{
|
||||
$this->guard = $guard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to authenticate a new session using the two factor authentication code.
|
||||
*/
|
||||
public function store(TwoFactorLoginRequest $request): TwoFactorLoginResponse
|
||||
{
|
||||
$user = $request->challengedUser();
|
||||
|
||||
if ($code = $request->validRecoveryCode()) {
|
||||
$user->replaceRecoveryCode($code);
|
||||
|
||||
event(new RecoveryCodeReplaced($user, $code));
|
||||
} elseif (! $request->hasValidCode()) {
|
||||
throw ValidationException::withMessages([
|
||||
'code' => __('Invalid Two Factor Authentication code'),
|
||||
]);
|
||||
}
|
||||
|
||||
$this->guard->login($user, $request->remember());
|
||||
|
||||
$request->session()->regenerate();
|
||||
|
||||
$user->update([
|
||||
'ip_current' => $request->ip(),
|
||||
]);
|
||||
|
||||
return app(TwoFactorLoginResponse::class);
|
||||
}
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Fortify;
|
||||
|
||||
use App\Actions\Fortify\Rules\PasswordValidationRules;
|
||||
use App\Models\Miscellaneous\WebsiteBetaCode;
|
||||
use App\Models\User;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use App\Rules\BetaCodeRule;
|
||||
use App\Rules\GoogleRecaptchaRule;
|
||||
use App\Rules\WebsiteWordfilterRule;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Laravel\Fortify\Contracts\CreatesNewUsers;
|
||||
use RyanChandler\LaravelCloudflareTurnstile\Rules\Turnstile;
|
||||
|
||||
class CreateNewUser implements CreatesNewUsers
|
||||
{
|
||||
use PasswordValidationRules;
|
||||
|
||||
/**
|
||||
* Validate and create a newly registered user.
|
||||
*/
|
||||
public function create(array $input)
|
||||
{
|
||||
if (setting('disable_registration') ?: '0' === '1') {
|
||||
throw ValidationException::withMessages([
|
||||
'registration' => __('Registration is disabled.'),
|
||||
]);
|
||||
}
|
||||
|
||||
$ip = request()?->ip();
|
||||
if (! filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6)) {
|
||||
throw ValidationException::withMessages([
|
||||
'registration' => __('Your IP address seems to be invalid'),
|
||||
]);
|
||||
}
|
||||
|
||||
$matchingIpCount = User::query()
|
||||
->where('ip_current', '=', $ip)
|
||||
->orWhere('ip_register', '=', $ip)
|
||||
->count();
|
||||
|
||||
if ($matchingIpCount >= (int) (setting('max_accounts_per_ip') ?: 99)) {
|
||||
throw ValidationException::withMessages([
|
||||
'registration' => __('You have reached the max amount of allowed account'),
|
||||
]);
|
||||
}
|
||||
|
||||
$this->validate($input);
|
||||
|
||||
$user = User::create([
|
||||
'username' => $input['username'],
|
||||
'mail' => $input['mail'],
|
||||
'password' => Hash::make($input['password']),
|
||||
'account_created' => time(),
|
||||
'last_login' => time(),
|
||||
'motto' => setting('start_motto') ?: 'Welcome to the hotel!',
|
||||
'look' => setting('start_look') ?: 'hr-100-61.hd-180-1.ch-210-66.lg-270-110.sh-305-62',
|
||||
'credits' => setting('start_credits') ?: 1000,
|
||||
'ip_register' => $ip,
|
||||
'ip_current' => $ip,
|
||||
'auth_ticket' => '',
|
||||
'home_room' => (int) (setting('hotel_home_room') ?: 0),
|
||||
]);
|
||||
|
||||
$user->update([
|
||||
'referral_code' => sprintf('%s%s', $user->id, Str::random(8)),
|
||||
]);
|
||||
|
||||
if (setting('requires_beta_code') !== '' && setting('requires_beta_code') !== '0') {
|
||||
WebsiteBetaCode::where('code', '=', $input['beta_code'])->update([
|
||||
'user_id' => $user->id,
|
||||
]);
|
||||
}
|
||||
|
||||
// Referral
|
||||
if (isset($input['referral_code'])) {
|
||||
$referralUser = User::query()
|
||||
->where('referral_code', '=', $input['referral_code'])
|
||||
->first();
|
||||
|
||||
if (is_null($referralUser)) {
|
||||
return redirect(RouteServiceProvider::HOME);
|
||||
}
|
||||
|
||||
// If same IP skip referral incrementation
|
||||
if ($referralUser->ip_current == $user->ip_current || $referralUser->ip_register == $user->ip_register) {
|
||||
return redirect(RouteServiceProvider::HOME);
|
||||
}
|
||||
|
||||
$referralUser->referrals()->updateOrCreate(['user_id' => $referralUser->id], [
|
||||
'referrals_total' => $referralUser->referrals != null ? $referralUser->referrals->referrals_total += 1 : 1,
|
||||
]);
|
||||
|
||||
$referralUser->userReferrals()->create([
|
||||
'referred_user_id' => $user->id,
|
||||
'referred_user_ip' => $ip,
|
||||
]);
|
||||
}
|
||||
|
||||
if (setting('enable_discord_webhook') === '1') {
|
||||
$this->sendDiscordWebhook($user->username, $user->ip_register, $user->mail);
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
private function validate(array $inputs): array
|
||||
{
|
||||
$rules = [
|
||||
'username' => ['required', 'string', sprintf('regex:%s', setting('username_regex') ?: '/^[a-zA-Z0-9_.-]+$/'), 'max:25', Rule::unique('users'), new WebsiteWordfilterRule],
|
||||
'mail' => ['required', 'string', 'email', 'max:255', Rule::unique('users')],
|
||||
'password' => $this->passwordRules(),
|
||||
'beta_code' => ['sometimes', 'string', new BetaCodeRule],
|
||||
'terms' => ['required', 'accepted'],
|
||||
'g-recaptcha-response' => ['sometimes', 'string', new GoogleRecaptchaRule],
|
||||
'cf-turnstile-response' => [app(Turnstile::class)],
|
||||
];
|
||||
|
||||
$messages = [
|
||||
'g-recaptcha-response.required' => __('The Google recaptcha must be completed'),
|
||||
'g-recaptcha-response.string' => __('The google recaptcha was submitted with an invalid type'),
|
||||
];
|
||||
|
||||
return Validator::make($inputs, $rules, $messages)->validate();
|
||||
}
|
||||
|
||||
private function sendDiscordWebhook(string $username, string $ip, string $email): void
|
||||
{
|
||||
if (setting('discord_webhook_url') === '') {
|
||||
Log::error('Discord webhook url not provided', ['Please provide a discord webhook url before being able to send any webhook requests.']);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$request = Http::asJson()->post(setting('discord_webhook_url'), [
|
||||
'username' => sprintf('%s Bot', setting('hotel_name')),
|
||||
'content' => "User: {$username} has just registered, with the IP: {$ip} and E-mail: {$email}",
|
||||
]);
|
||||
|
||||
// Log the error in-case webhook wasn't sent
|
||||
if (! $request->successful()) {
|
||||
Log::error('Failed to send Discord webhook notification', [
|
||||
'username' => $username,
|
||||
'ip' => $ip,
|
||||
'email' => $email,
|
||||
'response_status' => $request->status(),
|
||||
'response_body' => $request->body(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Fortify;
|
||||
|
||||
class DisableTwoFactorAuthentication extends \Laravel\Fortify\Actions\DisableTwoFactorAuthentication
|
||||
{
|
||||
#[\Override]
|
||||
public function __invoke($user)
|
||||
{
|
||||
$user->forceFill([
|
||||
'two_factor_secret' => null,
|
||||
'two_factor_recovery_codes' => null,
|
||||
'two_factor_confirmed' => false,
|
||||
])->save();
|
||||
}
|
||||
}
|
||||
@@ -1,194 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Fortify;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Rules\GoogleRecaptchaRule;
|
||||
use Illuminate\Auth\Events\Failed;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use Illuminate\Contracts\Auth\StatefulGuard;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Laravel\Fortify\Events\TwoFactorAuthenticationChallenged;
|
||||
use Laravel\Fortify\Fortify;
|
||||
use Laravel\Fortify\LoginRateLimiter;
|
||||
use Laravel\Fortify\TwoFactorAuthenticatable;
|
||||
use RyanChandler\LaravelCloudflareTurnstile\Rules\Turnstile;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class RedirectIfTwoFactorAuthenticatable
|
||||
{
|
||||
/**
|
||||
* The guard implementation.
|
||||
*
|
||||
* @var StatefulGuard
|
||||
*/
|
||||
protected $guard;
|
||||
|
||||
/**
|
||||
* The login rate limiter instance.
|
||||
*
|
||||
* @var LoginRateLimiter
|
||||
*/
|
||||
protected $limiter;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(StatefulGuard $guard, LoginRateLimiter $limiter)
|
||||
{
|
||||
$this->guard = $guard;
|
||||
$this->limiter = $limiter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the incoming request.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, callable $next)
|
||||
{
|
||||
$user = $this->validateCredentials($request);
|
||||
|
||||
if (Fortify::confirmsTwoFactorAuthentication()) {
|
||||
if ($user?->two_factor_secret &&
|
||||
! is_null($user?->two_factor_confirmed_at) &&
|
||||
in_array(TwoFactorAuthenticatable::class, class_uses_recursive($user))) {
|
||||
return $this->twoFactorChallengeResponse($request, $user);
|
||||
} else {
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
|
||||
if ($user?->two_factor_secret &&
|
||||
in_array(TwoFactorAuthenticatable::class, class_uses_recursive($user))) {
|
||||
return $this->twoFactorChallengeResponse($request, $user);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to validate the incoming credentials.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function validateCredentials(Request $request)
|
||||
{
|
||||
if (Fortify::$authenticateUsingCallback) {
|
||||
return tap(call_user_func(Fortify::$authenticateUsingCallback, $request), function ($user) use ($request): void {
|
||||
if (! $user) {
|
||||
$this->fireFailedEvent($request);
|
||||
|
||||
$this->throwFailedAuthenticationException($request);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$model = $this->guard->getProvider()->getModel();
|
||||
|
||||
return tap($model::where(Fortify::username(), $request->{Fortify::username()})->first(), function ($user) use ($request): void {
|
||||
// Update the users password to bcrypt, if they previously used md5
|
||||
if ($user && config('habbo.site.convert_passwords')) {
|
||||
$this->convertUserPassword($user, $request->input('password'));
|
||||
}
|
||||
|
||||
if (! $user || ! $this->guard->getProvider()->validateCredentials($user, ['password' => $request->password])) {
|
||||
$this->fireFailedEvent($request, $user);
|
||||
|
||||
$this->throwFailedAuthenticationException($request);
|
||||
}
|
||||
|
||||
$this->validate($request);
|
||||
|
||||
$user = User::select('id', 'password', 'rank')
|
||||
->where('username', '=', $request->input('username'))
|
||||
->first();
|
||||
|
||||
if (setting('maintenance_enabled') === '1' && setting('min_maintenance_login_rank') > $user->rank) {
|
||||
throw ValidationException::withMessages([
|
||||
'username' => __('Only staff can login during maintenance!'),
|
||||
]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw a failed authentication validation exception.
|
||||
*
|
||||
*
|
||||
* @throws ValidationException
|
||||
*/
|
||||
protected function throwFailedAuthenticationException(Request $request): void
|
||||
{
|
||||
$this->limiter->increment($request);
|
||||
|
||||
throw ValidationException::withMessages([
|
||||
Fortify::username() => [trans('auth.failed')],
|
||||
])->errorBag('login');
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire the failed authentication attempt event with the given arguments.
|
||||
*/
|
||||
protected function fireFailedEvent(Request $request, ?Authenticatable $user = null): void
|
||||
{
|
||||
event(new Failed(config('fortify.guard'), $user, [
|
||||
Fortify::username() => $request->{Fortify::username()},
|
||||
'password' => $request->password,
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the two factor authentication enabled response.
|
||||
*
|
||||
* @param mixed $user
|
||||
*/
|
||||
protected function twoFactorChallengeResponse(Request $request, $user): Response
|
||||
{
|
||||
$request->session()->put([
|
||||
'login.id' => $user->getKey(),
|
||||
'login.remember' => $request->filled('remember'),
|
||||
]);
|
||||
|
||||
event(new \Laravel\Fortify\Events\TwoFactorAuthenticationChallenged($user));
|
||||
|
||||
return $request->wantsJson()
|
||||
? response()->json(['two_factor' => true])
|
||||
: to_route('two-factor.login');
|
||||
}
|
||||
|
||||
private function convertUserPassword(User $user, string $password)
|
||||
{
|
||||
if ($user->password == md5($password)) {
|
||||
$user->update([
|
||||
'password' => Hash::make($password),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
private function validate(Request $request): array
|
||||
{
|
||||
$rules = [];
|
||||
|
||||
if (setting('google_recaptcha_enabled') !== '' && setting('google_recaptcha_enabled') !== '0') {
|
||||
$rules['g-recaptcha-response'] = ['required', 'string', new GoogleRecaptchaRule];
|
||||
}
|
||||
|
||||
if (setting('cloudflare_turnstile_enabled') !== '' && setting('cloudflare_turnstile_enabled') !== '0') {
|
||||
$rules['cf-turnstile-response'] = ['required', app(Turnstile::class)];
|
||||
}
|
||||
|
||||
$messages = [
|
||||
'g-recaptcha-response.required' => __('The Google reCAPTCHA must be completed'),
|
||||
'g-recaptcha-response.string' => __('The Google reCAPTCHA was submitted with an invalid type'),
|
||||
'cf-turnstile-response.required' => __('The Cloudflare Turnstile response is required'),
|
||||
];
|
||||
|
||||
return Validator::make($request->all(), $rules, $messages)->validate();
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Fortify;
|
||||
|
||||
use Laravel\Fortify\Actions\RedirectIfTwoFactorAuthenticatable;
|
||||
|
||||
class RedirectIfTwoFactorConfirmed extends RedirectIfTwoFactorAuthenticatable
|
||||
{
|
||||
// This class can use the default behavior from the parent class
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Fortify;
|
||||
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Laravel\Fortify\Contracts\ResetsUserPasswords;
|
||||
|
||||
class ResetUserPassword implements ResetsUserPasswords
|
||||
{
|
||||
use PasswordValidationRules;
|
||||
|
||||
/**
|
||||
* Validate and reset the user's forgotten password.
|
||||
*
|
||||
* @param mixed $user
|
||||
*/
|
||||
public function reset($user, array $input): void
|
||||
{
|
||||
Validator::make($input, [
|
||||
'password' => $this->passwordRules(),
|
||||
])->validate();
|
||||
|
||||
$user->forceFill([
|
||||
'password' => Hash::make($input['password']),
|
||||
])->save();
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Fortify\Rules;
|
||||
|
||||
use App\Rules\Password;
|
||||
|
||||
trait PasswordValidationRules
|
||||
{
|
||||
/**
|
||||
* Get the validation rules used to validate passwords.
|
||||
*/
|
||||
protected function passwordRules(): array
|
||||
{
|
||||
return ['required', 'string', new Password, 'confirmed'];
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Fortify;
|
||||
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Laravel\Fortify\Contracts\UpdatesUserPasswords;
|
||||
|
||||
class UpdateUserPassword implements UpdatesUserPasswords
|
||||
{
|
||||
use PasswordValidationRules;
|
||||
|
||||
/**
|
||||
* Validate and update the user's password.
|
||||
*
|
||||
* @param mixed $user
|
||||
*/
|
||||
public function update($user, array $input): void
|
||||
{
|
||||
Validator::make($input, [
|
||||
'current_password' => ['required', 'string', 'current_password:web'],
|
||||
'password' => $this->passwordRules(),
|
||||
], [
|
||||
'current_password.current_password' => __('The provided password does not match your current password.'),
|
||||
])->validateWithBag('updatePassword');
|
||||
|
||||
$user->forceFill([
|
||||
'password' => Hash::make($input['password']),
|
||||
])->save();
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Fortify;
|
||||
|
||||
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Laravel\Fortify\Contracts\UpdatesUserProfileInformation;
|
||||
|
||||
class UpdateUserProfileInformation implements UpdatesUserProfileInformation
|
||||
{
|
||||
/**
|
||||
* Validate and update the given user's profile information.
|
||||
*
|
||||
* @param mixed $user
|
||||
*/
|
||||
public function update($user, array $input): void
|
||||
{
|
||||
Validator::make($input, [
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
|
||||
'email' => [
|
||||
'required',
|
||||
'string',
|
||||
'email',
|
||||
'max:255',
|
||||
Rule::unique('users')->ignore($user->id),
|
||||
],
|
||||
])->validateWithBag('updateProfileInformation');
|
||||
|
||||
if ($input['email'] !== $user->email &&
|
||||
$user instanceof MustVerifyEmail) {
|
||||
$this->updateVerifiedUser($user, $input);
|
||||
} else {
|
||||
$user->forceFill([
|
||||
'name' => $input['name'],
|
||||
'email' => $input['email'],
|
||||
])->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the given verified user's profile information.
|
||||
*
|
||||
* @param mixed $user
|
||||
*/
|
||||
protected function updateVerifiedUser($user, array $input): void
|
||||
{
|
||||
$user->forceFill([
|
||||
'name' => $input['name'],
|
||||
'email' => $input['email'],
|
||||
'email_verified_at' => null,
|
||||
])->save();
|
||||
|
||||
$user->sendEmailVerificationNotification();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user