From e30f547891661904bda5bd35bbb19e8d4e24e1bc Mon Sep 17 00:00:00 2001 From: Hungerdream <1710233908@qq.com> Date: Tue, 28 Jul 2026 19:14:50 +0800 Subject: [PATCH 1/4] fix(ansible): harden mysql data_disk path validation Reject bare '/', path traversal ('..') and duplicated slashes ('//') in mysql_data_disk assertions to avoid deploying into unsafe directories. --- ansible/mysql-deploy.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ansible/mysql-deploy.yml b/ansible/mysql-deploy.yml index 28e5ec9..a256b6f 100644 --- a/ansible/mysql-deploy.yml +++ b/ansible/mysql-deploy.yml @@ -74,7 +74,10 @@ - topology in ['standalone', 'primary_replica', 'mgr_3'] - mysql_instance is match('^[a-z0-9][a-z0-9-]{0,62}$') - mysql_version_value in mysql_package_map - - mysql_data_disk is match('^/') + - mysql_data_disk is match('^/.+') + - mysql_data_disk != '/' + - "'..' not in mysql_data_disk" + - "'//' not in mysql_data_disk" - (mysql_port_value | int) >= 13306 - (mysql_port_value | int) <= 13999 - (mysql_memory_mb_value | int) >= 2048 From c139ed6d2f95b0ab6ee54852656b305185e00f06 Mon Sep 17 00:00:00 2001 From: Hungerdream <1710233908@qq.com> Date: Tue, 28 Jul 2026 19:14:59 +0800 Subject: [PATCH 2/4] fix(ui): remove duplicate function implementations in TaskCenter scrollToBottom and handleScroll were defined twice (verbatim), causing TS2393 duplicate implementation errors now surfaced by vue-tsc 2.x. --- frontend/src/views/task/TaskCenter.vue | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/frontend/src/views/task/TaskCenter.vue b/frontend/src/views/task/TaskCenter.vue index f229aeb..402ac67 100644 --- a/frontend/src/views/task/TaskCenter.vue +++ b/frontend/src/views/task/TaskCenter.vue @@ -240,31 +240,6 @@ function selectTask(taskId: string) { void loadLogs(taskId) } -function scrollToBottom() { - if (!autoScroll.value) return - - nextTick(() => { - if (logContainerRef.value) { - logContainerRef.value.scrollTop = logContainerRef.value.scrollHeight - } - }) -} - -function handleScroll() { - if (!logContainerRef.value) return - - const { scrollTop, scrollHeight, clientHeight } = logContainerRef.value - const distanceFromBottom = scrollHeight - scrollTop - clientHeight - - // 距离底部小于 50px 时认为在底部,恢复自动滚动 - if (distanceFromBottom < 50) { - autoScroll.value = true - } else if (distanceFromBottom > 100) { - // 用户向上滚动超过 100px 时暂停自动滚动 - autoScroll.value = false - } -} - function refreshCurrent() { void loadTasks() } From f01398cc67d774a9b316716de7aa2f041bd1a49e Mon Sep 17 00:00:00 2001 From: Hungerdream <1710233908@qq.com> Date: Tue, 28 Jul 2026 19:15:14 +0800 Subject: [PATCH 3/4] feat(ui): rework MySQL delivery workbench form and flow Rebuild the MySQL standardized delivery form in Catalog.vue: sectioned layout (scope/resources/db config/advanced params), client-generated root password with regenerate/copy, storage slider, install/data path hints, inline field validation, delivery history and task polling. Align CreateMySQLDeliveryPayload with the backend MySQLDeliveryInput contract (cpu_milli/memory_mi/storage_gi required, legacy fields optional, drop nonexistent param_template) and send mysql_root_password/mysql_admin_password as a pair so the credential shown to the user is the one actually deployed. --- frontend/src/api/delivery.ts | 46 +- frontend/src/views/service/Catalog.vue | 2025 +++++++++++++++++------- 2 files changed, 1444 insertions(+), 627 deletions(-) diff --git a/frontend/src/api/delivery.ts b/frontend/src/api/delivery.ts index 62d3f57..1e4458a 100644 --- a/frontend/src/api/delivery.ts +++ b/frontend/src/api/delivery.ts @@ -26,25 +26,26 @@ export interface CreateMySQLDeliveryPayload { mysql_port?: number data_disk: string target_host?: string - cpu_cores: number - memory_gb: number - storage_gb: number cpu_milli: number memory_mi: number storage_gi: number - param_template: string - timezone: string - lower_case_table_names: number - character_set: string - collation: string - max_connections: string | number - innodb_redo_log_capacity: string - innodb_flush_log_at_trx_commit: number - sync_binlog: number - innodb_io_capacity: number - long_query_time: number - binlog_expire_logs_seconds: number - max_binlog_size: string + cpu_cores?: number + memory_gb?: number + storage_gb?: number + timezone?: string + lower_case_table_names?: number + character_set?: string + collation?: string + max_connections?: string | number + innodb_redo_log_capacity?: string + innodb_flush_log_at_trx_commit?: number + sync_binlog?: number + innodb_io_capacity?: number + long_query_time?: number + binlog_expire_logs_seconds?: number + max_binlog_size?: string + mysql_root_password?: string + mysql_admin_password?: string } export interface DeliveryTask { @@ -83,6 +84,12 @@ export interface DeliveryTaskSnapshot { events: TaskEvent[] } +export interface DeploymentCredential { + username: string + host: string + password: string +} + export interface MySQLServiceLedgerItem { name: string datacenter: string @@ -172,6 +179,13 @@ export const deliveryApi = { method: 'POST', }) }, + + async revealCredentials(taskId: string): Promise { + const data = await authRequest(`/auth/api/v1/delivery/tasks/${encodeURIComponent(taskId)}/credentials/reveal`, { + method: 'POST', + }) + return Array.isArray(data.items) ? data.items : [] + }, } function createIdempotencyKey(payload: CreateMySQLDeliveryPayload) { diff --git a/frontend/src/views/service/Catalog.vue b/frontend/src/views/service/Catalog.vue index 2232db2..8e08636 100644 --- a/frontend/src/views/service/Catalog.vue +++ b/frontend/src/views/service/Catalog.vue @@ -42,25 +42,14 @@

任务编号 {{ taskNo }} · 当前业务线:{{ currentName }}

+ {{ deliveryStateText }} 返回目录 重置工作台
-
-
-

{{ activeService.name }} 标准化交付

- 任务编号:{{ taskNo }} · 当前业务线:{{ currentName }} -
-
- {{ deliveryStateText }} - 新建任务 -
-
-
-
正在检查未完成交付任务...
- 标准模板 + 默认基线
-
- - - - -
- -
-
-
实例架构
+
+
+ +
部署范围实例身份与运行位置
+
+
+ + + +
+ 数据库管理员密码(root) +
+ + + +
+ {{ rootPasswordError }} + 默认随机生成;交付后由数据库管理员保存,平台不提供找回。 +
+
+
+
实例架构
-
-
数据盘
-
- - - -
+
+ +
+
+ +
资源规格计算、内存与数据盘配额
-
-
运行规格
+
+ 运行规格
-
-
数据盘容量
-
- +
+
+ 硬盘容量 + 20–2000 GB · 步长 5 GB
+
+ + + GB +
+
20 GB500 GB1000 GB1500 GB2000 GB
-
-
服务端口
-
+
+ + +
+
+
安装目录{{ mysqlInstallPath }}
+
数据目录{{ mysqlDataPath }}
+ 程序安装在系统盘,数据盘只决定实例数据、日志和临时文件的落点。 +
+
+ +
+ + + 数据库配置可选,默认值已按标准基线填充 + + +
+
- + +
-
+ + +
+ + + 高级参数默认按规格自动联动 + + +
+ + + + + + + + +
+
-

架构预览

+

交付预览

{{ topologySummary }}

+ {{ selectedTarget ? '后台已匹配' : '等待后台配置' }} +
+ +
+
执行方式自动调度
+
部署主机{{ deliveryForm.targetHost || '由 AWX Inventory 分配' }}
+
数据位置{{ deliveryForm.dataDisk }}
@@ -238,7 +311,7 @@ {{ node.ip }} {{ deliveryForm.spec }} {{ node.role }} - 可用 {{ node.freeDisk }} + {{ storageLabel }} 配额
@@ -259,8 +332,7 @@

{{ deploymentId || '创建任务后生成 task_id' }} · {{ activeService.runner }} · {{ activeService.template }}

- 刷新状态 - 取消任务 + 取消任务
@@ -308,50 +380,97 @@
-
-
- 访问地址 - {{ resultAddress }} +
+
+
+
+ PRIMARY ENDPOINT +

MySQL 连接入口

+
+ {{ connectionReady ? '可连接' : '等待地址' }} +
+
{{ resultAddress }}
+

使用交付时设置的 root 管理员账号连接。

+
+ {{ mysqlCommand }} + +
+
+ 复制连接地址 + 复制连接命令 +
+ +
+
+
+ ONE-TIME CREDENTIAL +

root 管理员凭证

+
+ 仅展示一次 +
+

请立即复制或下载凭证文件;关闭后页面不再显示明文密码。

+ 查看一次性密码 +
+ {{ deliveryForm.rootPassword }} +
+ 复制密码 + 下载凭证文件 + 已保存,关闭 +
+
+
+
+ 一次性凭证已关闭 + 历史任务仍可查看连接信息,但平台不会再次展示 root 明文密码。 +
-
- 配置基线 - {{ activeService.configId }} -
-
- 资产编号 - {{ activeService.assetId }} -
-
- 健康状态 - {{ deliveryFailed ? resultSubtitle : activeService.healthText }} + +
+
+
+ INSTANCE DETAILS +

实例资源

+
+ {{ deliveryForm.version }} +
+
+
实例名称
{{ deliveryForm.instanceName }}
+
部署主机
{{ deliveredHost || 'AWX 自动分配' }}
+
运行规格
{{ deliveryForm.spec }} · {{ storageLabel }}
+
数据盘
{{ deliveryForm.dataDisk }}
+
管理账号
root · 一次性交付
+
健康状态
{{ deliveryFailed ? resultSubtitle : activeService.healthText }}
+
-
- - - - - - - - - - - - - - - - - - - - - - - -
实例组件版本架构地址状态注册系统
{{ deliveryForm.instanceName }}{{ activeService.name }}{{ deliveryForm.version }}{{ currentModeLabel }}{{ resultAddress }}{{ deliveryRolledBack ? '已回退' : deliveryAcknowledged ? '已确认释放' : deliveryRegisterFailed ? '实例保留' : deliveryFailed ? '需处理' : '正常' }}{{ activeService.registerTo }}
+
+
+
+ OPERATIONS +

运维定位信息

+
+ 任务 {{ deploymentId || taskNo }} +
+
+
本地 Socket{{ mysqlSocketPath }}
+
配置文件{{ mysqlConfigPath }}
+
systemd 服务{{ mysqlServiceName }}
+
注册系统{{ activeService.registerTo }}
+
+
+ +
+ 查看交付日志与状态事件 +
{{ deliveryLog }}
+
+ +
+
+ 需要查看历史任务或领取未消费凭证? + 交付记录已统一归档到服务管理。 +
+ 查看全部交付记录
@@ -368,11 +487,11 @@