fix(api): audit moved resources

This commit is contained in:
Andras Bacsai 2026-07-07 21:20:41 +02:00
parent f244b5e25d
commit 6872f63f5f
2 changed files with 53 additions and 3 deletions

View file

@ -3,12 +3,15 @@
use App\Enums\BuildPackTypes;
use App\Enums\RedirectTypes;
use App\Enums\StaticImageTypes;
use App\Models\Environment;
use App\Rules\ValidGitBranch;
use App\Support\ValidationPatterns;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
function getTeamIdFromToken()
@ -173,10 +176,10 @@ function sharedDataApplications()
];
}
function moveResourceToEnvironment(Request $request, $resource, string $resourceType, int $teamId): \Illuminate\Http\JsonResponse
function moveResourceToEnvironment(Request $request, $resource, string $resourceType, int $teamId): JsonResponse
{
$validator = \Illuminate\Support\Facades\Validator::make($request->all(), [
$validator = Validator::make($request->all(), [
'environment_uuid' => 'required|string',
]);
@ -195,7 +198,7 @@ function moveResourceToEnvironment(Request $request, $resource, string $resource
], 422);
}
$newEnvironment = \App\Models\Environment::ownedByCurrentTeamAPI($teamId)
$newEnvironment = Environment::ownedByCurrentTeamAPI($teamId)
->whereUuid($request->environment_uuid)
->first();
@ -209,8 +212,20 @@ function moveResourceToEnvironment(Request $request, $resource, string $resource
return response()->json(['message' => "$resourceType is already in this environment."], 400);
}
$oldEnvironment = $resource->environment()->with('project')->first();
$resource->update(['environment_id' => $newEnvironment->id]);
auditLog('api.'.str($resourceType)->lower()->value().'.moved', [
'team_id' => $teamId,
'resource_uuid' => $resource->uuid,
'resource_type' => str($resourceType)->lower()->value(),
'from_project_uuid' => $oldEnvironment?->project?->uuid,
'from_environment_uuid' => $oldEnvironment?->uuid,
'to_project_uuid' => $newEnvironment->project->uuid,
'to_environment_uuid' => $newEnvironment->uuid,
]);
return response()->json([
'message' => "$resourceType moved successfully.",
'uuid' => $resource->uuid,

View file

@ -15,6 +15,7 @@
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Log;
uses(RefreshDatabase::class);
@ -62,6 +63,40 @@
expect($application->environment_id)->toBe($this->targetEnvironment->id);
});
test('writes audit log when application is moved', function () {
$application = Application::factory()->create([
'environment_id' => $this->environment->id,
'destination_id' => $this->destination->id,
'destination_type' => $this->destination->getMorphClass(),
]);
$auditChannel = Mockery::mock();
$auditChannel->shouldReceive('info')
->once()
->with('api.application.moved', Mockery::on(function (array $context) use ($application) {
return $context['event'] === 'api.application.moved'
&& $context['resource_uuid'] === $application->uuid
&& $context['resource_type'] === 'application'
&& $context['from_environment_uuid'] === $this->environment->uuid
&& $context['to_environment_uuid'] === $this->targetEnvironment->uuid
&& $context['from_project_uuid'] === $this->project->uuid
&& $context['to_project_uuid'] === $this->targetProject->uuid;
}));
Log::shouldReceive('channel')->with('audit')->andReturn($auditChannel);
Log::shouldReceive('warning')->andReturnNull();
$this->actingAs($this->user);
$request = Request::create('/', 'POST', [
'environment_uuid' => $this->targetEnvironment->uuid,
]);
$response = moveResourceToEnvironment($request, $application, 'Application', $this->team->id);
expect($response->getStatusCode())->toBe(200);
});
test('returns 404 when application not found', function () {
$response = $this->withHeaders([
'Authorization' => 'Bearer '.$this->bearerToken,