36 lines
1.8 KiB
PHP
36 lines
1.8 KiB
PHP
<?php
|
|
defined('BASEPATH') OR exit('No direct script access allowed');
|
|
|
|
class AuditService
|
|
{
|
|
private $CI;
|
|
public function __construct() { $this->CI =& get_instance(); }
|
|
|
|
public function record($module, $entityType, $entityId, $action, $before = null, $after = null, $userId = null)
|
|
{
|
|
$previous = $this->CI->db->select('record_hash')->order_by('id','DESC')->limit(1)->get('immutable_audit_logs')->row();
|
|
$created = date('Y-m-d H:i:s');
|
|
$data = array(
|
|
'module'=>(string)$module, 'entity_type'=>(string)$entityType, 'entity_id'=>(string)$entityId,
|
|
'action'=>(string)$action, 'before_data'=>$this->encode($before), 'after_data'=>$this->encode($after),
|
|
'user_id'=>$userId ? (int)$userId : null,
|
|
'ip_address'=>isset($this->CI->input) ? $this->CI->input->ip_address() : null,
|
|
'user_agent'=>isset($this->CI->input) ? substr((string)$this->CI->input->user_agent(),0,255) : null,
|
|
'request_id'=>app_env('HTTP_X_REQUEST_ID', null) ?: null,
|
|
'previous_hash'=>$previous ? $previous->record_hash : null, 'created_at'=>$created
|
|
);
|
|
$data['record_hash'] = hash('sha256', ($data['previous_hash'] ?: '') . json_encode($data, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES));
|
|
if (!$this->CI->db->insert('immutable_audit_logs', $data)) throw new RuntimeException('Gagal menulis audit trail.');
|
|
return (int)$this->CI->db->insert_id();
|
|
}
|
|
|
|
private function encode($value)
|
|
{
|
|
if ($value === null) return null;
|
|
$value = json_decode(json_encode($value), true);
|
|
$walk = function (&$item, $key) { if (preg_match('/password|token|secret|authorization/i', (string)$key)) $item = '[REDACTED]'; };
|
|
array_walk_recursive($value, $walk);
|
|
return json_encode($value, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
|
|
}
|
|
}
|