Fix various API 500 errors.

This commit is contained in:
James Cole
2025-01-26 06:30:38 +01:00
parent 6d89485792
commit c204533195
6 changed files with 39 additions and 20 deletions

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Exceptions; namespace FireflyIII\Exceptions;
use Brick\Math\Exception\NumberFormatException;
use FireflyIII\Jobs\MailError; use FireflyIII\Jobs\MailError;
use Illuminate\Auth\Access\AuthorizationException; use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Auth\AuthenticationException; use Illuminate\Auth\AuthenticationException;
@@ -133,10 +134,10 @@ class Handler extends ExceptionHandler
return response()->json(['message' => $e->getMessage(), 'exception' => 'BadHttpHeaderException'], $e->statusCode); return response()->json(['message' => $e->getMessage(), 'exception' => 'BadHttpHeaderException'], $e->statusCode);
} }
if($e instanceof ValidationException && $expectsJson) { if(($e instanceof ValidationException || $e instanceof NumberFormatException) && $expectsJson) {
$errorCode = 422; $errorCode = 422;
return response()->json( return response()->json(
['message' => sprintf('Validation exception: %s', $e->getMessage()), 'errors' => ['date' => 'Date is invalid']], ['message' => sprintf('Validation exception: %s', $e->getMessage()), 'errors' => ['field' => 'Field is invalid']],
$errorCode $errorCode
); );
} }

View File

@@ -79,6 +79,11 @@ class UniqueAccountNumber implements ValidationRule
if (null === $this->expectedType) { if (null === $this->expectedType) {
return; return;
} }
if(is_array($value)) {
$fail('validation.generic_invalid')->translate();
return;
}
$value = (string) $value;
$maxCounts = $this->getMaxOccurrences(); $maxCounts = $this->getMaxOccurrences();
foreach ($maxCounts as $type => $max) { foreach ($maxCounts as $type => $max) {

View File

@@ -94,6 +94,10 @@ class UniqueIban implements ValidationRule
if (0 === count($this->expectedTypes)) { if (0 === count($this->expectedTypes)) {
return true; return true;
} }
if(is_array($value)) {
return false;
}
$value = (string) $value;
$maxCounts = $this->getMaxOccurrences(); $maxCounts = $this->getMaxOccurrences();
foreach ($maxCounts as $type => $max) { foreach ($maxCounts as $type => $max) {

View File

@@ -90,7 +90,7 @@ trait ChartGeneration
$balance = $range[$format] ?? $previous; $balance = $range[$format] ?? $previous;
$previous = $balance; $previous = $balance;
$currentStart->addDay(); $currentStart->addDay();
$currentSet['entries'][$label] = $balance[$field]; $currentSet['entries'][$label] = $balance[$field] ?? '0';
} }
$chartData[] = $currentSet; $chartData[] = $currentSet;
} }

View File

@@ -38,6 +38,7 @@ use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Services\Password\Verifier; use FireflyIII\Services\Password\Verifier;
use FireflyIII\Support\ParseDateString; use FireflyIII\Support\ParseDateString;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\Validator; use Illuminate\Validation\Validator;
use PragmaRX\Google2FA\Exceptions\IncompatibleWithGoogleAuthenticatorException; use PragmaRX\Google2FA\Exceptions\IncompatibleWithGoogleAuthenticatorException;
use PragmaRX\Google2FA\Exceptions\InvalidCharactersException; use PragmaRX\Google2FA\Exceptions\InvalidCharactersException;
@@ -66,7 +67,7 @@ class FireflyValidator extends Validator
} }
$user = auth()->user(); $user = auth()->user();
if (null === $user) { if (null === $user) {
app('log')->error('No user during validate2faCode'); Log::error('No user during validate2faCode');
return false; return false;
} }
@@ -104,6 +105,9 @@ class FireflyValidator extends Validator
*/ */
public function validateBic(mixed $attribute, mixed $value): bool public function validateBic(mixed $attribute, mixed $value): bool
{ {
if(!is_string($value) || strlen($value) < 8) {
return false;
}
$regex = '/^[a-z]{6}[0-9a-z]{2}([0-9a-z]{3})?\z/i'; $regex = '/^[a-z]{6}[0-9a-z]{2}([0-9a-z]{3})?\z/i';
$result = preg_match($regex, $value); $result = preg_match($regex, $value);
if (false === $result || 0 === $result) { if (false === $result || 0 === $result) {
@@ -120,7 +124,7 @@ class FireflyValidator extends Validator
} }
$user = auth()->user(); $user = auth()->user();
if (null === $user) { if (null === $user) {
app('log')->error('No user during validate2faCode'); Log::error('No user during validate2faCode');
return false; return false;
} }
@@ -212,8 +216,8 @@ class FireflyValidator extends Validator
$checksum = bcmod($iban, '97'); $checksum = bcmod($iban, '97');
} catch (\ValueError $e) { // @phpstan-ignore-line } catch (\ValueError $e) { // @phpstan-ignore-line
$message = sprintf('Could not validate IBAN check value "%s" (IBAN "%s")', $iban, $value); $message = sprintf('Could not validate IBAN check value "%s" (IBAN "%s")', $iban, $value);
app('log')->error($message); Log::error($message);
app('log')->error($e->getTraceAsString()); Log::error($e->getTraceAsString());
return false; return false;
} }
@@ -427,7 +431,7 @@ class FireflyValidator extends Validator
try { try {
$parser->parseDate($value); $parser->parseDate($value);
} catch (FireflyException $e) { } catch (FireflyException $e) {
app('log')->error($e->getMessage()); Log::error($e->getMessage());
return false; return false;
} }
@@ -467,41 +471,45 @@ class FireflyValidator extends Validator
*/ */
public function validateUniqueAccountForUser($attribute, $value, $parameters): bool public function validateUniqueAccountForUser($attribute, $value, $parameters): bool
{ {
if(is_array($value)) {
Log::debug('$value is an array, always return false', $value);
return false;
}
// because a user does not have to be logged in (tests and what-not). // because a user does not have to be logged in (tests and what-not).
if (!auth()->check()) { if (!auth()->check()) {
app('log')->debug('validateUniqueAccountForUser::anon'); Log::debug('validateUniqueAccountForUser::anon');
return $this->validateAccountAnonymously(); return $this->validateAccountAnonymously();
} }
if (array_key_exists('objectType', $this->data)) { if (array_key_exists('objectType', $this->data)) {
app('log')->debug('validateUniqueAccountForUser::typeString'); Log::debug('validateUniqueAccountForUser::typeString');
return $this->validateByAccountTypeString($value, $parameters, $this->data['objectType']); return $this->validateByAccountTypeString($value, $parameters, $this->data['objectType']);
} }
if (array_key_exists('type', $this->data)) { if (array_key_exists('type', $this->data) && !is_array($this->data['type'])) {
app('log')->debug('validateUniqueAccountForUser::typeString'); Log::debug('validateUniqueAccountForUser::typeString');
return $this->validateByAccountTypeString($value, $parameters, (string) $this->data['type']); return $this->validateByAccountTypeString($value, $parameters, (string) $this->data['type']);
} }
if (array_key_exists('account_type_id', $this->data)) { if (array_key_exists('account_type_id', $this->data)) {
app('log')->debug('validateUniqueAccountForUser::typeId'); Log::debug('validateUniqueAccountForUser::typeId');
return $this->validateByAccountTypeId($value, $parameters); return $this->validateByAccountTypeId($value, $parameters);
} }
$parameterId = $parameters[0] ?? null; $parameterId = $parameters[0] ?? null;
if (null !== $parameterId) { if (null !== $parameterId) {
app('log')->debug('validateUniqueAccountForUser::paramId'); Log::debug('validateUniqueAccountForUser::paramId');
return $this->validateByParameterId((int) $parameterId, $value); return $this->validateByParameterId((int) $parameterId, $value);
} }
if (array_key_exists('id', $this->data)) { if (array_key_exists('id', $this->data)) {
app('log')->debug('validateUniqueAccountForUser::accountId'); Log::debug('validateUniqueAccountForUser::accountId');
return $this->validateByAccountId($value); return $this->validateByAccountId($value);
} }
// without type, just try to validate the name. // without type, just try to validate the name.
app('log')->debug('validateUniqueAccountForUser::accountName'); Log::debug('validateUniqueAccountForUser::accountName');
return $this->validateByAccountName($value); return $this->validateByAccountName($value);
} }
@@ -642,11 +650,11 @@ class FireflyValidator extends Validator
} }
$type = $this->data['objectType'] ?? 'unknown'; $type = $this->data['objectType'] ?? 'unknown';
if ('expense' !== $type && 'revenue' !== $type) { if ('expense' !== $type && 'revenue' !== $type) {
app('log')->warning(sprintf('Account number "%s" is not unique and account type "%s" cannot share its account number.', $value, $type)); Log::warning(sprintf('Account number "%s" is not unique and account type "%s" cannot share its account number.', $value, $type));
return false; return false;
} }
app('log')->debug(sprintf('Account number "%s" is not unique but account type "%s" may share its account number.', $value, $type)); Log::debug(sprintf('Account number "%s" is not unique but account type "%s" may share its account number.', $value, $type));
// one other account with this account number. // one other account with this account number.
/** @var AccountMeta $entry */ /** @var AccountMeta $entry */
@@ -654,11 +662,11 @@ class FireflyValidator extends Validator
$otherAccount = $entry->account; $otherAccount = $entry->account;
$otherType = (string) config(sprintf('firefly.shortNamesByFullName.%s', $otherAccount->accountType->type)); $otherType = (string) config(sprintf('firefly.shortNamesByFullName.%s', $otherAccount->accountType->type));
if (('expense' === $otherType || 'revenue' === $otherType) && $otherType !== $type) { if (('expense' === $otherType || 'revenue' === $otherType) && $otherType !== $type) {
app('log')->debug(sprintf('The other account with this account number is a "%s" so return true.', $otherType)); Log::debug(sprintf('The other account with this account number is a "%s" so return true.', $otherType));
return true; return true;
} }
app('log')->debug(sprintf('The other account with this account number is a "%s" so return false.', $otherType)); Log::debug(sprintf('The other account with this account number is a "%s" so return false.', $otherType));
} }
return false; return false;

View File

@@ -144,6 +144,7 @@ return [
'numeric_native' => 'The native amount must be a number.', 'numeric_native' => 'The native amount must be a number.',
'numeric_destination' => 'The destination amount must be a number.', 'numeric_destination' => 'The destination amount must be a number.',
'numeric_source' => 'The source amount must be a number.', 'numeric_source' => 'The source amount must be a number.',
'generic_invalid' => 'This value is invalid.',
'regex' => 'The :attribute format is invalid.', 'regex' => 'The :attribute format is invalid.',
'required' => 'The :attribute field is required.', 'required' => 'The :attribute field is required.',
'required_if' => 'The :attribute field is required when :other is :value.', 'required_if' => 'The :attribute field is required when :other is :value.',