mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-08-17 19:26:40 +00:00
Compare commits
122 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 | ||
|
5b11c86113 |
13
.ci/php-cs-fixer/composer.lock
generated
13
.ci/php-cs-fixer/composer.lock
generated
@@ -226,21 +226,22 @@
|
||||
},
|
||||
{
|
||||
"name": "friendsofphp/php-cs-fixer",
|
||||
"version": "v3.45.0",
|
||||
"version": "v3.48.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
|
||||
"reference": "c0daa33cb2533cd73f48dde1c70c2afa3e7953b5"
|
||||
"reference": "a92472c6fb66349de25211f31c77eceae3df024e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/c0daa33cb2533cd73f48dde1c70c2afa3e7953b5",
|
||||
"reference": "c0daa33cb2533cd73f48dde1c70c2afa3e7953b5",
|
||||
"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",
|
||||
@@ -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.45.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-30T02:07:07+00:00"
|
||||
"time": "2024-01-19T21:44:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
|
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
|
||||
#
|
||||
|
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/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
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -67,7 +67,7 @@ class DestroyController extends Controller
|
||||
public function destroy(Attachment $attachment): JsonResponse
|
||||
{
|
||||
if(true === auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->info(sprintf('Demo user tries to access attachment API in %s', __METHOD__));
|
||||
Log::channel('audit')->warning(sprintf('Demo user tries to access attachment API in %s', __METHOD__));
|
||||
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
|
@@ -76,7 +76,7 @@ class ShowController extends Controller
|
||||
public function download(Attachment $attachment): LaravelResponse
|
||||
{
|
||||
if(true === auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->info(sprintf('Demo user tries to access attachment API in %s', __METHOD__));
|
||||
Log::channel('audit')->warning(sprintf('Demo user tries to access attachment API in %s', __METHOD__));
|
||||
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
@@ -124,7 +124,7 @@ class ShowController extends Controller
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
if(true === auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->info(sprintf('Demo user tries to access attachment API in %s', __METHOD__));
|
||||
Log::channel('audit')->warning(sprintf('Demo user tries to access attachment API in %s', __METHOD__));
|
||||
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
@@ -162,7 +162,7 @@ class ShowController extends Controller
|
||||
public function show(Attachment $attachment): JsonResponse
|
||||
{
|
||||
if(true === auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->info(sprintf('Demo user tries to access attachment API in %s', __METHOD__));
|
||||
Log::channel('audit')->warning(sprintf('Demo user tries to access attachment API in %s', __METHOD__));
|
||||
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
|
@@ -75,7 +75,7 @@ class StoreController extends Controller
|
||||
public function store(StoreRequest $request): JsonResponse
|
||||
{
|
||||
if(true === auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->info(sprintf('Demo user tries to access attachment API in %s', __METHOD__));
|
||||
Log::channel('audit')->warning(sprintf('Demo user tries to access attachment API in %s', __METHOD__));
|
||||
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
@@ -99,7 +99,7 @@ class StoreController extends Controller
|
||||
public function upload(Request $request, Attachment $attachment): JsonResponse
|
||||
{
|
||||
if(true === auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->info(sprintf('Demo user tries to access attachment API in %s', __METHOD__));
|
||||
Log::channel('audit')->warning(sprintf('Demo user tries to access attachment API in %s', __METHOD__));
|
||||
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
|
@@ -70,7 +70,7 @@ class UpdateController extends Controller
|
||||
public function update(UpdateRequest $request, Attachment $attachment): JsonResponse
|
||||
{
|
||||
if(true === auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->info(sprintf('Demo user tries to access attachment API in %s', __METHOD__));
|
||||
Log::channel('audit')->warning(sprintf('Demo user tries to access attachment API in %s', __METHOD__));
|
||||
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
|
@@ -71,7 +71,7 @@ class AttemptController extends Controller
|
||||
throw new FireflyException('200040: Webhook and webhook message are no match');
|
||||
}
|
||||
if(false === config('firefly.allow_webhooks')) {
|
||||
Log::channel('audit')->info(sprintf('User lists webhook attempts of webhook #%d and message #%d, but webhooks are DISABLED.', $webhook->id, $message->id));
|
||||
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.');
|
||||
}
|
||||
@@ -115,7 +115,7 @@ class AttemptController extends Controller
|
||||
}
|
||||
|
||||
if(false === config('firefly.allow_webhooks')) {
|
||||
Log::channel('audit')->info(sprintf('User views single webhook attempt #%d of webhook #%d and message #%d, but webhooks are DISABLED', $attempt->id, $webhook->id, $message->id));
|
||||
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.');
|
||||
}
|
||||
|
@@ -63,7 +63,7 @@ class DestroyController extends Controller
|
||||
public function destroy(Webhook $webhook): JsonResponse
|
||||
{
|
||||
if(false === config('firefly.allow_webhooks')) {
|
||||
Log::channel('audit')->info(sprintf('User tries to destroy webhook #%d. but webhooks are DISABLED.', $webhook->id));
|
||||
Log::channel('audit')->warning(sprintf('User tries to destroy webhook #%d. but webhooks are DISABLED.', $webhook->id));
|
||||
|
||||
throw new NotFoundHttpException('Webhooks are not enabled.');
|
||||
}
|
||||
@@ -93,7 +93,7 @@ class DestroyController extends Controller
|
||||
}
|
||||
|
||||
if (false === config('firefly.allow_webhooks')) {
|
||||
Log::channel('audit')->info(sprintf('User tries to destroy webhook #%d, message #%d, attempt #%d, but webhooks are DISABLED.', $webhook->id, $message->id, $attempt->id));
|
||||
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.');
|
||||
}
|
||||
@@ -121,7 +121,7 @@ class DestroyController extends Controller
|
||||
}
|
||||
|
||||
if(false === config('firefly.allow_webhooks')) {
|
||||
Log::channel('audit')->info(sprintf('User tries to destroy webhook #%d, message #%d, but webhooks are DISABLED.', $webhook->id, $message->id));
|
||||
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.');
|
||||
}
|
||||
|
@@ -67,7 +67,7 @@ class MessageController extends Controller
|
||||
public function index(Webhook $webhook): JsonResponse
|
||||
{
|
||||
if(false === config('firefly.allow_webhooks')) {
|
||||
Log::channel('audit')->info(sprintf('User tries to view messages of webhook #%d, but webhooks are DISABLED.', $webhook->id));
|
||||
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.');
|
||||
}
|
||||
@@ -107,7 +107,7 @@ class MessageController extends Controller
|
||||
throw new FireflyException('200040: Webhook and webhook message are no match');
|
||||
}
|
||||
if(false === config('firefly.allow_webhooks')) {
|
||||
Log::channel('audit')->info(sprintf('User tries to view message #%d of webhook #%d, but webhooks are DISABLED.', $message->id, $webhook->id));
|
||||
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.');
|
||||
}
|
||||
|
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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',
|
||||
];
|
||||
|
@@ -101,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',
|
||||
@@ -117,9 +117,9 @@ class StoreRequest extends FormRequest
|
||||
'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)],
|
||||
];
|
||||
|
@@ -28,6 +28,7 @@ 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;
|
||||
|
||||
/**
|
||||
@@ -87,5 +88,8 @@ class Request extends FormRequest
|
||||
}
|
||||
}
|
||||
);
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -29,6 +29,7 @@ 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;
|
||||
|
||||
/**
|
||||
@@ -72,7 +73,7 @@ class StoreRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'between:1,255|uniqueObjectForUser:bills,name',
|
||||
'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',
|
||||
@@ -81,9 +82,9 @@ class StoreRequest extends FormRequest
|
||||
'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',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -103,5 +104,8 @@ class StoreRequest extends FormRequest
|
||||
}
|
||||
}
|
||||
);
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -30,6 +30,7 @@ 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;
|
||||
|
||||
/**
|
||||
@@ -75,7 +76,7 @@ class UpdateRequest extends FormRequest
|
||||
$bill = $this->route()->parameter('bill');
|
||||
|
||||
return [
|
||||
'name' => sprintf('between:1,255|uniqueObjectForUser:bills,name,%d', $bill->id),
|
||||
'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',
|
||||
@@ -84,9 +85,9 @@ class UpdateRequest extends FormRequest
|
||||
'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',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -108,5 +109,8 @@ class UpdateRequest extends FormRequest
|
||||
}
|
||||
}
|
||||
);
|
||||
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\Validation\AutoBudget\ValidatesAutoBudgetRequest;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
@@ -68,11 +69,11 @@ 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' => ['required_if:auto_budget_type,reset', 'required_if:auto_budget_type,rollover', 'required_if:auto_budget_type,adjusted', new IsValidPositiveAmount()],
|
||||
@@ -91,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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -30,6 +30,7 @@ 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;
|
||||
|
||||
/**
|
||||
@@ -81,9 +82,9 @@ 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',
|
||||
@@ -103,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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -28,6 +28,7 @@ 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;
|
||||
|
||||
/**
|
||||
@@ -70,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
|
||||
{
|
||||
@@ -84,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),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -64,11 +64,11 @@ class StoreRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'required|between:1,255|uniquePiggyBankForUser',
|
||||
'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',
|
||||
'object_group_title' => ['min:1', 'max:255'],
|
||||
'target_amount' => ['required', new IsValidPositiveAmount()],
|
||||
'start_date' => 'date|nullable',
|
||||
'target_date' => 'date|nullable|after:start_date',
|
||||
|
@@ -69,7 +69,7 @@ class UpdateRequest extends FormRequest
|
||||
$piggyBank = $this->route()->parameter('piggyBank');
|
||||
|
||||
return [
|
||||
'name' => 'between:1,255|uniquePiggyBankForUser:'.$piggyBank->id,
|
||||
'name' => 'min:1|max:255|uniquePiggyBankForUser:'.$piggyBank->id,
|
||||
'current_amount' => ['nullable', new LessThanPiggyTarget(), new IsValidPositiveAmount()],
|
||||
'target_amount' => ['nullable', new IsValidPositiveAmount()],
|
||||
'start_date' => 'date|nullable',
|
||||
|
@@ -33,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;
|
||||
|
||||
/**
|
||||
@@ -79,20 +80,20 @@ 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.*.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',
|
||||
@@ -100,18 +101,18 @@ class StoreRequest extends FormRequest
|
||||
'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,255',
|
||||
'transactions.*.piggy_bank_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()],
|
||||
'transactions.*.tags' => 'nullable|min:1|max:255',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -131,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());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -34,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;
|
||||
|
||||
/**
|
||||
@@ -86,20 +87,20 @@ 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.*.description' => ['min:1', 'max:255'],
|
||||
'transactions.*.amount' => [new IsValidPositiveAmount()],
|
||||
'transactions.*.foreign_amount' => ['nullable', new IsValidPositiveAmount()],
|
||||
'transactions.*.currency_id' => 'nullable|numeric|exists:transaction_currencies,id',
|
||||
@@ -107,18 +108,18 @@ class UpdateRequest extends FormRequest
|
||||
'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,255',
|
||||
'transactions.*.piggy_bank_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()],
|
||||
'transactions.*.tags' => 'nullable|min:1|max:255',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -141,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());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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',
|
||||
];
|
||||
|
||||
|
@@ -28,6 +28,7 @@ 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;
|
||||
@@ -36,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;
|
||||
|
||||
/**
|
||||
@@ -77,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()],
|
||||
|
||||
@@ -94,40 +96,40 @@ class StoreRequest extends FormRequest
|
||||
|
||||
// amount
|
||||
'transactions.*.amount' => ['required', new IsValidPositiveAmount()],
|
||||
'transactions.*.foreign_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_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.*.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',
|
||||
@@ -190,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());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -36,6 +36,7 @@ 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;
|
||||
|
||||
/**
|
||||
@@ -99,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):
|
||||
@@ -121,29 +122,29 @@ class UpdateRequest extends FormRequest
|
||||
'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.*.tags.*' => 'between:0,255',
|
||||
'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',
|
||||
@@ -205,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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -77,11 +77,7 @@ class BudgetController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DateRequest $request
|
||||
*
|
||||
* TODO see autocomplete/accountcontroller
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function dashboard(DateRequest $request): JsonResponse
|
||||
{
|
||||
|
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);
|
||||
}
|
||||
}
|
@@ -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,81 +92,84 @@ class StoreRequest extends FormRequest
|
||||
|
||||
return [
|
||||
// basic fields for group:
|
||||
'group_title' => 'between:1,1000|nullable',
|
||||
'error_if_duplicate_hash' => [new IsBoolean()],
|
||||
'apply_rules' => [new IsBoolean()],
|
||||
'group_title' => 'min:1|max:1000|nullable',
|
||||
'error_if_duplicate_hash' => [new IsBoolean()],
|
||||
'apply_rules' => [new IsBoolean()],
|
||||
|
||||
// transaction rules (in array for splits):
|
||||
'transactions.*.type' => 'required|in:withdrawal,deposit,transfer,opening-balance,reconciliation',
|
||||
'transactions.*.date' => ['required', new IsDateOrTime()],
|
||||
'transactions.*.order' => 'numeric|min:0',
|
||||
'transactions.*.type' => 'required|in:withdrawal,deposit,transfer,opening-balance,reconciliation',
|
||||
'transactions.*.date' => ['required', new IsDateOrTime()],
|
||||
'transactions.*.order' => 'numeric|min:0',
|
||||
|
||||
// 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' => 'numeric|exists:transaction_currencies,id|nullable',
|
||||
'transactions.*.foreign_currency_code' => 'min:3|max:51|exists:transaction_currencies,code|nullable',
|
||||
'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' => 'numeric|exists:transaction_currencies,id|nullable',
|
||||
'transactions.*.foreign_currency_code' => 'min:3|max:51|exists:transaction_currencies,code|nullable',
|
||||
|
||||
// amount
|
||||
'transactions.*.amount' => 'required|numeric|gt:0|max:1000000000',
|
||||
'transactions.*.foreign_amount' => 'numeric|gt:0|max:1000000000',
|
||||
'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_id' => ['numeric', 'nullable', new BelongsUserGroup($userGroup)],
|
||||
'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_id' => ['numeric', 'nullable', new BelongsUserGroup($userGroup)],
|
||||
'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.*.category_id' => ['mustExist:categories,id', new BelongsUserGroup($userGroup), 'nullable'],
|
||||
'transactions.*.category_name' => 'between:1,255|nullable',
|
||||
'transactions.*.bill_id' => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUserGroup($userGroup)],
|
||||
'transactions.*.bill_name' => ['between:1,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.*.budget_id' => ['mustExist:budgets,id', 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' => 'min:1|max:255|nullable',
|
||||
'transactions.*.bill_id' => ['numeric', 'nullable', 'mustExist:bills,id', 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' => ['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.*.reconciled' => [new IsBoolean()],
|
||||
'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',
|
||||
'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' => 'min:1|max:255|nullable|url',
|
||||
'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' => 'min:1|max:255|nullable|url',
|
||||
|
||||
// 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',
|
||||
'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',
|
||||
'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',
|
||||
|
||||
// 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(
|
||||
|
@@ -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();
|
||||
@@ -360,16 +376,13 @@ class TransactionJournalFactory
|
||||
->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));
|
||||
}
|
||||
|
@@ -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();
|
||||
@@ -682,6 +682,7 @@ trait MetaCollection
|
||||
$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'] = [];
|
||||
@@ -701,7 +702,12 @@ trait MetaCollection
|
||||
if (in_array(strtolower($tag['name']), $list, true)) {
|
||||
app('log')->debug(sprintf('Transaction has tag "%s" so count++.', $tag['name']));
|
||||
++$foundTagCount;
|
||||
$return['transactions'][] = $transaction;
|
||||
$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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
@@ -106,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',
|
||||
@@ -702,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' => [],
|
||||
@@ -928,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)));
|
||||
|
||||
/**
|
||||
@@ -951,11 +953,11 @@ class GroupCollector implements GroupCollectorInterface
|
||||
continue;
|
||||
}
|
||||
// if the result is a bool, use the unedited results.
|
||||
if(true === $result) {
|
||||
if (true === $result) {
|
||||
$nextCollection->push($item);
|
||||
}
|
||||
// if the result is an array, the filter has changed what's being returned.
|
||||
if(is_array($result)) {
|
||||
if (is_array($result)) {
|
||||
$nextCollection->push($result);
|
||||
}
|
||||
}
|
||||
|
@@ -161,7 +161,7 @@ class CreateController extends Controller
|
||||
$this->attachments->saveAttachmentsForModel($account, $files);
|
||||
}
|
||||
if (null !== $files && auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->info(sprintf('The demo user is trying to upload attachments in %s.', __METHOD__));
|
||||
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'));
|
||||
}
|
||||
|
||||
|
@@ -187,7 +187,7 @@ class EditController extends Controller
|
||||
$this->attachments->saveAttachmentsForModel($account, $files);
|
||||
}
|
||||
if (null !== $files && auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->info(sprintf('The demo user is trying to upload attachments in %s.', __METHOD__));
|
||||
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);
|
||||
|
||||
|
@@ -116,7 +116,7 @@ class CreateController extends Controller
|
||||
$this->attachments->saveAttachmentsForModel($bill, $files);
|
||||
}
|
||||
if (null !== $files && auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->info(sprintf('The demo user is trying to upload attachments in %s.', __METHOD__));
|
||||
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'));
|
||||
}
|
||||
|
||||
|
@@ -128,7 +128,7 @@ class EditController extends Controller
|
||||
$this->attachments->saveAttachmentsForModel($bill, $files);
|
||||
}
|
||||
if (null !== $files && auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->info(sprintf('The demo user is trying to upload attachments in %s.', __METHOD__));
|
||||
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'));
|
||||
}
|
||||
|
||||
|
@@ -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');
|
||||
}
|
||||
|
@@ -127,7 +127,7 @@ class CreateController extends Controller
|
||||
$this->attachments->saveAttachmentsForModel($budget, $files);
|
||||
}
|
||||
if (null !== $files && auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->info(sprintf('The demo user is trying to upload attachments in %s.', __METHOD__));
|
||||
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'));
|
||||
}
|
||||
|
||||
|
@@ -137,7 +137,7 @@ class EditController extends Controller
|
||||
$this->attachments->saveAttachmentsForModel($budget, $files);
|
||||
}
|
||||
if (null !== $files && auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->info(sprintf('The demo user is trying to upload attachments in %s.', __METHOD__));
|
||||
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'));
|
||||
}
|
||||
|
||||
|
@@ -100,7 +100,7 @@ class CreateController extends Controller
|
||||
$this->attachments->saveAttachmentsForModel($category, $files);
|
||||
}
|
||||
if (null !== $files && auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->info(sprintf('The demo user is trying to upload attachments in %s.', __METHOD__));
|
||||
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'));
|
||||
}
|
||||
|
||||
|
@@ -104,7 +104,7 @@ class EditController extends Controller
|
||||
$this->attachments->saveAttachmentsForModel($category, $files);
|
||||
}
|
||||
if (null !== $files && auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->info(sprintf('The demo user is trying to upload attachments in %s.', __METHOD__));
|
||||
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'));
|
||||
}
|
||||
|
||||
|
@@ -108,7 +108,7 @@ class ReportController extends Controller
|
||||
continue;
|
||||
}
|
||||
$currencyId = $netWorthItem['currency_id'];
|
||||
$label = $current->isoFormat((string) trans('config.month_and_day_js', [], $locale));
|
||||
$label = $current->isoFormat((string)trans('config.month_and_day_js', [], $locale));
|
||||
if (!array_key_exists($currencyId, $chartData)) {
|
||||
$chartData[$currencyId] = [
|
||||
'label' => 'Net worth in '.$netWorthItem['currency_name'],
|
||||
@@ -145,6 +145,7 @@ class ReportController extends Controller
|
||||
if ($cache->has()) {
|
||||
return response()->json($cache->get());
|
||||
}
|
||||
|
||||
app('log')->debug('Going to do operations for accounts ', $accounts->pluck('id')->toArray());
|
||||
$format = app('navigation')->preferredCarbonFormat($start, $end);
|
||||
$titleFormat = app('navigation')->preferredCarbonLocalizedFormat($start, $end);
|
||||
@@ -164,13 +165,13 @@ class ReportController extends Controller
|
||||
/** @var array $journal */
|
||||
foreach ($journals as $journal) {
|
||||
$period = $journal['date']->format($format);
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$currencyId = (int)$journal['currency_id'];
|
||||
$data[$currencyId] ??= [
|
||||
'currency_id' => $currencyId,
|
||||
'currency_symbol' => $journal['currency_symbol'],
|
||||
'currency_code' => $journal['currency_code'],
|
||||
'currency_name' => $journal['currency_name'],
|
||||
'currency_decimal_places' => (int) $journal['currency_decimal_places'],
|
||||
'currency_decimal_places' => (int)$journal['currency_decimal_places'],
|
||||
];
|
||||
$data[$currencyId][$period] ??= [
|
||||
'period' => $period,
|
||||
@@ -193,7 +194,7 @@ class ReportController extends Controller
|
||||
/** @var array $currency */
|
||||
foreach ($data as $currency) {
|
||||
$income = [
|
||||
'label' => (string) trans('firefly.box_earned_in_currency', ['currency' => $currency['currency_name']]),
|
||||
'label' => (string)trans('firefly.box_earned_in_currency', ['currency' => $currency['currency_name']]),
|
||||
'type' => 'bar',
|
||||
'backgroundColor' => 'rgba(0, 141, 76, 0.5)', // green
|
||||
'currency_id' => $currency['currency_id'],
|
||||
@@ -202,7 +203,7 @@ class ReportController extends Controller
|
||||
'entries' => [],
|
||||
];
|
||||
$expense = [
|
||||
'label' => (string) trans('firefly.box_spent_in_currency', ['currency' => $currency['currency_name']]),
|
||||
'label' => (string)trans('firefly.box_spent_in_currency', ['currency' => $currency['currency_name']]),
|
||||
'type' => 'bar',
|
||||
'backgroundColor' => 'rgba(219, 68, 55, 0.5)', // red
|
||||
'currency_id' => $currency['currency_id'],
|
||||
@@ -212,7 +213,13 @@ class ReportController extends Controller
|
||||
];
|
||||
// loop all possible periods between $start and $end
|
||||
$currentStart = clone $start;
|
||||
while ($currentStart <= $end) {
|
||||
$currentEnd = clone $end;
|
||||
|
||||
// #8374. Sloppy fix for yearly charts. Not really interested in a better fix with v2 layout and all.
|
||||
if ('1Y' === $preferredRange) {
|
||||
$currentEnd = app('navigation')->endOfPeriod($currentEnd, $preferredRange);
|
||||
}
|
||||
while ($currentStart <= $currentEnd) {
|
||||
$key = $currentStart->format($format);
|
||||
$title = $currentStart->isoFormat($titleFormat);
|
||||
$income['entries'][$title] = app('steam')->bcround($currency[$key]['earned'] ?? '0', $currency['currency_decimal_places']);
|
||||
|
@@ -107,7 +107,7 @@ class CreateController extends Controller
|
||||
$this->attachments->saveAttachmentsForModel($piggyBank, $files);
|
||||
}
|
||||
if (null !== $files && auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->info(sprintf('The demo user is trying to upload attachments in %s.', __METHOD__));
|
||||
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'));
|
||||
}
|
||||
|
||||
|
@@ -127,7 +127,7 @@ class EditController extends Controller
|
||||
$this->attachments->saveAttachmentsForModel($piggyBank, $files);
|
||||
}
|
||||
if (null !== $files && auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->info(sprintf('The demo user is trying to upload attachments in %s.', __METHOD__));
|
||||
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'));
|
||||
}
|
||||
|
||||
|
@@ -231,6 +231,7 @@ class CreateController extends Controller
|
||||
|
||||
return redirect(route('recurring.create'))->withInput();
|
||||
}
|
||||
Log::channel('audit')->info('Stored new recurrence.', $data);
|
||||
|
||||
$request->session()->flash('success', (string)trans('firefly.stored_new_recurrence', ['title' => $recurrence->title]));
|
||||
app('preferences')->mark();
|
||||
@@ -242,7 +243,7 @@ class CreateController extends Controller
|
||||
$this->attachments->saveAttachmentsForModel($recurrence, $files);
|
||||
}
|
||||
if (null !== $files && auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->info(sprintf('The demo user is trying to upload attachments in %s.', __METHOD__));
|
||||
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'));
|
||||
}
|
||||
|
||||
|
@@ -172,6 +172,7 @@ class EditController extends Controller
|
||||
$this->recurring->update($recurrence, $data);
|
||||
|
||||
$request->session()->flash('success', (string)trans('firefly.updated_recurrence', ['title' => $recurrence->title]));
|
||||
Log::channel('audit')->info(sprintf('Updated recurrence #%d.', $recurrence->id), $data);
|
||||
|
||||
// store new attachment(s):
|
||||
/** @var null|array $files */
|
||||
@@ -180,7 +181,7 @@ class EditController extends Controller
|
||||
$this->attachments->saveAttachmentsForModel($recurrence, $files);
|
||||
}
|
||||
if (null !== $files && auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->info(sprintf('The demo user is trying to upload attachments in %s.', __METHOD__));
|
||||
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'));
|
||||
}
|
||||
|
||||
|
@@ -305,7 +305,7 @@ class TagController extends Controller
|
||||
$this->attachmentsHelper->saveAttachmentsForModel($result, $files);
|
||||
}
|
||||
if (null !== $files && auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->info(sprintf('The demo user is trying to upload attachments in %s.', __METHOD__));
|
||||
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'));
|
||||
}
|
||||
|
||||
@@ -340,7 +340,7 @@ class TagController extends Controller
|
||||
$this->attachmentsHelper->saveAttachmentsForModel($tag, $files);
|
||||
}
|
||||
if (null !== $files && auth()->user()->hasRole('demo')) {
|
||||
Log::channel('audit')->info(sprintf('The demo user is trying to upload attachments in %s.', __METHOD__));
|
||||
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'));
|
||||
}
|
||||
|
||||
|
@@ -50,7 +50,7 @@ class CreateController extends Controller
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
app('view')->share('title', (string)trans('firefly.transactions'));
|
||||
app('view')->share('title', (string) trans('firefly.transactions'));
|
||||
app('view')->share('mainTitleIcon', 'fa-exchange');
|
||||
$this->repository = app(TransactionGroupRepositoryInterface::class);
|
||||
|
||||
@@ -61,7 +61,7 @@ class CreateController extends Controller
|
||||
|
||||
public function cloneGroup(Request $request): JsonResponse
|
||||
{
|
||||
$groupId = (int)$request->get('id');
|
||||
$groupId = (int) $request->get('id');
|
||||
if (0 !== $groupId) {
|
||||
$group = $this->repository->find($groupId);
|
||||
if (null !== $group) {
|
||||
@@ -101,23 +101,43 @@ class CreateController extends Controller
|
||||
{
|
||||
app('preferences')->mark();
|
||||
|
||||
$sourceId = (int)request()->get('source');
|
||||
$destinationId = (int)request()->get('destination');
|
||||
$sourceId = (int) request()->get('source');
|
||||
$destinationId = (int) request()->get('destination');
|
||||
|
||||
/** @var AccountRepositoryInterface $accountRepository */
|
||||
$accountRepository = app(AccountRepositoryInterface::class);
|
||||
$cash = $accountRepository->getCashAccount();
|
||||
$preFilled = session()->has('preFilled') ? session('preFilled') : [];
|
||||
$subTitle = (string)trans(sprintf('breadcrumbs.create_%s', strtolower((string)$objectType)));
|
||||
$subTitleIcon = 'fa-plus';
|
||||
$optionalFields = app('preferences')->get('transaction_journal_optional_fields', [])->data;
|
||||
$allowedOpposingTypes = config('firefly.allowed_opposing_types');
|
||||
$accountToTypes = config('firefly.account_to_transaction');
|
||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||
$previousUrl = $this->rememberPreviousUrl('transactions.create.url');
|
||||
$parts = parse_url($previousUrl);
|
||||
$search = sprintf('?%s', $parts['query'] ?? '');
|
||||
$previousUrl = str_replace($search, '', $previousUrl);
|
||||
$accountRepository = app(AccountRepositoryInterface::class);
|
||||
$cash = $accountRepository->getCashAccount();
|
||||
$preFilled = session()->has('preFilled') ? session('preFilled') : [];
|
||||
$subTitle = (string) trans(sprintf('breadcrumbs.create_%s', strtolower((string) $objectType)));
|
||||
$subTitleIcon = 'fa-plus';
|
||||
$optionalFields = app('preferences')->get('transaction_journal_optional_fields', [])->data;
|
||||
$allowedOpposingTypes = config('firefly.allowed_opposing_types');
|
||||
$accountToTypes = config('firefly.account_to_transaction');
|
||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||
$previousUrl = $this->rememberPreviousUrl('transactions.create.url');
|
||||
$parts = parse_url($previousUrl);
|
||||
$search = sprintf('?%s', $parts['query'] ?? '');
|
||||
$previousUrl = str_replace($search, '', $previousUrl);
|
||||
if (!is_array($optionalFields)) {
|
||||
$optionalFields = [];
|
||||
}
|
||||
// not really a fan of this, but meh.
|
||||
$optionalDateFields = [
|
||||
'interest_date' => $optionalFields['interest_date'] ?? false,
|
||||
'book_date' => $optionalFields['book_date'] ?? false,
|
||||
'process_date' => $optionalFields['process_date'] ?? false,
|
||||
'due_date' => $optionalFields['due_date'] ?? false,
|
||||
'payment_date' => $optionalFields['payment_date'] ?? false,
|
||||
'invoice_date' => $optionalFields['invoice_date'] ?? false,
|
||||
];
|
||||
$optionalFields['external_url'] ??= false;
|
||||
$optionalFields['location'] ??= false;
|
||||
$optionalFields['location'] = $optionalFields['location'] && true === config('firefly.enable_external_map');
|
||||
|
||||
// map info:
|
||||
$longitude = config('firefly.default_location.longitude');
|
||||
$latitude = config('firefly.default_location.latitude');
|
||||
$zoomLevel = config('firefly.default_location.zoom_level');
|
||||
|
||||
session()->put('preFilled', $preFilled);
|
||||
|
||||
@@ -126,7 +146,11 @@ class CreateController extends Controller
|
||||
compact(
|
||||
'subTitleIcon',
|
||||
'cash',
|
||||
'longitude',
|
||||
'latitude',
|
||||
'zoomLevel',
|
||||
'objectType',
|
||||
'optionalDateFields',
|
||||
'subTitle',
|
||||
'defaultCurrency',
|
||||
'previousUrl',
|
||||
|
@@ -51,7 +51,7 @@ class EditController extends Controller
|
||||
// translations:
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
app('view')->share('title', (string)trans('firefly.transactions'));
|
||||
app('view')->share('title', (string) trans('firefly.transactions'));
|
||||
app('view')->share('mainTitleIcon', 'fa-exchange');
|
||||
|
||||
$this->repository = app(JournalRepositoryInterface::class);
|
||||
@@ -73,18 +73,43 @@ class EditController extends Controller
|
||||
}
|
||||
|
||||
/** @var AccountRepositoryInterface $repository */
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$allowedOpposingTypes = config('firefly.allowed_opposing_types');
|
||||
$accountToTypes = config('firefly.account_to_transaction');
|
||||
$expectedSourceTypes = config('firefly.expected_source_types');
|
||||
$allowedSourceDests = config('firefly.source_dests');
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$allowedOpposingTypes = config('firefly.allowed_opposing_types');
|
||||
$accountToTypes = config('firefly.account_to_transaction');
|
||||
$expectedSourceTypes = config('firefly.expected_source_types');
|
||||
$allowedSourceDests = config('firefly.source_dests');
|
||||
$title = $transactionGroup->transactionJournals()->count() > 1 ? $transactionGroup->title : $transactionGroup->transactionJournals()->first()->description;
|
||||
$subTitle = (string) trans('firefly.edit_transaction_title', ['description' => $title]);
|
||||
$subTitleIcon = 'fa-plus';
|
||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||
$cash = $repository->getCashAccount();
|
||||
$previousUrl = $this->rememberPreviousUrl('transactions.edit.url');
|
||||
$parts = parse_url($previousUrl);
|
||||
$search = sprintf('?%s', $parts['query'] ?? '');
|
||||
$previousUrl = str_replace($search, '', $previousUrl);
|
||||
|
||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||
$cash = $repository->getCashAccount();
|
||||
$previousUrl = $this->rememberPreviousUrl('transactions.edit.url');
|
||||
$parts = parse_url($previousUrl);
|
||||
$search = sprintf('?%s', $parts['query'] ?? '');
|
||||
$previousUrl = str_replace($search, '', $previousUrl);
|
||||
// settings necessary for v2
|
||||
$optionalFields = app('preferences')->get('transaction_journal_optional_fields', [])->data;
|
||||
if (!is_array($optionalFields)) {
|
||||
$optionalFields = [];
|
||||
}
|
||||
// not really a fan of this, but meh.
|
||||
$optionalDateFields = [
|
||||
'interest_date' => $optionalFields['interest_date'] ?? false,
|
||||
'book_date' => $optionalFields['book_date'] ?? false,
|
||||
'process_date' => $optionalFields['process_date'] ?? false,
|
||||
'due_date' => $optionalFields['due_date'] ?? false,
|
||||
'payment_date' => $optionalFields['payment_date'] ?? false,
|
||||
'invoice_date' => $optionalFields['invoice_date'] ?? false,
|
||||
];
|
||||
$optionalFields['external_url'] ??= false;
|
||||
$optionalFields['location'] ??= false;
|
||||
$optionalFields['location'] = $optionalFields['location'] && true === config('firefly.enable_external_map');
|
||||
|
||||
// map info voor v2:
|
||||
$longitude = config('firefly.default_location.longitude');
|
||||
$latitude = config('firefly.default_location.latitude');
|
||||
$zoomLevel = config('firefly.default_location.zoom_level');
|
||||
|
||||
return view(
|
||||
'transactions.edit',
|
||||
@@ -92,6 +117,13 @@ class EditController extends Controller
|
||||
'cash',
|
||||
'allowedSourceDests',
|
||||
'expectedSourceTypes',
|
||||
'optionalDateFields',
|
||||
'longitude',
|
||||
'latitude',
|
||||
'zoomLevel',
|
||||
'optionalFields',
|
||||
'subTitle',
|
||||
'subTitleIcon',
|
||||
'transactionGroup',
|
||||
'allowedOpposingTypes',
|
||||
'accountToTypes',
|
||||
|
@@ -75,45 +75,52 @@ class IndexController extends Controller
|
||||
$objectType = 'transfer';
|
||||
}
|
||||
|
||||
$subTitleIcon = config('firefly.transactionIconsByType.'.$objectType);
|
||||
$types = config('firefly.transactionTypesByType.'.$objectType);
|
||||
$page = (int)$request->get('page');
|
||||
$pageSize = (int)app('preferences')->get('listPageSize', 50)->data;
|
||||
if (null === $start) {
|
||||
$start = session('start');
|
||||
$end = session('end');
|
||||
// add a split for the (future) v2 release.
|
||||
$periods = [];
|
||||
$groups = [];
|
||||
$subTitle = 'TODO page subtitle in v2';
|
||||
|
||||
$subTitleIcon = config('firefly.transactionIconsByType.'.$objectType);
|
||||
$types = config('firefly.transactionTypesByType.'.$objectType);
|
||||
$page = (int)$request->get('page');
|
||||
$pageSize = (int)app('preferences')->get('listPageSize', 50)->data;
|
||||
|
||||
if ('v2' !== (string)config('firefly.layout')) {
|
||||
if (null === $start) {
|
||||
$start = session('start');
|
||||
$end = session('end');
|
||||
}
|
||||
if (null === $end) {
|
||||
// get last transaction ever?
|
||||
$last = $this->repository->getLast();
|
||||
$end = null !== $last ? $last->date : session('end');
|
||||
}
|
||||
|
||||
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
|
||||
$startStr = $start->isoFormat($this->monthAndDayFormat);
|
||||
$endStr = $end->isoFormat($this->monthAndDayFormat);
|
||||
$subTitle = (string)trans(sprintf('firefly.title_%s_between', $objectType), ['start' => $startStr, 'end' => $endStr]);
|
||||
$path = route('transactions.index', [$objectType, $start->format('Y-m-d'), $end->format('Y-m-d')]);
|
||||
$firstJournal = $this->repository->firstNull();
|
||||
$startPeriod = null === $firstJournal ? new Carbon() : $firstJournal->date;
|
||||
$endPeriod = clone $end;
|
||||
$periods = $this->getTransactionPeriodOverview($objectType, $startPeriod, $endPeriod);
|
||||
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
|
||||
$collector->setRange($start, $end)
|
||||
->setTypes($types)
|
||||
->setLimit($pageSize)
|
||||
->setPage($page)
|
||||
->withBudgetInformation()
|
||||
->withCategoryInformation()
|
||||
->withAccountInformation()
|
||||
->withAttachmentInformation()
|
||||
;
|
||||
$groups = $collector->getPaginatedGroups();
|
||||
$groups->setPath($path);
|
||||
}
|
||||
if (null === $end) {
|
||||
// get last transaction ever?
|
||||
$last = $this->repository->getLast();
|
||||
$end = null !== $last ? $last->date : session('end');
|
||||
}
|
||||
|
||||
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
|
||||
$path = route('transactions.index', [$objectType, $start->format('Y-m-d'), $end->format('Y-m-d')]);
|
||||
$startStr = $start->isoFormat($this->monthAndDayFormat);
|
||||
$endStr = $end->isoFormat($this->monthAndDayFormat);
|
||||
$subTitle = (string)trans(sprintf('firefly.title_%s_between', $objectType), ['start' => $startStr, 'end' => $endStr]);
|
||||
|
||||
$firstJournal = $this->repository->firstNull();
|
||||
$startPeriod = null === $firstJournal ? new Carbon() : $firstJournal->date;
|
||||
$endPeriod = clone $end;
|
||||
$periods = $this->getTransactionPeriodOverview($objectType, $startPeriod, $endPeriod);
|
||||
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
|
||||
$collector->setRange($start, $end)
|
||||
->setTypes($types)
|
||||
->setLimit($pageSize)
|
||||
->setPage($page)
|
||||
->withBudgetInformation()
|
||||
->withCategoryInformation()
|
||||
->withAccountInformation()
|
||||
->withAttachmentInformation()
|
||||
;
|
||||
$groups = $collector->getPaginatedGroups();
|
||||
$groups->setPath($path);
|
||||
|
||||
return view('transactions.index', compact('subTitle', 'objectType', 'subTitleIcon', 'groups', 'periods', 'start', 'end'));
|
||||
}
|
||||
|
@@ -105,7 +105,7 @@ class CreateController extends Controller
|
||||
$data = $request->getCurrencyData();
|
||||
if (!$this->userRepository->hasRole($user, 'owner')) {
|
||||
app('log')->error('User '.auth()->user()->id.' is not admin, but tried to store a currency.');
|
||||
Log::channel('audit')->info('Tried to create (POST) currency without admin rights.', $data);
|
||||
Log::channel('audit')->warning('Tried to create (POST) currency without admin rights.', $data);
|
||||
|
||||
return redirect($this->getPreviousUrl('currencies.create.url'))->withInput();
|
||||
}
|
||||
@@ -116,7 +116,7 @@ class CreateController extends Controller
|
||||
$currency = $this->repository->store($data);
|
||||
} catch (FireflyException $e) {
|
||||
app('log')->error($e->getMessage());
|
||||
Log::channel('audit')->info('Could not store (POST) currency without admin rights.', $data);
|
||||
Log::channel('audit')->warning('Could not store (POST) currency without admin rights.', $data);
|
||||
$request->session()->flash('error', (string)trans('firefly.could_not_store_currency'));
|
||||
$currency = null;
|
||||
}
|
||||
|
@@ -74,7 +74,7 @@ class DeleteController extends Controller
|
||||
$user = auth()->user();
|
||||
if (!$this->userRepository->hasRole($user, 'owner')) {
|
||||
$request->session()->flash('error', (string)trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))]));
|
||||
Log::channel('audit')->info(sprintf('Tried to visit page to delete currency %s but is not site owner.', $currency->code));
|
||||
Log::channel('audit')->warning(sprintf('Tried to visit page to delete currency %s but is not site owner.', $currency->code));
|
||||
|
||||
return redirect(route('currencies.index'));
|
||||
}
|
||||
@@ -83,7 +83,7 @@ class DeleteController extends Controller
|
||||
$location = $this->repository->currencyInUseAt($currency);
|
||||
$message = (string)trans(sprintf('firefly.cannot_disable_currency_%s', $location), ['name' => e($currency->name)]);
|
||||
$request->session()->flash('error', $message);
|
||||
Log::channel('audit')->info(sprintf('Tried to visit page to delete currency %s but currency is in use.', $currency->code));
|
||||
Log::channel('audit')->warning(sprintf('Tried to visit page to delete currency %s but currency is in use.', $currency->code));
|
||||
|
||||
return redirect(route('currencies.index'));
|
||||
}
|
||||
@@ -107,7 +107,7 @@ class DeleteController extends Controller
|
||||
$user = auth()->user();
|
||||
if (!$this->userRepository->hasRole($user, 'owner')) {
|
||||
$request->session()->flash('error', (string)trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))]));
|
||||
Log::channel('audit')->info(sprintf('Tried to delete currency %s but is not site owner.', $currency->code));
|
||||
Log::channel('audit')->warning(sprintf('Tried to delete currency %s but is not site owner.', $currency->code));
|
||||
|
||||
return redirect(route('currencies.index'));
|
||||
}
|
||||
|
@@ -72,7 +72,7 @@ class EditController extends Controller
|
||||
$user = auth()->user();
|
||||
if (!$this->userRepository->hasRole($user, 'owner')) {
|
||||
$request->session()->flash('error', (string)trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))]));
|
||||
Log::channel('audit')->info(sprintf('Tried to edit currency %s but is not owner.', $currency->code));
|
||||
Log::channel('audit')->warning(sprintf('Tried to edit currency %s but is not owner.', $currency->code));
|
||||
|
||||
return redirect(route('currencies.index'));
|
||||
}
|
||||
@@ -120,7 +120,7 @@ class EditController extends Controller
|
||||
|
||||
if (!$this->userRepository->hasRole($user, 'owner')) {
|
||||
$request->session()->flash('error', (string)trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))]));
|
||||
Log::channel('audit')->info('Tried to update (POST) currency without admin rights.', $data);
|
||||
Log::channel('audit')->warning('Tried to update (POST) currency without admin rights.', $data);
|
||||
|
||||
return redirect(route('currencies.index'));
|
||||
}
|
||||
|
@@ -60,7 +60,7 @@ class CreateController extends Controller
|
||||
public function index()
|
||||
{
|
||||
if(false === config('firefly.allow_webhooks')) {
|
||||
Log::channel('audit')->info('User visits webhook create page, but webhooks are DISABLED.');
|
||||
Log::channel('audit')->warning('User visits webhook create page, but webhooks are DISABLED.');
|
||||
|
||||
throw new NotFoundHttpException('Webhooks are not enabled.');
|
||||
}
|
||||
|
@@ -64,7 +64,7 @@ class DeleteController extends Controller
|
||||
public function index(Webhook $webhook)
|
||||
{
|
||||
if(false === config('firefly.allow_webhooks')) {
|
||||
Log::channel('audit')->info('User visits webhook delete page, but webhooks are DISABLED.');
|
||||
Log::channel('audit')->warning('User visits webhook delete page, but webhooks are DISABLED.');
|
||||
|
||||
throw new NotFoundHttpException('Webhooks are not enabled.');
|
||||
}
|
||||
|
@@ -63,7 +63,7 @@ class EditController extends Controller
|
||||
public function index(Webhook $webhook)
|
||||
{
|
||||
if(false === config('firefly.allow_webhooks')) {
|
||||
Log::channel('audit')->info('User visits webhook edit page, but webhooks are DISABLED.');
|
||||
Log::channel('audit')->warning('User visits webhook edit page, but webhooks are DISABLED.');
|
||||
|
||||
throw new NotFoundHttpException('Webhooks are not enabled.');
|
||||
}
|
||||
|
@@ -56,7 +56,7 @@ class IndexController extends Controller
|
||||
public function index()
|
||||
{
|
||||
if(false === config('firefly.allow_webhooks')) {
|
||||
Log::channel('audit')->info('User visits webhook index page, but webhooks are DISABLED.');
|
||||
Log::channel('audit')->warning('User visits webhook index page, but webhooks are DISABLED.');
|
||||
|
||||
throw new NotFoundHttpException('Webhooks are not enabled.');
|
||||
}
|
||||
|
@@ -63,7 +63,7 @@ class ShowController extends Controller
|
||||
public function index(Webhook $webhook)
|
||||
{
|
||||
if(false === config('firefly.allow_webhooks')) {
|
||||
Log::channel('audit')->info(sprintf('User visits webhook #%d page, but webhooks are DISABLED.', $webhook->id));
|
||||
Log::channel('audit')->warning(sprintf('User visits webhook #%d page, but webhooks are DISABLED.', $webhook->id));
|
||||
|
||||
throw new NotFoundHttpException('Webhooks are not enabled.');
|
||||
}
|
||||
|
@@ -32,6 +32,8 @@ use FireflyIII\Support\Request\AppendsLocationData;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
* Class AccountFormRequest.
|
||||
@@ -108,7 +110,7 @@ class AccountFormRequest extends FormRequest
|
||||
'BIC' => 'bic|nullable',
|
||||
'virtual_balance' => ['nullable', new IsValidAmount()],
|
||||
'currency_id' => 'exists:transaction_currencies,id',
|
||||
'account_number' => 'between:1,255|uniqueAccountNumberForUser|nullable',
|
||||
'account_number' => 'min:1|max:255|uniqueAccountNumberForUser|nullable',
|
||||
'account_role' => 'in:'.$accountRoles,
|
||||
'active' => 'boolean',
|
||||
'cc_type' => 'in:'.$ccPaymentTypes,
|
||||
@@ -116,7 +118,7 @@ class AccountFormRequest extends FormRequest
|
||||
'amount_currency_id_virtual_balance' => 'exists:transaction_currencies,id',
|
||||
'what' => 'in:'.$types,
|
||||
'interest_period' => 'in:daily,monthly,yearly',
|
||||
'notes' => 'between:1,65536|nullable',
|
||||
'notes' => 'min:1|max:32768|nullable',
|
||||
];
|
||||
$rules = Location::requestRules($rules);
|
||||
|
||||
@@ -131,4 +133,11 @@ class AccountFormRequest extends FormRequest
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -26,6 +26,8 @@ namespace FireflyIII\Http\Requests;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
* Class AttachmentFormRequest.
|
||||
@@ -53,8 +55,15 @@ class AttachmentFormRequest extends FormRequest
|
||||
{
|
||||
// fixed
|
||||
return [
|
||||
'title' => 'between:1,255|nullable',
|
||||
'notes' => 'between:1,65536|nullable',
|
||||
'title' => 'min:1|max:255|nullable',
|
||||
'notes' => 'min:1|max:32768|nullable',
|
||||
];
|
||||
}
|
||||
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -27,6 +27,8 @@ 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;
|
||||
|
||||
/**
|
||||
* Class BillStoreRequest.
|
||||
@@ -64,12 +66,12 @@ class BillStoreRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'required|between:1,255|uniqueObjectForUser:bills,name',
|
||||
'name' => 'required|min:1|max:255|uniqueObjectForUser:bills,name',
|
||||
'amount_min' => ['required', new IsValidPositiveAmount()],
|
||||
'amount_max' => ['required', new IsValidPositiveAmount()],
|
||||
'transaction_currency_id' => 'required|exists:transaction_currencies,id',
|
||||
'date' => 'required|date',
|
||||
'notes' => 'between:1,65536|nullable',
|
||||
'notes' => 'min:1|max:32768|nullable',
|
||||
'bill_end_date' => 'nullable|date',
|
||||
'extension_date' => 'nullable|date',
|
||||
'repeat_freq' => sprintf('required|in:%s', implode(',', config('firefly.bill_periods'))),
|
||||
@@ -77,4 +79,11 @@ class BillStoreRequest extends FormRequest
|
||||
'active' => 'boolean',
|
||||
];
|
||||
}
|
||||
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -28,6 +28,8 @@ 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;
|
||||
|
||||
/**
|
||||
* Class BillUpdateRequest.
|
||||
@@ -68,7 +70,7 @@ class BillUpdateRequest extends FormRequest
|
||||
$bill = $this->route()->parameter('bill');
|
||||
|
||||
return [
|
||||
'name' => sprintf('required|between:1,255|uniqueObjectForUser:bills,name,%d', $bill->id),
|
||||
'name' => sprintf('required|min:1|max:255|uniqueObjectForUser:bills,name,%d', $bill->id),
|
||||
'amount_min' => ['required', new IsValidPositiveAmount()],
|
||||
'amount_max' => ['required', new IsValidPositiveAmount()],
|
||||
'transaction_currency_id' => 'required|exists:transaction_currencies,id',
|
||||
@@ -78,7 +80,14 @@ class BillUpdateRequest extends FormRequest
|
||||
'repeat_freq' => sprintf('required|in:%s', implode(',', config('firefly.bill_periods'))),
|
||||
'skip' => 'required|integer|gte:0|lte:31',
|
||||
'active' => 'boolean',
|
||||
'notes' => 'between:1,65536|nullable',
|
||||
'notes' => 'min:1|max:32768|nullable',
|
||||
];
|
||||
}
|
||||
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -61,13 +61,13 @@ class BudgetFormStoreRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'required|between:1,100|uniqueObjectForUser:budgets,name',
|
||||
'active' => 'numeric|between:0,1',
|
||||
'name' => 'required|min:1|max:255|uniqueObjectForUser:budgets,name',
|
||||
'active' => 'numeric|min:0|max:1',
|
||||
'auto_budget_type' => 'numeric|integer|gte:0|lte:3',
|
||||
'auto_budget_currency_id' => 'exists:transaction_currencies,id',
|
||||
'auto_budget_amount' => ['required_if:auto_budget_type,1', 'required_if:auto_budget_type,2', new IsValidPositiveAmount()],
|
||||
'auto_budget_period' => 'in:daily,weekly,monthly,quarterly,half_year,yearly',
|
||||
'notes' => 'between:1,65536|nullable',
|
||||
'notes' => 'min:1|max:32768|nullable',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -76,15 +76,15 @@ class BudgetFormStoreRequest extends FormRequest
|
||||
*/
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error('Validation errors for budget', $validator->errors()->toArray());
|
||||
}
|
||||
|
||||
$validator->after(
|
||||
function (Validator $validator): void {
|
||||
// validate all account info
|
||||
$this->validateAutoBudgetAmount($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\Validation\AutoBudget\ValidatesAutoBudgetRequest;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
@@ -60,23 +61,23 @@ class BudgetFormUpdateRequest extends FormRequest
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$nameRule = 'required|between:1,100|uniqueObjectForUser:budgets,name';
|
||||
$nameRule = 'required|min:1|max:255|uniqueObjectForUser:budgets,name';
|
||||
|
||||
/** @var null|Budget $budget */
|
||||
$budget = $this->route()->parameter('budget');
|
||||
|
||||
if (null !== $budget) {
|
||||
$nameRule = 'required|between:1,100|uniqueObjectForUser:budgets,name,'.$budget->id;
|
||||
$nameRule = 'required|min:1|max:255|uniqueObjectForUser:budgets,name,'.$budget->id;
|
||||
}
|
||||
|
||||
return [
|
||||
'name' => $nameRule,
|
||||
'active' => 'numeric|between:0,1',
|
||||
'active' => 'numeric|min:0|max:1',
|
||||
'auto_budget_type' => 'numeric|integer|gte:0|lte:31',
|
||||
'auto_budget_currency_id' => 'exists:transaction_currencies,id',
|
||||
'auto_budget_amount' => ['required_if:auto_budget_type,1', 'required_if:auto_budget_type,2|numeric', new IsValidPositiveAmount()],
|
||||
'auto_budget_period' => 'in:daily,weekly,monthly,quarterly,half_year,yearly',
|
||||
'notes' => 'between:1,65536|nullable',
|
||||
'notes' => 'min:1|max:32768|nullable',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -91,5 +92,8 @@ class BudgetFormUpdateRequest extends FormRequest
|
||||
$this->validateAutoBudgetAmount($validator);
|
||||
}
|
||||
);
|
||||
if($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user