Compare commits

..

6 Commits

Author SHA1 Message Date
github-actions[bot]
857fe8ed76 Merge pull request #11579 from firefly-iii/release-1769181522
🤖 Automatically merge the PR into the develop branch.
2026-01-23 16:18:50 +01:00
JC5
2cca32d021 🤖 Auto commit for release 'develop' on 2026-01-23 2026-01-23 16:18:42 +01:00
James Cole
09c4f4702d Missing return statement 2026-01-23 16:13:33 +01:00
James Cole
a44f0f362f Catch on user login. 2026-01-23 16:12:49 +01:00
James Cole
b147c5abc6 Merge branch 'main' into develop 2026-01-23 15:16:48 +01:00
James Cole
099e60a2fa Do format. 2026-01-23 15:16:41 +01:00
20 changed files with 77 additions and 49 deletions

View File

@@ -176,8 +176,7 @@ jobs:
run: |
rm -rf vendor composer.lock
composer update --no-scripts --no-plugins -q
mago format --dry-run || true
mago lint --reporting-format=github || true
mago format || true
mago analyze --reporting-format=github || true
sudo chown -R runner:docker resources/lang
.ci/phpcs.sh || true

View File

@@ -36,7 +36,7 @@ use League\Fractal\Resource\Item;
/**
* Class UpdateController
*/
class UpdateController extends Controller
final class UpdateController extends Controller
{
private RuleGroupRepositoryInterface $ruleGroupRepository;

View File

@@ -240,8 +240,8 @@ class BasicController extends Controller
'value_parsed' => Amount::formatAnything($currency, $sums[$currencyId]['sum'] ?? '0', false),
'local_icon' => 'balance-scale',
'sub_title' => Amount::formatAnything($currency, $expenses[$currencyId]['sum'] ?? '0', false)
.' + '
.Amount::formatAnything($currency, $incomes[$currencyId]['sum'] ?? '0', false),
.' + '
.Amount::formatAnything($currency, $incomes[$currencyId]['sum'] ?? '0', false),
];
$return[] = [
'key' => sprintf('spent-in-%s', $currency->code),

View File

@@ -75,8 +75,19 @@ class UpdateRequest extends FormRequest
/** @var Webhook $webhook */
$webhook = $this->route()->parameter('webhook');
return ['title' => sprintf('min:1|max:255|uniqueObjectForUser:webhooks,title,%d', $webhook->id), 'active' => [new IsBoolean()],
'trigger' => 'prohibited', 'triggers' => 'required|array|min:1|max:10', 'triggers.*' => sprintf('required|in:%s', $triggers), 'response' => 'prohibited', 'responses' => 'required|array|min:1|max:1', 'responses.*' => sprintf('required|in:%s', $responses), 'delivery' => 'prohibited', 'deliveries' => 'required|array|min:1|max:1', 'deliveries.*' => sprintf('required|in:%s', $deliveries),
'url' => [sprintf('url:%s', $validProtocols), sprintf('uniqueExistingWebhook:%d', $webhook->id)]];
return [
'title' => sprintf('min:1|max:255|uniqueObjectForUser:webhooks,title,%d', $webhook->id),
'active' => [new IsBoolean()],
'trigger' => 'prohibited',
'triggers' => 'required|array|min:1|max:10',
'triggers.*' => sprintf('required|in:%s', $triggers),
'response' => 'prohibited',
'responses' => 'required|array|min:1|max:1',
'responses.*' => sprintf('required|in:%s', $responses),
'delivery' => 'prohibited',
'deliveries' => 'required|array|min:1|max:1',
'deliveries.*' => sprintf('required|in:%s', $deliveries),
'url' => [sprintf('url:%s', $validProtocols), sprintf('uniqueExistingWebhook:%d', $webhook->id)],
];
}
}

View File

@@ -44,6 +44,6 @@ class UserFailedLoginAttempt extends Event
return;
}
throw new InvalidArgumentException('User must be an instance of User.');
throw new InvalidArgumentException(sprintf('User cannot be an instance of %s.', get_class($user)));
}
}

View File

@@ -44,6 +44,6 @@ class UserHasDisabledMFA extends Event
return;
}
throw new InvalidArgumentException('User must be an instance of User.');
throw new InvalidArgumentException(sprintf('User cannot be an instance of %s.', get_class($user)));
}
}

View File

@@ -44,6 +44,6 @@ class UserHasEnabledMFA extends Event
return;
}
throw new InvalidArgumentException('User must be an instance of User.');
throw new InvalidArgumentException(sprintf('User cannot be an instance of %s.', get_class($user)));
}
}

View File

@@ -46,6 +46,6 @@ class UserHasFewMFABackupCodesLeft extends Event
return;
}
throw new InvalidArgumentException('User must be an instance of User.');
throw new InvalidArgumentException(sprintf('User cannot be an instance of %s.', get_class($user)));
}
}

View File

@@ -44,6 +44,6 @@ class UserHasGeneratedNewBackupCodes extends Event
return;
}
throw new InvalidArgumentException('User must be an instance of User.');
throw new InvalidArgumentException(sprintf('User cannot be an instance of %s.', get_class($user)));
}
}

View File

@@ -44,6 +44,6 @@ class UserHasNoMFABackupCodesLeft extends Event
return;
}
throw new InvalidArgumentException('User must be an instance of User.');
throw new InvalidArgumentException(sprintf('User cannot be an instance of %s.', get_class($user)));
}
}

View File

@@ -44,6 +44,6 @@ class UserHasUsedBackupCode extends Event
return;
}
throw new InvalidArgumentException('User must be an instance of User.');
throw new InvalidArgumentException(sprintf('User cannot be an instance of %s.', get_class($user)));
}
}

View File

@@ -46,6 +46,6 @@ class UserKeepsFailingMFA extends Event
return;
}
throw new InvalidArgumentException('User must be an instance of User.');
throw new InvalidArgumentException(sprintf('User cannot be an instance of %s.', get_class($user)));
}
}

View File

@@ -40,8 +40,10 @@ class UserSuccessfullyLoggedIn extends Event
{
if ($user instanceof User) {
$this->user = $user;
return;
}
throw new InvalidArgumentException('User must be an instance of User.');
throw new InvalidArgumentException(sprintf('User cannot be an instance of %s.', get_class($user)));
}
}

View File

@@ -99,10 +99,7 @@ class LoginController extends Controller
// basic validation exception.
// report the failed login to the user if the count is 2 or 5.
// TODO here be warning.
return redirect(route('login'))
->withErrors([$this->username => trans('auth.failed')])
->onlyInput($this->username)
;
return redirect(route('login'))->withErrors([$this->username => trans('auth.failed')])->onlyInput($this->username);
}
Log::debug('Login data is present.');

View File

@@ -51,7 +51,7 @@ use Illuminate\View\View;
/**
* Class IndexController
*/
class IndexController extends Controller
final class IndexController extends Controller
{
use DateCalculation;

View File

@@ -40,12 +40,16 @@ class ConfigurationRequest extends FormRequest
*/
public function getConfigurationData(): array
{
return ['single_user_mode' => $this->boolean('single_user_mode'),
'enable_exchange_rates' => $this->boolean('enable_exchange_rates'), 'use_running_balance' => $this->boolean('use_running_balance'),
'enable_external_map' => $this->boolean(
'enable_external_map'
), 'enable_external_rates' => $this->boolean('enable_external_rates'), 'allow_webhooks' => $this->boolean('allow_webhooks'),
'valid_url_protocols' => $this->string('valid_url_protocols'), 'is_demo_site' => $this->boolean('is_demo_site')];
return [
'single_user_mode' => $this->boolean('single_user_mode'),
'enable_exchange_rates' => $this->boolean('enable_exchange_rates'),
'use_running_balance' => $this->boolean('use_running_balance'),
'enable_external_map' => $this->boolean('enable_external_map'),
'enable_external_rates' => $this->boolean('enable_external_rates'),
'allow_webhooks' => $this->boolean('allow_webhooks'),
'valid_url_protocols' => $this->string('valid_url_protocols'),
'is_demo_site' => $this->boolean('is_demo_site'),
];
}
/**
@@ -54,10 +58,16 @@ class ConfigurationRequest extends FormRequest
public function rules(): array
{
// fixed
return ['single_user_mode' => 'min:0|max:1|numeric',
'enable_exchange_rates' => 'min:0|max:1|numeric', 'use_running_balance' => 'min:0|max:1|numeric',
'enable_external_map' => 'min:0|max:1|numeric', 'enable_external_rates' => 'min:0|max:1|numeric', 'allow_webhooks' => 'min:0|max:1|numeric',
'valid_url_protocols' => 'min:0|max:255', 'is_demo_site' => 'min:0|max:1|numeric'];
return [
'single_user_mode' => 'min:0|max:1|numeric',
'enable_exchange_rates' => 'min:0|max:1|numeric',
'use_running_balance' => 'min:0|max:1|numeric',
'enable_external_map' => 'min:0|max:1|numeric',
'enable_external_rates' => 'min:0|max:1|numeric',
'allow_webhooks' => 'min:0|max:1|numeric',
'valid_url_protocols' => 'min:0|max:255',
'is_demo_site' => 'min:0|max:1|numeric',
];
}
public function withValidator(Validator $validator): void

View File

@@ -322,12 +322,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface, UserGroupInte
$query->where('accounts.user_id', $this->user->id);
}
return $query
->with(['objectGroups'])
->orderBy('piggy_banks.order', 'ASC')
->distinct()
->get(['piggy_banks.*'])
;
return $query->with(['objectGroups'])->orderBy('piggy_banks.order', 'ASC')->distinct()->get(['piggy_banks.*']);
}
public function getRepetition(PiggyBank $piggyBank, bool $overrule = false): ?PiggyBankRepetition

View File

@@ -42,9 +42,23 @@ class ExchangeRateTransformer extends AbstractTransformer
*/
public function transform(CurrencyExchangeRate $rate): array
{
return ['id' => (string) $rate->id, 'created_at' => $rate->created_at->toAtomString(), 'updated_at' => $rate->updated_at->toAtomString(),
'from_currency_id' => (string) $rate->fromCurrency->id, 'from_currency_name' => $rate->fromCurrency->name, 'from_currency_code' => $rate->fromCurrency->code, 'from_currency_symbol' => $rate->fromCurrency->symbol, 'from_currency_decimal_places' => $rate->fromCurrency->decimal_places,
'to_currency_id' => (string) $rate->toCurrency->id, 'to_currency_name' => $rate->toCurrency->name, 'to_currency_code' => $rate->toCurrency->code, 'to_currency_symbol' => $rate->toCurrency->symbol, 'to_currency_decimal_places' => $rate->toCurrency->decimal_places,
'rate' => $rate->rate, 'date' => $rate->date->toAtomString(), 'links' => [['rel' => 'self', 'uri' => sprintf('/exchange-rates/%s', $rate->id)]]];
return [
'id' => (string) $rate->id,
'created_at' => $rate->created_at->toAtomString(),
'updated_at' => $rate->updated_at->toAtomString(),
'from_currency_id' => (string) $rate->fromCurrency->id,
'from_currency_name' => $rate->fromCurrency->name,
'from_currency_code' => $rate->fromCurrency->code,
'from_currency_symbol' => $rate->fromCurrency->symbol,
'from_currency_decimal_places' => $rate->fromCurrency->decimal_places,
'to_currency_id' => (string) $rate->toCurrency->id,
'to_currency_name' => $rate->toCurrency->name,
'to_currency_code' => $rate->toCurrency->code,
'to_currency_symbol' => $rate->toCurrency->symbol,
'to_currency_decimal_places' => $rate->toCurrency->decimal_places,
'rate' => $rate->rate,
'date' => $rate->date->toAtomString(),
'links' => [['rel' => 'self', 'uri' => sprintf('/exchange-rates/%s', $rate->id)]],
];
}
}

12
composer.lock generated
View File

@@ -10079,16 +10079,16 @@
"packages-dev": [
{
"name": "barryvdh/laravel-debugbar",
"version": "v3.16.4",
"version": "v3.16.5",
"source": {
"type": "git",
"url": "https://github.com/fruitcake/laravel-debugbar.git",
"reference": "8c24feb48f26c830c433abf3f98947d828c7ed29"
"reference": "e85c0a8464da67e5b4a53a42796d46a43fc06c9a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/fruitcake/laravel-debugbar/zipball/8c24feb48f26c830c433abf3f98947d828c7ed29",
"reference": "8c24feb48f26c830c433abf3f98947d828c7ed29",
"url": "https://api.github.com/repos/fruitcake/laravel-debugbar/zipball/e85c0a8464da67e5b4a53a42796d46a43fc06c9a",
"reference": "e85c0a8464da67e5b4a53a42796d46a43fc06c9a",
"shasum": ""
},
"require": {
@@ -10148,7 +10148,7 @@
],
"support": {
"issues": "https://github.com/fruitcake/laravel-debugbar/issues",
"source": "https://github.com/fruitcake/laravel-debugbar/tree/v3.16.4"
"source": "https://github.com/fruitcake/laravel-debugbar/tree/v3.16.5"
},
"funding": [
{
@@ -10160,7 +10160,7 @@
"type": "github"
}
],
"time": "2026-01-23T10:40:24+00:00"
"time": "2026-01-23T15:03:22+00:00"
},
{
"name": "barryvdh/laravel-ide-helper",

View File

@@ -79,7 +79,7 @@ return [
// see cer.php for exchange rates feature flag.
],
'version' => 'develop/2026-01-23',
'build_time' => 1769177534,
'build_time' => 1769181393,
'api_version' => '2.1.0', // field is no longer used.
'db_version' => 28, // field is no longer used.