Compare commits

..

20 Commits

Author SHA1 Message Date
github-actions[bot]
0aa31fde49 Merge pull request #11178 from firefly-iii/release-1762406581
🤖 Automatically merge the PR into the develop branch.
2025-11-06 06:23:09 +01:00
JC5
cf1c7262cd 🤖 Auto commit for release 'develop' on 2025-11-06 2025-11-06 06:23:01 +01:00
James Cole
d2b15734cc Fix account list filter. 2025-11-06 06:18:07 +01:00
James Cole
e0153dd33f Fix https://github.com/firefly-iii/firefly-iii/issues/11177 2025-11-06 06:17:59 +01:00
James Cole
0bc2d40d9b Don't throw error, report it. 2025-11-04 20:48:58 +01:00
github-actions[bot]
a3eb3bb1a4 Merge pull request #11174 from firefly-iii/release-1762232070
🤖 Automatically merge the PR into the develop branch.
2025-11-04 05:54:39 +01:00
JC5
bc5d52435e 🤖 Auto commit for release 'develop' on 2025-11-04 2025-11-04 05:54:30 +01:00
James Cole
eda81ef7b5 Rename the variable so there is no doubt what it does. 2025-11-04 05:50:06 +01:00
github-actions[bot]
5be32b1675 Merge pull request #11173 from firefly-iii/release-1762229827
🤖 Automatically merge the PR into the develop branch.
2025-11-04 05:17:13 +01:00
JC5
917b919503 🤖 Auto commit for release 'develop' on 2025-11-04 2025-11-04 05:17:07 +01:00
github-actions[bot]
43c38be0ed Merge pull request #11170 from firefly-iii/release-1762200216
🤖 Automatically merge the PR into the develop branch.
2025-11-03 21:03:45 +01:00
JC5
35e4ece205 🤖 Auto commit for release 'develop' on 2025-11-03 2025-11-03 21:03:36 +01:00
James Cole
b3421faf25 Fix #11168 2025-11-03 20:58:04 +01:00
github-actions[bot]
8d927a76d5 Merge pull request #11169 from firefly-iii/release-1762199642
🤖 Automatically merge the PR into the develop branch.
2025-11-03 20:54:14 +01:00
JC5
f000f96b00 🤖 Auto commit for release 'develop' on 2025-11-03 2025-11-03 20:54:02 +01:00
James Cole
9bd294257b Whoops. 2025-11-03 20:49:42 +01:00
github-actions[bot]
6d430c5d29 Merge pull request #11167 from firefly-iii/release-1762197221
🤖 Automatically merge the PR into the develop branch.
2025-11-03 20:13:49 +01:00
JC5
774e020177 🤖 Auto commit for release 'develop' on 2025-11-03 2025-11-03 20:13:41 +01:00
James Cole
47f938c71b Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-11-03 20:08:37 +01:00
James Cole
d66f03d538 Add support for sentry. 2025-11-03 20:08:31 +01:00
20 changed files with 664 additions and 169 deletions

View File

@@ -275,6 +275,16 @@ DISABLE_CSP_HEADER=false
TRACKER_SITE_ID=
TRACKER_URL=
#
# You can automatically submit errors to the Firefly III developer using sentry.io
#
# This is entirely optional of course. If you run into errors, I will gladly accept GitHub
# issues or a forwared email message.
#
# If you set this to true, your installation will try to contact sentry.io when it runs into errors.
#
REPORT_ERRORS_ONLINE=false
#
# Firefly III supports webhooks. These are security sensitive and must be enabled manually first.
#

View File

@@ -82,7 +82,6 @@ class ShowController extends Controller
'date' => $date,
]
= $request->attributes->all();
// get list of accounts. Count it and split it.
$this->repository->resetAccountOrder();
$collection = $this->repository->getAccountsByType($types, $sort);

View File

@@ -36,7 +36,7 @@ abstract class AggregateFormRequest extends ApiRequest
*/
protected array $requests = [];
/** @return class-string[] */
/** @return array<array|string> */
abstract protected function getRequests(): array;
public function initialize(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null): void
@@ -46,6 +46,7 @@ abstract class AggregateFormRequest extends ApiRequest
// instantiate all subrequests and share current requests' bags with them
Log::debug('Initializing AggregateFormRequest.');
/** @var array|string $config */
foreach ($this->getRequests() as $config) {
$requestClass = is_array($config) ? array_shift($config) : $config;

View File

@@ -36,7 +36,7 @@ class QueryRequest extends ApiRequest
public function rules(): array
{
return [
'query' => sprintf('min:1|max:50|%s', $this->required),
'query' => sprintf('min:0|max:50|%s', $this->required),
];
}

View File

@@ -39,7 +39,7 @@ class ShowRequest extends AggregateFormRequest
DateRangeRequest::class,
DateRequest::class,
AccountTypeApiRequest::class,
[ObjectTypeApiRequest::class, 'object_type' => Account::class],
// [ObjectTypeApiRequest::class, 'object_type' => Account::class],
];
}
}

View File

@@ -42,6 +42,7 @@ use Illuminate\Validation\ValidationException as LaravelValidationException;
use Laravel\Passport\Exceptions\OAuthServerException as LaravelOAuthException;
use League\OAuth2\Server\Exception\OAuthServerException;
use Override;
use Sentry\Laravel\Integration;
use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
@@ -54,6 +55,7 @@ use function Safe\json_encode;
use function Safe\parse_url;
// temp
/**
* Class Handler
*/
@@ -81,7 +83,14 @@ class Handler extends ExceptionHandler
* Register the exception handling callbacks for the application.
*/
#[Override]
public function register(): void {}
public function register(): void
{
if (true === config('firefly.report_errors_online')) {
$this->reportable(function (Throwable $e): void {
Integration::captureUnhandledException($e);
});
}
}
/**
* Render an exception into an HTTP response. It's complex but lucky for us, we never use it because
@@ -160,7 +169,7 @@ class Handler extends ExceptionHandler
$errorCode = 500;
$errorCode = $e instanceof MethodNotAllowedHttpException ? 405 : $errorCode;
$isDebug = (bool) config('app.debug', false);
$isDebug = (bool)config('app.debug', false);
if ($isDebug) {
Log::debug(sprintf('Return JSON %s with debug.', $e::class));
@@ -219,7 +228,7 @@ class Handler extends ExceptionHandler
public function report(Throwable $e): void
{
self::$lastError = $e;
$doMailError = (bool) config('firefly.send_error_message');
$doMailError = (bool)config('firefly.send_error_message');
if ($this->shouldntReportLocal($e) || !$doMailError) {
parent::report($e);
@@ -255,7 +264,7 @@ class Handler extends ExceptionHandler
// create job that will mail.
$ipAddress = request()->ip() ?? '0.0.0.0';
$job = new MailError($userData, (string) config('firefly.site_owner'), $ipAddress, $data);
$job = new MailError($userData, (string)config('firefly.site_owner'), $ipAddress, $data);
dispatch($job);
parent::report($e);

View File

@@ -95,7 +95,7 @@ class AttachmentController extends Controller
/**
* Download attachment to PC.
*
* @return LaravelResponse
* @return LaravelResponse|View
*
* @throws FireflyException
*/
@@ -121,8 +121,9 @@ class AttachmentController extends Controller
return $response;
}
$message = 'Could not find the indicated attachment. The file is no longer there.';
throw new FireflyException('Could not find the indicated attachment. The file is no longer there.');
return view('errors.error', compact('message'));
}
/**
@@ -194,7 +195,7 @@ class AttachmentController extends Controller
*
* @throws FireflyException
*/
public function view(Attachment $attachment): LaravelResponse
public function view(Attachment $attachment): LaravelResponse|View
{
if ($this->repository->exists($attachment)) {
$content = $this->repository->getContent($attachment);
@@ -223,6 +224,8 @@ class AttachmentController extends Controller
);
}
throw new FireflyException('Could not find the indicated attachment. The file is no longer there.');
$message = 'Could not find the indicated attachment. The file is no longer there.';
return view('errors.error', compact('message'));
}
}

View File

@@ -73,7 +73,7 @@ class ForgotPasswordController extends Controller
$message = sprintf('Cannot reset password when authenticating over "%s".', config('firefly.authentication_guard'));
Log::error($message);
return view('error', compact('message'));
return view('errors.error', compact('message'));
}
// validate host header.
@@ -138,7 +138,7 @@ class ForgotPasswordController extends Controller
if ('web' !== config('firefly.authentication_guard')) {
$message = sprintf('Cannot reset password when authenticating over "%s".', config('firefly.authentication_guard'));
return view('error', compact('message'));
return view('errors.error', compact('message'));
}
// is allowed to?

View File

@@ -158,12 +158,12 @@ class RegisterController extends Controller
if (true === $allowRegistration) {
$message = 'You do not need an invite code on this installation.';
return view('error', compact('message'));
return view('errors.error', compact('message'));
}
if (false === $validCode) {
$message = 'Invalid code.';
return view('error', compact('message'));
return view('errors.error', compact('message'));
}
$email = $request->old('email');
@@ -189,7 +189,7 @@ class RegisterController extends Controller
if (false === $allowRegistration) {
$message = 'Registration is currently not available. If you are the administrator, you can enable this in the administration.';
return view('error', compact('message'));
return view('errors.error', compact('message'));
}
$email = $request?->old('email');

View File

@@ -80,7 +80,7 @@ class ResetPasswordController extends Controller
if ('web' !== config('firefly.authentication_guard')) {
$message = sprintf('Cannot reset password when authenticating over "%s".', config('firefly.authentication_guard'));
return view('error', compact('message'));
return view('errors.error', compact('message'));
}
$rules = [
@@ -127,7 +127,7 @@ class ResetPasswordController extends Controller
if ('web' !== config('firefly.authentication_guard')) {
$message = sprintf('Cannot reset password when authenticating over "%s".', config('firefly.authentication_guard'));
return view('error', compact('message'));
return view('errors.error', compact('message'));
}
// is allowed to register?

View File

@@ -82,7 +82,7 @@ class ReportController extends Controller
public function auditReport(Collection $accounts, Carbon $start, Carbon $end)
{
if ($end < $start) {
return view('error')->with('message', (string) trans('firefly.end_after_start_date'));
return view('errors.error')->with('message', (string) trans('firefly.end_after_start_date'));
}
$this->repository->cleanupBudgets();
$start->endOfDay(); // end of day so the final balance is at the end of that day.
@@ -115,7 +115,7 @@ class ReportController extends Controller
public function budgetReport(Collection $accounts, Collection $budgets, Carbon $start, Carbon $end)
{
if ($end < $start) {
return view('error')->with('message', (string) trans('firefly.end_after_start_date'));
return view('errors.error')->with('message', (string) trans('firefly.end_after_start_date'));
}
$this->repository->cleanupBudgets();
$start->endOfDay(); // end of day so the final balance is at the end of that day.
@@ -149,7 +149,7 @@ class ReportController extends Controller
public function categoryReport(Collection $accounts, Collection $categories, Carbon $start, Carbon $end)
{
if ($end < $start) {
return view('error')->with('message', (string) trans('firefly.end_after_start_date'));
return view('errors.error')->with('message', (string) trans('firefly.end_after_start_date'));
}
$this->repository->cleanupBudgets();
$start->endOfDay(); // end of day so the final balance is at the end of that day.
@@ -183,7 +183,7 @@ class ReportController extends Controller
public function defaultReport(Collection $accounts, Carbon $start, Carbon $end)
{
if ($end < $start) {
return view('error')->with('message', (string) trans('firefly.end_after_start_date'));
return view('errors.error')->with('message', (string) trans('firefly.end_after_start_date'));
}
$this->repository->cleanupBudgets();
@@ -336,7 +336,7 @@ class ReportController extends Controller
}
if ($request->getEndDate() < $request->getStartDate()) {
return view('error')->with('message', (string) trans('firefly.end_after_start_date'));
return view('errors.error')->with('message', (string) trans('firefly.end_after_start_date'));
}
$url = match ($reportType) {
@@ -361,7 +361,7 @@ class ReportController extends Controller
public function tagReport(Collection $accounts, Collection $tags, Carbon $start, Carbon $end)
{
if ($end < $start) {
return view('error')->with('message', (string) trans('firefly.end_after_start_date'));
return view('errors.error')->with('message', (string) trans('firefly.end_after_start_date'));
}
$this->repository->cleanupBudgets();
$start->endOfDay(); // end of day so the final balance is at the end of that day.

View File

@@ -33,10 +33,12 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Collection;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* @property User $user
* @property Collection $rules
*/
#[ObservedBy([RuleGroupObserver::class])]
class RuleGroup extends Model

View File

@@ -263,7 +263,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface, UserGroupInte
[ // @phpstan-ignore-line
'rules' => static function (HasMany $query): void {
$query->orderBy('order', 'ASC');
$query->where('rules.active', true);
// $query->where('rules.active', true);
},
'rules.ruleTriggers' => static function (HasMany $query): void {
$query->orderBy('order', 'ASC');

View File

@@ -103,6 +103,7 @@
"psr/log": "<4",
"ramsey/uuid": "^4.7",
"rcrowe/twigbridge": "^0.14",
"sentry/sentry-laravel": "^4.18",
"spatie/laravel-html": "^3.2",
"spatie/laravel-ignition": "^2",
"spatie/period": "^2.4",

339
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "5c65637d2a997c3503e4922eb7647e2a",
"content-hash": "946638fa99da77780e75953c338d9a55",
"packages": [
{
"name": "bacon/bacon-qr-code",
@@ -1808,6 +1808,66 @@
},
"time": "2022-03-31T05:55:34+00:00"
},
{
"name": "jean85/pretty-package-versions",
"version": "2.1.1",
"source": {
"type": "git",
"url": "https://github.com/Jean85/pretty-package-versions.git",
"reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/4d7aa5dab42e2a76d99559706022885de0e18e1a",
"reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a",
"shasum": ""
},
"require": {
"composer-runtime-api": "^2.1.0",
"php": "^7.4|^8.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.2",
"jean85/composer-provided-replaced-stub-package": "^1.0",
"phpstan/phpstan": "^2.0",
"phpunit/phpunit": "^7.5|^8.5|^9.6",
"rector/rector": "^2.0",
"vimeo/psalm": "^4.3 || ^5.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Jean85\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Alessandro Lai",
"email": "alessandro.lai85@gmail.com"
}
],
"description": "A library to get pretty versions strings of installed dependencies",
"keywords": [
"composer",
"package",
"release",
"versions"
],
"support": {
"issues": "https://github.com/Jean85/pretty-package-versions/issues",
"source": "https://github.com/Jean85/pretty-package-versions/tree/2.1.1"
},
"time": "2025-03-19T14:43:43+00:00"
},
{
"name": "laravel-notification-channels/pushover",
"version": "4.1.2",
@@ -1877,16 +1937,16 @@
},
{
"name": "laravel/framework",
"version": "v12.36.1",
"version": "v12.37.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
"reference": "cad110d7685fbab990a6bb8184d0cfd847d7c4d8"
"reference": "3c3c4ad30f5b528b164a7c09aa4ad03118c4c125"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/cad110d7685fbab990a6bb8184d0cfd847d7c4d8",
"reference": "cad110d7685fbab990a6bb8184d0cfd847d7c4d8",
"url": "https://api.github.com/repos/laravel/framework/zipball/3c3c4ad30f5b528b164a7c09aa4ad03118c4c125",
"reference": "3c3c4ad30f5b528b164a7c09aa4ad03118c4c125",
"shasum": ""
},
"require": {
@@ -2092,7 +2152,7 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2025-10-29T14:20:57+00:00"
"time": "2025-11-04T15:39:33+00:00"
},
{
"name": "laravel/passport",
@@ -5903,6 +5963,183 @@
},
"time": "2025-08-20T11:25:49+00:00"
},
{
"name": "sentry/sentry",
"version": "4.18.0",
"source": {
"type": "git",
"url": "https://github.com/getsentry/sentry-php.git",
"reference": "75f7efb7d435d24767c93d0081b8edf228be5772"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/getsentry/sentry-php/zipball/75f7efb7d435d24767c93d0081b8edf228be5772",
"reference": "75f7efb7d435d24767c93d0081b8edf228be5772",
"shasum": ""
},
"require": {
"ext-curl": "*",
"ext-json": "*",
"ext-mbstring": "*",
"guzzlehttp/psr7": "^1.8.4|^2.1.1",
"jean85/pretty-package-versions": "^1.5|^2.0.4",
"php": "^7.2|^8.0",
"psr/log": "^1.0|^2.0|^3.0",
"symfony/options-resolver": "^4.4.30|^5.0.11|^6.0|^7.0|^8.0"
},
"conflict": {
"raven/raven": "*"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.4",
"guzzlehttp/promises": "^2.0.3",
"guzzlehttp/psr7": "^1.8.4|^2.1.1",
"monolog/monolog": "^1.6|^2.0|^3.0",
"phpbench/phpbench": "^1.0",
"phpstan/phpstan": "^1.3",
"phpunit/phpunit": "^8.5|^9.6",
"vimeo/psalm": "^4.17"
},
"suggest": {
"monolog/monolog": "Allow sending log messages to Sentry by using the included Monolog handler."
},
"type": "library",
"autoload": {
"files": [
"src/functions.php"
],
"psr-4": {
"Sentry\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Sentry",
"email": "accounts@sentry.io"
}
],
"description": "PHP SDK for Sentry (http://sentry.io)",
"homepage": "http://sentry.io",
"keywords": [
"crash-reporting",
"crash-reports",
"error-handler",
"error-monitoring",
"log",
"logging",
"profiling",
"sentry",
"tracing"
],
"support": {
"issues": "https://github.com/getsentry/sentry-php/issues",
"source": "https://github.com/getsentry/sentry-php/tree/4.18.0"
},
"funding": [
{
"url": "https://sentry.io/",
"type": "custom"
},
{
"url": "https://sentry.io/pricing/",
"type": "custom"
}
],
"time": "2025-11-05T14:37:07+00:00"
},
{
"name": "sentry/sentry-laravel",
"version": "4.18.0",
"source": {
"type": "git",
"url": "https://github.com/getsentry/sentry-laravel.git",
"reference": "b9a647f93f9a040eaf6f21d0684f2351310d3360"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/b9a647f93f9a040eaf6f21d0684f2351310d3360",
"reference": "b9a647f93f9a040eaf6f21d0684f2351310d3360",
"shasum": ""
},
"require": {
"illuminate/support": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0 | ^12.0",
"nyholm/psr7": "^1.0",
"php": "^7.2 | ^8.0",
"sentry/sentry": "^4.16.0",
"symfony/psr-http-message-bridge": "^1.0 | ^2.0 | ^6.0 | ^7.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.11",
"guzzlehttp/guzzle": "^7.2",
"laravel/folio": "^1.1",
"laravel/framework": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0 | ^12.0",
"livewire/livewire": "^2.0 | ^3.0",
"mockery/mockery": "^1.3",
"orchestra/testbench": "^4.7 | ^5.1 | ^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^8.4 | ^9.3 | ^10.4 | ^11.5"
},
"type": "library",
"extra": {
"laravel": {
"aliases": {
"Sentry": "Sentry\\Laravel\\Facade"
},
"providers": [
"Sentry\\Laravel\\ServiceProvider",
"Sentry\\Laravel\\Tracing\\ServiceProvider"
]
}
},
"autoload": {
"psr-0": {
"Sentry\\Laravel\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Sentry",
"email": "accounts@sentry.io"
}
],
"description": "Laravel SDK for Sentry (https://sentry.io)",
"homepage": "https://sentry.io",
"keywords": [
"crash-reporting",
"crash-reports",
"error-handler",
"error-monitoring",
"laravel",
"log",
"logging",
"profiling",
"sentry",
"tracing"
],
"support": {
"issues": "https://github.com/getsentry/sentry-laravel/issues",
"source": "https://github.com/getsentry/sentry-laravel/tree/4.18.0"
},
"funding": [
{
"url": "https://sentry.io/",
"type": "custom"
},
{
"url": "https://sentry.io/pricing/",
"type": "custom"
}
],
"time": "2025-10-20T12:57:51+00:00"
},
{
"name": "spatie/backtrace",
"version": "1.8.1",
@@ -10493,21 +10730,22 @@
},
{
"name": "driftingly/rector-laravel",
"version": "2.1.2",
"version": "2.1.3",
"source": {
"type": "git",
"url": "https://github.com/driftingly/rector-laravel.git",
"reference": "d7cd932cff9e398a43393f1a1a63b27d574e35ef"
"reference": "2f1e9c3997bf45592d58916f0cedd775e844b9c6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/driftingly/rector-laravel/zipball/d7cd932cff9e398a43393f1a1a63b27d574e35ef",
"reference": "d7cd932cff9e398a43393f1a1a63b27d574e35ef",
"url": "https://api.github.com/repos/driftingly/rector-laravel/zipball/2f1e9c3997bf45592d58916f0cedd775e844b9c6",
"reference": "2f1e9c3997bf45592d58916f0cedd775e844b9c6",
"shasum": ""
},
"require": {
"php": "^7.4 || ^8.0",
"rector/rector": "^2.2.7"
"rector/rector": "^2.2.7",
"webmozart/assert": "^1.11"
},
"type": "rector-extension",
"autoload": {
@@ -10522,9 +10760,9 @@
"description": "Rector upgrades rules for Laravel Framework",
"support": {
"issues": "https://github.com/driftingly/rector-laravel/issues",
"source": "https://github.com/driftingly/rector-laravel/tree/2.1.2"
"source": "https://github.com/driftingly/rector-laravel/tree/2.1.3"
},
"time": "2025-10-31T21:56:58+00:00"
"time": "2025-11-04T18:32:57+00:00"
},
{
"name": "fakerphp/faker",
@@ -10683,16 +10921,16 @@
},
{
"name": "larastan/larastan",
"version": "v3.7.2",
"version": "v3.8.0",
"source": {
"type": "git",
"url": "https://github.com/larastan/larastan.git",
"reference": "a761859a7487bd7d0cb8b662a7538a234d5bb5ae"
"reference": "d13ef96d652d1b2a8f34f1760ba6bf5b9c98112e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/larastan/larastan/zipball/a761859a7487bd7d0cb8b662a7538a234d5bb5ae",
"reference": "a761859a7487bd7d0cb8b662a7538a234d5bb5ae",
"url": "https://api.github.com/repos/larastan/larastan/zipball/d13ef96d652d1b2a8f34f1760ba6bf5b9c98112e",
"reference": "d13ef96d652d1b2a8f34f1760ba6bf5b9c98112e",
"shasum": ""
},
"require": {
@@ -10706,7 +10944,7 @@
"illuminate/pipeline": "^11.44.2 || ^12.4.1",
"illuminate/support": "^11.44.2 || ^12.4.1",
"php": "^8.2",
"phpstan/phpstan": "^2.1.28"
"phpstan/phpstan": "^2.1.29"
},
"require-dev": {
"doctrine/coding-standard": "^13",
@@ -10719,7 +10957,8 @@
"phpunit/phpunit": "^10.5.35 || ^11.5.15"
},
"suggest": {
"orchestra/testbench": "Using Larastan for analysing a package needs Testbench"
"orchestra/testbench": "Using Larastan for analysing a package needs Testbench",
"phpmyadmin/sql-parser": "Install to enable Larastan's optional phpMyAdmin-based SQL parser automatically"
},
"type": "phpstan-extension",
"extra": {
@@ -10760,7 +10999,7 @@
],
"support": {
"issues": "https://github.com/larastan/larastan/issues",
"source": "https://github.com/larastan/larastan/tree/v3.7.2"
"source": "https://github.com/larastan/larastan/tree/v3.8.0"
},
"funding": [
{
@@ -10768,7 +11007,7 @@
"type": "github"
}
],
"time": "2025-09-19T09:03:05+00:00"
"time": "2025-10-27T23:09:14+00:00"
},
{
"name": "laravel-json-api/testing",
@@ -12978,6 +13217,64 @@
}
],
"time": "2024-03-03T12:36:25+00:00"
},
{
"name": "webmozart/assert",
"version": "1.12.1",
"source": {
"type": "git",
"url": "https://github.com/webmozarts/assert.git",
"reference": "9be6926d8b485f55b9229203f962b51ed377ba68"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozarts/assert/zipball/9be6926d8b485f55b9229203f962b51ed377ba68",
"reference": "9be6926d8b485f55b9229203f962b51ed377ba68",
"shasum": ""
},
"require": {
"ext-ctype": "*",
"ext-date": "*",
"ext-filter": "*",
"php": "^7.2 || ^8.0"
},
"suggest": {
"ext-intl": "",
"ext-simplexml": "",
"ext-spl": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.10-dev"
}
},
"autoload": {
"psr-4": {
"Webmozart\\Assert\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "Assertions to validate method input/output with nice error messages.",
"keywords": [
"assert",
"check",
"validate"
],
"support": {
"issues": "https://github.com/webmozarts/assert/issues",
"source": "https://github.com/webmozarts/assert/tree/1.12.1"
},
"time": "2025-10-29T15:56:20+00:00"
}
],
"aliases": [],

View File

@@ -78,8 +78,8 @@ return [
'running_balance_column' => env('USE_RUNNING_BALANCE', false),
// see cer.php for exchange rates feature flag.
],
'version' => 'develop/2025-11-03',
'build_time' => 1762140500,
'version' => 'develop/2025-11-06',
'build_time' => 1762406472,
'api_version' => '2.1.0', // field is no longer used.
'db_version' => 28, // field is no longer used.
@@ -107,6 +107,7 @@ return [
'demo_password' => env('DEMO_PASSWORD', ''),
'tracker_site_id' => env('TRACKER_SITE_ID', ''),
'tracker_url' => env('TRACKER_URL', ''),
'report_errors_online' => env('REPORT_ERRORS_ONLINE', false),
// authentication settings
'authentication_guard' => envNonEmpty('AUTHENTICATION_GUARD', 'web'),

130
config/sentry.php Normal file
View File

@@ -0,0 +1,130 @@
<?php
declare(strict_types=1);
use Illuminate\Auth\AuthenticationException;
/*
* Sentry Laravel SDK configuration file.
*
* @see https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/
*/
return [
'dsn' => 'https://cf9d7aea92537db1e97e3e758b88b0a3@o4510302583848960.ingest.de.sentry.io/4510302585290832',
'release' => env('SENTRY_RELEASE'),
// When left empty or `null` the Laravel environment will be used (usually discovered from `APP_ENV` in your `.env`)
'environment' => env('SENTRY_ENVIRONMENT'),
// @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#sample_rate
'sample_rate' => null === env('SENTRY_SAMPLE_RATE') ? 1.0 : (float)env('SENTRY_SAMPLE_RATE'),
// @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#traces_sample_rate
'traces_sample_rate' => null === env('SENTRY_TRACES_SAMPLE_RATE') ? null : (float)env('SENTRY_TRACES_SAMPLE_RATE'),
// @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#profiles-sample-rate
'profiles_sample_rate' => null === env('SENTRY_PROFILES_SAMPLE_RATE') ? null : (float)env('SENTRY_PROFILES_SAMPLE_RATE'),
// @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#enable_logs
'enable_logs' => env('SENTRY_ENABLE_LOGS', false),
// The minimum log level that will be sent to Sentry as logs using the `sentry_logs` logging channel
'logs_channel_level' => env('SENTRY_LOG_LEVEL', env('SENTRY_LOGS_LEVEL', env('LOG_LEVEL', 'debug'))),
// @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#send_default_pii
'send_default_pii' => env('SENTRY_SEND_DEFAULT_PII', false),
// @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#ignore_exceptions
'ignore_exceptions' => [
AuthenticationException::class,
],
// @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#ignore_transactions
'ignore_transactions' => [
// Ignore Laravel's default health URL
'/up',
],
// Breadcrumb specific configuration
'breadcrumbs' => [
// Capture Laravel logs as breadcrumbs
'logs' => env('SENTRY_BREADCRUMBS_LOGS_ENABLED', true),
// Capture Laravel cache events (hits, writes etc.) as breadcrumbs
'cache' => env('SENTRY_BREADCRUMBS_CACHE_ENABLED', true),
// Capture Livewire components like routes as breadcrumbs
'livewire' => env('SENTRY_BREADCRUMBS_LIVEWIRE_ENABLED', true),
// Capture SQL queries as breadcrumbs
'sql_queries' => env('SENTRY_BREADCRUMBS_SQL_QUERIES_ENABLED', true),
// Capture SQL query bindings (parameters) in SQL query breadcrumbs
'sql_bindings' => env('SENTRY_BREADCRUMBS_SQL_BINDINGS_ENABLED', false),
// Capture queue job information as breadcrumbs
'queue_info' => env('SENTRY_BREADCRUMBS_QUEUE_INFO_ENABLED', true),
// Capture command information as breadcrumbs
'command_info' => env('SENTRY_BREADCRUMBS_COMMAND_JOBS_ENABLED', true),
// Capture HTTP client request information as breadcrumbs
'http_client_requests' => env('SENTRY_BREADCRUMBS_HTTP_CLIENT_REQUESTS_ENABLED', true),
// Capture send notifications as breadcrumbs
'notifications' => env('SENTRY_BREADCRUMBS_NOTIFICATIONS_ENABLED', true),
],
// Performance monitoring specific configuration
'tracing' => [
// Trace queue jobs as their own transactions (this enables tracing for queue jobs)
'queue_job_transactions' => env('SENTRY_TRACE_QUEUE_ENABLED', true),
// Capture queue jobs as spans when executed on the sync driver
'queue_jobs' => env('SENTRY_TRACE_QUEUE_JOBS_ENABLED', true),
// Capture SQL queries as spans
'sql_queries' => env('SENTRY_TRACE_SQL_QUERIES_ENABLED', true),
// Capture SQL query bindings (parameters) in SQL query spans
'sql_bindings' => env('SENTRY_TRACE_SQL_BINDINGS_ENABLED', false),
// Capture where the SQL query originated from on the SQL query spans
'sql_origin' => env('SENTRY_TRACE_SQL_ORIGIN_ENABLED', true),
// Define a threshold in milliseconds for SQL queries to resolve their origin
'sql_origin_threshold_ms' => env('SENTRY_TRACE_SQL_ORIGIN_THRESHOLD_MS', 100),
// Capture views rendered as spans
'views' => env('SENTRY_TRACE_VIEWS_ENABLED', true),
// Capture Livewire components as spans
'livewire' => env('SENTRY_TRACE_LIVEWIRE_ENABLED', true),
// Capture HTTP client requests as spans
'http_client_requests' => env('SENTRY_TRACE_HTTP_CLIENT_REQUESTS_ENABLED', true),
// Capture Laravel cache events (hits, writes etc.) as spans
'cache' => env('SENTRY_TRACE_CACHE_ENABLED', true),
// Capture Redis operations as spans (this enables Redis events in Laravel)
'redis_commands' => env('SENTRY_TRACE_REDIS_COMMANDS', false),
// Capture where the Redis command originated from on the Redis command spans
'redis_origin' => env('SENTRY_TRACE_REDIS_ORIGIN_ENABLED', true),
// Capture send notifications as spans
'notifications' => env('SENTRY_TRACE_NOTIFICATIONS_ENABLED', true),
// Enable tracing for requests without a matching route (404's)
'missing_routes' => env('SENTRY_TRACE_MISSING_ROUTES_ENABLED', false),
// Configures if the performance trace should continue after the response has been sent to the user until the application terminates
// This is required to capture any spans that are created after the response has been sent like queue jobs dispatched using `dispatch(...)->afterResponse()` for example
'continue_after_response' => env('SENTRY_TRACE_CONTINUE_AFTER_RESPONSE', true),
// Enable the tracing integrations supplied by Sentry (recommended)
'default_integrations' => env('SENTRY_TRACE_DEFAULT_INTEGRATIONS_ENABLED', true),
],
];

84
package-lock.json generated
View File

@@ -3291,57 +3291,57 @@
}
},
"node_modules/@vue/compiler-core": {
"version": "3.5.22",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.22.tgz",
"integrity": "sha512-jQ0pFPmZwTEiRNSb+i9Ow/I/cHv2tXYqsnHKKyCQ08irI2kdF5qmYedmF8si8mA7zepUFmJ2hqzS8CQmNOWOkQ==",
"version": "3.5.23",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.23.tgz",
"integrity": "sha512-nW7THWj5HOp085ROk65LwaoxuzDsjIxr485F4iu63BoxsXoSqKqmsUUoP4A7Gl67DgIgi0zJ8JFgHfvny/74MA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.28.4",
"@vue/shared": "3.5.22",
"@babel/parser": "^7.28.5",
"@vue/shared": "3.5.23",
"entities": "^4.5.0",
"estree-walker": "^2.0.2",
"source-map-js": "^1.2.1"
}
},
"node_modules/@vue/compiler-dom": {
"version": "3.5.22",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.22.tgz",
"integrity": "sha512-W8RknzUM1BLkypvdz10OVsGxnMAuSIZs9Wdx1vzA3mL5fNMN15rhrSCLiTm6blWeACwUwizzPVqGJgOGBEN/hA==",
"version": "3.5.23",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.23.tgz",
"integrity": "sha512-AT8RMw0vEzzzO0JU5gY0F6iCzaWUIh/aaRVordzMBKXRpoTllTT4kocHDssByPsvodNCfump/Lkdow2mT/O5KQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@vue/compiler-core": "3.5.22",
"@vue/shared": "3.5.22"
"@vue/compiler-core": "3.5.23",
"@vue/shared": "3.5.23"
}
},
"node_modules/@vue/compiler-sfc": {
"version": "3.5.22",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.22.tgz",
"integrity": "sha512-tbTR1zKGce4Lj+JLzFXDq36K4vcSZbJ1RBu8FxcDv1IGRz//Dh2EBqksyGVypz3kXpshIfWKGOCcqpSbyGWRJQ==",
"version": "3.5.23",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.23.tgz",
"integrity": "sha512-3QTEUo4qg7FtQwaDJa8ou1CUikx5WTtZlY61rRRDu3lK2ZKrGoAGG8mvDgOpDsQ4A1bez9s+WtBB6DS2KuFCPw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.28.4",
"@vue/compiler-core": "3.5.22",
"@vue/compiler-dom": "3.5.22",
"@vue/compiler-ssr": "3.5.22",
"@vue/shared": "3.5.22",
"@babel/parser": "^7.28.5",
"@vue/compiler-core": "3.5.23",
"@vue/compiler-dom": "3.5.23",
"@vue/compiler-ssr": "3.5.23",
"@vue/shared": "3.5.23",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.19",
"magic-string": "^0.30.21",
"postcss": "^8.5.6",
"source-map-js": "^1.2.1"
}
},
"node_modules/@vue/compiler-ssr": {
"version": "3.5.22",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.22.tgz",
"integrity": "sha512-GdgyLvg4R+7T8Nk2Mlighx7XGxq/fJf9jaVofc3IL0EPesTE86cP/8DD1lT3h1JeZr2ySBvyqKQJgbS54IX1Ww==",
"version": "3.5.23",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.23.tgz",
"integrity": "sha512-Hld2xphbMjXs9Q9WKxPf2EqmE+Rq/FEDnK/wUBtmYq74HCV4XDdSCheAaB823OQXIIFGq9ig/RbAZkF9s4U0Ow==",
"dev": true,
"license": "MIT",
"dependencies": {
"@vue/compiler-dom": "3.5.22",
"@vue/shared": "3.5.22"
"@vue/compiler-dom": "3.5.23",
"@vue/shared": "3.5.23"
}
},
"node_modules/@vue/component-compiler-utils": {
@@ -3423,9 +3423,9 @@
"license": "MIT"
},
"node_modules/@vue/shared": {
"version": "3.5.22",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.22.tgz",
"integrity": "sha512-F4yc6palwq3TT0u+FYf0Ns4Tfl9GRFURDN2gWG7L1ecIaS/4fCIuFOjMTnCyjsu/OK6vaDKLCrGAa+KvvH+h4w==",
"version": "3.5.23",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.23.tgz",
"integrity": "sha512-0YZ1DYuC5o/YJPf6pFdt2KYxVGDxkDbH/1NYJnVJWUkzr8ituBEmFVQRNX2gCaAsFEjEDnLkWpgqlZA7htgS/g==",
"dev": true,
"license": "MIT"
},
@@ -3963,9 +3963,9 @@
}
},
"node_modules/axios": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.1.tgz",
"integrity": "sha512-hU4EGxxt+j7TQijx1oYdAjw4xuIp1wRQSsbMFwSthCWeBQur1eF+qJ5iQ5sN3Tw8YRzQNKb8jszgBdMDVqwJcw==",
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz",
"integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4075,9 +4075,9 @@
"license": "MIT"
},
"node_modules/baseline-browser-mapping": {
"version": "2.8.23",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.23.tgz",
"integrity": "sha512-616V5YX4bepJFzNyOfce5Fa8fDJMfoxzOIzDCZwaGL8MKVpFrXqfNUoIpRn9YMI5pXf/VKgzjB4htFMsFKKdiQ==",
"version": "2.8.25",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.25.tgz",
"integrity": "sha512-2NovHVesVF5TXefsGX1yzx1xgr7+m9JQenvz6FQY3qd+YXkKkYiv+vTCc7OriP9mcDZpTC5mAOYN4ocd29+erA==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -5736,9 +5736,9 @@
"license": "MIT"
},
"node_modules/electron-to-chromium": {
"version": "1.5.244",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.244.tgz",
"integrity": "sha512-OszpBN7xZX4vWMPJwB9illkN/znA8M36GQqQxi6MNy9axWxhOfJyZZJtSLQCpEFLHP2xK33BiWx9aIuIEXVCcw==",
"version": "1.5.245",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.245.tgz",
"integrity": "sha512-rdmGfW47ZhL/oWEJAY4qxRtdly2B98ooTJ0pdEI4jhVLZ6tNf8fPtov2wS1IRKwFJT92le3x4Knxiwzl7cPPpQ==",
"dev": true,
"license": "ISC"
},
@@ -11008,9 +11008,9 @@
}
},
"node_modules/terser": {
"version": "5.44.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.44.0.tgz",
"integrity": "sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==",
"version": "5.44.1",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.44.1.tgz",
"integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
@@ -11517,9 +11517,9 @@
}
},
"node_modules/vite": {
"version": "7.1.12",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.1.12.tgz",
"integrity": "sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug==",
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.2.1.tgz",
"integrity": "sha512-qTl3VF7BvOupTR85Zc561sPEgxyUSNSvTQ9fit7DEMP7yPgvvIGm5Zfa1dOM+kOwWGNviK9uFM9ra77+OjK7lQ==",
"dev": true,
"license": "MIT",
"dependencies": {

View File

@@ -0,0 +1,42 @@
@extends('layout.v2.error')
@section('status_code','')
@section('status','Error message')
@section('sub_title', trans('errors.error_occurred'))
@section('content')
<div class="row">
<div class="col">
<p>
{{ trans('errors.error_not_recoverable') }}
</p>
<p class="text-danger">
{{ $message }}
</p>
</div>
</div>
<div class="row">
<div class="col">
<h4>
{{ trans('errors.more_info') }}
</h4>
<p>
{!! trans('errors.collect_info') !!}
{!! trans('errors.collect_info_more') !!}
</p>
<h4>
{{ trans('errors.github_help') }}
</h4>
<p>
{!! trans('errors.github_instructions') !!}
</p>
<ol>
<li>{{ trans('errors.use_search') }}</li>
<li>{!! trans('errors.include_info', ['link' => route('debug') ]) !!}</li>
<li>{{ trans('errors.tell_more') }}</li>
<li>{{ trans('errors.include_logs') }}</li>
<li>{{ trans('errors.what_did_you_do') }}</li>
</ol>
</div>
</div>
@endsection