mirror of
https://github.com/flarum/core.git
synced 2025-07-23 09:41:26 +02:00
WIP sudo mode, better error responses
This commit is contained in:
@@ -10,38 +10,22 @@
|
|||||||
|
|
||||||
namespace Flarum\Admin\Middleware;
|
namespace Flarum\Admin\Middleware;
|
||||||
|
|
||||||
use Flarum\Core\Access\Gate;
|
use Flarum\Core\Access\AssertPermissionTrait;
|
||||||
use Illuminate\Contracts\Container\Container;
|
use Illuminate\Contracts\Container\Container;
|
||||||
use Psr\Http\Message\ResponseInterface as Response;
|
use Psr\Http\Message\ResponseInterface as Response;
|
||||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||||
use Flarum\Core\Exception\PermissionDeniedException;
|
|
||||||
use Zend\Stratigility\MiddlewareInterface;
|
use Zend\Stratigility\MiddlewareInterface;
|
||||||
|
|
||||||
class RequireAdministrateAbility implements MiddlewareInterface
|
class RequireAdministrateAbility implements MiddlewareInterface
|
||||||
{
|
{
|
||||||
/**
|
use AssertPermissionTrait;
|
||||||
* @var Gate
|
|
||||||
*/
|
|
||||||
protected $gate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Gate $gate
|
|
||||||
*/
|
|
||||||
public function __construct(Gate $gate)
|
|
||||||
{
|
|
||||||
$this->gate = $gate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function __invoke(Request $request, Response $response, callable $out = null)
|
public function __invoke(Request $request, Response $response, callable $out = null)
|
||||||
{
|
{
|
||||||
$actor = $request->getAttribute('actor');
|
$this->assertAdminAndSudo($request);
|
||||||
|
|
||||||
if (! $this->gate->forUser($actor)->allows('administrate')) {
|
|
||||||
throw new PermissionDeniedException;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $out ? $out($request, $response) : $response;
|
return $out ? $out($request, $response) : $response;
|
||||||
}
|
}
|
||||||
|
@@ -18,6 +18,7 @@ use DateTime;
|
|||||||
* @property int $user_id
|
* @property int $user_id
|
||||||
* @property \Carbon\Carbon $created_at
|
* @property \Carbon\Carbon $created_at
|
||||||
* @property \Carbon\Carbon $expires_at
|
* @property \Carbon\Carbon $expires_at
|
||||||
|
* @property \Carbon\Carbon $sudo_expires_at
|
||||||
* @property \Flarum\Core\User|null $user
|
* @property \Flarum\Core\User|null $user
|
||||||
*/
|
*/
|
||||||
class AccessToken extends AbstractModel
|
class AccessToken extends AbstractModel
|
||||||
@@ -37,7 +38,7 @@ class AccessToken extends AbstractModel
|
|||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
protected $dates = ['created_at', 'expires_at'];
|
protected $dates = ['created_at', 'expires_at', 'sudo_expires_at'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate an access token for the specified user.
|
* Generate an access token for the specified user.
|
||||||
@@ -54,6 +55,7 @@ class AccessToken extends AbstractModel
|
|||||||
$token->user_id = $userId;
|
$token->user_id = $userId;
|
||||||
$token->created_at = time();
|
$token->created_at = time();
|
||||||
$token->expires_at = time() + $minutes * 60;
|
$token->expires_at = time() + $minutes * 60;
|
||||||
|
$token->sudo_expires_at = time() + $minutes * 30;
|
||||||
|
|
||||||
return $token;
|
return $token;
|
||||||
}
|
}
|
||||||
@@ -68,6 +70,11 @@ class AccessToken extends AbstractModel
|
|||||||
return $this->expires_at > new DateTime;
|
return $this->expires_at > new DateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isSudo()
|
||||||
|
{
|
||||||
|
return $this->sudo_expires_at > new DateTime;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the relationship with the owner of this access token.
|
* Define the relationship with the owner of this access token.
|
||||||
*
|
*
|
||||||
|
@@ -45,8 +45,11 @@ class ApiServiceProvider extends AbstractServiceProvider
|
|||||||
$handler->registerHandler(new Handler\FloodingExceptionHandler);
|
$handler->registerHandler(new Handler\FloodingExceptionHandler);
|
||||||
$handler->registerHandler(new Handler\IlluminateValidationExceptionHandler);
|
$handler->registerHandler(new Handler\IlluminateValidationExceptionHandler);
|
||||||
$handler->registerHandler(new Handler\InvalidConfirmationTokenExceptionHandler);
|
$handler->registerHandler(new Handler\InvalidConfirmationTokenExceptionHandler);
|
||||||
|
$handler->registerHandler(new Handler\MethodNotAllowedExceptionHandler);
|
||||||
$handler->registerHandler(new Handler\ModelNotFoundExceptionHandler);
|
$handler->registerHandler(new Handler\ModelNotFoundExceptionHandler);
|
||||||
$handler->registerHandler(new Handler\PermissionDeniedExceptionHandler);
|
$handler->registerHandler(new Handler\PermissionDeniedExceptionHandler);
|
||||||
|
$handler->registerHandler(new Handler\RouteNotFoundExceptionHandler);
|
||||||
|
$handler->registerHandler(new Handler\SudoRequiredExceptionHandler);
|
||||||
$handler->registerHandler(new Handler\ValidationExceptionHandler);
|
$handler->registerHandler(new Handler\ValidationExceptionHandler);
|
||||||
$handler->registerHandler(new InvalidParameterExceptionHandler);
|
$handler->registerHandler(new InvalidParameterExceptionHandler);
|
||||||
$handler->registerHandler(new FallbackExceptionHandler($this->app->inDebugMode()));
|
$handler->registerHandler(new FallbackExceptionHandler($this->app->inDebugMode()));
|
||||||
|
@@ -10,12 +10,15 @@
|
|||||||
|
|
||||||
namespace Flarum\Api\Controller;
|
namespace Flarum\Api\Controller;
|
||||||
|
|
||||||
|
use Flarum\Core\Access\AssertPermissionTrait;
|
||||||
use Flarum\Core\Command\DeleteDiscussion;
|
use Flarum\Core\Command\DeleteDiscussion;
|
||||||
use Illuminate\Contracts\Bus\Dispatcher;
|
use Illuminate\Contracts\Bus\Dispatcher;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
|
||||||
class DeleteDiscussionController extends AbstractDeleteController
|
class DeleteDiscussionController extends AbstractDeleteController
|
||||||
{
|
{
|
||||||
|
use AssertPermissionTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Dispatcher
|
* @var Dispatcher
|
||||||
*/
|
*/
|
||||||
@@ -38,6 +41,8 @@ class DeleteDiscussionController extends AbstractDeleteController
|
|||||||
$actor = $request->getAttribute('actor');
|
$actor = $request->getAttribute('actor');
|
||||||
$input = $request->getParsedBody();
|
$input = $request->getParsedBody();
|
||||||
|
|
||||||
|
$this->assertSudo($request);
|
||||||
|
|
||||||
$this->bus->dispatch(
|
$this->bus->dispatch(
|
||||||
new DeleteDiscussion($id, $actor, $input)
|
new DeleteDiscussion($id, $actor, $input)
|
||||||
);
|
);
|
||||||
|
@@ -10,12 +10,15 @@
|
|||||||
|
|
||||||
namespace Flarum\Api\Controller;
|
namespace Flarum\Api\Controller;
|
||||||
|
|
||||||
|
use Flarum\Core\Access\AssertPermissionTrait;
|
||||||
use Flarum\Core\Command\DeleteGroup;
|
use Flarum\Core\Command\DeleteGroup;
|
||||||
use Illuminate\Contracts\Bus\Dispatcher;
|
use Illuminate\Contracts\Bus\Dispatcher;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
|
||||||
class DeleteGroupController extends AbstractDeleteController
|
class DeleteGroupController extends AbstractDeleteController
|
||||||
{
|
{
|
||||||
|
use AssertPermissionTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Dispatcher
|
* @var Dispatcher
|
||||||
*/
|
*/
|
||||||
@@ -34,6 +37,8 @@ class DeleteGroupController extends AbstractDeleteController
|
|||||||
*/
|
*/
|
||||||
protected function delete(ServerRequestInterface $request)
|
protected function delete(ServerRequestInterface $request)
|
||||||
{
|
{
|
||||||
|
$this->assertSudo($request);
|
||||||
|
|
||||||
$this->bus->dispatch(
|
$this->bus->dispatch(
|
||||||
new DeleteGroup(array_get($request->getQueryParams(), 'id'), $request->getAttribute('actor'))
|
new DeleteGroup(array_get($request->getQueryParams(), 'id'), $request->getAttribute('actor'))
|
||||||
);
|
);
|
||||||
|
@@ -10,12 +10,15 @@
|
|||||||
|
|
||||||
namespace Flarum\Api\Controller;
|
namespace Flarum\Api\Controller;
|
||||||
|
|
||||||
|
use Flarum\Core\Access\AssertPermissionTrait;
|
||||||
use Flarum\Core\Command\DeletePost;
|
use Flarum\Core\Command\DeletePost;
|
||||||
use Illuminate\Contracts\Bus\Dispatcher;
|
use Illuminate\Contracts\Bus\Dispatcher;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
|
||||||
class DeletePostController extends AbstractDeleteController
|
class DeletePostController extends AbstractDeleteController
|
||||||
{
|
{
|
||||||
|
use AssertPermissionTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Dispatcher
|
* @var Dispatcher
|
||||||
*/
|
*/
|
||||||
@@ -34,6 +37,8 @@ class DeletePostController extends AbstractDeleteController
|
|||||||
*/
|
*/
|
||||||
protected function delete(ServerRequestInterface $request)
|
protected function delete(ServerRequestInterface $request)
|
||||||
{
|
{
|
||||||
|
$this->assertSudo($request);
|
||||||
|
|
||||||
$this->bus->dispatch(
|
$this->bus->dispatch(
|
||||||
new DeletePost(array_get($request->getQueryParams(), 'id'), $request->getAttribute('actor'))
|
new DeletePost(array_get($request->getQueryParams(), 'id'), $request->getAttribute('actor'))
|
||||||
);
|
);
|
||||||
|
@@ -10,12 +10,15 @@
|
|||||||
|
|
||||||
namespace Flarum\Api\Controller;
|
namespace Flarum\Api\Controller;
|
||||||
|
|
||||||
|
use Flarum\Core\Access\AssertPermissionTrait;
|
||||||
use Flarum\Core\Command\DeleteUser;
|
use Flarum\Core\Command\DeleteUser;
|
||||||
use Illuminate\Contracts\Bus\Dispatcher;
|
use Illuminate\Contracts\Bus\Dispatcher;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
|
||||||
class DeleteUserController extends AbstractDeleteController
|
class DeleteUserController extends AbstractDeleteController
|
||||||
{
|
{
|
||||||
|
use AssertPermissionTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Dispatcher
|
* @var Dispatcher
|
||||||
*/
|
*/
|
||||||
@@ -34,6 +37,8 @@ class DeleteUserController extends AbstractDeleteController
|
|||||||
*/
|
*/
|
||||||
protected function delete(ServerRequestInterface $request)
|
protected function delete(ServerRequestInterface $request)
|
||||||
{
|
{
|
||||||
|
$this->assertSudo($request);
|
||||||
|
|
||||||
$this->bus->dispatch(
|
$this->bus->dispatch(
|
||||||
new DeleteUser(array_get($request->getQueryParams(), 'id'), $request->getAttribute('actor'))
|
new DeleteUser(array_get($request->getQueryParams(), 'id'), $request->getAttribute('actor'))
|
||||||
);
|
);
|
||||||
|
@@ -25,7 +25,7 @@ class SetPermissionController implements ControllerInterface
|
|||||||
*/
|
*/
|
||||||
public function handle(ServerRequestInterface $request)
|
public function handle(ServerRequestInterface $request)
|
||||||
{
|
{
|
||||||
$this->assertAdmin($request->getAttribute('actor'));
|
$this->assertAdminAndSudo($request);
|
||||||
|
|
||||||
$body = $request->getParsedBody();
|
$body = $request->getParsedBody();
|
||||||
$permission = array_get($body, 'permission');
|
$permission = array_get($body, 'permission');
|
||||||
|
@@ -47,7 +47,7 @@ class SetSettingsController implements ControllerInterface
|
|||||||
*/
|
*/
|
||||||
public function handle(ServerRequestInterface $request)
|
public function handle(ServerRequestInterface $request)
|
||||||
{
|
{
|
||||||
$this->assertAdmin($request->getAttribute('actor'));
|
$this->assertAdminAndSudo($request);
|
||||||
|
|
||||||
$settings = $request->getParsedBody();
|
$settings = $request->getParsedBody();
|
||||||
|
|
||||||
|
@@ -33,7 +33,7 @@ class UninstallExtensionController extends AbstractDeleteController
|
|||||||
|
|
||||||
protected function delete(ServerRequestInterface $request)
|
protected function delete(ServerRequestInterface $request)
|
||||||
{
|
{
|
||||||
$this->assertAdmin($request->getAttribute('actor'));
|
$this->assertAdminAndSudo($request);
|
||||||
|
|
||||||
$name = array_get($request->getQueryParams(), 'name');
|
$name = array_get($request->getQueryParams(), 'name');
|
||||||
|
|
||||||
|
@@ -38,7 +38,7 @@ class UpdateExtensionController implements ControllerInterface
|
|||||||
*/
|
*/
|
||||||
public function handle(ServerRequestInterface $request)
|
public function handle(ServerRequestInterface $request)
|
||||||
{
|
{
|
||||||
$this->assertAdmin($request->getAttribute('actor'));
|
$this->assertAdminAndSudo($request);
|
||||||
|
|
||||||
$enabled = array_get($request->getParsedBody(), 'enabled');
|
$enabled = array_get($request->getParsedBody(), 'enabled');
|
||||||
$name = array_get($request->getQueryParams(), 'name');
|
$name = array_get($request->getQueryParams(), 'name');
|
||||||
|
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Flarum\Api\Exception;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class InvalidAccessTokenException extends Exception
|
||||||
|
{
|
||||||
|
}
|
@@ -31,7 +31,10 @@ class FloodingExceptionHandler implements ExceptionHandlerInterface
|
|||||||
public function handle(Exception $e)
|
public function handle(Exception $e)
|
||||||
{
|
{
|
||||||
$status = 429;
|
$status = 429;
|
||||||
$error = [];
|
$error = [
|
||||||
|
'status' => (string) $status,
|
||||||
|
'code' => 'too_many_requests'
|
||||||
|
];
|
||||||
|
|
||||||
return new ResponseBag($status, [$error]);
|
return new ResponseBag($status, [$error]);
|
||||||
}
|
}
|
||||||
|
@@ -44,8 +44,10 @@ class IlluminateValidationExceptionHandler implements ExceptionHandlerInterface
|
|||||||
{
|
{
|
||||||
$errors = array_map(function ($field, $messages) {
|
$errors = array_map(function ($field, $messages) {
|
||||||
return [
|
return [
|
||||||
|
'status' => '422',
|
||||||
|
'code' => 'validation_error',
|
||||||
'detail' => implode("\n", $messages),
|
'detail' => implode("\n", $messages),
|
||||||
'source' => ['pointer' => '/data/attributes/' . $field],
|
'source' => ['pointer' => "/data/attributes/$field"]
|
||||||
];
|
];
|
||||||
}, array_keys($errors), $errors);
|
}, array_keys($errors), $errors);
|
||||||
|
|
||||||
|
@@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Flarum\Api\Handler;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Flarum\Api\Exception\InvalidAccessTokenException;
|
||||||
|
use Tobscure\JsonApi\Exception\Handler\ExceptionHandlerInterface;
|
||||||
|
use Tobscure\JsonApi\Exception\Handler\ResponseBag;
|
||||||
|
|
||||||
|
class InvalidAccessTokenExceptionHandler implements ExceptionHandlerInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function manages(Exception $e)
|
||||||
|
{
|
||||||
|
return $e instanceof InvalidAccessTokenException;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function handle(Exception $e)
|
||||||
|
{
|
||||||
|
$status = 401;
|
||||||
|
$error = [
|
||||||
|
'status' => (string) $status,
|
||||||
|
'code' => 'invalid_access_token'
|
||||||
|
];
|
||||||
|
|
||||||
|
return new ResponseBag($status, [$error]);
|
||||||
|
}
|
||||||
|
}
|
@@ -31,7 +31,10 @@ class InvalidConfirmationTokenExceptionHandler implements ExceptionHandlerInterf
|
|||||||
public function handle(Exception $e)
|
public function handle(Exception $e)
|
||||||
{
|
{
|
||||||
$status = 403;
|
$status = 403;
|
||||||
$error = ['code' => 'invalid_confirmation_token'];
|
$error = [
|
||||||
|
'status' => (string) $status,
|
||||||
|
'code' => 'invalid_confirmation_token'
|
||||||
|
];
|
||||||
|
|
||||||
return new ResponseBag($status, [$error]);
|
return new ResponseBag($status, [$error]);
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Flarum\Api\Handler;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Flarum\Http\Exception\MethodNotAllowedException;
|
||||||
|
use Tobscure\JsonApi\Exception\Handler\ExceptionHandlerInterface;
|
||||||
|
use Tobscure\JsonApi\Exception\Handler\ResponseBag;
|
||||||
|
|
||||||
|
class MethodNotAllowedExceptionHandler implements ExceptionHandlerInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function manages(Exception $e)
|
||||||
|
{
|
||||||
|
return $e instanceof MethodNotAllowedException;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function handle(Exception $e)
|
||||||
|
{
|
||||||
|
$status = 405;
|
||||||
|
$error = [
|
||||||
|
'status' => (string) $status,
|
||||||
|
'code' => 'method_not_allowed'
|
||||||
|
];
|
||||||
|
|
||||||
|
return new ResponseBag($status, [$error]);
|
||||||
|
}
|
||||||
|
}
|
@@ -11,6 +11,7 @@
|
|||||||
namespace Flarum\Api\Handler;
|
namespace Flarum\Api\Handler;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use Flarum\Http\Exception\RouteNotFoundException;
|
||||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||||
use Tobscure\JsonApi\Exception\Handler\ExceptionHandlerInterface;
|
use Tobscure\JsonApi\Exception\Handler\ExceptionHandlerInterface;
|
||||||
use Tobscure\JsonApi\Exception\Handler\ResponseBag;
|
use Tobscure\JsonApi\Exception\Handler\ResponseBag;
|
||||||
@@ -31,7 +32,10 @@ class ModelNotFoundExceptionHandler implements ExceptionHandlerInterface
|
|||||||
public function handle(Exception $e)
|
public function handle(Exception $e)
|
||||||
{
|
{
|
||||||
$status = 404;
|
$status = 404;
|
||||||
$error = [];
|
$error = [
|
||||||
|
'status' => '404',
|
||||||
|
'code' => 'resource_not_found'
|
||||||
|
];
|
||||||
|
|
||||||
return new ResponseBag($status, [$error]);
|
return new ResponseBag($status, [$error]);
|
||||||
}
|
}
|
||||||
|
@@ -31,7 +31,10 @@ class PermissionDeniedExceptionHandler implements ExceptionHandlerInterface
|
|||||||
public function handle(Exception $e)
|
public function handle(Exception $e)
|
||||||
{
|
{
|
||||||
$status = 401;
|
$status = 401;
|
||||||
$error = [];
|
$error = [
|
||||||
|
'status' => (string) $status,
|
||||||
|
'code' => 'permission_denied'
|
||||||
|
];
|
||||||
|
|
||||||
return new ResponseBag($status, [$error]);
|
return new ResponseBag($status, [$error]);
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Flarum\Api\Handler;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Flarum\Http\Exception\RouteNotFoundException;
|
||||||
|
use Tobscure\JsonApi\Exception\Handler\ExceptionHandlerInterface;
|
||||||
|
use Tobscure\JsonApi\Exception\Handler\ResponseBag;
|
||||||
|
|
||||||
|
class RouteNotFoundExceptionHandler implements ExceptionHandlerInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function manages(Exception $e)
|
||||||
|
{
|
||||||
|
return $e instanceof RouteNotFoundException;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function handle(Exception $e)
|
||||||
|
{
|
||||||
|
$status = 404;
|
||||||
|
$error = [
|
||||||
|
'status' => (string) $status,
|
||||||
|
'code' => 'route_not_found'
|
||||||
|
];
|
||||||
|
|
||||||
|
return new ResponseBag($status, [$error]);
|
||||||
|
}
|
||||||
|
}
|
@@ -33,10 +33,13 @@ class ValidationExceptionHandler implements ExceptionHandlerInterface
|
|||||||
$status = 422;
|
$status = 422;
|
||||||
|
|
||||||
$messages = $e->getMessages();
|
$messages = $e->getMessages();
|
||||||
$errors = array_map(function ($path, $detail) {
|
$errors = array_map(function ($path, $detail) use ($status) {
|
||||||
$source = ['pointer' => '/data/attributes/' . $path];
|
return [
|
||||||
|
'status' => (string) $status,
|
||||||
return compact('source', 'detail');
|
'code' => 'validation_error',
|
||||||
|
'detail' => $detail,
|
||||||
|
'source' => ['pointer' => "/data/attributes/$path"]
|
||||||
|
];
|
||||||
}, array_keys($messages), $messages);
|
}, array_keys($messages), $messages);
|
||||||
|
|
||||||
return new ResponseBag($status, $errors);
|
return new ResponseBag($status, $errors);
|
||||||
|
@@ -69,6 +69,8 @@ class AuthenticateWithHeader implements MiddlewareInterface
|
|||||||
$actor = $accessToken->user;
|
$actor = $accessToken->user;
|
||||||
|
|
||||||
$actor->updateLastSeen()->save();
|
$actor->updateLastSeen()->save();
|
||||||
|
|
||||||
|
$request = $request->withAttribute('sudo', $accessToken->isSudo());
|
||||||
} elseif (isset($parts[1]) && ($apiKey = ApiKey::valid($token))) {
|
} elseif (isset($parts[1]) && ($apiKey = ApiKey::valid($token))) {
|
||||||
$userParts = explode('=', trim($parts[1]));
|
$userParts = explode('=', trim($parts[1]));
|
||||||
|
|
||||||
|
@@ -10,8 +10,10 @@
|
|||||||
|
|
||||||
namespace Flarum\Core\Access;
|
namespace Flarum\Core\Access;
|
||||||
|
|
||||||
|
use Flarum\Api\Exception\InvalidAccessTokenException;
|
||||||
use Flarum\Core\Exception\PermissionDeniedException;
|
use Flarum\Core\Exception\PermissionDeniedException;
|
||||||
use Flarum\Core\User;
|
use Flarum\Core\User;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
|
||||||
trait AssertPermissionTrait
|
trait AssertPermissionTrait
|
||||||
{
|
{
|
||||||
@@ -61,6 +63,28 @@ trait AssertPermissionTrait
|
|||||||
*/
|
*/
|
||||||
protected function assertAdmin(User $actor)
|
protected function assertAdmin(User $actor)
|
||||||
{
|
{
|
||||||
$this->assertPermission($actor->isAdmin());
|
$this->assertCan($actor, 'administrate');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ServerRequestInterface $request
|
||||||
|
* @throws InvalidAccessTokenException
|
||||||
|
*/
|
||||||
|
protected function assertSudo(ServerRequestInterface $request)
|
||||||
|
{
|
||||||
|
if (! $request->getAttribute('sudo')) {
|
||||||
|
throw new InvalidAccessTokenException;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ServerRequestInterface $request
|
||||||
|
* @throws PermissionDeniedException
|
||||||
|
*/
|
||||||
|
protected function assertAdminAndSudo(ServerRequestInterface $request)
|
||||||
|
{
|
||||||
|
$this->assertAdmin($request->getAttribute('actor'));
|
||||||
|
|
||||||
|
$this->assertSudo($request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Flarum\Http\Exception;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class MethodNotAllowedException extends Exception
|
||||||
|
{
|
||||||
|
public function __construct($message = null, $code = 405, Exception $previous = null)
|
||||||
|
{
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
@@ -11,6 +11,7 @@
|
|||||||
namespace Flarum\Http\Middleware;
|
namespace Flarum\Http\Middleware;
|
||||||
|
|
||||||
use Flarum\Api\AccessToken;
|
use Flarum\Api\AccessToken;
|
||||||
|
use Flarum\Api\Exception\InvalidAccessTokenException;
|
||||||
use Flarum\Core\Guest;
|
use Flarum\Core\Guest;
|
||||||
use Flarum\Locale\LocaleManager;
|
use Flarum\Locale\LocaleManager;
|
||||||
use Psr\Http\Message\ResponseInterface as Response;
|
use Psr\Http\Message\ResponseInterface as Response;
|
||||||
@@ -47,6 +48,7 @@ class AuthenticateWithCookie implements MiddlewareInterface
|
|||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @return Request
|
* @return Request
|
||||||
|
* @throws InvalidAccessTokenException
|
||||||
*/
|
*/
|
||||||
protected function logIn(Request $request)
|
protected function logIn(Request $request)
|
||||||
{
|
{
|
||||||
@@ -54,9 +56,11 @@ class AuthenticateWithCookie implements MiddlewareInterface
|
|||||||
|
|
||||||
if ($token = $this->getToken($request)) {
|
if ($token = $this->getToken($request)) {
|
||||||
if (! $token->isValid()) {
|
if (! $token->isValid()) {
|
||||||
// TODO: https://github.com/flarum/core/issues/253
|
throw new InvalidAccessTokenException;
|
||||||
} elseif ($actor = $token->user) {
|
} elseif ($actor = $token->user) {
|
||||||
$actor->updateLastSeen()->save();
|
$actor->updateLastSeen()->save();
|
||||||
|
|
||||||
|
$request = $request->withAttribute('sudo', $token->isSudo());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -13,8 +13,9 @@ namespace Flarum\Http\Middleware;
|
|||||||
|
|
||||||
use FastRoute\Dispatcher;
|
use FastRoute\Dispatcher;
|
||||||
use FastRoute\RouteParser;
|
use FastRoute\RouteParser;
|
||||||
use Flarum\Http\RouteCollection;
|
use Flarum\Http\Exception\MethodNotAllowedException;
|
||||||
use Flarum\Http\Exception\RouteNotFoundException;
|
use Flarum\Http\Exception\RouteNotFoundException;
|
||||||
|
use Flarum\Http\RouteCollection;
|
||||||
use Psr\Http\Message\ResponseInterface as Response;
|
use Psr\Http\Message\ResponseInterface as Response;
|
||||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||||
|
|
||||||
@@ -47,6 +48,7 @@ class DispatchRoute
|
|||||||
* @param Response $response
|
* @param Response $response
|
||||||
* @param callable $out
|
* @param callable $out
|
||||||
* @return Response
|
* @return Response
|
||||||
|
* @throws MethodNotAllowedException
|
||||||
* @throws RouteNotFoundException
|
* @throws RouteNotFoundException
|
||||||
*/
|
*/
|
||||||
public function __invoke(Request $request, Response $response, callable $out = null)
|
public function __invoke(Request $request, Response $response, callable $out = null)
|
||||||
@@ -58,8 +60,11 @@ class DispatchRoute
|
|||||||
|
|
||||||
switch ($routeInfo[0]) {
|
switch ($routeInfo[0]) {
|
||||||
case Dispatcher::NOT_FOUND:
|
case Dispatcher::NOT_FOUND:
|
||||||
case Dispatcher::METHOD_NOT_ALLOWED:
|
|
||||||
throw new RouteNotFoundException;
|
throw new RouteNotFoundException;
|
||||||
|
|
||||||
|
case Dispatcher::METHOD_NOT_ALLOWED:
|
||||||
|
throw new MethodNotAllowedException;
|
||||||
|
|
||||||
case Dispatcher::FOUND:
|
case Dispatcher::FOUND:
|
||||||
$handler = $routeInfo[1];
|
$handler = $routeInfo[1];
|
||||||
$parameters = $routeInfo[2];
|
$parameters = $routeInfo[2];
|
||||||
|
Reference in New Issue
Block a user