Fix support API audit logging
This commit is contained in:
@@ -8,6 +8,7 @@ use App\Http\Requests\Support\Resources\SupportResourceFormRequest;
|
||||
use App\Http\Requests\Support\SupportResourceRequest;
|
||||
use App\Jobs\GenerateDataExport;
|
||||
use App\Models\DataExport;
|
||||
use App\Services\Audit\SuperAdminAuditLogger;
|
||||
use App\Support\ApiError;
|
||||
use App\Support\SupportApiAuthorizer;
|
||||
use App\Support\SupportApiRegistry;
|
||||
@@ -77,7 +78,7 @@ class SupportResourceController extends Controller
|
||||
|
||||
public function store(SupportResourceRequest $request, string $resource): JsonResponse
|
||||
{
|
||||
if ($response = SupportApiAuthorizer::authorizeResource($request, $resource, 'write')) {
|
||||
if ($response = SupportApiAuthorizer::authorizeAnyAbility($request, SupportApiRegistry::abilitiesFor($resource, 'write'), 'write')) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
@@ -110,6 +111,14 @@ class SupportResourceController extends Controller
|
||||
|
||||
$record = $modelClass::query()->create($payload);
|
||||
|
||||
app(SuperAdminAuditLogger::class)->record(
|
||||
SupportApiRegistry::auditAction($resource, 'created'),
|
||||
$record,
|
||||
SuperAdminAuditLogger::fieldsMetadata($payload),
|
||||
actor: $request->user(),
|
||||
source: static::class
|
||||
);
|
||||
|
||||
if ($resource === 'data-exports') {
|
||||
GenerateDataExport::dispatch($record->id);
|
||||
}
|
||||
@@ -121,7 +130,7 @@ class SupportResourceController extends Controller
|
||||
|
||||
public function update(SupportResourceRequest $request, string $resource, string $record): JsonResponse
|
||||
{
|
||||
if ($response = SupportApiAuthorizer::authorizeResource($request, $resource, 'write')) {
|
||||
if ($response = SupportApiAuthorizer::authorizeAnyAbility($request, SupportApiRegistry::abilitiesFor($resource, 'write'), 'write')) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
@@ -148,6 +157,14 @@ class SupportResourceController extends Controller
|
||||
$model->fill($payload);
|
||||
$model->save();
|
||||
|
||||
app(SuperAdminAuditLogger::class)->record(
|
||||
SupportApiRegistry::auditAction($resource, 'updated'),
|
||||
$model,
|
||||
SuperAdminAuditLogger::fieldsMetadata($payload),
|
||||
actor: $request->user(),
|
||||
source: static::class
|
||||
);
|
||||
|
||||
return response()->json([
|
||||
'data' => $model->refresh(),
|
||||
]);
|
||||
@@ -155,7 +172,7 @@ class SupportResourceController extends Controller
|
||||
|
||||
public function destroy(Request $request, string $resource, string $record): JsonResponse
|
||||
{
|
||||
if ($response = SupportApiAuthorizer::authorizeResource($request, $resource, 'write')) {
|
||||
if ($response = SupportApiAuthorizer::authorizeAnyAbility($request, SupportApiRegistry::abilitiesFor($resource, 'write'), 'write')) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
@@ -171,6 +188,14 @@ class SupportResourceController extends Controller
|
||||
|
||||
$model->delete();
|
||||
|
||||
app(SuperAdminAuditLogger::class)->record(
|
||||
SupportApiRegistry::auditAction($resource, 'deleted'),
|
||||
$model,
|
||||
SuperAdminAuditLogger::fieldsMetadata([]),
|
||||
actor: $request->user(),
|
||||
source: static::class
|
||||
);
|
||||
|
||||
return response()->json(['ok' => true]);
|
||||
}
|
||||
|
||||
|
||||
@@ -93,11 +93,15 @@ class SuperAdminAuditLogger
|
||||
return $panel->getId() === 'superadmin';
|
||||
}
|
||||
|
||||
if (request()->is('super-admin*') || request()->is('api/v1/support*')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (app()->runningInConsole()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return request()->is('super-admin*');
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -48,4 +48,39 @@ class SupportApiAuthorizer
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, string> $abilities
|
||||
*/
|
||||
public static function authorizeAnyAbility(Request $request, array $abilities, string $actionLabel = 'resource'): ?JsonResponse
|
||||
{
|
||||
if ($abilities === []) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$token = $request->user()?->currentAccessToken();
|
||||
|
||||
if (! $token) {
|
||||
return ApiError::response(
|
||||
'unauthenticated',
|
||||
'Unauthenticated',
|
||||
'Missing access token for support request.',
|
||||
401
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($abilities as $ability) {
|
||||
if ($token->can($ability)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return ApiError::response(
|
||||
'forbidden',
|
||||
'Forbidden',
|
||||
"Missing required ability for support {$actionLabel}.",
|
||||
403,
|
||||
['required' => $abilities]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +88,23 @@ class SupportApiRegistry
|
||||
return (bool) ($config['read_only'] ?? false);
|
||||
}
|
||||
|
||||
public static function auditAction(string $resource, string $operation): string
|
||||
{
|
||||
$config = self::get($resource);
|
||||
|
||||
$action = null;
|
||||
|
||||
if ($config && is_array($config['audit'] ?? null)) {
|
||||
$action = $config['audit'][$operation] ?? null;
|
||||
}
|
||||
|
||||
if (is_string($action) && $action !== '') {
|
||||
return $action;
|
||||
}
|
||||
|
||||
return $resource.'.'.$operation;
|
||||
}
|
||||
|
||||
public static function allowsMutation(string $resource, string $action): bool
|
||||
{
|
||||
if (self::isReadOnly($resource)) {
|
||||
|
||||
Reference in New Issue
Block a user