146 lines
4.7 KiB
PHP
146 lines
4.7 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace app\admin\model;
|
||
|
||
use Throwable;
|
||
use app\admin\library\Auth;
|
||
use app\common\model\traits\TimestampInteger;
|
||
use support\think\Model;
|
||
use Webman\Http\Request;
|
||
|
||
/**
|
||
* AdminLog 模型(Webman 迁移版)
|
||
*/
|
||
class AdminLog extends Model
|
||
{
|
||
use TimestampInteger;
|
||
|
||
protected string $table = 'admin_log';
|
||
protected string $pk = 'id';
|
||
protected bool $autoWriteTimestamp = true;
|
||
protected bool $updateTime = false;
|
||
|
||
protected string $title = '';
|
||
/** 日志内容(勿用 $data,会与 ThinkORM Model 的 data 选项冲突) */
|
||
protected string|array $logData = '';
|
||
protected array $urlIgnoreRegex = [
|
||
'/^(.*)\/(select|index|logout)$/i',
|
||
];
|
||
protected array $desensitizationRegex = [
|
||
'/(password|salt|token)/i'
|
||
];
|
||
|
||
public static function instance(?Request $request = null): self
|
||
{
|
||
$request = $request ?? (function_exists('request') ? request() : null);
|
||
if ($request !== null && isset($request->adminLog) && $request->adminLog instanceof self) {
|
||
return $request->adminLog;
|
||
}
|
||
$log = new static();
|
||
if ($request !== null) {
|
||
$request->adminLog = $log;
|
||
}
|
||
return $log;
|
||
}
|
||
|
||
public function setTitle(string $title): void
|
||
{
|
||
$this->title = $title;
|
||
}
|
||
|
||
/** 设置日志内容(BuildAdmin 控制器调用) */
|
||
public function setLogData(string|array $data): void
|
||
{
|
||
$this->logData = $data;
|
||
}
|
||
|
||
public function setUrlIgnoreRegex(array|string $regex = []): void
|
||
{
|
||
$this->urlIgnoreRegex = array_merge($this->urlIgnoreRegex, is_array($regex) ? $regex : [$regex]);
|
||
}
|
||
|
||
public function setDesensitizationRegex(array|string $regex = []): void
|
||
{
|
||
$this->desensitizationRegex = array_merge($this->desensitizationRegex, is_array($regex) ? $regex : [$regex]);
|
||
}
|
||
|
||
protected function desensitization(array|string $data): array|string
|
||
{
|
||
if (!is_array($data) || !$this->desensitizationRegex) {
|
||
return $data;
|
||
}
|
||
foreach ($data as $index => &$item) {
|
||
foreach ($this->desensitizationRegex as $reg) {
|
||
if (preg_match($reg, (string) $index)) {
|
||
$item = '***';
|
||
} elseif (is_array($item)) {
|
||
$item = $this->desensitization($item);
|
||
}
|
||
}
|
||
}
|
||
return $data;
|
||
}
|
||
|
||
public function record(string $title = '', string|array|null $data = null, ?Request $request = null): void
|
||
{
|
||
$request = $request ?? (function_exists('request') ? request() : null);
|
||
if (!$request) {
|
||
return;
|
||
}
|
||
|
||
$auth = Auth::instance();
|
||
$adminId = $auth->isLogin() ? $auth->id : 0;
|
||
$username = $auth->isLogin() ? $auth->username : ($request->get('username') ?? $request->post('username') ?? __('Unknown'));
|
||
|
||
$controllerPath = get_controller_path($request) ?? '';
|
||
$pathParts = explode('/', trim($request->path(), '/'));
|
||
$action = $pathParts[array_key_last($pathParts)] ?? '';
|
||
$path = $controllerPath . ($action ? '/' . $action : '');
|
||
|
||
foreach ($this->urlIgnoreRegex as $item) {
|
||
if (preg_match($item, $path)) {
|
||
return;
|
||
}
|
||
}
|
||
|
||
$data = $data ?: $this->logData;
|
||
if (!$data) {
|
||
$data = array_merge($request->get(), $request->post());
|
||
}
|
||
$data = $this->desensitization($data);
|
||
$title = $title ?: $this->title;
|
||
if (!$title && class_exists(\app\admin\model\AdminRule::class)) {
|
||
$controllerTitle = \app\admin\model\AdminRule::where('name', $controllerPath)->value('title');
|
||
$pathTitle = \app\admin\model\AdminRule::where('name', $path)->value('title');
|
||
$title = $pathTitle ?: __('Unknown') . '(' . $action . ')';
|
||
$title = $controllerTitle ? ($controllerTitle . '-' . $title) : $title;
|
||
}
|
||
if (!$title) {
|
||
$title = __('Unknown');
|
||
}
|
||
|
||
$url = $request->url();
|
||
$url = strlen($url) > 1500 ? substr($url, 0, 1500) : $url;
|
||
$useragent = $request->header('user-agent', '');
|
||
$useragent = strlen($useragent) > 255 ? substr($useragent, 0, 255) : $useragent;
|
||
|
||
self::create([
|
||
'admin_id' => $adminId,
|
||
'username' => $username,
|
||
'url' => $url,
|
||
'title' => $title,
|
||
'data' => !is_scalar($data) ? json_encode($data, JSON_UNESCAPED_UNICODE) : $data,
|
||
'ip' => $request->getRealIp(),
|
||
'useragent' => $useragent,
|
||
'create_time' => time(),
|
||
]);
|
||
}
|
||
|
||
public function admin()
|
||
{
|
||
return $this->belongsTo(Admin::class);
|
||
}
|
||
}
|