Update all the middlewares
This commit is contained in:
parent
e0d03513e4
commit
79decafdc8
|
@ -28,6 +28,7 @@ This project follows [Semantic Versioning](http://semver.org) guidelines.
|
||||||
* Server creation page now only asks for a node to deploy to, rather than requiring a location and then a node.
|
* Server creation page now only asks for a node to deploy to, rather than requiring a location and then a node.
|
||||||
* Database passwords are now hidden by default and will only show if clicked on. In addition, database view in ACP now indicates that passwords must be viewed on the front-end.
|
* Database passwords are now hidden by default and will only show if clicked on. In addition, database view in ACP now indicates that passwords must be viewed on the front-end.
|
||||||
* Localhost cannot be used as a connection address in the environment configuration script. `127.0.0.1` is allowed.
|
* Localhost cannot be used as a connection address in the environment configuration script. `127.0.0.1` is allowed.
|
||||||
|
* Application locale can now be quickly set using an environment variable `APP_LOCALE` rather than having to edit core files.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
* Unable to change the daemon secret for a server via the Admin CP.
|
* Unable to change the daemon secret for a server via the Admin CP.
|
||||||
|
|
|
@ -6,6 +6,7 @@ use Pterodactyl\Http\Middleware\DaemonAuthenticate;
|
||||||
use Illuminate\Foundation\Http\Kernel as HttpKernel;
|
use Illuminate\Foundation\Http\Kernel as HttpKernel;
|
||||||
use Illuminate\Routing\Middleware\SubstituteBindings;
|
use Illuminate\Routing\Middleware\SubstituteBindings;
|
||||||
use Pterodactyl\Http\Middleware\AccessingValidServer;
|
use Pterodactyl\Http\Middleware\AccessingValidServer;
|
||||||
|
use Pterodactyl\Http\Middleware\Server\AuthenticateAsSubuser;
|
||||||
use Pterodactyl\Http\Middleware\Server\SubuserBelongsToServer;
|
use Pterodactyl\Http\Middleware\Server\SubuserBelongsToServer;
|
||||||
use Pterodactyl\Http\Middleware\Server\DatabaseBelongsToServer;
|
use Pterodactyl\Http\Middleware\Server\DatabaseBelongsToServer;
|
||||||
use Pterodactyl\Http\Middleware\Server\ScheduleBelongsToServer;
|
use Pterodactyl\Http\Middleware\Server\ScheduleBelongsToServer;
|
||||||
|
@ -66,7 +67,7 @@ class Kernel extends HttpKernel
|
||||||
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
|
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
|
||||||
'guest' => \Pterodactyl\Http\Middleware\RedirectIfAuthenticated::class,
|
'guest' => \Pterodactyl\Http\Middleware\RedirectIfAuthenticated::class,
|
||||||
'server' => AccessingValidServer::class,
|
'server' => AccessingValidServer::class,
|
||||||
'subuser.auth' => \Pterodactyl\Http\Middleware\SubuserAccessAuthenticate::class,
|
'subuser.auth' => AuthenticateAsSubuser::class,
|
||||||
'admin' => \Pterodactyl\Http\Middleware\AdminAuthenticate::class,
|
'admin' => \Pterodactyl\Http\Middleware\AdminAuthenticate::class,
|
||||||
'daemon-old' => DaemonAuthenticate::class,
|
'daemon-old' => DaemonAuthenticate::class,
|
||||||
'csrf' => \Pterodactyl\Http\Middleware\VerifyCsrfToken::class,
|
'csrf' => \Pterodactyl\Http\Middleware\VerifyCsrfToken::class,
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
namespace Pterodactyl\Http\Middleware;
|
namespace Pterodactyl\Http\Middleware;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||||
|
|
||||||
class AdminAuthenticate
|
class AdminAuthenticate
|
||||||
{
|
{
|
||||||
|
@ -20,18 +22,10 @@ class AdminAuthenticate
|
||||||
* @param \Closure $next
|
* @param \Closure $next
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function handle($request, Closure $next)
|
public function handle(Request $request, Closure $next)
|
||||||
{
|
{
|
||||||
if (! $request->user()) {
|
if (! $request->user() || ! $request->user()->root_admin) {
|
||||||
if ($request->expectsJson() || $request->json()) {
|
throw new HttpException(403, 'Access Denied');
|
||||||
return response('Unauthorized.', 401);
|
|
||||||
} else {
|
|
||||||
return redirect()->guest('auth/login');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! $request->user()->root_admin) {
|
|
||||||
return abort(403);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace Pterodactyl\Http\Middleware;
|
namespace Pterodactyl\Http\Middleware;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Contracts\Auth\Guard;
|
use Illuminate\Contracts\Auth\Guard;
|
||||||
|
|
||||||
class Authenticate
|
class Authenticate
|
||||||
|
@ -31,7 +32,7 @@ class Authenticate
|
||||||
* @param \Closure $next
|
* @param \Closure $next
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function handle($request, Closure $next)
|
public function handle(Request $request, Closure $next)
|
||||||
{
|
{
|
||||||
if ($this->auth->guest()) {
|
if ($this->auth->guest()) {
|
||||||
if ($request->ajax()) {
|
if ($request->ajax()) {
|
||||||
|
|
|
@ -33,9 +33,12 @@ use Pterodactyl\Exceptions\Repository\RecordNotFoundException;
|
||||||
class DaemonAuthenticate
|
class DaemonAuthenticate
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
* Daemon routes that this middleware should be skipped on.
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $except = ['daemon.configuration'];
|
protected $except = [
|
||||||
|
'daemon.configuration',
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \Pterodactyl\Contracts\Repository\NodeRepositoryInterface
|
* @var \Pterodactyl\Contracts\Repository\NodeRepositoryInterface
|
||||||
|
@ -63,6 +66,10 @@ class DaemonAuthenticate
|
||||||
*/
|
*/
|
||||||
public function handle(Request $request, Closure $next)
|
public function handle(Request $request, Closure $next)
|
||||||
{
|
{
|
||||||
|
if (in_array($request->route()->getName(), $this->except)) {
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
|
||||||
$token = $request->bearerToken();
|
$token = $request->bearerToken();
|
||||||
|
|
||||||
if (is_null($token)) {
|
if (is_null($token)) {
|
||||||
|
|
|
@ -10,35 +10,36 @@
|
||||||
namespace Pterodactyl\Http\Middleware;
|
namespace Pterodactyl\Http\Middleware;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use Pterodactyl\Models\Node;
|
use Pterodactyl\Models\Node;
|
||||||
use Illuminate\Contracts\Auth\Guard;
|
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||||
|
use Pterodactyl\Contracts\Repository\NodeRepositoryInterface;
|
||||||
|
use Pterodactyl\Exceptions\Repository\RecordNotFoundException;
|
||||||
|
|
||||||
class DaemonAuthenticate
|
class DaemonAuthenticate
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* The Guard implementation.
|
|
||||||
*
|
|
||||||
* @var \Illuminate\Contracts\Auth\Guard
|
|
||||||
*/
|
|
||||||
protected $auth;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An array of route names to not apply this middleware to.
|
* An array of route names to not apply this middleware to.
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $except = [
|
private $except = [
|
||||||
'daemon.configuration',
|
'daemon.configuration',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Pterodactyl\Contracts\Repository\NodeRepositoryInterface
|
||||||
|
*/
|
||||||
|
private $repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new filter instance.
|
* Create a new filter instance.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Contracts\Auth\Guard $auth
|
* @param \Pterodactyl\Contracts\Repository\NodeRepositoryInterface $repository
|
||||||
*/
|
*/
|
||||||
public function __construct(Guard $auth)
|
public function __construct(NodeRepositoryInterface $repository)
|
||||||
{
|
{
|
||||||
$this->auth = $auth;
|
$this->repository = $repository;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,21 +49,24 @@ class DaemonAuthenticate
|
||||||
* @param \Closure $next
|
* @param \Closure $next
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function handle($request, Closure $next)
|
public function handle(Request $request, Closure $next)
|
||||||
{
|
{
|
||||||
if (in_array($request->route()->getName(), $this->except)) {
|
if (in_array($request->route()->getName(), $this->except)) {
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! $request->header('X-Access-Node')) {
|
if (! $request->header('X-Access-Node')) {
|
||||||
return abort(403);
|
throw new HttpException(403);
|
||||||
}
|
}
|
||||||
|
|
||||||
$node = Node::where('daemonSecret', $request->header('X-Access-Node'))->first();
|
try {
|
||||||
if (! $node) {
|
$node = $this->repository->findWhere(['daemonSecret' => $request->header('X-Access-Node')]);
|
||||||
return abort(401);
|
} catch (RecordNotFoundException $exception) {
|
||||||
|
throw new HttpException(401);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$request->attributes->set('node', $node);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,5 @@ class EncryptCookies extends BaseEncrypter
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $except = [
|
protected $except = [];
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,14 +9,28 @@
|
||||||
|
|
||||||
namespace Pterodactyl\Http\Middleware;
|
namespace Pterodactyl\Http\Middleware;
|
||||||
|
|
||||||
use Auth;
|
|
||||||
use Closure;
|
use Closure;
|
||||||
use Session;
|
use Illuminate\Http\Request;
|
||||||
use Settings;
|
|
||||||
use Illuminate\Support\Facades\App;
|
use Illuminate\Support\Facades\App;
|
||||||
|
use Illuminate\Contracts\Config\Repository;
|
||||||
|
|
||||||
class LanguageMiddleware
|
class LanguageMiddleware
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var \Illuminate\Contracts\Config\Repository
|
||||||
|
*/
|
||||||
|
private $config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LanguageMiddleware constructor.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Contracts\Config\Repository $config
|
||||||
|
*/
|
||||||
|
public function __construct(Repository $config)
|
||||||
|
{
|
||||||
|
$this->config = $config;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle an incoming request.
|
* Handle an incoming request.
|
||||||
*
|
*
|
||||||
|
@ -24,17 +38,9 @@ class LanguageMiddleware
|
||||||
* @param \Closure $next
|
* @param \Closure $next
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function handle($request, Closure $next)
|
public function handle(Request $request, Closure $next)
|
||||||
{
|
{
|
||||||
// if (Session::has('applocale')) {
|
App::setLocale($this->config->get('app.locale', 'en'));
|
||||||
// App::setLocale(Session::get('applocale'));
|
|
||||||
// } elseif (Auth::check() && isset(Auth::user()->language)) {
|
|
||||||
// Session::put('applocale', Auth::user()->language);
|
|
||||||
// App::setLocale(Auth::user()->language);
|
|
||||||
// } else {
|
|
||||||
// App::setLocale(Settings::get('default_language', 'en'));
|
|
||||||
// }
|
|
||||||
App::setLocale('en');
|
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,26 @@
|
||||||
namespace Pterodactyl\Http\Middleware;
|
namespace Pterodactyl\Http\Middleware;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Auth\AuthManager;
|
||||||
|
|
||||||
class RedirectIfAuthenticated
|
class RedirectIfAuthenticated
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var \Illuminate\Contracts\Auth\Guard
|
||||||
|
*/
|
||||||
|
private $authManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RedirectIfAuthenticated constructor.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Auth\AuthManager $authManager
|
||||||
|
*/
|
||||||
|
public function __construct(AuthManager $authManager)
|
||||||
|
{
|
||||||
|
$this->authManager = $authManager;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle an incoming request.
|
* Handle an incoming request.
|
||||||
*
|
*
|
||||||
|
@ -15,9 +31,9 @@ class RedirectIfAuthenticated
|
||||||
* @param string|null $guard
|
* @param string|null $guard
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function handle($request, Closure $next, $guard = null)
|
public function handle(Request $request, Closure $next, string $guard = null)
|
||||||
{
|
{
|
||||||
if (Auth::guard($guard)->check()) {
|
if ($this->authManager->guard($guard)->check()) {
|
||||||
return redirect(route('index'));
|
return redirect(route('index'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
namespace Pterodactyl\Http\Middleware;
|
namespace Pterodactyl\Http\Middleware;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use Krucas\Settings\Settings;
|
use Krucas\Settings\Settings;
|
||||||
use Prologue\Alerts\AlertsMessageBag;
|
use Prologue\Alerts\AlertsMessageBag;
|
||||||
|
|
||||||
|
@ -22,28 +23,35 @@ class RequireTwoFactorAuthentication
|
||||||
/**
|
/**
|
||||||
* @var \Prologue\Alerts\AlertsMessageBag
|
* @var \Prologue\Alerts\AlertsMessageBag
|
||||||
*/
|
*/
|
||||||
protected $alert;
|
private $alert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \Krucas\Settings\Settings
|
* @var \Krucas\Settings\Settings
|
||||||
*/
|
*/
|
||||||
protected $settings;
|
private $settings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All TOTP related routes.
|
* The names of routes that should be accessable without 2FA enabled.
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $ignoreRoutes = [
|
protected $except = [
|
||||||
'account.security',
|
'account.security',
|
||||||
'account.security.revoke',
|
'account.security.revoke',
|
||||||
'account.security.totp',
|
'account.security.totp',
|
||||||
'account.security.totp.set',
|
'account.security.totp.set',
|
||||||
'account.security.totp.disable',
|
'account.security.totp.disable',
|
||||||
'auth.totp',
|
'auth.totp',
|
||||||
'auth.logout',
|
'auth.logout',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The route to redirect a user to to enable 2FA.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $redirectRoute = 'account.security';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RequireTwoFactorAuthentication constructor.
|
* RequireTwoFactorAuthentication constructor.
|
||||||
*
|
*
|
||||||
|
@ -63,7 +71,7 @@ class RequireTwoFactorAuthentication
|
||||||
* @param \Closure $next
|
* @param \Closure $next
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function handle($request, Closure $next)
|
public function handle(Request $request, Closure $next)
|
||||||
{
|
{
|
||||||
// Ignore non-users
|
// Ignore non-users
|
||||||
if (! $request->user()) {
|
if (! $request->user()) {
|
||||||
|
@ -71,7 +79,7 @@ class RequireTwoFactorAuthentication
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip the 2FA pages
|
// Skip the 2FA pages
|
||||||
if (in_array($request->route()->getName(), $this->ignoreRoutes)) {
|
if (in_array($request->route()->getName(), $this->except)) {
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,8 +101,8 @@ class RequireTwoFactorAuthentication
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->alert->danger('The administrator has required 2FA to be enabled. You must enable it before you can do any other action.')->flash();
|
$this->alert->danger(trans('auth.2fa_must_be_enabled'))->flash();
|
||||||
|
|
||||||
return redirect()->route('account.security');
|
return redirect()->route($this->redirectRoute);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* https://opensource.org/licenses/MIT
|
* https://opensource.org/licenses/MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace Pterodactyl\Http\Middleware;
|
namespace Pterodactyl\Http\Middleware\Server;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
@ -16,17 +16,17 @@ use Illuminate\Auth\AuthenticationException;
|
||||||
use Pterodactyl\Services\DaemonKeys\DaemonKeyProviderService;
|
use Pterodactyl\Services\DaemonKeys\DaemonKeyProviderService;
|
||||||
use Pterodactyl\Exceptions\Repository\RecordNotFoundException;
|
use Pterodactyl\Exceptions\Repository\RecordNotFoundException;
|
||||||
|
|
||||||
class SubuserAccessAuthenticate
|
class AuthenticateAsSubuser
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var \Pterodactyl\Services\DaemonKeys\DaemonKeyProviderService
|
* @var \Pterodactyl\Services\DaemonKeys\DaemonKeyProviderService
|
||||||
*/
|
*/
|
||||||
protected $keyProviderService;
|
private $keyProviderService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \Illuminate\Contracts\Session\Session
|
* @var \Illuminate\Contracts\Session\Session
|
||||||
*/
|
*/
|
||||||
protected $session;
|
private $session;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SubuserAccessAuthenticate constructor.
|
* SubuserAccessAuthenticate constructor.
|
||||||
|
@ -34,10 +34,8 @@ class SubuserAccessAuthenticate
|
||||||
* @param \Pterodactyl\Services\DaemonKeys\DaemonKeyProviderService $keyProviderService
|
* @param \Pterodactyl\Services\DaemonKeys\DaemonKeyProviderService $keyProviderService
|
||||||
* @param \Illuminate\Contracts\Session\Session $session
|
* @param \Illuminate\Contracts\Session\Session $session
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(DaemonKeyProviderService $keyProviderService, Session $session)
|
||||||
DaemonKeyProviderService $keyProviderService,
|
{
|
||||||
Session $session
|
|
||||||
) {
|
|
||||||
$this->keyProviderService = $keyProviderService;
|
$this->keyProviderService = $keyProviderService;
|
||||||
$this->session = $session;
|
$this->session = $session;
|
||||||
}
|
}
|
||||||
|
@ -55,16 +53,17 @@ class SubuserAccessAuthenticate
|
||||||
*/
|
*/
|
||||||
public function handle(Request $request, Closure $next)
|
public function handle(Request $request, Closure $next)
|
||||||
{
|
{
|
||||||
$server = $this->session->get('server_data.model');
|
$server = $request->attributes->get('server');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$token = $this->keyProviderService->handle($server->id, $request->user()->id);
|
$token = $this->keyProviderService->handle($server->id, $request->user()->id);
|
||||||
$this->session->now('server_data.token', $token);
|
|
||||||
$request->attributes->set('server_token', $token);
|
|
||||||
} catch (RecordNotFoundException $exception) {
|
} catch (RecordNotFoundException $exception) {
|
||||||
throw new AuthenticationException('This account does not have permission to access this server.');
|
throw new AuthenticationException('This account does not have permission to access this server.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->session->now('server_data.token', $token);
|
||||||
|
$request->attributes->set('server_token', $token);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
namespace Pterodactyl\Http\Middleware\Server;
|
namespace Pterodactyl\Http\Middleware\Server;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use Pterodactyl\Contracts\Extensions\HashidsInterface;
|
use Pterodactyl\Contracts\Extensions\HashidsInterface;
|
||||||
use Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface;
|
use Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface;
|
||||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
@ -41,7 +42,7 @@ class ScheduleBelongsToServer
|
||||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||||
*/
|
*/
|
||||||
public function handle($request, Closure $next)
|
public function handle(Request $request, Closure $next)
|
||||||
{
|
{
|
||||||
$server = $request->attributes->get('server');
|
$server = $request->attributes->get('server');
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace Pterodactyl\Http\Middleware\Server;
|
namespace Pterodactyl\Http\Middleware\Server;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use Pterodactyl\Exceptions\DisplayException;
|
use Pterodactyl\Exceptions\DisplayException;
|
||||||
use Pterodactyl\Contracts\Extensions\HashidsInterface;
|
use Pterodactyl\Contracts\Extensions\HashidsInterface;
|
||||||
use Pterodactyl\Contracts\Repository\SubuserRepositoryInterface;
|
use Pterodactyl\Contracts\Repository\SubuserRepositoryInterface;
|
||||||
|
@ -43,7 +44,7 @@ class SubuserBelongsToServer
|
||||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||||
*/
|
*/
|
||||||
public function handle($request, Closure $next)
|
public function handle(Request $request, Closure $next)
|
||||||
{
|
{
|
||||||
$server = $request->attributes->get('server');
|
$server = $request->attributes->get('server');
|
||||||
|
|
||||||
|
|
|
@ -3,28 +3,46 @@
|
||||||
namespace Pterodactyl\Http\Middleware;
|
namespace Pterodactyl\Http\Middleware;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use Pterodactyl\Events\Auth\FailedCaptcha;
|
use Pterodactyl\Events\Auth\FailedCaptcha;
|
||||||
|
use Illuminate\Contracts\Config\Repository;
|
||||||
|
|
||||||
class VerifyReCaptcha
|
class VerifyReCaptcha
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var \Illuminate\Contracts\Config\Repository
|
||||||
|
*/
|
||||||
|
private $config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VerifyReCaptcha constructor.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Contracts\Config\Repository $config
|
||||||
|
*/
|
||||||
|
public function __construct(Repository $config)
|
||||||
|
{
|
||||||
|
$this->config = $config;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle an incoming request.
|
* Handle an incoming request.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @param \Closure $next
|
* @param \Closure $next
|
||||||
* @return \Illuminate\Http\RediectResponse
|
* @return \Illuminate\Http\RedirectResponse|mixed
|
||||||
*/
|
*/
|
||||||
public function handle($request, Closure $next)
|
public function handle($request, Closure $next)
|
||||||
{
|
{
|
||||||
if (! config('recaptcha.enabled')) {
|
if (! $this->config->get('recaptcha.enabled')) {
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->has('g-recaptcha-response')) {
|
if ($request->has('g-recaptcha-response')) {
|
||||||
$client = new \GuzzleHttp\Client();
|
$client = new Client();
|
||||||
$res = $client->post(config('recaptcha.domain'), [
|
$res = $client->post($this->config->get('recaptcha.domain'), [
|
||||||
'form_params' => [
|
'form_params' => [
|
||||||
'secret' => config('recaptcha.secret_key'),
|
'secret' => $this->config->get('recaptcha.secret_key'),
|
||||||
'response' => $request->input('g-recaptcha-response'),
|
'response' => $request->input('g-recaptcha-response'),
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
@ -32,29 +50,33 @@ class VerifyReCaptcha
|
||||||
if ($res->getStatusCode() === 200) {
|
if ($res->getStatusCode() === 200) {
|
||||||
$result = json_decode($res->getBody());
|
$result = json_decode($res->getBody());
|
||||||
|
|
||||||
$verified = function ($result, $request) {
|
if ($result->success && (! $this->config->get('recaptcha.verify_domain') || $this->isResponseVerified($result, $request))) {
|
||||||
if (! config('recaptcha.verify_domain')) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$url = parse_url($request->url());
|
|
||||||
|
|
||||||
if (! array_key_exists('host', $url)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result->hostname === $url['host'];
|
|
||||||
};
|
|
||||||
|
|
||||||
if ($result->success && (! config('recaptcha.verify_domain') || $verified($result, $request))) {
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit an event and return to the previous view with an error (only the captcha error will be shown!)
|
// Emit an event and return to the previous view with an error (only the captcha error will be shown!)
|
||||||
event(new FailedCaptcha($request->ip(), (! isset($result->hostname) ?: $result->hostname)));
|
event(new FailedCaptcha($request->ip(), (! isset($result) ?: object_get($result, 'hostname'))));
|
||||||
|
|
||||||
return back()->withErrors(['g-recaptcha-response' => trans('strings.captcha_invalid')])->withInput();
|
return redirect()->back()->withErrors(['g-recaptcha-response' => trans('strings.captcha_invalid')])->withInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the response from the recaptcha servers was valid.
|
||||||
|
*
|
||||||
|
* @param object $result
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function isResponseVerified(object $result, Request $request): bool
|
||||||
|
{
|
||||||
|
if (! $this->config->get('recaptcha.verify_domain')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$url = parse_url($request->url());
|
||||||
|
|
||||||
|
return $result->hostname === array_get($url, 'host');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ return [
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'locale' => 'en',
|
'locale' => env('APP_LOCALE', 'en'),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
@ -18,4 +18,5 @@ return [
|
||||||
'2fa_required' => '2-Factor Authentication',
|
'2fa_required' => '2-Factor Authentication',
|
||||||
'2fa_failed' => 'The 2FA token provided was invalid.',
|
'2fa_failed' => 'The 2FA token provided was invalid.',
|
||||||
'totp_failed' => 'There was an error while attempting to validate TOTP.',
|
'totp_failed' => 'There was an error while attempting to validate TOTP.',
|
||||||
|
'2fa_must_be_enabled' => 'The administrator has required that 2-Factor Authentication be enabled for your account in order to use the Panel.',
|
||||||
];
|
];
|
||||||
|
|
Loading…
Reference in New Issue