mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-10-31 02:36:28 +00:00 
			
		
		
		
	Compare commits
	
		
			71 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 | ||
|  | 7e62b75b12 | 
							
								
								
									
										12
									
								
								.ci/php-cs-fixer/composer.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										12
									
								
								.ci/php-cs-fixer/composer.lock
									
									
									
										generated
									
									
									
								
							| @@ -226,16 +226,16 @@ | ||||
|         }, | ||||
|         { | ||||
|             "name": "friendsofphp/php-cs-fixer", | ||||
|             "version": "v3.46.0", | ||||
|             "version": "v3.48.0", | ||||
|             "source": { | ||||
|                 "type": "git", | ||||
|                 "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", | ||||
|                 "reference": "be6831c9af1740470d2a773119b9273f8ac1c3d2" | ||||
|                 "reference": "a92472c6fb66349de25211f31c77eceae3df024e" | ||||
|             }, | ||||
|             "dist": { | ||||
|                 "type": "zip", | ||||
|                 "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/be6831c9af1740470d2a773119b9273f8ac1c3d2", | ||||
|                 "reference": "be6831c9af1740470d2a773119b9273f8ac1c3d2", | ||||
|                 "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/a92472c6fb66349de25211f31c77eceae3df024e", | ||||
|                 "reference": "a92472c6fb66349de25211f31c77eceae3df024e", | ||||
|                 "shasum": "" | ||||
|             }, | ||||
|             "require": { | ||||
| @@ -305,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.46.0" | ||||
|                 "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.48.0" | ||||
|             }, | ||||
|             "funding": [ | ||||
|                 { | ||||
| @@ -313,7 +313,7 @@ | ||||
|                     "type": "github" | ||||
|                 } | ||||
|             ], | ||||
|             "time": "2024-01-03T21:38:46+00:00" | ||||
|             "time": "2024-01-19T21:44:39+00:00" | ||||
|         }, | ||||
|         { | ||||
|             "name": "psr/container", | ||||
|   | ||||
| @@ -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. | ||||
|   | ||||
							
								
								
									
										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 | ||||
|   | ||||
| @@ -183,7 +183,7 @@ class DestroyController extends Controller | ||||
|             } | ||||
|             if (false === $this->unused) { | ||||
|                 app('log')->info(sprintf('Deleting account #%d "%s"', $account->id, $account->name)); | ||||
|                 Log::channel('audit')->info(sprintf('Deleted 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; | ||||
| 
 | ||||
| /** | ||||
| @@ -72,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 | ||||
|   | ||||
| @@ -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', | ||||
|         ]; | ||||
|   | ||||
| @@ -119,7 +119,7 @@ class StoreRequest extends FormRequest | ||||
|             'liability_direction'  => 'nullable|required_if:type,liability|required_if:type,liabilities|in:credit,debit', | ||||
|             '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); | ||||
|   | ||||
| @@ -107,7 +107,7 @@ class UpdateRequest extends FormRequest | ||||
|             'liability_direction'  => 'required_if:type,liability|in:credit,debit', | ||||
|             '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); | ||||
|   | ||||
| @@ -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; | ||||
| 
 | ||||
| /** | ||||
| @@ -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; | ||||
| 
 | ||||
| /** | ||||
| @@ -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; | ||||
| 
 | ||||
| /** | ||||
| @@ -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; | ||||
| 
 | ||||
| /** | ||||
| @@ -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; | ||||
| 
 | ||||
| /** | ||||
| @@ -87,5 +88,8 @@ class UpdateRequest extends FormRequest | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|         if($validator->fails()) { | ||||
|             Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
| 
 | ||||
| /** | ||||
| @@ -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; | ||||
| 
 | ||||
| /** | ||||
| @@ -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; | ||||
| 
 | ||||
| /** | ||||
| @@ -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; | ||||
| 
 | ||||
| /** | ||||
| @@ -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()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|   | ||||
| @@ -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', | ||||
|         ]; | ||||
| 
 | ||||
|   | ||||
| @@ -37,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; | ||||
| 
 | ||||
| /** | ||||
| @@ -191,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; | ||||
| 
 | ||||
| /** | ||||
| @@ -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()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|   | ||||
| @@ -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'], | ||||
|   | ||||
| @@ -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; | ||||
| 
 | ||||
| /** | ||||
| @@ -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; | ||||
| 
 | ||||
| /** | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -38,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; | ||||
| 
 | ||||
| /** | ||||
| @@ -211,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()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|   | ||||
							
								
								
									
										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; | ||||
|     } | ||||
| } | ||||
| @@ -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( | ||||
|   | ||||
| @@ -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; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|   | ||||
| @@ -286,7 +286,7 @@ class GroupCollector implements GroupCollectorInterface | ||||
|         foreach ($params as $param) { | ||||
|             $replace = sprintf('"%s"', $param); | ||||
|             if (is_int($param)) { | ||||
|                 $replace = (string) $param; | ||||
|                 $replace = (string)$param; | ||||
|             } | ||||
|             $pos     = strpos($query, '?'); | ||||
|             if (false !== $pos) { | ||||
| @@ -692,13 +692,13 @@ class GroupCollector implements GroupCollectorInterface | ||||
| 
 | ||||
|         /** @var TransactionJournal $augumentedJournal */ | ||||
|         foreach ($collection as $augumentedJournal) { | ||||
|             $groupId   = (int) $augumentedJournal->transaction_group_id; | ||||
|             $groupId   = (int)$augumentedJournal->transaction_group_id; | ||||
| 
 | ||||
|             if (!array_key_exists($groupId, $groups)) { | ||||
|                 // make new array
 | ||||
|                 $parsedGroup                            = $this->parseAugmentedJournal($augumentedJournal); | ||||
|                 $groupArray                             = [ | ||||
|                     'id'               => (int) $augumentedJournal->transaction_group_id, | ||||
|                     'id'               => (int)$augumentedJournal->transaction_group_id, | ||||
|                     'user_id'          => $augumentedJournal->user_id, | ||||
|                     'user_group_id'    => $augumentedJournal->user_group_id, | ||||
|                     // Field transaction_group_title was added by the query.
 | ||||
| @@ -711,7 +711,7 @@ class GroupCollector implements GroupCollectorInterface | ||||
|                     'transactions'     => [], | ||||
|                 ]; | ||||
|                 // Field transaction_journal_id was added by the query.
 | ||||
|                 $journalId                              = (int) $augumentedJournal->transaction_journal_id; // @phpstan-ignore-line
 | ||||
|                 $journalId                              = (int)$augumentedJournal->transaction_journal_id; // @phpstan-ignore-line
 | ||||
|                 $groupArray['transactions'][$journalId] = $parsedGroup; | ||||
|                 $groups[$groupId]                       = $groupArray; | ||||
| 
 | ||||
| @@ -719,7 +719,7 @@ class GroupCollector implements GroupCollectorInterface | ||||
|             } | ||||
|             // or parse the rest.
 | ||||
|             // Field transaction_journal_id was added by the query.
 | ||||
|             $journalId = (int) $augumentedJournal->transaction_journal_id; // @phpstan-ignore-line
 | ||||
|             $journalId = (int)$augumentedJournal->transaction_journal_id; // @phpstan-ignore-line
 | ||||
|             if (array_key_exists($journalId, $groups[$groupId]['transactions'])) { | ||||
|                 // append data to existing group + journal (for multiple tags or multiple attachments)
 | ||||
|                 $groups[$groupId]['transactions'][$journalId] = $this->mergeTags($groups[$groupId]['transactions'][$journalId], $augumentedJournal); | ||||
| @@ -772,7 +772,7 @@ class GroupCollector implements GroupCollectorInterface | ||||
|         $dates                   = ['interest_date', 'payment_date', 'invoice_date', 'book_date', 'due_date', 'process_date']; | ||||
|         if (array_key_exists('meta_name', $result) && in_array($result['meta_name'], $dates, true)) { | ||||
|             $name = $result['meta_name']; | ||||
|             if (array_key_exists('meta_data', $result) && '' !== (string) $result['meta_data']) { | ||||
|             if (array_key_exists('meta_data', $result) && '' !== (string)$result['meta_data']) { | ||||
|                 $result[$name] = Carbon::createFromFormat('!Y-m-d', substr(json_decode($result['meta_data']), 0, 10)); | ||||
|             } | ||||
|         } | ||||
| @@ -783,9 +783,9 @@ class GroupCollector implements GroupCollectorInterface | ||||
|         // convert back to strings because SQLite is dumb like that.
 | ||||
|         $result                  = $this->convertToStrings($result); | ||||
| 
 | ||||
|         $result['reconciled']    = 1 === (int) $result['reconciled']; | ||||
|         $result['reconciled']    = 1 === (int)$result['reconciled']; | ||||
|         if (array_key_exists('tag_id', $result) && null !== $result['tag_id']) { // assume the other fields are present as well.
 | ||||
|             $tagId                  = (int) $augumentedJournal['tag_id']; | ||||
|             $tagId                  = (int)$augumentedJournal['tag_id']; | ||||
|             $tagDate                = null; | ||||
| 
 | ||||
|             try { | ||||
| @@ -795,7 +795,7 @@ class GroupCollector implements GroupCollectorInterface | ||||
|             } | ||||
| 
 | ||||
|             $result['tags'][$tagId] = [ | ||||
|                 'id'          => (int) $result['tag_id'], | ||||
|                 'id'          => (int)$result['tag_id'], | ||||
|                 'name'        => $result['tag_name'], | ||||
|                 'date'        => $tagDate, | ||||
|                 'description' => $result['tag_description'], | ||||
| @@ -804,8 +804,8 @@ class GroupCollector implements GroupCollectorInterface | ||||
| 
 | ||||
|         // also merge attachments:
 | ||||
|         if (array_key_exists('attachment_id', $result)) { | ||||
|             $uploaded     = 1 === (int) $result['attachment_uploaded']; | ||||
|             $attachmentId = (int) $augumentedJournal['attachment_id']; | ||||
|             $uploaded     = 1 === (int)$result['attachment_uploaded']; | ||||
|             $attachmentId = (int)$augumentedJournal['attachment_id']; | ||||
|             if (0 !== $attachmentId && $uploaded) { | ||||
|                 $result['attachments'][$attachmentId] = [ | ||||
|                     'id'       => $attachmentId, | ||||
| @@ -831,7 +831,7 @@ class GroupCollector implements GroupCollectorInterface | ||||
|     private function convertToInteger(array $array): array | ||||
|     { | ||||
|         foreach ($this->integerFields as $field) { | ||||
|             $array[$field] = array_key_exists($field, $array) ? (int) $array[$field] : null; | ||||
|             $array[$field] = array_key_exists($field, $array) ? (int)$array[$field] : null; | ||||
|         } | ||||
| 
 | ||||
|         return $array; | ||||
| @@ -840,7 +840,7 @@ class GroupCollector implements GroupCollectorInterface | ||||
|     private function convertToStrings(array $array): array | ||||
|     { | ||||
|         foreach ($this->stringFields as $field) { | ||||
|             $array[$field] = array_key_exists($field, $array) && null !== $array[$field] ? (string) $array[$field] : null; | ||||
|             $array[$field] = array_key_exists($field, $array) && null !== $array[$field] ? (string)$array[$field] : null; | ||||
|         } | ||||
| 
 | ||||
|         return $array; | ||||
| @@ -850,7 +850,7 @@ class GroupCollector implements GroupCollectorInterface | ||||
|     { | ||||
|         $newArray = $newJournal->toArray(); | ||||
|         if (array_key_exists('tag_id', $newArray)) { // assume the other fields are present as well.
 | ||||
|             $tagId                           = (int) $newJournal['tag_id']; | ||||
|             $tagId                           = (int)$newJournal['tag_id']; | ||||
| 
 | ||||
|             $tagDate                         = null; | ||||
| 
 | ||||
| @@ -861,7 +861,7 @@ class GroupCollector implements GroupCollectorInterface | ||||
|             } | ||||
| 
 | ||||
|             $existingJournal['tags'][$tagId] = [ | ||||
|                 'id'          => (int) $newArray['tag_id'], | ||||
|                 'id'          => (int)$newArray['tag_id'], | ||||
|                 'name'        => $newArray['tag_name'], | ||||
|                 'date'        => $tagDate, | ||||
|                 'description' => $newArray['tag_description'], | ||||
| @@ -875,7 +875,7 @@ class GroupCollector implements GroupCollectorInterface | ||||
|     { | ||||
|         $newArray = $newJournal->toArray(); | ||||
|         if (array_key_exists('attachment_id', $newArray)) { | ||||
|             $attachmentId                                  = (int) $newJournal['attachment_id']; | ||||
|             $attachmentId                                  = (int)$newJournal['attachment_id']; | ||||
| 
 | ||||
|             $existingJournal['attachments'][$attachmentId] = [ | ||||
|                 'id' => $attachmentId, | ||||
| @@ -894,7 +894,7 @@ class GroupCollector implements GroupCollectorInterface | ||||
|         foreach ($groups as $groudId => $group) { | ||||
|             /** @var array $transaction */ | ||||
|             foreach ($group['transactions'] as $transaction) { | ||||
|                 $currencyId                                      = (int) $transaction['currency_id']; | ||||
|                 $currencyId                                      = (int)$transaction['currency_id']; | ||||
|                 if (null === $transaction['amount']) { | ||||
|                     throw new FireflyException(sprintf('Amount is NULL for a transaction in group #%d, please investigate.', $groudId)); | ||||
|                 } | ||||
| @@ -910,7 +910,7 @@ class GroupCollector implements GroupCollectorInterface | ||||
|                 $groups[$groudId]['sums'][$currencyId]['amount'] = bcadd($groups[$groudId]['sums'][$currencyId]['amount'], $transaction['amount']); | ||||
| 
 | ||||
|                 if (null !== $transaction['foreign_amount'] && null !== $transaction['foreign_currency_id']) { | ||||
|                     $currencyId                                      = (int) $transaction['foreign_currency_id']; | ||||
|                     $currencyId                                      = (int)$transaction['foreign_currency_id']; | ||||
| 
 | ||||
|                     // set default:
 | ||||
|                     if (!array_key_exists($currencyId, $groups[$groudId]['sums'])) { | ||||
| @@ -931,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))); | ||||
| 
 | ||||
|         /** | ||||
|   | ||||
| @@ -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')); | ||||
|         } | ||||
| 
 | ||||
|   | ||||
| @@ -243,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')); | ||||
|         } | ||||
| 
 | ||||
|   | ||||
| @@ -181,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')); | ||||
|         } | ||||
| 
 | ||||
|   | ||||
| @@ -106,7 +106,7 @@ class EditController extends Controller | ||||
|         $optionalFields['location']     ??= false; | ||||
|         $optionalFields['location'] = $optionalFields['location'] && true === config('firefly.enable_external_map'); | ||||
| 
 | ||||
|         // map info:
 | ||||
|         // map info voor v2:
 | ||||
|         $longitude                  = config('firefly.default_location.longitude'); | ||||
|         $latitude                   = config('firefly.default_location.latitude'); | ||||
|         $zoomLevel                  = config('firefly.default_location.zoom_level'); | ||||
|   | ||||
| @@ -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. | ||||
| @@ -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. | ||||
| @@ -57,4 +59,11 @@ class AttachmentFormRequest extends FormRequest | ||||
|             '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. | ||||
| @@ -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. | ||||
| @@ -81,4 +83,11 @@ class BillUpdateRequest extends FormRequest | ||||
|             '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()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
| 
 | ||||
| /** | ||||
| @@ -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()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -26,6 +26,8 @@ namespace FireflyIII\Http\Requests; | ||||
| use FireflyIII\Rules\IsValidPositiveAmount; | ||||
| use FireflyIII\Support\Request\ChecksLogin; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use Illuminate\Validation\Validator; | ||||
| 
 | ||||
| /** | ||||
|  * Class BudgetIncomeRequest. | ||||
| @@ -46,4 +48,11 @@ class BudgetIncomeRequest extends FormRequest | ||||
|             'end'    => 'required|date|after:start', | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     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 MassEditBulkJournalRequest. | ||||
| @@ -46,4 +48,11 @@ class BulkEditJournalRequest extends FormRequest | ||||
|             'tags_action' => 'in:no_nothing,do_replace,do_append', | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     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\Models\Category; | ||||
| 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 CategoryFormRequest. | ||||
| @@ -67,4 +69,11 @@ class CategoryFormRequest extends FormRequest | ||||
|             '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()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -25,6 +25,8 @@ namespace FireflyIII\Http\Requests; | ||||
| 
 | ||||
| use FireflyIII\Support\Request\ChecksLogin; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use Illuminate\Validation\Validator; | ||||
| 
 | ||||
| /** | ||||
|  * Class ConfigurationRequest. | ||||
| @@ -55,4 +57,11 @@ class ConfigurationRequest extends FormRequest | ||||
|             'is_demo_site'     => 'min:0|max:1|numeric', | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     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\Models\TransactionCurrency; | ||||
| 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 CurrencyFormRequest. | ||||
| @@ -79,4 +81,11 @@ class CurrencyFormRequest 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()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -25,6 +25,8 @@ namespace FireflyIII\Http\Requests; | ||||
| 
 | ||||
| use FireflyIII\Support\Request\ChecksLogin; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use Illuminate\Validation\Validator; | ||||
| 
 | ||||
| /** | ||||
|  * Class DeleteAccountFormRequest. | ||||
| @@ -43,4 +45,11 @@ class DeleteAccountFormRequest extends FormRequest | ||||
|             'password' => 'required', | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     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 EmailFormRequest. | ||||
| @@ -45,4 +47,11 @@ class EmailFormRequest extends FormRequest | ||||
|             'email' => 'required|email', | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     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 @@ 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 InviteUserFormRequest | ||||
| @@ -45,4 +47,11 @@ class InviteUserFormRequest extends FormRequest | ||||
|             'invited_user' => 'required|email|unique:invited_users,email', | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     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\Models\LinkType; | ||||
| 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 JournalLink. | ||||
| @@ -74,4 +76,11 @@ class JournalLinkRequest extends FormRequest | ||||
|             'opposing'  => 'belongsToUser:transaction_journals', | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     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 LinkTypeFormRequest. | ||||
| @@ -59,4 +61,11 @@ class LinkTypeFormRequest extends FormRequest | ||||
|             'outward' => 'required|max:255|min:1|different:inward', | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     public function withValidator(Validator $validator): void | ||||
|     { | ||||
|         if($validator->fails()) { | ||||
|             Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -25,6 +25,8 @@ namespace FireflyIII\Http\Requests; | ||||
| 
 | ||||
| use FireflyIII\Support\Request\ChecksLogin; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use Illuminate\Validation\Validator; | ||||
| 
 | ||||
| /** | ||||
|  * Class MassDeleteJournalRequest. | ||||
| @@ -43,4 +45,11 @@ class MassDeleteJournalRequest extends FormRequest | ||||
|             'confirm_mass_delete.*' => 'required|belongsToUser:transaction_journals,id', | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     public function withValidator(Validator $validator): void | ||||
|     { | ||||
|         if($validator->fails()) { | ||||
|             Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -25,6 +25,8 @@ namespace FireflyIII\Http\Requests; | ||||
| 
 | ||||
| use FireflyIII\Support\Request\ChecksLogin; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use Illuminate\Validation\Validator; | ||||
| 
 | ||||
| /** | ||||
|  * Class MassEditJournalRequest. | ||||
| @@ -49,4 +51,11 @@ class MassEditJournalRequest extends FormRequest | ||||
|             'expense_account'  => 'max:255', | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     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\IsValidAmount; | ||||
| 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 NewUserFormRequest. | ||||
| @@ -52,4 +54,11 @@ class NewUserFormRequest extends FormRequest | ||||
|             'amount_currency_id_credit_card_limit' => 'exists:transaction_currencies,id', | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     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\Models\ObjectGroup; | ||||
| 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 ObjectGroupFormRequest. | ||||
| @@ -63,4 +65,11 @@ class ObjectGroupFormRequest extends FormRequest | ||||
|             'title' => $titleRule, | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     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 PiggyBankStoreRequest. | ||||
| @@ -68,4 +70,11 @@ class PiggyBankStoreRequest extends FormRequest | ||||
|             '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()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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 PiggyBankFormRequest. | ||||
| @@ -67,9 +69,16 @@ class PiggyBankUpdateRequest extends FormRequest | ||||
|             'targetamount' => ['nullable', new IsValidPositiveAmount()], | ||||
|             'startdate'    => 'date', | ||||
|             'targetdate'   => 'date|nullable', | ||||
|             'order'        => 'integer|max:65536|min:1', | ||||
|             'order'        => 'integer|max:32768|min:1', | ||||
|             'object_group' => 'min:0|max:255', | ||||
|             '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()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -25,6 +25,8 @@ namespace FireflyIII\Http\Requests; | ||||
| 
 | ||||
| use FireflyIII\Support\Request\ChecksLogin; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use Illuminate\Validation\Validator; | ||||
| 
 | ||||
| /** | ||||
|  * Class ProfileFormRequest. | ||||
| @@ -45,4 +47,11 @@ class ProfileFormRequest extends FormRequest | ||||
|             'new_password_confirmation' => 'required', | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     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\ValidJournals; | ||||
| 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 ReconciliationStoreRequest | ||||
| @@ -75,4 +77,11 @@ class ReconciliationStoreRequest extends FormRequest | ||||
|             'reconcile'    => 'required|in:create,nothing', | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     public function withValidator(Validator $validator): void | ||||
|     { | ||||
|         if($validator->fails()) { | ||||
|             Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -34,6 +34,7 @@ use FireflyIII\Support\Request\ChecksLogin; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use FireflyIII\Validation\AccountValidator; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use Illuminate\Validation\Validator; | ||||
| 
 | ||||
| /** | ||||
| @@ -246,6 +247,9 @@ class RecurrenceFormRequest extends FormRequest | ||||
|                 $this->validateAccountInformation($validator); | ||||
|             } | ||||
|         ); | ||||
|         if($validator->fails()) { | ||||
|             Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|   | ||||
| @@ -33,6 +33,8 @@ use FireflyIII\Repositories\Tag\TagRepositoryInterface; | ||||
| use FireflyIII\Support\Request\ChecksLogin; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
| use Illuminate\Support\Collection; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use Illuminate\Validation\Validator; | ||||
| 
 | ||||
| /** | ||||
|  * Class CategoryFormRequest. | ||||
| @@ -215,7 +217,7 @@ class ReportFormRequest extends FormRequest | ||||
|             app('log')->debug('Set is:', $set); | ||||
|         } | ||||
|         if (!is_array($set)) { | ||||
|             app('log')->error(sprintf('Set is not an array! "%s"', $set)); | ||||
|             app('log')->debug(sprintf('Set is not an array! "%s"', $set)); | ||||
| 
 | ||||
|             return $collection; | ||||
|         } | ||||
| @@ -245,4 +247,11 @@ class ReportFormRequest extends FormRequest | ||||
|             'report_type' => 'in:audit,default,category,budget,tag,double', | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     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\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; | ||||
| 
 | ||||
| /** | ||||
|  * Class RuleFormRequest. | ||||
| @@ -119,6 +121,13 @@ class RuleFormRequest 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()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private function getRuleTriggerData(): array | ||||
|     { | ||||
|         $return      = []; | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user