Merge branch 'develop' into 5.8-dev

# Conflicts:
#	app/Http/Middleware/Authenticate.php
#	app/Models/Account.php
#	app/Support/Authentication/RemoteUserGuard.php
This commit is contained in:
James Cole
2023-01-01 15:14:15 +01:00
8 changed files with 78 additions and 29 deletions

View File

@@ -40,10 +40,8 @@ use Illuminate\View\View;
*/ */
class EditController extends Controller class EditController extends Controller
{ {
/** @var AttachmentHelperInterface Helper for attachments. */ private AttachmentHelperInterface $attachments;
private $attachments; private BudgetRepositoryInterface $repository;
/** @var BudgetRepositoryInterface The budget repository */
private $repository;
/** /**
* EditController constructor. * EditController constructor.

View File

@@ -178,13 +178,15 @@ class Kernel extends HttpKernel
CreateFreshApiToken::class, CreateFreshApiToken::class,
], ],
// full API authentication
'api' => [ 'api' => [
AcceptHeaders::class, AcceptHeaders::class,
EnsureFrontendRequestsAreStateful::class, EnsureFrontendRequestsAreStateful::class,
'auth:api,sanctum', 'auth:api,sanctum',
'bindings', 'bindings',
], ],
'apiY' => [ // do only bindings, no auth
'api_basic' => [
'bindings', 'bindings',
], ],
]; ];

View File

@@ -29,8 +29,8 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Auth\AuthenticationException; use Illuminate\Auth\AuthenticationException;
use Illuminate\Contracts\Auth\Factory as Auth; use Illuminate\Contracts\Auth\Factory as Auth;
use Illuminate\Database\QueryException;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Log;
/** /**
* Class Authenticate * Class Authenticate
@@ -87,13 +87,22 @@ class Authenticate
*/ */
protected function authenticate($request, array $guards) protected function authenticate($request, array $guards)
{ {
Log::debug(sprintf('Now in %s', __METHOD__));
if (0 === count($guards)) { if (0 === count($guards)) {
try { Log::debug('No guards present.');
// go for default guard: // go for default guard:
if ($this->auth->check()) { /** @noinspection PhpUndefinedMethodInspection */
// do an extra check on user object. if ($this->auth->check()) {
/** @var User $user */ Log::debug('Default guard says user is authenticated.');
$user = $this->auth->authenticate(); // @phpstan-ignore-line (thinks function returns void) // do an extra check on user object.
/** @noinspection PhpUndefinedMethodInspection */
/** @var User $user */
$user = $this->auth->authenticate();
if (null === $user) {
Log::warning('User is null, throw exception?');
}
if (null !== $user) {
Log::debug(get_class($user));
if (1 === (int)$user->blocked) { if (1 === (int)$user->blocked) {
$message = (string)trans('firefly.block_account_logout'); $message = (string)trans('firefly.block_account_logout');
if ('email_changed' === $user->blocked_code) { if ('email_changed' === $user->blocked_code) {
@@ -105,20 +114,11 @@ class Authenticate
throw new AuthenticationException('Blocked account.', $guards); throw new AuthenticationException('Blocked account.', $guards);
} }
} }
} catch (QueryException $e) {
throw new FireflyException(
sprintf(
'It seems the database has not yet been initialized. Did you run the correct upgrade or installation commands? Error: %s',
$e->getMessage()
),
0,
$e
);
} }
return $this->auth->authenticate(); // @phpstan-ignore-line (thinks function returns void) return $this->auth->authenticate(); // @phpstan-ignore-line (thinks function returns void)
} }
Log::debug('Guard array is not empty.');
foreach ($guards as $guard) { foreach ($guards as $guard) {
if ($this->auth->guard($guard)->check()) { if ($this->auth->guard($guard)->check()) {

View File

@@ -27,6 +27,7 @@ use Carbon\Carbon;
use Eloquent; use Eloquent;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
@@ -291,4 +292,16 @@ class Account extends Model
{ {
return $this->hasMany(Transaction::class); return $this->hasMany(Transaction::class);
} }
/**
* Get the virtual balance
*
* @return Attribute
*/
protected function virtualBalance(): Attribute
{
return Attribute::make(
get: fn($value) => (string) $value,
);
}
} }

View File

@@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Models; namespace FireflyIII\Models;
use Eloquent; use Eloquent;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
@@ -86,4 +87,14 @@ class AutoBudget extends Model
{ {
return $this->belongsTo(TransactionCurrency::class); return $this->belongsTo(TransactionCurrency::class);
} }
/**
* @return Attribute
*/
protected function amount(): Attribute
{
return Attribute::make(
get: fn($value) => (string) $value,
);
}
} }

View File

@@ -59,7 +59,7 @@ class RouteServiceProvider extends ServiceProvider
->group(base_path('routes/api.php')); ->group(base_path('routes/api.php'));
Route::prefix('api/v1/cron') Route::prefix('api/v1/cron')
->middleware('apiY') ->middleware('api_basic')
->namespace($this->namespace) ->namespace($this->namespace)
->group(base_path('routes/api-noauth.php')); ->group(base_path('routes/api-noauth.php'));

View File

@@ -30,6 +30,7 @@ use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Guard; use Illuminate\Contracts\Auth\Guard;
use Illuminate\Contracts\Auth\UserProvider; use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\Foundation\Application;
use Illuminate\Http\Request;
use Log; use Log;
/** /**
@@ -49,26 +50,40 @@ class RemoteUserGuard implements Guard
*/ */
public function __construct(UserProvider $provider, Application $app) public function __construct(UserProvider $provider, Application $app)
{ {
/** @var Request $request */
$request = $app->get('request');
Log::debug(sprintf('Created RemoteUserGuard for "%s"', $request?->getRequestUri()));
$this->application = $app; $this->application = $app;
$this->provider = $provider; $this->provider = $provider;
$this->user = null; $this->user = null;
} }
/**
* @return bool
*/
public function viaRemember(): bool
{
Log::debug(sprintf('Now at %s', __METHOD__));
return false;
}
/** /**
* *
*/ */
public function authenticate(): void public function authenticate(): void
{ {
Log::debug(sprintf('Now at %s', __METHOD__)); Log::debug(sprintf('Now at %s', __METHOD__));
if (!is_null($this->user)) { if (null !== $this->user) {
Log::debug('User is found.'); Log::debug(sprintf('%s is found: #%d, "%s".', get_class($this->user), $this->user->id, $this->user->email));
return; return;
} }
// Get the user identifier from $_SERVER or apache filtered headers // Get the user identifier from $_SERVER or apache filtered headers
$header = config('auth.guard_header', 'REMOTE_USER'); $header = config('auth.guard_header', 'REMOTE_USER');
$userID = request()->server($header) ?? apache_request_headers()[$header] ?? null; $userID = request()->server($header) ?? null;
if (function_exists('apache_request_headers')) {
$userID = request()->server($header) ?? apache_request_headers()[$header] ?? null;
}
if (null === $userID) { if (null === $userID) {
Log::error(sprintf('No user in header "%s".', $header)); Log::error(sprintf('No user in header "%s".', $header));
throw new FireflyException('The guard header was unexpectedly empty. See the logs.'); throw new FireflyException('The guard header was unexpectedly empty. See the logs.');
@@ -102,6 +117,8 @@ class RemoteUserGuard implements Guard
*/ */
public function guest(): bool public function guest(): bool
{ {
Log::debug(sprintf('Now at %s', __METHOD__));
$this->authenticate();
return !$this->check(); return !$this->check();
} }
@@ -110,6 +127,8 @@ class RemoteUserGuard implements Guard
*/ */
public function check(): bool public function check(): bool
{ {
Log::debug(sprintf('Now at %s', __METHOD__));
$this->authenticate();
return !is_null($this->user()); return !is_null($this->user());
} }
@@ -118,6 +137,8 @@ class RemoteUserGuard implements Guard
*/ */
public function user(): ?User public function user(): ?User
{ {
Log::debug(sprintf('Now at %s', __METHOD__));
$this->authenticate();
return $this->user; return $this->user;
} }
@@ -126,7 +147,8 @@ class RemoteUserGuard implements Guard
*/ */
public function hasUser(): bool public function hasUser(): bool
{ {
throw new FireflyException(sprintf('%s is not implemented', __METHOD__)); Log::debug(sprintf('Now at %s', __METHOD__));
// TODO: Implement hasUser() method.
} }
/** /**
@@ -134,6 +156,7 @@ class RemoteUserGuard implements Guard
*/ */
public function id(): ?User public function id(): ?User
{ {
Log::debug(sprintf('Now at %s', __METHOD__));
return $this->user; return $this->user;
} }
@@ -142,6 +165,7 @@ class RemoteUserGuard implements Guard
*/ */
public function setUser(Authenticatable $user) public function setUser(Authenticatable $user)
{ {
Log::debug(sprintf('Now at %s', __METHOD__));
$this->user = $user; $this->user = $user;
} }
@@ -150,6 +174,7 @@ class RemoteUserGuard implements Guard
*/ */
public function validate(array $credentials = []) public function validate(array $credentials = [])
{ {
Log::debug(sprintf('Now at %s', __METHOD__));
throw new FireflyException('Did not implement RemoteUserGuard::validate()'); throw new FireflyException('Did not implement RemoteUserGuard::validate()');
} }
} }

View File

@@ -15,7 +15,7 @@ return [
| |
*/ */
'guard' => 'web', 'guard' => envNonEmpty('AUTHENTICATION_GUARD', 'web'),
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------