-- 015_server_security.sql -- 服务器安全监控日志:建表 + 菜单/权限种子。 -- 依赖:service 主库;admin_menu / admin_role_menu 已存在。 -- 幂等:CREATE TABLE IF NOT EXISTS + INSERT ... ON DUPLICATE KEY UPDATE + INSERT IGNORE,可重复执行。 -- ============ 1) 安全日志表 ============ CREATE TABLE IF NOT EXISTS `server_security_log` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `log_time` DATETIME NOT NULL COMMENT '事件发生时间', `src_ip` VARCHAR(45) NOT NULL DEFAULT '' COMMENT '来源IP(含IPv6)', `src_port` INT NOT NULL DEFAULT 0 COMMENT '来源端口', `dest_port` INT NOT NULL DEFAULT 0 COMMENT '目标端口(如22025)', `event_type` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '事件类型 failed_ssh/accepted_ssh/banned/unbanned', `detail` VARCHAR(500) NOT NULL DEFAULT '' COMMENT '日志详情/原文', `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_time` (`log_time`), KEY `idx_ip` (`src_ip`), KEY `idx_type` (`event_type`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='服务器安全监控日志(宿主机采集上报)'; -- ============ 2) 菜单:挂到「系统监控」(id=5) 下 ============ INSERT INTO admin_menu (id, parent_id, name, icon, type, path, component, permission, sort, status, hidden, created_at, updated_at) VALUES (96, 5, '安全日志', 'mdi:shield-alert-outline', 1, 'security', 'monitor/security/index', 'server:security', 2, 1, 0, NOW(), NOW()) ON DUPLICATE KEY UPDATE parent_id=VALUES(parent_id), name=VALUES(name), icon=VALUES(icon), type=VALUES(type), path=VALUES(path), component=VALUES(component), permission=VALUES(permission), sort=VALUES(sort), status=VALUES(status), hidden=VALUES(hidden), deleted_at=NULL; -- ============ 3) API 权限(type=2,path 必须与实际路由一致) ============ INSERT INTO admin_menu (id, parent_id, name, icon, type, path, component, permission, sort, status, hidden, created_at, updated_at) VALUES (960, 96, '查询', '', 2, 'POST /api/service/admin/server-security/log/list', '', 'server:security:list', 1, 1, 0, NOW(), NOW()), (961, 96, '统计', '', 2, 'POST /api/service/admin/server-security/log/stats', '', 'server:security:stats', 2, 1, 0, NOW(), NOW()) ON DUPLICATE KEY UPDATE parent_id=VALUES(parent_id), name=VALUES(name), type=VALUES(type), path=VALUES(path), permission=VALUES(permission), sort=VALUES(sort), status=VALUES(status), hidden=VALUES(hidden), deleted_at=NULL; -- ============ 4) 超管角色绑定 ============ INSERT IGNORE INTO admin_role_menu (role_id, menu_id, created_at, updated_at) SELECT 1, id, NOW(), NOW() FROM admin_menu WHERE id IN (96, 960, 961);