From 1244a5ce9d8bc911e13e3e299325333123110e49 Mon Sep 17 00:00:00 2001 From: Ned Zimmerman Date: Fri, 8 Nov 2024 11:06:48 -0400 Subject: [PATCH] feat: remove models and such --- .vscode/extensions.json | 9 - composer.json | 7 - config/hearth.php | 15 - database/factories/InvitationFactory.php | 32 - database/factories/OrganizationFactory.php | 35 - .../factories/ResourceCollectionFactory.php | 33 - database/factories/ResourceFactory.php | 33 - database/factories/UserFactory.php | 39 -- ...00_add_joinable_columns_to_users_table.php | 32 - ..._03_01_000000_create_invitations_table.php | 35 - ..._03_01_000000_create_memberships_table.php | 36 - .../create_organizations_table.php.stub | 35 - ...create_resource_collections_table.php.stub | 37 - ...source_resource_collections_table.php.stub | 35 - .../create_resources_table.php.stub | 37 - .../migrations/create_users_table.php.stub | 36 - .../migrations/update_users_table.php.stub | 33 - phpstan.neon.dist | 4 - src/Commands/HearthCommand.php | 81 +-- src/HearthServiceProvider.php | 8 - src/Models/Invitation.php | 58 -- src/Models/Membership.php | 39 -- src/Traits/HasInvitations.php | 17 - src/Traits/HasMembers.php | 52 -- src/Traits/HasRequestsToJoin.php | 17 - src/helpers.php | 112 --- stubs/app/Actions/Fortify/CreateNewUser.php | 49 -- .../Fortify/PasswordValidationRules.php | 18 - .../RedirectIfTwoFactorAuthenticatable.php | 27 - .../app/Actions/Fortify/ResetUserPassword.php | 29 - .../Actions/Fortify/UpdateUserPassword.php | 37 - .../Fortify/UpdateUserProfileInformation.php | 66 -- .../Http/Controllers/InvitationController.php | 74 -- stubs/app/Http/Controllers/JoinController.php | 73 -- .../Http/Controllers/MembershipController.php | 95 --- .../Controllers/OrganizationController.php | 110 --- .../ResourceCollectionController.php | 106 --- .../Http/Controllers/ResourceController.php | 96 --- stubs/app/Http/Controllers/UserController.php | 54 -- .../UserProfileInformationController.php | 26 - .../Controllers/VerifyEmailController.php | 30 - stubs/app/Http/Livewire/ResourceSelect.php | 57 -- stubs/app/Http/Middleware/Authenticate.php | 23 - .../Middleware/RedirectIfAuthenticated.php | 29 - .../Middleware/RedirectToPreferredLocale.php | 29 - stubs/app/Http/Middleware/RequirePassword.php | 35 - .../Http/Requests/AcceptInvitationRequest.php | 88 --- stubs/app/Http/Requests/Auth/LoginRequest.php | 93 --- .../Http/Requests/CreateInvitationRequest.php | 60 -- .../Requests/CreateOrganizationRequest.php | 56 -- .../CreateResourceCollectionRequest.php | 52 -- .../Http/Requests/CreateResourceRequest.php | 52 -- .../Requests/DestroyOrganizationRequest.php | 51 -- .../DestroyResourceCollectionRequest.php | 51 -- .../Http/Requests/DestroyResourceRequest.php | 51 -- .../app/Http/Requests/DestroyUserRequest.php | 56 -- .../Http/Requests/UpdateMembershipRequest.php | 52 -- .../Requests/UpdateOrganizationRequest.php | 43 -- .../UpdateResourceCollectionRequest.php | 52 -- .../Http/Requests/UpdateResourceRequest.php | 51 -- .../FailedTwoFactorLoginResponse.php | 28 - stubs/app/Http/Responses/LoginResponse.php | 26 - .../Http/Responses/PasswordResetResponse.php | 23 - stubs/app/Http/Responses/RegisterResponse.php | 26 - .../Http/Responses/TwoFactorLoginResponse.php | 26 - stubs/app/Mail/Invitation.php | 48 -- stubs/app/Models/Organization.php | 67 -- stubs/app/Models/Resource.php | 55 -- stubs/app/Models/ResourceCollection.php | 64 -- stubs/app/Models/User.php | 155 ----- stubs/app/Policies/OrganizationPolicy.php | 53 -- .../app/Policies/ResourceCollectionPolicy.php | 41 -- stubs/app/Policies/ResourcePolicy.php | 41 -- stubs/app/Policies/UserPolicy.php | 32 - .../app/Providers/FortifyServiceProvider.php | 108 --- stubs/app/Rules/NotLastAdmin.php | 41 -- stubs/app/Rules/Password.php | 76 --- stubs/app/View/Components/AppLayout.php | 18 - stubs/app/View/Components/GuestLayout.php | 18 - stubs/config/fortify.php | 130 ---- stubs/config/laravel-multilingual-routes.php | 50 -- stubs/config/livewire.php | 5 - stubs/config/locales.php | 17 - stubs/routes/fortify.php | 144 ---- stubs/routes/organizations.php | 65 -- stubs/routes/resource-collections.php | 33 - stubs/routes/resources.php | 34 - stubs/routes/web.php | 64 -- stubs/tests/Feature/AccountDeletionTest.php | 50 -- stubs/tests/Feature/AuthenticationTest.php | 52 -- stubs/tests/Feature/EmailVerificationTest.php | 55 -- stubs/tests/Feature/JoinTest.php | 119 ---- stubs/tests/Feature/LocalizationTest.php | 29 - stubs/tests/Feature/OrganizationTest.php | 638 ------------------ stubs/tests/Feature/PasswordChangeTest.php | 42 -- .../Feature/PasswordConfirmationTest.php | 35 - stubs/tests/Feature/PasswordResetTest.php | 60 -- stubs/tests/Feature/RegistrationTest.php | 24 - .../tests/Feature/ResourceCollectionTest.php | 356 ---------- stubs/tests/Feature/ResourceSelectTest.php | 103 --- stubs/tests/Feature/ResourceTest.php | 186 ----- .../Feature/TwoFactorAuthenticationTest.php | 152 ----- tests/Feature/InvitationTest.php | 54 -- tests/Feature/JoinTest.php | 23 - tests/Feature/MembershipTest.php | 32 - tests/Feature/TranslatableSlugTest.php | 34 - tests/Feature/UserTest.php | 14 - tests/TestCase.php | 23 - tests/Unit/HelpersTest.php | 29 - 109 files changed, 5 insertions(+), 6371 deletions(-) delete mode 100644 .vscode/extensions.json delete mode 100644 config/hearth.php delete mode 100644 database/factories/InvitationFactory.php delete mode 100644 database/factories/OrganizationFactory.php delete mode 100644 database/factories/ResourceCollectionFactory.php delete mode 100644 database/factories/ResourceFactory.php delete mode 100644 database/factories/UserFactory.php delete mode 100644 database/migrations/2021_03_01_000000_add_joinable_columns_to_users_table.php delete mode 100644 database/migrations/2021_03_01_000000_create_invitations_table.php delete mode 100644 database/migrations/2021_03_01_000000_create_memberships_table.php delete mode 100644 database/migrations/create_organizations_table.php.stub delete mode 100644 database/migrations/create_resource_collections_table.php.stub delete mode 100644 database/migrations/create_resource_resource_collections_table.php.stub delete mode 100644 database/migrations/create_resources_table.php.stub delete mode 100644 database/migrations/create_users_table.php.stub delete mode 100644 database/migrations/update_users_table.php.stub delete mode 100644 src/Models/Invitation.php delete mode 100644 src/Models/Membership.php delete mode 100644 src/Traits/HasInvitations.php delete mode 100644 src/Traits/HasMembers.php delete mode 100644 src/Traits/HasRequestsToJoin.php delete mode 100644 stubs/app/Actions/Fortify/CreateNewUser.php delete mode 100644 stubs/app/Actions/Fortify/PasswordValidationRules.php delete mode 100644 stubs/app/Actions/Fortify/RedirectIfTwoFactorAuthenticatable.php delete mode 100644 stubs/app/Actions/Fortify/ResetUserPassword.php delete mode 100644 stubs/app/Actions/Fortify/UpdateUserPassword.php delete mode 100644 stubs/app/Actions/Fortify/UpdateUserProfileInformation.php delete mode 100644 stubs/app/Http/Controllers/InvitationController.php delete mode 100644 stubs/app/Http/Controllers/JoinController.php delete mode 100644 stubs/app/Http/Controllers/MembershipController.php delete mode 100644 stubs/app/Http/Controllers/OrganizationController.php delete mode 100644 stubs/app/Http/Controllers/ResourceCollectionController.php delete mode 100644 stubs/app/Http/Controllers/ResourceController.php delete mode 100644 stubs/app/Http/Controllers/UserController.php delete mode 100644 stubs/app/Http/Controllers/UserProfileInformationController.php delete mode 100644 stubs/app/Http/Controllers/VerifyEmailController.php delete mode 100644 stubs/app/Http/Livewire/ResourceSelect.php delete mode 100644 stubs/app/Http/Middleware/Authenticate.php delete mode 100644 stubs/app/Http/Middleware/RedirectIfAuthenticated.php delete mode 100644 stubs/app/Http/Middleware/RedirectToPreferredLocale.php delete mode 100644 stubs/app/Http/Middleware/RequirePassword.php delete mode 100644 stubs/app/Http/Requests/AcceptInvitationRequest.php delete mode 100644 stubs/app/Http/Requests/Auth/LoginRequest.php delete mode 100644 stubs/app/Http/Requests/CreateInvitationRequest.php delete mode 100644 stubs/app/Http/Requests/CreateOrganizationRequest.php delete mode 100644 stubs/app/Http/Requests/CreateResourceCollectionRequest.php delete mode 100644 stubs/app/Http/Requests/CreateResourceRequest.php delete mode 100644 stubs/app/Http/Requests/DestroyOrganizationRequest.php delete mode 100644 stubs/app/Http/Requests/DestroyResourceCollectionRequest.php delete mode 100644 stubs/app/Http/Requests/DestroyResourceRequest.php delete mode 100644 stubs/app/Http/Requests/DestroyUserRequest.php delete mode 100644 stubs/app/Http/Requests/UpdateMembershipRequest.php delete mode 100644 stubs/app/Http/Requests/UpdateOrganizationRequest.php delete mode 100644 stubs/app/Http/Requests/UpdateResourceCollectionRequest.php delete mode 100644 stubs/app/Http/Requests/UpdateResourceRequest.php delete mode 100644 stubs/app/Http/Responses/FailedTwoFactorLoginResponse.php delete mode 100644 stubs/app/Http/Responses/LoginResponse.php delete mode 100644 stubs/app/Http/Responses/PasswordResetResponse.php delete mode 100644 stubs/app/Http/Responses/RegisterResponse.php delete mode 100644 stubs/app/Http/Responses/TwoFactorLoginResponse.php delete mode 100644 stubs/app/Mail/Invitation.php delete mode 100644 stubs/app/Models/Organization.php delete mode 100644 stubs/app/Models/Resource.php delete mode 100644 stubs/app/Models/ResourceCollection.php delete mode 100644 stubs/app/Models/User.php delete mode 100644 stubs/app/Policies/OrganizationPolicy.php delete mode 100644 stubs/app/Policies/ResourceCollectionPolicy.php delete mode 100644 stubs/app/Policies/ResourcePolicy.php delete mode 100644 stubs/app/Policies/UserPolicy.php delete mode 100644 stubs/app/Providers/FortifyServiceProvider.php delete mode 100644 stubs/app/Rules/NotLastAdmin.php delete mode 100644 stubs/app/Rules/Password.php delete mode 100644 stubs/app/View/Components/AppLayout.php delete mode 100644 stubs/app/View/Components/GuestLayout.php delete mode 100644 stubs/config/fortify.php delete mode 100644 stubs/config/laravel-multilingual-routes.php delete mode 100644 stubs/config/livewire.php delete mode 100644 stubs/config/locales.php delete mode 100644 stubs/routes/fortify.php delete mode 100644 stubs/routes/organizations.php delete mode 100644 stubs/routes/resource-collections.php delete mode 100644 stubs/routes/resources.php delete mode 100644 stubs/routes/web.php delete mode 100644 stubs/tests/Feature/AccountDeletionTest.php delete mode 100644 stubs/tests/Feature/AuthenticationTest.php delete mode 100644 stubs/tests/Feature/EmailVerificationTest.php delete mode 100644 stubs/tests/Feature/JoinTest.php delete mode 100644 stubs/tests/Feature/LocalizationTest.php delete mode 100644 stubs/tests/Feature/OrganizationTest.php delete mode 100644 stubs/tests/Feature/PasswordChangeTest.php delete mode 100644 stubs/tests/Feature/PasswordConfirmationTest.php delete mode 100644 stubs/tests/Feature/PasswordResetTest.php delete mode 100644 stubs/tests/Feature/RegistrationTest.php delete mode 100644 stubs/tests/Feature/ResourceCollectionTest.php delete mode 100644 stubs/tests/Feature/ResourceSelectTest.php delete mode 100644 stubs/tests/Feature/ResourceTest.php delete mode 100644 stubs/tests/Feature/TwoFactorAuthenticationTest.php delete mode 100644 tests/Feature/InvitationTest.php delete mode 100644 tests/Feature/JoinTest.php delete mode 100644 tests/Feature/MembershipTest.php delete mode 100644 tests/Feature/TranslatableSlugTest.php delete mode 100644 tests/Feature/UserTest.php diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index 05f53f0a..00000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "recommendations": [ - "junstyle.php-cs-fixer", - "mehedidracula.php-namespace-resolver", - "amiralizadeh9480.laravel-extra-intellisense", - "shufo.vscode-blade-formatter", - "cjhowe7.laravel-blade" - ] -} diff --git a/composer.json b/composer.json index 968e08b9..34ad7ca9 100644 --- a/composer.json +++ b/composer.json @@ -19,15 +19,10 @@ "require": { "php": "^8.2|^8.3", "chinleung/laravel-locales": "^2.1", - "chinleung/laravel-multilingual-routes": "^4.1", "codezero/laravel-unique-translation": "^4.3", - "commerceguys/addressing": "^2.2", "commerceguys/intl": "^2.0", - "laravel/fortify": "^1.24", "laravel/framework": "^11.29", "livewire/livewire": "^3.0", - "shiftonelabs/laravel-cascade-deletes": "^2.0", - "spatie/laravel-flash": "^1.10", "spatie/laravel-google-fonts": "^1.4", "spatie/laravel-package-tools": "^1.16", "spatie/laravel-sluggable": "^3.6", @@ -73,8 +68,6 @@ }, "autoload-dev": { "psr-4": { - "App\\Models\\": "stubs/app/Models", - "Database\\Factories\\": "database/factories", "Hearth\\Tests\\": "tests" } }, diff --git a/config/hearth.php b/config/hearth.php deleted file mode 100644 index b9079890..00000000 --- a/config/hearth.php +++ /dev/null @@ -1,15 +0,0 @@ - [ - 'enabled' => true, - 'roles' => [ - 'member', - 'admin', - ], - ], - 'resources' => [ - 'enabled' => true, - ], -]; diff --git a/database/factories/InvitationFactory.php b/database/factories/InvitationFactory.php deleted file mode 100644 index 2bb2d301..00000000 --- a/database/factories/InvitationFactory.php +++ /dev/null @@ -1,32 +0,0 @@ - $this->faker->unique()->safeEmail(), - 'role' => $roles[$this->faker->numberBetween(0, count($roles) - 1)], - 'invitationable_id' => Organization::factory(), - 'invitationable_type' => 'App\Models\Organization', - ]; - } -} diff --git a/database/factories/OrganizationFactory.php b/database/factories/OrganizationFactory.php deleted file mode 100644 index 5af74bc0..00000000 --- a/database/factories/OrganizationFactory.php +++ /dev/null @@ -1,35 +0,0 @@ -faker->company(); - - return [ - 'name' => $name, - 'slug' => Str::slug($name), - 'locality' => $this->faker->city(), - 'region' => $regions[$this->faker->numberBetween(0, 12)]['value'], - ]; - } -} diff --git a/database/factories/ResourceCollectionFactory.php b/database/factories/ResourceCollectionFactory.php deleted file mode 100644 index cb7cf18a..00000000 --- a/database/factories/ResourceCollectionFactory.php +++ /dev/null @@ -1,33 +0,0 @@ -faker->words(3, true); - - return [ - 'title' => $title, - 'slug' => Str::slug($title), - 'description' => $this->faker->sentence(), - 'user_id' => User::factory(), - ]; - } -} diff --git a/database/factories/ResourceFactory.php b/database/factories/ResourceFactory.php deleted file mode 100644 index 8206c621..00000000 --- a/database/factories/ResourceFactory.php +++ /dev/null @@ -1,33 +0,0 @@ -faker->words(3, true); - - return [ - 'title' => $title, - 'slug' => Str::slug($title), - 'summary' => $this->faker->sentence(), - 'user_id' => User::factory(), - ]; - } -} diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php deleted file mode 100644 index 260a385c..00000000 --- a/database/factories/UserFactory.php +++ /dev/null @@ -1,39 +0,0 @@ - $this->faker->name(), - 'slug' => function (array $attributes) { - return Str::slug($attributes['name']); - }, - 'email' => function (array $attributes) { - return Str::slug($attributes['name']).'@'.$this->faker->safeEmailDomain(); - }, - 'email_verified_at' => now(), - 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password - 'remember_token' => Str::random(10), - 'locale' => config('app.locale'), - ]; - } -} diff --git a/database/migrations/2021_03_01_000000_add_joinable_columns_to_users_table.php b/database/migrations/2021_03_01_000000_add_joinable_columns_to_users_table.php deleted file mode 100644 index 887e5155..00000000 --- a/database/migrations/2021_03_01_000000_add_joinable_columns_to_users_table.php +++ /dev/null @@ -1,32 +0,0 @@ -nullableMorphs('joinable'); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::table('users', function (Blueprint $table) { - $table->dropMorphs('joinable'); - }); - } -}; diff --git a/database/migrations/2021_03_01_000000_create_invitations_table.php b/database/migrations/2021_03_01_000000_create_invitations_table.php deleted file mode 100644 index 710b97a3..00000000 --- a/database/migrations/2021_03_01_000000_create_invitations_table.php +++ /dev/null @@ -1,35 +0,0 @@ -id(); - $table->morphs('invitationable'); - $table->string('email'); - $table->string('role'); - $table->timestamps(); - $table->unique(['invitationable_id', 'invitationable_type', 'email']); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::dropIfExists('invitations'); - } -}; diff --git a/database/migrations/2021_03_01_000000_create_memberships_table.php b/database/migrations/2021_03_01_000000_create_memberships_table.php deleted file mode 100644 index 22720bb1..00000000 --- a/database/migrations/2021_03_01_000000_create_memberships_table.php +++ /dev/null @@ -1,36 +0,0 @@ -id(); - $table->morphs('membershipable'); - $table->foreignId('user_id') - ->constrained() - ->onDelete('cascade'); - $table->string('role')->default('member'); - $table->timestamps(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::dropIfExists('memberships'); - } -}; diff --git a/database/migrations/create_organizations_table.php.stub b/database/migrations/create_organizations_table.php.stub deleted file mode 100644 index ee9eeb9b..00000000 --- a/database/migrations/create_organizations_table.php.stub +++ /dev/null @@ -1,35 +0,0 @@ -id(); - $table->json('name'); - $table->json('slug'); - $table->string('locality'); - $table->string('region'); - $table->timestamps(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::dropIfExists('organizations'); - } -}; diff --git a/database/migrations/create_resource_collections_table.php.stub b/database/migrations/create_resource_collections_table.php.stub deleted file mode 100644 index 10c16df1..00000000 --- a/database/migrations/create_resource_collections_table.php.stub +++ /dev/null @@ -1,37 +0,0 @@ -id(); - $table->foreignId('user_id') - ->constrained() - ->onDelete('cascade'); - $table->json('title'); - $table->json('slug'); - $table->json('description'); - $table->timestamps(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::dropIfExists('resource_collections'); - } -} diff --git a/database/migrations/create_resource_resource_collections_table.php.stub b/database/migrations/create_resource_resource_collections_table.php.stub deleted file mode 100644 index a25fde0c..00000000 --- a/database/migrations/create_resource_resource_collections_table.php.stub +++ /dev/null @@ -1,35 +0,0 @@ -foreignId('resource_id') - ->constrained() - ->onDelete('cascade'); - $table->foreignId('resource_collection_id') - ->constrained() - ->onDelete('cascade'); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::dropIfExists('resource_resource_collection'); - } -} diff --git a/database/migrations/create_resources_table.php.stub b/database/migrations/create_resources_table.php.stub deleted file mode 100644 index 07f08974..00000000 --- a/database/migrations/create_resources_table.php.stub +++ /dev/null @@ -1,37 +0,0 @@ -id(); - $table->foreignId('user_id') - ->constrained() - ->onDelete('cascade'); - $table->json('title'); - $table->json('slug'); - $table->json('summary'); - $table->timestamps(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::dropIfExists('resources'); - } -}; diff --git a/database/migrations/create_users_table.php.stub b/database/migrations/create_users_table.php.stub deleted file mode 100644 index cf6b7766..00000000 --- a/database/migrations/create_users_table.php.stub +++ /dev/null @@ -1,36 +0,0 @@ -id(); - $table->string('name'); - $table->string('email')->unique(); - $table->timestamp('email_verified_at')->nullable(); - $table->string('password'); - $table->rememberToken(); - $table->timestamps(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::dropIfExists('users'); - } -}; diff --git a/database/migrations/update_users_table.php.stub b/database/migrations/update_users_table.php.stub deleted file mode 100644 index cf0c263c..00000000 --- a/database/migrations/update_users_table.php.stub +++ /dev/null @@ -1,33 +0,0 @@ -string('slug'); - $table->string('locale')->default('en'); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::table('users', function (Blueprint $table) { - $table->dropColumn(['slug', 'locale']); - }); - } -}; diff --git a/phpstan.neon.dist b/phpstan.neon.dist index cb7217ab..af45db42 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -3,7 +3,6 @@ includes: parameters: paths: - - config - resources - src level: 5 # The level 9 is the highest level @@ -11,6 +10,3 @@ parameters: excludePaths: [] scanFiles: - vendor/chinleung/laravel-locales/src/helpers.php - scanDirectories: - - database/factories - - stubs/app/Models diff --git a/src/Commands/HearthCommand.php b/src/Commands/HearthCommand.php index 9249a9dd..47d46387 100644 --- a/src/Commands/HearthCommand.php +++ b/src/Commands/HearthCommand.php @@ -6,6 +6,7 @@ use Illuminate\Console\Command; use Illuminate\Filesystem\Filesystem; use Illuminate\Support\Facades\App; +use Illuminate\Support\ServiceProvider; use Illuminate\Support\Str; class HearthCommand extends Command @@ -26,18 +27,6 @@ public function __construct() public function handle() { if (! App::environment('testing')) { - // Publish vendor files... - $this->callSilent('vendor:publish', ['--tag' => 'hearth-config', '--force' => true]); - $this->callSilent('vendor:publish', ['--tag' => 'hearth-migrations', '--force' => true]); - $this->callSilent('vendor:publish', ['--provider' => 'Laravel\Fortify\FortifyServiceProvider']); - $this->callSilent('vendor:publish', [ - '--provider' => 'ChinLeung\LaravelLocales\LaravelLocalesServiceProvider', - '--tag' => 'config', - ]); - $this->callSilent('vendor:publish', [ - '--provider' => 'Spatie\GoogleFonts\GoogleFontsServiceProvider', - '--tag' => 'google-fonts-config', - ]); // Install NPM packages... $this->updateNodePackages(function ($packages) { @@ -63,12 +52,12 @@ public function handle() $this->replaceInFile( '// \Illuminate\Session\Middleware\AuthenticateSession::class,', "\Illuminate\Session\Middleware\AuthenticateSession::class,", - app_path('Http/Kernel.php') + app_path('bootstrap/app.php') ); // DetectRequestLocale Middleware... $this->installMiddlewareBefore( - '\App\Http\Middleware\EncryptCookies::class', + '\Illuminate\Cookie\Middleware\EncryptCookies::class', '\ChinLeung\MultilingualRoutes\DetectRequestLocale::class' ); @@ -89,9 +78,6 @@ public function handle() app_path('Http/Kernel.php') ); - // FortifyServiceProvider... - $this->installServiceProviderAfter('RouteServiceProvider', 'FortifyServiceProvider'); - // Ensure folders are in place... $this->filesystem->ensureDirectoryExists(app_path('Actions/Fortify')); $this->filesystem->ensureDirectoryExists(app_path('Http/Requests')); @@ -104,30 +90,6 @@ public function handle() $this->filesystem->ensureDirectoryExists(app_path('View/Components')); $this->filesystem->ensureDirectoryExists(lang_path('fr')); - // App stubs... - $app_stubs = array_merge( - $this->filesystem->glob(__DIR__.'/../../stubs/app/**/*.php'), - $this->filesystem->glob(__DIR__.'/../../stubs/app/**/**/*.php') - ); - - foreach ($app_stubs as $stub) { - copy($stub, str_replace(__DIR__.'/../../stubs/app', app_path(), $stub)); - } - - // Config stubs... - $config_stubs = $this->filesystem->glob(__DIR__.'/../../stubs/config/*.php'); - - foreach ($config_stubs as $stub) { - copy($stub, str_replace(__DIR__.'/../../stubs/config', config_path(), $stub)); - } - - // Database factories... - $factories = $this->filesystem->glob(__DIR__.'/../../database/factories/*.php'); - - foreach ($factories as $stub) { - copy($stub, str_replace(__DIR__.'/../../database/factories', base_path('database/factories'), $stub)); - } - // Language stubs... $lang_stubs = $this->filesystem->glob(__DIR__.'/../../stubs/lang/**/*.php'); @@ -141,23 +103,6 @@ public function handle() $this->filesystem->copyDirectory(__DIR__.'/../../stubs/resources/js/', resource_path('js')); $this->filesystem->copyDirectory(__DIR__.'/../../stubs/resources/views/', resource_path('views')); - // Route stubs... - $route_stubs = $this->filesystem->glob(__DIR__.'/../../stubs/routes/*.php'); - - foreach ($route_stubs as $stub) { - copy($stub, str_replace(__DIR__.'/../../stubs/routes', base_path('routes/'), $stub)); - } - - // Test stubs... - $this->filesystem->delete(base_path('tests/Feature/ExampleTest.php')); - $this->filesystem->delete(base_path('tests/Unit/ExampleTest.php')); - - $test_stubs = $this->filesystem->glob(__DIR__.'/../../stubs/tests/**/*.php'); - - foreach ($test_stubs as $stub) { - copy($stub, str_replace(__DIR__.'/../../stubs/tests', base_path('tests'), $stub)); - } - // Vite configuration... copy(__DIR__.'/../../stubs/vite.config.js', base_path('vite.config.js')); @@ -235,22 +180,6 @@ protected function maybeAddLocale(string $after = 'fr') } } - /** - * Install the service provider in the application configuration file. - * - * @return void - */ - protected function installServiceProviderAfter(string $after, string $name) - { - if (! Str::contains($appConfig = file_get_contents(config_path('app.php')), 'App\\Providers\\'.$name.'::class')) { - file_put_contents(config_path('app.php'), str_replace( - 'App\\Providers\\'.$after.'::class,', - 'App\\Providers\\'.$after.'::class,'.PHP_EOL.' App\\Providers\\'.$name.'::class,', - $appConfig - )); - } - } - /** * Install the middleware to a group in the application Http Kernel. * @@ -258,7 +187,7 @@ protected function installServiceProviderAfter(string $after, string $name) */ protected function installMiddlewareBefore(string $before, string $name, string $group = 'web') { - $httpKernel = file_get_contents(app_path('Http/Kernel.php')); + $httpKernel = file_get_contents(app_path('bootstrap/app.php')); $middlewareGroups = Str::before(Str::after($httpKernel, '$middlewareGroups = ['), '];'); $middlewareGroup = Str::before(Str::after($middlewareGroups, "'$group' => ["), '],'); @@ -270,7 +199,7 @@ protected function installMiddlewareBefore(string $before, string $name, string $middlewareGroup, ); - file_put_contents(app_path('Http/Kernel.php'), str_replace( + file_put_contents(app_path('bootstrap/app.php'), str_replace( $middlewareGroups, str_replace($middlewareGroup, $modifiedMiddlewareGroup, $middlewareGroups), $httpKernel diff --git a/src/HearthServiceProvider.php b/src/HearthServiceProvider.php index ceb8fb13..cb5b1abe 100644 --- a/src/HearthServiceProvider.php +++ b/src/HearthServiceProvider.php @@ -34,7 +34,6 @@ public function configurePackage(Package $package): void { $package ->name('hearth') - ->hasConfigFile() ->hasViews() ->hasViewComponent('hearth', Alert::class) ->hasViewComponent('hearth', Checkbox::class) @@ -54,13 +53,6 @@ public function configurePackage(Package $package): void ->hasViewComponent('hearth', TranslatableInput::class) ->hasViewComponent('hearth', TranslatableTextarea::class) ->hasTranslations() - ->hasMigrations([ - 'update_users_table', - 'create_organizations_table', - 'create_resources_table', - 'create_resource_collections_table', - 'create_resource_resource_collections_table', - ]) ->hasCommand(HearthCommand::class); } diff --git a/src/Models/Invitation.php b/src/Models/Invitation.php deleted file mode 100644 index 5e9ab269..00000000 --- a/src/Models/Invitation.php +++ /dev/null @@ -1,58 +0,0 @@ -morphTo(); - } - - /** - * Accept an invitation. - */ - public function accept(): void - { - $invitee = User::where('email', $this->email)->first(); - - $this->invitationable->users()->attach( - $invitee, - ['role' => $this->role] - ); - - $this->delete(); - } -} diff --git a/src/Models/Membership.php b/src/Models/Membership.php deleted file mode 100644 index ce182398..00000000 --- a/src/Models/Membership.php +++ /dev/null @@ -1,39 +0,0 @@ -belongsTo(User::class); - } - - /** - * Retrieve the parent model of the membership. - */ - public function membershipable(): mixed - { - return $this->membershipable_type::where('id', $this->membershipable_id)->first(); - } -} diff --git a/src/Traits/HasInvitations.php b/src/Traits/HasInvitations.php deleted file mode 100644 index 161c8ad9..00000000 --- a/src/Traits/HasInvitations.php +++ /dev/null @@ -1,17 +0,0 @@ -morphMany(Invitation::class, 'invitationable'); - } -} diff --git a/src/Traits/HasMembers.php b/src/Traits/HasMembers.php deleted file mode 100644 index 2890c32a..00000000 --- a/src/Traits/HasMembers.php +++ /dev/null @@ -1,52 +0,0 @@ -morphToMany(User::class, 'membershipable', 'memberships') - ->as('membership') - ->withPivot(['role', 'id']) - ->withTimestamps(); - } - - /** - * Get all the administrators of the model. - */ - public function administrators(): MorphToMany - { - return $this->morphToMany(User::class, 'membershipable', 'memberships') - ->as('membership') - ->wherePivot('role', 'admin') - ->withPivot('id') - ->withTimestamps(); - } - - /** - * Determine if the given email address belongs to a member of the model. - */ - public function hasUserWithEmail(string $email): bool - { - return $this->users->contains(function ($user) use ($email) { - return $user->email === $email; - }); - } - - /** - * Determine if the given email address belongs to an administrator of the model. - */ - public function hasAdministratorWithEmail(string $email): bool - { - return $this->administrators->contains(function ($user) use ($email) { - return $user->email === $email; - }); - } -} diff --git a/src/Traits/HasRequestsToJoin.php b/src/Traits/HasRequestsToJoin.php deleted file mode 100644 index 89424795..00000000 --- a/src/Traits/HasRequestsToJoin.php +++ /dev/null @@ -1,17 +0,0 @@ -morphMany(User::class, 'joinable'); - } -} diff --git a/src/helpers.php b/src/helpers.php index 8c0a5810..952943c0 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -1,79 +1,8 @@ get($code, $countries); - - if ($subdivision) { - return ($locale === $subdivision->getLocale()) ? $subdivision->getLocalName() : $subdivision->getName(); - } - - return null; - } -} - -if (! function_exists('get_regions')) { - /** - * Retrieve an array of administrative subdivisions within a country or countries. - * - * @param array $countries An array of ISO 3166-1 alpha-2 country codes. - * @param string $locale An ISO 639-1 language code. - * @return array An array of administrative subdivision names keyed by administrative subdivision codes. - */ - function get_regions(array $countries = ['CA'], string $locale = 'en'): array - { - $subdivisionRepository = new SubdivisionRepository; - - $regions = []; - - foreach ($subdivisionRepository->getAll($countries) as $region) { - $regions[] = [ - 'value' => $region->getCode(), - 'label' => ($locale === $region->getLocale()) ? $region->getLocalName() : $region->getName(), - ]; - } - - return $regions; - } -} - -if (! function_exists('get_region_codes')) { - /** - * Retrieve an array of administrative subdivision codes within a country or countries. - * - * @param array $countries An array of ISO 3166-1 alpha-2 country codes. - * @return array An array of administrative subdivision codes. - */ - function get_region_codes(array $countries = ['CA']): array - { - $subdivisionRepository = new SubdivisionRepository; - - $regions = []; - - foreach ($subdivisionRepository->getAll($countries) as $region) { - $regions[] = $region->getCode(); - } - - return $regions; - } -} - if (! function_exists('get_locale_name')) { /** * Get the name of a locale from its code. @@ -95,44 +24,3 @@ function get_locale_name(string $code, string $locale = 'en', $capitalize = true } } } - -if (! function_exists('trans_current_route')) { - /** - * Retrieve the current route in another locale. - */ - function trans_current_route(?string $locale = null, ?string $fallback = null, bool $absolute = true): string - { - if (is_null($fallback)) { - $fallback = url(request()->server('REQUEST_URI')); - } - - $route = Route::getCurrentRoute(); - - if (! $route) { - return $fallback; - } - - $name = Str::replaceFirst( - locale().'.', - "{$locale}.", - $route->getName() - ); - - if (! $name || ! in_array($locale, locales()) || ! Route::has($name)) { - return $fallback; - } - - $current = locale(); - - locale($locale); - - $url = route($name, array_merge( - (array) $route->parameters, - (array) request()->getQueryString() - ), $absolute); - - locale($current); - - return $url; - } -} diff --git a/stubs/app/Actions/Fortify/CreateNewUser.php b/stubs/app/Actions/Fortify/CreateNewUser.php deleted file mode 100644 index 163864d7..00000000 --- a/stubs/app/Actions/Fortify/CreateNewUser.php +++ /dev/null @@ -1,49 +0,0 @@ - ['required', 'string', 'max:255'], - 'email' => [ - 'required', - 'string', - 'email', - 'max:255', - Rule::unique(User::class), - ], - 'password' => $this->passwordRules(), - 'locale' => ['required', Rule::in(config('locales.supported', ['en', 'fr']))], - ], - [ - - ] - )->validate(); - - Cookie::queue('locale', $input['locale']); - - return User::create([ - 'name' => $input['name'], - 'email' => $input['email'], - 'password' => Hash::make($input['password']), - 'locale' => $input['locale'], - ]); - } -} diff --git a/stubs/app/Actions/Fortify/PasswordValidationRules.php b/stubs/app/Actions/Fortify/PasswordValidationRules.php deleted file mode 100644 index 432fb312..00000000 --- a/stubs/app/Actions/Fortify/PasswordValidationRules.php +++ /dev/null @@ -1,18 +0,0 @@ -session()->put([ - 'login.id' => $user->getKey(), - 'login.remember' => $request->filled('remember'), - ]); - - return $request->wantsJson() - ? response()->json(['two_factor' => true]) - : redirect()->route($user->locale.'.two-factor.login'); - } -} diff --git a/stubs/app/Actions/Fortify/ResetUserPassword.php b/stubs/app/Actions/Fortify/ResetUserPassword.php deleted file mode 100644 index 86e38cc4..00000000 --- a/stubs/app/Actions/Fortify/ResetUserPassword.php +++ /dev/null @@ -1,29 +0,0 @@ - $this->passwordRules(), - ])->validate(); - - $user->forceFill([ - 'password' => Hash::make($input['password']), - ])->save(); - } -} diff --git a/stubs/app/Actions/Fortify/UpdateUserPassword.php b/stubs/app/Actions/Fortify/UpdateUserPassword.php deleted file mode 100644 index fc94ca64..00000000 --- a/stubs/app/Actions/Fortify/UpdateUserPassword.php +++ /dev/null @@ -1,37 +0,0 @@ - ['required', 'string'], - 'password' => $this->passwordRules(), - ])->after(function ($validator) use ($user, $input) { - if (! isset($input['current_password']) || ! Hash::check($input['current_password'], $user->password)) { - $validator->errors()->add( - 'current_password', - __('hearth::auth.wrong_password') - ); - } - })->validateWithBag('updatePassword'); - - $user->forceFill([ - 'password' => Hash::make($input['password']), - ])->save(); - } -} diff --git a/stubs/app/Actions/Fortify/UpdateUserProfileInformation.php b/stubs/app/Actions/Fortify/UpdateUserProfileInformation.php deleted file mode 100644 index 8cec7ef7..00000000 --- a/stubs/app/Actions/Fortify/UpdateUserProfileInformation.php +++ /dev/null @@ -1,66 +0,0 @@ - ['required', 'string', 'max:255'], - 'email' => [ - 'required', - 'string', - 'email', - 'max:255', - Rule::unique('users')->ignore($user->id), - ], - 'locale' => ['required', Rule::in(config('locales.supported', ['en', 'fr']))], - ])->validateWithBag('updateProfileInformation'); - - if ( - $input['email'] !== $user->email && - $user instanceof MustVerifyEmail - ) { - $this->updateVerifiedUser($user, $input); - } else { - $user->forceFill([ - 'name' => $input['name'], - 'email' => $input['email'], - 'locale' => $input['locale'], - ])->save(); - } - - Cookie::queue('locale', $input['locale']); - } - - /** - * Update the given verified user's profile information. - * - * @param mixed $user - * @return void - */ - protected function updateVerifiedUser($user, array $input) - { - $user->forceFill([ - 'name' => $input['name'], - 'email' => $input['email'], - 'email_verified_at' => null, - 'locale' => $input['locale'], - ])->save(); - - $user->sendEmailVerificationNotification(); - } -} diff --git a/stubs/app/Http/Controllers/InvitationController.php b/stubs/app/Http/Controllers/InvitationController.php deleted file mode 100644 index a429b4f2..00000000 --- a/stubs/app/Http/Controllers/InvitationController.php +++ /dev/null @@ -1,74 +0,0 @@ -validated(); - - $invitationable = $request->input('invitationable_type')::where('id', $request->input('invitationable_id'))->first(); - - $invitation = $invitationable->invitations()->create($validated); - - Mail::to($validated['email'])->send(new InvitationMessage($invitation)); - - flash(__('invitation.create_invitation_succeeded'), 'success'); - - return redirect(\localized_route($invitationable->getRoutePrefix().'.edit', $invitationable)); - } - - /** - * Accept the specified invitation. - * - * @return RedirectResponse - */ - public function accept(AcceptInvitationRequest $request, Invitation $invitation) - { - $validated = $request->validated(); - - $invitation->accept(); - - flash( - __('invitation.accept_invitation_succeeded', ['invitationable' => $invitation->invitationable->name]), - 'success' - ); - - return redirect(\localized_route($invitation->invitationable->getRoutePrefix().'.show', $invitation->invitationable)); - } - - /** - * Cancel the specified invitation. - * - * @return RedirectResponse - */ - public function destroy(Request $request, Invitation $invitation) - { - if (! Gate::forUser($request->user())->check('update', $invitation->invitationable)) { - throw new AuthorizationException; - } - - $invitation->delete(); - - flash(__('invitation.cancel_invitation_succeeded'), 'success'); - - return redirect(\localized_route($invitation->invitationable->getRoutePrefix().'.edit', $invitation->invitationable)); - } -} diff --git a/stubs/app/Http/Controllers/JoinController.php b/stubs/app/Http/Controllers/JoinController.php deleted file mode 100644 index 6d08db44..00000000 --- a/stubs/app/Http/Controllers/JoinController.php +++ /dev/null @@ -1,73 +0,0 @@ -user()->joinable; - - flash(__('You have cancelled your request to join :team.', ['team' => $joinable->getTranslation('name', 'en')]), 'success'); - - $request->user()->forceFill([ - 'joinable_type' => null, - 'joinable_id' => null, - ])->save(); - - return redirect(\localized_route($joinable->getRoutePrefix().'.show', $joinable)); - } - - /** - * Approve a request to join a team. - */ - public function approve(Request $request, User $user): RedirectResponse - { - /** @var Organization */ - $joinable = $user->joinable; - - Gate::forUser($request->user())->authorize('update', $joinable); - - $user->forceFill([ - 'joinable_type' => null, - 'joinable_id' => null, - ])->save(); - - $joinable->users()->attach($user); - - flash(__('You have approved :name’s request to join :team and they are now a member.', ['name' => $user->name, 'team' => $joinable->name]), 'success'); - - return redirect(\localized_route($joinable->getRoutePrefix().'.edit', $joinable)); - } - - /** - * Deny a request to join a team. - */ - public function deny(Request $request, User $user): RedirectResponse - { - /** @var Organization */ - $joinable = $user->joinable; - - Gate::forUser($request->user())->authorize('update', $joinable); - - $user->forceFill([ - 'joinable_type' => null, - 'joinable_id' => null, - ])->save(); - - flash(__('You have denied :name’s request to join :team.', ['name' => $user->name, 'team' => $joinable->name]), 'success'); - - return redirect(\localized_route($joinable->getRoutePrefix().'.edit', $joinable)); - } -} diff --git a/stubs/app/Http/Controllers/MembershipController.php b/stubs/app/Http/Controllers/MembershipController.php deleted file mode 100644 index 5eb4de20..00000000 --- a/stubs/app/Http/Controllers/MembershipController.php +++ /dev/null @@ -1,95 +0,0 @@ - $role, 'label' => __('roles.'.$role)]; - } - - return view('memberships.edit', [ - 'membership' => $membership, - 'user' => $membership->user, - 'membershipable' => $membership->membershipable(), - 'roles' => $roles, - ]); - } - - /** - * Update the given member's role. - */ - public function update(UpdateMembershipRequest $request, Membership $membership): RedirectResponse - { - $validated = $request->validated(); - - $membership->membershipable()->users()->updateExistingPivot($membership->user->id, [ - 'role' => $validated['role'], - ]); - - if ($request->user()->id === $membership->user->id && $request->input('role') !== 'admin') { - return redirect( - \localized_route($membership->membershipable()->getRoutePrefix().'.show', $membership->membershipable()) - ); - } - - return redirect( - \localized_route($membership->membershipable()->getRoutePrefix().'.edit', $membership->membershipable()) - ); - } - - /** - * Remove the given member from the organization. - */ - public function destroy(Request $request, Membership $membership): RedirectResponse - { - Gate::forUser($request->user())->authorize('update', $membership->membershipable()); - - $validator = Validator::make( - [ - 'membership' => $membership, - ], - [] - ); - - $validator->sometimes( - 'membership', - [new NotLastAdmin($membership)], - function ($input) { - return $input->membership->role === 'admin'; - } - ); - - $validator->validate(); - - $membership->membershipable()->users()->detach($membership->user->id); - - if ($request->user()->id === $membership->user->id) { - return redirect( - \localized_route($membership->membershipable()->getRoutePrefix().'.show', $membership->membershipable()) - ); - } - - return redirect( - \localized_route($membership->membershipable()->getRoutePrefix().'.edit', $membership->membershipable()) - ); - } -} diff --git a/stubs/app/Http/Controllers/OrganizationController.php b/stubs/app/Http/Controllers/OrganizationController.php deleted file mode 100644 index 73bb81f8..00000000 --- a/stubs/app/Http/Controllers/OrganizationController.php +++ /dev/null @@ -1,110 +0,0 @@ - Organization::orderBy('name')->get()]); - } - - /** - * Show the form for creating a new resource. - */ - public function create(): View - { - return view('organizations.create', [ - 'regions' => array_merge([['value' => '', 'label' => '']], get_regions(['CA'], \locale())), - ]); - } - - /** - * Store a newly created resource in storage. - */ - public function store(CreateOrganizationRequest $request): RedirectResponse - { - $organization = Organization::create($request->validated()); - - $organization->users()->attach( - $request->user(), - ['role' => 'admin'] - ); - - flash(__('organization.create_succeeded'), 'success'); - - return redirect(\localized_route('organizations.show', $organization)); - } - - /** - * Display the specified resource. - */ - public function show(Organization $organization): View - { - return view('organizations.show', ['organization' => $organization]); - } - - /** - * Show the form for editing the specified resource. - */ - public function edit(Organization $organization): View - { - $roles = []; - - foreach (config('hearth.organizations.roles') as $role) { - $roles[] = ['value' => $role, 'label' => __('roles.'.$role)]; - } - - return view('organizations.edit', [ - 'organization' => $organization, - 'regions' => array_merge([['value' => '', 'label' => '']], get_regions(['CA'], \locale())), - 'roles' => $roles, - ]); - } - - /** - * Update the specified resource in storage. - */ - public function update(UpdateOrganizationRequest $request, Organization $organization): RedirectResponse - { - $organization->fill($request->validated()); - $organization->save(); - - flash(__('organization.update_succeeded'), 'success'); - - return redirect(\localized_route('organizations.show', $organization)); - } - - public function join(Request $request, Organization $organization): RedirectResponse - { - $organization->requestsToJoin()->save($request->user()); - - flash(__('You have successfully requested to join :organization. You will be notified when an administrator has approved or denied your request.', ['organization' => $organization->getTranslation('name', locale())]), 'success'); - - return redirect(\localized_route('organizations.show', $organization)); - } - - /** - * Remove the specified resource from storage. - */ - public function destroy(DestroyOrganizationRequest $request, Organization $organization): RedirectResponse - { - $organization->delete(); - - flash(__('organization.destroy_succeeded'), 'success'); - - return redirect(\localized_route('dashboard')); - } -} diff --git a/stubs/app/Http/Controllers/ResourceCollectionController.php b/stubs/app/Http/Controllers/ResourceCollectionController.php deleted file mode 100644 index e6ad54e0..00000000 --- a/stubs/app/Http/Controllers/ResourceCollectionController.php +++ /dev/null @@ -1,106 +0,0 @@ - ResourceCollection::orderBy('title')->get()]); - } - - /** - * Show the form for creating a new resource collection. - * - * @return \Illuminate\View\View - */ - public function create() - { - $this->authorize('create', ResourceCollection::class); - - return view('resource-collections.create', [ - 'resourceCollectionId' => null, - ]); - } - - /** - * Store a newly created resource in storage. - * - * @return \Illuminate\Http\RedirectResponse - */ - public function store(CreateResourceCollectionRequest $request) - { - $data = $request->validated(); - - $resourceCollection = ResourceCollection::create($data); - - $resourceCollection->resources()->attach($data['resource_ids']); - - flash(__('resource-collection.create_succeeded'), 'success'); - - return redirect(\localized_route('resource-collections.show', ['resourceCollection' => $resourceCollection])); - } - - /** - * Display the specified resource collection. - * - * @return \Illuminate\View\View - */ - public function show(ResourceCollection $resourceCollection) - { - return view('resource-collections.show', ['resourceCollection' => $resourceCollection]); - } - - /** - * Show the form for editing the specified resource collection. - * - * @return \Illuminate\View\View - */ - public function edit(ResourceCollection $resourceCollection) - { - return view('resource-collections.edit', [ - 'resourceCollection' => $resourceCollection, - 'resourceCollectionId' => $resourceCollection->id, - ]); - } - - /** - * Update the specified resource in storage. - * - * @return \Illuminate\Http\RedirectResponse - */ - public function update(UpdateResourceCollectionRequest $request, ResourceCollection $resourceCollection) - { - $resourceCollection->fill($request->validated()); - $resourceCollection->resources()->sync($request['resource_ids']); - $resourceCollection->save(); - - flash(__('resource-collection.update_succeeded'), 'success'); - - return redirect(\localized_route('resource-collections.show', $resourceCollection)); - } - - /** - * Remove the specified resource from storage. - * - * @return \Illuminate\Http\RedirectResponse - */ - public function destroy(DestroyResourceCollectionRequest $request, ResourceCollection $resourceCollection) - { - $resourceCollection->delete(); - - flash(__('resource-collection.destroy_succeeded'), 'success'); - - return redirect(\localized_route('dashboard')); - } -} diff --git a/stubs/app/Http/Controllers/ResourceController.php b/stubs/app/Http/Controllers/ResourceController.php deleted file mode 100644 index 2110aea0..00000000 --- a/stubs/app/Http/Controllers/ResourceController.php +++ /dev/null @@ -1,96 +0,0 @@ - Resource::orderBy('title')->get()]); - } - - /** - * Show the form for creating a new resource. - * - * @return \Illuminate\View\View - */ - public function create() - { - $this->authorize('create', Resource::class); - - return view('resources.create'); - } - - /** - * Store a newly created resource in storage. - * - * @return \Illuminate\Http\RedirectResponse - */ - public function store(CreateResourceRequest $request) - { - $resource = Resource::create($request->validated()); - - flash(__('resource.create_succeeded'), 'success'); - - return redirect(\localized_route('resources.show', ['resource' => $resource])); - } - - /** - * Display the specified resource. - * - * @return \Illuminate\View\View - */ - public function show(Resource $resource) - { - return view('resources.show', ['resource' => $resource]); - } - - /** - * Show the form for editing the specified resource. - * - * @return \Illuminate\View\View - */ - public function edit(Resource $resource) - { - return view('resources.edit', ['resource' => $resource]); - } - - /** - * Update the specified resource in storage. - * - * @return \Illuminate\Http\RedirectResponse - */ - public function update(UpdateResourceRequest $request, Resource $resource) - { - $resource->fill($request->validated()); - $resource->save(); - - flash(__('resource.update_succeeded'), 'success'); - - return redirect(\localized_route('resources.show', $resource)); - } - - /** - * Remove the specified resource from storage. - * - * @return \Illuminate\Http\RedirectResponse - */ - public function destroy(DestroyResourceRequest $request, Resource $resource) - { - $resource->delete(); - - flash(__('resource.destroy_succeeded'), 'success'); - - return redirect(\localized_route('dashboard')); - } -} diff --git a/stubs/app/Http/Controllers/UserController.php b/stubs/app/Http/Controllers/UserController.php deleted file mode 100644 index a0f46be9..00000000 --- a/stubs/app/Http/Controllers/UserController.php +++ /dev/null @@ -1,54 +0,0 @@ - Auth::user(), - ]); - } - - /** - * Show the account admin view for the logged-in user. - * - * @return \Illuminate\View\View - */ - public function admin() - { - return view('users.admin', ['user' => Auth::user()]); - } - - /** - * Destroy a given user. - * - * @return \Illuminate\Http\RedirectResponse - */ - public function destroy(DestroyUserRequest $request) - { - $user = $request->user(); - - Auth::guard('web')->logout(); - - $request->session()->invalidate(); - - $request->session()->regenerateToken(); - - $user->delete(); - - flash(__('hearth::user.destroy_succeeded'), 'success'); - - return redirect(\localized_route('welcome')); - } -} diff --git a/stubs/app/Http/Controllers/UserProfileInformationController.php b/stubs/app/Http/Controllers/UserProfileInformationController.php deleted file mode 100644 index 25451c05..00000000 --- a/stubs/app/Http/Controllers/UserProfileInformationController.php +++ /dev/null @@ -1,26 +0,0 @@ -update($request->user(), $request->all()); - - return $request->wantsJson() - ? new JsonResponse('', 200) - : redirect(localized_route('users.edit', [], $request->input('locale') ?? 'en'))->with('status', 'profile-information-updated'); - } -} diff --git a/stubs/app/Http/Controllers/VerifyEmailController.php b/stubs/app/Http/Controllers/VerifyEmailController.php deleted file mode 100644 index 825d026e..00000000 --- a/stubs/app/Http/Controllers/VerifyEmailController.php +++ /dev/null @@ -1,30 +0,0 @@ - 1], $request->user()->locale); - - if ($request->user()->hasVerifiedEmail()) { - return redirect()->intended($dashboard); - } - - if ($request->user()->markEmailAsVerified()) { - event(new Verified($request->user())); - } - - flash(__('hearth::auth.verification_succeeded'), 'success'); - - return redirect()->intended($dashboard); - } -} diff --git a/stubs/app/Http/Livewire/ResourceSelect.php b/stubs/app/Http/Livewire/ResourceSelect.php deleted file mode 100644 index 33ededac..00000000 --- a/stubs/app/Http/Livewire/ResourceSelect.php +++ /dev/null @@ -1,57 +0,0 @@ -availableResources = new Collection; - $this->selectedResources = new Collection; - if ($resourceCollectionId != null) { - $resourcesInCollection = ResourceCollection::find($resourceCollectionId)->resources()->get(); - $this->availableResources = Resource::whereNotIn('id', $resourcesInCollection->pluck('id'))->get(); - $this->selectedResources = $resourcesInCollection; - } else { - $this->availableResources = Resource::orderBy('title')->get(); - } - } - - public function addResource(int $id): void - { - /** @var ?Resource $resourceToAdd */ - $resourceToAdd = $this->availableResources->find($id); - if ($resourceToAdd) { - $this->selectedResources->push($resourceToAdd); - $this->availableResources = $this->availableResources->except([$id]); - $this->message = __('Resource ":resource" added to collection.', ['resource' => $resourceToAdd->getTranslation('title', locale())]); - } - } - - public function removeResource(int $id): void - { - /** @var ?Resource $resourceToRemove */ - $resourceToRemove = $this->selectedResources->find($id); - if ($resourceToRemove) { - $this->availableResources->push($resourceToRemove); - $this->selectedResources = $this->selectedResources->except([$id]); - $this->message = __('Resource ":resource" removed from collection.', ['resource' => $resourceToRemove->getTranslation('title', locale())]); - } - } - - public function render() - { - return view('livewire.resource-select'); - } -} diff --git a/stubs/app/Http/Middleware/Authenticate.php b/stubs/app/Http/Middleware/Authenticate.php deleted file mode 100644 index 2aab1efe..00000000 --- a/stubs/app/Http/Middleware/Authenticate.php +++ /dev/null @@ -1,23 +0,0 @@ -expectsJson()) { - return \localized_route('login'); - } - - return null; - } -} diff --git a/stubs/app/Http/Middleware/RedirectIfAuthenticated.php b/stubs/app/Http/Middleware/RedirectIfAuthenticated.php deleted file mode 100644 index 1ba35bd2..00000000 --- a/stubs/app/Http/Middleware/RedirectIfAuthenticated.php +++ /dev/null @@ -1,29 +0,0 @@ -check()) { - return redirect(\localized_route('dashboard')); - } - } - - return $next($request); - } -} diff --git a/stubs/app/Http/Middleware/RedirectToPreferredLocale.php b/stubs/app/Http/Middleware/RedirectToPreferredLocale.php deleted file mode 100644 index 0857c17c..00000000 --- a/stubs/app/Http/Middleware/RedirectToPreferredLocale.php +++ /dev/null @@ -1,29 +0,0 @@ -cookie('locale'); - - if ( - $locale - && in_array($locale, \locales()) - && $locale !== $request->segment(1) - ) { - return redirect(\trans_current_route($locale)); - } - - return $next($request); - } -} diff --git a/stubs/app/Http/Middleware/RequirePassword.php b/stubs/app/Http/Middleware/RequirePassword.php deleted file mode 100644 index 367df8bf..00000000 --- a/stubs/app/Http/Middleware/RequirePassword.php +++ /dev/null @@ -1,35 +0,0 @@ -shouldConfirmPassword($request, $passwordTimeoutSeconds)) { - if ($request->expectsJson()) { - return $this->responseFactory->json([ - 'message' => 'Password confirmation required.', - ], 423); - } - - return $this->responseFactory->redirectGuest( - $this->urlGenerator->route($redirectToRoute ?? Auth::user()->locale.'.password.confirm') - ); - } - - return $next($request); - } -} diff --git a/stubs/app/Http/Requests/AcceptInvitationRequest.php b/stubs/app/Http/Requests/AcceptInvitationRequest.php deleted file mode 100644 index 29d0155f..00000000 --- a/stubs/app/Http/Requests/AcceptInvitationRequest.php +++ /dev/null @@ -1,88 +0,0 @@ - - */ - public function rules(): array - { - return []; - } - - /** - * Configure the validator instance. - * - * @return void - */ - public function withValidator(Validator $validator) - { - $validator - ->after($this->ensureInviteeHasNoExistingMemberships(Auth::user())) - ->after($this->ensureInviteeIsNotAlreadyAMember($this->invitation->invitationable, $this->invitation->email)) - ->after($this->ensureCurrentUserIsInvitee(Auth::user(), $this->invitation->email)); - } - - /** - * Ensure that the user is not already part of a team. - */ - protected function ensureInviteeHasNoExistingMemberships(User $user): \Closure - { - return function ($validator) use ($user) { - $validator->errors()->addIf( - Membership::where('user_id', $user->id)->first(), - 'email', - __('invitation.invited_user_already_belongs_to_a_team') - ); - }; - } - - /** - * Ensure that the user is not already part of this team. - */ - protected function ensureInviteeIsNotAlreadyAMember(mixed $invitationable, string $email): \Closure - { - return function ($validator) use ($invitationable, $email) { - $validator->errors()->addIf( - $invitationable->hasUserWithEmail($email), - 'email', - __('invitation.invited_user_already_belongs_to_this_team') - ); - }; - } - - /** - * Ensure that the authenticated user is the user who was invited. - */ - protected function ensureCurrentUserIsInvitee(User $user, string $email): \Closure - { - return function ($validator) use ($user, $email) { - if ($user->email !== $email) { - $validator->errors()->add( - 'email', - __('invitation.email_not_valid', ['email' => $user->email]) - ); - } - }; - } -} diff --git a/stubs/app/Http/Requests/Auth/LoginRequest.php b/stubs/app/Http/Requests/Auth/LoginRequest.php deleted file mode 100644 index b93db79f..00000000 --- a/stubs/app/Http/Requests/Auth/LoginRequest.php +++ /dev/null @@ -1,93 +0,0 @@ - 'required|string|email', - 'password' => 'required|string', - ]; - } - - /** - * Attempt to authenticate the request's credentials. - * - * @return void - * - * @throws \Illuminate\Validation\ValidationException - */ - public function authenticate() - { - $this->ensureIsNotRateLimited(); - - if (! Auth::attempt($this->only('email', 'password'), $this->filled('remember'))) { - RateLimiter::hit($this->throttleKey()); - - throw ValidationException::withMessages([ - 'email' => __('hearth::auth.failed'), - ]); - } - - RateLimiter::clear($this->throttleKey()); - } - - /** - * Ensure the login request is not rate limited. - * - * @return void - * - * @throws \Illuminate\Validation\ValidationException - */ - public function ensureIsNotRateLimited() - { - if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) { - return; - } - - event(new Lockout($this)); - - $seconds = RateLimiter::availableIn($this->throttleKey()); - - throw ValidationException::withMessages([ - 'email' => trans('hearth::auth.throttle', [ - 'seconds' => $seconds, - 'minutes' => ceil($seconds / 60), - ]), - ]); - } - - /** - * Get the rate limiting throttle key for the request. - * - * @return string - */ - public function throttleKey() - { - return Str::lower($this->input('email')).'|'.$this->ip(); - } -} diff --git a/stubs/app/Http/Requests/CreateInvitationRequest.php b/stubs/app/Http/Requests/CreateInvitationRequest.php deleted file mode 100644 index c54b28b4..00000000 --- a/stubs/app/Http/Requests/CreateInvitationRequest.php +++ /dev/null @@ -1,60 +0,0 @@ -input('invitationable_type')::where('id', $this->input('invitationable_id'))->first(); - - return $invitationable && $this->user()->can('update', $invitationable); - } - - /** - * Get the validation rules that apply to the request. - * - * @return array - */ - public function rules() - { - $invitationable_type = $this->input('invitationable_type'); - $invitationable_id = $this->input('invitationable_id'); - - return [ - 'email' => ['required', 'email', Rule::unique('invitations')->where(function ($query) use ($invitationable_type, $invitationable_id) { - $query - ->where('invitationable_type', $invitationable_type) - ->where('invitationable_id', $invitationable_id); - })], - 'role' => ['required', 'string', Rule::in(config('hearth.organizations.roles'))], - ]; - } - - /** - * Configure the validator instance. - * - * @param \Illuminate\Validation\Validator $validator - * @return void - */ - public function withValidator($validator) - { - $invitationable = $this->input('invitationable_type')::where('id', $this->input('invitationable_id'))->first(); - - $validator->after(function ($validator) use ($invitationable) { - $validator->errors()->addIf( - $invitationable->hasUserWithEmail($this->email), - 'email', - __('invitation.invited_user_already_belongs_to_team') - ); - })->validateWithBag('inviteMember'); - } -} diff --git a/stubs/app/Http/Requests/CreateOrganizationRequest.php b/stubs/app/Http/Requests/CreateOrganizationRequest.php deleted file mode 100644 index d75a02fb..00000000 --- a/stubs/app/Http/Requests/CreateOrganizationRequest.php +++ /dev/null @@ -1,56 +0,0 @@ - [ - 'required', - 'string', - 'max:255', - Rule::unique(Organization::class), - - ], - 'locality' => ['required', 'string', 'max:255'], - 'region' => [ - 'required', - Rule::in(get_region_codes()), - ], - ]; - } - - /** - * Get the error messages for the defined validation rules. - * - * @return array - */ - public function messages() - { - return [ - 'name.unique' => __('validation.organization.name_exists'), - ]; - } -} diff --git a/stubs/app/Http/Requests/CreateResourceCollectionRequest.php b/stubs/app/Http/Requests/CreateResourceCollectionRequest.php deleted file mode 100644 index 0b9fd817..00000000 --- a/stubs/app/Http/Requests/CreateResourceCollectionRequest.php +++ /dev/null @@ -1,52 +0,0 @@ - [ - 'required', - 'string', - 'max:255', - UniqueTranslationRule::for('resource_collections'), - ], - 'description' => 'required|string', - 'user_id' => 'required', - 'resource_ids' => 'array|nullable', - 'resource_ids.*' => 'exists:resources,id', - ]; - } - - /** - * Get the error messages for the defined validation rules. - * - * @return array - */ - public function messages() - { - return [ - 'title.unique' => __('validation.custom.resource_collection.title_exists'), - ]; - } -} diff --git a/stubs/app/Http/Requests/CreateResourceRequest.php b/stubs/app/Http/Requests/CreateResourceRequest.php deleted file mode 100644 index bc16e96d..00000000 --- a/stubs/app/Http/Requests/CreateResourceRequest.php +++ /dev/null @@ -1,52 +0,0 @@ -user()->id == $this->user_id; - } - - /** - * Get the validation rules that apply to the request. - * - * @return array - */ - public function rules() - { - return [ - 'title' => [ - 'required', - 'string', - 'max:255', - Rule::unique(Resource::class), - - ], - 'summary' => 'required|string', - 'user_id' => 'required', - ]; - } - - /** - * Get the error messages for the defined validation rules. - * - * @return array - */ - public function messages() - { - return [ - 'title.unique' => __('validation.custom.resource.title_exists'), - ]; - } -} diff --git a/stubs/app/Http/Requests/DestroyOrganizationRequest.php b/stubs/app/Http/Requests/DestroyOrganizationRequest.php deleted file mode 100644 index 83a2e825..00000000 --- a/stubs/app/Http/Requests/DestroyOrganizationRequest.php +++ /dev/null @@ -1,51 +0,0 @@ -route('organization'); - - return $organization && $this->user()->can('delete', $organization); - } - - /** - * Get the validation rules that apply to the request. - * - * @return array - */ - public function rules() - { - return [ - 'current_password' => 'required|string', - ]; - } - - /** - * Configure the validator instance. - * - * @param \Illuminate\Validation\Validator $validator - * @return void - */ - public function withValidator($validator) - { - $validator->after(function ($validator) { - if (! Hash::check($this->current_password, $this->user()->password)) { - $validator->errors()->add( - 'current_password', - __('validation.current_password') - ); - } - })->validateWithBag('destroyOrganization'); - } -} diff --git a/stubs/app/Http/Requests/DestroyResourceCollectionRequest.php b/stubs/app/Http/Requests/DestroyResourceCollectionRequest.php deleted file mode 100644 index cc30fe83..00000000 --- a/stubs/app/Http/Requests/DestroyResourceCollectionRequest.php +++ /dev/null @@ -1,51 +0,0 @@ -route('resourceCollection'); - - return $resourceCollection && $this->user()->can('delete', $resourceCollection); - } - - /** - * Get the validation rules that apply to the request. - * - * @return array - */ - public function rules() - { - return [ - 'current_password' => 'required|string', - ]; - } - - /** - * Configure the validator instance. - * - * @param \Illuminate\Validation\Validator $validator - * @return void - */ - public function withValidator($validator) - { - $validator->after(function ($validator) { - if (! Hash::check($this->current_password, $this->user()->password)) { - $validator->errors()->add( - 'current_password', - __('validation.current_password') - ); - } - })->validateWithBag('destroyResourceCollection'); - } -} diff --git a/stubs/app/Http/Requests/DestroyResourceRequest.php b/stubs/app/Http/Requests/DestroyResourceRequest.php deleted file mode 100644 index 48d084cd..00000000 --- a/stubs/app/Http/Requests/DestroyResourceRequest.php +++ /dev/null @@ -1,51 +0,0 @@ -route('resource'); - - return $resource && $this->user()->can('delete', $resource); - } - - /** - * Get the validation rules that apply to the request. - * - * @return array - */ - public function rules() - { - return [ - 'current_password' => 'required|string', - ]; - } - - /** - * Configure the validator instance. - * - * @param \Illuminate\Validation\Validator $validator - * @return void - */ - public function withValidator($validator) - { - $validator->after(function ($validator) { - if (! Hash::check($this->current_password, $this->user()->password)) { - $validator->errors()->add( - 'current_password', - __('validation.current_password') - ); - } - })->validateWithBag('destroyResource'); - } -} diff --git a/stubs/app/Http/Requests/DestroyUserRequest.php b/stubs/app/Http/Requests/DestroyUserRequest.php deleted file mode 100644 index f5a5ede6..00000000 --- a/stubs/app/Http/Requests/DestroyUserRequest.php +++ /dev/null @@ -1,56 +0,0 @@ - 'required|string', - ]; - } - - /** - * Configure the validator instance. - * - * @return void - */ - public function withValidator(Validator $validator) - { - $validator->after(function ($validator) { - if (! Hash::check($this->current_password, $this->user()->password)) { - $validator->errors()->add( - 'current_password', - __('hearth::auth.wrong_password') - ); - } - if (count($this->user()->organizations) > 0) { - if ($this->user->organization->administrators()->count() === 1 && $this->user()->isAdministratorOf($this->user->organization)) { - $validator->errors()->add( - 'organizations', - __( - 'organization.error_new_administrator_required_before_user_deletion', - ['organization' => ''.$this->user->organization->getTranslation('name', locale()).''], - ) - ); - } - } - })->validateWithBag('destroyAccount'); - } -} diff --git a/stubs/app/Http/Requests/UpdateMembershipRequest.php b/stubs/app/Http/Requests/UpdateMembershipRequest.php deleted file mode 100644 index be68af1d..00000000 --- a/stubs/app/Http/Requests/UpdateMembershipRequest.php +++ /dev/null @@ -1,52 +0,0 @@ -user()->can('update', $this->membership->membershipable()); - } - - /** - * Get the validation rules that apply to the request. - * - * @return array - */ - public function rules(): array - { - return [ - 'role' => [ - 'required', - 'string', - Rule::in(config('hearth.organizations.roles')), - ], - ]; - } - - /** - * Configure the validator instance. - * - * @return void - */ - public function withValidator(Validator $validator) - { - $validator - ->sometimes( - 'role', - [new NotLastAdmin($this->membership)], - function ($input) { - return $this->membership->role === 'admin' && $input->role !== 'admin'; - } - ); - } -} diff --git a/stubs/app/Http/Requests/UpdateOrganizationRequest.php b/stubs/app/Http/Requests/UpdateOrganizationRequest.php deleted file mode 100644 index 2323262b..00000000 --- a/stubs/app/Http/Requests/UpdateOrganizationRequest.php +++ /dev/null @@ -1,43 +0,0 @@ -user()->can('update', $this->organization); - } - - /** - * Get the validation rules that apply to the request. - * - * @return array - */ - public function rules() - { - return [ - 'name' => [ - 'required', - 'string', - 'max:255', - Rule::unique(Organization::class)->ignore($this->organization->id), - - ], - 'locality' => ['required', 'string', 'max:255'], - 'region' => [ - 'required', - Rule::in(get_region_codes()), - ], - ]; - } -} diff --git a/stubs/app/Http/Requests/UpdateResourceCollectionRequest.php b/stubs/app/Http/Requests/UpdateResourceCollectionRequest.php deleted file mode 100644 index 5be8aba8..00000000 --- a/stubs/app/Http/Requests/UpdateResourceCollectionRequest.php +++ /dev/null @@ -1,52 +0,0 @@ -user()->can('update', $this->resourceCollection); - } - - /** - * Get the validation rules that apply to the request. - * - * @return array - */ - public function rules() - { - return [ - 'title' => [ - 'required', - 'string', - 'max:255', - UniqueTranslationRule::for('resource_collections')->ignore($this->resourceCollection->id), - - ], - 'description' => 'required|string', - 'resource_ids' => 'array', - 'resource_ids.*' => 'integer', - ]; - } - - /** - * Get the error messages for the defined validation rules. - * - * @return array - */ - public function messages() - { - return [ - 'title.unique' => __('validation.custom.resource_collection.title_exists'), - ]; - } -} diff --git a/stubs/app/Http/Requests/UpdateResourceRequest.php b/stubs/app/Http/Requests/UpdateResourceRequest.php deleted file mode 100644 index 086ac3bb..00000000 --- a/stubs/app/Http/Requests/UpdateResourceRequest.php +++ /dev/null @@ -1,51 +0,0 @@ -user()->can('update', $this->resource); - } - - /** - * Get the validation rules that apply to the request. - * - * @return array - */ - public function rules() - { - return [ - 'title' => [ - 'required', - 'string', - 'max:255', - Rule::unique(Resource::class)->ignore($this->resource->id), - - ], - 'summary' => 'required|string', - ]; - } - - /** - * Get the error messages for the defined validation rules. - * - * @return array - */ - public function messages() - { - return [ - 'title.unique' => __('validation.custom.resource.title_exists'), - ]; - } -} diff --git a/stubs/app/Http/Responses/FailedTwoFactorLoginResponse.php b/stubs/app/Http/Responses/FailedTwoFactorLoginResponse.php deleted file mode 100644 index 4d59ee66..00000000 --- a/stubs/app/Http/Responses/FailedTwoFactorLoginResponse.php +++ /dev/null @@ -1,28 +0,0 @@ -wantsJson()) { - throw ValidationException::withMessages([ - 'code' => [$message], - ]); - } - - return redirect()->route(\locale().'.login')->withErrors(['email' => $message]); - } -} diff --git a/stubs/app/Http/Responses/LoginResponse.php b/stubs/app/Http/Responses/LoginResponse.php deleted file mode 100644 index c9ca77e7..00000000 --- a/stubs/app/Http/Responses/LoginResponse.php +++ /dev/null @@ -1,26 +0,0 @@ -locale); - - if ($request->wantsJson()) { - return response()->json(['two_factor' => false]); - } - - return redirect()->intended($dashboard); - } -} diff --git a/stubs/app/Http/Responses/PasswordResetResponse.php b/stubs/app/Http/Responses/PasswordResetResponse.php deleted file mode 100644 index 41eabde4..00000000 --- a/stubs/app/Http/Responses/PasswordResetResponse.php +++ /dev/null @@ -1,23 +0,0 @@ -wantsJson()) { - return response()->json(['two_factor' => false]); - } - - return redirect()->intended(\localized_route('login')); - } -} diff --git a/stubs/app/Http/Responses/RegisterResponse.php b/stubs/app/Http/Responses/RegisterResponse.php deleted file mode 100644 index 220e15eb..00000000 --- a/stubs/app/Http/Responses/RegisterResponse.php +++ /dev/null @@ -1,26 +0,0 @@ -locale); - - if ($request->wantsJson()) { - return response()->json(['two_factor' => false]); - } - - return redirect()->intended($dashboard); - } -} diff --git a/stubs/app/Http/Responses/TwoFactorLoginResponse.php b/stubs/app/Http/Responses/TwoFactorLoginResponse.php deleted file mode 100644 index 7eca79a7..00000000 --- a/stubs/app/Http/Responses/TwoFactorLoginResponse.php +++ /dev/null @@ -1,26 +0,0 @@ -locale); - - if ($request->wantsJson()) { - return response('', 204); - } - - return redirect()->intended($dashboard); - } -} diff --git a/stubs/app/Mail/Invitation.php b/stubs/app/Mail/Invitation.php deleted file mode 100644 index fa79b8f0..00000000 --- a/stubs/app/Mail/Invitation.php +++ /dev/null @@ -1,48 +0,0 @@ -invitation = $invitation; - } - - /** - * Build the message. - * - * @return $this - */ - public function build() - { - return $this->markdown( - 'mail.invitation', - [ - 'acceptUrl' => URL::signedRoute('invitations.accept', $this->invitation), - 'invitation' => $this->invitation, - ] - )->subject(__('Team Invitation')); - } -} diff --git a/stubs/app/Models/Organization.php b/stubs/app/Models/Organization.php deleted file mode 100644 index 9745319e..00000000 --- a/stubs/app/Models/Organization.php +++ /dev/null @@ -1,67 +0,0 @@ -generateSlugsFrom('name') - ->saveSlugsTo('slug'); - } - - /** - * Get the route key for the model. - */ - public function getRouteKeyName(): string - { - return 'slug'; - } - - /** - * Get the route prefix for the model. - */ - public function getRoutePrefix(): string - { - return 'organizations'; - } -} diff --git a/stubs/app/Models/Resource.php b/stubs/app/Models/Resource.php deleted file mode 100644 index aff7658e..00000000 --- a/stubs/app/Models/Resource.php +++ /dev/null @@ -1,55 +0,0 @@ -generateSlugsFrom('title') - ->saveSlugsTo('slug'); - } - - /** - * Get the route key for the model. - */ - public function getRouteKeyName(): string - { - return 'slug'; - } - - /** - * Get all of the resource collections that include this resource. - */ - public function resourceCollections(): BelongsToMany - { - return $this->belongsToMany(ResourceCollection::class); - } -} diff --git a/stubs/app/Models/ResourceCollection.php b/stubs/app/Models/ResourceCollection.php deleted file mode 100644 index cbbfbc88..00000000 --- a/stubs/app/Models/ResourceCollection.php +++ /dev/null @@ -1,64 +0,0 @@ -generateSlugsFrom('title') - ->saveSlugsTo('slug'); - } - - /** - * Get the route key for the model. - */ - public function getRouteKeyName(): string - { - return 'slug'; - } - - /** - * Get user of this resource collection - */ - public function user(): BelongsTo - { - return $this->belongsTo(User::class); - } - - /** - * Get all of the resources that are assigned this collection. - */ - public function resources(): BelongsToMany - { - return $this->belongsToMany(Resource::class); - } -} diff --git a/stubs/app/Models/User.php b/stubs/app/Models/User.php deleted file mode 100644 index 89e7db58..00000000 --- a/stubs/app/Models/User.php +++ /dev/null @@ -1,155 +0,0 @@ - 'datetime', - ]; - - protected mixed $cascadeDeletes = [ - 'organizations', - ]; - - /** - * Get the options for generating the slug. - */ - public function getSlugOptions(): SlugOptions - { - return SlugOptions::create() - ->generateSlugsFrom('name') - ->saveSlugsTo('slug'); - } - - /** - * Get the route key for the model. - */ - public function getRouteKeyName(): string - { - return 'slug'; - } - - /** - * Get the user's preferred locale. - */ - public function preferredLocale(): string - { - return $this->locale; - } - - /** - * Get the user's resource collections. - */ - public function resourceCollections(): HasMany - { - return $this->hasMany(ResourceCollection::class); - } - - /** - * Get the user's resources. - */ - public function resources() - { - return $this->hasMany(Resource::class); - } - - /** - * Get the parent joinable model. - */ - public function joinable(): MorphTo - { - return $this->morphTo(); - } - - /** - * Has the user requested to join a model? - * - * @return bool - */ - public function hasRequestedToJoin(mixed $model) - { - /** @var Organization|null */ - $joinable = $this->joinable; - - return ! is_null($joinable) && $joinable->id === $model->id; - } - - /** - * Get the organizations that belong to this user. - */ - public function organizations(): MorphToMany - { - return $this->morphedByMany(Organization::class, 'membershipable', 'memberships') - ->as('membership') - ->using(Membership::class) - ->withPivot(['role', 'id']) - ->withTimestamps(); - } - - /** - * Get the organization that belongs to the user. - */ - public function getOrganizationAttribute(): mixed - { - return $this->organizations->first(); - } - - /** - * Determine if the user is a member of a given membershipable model. - */ - public function isMemberOf(mixed $model): bool - { - return $model->hasMemberWithEmail($this->email); - } - - /** - * Determine if the user is an administrator of a given model. - */ - public function isAdministratorOf(mixed $model): bool - { - return $model->hasAdministratorWithEmail($this->email); - } - - /** - * Is two-factor authentication enabled for this user? - */ - public function twoFactorAuthEnabled(): bool - { - return ! is_null($this->two_factor_secret); - } -} diff --git a/stubs/app/Policies/OrganizationPolicy.php b/stubs/app/Policies/OrganizationPolicy.php deleted file mode 100644 index 7bc1da5d..00000000 --- a/stubs/app/Policies/OrganizationPolicy.php +++ /dev/null @@ -1,53 +0,0 @@ -joinable && $user->organizations->isEmpty() - ? Response::allow() - : Response::deny(__('You already belong to an organization, so you cannot create a new one.')); - } - - /** - * Determine whether the user can join the model. - */ - public function join(User $user, Organization $organization): Response - { - return ! $user->joinable && $user->organizations->isEmpty() - ? Response::allow() - : Response::deny(__('You cannot join this organization.')); - } - - /** - * Determine whether the user can update the model. - */ - public function update(User $user, Organization $organization): Response - { - return $user->isAdministratorOf($organization) - ? Response::allow() - : Response::deny(__('You cannot edit this organization.')); - } - - /** - * Determine whether the user can delete the model. - */ - public function delete(User $user, Organization $organization): Response - { - return $user->isAdministratorOf($organization) - ? Response::allow() - : Response::deny(__('You cannot delete this organization.')); - } -} diff --git a/stubs/app/Policies/ResourceCollectionPolicy.php b/stubs/app/Policies/ResourceCollectionPolicy.php deleted file mode 100644 index f13176ff..00000000 --- a/stubs/app/Policies/ResourceCollectionPolicy.php +++ /dev/null @@ -1,41 +0,0 @@ -id === $resourceCollection->user_id - ? Response::allow() - : Response::deny('You cannot edit this resource collection.'); - } - - /** - * Determine whether the user can delete the model. - */ - public function delete(User $user, ResourceCollection $resourceCollection): Response - { - return $user->id === $resourceCollection->user_id - ? Response::allow() - : Response::deny('You cannot delete this resource collection.'); - } -} diff --git a/stubs/app/Policies/ResourcePolicy.php b/stubs/app/Policies/ResourcePolicy.php deleted file mode 100644 index a696ddc6..00000000 --- a/stubs/app/Policies/ResourcePolicy.php +++ /dev/null @@ -1,41 +0,0 @@ -id === $resource->user_id - ? Response::allow() - : Response::deny('You cannot edit this resource.'); - } - - /** - * Determine whether the user can delete the model. - */ - public function delete(User $user, Resource $resource): Response - { - return $user->id === $resource->user_id - ? Response::allow() - : Response::deny('You cannot delete this resource.'); - } -} diff --git a/stubs/app/Policies/UserPolicy.php b/stubs/app/Policies/UserPolicy.php deleted file mode 100644 index fb2e4e67..00000000 --- a/stubs/app/Policies/UserPolicy.php +++ /dev/null @@ -1,32 +0,0 @@ -id === $model->id - ? Response::allow() - : Response::deny(__('You cannot edit this account.')); - } - - /** - * Determine whether the user can delete the model. - */ - public function delete(User $user, User $model): Response - { - return $user->id === $model->id - ? Response::allow() - : Response::deny(__('You cannot delete this account.')); - } -} diff --git a/stubs/app/Providers/FortifyServiceProvider.php b/stubs/app/Providers/FortifyServiceProvider.php deleted file mode 100644 index 34d2ceed..00000000 --- a/stubs/app/Providers/FortifyServiceProvider.php +++ /dev/null @@ -1,108 +0,0 @@ -registerResponseBindings(); - - Fortify::ignoreRoutes(); - } - - /** - * Bootstrap any application services. - * - * @return void - */ - public function boot() - { - Fortify::createUsersUsing(CreateNewUser::class); - Fortify::updateUserProfileInformationUsing(UpdateUserProfileInformation::class); - Fortify::updateUserPasswordsUsing(UpdateUserPassword::class); - Fortify::resetUserPasswordsUsing(ResetUserPassword::class); - - RateLimiter::for('login', function (Request $request) { - return Limit::perMinute(5)->by($request->email.$request->ip()); - }); - - RateLimiter::for('two-factor', function (Request $request) { - return Limit::perMinute(5)->by($request->session()->get('login.id')); - }); - - Fortify::loginView(fn () => view('auth.login')); - Fortify::registerView(fn () => view('auth.register')); - Fortify::requestPasswordResetLinkView(fn () => view('auth.forgot-password')); - Fortify::resetPasswordView(fn () => view('auth.reset-password')); - Fortify::confirmPasswordView(fn () => view('auth.confirm-password')); - Fortify::twoFactorChallengeView(fn () => view('auth.two-factor-challenge')); - Fortify::verifyEmailView(fn () => view('auth.verify-email')); - - Fortify::authenticateThrough(function (Request $request) { - return array_filter([ - config('fortify.limiters.login') ? null : EnsureLoginIsNotThrottled::class, - Features::enabled(Features::twoFactorAuthentication()) ? RedirectIfTwoFactorAuthenticatable::class : null, - AttemptToAuthenticate::class, - PrepareAuthenticatedSession::class, - ]); - }); - } - - /** - * Register response bindings. - */ - protected function registerResponseBindings(): void - { - $this->app->singleton( - FailedTwoFactorLoginResponseContract::class, - FailedTwoFactorLoginResponse::class - ); - $this->app->singleton( - LoginResponseContract::class, - LoginResponse::class - ); - $this->app->singleton( - TwoFactorLoginResponseContract::class, - TwoFactorLoginResponse::class - ); - $this->app->singleton( - RegisterResponseContract::class, - RegisterResponse::class - ); - $this->app->singleton( - PasswordResetResponseContract::class, - PasswordResetResponse::class - ); - } -} diff --git a/stubs/app/Rules/NotLastAdmin.php b/stubs/app/Rules/NotLastAdmin.php deleted file mode 100644 index 5e43978b..00000000 --- a/stubs/app/Rules/NotLastAdmin.php +++ /dev/null @@ -1,41 +0,0 @@ -membership = $membership; - } - - /** - * Determine if the validation rule passes. - * - * @param string $attribute - * @param mixed $value - */ - public function passes($attribute, $value): bool - { - return $this->membership->membershipable()->administrators->count() > 1; - } - - /** - * Get the validation error message. - */ - public function message(): string - { - return __('validation.custom.membership.not_last_admin'); - } -} diff --git a/stubs/app/Rules/Password.php b/stubs/app/Rules/Password.php deleted file mode 100644 index 9666cc6c..00000000 --- a/stubs/app/Rules/Password.php +++ /dev/null @@ -1,76 +0,0 @@ -message) { - return $this->message; - } - - switch (true) { - case $this->requireUppercase - && ! $this->requireNumeric - && ! $this->requireSpecialCharacter: - return __('hearth::validation.password.length-uppercase', [ - 'length' => $this->length, - ]); - - case $this->requireNumeric - && ! $this->requireUppercase - && ! $this->requireSpecialCharacter: - return __('hearth::validation.password.length-numeric', [ - 'length' => $this->length, - ]); - - case $this->requireSpecialCharacter - && ! $this->requireUppercase - && ! $this->requireNumeric: - return __('hearth::validation.password.length-specialcharacter', [ - 'length' => $this->length, - ]); - - case $this->requireUppercase - && $this->requireNumeric - && ! $this->requireSpecialCharacter: - return __('hearth::validation.password.length-uppercase-numeric', [ - 'length' => $this->length, - ]); - - case $this->requireUppercase - && $this->requireSpecialCharacter - && ! $this->requireNumeric: - return __('hearth::validation.password.length-uppercase-specialcharacter', [ - 'length' => $this->length, - ]); - - case $this->requireUppercase - && $this->requireNumeric - && $this->requireSpecialCharacter: - return __('hearth::validation.password.length-uppercase-numeric-specialcharacter', [ - 'length' => $this->length, - ]); - - case $this->requireNumeric - && $this->requireSpecialCharacter - && ! $this->requireUppercase: - return __('hearth::validation.password.length-numeric-specialcharacter', [ - 'length' => $this->length, - ]); - - default: - return __('hearth::validation.password.length', [ - 'length' => $this->length, - ]); - } - } -} diff --git a/stubs/app/View/Components/AppLayout.php b/stubs/app/View/Components/AppLayout.php deleted file mode 100644 index b45d3425..00000000 --- a/stubs/app/View/Components/AppLayout.php +++ /dev/null @@ -1,18 +0,0 @@ - 'web', - - /* - |-------------------------------------------------------------------------- - | Fortify Password Broker - |-------------------------------------------------------------------------- - | - | Here you may specify which password broker Fortify can use when a user - | is resetting their password. This configured value should match one - | of your password brokers setup in your "auth" configuration file. - | - */ - - 'passwords' => 'users', - - /* - |-------------------------------------------------------------------------- - | Username / Email - |-------------------------------------------------------------------------- - | - | This value defines which model attribute should be considered as your - | application's "username" field. Typically, this might be the email - | address of the users but you are free to change this value here. - | - | Out of the box, Fortify expects forgot password and reset password - | requests to have a field named 'email'. If the application uses - | another name for the field you may define it below as needed. - | - */ - - 'username' => 'email', - - 'email' => 'email', - - /* - |-------------------------------------------------------------------------- - | Home Path - |-------------------------------------------------------------------------- - | - | Here you may configure the path where users will get redirected during - | authentication or password reset when the operations are successful - | and the user is authenticated. You are free to change this value. - | - */ - - 'home' => RouteServiceProvider::HOME, - - /* - |-------------------------------------------------------------------------- - | Fortify Routes Prefix / Subdomain - |-------------------------------------------------------------------------- - | - | Here you may specify which prefix Fortify will assign to all the routes - | that it registers with the application. If necessary, you may change - | subdomain under which all of the Fortify routes will be available. - | - */ - - 'prefix' => '', - - 'domain' => null, - - /* - |-------------------------------------------------------------------------- - | Fortify Routes Middleware - |-------------------------------------------------------------------------- - | - | Here you may specify which middleware Fortify will assign to the routes - | that it registers with the application. If necessary, you may change - | these middleware but typically this provided default is preferred. - | - */ - - 'middleware' => ['web'], - - /* - |-------------------------------------------------------------------------- - | Rate Limiting - |-------------------------------------------------------------------------- - | - | By default, Fortify will throttle logins to five requests per minute for - | every email and IP address combination. However, if you would like to - | specify a custom rate limiter to call then you may specify it here. - | - */ - - 'limiters' => [ - 'login' => 'login', - 'two-factor' => 'two-factor', - ], - - /* - |-------------------------------------------------------------------------- - | Features - |-------------------------------------------------------------------------- - | - | Some of the Fortify features are optional. You may disable the features - | by removing them from this array. You're free to only remove some of - | these features or you can even remove all of these if you need to. - | - */ - - 'features' => [ - Features::registration(), - Features::resetPasswords(), - Features::emailVerification(), - Features::updateProfileInformation(), - Features::updatePasswords(), - // Features::twoFactorAuthentication([ 'confirmPassword' => true ]), - ], - -]; diff --git a/stubs/config/laravel-multilingual-routes.php b/stubs/config/laravel-multilingual-routes.php deleted file mode 100644 index 67dc4c2b..00000000 --- a/stubs/config/laravel-multilingual-routes.php +++ /dev/null @@ -1,50 +0,0 @@ - env('MULTILINGUAL_ROUTES_DEFAULT_LOCALE', config('app.fallback_locale')), - - /* - |-------------------------------------------------------------------------- - | Prefix Configuration - |-------------------------------------------------------------------------- - | - | The configuration option that defines if the routes of the default - | locale should be prefixed. - | - */ - - 'prefix_default' => env('MULTILINGUAL_ROUTES_PREFIX_DEFAULT', true), - - /* - |-------------------------------------------------------------------------- - | Home Prefix Configuration - |-------------------------------------------------------------------------- - | - | The configuration option defines if the home route of the default locale - | should be prefixed. - | - */ - - 'prefix_default_home' => env('MULTILINGUAL_ROUTES_PREFIX_DEFAULT_HOME', true), - - /* - |-------------------------------------------------------------------------- - | Name Prefix Configuration - |-------------------------------------------------------------------------- - | - | The configuration option that defines if the route name prefix should - | be before the locale. - | - */ - - 'name_prefix_before_locale' => env('MULTILINGUAL_ROUTES_NAME_PREFIX_BEFORE_LOCALE', false), -]; diff --git a/stubs/config/livewire.php b/stubs/config/livewire.php deleted file mode 100644 index 76d2e266..00000000 --- a/stubs/config/livewire.php +++ /dev/null @@ -1,5 +0,0 @@ - 'App\\Http\\Livewire', -]; diff --git a/stubs/config/locales.php b/stubs/config/locales.php deleted file mode 100644 index 45cb52c3..00000000 --- a/stubs/config/locales.php +++ /dev/null @@ -1,17 +0,0 @@ - [ - 'en', - 'fr', - ], -]; diff --git a/stubs/routes/fortify.php b/stubs/routes/fortify.php deleted file mode 100644 index 28aeb7b1..00000000 --- a/stubs/routes/fortify.php +++ /dev/null @@ -1,144 +0,0 @@ - config('fortify.middleware', ['web'])], function () { - if (Features::enabled(Features::registration())) { - Route::multilingual('/register', [RegisteredUserController::class, 'create']) - ->middleware('guest') - ->name('register'); - - Route::multilingual('/register', [RegisteredUserController::class, 'store']) - ->method('post') - ->middleware('guest'); - } - - Route::multilingual('/login', [AuthenticatedSessionController::class, 'create']) - ->middleware('guest') - ->name('login'); - - $limiter = config('fortify.limiters.login'); - $twoFactorLimiter = config('fortify.limiters.two-factor'); - - Route::multilingual('/login', [AuthenticatedSessionController::class, 'store']) - ->method('post') - ->middleware(array_filter([ - 'guest', - $limiter ? 'throttle:'.$limiter : null, - ])); - - Route::multilingual('/logout', [AuthenticatedSessionController::class, 'destroy']) - ->method('post') - ->middleware('auth') - ->name('logout'); - - if (Features::enabled(Features::resetPasswords())) { - Route::multilingual('/forgot-password', [PasswordResetLinkController::class, 'create']) - ->middleware('guest') - ->name('password.request'); - - Route::get('/reset-password/{token}', [NewPasswordController::class, 'create']) - ->middleware('guest') - ->name('password.reset'); - - Route::post('/forgot-password', [PasswordResetLinkController::class, 'store']) - ->middleware('guest') - ->name('password.email'); - - Route::multilingual('/reset-password', [NewPasswordController::class, 'store']) - ->method('post') - ->middleware('guest') - ->name('password.update'); - } - - if (Features::enabled(Features::emailVerification())) { - Route::multilingual('/verify-email', [EmailVerificationPromptController::class, '__invoke']) - ->middleware('auth') - ->name('verification.notice'); - - Route::get('/verify-email/{id}/{hash}', [VerifyEmailController::class, '__invoke']) - ->middleware(['auth', 'signed', 'throttle:6,1']) - ->name('verification.verify'); - - Route::post('/email/verification-notification', [EmailVerificationNotificationController::class, 'store']) - ->middleware(['auth', 'throttle:6,1']) - ->name('verification.send'); - } - - if (Features::enabled(Features::updateProfileInformation())) { - Route::multilingual('/account/update', [UserProfileInformationController::class, 'update']) - ->method('put') - ->middleware(['auth']) - ->name('user-profile-information.update'); - } - - if (Features::enabled(Features::updatePasswords())) { - Route::multilingual('/account/update-password', [PasswordController::class, 'update']) - ->method('put') - ->middleware(['auth']) - ->name('user-password.update'); - } - - Route::multilingual('/confirm-password', [ConfirmablePasswordController::class, 'show']) - ->middleware('auth') - ->name('password.confirm'); - - Route::get('/confirmed-password-status', [ConfirmedPasswordStatusController::class, 'show']) - ->middleware(['auth']) - ->name('password.confirmation'); - - Route::multilingual('/confirm-password', [ConfirmablePasswordController::class, 'store']) - ->method('post') - ->middleware('auth'); - - if (Features::enabled(Features::twoFactorAuthentication())) { - Route::multilingual('/two-factor-challenge', [TwoFactorAuthenticatedSessionController::class, 'create']) - ->middleware(['guest:'.config('fortify.guard')]) - ->name('two-factor.login'); - - Route::multilingual('/two-factor-challenge', [TwoFactorAuthenticatedSessionController::class, 'store']) - ->method('post') - ->middleware(array_filter([ - 'guest:'.config('fortify.guard'), - $twoFactorLimiter ? 'throttle:'.$twoFactorLimiter : null, - ])); - - $twoFactorMiddleware = Features::optionEnabled(Features::twoFactorAuthentication(), 'confirmPassword') - ? ['auth', 'password.confirm'] - : ['auth']; - - Route::post('/user/two-factor-authentication', [TwoFactorAuthenticationController::class, 'store']) - ->middleware($twoFactorMiddleware) - ->name('two-factor.enable'); - - Route::delete('/user/two-factor-authentication', [TwoFactorAuthenticationController::class, 'destroy']) - ->middleware($twoFactorMiddleware) - ->name('two-factor.disable'); - - Route::get('/user/two-factor-qr-code', [TwoFactorQrCodeController::class, 'show']) - ->middleware($twoFactorMiddleware); - - Route::get('/user/two-factor-recovery-codes', [RecoveryCodeController::class, 'index']) - ->middleware($twoFactorMiddleware); - - Route::post('/user/two-factor-recovery-codes', [RecoveryCodeController::class, 'store']) - ->middleware($twoFactorMiddleware) - ->name('two-factor.regenerate'); - } -}); diff --git a/stubs/routes/organizations.php b/stubs/routes/organizations.php deleted file mode 100644 index ba71a9f6..00000000 --- a/stubs/routes/organizations.php +++ /dev/null @@ -1,65 +0,0 @@ - -middleware(['auth']) - ->name('organizations.index'); - -Route::multilingual('/organizations/create', [OrganizationController::class, 'create']) - ->middleware(['auth', 'can:create,App\Models\Organization']) - ->name('organizations.create'); - -Route::multilingual('/organizations/create', [OrganizationController::class, 'store']) - ->method('post') - ->middleware(['auth', 'can:create,App\Models\Organization']) - ->name('organizations.store'); - -Route::multilingual('/organizations/{organization}', [OrganizationController::class, 'show']) - ->middleware(['auth']) - ->name('organizations.show'); - -Route::multilingual('/organizations/{organization}/join', [OrganizationController::class, 'join']) - ->method('post') - ->middleware(['auth', 'can:join,organization']) - ->name('organizations.join'); - -Route::multilingual('/organizations/{organization}/edit', [OrganizationController::class, 'edit']) - ->middleware(['auth', 'can:update,organization']) - ->name('organizations.edit'); - -Route::multilingual('/organizations/{organization}/edit', [OrganizationController::class, 'update']) - ->middleware(['auth', 'can:update,organization']) - ->method('put') - ->name('organizations.update'); - -Route::multilingual('/organizations/{organization}/delete', [OrganizationController::class, 'destroy']) - ->middleware(['auth', 'can:delete,organization']) - ->method('delete') - ->name('organizations.destroy'); - -Route::multilingual('/memberships/{membership}/edit', [MembershipController::class, 'edit']) - ->name('memberships.edit'); - -Route::multilingual('/memberships/{membership}/update', [MembershipController::class, 'update']) - ->method('put') - ->name('memberships.update'); - -Route::delete('/memberships/{membership}/delete', [MembershipController::class, 'destroy']) - ->name('memberships.destroy'); - -Route::multilingual('/invitations/create', [InvitationController::class, 'create']) - ->method('post') - ->name('invitations.create'); - -Route::get('/invitations/{invitation}', [InvitationController::class, 'accept']) - ->middleware(['auth', 'signed']) - ->name('invitations.accept'); - -Route::delete('/invitations/{invitation}/cancel', [InvitationController::class, 'destroy']) - ->middleware(['auth']) - ->name('invitations.destroy'); diff --git a/stubs/routes/resource-collections.php b/stubs/routes/resource-collections.php deleted file mode 100644 index 1919ea11..00000000 --- a/stubs/routes/resource-collections.php +++ /dev/null @@ -1,33 +0,0 @@ -name('resource-collections.index'); - -Route::multilingual('/resource-collections/create', [ResourceCollectionController::class, 'create']) - ->middleware(['auth', 'can:create,App\Models\ResourceCollection']) - ->name('resource-collections.create'); - -Route::multilingual('/resource-collections/create', [ResourceCollectionController::class, 'store']) - ->method('post') - ->middleware(['auth', 'can:create,App\Models\ResourceCollection']) - ->name('resource-collections.store'); - -Route::multilingual('/resource-collections/{resourceCollection}', [ResourceCollectionController::class, 'show']) - ->name('resource-collections.show'); - -Route::multilingual('/resource-collections/{resourceCollection}/edit', [ResourceCollectionController::class, 'edit']) - ->middleware(['auth', 'can:update,resourceCollection']) - ->name('resource-collections.edit'); - -Route::multilingual('/resource-collections/{resourceCollection}/edit', [ResourceCollectionController::class, 'update']) - ->middleware(['auth', 'can:update,resourceCollection']) - ->method('put') - ->name('resource-collections.update'); - -Route::multilingual('/resource-collections/{resourceCollection}/delete', [ResourceCollectionController::class, 'destroy']) - ->middleware(['auth', 'can:delete,resourceCollection']) - ->method('delete') - ->name('resource-collections.destroy'); diff --git a/stubs/routes/resources.php b/stubs/routes/resources.php deleted file mode 100644 index d2bb352d..00000000 --- a/stubs/routes/resources.php +++ /dev/null @@ -1,34 +0,0 @@ - -name('resources.index'); - -Route::multilingual('/resources/create', [ResourceController::class, 'create']) - ->middleware(['auth', 'can:create,App\Models\Resource']) - ->name('resources.create'); - -Route::multilingual('/resources/create', [ResourceController::class, 'store']) - ->method('post') - ->middleware(['auth', 'can:create,App\Models\Resource']) - ->name('resources.store'); - -Route::multilingual('/resources/{resource}', [ResourceController::class, 'show']) - ->name('resources.show'); - -Route::multilingual('/resources/{resource}/edit', [ResourceController::class, 'edit']) - ->middleware(['auth', 'can:update,resource']) - ->name('resources.edit'); - -Route::multilingual('/resources/{resource}/edit', [ResourceController::class, 'update']) - ->middleware(['auth', 'can:update,resource']) - ->method('put') - ->name('resources.update'); - -Route::multilingual('/resources/{resource}/delete', [ResourceController::class, 'destroy']) - ->middleware(['auth', 'can:delete,resource']) - ->method('delete') - ->name('resources.destroy'); diff --git a/stubs/routes/web.php b/stubs/routes/web.php deleted file mode 100644 index 9a7f29e1..00000000 --- a/stubs/routes/web.php +++ /dev/null @@ -1,64 +0,0 @@ -name('welcome'); - -Route::multilingual('/dashboard', function () { - return view('dashboard'); -})->middleware(['auth', 'verified:'.\locale().'.verification.notice'])->name('dashboard'); - -Route::multilingual('/account/edit', [UserController::class, 'edit']) - ->middleware(['auth']) - ->name('users.edit'); - -Route::multilingual('/account/admin', [UserController::class, 'admin']) - ->middleware(['auth']) - ->name('users.admin'); - -Route::multilingual('/account/delete', [UserController::class, 'destroy']) - ->method('delete') - ->middleware(['auth']) - ->name('users.destroy'); - -Route::multilingual('/requests/cancel', [JoinController::class, 'cancel']) - ->method('post') - ->middleware(['auth']) - ->name('requests.cancel'); - -Route::multilingual('/requests/{user:id}/deny', [JoinController::class, 'deny']) - ->method('post') - ->middleware(['auth']) - ->name('requests.deny'); - -Route::multilingual('/requests/{user:id}/approve', [JoinController::class, 'approve']) - ->method('post') - ->middleware(['auth']) - ->name('requests.approve'); - -if (config('hearth.organizations.enabled')) { - require __DIR__.'/organizations.php'; -} - -if (config('hearth.resources.enabled')) { - require __DIR__.'/resources.php'; - require __DIR__.'/resource-collections.php'; -} - -require __DIR__.'/fortify.php'; diff --git a/stubs/tests/Feature/AccountDeletionTest.php b/stubs/tests/Feature/AccountDeletionTest.php deleted file mode 100644 index 0069043c..00000000 --- a/stubs/tests/Feature/AccountDeletionTest.php +++ /dev/null @@ -1,50 +0,0 @@ -create(); - - $response = $this->post(localized_route('login'), [ - 'email' => $user->email, - 'password' => 'password', - ]); - - $this->assertAuthenticated(); - - $response = $this->from(localized_route('users.admin'))->delete(localized_route('users.destroy'), [ - 'current_password' => 'password', - ]); - - $this->assertGuest(); - - $response->assertRedirect(localized_route('welcome')); -}); - -test('users cannot delete their own accounts with incorrect password', function () { - $user = User::factory()->create(); - - $response = $this->post(localized_route('login'), [ - 'email' => $user->email, - 'password' => 'password', - ]); - - $this->assertAuthenticated(); - - $response = $this->from(localized_route('users.admin'))->delete(localized_route('users.destroy'), [ - 'current_password' => 'wrong_password', - ]); - - $response->assertRedirect(localized_route('users.admin')); -}); - -test('guests cannot delete accounts', function () { - $user = User::factory()->create(); - - $response = $this->delete(localized_route('users.destroy')); - - $response->assertRedirect(localized_route('login')); -}); diff --git a/stubs/tests/Feature/AuthenticationTest.php b/stubs/tests/Feature/AuthenticationTest.php deleted file mode 100644 index 8b31ac46..00000000 --- a/stubs/tests/Feature/AuthenticationTest.php +++ /dev/null @@ -1,52 +0,0 @@ -get(localized_route('login')); - - $response->assertOk(); -}); - -test('users can authenticate using the login screen', function () { - $user = User::factory()->create(); - - $response = $this->post(localized_route('login'), [ - 'email' => $user->email, - 'password' => 'password', - ]); - - $this->assertAuthenticated(); - $response->assertRedirect(localized_route('dashboard')); -}); - -test('users can not authenticate with invalid password', function () { - $user = User::factory()->create(); - - $this->post(localized_route('login'), [ - 'email' => $user->email, - 'password' => 'wrong-password', - ]); - - $this->assertGuest(); -}); - -test('users can edit own profiles', function () { - $user = User::factory()->create(); - - $response = $this->post(localized_route('login'), [ - 'email' => $user->email, - 'password' => 'password', - ]); - - $response = $this->get(localized_route('users.edit')); - $response->assertOk(); -}); - -test('guests can not edit profiles', function () { - $response = $this->get(localized_route('users.edit')); - $response->assertRedirect(localized_route('login')); -}); diff --git a/stubs/tests/Feature/EmailVerificationTest.php b/stubs/tests/Feature/EmailVerificationTest.php deleted file mode 100644 index 75d0950f..00000000 --- a/stubs/tests/Feature/EmailVerificationTest.php +++ /dev/null @@ -1,55 +0,0 @@ -create([ - 'email_verified_at' => null, - ]); - - $response = $this->actingAs($user)->get(localized_route('verification.notice')); - - $response->assertOk(); -}); - -test('email can be verified', function () { - Event::fake(); - - $user = User::factory()->create([ - 'email_verified_at' => null, - ]); - - $verificationUrl = URL::temporarySignedRoute( - 'verification.verify', - now()->addMinutes(60), - ['id' => $user->id, 'hash' => sha1($user->email)] - ); - - $response = $this->actingAs($user)->get($verificationUrl); - - Event::assertDispatched(Verified::class); - expect($user->fresh()->hasVerifiedEmail())->toBeTrue(); - $response->assertRedirect(localized_route('dashboard', ['verified' => 1])); -}); - -test('email is not verified with invalid hash', function () { - $user = User::factory()->create([ - 'email_verified_at' => null, - ]); - - $verificationUrl = URL::temporarySignedRoute( - 'verification.verify', - now()->addMinutes(60), - ['id' => $user->id, 'hash' => sha1('wrong-email')] - ); - - $this->actingAs($user)->get($verificationUrl); - - expect($user->fresh()->hasVerifiedEmail())->toBeFalse(); -}); diff --git a/stubs/tests/Feature/JoinTest.php b/stubs/tests/Feature/JoinTest.php deleted file mode 100644 index cd1edbe9..00000000 --- a/stubs/tests/Feature/JoinTest.php +++ /dev/null @@ -1,119 +0,0 @@ -create(); - $organization = Organization::factory()->create(); - - $response = $this->actingAs($user)->get(localized_route('organizations.show', $organization)); - $response->assertSee('Request to join'); - - $response = $this->actingAs($user) - ->from(localized_route('organizations.show', $organization)) - ->post(localized_route('organizations.join', $organization)); - - $response->assertSessionHasNoErrors(); - $response->assertRedirect(localized_route('organizations.show', $organization)); - - $organization = $organization->fresh(); - - expect($organization->requestsToJoin->count())->toEqual(1); - expect($organization->requestsToJoin->first()->id)->toEqual($user->id); -}); - -test('user with outstanding join request cannot request to join team', function () { - $user = User::factory()->create(); - $organization = Organization::factory()->create(); - $organization->requestsToJoin()->save($user); - $otherOrganization = Organization::factory()->create(); - - $response = $this->actingAs($user)->get(localized_route('organizations.show', $otherOrganization)); - $response->assertDontSee('Request to join'); - - $response = $this->actingAs($user) - ->from(localized_route('organizations.show', $otherOrganization)) - ->post(localized_route('organizations.join', $otherOrganization)); - - $response->assertForbidden(); -}); - -test('user with existing membership cannot request to join team', function () { - $user = User::factory()->create(); - $organization = Organization::factory()->create(); - $organization->users()->attach($user, ['role' => 'admin']); - $otherOrganization = Organization::factory()->create(); - - $response = $this->actingAs($user)->get(localized_route('organizations.show', $otherOrganization)); - $response->assertDontSee('Request to join'); - - $response = $this->actingAs($user) - ->from(localized_route('organizations.show', $otherOrganization)) - ->post(localized_route('organizations.join', $otherOrganization)); - - $response->assertForbidden(); -}); - -test('user can cancel request to join team', function () { - $user = User::factory()->create(); - $organization = Organization::factory()->create(); - $organization->requestsToJoin()->save($user); - - $response = $this->actingAs($user)->get(localized_route('organizations.show', $organization)); - $response->assertSee('Cancel request'); - - $response = $this->actingAs($user)->post(localized_route('requests.cancel')); - $response->assertRedirect(localized_route('organizations.show', $organization)); - - $user = $user->fresh(); - $organization = $organization->fresh(); - - expect($user->joinable)->toBeNull(); - expect($organization->requestsToJoin->count())->toEqual(0); -}); - -test('admin can approve request to join team', function () { - $user = User::factory()->create(); - $admin = User::factory()->create(); - $organization = Organization::factory()->hasAttached($admin, ['role' => 'admin'])->create(); - $organization->requestsToJoin()->save($user); - - $response = $this->actingAs($admin)->get(localized_route('organizations.edit', $organization)); - $response->assertSee('Approve '.$user->name.'’s request'); - - $response = $this->actingAs($admin)->post(localized_route('requests.approve', $user)); - - $response->assertSessionHasNoErrors(); - $response->assertRedirect(localized_route('organizations.edit', $organization)); - - $user = $user->fresh(); - $organization = $organization->fresh(); - - expect($user->joinable)->toBeNull(); - expect($organization->hasUserWithEmail($user->email))->toBeTrue(); -}); - -test('admin can deny request to join team', function () { - $user = User::factory()->create(); - $admin = User::factory()->create(); - $organization = Organization::factory()->hasAttached($admin, ['role' => 'admin'])->create(); - $organization->requestsToJoin()->save($user); - - $response = $this->actingAs($admin)->get(localized_route('organizations.edit', $organization)); - $response->assertSee('Deny '.$user->name.'’s request'); - - $response = $this->actingAs($admin)->post(localized_route('requests.deny', $user)); - - $response->assertSessionHasNoErrors(); - $response->assertRedirect(localized_route('organizations.edit', $organization)); - - $user = $user->fresh(); - $organization = $organization->fresh(); - - expect($user->joinable)->toBeNull(); - expect($organization->hasUserWithEmail($user->email))->toBeFalse(); -}); diff --git a/stubs/tests/Feature/LocalizationTest.php b/stubs/tests/Feature/LocalizationTest.php deleted file mode 100644 index 13079f87..00000000 --- a/stubs/tests/Feature/LocalizationTest.php +++ /dev/null @@ -1,29 +0,0 @@ -create(['locale' => 'fr']); - - $response = $this->post(localized_route('login'), [ - 'email' => $user->email, - 'password' => 'password', - ]); - - $this->assertAuthenticated(); - $response->assertRedirect(localized_route('dashboard', [], 'fr')); -}); - -test('user is redirected to preferred locale when editing profile', function () { - $user = User::factory()->create(['locale' => 'fr']); - - $response = $this->withCookie('locale', 'fr')->actingAs($user)->from(localized_route('users.edit'))->put(localized_route('user-profile-information.update'), [ - 'name' => $user->name, - 'email' => $user->email, - 'locale' => 'en', - ]); - $response->assertRedirect(localized_route('users.edit', [], 'en')); -}); diff --git a/stubs/tests/Feature/OrganizationTest.php b/stubs/tests/Feature/OrganizationTest.php deleted file mode 100644 index cefa53e9..00000000 --- a/stubs/tests/Feature/OrganizationTest.php +++ /dev/null @@ -1,638 +0,0 @@ -markTestSkipped('Organization support is not enabled.'); - } - - $user = User::factory()->create(); - - $response = $this->actingAs($user)->get(localized_route('organizations.create')); - $response->assertOk(); - - $response = $this->actingAs($user)->post(localized_route('organizations.create'), [ - 'name' => $user->name.' Consulting', - 'locality' => 'Truro', - 'region' => 'NS', - ]); - - $organization = Organization::where('name->en', $user->name.' Consulting')->first(); - - $url = localized_route('organizations.show', $organization); - - $response->assertSessionHasNoErrors(); - - $response->assertRedirect($url); -}); - -test('users with admin role can edit organizations', function () { - if (! config('hearth.organizations.enabled')) { - return $this->markTestSkipped('Organization support is not enabled.'); - } - - $user = User::factory()->create(); - $organization = Organization::factory() - ->hasAttached($user, ['role' => 'admin']) - ->create(); - - $response = $this->actingAs($user)->get(localized_route('organizations.edit', $organization)); - $response->assertOk(); - - $response = $this->actingAs($user)->put(localized_route('organizations.update', $organization), [ - 'name' => $organization->name, - 'locality' => 'St John\'s', - 'region' => 'NL', - ]); - $response->assertRedirect(localized_route('organizations.show', $organization)); -}); - -test('users without admin role can not edit organizations', function () { - if (! config('hearth.organizations.enabled')) { - return $this->markTestSkipped('Organization support is not enabled.'); - } - - $user = User::factory()->create(); - $organization = Organization::factory() - ->hasAttached($user, ['role' => 'member']) - ->create(); - - $response = $this->actingAs($user)->get(localized_route('organizations.edit', $organization)); - $response->assertForbidden(); - - $response = $this->actingAs($user)->put(localized_route('organizations.update', $organization), [ - 'name' => $organization->name, - 'locality' => 'St John\'s', - 'region' => 'NL', - ]); - $response->assertForbidden(); -}); - -test('non members can not edit organizations', function () { - if (! config('hearth.organizations.enabled')) { - return $this->markTestSkipped('Organization support is not enabled.'); - } - - $user = User::factory()->create(); - $other_user = User::factory()->create(); - - $organization = Organization::factory() - ->hasAttached($user, ['role' => 'admin']) - ->create(); - - $other_organization = Organization::factory() - ->hasAttached($other_user, ['role' => 'admin']) - ->create(); - - $response = $this->actingAs($user)->get(localized_route('organizations.edit', $other_organization)); - $response->assertForbidden(); - - $response = $this->actingAs($user)->put(localized_route('organizations.update', $other_organization), [ - 'name' => $other_organization->name, - 'locality' => 'St John\'s', - 'region' => 'NL', - ]); - $response->assertForbidden(); -}); - -test('organizations can be translated', function () { - if (! config('hearth.organizations.enabled')) { - return $this->markTestSkipped('Organization support is not enabled.'); - } - - $organization = Organization::factory()->create(); - - $organization->setTranslation('name', 'en', 'Name in English'); - $organization->setTranslation('name', 'fr', 'Name in French'); - - expect($organization->name)->toEqual('Name in English'); - App::setLocale('fr'); - expect($organization->name)->toEqual('Name in French'); - - expect($organization->getTranslation('name', 'en'))->toEqual('Name in English'); - expect($organization->getTranslation('name', 'fr'))->toEqual('Name in French'); - - $translations = ['en' => 'Name in English', 'fr' => 'Name in French']; - - expect($organization->getTranslations('name'))->toEqual($translations); - - $this->expectException(AttributeIsNotTranslatable::class); - $organization->setTranslation('locality', 'en', 'Locality in English'); - - $user = User::factory()->create(); - - $response = $this->actingAs($user)->get('/en/organizations/name-in-english'); - $response->assertOk(); - - $response = $this->actingAs($user)->get('/fr/organizations/name-in-french'); - $response->assertOk(); -}); - -test('users with admin role can update other member roles', function () { - if (! config('hearth.organizations.enabled')) { - return $this->markTestSkipped('Organization support is not enabled.'); - } - - $user = User::factory()->create(); - $other_user = User::factory()->create(); - - $organization = Organization::factory() - ->hasAttached($user, ['role' => 'admin']) - ->hasAttached($other_user, ['role' => 'member']) - ->create(); - - $membership = Membership::where('user_id', $other_user->id) - ->where('membershipable_type', 'App\Models\Organization') - ->where('membershipable_id', $organization->id) - ->first(); - - $response = $this - ->actingAs($user) - ->from(localized_route('memberships.edit', $membership)) - ->put(localized_route('memberships.update', $membership), [ - 'role' => 'admin', - ]); - $response->assertRedirect(localized_route('organizations.edit', $organization)); -}); - -test('users without admin role can not update member roles', function () { - if (! config('hearth.organizations.enabled')) { - return $this->markTestSkipped('Organization support is not enabled.'); - } - - $user = User::factory()->create(); - - $organization = Organization::factory() - ->hasAttached($user, ['role' => 'member']) - ->create(); - - $membership = Membership::where('user_id', $user->id) - ->where('membershipable_type', 'App\Models\Organization') - ->where('membershipable_id', $organization->id) - ->first(); - - $response = $this - ->actingAs($user) - ->from(localized_route('memberships.edit', $membership)) - ->put(localized_route('memberships.update', $membership), [ - 'role' => 'admin', - ]); - - $response->assertForbidden(); -}); - -test('only administrator can not downgrade their role', function () { - if (! config('hearth.organizations.enabled')) { - return $this->markTestSkipped('Organization support is not enabled.'); - } - - $user = User::factory()->create(); - $other_user = User::factory()->create(); - $yet_another_user = User::factory()->create(); - - $organization = Organization::factory() - ->hasAttached($user, ['role' => 'admin']) - ->hasAttached($other_user, ['role' => 'admin']) - ->hasAttached($yet_another_user, ['role' => 'member']) - ->create(); - - $membership = Membership::where('user_id', $user->id) - ->where('membershipable_type', 'App\Models\Organization') - ->where('membershipable_id', $organization->id) - ->first(); - - $response = $this - ->actingAs($user) - ->from(localized_route('memberships.edit', $membership)) - ->put(localized_route('memberships.update', $membership), [ - 'role' => 'member', - ]); - - $response->assertSessionHasNoErrors(); - $response->assertRedirect(localized_route('organizations.show', $organization)); - - $membership = Membership::where('user_id', $other_user->id) - ->where('membershipable_type', 'App\Models\Organization') - ->where('membershipable_id', $organization->id) - ->first(); - - $response = $this - ->actingAs($other_user) - ->from(localized_route('memberships.edit', $membership)) - ->put(localized_route('memberships.update', $membership), [ - 'role' => 'member', - ]); - - $response->assertSessionHasErrors(['role']); - $response->assertRedirect(localized_route('memberships.edit', $membership)); -}); - -test('users with admin role can invite members', function () { - if (! config('hearth.organizations.enabled')) { - return $this->markTestSkipped('Organization support is not enabled.'); - } - - $user = User::factory()->create(); - - $organization = Organization::factory() - ->hasAttached($user, ['role' => 'admin']) - ->create(); - - $response = $this - ->actingAs($user) - ->from(localized_route('organizations.edit', ['organization' => $organization])) - ->post(localized_route('invitations.create'), [ - 'invitationable_id' => $organization->id, - 'invitationable_type' => get_class($organization), - 'email' => 'newuser@here.com', - 'role' => 'member', - ]); - - $response->assertRedirect(localized_route('organizations.edit', $organization)); -}); - -test('users without admin role can not invite members', function () { - if (! config('hearth.organizations.enabled')) { - return $this->markTestSkipped('Organization support is not enabled.'); - } - - $user = User::factory()->create(); - - $organization = Organization::factory() - ->hasAttached($user, ['role' => 'member']) - ->create(); - - $response = $this - ->actingAs($user) - ->from(localized_route('organizations.edit', ['organization' => $organization])) - ->post(localized_route('invitations.create'), [ - 'invitationable_id' => $organization->id, - 'invitationable_type' => get_class($organization), - 'email' => 'newuser@here.com', - 'role' => 'member', - ]); - - $response->assertForbidden(); -}); - -test('users with admin role can cancel invitations', function () { - if (! config('hearth.organizations.enabled')) { - return $this->markTestSkipped('Organization support is not enabled.'); - } - - $user = User::factory()->create(); - $organization = Organization::factory() - ->hasAttached($user, ['role' => 'admin']) - ->create(); - $invitation = Invitation::factory()->create([ - 'invitationable_id' => $organization->id, - 'invitationable_type' => get_class($organization), - 'email' => 'me@here.com', - ]); - - $response = $this - ->actingAs($user) - ->from(localized_route('organizations.edit', ['organization' => $organization])) - ->delete(route('invitations.destroy', ['invitation' => $invitation])); - - $response->assertSessionHasNoErrors(); - $response->assertRedirect(localized_route('organizations.edit', $organization)); -}); - -test('users without admin role can not cancel invitations', function () { - if (! config('hearth.organizations.enabled')) { - return $this->markTestSkipped('Organization support is not enabled.'); - } - - $user = User::factory()->create(); - $organization = Organization::factory() - ->hasAttached($user, ['role' => 'member']) - ->create(); - $invitation = Invitation::factory()->create([ - 'invitationable_id' => $organization->id, - 'invitationable_type' => get_class($organization), - 'email' => 'me@here.com', - ]); - - $response = $this - ->actingAs($user) - ->from(localized_route('organizations.edit', ['organization' => $organization])) - ->delete(route('invitations.destroy', ['invitation' => $invitation])); - - $response->assertForbidden(); -}); - -test('existing members cannot be invited', function () { - if (! config('hearth.organizations.enabled')) { - return $this->markTestSkipped('Organization support is not enabled.'); - } - - $user = User::factory()->create(); - $other_user = User::factory()->create(); - - $organization = Organization::factory() - ->hasAttached($user, ['role' => 'admin']) - ->hasAttached($other_user, ['role' => 'member']) - ->create(); - - $response = $this - ->actingAs($user) - ->from(localized_route('organizations.edit', ['organization' => $organization])) - ->post(localized_route('invitations.create'), [ - 'invitationable_id' => $organization->id, - 'invitationable_type' => get_class($organization), - 'email' => $other_user->email, - 'role' => 'member', - ]); - - $response->assertSessionHasErrorsIn('inviteMember', ['email']); - $response->assertRedirect(localized_route('organizations.edit', $organization)); -}); - -test('invitation can be accepted', function () { - if (! config('hearth.organizations.enabled')) { - return $this->markTestSkipped('Organization support is not enabled.'); - } - - $user = User::factory()->create(); - $organization = Organization::factory()->create(); - $invitation = Invitation::factory()->create([ - 'invitationable_id' => $organization->id, - 'invitationable_type' => get_class($organization), - 'email' => $user->email, - ]); - - $acceptUrl = URL::signedRoute('invitations.accept', ['invitation' => $invitation]); - - $response = $this->actingAs($user)->get($acceptUrl); - - expect($organization->fresh()->hasUserWithEmail($user->email))->toBeTrue(); - $response->assertRedirect(localized_route('organizations.show', $organization)); -}); - -test('invitation cannot be accepted by user with existing membership', function () { - if (! config('hearth.organizations.enabled')) { - return $this->markTestSkipped('Organization support is not enabled.'); - } - - $user = User::factory()->create(); - $organization = Organization::factory() - ->hasAttached($user, ['role' => 'admin']) - ->create(); - $other_organization = Organization::factory()->create(); - $invitation = Invitation::factory()->create([ - 'invitationable_id' => $other_organization->id, - 'invitationable_type' => get_class($other_organization), - 'email' => $user->email, - ]); - - $acceptUrl = URL::signedRoute('invitations.accept', ['invitation' => $invitation]); - - $response = $this->from(localized_route('dashboard'))->actingAs($user)->get($acceptUrl); - - expect($other_organization->fresh()->hasUserWithEmail($user->email))->toBeFalse(); - $response->assertSessionHasErrors(); - $response->assertRedirect(localized_route('dashboard')); -}); - -test('invitation cannot be accepted by different user', function () { - if (! config('hearth.organizations.enabled')) { - return $this->markTestSkipped('Organization support is not enabled.'); - } - - $user = User::factory()->create(); - $other_user = User::factory()->create(); - $organization = Organization::factory() - ->hasAttached($other_user, ['role' => 'admin']) - ->create(); - $invitation = Invitation::factory()->create([ - 'invitationable_id' => $organization->id, - 'invitationable_type' => get_class($organization), - 'email' => $user->email, - ]); - - $acceptUrl = URL::signedRoute('invitations.accept', ['invitation' => $invitation]); - - $response = $this->from(localized_route('dashboard'))->actingAs($other_user)->get($acceptUrl); - - expect($organization->fresh()->hasUserWithEmail($user->email))->toBeFalse(); - $response->assertSessionHasErrors(); - $response->assertRedirect(localized_route('dashboard')); -}); - -test('users with admin role can remove members', function () { - if (! config('hearth.organizations.enabled')) { - return $this->markTestSkipped('Organization support is not enabled.'); - } - - $user = User::factory()->create(); - $other_user = User::factory()->create(); - - $organization = Organization::factory() - ->hasAttached($user, ['role' => 'admin']) - ->hasAttached($other_user, ['role' => 'member']) - ->create(); - - $membership = Membership::where('user_id', $other_user->id) - ->where('membershipable_type', 'App\Models\Organization') - ->where('membershipable_id', $organization->id) - ->first(); - - $response = $this - ->actingAs($user) - ->from(localized_route('organizations.edit', ['organization' => $organization])) - ->delete(route('memberships.destroy', $membership)); - - $response->assertSessionHasNoErrors(); - $response->assertRedirect(localized_route('organizations.edit', $organization)); -}); - -test('users without admin role can not remove members', function () { - if (! config('hearth.organizations.enabled')) { - return $this->markTestSkipped('Organization support is not enabled.'); - } - - $user = User::factory()->create(); - $other_user = User::factory()->create(); - - $organization = Organization::factory() - ->hasAttached($user, ['role' => 'member']) - ->hasAttached($other_user, ['role' => 'admin']) - ->create(); - - $membership = Membership::where('user_id', $other_user->id) - ->where('membershipable_type', 'App\Models\Organization') - ->where('membershipable_id', $organization->id) - ->first(); - - $response = $this - ->actingAs($user) - ->from(localized_route('organizations.edit', ['organization' => $organization])) - ->delete(route('memberships.destroy', $membership)); - - $response->assertForbidden(); -}); - -test('only administrator can not remove themself', function () { - if (! config('hearth.organizations.enabled')) { - return $this->markTestSkipped('Organization support is not enabled.'); - } - - $user = User::factory()->create(); - - $organization = Organization::factory() - ->hasAttached($user, ['role' => 'admin']) - ->create(); - - $membership = Membership::where('user_id', $user->id) - ->where('membershipable_type', 'App\Models\Organization') - ->where('membershipable_id', $organization->id) - ->first(); - - $response = $this - ->actingAs($user) - ->from(localized_route('organizations.edit', ['organization' => $organization])) - ->delete(route('memberships.destroy', $membership)); - - $response->assertSessionHasErrors(); - $response->assertRedirect(localized_route('organizations.edit', $organization)); -}); - -test('users with admin role can delete organizations', function () { - if (! config('hearth.organizations.enabled')) { - return $this->markTestSkipped('Organization support is not enabled.'); - } - - $user = User::factory()->create(); - $organization = Organization::factory() - ->hasAttached($user, ['role' => 'admin']) - ->create(); - - $response = $this->post(localized_route('login'), [ - 'email' => $user->email, - 'password' => 'password', - ]); - - $response = $this->from(localized_route('organizations.edit', $organization))->delete(localized_route('organizations.destroy', $organization), [ - 'current_password' => 'password', - ]); - - $response->assertRedirect(localized_route('dashboard')); -}); - -test('users with admin role can not delete organizations with wrong password', function () { - if (! config('hearth.organizations.enabled')) { - return $this->markTestSkipped('Organization support is not enabled.'); - } - - $user = User::factory()->create(); - $organization = Organization::factory() - ->hasAttached($user, ['role' => 'admin']) - ->create(); - - $response = $this->post(localized_route('login'), [ - 'email' => $user->email, - 'password' => 'password', - ]); - - $response = $this->from(localized_route('organizations.edit', $organization))->delete(localized_route('organizations.destroy', $organization), [ - 'current_password' => 'wrong_password', - ]); - - $response->assertSessionHasErrors(); - $response->assertRedirect(localized_route('organizations.edit', $organization)); -}); - -test('users without admin role can not delete organizations', function () { - if (! config('hearth.organizations.enabled')) { - return $this->markTestSkipped('Organization support is not enabled.'); - } - - $user = User::factory()->create(); - $organization = Organization::factory() - ->hasAttached($user, ['role' => 'member']) - ->create(); - - $response = $this->post(localized_route('login'), [ - 'email' => $user->email, - 'password' => 'password', - ]); - - $response = $this->from(localized_route('organizations.edit', $organization))->delete(localized_route('organizations.destroy', $organization), [ - 'current_password' => 'password', - ]); - - $response->assertForbidden(); -}); - -test('non members can not delete organizations', function () { - if (! config('hearth.organizations.enabled')) { - return $this->markTestSkipped('Organization support is not enabled.'); - } - - $user = User::factory()->create(); - $other_user = User::factory()->create(); - - $organization = Organization::factory() - ->hasAttached($user, ['role' => 'admin']) - ->create(); - - $other_organization = Organization::factory() - ->hasAttached($other_user, ['role' => 'admin']) - ->create(); - - $response = $this->post(localized_route('login'), [ - 'email' => $user->email, - 'password' => 'password', - ]); - - $response = $this->from(localized_route('organizations.edit', $other_organization))->delete(localized_route('organizations.destroy', $other_organization), [ - 'current_password' => 'password', - ]); - - $response->assertForbidden(); -}); - -test('users can view organizations', function () { - if (! config('hearth.organizations.enabled')) { - return $this->markTestSkipped('Organization support is not enabled.'); - } - - $user = User::factory()->create(); - $organization = Organization::factory()->create(); - - $response = $this->post(localized_route('login'), [ - 'email' => $user->email, - 'password' => 'password', - ]); - - $response = $this->get(localized_route('organizations.index')); - $response->assertOk(); - - $response = $this->get(localized_route('organizations.show', $organization)); - $response->assertOk(); -}); - -test('guests can not view organizations', function () { - if (! config('hearth.organizations.enabled')) { - return $this->markTestSkipped('Organization support is not enabled.'); - } - - $organization = Organization::factory()->create(); - - $response = $this->get(localized_route('organizations.index')); - $response->assertRedirect(localized_route('login')); - - $response = $this->get(localized_route('organizations.show', $organization)); - $response->assertRedirect(localized_route('login')); -}); diff --git a/stubs/tests/Feature/PasswordChangeTest.php b/stubs/tests/Feature/PasswordChangeTest.php deleted file mode 100644 index 4499d381..00000000 --- a/stubs/tests/Feature/PasswordChangeTest.php +++ /dev/null @@ -1,42 +0,0 @@ -create(); - - $response = $this->from(localized_route('users.admin'))->actingAs($user)->put(localized_route('user-password.update'), [ - 'current_password' => 'password', - 'password' => 'new_password', - 'password_confirmation' => 'new_password', - ]); - - $response->assertRedirect(localized_route('users.admin')); -}); - -test('password cannot be updated with incorrect current password', function () { - $user = User::factory()->create(); - - $response = $this->from(localized_route('users.admin'))->actingAs($user)->put(localized_route('user-password.update'), [ - 'current_password' => 'wrong_password', - 'password' => 'new_password', - 'password_confirmation' => 'new_password', - ]); - - $response->assertRedirect(localized_route('users.admin')); -}); - -test('password cannot be updated with password that do not match', function () { - $user = User::factory()->create(); - - $response = $this->from(localized_route('users.admin'))->actingAs($user)->put(localized_route('user-password.update'), [ - 'current_password' => 'password', - 'password' => 'new_password', - 'password_confirmation' => 'different_new_password', - ]); - - $response->assertRedirect(localized_route('users.admin')); -}); diff --git a/stubs/tests/Feature/PasswordConfirmationTest.php b/stubs/tests/Feature/PasswordConfirmationTest.php deleted file mode 100644 index 637d2c5d..00000000 --- a/stubs/tests/Feature/PasswordConfirmationTest.php +++ /dev/null @@ -1,35 +0,0 @@ -create(); - - $response = $this->actingAs($user)->get(localized_route('password.confirm')); - - $response->assertOk(); -}); - -test('password can be confirmed', function () { - $user = User::factory()->create(); - - $response = $this->actingAs($user)->post(localized_route('password.confirm'), [ - 'password' => 'password', - ]); - - $response->assertRedirect(); - $response->assertSessionHasNoErrors(); -}); - -test('password is not confirmed with invalid password', function () { - $user = User::factory()->create(); - - $response = $this->actingAs($user)->post(localized_route('password.confirm'), [ - 'password' => 'wrong-password', - ]); - - $response->assertSessionHasErrors(); -}); diff --git a/stubs/tests/Feature/PasswordResetTest.php b/stubs/tests/Feature/PasswordResetTest.php deleted file mode 100644 index 3357d6fb..00000000 --- a/stubs/tests/Feature/PasswordResetTest.php +++ /dev/null @@ -1,60 +0,0 @@ -get(localized_route('password.request')); - - $response->assertOk(); -}); - -test('reset password link can be requested', function () { - Notification::fake(); - - $user = User::factory()->create(); - - $this->post(route('password.email'), ['email' => $user->email]); - - Notification::assertSentTo($user, ResetPassword::class); -}); - -test('reset password screen can be rendered', function () { - Notification::fake(); - - $user = User::factory()->create(); - - $this->post(route('password.email'), ['email' => $user->email]); - - Notification::assertSentTo($user, ResetPassword::class, function ($notification) { - $response = $this->get(route('password.reset', $notification->token)); - - $response->assertOk(); - - return true; - }); -}); - -test('password can be reset with valid token', function () { - Notification::fake(); - - $user = User::factory()->create(); - - $this->post(route('password.email'), ['email' => $user->email]); - - Notification::assertSentTo($user, ResetPassword::class, function ($notification) use ($user) { - $response = $this->post(route('password.reset', ['token' => $notification->token]), [ - 'email' => $user->email, - 'password' => 'password', - 'password_confirmation' => 'password', - ]); - - $response->assertSessionHasNoErrors(); - - return true; - }); -}); diff --git a/stubs/tests/Feature/RegistrationTest.php b/stubs/tests/Feature/RegistrationTest.php deleted file mode 100644 index 805d644f..00000000 --- a/stubs/tests/Feature/RegistrationTest.php +++ /dev/null @@ -1,24 +0,0 @@ -get(localized_route('register')); - - $response->assertOk(); -}); - -test('new users can register', function () { - $response = $this->post(localized_route('register'), [ - 'name' => 'Test User', - 'email' => 'test@example.com', - 'password' => 'password', - 'password_confirmation' => 'password', - 'locale' => 'en', - ]); - - $this->assertAuthenticated(); - $response->assertRedirect(localized_route('dashboard')); -}); diff --git a/stubs/tests/Feature/ResourceCollectionTest.php b/stubs/tests/Feature/ResourceCollectionTest.php deleted file mode 100644 index 534e2fae..00000000 --- a/stubs/tests/Feature/ResourceCollectionTest.php +++ /dev/null @@ -1,356 +0,0 @@ -markTestSkipped('Resource support is not enabled.'); - } - - $user = User::factory()->create(); - - $response = $this->actingAs($user)->get(localized_route('resource-collections.create')); - $response->assertOk(); - - $response = $this->actingAs($user)->post(localized_route('resource-collections.store', []), [ - 'user_id' => $user->id, - 'title' => 'Test resource collection', - 'description' => 'This is my resource collection.', - 'resource_ids' => [], - ]); - - $resourceCollection = ResourceCollection::where('title->en', 'Test resource collection')->first(); - - $url = localized_route('resource-collections.show', $resourceCollection); - - $response->assertSessionHasNoErrors(); - - $response->assertRedirect($url); -}); - -test('users can add resources to their new resource collection on create', function () { - if (! config('hearth.resources.enabled')) { - return $this->markTestSkipped('Resource support is not enabled.'); - } - - $user = User::factory()->create(); - $resources = Resource::factory(5)->create(); - - $response = $this->actingAs($user)->post(localized_route('resource-collections.store'), [ - 'user_id' => $user->id, - 'title' => 'unique title', - 'description' => 'This is my resource collection', - 'resource_ids' => $resources->modelKeys(), - ]); - $response->assertSessionHasNoErrors(); - - $resourceCollection = ResourceCollection::first(); - - $response->assertRedirect(localized_route('resource-collections.show', ['resourceCollection' => $resourceCollection])); -}); - -test('users can edit resource collections belonging to them', function () { - if (! config('hearth.resources.enabled')) { - return $this->markTestSkipped('Resource support is not enabled.'); - } - - $user = User::factory()->create(); - $resourceCollection = ResourceCollection::factory()->create(['user_id' => $user->id]); - - $response = $this->actingAs($user)->get(localized_route('resource-collections.edit', $resourceCollection)); - $response->assertOk(); - - $response = $this->actingAs($user)->put(localized_route('resource-collections.update', $resourceCollection), [ - 'title' => $resourceCollection->title, - 'description' => 'This is my updated resource collection.', - ]); - $response->assertRedirect(localized_route('resource-collections.show', $resourceCollection)); -}); - -test('users can not edit resources belonging to others', function () { - if (! config('hearth.resources.enabled')) { - return $this->markTestSkipped('Resource support is not enabled.'); - } - - $user = User::factory()->create(); - $resourceCollection = ResourceCollection::factory()->create(); - - $response = $this->actingAs($user)->get(localized_route('resource-collections.edit', $resourceCollection)); - $response->assertForbidden(); - - $response = $this->actingAs($user)->put(localized_route('resource-collections.update', $resourceCollection), [ - 'title' => $resourceCollection->title, - 'description' => 'This is my updated resource collection.', - ]); - $response->assertForbidden(); -}); - -test('users can delete resource collections belonging to them', function () { - if (! config('hearth.resources.enabled')) { - return $this->markTestSkipped('Resource support is not enabled.'); - } - - $user = User::factory()->create(); - $resourceCollection = ResourceCollection::factory()->create(['user_id' => $user->id]); - - $response = $this->actingAs($user)->from(localized_route('resource-collections.edit', $resourceCollection))->delete(localized_route('resource-collections.destroy', $resourceCollection), [ - 'current_password' => 'password', - ]); - - $response->assertRedirect(localized_route('dashboard')); -}); - -test('users can not delete resource collections belonging to them with wrong password', function () { - if (! config('hearth.resources.enabled')) { - return $this->markTestSkipped('Resource support is not enabled.'); - } - - $user = User::factory()->create(); - $resourceCollection = ResourceCollection::factory()->create(['user_id' => $user->id]); - - $response = $this->actingAs($user)->from(localized_route('resource-collections.edit', $resourceCollection))->delete(localized_route('resource-collections.destroy', $resourceCollection), [ - 'current_password' => 'wrong_password', - ]); - - $response->assertSessionHasErrors(); - $response->assertRedirect(localized_route('resource-collections.edit', $resourceCollection)); -}); - -test('users can not delete resource collections belonging to others', function () { - if (! config('hearth.resources.enabled')) { - return $this->markTestSkipped('Resource support is not enabled.'); - } - - $user = User::factory()->create(); - $resourceCollection = ResourceCollection::factory()->create(); - - $response = $this->actingAs($user)->from(localized_route('resource-collections.edit', $resourceCollection))->delete(localized_route('resource-collections.destroy', $resourceCollection), [ - 'current_password' => 'password', - ]); - - $response->assertForbidden(); -}); - -test('resource collections can have unique title for each locale', function () { - if (! config('hearth.resources.enabled')) { - return $this->markTestSkipped('Resource support is not enabled'); - } - - $user = User::factory()->create(); - - $response = $this->actingAs($user)->post(localized_route('resource-collections.store'), [ - 'user_id' => $user->id, - 'title' => 'unique title', - 'description' => 'This is my resource collection', - ]); - - $response = $this->actingAs($user)->post(localized_route('resource-collections.store'), [ - 'user_id' => $user->id, - 'title' => 'unique title', - 'description' => 'This is my resource collection', - ]); - - $response->assertSessionHasErrors(['title' => 'The title has already been taken.']); - - App::setLocale('fr'); - - $response = $this->actingAs($user)->post(localized_route('resource-collections.store'), [ - 'user_id' => $user->id, - 'title' => 'unique title', - 'description' => 'This is my resource collection', - ]); - - $response->assertSessionHasNoErrors(); -}); - -test('create resource collection validation', function () { - if (! config('hearth.resources.enabled')) { - return $this->markTestSkipped('Resource support is not enabled'); - } - - $user = User::factory()->create(); - - $response = $this->actingAs($user)->post(localized_route('resource-collections.store'), [ - 'user_id' => $user->id, - 'title' => 'Test resource collection', - ]); - - $response->assertSessionHasErrors(['description' => 'The description field is required.']); - - $response = $this->actingAs($user)->post(localized_route('resource-collections.store'), [ - 'user_id' => $user->id, - 'title' => 'Test resource collection', - 'description' => 1, - ]); - - $response->assertSessionHasErrors(['description' => 'The description must be a string.']); - - $response = $this->actingAs($user)->post(localized_route('resource-collections.store'), [ - 'user_id' => $user->id, - 'description' => 'This is my resource collection', - ]); - - $response->assertSessionHasErrors(['title' => 'The title field is required.']); - - $lengthyTitle = ''; - - for ($i = 0; $i <= 256; $i++) { - $lengthyTitle = $lengthyTitle.'a'; - } - - $response = $this->actingAs($user)->post(localized_route('resource-collections.store'), [ - 'user_id' => $user->id, - 'title' => $lengthyTitle, - 'description' => 'This is my resource collection', - ]); - - $response->assertSessionHasErrors(['title' => 'The title must not be greater than 255 characters.']); - - $response = $this->actingAs($user)->post(localized_route('resource-collections.store'), [ - 'user_id' => $user->id, - 'title' => 1, - 'description' => 'This is my resource collection', - ]); - - $response->assertSessionHasErrors(['title' => 'The title must be a string.']); -}); - -test('update resource collection validation', function () { - if (! config('hearth.resources.enabled')) { - return $this->markTestSkipped('Resource support is not enabled'); - } - - $user = User::factory()->create(); - $resourceCollection = ResourceCollection::factory()->create(['user_id' => $user->id]); - - $response = $this->actingAs($user)->put(localized_route('resource-collections.update', $resourceCollection), [ - 'title' => $resourceCollection->title, - ]); - - $response->assertSessionHasErrors(['description' => 'The description field is required.']); - - $response = $this->actingAs($user)->put(localized_route('resource-collections.update', $resourceCollection), [ - 'title' => $resourceCollection->title, - 'description' => 1, - ]); - - $response->assertSessionHasErrors(['description' => 'The description must be a string.']); - - $response = $this->actingAs($user)->put(localized_route('resource-collections.update', $resourceCollection), [ - 'description' => 'This is my updated resource collection.', - ]); - - $response->assertSessionHasErrors(['title' => 'The title field is required.']); - - $lengthyTitle = ''; - - for ($i = 0; $i <= 256; $i++) { - $lengthyTitle = $lengthyTitle.'a'; - } - - $response = $this->actingAs($user)->put(localized_route('resource-collections.update', $resourceCollection), [ - 'title' => $lengthyTitle, - 'description' => 'This is my updated resource collection.', - ]); - - $response->assertSessionHasErrors(['title' => 'The title must not be greater than 255 characters.']); - - $response = $this->actingAs($user)->put(localized_route('resource-collections.update', $resourceCollection), [ - 'title' => 1, - 'description' => 'This is my updated resource collection.', - ]); - - $response->assertSessionHasErrors(['title' => 'The title must be a string.']); -}); - -test('resource collections can be translated', function () { - if (! config('hearth.resources.enabled')) { - return $this->markTestSkipped('Resource support is not enabled.'); - } - - $resourceCollection = ResourceCollection::factory()->create(); - - $titleTranslations = ['en' => 'title in English', 'fr' => 'title in French']; - $descriptionTranslations = ['en' => 'description in English', 'fr' => 'description in French']; - - $resourceCollection->setTranslation('title', 'en', $titleTranslations['en']); - $resourceCollection->setTranslation('title', 'fr', $titleTranslations['fr']); - - $resourceCollection->setTranslation('description', 'en', $descriptionTranslations['en']); - $resourceCollection->setTranslation('description', 'fr', $descriptionTranslations['fr']); - - expect($resourceCollection->title)->toEqual($titleTranslations['en']); - expect($resourceCollection->description)->toEqual($descriptionTranslations['en']); - App::setLocale('fr'); - expect($resourceCollection->title)->toEqual($titleTranslations['fr']); - expect($resourceCollection->description)->toEqual($descriptionTranslations['fr']); - - expect($resourceCollection->getTranslation('title', 'en'))->toEqual($titleTranslations['en']); - expect($resourceCollection->getTranslation('description', 'en'))->toEqual($descriptionTranslations['en']); - expect($resourceCollection->getTranslation('title', 'fr'))->toEqual($titleTranslations['fr']); - expect($resourceCollection->getTranslation('description', 'fr'))->toEqual($descriptionTranslations['fr']); - - expect($resourceCollection->getTranslations('title'))->toEqual($titleTranslations); - expect($resourceCollection->getTranslations('description'))->toEqual($descriptionTranslations); - - $this->expectException(AttributeIsNotTranslatable::class); - $resourceCollection->setTranslation('user_id', 'en', 'user_id in English'); -}); - -test('resource collections belong to user get deleted on user delete', function () { - $resourceCollection = ResourceCollection::factory()->create(); - - $resourceCollection->user->delete(); - $this->assertModelMissing($resourceCollection); -}); - -test('single user can have multiple resource collections', function () { - $user = User::factory()->create(); - $resourceCollection = ResourceCollection::factory(5) - ->for($user) - ->create(); - expect($user->resourceCollections()->get())->toHaveCount(5); -}); - -test('many resources can belong in single resource collection', function () { - $resourceCollection = ResourceCollection::factory()->create(); - - $resources = Resource::factory(3)->create(); - - foreach ($resources as $resource) { - $resourceCollection->resources()->sync($resource->id); - $this->assertDatabaseHas('resource_resource_collection', [ - 'resource_collection_id' => $resourceCollection->id, - 'resource_id' => $resource->id, - ]); - } -}); - -test('deleting resource belong to resource collection', function () { - $resourceCollection = ResourceCollection::factory()->create(); - $resource = Resource::factory()->create(); - $resourceCollection->resources()->sync($resource->id); - - $this->assertDatabaseHas('resources', [ - 'id' => $resource->id, - ]); - - $this->assertDatabaseHas('resource_resource_collection', [ - 'resource_collection_id' => $resourceCollection->id, - 'resource_id' => $resource->id, - ]); - - $resource->delete(); - - $this->assertDatabaseMissing('resource_resource_collection', [ - 'resource_collection_id' => $resourceCollection->id, - 'resource_id' => $resource->id, - ]); -}); diff --git a/stubs/tests/Feature/ResourceSelectTest.php b/stubs/tests/Feature/ResourceSelectTest.php deleted file mode 100644 index b9e0eb22..00000000 --- a/stubs/tests/Feature/ResourceSelectTest.php +++ /dev/null @@ -1,103 +0,0 @@ -markTestSkipped('Resource support is not enabled.'); - } - - $resources = Resource::factory(5)->create(); - $resourceSelect = Livewire::test(ResourceSelect::class, ['resourceCollectionId' => null]); - expect(5)->toEqual(count($resourceSelect->availableResources)); - expect(0)->toEqual(count($resourceSelect->selectedResources)); - - $resourceIds = []; - foreach ($resources as $resource) { - $resourceIds[] = $resource->id; - } - foreach ($resourceSelect->availableResources as $availableResource) { - expect(in_array($availableResource['id'], $resourceIds, true))->toBeTrue(); - } -}); - -test('resource select when resource collection id parameter is not null', function () { - if (! config('hearth.resources.enabled')) { - return $this->markTestSkipped('Resource support is not enabled.'); - } - - $resourceCollection = ResourceCollection::factory()->create(); - $selectedResources = Resource::factory(5)->create(); - $resourceCollection->resources()->attach($selectedResources); - - $availableResources = Resource::factory(3)->create(); - $resourceSelect = Livewire::test(ResourceSelect::class, ['resourceCollectionId' => $resourceCollection->id]); - expect(3)->toEqual(count($resourceSelect->availableResources)); - expect(5)->toEqual(count($resourceSelect->selectedResources)); - - $selectedResourceIds = []; - foreach ($selectedResources as $selectedResource) { - $selectedResourceIds[] = $selectedResource->id; - } - foreach ($resourceSelect->selectedResources as $selectedResource) { - expect(in_array($selectedResource['id'], $selectedResourceIds, true))->toBeTrue(); - } - - $availableResourceIds = []; - foreach ($availableResources as $availableResource) { - $availableResourceIds[] = $availableResource->id; - } - foreach ($resourceSelect->availableResources as $availableResource) { - expect(in_array($availableResource['id'], $availableResourceIds, true))->toBeTrue(); - } -}); - -test('add resource', function () { - if (! config('hearth.resources.enabled')) { - return $this->markTestSkipped('Resource support is not enabled.'); - } - - $resources = Resource::factory(5)->create(); - $resourceSelect = Livewire::test(ResourceSelect::class, ['resourceCollectionId' => null]); - $sampleAvailableResource = $resourceSelect->availableResources->first(); - - expect(5)->toEqual(count($resourceSelect->availableResources)); - expect(0)->toEqual(count($resourceSelect->selectedResources)); - - $resourceSelect->call('addResource', $sampleAvailableResource->id); - - expect($resourceSelect->selectedResources->pluck('id')->toArray())->toContain($sampleAvailableResource->id); - - expect(4)->toEqual(count($resourceSelect->availableResources)); - expect(1)->toEqual(count($resourceSelect->selectedResources)); -}); - -test('remove resource', function () { - if (! config('hearth.resources.enabled')) { - return $this->markTestSkipped('Resource support is not enabled.'); - } - - $resourceCollection = ResourceCollection::factory()->create(); - $selectedResources = Resource::factory(5)->create(); - $resourceCollection->resources()->attach($selectedResources); - - $availableResources = Resource::factory(3)->create(); - $resourceSelect = Livewire::test(ResourceSelect::class, ['resourceCollectionId' => $resourceCollection->id]); - $sampleSelectedResource = $resourceSelect->selectedResources->first(); - - expect(3)->toEqual(count($resourceSelect->availableResources)); - expect(5)->toEqual(count($resourceSelect->selectedResources)); - - $resourceSelect->call('removeResource', $sampleSelectedResource->id); - - expect($resourceSelect->availableResources->pluck('id')->toArray())->toContain($sampleSelectedResource->id); - - expect(4)->toEqual(count($resourceSelect->availableResources)); - expect(4)->toEqual(count($resourceSelect->selectedResources)); -}); diff --git a/stubs/tests/Feature/ResourceTest.php b/stubs/tests/Feature/ResourceTest.php deleted file mode 100644 index 9b6f06a1..00000000 --- a/stubs/tests/Feature/ResourceTest.php +++ /dev/null @@ -1,186 +0,0 @@ -markTestSkipped('Resource support is not enabled.'); - } - - $user = User::factory()->create(); - - $response = $this->actingAs($user)->get(localized_route('resources.create')); - $response->assertOk(); - - $response = $this->actingAs($user)->post(localized_route('resources.create'), [ - 'user_id' => $user->id, - 'title' => 'Test resource', - 'summary' => 'This is my resource.', - ]); - - $resource = Resource::where('title->en', 'Test resource')->first(); - - $url = localized_route('resources.show', $resource); - - $response->assertSessionHasNoErrors(); - - $response->assertRedirect($url); -}); - -test('users can edit resources belonging to them', function () { - if (! config('hearth.resources.enabled')) { - return $this->markTestSkipped('Resource support is not enabled.'); - } - - $user = User::factory()->create(); - $resource = Resource::factory()->create(['user_id' => $user->id]); - - $response = $this->actingAs($user)->get(localized_route('resources.edit', $resource)); - $response->assertOk(); - - $response = $this->actingAs($user)->put(localized_route('resources.update', $resource), [ - 'title' => $resource->title, - 'summary' => 'This is my updated resource.', - ]); - $response->assertRedirect(localized_route('resources.show', $resource)); -}); - -test('resources can be translated', function () { - if (! config('hearth.resources.enabled')) { - return $this->markTestSkipped('Resource support is not enabled.'); - } - - $resource = Resource::factory()->create(); - - $resource->setTranslation('title', 'en', 'title in English'); - $resource->setTranslation('title', 'fr', 'title in French'); - - expect($resource->title)->toEqual('title in English'); - App::setLocale('fr'); - expect($resource->title)->toEqual('title in French'); - - expect($resource->getTranslation('title', 'en'))->toEqual('title in English'); - expect($resource->getTranslation('title', 'fr'))->toEqual('title in French'); - - $translations = ['en' => 'title in English', 'fr' => 'title in French']; - - expect($resource->getTranslations('title'))->toEqual($translations); - - $this->expectException(AttributeIsNotTranslatable::class); - $resource->setTranslation('user_id', 'en', 'user_id in English'); - - $user = User::factory()->create(); - - $response = $this->actingAs($user)->get('/en/resources/title-in-english'); - $response->assertOk(); - - $response = $this->actingAs($user)->get('/fr/resources/title-in-french'); - $response->assertOk(); -}); - -test('users can not edit resources belonging to others', function () { - if (! config('hearth.resources.enabled')) { - return $this->markTestSkipped('Resource support is not enabled.'); - } - - $user = User::factory()->create(); - $resource = Resource::factory()->create(); - - $response = $this->actingAs($user)->get(localized_route('resources.edit', $resource)); - $response->assertForbidden(); - - $response = $this->actingAs($user)->put(localized_route('resources.update', $resource), [ - 'title' => $resource->title, - 'summary' => 'This is my updated resource.', - ]); - $response->assertForbidden(); -}); - -test('users can delete resources belonging to them', function () { - if (! config('hearth.resources.enabled')) { - return $this->markTestSkipped('Resource support is not enabled.'); - } - - $user = User::factory()->create(); - $resource = Resource::factory()->create(['user_id' => $user->id]); - - $response = $this->actingAs($user)->from(localized_route('resources.edit', $resource))->delete(localized_route('resources.destroy', $resource), [ - 'current_password' => 'password', - ]); - - $response->assertRedirect(localized_route('dashboard')); -}); - -test('users can not delete resources belonging to them with wrong password', function () { - if (! config('hearth.resources.enabled')) { - return $this->markTestSkipped('Resource support is not enabled.'); - } - - $user = User::factory()->create(); - $resource = Resource::factory()->create(['user_id' => $user->id]); - - $response = $this->actingAs($user)->from(localized_route('resources.edit', $resource))->delete(localized_route('resources.destroy', $resource), [ - 'current_password' => 'wrong_password', - ]); - - $response->assertSessionHasErrors(); - $response->assertRedirect(localized_route('resources.edit', $resource)); -}); - -test('users can not delete resources belonging to others', function () { - if (! config('hearth.resources.enabled')) { - return $this->markTestSkipped('Resource support is not enabled.'); - } - - $user = User::factory()->create(); - $resource = Resource::factory()->create(); - - $response = $this->actingAs($user)->from(localized_route('resources.edit', $resource))->delete(localized_route('resources.destroy', $resource), [ - 'current_password' => 'password', - ]); - - $response->assertForbidden(); -}); - -test('single resource can be in many resource collections', function () { - $resource = Resource::factory()->create(); - - $resourceCollections = ResourceCollection::factory(3)->create(); - - foreach ($resourceCollections as $resourceCollection) { - $resource->resourceCollections()->sync($resourceCollection->id); - $this->assertDatabaseHas('resource_resource_collection', [ - 'resource_collection_id' => $resourceCollection->id, - 'resource_id' => $resource->id, - ]); - } -}); - -test('deleting resource collection with resource', function () { - $resource = Resource::factory()->create(); - $resourceCollection = ResourceCollection::factory()->create(); - $resource->resourceCollections()->sync($resourceCollection->id); - - $this->assertDatabaseHas('resource_collections', [ - 'id' => $resourceCollection->id, - ]); - - $this->assertDatabaseHas('resource_resource_collection', [ - 'resource_collection_id' => $resourceCollection->id, - 'resource_id' => $resource->id, - ]); - - $resourceCollection->delete(); - - $this->assertDatabaseMissing('resource_resource_collection', [ - 'resource_collection_id' => $resourceCollection->id, - 'resource_id' => $resource->id, - ]); -}); diff --git a/stubs/tests/Feature/TwoFactorAuthenticationTest.php b/stubs/tests/Feature/TwoFactorAuthenticationTest.php deleted file mode 100644 index 93af544b..00000000 --- a/stubs/tests/Feature/TwoFactorAuthenticationTest.php +++ /dev/null @@ -1,152 +0,0 @@ -markTestSkipped('Two-factor authentication support is not enabled.'); - } - - $this->actingAs($user = User::factory()->create()); - - $response = $this->post(route('two-factor.enable')); - - $response->assertRedirect(localized_route('password.confirm')); - - expect($user->twoFactorAuthEnabled())->toBeFalse(); -}); - -test('users who have confirmed password can enable two factor authentication', function () { - if (! Features::enabled(Features::twoFactorAuthentication())) { - return $this->markTestSkipped('Two-factor authentication support is not enabled.'); - } - - $this->actingAs($user = User::factory()->create()); - - $this->withSession(['auth.password_confirmed_at' => time()]); - - $this->post(route('two-factor.enable')); - - expect($user->twoFactorAuthEnabled())->toBeTrue(); -}); - -test('users can authenticate with two factor code', function () { - if (! Features::enabled(Features::twoFactorAuthentication())) { - return $this->markTestSkipped('Two-factor authentication support is not enabled.'); - } - - $this->actingAs($user = User::factory()->create()); - - $this->withSession(['auth.password_confirmed_at' => time()]); - - $this->post(route('two-factor.enable')); - - $this->post(localized_route('logout')); - - $this->assertGuest(); - - $this->post(localized_route('login'), [ - 'email' => $user->email, - 'password' => 'password', - ]); - - $response = $this->post(localized_route('two-factor.login'), [ - 'code' => (new Google2FA)->getCurrentOtp(decrypt($user->two_factor_secret)), - ]); - - $response->assertRedirect(localized_route('dashboard')); - - $this->assertAuthenticated(); -}); - -test('users can not authenticate with invalid two factor code', function () { - if (! Features::enabled(Features::twoFactorAuthentication())) { - return $this->markTestSkipped('Two-factor authentication support is not enabled.'); - } - - $this->actingAs($user = User::factory()->create()); - - $this->withSession(['auth.password_confirmed_at' => time()]); - - $this->post(route('two-factor.enable')); - - $this->post(localized_route('logout')); - - $this->assertGuest(); - - $this->post(localized_route('login'), [ - 'email' => $user->email, - 'password' => 'password', - ]); - - $response = $this->post(localized_route('two-factor.login'), [ - 'code' => '123456', - ]); - - $response->assertRedirect(localized_route('login')); - - $this->assertGuest(); -}); - -test('users can authenticate with recovery code', function () { - if (! Features::enabled(Features::twoFactorAuthentication())) { - return $this->markTestSkipped('Two-factor authentication support is not enabled.'); - } - - $this->actingAs($user = User::factory()->create()); - - $this->withSession(['auth.password_confirmed_at' => time()]); - - $this->post(route('two-factor.enable')); - - $this->post(localized_route('logout')); - - $this->assertGuest(); - - $this->post(localized_route('login'), [ - 'email' => $user->email, - 'password' => 'password', - ]); - - $response = $this->post(localized_route('two-factor.login'), [ - 'recovery_code' => $user->recoveryCodes()[0], - ]); - - $response->assertRedirect(localized_route('dashboard')); - - $this->assertAuthenticated(); -}); - -test('users can not authenticate with invalid recovery code', function () { - if (! Features::enabled(Features::twoFactorAuthentication())) { - return $this->markTestSkipped('Two-factor authentication support is not enabled.'); - } - - $this->actingAs($user = User::factory()->create()); - - $this->withSession(['auth.password_confirmed_at' => time()]); - - $this->post(route('two-factor.enable')); - - $this->post(localized_route('logout')); - - $this->assertGuest(); - - $this->post(localized_route('login'), [ - 'email' => $user->email, - 'password' => 'password', - ]); - - $response = $this->post(localized_route('two-factor.login'), [ - 'recovery_code' => 'fake recovery code', - ]); - - $response->assertRedirect(localized_route('login')); - - $this->assertGuest(); -}); diff --git a/tests/Feature/InvitationTest.php b/tests/Feature/InvitationTest.php deleted file mode 100644 index 4389d46d..00000000 --- a/tests/Feature/InvitationTest.php +++ /dev/null @@ -1,54 +0,0 @@ -toBeInstanceOf(InvitationFactory::class); -}); - -test('invitation can be created for organization', function () { - $user = User::forceCreate([ - 'name' => 'Frodo Baggins', - 'email' => 'frodo@bag-end.net', - 'password' => 'secret', - ]); - - $otherUser = User::forceCreate([ - 'name' => 'Samwise Gamgee', - 'email' => 'sam@bag-end.net', - 'password' => 'secret', - ]); - - $organization = Organization::forceCreate([ - 'name' => json_encode(['en' => 'Fellowship']), - 'locality' => 'Rivendell', - 'region' => 'BC', - ]); - - $invitation = Invitation::forceCreate([ - 'invitationable_id' => $organization->id, - 'invitationable_type' => get_class($organization), - 'email' => $user->email, - 'role' => 'admin', - ]); - - $otherInvitation = Invitation::forceCreate([ - 'invitationable_id' => $organization->id, - 'invitationable_type' => get_class($organization), - 'email' => $otherUser->email, - 'role' => 'member', - ]); - - expect($organization->invitations)->toHaveCount(2); - expect($invitation->invitationable->id)->toEqual($organization->id); - - $invitation->accept(); - $otherInvitation->accept(); - - $organization = $organization->fresh(); - expect($organization->hasAdministratorWithEmail($user->email))->toBeTrue(); - expect($organization->hasUserWithEmail($otherUser->email))->toBeTrue(); -}); diff --git a/tests/Feature/JoinTest.php b/tests/Feature/JoinTest.php deleted file mode 100644 index 5d384b74..00000000 --- a/tests/Feature/JoinTest.php +++ /dev/null @@ -1,23 +0,0 @@ - 'Frodo Baggins', - 'email' => 'frodo@bag-end.net', - 'password' => 'secret', - ]); - - $organization = Organization::forceCreate([ - 'name' => json_encode(['en' => 'Fellowship']), - 'locality' => 'Rivendell', - 'region' => 'BC', - ]); - - $organization->requestsToJoin()->save($user); - - expect($organization->requestsToJoin)->toHaveCount(1); - expect($organization->requestsToJoin->first()->id)->toEqual($user->id); -}); diff --git a/tests/Feature/MembershipTest.php b/tests/Feature/MembershipTest.php deleted file mode 100644 index d685e589..00000000 --- a/tests/Feature/MembershipTest.php +++ /dev/null @@ -1,32 +0,0 @@ - 'Frodo Baggins', - 'email' => 'frodo@bag-end.net', - 'password' => 'secret', - ]); - - $organization = Organization::forceCreate([ - 'name' => json_encode(['en' => 'Fellowship']), - 'locality' => 'Rivendell', - 'region' => 'BC', - ]); - - $organization->users()->attach($user, ['role' => 'admin']); - - $membership = Membership::where('id', $organization->users->first()->membership->id)->first(); - - expect($organization->users)->toHaveCount(1); - expect($organization->administrators)->toHaveCount(1); - expect($organization->hasUserWithEmail($user->email))->toBeTrue(); - expect($organization->hasAdministratorWithEmail($user->email))->toBeTrue(); - expect(get_class($organization))->toEqual($membership->membershipable_type); - expect($organization->id)->toEqual($membership->membershipable_id); - expect($membership->membershipable()->id)->toEqual($organization->id); - expect($membership->user->id)->toEqual($user->id); -}); diff --git a/tests/Feature/TranslatableSlugTest.php b/tests/Feature/TranslatableSlugTest.php deleted file mode 100644 index 41ab86e6..00000000 --- a/tests/Feature/TranslatableSlugTest.php +++ /dev/null @@ -1,34 +0,0 @@ - [ - 'en', 'fr', - ]]); -}); - -test('trans current route uses translated slug', function () { - $translatable = new TranslatableModel; - - $translatable->setTranslation('name', 'en', 'The Fellowship of the Ring'); - $translatable->setTranslation('name', 'fr', 'La communauté de l’anneau'); - - $translatable->save(); - - Route::multilingual( - '/translatables/{translatable}', - function (TranslatableModel $translatable) { - return $translatable->name; - } - ) - ->middleware(DetectRequestLocale::class) - ->name('translatables.show'); - - Route::dispatch(Request::create(localized_route('translatables.show', $translatable))); - - expect(trans_current_route('fr'))->toEqual(localized_route('translatables.show', $translatable, 'fr')); -}); diff --git a/tests/Feature/UserTest.php b/tests/Feature/UserTest.php deleted file mode 100644 index 1b3036aa..00000000 --- a/tests/Feature/UserTest.php +++ /dev/null @@ -1,14 +0,0 @@ - 'Bilbo Baggins', - 'email' => '', - 'password' => 'secret', - ]); - - expect(DB::table('users')->count())->toBe(1); -}); diff --git a/tests/TestCase.php b/tests/TestCase.php index b1144d06..e887a53b 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -3,13 +3,10 @@ namespace Hearth\Tests; use ChinLeung\LaravelLocales\LaravelLocalesServiceProvider; -use ChinLeung\MultilingualRoutes\MultilingualRoutesServiceProvider; use Hearth\HearthServiceProvider; -use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Database\Schema\Blueprint; use Illuminate\Foundation\Testing\Concerns\InteractsWithViews; use Illuminate\Support\Facades\Schema; -use Laravel\Fortify\FortifyServiceProvider; use Orchestra\Testbench\TestCase as Orchestra; class TestCase extends Orchestra @@ -19,19 +16,13 @@ class TestCase extends Orchestra protected function setUp(): void { parent::setUp(); - - Factory::guessFactoryNamesUsing( - fn (string $modelName) => 'Hearth\\Database\\Factories\\'.class_basename($modelName).'Factory' - ); } protected function getPackageProviders($app): array { return [ - FortifyServiceProvider::class, HearthServiceProvider::class, LaravelLocalesServiceProvider::class, - MultilingualRoutesServiceProvider::class, ]; } @@ -45,19 +36,5 @@ public function getEnvironmentSetUp($app) $table->json('name')->nullable(); $table->json('slug')->nullable(); }); - - $create_users_table = include __DIR__.'/../database/migrations/create_users_table.php.stub'; - $update_users_table = include __DIR__.'/../database/migrations/update_users_table.php.stub'; - $create_invitations_table = include __DIR__.'/../database/migrations/2021_03_01_000000_create_invitations_table.php'; - $add_joinable_columns = include __DIR__.'/../database/migrations/2021_03_01_000000_add_joinable_columns_to_users_table.php'; - $create_memberships_table = include __DIR__.'/../database/migrations/2021_03_01_000000_create_memberships_table.php'; - $create_organizations_table = include __DIR__.'/../database/migrations/create_organizations_table.php.stub'; - - $create_users_table->up(); - $update_users_table->up(); - $add_joinable_columns->up(); - $create_invitations_table->up(); - $create_memberships_table->up(); - $create_organizations_table->up(); } } diff --git a/tests/Unit/HelpersTest.php b/tests/Unit/HelpersTest.php index 6ed35103..2d264548 100644 --- a/tests/Unit/HelpersTest.php +++ b/tests/Unit/HelpersTest.php @@ -1,35 +1,6 @@ toEqual('Nova Scotia'); -}); - -test('get region name in alternate locale', function () { - $result = get_region_name('NS', ['CA'], 'fr'); - expect($result)->toEqual('Nouvelle-Écosse'); -}); - -test('get region name returns null for invalid region', function () { - $result = get_region_name('NS', ['US']); - expect($result)->toBeNull(); -}); - -test('get regions in default locale', function () { - $result = get_regions(['CA']); - expect($result)->toContain(['value' => 'NS', 'label' => 'Nova Scotia']); -}); - -test('get regions in alternate locale', function () { - $result = get_regions(['CA'], 'fr'); - expect($result)->toContain(['value' => 'NS', 'label' => 'Nouvelle-Écosse']); -}); - -test('get region codes', function () { - $result = get_region_codes(['CA']); - expect($result)->toContain('NS'); -}); test('get locale name', function () { $result = get_locale_name('fr');