Phase 1: DB 기반 구축 - trigger_audit_logs 테이블 (RANGE 파티셔닝 15개, 3개 인덱스) - 789개 MySQL AFTER 트리거 (263 테이블 × INSERT/UPDATE/DELETE) - SetAuditSessionVariables 미들웨어 (@sam_actor_id, @sam_session_info) Phase 2: 복구 메커니즘 - TriggerAuditLog 모델, TriggerAuditLogService, AuditRollbackService - 6개 API 엔드포인트 (index, show, stats, history, rollback-preview, rollback) - FormRequest 검증 (TriggerAuditLogIndexRequest, TriggerAuditRollbackRequest) Phase 3: 관리 도구 - v_unified_audit VIEW (APP + TRIGGER 통합, COLLATE 처리) - audit:partitions 커맨드 (파티션 추가/삭제, dry-run) - audit:triggers 커맨드 (트리거 재생성, 테이블별/전체) - 월 1회 파티션 자동 관리 스케줄러 등록 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
75 lines
1.6 KiB
PHP
75 lines
1.6 KiB
PHP
<?php
|
|
|
|
namespace App\Models\Audit;
|
|
|
|
use Illuminate\Database\Eloquent\Model;
|
|
|
|
class TriggerAuditLog extends Model
|
|
{
|
|
public $timestamps = false;
|
|
|
|
protected $table = 'trigger_audit_logs';
|
|
|
|
protected $fillable = [
|
|
'table_name',
|
|
'row_id',
|
|
'dml_type',
|
|
'old_values',
|
|
'new_values',
|
|
'changed_columns',
|
|
'tenant_id',
|
|
'actor_id',
|
|
'session_info',
|
|
'db_user',
|
|
'created_at',
|
|
];
|
|
|
|
protected $casts = [
|
|
'old_values' => 'array',
|
|
'new_values' => 'array',
|
|
'changed_columns' => 'array',
|
|
'created_at' => 'datetime',
|
|
];
|
|
|
|
/**
|
|
* changed_columns에서 NULL 값 필터링
|
|
*/
|
|
public function getChangedColumnsAttribute($value): ?array
|
|
{
|
|
$decoded = is_string($value) ? json_decode($value, true) : $value;
|
|
|
|
if (! is_array($decoded)) {
|
|
return null;
|
|
}
|
|
|
|
return array_values(array_filter($decoded, fn ($v) => $v !== null));
|
|
}
|
|
|
|
/**
|
|
* session_info JSON 디코딩
|
|
*/
|
|
public function getSessionInfoAttribute($value): ?array
|
|
{
|
|
if (is_string($value)) {
|
|
return json_decode($value, true);
|
|
}
|
|
|
|
return $value;
|
|
}
|
|
|
|
public function scopeForTable($query, string $tableName)
|
|
{
|
|
return $query->where('table_name', $tableName);
|
|
}
|
|
|
|
public function scopeForRecord($query, string $tableName, string $rowId)
|
|
{
|
|
return $query->where('table_name', $tableName)->where('row_id', $rowId);
|
|
}
|
|
|
|
public function scopeForTenant($query, int $tenantId)
|
|
{
|
|
return $query->where('tenant_id', $tenantId);
|
|
}
|
|
}
|