Skip to content

Commit dc8cbf4

Browse files
committed
Stricter FMCS enforcement in API
1 parent 5f81a48 commit dc8cbf4

7 files changed

Lines changed: 56 additions & 5 deletions

File tree

app/Http/Controllers/Api/AccessoriesController.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use App\Http\Transformers\SelectlistTransformer;
1515
use App\Models\Accessory;
1616
use App\Models\AccessoryCheckout;
17+
use App\Models\Company;
1718
use App\Models\User;
1819
use Carbon\Carbon;
1920
use Illuminate\Http\JsonResponse;
@@ -155,6 +156,7 @@ public function store(StoreAccessoryRequest $request)
155156
{
156157
$accessory = new Accessory;
157158
$accessory->fill($request->all());
159+
$accessory->company_id = Company::getIdForCurrentUser($request->input('company_id'));
158160
$accessory = $request->handleImages($accessory);
159161

160162
if ($accessory->save()) {
@@ -248,6 +250,7 @@ public function update(ImageUploadRequest $request, $id)
248250
$this->authorize('update', Accessory::class);
249251
$accessory = Accessory::findOrFail($id);
250252
$accessory->fill($request->all());
253+
$accessory->company_id = Company::getIdForCurrentUser($request->input('company_id'));
251254
$accessory = $request->handleImages($accessory);
252255

253256
if ($accessory->save()) {

app/Http/Controllers/Api/ComponentsController.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use App\Http\Transformers\ActionlogsTransformer;
1010
use App\Http\Transformers\ComponentsTransformer;
1111
use App\Models\Asset;
12+
use App\Models\Company;
1213
use App\Models\Component;
1314
use Carbon\Carbon;
1415
use Illuminate\Database\Query\Builder;
@@ -165,6 +166,7 @@ public function store(ImageUploadRequest $request): JsonResponse
165166
$this->authorize('create', Component::class);
166167
$component = new Component;
167168
$component->fill($request->all());
169+
$component->company_id = Company::getIdForCurrentUser($request->input('company_id'));
168170
$component = $request->handleImages($component);
169171

170172
if ($component->save()) {
@@ -205,6 +207,7 @@ public function update(ImageUploadRequest $request, $id): JsonResponse
205207
$this->authorize('update', Component::class);
206208
$component = Component::findOrFail($id);
207209
$component->fill($request->all());
210+
$component->company_id = Company::getIdForCurrentUser($request->input('company_id'));
208211
$component = $request->handleImages($component);
209212

210213
if ($component->save()) {

app/Http/Controllers/Api/ConsumablesController.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ public function store(StoreConsumableRequest $request): JsonResponse
155155
$this->authorize('create', Consumable::class);
156156
$consumable = new Consumable;
157157
$consumable->fill($request->all());
158+
$consumable->company_id = Company::getIdForCurrentUser($request->input('company_id'));
158159
$consumable = $request->handleImages($consumable);
159160

160161
if ($consumable->save()) {
@@ -194,6 +195,7 @@ public function update(StoreConsumableRequest $request, $id): JsonResponse
194195
$this->authorize('update', Consumable::class);
195196
$consumable = Consumable::findOrFail($id);
196197
$consumable->fill($request->all());
198+
$consumable->company_id = Company::getIdForCurrentUser($request->input('company_id'));
197199
$consumable = $request->handleImages($consumable);
198200

199201
if ($consumable->save()) {

app/Http/Controllers/Api/DepartmentsController.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use App\Http\Requests\StoreDepartmentRequest;
1010
use App\Http\Transformers\DepartmentsTransformer;
1111
use App\Http\Transformers\SelectlistTransformer;
12+
use App\Models\Company;
1213
use App\Models\Department;
1314
use Illuminate\Http\JsonResponse;
1415
use Illuminate\Http\Request;
@@ -111,6 +112,7 @@ public function store(StoreDepartmentRequest $request): JsonResponse
111112
{
112113
$department = new Department;
113114
$department->fill($request->validated());
115+
$department->company_id = Company::getIdForCurrentUser($request->input('company_id'));
114116
$department = $request->handleImages($department);
115117

116118
$department->created_by = auth()->id();
@@ -155,6 +157,7 @@ public function update(ImageUploadRequest $request, $id): JsonResponse
155157
$this->authorize('update', Department::class);
156158
$department = Department::findOrFail($id);
157159
$department->fill($request->all());
160+
$department->company_id = Company::getIdForCurrentUser($request->input('company_id'));
158161
$department = $request->handleImages($department);
159162

160163
if ($department->save()) {

app/Http/Controllers/Api/LicensesController.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use App\Http\Transformers\ActionlogsTransformer;
99
use App\Http\Transformers\LicensesTransformer;
1010
use App\Http\Transformers\SelectlistTransformer;
11+
use App\Models\Company;
1112
use App\Models\License;
1213
use App\Models\Setting;
1314
use Illuminate\Http\JsonResponse;
@@ -179,6 +180,7 @@ public function store(Request $request): JsonResponse
179180
$this->authorize('create', License::class);
180181
$license = new License;
181182
$license->fill($request->all());
183+
$license->company_id = Company::getIdForCurrentUser($request->input('company_id'));
182184

183185
if ($license->save()) {
184186
return response()->json(Helper::formatStandardApiResponse('success', $license, trans('admin/licenses/message.create.success')));
@@ -219,6 +221,7 @@ public function update(Request $request, $id): JsonResponse|array
219221

220222
$license = License::findOrFail($id);
221223
$license->fill($request->all());
224+
$license->company_id = Company::getIdForCurrentUser($request->input('company_id'));
222225

223226
if ($license->save()) {
224227
return response()->json(Helper::formatStandardApiResponse('success', $license, trans('admin/licenses/message.update.success')));

tests/Feature/Accessories/Api/StoreAccessoryTest.php

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Tests\Feature\Accessories\Api;
44

5+
use App\Models\Accessory;
56
use App\Models\Category;
67
use App\Models\Company;
78
use App\Models\Location;
@@ -23,27 +24,29 @@ public function test_requires_permission()
2324

2425
public function test_adheres_to_full_multiple_companies_support_scoping()
2526
{
26-
$this->markTestSkipped('This behavior is not implemented');
27-
2827
[$companyA, $companyB] = Company::factory()->count(2)->create();
2928
$userInCompanyA = User::factory()->for($companyA)->createAccessories()->create();
3029

3130
$this->settings->enableMultipleFullCompanySupport();
3231

3332
// attempt to store an accessory for company B
34-
$this->actingAsForApi($userInCompanyA)
33+
$response = $this->actingAsForApi($userInCompanyA)
3534
->postJson(route('api.accessories.store'), [
3635
'category_id' => Category::factory()->forAccessories()->create()->id,
3736
'name' => 'My Awesome Accessory',
3837
'qty' => 1,
3938
'company_id' => $companyB->id,
40-
])->assertStatusMessageIs('error');
39+
])->assertStatusMessageIs('success');
4140

41+
$accessory = Accessory::withoutGlobalScopes()->findOrFail($response['payload']['id']);
42+
43+
$this->assertSame($companyA->id, $accessory->company_id);
4244
$this->assertDatabaseMissing('accessories', [
4345
'name' => 'My Awesome Accessory',
46+
'company_id' => $companyB->id,
4447
]);
4548
}
46-
49+
4750

4851
public function test_can_store_accessory()
4952
{

tests/Feature/Accessories/Api/UpdateAccessoryTest.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,40 @@ public function test_adheres_to_full_multiple_companies_support_scoping()
5555
$this->assertEquals('New Name', $accessoryC->fresh()->name);
5656
}
5757

58+
public function test_prevents_cross_tenant_company_reassignment_when_fmcs_enabled()
59+
{
60+
[$companyA, $companyB] = Company::factory()->count(2)->create();
61+
$accessory = Accessory::factory()->for($companyA)->create();
62+
$userInCompanyA = User::factory()->for($companyA)->editAccessories()->create();
63+
64+
$this->settings->enableMultipleFullCompanySupport();
65+
66+
$this->actingAsForApi($userInCompanyA)
67+
->patchJson(route('api.accessories.update', $accessory), [
68+
'company_id' => $companyB->id,
69+
])
70+
->assertStatusMessageIs('success');
71+
72+
$this->assertSame($companyA->id, $accessory->fresh()->company_id);
73+
}
74+
75+
public function test_allows_superuser_company_reassignment_when_fmcs_enabled()
76+
{
77+
[$companyA, $companyB] = Company::factory()->count(2)->create();
78+
$accessory = Accessory::factory()->for($companyA)->create();
79+
$superuser = User::factory()->superuser()->create(['company_id' => null]);
80+
81+
$this->settings->enableMultipleFullCompanySupport();
82+
83+
$this->actingAsForApi($superuser)
84+
->patchJson(route('api.accessories.update', $accessory), [
85+
'company_id' => $companyB->id,
86+
])
87+
->assertStatusMessageIs('success');
88+
89+
$this->assertSame($companyB->id, $accessory->fresh()->company_id);
90+
}
91+
5892
public function test_can_update_accessory_via_patch()
5993
{
6094
[$categoryA, $categoryB] = Category::factory()->count(2)->create();

0 commit comments

Comments
 (0)