Fix various issues with new features, nullpointers and missing checks.

This commit is contained in:
James Cole
2024-12-31 08:05:25 +01:00
parent e4aa218b5f
commit 9e34314dbc
9 changed files with 55 additions and 51 deletions

View File

@@ -25,7 +25,6 @@ declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Chart; namespace FireflyIII\Api\V2\Request\Chart;
use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Support\Http\Api\ParsesQueryFilters;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
@@ -40,7 +39,6 @@ class ChartRequest extends FormRequest
{ {
use ChecksLogin; use ChecksLogin;
use ConvertsDataTypes; use ConvertsDataTypes;
use ParsesQueryFilters;
use ValidatesUserGroupTrait; use ValidatesUserGroupTrait;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY]; protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];

View File

@@ -137,13 +137,13 @@ class AccountController extends Controller
continue; continue;
} }
Log::debug(sprintf('Will process expense array "%s" with amount %s', $key, $endBalance)); //Log::debug(sprintf('Will process expense array "%s" with amount %s', $key, $endBalance));
$searchCode = $this->convertToNative ? $this->defaultCurrency->code : $key; $searchCode = $this->convertToNative ? $this->defaultCurrency->code : $key;
Log::debug(sprintf('Search code is %s', $searchCode)); //Log::debug(sprintf('Search code is %s', $searchCode));
// see if there is an accompanying start amount. // see if there is an accompanying start amount.
// grab the difference and find the currency. // grab the difference and find the currency.
$startBalance = ($startBalances[$account->id][$key] ?? '0'); $startBalance = ($startBalances[$account->id][$key] ?? '0');
Log::debug(sprintf('Start balance is %s', $startBalance)); // Log::debug(sprintf('Start balance is %s', $startBalance));
$diff = bcsub($endBalance, $startBalance); $diff = bcsub($endBalance, $startBalance);
$currencies[$searchCode] ??= $this->currencyRepository->findByCode($searchCode); $currencies[$searchCode] ??= $this->currencyRepository->findByCode($searchCode);
if (0 !== bccomp($diff, '0')) { if (0 !== bccomp($diff, '0')) {
@@ -596,13 +596,13 @@ class AccountController extends Controller
continue; continue;
} }
Log::debug(sprintf('Will process expense array "%s" with amount %s', $key, $endBalance)); //Log::debug(sprintf('Will process expense array "%s" with amount %s', $key, $endBalance));
$searchCode = $this->convertToNative ? $this->defaultCurrency->code : $key; $searchCode = $this->convertToNative ? $this->defaultCurrency->code : $key;
Log::debug(sprintf('Search code is %s', $searchCode)); //Log::debug(sprintf('Search code is %s', $searchCode));
// see if there is an accompanying start amount. // see if there is an accompanying start amount.
// grab the difference and find the currency. // grab the difference and find the currency.
$startBalance = ($startBalances[$account->id][$key] ?? '0'); $startBalance = ($startBalances[$account->id][$key] ?? '0');
Log::debug(sprintf('Start balance is %s', $startBalance)); //Log::debug(sprintf('Start balance is %s', $startBalance));
$diff = bcsub($endBalance, $startBalance); $diff = bcsub($endBalance, $startBalance);
$currencies[$searchCode] ??= $this->currencyRepository->findByCode($searchCode); $currencies[$searchCode] ??= $this->currencyRepository->findByCode($searchCode);
if (0 !== bccomp($diff, '0')) { if (0 !== bccomp($diff, '0')) {

View File

@@ -62,8 +62,6 @@ class InstallController extends Controller
'migrate' => ['--seed' => true, '--force' => true], 'migrate' => ['--seed' => true, '--force' => true],
'generate-keys' => [], // an exception :( 'generate-keys' => [], // an exception :(
'firefly-iii:upgrade-database' => [], 'firefly-iii:upgrade-database' => [],
// 'firefly-iii:correct-database' => [],
// 'firefly-iii:report-integrity' => [],
'firefly-iii:set-latest-version' => ['--james-is-cool' => true], 'firefly-iii:set-latest-version' => ['--james-is-cool' => true],
'firefly-iii:verify-security-alerts' => [], 'firefly-iii:verify-security-alerts' => [],
]; ];

View File

@@ -83,15 +83,17 @@ class ReturnsAvailableChannels
private static function returnUserChannels(User $user): array private static function returnUserChannels(User $user): array
{ {
Log::debug(sprintf('Checking channels for user #%d', $user->id));
$channels = ['mail']; $channels = ['mail'];
$slackUrl = app('preferences')->getEncryptedForUser($user, 'slack_webhook_url', '')->data; $slackUrl = (string) app('preferences')->getEncryptedForUser($user, 'slack_webhook_url', '')->data;
if (UrlValidator::isValidWebhookURL($slackUrl)) { if (UrlValidator::isValidWebhookURL($slackUrl)) {
$channels[] = 'slack'; $channels[] = 'slack';
} }
// validate presence of of Ntfy settings. // validate presence of of Ntfy settings.
if ('' !== (string) app('preferences')->getEncryptedForUser($user, 'ntfy_topic', '')->data) { $ntfyTopic = (string) app('preferences')->getEncryptedForUser($user, 'ntfy_topic', '')->data;
Log::debug('Enabled ntfy.'); if ('' !== $ntfyTopic) {
Log::debug(sprintf('Enabled ntfy, "%s"', $ntfyTopic));
$channels[] = NtfyChannel::class; $channels[] = NtfyChannel::class;
} }
if ('' === (string) app('preferences')->getEncryptedForUser($user, 'ntfy_topic', '')->data) { if ('' === (string) app('preferences')->getEncryptedForUser($user, 'ntfy_topic', '')->data) {

View File

@@ -550,9 +550,9 @@ class BillRepository implements BillRepositoryInterface
foreach ($set as $transactionJournal) { foreach ($set as $transactionJournal) {
$setAmount = bcadd($setAmount, Amount::getAmountFromJournalObject($transactionJournal)); $setAmount = bcadd($setAmount, Amount::getAmountFromJournalObject($transactionJournal));
} }
Log::debug(sprintf('Bill #%d ("%s") with %d transaction(s) and sum %s %s', $bill->id, $bill->name, $set->count(), $currency->code, $setAmount)); //Log::debug(sprintf('Bill #%d ("%s") with %d transaction(s) and sum %s %s', $bill->id, $bill->name, $set->count(), $currency->code, $setAmount));
$return[$currency->id]['sum'] = bcadd($return[$currency->id]['sum'], $setAmount); $return[$currency->id]['sum'] = bcadd($return[$currency->id]['sum'], $setAmount);
Log::debug(sprintf('Total sum is now %s', $return[$currency->id]['sum'])); //Log::debug(sprintf('Total sum is now %s', $return[$currency->id]['sum']));
} }
return $return; return $return;
@@ -586,7 +586,7 @@ class BillRepository implements BillRepositoryInterface
$minField = $convertToNative && $bill->transactionCurrency->id !== $default->id ? 'native_amount_min' : 'amount_min'; $minField = $convertToNative && $bill->transactionCurrency->id !== $default->id ? 'native_amount_min' : 'amount_min';
$maxField = $convertToNative && $bill->transactionCurrency->id !== $default->id ? 'native_amount_max' : 'amount_max'; $maxField = $convertToNative && $bill->transactionCurrency->id !== $default->id ? 'native_amount_max' : 'amount_max';
Log::debug(sprintf('min field is %s, max field is %s', $minField, $maxField)); // Log::debug(sprintf('min field is %s, max field is %s', $minField, $maxField));
if ($total > 0) { if ($total > 0) {
$currency = $convertToNative && $bill->transactionCurrency->id !== $default->id ? $default : $bill->transactionCurrency; $currency = $convertToNative && $bill->transactionCurrency->id !== $default->id ? $default : $bill->transactionCurrency;

View File

@@ -133,8 +133,8 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface
Log::debug(sprintf('Now in %s(%s, %s)', __METHOD__, $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s'))); Log::debug(sprintf('Now in %s(%s, %s)', __METHOD__, $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
$return = []; $return = [];
$availableBudgets = $this->user->availableBudgets() $availableBudgets = $this->user->availableBudgets()
->where('start_date', $start->format('Y-m-d H:i:s')) ->where('start_date', $start->format('Y-m-d'))
->where('end_date', $end->format('Y-m-d H:i:s'))->get() ->where('end_date', $end->format('Y-m-d'))->get()
; ;
Log::debug(sprintf('Found %d available budgets', $availableBudgets->count())); Log::debug(sprintf('Found %d available budgets', $availableBudgets->count()));

View File

@@ -287,7 +287,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
$amount = '' === $amount ? '0' : $amount; $amount = '' === $amount ? '0' : $amount;
$sum = bcadd($sum, $amount); $sum = bcadd($sum, $amount);
} }
Log::debug(sprintf('Current amount in piggy bank #%d ("%s") is %s', $piggyBank->id, $piggyBank->name, $sum)); // Log::debug(sprintf('Current amount in piggy bank #%d ("%s") is %s', $piggyBank->id, $piggyBank->name, $sum));
return $sum; return $sum;
} }

View File

@@ -47,16 +47,15 @@ class Preferences
} }
return Preference::where('user_id', $user->id) return Preference::where('user_id', $user->id)
->where('name', '!=', 'currencyPreference') ->where('name', '!=', 'currencyPreference')
->where(function (Builder $q) use ($user): void { ->where(function (Builder $q) use ($user): void {
$q->whereNull('user_group_id'); $q->whereNull('user_group_id');
$q->orWhere('user_group_id', $user->user_group_id); $q->orWhere('user_group_id', $user->user_group_id);
}) })
->get() ->get();
;
} }
public function get(string $name, null|array|bool|int|string $default = null): ?Preference public function get(string $name, null | array | bool | int | string $default = null): ?Preference
{ {
/** @var null|User $user */ /** @var null|User $user */
$user = auth()->user(); $user = auth()->user();
@@ -70,7 +69,7 @@ class Preferences
return $this->getForUser($user, $name, $default); return $this->getForUser($user, $name, $default);
} }
public function getForUser(User $user, string $name, null|array|bool|int|string $default = null): ?Preference public function getForUser(User $user, string $name, null | array | bool | int | string $default = null): ?Preference
{ {
// don't care about user group ID, except for some specific preferences. // don't care about user group ID, except for some specific preferences.
$userGroupId = $this->getUserGroupId($user, $name); $userGroupId = $this->getUserGroupId($user, $name);
@@ -122,16 +121,16 @@ class Preferences
Cache::put($key, '', 5); Cache::put($key, '', 5);
} }
public function setForUser(User $user, string $name, null|array|bool|int|string $value): Preference public function setForUser(User $user, string $name, null | array | bool | int | string $value): Preference
{ {
$fullName = sprintf('preference%s%s', $user->id, $name); $fullName = sprintf('preference%s%s', $user->id, $name);
$groupId = $this->getUserGroupId($user, $name); $groupId = $this->getUserGroupId($user, $name);
$groupId = 0 === (int) $groupId ? null : (int) $groupId; $groupId = 0 === (int) $groupId ? null : (int) $groupId;
Cache::forget($fullName); Cache::forget($fullName);
/** @var null|Preference $pref */ /** @var null|Preference $pref */
$pref = Preference::where('user_group_id', $groupId)->where('user_id', $user->id)->where('name', $name)->first(['id', 'name', 'data', 'updated_at', 'created_at']); $pref = Preference::where('user_group_id', $groupId)->where('user_id', $user->id)->where('name', $name)->first(['id', 'name', 'data', 'updated_at', 'created_at']);
if (null !== $pref && null === $value) { if (null !== $pref && null === $value) {
$pref->delete(); $pref->delete();
@@ -174,13 +173,12 @@ class Preferences
{ {
$result = []; $result = [];
$preferences = Preference::where('user_id', $user->id) $preferences = Preference::where('user_id', $user->id)
->where(function (Builder $q) use ($user): void { ->where(function (Builder $q) use ($user): void {
$q->whereNull('user_group_id'); $q->whereNull('user_group_id');
$q->orWhere('user_group_id', $user->user_group_id); $q->orWhere('user_group_id', $user->user_group_id);
}) })
->whereIn('name', $list) ->whereIn('name', $list)
->get(['id', 'name', 'data']) ->get(['id', 'name', 'data']);
;
/** @var Preference $preference */ /** @var Preference $preference */
foreach ($preferences as $preference) { foreach ($preferences as $preference) {
@@ -210,6 +208,10 @@ class Preferences
try { try {
$result->data = decrypt($result->data); $result->data = decrypt($result->data);
} catch (DecryptException $e) { } catch (DecryptException $e) {
if ('The MAC is invalid.' === $e->getMessage()) {
Log::debug('Set data to NULL');
$result->data = null;
}
Log::error(sprintf('Could not decrypt preference "%s": %s', $name, $e->getMessage())); Log::error(sprintf('Could not decrypt preference "%s": %s', $name, $e->getMessage()));
return $result; return $result;
@@ -218,7 +220,7 @@ class Preferences
return $result; return $result;
} }
public function getEncryptedForUser(User $user, string $name, null|array|bool|int|string $default = null): ?Preference public function getEncryptedForUser(User $user, string $name, null | array | bool | int | string $default = null): ?Preference
{ {
$result = $this->getForUser($user, $name, $default); $result = $this->getForUser($user, $name, $default);
if ('' === $result->data) { if ('' === $result->data) {
@@ -230,6 +232,10 @@ class Preferences
try { try {
$result->data = decrypt($result->data); $result->data = decrypt($result->data);
} catch (DecryptException $e) { } catch (DecryptException $e) {
if ('The MAC is invalid.' === $e->getMessage()) {
Log::debug('Set data to NULL');
$result->data = null;
}
Log::error(sprintf('Could not decrypt preference "%s": %s', $name, $e->getMessage())); Log::error(sprintf('Could not decrypt preference "%s": %s', $name, $e->getMessage()));
return $result; return $result;
@@ -239,7 +245,7 @@ class Preferences
return $result; return $result;
} }
public function getFresh(string $name, null|array|bool|int|string $default = null): ?Preference public function getFresh(string $name, null | array | bool | int | string $default = null): ?Preference
{ {
/** @var null|User $user */ /** @var null|User $user */
$user = auth()->user(); $user = auth()->user();
@@ -277,7 +283,7 @@ class Preferences
Session::forget('first'); Session::forget('first');
} }
public function set(string $name, null|array|bool|int|string $value): Preference public function set(string $name, null | array | bool | int | string $value): Preference
{ {
/** @var null|User $user */ /** @var null|User $user */
$user = auth()->user(); $user = auth()->user();

View File

@@ -331,7 +331,7 @@ class Steam
if ($native->id === $accountCurrency?->id) { if ($native->id === $accountCurrency?->id) {
$return['balance'] = bcadd('' === (string) $account->virtual_balance ? '0' : $account->virtual_balance, $return['balance']); $return['balance'] = bcadd('' === (string) $account->virtual_balance ? '0' : $account->virtual_balance, $return['balance']);
} }
Log::debug(sprintf('balance is (%s only) %s (with virtual balance)', $native->code, $this->bcround($return['balance'], 2))); //Log::debug(sprintf('balance is (%s only) %s (with virtual balance)', $native->code, $this->bcround($return['balance'], 2)));
// native balance // native balance
$return['native_balance'] = (string) $account->transactions() $return['native_balance'] = (string) $account->transactions()
@@ -342,7 +342,7 @@ class Steam
; ;
// plus native virtual balance. // plus native virtual balance.
$return['native_balance'] = bcadd('' === (string) $account->native_virtual_balance ? '0' : $account->native_virtual_balance, $return['native_balance']); $return['native_balance'] = bcadd('' === (string) $account->native_virtual_balance ? '0' : $account->native_virtual_balance, $return['native_balance']);
Log::debug(sprintf('native_balance is (all transactions to %s) %s (with virtual balance)', $native->code, $this->bcround($return['native_balance']))); //Log::debug(sprintf('native_balance is (all transactions to %s) %s (with virtual balance)', $native->code, $this->bcround($return['native_balance'])));
// plus foreign transactions in THIS currency. // plus foreign transactions in THIS currency.
$sum = (string) $account->transactions() $sum = (string) $account->transactions()
@@ -354,7 +354,7 @@ class Steam
; ;
$return['native_balance'] = bcadd($return['native_balance'], $sum); $return['native_balance'] = bcadd($return['native_balance'], $sum);
Log::debug(sprintf('Foreign amount transactions add (%s only) %s, total native_balance is now %s', $native->code, $this->bcround($sum), $this->bcround($return['native_balance']))); // Log::debug(sprintf('Foreign amount transactions add (%s only) %s, total native_balance is now %s', $native->code, $this->bcround($sum), $this->bcround($return['native_balance'])));
} }
// balance(s) in other (all) currencies. // balance(s) in other (all) currencies.
@@ -365,12 +365,12 @@ class Steam
->get(['transaction_currencies.code', 'transactions.amount'])->toArray() ->get(['transaction_currencies.code', 'transactions.amount'])->toArray()
; ;
$others = $this->groupAndSumTransactions($array, 'code', 'amount'); $others = $this->groupAndSumTransactions($array, 'code', 'amount');
Log::debug('All balances are (joined)', $others); // Log::debug('All balances are (joined)', $others);
// if the account has no own currency preference, drop balance in favor of native balance // if the account has no own currency preference, drop balance in favor of native balance
if ($hasCurrency && !$convertToNative) { if ($hasCurrency && !$convertToNative) {
$return['balance'] = $others[$currency->code] ?? '0'; $return['balance'] = $others[$currency->code] ?? '0';
$return['native_balance'] = $others[$currency->code] ?? '0'; $return['native_balance'] = $others[$currency->code] ?? '0';
Log::debug(sprintf('Set balance + native_balance to %s', $return['balance'])); // Log::debug(sprintf('Set balance + native_balance to %s', $return['balance']));
} }
// if the currency is the same as the native currency, set the native_balance to the balance for consistency. // if the currency is the same as the native currency, set the native_balance to the balance for consistency.
@@ -379,14 +379,14 @@ class Steam
// } // }
if (!$hasCurrency && array_key_exists('balance', $return) && array_key_exists('native_balance', $return)) { if (!$hasCurrency && array_key_exists('balance', $return) && array_key_exists('native_balance', $return)) {
Log::debug('Account has no currency preference, dropping balance in favor of native balance.'); // Log::debug('Account has no currency preference, dropping balance in favor of native balance.');
$sum = bcadd($return['balance'], $return['native_balance']); $sum = bcadd($return['balance'], $return['native_balance']);
Log::debug(sprintf('%s + %s = %s', $return['balance'], $return['native_balance'], $sum)); // Log::debug(sprintf('%s + %s = %s', $return['balance'], $return['native_balance'], $sum));
$return['native_balance'] = $sum; $return['native_balance'] = $sum;
unset($return['balance']); unset($return['balance']);
} }
$final = array_merge($return, $others); $final = array_merge($return, $others);
Log::debug('Return is', $final); // Log::debug('Return is', $final);
return $final; return $final;
} }