Compare commits

...

260 Commits

Author SHA1 Message Date
github-actions
7170931464 Auto commit for release 'develop' on 2024-05-20 2024-05-20 05:09:44 +02:00
github-actions
c1b5a1a13e Auto commit for release 'develop' on 2024-05-19 2024-05-19 10:37:08 +02:00
James Cole
a6265ce8ab Fix line in job. 2024-05-19 10:28:01 +02:00
github-actions
90109917df Auto commit for release 'v6.1.16' on 2024-05-19 2024-05-19 10:26:25 +02:00
James Cole
0acd54c2b7 Update changelog. 2024-05-19 10:21:03 +02:00
James Cole
c96226b9b4 Add final API changes 2024-05-19 10:17:21 +02:00
James Cole
6d143f1624 Clean up API 2024-05-19 06:36:31 +02:00
James Cole
93324d1154 Remove unused variables 2024-05-18 06:57:38 +02:00
github-actions
a39f0e1891 Auto commit for release 'develop' on 2024-05-18 2024-05-18 06:49:29 +02:00
James Cole
822f609a22 Fix ibans 2024-05-18 06:44:18 +02:00
James Cole
cd7ddd1c61 Add more IBAN filters 2024-05-18 06:42:09 +02:00
James Cole
0b63ba26bb Fix autocomplete entries. 2024-05-18 05:51:02 +02:00
James Cole
94d70cdb62 Fix missing parameters 2024-05-17 20:45:16 +02:00
James Cole
acb3831c8b Add parallel thing 2024-05-16 07:30:07 +02:00
github-actions
c9d9ecede4 Auto commit for release 'develop' on 2024-05-16 2024-05-16 07:22:12 +02:00
James Cole
4eb5873353 Merge branch 'main' into develop 2024-05-16 07:17:18 +02:00
James Cole
7ca39fdb21 Fix commands 2024-05-16 07:16:47 +02:00
James Cole
b8d1d7a8c0 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop
# Conflicts:
#	app/Support/Models/AccountBalanceCalculator.php
2024-05-16 07:15:36 +02:00
James Cole
1af79eab30 Clean up commands 2024-05-16 07:14:44 +02:00
github-actions
03be2704ce Auto commit for release 'develop' on 2024-05-16 2024-05-16 05:10:41 +02:00
James Cole
34baea66a7 Merge pull request #8880 from firefly-iii/dependabot/github_actions/github/command-1.2.0 2024-05-14 05:43:54 +02:00
James Cole
0638d109d0 Clean up code. 2024-05-13 20:31:52 +02:00
dependabot[bot]
561e228a2d Bump github/command from 1.1.1 to 1.2.0
Bumps [github/command](https://github.com/github/command) from 1.1.1 to 1.2.0.
- [Release notes](https://github.com/github/command/releases)
- [Commits](https://github.com/github/command/compare/v1.1.1...v1.2.0)

---
updated-dependencies:
- dependency-name: github/command
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-13 03:12:36 +00:00
github-actions
cb5d856769 Auto commit for release 'develop' on 2024-05-13 2024-05-13 05:10:16 +02:00
James Cole
04fe5d1fc4 Correct account balances better. 2024-05-12 18:24:38 +02:00
James Cole
45e9d4f8de Fix auto complete 2024-05-12 17:50:54 +02:00
James Cole
73fdbb6202 Update API endpoints and account autocomplete. 2024-05-12 13:31:33 +02:00
James Cole
e49dbefddd Make the combined combination unique. 2024-05-12 08:10:12 +02:00
James Cole
fc5143337a Add a title to the table, so multiple balances per account are possible. 2024-05-12 08:09:50 +02:00
James Cole
4b3eb6dace Rename command. 2024-05-12 06:26:50 +02:00
James Cole
c741b2a819 Add related models. 2024-05-12 06:25:13 +02:00
James Cole
cebfaa32bf Add routine that caches account balances. Add it to the /flush routine as well. 2024-05-12 06:24:11 +02:00
James Cole
d356d39d43 add account balances with some random data 2024-05-11 20:32:25 +02:00
James Cole
7d9f22d3f4 Merge branch 'api' into develop
# Conflicts:
#	app/JsonApi/V3/Accounts/AccountRepository.php
#	app/JsonApi/V3/Accounts/AccountResource.php
#	app/JsonApi/V3/Accounts/Capabilities/AccountQuery.php
#	app/JsonApi/V3/Users/UserSchema.php
2024-05-10 12:52:44 +02:00
James Cole
c6c8f282e2 Restore previous stuff 2024-05-10 12:51:02 +02:00
James Cole
6a64420721 Refactor resources 2024-05-10 09:42:09 +02:00
James Cole
fcde4e2488 no message 2024-05-10 09:41:53 +02:00
James Cole
aa5c4c20e9 Various messy code. 2024-05-10 09:17:09 +02:00
James Cole
794e31e487 Add some experimental account endpoints using a package 2024-05-10 06:43:18 +02:00
James Cole
16bf186312 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop
# Conflicts:
#	composer.lock
2024-05-10 06:42:47 +02:00
James Cole
45c722e786 Add config, merge later. 2024-05-10 06:36:57 +02:00
github-actions
36d9e5c3fe Auto commit for release 'develop' on 2024-05-09 2024-05-09 05:10:13 +02:00
James Cole
8d614de67f Possible fix for https://github.com/firefly-iii/firefly-iii/issues/8867 2024-05-08 21:55:14 +02:00
James Cole
d17da670ab Fix connect exception, add some debug logs. 2024-05-06 06:33:12 +02:00
github-actions
5bf4df9ad8 Auto commit for release 'develop' on 2024-05-06 2024-05-06 05:10:30 +02:00
James Cole
07db6b59ce Fix webhooks overview. 2024-05-02 06:15:41 +02:00
github-actions
e16f1cf4ee Auto commit for release 'develop' on 2024-05-02 2024-05-02 05:10:23 +02:00
James Cole
4c80d929ca Possible division by zero? 2024-05-01 06:29:28 +02:00
github-actions
16364d9859 Auto commit for release 'develop' on 2024-04-30 2024-04-30 20:33:00 +02:00
James Cole
c24f6acb2c Fix styles 2024-04-30 20:26:05 +02:00
James Cole
4bd19e0627 Expand and fix sort columns 2024-04-30 20:22:31 +02:00
James Cole
69d839997a Fix sorting and order for account lists. 2024-04-29 20:20:11 +02:00
github-actions
c02c027f4f Auto commit for release 'develop' on 2024-04-29 2024-04-29 06:36:36 +02:00
James Cole
b14606625e Upload corrected file 2024-04-29 06:31:18 +02:00
James Cole
222d7b56c7 Merge pull request #8835 from firefly-iii/dependabot/npm_and_yarn/develop/chartjs-chart-sankey-0.12.1 2024-04-29 06:07:17 +02:00
James Cole
b7f7bf42b2 Merge pull request #8834 from firefly-iii/dependabot/composer/develop/ramsey/uuid-4.7.6 2024-04-29 06:07:09 +02:00
dependabot[bot]
0cbd64d31a Bump chartjs-chart-sankey from 0.12.0 to 0.12.1
Bumps [chartjs-chart-sankey](https://github.com/kurkle/chartjs-chart-sankey) from 0.12.0 to 0.12.1.
- [Release notes](https://github.com/kurkle/chartjs-chart-sankey/releases)
- [Commits](https://github.com/kurkle/chartjs-chart-sankey/compare/v0.12.0...v0.12.1)

---
updated-dependencies:
- dependency-name: chartjs-chart-sankey
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-29 03:55:28 +00:00
dependabot[bot]
60bdae47c4 Bump ramsey/uuid from 4.7.5 to 4.7.6
Bumps [ramsey/uuid](https://github.com/ramsey/uuid) from 4.7.5 to 4.7.6.
- [Release notes](https://github.com/ramsey/uuid/releases)
- [Changelog](https://github.com/ramsey/uuid/blob/4.x/CHANGELOG.md)
- [Commits](https://github.com/ramsey/uuid/compare/4.7.5...4.7.6)

---
updated-dependencies:
- dependency-name: ramsey/uuid
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-29 03:34:37 +00:00
James Cole
ca4b38d905 Add debug thing for tables. 2024-04-28 20:20:18 +02:00
James Cole
3674465f53 Translate stuff 2024-04-28 14:43:23 +02:00
James Cole
b951d4130c Allow account grouping 2024-04-28 14:40:22 +02:00
James Cole
7992b810fd Expand view with several new options. Move cache to api endpoints. 2024-04-28 13:30:42 +02:00
James Cole
c1c0afa40b Expand account index overview. 2024-04-28 09:54:28 +02:00
github-actions
56c9026299 Auto commit for release 'develop' on 2024-04-26 2024-04-26 06:18:27 +02:00
James Cole
021ddfc36b Clear out file to see if develop action picks it up correctly. 2024-04-26 06:13:03 +02:00
James Cole
5bd72f6428 Add command 2024-04-26 05:32:21 +02:00
James Cole
feabfe54f0 First attempt at comma based preference collector 2024-04-26 05:31:02 +02:00
James Cole
565409b486 Remove address 2024-04-25 19:51:15 +02:00
James Cole
f57366da5f Add thanks file. 2024-04-25 19:49:58 +02:00
github-actions
064217ccb0 Auto commit for release 'develop' on 2024-04-25 2024-04-25 05:10:20 +02:00
James Cole
fa3ccbda33 Fix phpstan issues. 2024-04-23 19:40:48 +02:00
github-actions
f43aadf02d Auto commit for release 'v6.1.15' on 2024-04-23 2024-04-23 16:34:26 +02:00
James Cole
3b8a4d3e9b Expand changelog. 2024-04-23 16:27:58 +02:00
James Cole
3d410556ef Fix https://github.com/firefly-iii/firefly-iii/issues/8812 2024-04-23 16:24:46 +02:00
github-actions
f15ca1d0a1 Auto commit for release 'v6.1.14' on 2024-04-23 2024-04-23 07:13:10 +02:00
James Cole
7002463c54 Update changelog for new release. 2024-04-23 07:06:37 +02:00
James Cole
649f876437 Better account index in v2. 2024-04-23 07:00:08 +02:00
James Cole
3cfd178cbd New translations. 2024-04-23 06:59:49 +02:00
github-actions
cefbaafa19 Auto commit for release 'develop' on 2024-04-22 2024-04-22 05:11:03 +02:00
James Cole
a8c88800c4 Fix column 2024-04-21 19:49:28 +02:00
github-actions
9d1a127200 Auto commit for release 'develop' on 2024-04-21 2024-04-21 17:23:16 +02:00
James Cole
3fdde2d1c8 Removed for now, needs dynamic configuration. 2024-04-21 17:18:35 +02:00
James Cole
cdc0b8dd2c Add index options 2024-04-21 17:09:15 +02:00
James Cole
1a1e06e6e8 Fix tests 2024-04-21 07:07:06 +02:00
James Cole
6d39b8468c Add two buttons and options for them 2024-04-21 06:57:57 +02:00
James Cole
bdee3947b2 Add debugbar settings 2024-04-21 06:56:14 +02:00
James Cole
2317037655 Clean up transactions, first attempt at navigation. 2024-04-21 06:26:17 +02:00
James Cole
dcea6b757b Better button response in category overview. 2024-04-20 17:08:30 +02:00
James Cole
bd7fe92818 Expand accounts page. 2024-04-20 16:18:41 +02:00
James Cole
850e47d8db Fix https://github.com/firefly-iii/firefly-iii/issues/8776 2024-04-20 08:15:17 +02:00
James Cole
96fe62400f Fix undefined index 2024-04-20 07:38:05 +02:00
James Cole
5d07fcdcb6 Add user roles. 2024-04-20 07:36:53 +02:00
James Cole
fd5d2d57a8 Fix https://github.com/firefly-iii/firefly-iii/issues/8804 2024-04-20 07:19:15 +02:00
James Cole
8e7d42201f Merge branch 'main' into develop 2024-04-20 07:18:51 +02:00
James Cole
f26bd3cb31 Fix https://github.com/firefly-iii/firefly-iii/issues/8613 2024-04-19 19:59:42 +02:00
James Cole
36915cdace Fix https://github.com/firefly-iii/firefly-iii/issues/8752 2024-04-19 19:58:32 +02:00
James Cole
8a5cecd2a0 Fix https://github.com/firefly-iii/firefly-iii/issues/8781 2024-04-19 19:58:09 +02:00
James Cole
78da1b22bb Update vite.config.js
Signed-off-by: James Cole <james@firefly-iii.org>
2024-04-19 08:28:31 +02:00
github-actions
6d970a9794 Auto commit for release 'develop' on 2024-04-18 2024-04-18 10:25:45 +02:00
Sander D
8bb7739f05 Update release.yml
Signed-off-by: Sander D <git@sanderdorigo.nl>
2024-04-18 10:20:47 +02:00
James Cole
7788bb4b33 Update composer.lock 2024-04-18 09:52:01 +02:00
James Cole
2ecb4bb3b7 Update composer.json 2024-04-18 09:51:45 +02:00
James Cole
4a783d3c3c Drop a specific preference from the return of Firefly III 2024-04-18 05:54:57 +02:00
github-actions
e16645ae87 Auto commit for release 'develop' on 2024-04-18 2024-04-18 05:09:58 +02:00
github-actions
9d3189be7e Auto commit for release 'develop' on 2024-04-15 2024-04-15 07:59:54 +02:00
James Cole
07fca78293 Merge pull request #8791 from firefly-iii/dependabot/npm_and_yarn/develop/i18next-23.11.2
Bump i18next from 23.11.1 to 23.11.2
2024-04-15 07:55:47 +02:00
James Cole
82080501c7 Merge pull request #8790 from firefly-iii/dependabot/npm_and_yarn/develop/sass-1.75.0
Bump sass from 1.74.1 to 1.75.0
2024-04-15 07:55:37 +02:00
James Cole
d93d6bfc66 Update phpcs.sh
Signed-off-by: James Cole <james@firefly-iii.org>
2024-04-15 07:54:52 +02:00
dependabot[bot]
a41326ef94 Bump i18next from 23.11.1 to 23.11.2
Bumps [i18next](https://github.com/i18next/i18next) from 23.11.1 to 23.11.2.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v23.11.1...v23.11.2)

---
updated-dependencies:
- dependency-name: i18next
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-15 03:55:25 +00:00
dependabot[bot]
90b77845c3 Bump sass from 1.74.1 to 1.75.0
Bumps [sass](https://github.com/sass/dart-sass) from 1.74.1 to 1.75.0.
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/dart-sass/compare/1.74.1...1.75.0)

---
updated-dependencies:
- dependency-name: sass
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-15 03:55:12 +00:00
James Cole
57af80d820 Merge pull request #8788 from firefly-iii/dependabot/composer/develop/larastan/larastan-2.9.4 2024-04-15 05:45:30 +02:00
James Cole
fc4d5a1dfd Merge pull request #8787 from firefly-iii/dependabot/composer/develop/phpunit/phpunit-10.5.18 2024-04-15 05:45:21 +02:00
dependabot[bot]
8ab9ab8d21 Bump larastan/larastan from 2.9.2 to 2.9.4
Bumps [larastan/larastan](https://github.com/larastan/larastan) from 2.9.2 to 2.9.4.
- [Release notes](https://github.com/larastan/larastan/releases)
- [Changelog](https://github.com/larastan/larastan/blob/2.x/RELEASE.md)
- [Commits](https://github.com/larastan/larastan/compare/v2.9.2...v2.9.4)

---
updated-dependencies:
- dependency-name: larastan/larastan
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-15 03:01:51 +00:00
dependabot[bot]
75674b5793 Bump phpunit/phpunit from 10.5.17 to 10.5.18
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 10.5.17 to 10.5.18.
- [Release notes](https://github.com/sebastianbergmann/phpunit/releases)
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/10.5.18/ChangeLog-10.5.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/10.5.17...10.5.18)

---
updated-dependencies:
- dependency-name: phpunit/phpunit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-15 03:01:41 +00:00
James Cole
a7d6f26051 Sign release 2024-04-14 13:34:41 +02:00
James Cole
eb540ce148 New PR template 2024-04-14 13:32:56 +02:00
James Cole
a3077fe43b Merge branch 'main' into develop 2024-04-14 08:52:38 +02:00
James Cole
63bb84d375 Workflow runs on "main" 2024-04-14 08:52:27 +02:00
James Cole
e5f5aa628e Small changes in CI script and vite config 2024-04-14 08:51:59 +02:00
James Cole
c54f84dc8e Fix https://github.com/firefly-iii/firefly-iii/issues/8779 2024-04-13 05:50:26 +02:00
github-actions
c2e562623c Auto commit for release 'develop' on 2024-04-11 2024-04-11 05:10:20 +02:00
James Cole
c8d5e8a9dc Add roles 2024-04-10 19:45:08 +02:00
James Cole
963f017be3 Merge branch 'main' into develop 2024-04-08 07:46:41 +02:00
James Cole
0e0eeb736f Point to single source of truth for view name. 2024-04-08 07:45:58 +02:00
James Cole
e8d9b8fa49 Merge pull request #8768 from firefly-iii/dependabot/github_actions/github/command-1.1.1
Bump github/command from 1.1.0 to 1.1.1
2024-04-08 07:39:05 +02:00
James Cole
c166b9242e Merge pull request #8766 from firefly-iii/dependabot/npm_and_yarn/develop/date-fns-3.6.0
Bump date-fns from 2.30.0 to 3.6.0
2024-04-08 07:34:35 +02:00
dependabot[bot]
8ff8efced2 Bump date-fns from 2.30.0 to 3.6.0
Bumps [date-fns](https://github.com/date-fns/date-fns) from 2.30.0 to 3.6.0.
- [Release notes](https://github.com/date-fns/date-fns/releases)
- [Changelog](https://github.com/date-fns/date-fns/blob/main/CHANGELOG.md)
- [Commits](https://github.com/date-fns/date-fns/compare/v2.30.0...v3.6.0)

---
updated-dependencies:
- dependency-name: date-fns
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-08 04:54:48 +00:00
James Cole
0b4fb9a806 Revert to v8, also update other packages. 2024-04-08 06:53:51 +02:00
James Cole
ba9fef9410 Merge pull request #8765 from firefly-iii/dependabot/npm_and_yarn/develop/laravel-vite-plugin-1.0.2
Bump laravel-vite-plugin from 0.8.1 to 1.0.2
2024-04-08 06:29:54 +02:00
James Cole
f7d94d17cd Merge pull request #8764 from firefly-iii/dependabot/npm_and_yarn/develop/vue-i18n-9.11.0
Bump vue-i18n from 8.28.2 to 9.11.0
2024-04-08 06:23:42 +02:00
dependabot[bot]
1fea9c6817 Bump github/command from 1.1.0 to 1.1.1
Bumps [github/command](https://github.com/github/command) from 1.1.0 to 1.1.1.
- [Release notes](https://github.com/github/command/releases)
- [Commits](https://github.com/github/command/compare/v1.1.0...v1.1.1)

---
updated-dependencies:
- dependency-name: github/command
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-08 04:03:50 +00:00
dependabot[bot]
a88c8bedbe Bump laravel-vite-plugin from 0.8.1 to 1.0.2
Bumps [laravel-vite-plugin](https://github.com/laravel/vite-plugin) from 0.8.1 to 1.0.2.
- [Release notes](https://github.com/laravel/vite-plugin/releases)
- [Changelog](https://github.com/laravel/vite-plugin/blob/1.x/CHANGELOG.md)
- [Upgrade guide](https://github.com/laravel/vite-plugin/blob/1.x/UPGRADE.md)
- [Commits](https://github.com/laravel/vite-plugin/compare/v0.8.1...v1.0.2)

---
updated-dependencies:
- dependency-name: laravel-vite-plugin
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-08 03:27:28 +00:00
dependabot[bot]
fbf3468053 Bump vue-i18n from 8.28.2 to 9.11.0
Bumps [vue-i18n](https://github.com/intlify/vue-i18n-next/tree/HEAD/packages/vue-i18n) from 8.28.2 to 9.11.0.
- [Release notes](https://github.com/intlify/vue-i18n-next/releases)
- [Changelog](https://github.com/intlify/vue-i18n-next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/intlify/vue-i18n-next/commits/v9.11.0/packages/vue-i18n)

---
updated-dependencies:
- dependency-name: vue-i18n
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-08 03:27:11 +00:00
github-actions
2a3ba9799e Auto commit for release 'develop' on 2024-04-08 2024-04-08 05:09:59 +02:00
James Cole
d121aad28f Check the directory, not the file. 2024-04-07 16:27:15 +02:00
github-actions
dc808fa807 Auto commit for release 'develop' on 2024-04-07 2024-04-07 16:22:39 +02:00
James Cole
a1be6ff62b Limit the number of error messages Firefly III will send. 2024-04-07 16:12:41 +02:00
James Cole
20dc5b0256 Fix layout errors. 2024-04-07 15:57:51 +02:00
James Cole
edd54e23c5 Merge branch 'main' into develop 2024-04-07 10:40:03 +02:00
James Cole
1238df8784 Switch to v38 2024-04-07 10:38:17 +02:00
github-actions
b8c62652b0 Auto commit for release 'develop' on 2024-04-07 2024-04-07 10:37:19 +02:00
James Cole
54b2d02f63 Build JS in one go. 2024-04-07 10:31:24 +02:00
James Cole
47faf89a5c Update script to apply patch. 2024-04-07 10:29:54 +02:00
James Cole
b7fb5a3854 This configuration works but patch-package doesn't take (yt) 2024-04-07 10:12:23 +02:00
James Cole
a384b4202a Add gitkeep file 2024-04-07 07:26:31 +02:00
James Cole
99ecac0ce4 Clean up some scripts. 2024-04-07 07:25:54 +02:00
James Cole
6102982456 Move more JS files 2024-04-07 07:21:08 +02:00
James Cole
b88e981b4b Move v2 files 2024-04-07 07:17:34 +02:00
James Cole
827263b03e Move v1 assets 2024-04-07 07:16:38 +02:00
James Cole
d44e74d334 Merge branch 'main' into develop 2024-04-07 06:52:49 +02:00
github-actions
911f46c590 Auto commit for release 'develop' on 2024-04-07 2024-04-07 06:51:34 +02:00
James Cole
7d42c4ee5d Move to v37 2024-04-07 06:45:48 +02:00
James Cole
ea89f6177f Move selected translations to Firefly III 2024-04-07 06:44:45 +02:00
James Cole
74291b3870 Expand API administration validation 2024-04-07 06:06:40 +02:00
James Cole
2c4f2082fe Update workflows. 2024-04-06 06:26:21 +02:00
github-actions
d8d58cc29b Auto commit for release 'develop' on 2024-04-04 2024-04-04 05:11:18 +02:00
James Cole
85b17e4035 Drop the type for now, fixes https://github.com/orgs/firefly-iii/discussions/8750 2024-04-03 20:07:18 +02:00
James Cole
83de5667b3 Fix icons en styling 2024-04-03 08:59:44 +02:00
James Cole
5fffe873c6 Update PR template 2024-04-03 05:55:39 +02:00
James Cole
78c09c82d6 Merge branch 'main' into develop 2024-04-03 05:48:55 +02:00
James Cole
704abc315d New template 2024-04-03 05:48:38 +02:00
github-actions
86b4965458 Auto commit for release 'develop' on 2024-04-03 2024-04-03 05:19:06 +02:00
James Cole
d2dc0c2bf0 Merge branch 'main' into develop 2024-04-03 05:12:51 +02:00
James Cole
9f4894bbb5 Fix https://github.com/firefly-iii/firefly-iii/issues/8748 2024-04-03 05:12:28 +02:00
James Cole
76a8675a34 make sure boxes are empty 2024-04-02 18:04:42 +02:00
James Cole
6988301da1 Merge pull request #8746 from imlonghao/patch-1
Set date to now when cloning journal
2024-04-02 18:03:52 +02:00
imlonghao
109cd37211 Set date to now when cloning journal
Signed-off-by: imlonghao <git@imlonghao.com>
2024-04-02 23:44:45 +08:00
James Cole
284ff4d1b0 Merge branch 'main' into develop 2024-04-02 16:53:31 +02:00
James Cole
bc0ab7af99 Spelling error in nightly release instructions 2024-04-02 16:53:18 +02:00
James Cole
a17bc7258f Fix phpstan error courtesy of the laravel 11 upgrade (changed signatures and return types) 2024-04-02 15:40:33 +02:00
James Cole
87911c2438 Catch empty preference, just in case. 2024-04-02 12:38:31 +02:00
github-actions
746f1fd300 Auto commit for release 'develop' on 2024-04-02 2024-04-02 07:47:24 +02:00
James Cole
9e5faf919f Add space 2024-04-02 07:40:40 +02:00
James Cole
cc6cbe6605 Add something to changelog before I forget. 2024-04-02 07:01:13 +02:00
James Cole
dc6d708897 Replace frontpageAccounts variable name. 2024-04-02 06:59:40 +02:00
James Cole
6189d24b98 Replace variable names. 2024-04-01 20:26:02 +02:00
James Cole
f6e28dc88f Fine tune preferences to handle multi-administration options. 2024-04-01 19:59:21 +02:00
James Cole
75ea035630 Preferences can be administration specific. Not yet really working. 2024-04-01 18:18:48 +02:00
James Cole
4cdb14301d Add administration specific thing to preferences. 2024-04-01 18:03:43 +02:00
James Cole
9f95221ba3 Various code cleanup. 2024-04-01 17:43:31 +02:00
James Cole
e3a67be412 Clear user groups when loading 2024-04-01 16:07:14 +02:00
James Cole
5749b642ce Wrong response code. 2024-04-01 16:07:03 +02:00
James Cole
baff7c67f9 Expand user group views and translations 2024-04-01 15:41:16 +02:00
James Cole
ccc005942f Expand user group pages. 2024-04-01 15:40:53 +02:00
James Cole
5b83c33039 Turns out it's pointless to add "default_administration", you can force that already through the owner role (which is already in place). 2024-04-01 14:15:35 +02:00
James Cole
cc32578c5f Add new strings. 2024-04-01 14:04:36 +02:00
James Cole
80f410835b Expand models, user groups need more properties. 2024-04-01 14:04:22 +02:00
James Cole
b537a3145d Expand financial administrations views. 2024-04-01 14:01:52 +02:00
James Cole
bfa1fcbaf8 make sure output.txt is writeable. 2024-04-01 09:08:19 +02:00
James Cole
56243907c4 Add some debug info 2024-04-01 09:01:53 +02:00
James Cole
5928dd72e6 Forgot the zip name 2024-04-01 08:53:56 +02:00
github-actions
c6bf0ff1cd Auto commit for release 'v6.1.13' on 2024-04-01 2024-04-01 08:51:46 +02:00
James Cole
19d1cf192b Fix tests, update changelog. 2024-04-01 08:46:13 +02:00
James Cole
37d7dc7e3e Merge branch 'main' into develop 2024-04-01 08:37:57 +02:00
James Cole
95a3a194b8 Better instructions 2024-04-01 08:37:49 +02:00
James Cole
3542387188 Merge branch 'main' into develop 2024-04-01 08:36:25 +02:00
James Cole
da1b002a64 Clean up and expand normal release 2024-04-01 08:36:15 +02:00
James Cole
46daee28e7 Merge branch 'main' into develop 2024-04-01 08:33:02 +02:00
James Cole
9ade5635d4 Add file with revision of the used branch. 2024-04-01 08:32:51 +02:00
James Cole
e14e80f33c Merge branch 'main' into develop 2024-04-01 08:31:32 +02:00
github-actions
0c824e21c8 Auto commit for release 'develop' on 2024-04-01 2024-04-01 05:10:33 +02:00
James Cole
fab1c68569 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2024-03-31 19:32:00 +02:00
James Cole
c1534657f2 Fix the installation template. 2024-03-31 19:31:52 +02:00
github-actions
39841de680 Auto commit for release 'develop' on 2024-03-31 2024-03-31 17:12:02 +02:00
James Cole
43a720b62b It helps when you actually add 1 2024-03-31 17:06:37 +02:00
James Cole
5ec54de29e Fix shitty test 2024-03-31 16:51:53 +02:00
James Cole
397e37f344 Fix another division by zero 2024-03-31 16:46:38 +02:00
James Cole
b6f84c2b99 Expand v2 layout, add user administration pages. 2024-03-31 16:46:20 +02:00
James Cole
843f86fc66 Merge branch 'main' into develop 2024-03-31 11:29:35 +02:00
James Cole
0e8e364074 Can now release multiple development builds per day 2024-03-31 10:01:21 +02:00
James Cole
bbccbef578 Fix loop 2024-03-31 09:55:17 +02:00
James Cole
ee11a8e3a0 Add check for duplicate tags 2024-03-31 09:48:20 +02:00
James Cole
e8618047bd More readable fix for division by zero error. 2024-03-31 08:40:47 +02:00
James Cole
f104b76f73 Merge pull request #8735 from mansuf/develop
Fix `Division error by zero` in budget views
2024-03-31 08:37:09 +02:00
Rahman Yusuf
cb701d8506 Fix Division error by zero in budget views 2024-03-31 12:03:54 +07:00
James Cole
70a334c56e Merge branch 'main' into develop 2024-03-31 03:16:54 +02:00
github-actions
e6b2db1e29 Auto commit for release 'develop' on 2024-03-31 2024-03-31 03:14:08 +02:00
James Cole
e8dffa0052 Update script version 2024-03-31 03:09:00 +02:00
James Cole
c4f0512f39 Run another composer, and dump the autoload files. 2024-03-31 03:06:58 +02:00
James Cole
3268019d0c Fix #8732 2024-03-31 01:24:18 +01:00
James Cole
a0ef6a1fc8 Fix https://github.com/firefly-iii/firefly-iii/issues/8725 2024-03-30 09:56:51 +01:00
James Cole
99d0098b20 Merge branch 'main' into develop 2024-03-28 05:59:30 +01:00
James Cole
a7a54c042c Touch and exclude tar name 2024-03-28 05:53:31 +01:00
github-actions
c44e48a793 Auto commit for release 'develop' on 2024-03-28 2024-03-28 04:10:19 +01:00
James Cole
53b501ca73 Add tar.gz file 2024-03-27 20:04:14 +01:00
James Cole
322f70bcca Merge branch 'main' into develop
# Conflicts:
#	.github/workflows/release.yml
2024-03-27 07:10:24 +01:00
James Cole
35559c077b Update text in output. 2024-03-27 06:59:48 +01:00
github-actions
590ffe7c76 Auto commit for release 'develop' on 2024-03-27 2024-03-27 06:58:44 +01:00
James Cole
8a2d8f148e Expand text under development release 2024-03-27 06:50:39 +01:00
James Cole
4f0e15e07d Expand text in dev release. 2024-03-27 06:49:56 +01:00
James Cole
7463861e0c Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2024-03-26 07:40:51 +01:00
James Cole
1e70fa28be Fix https://github.com/firefly-iii/firefly-iii/issues/8648 2024-03-26 07:37:21 +01:00
github-actions
26c6ca470b Auto commit for release 'develop' on 2024-03-26 2024-03-26 07:37:05 +01:00
James Cole
5e54034e0e Merge branch 'main' into develop
# Conflicts:
#	.github/workflows/release.yml
2024-03-26 07:32:26 +01:00
James Cole
25873ef734 add npm update. 2024-03-26 07:31:33 +01:00
James Cole
1092b04b22 Merge branch 'main' into develop 2024-03-26 07:30:27 +01:00
James Cole
01ce74dd72 Expand release script with shasum 2024-03-26 07:30:15 +01:00
James Cole
41430d8386 Fix bill box and hover CSS 2024-03-26 07:25:36 +01:00
James Cole
01eb19169c Merge pull request #8714 from firefly-iii/dependabot/npm_and_yarn/develop/vite-4.5.3 2024-03-25 07:08:14 +01:00
dependabot[bot]
cfaa7d7c68 Bump vite from 4.5.2 to 4.5.3
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 4.5.2 to 4.5.3.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v4.5.3/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v4.5.3/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-25 03:13:52 +00:00
github-actions
14d3312a10 Auto commit for release 'develop' on 2024-03-25 2024-03-25 04:10:34 +01:00
James Cole
87be478dd8 Expand dashboard view 2024-03-24 16:22:27 +01:00
James Cole
0b6877a20e Fix null pointer 2024-03-24 14:11:30 +01:00
James Cole
7186f0ef60 Improve boxes 2024-03-24 14:10:07 +01:00
James Cole
538933691e Add sort column to account overview. and some css fixes 2024-03-24 13:24:48 +01:00
James Cole
46c49ddbd8 Add translations, fix error message. 2024-03-24 12:07:26 +01:00
James Cole
bcfb134b6e Clean up 2024-03-24 11:43:37 +01:00
James Cole
57981f1cf9 Read and remember sort order by URL 2024-03-24 11:08:24 +01:00
James Cole
0310186fb7 Expand accounts page. 2024-03-23 20:37:15 +01:00
James Cole
4dcb38290e Better inline editor. 2024-03-23 15:20:49 +01:00
James Cole
2f5c37048b Update vite.config.js
Add relative path.

Signed-off-by: James Cole <james@firefly-iii.org>
2024-03-21 13:44:51 +01:00
github-actions
370c8b16ae Auto commit for release 'develop' on 2024-03-21 2024-03-21 04:11:26 +01:00
github-actions
af0555592a Auto commit for release 'v6.1.12' on 2024-03-20 2024-03-20 17:55:25 +01:00
James Cole
9c07ddaed6 Replace shitty Laravel Passport command. 2024-03-20 17:48:13 +01:00
James Cole
bb7355a566 Fix https://github.com/orgs/firefly-iii/discussions/8696 2024-03-20 17:32:06 +01:00
James Cole
1d48347f8c Update release notes for new version. 2024-03-20 17:28:56 +01:00
James Cole
060b76ca9c Replace command in composer.json 2024-03-20 11:45:56 +01:00
James Cole
2b2b9b6f7a Drop duplicate index 2024-03-20 06:14:32 +01:00
James Cole
f3dd05a0c0 Move jobs to better times. 2024-03-20 06:12:56 +01:00
James Cole
47a91aa273 Exclude file from release. 2024-03-19 17:52:00 +01:00
708 changed files with 26842 additions and 4372 deletions

View File

@@ -19,6 +19,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use PhpCsFixer\Runner\Parallel\ParallelConfigFactory;
$current = __DIR__;
$paths = [
@@ -35,6 +37,7 @@ $finder = PhpCsFixer\Finder::create()
$config = new PhpCsFixer\Config();
$config->setParallelConfig(ParallelConfigFactory::detect());
return $config->setRules(
[
// rule sets

View File

@@ -1,5 +1,5 @@
{
"require": {
"friendsofphp/php-cs-fixer": "^3.12"
}
"require": {
"friendsofphp/php-cs-fixer": "^3.12"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -20,23 +20,8 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# Install composer packages
#composer install --no-scripts --no-ansi
SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
# enable test .env file.
# cp .ci/.env.ci .env
OUTPUT_FORMAT=txt
EXTRA_PARAMS=""
if [[ $GITHUB_ACTIONS = "true" ]]
then
OUTPUT_FORMAT=txt
EXTRA_PARAMS=""
fi
# clean up php code
cd $SCRIPT_DIR/php-cs-fixer
composer update --quiet
@@ -44,8 +29,8 @@ rm -f .php-cs-fixer.cache
PHP_CS_FIXER_IGNORE_ENV=true
./vendor/bin/php-cs-fixer fix \
--config $SCRIPT_DIR/php-cs-fixer/.php-cs-fixer.php \
--format=$OUTPUT_FORMAT \
--allow-risky=yes $EXTRA_PARAMS
--format=txt \
--allow-risky=yes
EXIT_CODE=$?

View File

@@ -9,16 +9,16 @@
"packages-dev": [
{
"name": "composer/pcre",
"version": "3.1.2",
"version": "3.1.3",
"source": {
"type": "git",
"url": "https://github.com/composer/pcre.git",
"reference": "4775f35b2d70865807c89d32c8e7385b86eb0ace"
"reference": "5b16e25a5355f1f3afdfc2f954a0a80aec4826a8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/pcre/zipball/4775f35b2d70865807c89d32c8e7385b86eb0ace",
"reference": "4775f35b2d70865807c89d32c8e7385b86eb0ace",
"url": "https://api.github.com/repos/composer/pcre/zipball/5b16e25a5355f1f3afdfc2f954a0a80aec4826a8",
"reference": "5b16e25a5355f1f3afdfc2f954a0a80aec4826a8",
"shasum": ""
},
"require": {
@@ -60,7 +60,7 @@
],
"support": {
"issues": "https://github.com/composer/pcre/issues",
"source": "https://github.com/composer/pcre/tree/3.1.2"
"source": "https://github.com/composer/pcre/tree/3.1.3"
},
"funding": [
{
@@ -76,20 +76,20 @@
"type": "tidelift"
}
],
"time": "2024-03-07T15:38:35+00:00"
"time": "2024-03-19T10:26:25+00:00"
},
{
"name": "composer/xdebug-handler",
"version": "3.0.3",
"version": "3.0.4",
"source": {
"type": "git",
"url": "https://github.com/composer/xdebug-handler.git",
"reference": "ced299686f41dce890debac69273b47ffe98a40c"
"reference": "4f988f8fdf580d53bdb2d1278fe93d1ed5462255"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c",
"reference": "ced299686f41dce890debac69273b47ffe98a40c",
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/4f988f8fdf580d53bdb2d1278fe93d1ed5462255",
"reference": "4f988f8fdf580d53bdb2d1278fe93d1ed5462255",
"shasum": ""
},
"require": {
@@ -100,7 +100,7 @@
"require-dev": {
"phpstan/phpstan": "^1.0",
"phpstan/phpstan-strict-rules": "^1.1",
"symfony/phpunit-bridge": "^6.0"
"phpunit/phpunit": "^8.5 || ^9.6 || ^10.5"
},
"type": "library",
"autoload": {
@@ -124,9 +124,9 @@
"performance"
],
"support": {
"irc": "irc://irc.freenode.org/composer",
"irc": "ircs://irc.libera.chat:6697/composer",
"issues": "https://github.com/composer/xdebug-handler/issues",
"source": "https://github.com/composer/xdebug-handler/tree/3.0.3"
"source": "https://github.com/composer/xdebug-handler/tree/3.0.4"
},
"funding": [
{
@@ -142,7 +142,7 @@
"type": "tidelift"
}
],
"time": "2022-02-25T21:32:43+00:00"
"time": "2024-03-26T18:29:49+00:00"
},
{
"name": "pdepend/pdepend",

View File

@@ -19,9 +19,9 @@
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<ruleset name="pcsg-generated-ruleset"
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
name="pcsg-generated-ruleset"
xmlns="http://pmd.sf.net/ruleset/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
<description>Firefly III ruleset.</description>

View File

@@ -111,7 +111,10 @@ PGSQL_SSL_CERT=null
PGSQL_SSL_KEY=null
PGSQL_SSL_CRL_FILE=null
# more PostgreSQL settings
# For postgresql 15 and up, setting this to public will no longer work as expected, becasuse the
# 'public' schema is without grants. This can be worked around by having a super user grant those
# necessary privileges, but in security conscious setups that's not viable.
# You will need to set this to the schema you want to use.
PGSQL_SCHEMA=public
# If you're looking for performance improvements, you could install memcached or redis
@@ -296,27 +299,6 @@ DKR_BUILD_LOCALE=false
# Won't significantly speed up things.
DKR_CHECK_SQLITE=true
# Run database creation and migration commands. Disable this only if you're 100% sure the DB exists
# and is up to date.
DKR_RUN_MIGRATION=true
# Run database upgrade commands. Disable this only when you're 100% sure your DB is up-to-date
# with the latest fixes (outside of migrations!)
DKR_RUN_UPGRADE=true
# Verify database integrity. Includes all data checks and verifications.
# Disabling this makes Firefly III assume your DB is intact.
DKR_RUN_VERIFY=true
# Run database reporting commands. When disabled, Firefly III won't go over your data to report current state.
# Disabling this should have no impact on data integrity or safety but it won't warn you of possible issues.
DKR_RUN_REPORT=true
# Generate OAuth2 keys.
# When disabled, Firefly III won't attempt to generate OAuth2 Passport keys. This won't be an issue, IFF (if and only if)
# you had previously generated keys already and they're stored in your database for restoration.
DKR_RUN_PASSPORT_INSTALL=true
# Leave the following configuration vars as is.
# Unless you like to tinker and know what you're doing.
APP_NAME=FireflyIII

View File

@@ -1,13 +1,19 @@
<!--
Before you create a new PR, please consider:
Thank you for submitting new code to Firefly III, or any of the related projects. Please read the following rules carefully.
1) Pull requests for the MAIN branch will be closed.
2) DO NOT include translations in your PR. Only English US sentences.
- Please do not submit solutions for problems that are not already reported in an issue.
- Unfortunately, Firefly III can't be your learning experience. If you're new to all of this, please open an issue first.
- Please do not open PRs to "discuss" possible solutions or to "get feedback" on your code. I simply don't have time for that.
- Pull requests for the MAIN branch will be closed.
- DO NOT include translated strings in your PR.
If it feels necessary to open an issue first, please do so, before you open a PR.
See also: https://docs.firefly-iii.org/explanation/support/#contributing-code
Thanks.
-->
Fixes issue # (if relevant)
This PR fixes issue # (if relevant).
Changes in this pull request:

58
.github/stale.yml vendored
View File

@@ -1,58 +0,0 @@
# Configuration for probot-stale - https://github.com/probot/stale
# Number of days of inactivity before an Issue or Pull Request becomes stale
daysUntilStale: 14
# Number of days of inactivity before a stale Issue or Pull Request is closed.
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
daysUntilClose: 14
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
# - "[Status] Maybe Later"
exemptLabels:
- enhancement
- feature
- bug
- announcement
- "layout-v3"
# Set to true to ignore issues in a project (defaults to false)
exemptProjects: false
# Set to true to ignore issues in a milestone (defaults to false)
exemptMilestones: false
# Label to use when marking as stale
staleLabel: stale
# Comment to post when marking as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when removing the stale label.
# unmarkComment: >
# Your comment here.
# Comment to post when closing a stale Issue or Pull Request.
# closeComment: >
# Your comment here.
# Limit the number of actions per hour, from 1-30. Default is 30
limitPerRun: 30
# Limit to only `issues` or `pulls`
# only: issues
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
# pulls:
# daysUntilStale: 30
# markComment: >
# This pull request has been automatically marked as stale because it has not had
# recent activity. It will be closed if no further activity occurs. Thank you
# for your contributions.
# issues:
# exemptLabels:
# - confirmed

View File

@@ -7,7 +7,7 @@ permissions:
on:
schedule:
- cron: '0 0 * * *'
- cron: '0 1 * * *'
workflow_dispatch:
jobs:
prune:

View File

@@ -3,7 +3,7 @@ name: "Issues - Command to close duplicate issues"
# the workflow to execute on is comments that are newly created
on:
issue_comment:
types: [created]
types: [ created ]
permissions:
issues: write
@@ -13,7 +13,7 @@ jobs:
close_duplicates:
runs-on: ubuntu-latest
steps:
- uses: github/command@v1.1.0
- uses: github/command@v1.2.0
id: command
with:
allowed_contexts: "issue"

View File

@@ -3,9 +3,9 @@ name: 'Issues - Respond to hidden commands'
# the workflow to execute on is comments that are newly created
on:
issues:
types: [opened, edited]
types: [ opened, edited ]
issue_comment:
types: [created]
types: [ created ]
# permissions needed for reacting to IssueOps commands on issues and PRs
permissions:

View File

@@ -2,11 +2,11 @@ name: 'Issues - Reply to specific labels'
on:
issues:
types: [labeled, unlabeled]
types: [ labeled, unlabeled ]
pull_request_target:
types: [labeled, unlabeled]
types: [ labeled, unlabeled ]
discussion:
types: [labeled, unlabeled]
types: [ labeled, unlabeled ]
permissions:
contents: read

View File

@@ -3,7 +3,7 @@ name: 'Issues - Lock old issues'
on:
workflow_dispatch:
schedule:
- cron: '0 0 * * *'
- cron: '0 2 * * *'
concurrency:
group: lock-threads

View File

@@ -4,11 +4,11 @@ on:
workflow_dispatch:
inputs:
version:
description: 'Version to release'
description: 'Release "v1.2.3" or "develop"'
required: true
default: 'develop'
schedule:
- cron: '15 0 * * MON,THU'
- cron: '0 3 * * MON,THU'
jobs:
build:
@@ -51,7 +51,7 @@ jobs:
CROWDIN_TOKEN: ${{ secrets.CROWDIN_TOKEN }}
- name: Cleanup translations
id: cleanup-transactions
uses: JC5/firefly-iii-dev@v34
uses: JC5/firefly-iii-dev@main
with:
action: 'ff3:crowdin-warning'
output: ''
@@ -60,16 +60,25 @@ jobs:
GH_TOKEN: ''
- name: Cleanup changelog
id: cleanup-changelog
uses: JC5/firefly-iii-dev@v34
uses: JC5/firefly-iii-dev@main
with:
action: 'ff3:changelog'
output: ''
env:
FIREFLY_III_ROOT: /github/workspace
GH_TOKEN: ${{ secrets.CHANGELOG_TOKEN }}
- name: "Create THANKS.md"
id: thank-you
uses: JC5/firefly-iii-dev@main
with:
action: 'ff3:thank-you'
output: ''
env:
FIREFLY_III_ROOT: /github/workspace
GH_TOKEN: ''
- name: Extract changelog
id: extract-changelog
uses: JC5/firefly-iii-dev@v34
uses: JC5/firefly-iii-dev@main
with:
action: 'ff3:extract-changelog'
output: 'output'
@@ -78,7 +87,7 @@ jobs:
GH_TOKEN: ""
- name: Replace version
id: replace-version
uses: JC5/firefly-iii-dev@v34
uses: JC5/firefly-iii-dev@main
with:
action: 'ff3:version'
output: ''
@@ -88,7 +97,7 @@ jobs:
FF_III_VERSION: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }}
- name: Generate JSON v1
id: json-v1
uses: JC5/firefly-iii-dev@v34
uses: JC5/firefly-iii-dev@main
with:
action: 'ff3:json-translations v1'
output: ''
@@ -97,7 +106,7 @@ jobs:
GH_TOKEN: ''
- name: Generate JSON v2
id: json-v2
uses: JC5/firefly-iii-dev@v34
uses: JC5/firefly-iii-dev@main
with:
action: 'ff3:json-translations v2'
output: ''
@@ -106,50 +115,76 @@ jobs:
GH_TOKEN: ''
- name: Code cleanup
id: code-cleanup
uses: JC5/firefly-iii-dev@v34
uses: JC5/firefly-iii-dev@main
with:
action: 'ff3:code'
output: ''
env:
FIREFLY_III_ROOT: /github/workspace
GH_TOKEN: ''
- name: Build new JS
- name: Build JS
run: |
pwd
npm install
npm run build
- name: Build old JS
id: old-js
uses: JC5/firefly-iii-dev@v34
with:
action: 'ff3:old-js'
output: ''
env:
FIREFLY_III_ROOT: /github/workspace
GH_TOKEN: ''
npm update
npm run prod --workspace=v1
npm run build --workspace=v2
- name: Run CI
run: |
rm -rf vendor composer.lock
composer validate --strict
composer update --no-dev --no-scripts --no-plugins -q
sudo chown -R runner:docker resources/lang
.ci/phpcs.sh
- name: Import GPG key
uses: crazy-max/ghaction-import-gpg@v6
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.PASSPHRASE }}
- name: Release
run: |
# do some configuration
sudo timedatectl set-timezone Europe/Amsterdam
git config user.name github-actions
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
git config advice.addIgnoredFile false
# set some variables
releaseName=$version
originalName=$version
zipName=FireflyIII-$version.zip
tarName=FireflyIII-$version.tar.gz
# update composer (again)
composer update --no-dev --no-scripts --no-plugins
composer dump-autoload
# if this is a develop build, slightly different variable names.
if [[ "develop" == "$version" ]]; then
[[ -z $(git status --untracked-files=normal --porcelain) ]] && echo "this branch is clean, no need to push..." && exit 0;
releaseName=$version-$(date +'%Y%m%d')
originalName=$releaseName
zipName=FireflyIII-develop.zip
tarName=FireflyIII-develop.tar.gz
fi
# in both cases, if the release or tag already exists, add ".1" until it no longer exists.
tagFound=true
tagCount=1
while [ "$tagFound" = true ]
do
if [ $(git tag -l "$releaseName") ]; then
echo "Tag $releaseName exists already."
releaseName="$originalName"."$tagCount"
echo "Tag for release is now $releaseName"
tagCount=$((tagCount+1))
else
echo "Tag $releaseName does not exist, can continue"
tagFound=false
fi
done
echo "Will use tag and release name $releaseName."
# add all content, except output.txt (this contains the changelog and/or the download instructions)
echo 'Add all and reset output.txt'
git add -A
if test -f "output.txt"; then
git reset output.txt
@@ -157,29 +192,101 @@ jobs:
git commit -m "Auto commit for release '$version' on $(date +'%Y-%m-%d')" || true
git push
# zip everything
zip -rq $zipName . -x "*.git*" "*.ci*" "*.github*" "*node_modules*"
# zip and tar everything
echo 'Zip and tar...'
zip -rq $zipName . -x "*.git*" "*.ci*" "*.github*" "*node_modules*" "*output.txt*"
touch $tarName
tar --exclude=$tarName --exclude=$zipName --exclude='./.git' --exclude='./.ci' --exclude='./.github' --exclude='./node_modules' --exclude='./output.txt' -czf $tarName .
# add sha256 sum
echo 'Sha sum ...'
sha256sum -b $zipName > $zipName.sha256
sha256sum -b $tarName > $tarName.sha256
# add signatures:
gpg --armor --detach-sign $zipName
gpg --armor --detach-sign $tarName
# create a development (nightly) release:
if [[ "develop" == "$version" ]]; then
echo 'Develop release.'
# add text to output.txt (instructions)
rm output.txt
echo "Bi-weekly development release of Firefly III with the latest fixes, translations and features. Docker users can find this release under the \`develop\` tag." >> output.txt
echo "" >> output.txt
echo "This release was created on **$(date +'%Y-%m-%d')** and may contain unexpected bugs. Data loss is rare but is not impossible. The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
echo "" >> output.txt
echo "* Please read the installation instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/installation/docker/), [Portainer](https://docs.firefly-iii.org/how-to/firefly-iii/installation/portainer/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/installation/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/installation/self-managed/)" >> output.txt
echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt
echo "" >> output.txt
echo ":warning: Please be careful with this pre-release, as it may not work as expected." >> output.txt
# create the release:
echo "Create nightly release."
git tag -a $releaseName -m "Nightly development release '$version' on $(date +'%Y-%m-%d')"
git push origin $releaseName
gh release create $releaseName -p --verify-tag \
-t "Development release for $(date +'%Y-%m-%d')" \
-n "Bi-weekly development release of Firefly III with the latest fixes, translations and features. This release was created on **$(date +'%Y-%m-%d')** and may contain bugs. Use at your own risk. Docker users can find this release under the \`develop\` tag."
-F output.txt
# add zip file to release.
gh release upload $releaseName $zipName
gh release upload $releaseName $tarName
# add sha256 sum to release
gh release upload $releaseName $zipName.sha256
gh release upload $releaseName $tarName.sha256
# add signatures to release
gh release upload $releaseName $zipName.asc
gh release upload $releaseName $tarName.asc
# get current HEAD and add as file to the release
HEAD=$(git rev-parse HEAD)
echo $HEAD > HEAD.txt
gh release upload $releaseName HEAD.txt
else
echo 'MAIN (real) release'
sudo chown -R runner:docker output.txt
# add text to output.txt (more instructions)
echo '' >> output.txt
echo '### Instructions' >> output.txt
echo '' >> output.txt
echo "* Installation instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/installation/docker/), [Portainer](https://docs.firefly-iii.org/how-to/firefly-iii/installation/portainer/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/installation/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/installation/self-managed/)" >> output.txt
echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt
echo "* The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
echo "Create default release."
git tag -a $releaseName -m "Here be changelog"
git push origin $releaseName
gh release create $releaseName -F output.txt -t "$releaseName" --verify-tag
# add zip file to release.
# add archive files to release
gh release upload $releaseName $zipName
gh release upload $releaseName $tarName
# add sha256 sums to release
gh release upload $releaseName $zipName.sha256
gh release upload $releaseName $tarName.sha256
# add signatures to release
gh release upload $releaseName $zipName.asc
gh release upload $releaseName $tarName.asc
# get current HEAD and add as file to the release
HEAD=$(git rev-parse HEAD)
echo $HEAD > HEAD.txt
gh release upload $releaseName HEAD.txt
# remove all temporary files
rm output.txt
rm HEAD.txt
rm $zipName
rm $zipName.sha256
rm $tarName
rm $tarName.sha256
# merge main back into develop
git checkout develop
git merge main
git push

View File

@@ -1,7 +1,7 @@
name: "Issues - Mark and close stale issues"
on:
schedule:
- cron: "30 1 * * *"
- cron: "0 4 * * *"
workflow_dispatch:
permissions:
@@ -17,17 +17,17 @@ jobs:
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: >
Hi there!
stale-issue-message: |
Hi there!
This is an automatic reply. `Share and enjoy`
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
Thank you for your contributions.
stale-pr-message: >
Hi there!
stale-pr-message: |
Hi there!
This is an automatic reply. `Share and enjoy`
This PR has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

8
.gitignore vendored
View File

@@ -10,3 +10,11 @@ coverage.xml
# ignore generated files.
public/build
# ignore v1 build files
resources/assets/v1/node_modules
resources/assets/v1/build
# ignore v2 build files
resources/assets/v2/node_modules
resources/assets/v2/build

193
THANKS.md Executable file
View File

@@ -0,0 +1,193 @@
# Thank you! :tada: :heart: :tada:
Over time, many people have contributed to Firefly III. Their efforts are not always visible, but always remembered and appreciated.
Please find below all the people who contributed to the Firefly III code. Their names are mentioned in the year of their first contribution.
## 2024
- imlonghao
- Rahman Yusuf
- Michael Thomas
- WardenJakx
- kuilin
- Stevie Robinson
- luzpaz
- Lemuel Roberto Bonifácio
- maureenferreira
## 2023
- tieu1991
- Maxco10
- zqye
- Mateus Pereira
- josephbadow
- Christian Desktop
- Edgars
- Hannah K
- noxonad
- Kaijia Feng
- Marc Ordinas i Llopis
- Kuba Turek
- Julien Stébenne
## 2022
- Johannes Zellner
- Janne Heß
- charlesteets
- Nathan PERIER
- Jan Willhaus
- canoine
- Rick Cuddy
- James
- Hugo Meyronneinc
- naveen
- neilnaveen
- naveensrinivasan
- Federico Micelli
- George Hahn
## 2021
- StillLoading
- Igor Rzegocki
- Lorenzo Breda
- Hosh
- Flightkick
- alex6480
- VREEdom
- Hamza FADIL
- Kasper Læssø Sørensen
- Alex
- Jeroen De Meerleer
- Ruben van Erk
- Fabian Zimmermann
- Mirko Berger
- KaihatsuOnline
- MihataBG
## 2020
- Hannes Körber
- Julien Cassagne
- bu4ak
- Viktor Yakovlev
- Oliver Kaufmann
- Arvind Chembarpu
- GrayStrider
- psychowood
- Hosh Sadiq
- emansih
- Aniruddha Maru
- johnny
- sephrat
- bpatath
- Florian Dupret
- Maxim Kurbatov
- Lucas Guima
- Sandro
- Ruben Verhoef
- Daniel Idzerda
- Calum Smith
- Agraphie
- Tomer Shvueli
- Tomer S
## 2019
- Pascal Jungblut
- Justyn Shull
- Timendum
- Nicolas Lœuillet
- Dominic Guhl
- Melroy van den Berg
- Henning Stein
- Jan Klepek
- Jonathan
- Geoffrey “Frogeye” Preud'homme
- Michael Fix
- Juraj Mlich
- Eddybrando Vásquez
- hulloanson
- Will Rouesnel
- lastlink
- Mr. Funk
- Simon Taddiken
- Joris
- Bastiaan Nijkamp
## 2018
- a1ex4
- Daniel Quah
- Marco Lourenço
- Dennis Enderink
- Luca Bognolo
- Mike Conway
- Ben
- Mathieu Post
- George Hertz
- HamuZ HamuZ
- David Meiseles
- Erik Gelderblom
- Luca Vallerini
- Clemens Wijnekus
- Jacob Weisz
- Mateusz Gozdek
- anmol26s
- Kevin Hellemun
- Shashank M Chakravarthy
- Nico Schreiner
- Paul Sohier
- Brenden Conte
- Ben Yanke
- Andrew Prokhorenkov
- devlearner
- Kelvin
- J'informatique
## 2017
- Victor Mosin
- Justin
- Hugo van Duijn
- Lukas Winkler
- Marcin Szymanski
- Jens Kat
- koziolek
- jleeong
- Simon Hanna
- richard & xeli.eu
- Sergey Besedin
- Welbert Serra
- Joris de Vries
- Patrick Kostjens
- Enrico Lamperti
- Christian Musa
- Enno Lohmeier
## 2016
- Sander
- Toon Schoenmakers
- Telyn
- Sander Kleykens
- Tom van der Werf
- Matthew Peck
- Sander Mulders
- Bonno Nachtegaal-Karels
- Niek Haarman
- Edwin
- Thijs Alkemade
- zjean
- Graham Miller
- Robert Horlings
- leander091
## 2015
- Antonio Spinelli
- Colin O'Dell
- RonaldvanMeer
- Richard Ebbers
- Balazs Varkonyi
- Niek van der Kooy
- Ilya Kil
## 2014
- Stewart Malik
- Graham Campbell
Thank you for all your support!

View File

@@ -83,17 +83,17 @@ class AccountController extends Controller
// user's preferences
$defaultSet = $this->repository->getAccountsByType([AccountType::ASSET])->pluck('id')->toArray();
/** @var Preference $frontPage */
$frontPage = app('preferences')->get('frontPageAccounts', $defaultSet);
/** @var Preference $frontpage */
$frontpage = app('preferences')->get('frontpageAccounts', $defaultSet);
$default = app('amount')->getDefaultCurrency();
if (!(is_array($frontPage->data) && count($frontPage->data) > 0)) {
$frontPage->data = $defaultSet;
$frontPage->save();
if (!(is_array($frontpage->data) && count($frontpage->data) > 0)) {
$frontpage->data = $defaultSet;
$frontpage->save();
}
// get accounts:
$accounts = $this->repository->getAccountsById($frontPage->data);
$accounts = $this->repository->getAccountsById($frontpage->data);
$chartData = [];
/** @var Account $account */

View File

@@ -72,6 +72,12 @@ class UpdateController extends Controller
app('log')->debug('Now in update routine for transaction group!');
$data = $request->getAll();
// Fixes 8750.
$transactions = $data['transactions'] ?? [];
foreach ($transactions as $index => $info) {
unset($data['transactions'][$index]['type']);
}
$transactionGroup = $this->groupRepository->update($transactionGroup, $data);
$manager = $this->getManager();

View File

@@ -32,6 +32,7 @@ use FireflyIII\Models\Preference;
use FireflyIII\Transformers\PreferenceTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection as FractalCollection;
use League\Fractal\Resource\Item;
@@ -84,6 +85,10 @@ class PreferencesController extends Controller
{
$manager = $this->getManager();
if ('currencyPreference' === $preference->name) {
throw new FireflyException('Please use api/v1/currencies/default instead.');
}
/** @var PreferenceTransformer $transformer */
$transformer = app(PreferenceTransformer::class);
$transformer->setParameters($this->parameters);
@@ -93,6 +98,32 @@ class PreferencesController extends Controller
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
}
/**
* TODO This endpoint is not documented.
*
* Return a single preference by name.
*/
public function showList(Collection $collection): JsonResponse
{
$manager = $this->getManager();
$count = $collection->count();
$pageSize = $this->parameters->get('limit');
$preferences = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// make paginator:
$paginator = new LengthAwarePaginator($preferences, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.preferences.show-list').$this->buildParams());
/** @var PreferenceTransformer $transformer */
$transformer = app(PreferenceTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($preferences, $transformer, self::RESOURCE_KEY);
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
}
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/preferences/storePreference
@@ -103,6 +134,11 @@ class PreferencesController extends Controller
{
$manager = $this->getManager();
$data = $request->getAll();
if ('currencyPreference' === $data['name']) {
throw new FireflyException('Please use api/v1/currencies/default instead.');
}
$pref = app('preferences')->set($data['name'], $data['data']);
/** @var PreferenceTransformer $transformer */
@@ -122,6 +158,10 @@ class PreferencesController extends Controller
*/
public function update(PreferenceUpdateRequest $request, Preference $preference): JsonResponse
{
if ('currencyPreference' === $preference->name) {
throw new FireflyException('Please use api/v1/currencies/default instead.');
}
$manager = $this->getManager();
$data = $request->getAll();
$pref = app('preferences')->set($preference->name, $data['data']);

View File

@@ -63,7 +63,7 @@ class StoreRequest extends FormRequest
'order' => $this->convertInteger('order'),
'currency_code' => $this->convertString('currency_code'),
'virtual_balance' => $this->convertString('virtual_balance'),
'iban' => $this->convertString('iban'),
'iban' => $this->convertIban('iban'),
'BIC' => $this->convertString('bic'),
'account_number' => $this->convertString('account_number'),
'account_role' => $this->convertString('account_role'),

View File

@@ -51,7 +51,7 @@ class UpdateRequest extends FormRequest
'include_net_worth' => ['include_net_worth', 'boolean'],
'account_type_name' => ['type', 'convertString'],
'virtual_balance' => ['virtual_balance', 'convertString'],
'iban' => ['iban', 'convertString'],
'iban' => ['iban', 'convertIban'],
'BIC' => ['bic', 'convertString'],
'account_number' => ['account_number', 'convertString'],
'account_role' => ['account_role', 'convertString'],

View File

@@ -71,8 +71,9 @@ class StoreRequest extends FormRequest
if (is_array($triggers)) {
foreach ($triggers as $trigger) {
$return[] = [
'type' => $trigger['type'],
'value' => $trigger['value'],
'type' => $trigger['type'] ?? '',
'value' => $trigger['value'] ?? null,
'prohibited' => $this->convertBoolean((string)($trigger['prohibited'] ?? 'false')),
'active' => $this->convertBoolean((string)($trigger['active'] ?? 'true')),
'stop_processing' => $this->convertBoolean((string)($trigger['stop_processing'] ?? 'false')),
];

View File

@@ -54,17 +54,13 @@ class TestRequest extends FormRequest
private function getDate(string $field): ?Carbon
{
$value = $this->query($field);
$value = $this->query($field);
if (is_array($value)) {
return null;
}
$value = (string)$value;
$result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
if (false === $result) {
return null;
}
$value = (string)$value;
return $result;
return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
}
private function getAccounts(): array

View File

@@ -48,17 +48,13 @@ class TriggerRequest extends FormRequest
private function getDate(string $field): ?Carbon
{
$value = $this->query($field);
$value = $this->query($field);
if (is_array($value)) {
return null;
}
$value = (string)$value;
$result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
if (false === $result) {
return null;
}
$value = (string)$value;
return $result;
return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
}
private function getAccounts(): array

View File

@@ -81,10 +81,12 @@ class UpdateRequest extends FormRequest
if (is_array($triggers)) {
foreach ($triggers as $trigger) {
$active = array_key_exists('active', $trigger) ? $trigger['active'] : true;
$prohibited = array_key_exists('prohibited', $trigger) ? $trigger['prohibited'] : false;
$stopProcessing = array_key_exists('stop_processing', $trigger) ? $trigger['stop_processing'] : false;
$return[] = [
'type' => $trigger['type'],
'value' => $trigger['value'],
'prohibited' => $prohibited,
'active' => $active,
'stop_processing' => $stopProcessing,
];

View File

@@ -48,17 +48,13 @@ class TestRequest extends FormRequest
private function getDate(string $field): ?Carbon
{
$value = $this->query($field);
$value = $this->query($field);
if (is_array($value)) {
return null;
}
$value = (string)$value;
$result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
if (false === $result) {
return null;
}
$value = (string)$value;
return $result;
return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
}
private function getAccounts(): array

View File

@@ -48,17 +48,13 @@ class TriggerRequest extends FormRequest
private function getDate(string $field): ?Carbon
{
$value = $this->query($field);
$value = $this->query($field);
if (is_array($value)) {
return null;
}
$value = (string)$value;
$result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
if (false === $result) {
return null;
}
$value = (string)$value;
return $result;
return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
}
private function getAccounts(): array

View File

@@ -103,14 +103,14 @@ class StoreRequest extends FormRequest
// source of transaction. If everything is null, assume cash account.
'source_id' => $this->integerFromValue((string)$object['source_id']),
'source_name' => $this->clearString((string)$object['source_name']),
'source_iban' => $this->clearString((string)$object['source_iban']),
'source_iban' => $this->clearIban((string)$object['source_iban']),
'source_number' => $this->clearString((string)$object['source_number']),
'source_bic' => $this->clearString((string)$object['source_bic']),
// destination of transaction. If everything is null, assume cash account.
'destination_id' => $this->integerFromValue((string)$object['destination_id']),
'destination_name' => $this->clearString((string)$object['destination_name']),
'destination_iban' => $this->clearString((string)$object['destination_iban']),
'destination_iban' => $this->clearIban((string)$object['destination_iban']),
'destination_number' => $this->clearString((string)$object['destination_number']),
'destination_bic' => $this->clearString((string)$object['destination_bic']),

View File

@@ -28,22 +28,21 @@ use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Autocomplete\AutocompleteRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface as AdminAccountRepositoryInterface;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Models\AccountBalance;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
/**
* Class AccountController
*/
class AccountController extends Controller
{
use AccountFilter;
private AdminAccountRepositoryInterface $adminRepository;
private array $balanceTypes;
private AccountRepositoryInterface $repository;
private AccountRepositoryInterface $repository;
private TransactionCurrency $default;
private ExchangeRateConverter $converter;
/**
* AccountController constructor.
@@ -53,83 +52,88 @@ class AccountController extends Controller
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(AccountRepositoryInterface::class);
$this->adminRepository = app(AdminAccountRepositoryInterface::class);
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->adminRepository->setUserGroup($userGroup);
}
$userGroup = $this->validateUserGroup($request);
$this->repository = app(AccountRepositoryInterface::class);
$this->repository->setUserGroup($userGroup);
$this->default = app('amount')->getDefaultCurrency();
$this->converter = app(ExchangeRateConverter::class);
return $next($request);
}
);
$this->balanceTypes = [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE];
}
/**
* Documentation for this endpoint:
* TODO list of checks
* 1. use dates from ParameterBag
* 2. Request validates dates
* 3. Request includes user_group_id
* 4. Endpoint is documented.
* 5. Collector uses user_group_id
*
* @throws FireflyException
* @throws FireflyException
* Documentation: https://api-docs.firefly-iii.org/?urls.primaryName=2.1.0%20(v2)#/autocomplete/getAccountsAC
*/
public function accounts(AutocompleteRequest $request): JsonResponse
{
$data = $request->getData();
$types = $data['types'];
$query = $data['query'];
$date = $this->parameters->get('date') ?? today(config('app.timezone'));
$result = $this->adminRepository->searchAccount((string)$query, $types, $data['limit']);
$defaultCurrency = app('amount')->getDefaultCurrency();
$groupedResult = [];
$allItems = [];
$queryParameters = $request->getParameters();
$result = $this->repository->searchAccount($queryParameters['query'], $queryParameters['account_types'], $queryParameters['size']);
$return = [];
/** @var Account $account */
foreach ($result as $account) {
$nameWithBalance = $account->name;
$currency = $this->repository->getAccountCurrency($account) ?? $defaultCurrency;
if (in_array($account->accountType->type, $this->balanceTypes, true)) {
$balance = app('steam')->balance($account, $date);
$nameWithBalance = sprintf('%s (%s)', $account->name, app('amount')->formatAnything($currency, $balance, false));
}
$type = (string)trans(sprintf('firefly.%s', $account->accountType->type));
$groupedResult[$type] ??= [
'group ' => $type,
'items' => [],
];
$allItems[] = [
'id' => (string)$account->id,
'value' => (string)$account->id,
'name' => $account->name,
'name_with_balance' => $nameWithBalance,
'label' => $nameWithBalance,
'type' => $account->accountType->type,
'currency_id' => (string)$currency->id,
'currency_name' => $currency->name,
'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places,
];
$return[] = $this->parseAccount($account);
}
usort(
$allItems,
static function (array $left, array $right): int {
$order = [AccountType::ASSET, AccountType::REVENUE, AccountType::EXPENSE];
$posLeft = (int)array_search($left['type'], $order, true);
$posRight = (int)array_search($right['type'], $order, true);
return response()->json($return);
}
return $posLeft - $posRight;
private function parseAccount(Account $account): array
{
$currency = $this->repository->getAccountCurrency($account);
return [
'id' => (string) $account->id,
'title' => $account->name,
'meta' => [
'type' => $account->accountType->type,
'currency_id' => null === $currency ? null : (string) $currency->id,
'currency_code' => $currency?->code,
'currency_symbol' => $currency?->symbol,
'currency_decimal_places' => $currency?->decimal_places,
'account_balances' => $this->getAccountBalances($account),
],
];
}
private function getAccountBalances(Account $account): array
{
$return = [];
$balances = $this->repository->getAccountBalances($account);
/** @var AccountBalance $balance */
foreach ($balances as $balance) {
try {
$return[] = $this->parseAccountBalance($balance);
} catch (FireflyException $e) {
Log::error(sprintf('Could not parse convert account balance: %s', $e->getMessage()));
}
);
}
return response()->json($allItems);
return $return;
}
/**
* @throws FireflyException
*/
private function parseAccountBalance(AccountBalance $balance): array
{
$currency = $balance->transactionCurrency;
return [
'title' => $balance->title,
'native_amount' => $this->converter->convert($currency, $this->default, today(), $balance->balance),
'amount' => app('steam')->bcround($balance->balance, $currency->decimal_places),
'currency_id' => (string) $currency->id,
'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places,
'native_currency_id' => (string) $this->default->id,
'native_currency_code' => $this->default->code,
'native_currency_symbol' => $this->default->symbol,
'native_currency_decimal_places' => $this->default->decimal_places,
];
}
}

View File

@@ -45,11 +45,7 @@ class CategoryController extends Controller
$this->middleware(
function ($request, $next) {
$this->repository = app(CategoryRepositoryInterface::class);
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->repository->setUserGroup($userGroup);
}
$this->repository->setUserGroup($this->validateUserGroup($request));
return $next($request);
}
@@ -57,23 +53,18 @@ class CategoryController extends Controller
}
/**
* Documentation for this endpoint:
* TODO list of checks
* 1. use dates from ParameterBag
* 2. Request validates dates
* 3. Request includes user_group_id
* 4. Endpoint is documented.
* 5. Collector uses user_group_id
* Documentation: https://api-docs.firefly-iii.org/?urls.primaryName=2.1.0%20(v2)#/autocomplete/getCategoriesAC
*/
public function categories(AutocompleteRequest $request): JsonResponse
{
$data = $request->getData();
$result = $this->repository->searchCategory($data['query'], $this->parameters->get('limit'));
$filtered = $result->map(
$queryParameters = $request->getParameters();
$result = $this->repository->searchCategory($queryParameters['query'], $queryParameters['size']);
$filtered = $result->map(
static function (Category $item) {
return [
'id' => (string)$item->id,
'name' => $item->name,
'id' => (string)$item->id,
'title' => $item->name,
'meta' => [],
];
}
);

View File

@@ -45,11 +45,7 @@ class TagController extends Controller
$this->middleware(
function ($request, $next) {
$this->repository = app(TagRepositoryInterface::class);
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->repository->setUserGroup($userGroup);
}
$this->repository->setUserGroup($this->validateUserGroup($request));
return $next($request);
}
@@ -57,25 +53,20 @@ class TagController extends Controller
}
/**
* Documentation for this endpoint:
* TODO list of checks
* 1. use dates from ParameterBag
* 2. Request validates dates
* 3. Request includes user_group_id
* 4. Endpoint is documented.
* 5. Collector uses user_group_id
* Documentation: https://api-docs.firefly-iii.org/?urls.primaryName=2.1.0%20(v2)#/autocomplete/getTagsAC
*/
public function tags(AutocompleteRequest $request): JsonResponse
{
$data = $request->getData();
$result = $this->repository->searchTag($data['query'], $data['limit']);
$filtered = $result->map(
$queryParameters = $request->getParameters();
$result = $this->repository->searchTag($queryParameters['query'], $queryParameters['size']);
$filtered = $result->map(
static function (Tag $item) {
return [
'id' => (string)$item->id,
'name' => $item->tag,
'value' => (string)$item->id,
'id' => (string) $item->id,
'title' => $item->tag,
'value' => (string) $item->id,
'label' => $item->tag,
'meta' => [],
];
}
);

View File

@@ -45,11 +45,7 @@ class TransactionController extends Controller
$this->middleware(
function ($request, $next) {
$this->repository = app(JournalRepositoryInterface::class);
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->repository->setUserGroup($userGroup);
}
$this->repository->setUserGroup($this->validateUserGroup($request));
return $next($request);
}
@@ -57,30 +53,25 @@ class TransactionController extends Controller
}
/**
* Documentation for this endpoint:
* TODO list of checks
* 1. use dates from ParameterBag
* 2. Request validates dates
* 3. Request includes user_group_id
* 4. Endpoint is documented.
* 5. Collector uses user_group_id
* Documentation: https://api-docs.firefly-iii.org/?urls.primaryName=2.1.0%20(v2)#/autocomplete/getTransactionsAC
*/
public function transactionDescriptions(AutocompleteRequest $request): JsonResponse
{
$data = $request->getData();
$result = $this->repository->searchJournalDescriptions($data['query'], $data['limit']);
$queryParameters = $request->getParameters();
$result = $this->repository->searchJournalDescriptions($queryParameters['query'], $queryParameters['size']);
// limit and unique
$filtered = $result->unique('description');
$array = [];
$filtered = $result->unique('description');
$array = [];
/** @var TransactionJournal $journal */
foreach ($filtered as $journal) {
$array[] = [
'id' => (string)$journal->id,
'transaction_group_id' => (string)$journal->transaction_group_id,
'name' => $journal->description,
'description' => $journal->description,
'id' => (string) $journal->id,
'title' => $journal->description,
'meta' => [
'transaction_group_id' => (string) $journal->transaction_group_id,
],
];
}

View File

@@ -53,10 +53,7 @@ class AccountController extends Controller
$this->middleware(
function ($request, $next) {
$this->repository = app(AccountRepositoryInterface::class);
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->repository->setUserGroup($userGroup);
}
$this->repository->setUserGroup($this->validateUserGroup($request));
return $next($request);
}
@@ -75,8 +72,6 @@ class AccountController extends Controller
* TODO validate and set user_group_id from request
*
* @throws FireflyException
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function dashboard(DashboardChartRequest $request): JsonResponse
{
@@ -98,14 +93,14 @@ class AccountController extends Controller
// user's preferences
if (0 === $accounts->count()) {
$defaultSet = $this->repository->getAccountsByType([AccountType::ASSET, AccountType::DEFAULT])->pluck('id')->toArray();
$frontPage = app('preferences')->get('frontPageAccounts', $defaultSet);
$frontpage = app('preferences')->get('frontpageAccounts', $defaultSet);
if (!(is_array($frontPage->data) && count($frontPage->data) > 0)) {
$frontPage->data = $defaultSet;
$frontPage->save();
if (!(is_array($frontpage->data) && count($frontpage->data) > 0)) {
$frontpage->data = $defaultSet;
$frontpage->save();
}
$accounts = $this->repository->getAccountsById($frontPage->data);
$accounts = $this->repository->getAccountsById($frontpage->data);
}
// both options are overruled by "preselected"

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V2\Controllers\Chart;
use Carbon\Carbon;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Chart\BalanceChartRequest;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\TransactionCurrency;
@@ -42,6 +43,7 @@ use Illuminate\Support\Collection;
class BalanceController extends Controller
{
use CleansChartData;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
/**
* The code is practically a duplicate of ReportController::operations.

View File

@@ -64,12 +64,9 @@ class BudgetController extends Controller
$this->blRepository = app(BudgetLimitRepositoryInterface::class);
$this->opsRepository = app(OperationsRepositoryInterface::class);
$this->currency = app('amount')->getDefaultCurrency();
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->repository->setUserGroup($userGroup);
$this->opsRepository->setUserGroup($userGroup);
}
$this->repository->setUserGroup($userGroup);
$this->opsRepository->setUserGroup($userGroup);
return $next($request);
}
@@ -124,11 +121,11 @@ class BudgetController extends Controller
foreach ($rows as $row) {
$current = [
'label' => $budget->name,
'currency_id' => (string)$row['currency_id'],
'currency_id' => (string) $row['currency_id'],
'currency_code' => $row['currency_code'],
'currency_name' => $row['currency_name'],
'currency_decimal_places' => $row['currency_decimal_places'],
'native_currency_id' => (string)$row['native_currency_id'],
'native_currency_id' => (string) $row['native_currency_id'],
'native_currency_code' => $row['native_currency_code'],
'native_currency_name' => $row['native_currency_name'],
'native_currency_decimal_places' => $row['native_currency_decimal_places'],
@@ -189,12 +186,12 @@ class BudgetController extends Controller
foreach ($array as $currencyId => $block) {
$this->currencies[$currencyId] ??= TransactionCurrency::find($currencyId);
$return[$currencyId] ??= [
'currency_id' => (string)$currencyId,
'currency_id' => (string) $currencyId,
'currency_code' => $block['currency_code'],
'currency_name' => $block['currency_name'],
'currency_symbol' => $block['currency_symbol'],
'currency_decimal_places' => (int)$block['currency_decimal_places'],
'native_currency_id' => (string)$this->currency->id,
'currency_decimal_places' => (int) $block['currency_decimal_places'],
'native_currency_id' => (string) $this->currency->id,
'native_currency_code' => $this->currency->code,
'native_currency_name' => $this->currency->name,
'native_currency_symbol' => $this->currency->symbol,

View File

@@ -57,10 +57,7 @@ class CategoryController extends Controller
function ($request, $next) {
$this->accountRepos = app(AccountRepositoryInterface::class);
$this->currencyRepos = app(CurrencyRepositoryInterface::class);
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->accountRepos->setUserGroup($userGroup);
}
$this->accountRepos->setUserGroup($this->validateUserGroup($request));
return $next($request);
}
@@ -100,25 +97,25 @@ class CategoryController extends Controller
/** @var array $journal */
foreach ($journals as $journal) {
$currencyId = (int)$journal['currency_id'];
$currencyId = (int) $journal['currency_id'];
$currency = $currencies[$currencyId] ?? $this->currencyRepos->find($currencyId);
$currencies[$currencyId] = $currency;
$categoryName = null === $journal['category_name'] ? (string)trans('firefly.no_category') : $journal['category_name'];
$categoryName = null === $journal['category_name'] ? (string) trans('firefly.no_category') : $journal['category_name'];
$amount = app('steam')->positive($journal['amount']);
$nativeAmount = $converter->convert($default, $currency, $journal['date'], $amount);
$key = sprintf('%s-%s', $categoryName, $currency->code);
if ((int)$journal['foreign_currency_id'] === $default->id) {
if ((int) $journal['foreign_currency_id'] === $default->id) {
$nativeAmount = app('steam')->positive($journal['foreign_amount']);
}
// create arrays
$return[$key] ??= [
'label' => $categoryName,
'currency_id' => (string)$currency->id,
'currency_id' => (string) $currency->id,
'currency_code' => $currency->code,
'currency_name' => $currency->name,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places,
'native_currency_id' => (string)$default->id,
'native_currency_id' => (string) $default->id,
'native_currency_code' => $default->code,
'native_currency_name' => $default->name,
'native_currency_symbol' => $default->symbol,
@@ -138,7 +135,7 @@ class CategoryController extends Controller
// order by native amount
usort($return, static function (array $a, array $b) {
return (float)$a['native_amount'] < (float)$b['native_amount'] ? 1 : -1;
return (float) $a['native_amount'] < (float) $b['native_amount'] ? 1 : -1;
});
$converter->summarize();

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V2\Controllers;
use Carbon\Carbon;
use Carbon\Exceptions\InvalidDateException;
use Carbon\Exceptions\InvalidFormatException;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Transformers\V2\AbstractTransformer;
use Illuminate\Database\Eloquent\Model;
@@ -55,6 +56,7 @@ class Controller extends BaseController
protected const string CONTENT_TYPE = 'application/vnd.api+json';
protected ParameterBag $parameters;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
public function __construct()
{
@@ -120,6 +122,9 @@ class Controller extends BaseController
$obj = null;
}
}
if (null !== $date && 'end' === $field) {
$obj->endOfDay();
}
$bag->set($field, $obj);
}
@@ -152,6 +157,9 @@ class Controller extends BaseController
{
$manager = new Manager();
$baseUrl = request()->getSchemeAndHttpHost().'/api/v2';
// TODO add stuff to path?
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$objects = $paginator->getCollection();

View File

@@ -25,17 +25,19 @@ namespace FireflyIII\Api\V2\Controllers\Model\Account;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Model\Account\IndexRequest;
use FireflyIII\Api\V2\Request\Model\Transaction\InfiniteListRequest;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
use FireflyIII\Transformers\V2\AccountTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\Log;
class IndexController extends Controller
{
public const string RESOURCE_KEY = 'accounts';
public const string RESOURCE_KEY = 'accounts';
private AccountRepositoryInterface $repository;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY, UserRoleEnum::MANAGE_TRANSACTIONS];
/**
* AccountController constructor.
@@ -48,9 +50,7 @@ class IndexController extends Controller
$this->repository = app(AccountRepositoryInterface::class);
// new way of user group validation
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->repository->setUserGroup($userGroup);
}
$this->repository->setUserGroup($userGroup);
return $next($request);
}
@@ -58,21 +58,35 @@ class IndexController extends Controller
}
/**
* TODO see autocomplete/accountcontroller for list.
* TODO the sort instructions need proper repeatable documentation.
* TODO see autocomplete/account controller for list.
*/
public function index(IndexRequest $request): JsonResponse
{
$this->repository->resetAccountOrder();
$types = $request->getAccountTypes();
$instructions = $request->getSortInstructions('accounts');
$accounts = $this->repository->getAccountsByType($types, $instructions);
$pageSize = $this->parameters->get('limit');
$count = $accounts->count();
$accounts = $accounts->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page'));
$transformer = new AccountTransformer();
$types = $request->getAccountTypes();
$sorting = $request->getSortInstructions('accounts');
$filters = $request->getFilterInstructions('accounts');
$accounts = $this->repository->getAccountsByType($types, $sorting, $filters);
$pageSize = $this->parameters->get('limit');
$count = $accounts->count();
$this->parameters->set('sort', $instructions);
// depending on the sort parameters, this list must not be split, because the
// order is calculated in the account transformer and by that time it's too late.
$first = array_key_first($sorting);
$disablePagination = in_array($first, ['last_activity', 'balance', 'balance_difference'], true);
Log::debug(sprintf('Will disable pagination in account index v2? %s', var_export($disablePagination, true)));
if (!$disablePagination) {
$accounts = $accounts->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
}
$paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page'));
$transformer = new AccountTransformer();
$this->parameters->set('disablePagination', $disablePagination);
$this->parameters->set('pageSize', $pageSize);
$this->parameters->set('sort', $sorting);
$this->parameters->set('filters', $filters);
$transformer->setParameters($this->parameters); // give params to transformer
return response()
@@ -80,25 +94,4 @@ class IndexController extends Controller
->header('Content-Type', self::CONTENT_TYPE)
;
}
public function infiniteList(InfiniteListRequest $request): JsonResponse
{
$this->repository->resetAccountOrder();
// get accounts of the specified type, and return.
$types = $request->getAccountTypes();
// get from repository
$accounts = $this->repository->getAccountsInOrder($types, $request->getSortInstructions('accounts'), $request->getStartRow(), $request->getEndRow());
$total = $this->repository->countAccounts($types);
$count = $request->getEndRow() - $request->getStartRow();
$paginator = new LengthAwarePaginator($accounts, $total, $count, $this->parameters->get('page'));
$transformer = new AccountTransformer();
$transformer->setParameters($this->parameters); // give params to transformer
return response()
->json($this->jsonApiList(self::RESOURCE_KEY, $paginator, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -25,7 +25,9 @@ declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Model\Account;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\Account;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
use FireflyIII\Transformers\V2\AccountTransformer;
use Illuminate\Http\JsonResponse;
@@ -36,6 +38,29 @@ use Illuminate\Http\JsonResponse;
*/
class ShowController extends Controller
{
public const string RESOURCE_KEY = 'accounts';
private AccountRepositoryInterface $repository;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY, UserRoleEnum::MANAGE_TRANSACTIONS];
/**
* AccountController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(AccountRepositoryInterface::class);
// new way of user group validation
$userGroup = $this->validateUserGroup($request);
$this->repository->setUserGroup($userGroup);
return $next($request);
}
);
}
/**
* TODO this endpoint is not yet reachable.
*/

View File

@@ -45,11 +45,7 @@ class UpdateController extends Controller
$this->middleware(
function ($request, $next) {
$this->repository = app(AccountRepositoryInterface::class);
// new way of user group validation
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->repository->setUserGroup($userGroup);
}
$this->repository->setUserGroup($this->validateUserGroup($request));
return $next($request);
}

View File

@@ -46,12 +46,7 @@ class IndexController extends Controller
$this->middleware(
function ($request, $next) {
$this->repository = app(BillRepositoryInterface::class);
// new way of user group validation
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->repository->setUserGroup($userGroup);
}
$this->repository->setUserGroup($this->validateUserGroup($request));
return $next($request);
}

View File

@@ -46,12 +46,7 @@ class ShowController extends Controller
$this->middleware(
function ($request, $next) {
$this->repository = app(BillRepositoryInterface::class);
// new way of user group validation
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->repository->setUserGroup($userGroup);
}
$this->repository->setUserGroup($this->validateUserGroup($request));
return $next($request);
}

View File

@@ -45,11 +45,7 @@ class SumController extends Controller
$this->middleware(
function ($request, $next) {
$this->repository = app(BillRepositoryInterface::class);
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->repository->setUserGroup($userGroup);
}
$this->repository->setUserGroup($this->validateUserGroup($request));
return $next($request);
}

View File

@@ -46,11 +46,7 @@ class IndexController extends Controller
$this->middleware(
function ($request, $next) {
$this->repository = app(PiggyBankRepositoryInterface::class);
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->repository->setUserGroup($userGroup);
}
$this->repository->setUserGroup($this->validateUserGroup($request));
return $next($request);
}

View File

@@ -77,13 +77,11 @@ class BasicController extends Controller
$this->opsRepository = app(OperationsRepositoryInterface::class);
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->abRepository->setUserGroup($userGroup);
$this->accountRepository->setUserGroup($userGroup);
$this->billRepository->setUserGroup($userGroup);
$this->budgetRepository->setUserGroup($userGroup);
$this->opsRepository->setUserGroup($userGroup);
}
$this->abRepository->setUserGroup($userGroup);
$this->accountRepository->setUserGroup($userGroup);
$this->billRepository->setUserGroup($userGroup);
$this->budgetRepository->setUserGroup($userGroup);
$this->opsRepository->setUserGroup($userGroup);
return $next($request);
}
@@ -298,7 +296,7 @@ class BasicController extends Controller
app('log')->debug(sprintf('Amount left is %s', $left));
// how much left per day?
$days = (int) $today->diffInDays($end, true) + 1;
$days = (int)$today->diffInDays($end, true) + 1;
$perDay = '0';
$perDayNative = '0';
if (0 !== $days && bccomp($left, '0') > -1) {

View File

@@ -52,10 +52,8 @@ class NetWorthController extends Controller
$this->repository = app(AccountRepositoryInterface::class);
// new way of user group validation
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->netWorth->setUserGroup($userGroup);
$this->repository->setUserGroup($userGroup);
}
$this->netWorth->setUserGroup($userGroup);
$this->repository->setUserGroup($userGroup);
return $next($request);
}

View File

@@ -0,0 +1,73 @@
<?php
/*
* IndexController.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\UserGroup;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Model\Account\IndexRequest;
use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface;
use FireflyIII\Transformers\V2\UserGroupTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator;
class IndexController extends Controller
{
public const string RESOURCE_KEY = 'user_groups';
private UserGroupRepositoryInterface $repository;
/**
* AccountController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(UserGroupRepositoryInterface::class);
return $next($request);
}
);
}
/**
* TODO see autocomplete/accountcontroller for list.
*/
public function index(IndexRequest $request): JsonResponse
{
$administrations = $this->repository->get();
$pageSize = $this->parameters->get('limit');
$count = $administrations->count();
$administrations = $administrations->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($administrations, $count, $pageSize, $this->parameters->get('page'));
$transformer = new UserGroupTransformer();
$transformer->setParameters($this->parameters); // give params to transformer
return response()
->json($this->jsonApiList(self::RESOURCE_KEY, $paginator, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -79,4 +79,12 @@ class UpdateController extends Controller
->header('Content-Type', self::CONTENT_TYPE)
;
}
public function useUserGroup(UserGroup $userGroup): JsonResponse
{
// group validation is already in place, so can just update the user.
$this->repository->useUserGroup($userGroup);
return response()->json([], 204);
}
}

View File

@@ -23,47 +23,68 @@ declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Autocomplete;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\AccountType;
use FireflyIII\JsonApi\Rules\IsValidFilter;
use FireflyIII\JsonApi\Rules\IsValidPage;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Http\Api\ParsesQueryFilters;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
use LaravelJsonApi\Core\Query\QueryParameters;
use LaravelJsonApi\Validation\Rule as JsonApiRule;
/**
* Class AutocompleteRequest
*/
class AutocompleteRequest extends FormRequest
{
use AccountFilter;
use ChecksLogin;
use ConvertsDataTypes;
use ParsesQueryFilters;
protected array $acceptedRoles = [UserRoleEnum::MANAGE_TRANSACTIONS];
public function getData(): array
/**
* Loops over all possible query parameters (these are shared over ALL auto complete requests)
* and returns a validated array of parameters.
*
* The advantage is a single class. But you may also submit "account types" to an endpoint that doesn't use these.
*/
public function getParameters(): array
{
$types = $this->convertString('types');
$array = [];
if ('' !== $types) {
$array = explode(',', $types);
}
$limit = $this->convertInteger('limit');
$limit = 0 === $limit ? 10 : $limit;
// remove 'initial balance' and another from allowed types. its internal
$array = array_diff($array, [AccountType::INITIAL_BALANCE, AccountType::RECONCILIATION]);
$queryParameters = QueryParameters::cast($this->all());
return [
'types' => $array,
'query' => $this->convertString('query'),
'date' => $this->getCarbonDate('date'),
'limit' => $limit,
'date' => $this->dateOrToday($queryParameters, 'date'),
'query' => $this->arrayOfStrings($queryParameters, 'query'),
'size' => $this->integerFromQueryParams($queryParameters, 'size', 50),
'account_types' => $this->getAccountTypeParameter($this->arrayOfStrings($queryParameters, 'account_types')),
];
}
public function rules(): array
{
return [
'limit' => 'min:0|max:1337',
'fields' => JsonApiRule::notSupported(),
'filter' => ['nullable', 'array', new IsValidFilter(['query', 'date', 'account_types'])],
'include' => JsonApiRule::notSupported(),
'page' => ['nullable', 'array', new IsValidPage(['size'])],
'sort' => JsonApiRule::notSupported(),
];
}
private function getAccountTypeParameter(mixed $types): array
{
if (is_string($types) && str_contains($types, ',')) {
$types = explode(',', $types);
}
if (!is_iterable($types)) {
$types = [$types];
}
$return = [];
foreach ($types as $type) {
$return = array_merge($return, $this->mapAccountTypes($type));
}
return array_unique($return);
}
}

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Chart;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
@@ -39,6 +40,7 @@ class BalanceChartRequest extends FormRequest
use ChecksLogin;
use ConvertsDataTypes;
use ValidatesUserGroupTrait;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
/**
* Get all data from the request.

View File

@@ -0,0 +1,112 @@
<?php
/*
* DashboardChartRequest.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Chart;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\JsonApi\Rules\IsValidFilter;
use FireflyIII\Support\Http\Api\ParsesQueryFilters;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\Validator;
use LaravelJsonApi\Core\Query\QueryParameters;
use LaravelJsonApi\Validation\Rule as JsonApiRule;
/**
* Class ChartRequest
*/
class ChartRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
use ParsesQueryFilters;
use ValidatesUserGroupTrait;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
public function getParameters(): array
{
$queryParameters = QueryParameters::cast($this->all());
return [
'start' => $this->dateOrToday($queryParameters, 'start'),
'end' => $this->dateOrToday($queryParameters, 'end'),
// preselected heeft maar een paar toegestane waardes.
// 'query' => $this->arrayOfStrings($queryParameters, 'query'),
// 'size' => $this->integerFromQueryParams($queryParameters,'size', 50),
// 'account_types' => $this->getAccountTypeParameter($this->arrayOfStrings($queryParameters, 'account_types')),
];
}
// return [
// 'accounts' => $this->getAccountList(),
// 'preselected' => $this->convertString('preselected'),
// ];
// }
/**
* The rules that the incoming request must be matched against.
*/
public function rules(): array
{
return [
'fields' => JsonApiRule::notSupported(),
'filter' => ['nullable', 'array', new IsValidFilter(['start', 'end', 'preselected', 'accounts'])],
'include' => JsonApiRule::notSupported(),
'page' => JsonApiRule::notSupported(),
'sort' => JsonApiRule::notSupported(),
];
// return [
// 'start' => 'required|date|after:1900-01-01|before:2099-12-31',
// 'end' => 'required|date|after_or_equal:start|before:2099-12-31|after:1900-01-01',
// 'preselected' => sprintf('in:%s', implode(',', config('firefly.preselected_accounts'))),
// 'accounts.*' => 'exists:accounts,id',
// ];
}
public function withValidator(Validator $validator): void
{
$validator->after(
static function (Validator $validator): void {
// validate transaction query data.
$data = $validator->getData();
if (!array_key_exists('accounts', $data)) {
// $validator->errors()->add('accounts', trans('validation.filled', ['attribute' => 'accounts']));
return;
}
if (!is_array($data['accounts'])) {
$validator->errors()->add('accounts', trans('validation.filled', ['attribute' => 'accounts']));
}
}
);
if ($validator->fails()) {
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
}
}
}

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Chart;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
@@ -39,6 +40,8 @@ class DashboardChartRequest extends FormRequest
use ConvertsDataTypes;
use ValidatesUserGroupTrait;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
/**
* Get all data from the request.
*/

View File

@@ -27,6 +27,7 @@ use Carbon\Carbon;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Support\Request\GetFilterInstructions;
use FireflyIII\Support\Request\GetSortInstructions;
use Illuminate\Foundation\Http\FormRequest;
@@ -40,18 +41,16 @@ class IndexRequest extends FormRequest
use AccountFilter;
use ChecksLogin;
use ConvertsDataTypes;
use GetFilterInstructions;
use GetSortInstructions;
public function getAccountTypes(): array
{
$type = (string)$this->get('type', 'default');
$type = (string) $this->get('type', 'default');
return $this->mapAccountTypes($type);
}
/**
* Get all data from the request.
*/
public function getDate(): Carbon
{
return $this->getCarbonDate('date');
@@ -63,7 +62,9 @@ class IndexRequest extends FormRequest
public function rules(): array
{
return [
'date' => 'date|after:1900-01-01|before:2099-12-31',
'date' => 'date|after:1900-01-01|before:2099-12-31',
'start' => 'date|after:1900-01-01|before:2099-12-31|before:end|required_with:end',
'end' => 'date|after:1900-01-01|before:2099-12-31|after:start|required_with:start',
];
}
}

View File

@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V2\Request\UserGroup;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\UserGroup;
use FireflyIII\Rules\IsDefaultUserGroupName;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
@@ -53,7 +54,7 @@ class UpdateRequest extends FormRequest
$userGroup = $this->route()->parameter('userGroup');
return [
'title' => sprintf('required|min:1|max:255|unique:user_groups,title,%d', $userGroup->id),
'title' => ['required', 'min:1', 'max:255', sprintf('unique:user_groups,title,%d', $userGroup->id), new IsDefaultUserGroupName($userGroup)],
];
}
}

View File

@@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Support\Models\AccountBalanceCalculator;
use Illuminate\Console\Command;
/**
* Class CorrectionSkeleton
*/
class CorrectAccountBalance extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Recalculate all account balance amounts';
protected $signature = 'firefly-iii:correct-account-balance';
public function handle(): int
{
$this->correctBalanceAmounts();
return 0;
}
private function correctBalanceAmounts(): void
{
AccountBalanceCalculator::recalculateAll();
}
}

View File

@@ -73,6 +73,8 @@ class CorrectDatabase extends Command
// new!
'firefly-iii:unify-group-accounts',
'firefly-iii:trigger-credit-recalculation',
'firefly-iii:migrate-preferences',
'firefly-iii:correct-account-balance',
];
foreach ($commands as $command) {
$this->friendlyLine(sprintf('Now executing command "%s"', $command));

View File

@@ -50,7 +50,7 @@ class FixFrontpageAccounts extends Command
/** @var User $user */
foreach ($users as $user) {
$preference = app('preferences')->getForUser($user, 'frontPageAccounts');
$preference = app('preferences')->getForUser($user, 'frontpageAccounts');
if (null !== $preference) {
$this->fixPreference($preference);
}
@@ -83,6 +83,6 @@ class FixFrontpageAccounts extends Command
}
}
}
app('preferences')->setForUser($preference->user, 'frontPageAccounts', $fixed);
app('preferences')->setForUser($preference->user, 'frontpageAccounts', $fixed);
}
}

View File

@@ -60,15 +60,13 @@ class FixIbans extends Command
{
/** @var Account $account */
foreach ($accounts as $account) {
$iban = $account->iban;
if (str_contains($iban, ' ')) {
$iban = app('steam')->filterSpaces((string)$account->iban);
if ('' !== $iban) {
$account->iban = $iban;
$account->save();
$this->friendlyInfo(sprintf('Removed spaces from IBAN of account #%d', $account->id));
++$this->count;
}
$iban = (string) $account->iban;
$newIban = app('steam')->filterSpaces($iban);
if ('' !== $iban && $iban !== $newIban) {
$account->iban = $newIban;
$account->save();
$this->friendlyInfo(sprintf('Removed spaces from IBAN of account #%d', $account->id));
++$this->count;
}
}
}
@@ -81,7 +79,7 @@ class FixIbans extends Command
foreach ($accounts as $account) {
$userId = $account->user_id;
$set[$userId] ??= [];
$iban = (string)$account->iban;
$iban = (string) $account->iban;
if ('' === $iban) {
continue;
}

View File

@@ -0,0 +1,66 @@
<?php
declare(strict_types=1);
/*
* MigratePreferences.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Models\Preference;
use FireflyIII\User;
use Illuminate\Console\Command;
use Symfony\Component\Console\Command\Command as CommandAlias;
class MigratePreferences extends Command
{
protected $description = 'Give Firefly III preferences a user group ID so they can be made administration specific.';
protected $signature = 'firefly-iii:migrate-preferences';
/**
* Execute the console command.
*/
public function handle(): int
{
$items = config('firefly.admin_specific_prefs');
$users = User::get();
/** @var User $user */
foreach ($users as $user) {
$count = 0;
foreach ($items as $item) {
$preference = Preference::where('name', $item)->where('user_id', $user->id)->first();
if (null === $preference) {
continue;
}
if (null !== $preference->user_group_id) {
$preference->user_group_id = $user->user_group_id;
$preference->save();
++$count;
}
}
if ($count > 0) {
$this->info(sprintf('Migrated %d preference(s) for user #%d ("%s").', $count, $user->id, $user->email));
}
}
return CommandAlias::SUCCESS;
}
}

View File

@@ -191,7 +191,7 @@ class ExportData extends Command
$this->friendlyError(sprintf('%s date "%s" must be formatted YYYY-MM-DD. Field will be ignored.', $field, $this->option('start')));
$error = true;
}
if (false === $date) {
if (null === $date) {
$this->friendlyError(sprintf('%s date "%s" must be formatted YYYY-MM-DD.', $field, $this->option('start')));
throw new FireflyException(sprintf('%s date "%s" must be formatted YYYY-MM-DD.', $field, $this->option('start')));

View File

@@ -0,0 +1,54 @@
<?php
declare(strict_types=1);
/*
* LaravelPassportKeys.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
namespace FireflyIII\Console\Commands\System;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Artisan;
use Symfony\Component\Console\Command\Command as CommandAlias;
class LaravelPassportKeys extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Calls the Laravel "passport:keys" but doesn\'t exit 1.';
protected $signature = 'firefly-iii:laravel-passport-keys';
/**
* Execute the console command.
*/
public function handle(): int
{
Artisan::call('passport:keys --no-interaction', []);
$result = Artisan::output();
if (str_contains($result, 'Encryption keys already exist')) {
$this->friendlyInfo('Encryption keys exist already.');
return CommandAlias::SUCCESS;
}
$this->friendlyPositive('Encryption keys have been created, nice!');
return CommandAlias::SUCCESS;
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
/*
* ApplyRules.php
* Copyright (c) 2020 james@firefly-iii.org
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@@ -16,7 +16,7 @@
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
@@ -285,7 +285,7 @@ class ApplyRules extends Command
if (null !== $endString && '' !== $endString) {
$inputEnd = Carbon::createFromFormat('Y-m-d', $endString);
}
if (false === $inputEnd || false === $inputStart) {
if (null === $inputEnd || null === $inputStart) {
Log::error('Could not parse start or end date in verifyInputDate().');
return;

View File

@@ -1,8 +1,8 @@
<?php
/**
/*
* Cron.php
* Copyright (c) 2020 james@firefly-iii.org
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@@ -17,7 +17,7 @@
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);

View File

@@ -69,6 +69,7 @@ class UpgradeDatabase extends Command
'firefly-iii:create-group-memberships',
'firefly-iii:upgrade-group-information',
'firefly-iii:upgrade-currency-preferences',
'firefly-iii:correct-database',
];
$args = [];
if ($this->option('force')) {

View File

@@ -0,0 +1,49 @@
<?php
/*
* AccountBalance.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Entities;
use FireflyIII\Models\Account;
class AccountBalance
{
public string $id;
public string $amount;
public string $currencyId;
public static function fromArray(): self
{
$balance = new self();
$balance->id = (string) random_int(1, 1000);
$balance->name = (string) random_int(1, 1000);
$balance->amount = (string) random_int(1, 1000);
$balance->currencyId = '1';
return $balance;
}
public function getAccount(): Account
{
return Account::inRandomOrder()->first();
}
}

View File

@@ -41,7 +41,6 @@ enum UserRoleEnum: string
// manage other financial objects:
case MANAGE_BUDGETS = 'mng_budgets';
case MANAGE_PIGGY_BANKS = 'mng_piggies';
case MANAGE_REPETITIONS = 'mng_reps';
case MANAGE_SUBSCRIPTIONS = 'mng_subscriptions';
case MANAGE_RULES = 'mng_rules';
case MANAGE_RECURRING = 'mng_recurring';
@@ -51,7 +50,7 @@ enum UserRoleEnum: string
// view and generate reports
case VIEW_REPORTS = 'view_reports';
// view memberships. needs FULL to manage them.
// view memberships AND roles. needs FULL to manage them.
case VIEW_MEMBERSHIPS = 'view_memberships';
// everything the creator can, except remove/change original creator and delete group

View File

@@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Exceptions;
use FireflyIII\Jobs\MailError;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Database\QueryException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
@@ -35,6 +36,7 @@ use Illuminate\Session\TokenMismatchException;
use Illuminate\Support\Arr;
use Illuminate\Validation\ValidationException as LaravelValidationException;
use Laravel\Passport\Exceptions\OAuthServerException as LaravelOAuthException;
use LaravelJsonApi\Core\Exceptions\JsonApiException;
use League\OAuth2\Server\Exception\OAuthServerException;
use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;
use Symfony\Component\HttpFoundation\Response;
@@ -62,6 +64,7 @@ class Handler extends ExceptionHandler
HttpException::class,
SuspiciousOperationException::class,
BadHttpHeaderException::class,
JsonApiException::class,
];
/**
@@ -98,6 +101,13 @@ class Handler extends ExceptionHandler
return response()->json(['message' => 'Resource not found', 'exception' => 'NotFoundHttpException'], 404);
}
if ($e instanceof AuthorizationException && $expectsJson) {
// somehow Laravel handler does not catch this:
app('log')->debug('Return JSON unauthorized error.');
return response()->json(['message' => $e->getMessage(), 'exception' => 'AuthorizationException'], 401);
}
if ($e instanceof AuthenticationException && $expectsJson) {
// somehow Laravel handler does not catch this:
app('log')->debug('Return JSON unauthenticated error.');

View File

@@ -405,7 +405,7 @@ class UserEventHandler
}
// clean up old entries (6 months)
$carbon = Carbon::createFromFormat('Y-m-d H:i:s', $preference[$index]['time']);
if (false !== $carbon && $carbon->diffInMonths(today(), true) > 6) {
if (null !== $carbon && $carbon->diffInMonths(today(), true) > 6) {
app('log')->debug(sprintf('Entry for %s is very old, remove it.', $row['ip']));
unset($preference[$index]);
}

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Handlers\Observer;
use FireflyIII\Models\Transaction;
use FireflyIII\Support\Models\AccountBalanceCalculator;
/**
* Class TransactionObserver
@@ -35,4 +36,16 @@ class TransactionObserver
app('log')->debug('Observe "deleting" of a transaction.');
$transaction?->transactionJournal?->delete();
}
public function updated(Transaction $transaction): void
{
app('log')->debug('Observe "updated" of a transaction.');
AccountBalanceCalculator::recalculateForJournal($transaction->transactionJournal);
}
public function created(Transaction $transaction): void
{
app('log')->debug('Observe "created" of a transaction.');
AccountBalanceCalculator::recalculateForJournal($transaction->transactionJournal);
}
}

View File

@@ -145,13 +145,13 @@ class CreateController extends Controller
Log::channel('audit')->info('Stored new account.', $data);
// update preferences if necessary:
$frontPage = app('preferences')->get('frontPageAccounts', [])->data;
if (!is_array($frontPage)) {
$frontPage = [];
$frontpage = app('preferences')->get('frontpageAccounts', [])->data;
if (!is_array($frontpage)) {
$frontpage = [];
}
if (AccountType::ASSET === $account->accountType->type) {
$frontPage[] = $account->id;
app('preferences')->set('frontPageAccounts', $frontPage);
$frontpage[] = $account->id;
app('preferences')->set('frontpageAccounts', $frontpage);
}
// store attachment(s):

View File

@@ -106,7 +106,7 @@ class ShowController extends Controller
$periods = $this->getAccountPeriodOverview($account, $firstTransaction, $end);
// if layout = v2, overrule the page title.
if ('v1' !== config('firefly.layout')) {
if ('v1' !== config('view.layout')) {
$subTitle = (string)trans('firefly.all_journals_for_account', ['name' => $account->name]);
}

View File

@@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Api\V3\Controllers;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\JsonApi\V3\AccountBalances\AccountBalanceSchema;
use FireflyIII\Models\Account;
use Illuminate\Contracts\Support\Responsable;
use LaravelJsonApi\Core\Facades\JsonApi;
use LaravelJsonApi\Core\Responses\DataResponse;
use LaravelJsonApi\Laravel\Http\Controllers\Actions;
use LaravelJsonApi\Laravel\Http\Requests\AnonymousQuery;
class AccountController extends Controller
{
use Actions\AttachRelationship;
use Actions\Destroy;
use Actions\DetachRelationship;
use Actions\FetchMany;
use Actions\FetchOne;
use Actions\FetchRelated;
use Actions\FetchRelationship;
use Actions\Store;
use Actions\Update;
use Actions\UpdateRelationship;
public function readAccountBalances(AnonymousQuery $query, AccountBalanceSchema $schema, Account $account): Responsable
{
$schema = JsonApi::server()->schemas()->schemaFor('account-balances');
$models = $schema
->repository()
->queryAll()
->withRequest($query)
->withAccount($account)
->get()
;
return DataResponse::make($models);
}
}

View File

@@ -31,6 +31,7 @@ use Illuminate\Contracts\View\Factory;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;
/**
@@ -106,6 +107,8 @@ class ForgotPasswordController extends Controller
}
$host = request()->host();
if ($configuredHost !== $host) {
Log::error(sprintf('Host header is "%s", APP_URL is "%s".', $host, $configuredHost));
throw new FireflyException('The Host-header does not match the host in the APP_URL environment variable. Please make sure these match. See also: https://bit.ly/FF3-host-header');
}
}

View File

@@ -128,7 +128,7 @@ class BudgetLimitController extends Controller
$start = Carbon::createFromFormat('Y-m-d', $request->get('start'));
$end = Carbon::createFromFormat('Y-m-d', $request->get('end'));
if (false === $start || false === $end) {
if (null === $start || null === $end) {
return response()->json([]);
}
@@ -235,12 +235,12 @@ class BudgetLimitController extends Controller
new Collection([$budgetLimit->budget]),
$budgetLimit->transactionCurrency
);
$daysLeft = $this->activeDaysLeft($limit->start_date, $limit->end_date);
$array['spent'] = $spentArr[$budgetLimit->transactionCurrency->id]['sum'] ?? '0';
$array['left_formatted'] = app('amount')->formatAnything($limit->transactionCurrency, bcadd($array['spent'], $array['amount']));
$array['amount_formatted'] = app('amount')->formatAnything($limit->transactionCurrency, $limit['amount']);
$array['days_left'] = (string)$this->activeDaysLeft($limit->start_date, $limit->end_date);
// left per day:
$array['left_per_day'] = bcdiv(bcadd($array['spent'], $array['amount']), $array['days_left']);
$array['days_left'] = (string)$daysLeft;
$array['left_per_day'] = 0 === $daysLeft ? bcadd($array['spent'], $array['amount']) : bcdiv(bcadd($array['spent'], $array['amount']), $array['days_left']);
// left per day formatted.
$array['amount'] = app('steam')->bcround($limit['amount'], $limit->transactionCurrency->decimal_places);

View File

@@ -301,14 +301,14 @@ class AccountController extends Controller
$end = clone session('end', today(config('app.timezone'))->endOfMonth());
$defaultSet = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET])->pluck('id')->toArray();
app('log')->debug('Default set is ', $defaultSet);
$frontPage = app('preferences')->get('frontPageAccounts', $defaultSet);
$frontPageArray = !is_array($frontPage->data) ? [] : $frontPage->data;
app('log')->debug('Frontpage preference set is ', $frontPageArray);
if (0 === count($frontPageArray)) {
app('preferences')->set('frontPageAccounts', $defaultSet);
$frontpage = app('preferences')->get('frontpageAccounts', $defaultSet);
$frontpageArray = !is_array($frontpage->data) ? [] : $frontpage->data;
app('log')->debug('Frontpage preference set is ', $frontpageArray);
if (0 === count($frontpageArray)) {
app('preferences')->set('frontpageAccounts', $defaultSet);
app('log')->debug('frontpage set is empty!');
}
$accounts = $repository->getAccountsById($frontPageArray);
$accounts = $repository->getAccountsById($frontpageArray);
return response()->json($this->accountBalanceChart($accounts, $start, $end));
}

View File

@@ -116,8 +116,8 @@ class CategoryController extends Controller
return response()->json($cache->get());
}
$frontPageGenerator = new FrontpageChartGenerator($start, $end);
$chartData = $frontPageGenerator->generate();
$frontpageGenerator = new FrontpageChartGenerator($start, $end);
$chartData = $frontpageGenerator->generate();
$data = $this->generator->multiSet($chartData);
$cache->store($data);

View File

@@ -70,7 +70,7 @@ abstract class Controller extends BaseController
$logoutUrl = config('firefly.custom_logout_url');
// overrule v2 layout back to v1.
if ('true' === request()->get('force_default_layout') && 'v2' === config('firefly.layout')) {
if ('true' === request()->get('force_default_layout') && 'v2' === config('view.layout')) {
app('view')->getFinder()->setPaths([realpath(base_path('resources/views'))]); // @phpstan-ignore-line
}

View File

@@ -86,14 +86,15 @@ class DebugController extends Controller
{
app('preferences')->mark();
$request->session()->forget(['start', 'end', '_previous', 'viewRange', 'range', 'is_custom_range', 'temp-mfa-secret', 'temp-mfa-codes']);
app('log')->debug('Call cache:clear...');
Artisan::call('cache:clear');
app('log')->debug('Call config:clear...');
Artisan::call('config:clear');
app('log')->debug('Call route:clear...');
Artisan::call('route:clear');
app('log')->debug('Call twig:clean...');
Artisan::call('view:clear');
// also do some recalculations.
Artisan::call('firefly-iii:correct-account-balance');
Artisan::call('firefly-iii:trigger-credit-recalculation');
try {
Artisan::call('twig:clean');
@@ -101,7 +102,6 @@ class DebugController extends Controller
throw new FireflyException($e->getMessage(), 0, $e);
}
app('log')->debug('Call view:clear...');
Artisan::call('view:clear');
return redirect(route('index'));

View File

@@ -79,17 +79,17 @@ class HomeController extends Controller
app('log')->error(sprintf('End could not parse date string "%s" so ignore it.', $stringEnd));
$end = Carbon::now()->endOfMonth();
}
if (false === $start) {
if (null === $start) {
$start = Carbon::now()->startOfMonth();
}
if (false === $end) {
if (null === $end) {
$end = Carbon::now()->endOfMonth();
}
$label = $request->get('label');
$isCustomRange = false;
app('log')->debug('Received dateRange', ['start' => $stringStart, 'end' => $stringEnd, 'label' => $request->get('label')]);
app('log')->debug('dateRange: Received dateRange', ['start' => $stringStart, 'end' => $stringEnd, 'label' => $request->get('label')]);
// check if the label is "everything" or "Custom range" which will betray
// a possible problem with the budgets.
if ($label === (string)trans('firefly.everything') || $label === (string)trans('firefly.customRange')) {
@@ -99,7 +99,7 @@ class HomeController extends Controller
$diff = $start->diffInDays($end, true) + 1;
if ($diff > 50) {
if ($diff > 366) {
$request->session()->flash('warning', (string)trans('firefly.warning_much_data', ['days' => (int)$diff]));
}
@@ -120,19 +120,34 @@ class HomeController extends Controller
*/
public function index(AccountRepositoryInterface $repository): mixed
{
$types = config('firefly.accountTypesByIdentifier.asset');
$count = $repository->count($types);
$types = config('firefly.accountTypesByIdentifier.asset');
$count = $repository->count($types);
Log::channel('audit')->info('User visits homepage.');
if (0 === $count) {
return redirect(route('new-user.index'));
}
if ('v1' === (string)config('view.layout')) {
return $this->indexV1($repository);
}
if ('v2' === (string)config('view.layout')) {
return $this->indexV2();
}
throw new FireflyException('Invalid layout configuration');
}
private function indexV1(AccountRepositoryInterface $repository): mixed
{
$types = config('firefly.accountTypesByIdentifier.asset');
$count = $repository->count($types);
$subTitle = (string)trans('firefly.welcome_back');
$transactions = [];
$frontPage = app('preferences')->getFresh('frontPageAccounts', $repository->getAccountsByType([AccountType::ASSET])->pluck('id')->toArray());
$frontPageArray = $frontPage->data;
if (!is_array($frontPageArray)) {
$frontPageArray = [];
$frontpage = app('preferences')->getFresh('frontpageAccounts', $repository->getAccountsByType([AccountType::ASSET])->pluck('id')->toArray());
$frontpageArray = $frontpage->data;
if (!is_array($frontpageArray)) {
$frontpageArray = [];
}
/** @var Carbon $start */
@@ -140,13 +155,11 @@ class HomeController extends Controller
/** @var Carbon $end */
$end = session('end', today(config('app.timezone'))->endOfMonth());
$accounts = $repository->getAccountsById($frontPageArray);
$accounts = $repository->getAccountsById($frontpageArray);
$today = today(config('app.timezone'));
$accounts = $accounts->sortBy('order'); // sort frontpage accounts by order
// sort frontpage accounts by order
$accounts = $accounts->sortBy('order');
app('log')->debug('Frontpage accounts are ', $frontPageArray);
app('log')->debug('Frontpage accounts are ', $frontpageArray);
/** @var BillRepositoryInterface $billRepository */
$billRepository = app(BillRepositoryInterface::class);
@@ -166,4 +179,18 @@ class HomeController extends Controller
return view('index', compact('count', 'subTitle', 'transactions', 'billCount', 'start', 'end', 'today'));
}
private function indexV2(): mixed
{
$subTitle = (string)trans('firefly.welcome_back');
$start = session('start', today(config('app.timezone'))->startOfMonth());
$end = session('end', today(config('app.timezone'))->endOfMonth());
/** @var User $user */
$user = auth()->user();
event(new RequestedVersionCheckStatus($user));
return view('index', compact('subTitle', 'start', 'end'));
}
}

View File

@@ -130,7 +130,7 @@ class BoxController extends Controller
$boxTitle = (string)trans('firefly.left_to_spend');
$activeDaysLeft = $this->activeDaysLeft($start, $end); // see method description.
$display = 1; // not overspent
$leftPerDayAmount = bcdiv($leftToSpendAmount, (string)$activeDaysLeft);
$leftPerDayAmount = 0 === $activeDaysLeft ? $leftToSpendAmount : bcdiv($leftToSpendAmount, (string)$activeDaysLeft);
app('log')->debug(sprintf('Left to spend per day is %s', $leftPerDayAmount));
}
}

View File

@@ -81,7 +81,7 @@ class RecurrenceController extends Controller
$skip = $skip < 0 || $skip > 31 ? 0 : $skip;
$weekend = $weekend < 1 || $weekend > 4 ? 1 : $weekend;
if (false === $start || false === $end || false === $firstDate || false === $endDate) {
if (null === $start || null === $end || null === $firstDate || null === $endDate) {
return response()->json();
}
@@ -112,7 +112,7 @@ class RecurrenceController extends Controller
$actualEnd = clone $end;
if ('until_date' === $endsAt) {
$actualEnd = $endDate ?? clone $end;
$actualEnd = $endDate;
$occurrences = $this->recurring->getOccurrencesInRange($repetition, $actualStart, $actualEnd);
}
if ('times' === $endsAt) {
@@ -155,7 +155,7 @@ class RecurrenceController extends Controller
} catch (InvalidFormatException $e) {
$date = Carbon::today(config('app.timezone'));
}
if (false === $date) {
if (null === $date) {
return response()->json();
}
$date->startOfDay();

View File

@@ -115,7 +115,7 @@ class NewUserController extends Controller
// store frontpage preferences:
$accounts = $this->repository->getAccountsByType([AccountType::ASSET])->pluck('id')->toArray();
app('preferences')->set('frontPageAccounts', $accounts);
app('preferences')->set('frontpageAccounts', $accounts);
// mark.
app('preferences')->mark();

View File

@@ -89,10 +89,10 @@ class PreferencesController extends Controller
/** @var array<int, int> $accountIds */
$accountIds = $accounts->pluck('id')->toArray();
$viewRange = app('navigation')->getViewRange(false);
$frontPageAccountsPref = app('preferences')->get('frontPageAccounts', $accountIds);
$frontPageAccounts = $frontPageAccountsPref->data;
if (!is_array($frontPageAccounts)) {
$frontPageAccounts = $accountIds;
$frontpageAccountsPref = app('preferences')->get('frontpageAccounts', $accountIds);
$frontpageAccounts = $frontpageAccountsPref->data;
if (!is_array($frontpageAccounts)) {
$frontpageAccounts = $accountIds;
}
$language = app('steam')->getLanguage();
$languages = config('firefly.languages');
@@ -128,8 +128,8 @@ class PreferencesController extends Controller
$locales = ['equal' => (string)trans('firefly.equal_to_language')] + $locales;
// an important fallback is that the frontPageAccount array gets refilled automatically
// when it turns up empty.
if (0 === count($frontPageAccounts)) {
$frontPageAccounts = $accountIds;
if (0 === count($frontpageAccounts)) {
$frontpageAccounts = $accountIds;
}
// for the demo user, the slackUrl is automatically emptied.
@@ -139,7 +139,7 @@ class PreferencesController extends Controller
$slackUrl = '';
}
return view('preferences.index', compact('language', 'groupedAccounts', 'isDocker', 'frontPageAccounts', 'languages', 'darkMode', 'availableDarkModes', 'notifications', 'slackUrl', 'locales', 'locale', 'tjOptionalFields', 'viewRange', 'customFiscalYear', 'listPageSize', 'fiscalYearStart'));
return view('preferences.index', compact('language', 'groupedAccounts', 'isDocker', 'frontpageAccounts', 'languages', 'darkMode', 'availableDarkModes', 'notifications', 'slackUrl', 'locales', 'locale', 'tjOptionalFields', 'viewRange', 'customFiscalYear', 'listPageSize', 'fiscalYearStart'));
}
/**
@@ -155,12 +155,12 @@ class PreferencesController extends Controller
public function postIndex(Request $request)
{
// front page accounts
$frontPageAccounts = [];
if (is_array($request->get('frontPageAccounts')) && count($request->get('frontPageAccounts')) > 0) {
foreach ($request->get('frontPageAccounts') as $id) {
$frontPageAccounts[] = (int)$id;
$frontpageAccounts = [];
if (is_array($request->get('frontpageAccounts')) && count($request->get('frontpageAccounts')) > 0) {
foreach ($request->get('frontpageAccounts') as $id) {
$frontpageAccounts[] = (int)$id;
}
app('preferences')->set('frontPageAccounts', $frontPageAccounts);
app('preferences')->set('frontpageAccounts', $frontpageAccounts);
}
// extract notifications:
@@ -223,8 +223,8 @@ class PreferencesController extends Controller
// same for locale:
if (!auth()->user()->hasRole('demo')) {
/** @var Preference $locale */
$locale = $request->get('locale');
$locale = (string) $request->get('locale');
$locale = '' === $locale ? null : $locale;
app('preferences')->set('locale', $locale);
}

View File

@@ -23,7 +23,6 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers;
use Auth;
use FireflyIII\Events\UserChangedEmail;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Exceptions\ValidationException;
@@ -467,9 +466,7 @@ class ProfileController extends Controller
if (is_array($secret)) {
$secret = null;
}
if (is_int($secret)) {
$secret = (string)$secret;
}
$secret = (string)$secret;
$repository->setMFACode($user, $secret);

View File

@@ -0,0 +1,45 @@
<?php
/*
* CreateController.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\UserGroup;
use FireflyIII\Http\Controllers\Controller;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Foundation\Application;
class CreateController extends Controller
{
/**
* @return Application|Factory|\Illuminate\Contracts\Foundation\Application|View
*/
public function create()
{
$title = (string)trans('firefly.administrations_page_title');
$subTitle = (string)trans('firefly.administrations_page_create_sub_title');
$mainTitleIcon = 'fa-book';
app('log')->debug(sprintf('Now at %s', __METHOD__));
return view('administrations.create')->with(compact('title', 'subTitle', 'mainTitleIcon'));
}
}

View File

@@ -0,0 +1,46 @@
<?php
/*
* CreateController.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\UserGroup;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\UserGroup;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Foundation\Application;
class EditController extends Controller
{
/**
* @return Application|Factory|\Illuminate\Contracts\Foundation\Application|View
*/
public function edit(UserGroup $userGroup)
{
$title = (string)trans('firefly.administrations_page_title');
$subTitle = (string)trans('firefly.administrations_page_edit_sub_title', ['title' => $userGroup->title]);
$mainTitleIcon = 'fa-book';
app('log')->debug(sprintf('Now at %s', __METHOD__));
return view('administrations.edit')->with(compact('title', 'subTitle', 'mainTitleIcon'));
}
}

View File

@@ -0,0 +1,47 @@
<?php
/*
* IndexController.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\UserGroup;
use FireflyIII\Http\Controllers\Controller;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\Request;
use Illuminate\View\View;
class IndexController extends Controller
{
/**
* Show all administrations.
*
* @return Factory|View
*/
public function index(Request $request)
{
$title = (string)trans('firefly.administrations_page_title');
$subTitle = (string)trans('firefly.administrations_page_sub_title');
$mainTitleIcon = 'fa-book';
app('log')->debug(sprintf('Now at %s', __METHOD__));
return view('administrations.index')->with(compact('title', 'subTitle', 'mainTitleIcon'));
}
}

View File

@@ -25,6 +25,7 @@ namespace FireflyIII\Http\Middleware;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Vite;
use Barryvdh\Debugbar\Facades\Debugbar;
/**
* Class SecureHeaders
@@ -43,6 +44,9 @@ class SecureHeaders
// generate and share nonce.
$nonce = base64_encode(random_bytes(16));
Vite::useCspNonce($nonce);
if (class_exists('Barryvdh\Debugbar\Facades\Debugbar')) {
Debugbar::getJavascriptRenderer()->setCspNonce($nonce);
}
app('view')->share('JS_NONCE', $nonce);
$response = $next($request);
@@ -55,14 +59,29 @@ class SecureHeaders
"base-uri 'self'",
"font-src 'self' data:",
sprintf("connect-src 'self' %s", $trackingScriptSrc),
sprintf("img-src 'self' 'nonce-%1s'", $nonce),
sprintf("img-src 'self' data: 'nonce-%1s' ", $nonce),
"manifest-src 'self'",
];
// overrule in development mode
if (true === env('IS_LOCAL_DEV')) {
$csp = [
"default-src 'none'",
"object-src 'none'",
sprintf("script-src 'unsafe-eval' 'strict-dynamic' 'nonce-%1s' https://firefly.sd.internal/_debugbar/assets", $nonce),
"style-src 'unsafe-inline' 'self' https://10.0.0.15:5173/",
"base-uri 'self'",
"font-src 'self' data: https://10.0.0.15:5173/",
sprintf("connect-src 'self' %s https://10.0.0.15:5173/ wss://10.0.0.15:5173/", $trackingScriptSrc),
sprintf("img-src 'self' data: 'nonce-%1s'", $nonce),
"manifest-src 'self'",
];
}
$route = $request->route();
$customUrl = '';
$authGuard = (string)config('firefly.authentication_guard');
$logoutUrl = (string)config('firefly.custom_logout_url');
$authGuard = (string) config('firefly.authentication_guard');
$logoutUrl = (string) config('firefly.custom_logout_url');
if ('remote_user_guard' === $authGuard && '' !== $logoutUrl) {
$customUrl = $logoutUrl;
}
@@ -110,8 +129,8 @@ class SecureHeaders
*/
private function getTrackingScriptSource(): string
{
if ('' !== (string)config('firefly.tracker_site_id') && '' !== (string)config('firefly.tracker_url')) {
return (string)config('firefly.tracker_url');
if ('' !== (string) config('firefly.tracker_site_id') && '' !== (string) config('firefly.tracker_url')) {
return (string) config('firefly.tracker_url');
}
return '';

View File

@@ -57,7 +57,7 @@ class AccountFormRequest extends FormRequest
'account_type_name' => $this->convertString('objectType'),
'currency_id' => $this->convertInteger('currency_id'),
'virtual_balance' => $this->convertString('virtual_balance'),
'iban' => $this->convertString('iban'),
'iban' => $this->convertIban('iban'),
'BIC' => $this->convertString('BIC'),
'account_number' => $this->convertString('account_number'),
'account_role' => $this->convertString('account_role'),

View File

@@ -29,6 +29,7 @@ use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Exception\RequestException;
use Illuminate\Bus\Queueable;
@@ -100,7 +101,7 @@ class DownloadExchangeRates implements ShouldQueue
try {
$res = $client->get($url);
} catch (RequestException $e) {
} catch (ConnectException|RequestException $e) {
app('log')->warning(sprintf('Trying to grab "%s" resulted in error "%d".', $url, $e->getMessage()));
return;
@@ -119,7 +120,7 @@ class DownloadExchangeRates implements ShouldQueue
return;
}
$date = Carbon::createFromFormat('Y-m-d', $json['date'], config('app.timezone'));
if (false === $date) {
if (null === $date) {
return;
}
$this->saveRates($currency, $date, $json['rates']);

View File

@@ -27,6 +27,7 @@ use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Message;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Symfony\Component\Mailer\Exception\TransportException;
/**
@@ -68,6 +69,14 @@ class MailError extends Job implements ShouldQueue
$args['user'] = $this->userData;
$args['ip'] = $this->ipAddress;
$args['token'] = config('firefly.ipinfo_token');
// limit number of error mails that can be sent.
if ($this->reachedLimit()) {
Log::info('MailError: reached limit, not sending email.');
return;
}
if ($this->attempts() < 3 && '' !== $email) {
try {
\Mail::send(
@@ -96,4 +105,62 @@ class MailError extends Job implements ShouldQueue
}
}
}
private function reachedLimit(): bool
{
Log::debug('reachedLimit()');
$types = [
'5m' => ['limit' => 5, 'reset' => 5 * 60],
'1h' => ['limit' => 15, 'reset' => 60 * 60],
'24h' => ['limit' => 15, 'reset' => 24 * 60 * 60],
];
$file = storage_path('framework/cache/error-count.json');
$directory = storage_path('framework/cache');
$limits = [];
if (!is_writable($directory)) {
Log::error(sprintf('MailError: cannot write to "%s", cannot rate limit errors!', $directory));
return false;
}
if (!file_exists($file)) {
Log::debug(sprintf('Wrote new file in "%s"', $file));
file_put_contents($file, json_encode($limits, JSON_PRETTY_PRINT));
}
if (file_exists($file)) {
Log::debug(sprintf('Read file in "%s"', $file));
$limits = json_decode((string)file_get_contents($file), true);
}
// limit reached?
foreach ($types as $type => $info) {
Log::debug(sprintf('Now checking limit "%s"', $type), $info);
if (!array_key_exists($type, $limits)) {
Log::debug(sprintf('Limit "%s" reset to zero, did not exist yet.', $type));
$limits[$type] = [
'time' => time(),
'sent' => 0,
];
}
if (time() - $limits[$type]['time'] > $info['reset']) {
Log::debug(sprintf('Time past for this limit is %d seconds, exceeding %d seconds. Reset to zero.', time() - $limits[$type]['time'], $info['reset']));
$limits[$type] = [
'time' => time(),
'sent' => 0,
];
}
if ($limits[$type]['sent'] > $info['limit']) {
Log::warning(sprintf('Sent %d emails in %s, return true.', $limits[$type]['sent'], $type));
return true;
}
++$limits[$type]['sent'];
}
file_put_contents($file, json_encode($limits, JSON_PRETTY_PRINT));
Log::debug('No limits reached, return FALSE.');
return false;
}
}

View File

@@ -128,7 +128,7 @@ class WarnAboutBills implements ShouldQueue
$today = clone $this->date;
$carbon = clone $bill->{$field};
return (int) $today->diffInDays($carbon);
return (int)$today->diffInDays($carbon);
}
private function sendWarning(Bill $bill, string $field): void

View File

@@ -0,0 +1,53 @@
<?php
/*
* IsValidFilter.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\JsonApi\Rules;
use Illuminate\Contracts\Validation\ValidationRule;
class IsValidFilter implements ValidationRule
{
private array $allowed;
public function __construct(array $keys)
{
$this->allowed = $keys;
$this->allowed[] = 'user_group_id';
}
#[\Override]
public function validate(string $attribute, mixed $value, \Closure $fail): void
{
if ('filter' !== $attribute) {
$fail('validation.bad_api_filter')->translate();
}
if (!is_array($value)) {
$value = explode(',', $value);
}
foreach ($value as $key => $val) {
if (!in_array($key, $this->allowed, true)) {
$fail('validation.bad_api_filter')->translate(['filter' => $key]);
}
}
}
}

View File

@@ -0,0 +1,52 @@
<?php
/*
* IsValidFilter.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\JsonApi\Rules;
use Illuminate\Contracts\Validation\ValidationRule;
class IsValidPage implements ValidationRule
{
private array $allowed;
public function __construct(array $keys)
{
$this->allowed = $keys;
}
#[\Override]
public function validate(string $attribute, mixed $value, \Closure $fail): void
{
if ('page' !== $attribute) {
$fail('validation.bad_api_filter')->translate();
}
if (!is_array($value)) {
$value = explode(',', $value);
}
foreach ($value as $key => $val) {
if (!in_array($key, $this->allowed, true)) {
$fail('validation.bad_api_page')->translate();
}
}
}
}

View File

@@ -0,0 +1,45 @@
<?php
/*
* AccountBalanceRepository.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\JsonApi\V3\AccountBalances;
use FireflyIII\Entities\AccountBalance;
use LaravelJsonApi\Contracts\Store\QueriesAll;
use LaravelJsonApi\NonEloquent\AbstractRepository;
class AccountBalanceRepository extends AbstractRepository implements QueriesAll
{
#[\Override]
public function find(string $resourceId): ?object
{
return AccountBalance::fromArray();
}
public function queryAll(): Capabilities\AccountBalanceQuery
{
return Capabilities\AccountBalanceQuery::make()
->withServer($this->server)
->withSchema($this->schema)
;
}
}

View File

@@ -0,0 +1,44 @@
<?php
declare(strict_types=1);
namespace FireflyIII\JsonApi\V3\AccountBalances;
use Illuminate\Http\Request;
use LaravelJsonApi\Core\Resources\JsonApiResource;
class AccountBalanceResource extends JsonApiResource
{
/**
* Get the resource id.
*/
public function id(): string
{
return $this->resource->id;
}
/**
* Get the resource's attributes.
*
* @param null|Request $request
*/
public function attributes($request): iterable
{
return [
'name' => $this->resource->amount,
'amount' => $this->resource->amount,
];
}
/**
* Get the resource's relationships.
*
* @param null|Request $request
*/
public function relationships($request): iterable
{
return [
$this->relation('account')->withData($this->resource->getAccount()),
];
}
}

View File

@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
namespace FireflyIII\JsonApi\V3\AccountBalances;
use FireflyIII\Entities\AccountBalance;
use LaravelJsonApi\Core\Schema\Schema;
use LaravelJsonApi\Eloquent\Fields\Relations\HasOne;
use LaravelJsonApi\NonEloquent\Fields\Attribute;
use LaravelJsonApi\NonEloquent\Fields\ID;
class AccountBalanceSchema extends Schema
{
/**
* The model the schema corresponds to.
*/
public static string $model = AccountBalance::class;
/**
* Get the resource fields.
*/
public function fields(): array
{
return [
ID::make(),
Attribute::make('name'),
Attribute::make('amount'),
HasOne::make('account'),
];
}
/**
* Get the resource filters.
*/
public function filters(): array
{
return [
// Filter::make('id'),
];
}
public function repository(): AccountBalanceRepository
{
return AccountBalanceRepository::make()
->withServer($this->server)
->withSchema($this)
;
}
}

View File

@@ -0,0 +1,58 @@
<?php
/*
* AccountBalanceQuery.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\JsonApi\V3\AccountBalances\Capabilities;
use FireflyIII\Entities\AccountBalance;
use FireflyIII\Models\Account;
use LaravelJsonApi\NonEloquent\Capabilities\QueryAll;
class AccountBalanceQuery extends QueryAll
{
private Account $account;
/**
* QuerySites constructor.
*/
public function __construct()
{
parent::__construct();
}
public function get(): iterable
{
return [
AccountBalance::fromArray(),
AccountBalance::fromArray(),
AccountBalance::fromArray(),
AccountBalance::fromArray(),
];
}
public function withAccount(Account $account): self
{
$this->account = $account;
return $this;
}
}

Some files were not shown because too many files have changed in this diff Show More