diff --git a/src/App/Providers/AppServiceProvider.php b/src/App/Providers/AppServiceProvider.php index b0579089..32322f07 100644 --- a/src/App/Providers/AppServiceProvider.php +++ b/src/App/Providers/AppServiceProvider.php @@ -46,6 +46,10 @@ class AppServiceProvider extends ServiceProvider private function setSubscriptionConfig(): void { + if (app()->runningUnitTests()) { + return; + } + $settings = getAllSettings(); config([ diff --git a/src/App/Users/Restrictions/Engines/MeteredBillingRestrictionsEngine.php b/src/App/Users/Restrictions/Engines/MeteredBillingRestrictionsEngine.php index 07f594b0..7191b023 100644 --- a/src/App/Users/Restrictions/Engines/MeteredBillingRestrictionsEngine.php +++ b/src/App/Users/Restrictions/Engines/MeteredBillingRestrictionsEngine.php @@ -8,26 +8,46 @@ class MeteredBillingRestrictionsEngine implements RestrictionsEngine { public function canUpload(User $user, int $fileSize = 0): bool { + // Check the count of the dunning emails + if ($this->getDunningSequenceCount($user) === 3) { + return false; + } + // Disable upload when user has more than 3 failed payments - return ! ($user->failedPayments()->count() >= 3); + return $this->checkFailedPayments($user); } public function canDownload(User $user): bool { + // Check the count of the dunning emails + if ($this->getDunningSequenceCount($user) === 3) { + return false; + } + // Disable download when user has more than 3 failed payments - return ! ($user->failedPayments()->count() >= 3); + return $this->checkFailedPayments($user); } public function canCreateFolder(User $user): bool { + // Check the count of the dunning emails + if ($this->getDunningSequenceCount($user) === 3) { + return false; + } + // Disable create folder when user has more than 3 failed payments - return ! ($user->failedPayments()->count() >= 3); + return $this->checkFailedPayments($user); } public function canCreateTeamFolder(User $user): bool { + // Check the count of the dunning emails + if ($this->getDunningSequenceCount($user) === 3) { + return false; + } + // Disable create folder when user has more than 3 failed payments - return ! ($user->failedPayments()->count() >= 3); + return $this->checkFailedPayments($user); } public function canInviteTeamMembers(User $user, array $newInvites = []): bool @@ -37,7 +57,22 @@ class MeteredBillingRestrictionsEngine implements RestrictionsEngine public function canVisitShared(User $user): bool { + // Check the count of the dunning emails + if ($this->getDunningSequenceCount($user) === 3) { + return false; + } + // Disable share visit when user has more than 3 failed payments - return ! ($user->failedPayments()->count() >= 3); + return $this->checkFailedPayments($user); + } + + private function getDunningSequenceCount(User $user): int + { + return cache()->remember("dunning-count.$user->id", 3600, fn () => $user?->dunning->sequence ?? 0); + } + + private function checkFailedPayments(User $user): bool + { + return cache()->remember("failed-payments-count.$user->id", 3600, fn () => !($user->failedPayments()->count() >= 3)); } } diff --git a/tests/App/Restrictions/MeteredBillingRestrictionsTest.php b/tests/App/Restrictions/MeteredBillingRestrictionsTest.php index 0145b01d..c43050d4 100644 --- a/tests/App/Restrictions/MeteredBillingRestrictionsTest.php +++ b/tests/App/Restrictions/MeteredBillingRestrictionsTest.php @@ -1,4 +1,5 @@ 'subscription_type', + 'name' => 'subscription_type', ], [ 'value' => 'metered', ]); @@ -32,6 +34,13 @@ class MeteredBillingRestrictionsTest extends TestCase ->hasFailedpayments(2) ->create(); + Dunning::factory() + ->createOneQuietly([ + 'type' => 'limit_usage_in_new_accounts', + 'user_id' => $user->id, + 'sequence' => 2, + ]); + $this->assertEquals(true, $user->canUpload()); } @@ -47,6 +56,24 @@ class MeteredBillingRestrictionsTest extends TestCase $this->assertEquals(false, $user->canUpload()); } + /** + * @test + */ + public function it_cant_upload_because_user_has_3_dunning_mails() + { + $user = User::factory() + ->create(); + + Dunning::factory() + ->createOneQuietly([ + 'type' => 'limit_usage_in_new_accounts', + 'user_id' => $user->id, + 'sequence' => 3, + ]); + + $this->assertEquals(false, $user->canUpload()); + } + /** * @test */ @@ -117,6 +144,47 @@ class MeteredBillingRestrictionsTest extends TestCase $this->assertDatabaseCount('folders', 0); } + /** + * @test + */ + public function it_cant_create_new_folder_because_user_has_3_dunning_mails() + { + $user = User::factory() + ->create(); + + Dunning::factory() + ->createOneQuietly([ + 'type' => 'limit_usage_in_new_accounts', + 'user_id' => $user->id, + 'sequence' => 3, + ]); + + // Create basic folder + $this + ->actingAs($user) + ->postJson('/api/create-folder', [ + 'name' => 'New Folder', + ]) + ->assertStatus(401); + + // Create team folder + $this + ->actingAs($user) + ->postJson('/api/teams/folders', [ + 'name' => 'New Folder', + 'invitations' => [ + [ + 'email' => 'john@doe.com', + 'permission' => 'can-edit', + 'type' => 'invitation', + ], + ], + ]) + ->assertStatus(401); + + $this->assertDatabaseCount('folders', 0); + } + /** * @test */ @@ -139,6 +207,34 @@ class MeteredBillingRestrictionsTest extends TestCase ->assertStatus(401); } + /** + * @test + */ + public function it_cant_get_private_file_because_user_has_3_dunning_mails() + { + $user = User::factory() + ->create(); + + Dunning::factory() + ->createOneQuietly([ + 'type' => 'limit_usage_in_new_accounts', + 'user_id' => $user->id, + 'sequence' => 3, + ]); + + $file = File::factory() + ->create([ + 'user_id' => $user->id, + 'basename' => 'fake-file.pdf', + 'name' => 'fake-file.pdf', + ]); + + $this + ->actingAs($user) + ->get("file/$file->name") + ->assertStatus(401); + } + /** * @test */ @@ -160,11 +256,10 @@ class MeteredBillingRestrictionsTest extends TestCase 'name' => 'fake-file.pdf', ]); - // 404 but, ok, because there is not stored temporary file in test $this ->actingAs($user) - ->get("file/$file->name") - ->assertStatus(404); + ->get("file/$file->basename") + ->assertStatus(200); } /** @@ -196,6 +291,41 @@ class MeteredBillingRestrictionsTest extends TestCase ->assertStatus(401); } + /** + * @test + */ + public function it_cant_get_shared_file_because_user_has_3_dunning_mails() + { + $user = User::factory() + ->create(); + + Dunning::factory() + ->createOneQuietly([ + 'type' => 'limit_usage_in_new_accounts', + 'user_id' => $user->id, + 'sequence' => 3, + ]); + + $file = File::factory() + ->create([ + 'user_id' => $user->id, + 'basename' => 'fake-file.pdf', + 'name' => 'fake-file.pdf', + ]); + + $share = Share::factory() + ->create([ + 'item_id' => $file->id, + 'user_id' => $user->id, + 'type' => 'file', + 'is_protected' => false, + ]); + + $this + ->get("file/$file->name/shared/$share->token") + ->assertStatus(401); + } + /** * @test */ @@ -234,7 +364,7 @@ class MeteredBillingRestrictionsTest extends TestCase /** * @test */ - public function it_cant_get_share_page() + public function it_cant_get_share_page_because_user_has_3_failed_payments() { $user = User::factory() ->hasFailedpayments(3) @@ -250,4 +380,30 @@ class MeteredBillingRestrictionsTest extends TestCase $this->get("/share/$share->token") ->assertRedirect('/temporary-unavailable'); } + + /** + * @test + */ + public function it_cant_get_share_page_because_user_has_3_dunning_mails() + { + $user = User::factory() + ->create(); + + Dunning::factory() + ->createOneQuietly([ + 'type' => 'limit_usage_in_new_accounts', + 'user_id' => $user->id, + 'sequence' => 3, + ]); + + $share = Share::factory() + ->create([ + 'user_id' => $user->id, + 'type' => 'folder', + 'is_protected' => false, + ]); + + $this->get("/share/$share->token") + ->assertRedirect('/temporary-unavailable'); + } } diff --git a/tests/Domain/Admin/AdminTest.php b/tests/Domain/Admin/AdminTest.php index 71c7d83c..4bbf4db9 100644 --- a/tests/Domain/Admin/AdminTest.php +++ b/tests/Domain/Admin/AdminTest.php @@ -307,7 +307,7 @@ class AdminTest extends TestCase Sanctum::actingAs($admin); // Delete user - $this->deleteJson("/api/admin/users/$user->id/delete", [ + $this->deleteJson("/api/admin/users/$user->id", [ 'name' => $user->settings->name, ]) ->assertStatus(200);