mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-08-25 15:08:06 +00:00
Compare commits
219 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
e00addc0b0 | ||
|
da7a2cf0c0 | ||
|
2368788405 | ||
|
f603415931 | ||
|
523fa42998 | ||
|
e449395f3f | ||
|
d8d8002f1e | ||
|
2570ca9573 | ||
|
e5fdc2cbfd | ||
|
0349cdbc1b | ||
|
122f0309a6 | ||
|
09bff5ea4e | ||
|
7ea112c5e7 | ||
|
44df07a5f5 | ||
|
66b0d9d309 | ||
|
6ac3d3e62c | ||
|
925450f84c | ||
|
62f59c6a19 | ||
|
7db21612a0 | ||
|
2c0da2cf26 | ||
|
79484cc194 | ||
|
6f18748c72 | ||
|
577824930f | ||
|
d614519ee7 | ||
|
ae31041f7f | ||
|
62c4d0cf86 | ||
|
c2ddabbad2 | ||
|
458402aaff | ||
|
5c81e98218 | ||
|
37a46b02f4 | ||
|
b3e1ecdd02 | ||
|
1780e6dc61 | ||
|
50f346d092 | ||
|
ccc851090a | ||
|
4605d84cc8 | ||
|
8c7ab50325 | ||
|
908539836b | ||
|
9f71cf966c | ||
|
02ed47c578 | ||
|
1ddbaf0884 | ||
|
d3ed8c6f0f | ||
|
4f1ac2ac6f | ||
|
1e733f4c8b | ||
|
8e2546da9d | ||
|
3a8162d3c5 | ||
|
f7ceb75316 | ||
|
744e193faa | ||
|
12b0e11592 | ||
|
717f3a9e3d | ||
|
b9f0682f04 | ||
|
8792465fd5 | ||
|
6fbf9a119d | ||
|
0dfa21a92e | ||
|
136fe8e8eb | ||
|
d510c4e31d | ||
|
c066bcc4ce | ||
|
c9e7ae1f08 | ||
|
6a9b4f4d55 | ||
|
2b5054b905 | ||
|
0a45a2485b | ||
|
fcc0294d07 | ||
|
ad981c2bf0 | ||
|
75a32b2f94 | ||
|
70b60f756b | ||
|
0d2ae8ae23 | ||
|
8043c86942 | ||
|
4c30a7bc55 | ||
|
f615b9c252 | ||
|
c19b36a391 | ||
|
935634e487 | ||
|
2c3f032a2b | ||
|
7e62b75b12 | ||
|
de57ab0874 | ||
|
6fb4aaecd3 | ||
|
45fdbf5a11 | ||
|
c6615a7b17 | ||
|
0efb3d2dcf | ||
|
b8a58f83ee | ||
|
110228e65e | ||
|
8ad27e0eda | ||
|
2e0d90c685 | ||
|
bd2ecb13b8 | ||
|
5725570dbb | ||
|
11f77685e4 | ||
|
0521c46d27 | ||
|
50d6225590 | ||
|
df55f7de79 | ||
|
5152ae9622 | ||
|
075d0da63d | ||
|
d804df2a2f | ||
|
ff0f8beb81 | ||
|
c00be92f97 | ||
|
88f6221424 | ||
|
f9463e02a2 | ||
|
25a23801be | ||
|
fe7bb02dc5 | ||
|
68edcfc4e8 | ||
|
5f8a24a684 | ||
|
0a5d62605a | ||
|
1873be8d95 | ||
|
01892c3828 | ||
|
b87e60c72f | ||
|
3a083f88b5 | ||
|
566bb2f097 | ||
|
1ba7847d84 | ||
|
c32044a8eb | ||
|
72a2d417af | ||
|
09c18d6d44 | ||
|
84ae6a633e | ||
|
82749cea07 | ||
|
23aa0e3ba3 | ||
|
8be27a2201 | ||
|
ff98f3cc3e | ||
|
01c4d25646 | ||
|
292b9ac9d0 | ||
|
6bdae03961 | ||
|
7426c6aac3 | ||
|
211526c032 | ||
|
e6fe08dd61 | ||
|
7bba67130a | ||
|
7186d8ddfd | ||
|
1a6bc6decd | ||
|
5b11c86113 | ||
|
98b95ab891 | ||
|
c3068d10bf | ||
|
fa1a1b084b | ||
|
387e44b8b9 | ||
|
6dafa89a15 | ||
|
5b5b8008b0 | ||
|
38a955e663 | ||
|
62921df702 | ||
|
c7c2b85882 | ||
|
bc26ee5cde | ||
|
9eca31529c | ||
|
25e3abeeb8 | ||
|
53d6281ba4 | ||
|
4b9fd949ad | ||
|
786b4c18a1 | ||
|
97b65ac44c | ||
|
102da7b21e | ||
|
85bde79fd1 | ||
|
09a25957d0 | ||
|
fd7a2181a4 | ||
|
2ede3b420b | ||
|
4bed30347d | ||
|
ffdcab3220 | ||
|
956108399b | ||
|
61c38f2a99 | ||
|
f3773ebfc2 | ||
|
f963ac63f1 | ||
|
1368aafe5f | ||
|
657262f179 | ||
|
8b9dce70bb | ||
|
30bbd0b3a4 | ||
|
d4488f041b | ||
|
fa8dc1ae4b | ||
|
c2b60edca3 | ||
|
949ca4f79e | ||
|
ab0b03dd14 | ||
|
5b41e58025 | ||
|
88bf76fa27 | ||
|
3ad155882a | ||
|
4747e28621 | ||
|
5664695a92 | ||
|
fdcd31652a | ||
|
e5397b6659 | ||
|
51e5b9a994 | ||
|
dc95632834 | ||
|
3e888382c9 | ||
|
de8d6f8439 | ||
|
60543b8f1d | ||
|
268cec6d08 | ||
|
94aea91927 | ||
|
135a6993aa | ||
|
16079f496a | ||
|
e318e8e9cf | ||
|
51ca8277bb | ||
|
a49cf1fd3d | ||
|
81a11ee5b4 | ||
|
b778424b7e | ||
|
d408d7cc20 | ||
|
228870ceac | ||
|
ae1939cd1b | ||
|
f7a4bd5d12 | ||
|
eec1888f87 | ||
|
a42470e5b4 | ||
|
098f1fe0f6 | ||
|
2e5bc750d1 | ||
|
d777a1f2b8 | ||
|
5178e19cea | ||
|
be8aaa68af | ||
|
1e31a1184a | ||
|
c269be7f07 | ||
|
6bf42ba237 | ||
|
1901648a05 | ||
|
789a6cebcd | ||
|
4230349c07 | ||
|
33b95b9371 | ||
|
e47110607c | ||
|
1e3665e54f | ||
|
47147066d2 | ||
|
5b8f67e992 | ||
|
fb1a66d872 | ||
|
e594b9304a | ||
|
0d7fd36c38 | ||
|
bdba786322 | ||
|
507e0fb54c | ||
|
e4d91aa337 | ||
|
4e6fc8e2a2 | ||
|
244ffb2450 | ||
|
7aa3aef508 | ||
|
c16f7d214f | ||
|
c08d44ea48 | ||
|
6381d04e2b | ||
|
ec43d10e35 | ||
|
b32d9aab34 | ||
|
de5cb4c165 | ||
|
609edb9dff | ||
|
636b3921fa |
27
.ci/all.sh
Executable file
27
.ci/all.sh
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#
|
||||
# all.sh
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
||||
|
||||
$SCRIPT_DIR/phpcs.sh
|
||||
$SCRIPT_DIR/phpstan.sh
|
||||
$SCRIPT_DIR/phpmd.sh
|
@@ -57,7 +57,14 @@ return $config->setRules([
|
||||
'statement_indentation' => true,
|
||||
'type_declaration_spaces' => false,
|
||||
'cast_spaces' => false,
|
||||
'binary_operator_spaces' => false,
|
||||
'binary_operator_spaces' => [
|
||||
'default' => 'at_least_single_space',
|
||||
'operators' => [
|
||||
'=>' => 'align_single_space_by_scope',
|
||||
'=' => 'align_single_space_minimal_by_scope',
|
||||
'??=' => 'align_single_space_minimal_by_scope',
|
||||
],
|
||||
],
|
||||
'void_return' => true,
|
||||
])
|
||||
->setFinder($finder);
|
||||
|
77
.ci/php-cs-fixer/composer.lock
generated
77
.ci/php-cs-fixer/composer.lock
generated
@@ -226,21 +226,22 @@
|
||||
},
|
||||
{
|
||||
"name": "friendsofphp/php-cs-fixer",
|
||||
"version": "v3.42.0",
|
||||
"version": "v3.48.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
|
||||
"reference": "632ef1be3447a9b890bef06147475facee535d0f"
|
||||
"reference": "a92472c6fb66349de25211f31c77eceae3df024e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/632ef1be3447a9b890bef06147475facee535d0f",
|
||||
"reference": "632ef1be3447a9b890bef06147475facee535d0f",
|
||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/a92472c6fb66349de25211f31c77eceae3df024e",
|
||||
"reference": "a92472c6fb66349de25211f31c77eceae3df024e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"composer/semver": "^3.4",
|
||||
"composer/xdebug-handler": "^3.0.3",
|
||||
"ext-filter": "*",
|
||||
"ext-json": "*",
|
||||
"ext-tokenizer": "*",
|
||||
"php": "^7.4 || ^8.0",
|
||||
@@ -265,7 +266,7 @@
|
||||
"php-cs-fixer/accessible-object": "^1.1",
|
||||
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.4",
|
||||
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.4",
|
||||
"phpunit/phpunit": "^9.6",
|
||||
"phpunit/phpunit": "^9.6 || ^10.5.5",
|
||||
"symfony/yaml": "^5.4 || ^6.0 || ^7.0"
|
||||
},
|
||||
"suggest": {
|
||||
@@ -304,7 +305,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
|
||||
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.42.0"
|
||||
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.48.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -312,7 +313,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-12-24T14:38:51+00:00"
|
||||
"time": "2024-01-19T21:44:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
@@ -536,16 +537,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v7.0.1",
|
||||
"version": "v7.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "cdce5c684b2f920bb1343deecdfba356ffad83d5"
|
||||
"reference": "f8587c4cdc5acad67af71c37db34ef03af91e59c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/cdce5c684b2f920bb1343deecdfba356ffad83d5",
|
||||
"reference": "cdce5c684b2f920bb1343deecdfba356ffad83d5",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/f8587c4cdc5acad67af71c37db34ef03af91e59c",
|
||||
"reference": "f8587c4cdc5acad67af71c37db34ef03af91e59c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -609,7 +610,7 @@
|
||||
"terminal"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/v7.0.1"
|
||||
"source": "https://github.com/symfony/console/tree/v7.0.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -625,7 +626,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-12-01T15:10:06+00:00"
|
||||
"time": "2023-12-10T16:54:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
@@ -696,16 +697,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher",
|
||||
"version": "v7.0.0",
|
||||
"version": "v7.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/event-dispatcher.git",
|
||||
"reference": "c459b40ffe67c49af6fd392aac374c9edf8a027e"
|
||||
"reference": "098b62ae81fdd6cbf941f355059f617db28f4f9a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c459b40ffe67c49af6fd392aac374c9edf8a027e",
|
||||
"reference": "c459b40ffe67c49af6fd392aac374c9edf8a027e",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/098b62ae81fdd6cbf941f355059f617db28f4f9a",
|
||||
"reference": "098b62ae81fdd6cbf941f355059f617db28f4f9a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -756,7 +757,7 @@
|
||||
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/event-dispatcher/tree/v7.0.0"
|
||||
"source": "https://github.com/symfony/event-dispatcher/tree/v7.0.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -772,7 +773,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-07-27T16:29:09+00:00"
|
||||
"time": "2023-12-27T22:24:19+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher-contracts",
|
||||
@@ -1538,16 +1539,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
"version": "v7.0.0",
|
||||
"version": "v7.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/process.git",
|
||||
"reference": "13bdb1670c7f510494e04fcb2bfa29af63db9c0d"
|
||||
"reference": "acd3eb5cb02382c1cb0287ba29b2908cc6ffa83a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/13bdb1670c7f510494e04fcb2bfa29af63db9c0d",
|
||||
"reference": "13bdb1670c7f510494e04fcb2bfa29af63db9c0d",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/acd3eb5cb02382c1cb0287ba29b2908cc6ffa83a",
|
||||
"reference": "acd3eb5cb02382c1cb0287ba29b2908cc6ffa83a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1579,7 +1580,7 @@
|
||||
"description": "Executes commands in sub-processes",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/process/tree/v7.0.0"
|
||||
"source": "https://github.com/symfony/process/tree/v7.0.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1595,25 +1596,25 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-11-20T16:43:42+00:00"
|
||||
"time": "2023-12-24T09:15:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/service-contracts",
|
||||
"version": "v3.4.0",
|
||||
"version": "v3.4.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/service-contracts.git",
|
||||
"reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838"
|
||||
"reference": "fe07cbc8d837f60caf7018068e350cc5163681a0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/b3313c2dbffaf71c8de2934e2ea56ed2291a3838",
|
||||
"reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838",
|
||||
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0",
|
||||
"reference": "fe07cbc8d837f60caf7018068e350cc5163681a0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.1",
|
||||
"psr/container": "^2.0"
|
||||
"psr/container": "^1.1|^2.0"
|
||||
},
|
||||
"conflict": {
|
||||
"ext-psr": "<1.1|>=2"
|
||||
@@ -1661,7 +1662,7 @@
|
||||
"standards"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/service-contracts/tree/v3.4.0"
|
||||
"source": "https://github.com/symfony/service-contracts/tree/v3.4.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1677,7 +1678,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-07-30T20:28:31+00:00"
|
||||
"time": "2023-12-26T14:02:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/stopwatch",
|
||||
@@ -1743,16 +1744,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/string",
|
||||
"version": "v7.0.0",
|
||||
"version": "v7.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/string.git",
|
||||
"reference": "92bd2bfbba476d4a1838e5e12168bef2fd1e6620"
|
||||
"reference": "cc78f14f91f5e53b42044d0620961c48028ff9f5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/92bd2bfbba476d4a1838e5e12168bef2fd1e6620",
|
||||
"reference": "92bd2bfbba476d4a1838e5e12168bef2fd1e6620",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/cc78f14f91f5e53b42044d0620961c48028ff9f5",
|
||||
"reference": "cc78f14f91f5e53b42044d0620961c48028ff9f5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1809,7 +1810,7 @@
|
||||
"utf8"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/string/tree/v7.0.0"
|
||||
"source": "https://github.com/symfony/string/tree/v7.0.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1825,7 +1826,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-11-29T08:40:23+00:00"
|
||||
"time": "2023-12-10T16:54:46+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
|
38
.ci/phpmd/composer.lock
generated
38
.ci/phpmd/composer.lock
generated
@@ -470,16 +470,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/dependency-injection",
|
||||
"version": "v7.0.1",
|
||||
"version": "v7.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/dependency-injection.git",
|
||||
"reference": "f6667642954bce638733f254c39e5b5700b47ba4"
|
||||
"reference": "bd25ef7c937b9da12510bdc4f1c66728f19620e3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f6667642954bce638733f254c39e5b5700b47ba4",
|
||||
"reference": "f6667642954bce638733f254c39e5b5700b47ba4",
|
||||
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/bd25ef7c937b9da12510bdc4f1c66728f19620e3",
|
||||
"reference": "bd25ef7c937b9da12510bdc4f1c66728f19620e3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -530,7 +530,7 @@
|
||||
"description": "Allows you to standardize and centralize the way objects are constructed in your application",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/dependency-injection/tree/v7.0.1"
|
||||
"source": "https://github.com/symfony/dependency-injection/tree/v7.0.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -546,7 +546,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-12-01T15:10:06+00:00"
|
||||
"time": "2023-12-28T19:18:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
@@ -845,21 +845,21 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/service-contracts",
|
||||
"version": "v3.4.0",
|
||||
"version": "v3.4.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/service-contracts.git",
|
||||
"reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838"
|
||||
"reference": "fe07cbc8d837f60caf7018068e350cc5163681a0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/b3313c2dbffaf71c8de2934e2ea56ed2291a3838",
|
||||
"reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838",
|
||||
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0",
|
||||
"reference": "fe07cbc8d837f60caf7018068e350cc5163681a0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.1",
|
||||
"psr/container": "^2.0"
|
||||
"psr/container": "^1.1|^2.0"
|
||||
},
|
||||
"conflict": {
|
||||
"ext-psr": "<1.1|>=2"
|
||||
@@ -907,7 +907,7 @@
|
||||
"standards"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/service-contracts/tree/v3.4.0"
|
||||
"source": "https://github.com/symfony/service-contracts/tree/v3.4.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -923,20 +923,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-07-30T20:28:31+00:00"
|
||||
"time": "2023-12-26T14:02:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/var-exporter",
|
||||
"version": "v7.0.1",
|
||||
"version": "v7.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/var-exporter.git",
|
||||
"reference": "a3d7c877414fcd59ab7075ecdc3b8f9c00f7bcc3"
|
||||
"reference": "345c62fefe92243c3a06fc0cc65f2ec1a47e0764"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/var-exporter/zipball/a3d7c877414fcd59ab7075ecdc3b8f9c00f7bcc3",
|
||||
"reference": "a3d7c877414fcd59ab7075ecdc3b8f9c00f7bcc3",
|
||||
"url": "https://api.github.com/repos/symfony/var-exporter/zipball/345c62fefe92243c3a06fc0cc65f2ec1a47e0764",
|
||||
"reference": "345c62fefe92243c3a06fc0cc65f2ec1a47e0764",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -981,7 +981,7 @@
|
||||
"serialize"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/var-exporter/tree/v7.0.1"
|
||||
"source": "https://github.com/symfony/var-exporter/tree/v7.0.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -997,7 +997,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-11-30T11:38:21+00:00"
|
||||
"time": "2023-12-27T08:42:13+00:00"
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
|
10
.env.example
10
.env.example
@@ -78,7 +78,7 @@ PAPERTRAIL_HOST=
|
||||
PAPERTRAIL_PORT=
|
||||
|
||||
# Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III
|
||||
# For other database types, please see the FAQ: https://docs.firefly-iii.org/firefly-iii/faq/self-hosted/#i-want-to-use-sqlite
|
||||
# For other database types, please see the FAQ: https://docs.firefly-iii.org/references/faq/install/#i-want-to-use-sqlite
|
||||
# If you use Docker or similar, you can set these variables from a file by appending them with _FILE
|
||||
# Use "pgsql" for PostgreSQL
|
||||
# Use "mysql" for MySQL and MariaDB.
|
||||
@@ -122,7 +122,7 @@ SESSION_DRIVER=file
|
||||
# If you use Docker or similar, you can set REDIS_HOST_FILE, REDIS_PASSWORD_FILE or
|
||||
# REDIS_PORT_FILE to set the value from a file instead of from an environment variable
|
||||
|
||||
# can be tcp, unix or http
|
||||
# can be tcp or unix. http is not supported
|
||||
REDIS_SCHEME=tcp
|
||||
|
||||
# use only when using 'unix' for REDIS_SCHEME. Leave empty otherwise.
|
||||
@@ -150,7 +150,7 @@ COOKIE_SECURE=false
|
||||
COOKIE_SAMESITE=lax
|
||||
|
||||
# If you want Firefly III to email you, update these settings
|
||||
# For instructions, see: https://docs.firefly-iii.org/firefly-iii/advanced-installation/email/#email
|
||||
# For instructions, see: https://docs.firefly-iii.org/how-to/firefly-iii/advanced/notifications/#email
|
||||
# If you use Docker or similar, you can set these variables from a file by appending them with _FILE
|
||||
MAIL_MAILER=log
|
||||
MAIL_HOST=null
|
||||
@@ -214,7 +214,7 @@ VALID_URL_PROTOCOLS=
|
||||
# - 'web' (default, uses built in DB)
|
||||
# - 'remote_user_guard' for Authelia etc
|
||||
# Read more about these settings in the documentation.
|
||||
# https://docs.firefly-iii.org/firefly-iii/advanced-installation/authentication
|
||||
# https://docs.firefly-iii.org/how-to/firefly-iii/advanced/authentication/
|
||||
#
|
||||
# LDAP is no longer supported :(
|
||||
#
|
||||
@@ -269,7 +269,7 @@ ALLOW_WEBHOOKS=false
|
||||
# 1. Set this token to any 32-character value (this is important!).
|
||||
# 2. Use this token in the cron URL instead of a user's command line token that you can find in /profile
|
||||
#
|
||||
# For more info: https://docs.firefly-iii.org/firefly-iii/advanced-installation/cron/
|
||||
# For more info: https://docs.firefly-iii.org/how-to/firefly-iii/advanced/cron/
|
||||
#
|
||||
# You can set this variable from a file by appending it with _FILE
|
||||
#
|
||||
|
2
.github/ISSUE_TEMPLATE/fr.yml
vendored
2
.github/ISSUE_TEMPLATE/fr.yml
vendored
@@ -8,7 +8,7 @@ body:
|
||||
options:
|
||||
- label: I've read the [support guidelines](https://github.com/firefly-iii/firefly-iii/blob/main/.github/support.md)
|
||||
required: true
|
||||
- label: My request is not listed as [a very good idea, but unfortunately...](https://docs.firefly-iii.org/firefly-iii/more-information/what-its-not/)
|
||||
- label: My request is not listed as [a very good idea, but unfortunately...](https://docs.firefly-iii.org/explanation/more-information/what-its-not/)
|
||||
required: true
|
||||
- label: I've used [the search](https://github.com/firefly-iii/firefly-iii/issues?q=is%3Aissue) and this has not been requested before.
|
||||
required: true
|
||||
|
4
.github/contributing.md
vendored
4
.github/contributing.md
vendored
@@ -1,3 +1,3 @@
|
||||
# [Contributing guidelines](https://docs.firefly-iii.org/firefly-iii/support/#contributing-code)
|
||||
# [Contributing guidelines](https://docs.firefly-iii.org/explanation/support/#contributing-code)
|
||||
|
||||
[Contributing guidelines](https://docs.firefly-iii.org/firefly-iii/support/#contributing-code)
|
||||
[Contributing guidelines](https://docs.firefly-iii.org/explanation/support/#contributing-code)
|
||||
|
48
.github/label-actions.yml
vendored
48
.github/label-actions.yml
vendored
@@ -35,3 +35,51 @@ triage:
|
||||
This issue has been marked as being in triage. The root cause is not known yet, or the issue needs more investigation. You can help by sharing debug information (from `/debug`) if you also have this issue or when you haven't already done so.
|
||||
|
||||
Thank you for your contributions.
|
||||
|
||||
needs-moar-debug:
|
||||
issues:
|
||||
comment: |
|
||||
Hi there! This is an automatic reply. `Share and enjoy`
|
||||
|
||||
To learn more about this issue, please share the output of the `/debug` page of your Firefly III installation.
|
||||
|
||||
If this page is no available due to the issue you have, please make sure you share at least:
|
||||
|
||||
1. Firefly III version
|
||||
2. Docker, self-hosted, or hosted by a third party?
|
||||
3. Operating system and browser
|
||||
|
||||
Thank you for your contributions.
|
||||
unlabel: needs-moar-debug
|
||||
|
||||
|
||||
needs-moar-logs:
|
||||
issues:
|
||||
comment: |
|
||||
Hi there! This is an automatic reply. `Share and enjoy`
|
||||
|
||||
To learn more about this issue, please share the relevant log files from your Firefly III or data importer installation.
|
||||
|
||||
The relevant instructions can be found in the documentation: [How to debug Firefly III?](https://docs.firefly-iii.org/how-to/general/debug/) Once debug mode is activated per these instructions, you can repeat your action and find the logs, depending on your method of installation. All is explained on the page.
|
||||
|
||||
Please share the relevant log lines in your issue, either inline or as an attachment. If you feel the logs contain sensitive information, you may also send them to [james@firefly-iii.org](mailto:james@firefly-iii.org). Without these logs, it may not be possible to properly investigate this issue.
|
||||
|
||||
Thank you for your contributions.
|
||||
unlabel: needs-moar-logs
|
||||
|
||||
v2-layout-issue:
|
||||
issues:
|
||||
comment: |
|
||||
Hi there! This is an automatic reply. `Share and enjoy`
|
||||
|
||||
It seems your issue is about the new v2-layout that is currently in development for Firefly III.
|
||||
|
||||
These issues are collected in [a GitHub discussion](https://github.com/firefly-iii/firefly-iii/issues/8361).
|
||||
|
||||
Please note that the v2 layout is still very much in development.
|
||||
|
||||
Thank you for your contributions.
|
||||
close: true
|
||||
close-reason: completed
|
||||
lock: false
|
||||
unlabel: v2-layout-issue
|
||||
|
2
.github/support.md
vendored
2
.github/support.md
vendored
@@ -27,7 +27,7 @@ Only then [create a new issue](https://github.com/firefly-iii/firefly-iii/issues
|
||||
|
||||
- Issues can be converted into discussions if it's not a bug or feature request.
|
||||
- Features that won't be implemented will be labelled "
|
||||
wontfix". [This isn't personal](https://docs.firefly-iii.org/firefly-iii/about-firefly-iii/what-its-not/).
|
||||
wontfix". [This isn't personal](https://docs.firefly-iii.org/explanation/more-information/what-its-not/).
|
||||
- Issues can be closed if they're duplicates of other issues.
|
||||
- Issues can be closed if the answer is in the FAQ.
|
||||
- Issues will be closed automatically after 14 days.
|
||||
|
2
.github/workflows/cleanup.yml
vendored
2
.github/workflows/cleanup.yml
vendored
@@ -56,7 +56,9 @@ jobs:
|
||||
|
||||
const workflows = [
|
||||
'cleanup.yml',
|
||||
'close-duplicates.yml',
|
||||
'closed-issues.yml',
|
||||
'debug-info-actions.yml',
|
||||
'depsreview.yml',
|
||||
'label-actions.yml',
|
||||
'lock.yml',
|
||||
|
39
.github/workflows/close-duplicates.yml
vendored
Normal file
39
.github/workflows/close-duplicates.yml
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
name: "Issues - Command to close duplicate issues"
|
||||
|
||||
# the workflow to execute on is comments that are newly created
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
checks: read
|
||||
|
||||
jobs:
|
||||
close_duplicates:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: github/command@v1.1.0
|
||||
id: command
|
||||
with:
|
||||
allowed_contexts: "issue"
|
||||
command: ".duplicate"
|
||||
- name: reply
|
||||
if: ${{ steps.command.outputs.continue == 'true' }}
|
||||
run: |
|
||||
|
||||
ISSUE_TITLE=$(gh issue view ${{ steps.command.outputs.params }} --json title --jq '.title')
|
||||
|
||||
gh issue comment "$NUMBER" --body "Hi there!
|
||||
|
||||
This is an automatic reply. \`Share and enjoy\`.
|
||||
|
||||
Your issue is probably a duplicate of issue <span>#</span>${{ steps.command.outputs.params }}: [$ISSUE_TITLE](https://github.com/firefly-iii/firefly-iii/issues/${{ steps.command.outputs.params }}). Please refer to issue #${{ steps.command.outputs.params }} for support.
|
||||
|
||||
You can close this issue now. If you believe this is not in fact a duplicate, please reply and let us know. Otherwise, this issue will be automatically closed in a few days time.
|
||||
|
||||
Thank you for your contributions."
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
NUMBER: ${{ github.event.issue.number }}
|
32
.github/workflows/debug-info-actions.yml
vendored
Normal file
32
.github/workflows/debug-info-actions.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: 'Issues - Respond to hidden commands'
|
||||
|
||||
# the workflow to execute on is comments that are newly created
|
||||
on:
|
||||
issues:
|
||||
types: [opened, edited]
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
# permissions needed for reacting to IssueOps commands on issues and PRs
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
issues: write
|
||||
checks: read
|
||||
|
||||
jobs:
|
||||
respond:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: |
|
||||
ISSUE_BODY=$(gh issue view $NUMBER --json body)
|
||||
if [[ $ISSUE_BODY == *".eOxNZAmyGz6CXMyf"* ]]; then
|
||||
gh issue comment "$NUMBER" --body "$V2_ISSUE_REPLY_BODY"
|
||||
gh issue close "$NUMBER" --reason completed
|
||||
fi
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
NUMBER: ${{ github.event.issue.number }}
|
||||
V2_ISSUE_REPLY_BODY: ${{ secrets.V2_ISSUE_REPLY_BODY }}
|
||||
LABELS: v2-layout-issue
|
2
.github/workflows/label-actions.yml
vendored
2
.github/workflows/label-actions.yml
vendored
@@ -18,4 +18,4 @@ jobs:
|
||||
action:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/label-actions@v3
|
||||
- uses: dessant/label-actions@v4
|
||||
|
4
.github/workflows/lock.yml
vendored
4
.github/workflows/lock.yml
vendored
@@ -15,5 +15,5 @@ jobs:
|
||||
- uses: JC5/lock-threads@main
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
issue-inactive-days: 90
|
||||
pr-inactive-days: 90
|
||||
issue-inactive-days: 7
|
||||
pr-inactive-days: 7
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,6 +1,7 @@
|
||||
/node_modules
|
||||
/storage/*.key
|
||||
/vendor
|
||||
public/hot
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
.env
|
||||
|
@@ -76,10 +76,9 @@ class AccountController extends Controller
|
||||
$types = $data['types'];
|
||||
$query = $data['query'];
|
||||
$date = $data['date'] ?? today(config('app.timezone'));
|
||||
|
||||
$return = [];
|
||||
|
||||
$result = $this->repository->searchAccount((string) $query, $types, $this->parameters->get('limit'));
|
||||
|
||||
// TODO this code is duplicated in the V2 Autocomplete controller, which means this code is due to be deprecated.
|
||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||
|
||||
|
@@ -62,7 +62,6 @@ class TagController extends Controller
|
||||
public function tags(AutocompleteRequest $request): JsonResponse
|
||||
{
|
||||
$data = $request->getData();
|
||||
|
||||
$result = $this->repository->searchTags($data['query'], $this->parameters->get('limit'));
|
||||
$array = [];
|
||||
|
||||
|
@@ -45,6 +45,7 @@ use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use FireflyIII\Services\Internal\Destroy\AccountDestroyService;
|
||||
use FireflyIII\Services\Internal\Destroy\JournalDestroyService;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class DestroyController
|
||||
@@ -175,12 +176,14 @@ class DestroyController extends Controller
|
||||
$count = $account->transactions()->count();
|
||||
if (true === $this->unused && 0 === $count) {
|
||||
app('log')->info(sprintf('Deleted unused account #%d "%s"', $account->id, $account->name));
|
||||
Log::channel('audit')->info(sprintf('Deleted unused account #%d "%s"', $account->id, $account->name));
|
||||
$service->destroy($account, null);
|
||||
|
||||
continue;
|
||||
}
|
||||
if (false === $this->unused) {
|
||||
app('log')->info(sprintf('Deleting account #%d "%s"', $account->id, $account->name));
|
||||
Log::channel('audit')->warning(sprintf('Deleted account #%d "%s"', $account->id, $account->name));
|
||||
$service->destroy($account, null);
|
||||
}
|
||||
}
|
||||
|
@@ -75,28 +75,28 @@ class TagController extends Controller
|
||||
$genericSet = $collector->getExtractedJournals();
|
||||
|
||||
foreach ($genericSet as $journal) {
|
||||
$currencyId = (int)$journal['currency_id'];
|
||||
$foreignCurrencyId = (int)$journal['foreign_currency_id'];
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$foreignCurrencyId = (int) $journal['foreign_currency_id'];
|
||||
|
||||
if (0 !== $currencyId) {
|
||||
$response[$currencyId] ??= [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$currencyId,
|
||||
'currency_id' => (string) $currencyId,
|
||||
'currency_code' => $journal['currency_code'],
|
||||
];
|
||||
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], $journal['amount']);
|
||||
$response[$currencyId]['difference_float'] = (float)$response[$currencyId]['difference']; // float but on purpose.
|
||||
$response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // float but on purpose.
|
||||
}
|
||||
if (0 !== $foreignCurrencyId) {
|
||||
$response[$foreignCurrencyId] ??= [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$foreignCurrencyId,
|
||||
'currency_id' => (string) $foreignCurrencyId,
|
||||
'currency_code' => $journal['foreign_currency_code'],
|
||||
];
|
||||
$response[$foreignCurrencyId]['difference'] = bcadd($response[$foreignCurrencyId]['difference'], $journal['foreign_amount']);
|
||||
$response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference']; // float but on purpose.
|
||||
$response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference']; // float but on purpose.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,8 +130,8 @@ class TagController extends Controller
|
||||
|
||||
/** @var array $journal */
|
||||
foreach ($genericSet as $journal) {
|
||||
$currencyId = (int)$journal['currency_id'];
|
||||
$foreignCurrencyId = (int)$journal['foreign_currency_id'];
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$foreignCurrencyId = (int) $journal['foreign_currency_id'];
|
||||
|
||||
/** @var array $tag */
|
||||
foreach ($journal['tags'] as $tag) {
|
||||
@@ -142,15 +142,15 @@ class TagController extends Controller
|
||||
// on currency ID
|
||||
if (0 !== $currencyId) {
|
||||
$response[$key] ??= [
|
||||
'id' => (string)$tagId,
|
||||
'id' => (string) $tagId,
|
||||
'name' => $tag['name'],
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$currencyId,
|
||||
'currency_id' => (string) $currencyId,
|
||||
'currency_code' => $journal['currency_code'],
|
||||
];
|
||||
$response[$key]['difference'] = bcadd($response[$key]['difference'], $journal['amount']);
|
||||
$response[$key]['difference_float'] = (float)$response[$key]['difference']; // float but on purpose.
|
||||
$response[$key]['difference_float'] = (float) $response[$key]['difference']; // float but on purpose.
|
||||
}
|
||||
|
||||
// on foreign ID
|
||||
@@ -158,11 +158,11 @@ class TagController extends Controller
|
||||
$response[$foreignKey] = $journal[$foreignKey] ?? [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$foreignCurrencyId,
|
||||
'currency_id' => (string) $foreignCurrencyId,
|
||||
'currency_code' => $journal['foreign_currency_code'],
|
||||
];
|
||||
$response[$foreignKey]['difference'] = bcadd($response[$foreignKey]['difference'], $journal['foreign_amount']);
|
||||
$response[$foreignKey]['difference_float'] = (float)$response[$foreignKey]['difference']; // float but on purpose.
|
||||
$response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference']; // float but on purpose.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -29,6 +29,8 @@ use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* Class DestroyController
|
||||
@@ -64,6 +66,12 @@ class DestroyController extends Controller
|
||||
*/
|
||||
public function destroy(Attachment $attachment): JsonResponse
|
||||
{
|
||||
if(true === auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->warning(sprintf('Demo user tries to access attachment API in %s', __METHOD__));
|
||||
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
|
||||
$this->repository->destroy($attachment);
|
||||
app('preferences')->mark();
|
||||
|
||||
|
@@ -33,9 +33,11 @@ use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Response as LaravelResponse;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* Class ShowController
|
||||
@@ -73,6 +75,11 @@ class ShowController extends Controller
|
||||
*/
|
||||
public function download(Attachment $attachment): LaravelResponse
|
||||
{
|
||||
if(true === auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->warning(sprintf('Demo user tries to access attachment API in %s', __METHOD__));
|
||||
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
if (false === $attachment->uploaded) {
|
||||
throw new FireflyException('200000: File has not been uploaded (yet).');
|
||||
}
|
||||
@@ -116,6 +123,12 @@ class ShowController extends Controller
|
||||
*/
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
if(true === auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->warning(sprintf('Demo user tries to access attachment API in %s', __METHOD__));
|
||||
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
|
||||
$manager = $this->getManager();
|
||||
|
||||
// types to get, page size:
|
||||
@@ -148,6 +161,11 @@ class ShowController extends Controller
|
||||
*/
|
||||
public function show(Attachment $attachment): JsonResponse
|
||||
{
|
||||
if(true === auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->warning(sprintf('Demo user tries to access attachment API in %s', __METHOD__));
|
||||
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
$manager = $this->getManager();
|
||||
|
||||
/** @var AttachmentTransformer $transformer */
|
||||
|
@@ -34,7 +34,9 @@ use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use League\Fractal\Resource\Item;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* Class StoreController
|
||||
@@ -72,6 +74,11 @@ class StoreController extends Controller
|
||||
*/
|
||||
public function store(StoreRequest $request): JsonResponse
|
||||
{
|
||||
if(true === auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->warning(sprintf('Demo user tries to access attachment API in %s', __METHOD__));
|
||||
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||
$data = $request->getAll();
|
||||
$attachment = $this->repository->store($data);
|
||||
@@ -91,6 +98,12 @@ class StoreController extends Controller
|
||||
*/
|
||||
public function upload(Request $request, Attachment $attachment): JsonResponse
|
||||
{
|
||||
if(true === auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->warning(sprintf('Demo user tries to access attachment API in %s', __METHOD__));
|
||||
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
|
||||
/** @var AttachmentHelperInterface $helper */
|
||||
$helper = app(AttachmentHelperInterface::class);
|
||||
$body = $request->getContent();
|
||||
|
@@ -31,7 +31,9 @@ use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use League\Fractal\Resource\Item;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* Class UpdateController
|
||||
@@ -67,6 +69,11 @@ class UpdateController extends Controller
|
||||
*/
|
||||
public function update(UpdateRequest $request, Attachment $attachment): JsonResponse
|
||||
{
|
||||
if(true === auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->warning(sprintf('Demo user tries to access attachment API in %s', __METHOD__));
|
||||
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
$data = $request->getAll();
|
||||
$this->repository->update($attachment, $data);
|
||||
$manager = $this->getManager();
|
||||
|
@@ -32,9 +32,11 @@ use FireflyIII\Repositories\Webhook\WebhookRepositoryInterface;
|
||||
use FireflyIII\Transformers\WebhookAttemptTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* Class AttemptController
|
||||
@@ -68,6 +70,12 @@ class AttemptController extends Controller
|
||||
if ($message->webhook_id !== $webhook->id) {
|
||||
throw new FireflyException('200040: Webhook and webhook message are no match');
|
||||
}
|
||||
if(false === config('firefly.allow_webhooks')) {
|
||||
Log::channel('audit')->warning(sprintf('User lists webhook attempts of webhook #%d and message #%d, but webhooks are DISABLED.', $webhook->id, $message->id));
|
||||
|
||||
throw new NotFoundHttpException('Webhooks are not enabled.');
|
||||
}
|
||||
Log::channel('audit')->info(sprintf('User lists webhook attempts of webhook #%d and message #%d.', $webhook->id, $message->id));
|
||||
|
||||
$manager = $this->getManager();
|
||||
$pageSize = $this->parameters->get('limit');
|
||||
@@ -106,6 +114,14 @@ class AttemptController extends Controller
|
||||
throw new FireflyException('200041: Webhook message and webhook attempt are no match');
|
||||
}
|
||||
|
||||
if(false === config('firefly.allow_webhooks')) {
|
||||
Log::channel('audit')->warning(sprintf('User views single webhook attempt #%d of webhook #%d and message #%d, but webhooks are DISABLED', $attempt->id, $webhook->id, $message->id));
|
||||
|
||||
throw new NotFoundHttpException('Webhooks are not enabled.');
|
||||
}
|
||||
|
||||
Log::channel('audit')->info(sprintf('User views single webhook attempt #%d of webhook #%d and message #%d.', $attempt->id, $webhook->id, $message->id));
|
||||
|
||||
$manager = $this->getManager();
|
||||
|
||||
/** @var WebhookAttemptTransformer $transformer */
|
||||
|
@@ -31,6 +31,8 @@ use FireflyIII\Models\WebhookAttempt;
|
||||
use FireflyIII\Models\WebhookMessage;
|
||||
use FireflyIII\Repositories\Webhook\WebhookRepositoryInterface;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* Class DestroyController
|
||||
@@ -60,6 +62,13 @@ class DestroyController extends Controller
|
||||
*/
|
||||
public function destroy(Webhook $webhook): JsonResponse
|
||||
{
|
||||
if(false === config('firefly.allow_webhooks')) {
|
||||
Log::channel('audit')->warning(sprintf('User tries to destroy webhook #%d. but webhooks are DISABLED.', $webhook->id));
|
||||
|
||||
throw new NotFoundHttpException('Webhooks are not enabled.');
|
||||
}
|
||||
|
||||
Log::channel('audit')->info(sprintf('User destroys webhook #%d.', $webhook->id));
|
||||
$this->repository->destroy($webhook);
|
||||
app('preferences')->mark();
|
||||
|
||||
@@ -83,6 +92,14 @@ class DestroyController extends Controller
|
||||
throw new FireflyException('200041: Webhook message and webhook attempt are no match');
|
||||
}
|
||||
|
||||
if (false === config('firefly.allow_webhooks')) {
|
||||
Log::channel('audit')->warning(sprintf('User tries to destroy webhook #%d, message #%d, attempt #%d, but webhooks are DISABLED.', $webhook->id, $message->id, $attempt->id));
|
||||
|
||||
throw new NotFoundHttpException('Webhooks are not enabled.');
|
||||
}
|
||||
|
||||
Log::channel('audit')->info(sprintf('User destroys webhook #%d, message #%d, attempt #%d.', $webhook->id, $message->id, $attempt->id));
|
||||
|
||||
$this->repository->destroyAttempt($attempt);
|
||||
app('preferences')->mark();
|
||||
|
||||
@@ -102,6 +119,14 @@ class DestroyController extends Controller
|
||||
if ($message->webhook_id !== $webhook->id) {
|
||||
throw new FireflyException('200040: Webhook and webhook message are no match');
|
||||
}
|
||||
|
||||
if(false === config('firefly.allow_webhooks')) {
|
||||
Log::channel('audit')->warning(sprintf('User tries to destroy webhook #%d, message #%d, but webhooks are DISABLED.', $webhook->id, $message->id));
|
||||
|
||||
throw new NotFoundHttpException('Webhooks are not enabled.');
|
||||
}
|
||||
Log::channel('audit')->info(sprintf('User destroys webhook #%d, message #%d.', $webhook->id, $message->id));
|
||||
|
||||
$this->repository->destroyMessage($message);
|
||||
app('preferences')->mark();
|
||||
|
||||
|
@@ -31,9 +31,11 @@ use FireflyIII\Repositories\Webhook\WebhookRepositoryInterface;
|
||||
use FireflyIII\Transformers\WebhookMessageTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* Class MessageController
|
||||
@@ -64,6 +66,12 @@ class MessageController extends Controller
|
||||
*/
|
||||
public function index(Webhook $webhook): JsonResponse
|
||||
{
|
||||
if(false === config('firefly.allow_webhooks')) {
|
||||
Log::channel('audit')->warning(sprintf('User tries to view messages of webhook #%d, but webhooks are DISABLED.', $webhook->id));
|
||||
|
||||
throw new NotFoundHttpException('Webhooks are not enabled.');
|
||||
}
|
||||
Log::channel('audit')->info(sprintf('User views messages of webhook #%d.', $webhook->id));
|
||||
$manager = $this->getManager();
|
||||
$pageSize = $this->parameters->get('limit');
|
||||
$collection = $this->repository->getMessages($webhook);
|
||||
@@ -98,6 +106,13 @@ class MessageController extends Controller
|
||||
if ($message->webhook_id !== $webhook->id) {
|
||||
throw new FireflyException('200040: Webhook and webhook message are no match');
|
||||
}
|
||||
if(false === config('firefly.allow_webhooks')) {
|
||||
Log::channel('audit')->warning(sprintf('User tries to view message #%d of webhook #%d, but webhooks are DISABLED.', $message->id, $webhook->id));
|
||||
|
||||
throw new NotFoundHttpException('Webhooks are not enabled.');
|
||||
}
|
||||
|
||||
Log::channel('audit')->info(sprintf('User views message #%d of webhook #%d.', $message->id, $webhook->id));
|
||||
|
||||
$manager = $this->getManager();
|
||||
|
||||
|
@@ -34,9 +34,11 @@ use FireflyIII\Transformers\WebhookTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* Class ShowController
|
||||
@@ -69,6 +71,13 @@ class ShowController extends Controller
|
||||
*/
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
if(false === config('firefly.allow_webhooks')) {
|
||||
Log::channel('audit')->info('User tries to view all webhooks, but webhooks are DISABLED.');
|
||||
|
||||
throw new NotFoundHttpException('Webhooks are not enabled.');
|
||||
}
|
||||
|
||||
Log::channel('audit')->info('User views all webhooks.');
|
||||
$manager = $this->getManager();
|
||||
$collection = $this->repository->all();
|
||||
$pageSize = $this->parameters->get('limit');
|
||||
@@ -97,6 +106,13 @@ class ShowController extends Controller
|
||||
*/
|
||||
public function show(Webhook $webhook): JsonResponse
|
||||
{
|
||||
if(false === config('firefly.allow_webhooks')) {
|
||||
Log::channel('audit')->info(sprintf('User tries to view webhook #%d, but webhooks are DISABLED.', $webhook->id));
|
||||
|
||||
throw new NotFoundHttpException('Webhooks are not enabled.');
|
||||
}
|
||||
|
||||
Log::channel('audit')->info(sprintf('User views webhook #%d.', $webhook->id));
|
||||
$manager = $this->getManager();
|
||||
|
||||
/** @var WebhookTransformer $transformer */
|
||||
@@ -115,7 +131,14 @@ class ShowController extends Controller
|
||||
*/
|
||||
public function triggerTransaction(Webhook $webhook, TransactionGroup $group): JsonResponse
|
||||
{
|
||||
if(false === config('firefly.allow_webhooks')) {
|
||||
Log::channel('audit')->info(sprintf('User tries to trigger webhook #%d on transaction group #%d, but webhooks are DISABLED.', $webhook->id, $group->id));
|
||||
|
||||
throw new NotFoundHttpException('Webhooks are not enabled.');
|
||||
}
|
||||
|
||||
app('log')->debug(sprintf('Now in triggerTransaction(%d, %d)', $webhook->id, $group->id));
|
||||
Log::channel('audit')->info(sprintf('User triggers webhook #%d on transaction group #%d.', $webhook->id, $group->id));
|
||||
|
||||
/** @var MessageGeneratorInterface $engine */
|
||||
$engine = app(MessageGeneratorInterface::class);
|
||||
|
@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Requests\Models\Webhook\CreateRequest;
|
||||
use FireflyIII\Repositories\Webhook\WebhookRepositoryInterface;
|
||||
use FireflyIII\Transformers\WebhookTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use League\Fractal\Resource\Item;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* Class StoreController
|
||||
@@ -58,9 +60,17 @@ class StoreController extends Controller
|
||||
public function store(CreateRequest $request): JsonResponse
|
||||
{
|
||||
$data = $request->getData();
|
||||
if(false === config('firefly.allow_webhooks')) {
|
||||
Log::channel('audit')->info('User tries to store new webhook, but webhooks are DISABLED.', $data);
|
||||
|
||||
throw new NotFoundHttpException('Webhooks are not enabled.');
|
||||
}
|
||||
|
||||
$webhook = $this->repository->store($data);
|
||||
$manager = $this->getManager();
|
||||
|
||||
Log::channel('audit')->info('User stores new webhook', $data);
|
||||
|
||||
/** @var WebhookTransformer $transformer */
|
||||
$transformer = app(WebhookTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
@@ -28,6 +28,8 @@ use FireflyIII\Jobs\SendWebhookMessage;
|
||||
use FireflyIII\Models\Webhook;
|
||||
use FireflyIII\Repositories\Webhook\WebhookRepositoryInterface;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* Class SubmitController
|
||||
@@ -55,6 +57,13 @@ class SubmitController extends Controller
|
||||
*/
|
||||
public function submit(Webhook $webhook): JsonResponse
|
||||
{
|
||||
if(false === config('firefly.allow_webhooks')) {
|
||||
Log::channel('audit')->info(sprintf('User tries to submit webhook #%d, but webhooks are DISABLED.', $webhook->id));
|
||||
|
||||
throw new NotFoundHttpException('Webhooks are not enabled.');
|
||||
}
|
||||
|
||||
Log::channel('audit')->info(sprintf('User submits webhook #%d', $webhook->id));
|
||||
// count messages that can be sent.
|
||||
$messages = $this->repository->getReadyMessages($webhook);
|
||||
if (0 === $messages->count()) {
|
||||
|
@@ -29,7 +29,9 @@ use FireflyIII\Models\Webhook;
|
||||
use FireflyIII\Repositories\Webhook\WebhookRepositoryInterface;
|
||||
use FireflyIII\Transformers\WebhookTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use League\Fractal\Resource\Item;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* Class UpdateController
|
||||
@@ -58,9 +60,17 @@ class UpdateController extends Controller
|
||||
public function update(Webhook $webhook, UpdateRequest $request): JsonResponse
|
||||
{
|
||||
$data = $request->getData();
|
||||
if(false === config('firefly.allow_webhooks')) {
|
||||
Log::channel('audit')->info(sprintf('User tries to update webhook #%d, but webhooks are DISABLED.', $webhook->id), $data);
|
||||
|
||||
throw new NotFoundHttpException('Webhooks are not enabled.');
|
||||
}
|
||||
|
||||
$webhook = $this->repository->update($webhook, $data);
|
||||
$manager = $this->getManager();
|
||||
|
||||
Log::channel('audit')->info(sprintf('User updates webhook #%d', $webhook->id), $data);
|
||||
|
||||
/** @var WebhookTransformer $transformer */
|
||||
$transformer = app(WebhookTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
@@ -28,6 +28,7 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
@@ -59,9 +60,7 @@ class MoveTransactionsRequest extends FormRequest
|
||||
|
||||
/**
|
||||
* Configure the validator instance with special rules for after the basic validation rules.
|
||||
*
|
||||
* @param validator $validator
|
||||
* TODO this is duplicate
|
||||
* TODO this is duplicate.
|
||||
*/
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
@@ -74,6 +73,9 @@ class MoveTransactionsRequest extends FormRequest
|
||||
}
|
||||
}
|
||||
);
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
|
||||
private function validateMove(Validator $validator): void
|
||||
@@ -81,12 +83,12 @@ class MoveTransactionsRequest extends FormRequest
|
||||
$data = $validator->getData();
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$repository->setUser(auth()->user());
|
||||
$original = $repository->find((int)$data['original_account']);
|
||||
$destination = $repository->find((int)$data['destination_account']);
|
||||
$original = $repository->find((int) $data['original_account']);
|
||||
$destination = $repository->find((int) $data['destination_account']);
|
||||
|
||||
// not the same type:
|
||||
if ($original->accountType->type !== $destination->accountType->type) {
|
||||
$validator->errors()->add('title', (string)trans('validation.same_account_type'));
|
||||
$validator->errors()->add('title', (string) trans('validation.same_account_type'));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -96,7 +98,7 @@ class MoveTransactionsRequest extends FormRequest
|
||||
|
||||
// check different scenario's.
|
||||
if (null === $originalCurrency xor null === $destinationCurrency) {
|
||||
$validator->errors()->add('title', (string)trans('validation.same_account_currency'));
|
||||
$validator->errors()->add('title', (string) trans('validation.same_account_currency'));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -105,7 +107,7 @@ class MoveTransactionsRequest extends FormRequest
|
||||
return;
|
||||
}
|
||||
if ($originalCurrency->code !== $destinationCurrency->code) {
|
||||
$validator->errors()->add('title', (string)trans('validation.same_account_currency'));
|
||||
$validator->errors()->add('title', (string) trans('validation.same_account_currency'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use FireflyIII\Validation\Api\Data\Bulk\ValidatesBulkTransactionQuery;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
@@ -72,5 +73,8 @@ class TransactionRequest extends FormRequest
|
||||
$this->validateTransactionQuery($validator);
|
||||
}
|
||||
);
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests\Data;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
@@ -43,9 +44,15 @@ class DateRequest extends FormRequest
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$start = $this->getCarbonDate('start');
|
||||
$end = $this->getCarbonDate('end');
|
||||
if($start->diffInYears($end) > 5) {
|
||||
throw new FireflyException('Date range out of range.');
|
||||
}
|
||||
|
||||
return [
|
||||
'start' => $this->getCarbonDate('start'),
|
||||
'end' => $this->getCarbonDate('end'),
|
||||
'start' => $start,
|
||||
'end' => $end,
|
||||
];
|
||||
}
|
||||
|
||||
|
@@ -71,7 +71,7 @@ class ExportRequest extends FormRequest
|
||||
{
|
||||
return [
|
||||
'type' => 'in:csv',
|
||||
'accounts' => 'min:1|max:65536',
|
||||
'accounts' => 'min:1|max:32768',
|
||||
'start' => 'date|before:end',
|
||||
'end' => 'date|after:start',
|
||||
];
|
||||
|
@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Requests\Models\Account;
|
||||
|
||||
use FireflyIII\Models\Location;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\Rules\IsValidPositiveAmount;
|
||||
use FireflyIII\Rules\UniqueAccountNumber;
|
||||
use FireflyIII\Rules\UniqueIban;
|
||||
use FireflyIII\Support\Request\AppendsLocationData;
|
||||
@@ -100,7 +101,7 @@ class StoreRequest extends FormRequest
|
||||
'type' => 'required|max:1024|min:1|'.sprintf('in:%s', $types),
|
||||
'iban' => ['iban', 'nullable', new UniqueIban(null, $type)],
|
||||
'bic' => 'bic|nullable',
|
||||
'account_number' => ['between:1,255', 'nullable', new UniqueAccountNumber(null, $type)],
|
||||
'account_number' => ['min:1', 'max:255', 'nullable', new UniqueAccountNumber(null, $type)],
|
||||
'opening_balance' => 'numeric|required_with:opening_balance_date|nullable',
|
||||
'opening_balance_date' => 'date|required_with:opening_balance|nullable',
|
||||
'virtual_balance' => 'numeric|nullable',
|
||||
@@ -113,12 +114,12 @@ class StoreRequest extends FormRequest
|
||||
'credit_card_type' => sprintf('nullable|in:%s|required_if:account_role,ccAsset', $ccPaymentTypes),
|
||||
'monthly_payment_date' => 'nullable|date|required_if:account_role,ccAsset|required_if:credit_card_type,monthlyFull',
|
||||
'liability_type' => 'nullable|required_if:type,liability|required_if:type,liabilities|in:loan,debt,mortgage',
|
||||
'liability_amount' => 'required_with:liability_start_date|min:0|numeric|max:1000000000',
|
||||
'liability_amount' => ['required_with:liability_start_date', new IsValidPositiveAmount()],
|
||||
'liability_start_date' => 'required_with:liability_amount|date',
|
||||
'liability_direction' => 'nullable|required_if:type,liability|required_if:type,liabilities|in:credit,debit',
|
||||
'interest' => 'between:0,100|numeric',
|
||||
'interest' => 'min:0|max:100|numeric',
|
||||
'interest_period' => sprintf('nullable|in:%s', implode(',', config('firefly.interest_periods'))),
|
||||
'notes' => 'min:0|max:65536',
|
||||
'notes' => 'min:0|max:32768',
|
||||
];
|
||||
|
||||
return Location::requestRules($rules);
|
||||
|
@@ -91,7 +91,7 @@ class UpdateRequest extends FormRequest
|
||||
'type' => sprintf('in:%s', $types),
|
||||
'iban' => ['iban', 'nullable', new UniqueIban($account, $this->convertString('type'))],
|
||||
'bic' => 'bic|nullable',
|
||||
'account_number' => ['between:1,255', 'nullable', new UniqueAccountNumber($account, $this->convertString('type'))],
|
||||
'account_number' => ['min:1', 'max:255', 'nullable', new UniqueAccountNumber($account, $this->convertString('type'))],
|
||||
'opening_balance' => 'numeric|required_with:opening_balance_date|nullable',
|
||||
'opening_balance_date' => 'date|required_with:opening_balance|nullable',
|
||||
'virtual_balance' => 'numeric|nullable',
|
||||
@@ -105,9 +105,9 @@ class UpdateRequest extends FormRequest
|
||||
'monthly_payment_date' => 'date|nullable|required_if:account_role,ccAsset|required_if:credit_card_type,monthlyFull',
|
||||
'liability_type' => 'required_if:type,liability|in:loan,debt,mortgage',
|
||||
'liability_direction' => 'required_if:type,liability|in:credit,debit',
|
||||
'interest' => 'required_if:type,liability|between:0,100|numeric',
|
||||
'interest' => 'required_if:type,liability|min:0|max:100|numeric',
|
||||
'interest_period' => 'required_if:type,liability|in:daily,monthly,yearly',
|
||||
'notes' => 'min:0|max:65536',
|
||||
'notes' => 'min:0|max:32768',
|
||||
];
|
||||
|
||||
return Location::requestRules($rules);
|
||||
|
@@ -66,9 +66,9 @@ class StoreRequest extends FormRequest
|
||||
$model = $this->convertString('attachable_type');
|
||||
|
||||
return [
|
||||
'filename' => 'required|between:1,255',
|
||||
'title' => 'between:1,255',
|
||||
'notes' => 'between:1,65000',
|
||||
'filename' => 'required|min:1|max:255',
|
||||
'title' => ['min:1', 'max:255'],
|
||||
'notes' => 'min:1|max:32768',
|
||||
'attachable_type' => sprintf('required|in:%s', $models),
|
||||
'attachable_id' => ['required', 'numeric', new IsValidAttachmentModel($model)],
|
||||
];
|
||||
|
@@ -68,9 +68,9 @@ class UpdateRequest extends FormRequest
|
||||
$model = $this->convertString('attachable_type');
|
||||
|
||||
return [
|
||||
'filename' => 'between:1,255',
|
||||
'title' => 'between:1,255',
|
||||
'notes' => 'between:1,65000',
|
||||
'filename' => ['min:1', 'max:255'],
|
||||
'title' => ['min:1', 'max:255'],
|
||||
'notes' => 'min:1|max:32768',
|
||||
'attachable_type' => sprintf('in:%s', $models),
|
||||
'attachable_id' => ['numeric', new IsValidAttachmentModel($model)],
|
||||
];
|
||||
|
@@ -24,9 +24,11 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Requests\Models\AvailableBudget;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Rules\IsValidPositiveAmount;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
@@ -62,7 +64,7 @@ class Request extends FormRequest
|
||||
return [
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
|
||||
'amount' => 'numeric|gt:0',
|
||||
'amount' => ['nullable', new IsValidPositiveAmount()],
|
||||
'start' => 'date',
|
||||
'end' => 'date',
|
||||
];
|
||||
@@ -86,5 +88,8 @@ class Request extends FormRequest
|
||||
}
|
||||
}
|
||||
);
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -25,9 +25,11 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Requests\Models\Bill;
|
||||
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\Rules\IsValidPositiveAmount;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
@@ -71,18 +73,18 @@ class StoreRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'between:1,255|uniqueObjectForUser:bills,name',
|
||||
'amount_min' => 'numeric|gt:0|required',
|
||||
'amount_max' => 'numeric|gt:0|required',
|
||||
'name' => 'min:1|max:255|uniqueObjectForUser:bills,name',
|
||||
'amount_min' => ['required', new IsValidPositiveAmount()],
|
||||
'amount_max' => ['required', new IsValidPositiveAmount()],
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
|
||||
'date' => 'date|required',
|
||||
'end_date' => 'date|after:date',
|
||||
'extension_date' => 'date|after:date',
|
||||
'repeat_freq' => 'in:weekly,monthly,quarterly,half-year,yearly|required',
|
||||
'skip' => 'between:0,31',
|
||||
'skip' => 'min:0|max:31|numeric',
|
||||
'active' => [new IsBoolean()],
|
||||
'notes' => 'between:1,65536',
|
||||
'notes' => 'min:1|max:32768',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -102,5 +104,8 @@ class StoreRequest extends FormRequest
|
||||
}
|
||||
}
|
||||
);
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -26,9 +26,11 @@ namespace FireflyIII\Api\V1\Requests\Models\Bill;
|
||||
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\Rules\IsValidPositiveAmount;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
@@ -74,18 +76,18 @@ class UpdateRequest extends FormRequest
|
||||
$bill = $this->route()->parameter('bill');
|
||||
|
||||
return [
|
||||
'name' => sprintf('between:1,255|uniqueObjectForUser:bills,name,%d', $bill->id),
|
||||
'amount_min' => 'numeric|gt:0',
|
||||
'amount_max' => 'numeric|gt:0',
|
||||
'name' => sprintf('min:1|max:255|uniqueObjectForUser:bills,name,%d', $bill->id),
|
||||
'amount_min' => ['nullable', new IsValidPositiveAmount()],
|
||||
'amount_max' => ['nullable', new IsValidPositiveAmount()],
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
|
||||
'date' => 'date',
|
||||
'end_date' => 'date|after:date',
|
||||
'extension_date' => 'date|after:date',
|
||||
'repeat_freq' => 'in:weekly,monthly,quarterly,half-year,yearly',
|
||||
'skip' => 'between:0,31',
|
||||
'skip' => 'min:0|max:31|numeric',
|
||||
'active' => [new IsBoolean()],
|
||||
'notes' => 'between:1,65536',
|
||||
'notes' => 'min:1|max:32768',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -107,5 +109,8 @@ class UpdateRequest extends FormRequest
|
||||
}
|
||||
}
|
||||
);
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -24,10 +24,12 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Requests\Models\Budget;
|
||||
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\Rules\IsValidPositiveAmount;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use FireflyIII\Validation\AutoBudget\ValidatesAutoBudgetRequest;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
@@ -67,14 +69,14 @@ class StoreRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'required|between:1,100|uniqueObjectForUser:budgets,name',
|
||||
'name' => 'required|min:1|max:255|uniqueObjectForUser:budgets,name',
|
||||
'active' => [new IsBoolean()],
|
||||
'currency_id' => 'exists:transaction_currencies,id',
|
||||
'currency_code' => 'exists:transaction_currencies,code',
|
||||
'notes' => 'nullable|between:1,65536',
|
||||
'notes' => 'nullable|min:1|max:32768',
|
||||
// auto budget info
|
||||
'auto_budget_type' => 'in:reset,rollover,adjusted,none',
|
||||
'auto_budget_amount' => 'numeric|min:0|max:1000000000|required_if:auto_budget_type,reset|required_if:auto_budget_type,rollover|required_if:auto_budget_type,adjusted',
|
||||
'auto_budget_amount' => ['required_if:auto_budget_type,reset', 'required_if:auto_budget_type,rollover', 'required_if:auto_budget_type,adjusted', new IsValidPositiveAmount()],
|
||||
'auto_budget_period' => 'in:daily,weekly,monthly,quarterly,half_year,yearly|required_if:auto_budget_type,reset|required_if:auto_budget_type,rollover|required_if:auto_budget_type,adjusted',
|
||||
];
|
||||
}
|
||||
@@ -90,5 +92,8 @@ class StoreRequest extends FormRequest
|
||||
$this->validateAutoBudgetAmount($validator);
|
||||
}
|
||||
);
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -25,10 +25,12 @@ namespace FireflyIII\Api\V1\Requests\Models\Budget;
|
||||
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\Rules\IsValidPositiveAmount;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use FireflyIII\Validation\AutoBudget\ValidatesAutoBudgetRequest;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
@@ -80,13 +82,13 @@ class UpdateRequest extends FormRequest
|
||||
$budget = $this->route()->parameter('budget');
|
||||
|
||||
return [
|
||||
'name' => sprintf('between:1,100|uniqueObjectForUser:budgets,name,%d', $budget->id),
|
||||
'name' => sprintf('min:1|max:100|uniqueObjectForUser:budgets,name,%d', $budget->id),
|
||||
'active' => [new IsBoolean()],
|
||||
'notes' => 'nullable|between:1,65536',
|
||||
'notes' => 'nullable|min:1|max:32768',
|
||||
'auto_budget_type' => 'in:reset,rollover,adjusted,none',
|
||||
'auto_budget_currency_id' => 'exists:transaction_currencies,id',
|
||||
'auto_budget_currency_code' => 'exists:transaction_currencies,code',
|
||||
'auto_budget_amount' => 'min:0|max:1000000000',
|
||||
'auto_budget_amount' => ['nullable', new IsValidPositiveAmount()],
|
||||
'auto_budget_period' => 'in:daily,weekly,monthly,quarterly,half_year,yearly',
|
||||
];
|
||||
}
|
||||
@@ -102,5 +104,8 @@ class UpdateRequest extends FormRequest
|
||||
$this->validateAutoBudgetAmount($validator);
|
||||
}
|
||||
);
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests\Models\BudgetLimit;
|
||||
|
||||
use FireflyIII\Rules\IsValidPositiveAmount;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
@@ -57,7 +58,7 @@ class StoreRequest extends FormRequest
|
||||
return [
|
||||
'start' => 'required|before:end|date',
|
||||
'end' => 'required|after:start|date',
|
||||
'amount' => 'required|gt:0',
|
||||
'amount' => ['required', new IsValidPositiveAmount()],
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
|
||||
];
|
||||
|
@@ -24,9 +24,11 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Requests\Models\BudgetLimit;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Rules\IsValidPositiveAmount;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
@@ -61,7 +63,7 @@ class UpdateRequest extends FormRequest
|
||||
return [
|
||||
'start' => 'date',
|
||||
'end' => 'date',
|
||||
'amount' => 'gt:0',
|
||||
'amount' => ['nullable', new IsValidPositiveAmount()],
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
|
||||
];
|
||||
@@ -69,9 +71,7 @@ class UpdateRequest extends FormRequest
|
||||
|
||||
/**
|
||||
* Configure the validator instance with special rules for after the basic validation rules.
|
||||
*
|
||||
* @param Validator $validator
|
||||
* TODO duplicate code
|
||||
* TODO duplicate code.
|
||||
*/
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
@@ -83,10 +83,13 @@ class UpdateRequest extends FormRequest
|
||||
$start = new Carbon($data['start']);
|
||||
$end = new Carbon($data['end']);
|
||||
if ($end->isBefore($start)) {
|
||||
$validator->errors()->add('end', (string)trans('validation.date_after'));
|
||||
$validator->errors()->add('end', (string) trans('validation.date_after'));
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -52,7 +52,7 @@ class StoreRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'required|between:1,100|uniqueObjectForUser:categories,name',
|
||||
'name' => 'required|min:1|max:100|uniqueObjectForUser:categories,name',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -58,7 +58,7 @@ class UpdateRequest extends FormRequest
|
||||
$category = $this->route()->parameter('category');
|
||||
|
||||
return [
|
||||
'name' => sprintf('between:1,100|uniqueObjectForUser:categories,name,%d', $category->id),
|
||||
'name' => sprintf('min:1|max:100|uniqueObjectForUser:categories,name,%d', $category->id),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests\Models\PiggyBank;
|
||||
|
||||
use FireflyIII\Rules\IsValidPositiveAmount;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
@@ -63,12 +64,12 @@ class StoreRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'required|between:1,255|uniquePiggyBankForUser',
|
||||
'current_amount' => ['numeric', 'gte:0', 'lte:target_amount'],
|
||||
'name' => 'required|min:1|max:255|uniquePiggyBankForUser',
|
||||
'current_amount' => ['nullable', new IsValidPositiveAmount()],
|
||||
'account_id' => 'required|numeric|belongsToUser:accounts,id',
|
||||
'object_group_id' => 'numeric|belongsToUser:object_groups,id',
|
||||
'object_group_title' => 'between:1,255',
|
||||
'target_amount' => ['numeric', 'gte:0', 'lte:target_amount', 'required'],
|
||||
'object_group_title' => ['min:1', 'max:255'],
|
||||
'target_amount' => ['required', new IsValidPositiveAmount()],
|
||||
'start_date' => 'date|nullable',
|
||||
'target_date' => 'date|nullable|after:start_date',
|
||||
'notes' => 'max:65000',
|
||||
|
@@ -25,6 +25,7 @@ namespace FireflyIII\Api\V1\Requests\Models\PiggyBank;
|
||||
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Rules\IsAssetAccountId;
|
||||
use FireflyIII\Rules\IsValidPositiveAmount;
|
||||
use FireflyIII\Rules\LessThanPiggyTarget;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
@@ -68,9 +69,9 @@ class UpdateRequest extends FormRequest
|
||||
$piggyBank = $this->route()->parameter('piggyBank');
|
||||
|
||||
return [
|
||||
'name' => 'between:1,255|uniquePiggyBankForUser:'.$piggyBank->id,
|
||||
'current_amount' => ['numeric', 'gte:0', new LessThanPiggyTarget()],
|
||||
'target_amount' => 'numeric|gte:0',
|
||||
'name' => 'min:1|max:255|uniquePiggyBankForUser:'.$piggyBank->id,
|
||||
'current_amount' => ['nullable', new LessThanPiggyTarget(), new IsValidPositiveAmount()],
|
||||
'target_amount' => ['nullable', new IsValidPositiveAmount()],
|
||||
'start_date' => 'date|nullable',
|
||||
'target_date' => 'date|nullable|after:start_date',
|
||||
'notes' => 'max:65000',
|
||||
|
@@ -25,6 +25,7 @@ namespace FireflyIII\Api\V1\Requests\Models\Recurrence;
|
||||
|
||||
use FireflyIII\Rules\BelongsUser;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\Rules\IsValidPositiveAmount;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use FireflyIII\Support\Request\GetRecurrenceData;
|
||||
@@ -32,6 +33,7 @@ use FireflyIII\Validation\CurrencyValidation;
|
||||
use FireflyIII\Validation\RecurrenceValidation;
|
||||
use FireflyIII\Validation\TransactionValidation;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
@@ -78,39 +80,39 @@ class StoreRequest extends FormRequest
|
||||
{
|
||||
return [
|
||||
'type' => 'required|in:withdrawal,transfer,deposit',
|
||||
'title' => 'required|between:1,255|uniqueObjectForUser:recurrences,title',
|
||||
'description' => 'between:1,65000',
|
||||
'title' => 'required|min:1|max:255|uniqueObjectForUser:recurrences,title',
|
||||
'description' => 'min:1|max:32768',
|
||||
'first_date' => 'required|date',
|
||||
'apply_rules' => [new IsBoolean()],
|
||||
'active' => [new IsBoolean()],
|
||||
'repeat_until' => 'nullable|date',
|
||||
'nr_of_repetitions' => 'nullable|numeric|between:1,31',
|
||||
'nr_of_repetitions' => 'nullable|numeric|min:1|max:31',
|
||||
|
||||
'repetitions.*.type' => 'required|in:daily,weekly,ndom,monthly,yearly',
|
||||
'repetitions.*.moment' => 'between:0,10',
|
||||
'repetitions.*.skip' => 'nullable|numeric|between:0,31',
|
||||
'repetitions.*.moment' => 'min:0|max:10',
|
||||
'repetitions.*.skip' => 'nullable|numeric|min:0|max:31',
|
||||
'repetitions.*.weekend' => 'numeric|min:1|max:4',
|
||||
|
||||
'transactions.*.description' => 'required|between:1,255',
|
||||
'transactions.*.amount' => 'required|numeric|gt:0',
|
||||
'transactions.*.foreign_amount' => 'nullable|numeric|gt:0',
|
||||
'transactions.*.description' => 'required|min:1|max:255',
|
||||
'transactions.*.amount' => ['required', new IsValidPositiveAmount()],
|
||||
'transactions.*.foreign_amount' => ['nullable', new IsValidPositiveAmount()],
|
||||
'transactions.*.currency_id' => 'nullable|numeric|exists:transaction_currencies,id',
|
||||
'transactions.*.currency_code' => 'nullable|min:3|max:51|exists:transaction_currencies,code',
|
||||
'transactions.*.foreign_currency_id' => 'nullable|numeric|exists:transaction_currencies,id',
|
||||
'transactions.*.foreign_currency_code' => 'nullable|min:3|max:51|exists:transaction_currencies,code',
|
||||
'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser()],
|
||||
'transactions.*.source_name' => 'between:1,255|nullable',
|
||||
'transactions.*.source_name' => 'min:1|max:255|nullable',
|
||||
'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser()],
|
||||
'transactions.*.destination_name' => 'between:1,255|nullable',
|
||||
'transactions.*.destination_name' => 'min:1|max:255|nullable',
|
||||
|
||||
// new and updated fields:
|
||||
'transactions.*.budget_id' => ['nullable', 'mustExist:budgets,id', new BelongsUser()],
|
||||
'transactions.*.budget_name' => ['between:1,255', 'nullable', new BelongsUser()],
|
||||
'transactions.*.budget_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()],
|
||||
'transactions.*.category_id' => ['nullable', 'mustExist:categories,id', new BelongsUser()],
|
||||
'transactions.*.category_name' => 'between:1,255|nullable',
|
||||
'transactions.*.category_name' => 'min:1|max:255|nullable',
|
||||
'transactions.*.piggy_bank_id' => ['nullable', 'numeric', 'mustExist:piggy_banks,id', new BelongsUser()],
|
||||
'transactions.*.piggy_bank_name' => ['between:1,255', 'nullable', new BelongsUser()],
|
||||
'transactions.*.tags' => 'nullable|between:1,64000',
|
||||
'transactions.*.piggy_bank_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()],
|
||||
'transactions.*.tags' => 'nullable|min:1|max:255',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -130,6 +132,9 @@ class StoreRequest extends FormRequest
|
||||
$this->validateAccountInformation($validator);
|
||||
}
|
||||
);
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Requests\Models\Recurrence;
|
||||
use FireflyIII\Models\Recurrence;
|
||||
use FireflyIII\Rules\BelongsUser;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\Rules\IsValidPositiveAmount;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use FireflyIII\Support\Request\GetRecurrenceData;
|
||||
@@ -33,6 +34,7 @@ use FireflyIII\Validation\CurrencyValidation;
|
||||
use FireflyIII\Validation\RecurrenceValidation;
|
||||
use FireflyIII\Validation\TransactionValidation;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
@@ -85,39 +87,39 @@ class UpdateRequest extends FormRequest
|
||||
$recurrence = $this->route()->parameter('recurrence');
|
||||
|
||||
return [
|
||||
'title' => sprintf('between:1,255|uniqueObjectForUser:recurrences,title,%d', $recurrence->id),
|
||||
'description' => 'between:1,65000',
|
||||
'title' => sprintf('min:1|max:255|uniqueObjectForUser:recurrences,title,%d', $recurrence->id),
|
||||
'description' => 'min:1|max:32768',
|
||||
'first_date' => 'date',
|
||||
'apply_rules' => [new IsBoolean()],
|
||||
'active' => [new IsBoolean()],
|
||||
'repeat_until' => 'nullable|date',
|
||||
'nr_of_repetitions' => 'nullable|numeric|between:1,31',
|
||||
'nr_of_repetitions' => 'nullable|numeric|min:1|max:31',
|
||||
|
||||
'repetitions.*.type' => 'in:daily,weekly,ndom,monthly,yearly',
|
||||
'repetitions.*.moment' => 'between:0,10',
|
||||
'repetitions.*.skip' => 'nullable|numeric|between:0,31',
|
||||
'repetitions.*.moment' => 'min:0|max:10|numeric',
|
||||
'repetitions.*.skip' => 'nullable|numeric|min:0|max:31',
|
||||
'repetitions.*.weekend' => 'nullable|numeric|min:1|max:4',
|
||||
|
||||
'transactions.*.description' => 'between:1,255',
|
||||
'transactions.*.amount' => 'numeric|gt:0',
|
||||
'transactions.*.foreign_amount' => 'nullable|numeric|gt:0',
|
||||
'transactions.*.description' => ['min:1', 'max:255'],
|
||||
'transactions.*.amount' => [new IsValidPositiveAmount()],
|
||||
'transactions.*.foreign_amount' => ['nullable', new IsValidPositiveAmount()],
|
||||
'transactions.*.currency_id' => 'nullable|numeric|exists:transaction_currencies,id',
|
||||
'transactions.*.currency_code' => 'nullable|min:3|max:51|exists:transaction_currencies,code',
|
||||
'transactions.*.foreign_currency_id' => 'nullable|numeric|exists:transaction_currencies,id',
|
||||
'transactions.*.foreign_currency_code' => 'nullable|min:3|max:51|exists:transaction_currencies,code',
|
||||
'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser()],
|
||||
'transactions.*.source_name' => 'between:1,255|nullable',
|
||||
'transactions.*.source_name' => 'min:1|max:255|nullable',
|
||||
'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser()],
|
||||
'transactions.*.destination_name' => 'between:1,255|nullable',
|
||||
'transactions.*.destination_name' => 'min:1|max:255|nullable',
|
||||
|
||||
// new and updated fields:
|
||||
'transactions.*.budget_id' => ['nullable', 'mustExist:budgets,id', new BelongsUser()],
|
||||
'transactions.*.budget_name' => ['between:1,255', 'nullable', new BelongsUser()],
|
||||
'transactions.*.budget_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()],
|
||||
'transactions.*.category_id' => ['nullable', 'mustExist:categories,id', new BelongsUser()],
|
||||
'transactions.*.category_name' => 'between:1,255|nullable',
|
||||
'transactions.*.category_name' => 'min:1|max:255|nullable',
|
||||
'transactions.*.piggy_bank_id' => ['nullable', 'numeric', 'mustExist:piggy_banks,id', new BelongsUser()],
|
||||
'transactions.*.piggy_bank_name' => ['between:1,255', 'nullable', new BelongsUser()],
|
||||
'transactions.*.tags' => 'nullable|between:1,64000',
|
||||
'transactions.*.piggy_bank_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()],
|
||||
'transactions.*.tags' => 'nullable|min:1|max:255',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -140,6 +142,9 @@ class UpdateRequest extends FormRequest
|
||||
$this->valUpdateAccountInfo($validator);
|
||||
}
|
||||
);
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -164,15 +169,15 @@ class UpdateRequest extends FormRequest
|
||||
}
|
||||
|
||||
if (array_key_exists('moment', $repetition)) {
|
||||
$current['moment'] = (string)$repetition['moment'];
|
||||
$current['moment'] = (string) $repetition['moment'];
|
||||
}
|
||||
|
||||
if (array_key_exists('skip', $repetition)) {
|
||||
$current['skip'] = (int)$repetition['skip'];
|
||||
$current['skip'] = (int) $repetition['skip'];
|
||||
}
|
||||
|
||||
if (array_key_exists('weekend', $repetition)) {
|
||||
$current['weekend'] = (int)$repetition['weekend'];
|
||||
$current['weekend'] = (int) $repetition['weekend'];
|
||||
}
|
||||
$return[] = $current;
|
||||
}
|
||||
|
@@ -28,6 +28,7 @@ use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use FireflyIII\Support\Request\GetRuleConfiguration;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
@@ -76,10 +77,10 @@ class StoreRequest extends FormRequest
|
||||
$contextActions = implode(',', config('firefly.context-rule-actions'));
|
||||
|
||||
return [
|
||||
'title' => 'required|between:1,100|uniqueObjectForUser:rules,title',
|
||||
'description' => 'between:1,5000|nullable',
|
||||
'title' => 'required|min:1|max:100|uniqueObjectForUser:rules,title',
|
||||
'description' => 'min:1|max:32768|nullable',
|
||||
'rule_group_id' => 'belongsToUser:rule_groups|required_without:rule_group_title',
|
||||
'rule_group_title' => 'nullable|between:1,255|required_without:rule_group_id|belongsToUser:rule_groups,title',
|
||||
'rule_group_title' => 'nullable|min:1|max:255|required_without:rule_group_id|belongsToUser:rule_groups,title',
|
||||
'trigger' => 'required|in:store-journal,update-journal',
|
||||
'triggers.*.type' => 'required|in:'.implode(',', $validTriggers),
|
||||
'triggers.*.value' => 'required_if:actions.*.type,'.$contextTriggers.'|min:1|ruleTriggerValue|max:1024',
|
||||
@@ -108,6 +109,9 @@ class StoreRequest extends FormRequest
|
||||
$this->atLeastOneActiveAction($validator);
|
||||
}
|
||||
);
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -29,6 +29,7 @@ use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use FireflyIII\Support\Request\GetRuleConfiguration;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
@@ -85,10 +86,10 @@ class UpdateRequest extends FormRequest
|
||||
$contextActions = implode(',', config('firefly.context-rule-actions'));
|
||||
|
||||
return [
|
||||
'title' => sprintf('between:1,100|uniqueObjectForUser:rules,title,%d', $rule->id),
|
||||
'description' => 'between:1,5000|nullable',
|
||||
'title' => sprintf('min:1|max:100|uniqueObjectForUser:rules,title,%d', $rule->id),
|
||||
'description' => 'min:1|max:32768|nullable',
|
||||
'rule_group_id' => 'belongsToUser:rule_groups',
|
||||
'rule_group_title' => 'nullable|between:1,255|belongsToUser:rule_groups,title',
|
||||
'rule_group_title' => 'nullable|min:1|max:255|belongsToUser:rule_groups,title',
|
||||
'trigger' => 'in:store-journal,update-journal',
|
||||
'triggers.*.type' => 'required|in:'.implode(',', $validTriggers),
|
||||
'triggers.*.value' => 'required_if:actions.*.type,'.$contextTriggers.'|min:1|ruleTriggerValue|max:1024',
|
||||
@@ -101,7 +102,7 @@ class UpdateRequest extends FormRequest
|
||||
'strict' => [new IsBoolean()],
|
||||
'stop_processing' => [new IsBoolean()],
|
||||
'active' => [new IsBoolean()],
|
||||
'order' => 'numeric|between:1,1337',
|
||||
'order' => 'numeric|min:1|max:2048',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -118,6 +119,9 @@ class UpdateRequest extends FormRequest
|
||||
$this->atLeastOneValidAction($validator);
|
||||
}
|
||||
);
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -64,8 +64,8 @@ class StoreRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'title' => 'required|between:1,100|uniqueObjectForUser:rule_groups,title',
|
||||
'description' => 'between:1,5000|nullable',
|
||||
'title' => 'required|min:1|max:100|uniqueObjectForUser:rule_groups,title',
|
||||
'description' => 'min:1|max:32768|nullable',
|
||||
'active' => [new IsBoolean()],
|
||||
];
|
||||
}
|
||||
|
@@ -62,8 +62,8 @@ class UpdateRequest extends FormRequest
|
||||
$ruleGroup = $this->route()->parameter('ruleGroup');
|
||||
|
||||
return [
|
||||
'title' => 'between:1,100|uniqueObjectForUser:rule_groups,title,'.$ruleGroup->id,
|
||||
'description' => 'between:1,5000|nullable',
|
||||
'title' => 'min:1|max:100|uniqueObjectForUser:rule_groups,title,'.$ruleGroup->id,
|
||||
'description' => 'min:1|max:32768|nullable',
|
||||
'active' => [new IsBoolean()],
|
||||
];
|
||||
}
|
||||
|
@@ -60,7 +60,7 @@ class StoreRequest extends FormRequest
|
||||
{
|
||||
$rules = [
|
||||
'tag' => 'required|min:1|uniqueObjectForUser:tags,tag|max:1024',
|
||||
'description' => 'min:1|nullable|max:65536',
|
||||
'description' => 'min:1|nullable|max:32768',
|
||||
'date' => 'date|nullable',
|
||||
];
|
||||
|
||||
|
@@ -66,7 +66,7 @@ class UpdateRequest extends FormRequest
|
||||
// TODO check if uniqueObjectForUser is obsolete
|
||||
$rules = [
|
||||
'tag' => 'min:1|max:1024|uniqueObjectForUser:tags,tag,'.$tag->id,
|
||||
'description' => 'min:1|nullable|max:65536',
|
||||
'description' => 'min:1|nullable|max:32768',
|
||||
'date' => 'date|nullable',
|
||||
];
|
||||
|
||||
|
@@ -27,6 +27,8 @@ namespace FireflyIII\Api\V1\Requests\Models\Transaction;
|
||||
use FireflyIII\Rules\BelongsUser;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\Rules\IsDateOrTime;
|
||||
use FireflyIII\Rules\IsValidPositiveAmount;
|
||||
use FireflyIII\Rules\IsValidZeroOrMoreAmount;
|
||||
use FireflyIII\Support\NullArrayObject;
|
||||
use FireflyIII\Support\Request\AppendsLocationData;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
@@ -35,6 +37,7 @@ use FireflyIII\Validation\CurrencyValidation;
|
||||
use FireflyIII\Validation\GroupValidation;
|
||||
use FireflyIII\Validation\TransactionValidation;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
@@ -76,7 +79,7 @@ class StoreRequest extends FormRequest
|
||||
|
||||
return [
|
||||
// basic fields for group:
|
||||
'group_title' => 'between:1,1000|nullable',
|
||||
'group_title' => 'min:1|max:1000|nullable',
|
||||
'error_if_duplicate_hash' => [new IsBoolean()],
|
||||
'apply_rules' => [new IsBoolean()],
|
||||
|
||||
@@ -92,40 +95,41 @@ class StoreRequest extends FormRequest
|
||||
'transactions.*.foreign_currency_code' => 'min:3|max:51|exists:transaction_currencies,code|nullable',
|
||||
|
||||
// amount
|
||||
'transactions.*.amount' => 'required|numeric|gt:0',
|
||||
'transactions.*.foreign_amount' => 'numeric',
|
||||
'transactions.*.amount' => ['required', new IsValidPositiveAmount()],
|
||||
'transactions.*.foreign_amount' => ['nullable', new IsValidZeroOrMoreAmount()],
|
||||
|
||||
// description
|
||||
'transactions.*.description' => 'nullable|between:1,1000',
|
||||
'transactions.*.description' => 'nullable|min:1|max:1000',
|
||||
|
||||
// source of transaction
|
||||
'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser()],
|
||||
'transactions.*.source_name' => 'between:1,255|nullable',
|
||||
'transactions.*.source_iban' => 'between:1,255|nullable|iban',
|
||||
'transactions.*.source_number' => 'between:1,255|nullable',
|
||||
'transactions.*.source_bic' => 'between:1,255|nullable|bic',
|
||||
'transactions.*.source_name' => 'min:1|max:255|nullable',
|
||||
'transactions.*.source_iban' => 'min:1|max:255|nullable|iban',
|
||||
'transactions.*.source_number' => 'min:1|max:255|nullable',
|
||||
'transactions.*.source_bic' => 'min:1|max:255|nullable|bic',
|
||||
|
||||
// destination of transaction
|
||||
'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser()],
|
||||
'transactions.*.destination_name' => 'between:1,255|nullable',
|
||||
'transactions.*.destination_iban' => 'between:1,255|nullable|iban',
|
||||
'transactions.*.destination_number' => 'between:1,255|nullable',
|
||||
'transactions.*.destination_bic' => 'between:1,255|nullable|bic',
|
||||
'transactions.*.destination_name' => 'min:1|max:255|nullable',
|
||||
'transactions.*.destination_iban' => 'min:1|max:255|nullable|iban',
|
||||
'transactions.*.destination_number' => 'min:1|max:255|nullable',
|
||||
'transactions.*.destination_bic' => 'min:1|max:255|nullable|bic',
|
||||
|
||||
// budget, category, bill and piggy
|
||||
'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUser()],
|
||||
'transactions.*.budget_name' => ['between:1,255', 'nullable', new BelongsUser()],
|
||||
'transactions.*.budget_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()],
|
||||
'transactions.*.category_id' => ['mustExist:categories,id', new BelongsUser(), 'nullable'],
|
||||
'transactions.*.category_name' => 'between:1,255|nullable',
|
||||
'transactions.*.category_name' => 'min:1|max:255|nullable',
|
||||
'transactions.*.bill_id' => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUser()],
|
||||
'transactions.*.bill_name' => ['between:1,255', 'nullable', new BelongsUser()],
|
||||
'transactions.*.bill_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()],
|
||||
'transactions.*.piggy_bank_id' => ['numeric', 'nullable', 'mustExist:piggy_banks,id', new BelongsUser()],
|
||||
'transactions.*.piggy_bank_name' => ['between:1,255', 'nullable', new BelongsUser()],
|
||||
'transactions.*.piggy_bank_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()],
|
||||
|
||||
// other interesting fields
|
||||
'transactions.*.reconciled' => [new IsBoolean()],
|
||||
'transactions.*.notes' => 'min:1|max:50000|nullable',
|
||||
'transactions.*.tags' => 'between:0,255',
|
||||
'transactions.*.notes' => 'min:1|max:32768|nullable',
|
||||
'transactions.*.tags' => 'min:0|max:255',
|
||||
'transactions.*.tags.*' => 'min:0|max:255',
|
||||
|
||||
// meta info fields
|
||||
'transactions.*.internal_reference' => 'min:1|max:255|nullable',
|
||||
@@ -188,6 +192,9 @@ class StoreRequest extends FormRequest
|
||||
$this->validateGroupDescription($validator);
|
||||
}
|
||||
);
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -29,11 +29,14 @@ use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Rules\BelongsUser;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\Rules\IsDateOrTime;
|
||||
use FireflyIII\Rules\IsValidPositiveAmount;
|
||||
use FireflyIII\Rules\IsValidZeroOrMoreAmount;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use FireflyIII\Validation\GroupValidation;
|
||||
use FireflyIII\Validation\TransactionValidation;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
@@ -97,7 +100,7 @@ class UpdateRequest extends FormRequest
|
||||
|
||||
return [
|
||||
// basic fields for group:
|
||||
'group_title' => 'between:1,1000|nullable',
|
||||
'group_title' => 'min:1|max:1000|nullable',
|
||||
'apply_rules' => [new IsBoolean()],
|
||||
|
||||
// transaction rules (in array for splits):
|
||||
@@ -115,32 +118,33 @@ class UpdateRequest extends FormRequest
|
||||
'transactions.*.foreign_currency_code' => 'nullable|min:3|max:51|exists:transaction_currencies,code',
|
||||
|
||||
// amount
|
||||
'transactions.*.amount' => 'numeric|gt:0|max:100000000000',
|
||||
'transactions.*.foreign_amount' => 'nullable|numeric|gte:0',
|
||||
'transactions.*.amount' => ['nullable', new IsValidPositiveAmount()],
|
||||
'transactions.*.foreign_amount' => ['nullable', new IsValidZeroOrMoreAmount()],
|
||||
|
||||
// description
|
||||
'transactions.*.description' => 'nullable|between:1,1000',
|
||||
'transactions.*.description' => 'nullable|min:1|max:1000',
|
||||
|
||||
// source of transaction
|
||||
'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser()],
|
||||
'transactions.*.source_name' => 'between:1,255|nullable',
|
||||
'transactions.*.source_name' => 'min:1|max:255|nullable',
|
||||
|
||||
// destination of transaction
|
||||
'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser()],
|
||||
'transactions.*.destination_name' => 'between:1,255|nullable',
|
||||
'transactions.*.destination_name' => 'min:1|max:255|nullable',
|
||||
|
||||
// budget, category, bill and piggy
|
||||
'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUser(), 'nullable'],
|
||||
'transactions.*.budget_name' => ['between:1,255', 'nullable', new BelongsUser()],
|
||||
'transactions.*.budget_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()],
|
||||
'transactions.*.category_id' => ['mustExist:categories,id', new BelongsUser(), 'nullable'],
|
||||
'transactions.*.category_name' => 'between:1,255|nullable',
|
||||
'transactions.*.category_name' => 'min:1|max:255|nullable',
|
||||
'transactions.*.bill_id' => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUser()],
|
||||
'transactions.*.bill_name' => ['between:1,255', 'nullable', new BelongsUser()],
|
||||
'transactions.*.bill_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()],
|
||||
|
||||
// other interesting fields
|
||||
'transactions.*.reconciled' => [new IsBoolean()],
|
||||
'transactions.*.notes' => 'min:1|max:50000|nullable',
|
||||
'transactions.*.tags' => 'between:0,255|nullable',
|
||||
'transactions.*.notes' => 'min:1|max:32768|nullable',
|
||||
'transactions.*.tags' => 'min:0|max:255|nullable',
|
||||
'transactions.*.tags.*' => 'min:0|max:255',
|
||||
|
||||
// meta info fields
|
||||
'transactions.*.internal_reference' => 'min:1|max:255|nullable',
|
||||
@@ -202,6 +206,9 @@ class UpdateRequest extends FormRequest
|
||||
$this->validateAccountInformationUpdate($validator, $transactionGroup);
|
||||
}
|
||||
);
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -66,10 +66,10 @@ class StoreRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'required|between:1,255|unique:transaction_currencies,name',
|
||||
'code' => 'required|between:3,51|unique:transaction_currencies,code',
|
||||
'symbol' => 'required|between:1,51|unique:transaction_currencies,symbol',
|
||||
'decimal_places' => 'between:0,20|numeric|min:0|max:12',
|
||||
'name' => 'required|min:1|max:255|unique:transaction_currencies,name',
|
||||
'code' => 'required|min:3|max:32|unique:transaction_currencies,code',
|
||||
'symbol' => 'required|min:1|max:32|unique:transaction_currencies,symbol',
|
||||
'decimal_places' => 'numeric|min:0|max:12',
|
||||
'enabled' => [new IsBoolean()],
|
||||
'default' => [new IsBoolean()],
|
||||
];
|
||||
|
@@ -42,7 +42,7 @@ class UpdateRequest extends FormRequest
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
// return nothing that isn't explicitely in the array:
|
||||
// return nothing that isn't explicitly in the array:
|
||||
$fields = [
|
||||
'name' => ['name', 'convertString'],
|
||||
'code' => ['code', 'convertString'],
|
||||
@@ -64,10 +64,10 @@ class UpdateRequest extends FormRequest
|
||||
$currency = $this->route()->parameter('currency_code');
|
||||
|
||||
return [
|
||||
'name' => sprintf('between:1,255|unique:transaction_currencies,name,%d', $currency->id),
|
||||
'code' => sprintf('between:3,51|unique:transaction_currencies,code,%d', $currency->id),
|
||||
'symbol' => sprintf('between:1,51|unique:transaction_currencies,symbol,%d', $currency->id),
|
||||
'decimal_places' => 'between:0,20|numeric|min:0|max:12',
|
||||
'name' => sprintf('min:1|max:255|unique:transaction_currencies,name,%d', $currency->id),
|
||||
'code' => sprintf('min:3|max:32|unique:transaction_currencies,code,%d', $currency->id),
|
||||
'symbol' => sprintf('min:1|max:32|unique:transaction_currencies,symbol,%d', $currency->id),
|
||||
'decimal_places' => 'numeric|min:0|max:12',
|
||||
'enabled' => [new IsBoolean()],
|
||||
'default' => [new IsBoolean()],
|
||||
];
|
||||
|
@@ -29,6 +29,7 @@ use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
@@ -63,7 +64,7 @@ class StoreRequest extends FormRequest
|
||||
'link_type_name' => 'exists:link_types,name|required_without:link_type_id',
|
||||
'inward_id' => 'required|belongsToUser:transaction_journals,id|different:outward_id',
|
||||
'outward_id' => 'required|belongsToUser:transaction_journals,id|different:inward_id',
|
||||
'notes' => 'between:0,65000',
|
||||
'notes' => 'min:1|max:32768|nullable',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -77,6 +78,9 @@ class StoreRequest extends FormRequest
|
||||
$this->validateExistingLink($validator);
|
||||
}
|
||||
);
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
|
||||
private function validateExistingLink(Validator $validator): void
|
||||
|
@@ -29,6 +29,7 @@ use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
@@ -63,7 +64,7 @@ class UpdateRequest extends FormRequest
|
||||
'link_type_name' => 'exists:link_types,name',
|
||||
'inward_id' => 'belongsToUser:transaction_journals,id|different:outward_id',
|
||||
'outward_id' => 'belongsToUser:transaction_journals,id|different:inward_id',
|
||||
'notes' => 'between:0,65000',
|
||||
'notes' => 'min:1|max:32768|nullable',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -77,6 +78,9 @@ class UpdateRequest extends FormRequest
|
||||
$this->validateUpdate($validator);
|
||||
}
|
||||
);
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
|
||||
private function validateUpdate(Validator $validator): void
|
||||
|
@@ -72,7 +72,7 @@ class CreateRequest extends FormRequest
|
||||
$validProtocols = config('firefly.valid_url_protocols');
|
||||
|
||||
return [
|
||||
'title' => 'required|between:1,512|uniqueObjectForUser:webhooks,title',
|
||||
'title' => 'required|min:1|max:255|uniqueObjectForUser:webhooks,title',
|
||||
'active' => [new IsBoolean()],
|
||||
'trigger' => sprintf('required|in:%s', $triggers),
|
||||
'response' => sprintf('required|in:%s', $responses),
|
||||
|
@@ -85,7 +85,7 @@ class UpdateRequest extends FormRequest
|
||||
$webhook = $this->route()->parameter('webhook');
|
||||
|
||||
return [
|
||||
'title' => sprintf('between:1,512|uniqueObjectForUser:webhooks,title,%d', $webhook->id),
|
||||
'title' => sprintf('min:1|max:255|uniqueObjectForUser:webhooks,title,%d', $webhook->id),
|
||||
'active' => [new IsBoolean()],
|
||||
'trigger' => sprintf('in:%s', $triggers),
|
||||
'response' => sprintf('in:%s', $responses),
|
||||
|
@@ -65,7 +65,7 @@ class UpdateRequest extends FormRequest
|
||||
return ['value' => ['required', new IsBoolean()]];
|
||||
}
|
||||
if ('configuration.permission_update_check' === $name) {
|
||||
return ['value' => 'required|numeric|between:-1,1'];
|
||||
return ['value' => 'required|numeric|min:-1|max:1'];
|
||||
}
|
||||
if ('configuration.last_update_check' === $name) {
|
||||
return ['value' => 'required|numeric|min:464272080'];
|
||||
|
@@ -29,6 +29,7 @@ use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
@@ -97,5 +98,8 @@ class UserUpdateRequest extends FormRequest
|
||||
}
|
||||
}
|
||||
);
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
83
app/Api/V2/Controllers/Autocomplete/CategoryController.php
Normal file
83
app/Api/V2/Controllers/Autocomplete/CategoryController.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
/*
|
||||
* CategoryController.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\Autocomplete;
|
||||
|
||||
use FireflyIII\Api\V2\Controllers\Controller;
|
||||
use FireflyIII\Api\V2\Request\Autocomplete\AutocompleteRequest;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Repositories\UserGroups\Category\CategoryRepositoryInterface;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
/**
|
||||
* Class CategoryController
|
||||
*/
|
||||
class CategoryController extends Controller
|
||||
{
|
||||
private CategoryRepositoryInterface $repository;
|
||||
|
||||
/**
|
||||
* AccountController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->repository = app(CategoryRepositoryInterface::class);
|
||||
|
||||
$userGroup = $this->validateUserGroup($request);
|
||||
if (null !== $userGroup) {
|
||||
$this->repository->setUserGroup($userGroup);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public function categories(AutocompleteRequest $request): JsonResponse
|
||||
{
|
||||
$data = $request->getData();
|
||||
$result = $this->repository->searchCategory($data['query'], $this->parameters->get('limit'));
|
||||
$filtered = $result->map(
|
||||
static function (Category $item) {
|
||||
return [
|
||||
'id' => (string) $item->id,
|
||||
'name' => $item->name,
|
||||
];
|
||||
}
|
||||
);
|
||||
|
||||
return response()->json($filtered);
|
||||
}
|
||||
}
|
85
app/Api/V2/Controllers/Autocomplete/TagController.php
Normal file
85
app/Api/V2/Controllers/Autocomplete/TagController.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
/*
|
||||
* CategoryController.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\Autocomplete;
|
||||
|
||||
use FireflyIII\Api\V2\Controllers\Controller;
|
||||
use FireflyIII\Api\V2\Request\Autocomplete\AutocompleteRequest;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Repositories\UserGroups\Tag\TagRepositoryInterface;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
/**
|
||||
* Class TagController
|
||||
*/
|
||||
class TagController extends Controller
|
||||
{
|
||||
private TagRepositoryInterface $repository;
|
||||
|
||||
/**
|
||||
* AccountController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->repository = app(TagRepositoryInterface::class);
|
||||
|
||||
$userGroup = $this->validateUserGroup($request);
|
||||
if (null !== $userGroup) {
|
||||
$this->repository->setUserGroup($userGroup);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public function tags(AutocompleteRequest $request): JsonResponse
|
||||
{
|
||||
$data = $request->getData();
|
||||
$result = $this->repository->searchTag($data['query'], $data['limit']);
|
||||
$filtered = $result->map(
|
||||
static function (Tag $item) {
|
||||
return [
|
||||
'id' => (string) $item->id,
|
||||
'name' => $item->tag,
|
||||
'value' => (string) $item->id,
|
||||
'label' => $item->tag,
|
||||
];
|
||||
}
|
||||
);
|
||||
|
||||
return response()->json($filtered);
|
||||
}
|
||||
}
|
@@ -134,10 +134,10 @@ class AccountController extends Controller
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
|
||||
// the default currency of the user (could be the same!)
|
||||
'native_id' => (string)$default->id,
|
||||
'native_code' => $default->code,
|
||||
'native_symbol' => $default->symbol,
|
||||
'native_decimal_places' => $default->decimal_places,
|
||||
'native_currency_id' => (string)$default->id,
|
||||
'native_currency_code' => $default->code,
|
||||
'native_currency_symbol' => $default->symbol,
|
||||
'native_currency_decimal_places' => $default->decimal_places,
|
||||
'start' => $start->toAtomString(),
|
||||
'end' => $end->toAtomString(),
|
||||
'period' => '1D',
|
||||
|
@@ -39,6 +39,7 @@ use FireflyIII\Support\Http\Api\ExchangeRateConverter;
|
||||
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class BudgetController
|
||||
@@ -76,11 +77,7 @@ class BudgetController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DateRequest $request
|
||||
*
|
||||
* TODO see autocomplete/accountcontroller
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function dashboard(DateRequest $request): JsonResponse
|
||||
{
|
||||
@@ -127,14 +124,14 @@ 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_id' => (string)$row['native_id'],
|
||||
'native_code' => $row['native_code'],
|
||||
'native_name' => $row['native_name'],
|
||||
'native_decimal_places' => $row['native_decimal_places'],
|
||||
'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'],
|
||||
'period' => null,
|
||||
'start' => $row['start'],
|
||||
'end' => $row['end'],
|
||||
@@ -169,7 +166,8 @@ class BudgetController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Shared between the "noBudgetLimits" function and "processLimit". Will take a single set of expenses and return its info.
|
||||
* Shared between the "noBudgetLimits" function and "processLimit". Will take a single set of expenses and return
|
||||
* its info.
|
||||
*
|
||||
* @param array<int, array<int, string>> $array
|
||||
*
|
||||
@@ -177,6 +175,7 @@ class BudgetController extends Controller
|
||||
*/
|
||||
private function processExpenses(int $budgetId, array $array, Carbon $start, Carbon $end): array
|
||||
{
|
||||
Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__));
|
||||
$converter = new ExchangeRateConverter();
|
||||
$return = [];
|
||||
|
||||
@@ -190,16 +189,16 @@ 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_id' => (string)$this->currency->id,
|
||||
'native_code' => $this->currency->code,
|
||||
'native_name' => $this->currency->name,
|
||||
'native_symbol' => $this->currency->symbol,
|
||||
'native_decimal_places' => $this->currency->decimal_places,
|
||||
'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,
|
||||
'native_currency_decimal_places' => $this->currency->decimal_places,
|
||||
'start' => $start->toAtomString(),
|
||||
'end' => $end->toAtomString(),
|
||||
'spent' => '0',
|
||||
@@ -258,6 +257,7 @@ class BudgetController extends Controller
|
||||
*/
|
||||
private function processLimit(Budget $budget, BudgetLimit $limit): array
|
||||
{
|
||||
Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__));
|
||||
$end = clone $limit->end_date;
|
||||
$end->endOfDay();
|
||||
$spent = $this->opsRepository->listExpenses($limit->start_date, $end, null, new Collection([$budget]));
|
||||
|
@@ -37,6 +37,7 @@ use FireflyIII\Support\Http\Api\CleansChartData;
|
||||
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
|
||||
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class BudgetController
|
||||
@@ -76,6 +77,8 @@ class CategoryController extends Controller
|
||||
*/
|
||||
public function dashboard(DateRequest $request): JsonResponse
|
||||
{
|
||||
Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__));
|
||||
|
||||
/** @var Carbon $start */
|
||||
$start = $this->parameters->get('start');
|
||||
|
||||
@@ -115,11 +118,11 @@ class CategoryController extends Controller
|
||||
'currency_name' => $currency->name,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'native_id' => (string)$default->id,
|
||||
'native_code' => $default->code,
|
||||
'native_name' => $default->name,
|
||||
'native_symbol' => $default->symbol,
|
||||
'native_decimal_places' => $default->decimal_places,
|
||||
'native_currency_id' => (string)$default->id,
|
||||
'native_currency_code' => $default->code,
|
||||
'native_currency_name' => $default->name,
|
||||
'native_currency_symbol' => $default->symbol,
|
||||
'native_currency_decimal_places' => $default->decimal_places,
|
||||
'period' => null,
|
||||
'start' => $start->toAtomString(),
|
||||
'end' => $end->toAtomString(),
|
||||
|
@@ -28,6 +28,7 @@ use FireflyIII\Api\V2\Controllers\Controller;
|
||||
use FireflyIII\Api\V2\Request\Generic\DateRequest;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Transformers\V2\BudgetTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
/**
|
||||
@@ -50,6 +51,20 @@ class ShowController extends Controller
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a budget.
|
||||
*/
|
||||
public function show(Budget $budget): JsonResponse
|
||||
{
|
||||
$transformer = new BudgetTransformer();
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
return response()
|
||||
->api($this->jsonApiObject('budgets', $budget, $transformer))
|
||||
->header('Content-Type', self::CONTENT_TYPE)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* 2023-10-29 removed the cerSum reference, not sure where this is used atm
|
||||
* so removed from api.php. Also applies to "spent" method.
|
||||
|
65
app/Api/V2/Controllers/Model/BudgetLimit/IndexController.php
Normal file
65
app/Api/V2/Controllers/Model/BudgetLimit/IndexController.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/*
|
||||
* IndexController.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\Controllers\Model\BudgetLimit;
|
||||
|
||||
use FireflyIII\Api\V2\Controllers\Controller;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
|
||||
use FireflyIII\Transformers\V2\BudgetLimitTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
|
||||
class IndexController extends Controller
|
||||
{
|
||||
private BudgetLimitRepositoryInterface $repository;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->repository = app(BudgetLimitRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This endpoint is documented at:
|
||||
* TODO add URL
|
||||
*/
|
||||
public function index(Budget $budget): JsonResponse
|
||||
{
|
||||
$pageSize = $this->parameters->get('limit');
|
||||
$collection = $this->repository->getBudgetLimits($budget);
|
||||
$total = $collection->count();
|
||||
$collection->slice($pageSize * $this->parameters->get('page'), $pageSize);
|
||||
|
||||
$paginator = new LengthAwarePaginator($collection, $total, $pageSize, $this->parameters->get('page'));
|
||||
$transformer = new BudgetLimitTransformer();
|
||||
|
||||
return response()->api($this->jsonApiList('budget-limits', $paginator, $transformer))->header('Content-Type', self::CONTENT_TYPE);
|
||||
}
|
||||
}
|
43
app/Api/V2/Controllers/Model/Transaction/ShowController.php
Normal file
43
app/Api/V2/Controllers/Model/Transaction/ShowController.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
/*
|
||||
* ShowController.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\Model\Transaction;
|
||||
|
||||
use FireflyIII\Api\V2\Controllers\Controller;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Transformers\V2\TransactionGroupTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
class ShowController extends Controller
|
||||
{
|
||||
/**
|
||||
* TODO this endpoint is not yet reachable.
|
||||
*/
|
||||
public function show(TransactionGroup $transactionGroup): JsonResponse
|
||||
{
|
||||
$transformer = new TransactionGroupTransformer();
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
return response()->api($this->jsonApiObject('transactions', $transactionGroup, $transformer))->header('Content-Type', self::CONTENT_TYPE);
|
||||
}
|
||||
}
|
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
/*
|
||||
* UpdateController.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\Model\Transaction;
|
||||
|
||||
use FireflyIII\Api\V2\Controllers\Controller;
|
||||
use FireflyIII\Api\V2\Request\Model\Transaction\UpdateRequest;
|
||||
use FireflyIII\Events\UpdatedTransactionGroup;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
|
||||
use FireflyIII\Transformers\V2\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
class UpdateController extends Controller
|
||||
{
|
||||
private TransactionGroupRepositoryInterface $groupRepository;
|
||||
|
||||
/**
|
||||
* TransactionController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->groupRepository = app(TransactionGroupRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This endpoint is documented at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/transactions/updateTransaction
|
||||
*
|
||||
* Update a transaction.
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function update(UpdateRequest $request, TransactionGroup $transactionGroup): JsonResponse
|
||||
{
|
||||
app('log')->debug('Now in update routine for transaction group [v2]!');
|
||||
$data = $request->getAll();
|
||||
$transactionGroup = $this->groupRepository->update($transactionGroup, $data);
|
||||
$applyRules = $data['apply_rules'] ?? true;
|
||||
$fireWebhooks = $data['fire_webhooks'] ?? true;
|
||||
|
||||
event(new UpdatedTransactionGroup($transactionGroup, $applyRules, $fireWebhooks));
|
||||
app('preferences')->mark();
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
// use new group collector:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setUser($admin)->setTransactionGroup($transactionGroup);
|
||||
|
||||
$selectedGroup = $collector->getGroups()->first();
|
||||
if (null === $selectedGroup) {
|
||||
throw new FireflyException('200032: Cannot find transaction. Possibly, a rule deleted this transaction after its creation.');
|
||||
}
|
||||
|
||||
$transformer = new TransactionGroupTransformer();
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
return response()->api($this->jsonApiObject('transactions', $selectedGroup, $transformer))->header('Content-Type', self::CONTENT_TYPE);
|
||||
}
|
||||
}
|
@@ -45,6 +45,7 @@ use FireflyIII\Support\Http\Api\SummaryBalanceGrouped;
|
||||
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class BasicController
|
||||
@@ -205,10 +206,10 @@ class BasicController extends Controller
|
||||
$return[] = [
|
||||
'key' => 'bills-paid-in-native',
|
||||
'value' => $nativeAmount,
|
||||
'currency_id' => (string)$info['native_id'],
|
||||
'currency_code' => $info['native_code'],
|
||||
'currency_symbol' => $info['native_symbol'],
|
||||
'currency_decimal_places' => $info['native_decimal_places'],
|
||||
'currency_id' => (string)$info['native_currency_id'],
|
||||
'currency_code' => $info['native_currency_code'],
|
||||
'currency_symbol' => $info['native_currency_symbol'],
|
||||
'currency_decimal_places' => $info['native_currency_decimal_places'],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -229,10 +230,10 @@ class BasicController extends Controller
|
||||
$return[] = [
|
||||
'key' => 'bills-unpaid-in-native',
|
||||
'value' => $nativeAmount,
|
||||
'currency_id' => (string)$info['native_id'],
|
||||
'currency_code' => $info['native_code'],
|
||||
'currency_symbol' => $info['native_symbol'],
|
||||
'currency_decimal_places' => $info['native_decimal_places'],
|
||||
'currency_id' => (string)$info['native_currency_id'],
|
||||
'currency_code' => $info['native_currency_code'],
|
||||
'currency_symbol' => $info['native_currency_symbol'],
|
||||
'currency_decimal_places' => $info['native_currency_decimal_places'],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -244,6 +245,7 @@ class BasicController extends Controller
|
||||
*/
|
||||
private function getLeftToSpendInfo(Carbon $start, Carbon $end): array
|
||||
{
|
||||
Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__));
|
||||
app('log')->debug('Now in getLeftToSpendInfo');
|
||||
$return = [];
|
||||
$today = today(config('app.timezone'));
|
||||
|
@@ -28,6 +28,7 @@ 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;
|
||||
|
||||
/**
|
||||
@@ -79,5 +80,8 @@ class BalanceChartRequest extends FormRequest
|
||||
}
|
||||
}
|
||||
);
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -27,6 +27,7 @@ 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;
|
||||
|
||||
/**
|
||||
@@ -77,5 +78,8 @@ class DashboardChartRequest extends FormRequest
|
||||
}
|
||||
}
|
||||
);
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -28,6 +28,7 @@ use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\Rules\BelongsUserGroup;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\Rules\IsDateOrTime;
|
||||
use FireflyIII\Rules\IsValidPositiveAmount;
|
||||
use FireflyIII\Support\NullArrayObject;
|
||||
use FireflyIII\Support\Request\AppendsLocationData;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
@@ -37,6 +38,7 @@ use FireflyIII\Validation\CurrencyValidation;
|
||||
use FireflyIII\Validation\GroupValidation;
|
||||
use FireflyIII\Validation\TransactionValidation;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
@@ -74,7 +76,6 @@ class StoreRequest extends FormRequest
|
||||
'fire_webhooks' => $this->boolean('fire_webhooks', true),
|
||||
'transactions' => $this->getTransactionData(),
|
||||
];
|
||||
// TODO include location and ability to process it.
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,7 +92,7 @@ class StoreRequest extends FormRequest
|
||||
|
||||
return [
|
||||
// basic fields for group:
|
||||
'group_title' => 'between:1,1000|nullable',
|
||||
'group_title' => 'min:1|max:1000|nullable',
|
||||
'error_if_duplicate_hash' => [new IsBoolean()],
|
||||
'apply_rules' => [new IsBoolean()],
|
||||
|
||||
@@ -107,40 +108,41 @@ class StoreRequest extends FormRequest
|
||||
'transactions.*.foreign_currency_code' => 'min:3|max:51|exists:transaction_currencies,code|nullable',
|
||||
|
||||
// amount
|
||||
'transactions.*.amount' => 'required|numeric|gt:0',
|
||||
'transactions.*.foreign_amount' => 'numeric',
|
||||
'transactions.*.amount' => ['required', new IsValidPositiveAmount()],
|
||||
'transactions.*.foreign_amount' => ['nullable', new IsValidPositiveAmount()],
|
||||
|
||||
// description
|
||||
'transactions.*.description' => 'nullable|between:1,1000',
|
||||
'transactions.*.description' => 'nullable|min:1|max:1000',
|
||||
|
||||
// source of transaction
|
||||
'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUserGroup($userGroup)],
|
||||
'transactions.*.source_name' => 'between:1,255|nullable',
|
||||
'transactions.*.source_iban' => 'between:1,255|nullable|iban',
|
||||
'transactions.*.source_number' => 'between:1,255|nullable',
|
||||
'transactions.*.source_bic' => 'between:1,255|nullable|bic',
|
||||
'transactions.*.source_name' => 'min:1|max:255|nullable',
|
||||
'transactions.*.source_iban' => 'min:1|max:255|nullable|iban',
|
||||
'transactions.*.source_number' => 'min:1|max:255|nullable',
|
||||
'transactions.*.source_bic' => 'min:1|max:255|nullable|bic',
|
||||
|
||||
// destination of transaction
|
||||
'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUserGroup($userGroup)],
|
||||
'transactions.*.destination_name' => 'between:1,255|nullable',
|
||||
'transactions.*.destination_iban' => 'between:1,255|nullable|iban',
|
||||
'transactions.*.destination_number' => 'between:1,255|nullable',
|
||||
'transactions.*.destination_bic' => 'between:1,255|nullable|bic',
|
||||
'transactions.*.destination_name' => 'min:1|max:255|nullable',
|
||||
'transactions.*.destination_iban' => 'min:1|max:255|nullable|iban',
|
||||
'transactions.*.destination_number' => 'min:1|max:255|nullable',
|
||||
'transactions.*.destination_bic' => 'min:1|max:255|nullable|bic',
|
||||
|
||||
// budget, category, bill and piggy
|
||||
'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUserGroup($userGroup)],
|
||||
'transactions.*.budget_name' => ['between:1,255', 'nullable', new BelongsUserGroup($userGroup)],
|
||||
'transactions.*.budget_name' => ['min:1', 'max:255', 'nullable', new BelongsUserGroup($userGroup)],
|
||||
'transactions.*.category_id' => ['mustExist:categories,id', new BelongsUserGroup($userGroup), 'nullable'],
|
||||
'transactions.*.category_name' => 'between:1,255|nullable',
|
||||
'transactions.*.category_name' => 'min:1|max:255|nullable',
|
||||
'transactions.*.bill_id' => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUserGroup($userGroup)],
|
||||
'transactions.*.bill_name' => ['between:1,255', 'nullable', new BelongsUserGroup($userGroup)],
|
||||
'transactions.*.bill_name' => ['min:1', 'max:255', 'nullable', new BelongsUserGroup($userGroup)],
|
||||
'transactions.*.piggy_bank_id' => ['numeric', 'nullable', 'mustExist:piggy_banks,id', new BelongsUserGroup($userGroup)],
|
||||
'transactions.*.piggy_bank_name' => ['between:1,255', 'nullable', new BelongsUserGroup($userGroup)],
|
||||
'transactions.*.piggy_bank_name' => ['min:1', 'max:255', 'nullable', new BelongsUserGroup($userGroup)],
|
||||
|
||||
// other interesting fields
|
||||
'transactions.*.reconciled' => [new IsBoolean()],
|
||||
'transactions.*.notes' => 'min:1|max:50000|nullable',
|
||||
'transactions.*.tags' => 'between:0,255',
|
||||
'transactions.*.notes' => 'min:1|max:32768|nullable',
|
||||
'transactions.*.tags' => 'min:0|max:255',
|
||||
'transactions.*.tags.*' => 'min:0|max:255',
|
||||
|
||||
// meta info fields
|
||||
'transactions.*.internal_reference' => 'min:1|max:255|nullable',
|
||||
@@ -166,6 +168,8 @@ class StoreRequest extends FormRequest
|
||||
'transactions.*.due_date' => 'date|nullable',
|
||||
'transactions.*.payment_date' => 'date|nullable',
|
||||
'transactions.*.invoice_date' => 'date|nullable',
|
||||
|
||||
// TODO include location and ability to process it.
|
||||
];
|
||||
}
|
||||
|
||||
@@ -208,6 +212,9 @@ class StoreRequest extends FormRequest
|
||||
$this->validateGroupDescription($validator);
|
||||
}
|
||||
);
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -222,7 +229,7 @@ class StoreRequest extends FormRequest
|
||||
*/
|
||||
foreach ($this->get('transactions') as $transaction) {
|
||||
$object = new NullArrayObject($transaction);
|
||||
$return[] = [
|
||||
$result = [
|
||||
'type' => $this->clearString($object['type']),
|
||||
'date' => $this->dateFromValue($object['date']),
|
||||
'order' => $this->integerFromValue((string)$object['order']),
|
||||
@@ -300,6 +307,8 @@ class StoreRequest extends FormRequest
|
||||
'payment_date' => $this->dateFromValue($object['payment_date']),
|
||||
'invoice_date' => $this->dateFromValue($object['invoice_date']),
|
||||
];
|
||||
$result = $this->addFromromTransactionStore($transaction, $result);
|
||||
$return[] = $result;
|
||||
}
|
||||
|
||||
return $return;
|
||||
|
366
app/Api/V2/Request/Model/Transaction/UpdateRequest.php
Normal file
366
app/Api/V2/Request/Model/Transaction/UpdateRequest.php
Normal file
@@ -0,0 +1,366 @@
|
||||
<?php
|
||||
/*
|
||||
* UpdateRequest.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\Request\Model\Transaction;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\Models\AvailableBudget\Request;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Rules\BelongsUser;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\Rules\IsDateOrTime;
|
||||
use FireflyIII\Rules\IsValidPositiveAmount;
|
||||
use FireflyIII\Rules\IsValidZeroOrMoreAmount;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use FireflyIII\Validation\GroupValidation;
|
||||
use FireflyIII\Validation\TransactionValidation;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
* Class UpdateRequest
|
||||
*
|
||||
* TODO it's the same as the v1
|
||||
*/
|
||||
class UpdateRequest extends Request
|
||||
{
|
||||
use ChecksLogin;
|
||||
use ConvertsDataTypes;
|
||||
use GroupValidation;
|
||||
use TransactionValidation;
|
||||
|
||||
private array $arrayFields;
|
||||
private array $booleanFields;
|
||||
private array $dateFields;
|
||||
private array $floatFields;
|
||||
private array $integerFields;
|
||||
private array $stringFields;
|
||||
private array $textareaFields;
|
||||
|
||||
/**
|
||||
* Get all data. Is pretty complex because of all the ??-statements.
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||
$this->integerFields = ['order', 'currency_id', 'foreign_currency_id', 'transaction_journal_id', 'source_id', 'destination_id', 'budget_id', 'category_id', 'bill_id', 'recurrence_id'];
|
||||
$this->dateFields = ['date', 'interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date'];
|
||||
$this->textareaFields = ['notes'];
|
||||
// not really floats, for validation.
|
||||
$this->floatFields = ['amount', 'foreign_amount'];
|
||||
$this->stringFields = ['type', 'currency_code', 'foreign_currency_code', 'description', 'source_name', 'source_iban', 'source_number', 'source_bic', 'destination_name', 'destination_iban', 'destination_number', 'destination_bic', 'budget_name', 'category_name', 'bill_name', 'internal_reference', 'external_id', 'bunq_payment_id', 'sepa_cc', 'sepa_ct_op', 'sepa_ct_id', 'sepa_db', 'sepa_country', 'sepa_ep', 'sepa_ci', 'sepa_batch_id', 'external_url'];
|
||||
$this->booleanFields = ['reconciled'];
|
||||
$this->arrayFields = ['tags'];
|
||||
$data = [];
|
||||
if ($this->has('transactions')) {
|
||||
$data['transactions'] = $this->getTransactionData();
|
||||
}
|
||||
if ($this->has('apply_rules')) {
|
||||
$data['apply_rules'] = $this->boolean('apply_rules', true);
|
||||
}
|
||||
if ($this->has('fire_webhooks')) {
|
||||
$data['fire_webhooks'] = $this->boolean('fire_webhooks', true);
|
||||
}
|
||||
if ($this->has('group_title')) {
|
||||
$data['group_title'] = $this->convertString('group_title');
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||
$validProtocols = config('firefly.valid_url_protocols');
|
||||
|
||||
return [
|
||||
// basic fields for group:
|
||||
'group_title' => 'min:1|max:1000|nullable',
|
||||
'apply_rules' => [new IsBoolean()],
|
||||
|
||||
// transaction rules (in array for splits):
|
||||
'transactions.*.type' => 'in:withdrawal,deposit,transfer,opening-balance,reconciliation',
|
||||
'transactions.*.date' => [new IsDateOrTime()],
|
||||
'transactions.*.order' => 'numeric|min:0',
|
||||
|
||||
// group id:
|
||||
'transactions.*.transaction_journal_id' => ['nullable', 'numeric', new BelongsUser()],
|
||||
|
||||
// currency info
|
||||
'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id|nullable',
|
||||
'transactions.*.currency_code' => 'min:3|max:51|exists:transaction_currencies,code|nullable',
|
||||
'transactions.*.foreign_currency_id' => 'nullable|numeric|exists:transaction_currencies,id',
|
||||
'transactions.*.foreign_currency_code' => 'nullable|min:3|max:51|exists:transaction_currencies,code',
|
||||
|
||||
// amount
|
||||
'transactions.*.amount' => ['nullable', new IsValidPositiveAmount()],
|
||||
'transactions.*.foreign_amount' => ['nullable', new IsValidZeroOrMoreAmount()],
|
||||
|
||||
// description
|
||||
'transactions.*.description' => 'nullable|min:1|max:1000',
|
||||
|
||||
// source of transaction
|
||||
'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser()],
|
||||
'transactions.*.source_name' => 'min:1|max:255|nullable',
|
||||
|
||||
// destination of transaction
|
||||
'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser()],
|
||||
'transactions.*.destination_name' => 'min:1|max:255|nullable',
|
||||
|
||||
// budget, category, bill and piggy
|
||||
'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUser(), 'nullable'],
|
||||
'transactions.*.budget_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()],
|
||||
'transactions.*.category_id' => ['mustExist:categories,id', new BelongsUser(), 'nullable'],
|
||||
'transactions.*.category_name' => 'min:1|max:255|nullable',
|
||||
'transactions.*.bill_id' => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUser()],
|
||||
'transactions.*.bill_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()],
|
||||
|
||||
// other interesting fields
|
||||
'transactions.*.reconciled' => [new IsBoolean()],
|
||||
'transactions.*.notes' => 'min:1|max:32768|nullable',
|
||||
'transactions.*.tags' => 'min:0|max:255|nullable',
|
||||
'transactions.*.tags.*' => 'min:0|max:255',
|
||||
|
||||
// meta info fields
|
||||
'transactions.*.internal_reference' => 'min:1|max:255|nullable',
|
||||
'transactions.*.external_id' => 'min:1|max:255|nullable',
|
||||
'transactions.*.recurrence_id' => 'min:1|max:255|nullable',
|
||||
'transactions.*.bunq_payment_id' => 'min:1|max:255|nullable',
|
||||
'transactions.*.external_url' => sprintf('min:1|max:255|nullable|url:%s', $validProtocols),
|
||||
|
||||
// SEPA fields:
|
||||
'transactions.*.sepa_cc' => 'min:1|max:255|nullable',
|
||||
'transactions.*.sepa_ct_op' => 'min:1|max:255|nullable',
|
||||
'transactions.*.sepa_ct_id' => 'min:1|max:255|nullable',
|
||||
'transactions.*.sepa_db' => 'min:1|max:255|nullable',
|
||||
'transactions.*.sepa_country' => 'min:1|max:255|nullable',
|
||||
'transactions.*.sepa_ep' => 'min:1|max:255|nullable',
|
||||
'transactions.*.sepa_ci' => 'min:1|max:255|nullable',
|
||||
'transactions.*.sepa_batch_id' => 'min:1|max:255|nullable',
|
||||
|
||||
// dates
|
||||
'transactions.*.interest_date' => 'date|nullable',
|
||||
'transactions.*.book_date' => 'date|nullable',
|
||||
'transactions.*.process_date' => 'date|nullable',
|
||||
'transactions.*.due_date' => 'date|nullable',
|
||||
'transactions.*.payment_date' => 'date|nullable',
|
||||
'transactions.*.invoice_date' => 'date|nullable',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the validator instance.
|
||||
*/
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
app('log')->debug('Now in withValidator');
|
||||
|
||||
/** @var TransactionGroup $transactionGroup */
|
||||
$transactionGroup = $this->route()->parameter('userGroupTransaction');
|
||||
$validator->after(
|
||||
function (Validator $validator) use ($transactionGroup): void {
|
||||
// if more than one, verify that there are journal ID's present.
|
||||
$this->validateJournalIds($validator, $transactionGroup);
|
||||
|
||||
// all transaction types must be equal:
|
||||
$this->validateTransactionTypesForUpdate($validator);
|
||||
|
||||
// user wants to update a reconciled transaction.
|
||||
// source, destination, amount + foreign_amount cannot be changed
|
||||
// and must be omitted from the request.
|
||||
$this->preventUpdateReconciled($validator, $transactionGroup);
|
||||
|
||||
// validate source/destination is equal, depending on the transaction journal type.
|
||||
$this->validateEqualAccountsForUpdate($validator, $transactionGroup);
|
||||
|
||||
// see method:
|
||||
// $this->preventNoAccountInfo($validator, );
|
||||
|
||||
// validate that the currency fits the source and/or destination account.
|
||||
// validate all account info
|
||||
$this->validateAccountInformationUpdate($validator, $transactionGroup);
|
||||
}
|
||||
);
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get transaction data.
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function getTransactionData(): array
|
||||
{
|
||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||
$return = [];
|
||||
|
||||
/** @var null|array $transactions */
|
||||
$transactions = $this->get('transactions');
|
||||
|
||||
if (!is_countable($transactions)) {
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** @var null|array $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
if (!is_array($transaction)) {
|
||||
throw new FireflyException('Invalid data submitted: transaction is not array.');
|
||||
}
|
||||
// default response is to update nothing in the transaction:
|
||||
$current = [];
|
||||
$current = $this->getIntegerData($current, $transaction);
|
||||
$current = $this->getStringData($current, $transaction);
|
||||
$current = $this->getNlStringData($current, $transaction);
|
||||
$current = $this->getDateData($current, $transaction);
|
||||
$current = $this->getBooleanData($current, $transaction);
|
||||
$current = $this->getArrayData($current, $transaction);
|
||||
$current = $this->getFloatData($current, $transaction);
|
||||
$return[] = $current;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* For each field, add it to the array if a reference is present in the request:
|
||||
*
|
||||
* @param array<string, string> $current
|
||||
* @param array<string, mixed> $transaction
|
||||
*/
|
||||
private function getIntegerData(array $current, array $transaction): array
|
||||
{
|
||||
foreach ($this->integerFields as $fieldName) {
|
||||
if (array_key_exists($fieldName, $transaction)) {
|
||||
$current[$fieldName] = $this->integerFromValue((string) $transaction[$fieldName]);
|
||||
}
|
||||
}
|
||||
|
||||
return $current;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $current
|
||||
* @param array<string, mixed> $transaction
|
||||
*/
|
||||
private function getStringData(array $current, array $transaction): array
|
||||
{
|
||||
foreach ($this->stringFields as $fieldName) {
|
||||
if (array_key_exists($fieldName, $transaction)) {
|
||||
$current[$fieldName] = $this->clearString((string) $transaction[$fieldName]);
|
||||
}
|
||||
}
|
||||
|
||||
return $current;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $current
|
||||
* @param array<string, mixed> $transaction
|
||||
*/
|
||||
private function getNlStringData(array $current, array $transaction): array
|
||||
{
|
||||
foreach ($this->textareaFields as $fieldName) {
|
||||
if (array_key_exists($fieldName, $transaction)) {
|
||||
$current[$fieldName] = $this->clearStringKeepNewlines((string) $transaction[$fieldName]); // keep newlines
|
||||
}
|
||||
}
|
||||
|
||||
return $current;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $current
|
||||
* @param array<string, mixed> $transaction
|
||||
*/
|
||||
private function getDateData(array $current, array $transaction): array
|
||||
{
|
||||
foreach ($this->dateFields as $fieldName) {
|
||||
app('log')->debug(sprintf('Now at date field %s', $fieldName));
|
||||
if (array_key_exists($fieldName, $transaction)) {
|
||||
app('log')->debug(sprintf('New value: "%s"', (string) $transaction[$fieldName]));
|
||||
$current[$fieldName] = $this->dateFromValue((string) $transaction[$fieldName]);
|
||||
}
|
||||
}
|
||||
|
||||
return $current;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $current
|
||||
* @param array<string, mixed> $transaction
|
||||
*/
|
||||
private function getBooleanData(array $current, array $transaction): array
|
||||
{
|
||||
foreach ($this->booleanFields as $fieldName) {
|
||||
if (array_key_exists($fieldName, $transaction)) {
|
||||
$current[$fieldName] = $this->convertBoolean((string) $transaction[$fieldName]);
|
||||
}
|
||||
}
|
||||
|
||||
return $current;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $current
|
||||
* @param array<string, mixed> $transaction
|
||||
*/
|
||||
private function getArrayData(array $current, array $transaction): array
|
||||
{
|
||||
foreach ($this->arrayFields as $fieldName) {
|
||||
if (array_key_exists($fieldName, $transaction)) {
|
||||
$current[$fieldName] = $this->arrayFromValue($transaction[$fieldName]);
|
||||
}
|
||||
}
|
||||
|
||||
return $current;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $current
|
||||
* @param array<string, mixed> $transaction
|
||||
*/
|
||||
private function getFloatData(array $current, array $transaction): array
|
||||
{
|
||||
foreach ($this->floatFields as $fieldName) {
|
||||
if (array_key_exists($fieldName, $transaction)) {
|
||||
$value = $transaction[$fieldName];
|
||||
if (is_float($value)) {
|
||||
$current[$fieldName] = sprintf('%.12f', $value);
|
||||
}
|
||||
if (!is_float($value)) {
|
||||
$current[$fieldName] = (string) $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $current;
|
||||
}
|
||||
}
|
@@ -49,7 +49,7 @@ class StoreRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'title' => 'unique:user_groups,title|required|min:2|max:255',
|
||||
'title' => 'unique:user_groups,title|required|min:1|max:255',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -53,7 +53,7 @@ class UpdateRequest extends FormRequest
|
||||
$userGroup = $this->route()->parameter('userGroup');
|
||||
|
||||
return [
|
||||
'title' => sprintf('required|min:2|max:255|unique:user_groups,title,%d', $userGroup->id),
|
||||
'title' => sprintf('required|min:1|max:255|unique:user_groups,title,%d', $userGroup->id),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -71,7 +71,6 @@ class EnableCurrencies extends Command
|
||||
$found = [$defaultCurrency->id];
|
||||
|
||||
// get all meta entries
|
||||
/** @var Collection $meta */
|
||||
$meta = AccountMeta::leftJoin('accounts', 'accounts.id', '=', 'account_meta.account_id')
|
||||
->where('accounts.user_group_id', $userGroup->id)
|
||||
->where('account_meta.name', 'currency_id')->groupBy('data')->get(['data'])
|
||||
@@ -108,6 +107,12 @@ class EnableCurrencies extends Command
|
||||
$found[] = $entry->transaction_currency_id;
|
||||
}
|
||||
|
||||
// also get all currencies already enabled.
|
||||
$alreadyEnabled = $userGroup->currencies()->get(['transaction_currencies.id'])->pluck('id')->toArray();
|
||||
foreach ($alreadyEnabled as $currencyId) {
|
||||
$found[] = $currencyId;
|
||||
}
|
||||
|
||||
$found = array_values(array_unique($found));
|
||||
$found = array_values(
|
||||
array_filter(
|
||||
|
@@ -32,6 +32,7 @@ use FireflyIII\Support\Cronjobs\BillWarningCronjob;
|
||||
use FireflyIII\Support\Cronjobs\ExchangeRatesCronjob;
|
||||
use FireflyIII\Support\Cronjobs\RecurringCronjob;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class Cron
|
||||
@@ -103,6 +104,7 @@ class Cron extends Command
|
||||
|
||||
private function exchangeRatesCronJob(bool $force, ?Carbon $date): void
|
||||
{
|
||||
Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__));
|
||||
$exchangeRates = new ExchangeRatesCronjob();
|
||||
$exchangeRates->setForce($force);
|
||||
// set date in cron job:
|
||||
|
@@ -25,9 +25,6 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Console\Commands\Upgrade;
|
||||
|
||||
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
|
||||
use FireflyIII\Models\Recurrence;
|
||||
use FireflyIII\Models\RecurrenceTransaction;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
/**
|
||||
@@ -53,8 +50,7 @@ class MigrateRecurrenceType extends Command
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
$this->migrateTypes();
|
||||
$this->friendlyWarning('This command has been disabled.');
|
||||
$this->markAsExecuted();
|
||||
|
||||
return 0;
|
||||
@@ -67,38 +63,6 @@ class MigrateRecurrenceType extends Command
|
||||
return (bool)$configVar?->data;
|
||||
}
|
||||
|
||||
private function migrateTypes(): void
|
||||
{
|
||||
$set = Recurrence::get();
|
||||
|
||||
/** @var Recurrence $recurrence */
|
||||
foreach ($set as $recurrence) {
|
||||
if (TransactionType::INVALID !== $recurrence->transactionType->type) {
|
||||
$this->migrateRecurrence($recurrence);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function migrateRecurrence(Recurrence $recurrence): void
|
||||
{
|
||||
$originalType = $recurrence->transaction_type_id;
|
||||
$newType = $this->getInvalidType();
|
||||
$recurrence->transaction_type_id = $newType->id;
|
||||
$recurrence->save();
|
||||
|
||||
/** @var RecurrenceTransaction $transaction */
|
||||
foreach ($recurrence->recurrenceTransactions as $transaction) {
|
||||
$transaction->transaction_type_id = $originalType;
|
||||
$transaction->save();
|
||||
}
|
||||
$this->friendlyInfo(sprintf('Updated recurrence #%d to new transaction type model.', $recurrence->id));
|
||||
}
|
||||
|
||||
private function getInvalidType(): TransactionType
|
||||
{
|
||||
return TransactionType::whereType(TransactionType::INVALID)->firstOrCreate(['type' => TransactionType::INVALID]);
|
||||
}
|
||||
|
||||
private function markAsExecuted(): void
|
||||
{
|
||||
app('fireflyconfig')->set(self::CONFIG_NAME, true);
|
||||
|
@@ -216,6 +216,7 @@ class Handler extends ExceptionHandler
|
||||
'json' => request()->acceptsJson(),
|
||||
'method' => request()->method(),
|
||||
'headers' => $headers,
|
||||
'post' => 'POST' === request()->method() ? json_encode(request()->all()) : '',
|
||||
];
|
||||
|
||||
// create job that will mail.
|
||||
|
@@ -28,6 +28,7 @@ use Carbon\Carbon;
|
||||
use FireflyIII\Exceptions\DuplicateTransactionException;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Location;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
@@ -49,6 +50,8 @@ use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class TransactionJournalFactory
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class TransactionJournalFactory
|
||||
{
|
||||
@@ -318,10 +321,23 @@ class TransactionJournalFactory
|
||||
$this->storePiggyEvent($journal, $row);
|
||||
$this->storeTags($journal, $row['tags']);
|
||||
$this->storeMetaFields($journal, $row);
|
||||
$this->storeLocation($journal, $row);
|
||||
|
||||
return $journal;
|
||||
}
|
||||
|
||||
private function storeLocation(TransactionJournal $journal, NullArrayObject $data): void
|
||||
{
|
||||
if (true === $data['store_location']) {
|
||||
$location = new Location();
|
||||
$location->longitude = $data['longitude'];
|
||||
$location->latitude = $data['latitude'];
|
||||
$location->zoom_level = $data['zoom_level'];
|
||||
$location->locatable()->associate($journal);
|
||||
$location->save();
|
||||
}
|
||||
}
|
||||
|
||||
private function hashArray(NullArrayObject $row): string
|
||||
{
|
||||
$dataRow = $row->getArrayCopy();
|
||||
@@ -355,18 +371,18 @@ class TransactionJournalFactory
|
||||
|
||||
/** @var null|TransactionJournalMeta $result */
|
||||
$result = TransactionJournalMeta::withTrashed()
|
||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id')
|
||||
->whereNotNull('transaction_journals.id')
|
||||
->where('transaction_journals.user_id', $this->user->id)
|
||||
->where('data', json_encode($hash, JSON_THROW_ON_ERROR))
|
||||
->with(['transactionJournal', 'transactionJournal.transactionGroup'])
|
||||
->first()
|
||||
->first(['journal_meta.*'])
|
||||
;
|
||||
if (null !== $result) {
|
||||
app('log')->warning(sprintf('Found a duplicate in errorIfDuplicate because hash %s is not unique!', $hash));
|
||||
$journal = $result->transactionJournal()->withTrashed()->first();
|
||||
$group = $journal?->transactionGroup()->withTrashed()->first();
|
||||
$groupId = $group?->id;
|
||||
if (null === $group) {
|
||||
$groupId = 0;
|
||||
}
|
||||
$groupId = (int) $group?->id;
|
||||
|
||||
throw new DuplicateTransactionException(sprintf('Duplicate of transaction #%d.', $groupId));
|
||||
}
|
||||
|
@@ -220,7 +220,7 @@ class UserEventHandler
|
||||
|
||||
public function sendAdminRegistrationNotification(RegisteredUser $event): void
|
||||
{
|
||||
$sendMail = (bool)app('fireflyconfig')->get('notification_admin_new_reg', true)->data;
|
||||
$sendMail = (bool) app('fireflyconfig')->get('notification_admin_new_reg', true)->data;
|
||||
if ($sendMail) {
|
||||
/** @var UserRepositoryInterface $repository */
|
||||
$repository = app(UserRepositoryInterface::class);
|
||||
@@ -285,7 +285,7 @@ class UserEventHandler
|
||||
$oldEmail = $event->oldEmail;
|
||||
$user = $event->user;
|
||||
$token = app('preferences')->getForUser($user, 'email_change_undo_token', 'invalid');
|
||||
$hashed = hash('sha256', sprintf('%s%s', (string)config('app.key'), $oldEmail));
|
||||
$hashed = hash('sha256', sprintf('%s%s', (string) config('app.key'), $oldEmail));
|
||||
$url = route('profile.undo-email-change', [$token->data, $hashed]);
|
||||
|
||||
try {
|
||||
@@ -347,7 +347,7 @@ class UserEventHandler
|
||||
*/
|
||||
public function sendRegistrationMail(RegisteredUser $event): void
|
||||
{
|
||||
$sendMail = (bool)app('fireflyconfig')->get('notification_user_new_reg', true)->data;
|
||||
$sendMail = (bool) app('fireflyconfig')->get('notification_user_new_reg', true)->data;
|
||||
if ($sendMail) {
|
||||
try {
|
||||
Notification::send($event->user, new UserRegistrationNotification());
|
||||
|
@@ -182,7 +182,7 @@ trait MetaCollection
|
||||
|
||||
public function excludeInternalReference(string $internalReference): GroupCollectorInterface
|
||||
{
|
||||
$internalReference = (string) json_encode($internalReference);
|
||||
$internalReference = (string)json_encode($internalReference);
|
||||
$internalReference = str_replace('\\', '\\\\', trim($internalReference, '"'));
|
||||
|
||||
$this->joinMetaDataTables();
|
||||
@@ -203,7 +203,7 @@ trait MetaCollection
|
||||
|
||||
public function externalIdContains(string $externalId): GroupCollectorInterface
|
||||
{
|
||||
$externalId = (string) json_encode($externalId);
|
||||
$externalId = (string)json_encode($externalId);
|
||||
$externalId = str_replace('\\', '\\\\', trim($externalId, '"'));
|
||||
|
||||
$this->joinMetaDataTables();
|
||||
@@ -215,7 +215,7 @@ trait MetaCollection
|
||||
|
||||
public function externalIdDoesNotContain(string $externalId): GroupCollectorInterface
|
||||
{
|
||||
$externalId = (string) json_encode($externalId);
|
||||
$externalId = (string)json_encode($externalId);
|
||||
$externalId = str_replace('\\', '\\\\', trim($externalId, '"'));
|
||||
|
||||
$this->joinMetaDataTables();
|
||||
@@ -227,7 +227,7 @@ trait MetaCollection
|
||||
|
||||
public function externalIdDoesNotEnd(string $externalId): GroupCollectorInterface
|
||||
{
|
||||
$externalId = (string) json_encode($externalId);
|
||||
$externalId = (string)json_encode($externalId);
|
||||
$externalId = str_replace('\\', '\\\\', trim($externalId, '"'));
|
||||
|
||||
$this->joinMetaDataTables();
|
||||
@@ -239,7 +239,7 @@ trait MetaCollection
|
||||
|
||||
public function externalIdDoesNotStart(string $externalId): GroupCollectorInterface
|
||||
{
|
||||
$externalId = (string) json_encode($externalId);
|
||||
$externalId = (string)json_encode($externalId);
|
||||
$externalId = str_replace('\\', '\\\\', trim($externalId, '"'));
|
||||
|
||||
$this->joinMetaDataTables();
|
||||
@@ -251,7 +251,7 @@ trait MetaCollection
|
||||
|
||||
public function externalIdEnds(string $externalId): GroupCollectorInterface
|
||||
{
|
||||
$externalId = (string) json_encode($externalId);
|
||||
$externalId = (string)json_encode($externalId);
|
||||
$externalId = str_replace('\\', '\\\\', trim($externalId, '"'));
|
||||
|
||||
$this->joinMetaDataTables();
|
||||
@@ -263,7 +263,7 @@ trait MetaCollection
|
||||
|
||||
public function externalIdStarts(string $externalId): GroupCollectorInterface
|
||||
{
|
||||
$externalId = (string) json_encode($externalId);
|
||||
$externalId = (string)json_encode($externalId);
|
||||
$externalId = str_replace('\\', '\\\\', trim($externalId, '"'));
|
||||
|
||||
$this->joinMetaDataTables();
|
||||
@@ -276,7 +276,7 @@ trait MetaCollection
|
||||
public function externalUrlContains(string $url): GroupCollectorInterface
|
||||
{
|
||||
$this->joinMetaDataTables();
|
||||
$url = (string) json_encode($url);
|
||||
$url = (string)json_encode($url);
|
||||
$url = str_replace('\\', '\\\\', trim($url, '"'));
|
||||
$this->query->where('journal_meta.name', '=', 'external_url');
|
||||
$this->query->where('journal_meta.data', 'LIKE', sprintf('%%%s%%', $url));
|
||||
@@ -287,7 +287,7 @@ trait MetaCollection
|
||||
public function externalUrlDoesNotContain(string $url): GroupCollectorInterface
|
||||
{
|
||||
$this->joinMetaDataTables();
|
||||
$url = (string) json_encode($url);
|
||||
$url = (string)json_encode($url);
|
||||
$url = str_replace('\\', '\\\\', trim($url, '"'));
|
||||
$this->query->where('journal_meta.name', '=', 'external_url');
|
||||
$this->query->where('journal_meta.data', 'NOT LIKE', sprintf('%%%s%%', $url));
|
||||
@@ -298,7 +298,7 @@ trait MetaCollection
|
||||
public function externalUrlDoesNotEnd(string $url): GroupCollectorInterface
|
||||
{
|
||||
$this->joinMetaDataTables();
|
||||
$url = (string) json_encode($url);
|
||||
$url = (string)json_encode($url);
|
||||
$url = str_replace('\\', '\\\\', ltrim($url, '"'));
|
||||
$this->query->where('journal_meta.name', '=', 'external_url');
|
||||
$this->query->where('journal_meta.data', 'NOT LIKE', sprintf('%%%s', $url));
|
||||
@@ -309,7 +309,7 @@ trait MetaCollection
|
||||
public function externalUrlDoesNotStart(string $url): GroupCollectorInterface
|
||||
{
|
||||
$this->joinMetaDataTables();
|
||||
$url = (string) json_encode($url);
|
||||
$url = (string)json_encode($url);
|
||||
$url = str_replace('\\', '\\\\', rtrim($url, '"'));
|
||||
// var_dump($url);
|
||||
|
||||
@@ -322,7 +322,7 @@ trait MetaCollection
|
||||
public function externalUrlEnds(string $url): GroupCollectorInterface
|
||||
{
|
||||
$this->joinMetaDataTables();
|
||||
$url = (string) json_encode($url);
|
||||
$url = (string)json_encode($url);
|
||||
$url = str_replace('\\', '\\\\', ltrim($url, '"'));
|
||||
$this->query->where('journal_meta.name', '=', 'external_url');
|
||||
$this->query->where('journal_meta.data', 'LIKE', sprintf('%%%s', $url));
|
||||
@@ -333,7 +333,7 @@ trait MetaCollection
|
||||
public function externalUrlStarts(string $url): GroupCollectorInterface
|
||||
{
|
||||
$this->joinMetaDataTables();
|
||||
$url = (string) json_encode($url);
|
||||
$url = (string)json_encode($url);
|
||||
$url = str_replace('\\', '\\\\', rtrim($url, '"'));
|
||||
// var_dump($url);
|
||||
|
||||
@@ -371,7 +371,7 @@ trait MetaCollection
|
||||
|
||||
public function internalReferenceContains(string $internalReference): GroupCollectorInterface
|
||||
{
|
||||
$internalReference = (string) json_encode($internalReference);
|
||||
$internalReference = (string)json_encode($internalReference);
|
||||
$internalReference = str_replace('\\', '\\\\', trim($internalReference, '"'));
|
||||
// var_dump($internalReference);
|
||||
// exit;
|
||||
@@ -385,7 +385,7 @@ trait MetaCollection
|
||||
|
||||
public function internalReferenceDoesNotContain(string $internalReference): GroupCollectorInterface
|
||||
{
|
||||
$internalReference = (string) json_encode($internalReference);
|
||||
$internalReference = (string)json_encode($internalReference);
|
||||
$internalReference = str_replace('\\', '\\\\', trim($internalReference, '"'));
|
||||
|
||||
$this->joinMetaDataTables();
|
||||
@@ -397,7 +397,7 @@ trait MetaCollection
|
||||
|
||||
public function internalReferenceDoesNotEnd(string $internalReference): GroupCollectorInterface
|
||||
{
|
||||
$internalReference = (string) json_encode($internalReference);
|
||||
$internalReference = (string)json_encode($internalReference);
|
||||
$internalReference = str_replace('\\', '\\\\', trim($internalReference, '"'));
|
||||
|
||||
$this->joinMetaDataTables();
|
||||
@@ -409,7 +409,7 @@ trait MetaCollection
|
||||
|
||||
public function internalReferenceDoesNotStart(string $internalReference): GroupCollectorInterface
|
||||
{
|
||||
$internalReference = (string) json_encode($internalReference);
|
||||
$internalReference = (string)json_encode($internalReference);
|
||||
$internalReference = str_replace('\\', '\\\\', trim($internalReference, '"'));
|
||||
|
||||
$this->joinMetaDataTables();
|
||||
@@ -421,7 +421,7 @@ trait MetaCollection
|
||||
|
||||
public function internalReferenceEnds(string $internalReference): GroupCollectorInterface
|
||||
{
|
||||
$internalReference = (string) json_encode($internalReference);
|
||||
$internalReference = (string)json_encode($internalReference);
|
||||
$internalReference = str_replace('\\', '\\\\', trim($internalReference, '"'));
|
||||
|
||||
$this->joinMetaDataTables();
|
||||
@@ -433,7 +433,7 @@ trait MetaCollection
|
||||
|
||||
public function internalReferenceStarts(string $internalReference): GroupCollectorInterface
|
||||
{
|
||||
$internalReference = (string) json_encode($internalReference);
|
||||
$internalReference = (string)json_encode($internalReference);
|
||||
$internalReference = str_replace('\\', '\\\\', trim($internalReference, '"'));
|
||||
|
||||
$this->joinMetaDataTables();
|
||||
@@ -629,7 +629,7 @@ trait MetaCollection
|
||||
|
||||
public function setInternalReference(string $internalReference): GroupCollectorInterface
|
||||
{
|
||||
$internalReference = (string) json_encode($internalReference);
|
||||
$internalReference = (string)json_encode($internalReference);
|
||||
$internalReference = str_replace('\\', '\\\\', trim($internalReference, '"'));
|
||||
|
||||
$this->joinMetaDataTables();
|
||||
@@ -670,7 +670,64 @@ trait MetaCollection
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit results to a specific set of tags.
|
||||
* Limit results to a SPECIFIC set of tags.
|
||||
*/
|
||||
public function setAllTags(Collection $tags): GroupCollectorInterface
|
||||
{
|
||||
Log::debug(sprintf('Now in setAllTags(%d tag(s))', $tags->count()));
|
||||
$this->withTagInformation();
|
||||
$this->query->whereNotNull('tag_transaction_journal.tag_id');
|
||||
|
||||
// this method adds a "postFilter" to the collector.
|
||||
$list = $tags->pluck('tag')->toArray();
|
||||
$list = array_map('strtolower', $list);
|
||||
$filter = static function (array $object) use ($list): bool|array {
|
||||
$includedJournals = [];
|
||||
$return = $object;
|
||||
unset($return['transactions']);
|
||||
$return['transactions'] = [];
|
||||
Log::debug(sprintf('Now in setAllTags(%s) filter', implode(', ', $list)));
|
||||
$expectedTagCount = count($list);
|
||||
$foundTagCount = 0;
|
||||
foreach ($object['transactions'] as $transaction) {
|
||||
$transactionTagCount = count($transaction['tags']);
|
||||
app('log')->debug(sprintf('Transaction #%d has %d tag(s)', $transaction['transaction_journal_id'], $transactionTagCount));
|
||||
if ($transactionTagCount < $expectedTagCount) {
|
||||
app('log')->debug(sprintf('Transaction has %d tag(s), we expect %d tag(s), return false.', $transactionTagCount, $expectedTagCount));
|
||||
|
||||
return false;
|
||||
}
|
||||
foreach ($transaction['tags'] as $tag) {
|
||||
Log::debug(sprintf('"%s" versus', strtolower($tag['name'])), $list);
|
||||
if (in_array(strtolower($tag['name']), $list, true)) {
|
||||
app('log')->debug(sprintf('Transaction has tag "%s" so count++.', $tag['name']));
|
||||
++$foundTagCount;
|
||||
$journalId = $transaction['transaction_journal_id'];
|
||||
// #8377 prevent adding a transaction twice when multiple tag searches find this transaction
|
||||
if (!in_array($journalId, $includedJournals, true)) {
|
||||
$includedJournals[] = $journalId;
|
||||
$return['transactions'][] = $transaction;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Log::debug(sprintf('Found %d tags, need at least %d.', $foundTagCount, $expectedTagCount));
|
||||
|
||||
// found at least the expected tags.
|
||||
$result = $foundTagCount >= $expectedTagCount;
|
||||
if (true === $result) {
|
||||
return $return;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
$this->postFilters[] = $filter;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit results to any of the tags in the list.
|
||||
*/
|
||||
public function setTags(Collection $tags): GroupCollectorInterface
|
||||
{
|
||||
@@ -683,28 +740,19 @@ trait MetaCollection
|
||||
$list = array_map('strtolower', $list);
|
||||
$filter = static function (array $object) use ($list): bool {
|
||||
Log::debug(sprintf('Now in setTags(%s) filter', implode(', ', $list)));
|
||||
$expectedTagCount = count($list);
|
||||
$foundTagCount = 0;
|
||||
foreach ($object['transactions'] as $transaction) {
|
||||
$transactionTagCount = count($transaction['tags']);
|
||||
app('log')->debug(sprintf('Transaction has %d tag(s)', $transactionTagCount));
|
||||
if ($transactionTagCount < $expectedTagCount) {
|
||||
app('log')->debug(sprintf('Transaction has %d tag(s), we expect %d tag(s), return false.', $transactionTagCount, $expectedTagCount));
|
||||
|
||||
return false;
|
||||
}
|
||||
foreach ($transaction['tags'] as $tag) {
|
||||
Log::debug(sprintf('"%s" versus', strtolower($tag['name'])), $list);
|
||||
if (in_array(strtolower($tag['name']), $list, true)) {
|
||||
app('log')->debug(sprintf('Transaction has tag "%s" so count++.', $tag['name']));
|
||||
++$foundTagCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
Log::debug(sprintf('Found %d tags, need at least %d.', $foundTagCount, $expectedTagCount));
|
||||
app('log')->debug(sprintf('Transaction has tag "%s" so return true.', $tag['name']));
|
||||
|
||||
// found at least the expected tags.
|
||||
return $foundTagCount >= $expectedTagCount;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
app('log')->debug('Transaction has no tags from the list, so return false.');
|
||||
|
||||
return false;
|
||||
};
|
||||
$this->postFilters[] = $filter;
|
||||
|
||||
|
@@ -462,7 +462,7 @@ trait TimeCollection
|
||||
*/
|
||||
public function setBefore(Carbon $date): GroupCollectorInterface
|
||||
{
|
||||
$beforeStr = $date->format('Y-m-d 00:00:00');
|
||||
$beforeStr = $date->format('Y-m-d 23:59:59');
|
||||
$this->query->where('transaction_journals.date', '<=', $beforeStr);
|
||||
|
||||
return $this;
|
||||
|
@@ -25,7 +25,6 @@ namespace FireflyIII\Helpers\Collector;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Carbon\Exceptions\InvalidFormatException;
|
||||
use Exception;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\Extensions\AccountCollection;
|
||||
use FireflyIII\Helpers\Collector\Extensions\AmountCollection;
|
||||
@@ -43,6 +42,7 @@ use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class GroupCollector
|
||||
@@ -105,6 +105,8 @@ class GroupCollector implements GroupCollectorInterface
|
||||
'transaction_groups.created_at as created_at',
|
||||
'transaction_groups.updated_at as updated_at',
|
||||
'transaction_groups.title as transaction_group_title',
|
||||
'transaction_groups.created_at as group_created_at',
|
||||
'transaction_groups.updated_at as group_updated_at',
|
||||
|
||||
// journal
|
||||
'transaction_journals.id as transaction_journal_id',
|
||||
@@ -560,6 +562,7 @@ class GroupCollector implements GroupCollectorInterface
|
||||
if (0 !== count($journalIds)) {
|
||||
// make all integers.
|
||||
$integerIDs = array_map('intval', $journalIds);
|
||||
Log::debug(sprintf('GroupCollector: setJournalIds: %s', implode(', ', $integerIDs)));
|
||||
|
||||
$this->query->whereIn('transaction_journals.id', $integerIDs);
|
||||
}
|
||||
@@ -700,6 +703,8 @@ class GroupCollector implements GroupCollectorInterface
|
||||
'user_group_id' => $augumentedJournal->user_group_id,
|
||||
// Field transaction_group_title was added by the query.
|
||||
'title' => $augumentedJournal->transaction_group_title, // @phpstan-ignore-line
|
||||
'created_at' => new Carbon($augumentedJournal->group_created_at, config('app.timezone')),
|
||||
'updated_at' => new Carbon($augumentedJournal->group_updated_at, config('app.timezone')),
|
||||
'transaction_type' => $parsedGroup['transaction_type_type'],
|
||||
'count' => 1,
|
||||
'sums' => [],
|
||||
@@ -926,7 +931,6 @@ class GroupCollector implements GroupCollectorInterface
|
||||
private function postFilterCollection(Collection $collection): Collection
|
||||
{
|
||||
$currentCollection = $collection;
|
||||
|
||||
app('log')->debug(sprintf('GroupCollector: postFilterCollection has %d filter(s) and %d transaction(s).', count($this->postFilters), count($currentCollection)));
|
||||
|
||||
/**
|
||||
@@ -948,8 +952,15 @@ class GroupCollector implements GroupCollectorInterface
|
||||
// skip other filters, continue to next item.
|
||||
continue;
|
||||
}
|
||||
// if the result is a bool, use the unedited results.
|
||||
if (true === $result) {
|
||||
$nextCollection->push($item);
|
||||
}
|
||||
// if the result is an array, the filter has changed what's being returned.
|
||||
if (is_array($result)) {
|
||||
$nextCollection->push($result);
|
||||
}
|
||||
}
|
||||
$currentCollection = $nextCollection;
|
||||
app('log')->debug(sprintf('GroupCollector: postFilterCollection has %d transaction(s) left.', count($currentCollection)));
|
||||
}
|
||||
|
@@ -559,10 +559,15 @@ interface GroupCollectorInterface
|
||||
public function setTag(Tag $tag): self;
|
||||
|
||||
/**
|
||||
* Limit results to a specific set of tags.
|
||||
* Limit results to any of the specified tags.
|
||||
*/
|
||||
public function setTags(Collection $tags): self;
|
||||
|
||||
/**
|
||||
* Limit results to a SPECIFIC set of tags.
|
||||
*/
|
||||
public function setAllTags(Collection $tags): self;
|
||||
|
||||
/**
|
||||
* Limit the search to one specific transaction group.
|
||||
*/
|
||||
|
@@ -36,6 +36,7 @@ use FireflyIII\Support\Http\Api\ExchangeRateConverter;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* This class can handle both request with and without a user group and will return the appropriate repository when
|
||||
@@ -72,7 +73,7 @@ class NetWorth implements NetWorthInterface
|
||||
return $cache->get();
|
||||
}
|
||||
app('log')->debug(sprintf('Now in byAccounts("%s", "%s")', $ids, $date->format('Y-m-d')));
|
||||
|
||||
Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__));
|
||||
$default = app('amount')->getDefaultCurrency();
|
||||
$converter = new ExchangeRateConverter();
|
||||
|
||||
@@ -86,11 +87,11 @@ class NetWorth implements NetWorthInterface
|
||||
'currency_name' => $default->name,
|
||||
'currency_symbol' => $default->symbol,
|
||||
'currency_decimal_places' => $default->decimal_places,
|
||||
'native_id' => $default->id,
|
||||
'native_code' => $default->code,
|
||||
'native_name' => $default->name,
|
||||
'native_symbol' => $default->symbol,
|
||||
'native_decimal_places' => $default->decimal_places,
|
||||
'native_currency_id' => $default->id,
|
||||
'native_currency_code' => $default->code,
|
||||
'native_currency_name' => $default->name,
|
||||
'native_currency_symbol' => $default->symbol,
|
||||
'native_currency_decimal_places' => $default->decimal_places,
|
||||
],
|
||||
];
|
||||
$balances = app('steam')->balancesByAccountsConverted($accounts, $date);
|
||||
@@ -102,7 +103,7 @@ class NetWorth implements NetWorthInterface
|
||||
if (null === $currency) {
|
||||
$currency = app('amount')->getDefaultCurrency();
|
||||
}
|
||||
$currencyId = $currency->id;
|
||||
$currencyCode = $currency->code;
|
||||
$balance = '0';
|
||||
$nativeBalance = '0';
|
||||
if (array_key_exists($account->id, $balances)) {
|
||||
@@ -117,23 +118,23 @@ class NetWorth implements NetWorthInterface
|
||||
$nativeVirtualBalance = $converter->convert($default, $currency, $account->created_at, $virtualBalance);
|
||||
$nativeBalance = bcsub($nativeBalance, $nativeVirtualBalance);
|
||||
}
|
||||
$netWorth[$currencyId] ??= [
|
||||
$netWorth[$currencyCode] ??= [
|
||||
'balance' => '0',
|
||||
'native_balance' => '0',
|
||||
'currency_id' => $currencyId,
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_name' => $currency->name,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'native_id' => $default->id,
|
||||
'native_code' => $default->code,
|
||||
'native_name' => $default->name,
|
||||
'native_symbol' => $default->symbol,
|
||||
'native_decimal_places' => $default->decimal_places,
|
||||
'native_currency_id' => (string) $default->id,
|
||||
'native_currency_code' => $default->code,
|
||||
'native_currency_name' => $default->name,
|
||||
'native_currency_symbol' => $default->symbol,
|
||||
'native_currency_decimal_places' => $default->decimal_places,
|
||||
];
|
||||
|
||||
$netWorth[$currencyId]['balance'] = bcadd($balance, $netWorth[$currencyId]['balance']);
|
||||
$netWorth[$currencyId]['native_balance'] = bcadd($nativeBalance, $netWorth[$currencyId]['native_balance']);
|
||||
$netWorth[$currencyCode]['balance'] = bcadd($balance, $netWorth[$currencyCode]['balance']);
|
||||
$netWorth[$currencyCode]['native_balance'] = bcadd($nativeBalance, $netWorth[$currencyCode]['native_balance']);
|
||||
$netWorth['native']['balance'] = bcadd($nativeBalance, $netWorth['native']['balance']);
|
||||
$netWorth['native']['native_balance'] = bcadd($nativeBalance, $netWorth['native']['native_balance']);
|
||||
}
|
||||
@@ -188,7 +189,7 @@ class NetWorth implements NetWorthInterface
|
||||
}
|
||||
|
||||
$return[$currency->id] ??= [
|
||||
'id' => (string)$currency->id,
|
||||
'id' => (string) $currency->id,
|
||||
'name' => $currency->name,
|
||||
'symbol' => $currency->symbol,
|
||||
'code' => $currency->code,
|
||||
@@ -219,7 +220,7 @@ class NetWorth implements NetWorthInterface
|
||||
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
if (1 === (int)$this->getRepository()->getMetaValue($account, 'include_net_worth')) {
|
||||
if (1 === (int) $this->getRepository()->getMetaValue($account, 'include_net_worth')) {
|
||||
$filtered->push($account);
|
||||
}
|
||||
}
|
||||
|
@@ -58,7 +58,7 @@ class CreateController extends Controller
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
app('view')->share('mainTitleIcon', 'fa-credit-card');
|
||||
app('view')->share('title', (string)trans('firefly.accounts'));
|
||||
app('view')->share('title', (string) trans('firefly.accounts'));
|
||||
|
||||
$this->repository = app(AccountRepositoryInterface::class);
|
||||
$this->attachments = app(AttachmentHelperInterface::class);
|
||||
@@ -77,7 +77,7 @@ class CreateController extends Controller
|
||||
{
|
||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||
$subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $objectType));
|
||||
$subTitle = (string)trans(sprintf('firefly.make_new_%s_account', $objectType));
|
||||
$subTitle = (string) trans(sprintf('firefly.make_new_%s_account', $objectType));
|
||||
$roles = $this->getRoles();
|
||||
$liabilityTypes = $this->getLiabilityTypes();
|
||||
$hasOldInput = null !== $request->old('_token');
|
||||
@@ -96,9 +96,9 @@ class CreateController extends Controller
|
||||
|
||||
// interest calculation periods:
|
||||
$interestPeriods = [
|
||||
'daily' => (string)trans('firefly.interest_calc_daily'),
|
||||
'monthly' => (string)trans('firefly.interest_calc_monthly'),
|
||||
'yearly' => (string)trans('firefly.interest_calc_yearly'),
|
||||
'daily' => (string) trans('firefly.interest_calc_daily'),
|
||||
'monthly' => (string) trans('firefly.interest_calc_monthly'),
|
||||
'yearly' => (string) trans('firefly.interest_calc_yearly'),
|
||||
];
|
||||
|
||||
// pre fill some data
|
||||
@@ -106,9 +106,14 @@ class CreateController extends Controller
|
||||
'preFilled',
|
||||
[
|
||||
'currency_id' => $defaultCurrency->id,
|
||||
'include_net_worth' => $hasOldInput ? (bool)$request->old('include_net_worth') : true,
|
||||
'include_net_worth' => $hasOldInput ? (bool) $request->old('include_net_worth') : true,
|
||||
]
|
||||
);
|
||||
// issue #8321
|
||||
$showNetWorth = true;
|
||||
if ('liabilities' !== $objectType && 'asset' !== $objectType) {
|
||||
$showNetWorth = false;
|
||||
}
|
||||
|
||||
// put previous url in session if not redirect from store (not "create another").
|
||||
if (true !== session('accounts.create.fromStore')) {
|
||||
@@ -119,7 +124,7 @@ class CreateController extends Controller
|
||||
|
||||
return view(
|
||||
'accounts.create',
|
||||
compact('subTitleIcon', 'liabilityDirections', 'locations', 'objectType', 'interestPeriods', 'subTitle', 'roles', 'liabilityTypes')
|
||||
compact('subTitleIcon', 'liabilityDirections', 'showNetWorth', 'locations', 'objectType', 'interestPeriods', 'subTitle', 'roles', 'liabilityTypes')
|
||||
);
|
||||
}
|
||||
|
||||
@@ -134,7 +139,7 @@ class CreateController extends Controller
|
||||
{
|
||||
$data = $request->getAccountData();
|
||||
$account = $this->repository->store($data);
|
||||
$request->session()->flash('success', (string)trans('firefly.stored_new_account', ['name' => $account->name]));
|
||||
$request->session()->flash('success', (string) trans('firefly.stored_new_account', ['name' => $account->name]));
|
||||
app('preferences')->mark();
|
||||
|
||||
Log::channel('audit')->info('Stored new account.', $data);
|
||||
@@ -156,7 +161,8 @@ class CreateController extends Controller
|
||||
$this->attachments->saveAttachmentsForModel($account, $files);
|
||||
}
|
||||
if (null !== $files && auth()->user()->hasRole('demo')) {
|
||||
session()->flash('info', (string)trans('firefly.no_att_demo_user'));
|
||||
Log::channel('audit')->warning(sprintf('The demo user is trying to upload attachments in %s.', __METHOD__));
|
||||
session()->flash('info', (string) trans('firefly.no_att_demo_user'));
|
||||
}
|
||||
|
||||
if (count($this->attachments->getMessages()->get('attachments')) > 0) {
|
||||
@@ -165,7 +171,7 @@ class CreateController extends Controller
|
||||
|
||||
// redirect to previous URL.
|
||||
$redirect = redirect($this->getPreviousUrl('accounts.create.url'));
|
||||
if (1 === (int)$request->get('create_another')) {
|
||||
if (1 === (int) $request->get('create_another')) {
|
||||
// set value so create routine will not overwrite URL:
|
||||
$request->session()->put('accounts.create.fromStore', true);
|
||||
|
||||
|
@@ -33,6 +33,7 @@ use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\View\View;
|
||||
|
||||
/**
|
||||
@@ -127,6 +128,12 @@ class EditController extends Controller
|
||||
$includeNetWorth = $repository->getMetaValue($account, 'include_net_worth');
|
||||
$includeNetWorth = null === $includeNetWorth ? true : '1' === $includeNetWorth;
|
||||
|
||||
// issue #8321
|
||||
$showNetWorth = true;
|
||||
if ('liabilities' !== $objectType && 'asset' !== $objectType) {
|
||||
$showNetWorth = false;
|
||||
}
|
||||
|
||||
// code to handle active-checkboxes
|
||||
$hasOldInput = null !== $request->old('_token');
|
||||
$virtualBalance = null === $account->virtual_balance ? '0' : $account->virtual_balance;
|
||||
@@ -154,7 +161,7 @@ class EditController extends Controller
|
||||
|
||||
$request->session()->flash('preFilled', $preFilled);
|
||||
|
||||
return view('accounts.edit', compact('account', 'currency', 'subTitle', 'subTitleIcon', 'locations', 'liabilityDirections', 'objectType', 'roles', 'preFilled', 'liabilityTypes', 'interestPeriods'));
|
||||
return view('accounts.edit', compact('account', 'currency', 'showNetWorth', 'subTitle', 'subTitleIcon', 'locations', 'liabilityDirections', 'objectType', 'roles', 'preFilled', 'liabilityTypes', 'interestPeriods'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,7 +177,7 @@ class EditController extends Controller
|
||||
|
||||
$data = $request->getAccountData();
|
||||
$this->repository->update($account, $data);
|
||||
|
||||
Log::channel('audit')->info(sprintf('Updated account #%d.', $account->id), $data);
|
||||
$request->session()->flash('success', (string) trans('firefly.updated_account', ['name' => $account->name]));
|
||||
|
||||
// store new attachment(s):
|
||||
@@ -180,6 +187,7 @@ class EditController extends Controller
|
||||
$this->attachments->saveAttachmentsForModel($account, $files);
|
||||
}
|
||||
if (null !== $files && auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->warning(sprintf('The demo user is trying to upload attachments in %s.', __METHOD__));
|
||||
session()->flash('info', (string) trans('firefly.no_att_demo_user'));
|
||||
}
|
||||
|
||||
|
@@ -78,7 +78,7 @@ class LoginController extends Controller
|
||||
public function login(Request $request): JsonResponse|RedirectResponse
|
||||
{
|
||||
Log::channel('audit')->info(sprintf('User is trying to login using "%s"', $request->get($this->username())));
|
||||
app('log')->info('User is trying to login.');
|
||||
app('log')->debug('User is trying to login.');
|
||||
|
||||
$this->validateLogin($request);
|
||||
app('log')->debug('Login data is present.');
|
||||
@@ -88,7 +88,7 @@ class LoginController extends Controller
|
||||
// the login attempts for this application. We'll key this by the username and
|
||||
// the IP address of the client making these requests into this application.
|
||||
if ($this->hasTooManyLoginAttempts($request)) {
|
||||
Log::channel('audit')->info(sprintf('Login for user "%s" was locked out.', $request->get($this->username())));
|
||||
Log::channel('audit')->warning(sprintf('Login for user "%s" was locked out.', $request->get($this->username())));
|
||||
app('log')->error(sprintf('Login for user "%s" was locked out.', $request->get($this->username())));
|
||||
$this->fireLockoutEvent($request);
|
||||
|
||||
@@ -114,7 +114,7 @@ class LoginController extends Controller
|
||||
// to login and redirect the user back to the login form. Of course, when this
|
||||
// user surpasses their maximum number of attempts they will get locked out.
|
||||
$this->incrementLoginAttempts($request);
|
||||
Log::channel('audit')->info(sprintf('Login failed. Attempt for user "%s" failed.', $request->get($this->username())));
|
||||
Log::channel('audit')->warning(sprintf('Login failed. Attempt for user "%s" failed.', $request->get($this->username())));
|
||||
|
||||
$this->sendFailedLoginResponse($request);
|
||||
|
||||
|
@@ -33,6 +33,7 @@ use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class CreateController
|
||||
@@ -104,6 +105,8 @@ class CreateController extends Controller
|
||||
|
||||
return redirect(route('bills.create'))->withInput();
|
||||
}
|
||||
|
||||
Log::channel('audit')->info('Stored new bill.', $billData);
|
||||
$request->session()->flash('success', (string)trans('firefly.stored_new_bill', ['name' => $bill->name]));
|
||||
app('preferences')->mark();
|
||||
|
||||
@@ -113,6 +116,7 @@ class CreateController extends Controller
|
||||
$this->attachments->saveAttachmentsForModel($bill, $files);
|
||||
}
|
||||
if (null !== $files && auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->warning(sprintf('The demo user is trying to upload attachments in %s.', __METHOD__));
|
||||
session()->flash('info', (string)trans('firefly.no_att_demo_user'));
|
||||
}
|
||||
|
||||
|
@@ -33,6 +33,7 @@ use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class EditController
|
||||
@@ -51,7 +52,7 @@ class EditController extends Controller
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
app('view')->share('title', (string)trans('firefly.bills'));
|
||||
app('view')->share('title', (string) trans('firefly.bills'));
|
||||
app('view')->share('mainTitleIcon', 'fa-calendar-o');
|
||||
$this->attachments = app(AttachmentHelperInterface::class);
|
||||
$this->repository = app(BillRepositoryInterface::class);
|
||||
@@ -74,10 +75,10 @@ class EditController extends Controller
|
||||
$billPeriods = config('firefly.bill_periods');
|
||||
|
||||
foreach ($billPeriods as $current) {
|
||||
$periods[$current] = (string)trans('firefly.'.$current);
|
||||
$periods[$current] = (string) trans('firefly.'.$current);
|
||||
}
|
||||
|
||||
$subTitle = (string)trans('firefly.edit_bill', ['name' => $bill->name]);
|
||||
$subTitle = (string) trans('firefly.edit_bill', ['name' => $bill->name]);
|
||||
|
||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||
if (true !== session('bills.edit.fromUpdate')) {
|
||||
@@ -98,7 +99,7 @@ class EditController extends Controller
|
||||
'extension_date' => $bill->extension_date,
|
||||
'notes' => $this->repository->getNoteText($bill),
|
||||
'transaction_currency_id' => $bill->transaction_currency_id,
|
||||
'active' => $hasOldInput ? (bool)$request->old('active') : $bill->active,
|
||||
'active' => $hasOldInput ? (bool) $request->old('active') : $bill->active,
|
||||
'object_group' => null !== $bill->objectGroups->first() ? $bill->objectGroups->first()->title : '',
|
||||
];
|
||||
|
||||
@@ -116,7 +117,9 @@ class EditController extends Controller
|
||||
$billData = $request->getBillData();
|
||||
$bill = $this->repository->update($bill, $billData);
|
||||
|
||||
$request->session()->flash('success', (string)trans('firefly.updated_bill', ['name' => $bill->name]));
|
||||
Log::channel('audit')->info(sprintf('Updated bill #%d.', $bill->id), $billData);
|
||||
|
||||
$request->session()->flash('success', (string) trans('firefly.updated_bill', ['name' => $bill->name]));
|
||||
app('preferences')->mark();
|
||||
|
||||
/** @var null|array $files */
|
||||
@@ -125,7 +128,8 @@ class EditController extends Controller
|
||||
$this->attachments->saveAttachmentsForModel($bill, $files);
|
||||
}
|
||||
if (null !== $files && auth()->user()->hasRole('demo')) {
|
||||
session()->flash('info', (string)trans('firefly.no_att_demo_user'));
|
||||
Log::channel('audit')->warning(sprintf('The demo user is trying to upload attachments in %s.', __METHOD__));
|
||||
session()->flash('info', (string) trans('firefly.no_att_demo_user'));
|
||||
}
|
||||
|
||||
// flash messages
|
||||
@@ -134,7 +138,7 @@ class EditController extends Controller
|
||||
}
|
||||
$redirect = redirect($this->getPreviousUrl('bills.edit.url'));
|
||||
|
||||
if (1 === (int)$request->get('return_to_edit')) {
|
||||
if (1 === (int) $request->get('return_to_edit')) {
|
||||
$request->session()->put('bills.edit.fromUpdate', true);
|
||||
|
||||
$redirect = redirect(route('bills.edit', [$bill->id]))->withInput(['return_to_edit' => 1]);
|
||||
|
@@ -202,7 +202,9 @@ class BudgetLimitController extends Controller
|
||||
if ('' === $amount) {
|
||||
$amount = '0';
|
||||
}
|
||||
|
||||
if ((int)$amount > 268435456) { // 268 million, intentional integer
|
||||
$amount = '268435456';
|
||||
}
|
||||
// sanity check on amount:
|
||||
if (0 === bccomp($amount, '0')) {
|
||||
$budgetId = $budgetLimit->budget_id;
|
||||
@@ -217,9 +219,7 @@ class BudgetLimitController extends Controller
|
||||
|
||||
return response()->json($array);
|
||||
}
|
||||
if ((int)$amount > 268435456) { // 268 million, intentional integer
|
||||
$amount = '268435456';
|
||||
}
|
||||
|
||||
if (-1 === bccomp($amount, '0')) {
|
||||
$amount = bcmul($amount, '-1');
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user