From 7a992cec3f76da973bd3828dab9d1060f6735b7e Mon Sep 17 00:00:00 2001 From: HolgerHatGarKeineNode Date: Mon, 23 Mar 2026 17:50:17 +0000 Subject: [PATCH] =?UTF-8?q?-=20=E2=9C=A8=20Refactor=20`edit.blade.php`=20t?= =?UTF-8?q?o=20handle=20admin-specific=20fields=20(`accepted`=20and=20`sat?= =?UTF-8?q?s=5Fpaid`)=20through=20conditional=20logic.=20-=20=F0=9F=93=A6?= =?UTF-8?q?=20Upgrade=20Laravel=20framework,=20Livewire,=20and=20dependenc?= =?UTF-8?q?ies=20to=20ensure=20compatibility=20with=20version=20`13.1.1`.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Auth/NostrUser.php | 3 +- app/Console/Commands/Nostr/FetchEvents.php | 3 +- .../Commands/Nostr/RenderAllEvents.php | 3 +- app/Livewire/Traits/WithNostrAuth.php | 3 +- app/Models/ProjectProposal.php | 3 - app/Policies/ProjectProposalPolicy.php | 3 +- app/Traits/NostrFetcherTrait.php | 3 +- bootstrap/app.php | 3 +- bootstrap/providers.php | 7 +- composer.json | 8 +- composer.lock | 737 ++++++++---------- config/auth.php | 4 +- config/backup.php | 31 +- config/cache.php | 13 + config/livewire-powergrid.php | 14 +- config/markdown.php | 4 +- config/media-library.php | 73 +- .../factories/EinundzwanzigPlebFactory.php | 12 +- database/factories/ElectionFactory.php | 3 +- database/factories/NotificationFactory.php | 9 +- database/factories/PaymentEventFactory.php | 6 +- database/factories/ProjectProposalFactory.php | 6 +- database/factories/UserFactory.php | 3 +- .../project-support/form/edit.blade.php | 9 +- routes/web.php | 3 +- .../Livewire/ProjectSupportEditTest.php | 18 +- tests/Feature/MediaSignedRouteTest.php | 11 +- tests/Feature/Policies/ElectionPolicyTest.php | 5 +- .../Policies/ProjectProposalPolicyTest.php | 5 +- tests/Feature/RateLimitingTest.php | 9 +- tests/Pest.php | 7 +- 31 files changed, 496 insertions(+), 525 deletions(-) diff --git a/app/Auth/NostrUser.php b/app/Auth/NostrUser.php index d629d7c..8d563c5 100644 --- a/app/Auth/NostrUser.php +++ b/app/Auth/NostrUser.php @@ -2,6 +2,7 @@ namespace App\Auth; +use App\Models\EinundzwanzigPleb; use Illuminate\Contracts\Auth\Authenticatable; class NostrUser implements Authenticatable @@ -13,7 +14,7 @@ class NostrUser implements Authenticatable public function __construct(string $pubkey) { $this->pubkey = $pubkey; - $this->pleb = \App\Models\EinundzwanzigPleb::query() + $this->pleb = EinundzwanzigPleb::query() ->where('pubkey', $pubkey) ->first(); } diff --git a/app/Console/Commands/Nostr/FetchEvents.php b/app/Console/Commands/Nostr/FetchEvents.php index a6f2c77..61571f7 100644 --- a/app/Console/Commands/Nostr/FetchEvents.php +++ b/app/Console/Commands/Nostr/FetchEvents.php @@ -2,6 +2,7 @@ namespace App\Console\Commands\Nostr; +use App\Models\EinundzwanzigPleb; use App\Models\Event; use App\Traits\NostrEventRendererTrait; use Illuminate\Console\Command; @@ -35,7 +36,7 @@ class FetchEvents extends Command */ public function handle() { - $plebs = \App\Models\EinundzwanzigPleb::query() + $plebs = EinundzwanzigPleb::query() ->get(); $subscription = new Subscription; diff --git a/app/Console/Commands/Nostr/RenderAllEvents.php b/app/Console/Commands/Nostr/RenderAllEvents.php index 86d5d7d..4b87655 100644 --- a/app/Console/Commands/Nostr/RenderAllEvents.php +++ b/app/Console/Commands/Nostr/RenderAllEvents.php @@ -2,6 +2,7 @@ namespace App\Console\Commands\Nostr; +use App\Models\Event; use App\Traits\NostrEventRendererTrait; use Illuminate\Console\Command; use Illuminate\Support\Facades\Broadcast; @@ -29,7 +30,7 @@ class RenderAllEvents extends Command */ public function handle() { - $events = \App\Models\Event::query() + $events = Event::query() ->get(); foreach ($events as $event) { diff --git a/app/Livewire/Traits/WithNostrAuth.php b/app/Livewire/Traits/WithNostrAuth.php index 6ec8b93..6c00a75 100644 --- a/app/Livewire/Traits/WithNostrAuth.php +++ b/app/Livewire/Traits/WithNostrAuth.php @@ -2,6 +2,7 @@ namespace App\Livewire\Traits; +use App\Models\EinundzwanzigPleb; use App\Support\NostrAuth; use Illuminate\Support\Facades\RateLimiter; use Livewire\Attributes\On; @@ -32,7 +33,7 @@ trait WithNostrAuth NostrAuth::login($pubkey); $this->currentPubkey = $pubkey; - $this->currentPleb = \App\Models\EinundzwanzigPleb::query() + $this->currentPleb = EinundzwanzigPleb::query() ->where('pubkey', $pubkey) ->first(); diff --git a/app/Models/ProjectProposal.php b/app/Models/ProjectProposal.php index ed75187..f358e0b 100644 --- a/app/Models/ProjectProposal.php +++ b/app/Models/ProjectProposal.php @@ -22,13 +22,10 @@ class ProjectProposal extends Model implements HasMedia /** @var list */ protected $fillable = [ - 'einundzwanzig_pleb_id', 'name', 'description', 'support_in_sats', 'website', - 'accepted', - 'sats_paid', ]; /** diff --git a/app/Policies/ProjectProposalPolicy.php b/app/Policies/ProjectProposalPolicy.php index 4754279..00ef9ad 100644 --- a/app/Policies/ProjectProposalPolicy.php +++ b/app/Policies/ProjectProposalPolicy.php @@ -3,6 +3,7 @@ namespace App\Policies; use App\Auth\NostrUser; +use App\Models\EinundzwanzigPleb; use App\Models\ProjectProposal; class ProjectProposalPolicy @@ -87,7 +88,7 @@ class ProjectProposalPolicy } /** - * @param \App\Models\EinundzwanzigPleb $pleb + * @param EinundzwanzigPleb $pleb */ private function isBoardMember(object $pleb): bool { diff --git a/app/Traits/NostrFetcherTrait.php b/app/Traits/NostrFetcherTrait.php index 9ba0641..f08d74d 100644 --- a/app/Traits/NostrFetcherTrait.php +++ b/app/Traits/NostrFetcherTrait.php @@ -3,6 +3,7 @@ namespace App\Traits; use App\Models\Profile; +use Illuminate\Support\Facades\Http; use swentel\nostr\Filter\Filter; use swentel\nostr\Key\Key; use swentel\nostr\Message\RequestMessage; @@ -21,7 +22,7 @@ trait NostrFetcherTrait public function getNip05HandlesForPubkey(string $pubkey): array { try { - $response = \Illuminate\Support\Facades\Http::get( + $response = Http::get( 'https://einundzwanzig.space/.well-known/nostr.json', ); $data = $response->json(); diff --git a/bootstrap/app.php b/bootstrap/app.php index 25db56c..a9a3625 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -4,6 +4,7 @@ use App\Services\SecurityMonitor; use Illuminate\Foundation\Application; use Illuminate\Foundation\Configuration\Exceptions; use Illuminate\Foundation\Configuration\Middleware; +use Illuminate\Routing\Middleware\ThrottleRequests; use Sentry\Laravel\Integration; return Application::configure(basePath: dirname(__DIR__)) @@ -16,7 +17,7 @@ return Application::configure(basePath: dirname(__DIR__)) ) ->withMiddleware(function (Middleware $middleware) { $middleware->api(prepend: [ - \Illuminate\Routing\Middleware\ThrottleRequests::class.':api', + ThrottleRequests::class.':api', ]); }) ->withExceptions(function (Exceptions $exceptions) { diff --git a/bootstrap/providers.php b/bootstrap/providers.php index d5af9d5..c52a3b3 100644 --- a/bootstrap/providers.php +++ b/bootstrap/providers.php @@ -1,7 +1,10 @@ =8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.0", + "php": ">=8.4", + "symfony/polyfill-mbstring": "^1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^7.2|^8.0" - }, - "conflict": { - "symfony/dependency-injection": "<6.4", - "symfony/dotenv": "<6.4", - "symfony/event-dispatcher": "<6.4", - "symfony/lock": "<6.4", - "symfony/process": "<6.4" + "symfony/string": "^7.4|^8.0" }, "provide": { "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/event-dispatcher": "^6.4|^7.0|^8.0", - "symfony/http-foundation": "^6.4|^7.0|^8.0", - "symfony/http-kernel": "^6.4|^7.0|^8.0", - "symfony/lock": "^6.4|^7.0|^8.0", - "symfony/messenger": "^6.4|^7.0|^8.0", - "symfony/process": "^6.4|^7.0|^8.0", - "symfony/stopwatch": "^6.4|^7.0|^8.0", - "symfony/var-dumper": "^6.4|^7.0|^8.0" + "symfony/config": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/event-dispatcher": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/lock": "^7.4|^8.0", + "symfony/messenger": "^7.4|^8.0", + "symfony/process": "^7.4|^8.0", + "symfony/stopwatch": "^7.4|^8.0", + "symfony/var-dumper": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -8285,7 +8279,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.4.7" + "source": "https://github.com/symfony/console/tree/v8.0.7" }, "funding": [ { @@ -8305,7 +8299,7 @@ "type": "tidelift" } ], - "time": "2026-03-06T14:06:20+00:00" + "time": "2026-03-06T14:06:22+00:00" }, { "name": "symfony/css-selector", @@ -8445,33 +8439,32 @@ }, { "name": "symfony/error-handler", - "version": "v7.4.4", + "version": "v8.0.4", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "8da531f364ddfee53e36092a7eebbbd0b775f6b8" + "reference": "7620b97ec0ab1d2d6c7fb737aa55da411bea776a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/8da531f364ddfee53e36092a7eebbbd0b775f6b8", - "reference": "8da531f364ddfee53e36092a7eebbbd0b775f6b8", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/7620b97ec0ab1d2d6c7fb737aa55da411bea776a", + "reference": "7620b97ec0ab1d2d6c7fb737aa55da411bea776a", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "psr/log": "^1|^2|^3", "symfony/polyfill-php85": "^1.32", - "symfony/var-dumper": "^6.4|^7.0|^8.0" + "symfony/var-dumper": "^7.4|^8.0" }, "conflict": { - "symfony/deprecation-contracts": "<2.5", - "symfony/http-kernel": "<6.4" + "symfony/deprecation-contracts": "<2.5" }, "require-dev": { - "symfony/console": "^6.4|^7.0|^8.0", + "symfony/console": "^7.4|^8.0", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-kernel": "^6.4|^7.0|^8.0", - "symfony/serializer": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/serializer": "^7.4|^8.0", "symfony/webpack-encore-bundle": "^1.0|^2.0" }, "bin": [ @@ -8503,7 +8496,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.4.4" + "source": "https://github.com/symfony/error-handler/tree/v8.0.4" }, "funding": [ { @@ -8523,7 +8516,7 @@ "type": "tidelift" } ], - "time": "2026-01-20T16:42:42+00:00" + "time": "2026-01-23T11:07:10+00:00" }, { "name": "symfony/event-dispatcher", @@ -8688,23 +8681,23 @@ }, { "name": "symfony/finder", - "version": "v7.4.6", + "version": "v8.0.6", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "8655bf1076b7a3a346cb11413ffdabff50c7ffcf" + "reference": "441404f09a54de6d1bd6ad219e088cdf4c91f97c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/8655bf1076b7a3a346cb11413ffdabff50c7ffcf", - "reference": "8655bf1076b7a3a346cb11413ffdabff50c7ffcf", + "url": "https://api.github.com/repos/symfony/finder/zipball/441404f09a54de6d1bd6ad219e088cdf4c91f97c", + "reference": "441404f09a54de6d1bd6ad219e088cdf4c91f97c", "shasum": "" }, "require": { - "php": ">=8.2" + "php": ">=8.4" }, "require-dev": { - "symfony/filesystem": "^6.4|^7.0|^8.0" + "symfony/filesystem": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -8732,7 +8725,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.4.6" + "source": "https://github.com/symfony/finder/tree/v8.0.6" }, "funding": [ { @@ -8752,41 +8745,39 @@ "type": "tidelift" } ], - "time": "2026-01-29T09:40:50+00:00" + "time": "2026-01-29T09:41:02+00:00" }, { "name": "symfony/http-foundation", - "version": "v7.4.7", + "version": "v8.0.7", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "f94b3e7b7dafd40e666f0c9ff2084133bae41e81" + "reference": "c5ecf7b07408dbc4a87482634307654190954ae8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/f94b3e7b7dafd40e666f0c9ff2084133bae41e81", - "reference": "f94b3e7b7dafd40e666f0c9ff2084133bae41e81", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/c5ecf7b07408dbc4a87482634307654190954ae8", + "reference": "c5ecf7b07408dbc4a87482634307654190954ae8", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", + "php": ">=8.4", "symfony/polyfill-mbstring": "^1.1" }, "conflict": { - "doctrine/dbal": "<3.6", - "symfony/cache": "<6.4.12|>=7.0,<7.1.5" + "doctrine/dbal": "<4.3" }, "require-dev": { - "doctrine/dbal": "^3.6|^4", + "doctrine/dbal": "^4.3", "predis/predis": "^1.1|^2.0", - "symfony/cache": "^6.4.12|^7.1.5|^8.0", - "symfony/clock": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/expression-language": "^6.4|^7.0|^8.0", - "symfony/http-kernel": "^6.4|^7.0|^8.0", - "symfony/mime": "^6.4|^7.0|^8.0", - "symfony/rate-limiter": "^6.4|^7.0|^8.0" + "symfony/cache": "^7.4|^8.0", + "symfony/clock": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/mime": "^7.4|^8.0", + "symfony/rate-limiter": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -8814,7 +8805,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.4.7" + "source": "https://github.com/symfony/http-foundation/tree/v8.0.7" }, "funding": [ { @@ -8834,78 +8825,63 @@ "type": "tidelift" } ], - "time": "2026-03-06T13:15:18+00:00" + "time": "2026-03-06T13:17:40+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.4.7", + "version": "v8.0.7", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "3b3fcf386c809be990c922e10e4c620d6367cab1" + "reference": "c04721f45723d8ce049fa3eee378b5a505272ac7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/3b3fcf386c809be990c922e10e4c620d6367cab1", - "reference": "3b3fcf386c809be990c922e10e4c620d6367cab1", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/c04721f45723d8ce049fa3eee378b5a505272ac7", + "reference": "c04721f45723d8ce049fa3eee378b5a505272ac7", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^6.4|^7.0|^8.0", - "symfony/event-dispatcher": "^7.3|^8.0", + "symfony/error-handler": "^7.4|^8.0", + "symfony/event-dispatcher": "^7.4|^8.0", "symfony/http-foundation": "^7.4|^8.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { - "symfony/browser-kit": "<6.4", - "symfony/cache": "<6.4", - "symfony/config": "<6.4", - "symfony/console": "<6.4", - "symfony/dependency-injection": "<6.4", - "symfony/doctrine-bridge": "<6.4", "symfony/flex": "<2.10", - "symfony/form": "<6.4", - "symfony/http-client": "<6.4", "symfony/http-client-contracts": "<2.5", - "symfony/mailer": "<6.4", - "symfony/messenger": "<6.4", - "symfony/translation": "<6.4", "symfony/translation-contracts": "<2.5", - "symfony/twig-bridge": "<6.4", - "symfony/validator": "<6.4", - "symfony/var-dumper": "<6.4", - "twig/twig": "<3.12" + "twig/twig": "<3.21" }, "provide": { "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", - "symfony/browser-kit": "^6.4|^7.0|^8.0", - "symfony/clock": "^6.4|^7.0|^8.0", - "symfony/config": "^6.4|^7.0|^8.0", - "symfony/console": "^6.4|^7.0|^8.0", - "symfony/css-selector": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4.1|^7.0.1|^8.0", - "symfony/dom-crawler": "^6.4|^7.0|^8.0", - "symfony/expression-language": "^6.4|^7.0|^8.0", - "symfony/finder": "^6.4|^7.0|^8.0", + "symfony/browser-kit": "^7.4|^8.0", + "symfony/clock": "^7.4|^8.0", + "symfony/config": "^7.4|^8.0", + "symfony/console": "^7.4|^8.0", + "symfony/css-selector": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/dom-crawler": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/finder": "^7.4|^8.0", "symfony/http-client-contracts": "^2.5|^3", - "symfony/process": "^6.4|^7.0|^8.0", - "symfony/property-access": "^7.1|^8.0", - "symfony/routing": "^6.4|^7.0|^8.0", - "symfony/serializer": "^7.1|^8.0", - "symfony/stopwatch": "^6.4|^7.0|^8.0", - "symfony/translation": "^6.4|^7.0|^8.0", + "symfony/process": "^7.4|^8.0", + "symfony/property-access": "^7.4|^8.0", + "symfony/routing": "^7.4|^8.0", + "symfony/serializer": "^7.4|^8.0", + "symfony/stopwatch": "^7.4|^8.0", + "symfony/translation": "^7.4|^8.0", "symfony/translation-contracts": "^2.5|^3", - "symfony/uid": "^6.4|^7.0|^8.0", - "symfony/validator": "^6.4|^7.0|^8.0", - "symfony/var-dumper": "^6.4|^7.0|^8.0", - "symfony/var-exporter": "^6.4|^7.0|^8.0", - "twig/twig": "^3.12" + "symfony/uid": "^7.4|^8.0", + "symfony/validator": "^7.4|^8.0", + "symfony/var-dumper": "^7.4|^8.0", + "symfony/var-exporter": "^7.4|^8.0", + "twig/twig": "^3.21" }, "type": "library", "autoload": { @@ -8933,7 +8909,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.4.7" + "source": "https://github.com/symfony/http-kernel/tree/v8.0.7" }, "funding": [ { @@ -8953,43 +8929,39 @@ "type": "tidelift" } ], - "time": "2026-03-06T16:33:18+00:00" + "time": "2026-03-06T16:58:46+00:00" }, { "name": "symfony/mailer", - "version": "v7.4.6", + "version": "v8.0.6", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "b02726f39a20bc65e30364f5c750c4ddbf1f58e9" + "reference": "a8971c86b25ff8557e844f08c1f6207d9b3e614c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/b02726f39a20bc65e30364f5c750c4ddbf1f58e9", - "reference": "b02726f39a20bc65e30364f5c750c4ddbf1f58e9", + "url": "https://api.github.com/repos/symfony/mailer/zipball/a8971c86b25ff8557e844f08c1f6207d9b3e614c", + "reference": "a8971c86b25ff8557e844f08c1f6207d9b3e614c", "shasum": "" }, "require": { "egulias/email-validator": "^2.1.10|^3|^4", - "php": ">=8.2", + "php": ">=8.4", "psr/event-dispatcher": "^1", "psr/log": "^1|^2|^3", - "symfony/event-dispatcher": "^6.4|^7.0|^8.0", - "symfony/mime": "^7.2|^8.0", + "symfony/event-dispatcher": "^7.4|^8.0", + "symfony/mime": "^7.4|^8.0", "symfony/service-contracts": "^2.5|^3" }, "conflict": { - "symfony/http-client-contracts": "<2.5", - "symfony/http-kernel": "<6.4", - "symfony/messenger": "<6.4", - "symfony/mime": "<6.4", - "symfony/twig-bridge": "<6.4" + "symfony/http-client-contracts": "<2.5" }, "require-dev": { - "symfony/console": "^6.4|^7.0|^8.0", - "symfony/http-client": "^6.4|^7.0|^8.0", - "symfony/messenger": "^6.4|^7.0|^8.0", - "symfony/twig-bridge": "^6.4|^7.0|^8.0" + "symfony/console": "^7.4|^8.0", + "symfony/http-client": "^7.4|^8.0", + "symfony/messenger": "^7.4|^8.0", + "symfony/twig-bridge": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -9017,7 +8989,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.4.6" + "source": "https://github.com/symfony/mailer/tree/v8.0.6" }, "funding": [ { @@ -9037,44 +9009,41 @@ "type": "tidelift" } ], - "time": "2026-02-25T16:50:00+00:00" + "time": "2026-02-25T16:59:43+00:00" }, { "name": "symfony/mime", - "version": "v7.4.7", + "version": "v8.0.7", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "da5ab4fde3f6c88ab06e96185b9922f48b677cd1" + "reference": "5d26d1958aeeba2ace8cc64a3a93d4f5d8f8022b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/da5ab4fde3f6c88ab06e96185b9922f48b677cd1", - "reference": "da5ab4fde3f6c88ab06e96185b9922f48b677cd1", + "url": "https://api.github.com/repos/symfony/mime/zipball/5d26d1958aeeba2ace8cc64a3a93d4f5d8f8022b", + "reference": "5d26d1958aeeba2ace8cc64a3a93d4f5d8f8022b", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", + "php": ">=8.4", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0" }, "conflict": { "egulias/email-validator": "~3.0.0", "phpdocumentor/reflection-docblock": "<5.2|>=7", - "phpdocumentor/type-resolver": "<1.5.1", - "symfony/mailer": "<6.4", - "symfony/serializer": "<6.4.3|>7.0,<7.0.3" + "phpdocumentor/type-resolver": "<1.5.1" }, "require-dev": { "egulias/email-validator": "^2.1.10|^3.1|^4", "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^5.2|^6.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/process": "^6.4|^7.0|^8.0", - "symfony/property-access": "^6.4|^7.0|^8.0", - "symfony/property-info": "^6.4|^7.0|^8.0", - "symfony/serializer": "^6.4.3|^7.0.3|^8.0" + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/process": "^7.4|^8.0", + "symfony/property-access": "^7.4|^8.0", + "symfony/property-info": "^7.4|^8.0", + "symfony/serializer": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -9106,7 +9075,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.4.7" + "source": "https://github.com/symfony/mime/tree/v8.0.7" }, "funding": [ { @@ -9126,7 +9095,7 @@ "type": "tidelift" } ], - "time": "2026-03-05T15:24:09+00:00" + "time": "2026-03-06T13:17:40+00:00" }, { "name": "symfony/options-resolver", @@ -9705,86 +9674,6 @@ ], "time": "2025-01-02T08:10:11+00:00" }, - { - "name": "symfony/polyfill-php83", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/17f6f9a6b1735c0f163024d959f700cfbc5155e5", - "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php83\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.33.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-08T02:45:35+00:00" - }, { "name": "symfony/polyfill-php84", "version": "v1.33.0", @@ -10030,20 +9919,20 @@ }, { "name": "symfony/process", - "version": "v7.4.5", + "version": "v8.0.5", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "608476f4604102976d687c483ac63a79ba18cc97" + "reference": "b5f3aa6762e33fd95efbaa2ec4f4bc9fdd16d674" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/608476f4604102976d687c483ac63a79ba18cc97", - "reference": "608476f4604102976d687c483ac63a79ba18cc97", + "url": "https://api.github.com/repos/symfony/process/zipball/b5f3aa6762e33fd95efbaa2ec4f4bc9fdd16d674", + "reference": "b5f3aa6762e33fd95efbaa2ec4f4bc9fdd16d674", "shasum": "" }, "require": { - "php": ">=8.2" + "php": ">=8.4" }, "type": "library", "autoload": { @@ -10071,7 +9960,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.4.5" + "source": "https://github.com/symfony/process/tree/v8.0.5" }, "funding": [ { @@ -10091,7 +9980,7 @@ "type": "tidelift" } ], - "time": "2026-01-26T15:07:59+00:00" + "time": "2026-01-26T15:08:38+00:00" }, { "name": "symfony/psr-http-message-bridge", @@ -10182,34 +10071,29 @@ }, { "name": "symfony/routing", - "version": "v7.4.6", + "version": "v8.0.6", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "238d749c56b804b31a9bf3e26519d93b65a60938" + "reference": "053c40fd46e1d19c5c5a94cada93ce6c3facdd55" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/238d749c56b804b31a9bf3e26519d93b65a60938", - "reference": "238d749c56b804b31a9bf3e26519d93b65a60938", + "url": "https://api.github.com/repos/symfony/routing/zipball/053c40fd46e1d19c5c5a94cada93ce6c3facdd55", + "reference": "053c40fd46e1d19c5c5a94cada93ce6c3facdd55", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/deprecation-contracts": "^2.5|^3" }, - "conflict": { - "symfony/config": "<6.4", - "symfony/dependency-injection": "<6.4", - "symfony/yaml": "<6.4" - }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/expression-language": "^6.4|^7.0|^8.0", - "symfony/http-foundation": "^6.4|^7.0|^8.0", - "symfony/yaml": "^6.4|^7.0|^8.0" + "symfony/config": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", + "symfony/yaml": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -10243,7 +10127,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.4.6" + "source": "https://github.com/symfony/routing/tree/v8.0.6" }, "funding": [ { @@ -10263,7 +10147,7 @@ "type": "tidelift" } ], - "time": "2026-02-25T16:50:00+00:00" + "time": "2026-02-25T16:59:43+00:00" }, { "name": "symfony/service-contracts", @@ -10619,24 +10503,24 @@ }, { "name": "symfony/uid", - "version": "v7.4.4", + "version": "v8.0.4", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "7719ce8aba76be93dfe249192f1fbfa52c588e36" + "reference": "8b81bd3700f5c1913c22a3266a647aa1bb974435" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/7719ce8aba76be93dfe249192f1fbfa52c588e36", - "reference": "7719ce8aba76be93dfe249192f1fbfa52c588e36", + "url": "https://api.github.com/repos/symfony/uid/zipball/8b81bd3700f5c1913c22a3266a647aa1bb974435", + "reference": "8b81bd3700f5c1913c22a3266a647aa1bb974435", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/polyfill-uuid": "^1.15" }, "require-dev": { - "symfony/console": "^6.4|^7.0|^8.0" + "symfony/console": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -10673,7 +10557,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v7.4.4" + "source": "https://github.com/symfony/uid/tree/v8.0.4" }, "funding": [ { @@ -10693,35 +10577,35 @@ "type": "tidelift" } ], - "time": "2026-01-03T23:30:35+00:00" + "time": "2026-01-03T23:40:55+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.4.6", + "version": "v8.0.6", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "045321c440ac18347b136c63d2e9bf28a2dc0291" + "reference": "2e14f7e0bf5ff02c6e63bd31cb8e4855a13d6209" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/045321c440ac18347b136c63d2e9bf28a2dc0291", - "reference": "045321c440ac18347b136c63d2e9bf28a2dc0291", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/2e14f7e0bf5ff02c6e63bd31cb8e4855a13d6209", + "reference": "2e14f7e0bf5ff02c6e63bd31cb8e4855a13d6209", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.0" + "php": ">=8.4", + "symfony/polyfill-mbstring": "^1.0" }, "conflict": { - "symfony/console": "<6.4" + "symfony/console": "<7.4", + "symfony/error-handler": "<7.4" }, "require-dev": { - "symfony/console": "^6.4|^7.0|^8.0", - "symfony/http-kernel": "^6.4|^7.0|^8.0", - "symfony/process": "^6.4|^7.0|^8.0", - "symfony/uid": "^6.4|^7.0|^8.0", + "symfony/console": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/process": "^7.4|^8.0", + "symfony/uid": "^7.4|^8.0", "twig/twig": "^3.12" }, "bin": [ @@ -10760,7 +10644,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.4.6" + "source": "https://github.com/symfony/var-dumper/tree/v8.0.6" }, "funding": [ { @@ -10780,7 +10664,7 @@ "type": "tidelift" } ], - "time": "2026-02-15T10:53:20+00:00" + "time": "2026-02-15T10:53:29+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -11386,33 +11270,33 @@ }, { "name": "laravel/boost", - "version": "v1.8.12", + "version": "v2.3.4", "source": { "type": "git", "url": "https://github.com/laravel/boost.git", - "reference": "5a0bf68e48e6d159182859f9ed6e404313103309" + "reference": "9e3dd5f05b59394e463e78853067dc36c63a0394" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/boost/zipball/5a0bf68e48e6d159182859f9ed6e404313103309", - "reference": "5a0bf68e48e6d159182859f9ed6e404313103309", + "url": "https://api.github.com/repos/laravel/boost/zipball/9e3dd5f05b59394e463e78853067dc36c63a0394", + "reference": "9e3dd5f05b59394e463e78853067dc36c63a0394", "shasum": "" }, "require": { "guzzlehttp/guzzle": "^7.9", - "illuminate/console": "^10.49.0|^11.45.3|^12.41.1", - "illuminate/contracts": "^10.49.0|^11.45.3|^12.41.1", - "illuminate/routing": "^10.49.0|^11.45.3|^12.41.1", - "illuminate/support": "^10.49.0|^11.45.3|^12.41.1", - "laravel/mcp": "^0.5.1", - "laravel/prompts": "0.1.25|^0.3.6", - "laravel/roster": "^0.2.9", - "php": "^8.1" + "illuminate/console": "^11.45.3|^12.41.1|^13.0", + "illuminate/contracts": "^11.45.3|^12.41.1|^13.0", + "illuminate/routing": "^11.45.3|^12.41.1|^13.0", + "illuminate/support": "^11.45.3|^12.41.1|^13.0", + "laravel/mcp": "^0.5.1|^0.6.0", + "laravel/prompts": "^0.3.10", + "laravel/roster": "^0.5.0", + "php": "^8.2" }, "require-dev": { - "laravel/pint": "^1.20.0", + "laravel/pint": "^1.27.0", "mockery/mockery": "^1.6.12", - "orchestra/testbench": "^8.36.0|^9.15.0|^10.6", + "orchestra/testbench": "^9.15.0|^10.6|^11.0", "pestphp/pest": "^2.36.0|^3.8.4|^4.1.5", "phpstan/phpstan": "^2.1.27", "rector/rector": "^2.1" @@ -11448,20 +11332,20 @@ "issues": "https://github.com/laravel/boost/issues", "source": "https://github.com/laravel/boost" }, - "time": "2026-03-12T07:25:30+00:00" + "time": "2026-03-17T16:42:14+00:00" }, { "name": "laravel/mcp", - "version": "v0.5.9", + "version": "v0.6.3", "source": { "type": "git", "url": "https://github.com/laravel/mcp.git", - "reference": "39e8da60eb7bce4737c5d868d35a3fe78938c129" + "reference": "8a2c97ec1184e16029080e3f6172a7ca73de4df9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/mcp/zipball/39e8da60eb7bce4737c5d868d35a3fe78938c129", - "reference": "39e8da60eb7bce4737c5d868d35a3fe78938c129", + "url": "https://api.github.com/repos/laravel/mcp/zipball/8a2c97ec1184e16029080e3f6172a7ca73de4df9", + "reference": "8a2c97ec1184e16029080e3f6172a7ca73de4df9", "shasum": "" }, "require": { @@ -11521,7 +11405,7 @@ "issues": "https://github.com/laravel/mcp/issues", "source": "https://github.com/laravel/mcp" }, - "time": "2026-02-17T19:05:53+00:00" + "time": "2026-03-12T12:46:43+00:00" }, { "name": "laravel/pail", @@ -11673,31 +11557,31 @@ }, { "name": "laravel/roster", - "version": "v0.2.9", + "version": "v0.5.1", "source": { "type": "git", "url": "https://github.com/laravel/roster.git", - "reference": "82bbd0e2de614906811aebdf16b4305956816fa6" + "reference": "5089de7615f72f78e831590ff9d0435fed0102bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/roster/zipball/82bbd0e2de614906811aebdf16b4305956816fa6", - "reference": "82bbd0e2de614906811aebdf16b4305956816fa6", + "url": "https://api.github.com/repos/laravel/roster/zipball/5089de7615f72f78e831590ff9d0435fed0102bb", + "reference": "5089de7615f72f78e831590ff9d0435fed0102bb", "shasum": "" }, "require": { - "illuminate/console": "^10.0|^11.0|^12.0", - "illuminate/contracts": "^10.0|^11.0|^12.0", - "illuminate/routing": "^10.0|^11.0|^12.0", - "illuminate/support": "^10.0|^11.0|^12.0", - "php": "^8.1|^8.2", - "symfony/yaml": "^6.4|^7.2" + "illuminate/console": "^11.0|^12.0|^13.0", + "illuminate/contracts": "^11.0|^12.0|^13.0", + "illuminate/routing": "^11.0|^12.0|^13.0", + "illuminate/support": "^11.0|^12.0|^13.0", + "php": "^8.2", + "symfony/yaml": "^7.2|^8.0" }, "require-dev": { "laravel/pint": "^1.14", "mockery/mockery": "^1.6", - "orchestra/testbench": "^8.22.0|^9.0|^10.0", - "pestphp/pest": "^2.0|^3.0", + "orchestra/testbench": "^9.0|^10.0|^11.0", + "pestphp/pest": "^3.0|^4.1", "phpstan/phpstan": "^2.0" }, "type": "library", @@ -11730,7 +11614,7 @@ "issues": "https://github.com/laravel/roster/issues", "source": "https://github.com/laravel/roster" }, - "time": "2025-10-20T09:56:46+00:00" + "time": "2026-03-05T07:58:43+00:00" }, { "name": "mockery/mockery", @@ -14177,28 +14061,27 @@ }, { "name": "symfony/yaml", - "version": "v7.4.6", + "version": "v8.0.6", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "58751048de17bae71c5aa0d13cb19d79bca26391" + "reference": "5f006c50a981e1630bbb70ad409c5d85f9a716e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/58751048de17bae71c5aa0d13cb19d79bca26391", - "reference": "58751048de17bae71c5aa0d13cb19d79bca26391", + "url": "https://api.github.com/repos/symfony/yaml/zipball/5f006c50a981e1630bbb70ad409c5d85f9a716e0", + "reference": "5f006c50a981e1630bbb70ad409c5d85f9a716e0", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", + "php": ">=8.4", "symfony/polyfill-ctype": "^1.8" }, "conflict": { - "symfony/console": "<6.4" + "symfony/console": "<7.4" }, "require-dev": { - "symfony/console": "^6.4|^7.0|^8.0" + "symfony/console": "^7.4|^8.0" }, "bin": [ "Resources/bin/yaml-lint" @@ -14229,7 +14112,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v7.4.6" + "source": "https://github.com/symfony/yaml/tree/v8.0.6" }, "funding": [ { @@ -14249,7 +14132,7 @@ "type": "tidelift" } ], - "time": "2026-02-09T09:33:46+00:00" + "time": "2026-02-09T10:14:57+00:00" }, { "name": "ta-tikoma/phpunit-architecture-test", diff --git a/config/auth.php b/config/auth.php index c8aee63..7905bbf 100644 --- a/config/auth.php +++ b/config/auth.php @@ -1,5 +1,7 @@ [ 'users' => [ 'driver' => 'eloquent', - 'model' => env('AUTH_MODEL', App\Models\User::class), + 'model' => env('AUTH_MODEL', User::class), ], 'nostr' => [ 'driver' => 'nostr', diff --git a/config/backup.php b/config/backup.php index 54f4c4c..94aa18c 100644 --- a/config/backup.php +++ b/config/backup.php @@ -1,5 +1,16 @@ [ @@ -196,19 +207,19 @@ return [ */ 'notifications' => [ 'notifications' => [ - \Spatie\Backup\Notifications\Notifications\BackupHasFailedNotification::class => ['mail'], - \Spatie\Backup\Notifications\Notifications\UnhealthyBackupWasFoundNotification::class => ['mail'], - \Spatie\Backup\Notifications\Notifications\CleanupHasFailedNotification::class => ['mail'], - \Spatie\Backup\Notifications\Notifications\BackupWasSuccessfulNotification::class => ['mail'], - \Spatie\Backup\Notifications\Notifications\HealthyBackupWasFoundNotification::class => ['mail'], - \Spatie\Backup\Notifications\Notifications\CleanupWasSuccessfulNotification::class => ['mail'], + BackupHasFailedNotification::class => ['mail'], + UnhealthyBackupWasFoundNotification::class => ['mail'], + CleanupHasFailedNotification::class => ['mail'], + BackupWasSuccessfulNotification::class => ['mail'], + HealthyBackupWasFoundNotification::class => ['mail'], + CleanupWasSuccessfulNotification::class => ['mail'], ], /* * Here you can specify the notifiable to which the notifications should be sent. The default * notifiable will use the variables specified in this config file. */ - 'notifiable' => \Spatie\Backup\Notifications\Notifiable::class, + 'notifiable' => Notifiable::class, 'mail' => [ 'to' => 'your@example.com', @@ -257,8 +268,8 @@ return [ 'name' => env('APP_NAME', 'laravel-backup'), 'disks' => ['backups'], 'health_checks' => [ - \Spatie\Backup\Tasks\Monitor\HealthChecks\MaximumAgeInDays::class => 1, - \Spatie\Backup\Tasks\Monitor\HealthChecks\MaximumStorageInMegabytes::class => 5000, + MaximumAgeInDays::class => 1, + MaximumStorageInMegabytes::class => 5000, ], ], @@ -284,7 +295,7 @@ return [ * No matter how you configure it the default strategy will never * delete the newest backup. */ - 'strategy' => \Spatie\Backup\Tasks\Cleanup\Strategies\DefaultStrategy::class, + 'strategy' => DefaultStrategy::class, 'default_strategy' => [ /* diff --git a/config/cache.php b/config/cache.php index 925f7d2..10d7904 100644 --- a/config/cache.php +++ b/config/cache.php @@ -105,4 +105,17 @@ return [ 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache_'), + /* + |-------------------------------------------------------------------------- + | Serializable Classes + |-------------------------------------------------------------------------- + | + | This option allows you to specify which classes may be unserialized from + | the cache to help prevent PHP deserialization gadget chain attacks. + | Set to false to allow no classes to be unserialized from cache. + | + */ + + 'serializable_classes' => false, + ]; diff --git a/config/livewire-powergrid.php b/config/livewire-powergrid.php index 6af01e7..f0d1e76 100644 --- a/config/livewire-powergrid.php +++ b/config/livewire-powergrid.php @@ -1,5 +1,9 @@ \PowerComponents\LivewirePowerGrid\Themes\Tailwind::class, + 'theme' => Tailwind::class, // 'theme' => \PowerComponents\LivewirePowerGrid\Themes\Bootstrap5::class, /* @@ -130,12 +134,12 @@ return [ 'exportable' => [ 'default' => 'openspout_v4', 'openspout_v4' => [ - 'xlsx' => \PowerComponents\LivewirePowerGrid\Components\Exports\OpenSpout\v4\ExportToXLS::class, - 'csv' => \PowerComponents\LivewirePowerGrid\Components\Exports\OpenSpout\v4\ExportToCsv::class, + 'xlsx' => ExportToXLS::class, + 'csv' => ExportToCsv::class, ], 'openspout_v3' => [ - 'xlsx' => \PowerComponents\LivewirePowerGrid\Components\Exports\OpenSpout\v3\ExportToXLS::class, - 'csv' => \PowerComponents\LivewirePowerGrid\Components\Exports\OpenSpout\v3\ExportToCsv::class, + 'xlsx' => PowerComponents\LivewirePowerGrid\Components\Exports\OpenSpout\v3\ExportToXLS::class, + 'csv' => PowerComponents\LivewirePowerGrid\Components\Exports\OpenSpout\v3\ExportToCsv::class, ], ], diff --git a/config/markdown.php b/config/markdown.php index 98666ab..dbdfdb1 100644 --- a/config/markdown.php +++ b/config/markdown.php @@ -1,5 +1,7 @@ [ /* @@ -64,7 +66,7 @@ return [ * * More info: https://spatie.be/docs/laravel-markdown/v1/advanced-usage/customizing-the-rendering-process */ - 'renderer_class' => Spatie\LaravelMarkdown\MarkdownRenderer::class, + 'renderer_class' => MarkdownRenderer::class, /* * These extensions should be added to the markdown environment. A valid diff --git a/config/media-library.php b/config/media-library.php index 6f8881c..ef9c807 100644 --- a/config/media-library.php +++ b/config/media-library.php @@ -1,5 +1,30 @@ Spatie\MediaLibrary\MediaCollections\Models\Media::class, + 'media_model' => Media::class, /* * When enabled, media collections will be serialised using the default @@ -54,7 +79,7 @@ return [ * * This model is only used in Media Library Pro (https://medialibrary.pro) */ - 'temporary_upload_model' => Spatie\MediaLibraryPro\Models\TemporaryUpload::class, + 'temporary_upload_model' => TemporaryUpload::class, /* * When enabled, Media Library Pro will only process temporary uploads that were uploaded @@ -71,17 +96,17 @@ return [ /* * This is the class that is responsible for naming generated files. */ - 'file_namer' => Spatie\MediaLibrary\Support\FileNamer\DefaultFileNamer::class, + 'file_namer' => DefaultFileNamer::class, /* * The class that contains the strategy for determining a media file's path. */ - 'path_generator' => Spatie\MediaLibrary\Support\PathGenerator\DefaultPathGenerator::class, + 'path_generator' => DefaultPathGenerator::class, /* * The class that contains the strategy for determining how to remove files. */ - 'file_remover_class' => Spatie\MediaLibrary\Support\FileRemover\DefaultFileRemover::class, + 'file_remover_class' => DefaultFileRemover::class, /* * Here you can specify which path generator should be used for the given class. @@ -96,7 +121,7 @@ return [ * When urls to files get generated, this class will be called. Use the default * if your files are stored locally above the site root or on s3. */ - 'url_generator' => Spatie\MediaLibrary\Support\UrlGenerator\DefaultUrlGenerator::class, + 'url_generator' => DefaultUrlGenerator::class, /* * Moves media on updating to keep path consistent. Enable it only with a custom @@ -116,34 +141,34 @@ return [ * the optimizers that will be used by default. */ 'image_optimizers' => [ - Spatie\ImageOptimizer\Optimizers\Jpegoptim::class => [ + Jpegoptim::class => [ '-m85', // set maximum quality to 85% '--force', // ensure that progressive generation is always done also if a little bigger '--strip-all', // this strips out all text information such as comments and EXIF data '--all-progressive', // this will make sure the resulting image is a progressive one ], - Spatie\ImageOptimizer\Optimizers\Pngquant::class => [ + Pngquant::class => [ '--force', // required parameter for this package ], - Spatie\ImageOptimizer\Optimizers\Optipng::class => [ + Optipng::class => [ '-i0', // this will result in a non-interlaced, progressive scanned image '-o2', // this set the optimization level to two (multiple IDAT compression trials) '-quiet', // required parameter for this package ], - Spatie\ImageOptimizer\Optimizers\Svgo::class => [ + Svgo::class => [ '--disable=cleanupIDs', // disabling because it is known to cause troubles ], - Spatie\ImageOptimizer\Optimizers\Gifsicle::class => [ + Gifsicle::class => [ '-b', // required parameter for this package '-O3', // this produces the slowest but best results ], - Spatie\ImageOptimizer\Optimizers\Cwebp::class => [ + Cwebp::class => [ '-m 6', // for the slowest compression method in order to get the best compression. '-pass 10', // for maximizing the amount of analysis pass. '-mt', // multithreading for some speed improvements. '-q 90', // quality factor that brings the least noticeable changes. ], - Spatie\ImageOptimizer\Optimizers\Avifenc::class => [ + Avifenc::class => [ '-a cq-level=23', // constant quality level, lower values mean better quality and greater file size (0-63). '-j all', // number of jobs (worker threads, "all" uses all available cores). '--min 0', // min quantizer for color (0-63). @@ -159,12 +184,12 @@ return [ * These generators will be used to create an image of media files. */ 'image_generators' => [ - Spatie\MediaLibrary\Conversions\ImageGenerators\Image::class, - Spatie\MediaLibrary\Conversions\ImageGenerators\Webp::class, - Spatie\MediaLibrary\Conversions\ImageGenerators\Avif::class, - Spatie\MediaLibrary\Conversions\ImageGenerators\Pdf::class, - Spatie\MediaLibrary\Conversions\ImageGenerators\Svg::class, - Spatie\MediaLibrary\Conversions\ImageGenerators\Video::class, + Image::class, + Webp::class, + Avif::class, + Pdf::class, + Svg::class, + Video::class, ], /* @@ -192,8 +217,8 @@ return [ * your custom jobs extend the ones provided by the package. */ 'jobs' => [ - 'perform_conversions' => Spatie\MediaLibrary\Conversions\Jobs\PerformConversionsJob::class, - 'generate_responsive_images' => Spatie\MediaLibrary\ResponsiveImages\Jobs\GenerateResponsiveImagesJob::class, + 'perform_conversions' => PerformConversionsJob::class, + 'generate_responsive_images' => GenerateResponsiveImagesJob::class, ], /* @@ -201,7 +226,7 @@ return [ * This is particularly useful when the url of the image is behind a firewall and * need to add additional flags, possibly using curl. */ - 'media_downloader' => Spatie\MediaLibrary\Downloaders\DefaultDownloader::class, + 'media_downloader' => DefaultDownloader::class, /* * When using the addMediaFromUrl method the SSL is verified by default. @@ -232,7 +257,7 @@ return [ * * https://docs.spatie.be/laravel-medialibrary/v9/advanced-usage/generating-responsive-images */ - 'width_calculator' => Spatie\MediaLibrary\ResponsiveImages\WidthCalculator\FileSizeOptimizedWidthCalculator::class, + 'width_calculator' => FileSizeOptimizedWidthCalculator::class, /* * By default rendering media to a responsive image will add some javascript and a tiny placeholder. @@ -245,7 +270,7 @@ return [ * This class will generate the tiny placeholder used for progressive image loading. By default * the media library will use a tiny blurred jpg image. */ - 'tiny_placeholder_generator' => Spatie\MediaLibrary\ResponsiveImages\TinyPlaceholderGenerator\Blurred::class, + 'tiny_placeholder_generator' => Blurred::class, ], /* diff --git a/database/factories/EinundzwanzigPlebFactory.php b/database/factories/EinundzwanzigPlebFactory.php index 92753b6..d4e1927 100644 --- a/database/factories/EinundzwanzigPlebFactory.php +++ b/database/factories/EinundzwanzigPlebFactory.php @@ -2,10 +2,12 @@ namespace Database\Factories; +use App\Enums\AssociationStatus; +use App\Models\EinundzwanzigPleb; use Illuminate\Database\Eloquent\Factories\Factory; /** - * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\EinundzwanzigPleb> + * @extends Factory */ class EinundzwanzigPlebFactory extends Factory { @@ -20,14 +22,14 @@ class EinundzwanzigPlebFactory extends Factory 'pubkey' => $this->faker->sha256(), 'npub' => $this->faker->word(), 'email' => $this->faker->safeEmail(), - 'association_status' => \App\Enums\AssociationStatus::DEFAULT, + 'association_status' => AssociationStatus::DEFAULT, ]; } public function active(): static { return $this->state(fn (array $attributes) => [ - 'association_status' => \App\Enums\AssociationStatus::ACTIVE, + 'association_status' => AssociationStatus::ACTIVE, ]); } @@ -35,13 +37,13 @@ class EinundzwanzigPlebFactory extends Factory { return $this->state(fn (array $attributes) => [ 'npub' => config('einundzwanzig.config.current_board')[0], - 'association_status' => \App\Enums\AssociationStatus::HONORARY, + 'association_status' => AssociationStatus::HONORARY, ]); } public function withPaidCurrentYear(): static { - return $this->afterCreating(function (\App\Models\EinundzwanzigPleb $pleb) { + return $this->afterCreating(function (EinundzwanzigPleb $pleb) { $pleb->paymentEvents()->create([ 'year' => date('Y'), 'amount' => 21000, diff --git a/database/factories/ElectionFactory.php b/database/factories/ElectionFactory.php index df3cf90..0a0cc16 100644 --- a/database/factories/ElectionFactory.php +++ b/database/factories/ElectionFactory.php @@ -2,10 +2,11 @@ namespace Database\Factories; +use App\Models\Election; use Illuminate\Database\Eloquent\Factories\Factory; /** - * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Election> + * @extends Factory */ class ElectionFactory extends Factory { diff --git a/database/factories/NotificationFactory.php b/database/factories/NotificationFactory.php index 3fa0bd3..2e257a4 100644 --- a/database/factories/NotificationFactory.php +++ b/database/factories/NotificationFactory.php @@ -2,10 +2,13 @@ namespace Database\Factories; +use App\Enums\NewsCategory; +use App\Models\EinundzwanzigPleb; +use App\Models\Notification; use Illuminate\Database\Eloquent\Factories\Factory; /** - * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Notification> + * @extends Factory */ class NotificationFactory extends Factory { @@ -19,8 +22,8 @@ class NotificationFactory extends Factory return [ 'name' => $this->faker->sentence(3), 'description' => $this->faker->paragraph(), - 'category' => $this->faker->randomElement(\App\Enums\NewsCategory::cases()), - 'einundzwanzig_pleb_id' => \App\Models\EinundzwanzigPleb::factory(), + 'category' => $this->faker->randomElement(NewsCategory::cases()), + 'einundzwanzig_pleb_id' => EinundzwanzigPleb::factory(), ]; } } diff --git a/database/factories/PaymentEventFactory.php b/database/factories/PaymentEventFactory.php index 40c0539..8d4eed0 100644 --- a/database/factories/PaymentEventFactory.php +++ b/database/factories/PaymentEventFactory.php @@ -2,17 +2,19 @@ namespace Database\Factories; +use App\Models\EinundzwanzigPleb; +use App\Models\PaymentEvent; use Illuminate\Database\Eloquent\Factories\Factory; /** - * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\PaymentEvent> + * @extends Factory */ class PaymentEventFactory extends Factory { public function definition(): array { return [ - 'einundzwanzig_pleb_id' => \App\Models\EinundzwanzigPleb::factory(), + 'einundzwanzig_pleb_id' => EinundzwanzigPleb::factory(), 'year' => fake()->year(), 'event_id' => fake()->uuid(), 'amount' => 21000, diff --git a/database/factories/ProjectProposalFactory.php b/database/factories/ProjectProposalFactory.php index 3c38ee1..1fe95de 100644 --- a/database/factories/ProjectProposalFactory.php +++ b/database/factories/ProjectProposalFactory.php @@ -2,10 +2,12 @@ namespace Database\Factories; +use App\Models\EinundzwanzigPleb; +use App\Models\ProjectProposal; use Illuminate\Database\Eloquent\Factories\Factory; /** - * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\ProjectProposal> + * @extends Factory */ class ProjectProposalFactory extends Factory { @@ -17,7 +19,7 @@ class ProjectProposalFactory extends Factory public function definition(): array { return [ - 'einundzwanzig_pleb_id' => \App\Models\EinundzwanzigPleb::factory(), + 'einundzwanzig_pleb_id' => EinundzwanzigPleb::factory(), 'name' => $this->faker->sentence(3), 'description' => $this->faker->paragraph(), 'support_in_sats' => $this->faker->numberBetween(10000, 1000000), diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index 584104c..c4ceb07 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -2,12 +2,13 @@ namespace Database\Factories; +use App\Models\User; use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Str; /** - * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User> + * @extends Factory */ class UserFactory extends Factory { diff --git a/resources/views/livewire/association/project-support/form/edit.blade.php b/resources/views/livewire/association/project-support/form/edit.blade.php index 71abe6a..d8af6fc 100644 --- a/resources/views/livewire/association/project-support/form/edit.blade.php +++ b/resources/views/livewire/association/project-support/form/edit.blade.php @@ -107,10 +107,15 @@ class extends Component 'description' => $this->form['description'], 'support_in_sats' => (int) $this->form['support_in_sats'], 'website' => $this->form['website'], - 'accepted' => $canAccept ? (bool) $this->form['accepted'] : $this->project->accepted, - 'sats_paid' => $canAccept ? $this->form['sats_paid'] : $this->project->sats_paid, ]); + // Update admin-only fields directly if user has permission + if ($canAccept) { + $this->project->accepted = (bool) $this->form['accepted']; + $this->project->sats_paid = $this->form['sats_paid']; + $this->project->save(); + } + if ($this->file) { $this->project->addMedia($this->file)->toMediaCollection('main'); } diff --git a/routes/web.php b/routes/web.php index 7850a11..49d784e 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,5 +1,6 @@ middleware('signed'); Route::post('logout', function () { - \App\Support\NostrAuth::logout(); + NostrAuth::logout(); Session::flush(); return redirect('/'); diff --git a/tests/Feature/Livewire/ProjectSupportEditTest.php b/tests/Feature/Livewire/ProjectSupportEditTest.php index 7b0f59d..7242223 100644 --- a/tests/Feature/Livewire/ProjectSupportEditTest.php +++ b/tests/Feature/Livewire/ProjectSupportEditTest.php @@ -22,15 +22,15 @@ beforeEach(function () { 'event_id' => 'test_event_'.Str::random(40), ]); - $this->project = ProjectProposal::query()->create([ - 'einundzwanzig_pleb_id' => $this->pleb->id, - 'name' => 'Original Project', - 'description' => 'Original Description', - 'support_in_sats' => 21000, - 'website' => 'https://original.example.com', - 'accepted' => false, - 'sats_paid' => 0, - ]); + $this->project = new ProjectProposal; + $this->project->einundzwanzig_pleb_id = $this->pleb->id; + $this->project->name = 'Original Project'; + $this->project->description = 'Original Description'; + $this->project->support_in_sats = 21000; + $this->project->website = 'https://original.example.com'; + $this->project->accepted = false; + $this->project->sats_paid = 0; + $this->project->save(); // Get board member pubkeys from config $this->boardMember = EinundzwanzigPleb::query()->create([ diff --git a/tests/Feature/MediaSignedRouteTest.php b/tests/Feature/MediaSignedRouteTest.php index de6be98..db9db3d 100644 --- a/tests/Feature/MediaSignedRouteTest.php +++ b/tests/Feature/MediaSignedRouteTest.php @@ -1,6 +1,7 @@ create(); $project->addMedia( - \Illuminate\Http\UploadedFile::fake()->image('test.jpg', 100, 100) + UploadedFile::fake()->image('test.jpg', 100, 100) )->toMediaCollection('main'); $media = $project->getFirstMedia('main'); @@ -25,7 +26,7 @@ it('serves conversion media via signed route when conversion parameter is provid $project = ProjectProposal::factory()->create(); $project->addMedia( - \Illuminate\Http\UploadedFile::fake()->image('test.jpg', 500, 500) + UploadedFile::fake()->image('test.jpg', 500, 500) )->toMediaCollection('main'); $media = $project->getFirstMedia('main'); @@ -44,7 +45,7 @@ it('falls back to original when conversion does not exist', function () { $project = ProjectProposal::factory()->create(); $project->addMedia( - \Illuminate\Http\UploadedFile::fake()->image('test.jpg', 100, 100) + UploadedFile::fake()->image('test.jpg', 100, 100) )->toMediaCollection('main'); $media = $project->getFirstMedia('main'); @@ -63,7 +64,7 @@ it('rejects unsigned media requests', function () { $project = ProjectProposal::factory()->create(); $project->addMedia( - \Illuminate\Http\UploadedFile::fake()->image('test.jpg', 100, 100) + UploadedFile::fake()->image('test.jpg', 100, 100) )->toMediaCollection('main'); $media = $project->getFirstMedia('main'); @@ -77,7 +78,7 @@ it('generates signed url with conversion parameter', function () { $project = ProjectProposal::factory()->create(); $project->addMedia( - \Illuminate\Http\UploadedFile::fake()->image('test.jpg', 500, 500) + UploadedFile::fake()->image('test.jpg', 500, 500) )->toMediaCollection('main'); $urlWithoutConversion = $project->getSignedMediaUrl('main'); diff --git a/tests/Feature/Policies/ElectionPolicyTest.php b/tests/Feature/Policies/ElectionPolicyTest.php index c38ac2c..46bec9d 100644 --- a/tests/Feature/Policies/ElectionPolicyTest.php +++ b/tests/Feature/Policies/ElectionPolicyTest.php @@ -1,6 +1,7 @@ create([ - 'association_status' => \App\Enums\AssociationStatus::HONORARY, + 'association_status' => AssociationStatus::HONORARY, ]); $election = Election::factory()->create(); $nostrUser = new NostrUser($pleb->pubkey); @@ -87,7 +88,7 @@ it('allows honorary member to vote in an election', function () { it('denies passive member from voting in an election', function () { $pleb = EinundzwanzigPleb::factory()->create([ - 'association_status' => \App\Enums\AssociationStatus::PASSIVE, + 'association_status' => AssociationStatus::PASSIVE, ]); $election = Election::factory()->create(); $nostrUser = new NostrUser($pleb->pubkey); diff --git a/tests/Feature/Policies/ProjectProposalPolicyTest.php b/tests/Feature/Policies/ProjectProposalPolicyTest.php index 1a786ab..2f01094 100644 --- a/tests/Feature/Policies/ProjectProposalPolicyTest.php +++ b/tests/Feature/Policies/ProjectProposalPolicyTest.php @@ -1,6 +1,7 @@ create([ - 'association_status' => \App\Enums\AssociationStatus::PASSIVE, + 'association_status' => AssociationStatus::PASSIVE, ]); $nostrUser = new NostrUser($pleb->pubkey); @@ -57,7 +58,7 @@ it('denies creation for passive member without paid membership', function () { it('allows passive member with paid membership to create project proposals', function () { $pleb = EinundzwanzigPleb::factory()->withPaidCurrentYear()->create([ - 'association_status' => \App\Enums\AssociationStatus::PASSIVE, + 'association_status' => AssociationStatus::PASSIVE, ]); $nostrUser = new NostrUser($pleb->pubkey); diff --git a/tests/Feature/RateLimitingTest.php b/tests/Feature/RateLimitingTest.php index 1106ec3..cc8688d 100644 --- a/tests/Feature/RateLimitingTest.php +++ b/tests/Feature/RateLimitingTest.php @@ -2,6 +2,7 @@ use App\Models\EinundzwanzigPleb; use App\Models\ProjectProposal; +use App\Models\Vote; use App\Support\NostrAuth; use Illuminate\Support\Facades\RateLimiter; use Livewire\Livewire; @@ -46,7 +47,7 @@ test('voting actions are rate limited after 10 attempts', function () { RateLimiter::attempt('voting:127.0.0.1', 10, function () {}); } - Livewire::test('association.project-support.show', ['projectProposal' => $project->slug]) + Livewire::test('association.project-support.show', ['projectProposal' => $project]) ->call('handleApprove') ->assertStatus(429); }); @@ -93,7 +94,7 @@ test('project proposal update is rate limited after 5 attempts', function () { RateLimiter::attempt('project-proposal-update:127.0.0.1', 5, function () {}); } - Livewire::test('association.project-support.form.edit', ['projectProposal' => $project->slug]) + Livewire::test('association.project-support.form.edit', ['projectProposal' => $project]) ->set('form.name', 'Updated Name') ->call('update') ->assertStatus(429); @@ -105,11 +106,11 @@ test('voting works within rate limit', function () { NostrAuth::login($pleb->pubkey); - Livewire::test('association.project-support.show', ['projectProposal' => $project->slug]) + Livewire::test('association.project-support.show', ['projectProposal' => $project]) ->call('handleApprove') ->assertHasNoErrors(); - $vote = \App\Models\Vote::query() + $vote = Vote::query() ->where('project_proposal_id', $project->id) ->where('einundzwanzig_pleb_id', $pleb->id) ->first(); diff --git a/tests/Pest.php b/tests/Pest.php index 3d4d875..126ca8b 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -1,5 +1,8 @@ in('Feature'); /*