mirror of
https://github.com/flarum/core.git
synced 2025-10-12 15:34:26 +02:00
Merge branch 'sudo-mode'
# Conflicts: # CHANGELOG.md
This commit is contained in:
@@ -1,80 +0,0 @@
|
||||
<?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;
|
||||
|
||||
use Flarum\Database\AbstractModel;
|
||||
use DateTime;
|
||||
|
||||
/**
|
||||
* @property string $id
|
||||
* @property int $user_id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $expires_at
|
||||
* @property \Flarum\Core\User|null $user
|
||||
*/
|
||||
class AccessToken extends AbstractModel
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $table = 'access_tokens';
|
||||
|
||||
/**
|
||||
* Use a custom primary key for this model.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $incrementing = false;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $dates = ['created_at', 'expires_at'];
|
||||
|
||||
/**
|
||||
* Generate an access token for the specified user.
|
||||
*
|
||||
* @param int $userId
|
||||
* @param int $minutes
|
||||
* @return static
|
||||
*/
|
||||
public static function generate($userId, $minutes = 60)
|
||||
{
|
||||
$token = new static;
|
||||
|
||||
$token->id = str_random(40);
|
||||
$token->user_id = $userId;
|
||||
$token->created_at = time();
|
||||
$token->expires_at = time() + $minutes * 60;
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the token has not expired.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isValid()
|
||||
{
|
||||
return $this->expires_at > new DateTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the relationship with the owner of this access token.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('Flarum\Core\User');
|
||||
}
|
||||
}
|
@@ -44,9 +44,13 @@ class ApiServiceProvider extends AbstractServiceProvider
|
||||
|
||||
$handler->registerHandler(new Handler\FloodingExceptionHandler);
|
||||
$handler->registerHandler(new Handler\IlluminateValidationExceptionHandler);
|
||||
$handler->registerHandler(new Handler\InvalidAccessTokenExceptionHandler);
|
||||
$handler->registerHandler(new Handler\InvalidConfirmationTokenExceptionHandler);
|
||||
$handler->registerHandler(new Handler\MethodNotAllowedExceptionHandler);
|
||||
$handler->registerHandler(new Handler\ModelNotFoundExceptionHandler);
|
||||
$handler->registerHandler(new Handler\PermissionDeniedExceptionHandler);
|
||||
$handler->registerHandler(new Handler\RouteNotFoundExceptionHandler);
|
||||
$handler->registerHandler(new Handler\TokenMismatchExceptionHandler);
|
||||
$handler->registerHandler(new Handler\ValidationExceptionHandler);
|
||||
$handler->registerHandler(new InvalidParameterExceptionHandler);
|
||||
$handler->registerHandler(new FallbackExceptionHandler($this->app->inDebugMode()));
|
||||
|
@@ -12,6 +12,7 @@ namespace Flarum\Api;
|
||||
|
||||
use Flarum\Http\Controller\ControllerInterface;
|
||||
use Flarum\Core\User;
|
||||
use Flarum\Http\Session;
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
@@ -43,14 +44,23 @@ class Client
|
||||
* Execute the given API action class, pass the input and return its response.
|
||||
*
|
||||
* @param string|ControllerInterface $controller
|
||||
* @param User $actor
|
||||
* @param Session|User|null $session
|
||||
* @param array $queryParams
|
||||
* @param array $body
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public function send($controller, User $actor, array $queryParams = [], array $body = [])
|
||||
public function send($controller, $session, array $queryParams = [], array $body = [])
|
||||
{
|
||||
$request = ServerRequestFactory::fromGlobals(null, $queryParams, $body)->withAttribute('actor', $actor);
|
||||
$request = ServerRequestFactory::fromGlobals(null, $queryParams, $body);
|
||||
|
||||
if ($session instanceof Session) {
|
||||
$request = $request->withAttribute('session', $session);
|
||||
$actor = $session->user;
|
||||
} else {
|
||||
$actor = $session;
|
||||
}
|
||||
|
||||
$request = $request->withAttribute('actor', $actor);
|
||||
|
||||
if (is_string($controller)) {
|
||||
$controller = $this->container->make($controller);
|
||||
|
@@ -1,29 +0,0 @@
|
||||
<?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\Command;
|
||||
|
||||
class GenerateAccessToken
|
||||
{
|
||||
/**
|
||||
* The ID of the user to generate an access token for.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $userId;
|
||||
|
||||
/**
|
||||
* @param int $userId The ID of the user to generate an access token for.
|
||||
*/
|
||||
public function __construct($userId)
|
||||
{
|
||||
$this->userId = $userId;
|
||||
}
|
||||
}
|
@@ -1,30 +0,0 @@
|
||||
<?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\Command;
|
||||
|
||||
use Flarum\Api\AccessToken;
|
||||
use Flarum\Api\Command\GenerateAccessToken;
|
||||
|
||||
class GenerateAccessTokenHandler
|
||||
{
|
||||
/**
|
||||
* @param GenerateAccessToken $command
|
||||
* @return AccessToken
|
||||
*/
|
||||
public function handle(GenerateAccessToken $command)
|
||||
{
|
||||
$token = AccessToken::generate($command->userId);
|
||||
|
||||
$token->save();
|
||||
|
||||
return $token;
|
||||
}
|
||||
}
|
@@ -10,12 +10,15 @@
|
||||
|
||||
namespace Flarum\Api\Controller;
|
||||
|
||||
use Flarum\Core\Access\AssertPermissionTrait;
|
||||
use Flarum\Core\Command\DeleteDiscussion;
|
||||
use Illuminate\Contracts\Bus\Dispatcher;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class DeleteDiscussionController extends AbstractDeleteController
|
||||
{
|
||||
use AssertPermissionTrait;
|
||||
|
||||
/**
|
||||
* @var Dispatcher
|
||||
*/
|
||||
@@ -38,6 +41,8 @@ class DeleteDiscussionController extends AbstractDeleteController
|
||||
$actor = $request->getAttribute('actor');
|
||||
$input = $request->getParsedBody();
|
||||
|
||||
$this->assertSudo($request);
|
||||
|
||||
$this->bus->dispatch(
|
||||
new DeleteDiscussion($id, $actor, $input)
|
||||
);
|
||||
|
@@ -10,12 +10,15 @@
|
||||
|
||||
namespace Flarum\Api\Controller;
|
||||
|
||||
use Flarum\Core\Access\AssertPermissionTrait;
|
||||
use Flarum\Core\Command\DeleteGroup;
|
||||
use Illuminate\Contracts\Bus\Dispatcher;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class DeleteGroupController extends AbstractDeleteController
|
||||
{
|
||||
use AssertPermissionTrait;
|
||||
|
||||
/**
|
||||
* @var Dispatcher
|
||||
*/
|
||||
@@ -34,6 +37,8 @@ class DeleteGroupController extends AbstractDeleteController
|
||||
*/
|
||||
protected function delete(ServerRequestInterface $request)
|
||||
{
|
||||
$this->assertSudo($request);
|
||||
|
||||
$this->bus->dispatch(
|
||||
new DeleteGroup(array_get($request->getQueryParams(), 'id'), $request->getAttribute('actor'))
|
||||
);
|
||||
|
@@ -10,12 +10,15 @@
|
||||
|
||||
namespace Flarum\Api\Controller;
|
||||
|
||||
use Flarum\Core\Access\AssertPermissionTrait;
|
||||
use Flarum\Core\Command\DeletePost;
|
||||
use Illuminate\Contracts\Bus\Dispatcher;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class DeletePostController extends AbstractDeleteController
|
||||
{
|
||||
use AssertPermissionTrait;
|
||||
|
||||
/**
|
||||
* @var Dispatcher
|
||||
*/
|
||||
@@ -34,6 +37,8 @@ class DeletePostController extends AbstractDeleteController
|
||||
*/
|
||||
protected function delete(ServerRequestInterface $request)
|
||||
{
|
||||
$this->assertSudo($request);
|
||||
|
||||
$this->bus->dispatch(
|
||||
new DeletePost(array_get($request->getQueryParams(), 'id'), $request->getAttribute('actor'))
|
||||
);
|
||||
|
@@ -10,12 +10,15 @@
|
||||
|
||||
namespace Flarum\Api\Controller;
|
||||
|
||||
use Flarum\Core\Access\AssertPermissionTrait;
|
||||
use Flarum\Core\Command\DeleteUser;
|
||||
use Illuminate\Contracts\Bus\Dispatcher;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class DeleteUserController extends AbstractDeleteController
|
||||
{
|
||||
use AssertPermissionTrait;
|
||||
|
||||
/**
|
||||
* @var Dispatcher
|
||||
*/
|
||||
@@ -34,6 +37,8 @@ class DeleteUserController extends AbstractDeleteController
|
||||
*/
|
||||
protected function delete(ServerRequestInterface $request)
|
||||
{
|
||||
$this->assertSudo($request);
|
||||
|
||||
$this->bus->dispatch(
|
||||
new DeleteUser(array_get($request->getQueryParams(), 'id'), $request->getAttribute('actor'))
|
||||
);
|
||||
|
@@ -25,7 +25,7 @@ class SetPermissionController implements ControllerInterface
|
||||
*/
|
||||
public function handle(ServerRequestInterface $request)
|
||||
{
|
||||
$this->assertAdmin($request->getAttribute('actor'));
|
||||
$this->assertAdminAndSudo($request);
|
||||
|
||||
$body = $request->getParsedBody();
|
||||
$permission = array_get($body, 'permission');
|
||||
|
@@ -47,7 +47,7 @@ class SetSettingsController implements ControllerInterface
|
||||
*/
|
||||
public function handle(ServerRequestInterface $request)
|
||||
{
|
||||
$this->assertAdmin($request->getAttribute('actor'));
|
||||
$this->assertAdminAndSudo($request);
|
||||
|
||||
$settings = $request->getParsedBody();
|
||||
|
||||
|
@@ -10,11 +10,10 @@
|
||||
|
||||
namespace Flarum\Api\Controller;
|
||||
|
||||
use Flarum\Api\Command\GenerateAccessToken;
|
||||
use Flarum\Core\Exception\PermissionDeniedException;
|
||||
use Flarum\Core\Repository\UserRepository;
|
||||
use Flarum\Event\UserEmailChangeWasRequested;
|
||||
use Flarum\Http\Controller\ControllerInterface;
|
||||
use Flarum\Http\Session;
|
||||
use Illuminate\Contracts\Bus\Dispatcher as BusDispatcher;
|
||||
use Illuminate\Contracts\Events\Dispatcher as EventDispatcher;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
@@ -65,19 +64,13 @@ class TokenController implements ControllerInterface
|
||||
throw new PermissionDeniedException;
|
||||
}
|
||||
|
||||
if (! $user->is_activated) {
|
||||
$this->events->fire(new UserEmailChangeWasRequested($user, $user->email));
|
||||
$session = $request->getAttribute('session') ?: Session::generate($user);
|
||||
$session->assign($user)->regenerateId()->renew()->save();
|
||||
|
||||
return new JsonResponse(['emailConfirmationRequired' => $user->email], 401);
|
||||
}
|
||||
|
||||
$token = $this->bus->dispatch(
|
||||
new GenerateAccessToken($user->id)
|
||||
);
|
||||
|
||||
return new JsonResponse([
|
||||
'token' => $token->id,
|
||||
return (new JsonResponse([
|
||||
'token' => $session->id,
|
||||
'userId' => $user->id
|
||||
]);
|
||||
]))
|
||||
->withHeader('X-CSRF-Token', $session->csrf_token);
|
||||
}
|
||||
}
|
||||
|
@@ -33,7 +33,7 @@ class UninstallExtensionController extends AbstractDeleteController
|
||||
|
||||
protected function delete(ServerRequestInterface $request)
|
||||
{
|
||||
$this->assertAdmin($request->getAttribute('actor'));
|
||||
$this->assertAdminAndSudo($request);
|
||||
|
||||
$name = array_get($request->getQueryParams(), 'name');
|
||||
|
||||
|
@@ -38,7 +38,7 @@ class UpdateExtensionController implements ControllerInterface
|
||||
*/
|
||||
public function handle(ServerRequestInterface $request)
|
||||
{
|
||||
$this->assertAdmin($request->getAttribute('actor'));
|
||||
$this->assertAdminAndSudo($request);
|
||||
|
||||
$enabled = array_get($request->getParsedBody(), 'enabled');
|
||||
$name = array_get($request->getQueryParams(), 'name');
|
||||
|
@@ -10,6 +10,7 @@
|
||||
|
||||
namespace Flarum\Api\Controller;
|
||||
|
||||
use Flarum\Core\Access\AssertPermissionTrait;
|
||||
use Flarum\Core\Command\EditUser;
|
||||
use Illuminate\Contracts\Bus\Dispatcher;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
@@ -17,6 +18,8 @@ use Tobscure\JsonApi\Document;
|
||||
|
||||
class UpdateUserController extends AbstractResourceController
|
||||
{
|
||||
use AssertPermissionTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -49,6 +52,8 @@ class UpdateUserController extends AbstractResourceController
|
||||
$actor = $request->getAttribute('actor');
|
||||
$data = array_get($request->getParsedBody(), 'data', []);
|
||||
|
||||
$this->assertSudo($request);
|
||||
|
||||
return $this->bus->dispatch(
|
||||
new EditUser($id, $actor, $data)
|
||||
);
|
||||
|
17
src/Api/Exception/InvalidAccessTokenException.php
Normal file
17
src/Api/Exception/InvalidAccessTokenException.php
Normal file
@@ -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)
|
||||
{
|
||||
$status = 429;
|
||||
$error = [];
|
||||
$error = [
|
||||
'status' => (string) $status,
|
||||
'code' => 'too_many_requests'
|
||||
];
|
||||
|
||||
return new ResponseBag($status, [$error]);
|
||||
}
|
||||
|
@@ -44,8 +44,10 @@ class IlluminateValidationExceptionHandler implements ExceptionHandlerInterface
|
||||
{
|
||||
$errors = array_map(function ($field, $messages) {
|
||||
return [
|
||||
'status' => '422',
|
||||
'code' => 'validation_error',
|
||||
'detail' => implode("\n", $messages),
|
||||
'source' => ['pointer' => '/data/attributes/' . $field],
|
||||
'source' => ['pointer' => "/data/attributes/$field"]
|
||||
];
|
||||
}, array_keys($errors), $errors);
|
||||
|
||||
|
41
src/Api/Handler/InvalidAccessTokenExceptionHandler.php
Normal file
41
src/Api/Handler/InvalidAccessTokenExceptionHandler.php
Normal file
@@ -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)
|
||||
{
|
||||
$status = 403;
|
||||
$error = ['code' => 'invalid_confirmation_token'];
|
||||
$error = [
|
||||
'status' => (string) $status,
|
||||
'code' => 'invalid_confirmation_token'
|
||||
];
|
||||
|
||||
return new ResponseBag($status, [$error]);
|
||||
}
|
||||
|
41
src/Api/Handler/MethodNotAllowedExceptionHandler.php
Normal file
41
src/Api/Handler/MethodNotAllowedExceptionHandler.php
Normal file
@@ -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;
|
||||
|
||||
use Exception;
|
||||
use Flarum\Http\Exception\RouteNotFoundException;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Tobscure\JsonApi\Exception\Handler\ExceptionHandlerInterface;
|
||||
use Tobscure\JsonApi\Exception\Handler\ResponseBag;
|
||||
@@ -31,7 +32,10 @@ class ModelNotFoundExceptionHandler implements ExceptionHandlerInterface
|
||||
public function handle(Exception $e)
|
||||
{
|
||||
$status = 404;
|
||||
$error = [];
|
||||
$error = [
|
||||
'status' => '404',
|
||||
'code' => 'resource_not_found'
|
||||
];
|
||||
|
||||
return new ResponseBag($status, [$error]);
|
||||
}
|
||||
|
@@ -31,7 +31,10 @@ class PermissionDeniedExceptionHandler implements ExceptionHandlerInterface
|
||||
public function handle(Exception $e)
|
||||
{
|
||||
$status = 401;
|
||||
$error = [];
|
||||
$error = [
|
||||
'status' => (string) $status,
|
||||
'code' => 'permission_denied'
|
||||
];
|
||||
|
||||
return new ResponseBag($status, [$error]);
|
||||
}
|
||||
|
41
src/Api/Handler/RouteNotFoundExceptionHandler.php
Normal file
41
src/Api/Handler/RouteNotFoundExceptionHandler.php
Normal file
@@ -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]);
|
||||
}
|
||||
}
|
41
src/Api/Handler/TokenMismatchExceptionHandler.php
Normal file
41
src/Api/Handler/TokenMismatchExceptionHandler.php
Normal file
@@ -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\TokenMismatchException;
|
||||
use Tobscure\JsonApi\Exception\Handler\ExceptionHandlerInterface;
|
||||
use Tobscure\JsonApi\Exception\Handler\ResponseBag;
|
||||
|
||||
class TokenMismatchExceptionHandler implements ExceptionHandlerInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function manages(Exception $e)
|
||||
{
|
||||
return $e instanceof TokenMismatchException;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function handle(Exception $e)
|
||||
{
|
||||
$status = 400;
|
||||
$error = [
|
||||
'status' => (string) $status,
|
||||
'code' => 'csrf_token_mismatch'
|
||||
];
|
||||
|
||||
return new ResponseBag($status, [$error]);
|
||||
}
|
||||
}
|
@@ -33,10 +33,13 @@ class ValidationExceptionHandler implements ExceptionHandlerInterface
|
||||
$status = 422;
|
||||
|
||||
$messages = $e->getMessages();
|
||||
$errors = array_map(function ($path, $detail) {
|
||||
$source = ['pointer' => '/data/attributes/' . $path];
|
||||
|
||||
return compact('source', 'detail');
|
||||
$errors = array_map(function ($path, $detail) use ($status) {
|
||||
return [
|
||||
'status' => (string) $status,
|
||||
'code' => 'validation_error',
|
||||
'detail' => $detail,
|
||||
'source' => ['pointer' => "/data/attributes/$path"]
|
||||
];
|
||||
}, array_keys($messages), $messages);
|
||||
|
||||
return new ResponseBag($status, $errors);
|
||||
|
@@ -1,93 +0,0 @@
|
||||
<?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\Middleware;
|
||||
|
||||
use Flarum\Api\AccessToken;
|
||||
use Flarum\Api\ApiKey;
|
||||
use Flarum\Core\Guest;
|
||||
use Flarum\Core\User;
|
||||
use Flarum\Locale\LocaleManager;
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Zend\Stratigility\MiddlewareInterface;
|
||||
|
||||
class AuthenticateWithHeader implements MiddlewareInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $prefix = 'Token ';
|
||||
|
||||
/**
|
||||
* @var LocaleManager
|
||||
*/
|
||||
protected $locales;
|
||||
|
||||
/**
|
||||
* @param LocaleManager $locales
|
||||
*/
|
||||
public function __construct(LocaleManager $locales)
|
||||
{
|
||||
$this->locales = $locales;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __invoke(Request $request, Response $response, callable $out = null)
|
||||
{
|
||||
$request = $this->logIn($request);
|
||||
|
||||
return $out ? $out($request, $response) : $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @return Request
|
||||
*/
|
||||
protected function logIn(Request $request)
|
||||
{
|
||||
$header = $request->getHeaderLine('authorization');
|
||||
|
||||
$parts = explode(';', $header);
|
||||
|
||||
$actor = new Guest;
|
||||
|
||||
if (isset($parts[0]) && starts_with($parts[0], $this->prefix)) {
|
||||
$token = substr($parts[0], strlen($this->prefix));
|
||||
|
||||
if (($accessToken = AccessToken::find($token)) && $accessToken->isValid()) {
|
||||
$actor = $accessToken->user;
|
||||
|
||||
$actor->updateLastSeen()->save();
|
||||
} elseif (isset($parts[1]) && ($apiKey = ApiKey::valid($token))) {
|
||||
$userParts = explode('=', trim($parts[1]));
|
||||
|
||||
if (isset($userParts[0]) && $userParts[0] === 'userId') {
|
||||
$actor = User::find($userParts[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($actor->exists) {
|
||||
$locale = $actor->getPreference('locale');
|
||||
} else {
|
||||
$locale = array_get($request->getCookieParams(), 'locale');
|
||||
}
|
||||
|
||||
if ($locale && $this->locales->hasLocale($locale)) {
|
||||
$this->locales->setLocale($locale);
|
||||
}
|
||||
|
||||
return $request->withAttribute('actor', $actor ?: new Guest);
|
||||
}
|
||||
}
|
@@ -28,10 +28,12 @@ class Server extends AbstractServer
|
||||
$apiPath = parse_url($app->url('api'), PHP_URL_PATH);
|
||||
|
||||
if ($app->isInstalled() && $app->isUpToDate()) {
|
||||
$pipe->pipe($apiPath, $app->make('Flarum\Http\Middleware\AuthenticateWithCookie'));
|
||||
$pipe->pipe($apiPath, $app->make('Flarum\Api\Middleware\AuthenticateWithHeader'));
|
||||
$pipe->pipe($apiPath, $app->make('Flarum\Http\Middleware\ParseJsonBody'));
|
||||
$pipe->pipe($apiPath, $app->make('Flarum\Api\Middleware\FakeHttpMethods'));
|
||||
$pipe->pipe($apiPath, $app->make('Flarum\Http\Middleware\AuthorizeWithCookie'));
|
||||
$pipe->pipe($apiPath, $app->make('Flarum\Http\Middleware\AuthorizeWithHeader'));
|
||||
$pipe->pipe($apiPath, $app->make('Flarum\Http\Middleware\StartSession'));
|
||||
$pipe->pipe($apiPath, $app->make('Flarum\Http\Middleware\SetLocale'));
|
||||
$pipe->pipe($apiPath, $app->make('Flarum\Http\Middleware\DispatchRoute', ['routes' => $app->make('flarum.api.routes')]));
|
||||
$pipe->pipe($apiPath, $app->make('Flarum\Api\Middleware\HandleErrors'));
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user