Fix issues with API authentication.

This commit is contained in:
James Cole
2018-02-09 14:47:37 +01:00
parent 3a813c30b4
commit d393c693de
8 changed files with 168 additions and 47 deletions

View File

@@ -25,12 +25,14 @@ namespace FireflyIII\Api\V1\Controllers;
use Auth; use Auth;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Models\Bill; use FireflyIII\Models\Bill;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Transformers\BillTransformer; use FireflyIII\Transformers\BillTransformer;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use League\Fractal\Manager; use League\Fractal\Manager;
use League\Fractal\Pagination\IlluminatePaginatorAdapter; use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection as FractalCollection; use League\Fractal\Resource\Collection as FractalCollection;
use League\Fractal\Resource\Item;
use League\Fractal\Serializer\JsonApiSerializer; use League\Fractal\Serializer\JsonApiSerializer;
use Preferences; use Preferences;
use Response; use Response;
@@ -40,6 +42,28 @@ use Response;
*/ */
class BillController extends Controller class BillController extends Controller
{ {
/** @var BillRepositoryInterface */
private $repository;
/**
* BillController constructor.
*
* @throws \FireflyIII\Exceptions\FireflyException
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
/** @var BillRepositoryInterface repository */
$this->repository = app(BillRepositoryInterface::class);
$this->repository->setUser(auth()->user());
return $next($request);
}
);
}
/** /**
* Remove the specified resource from storage. * Remove the specified resource from storage.
* *
@@ -49,7 +73,9 @@ class BillController extends Controller
*/ */
public function destroy(Bill $bill) public function destroy(Bill $bill)
{ {
// $this->repository->destroy($bill);
return response()->json(null, 204);
} }
/** /**
@@ -69,7 +95,7 @@ class BillController extends Controller
if (null !== $request->get('end')) { if (null !== $request->get('end')) {
$end = new Carbon($request->get('end')); $end = new Carbon($request->get('end'));
} }
$paginator = $user->bills()->paginate($pageSize); $paginator = $this->repository->getPaginator($pageSize);
/** @var Collection $bills */ /** @var Collection $bills */
$bills = $paginator->getCollection(); $bills = $paginator->getCollection();
@@ -84,16 +110,34 @@ class BillController extends Controller
return Response::json($manager->createData($resource)->toArray()); return Response::json($manager->createData($resource)->toArray());
} }
/** /**
* Display the specified resource. * @param Request $request
* @param Bill $bill
* *
* @param \FireflyIII\Models\Bill $bill * @return \Illuminate\Http\JsonResponse
*
* @return \Illuminate\Http\Response
*/ */
public function show(Bill $bill) public function show(Request $request, Bill $bill)
{ {
// $start = null;
$end = null;
if (null !== $request->get('start')) {
$start = new Carbon($request->get('start'));
}
if (null !== $request->get('end')) {
$end = new Carbon($request->get('end'));
}
$manager = new Manager();
$manager->parseIncludes(['attachments']);
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$resource = new Item($bill, new BillTransformer($start, $end), 'bill');
return Response::json($manager->createData($resource)->toArray());
} }
/** /**

View File

@@ -1,7 +1,7 @@
<?php <?php
/** /**
* Authenticate.php * Authenticate.php
* Copyright (c) 2017 thegrumpydictator@gmail.com * Copyright (c) 2018 thegrumpydictator@gmail.com
* *
* This file is part of Firefly III. * This file is part of Firefly III.
* *
@@ -18,50 +18,93 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>. * along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/ */
declare(strict_types=1);
namespace FireflyIII\Http\Middleware; namespace FireflyIII\Http\Middleware;
use Closure; use Closure;
use Illuminate\Http\Request; use Illuminate\Auth\AuthenticationException;
use Illuminate\Support\Facades\Auth; use Illuminate\Contracts\Auth\Factory as Auth;
use Session;
/** /**
* Class Authenticate. * Class Authenticate
*/ */
class Authenticate class Authenticate
{ {
/**
* The authentication factory instance.
*
* @var \Illuminate\Contracts\Auth\Factory
*/
protected $auth;
/**
* Create a new middleware instance.
*
* @param \Illuminate\Contracts\Auth\Factory $auth
*
* @return void
*/
public function __construct(Auth $auth)
{
$this->auth = $auth;
}
/** /**
* Handle an incoming request. * Handle an incoming request.
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @param \Closure $next * @param \Closure $next
* @param string|null $guard * @param string[] ...$guards
* *
* @return mixed * @return mixed
*
* @throws \Illuminate\Auth\AuthenticationException
*/ */
public function handle(Request $request, Closure $next, $guard = null) public function handle($request, Closure $next, ...$guards)
{ {
if (Auth::guard($guard)->guest()) { $this->authenticate($guards);
if ($request->ajax()) {
return response('Unauthorized.', 401);
}
return redirect()->guest('login');
}
if (1 === intval(Auth::guard($guard)->user()->blocked)) {
$message = strval(trans('firefly.block_account_logout'));
if ('email_changed' === Auth::guard($guard)->user()->blocked_code) {
$message = strval(trans('firefly.email_changed_logout'));
}
Session::flash('logoutMessage', $message);
Auth::guard($guard)->logout();
return redirect()->guest('login');
}
return $next($request); return $next($request);
} }
/**
* Determine if the user is logged in to any of the given guards.
*
* @param array $guards
*
* @return void
*
* @throws \Illuminate\Auth\AuthenticationException
*/
protected function authenticate(array $guards)
{
if (empty($guards)) {
// go for default guard:
if ($this->auth->check()) {
// do an extra check on user object.
$user = $this->auth->authenticate();
if (1 === intval($user->blocked)) {
$message = strval(trans('firefly.block_account_logout'));
if ('email_changed' === $user->blocked_code) {
$message = strval(trans('firefly.email_changed_logout'));
}
app('session')->flash('logoutMessage', $message);
$this->auth->logout();
return redirect()->guest('login');
}
}
return $this->auth->authenticate();
}
foreach ($guards as $guard) {
if ($this->auth->guard($guard)->check()) {
return $this->auth->shouldUse($guard);
}
}
throw new AuthenticationException('Unauthenticated.', $guards);
}
} }

View File

@@ -24,6 +24,7 @@ namespace FireflyIII\Http\Middleware;
use Closure; use Closure;
use FireflyIII\Support\Domain; use FireflyIII\Support\Domain;
use Illuminate\Contracts\Auth\Factory as Auth;
use Illuminate\Http\Request; use Illuminate\Http\Request;
/** /**
@@ -31,6 +32,12 @@ use Illuminate\Http\Request;
*/ */
class Binder class Binder
{ {
/**
* The authentication factory instance.
*
* @var \Illuminate\Contracts\Auth\Factory
*/
protected $auth;
/** /**
* @var array * @var array
*/ */
@@ -38,21 +45,27 @@ class Binder
/** /**
* Binder constructor. * Binder constructor.
*
* @param \Illuminate\Contracts\Auth\Factory $auth
*/ */
public function __construct() public function __construct(Auth $auth)
{ {
$this->binders = Domain::getBindables(); $this->binders = Domain::getBindables();
$this->auth = $auth;
} }
/** /**
* Handle an incoming request. * Handle an incoming request.
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @param \Closure $next * @param \Closure $next
* @param string[] ...$guards
* *
* @return mixed * @return mixed
*
* @throws \Illuminate\Auth\AuthenticationException
*/ */
public function handle(Request $request, Closure $next) public function handle($request, Closure $next, ...$guards)
{ {
foreach ($request->route()->parameters() as $key => $value) { foreach ($request->route()->parameters() as $key => $value) {
if (isset($this->binders[$key])) { if (isset($this->binders[$key])) {

View File

@@ -29,7 +29,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Watson\Validating\ValidatingTrait; use Watson\Validating\ValidatingTrait;
use Illuminate\Contracts\Auth\Factory as Auth;
/** /**
* Class Bill. * Class Bill.
*/ */

View File

@@ -49,6 +49,13 @@ class AttachmentTransformer extends TransformerAbstract
'notes' => $attachment->notes, 'notes' => $attachment->notes,
'mime' => $attachment->mime, 'mime' => $attachment->mime,
'size' => $attachment->size, 'size' => $attachment->size,
'links' => [
[
'rel' => 'self',
'uri' => '/attachment/' . $attachment->id,
],
]
]; ];
} }

View File

@@ -72,7 +72,8 @@ class BillTransformer extends TransformerAbstract
{ {
$attachments = $bill->attachments()->get(); $attachments = $bill->attachments()->get();
return $this->collection($attachments, new AttachmentTransformer); return $this->collection($attachments, new AttachmentTransformer,'attachment');
} }
/** /**
@@ -84,7 +85,8 @@ class BillTransformer extends TransformerAbstract
{ {
$notes = $bill->notes()->get(); $notes = $bill->notes()->get();
return $this->collection($notes, new NoteTransformer); return $this->collection($notes, new NoteTransformer,'note');
} }
/** /**
@@ -95,7 +97,9 @@ class BillTransformer extends TransformerAbstract
public function transform(Bill $bill): array public function transform(Bill $bill): array
{ {
$paidData = $this->paidData($bill); $paidData = $this->paidData($bill);
$data = [ $payDates = $this->payDates($bill);
$data = [
'id' => (int)$bill->id, 'id' => (int)$bill->id,
'name' => $bill->name, 'name' => $bill->name,
'match' => explode(',', $bill->match), 'match' => explode(',', $bill->match),
@@ -107,13 +111,13 @@ class BillTransformer extends TransformerAbstract
'automatch' => intval($bill->automatch) === 1, 'automatch' => intval($bill->automatch) === 1,
'active' => intval($bill->active) === 1, 'active' => intval($bill->active) === 1,
'attachments_count' => $bill->attachments()->count(), 'attachments_count' => $bill->attachments()->count(),
'pay_dates' => $this->payDates($bill), 'pay_dates' => $payDates,
'paid_dates' => $paidData['paid_dates'], 'paid_dates' => $paidData['paid_dates'],
'next_expected_match' => $paidData['next_expected_match'], 'next_expected_match' => $paidData['next_expected_match'],
'links' => [ 'links' => [
[ [
'rel' => 'self', 'rel' => 'self',
'uri' => '/bills/' . $bill->id, 'uri' => '/bill/' . $bill->id,
], ],
], ],
]; ];
@@ -217,6 +221,9 @@ class BillTransformer extends TransformerAbstract
*/ */
protected function payDates(Bill $bill): array protected function payDates(Bill $bill): array
{ {
if (is_null($this->start) || is_null($this->end)) {
return [];
}
$set = new Collection; $set = new Collection;
$currentStart = clone $this->start; $currentStart = clone $this->start;
while ($currentStart <= $this->end) { while ($currentStart <= $this->end) {

View File

@@ -48,6 +48,13 @@ class NoteTransformer extends TransformerAbstract
'title' => $note->title, 'title' => $note->title,
'text' => $note->text, 'text' => $note->text,
'markdown' => $converter->convertToHtml($note->text), 'markdown' => $converter->convertToHtml($note->text),
'links' => [
[
'rel' => 'self',
'uri' => '/note/' . $note->id,
],
]
]; ];
} }

View File

@@ -20,7 +20,7 @@
*/ */
Route::group( Route::group(
['middleware' => 'auth:api', 'namespace' => 'FireflyIII\Api\V1\Controllers', 'prefix' => 'bill', 'as' => 'api.v1.bills.'], function () { ['middleware' => ['auth:api','bindings'], 'namespace' => 'FireflyIII\Api\V1\Controllers', 'prefix' => 'bill', 'as' => 'api.v1.bills.'], function () {
// Bills API routes: // Bills API routes:
Route::get('', ['uses' => 'BillController@index', 'as' => 'index']); Route::get('', ['uses' => 'BillController@index', 'as' => 'index']);