diff --git a/public/mix-manifest.json b/public/mix-manifest.json
index 2f8ffa23..183759b5 100644
--- a/public/mix-manifest.json
+++ b/public/mix-manifest.json
@@ -70,7 +70,7 @@
"/chunks/profile~chunks/settings-password.js": "/chunks/profile~chunks/settings-password.js?id=dfa4128d68360d5e1b3b",
"/chunks/purchase-code.js": "/chunks/purchase-code.js?id=9e948882ae2315eb6132",
"/chunks/recent-uploads.js": "/chunks/recent-uploads.js?id=8577d4c771602671b38a",
- "/chunks/settings.js": "/chunks/settings.js?id=4466d97a0211f77d9317",
+ "/chunks/settings.js": "/chunks/settings.js?id=b8e396ca81993a2ac3c9",
"/chunks/settings-password.js": "/chunks/settings-password.js?id=b6eb94764cc7b47f835e",
"/chunks/settings-storage.js": "/chunks/settings-storage.js?id=76b45c336e8e12b23e81",
"/chunks/settings~chunks/settings-password.js": "/chunks/settings~chunks/settings-password.js?id=aafc9cd6aa47b01bc25a",
@@ -198,5 +198,7 @@
"/js/main.51906e2db8a6c36f5304.hot-update.js": "/js/main.51906e2db8a6c36f5304.hot-update.js",
"/js/main.c09b0f39fe6d0b43515b.hot-update.js": "/js/main.c09b0f39fe6d0b43515b.hot-update.js",
"/js/main.de28ca938da3825e62b3.hot-update.js": "/js/main.de28ca938da3825e62b3.hot-update.js",
- "/js/main.be91e0ed3d68ecb1af06.hot-update.js": "/js/main.be91e0ed3d68ecb1af06.hot-update.js"
+ "/js/main.be91e0ed3d68ecb1af06.hot-update.js": "/js/main.be91e0ed3d68ecb1af06.hot-update.js",
+ "/chunks/settings.91678a5fa053e1ee00a7.hot-update.js": "/chunks/settings.91678a5fa053e1ee00a7.hot-update.js",
+ "/js/main.000dc4eab65b819bb1e4.hot-update.js": "/js/main.000dc4eab65b819bb1e4.hot-update.js"
}
diff --git a/resources/js/helpers/ValidatorHelpers.js b/resources/js/helpers/ValidatorHelpers.js
index 7d904346..6494ded3 100644
--- a/resources/js/helpers/ValidatorHelpers.js
+++ b/resources/js/helpers/ValidatorHelpers.js
@@ -4,6 +4,11 @@ const ValidatorHelpers = {
install(Vue) {
Vue.prototype.$cantInviteMember = function (email, invitations) {
+
+ if (store.getters.config.subscriptionType === 'metered') {
+ return false
+ }
+
// Get max team members limitations
let limit = store.getters.user.data.meta.limitations.max_team_members
diff --git a/resources/js/views/Profile.vue b/resources/js/views/Profile.vue
index 9f8407b0..a9f4be25 100644
--- a/resources/js/views/Profile.vue
+++ b/resources/js/views/Profile.vue
@@ -42,31 +42,9 @@
{{ user.data.attributes.email }}
-
-
-
-
-
-
-
-
-
-
diff --git a/src/App/Limitations/Engines/DefaultLimitationEngine.php b/src/App/Limitations/Engines/DefaultLimitationEngine.php
index 98f1444e..464c8873 100644
--- a/src/App/Limitations/Engines/DefaultLimitationEngine.php
+++ b/src/App/Limitations/Engines/DefaultLimitationEngine.php
@@ -3,6 +3,7 @@ namespace App\Limitations\Engines;
use App\Users\Models\User;
use App\Limitations\LimitationEngine;
+use Domain\Teams\Actions\CheckMaxTeamMembersLimitAction;
class DefaultLimitationEngine implements LimitationEngine
{
@@ -20,8 +21,7 @@ class DefaultLimitationEngine implements LimitationEngine
);
// 2. Check if storage usage exceed predefined capacity
- return ! ($usedPercentage >= 100)
- ;
+ return ! ($usedPercentage >= 100);
}
public function canDownload(User $user): bool
@@ -33,4 +33,14 @@ class DefaultLimitationEngine implements LimitationEngine
{
return true;
}
+
+ public function canCreateTeamFolder(User $user): bool
+ {
+ return true;
+ }
+
+ public function canInviteTeamMembers(User $user, array $newInvites): bool
+ {
+ return resolve(CheckMaxTeamMembersLimitAction::class)($user, $newInvites);
+ }
}
diff --git a/src/App/Limitations/Engines/FixedBillingLimitationEngine.php b/src/App/Limitations/Engines/FixedBillingLimitationEngine.php
index 27603078..943fe03a 100644
--- a/src/App/Limitations/Engines/FixedBillingLimitationEngine.php
+++ b/src/App/Limitations/Engines/FixedBillingLimitationEngine.php
@@ -3,6 +3,7 @@ namespace App\Limitations\Engines;
use App\Users\Models\User;
use App\Limitations\LimitationEngine;
+use Domain\Teams\Actions\CheckMaxTeamMembersLimitAction;
class FixedBillingLimitationEngine implements LimitationEngine
{
@@ -27,4 +28,14 @@ class FixedBillingLimitationEngine implements LimitationEngine
{
return true;
}
+
+ public function canCreateTeamFolder(User $user): bool
+ {
+ return true;
+ }
+
+ public function canInviteTeamMembers(User $user, array $newInvites): bool
+ {
+ return resolve(CheckMaxTeamMembersLimitAction::class)($user, $newInvites);
+ }
}
diff --git a/src/App/Limitations/Engines/MeteredBillingLimitationEngine.php b/src/App/Limitations/Engines/MeteredBillingLimitationEngine.php
index b3cc26b3..bac7420d 100644
--- a/src/App/Limitations/Engines/MeteredBillingLimitationEngine.php
+++ b/src/App/Limitations/Engines/MeteredBillingLimitationEngine.php
@@ -23,4 +23,15 @@ class MeteredBillingLimitationEngine implements LimitationEngine
// Disable create folder when user has more than 3 failed payments
return ! ($user->failedPayments()->count() >= 3);
}
+
+ public function canCreateTeamFolder(User $user): bool
+ {
+ // Disable create folder when user has more than 3 failed payments
+ return ! ($user->failedPayments()->count() >= 3);
+ }
+
+ public function canInviteTeamMembers(User $user, array $newInvites): bool
+ {
+ return true;
+ }
}
diff --git a/src/App/Limitations/LimitationEngine.php b/src/App/Limitations/LimitationEngine.php
index a118c5ff..d63ccbed 100644
--- a/src/App/Limitations/LimitationEngine.php
+++ b/src/App/Limitations/LimitationEngine.php
@@ -10,4 +10,8 @@ interface LimitationEngine
public function canDownload(User $user): bool;
public function canCreateFolder(User $user): bool;
+
+ public function canCreateTeamFolder(User $user): bool;
+
+ public function canInviteTeamMembers(User $user, array $newInvites): bool;
}
diff --git a/src/Domain/Files/Actions/UploadFileAction.php b/src/Domain/Files/Actions/UploadFileAction.php
index c52d6760..511b2c4e 100644
--- a/src/Domain/Files/Actions/UploadFileAction.php
+++ b/src/Domain/Files/Actions/UploadFileAction.php
@@ -1,7 +1,6 @@
uploadFiles)($request);
return response(new FileResource($file), 201);
diff --git a/src/Domain/Teams/Actions/CheckMaxTeamMembersLimitAction.php b/src/Domain/Teams/Actions/CheckMaxTeamMembersLimitAction.php
index 3c75ea5c..bf8ccaf4 100644
--- a/src/Domain/Teams/Actions/CheckMaxTeamMembersLimitAction.php
+++ b/src/Domain/Teams/Actions/CheckMaxTeamMembersLimitAction.php
@@ -5,7 +5,7 @@ use App\Users\Models\User;
class CheckMaxTeamMembersLimitAction
{
- public function __invoke(array $invitations, User $user)
+ public function __invoke(User $user, array $newInvites): bool
{
// Get user limitation summary
$limits = $user->limitations->summary();
@@ -14,7 +14,7 @@ class CheckMaxTeamMembersLimitAction
$allowedEmails = $limits['max_team_members']['meta']['allowed_emails'];
// Get new email invites from request
- $invitationEmails = collect($invitations)
+ $invitationEmails = collect($newInvites)
->pluck('email');
// Count total unique members
@@ -24,8 +24,6 @@ class CheckMaxTeamMembersLimitAction
->count();
// Check if there is more unique members than total max team members are allowed
- if ($totalMembers > $limits['max_team_members']['total']) {
- abort(423, 'You exceed your members limit.');
- }
+ return ! ($totalMembers > $limits['max_team_members']['total']);
}
}
diff --git a/src/Domain/Teams/Controllers/ConvertFolderIntoTeamFolderController.php b/src/Domain/Teams/Controllers/ConvertFolderIntoTeamFolderController.php
index 35c4e4d5..ee37dbd5 100644
--- a/src/Domain/Teams/Controllers/ConvertFolderIntoTeamFolderController.php
+++ b/src/Domain/Teams/Controllers/ConvertFolderIntoTeamFolderController.php
@@ -7,7 +7,6 @@ use App\Http\Controllers\Controller;
use Domain\Teams\Models\TeamFolderMember;
use Illuminate\Contracts\Routing\ResponseFactory;
use Domain\Teams\Requests\ConvertIntoTeamFolderRequest;
-use Domain\Teams\Actions\CheckMaxTeamMembersLimitAction;
use Domain\Teams\Actions\InviteMembersIntoTeamFolderAction;
use Domain\Teams\Actions\SetTeamFolderPropertyForAllChildrenAction;
@@ -15,7 +14,6 @@ class ConvertFolderIntoTeamFolderController extends Controller
{
public function __construct(
public InviteMembersIntoTeamFolderAction $inviteMembers,
- public CheckMaxTeamMembersLimitAction $checkMaxTeamMembersLimit,
public SetTeamFolderPropertyForAllChildrenAction $setTeamFolderPropertyForAllChildren,
) {
}
@@ -25,7 +23,12 @@ class ConvertFolderIntoTeamFolderController extends Controller
Folder $folder
): ResponseFactory|Response {
// Check if user didn't exceed max team members limit
- ($this->checkMaxTeamMembersLimit)($request->input('invitations'), $folder->owner);
+ if (! $folder->owner->canInviteTeamMembers($request->input('invitations'))) {
+ return response([
+ 'type' => 'error',
+ 'message' => 'You exceed your members limit.',
+ ], 401);
+ }
// Update root team folder
$folder->update([
diff --git a/src/Domain/Teams/Controllers/TeamFoldersController.php b/src/Domain/Teams/Controllers/TeamFoldersController.php
index 3ad7fc85..168dd648 100644
--- a/src/Domain/Teams/Controllers/TeamFoldersController.php
+++ b/src/Domain/Teams/Controllers/TeamFoldersController.php
@@ -17,7 +17,6 @@ use Domain\Folders\Resources\FolderCollection;
use Domain\Teams\Actions\UpdateInvitationsAction;
use Illuminate\Contracts\Routing\ResponseFactory;
use Domain\Teams\Requests\CreateTeamFolderRequest;
-use Domain\Teams\Actions\CheckMaxTeamMembersLimitAction;
use Domain\Teams\Requests\UpdateTeamFolderMembersRequest;
use Domain\Teams\Actions\InviteMembersIntoTeamFolderAction;
use Domain\Teams\Actions\SetTeamFolderPropertyForAllChildrenAction;
@@ -27,7 +26,6 @@ class TeamFoldersController extends Controller
public function __construct(
public InviteMembersIntoTeamFolderAction $inviteMembers,
public SetTeamFolderPropertyForAllChildrenAction $setTeamFolderPropertyForAllChildren,
- public CheckMaxTeamMembersLimitAction $checkMaxTeamMembersLimit,
) {
}
@@ -61,8 +59,21 @@ class TeamFoldersController extends Controller
): ResponseFactory | Response {
$data = CreateTeamFolderData::fromRequest($request);
+ // Check if user can create team folder
+ if (! $request->user()->canCreateTeamFolder()) {
+ return response([
+ 'type' => 'error',
+ 'message' => 'This user action is not allowed.',
+ ], 401);
+ }
+
// Check if user didn't exceed max team members limit
- ($this->checkMaxTeamMembersLimit)($data->invitations, $request->user());
+ if (! $request->user()->canInviteTeamMembers($data->invitations)) {
+ return response([
+ 'type' => 'error',
+ 'message' => 'You exceed your members limit.',
+ ], 401);
+ }
// Create folder
$folder = Folder::create([
@@ -93,7 +104,12 @@ class TeamFoldersController extends Controller
$this->authorize('owner', $folder);
// Check if user didn't exceed max team members limit
- ($this->checkMaxTeamMembersLimit)($request->input('invitations'), $request->user());
+ if (! $request->user()->canInviteTeamMembers($request->input('invitations'))) {
+ return response([
+ 'type' => 'error',
+ 'message' => 'You exceed your members limit.',
+ ], 401);
+ }
$updateInvitations(
$folder,
diff --git a/tests/App/Limitations/DefaultLimitationTest.php b/tests/App/Limitations/DefaultLimitationTest.php
index 69461224..ae4946b1 100644
--- a/tests/App/Limitations/DefaultLimitationTest.php
+++ b/tests/App/Limitations/DefaultLimitationTest.php
@@ -5,6 +5,7 @@ use Tests\TestCase;
use App\Users\Models\User;
use Domain\Files\Models\File;
use Domain\Settings\Models\Setting;
+use Domain\Teams\Models\TeamFolderMember;
class DefaultLimitationTest extends TestCase
{
@@ -105,4 +106,82 @@ class DefaultLimitationTest extends TestCase
'name' => 'New Folder',
]);
}
+
+ /**
+ * @test
+ */
+ public function it_cant_invite_team_members_into_team_folder_because_user_exceeded_members_limit()
+ {
+ $user = User::factory()
+ ->hasFolders([
+ 'team_folder' => true,
+ ])
+ ->create();
+
+ TeamFolderMember::create([
+ 'parent_id' => $user->folders[0]->id,
+ 'user_id' => $user->id,
+ 'permission' => 'owner',
+ ]);
+
+ // Create team folder members
+ $members = User::factory()
+ ->count(5)
+ ->create()
+ ->each(
+ fn ($member) => TeamFolderMember::factory()
+ ->create([
+ 'parent_id' => $user->folders[0]->id,
+ 'user_id' => $member->id,
+ ])
+ );
+
+ // Try invite new members, it has to fail
+ $this
+ ->actingAs($user)
+ ->post('/api/teams/folders', [
+ 'name' => 'Company Project',
+ 'invitations' => [
+ [
+ 'email' => 'test@doe.com',
+ 'permission' => 'can-edit',
+ ],
+ [
+ 'email' => 'test2@doe.com',
+ 'permission' => 'can-edit',
+ ],
+ [
+ 'email' => 'test3@doe.com',
+ 'permission' => 'can-edit',
+ ],
+ [
+ 'email' => 'test4@doe.com',
+ 'permission' => 'can-edit',
+ ],
+ [
+ 'email' => 'test5@doe.com',
+ 'permission' => 'can-edit',
+ ],
+ [
+ 'email' => 'test6@doe.com',
+ 'permission' => 'can-edit',
+ ],
+ ],
+ ])
+ ->assertStatus(401);
+
+ // Invite existing member, it has to go through
+ $this
+ ->actingAs($user)
+ ->post('/api/teams/folders', [
+ 'name' => 'Company Project',
+ 'invitations' => [
+ [
+ 'email' => $members[0]->email,
+ 'permission' => 'can-edit',
+ ],
+ ],
+ ])
+ ->assertCreated();
+ }
}
diff --git a/tests/App/Limitations/FixedBillingLimitationTest.php b/tests/App/Limitations/FixedBillingLimitationTest.php
index e6903b38..ee1b7022 100644
--- a/tests/App/Limitations/FixedBillingLimitationTest.php
+++ b/tests/App/Limitations/FixedBillingLimitationTest.php
@@ -5,6 +5,7 @@ use Tests\TestCase;
use App\Users\Models\User;
use Domain\Files\Models\File;
use Domain\Settings\Models\Setting;
+use Domain\Teams\Models\TeamFolderMember;
class FixedBillingLimitationTest extends TestCase
{
@@ -13,7 +14,7 @@ class FixedBillingLimitationTest extends TestCase
parent::setUp();
Setting::updateOrCreate([
- 'name' => 'subscription_type',
+ 'name' => 'subscription_type',
], [
'value' => 'fixed',
]);
@@ -58,7 +59,7 @@ class FixedBillingLimitationTest extends TestCase
$this
->actingAs($user)
->postJson('/api/create-folder', [
- 'name' => 'New Folder',
+ 'name' => 'New Folder',
])
->assertStatus(201);
@@ -66,4 +67,82 @@ class FixedBillingLimitationTest extends TestCase
'name' => 'New Folder',
]);
}
+
+ /**
+ * @test
+ */
+ public function it_cant_invite_team_members_into_team_folder_because_user_exceeded_members_limit()
+ {
+ $user = User::factory()
+ ->hasFolders([
+ 'team_folder' => true,
+ ])
+ ->create();
+
+ TeamFolderMember::create([
+ 'parent_id' => $user->folders[0]->id,
+ 'user_id' => $user->id,
+ 'permission' => 'owner',
+ ]);
+
+ // Create team folder members
+ $members = User::factory()
+ ->count(5)
+ ->create()
+ ->each(
+ fn ($member) => TeamFolderMember::factory()
+ ->create([
+ 'parent_id' => $user->folders[0]->id,
+ 'user_id' => $member->id,
+ ])
+ );
+
+ // Try invite new members, it has to fail
+ $this
+ ->actingAs($user)
+ ->post('/api/teams/folders', [
+ 'name' => 'Company Project',
+ 'invitations' => [
+ [
+ 'email' => 'test@doe.com',
+ 'permission' => 'can-edit',
+ ],
+ [
+ 'email' => 'test2@doe.com',
+ 'permission' => 'can-edit',
+ ],
+ [
+ 'email' => 'test3@doe.com',
+ 'permission' => 'can-edit',
+ ],
+ [
+ 'email' => 'test4@doe.com',
+ 'permission' => 'can-edit',
+ ],
+ [
+ 'email' => 'test5@doe.com',
+ 'permission' => 'can-edit',
+ ],
+ [
+ 'email' => 'test6@doe.com',
+ 'permission' => 'can-edit',
+ ],
+ ],
+ ])
+ ->assertStatus(401);
+
+ // Invite existing member, it has to go through
+ $this
+ ->actingAs($user)
+ ->post('/api/teams/folders', [
+ 'name' => 'Company Project',
+ 'invitations' => [
+ [
+ 'email' => $members[0]->email,
+ 'permission' => 'can-edit',
+ ],
+ ],
+ ])
+ ->assertCreated();
+ }
}
diff --git a/tests/App/Limitations/MeteredBillingLimitationTest.php b/tests/App/Limitations/MeteredBillingLimitationTest.php
index 9af044d0..3d1d1052 100644
--- a/tests/App/Limitations/MeteredBillingLimitationTest.php
+++ b/tests/App/Limitations/MeteredBillingLimitationTest.php
@@ -49,16 +49,30 @@ class MeteredBillingLimitationTest extends TestCase
$user = User::factory()
->create();
+ // Create basic folder
$this
->actingAs($user)
->postJson('/api/create-folder', [
- 'name' => 'New Folder',
+ 'name' => 'New Folder',
])
->assertStatus(201);
- $this->assertDatabaseHas('folders', [
- 'name' => 'New Folder',
- ]);
+ // Create team folder
+ $this
+ ->actingAs($user)
+ ->postJson('/api/teams/folders', [
+ 'name' => 'New Team Folder',
+ 'invitations' => [
+ [
+ 'email' => 'john@doe.com',
+ 'permission' => 'can-edit',
+ 'type' => 'invitation',
+ ],
+ ],
+ ])
+ ->assertStatus(201);
+
+ $this->assertDatabaseCount('folders', 2);
}
/**
@@ -70,15 +84,29 @@ class MeteredBillingLimitationTest extends TestCase
->hasFailedpayments(3)
->create();
+ // Create basic folder
$this
->actingAs($user)
->postJson('/api/create-folder', [
- 'name' => 'New Folder',
+ 'name' => 'New Folder',
])
->assertStatus(401);
- $this->assertDatabaseMissing('folders', [
- 'name' => 'New Folder',
- ]);
+ // 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);
}
}
diff --git a/tests/Domain/Teams/TeamLimitsTest.php b/tests/Domain/Teams/TeamLimitsTest.php
deleted file mode 100644
index 51ffb32a..00000000
--- a/tests/Domain/Teams/TeamLimitsTest.php
+++ /dev/null
@@ -1,87 +0,0 @@
-hasFolders([
- 'team_folder' => true,
- ])
- ->create();
-
- TeamFolderMember::create([
- 'parent_id' => $user->folders[0]->id,
- 'user_id' => $user->id,
- 'permission' => 'owner',
- ]);
-
- $members = User::factory()
- ->count(5)
- ->create();
-
- $members->each(
- fn ($member) => TeamFolderMember::factory()
- ->create([
- 'parent_id' => $user->folders[0]->id,
- 'user_id' => $member->id,
- ])
- );
-
- // Try invite new member
- $this
- ->actingAs($user)
- ->post('/api/teams/folders', [
- 'name' => 'Company Project',
- 'invitations' => [
- [
- 'email' => 'test@doe.com',
- 'permission' => 'can-edit',
- ],
- [
- 'email' => 'test2@doe.com',
- 'permission' => 'can-edit',
- ],
- [
- 'email' => 'test3@doe.com',
- 'permission' => 'can-edit',
- ],
- [
- 'email' => 'test4@doe.com',
- 'permission' => 'can-edit',
- ],
- [
- 'email' => 'test5@doe.com',
- 'permission' => 'can-edit',
- ],
- [
- 'email' => 'test6@doe.com',
- 'permission' => 'can-edit',
- ],
- ],
- ])
- ->assertStatus(423);
-
- // Invite existing member
- $this
- ->actingAs($user)
- ->post('/api/teams/folders', [
- 'name' => 'Company Project',
- 'invitations' => [
- [
- 'email' => $members[0]->email,
- 'permission' => 'can-edit',
- ],
- ],
- ])
- ->assertCreated();
- }
-}