Merge pull request #12022 from firefly-iii/develop

🤖 Automatically merge the PR into the main branch.
This commit is contained in:
github-actions[bot]
2026-03-23 08:33:08 +01:00
committed by GitHub
17 changed files with 593 additions and 857 deletions
+8 -1
View File
@@ -6,6 +6,8 @@
2. If your PR is more than 25 lines, talk to me FIRST.
3. If you fix spelling or code comments, talk to me FIRST.
This is to prevent AI bots, low-effort PRs and spam. Sorry about that.
Wanna talk to me? Open a GitHub Issue, Discussion, or email me: james@firefly-iii.org
👀 Please ensure you have taken a look at the contribution guidelines:
@@ -17,7 +19,9 @@ Remember that your PR may be CLOSED:
2. If you open a PR on the main branch, your PR will be CLOSED.
3. If you only fix a spelling error or code comment, your PR will be CLOSED.
Thanks again, and happy developing!
Again, this is to prevent AI bots, low-effort PRs and spam. I apologize for the harsh tone.
But if you made it this far thanks again for contributing, and happy developing!
-->
@@ -48,3 +52,6 @@ I used AI assistance for:
<!--
Thanks for contributing!
-->
@JC5
+1
View File
@@ -4,6 +4,7 @@ Over time, many people have contributed to Firefly III. Their efforts are not al
Please find below all the people who contributed to the Firefly III code. Their names are mentioned in the year of their first contribution.
## 2026
- Joe Longendyke
- Daniel Holøien
- Matthew Grove
- Cinnamon Pyro
@@ -35,7 +35,6 @@ use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Transformers\CurrencyTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
use League\Fractal\Resource\Item;
/**
@@ -154,7 +153,6 @@ final class UpdateController extends Controller
public function update(UpdateRequest $request, TransactionCurrency $currency): JsonResponse
{
$data = $request->getAll();
Log::debug(__METHOD__, $data);
/** @var User $user */
$user = auth()->user();
@@ -28,6 +28,7 @@ use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\User;
use Illuminate\Foundation\Http\FormRequest;
/**
@@ -45,15 +46,23 @@ class UpdateRequest extends FormRequest
*/
public function getAll(): array
{
// return nothing that isn't explicitly in the array:
$fields = [
'name' => ['name', 'convertString'],
'code' => ['code', 'convertString'],
'symbol' => ['symbol', 'convertString'],
'decimal_places' => ['decimal_places', 'convertInteger'],
'default' => ['default', 'boolean'],
'enabled' => ['enabled', 'boolean'],
/** @var User $user */
$user = auth()->user();
$isAdmin = $user->hasRole('owner');
$fields = [
'enabled' => ['enabled', 'boolean'],
];
if ($isAdmin) {
$fields = [
'name' => ['name', 'convertString'],
'code' => ['code', 'convertString'],
'symbol' => ['symbol', 'convertString'],
'decimal_places' => ['decimal_places', 'convertInteger'],
'default' => ['default', 'boolean'],
'enabled' => ['enabled', 'boolean'],
];
}
return $this->getAllData($fields);
}
+1 -1
View File
@@ -251,7 +251,7 @@ class Handler extends ExceptionHandler
'method' => request()->method(),
'headers' => $headers,
// @mago-expect lint:no-request-all
'post' => 'POST' === request()->method() ? json_encode(request()->all()) : '',
'post' => 'PUT' === request()->method() || 'POST' === request()->method() ? json_encode(request()->all()) : '',
];
// create job that will mail.
+15 -34
View File
@@ -75,8 +75,6 @@ class GroupCollector implements GroupCollectorInterface
$this->userGroup = null;
$this->limit = null;
$this->page = null;
$this->startRow = null;
$this->endRow = null;
$this->hasAccountInfo = false;
$this->hasCatInformation = false;
@@ -443,9 +441,15 @@ class GroupCollector implements GroupCollectorInterface
$this->query->orWhereIn('transaction_journals.transaction_group_id', $groupIds);
}
$result = $this->query->get($this->fields);
$this->total = $result->count();
// if no post-filters are present, it can be sliced and returned.
if (0 === count($this->sorting) && 0 === count($this->postFilters) && null !== $this->limit && null !== $this->page) {
$offset = ($this->page - 1) * $this->limit;
$result = $result->slice($offset, $this->limit);
}
// $this->dumpQueryInLogs();
// Log::debug(sprintf('Count of result is %d', $result->count()));
// now to parse this into an array.
// now to parse the rest into an array.
$collection = $this->parseArray($result);
// filter the array using all available post filters:
@@ -454,19 +458,12 @@ class GroupCollector implements GroupCollectorInterface
// sort the collection, if sort instructions are present.
$collection = $this->sortCollection($collection);
// count it and continue:
$this->total = $collection->count();
// now filter the array according to the page and the limit (if necessary)
if (null !== $this->limit && null !== $this->page) {
if (count($this->postFilters) > 0 && null !== $this->limit && null !== $this->page) {
$offset = ($this->page - 1) * $this->limit;
return $collection->slice($offset, $this->limit);
}
// OR filter the array according to the start and end row variable
if (null !== $this->startRow && null !== $this->endRow) {
return $collection->slice($this->startRow, $this->endRow);
}
return $collection;
}
@@ -477,17 +474,11 @@ class GroupCollector implements GroupCollectorInterface
public function getPaginatedGroups(): LengthAwarePaginator
{
Log::debug('Now in getPaginatedGroups()');
$set = $this->getGroups();
$limit = $this->limit ?? 1;
if (0 === $this->limit) {
$this->setLimit(50);
}
if (null !== $this->startRow && null !== $this->endRow) {
/** @var int $total */
$total = $this->endRow - $this->startRow;
return new LengthAwarePaginator($set, $this->total, $total, 1);
}
$limit = $this->limit ?? 1;
$set = $this->getGroups();
return new LengthAwarePaginator($set, $this->total, $limit, $this->page);
}
@@ -519,13 +510,6 @@ class GroupCollector implements GroupCollectorInterface
return $this;
}
public function setEndRow(int $endRow): self
{
$this->endRow = $endRow;
return $this;
}
public function setExpandGroupSearch(bool $expandGroupSearch): GroupCollectorInterface
{
$this->expandGroupSearch = $expandGroupSearch;
@@ -636,13 +620,6 @@ class GroupCollector implements GroupCollectorInterface
return $this;
}
public function setStartRow(int $startRow): self
{
$this->startRow = $startRow;
return $this;
}
/**
* Limit the search to one specific transaction group.
*/
@@ -692,6 +669,10 @@ class GroupCollector implements GroupCollectorInterface
#[Override]
public function sortCollection(Collection $collection): Collection
{
if (0 === count($this->sorting)) {
return $collection;
}
/**
* @var string $field
* @var string $direction
@@ -469,11 +469,6 @@ interface GroupCollectorInterface
*/
public function setEnd(Carbon $end): self;
/**
* Set the page to get.
*/
public function setEndRow(int $endRow): self;
public function setExpandGroupSearch(bool $expandGroupSearch): self;
/**
@@ -573,11 +568,6 @@ interface GroupCollectorInterface
*/
public function setStart(Carbon $start): self;
/**
* Set the page to get.
*/
public function setStartRow(int $startRow): self;
/**
* Limit results to a specific tag.
*/
@@ -132,7 +132,7 @@ final class NotificationController extends Controller
return redirect(route('settings.notification.index'));
}
$all = $request->only(['channel']);
$all = $request->only(['test_submit']);
$channel = $all['test_submit'] ?? '';
switch ($channel) {
+5
View File
@@ -29,6 +29,7 @@ use FireflyIII\User;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
/**
* Class IsAdmin.
@@ -41,6 +42,8 @@ class IsAdminApi
* @param null|string $guard
*
* @return mixed
*
* @throws AuthorizationException
*/
public function handle(Request $request, Closure $next, $guard = null)
{
@@ -58,6 +61,8 @@ class IsAdminApi
/** @var UserRepositoryInterface $repository */
$repository = app(UserRepositoryInterface::class);
if (!$repository->hasRole($user, 'owner')) {
Log::error(sprintf('Cannot access %s?%s.', $request->url(), $request->getQueryString()));
throw new AuthorizationException();
}
@@ -202,7 +202,7 @@ class PrimaryAmountRecalculationService
/** @var Account $account */
foreach ($set as $account) {
$currencyId = (int) $account->accountMeta()->where('name', 'currency_id')->first()->data;
$currencyId = (int) $account->accountMeta()->where('name', 'currency_id')->first()?->data;
if ($groupCurrency->id === $currencyId) {
Log::debug(sprintf('Account "%s" is in group currency %s. Skip.', $account->name, $groupCurrency->code));
@@ -774,8 +774,8 @@ class JournalUpdateService
$this->transactionJournal,
'update_foreign_amount',
[
'currency_symbol' => $oldForeignCurrency->symbol,
'decimal_places' => $oldForeignCurrency->decimal_places,
'currency_symbol' => $oldForeignCurrency?->symbol,
'decimal_places' => $oldForeignCurrency?->decimal_places,
'amount' => $originalSourceAmount,
],
[
+1 -1
View File
@@ -70,7 +70,7 @@ class Date implements BinderInterface
try {
$result = new Carbon($value);
} catch (InvalidDateException|InvalidFormatException $e) {
$message = sprintf('Could not parse date "%s" for user #%d: %s', $value, auth()->user()->id, $e->getMessage());
$message = sprintf('Could not parse date "%s" for user #%d: %s', $value, (int) auth()->user()?->id, $e->getMessage());
Log::error($message);
throw new NotFoundHttpException('Could not parse value', $e);
+12 -1
View File
@@ -3,7 +3,18 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
### v6.5.8 - 2026-03-22
## v6.5.9 - 2026-03-23
<!-- summary: Bug fixes mainly, but also updated dependencies and new wording in the instructions you see when you open a PR. -->
### Fixed
- [Issue 12004](https://github.com/firefly-iii/firefly-iii/issues/12004) (Test notification buttons always generate an error) reported by @IDevJoe
- [Issue 12014](https://github.com/firefly-iii/firefly-iii/issues/12014) (Converting a transaction to a transfer and setting the destination account to one with a different currency breaks the audit log) reported by @avee87
# Changed
- [Issue 12000](https://github.com/firefly-iii/firefly-iii/issues/12000) (Improved transaction pagination for large data sets) reported by @christiaanderidder
## v6.5.8 - 2026-03-22
<!-- summary: This release fixes a regression bug in user registration. -->
+2 -2
View File
@@ -78,8 +78,8 @@ return [
'running_balance_column' => (bool)envDefaultWhenEmpty(env('USE_RUNNING_BALANCE'), true), // this is only the default value, is not used.
// see cer.php for exchange rates feature flag.
],
'version' => '6.5.8',
'build_time' => 1774090288,
'version' => '6.5.9',
'build_time' => 1774250981,
'api_version' => '2.1.0', // field is no longer used.
'db_version' => 28, // field is no longer used.
+524 -789
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -9,10 +9,10 @@
},
"devDependencies": {
"axios": "^1",
"laravel-vite-plugin": "^2",
"laravel-vite-plugin": "^3",
"patch-package": "^8",
"sass": "^1",
"vite": "^7",
"vite": "^8",
"vite-plugin-manifest-sri": "^0.2.0"
},
"dependencies": {
+1 -2
View File
@@ -347,7 +347,6 @@ Route::group(
'namespace' => 'FireflyIII\Api\V1\Controllers\Models\UserGroup',
'prefix' => 'v1/user-groups',
'as' => 'api.v1.user-groups.',
'middleware' => ['api-admin'],
],
static function (): void {
Route::get('', ['uses' => 'IndexController@index', 'as' => 'index']);
@@ -636,6 +635,7 @@ Route::group(
],
static function (): void {
Route::get('', ['uses' => 'ShowController@index', 'as' => 'index']);
Route::put('{currency_code?}', ['uses' => 'UpdateController@update', 'as' => 'update']);
Route::get('primary', ['uses' => 'ShowController@showPrimary', 'as' => 'show.primary']);
Route::get('default', ['uses' => 'ShowController@showPrimary', 'as' => 'show.default']);
Route::get('{currency_code}', ['uses' => 'ShowController@show', 'as' => 'show']);
@@ -666,7 +666,6 @@ Route::group(
static function (): void {
Route::delete('{currency_code}', ['uses' => 'DestroyController@destroy', 'as' => 'delete']);
Route::post('', ['uses' => 'StoreController@store', 'as' => 'store']);
Route::put('{currency_code?}', ['uses' => 'UpdateController@update', 'as' => 'update']);
}
);