fix(api): return JSON validation errors and reject unknown fields on PATCH /team

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Andras Bacsai
2026-10-02 16:01:00 +02:00
co-authored by Claude Opus 5.5
parent 0b581454cf
commit 5cb68cda16
2 changed files with 66 additions and 2 deletions
+16 -2
View File
@@ -268,11 +268,25 @@ class TeamController extends Controller
}
$this->authorize('update', $team);
$validated = $request->validate([
$allowedFields = ['is_build_server_fallback_enabled'];
$validator = customApiValidator($request->all(), [
'is_build_server_fallback_enabled' => ['required', 'boolean'],
]);
$extraFields = array_diff(array_keys($request->all()), $allowedFields);
if ($validator->fails() || ! empty($extraFields)) {
$errors = $validator->errors();
foreach ($extraFields as $field) {
$errors->add($field, 'This field is not allowed.');
}
$team->update($validated);
return response()->json([
'message' => 'Validation failed.',
'errors' => $errors,
], 422);
}
$team->update($validator->validated());
return response()->json($this->removeSensitiveData($team));
}
@@ -0,0 +1,50 @@
<?php
use App\Models\InstanceSettings;
use App\Models\Team;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
beforeEach(function () {
InstanceSettings::unguarded(fn () => InstanceSettings::updateOrCreate(['id' => 0], ['is_api_enabled' => true]));
$this->team = Team::factory()->create();
$this->user = User::factory()->create();
$this->team->members()->attach($this->user->id, ['role' => 'owner']);
session(['currentTeam' => $this->team]);
$this->bearerToken = $this->user->createToken('team-update-validation', ['write'])->plainTextToken;
});
test('PATCH /team returns JSON validation errors without an Accept header', function () {
$response = $this->call(
'PATCH',
'/api/v1/team',
server: [
'HTTP_AUTHORIZATION' => 'Bearer '.$this->bearerToken,
'CONTENT_TYPE' => 'application/json',
],
content: json_encode(['is_build_server_fallback_enabled' => 'invalid']),
);
$response->assertUnprocessable()
->assertJsonPath('message', 'Validation failed.')
->assertJsonStructure(['errors' => ['is_build_server_fallback_enabled']]);
expect($this->team->fresh()->is_build_server_fallback_enabled)->toBeTrue();
});
test('PATCH /team rejects unknown fields', function () {
$this->withToken($this->bearerToken)
->patchJson('/api/v1/team', [
'is_build_server_fallback_enabled' => false,
'name' => 'renamed',
])
->assertUnprocessable()
->assertJsonPath('errors.name.0', 'This field is not allowed.');
expect($this->team->fresh())
->is_build_server_fallback_enabled->toBeTrue()
->name->not->toBe('renamed');
});