diff --git a/app/Aspect/Admin/AdminLoginLogAspect.php b/app/Aspect/Admin/AdminLoginLogAspect.php index 26e01dd..e875d04 100644 --- a/app/Aspect/Admin/AdminLoginLogAspect.php +++ b/app/Aspect/Admin/AdminLoginLogAspect.php @@ -3,7 +3,7 @@ namespace App\Aspect\Admin; use App\Exception\AdminException; -use App\Service\Admin\User\LoginService; +use App\Service\Admin\Login\LoginService; use Hyperf\Di\Annotation\Aspect; use Hyperf\Di\Aop\AbstractAspect; use Hyperf\Di\Aop\ProceedingJoinPoint; @@ -17,7 +17,7 @@ class AdminLoginLogAspect extends AbstractAspect * @var array|\class-string[] */ public array $classes = [ -// LoginService::class, + LoginService::class, ]; /** diff --git a/app/Aspect/Admin/AdminOperationAspect.php b/app/Aspect/Admin/AdminOperationAspect.php new file mode 100644 index 0000000..7b73ad2 --- /dev/null +++ b/app/Aspect/Admin/AdminOperationAspect.php @@ -0,0 +1,91 @@ +checkAuthentication(); + + // 写操作日志 + $this->writeOperationLog(); + + // 在调用前进行处理 + return $proceedingJoinPoint->process(); + } + + /** + * @return void + */ + private function checkAuthentication(): void + { + $adminId = Context::get('admin_id'); + $roleId = Context::get('role_id'); + + //如果没有id 说明没有登录 抛出异常 + if (empty($adminId) || empty($roleId)) { + throw new AdminException('请先登录'); + } + + //超级管理员不需要鉴权 + if ($roleId == 1) return; + + //todo 其他角色需要鉴权 + } + + /** + * 写入请求日志 + * @return void + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + private function writeOperationLog(): void + { + $post = $this->request->all(); + $logParam = !$post ? '{}' : json_encode($post); + $userId = Context::get('user_id',0); + $header = json_encode($this->request->getHeaders()); + + // 写静态日志 + $this->log->requestAdminLog("\nadmin==path:{$this->request->getPathInfo()}\nuserId:$userId\nrequestData:$logParam\nheader:$header"); + } +} \ No newline at end of file diff --git a/app/Controller/Admin/LoginController.php b/app/Controller/Admin/LoginController.php index 6fa37d5..7711ea9 100644 --- a/app/Controller/Admin/LoginController.php +++ b/app/Controller/Admin/LoginController.php @@ -6,7 +6,7 @@ namespace App\Controller\Admin; use App\Controller\AbstractController; use App\Request\Admin\LoginRequest; -use App\Service\Admin\User\LoginService; +use App\Service\Admin\Login\LoginService; use Hyperf\HttpServer\Annotation\Controller; use Hyperf\HttpServer\Annotation\RequestMapping; use Hyperf\Validation\Annotation\Scene; diff --git a/app/Exception/Handler/AppExceptionHandler.php b/app/Exception/Handler/AppExceptionHandler.php index 17b5fd6..1138f75 100644 --- a/app/Exception/Handler/AppExceptionHandler.php +++ b/app/Exception/Handler/AppExceptionHandler.php @@ -12,6 +12,7 @@ declare(strict_types=1); namespace App\Exception\Handler; +use App\Lib\Log; use Hyperf\Contract\StdoutLoggerInterface; use Hyperf\ExceptionHandler\ExceptionHandler; use Hyperf\HttpMessage\Stream\SwooleStream; @@ -20,14 +21,18 @@ use Throwable; class AppExceptionHandler extends ExceptionHandler { - public function __construct(protected StdoutLoggerInterface $logger) + public function __construct(protected StdoutLoggerInterface $logger,protected Log $log) { } public function handle(Throwable $throwable, ResponseInterface $response) { - $this->logger->error(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile())); - $this->logger->error($throwable->getTraceAsString()); +// $this->logger->error(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile())); +// $this->logger->error($throwable->getTraceAsString()); + + $this->log->error(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile())); + $this->log->error($throwable->getTraceAsString()); + return $response->withHeader('Server', 'Hyperf')->withStatus(500)->withBody(new SwooleStream('Internal Server Error.')); } diff --git a/app/Lib/Log.php b/app/Lib/Log.php new file mode 100644 index 0000000..8fe77e0 --- /dev/null +++ b/app/Lib/Log.php @@ -0,0 +1,130 @@ +get(LoggerFactory::class)->get($name, $group); + } + + /** + * info级别日志 + * @param $msg + * @param array $content + * @param string $name + * @param string $group + * @return void + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + function info($msg, array $content = [],string $name = 'info',string $group = 'app'): void + { + $this->getLogger($name,$group)->info($msg,$content); + } + + /** + * debug级别日志 + * @param $msg + * @param array $content + * @param string $name + * @param string $group + * @return void + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + function debug($msg, array $content = [],string $name = 'debug',string $group = 'error'): void + { + $this->getLogger($name,$group)->debug($msg,$content); + } + + /** + * notice级别的日志 + * @param $msg + * @param array $content + * @param string $name + * @param string $group + * @return void + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + function notice($msg, array $content = [],string $name = 'notice',string $group = 'app'): void + { + $this->getLogger($name,$group)->notice($msg,$content); + } + + /** + * error级别的日志 + * @param $msg + * @param array $content + * @param string $name + * @param string $group + * @return void + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + function error($msg, array $content = [],string $name = 'error',string $group = 'error'): void + { + $this->getLogger($name,$group)->error($msg,$content); + } + + /** + * admin 请求日志 + * @param $msg + * @param string $name + * @param string $group + * @return void + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + function requestAdminLog($msg, string $name = 'info', string $group = 'request-admin'): void + { + $this->getLogger($name,$group)->info($msg); + } + + /** + * api 请求日志 + * @param $msg + * @param string $name + * @param string $group + * @return void + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + function requestApiLog($msg, string $name = 'info', string $group = 'request-api'): void + { + $this->getLogger($name,$group)->info($msg); + } + + + /** + * 用户级别的日志 + * @param int $userId + * @param string $msg + * @return void + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + function userLog(int $userId, string $msg = ''): void + { + $traces = debug_backtrace(); + $class = $traces[1] ? $traces[1]['class'] : ''; + $func = $traces[1] ? $traces[1]['function'] : ''; + $this->info("$class::$func==$userId==" . (is_string($msg) ? $msg : json_encode($msg))); + } +} \ No newline at end of file diff --git a/app/Model/AdminRole.php b/app/Model/AdminRole.php index fe73e10..6e747bc 100644 --- a/app/Model/AdminRole.php +++ b/app/Model/AdminRole.php @@ -12,7 +12,8 @@ use Hyperf\DbConnection\Model\Model; * @property string $name * @property string $remark * @property int $status - * @property string $create_time + * @property string $create_time + * @property string $update_time */ class AdminRole extends Model { diff --git a/app/Model/AdminUser.php b/app/Model/AdminUser.php index bff2586..ba10625 100644 --- a/app/Model/AdminUser.php +++ b/app/Model/AdminUser.php @@ -20,7 +20,8 @@ use Hyperf\DbConnection\Model\Model; * @property string $last_login_time * @property int $is_del * @property int $role_id - * @property string $create_time + * @property string $create_time + * @property string $update_time */ class AdminUser extends Model { @@ -43,7 +44,7 @@ class AdminUser extends Model const CREATED_AT = 'create_time'; - const UPDATED_AT = null; + const UPDATED_AT = 'update_time'; /** * @param $account diff --git a/app/Service/Admin/User/LoginService.php b/app/Service/Admin/Login/LoginService.php similarity index 98% rename from app/Service/Admin/User/LoginService.php rename to app/Service/Admin/Login/LoginService.php index b782418..daf2657 100644 --- a/app/Service/Admin/User/LoginService.php +++ b/app/Service/Admin/Login/LoginService.php @@ -8,7 +8,7 @@ declare(strict_types=1); -namespace App\Service\Admin\User; +namespace App\Service\Admin\Login; use App\Cache\Redis\Admin\UserCache; use App\Constants\Admin\UserCode; @@ -18,7 +18,6 @@ use App\Extend\SystemUtil; use App\Lib\Crypto\CryptoFactory; use App\Model\AdminUser; use App\Service\Admin\BaseService; -use Exception; use Hyperf\Di\Annotation\Inject; use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface; diff --git a/app/Service/Admin/User/RoleService.php b/app/Service/Admin/User/RoleService.php index e00e95c..cd4bb98 100644 --- a/app/Service/Admin/User/RoleService.php +++ b/app/Service/Admin/User/RoleService.php @@ -11,6 +11,7 @@ declare(strict_types=1); namespace App\Service\Admin\User; use App\Exception\AdminException; +use App\Lib\Log; use App\Model\AdminRole; use App\Service\Admin\BaseService; use Exception; @@ -25,7 +26,11 @@ class RoleService extends BaseService #[Inject] protected AdminRole $adminRoleModel; - private string $field = 'id as role_id, name, remark, status, created_at, updated_at'; + /** + * 查询字段 + * @var array|string[] + */ + private array $field = ['id as role_id', 'name', 'remark', 'status', 'create_time']; /** * 列表 diff --git a/config/autoload/aspects.php b/config/autoload/aspects.php index f46bd96..5f1fc41 100644 --- a/config/autoload/aspects.php +++ b/config/autoload/aspects.php @@ -10,4 +10,5 @@ declare(strict_types=1); * @license https://github.com/hyperf/hyperf/blob/master/LICENSE */ return [ + App\Aspect\Admin\AdminOperationAspect::class, ]; diff --git a/config/autoload/logger.php b/config/autoload/logger.php index ee4691f..76c8f9f 100644 --- a/config/autoload/logger.php +++ b/config/autoload/logger.php @@ -27,4 +27,76 @@ return [ ], ], ], + 'app' => [ + 'handler' => [ + 'class' => Monolog\Handler\RotatingFileHandler::class, + 'constructor' => [ + 'filename' => BASE_PATH . '/runtime/logs/info/hyperf.log', + 'level' => Monolog\Logger::DEBUG, + ], + ], + 'formatter' => [ + 'class' => Monolog\Formatter\LineFormatter::class, + 'constructor' => [ + 'format' => null, + 'dateFormat' => null, + 'allowInlineLineBreaks' => true, + 'ignoreEmptyContextAndExtra' => true, + ], + ], + ], + 'error' => [ + 'handler' => [ + 'class' => Monolog\Handler\RotatingFileHandler::class, + 'constructor' => [ + 'filename' => BASE_PATH . '/runtime/logs/error/hyperf-error.log', + 'level' => Monolog\Logger::DEBUG, + ], + ], + 'formatter' => [ + 'class' => Monolog\Formatter\LineFormatter::class, + 'constructor' => [ + 'format' => null, + 'dateFormat' => null, + 'allowInlineLineBreaks' => true, + 'ignoreEmptyContextAndExtra' => true, + ], + ], + ], + 'request-admin' => [ + 'handler' => [ + 'class' => Monolog\Handler\RotatingFileHandler::class, + 'constructor' => [ + 'filename' => BASE_PATH . '/runtime/logs/request/hyperf-admin.log', + 'level' => Monolog\Logger::DEBUG, + ], + ], + 'formatter' => [ + 'class' => Monolog\Formatter\LineFormatter::class, + 'constructor' => [ + 'format' => null, + 'dateFormat' => null, + 'allowInlineLineBreaks' => true, + 'ignoreEmptyContextAndExtra' => true, + ], + ], + ], + 'request-api' => [ + 'handler' => [ + 'class' => Monolog\Handler\RotatingFileHandler::class, + 'constructor' => [ + 'filename' => BASE_PATH . '/runtime/logs/request/hyperf-api.log', + 'level' => Monolog\Logger::DEBUG, + ], + ], + 'formatter' => [ + 'class' => Monolog\Formatter\LineFormatter::class, + 'constructor' => [ + 'format' => null, + 'dateFormat' => null, + 'allowInlineLineBreaks' => true, + 'ignoreEmptyContextAndExtra' => true, + ], + ], + ], ]; diff --git a/sync/database/admin.sql b/sync/database/admin.sql index e195eaa..0f74110 100644 --- a/sync/database/admin.sql +++ b/sync/database/admin.sql @@ -20,7 +20,8 @@ CREATE TABLE `app_admin_user` ( `last_login_time` datetime NOT NULL COMMENT '最后登录时间', `is_del` tinyint(1) NOT NULL DEFAULT '1' COMMENT '用户状态 1 正常 2 删除 涉及到后台操作日志表', `role_id` tinyint(1) NOT NULL DEFAULT '0' COMMENT '角色', - `create_time` datetime NOT NULL COMMENT '创建时间', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC COMMENT='后台用户表'; @@ -32,6 +33,7 @@ CREATE TABLE `app_admin_role` ( `remark` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '备注', `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1=正常 2=禁用', `create_time` datetime DEFAULT NULL, + `update_time` datetime DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;