From d2e08d341cc4492882aec8a9ad6575de593ff19c Mon Sep 17 00:00:00 2001 From: BugsGuru Date: Thu, 26 Mar 2026 14:50:59 +0800 Subject: [PATCH 1/5] feat(locale): add maintenance time block message for SQL Workbench in English and Chinese --- internal/pkg/locale/active.en.toml | 1 + internal/pkg/locale/active.zh.toml | 1 + internal/pkg/locale/message_zh.go | 5 +++++ 3 files changed, 7 insertions(+) diff --git a/internal/pkg/locale/active.en.toml b/internal/pkg/locale/active.en.toml index 7efe81a9..c828dfc8 100644 --- a/internal/pkg/locale/active.en.toml +++ b/internal/pkg/locale/active.en.toml @@ -209,6 +209,7 @@ ProjectName = "Project name" ProjectNotAvailable = "Unavailable" ProjectStatus = "Project status" SqlWorkbenchAuditCallSQLEErr = "The audit service is busy or unavailable. Please try again later." +SqlWorkbenchMaintenanceTimeBlocked = "Currently outside maintenance window (maintenance hours: %s). Non-query operations are prohibited. Please operate during maintenance hours or submit a change request." SqlWorkbenchAuditDBServiceMappingNotFoundErr = "Current data source was not found. Please confirm it exists, reselect it, and try again." SqlWorkbenchAuditGetDBServiceErr = "Current data source configuration was not found. Please confirm the data source exists and try again." SqlWorkbenchAuditGetDBServiceMappingErr = "We couldn't get the current data source information. Please reselect the data source and try again." diff --git a/internal/pkg/locale/active.zh.toml b/internal/pkg/locale/active.zh.toml index ae65b793..23f55bc9 100644 --- a/internal/pkg/locale/active.zh.toml +++ b/internal/pkg/locale/active.zh.toml @@ -209,6 +209,7 @@ ProjectName = "项目名称" ProjectNotAvailable = "不可用" ProjectStatus = "项目状态" SqlWorkbenchAuditCallSQLEErr = "审核服务当前繁忙或不可用,请稍后重试。" +SqlWorkbenchMaintenanceTimeBlocked = "当前处于非运维时间(运维时间:%s),禁止执行非查询类操作。请在运维时间内操作或提交上线工单。" SqlWorkbenchAuditDBServiceMappingNotFoundErr = "未找到当前数据源,请确认数据源存在并重新选择后重试。" SqlWorkbenchAuditGetDBServiceErr = "未找到当前数据源配置,请确认数据源存在后重试。" SqlWorkbenchAuditGetDBServiceMappingErr = "当前数据源信息获取失败,请重新选择数据源后重试。" diff --git a/internal/pkg/locale/message_zh.go b/internal/pkg/locale/message_zh.go index 87c9c9a8..371c15f7 100644 --- a/internal/pkg/locale/message_zh.go +++ b/internal/pkg/locale/message_zh.go @@ -195,6 +195,11 @@ var ( SqlWorkbenchAuditCallSQLEErr = &i18n.Message{ID: "SqlWorkbenchAuditCallSQLEErr", Other: "审核服务当前繁忙或不可用,请稍后重试。"} ) +// SQL Workbench Maintenance Time +var ( + SqlWorkbenchMaintenanceTimeBlocked = &i18n.Message{ID: "SqlWorkbenchMaintenanceTimeBlocked", Other: "当前处于非运维时间(运维时间:%s),禁止执行非查询类操作。请在运维时间内操作或提交上线工单。"} +) + // DB Service Sync Task var ( DBServiceSyncVersion = &i18n.Message{ID: "DBServiceSyncVersion", Other: "版本(支持DMP5.23.04.0及以上版本)"} From bf3121dd592441265edef8f03471974450a8b0fe Mon Sep 17 00:00:00 2001 From: BugsGuru Date: Thu, 26 Mar 2026 14:51:18 +0800 Subject: [PATCH 2/5] feat(sql-query-config): add MaintenancePeriods field to SQLEConfig and update conversion functions - Introduced MaintenancePeriods to the SqlQueryConfig struct for enhanced scheduling capabilities. - Updated conversion functions to include MaintenancePeriods when converting between biz and model representations. - Added logging for db service model conversion to assist in debugging. --- internal/dms/storage/convert.go | 26 ++++++++++++++----------- internal/dms/storage/model/model.go | 25 ++++++++++++------------ pkg/dms-common/api/dms/v1/db_service.go | 1 + 3 files changed, 29 insertions(+), 23 deletions(-) diff --git a/internal/dms/storage/convert.go b/internal/dms/storage/convert.go index 2199833c..598be415 100644 --- a/internal/dms/storage/convert.go +++ b/internal/dms/storage/convert.go @@ -83,6 +83,7 @@ func convertBizDBService(ds *biz.DBService) (*model.DBService, error) { QueryTimeoutSecond: sqleQueryConfig.QueryTimeoutSecond, RuleTemplateName: sqleQueryConfig.RuleTemplateName, RuleTemplateID: sqleQueryConfig.RuleTemplateID, + MaintenancePeriods: sqleQueryConfig.MaintenancePeriods, } } } @@ -154,6 +155,7 @@ func convertModelDBService(ds *model.DBService) (*biz.DBService, error) { QueryTimeoutSecond: sqleQueryConfig.QueryTimeoutSecond, RuleTemplateName: sqleQueryConfig.RuleTemplateName, RuleTemplateID: sqleQueryConfig.RuleTemplateID, + MaintenancePeriods: sqleQueryConfig.MaintenancePeriods, } dbService.SQLEConfig.SQLQueryConfig = sqc } @@ -989,22 +991,22 @@ func convertBizCompanyNotice(b *biz.CompanyNotice) (*model.CompanyNotice, error) UID: b.UID, }, CreateUserUID: b.CreateUserUID, - NoticeStr: b.NoticeStr, - ReadUserIds: b.ReadUserIds, - StartTime: b.StartTime, - EndTime: b.EndTime, + NoticeStr: b.NoticeStr, + ReadUserIds: b.ReadUserIds, + StartTime: b.StartTime, + EndTime: b.EndTime, }, nil } func convertModelCompanyNotice(m *model.CompanyNotice) (*biz.CompanyNotice, error) { p := &biz.CompanyNotice{ - Base: convertBase(m.Model), - UID: m.UID, - CreateUserUID: m.CreateUserUID, - NoticeStr: m.NoticeStr, - ReadUserIds: m.ReadUserIds, - StartTime: m.StartTime, - EndTime: m.EndTime, + Base: convertBase(m.Model), + UID: m.UID, + CreateUserUID: m.CreateUserUID, + NoticeStr: m.NoticeStr, + ReadUserIds: m.ReadUserIds, + StartTime: m.StartTime, + EndTime: m.EndTime, } return p, nil @@ -1331,6 +1333,7 @@ func toModelDBServiceSyncTask(u *biz.DBServiceSyncTask) *model.DBServiceSyncTask AllowQueryWhenLessThanAuditLevel: u.SQLEConfig.SQLQueryConfig.AllowQueryWhenLessThanAuditLevel, RuleTemplateName: u.SQLEConfig.SQLQueryConfig.RuleTemplateName, RuleTemplateID: u.SQLEConfig.SQLQueryConfig.RuleTemplateID, + MaintenancePeriods: u.SQLEConfig.SQLQueryConfig.MaintenancePeriods, } } } @@ -1370,6 +1373,7 @@ func toBizDBServiceSyncTask(m *model.DBServiceSyncTask) *biz.DBServiceSyncTask { AllowQueryWhenLessThanAuditLevel: m.ExtraParameters.SqleConfig.SqlQueryConfig.AllowQueryWhenLessThanAuditLevel, RuleTemplateName: m.ExtraParameters.SqleConfig.SqlQueryConfig.RuleTemplateName, RuleTemplateID: m.ExtraParameters.SqleConfig.SqlQueryConfig.RuleTemplateID, + MaintenancePeriods: m.ExtraParameters.SqleConfig.SqlQueryConfig.MaintenancePeriods, } } } diff --git a/internal/dms/storage/model/model.go b/internal/dms/storage/model/model.go index 422c7756..c9a71089 100644 --- a/internal/dms/storage/model/model.go +++ b/internal/dms/storage/model/model.go @@ -122,13 +122,14 @@ type SQLEConfig struct { SqlQueryConfig *SqlQueryConfig `json:"sql_query_config"` } type SqlQueryConfig struct { - MaxPreQueryRows int `json:"max_pre_query_rows"` - QueryTimeoutSecond int `json:"query_timeout_second"` - AuditEnabled bool `json:"audit_enabled"` - WorkflowExecEnabled bool `json:"workflow_exec_enabled"` - AllowQueryWhenLessThanAuditLevel string `json:"allow_query_when_less_than_audit_level"` - RuleTemplateID string `json:"rule_template_id"` - RuleTemplateName string `json:"rule_template_name"` + MaxPreQueryRows int `json:"max_pre_query_rows"` + QueryTimeoutSecond int `json:"query_timeout_second"` + AuditEnabled bool `json:"audit_enabled"` + WorkflowExecEnabled bool `json:"workflow_exec_enabled"` + AllowQueryWhenLessThanAuditLevel string `json:"allow_query_when_less_than_audit_level"` + RuleTemplateID string `json:"rule_template_id"` + RuleTemplateName string `json:"rule_template_name"` + MaintenancePeriods periods.Periods `json:"maintenance_periods"` } type User struct { @@ -438,11 +439,11 @@ type BasicConfig struct { type CompanyNotice struct { Model - CreateUserUID string `json:"create_user_uid" gorm:"column:create_user_uid;size:32;comment:'创建人uid'"` - NoticeStr string `gorm:"type:mediumtext;comment:'企业公告'" json:"notice_str"` - ReadUserIds ReadUsers `gorm:"type:longtext" json:"read_user_ids"` - StartTime *time.Time `json:"start_time" gorm:"column:start_time;comment:'公告开始时间'"` - EndTime *time.Time `json:"end_time" gorm:"column:end_time;comment:'公告结束时间'"` + CreateUserUID string `json:"create_user_uid" gorm:"column:create_user_uid;size:32;comment:'创建人uid'"` + NoticeStr string `gorm:"type:mediumtext;comment:'企业公告'" json:"notice_str"` + ReadUserIds ReadUsers `gorm:"type:longtext" json:"read_user_ids"` + StartTime *time.Time `json:"start_time" gorm:"column:start_time;comment:'公告开始时间'"` + EndTime *time.Time `json:"end_time" gorm:"column:end_time;comment:'公告结束时间'"` } type ReadUsers []string diff --git a/pkg/dms-common/api/dms/v1/db_service.go b/pkg/dms-common/api/dms/v1/db_service.go index 444815ed..e928b60e 100644 --- a/pkg/dms-common/api/dms/v1/db_service.go +++ b/pkg/dms-common/api/dms/v1/db_service.go @@ -206,6 +206,7 @@ type SQLQueryConfig struct { AllowQueryWhenLessThanAuditLevel SQLAllowQueryAuditLevel `json:"allow_query_when_less_than_audit_level" enums:"normal,notice,warn,error" valid:"omitempty,oneof=normal notice warn error " example:"error"` RuleTemplateName string `json:"rule_template_name"` RuleTemplateID string `json:"rule_template_id"` + MaintenanceTimes []*MaintenanceTime `json:"maintenance_times"` // 允许执行非 DQL 的运维时间窗口,与数据源 maintenance_times 结构一致 } // swagger:model ListDBServiceReply From c6f728ec474eee4fccc33c1f8b568d9487d9360b Mon Sep 17 00:00:00 2001 From: BugsGuru Date: Thu, 26 Mar 2026 14:51:31 +0800 Subject: [PATCH 3/5] feat(maintenance-time): implement maintenance time control logic and integrate with CloudbeaverUsecase - Added MaintenanceTimeUsecase for managing maintenance time checks during SQL execution. - Integrated maintenance time checks into CloudbeaverUsecase's GraphQLDistributor method. - Updated SQLQueryConfig to include MaintenancePeriods for enhanced scheduling capabilities. - Introduced new methods for checking SQL execution permissions based on maintenance time configurations. --- internal/dms/biz/cloudbeaver.go | 49 ++++++++++- internal/dms/biz/db_service.go | 15 ++-- internal/dms/biz/maintenance_time.go | 121 +++++++++++++++++++++++++++ 3 files changed, 177 insertions(+), 8 deletions(-) create mode 100644 internal/dms/biz/maintenance_time.go diff --git a/internal/dms/biz/cloudbeaver.go b/internal/dms/biz/cloudbeaver.go index 6378abe7..ba6d9cfe 100644 --- a/internal/dms/biz/cloudbeaver.go +++ b/internal/dms/biz/cloudbeaver.go @@ -89,9 +89,10 @@ type CloudbeaverUsecase struct { projectUsecase *ProjectUsecase repo CloudbeaverRepo proxyTargetRepo ProxyTargetRepo + maintenanceTimeUsecase *MaintenanceTimeUsecase } -func NewCloudbeaverUsecase(log utilLog.Logger, cfg *CloudbeaverCfg, userUsecase *UserUsecase, dbServiceUsecase *DBServiceUsecase, opPermissionVerifyUsecase *OpPermissionVerifyUsecase, dmsConfigUseCase *DMSConfigUseCase, dataMaskingUseCase *DataMaskingUsecase, cloudbeaverRepo CloudbeaverRepo, proxyTargetRepo ProxyTargetRepo, cbOperationUseDase *CbOperationLogUsecase, projectUsecase *ProjectUsecase) (cu *CloudbeaverUsecase) { +func NewCloudbeaverUsecase(log utilLog.Logger, cfg *CloudbeaverCfg, userUsecase *UserUsecase, dbServiceUsecase *DBServiceUsecase, opPermissionVerifyUsecase *OpPermissionVerifyUsecase, dmsConfigUseCase *DMSConfigUseCase, dataMaskingUseCase *DataMaskingUsecase, cloudbeaverRepo CloudbeaverRepo, proxyTargetRepo ProxyTargetRepo, cbOperationUseDase *CbOperationLogUsecase, projectUsecase *ProjectUsecase, maintenanceTimeUsecase *MaintenanceTimeUsecase) (cu *CloudbeaverUsecase) { cu = &CloudbeaverUsecase{ repo: cloudbeaverRepo, proxyTargetRepo: proxyTargetRepo, @@ -104,6 +105,7 @@ func NewCloudbeaverUsecase(log utilLog.Logger, cfg *CloudbeaverCfg, userUsecase projectUsecase: projectUsecase, cloudbeaverCfg: cfg, log: utilLog.NewHelper(log, utilLog.WithMessageKey("biz.cloudbeaver")), + maintenanceTimeUsecase: maintenanceTimeUsecase, } // 启动缓存清理协程 @@ -629,6 +631,11 @@ func (cu *CloudbeaverUsecase) GraphQLDistributor() echo.MiddlewareFunc { return nil, c.JSON(http.StatusOK, convertToResp(ctx, resp)) } + // [运维时间管控检查] 在审核通过后、工单判断前检查运维时间管控 + if blocked, err := cu.checkMaintenanceTime(c, resp.Results, dbService); blocked || err != nil { + return nil, err + } + // 判断是否需要通过工单执行(非 DQL 语句) if cu.shouldExecuteByWorkflow(dbService, resp.Results) { return cu.executeNonDQLByWorkflow(ctx, c, dbService, params, resp) @@ -2067,6 +2074,46 @@ func (cu *CloudbeaverUsecase) shouldExecuteByWorkflow(dbService *DBService, audi return false } +// checkMaintenanceTime 检查运维时间管控(CloudBeaver工作台) +// 返回 blocked=true 表示已构造拦截响应,调用方应立即返回 +func (cu *CloudbeaverUsecase) checkMaintenanceTime(c echo.Context, auditResults []cloudbeaver.AuditSQLResV2, dbService *DBService) (blocked bool, err error) { + if cu.maintenanceTimeUsecase == nil { + return false, fmt.Errorf("maintenance time usecase is nil") + } + + currentUserUid, _ := c.Get(dmsUserIdKey).(string) + if currentUserUid == "" { + return false, fmt.Errorf("current user uid is empty") + } + + sqlTypes := make([]string, 0, len(auditResults)) + for _, r := range auditResults { + sqlTypes = append(sqlTypes, r.SQLType) + } + + var sqlQueryConfig *SQLQueryConfig + if dbService != nil && dbService.SQLEConfig != nil { + sqlQueryConfig = dbService.SQLEConfig.SQLQueryConfig + } + + allowed, message, checkErr := cu.maintenanceTimeUsecase.CheckSQLExecutionAllowed( + c.Request().Context(), + currentUserUid, + sqlTypes, + time.Now(), + sqlQueryConfig, + ) + if checkErr != nil { + cu.log.Errorf("check maintenance time failed: %v", checkErr) + return false, checkErr + } + if !allowed { + return true, c.JSON(http.StatusOK, + newResp(c.Request().Context(), "Maintenance Time Blocked", CBErrorCode, message)) + } + return false, nil +} + // workflowExecParams 工单执行所需的参数 type workflowExecParams struct { contextIdStr string diff --git a/internal/dms/biz/db_service.go b/internal/dms/biz/db_service.go index 7350d9d1..58e56393 100644 --- a/internal/dms/biz/db_service.go +++ b/internal/dms/biz/db_service.go @@ -223,13 +223,14 @@ type BizDBServiceArgs struct { } type SQLQueryConfig struct { - MaxPreQueryRows int `json:"max_pre_query_rows"` - QueryTimeoutSecond int `json:"query_timeout_second"` - AuditEnabled bool `json:"audit_enabled"` - WorkflowExecEnabled bool `json:"workflow_exec_enabled"` - AllowQueryWhenLessThanAuditLevel string `json:"allow_query_when_less_than_audit_level"` - RuleTemplateID string `json:"rule_template_id"` - RuleTemplateName string `json:"rule_template_name"` + MaxPreQueryRows int `json:"max_pre_query_rows"` + QueryTimeoutSecond int `json:"query_timeout_second"` + AuditEnabled bool `json:"audit_enabled"` + WorkflowExecEnabled bool `json:"workflow_exec_enabled"` + AllowQueryWhenLessThanAuditLevel string `json:"allow_query_when_less_than_audit_level"` + RuleTemplateID string `json:"rule_template_id"` + RuleTemplateName string `json:"rule_template_name"` + MaintenancePeriods pkgPeriods.Periods `json:"maintenance_periods"` } func (d *DBServiceUsecase) CreateDBService(ctx context.Context, args *BizDBServiceArgs, currentUserUid string) (uid string, err error) { diff --git a/internal/dms/biz/maintenance_time.go b/internal/dms/biz/maintenance_time.go new file mode 100644 index 00000000..49322e25 --- /dev/null +++ b/internal/dms/biz/maintenance_time.go @@ -0,0 +1,121 @@ +package biz + +import ( + "context" + "fmt" + "strings" + "time" + + "github.com/actiontech/dms/internal/pkg/locale" + pkgPeriods "github.com/actiontech/dms/pkg/periods" + + utilLog "github.com/actiontech/dms/pkg/dms-common/pkg/log" +) + +// MaintenanceTimeConfig 运维时间管控配置 +type MaintenanceTimeConfig struct { + Enabled bool + Periods pkgPeriods.Periods +} + +// MaintenanceTimeUsecase 运维时间管控业务逻辑 +type MaintenanceTimeUsecase struct { + opPermissionVerifyUsecase *OpPermissionVerifyUsecase + log *utilLog.Helper +} + +// NewMaintenanceTimeUsecase 创建运维时间管控业务逻辑实例 +func NewMaintenanceTimeUsecase( + log utilLog.Logger, + opPermissionVerifyUsecase *OpPermissionVerifyUsecase, +) *MaintenanceTimeUsecase { + return &MaintenanceTimeUsecase{ + opPermissionVerifyUsecase: opPermissionVerifyUsecase, + log: utilLog.NewHelper(log, utilLog.WithMessageKey("biz.maintenance_time")), + } +} + +// MaintenanceTimeConfigFromSQLQuery 从数据源 sql_query_config 解析运维时间管控配置 +func MaintenanceTimeConfigFromSQLQuery(sqlQueryConfig *SQLQueryConfig) *MaintenanceTimeConfig { + cfg := &MaintenanceTimeConfig{} + if sqlQueryConfig == nil { + return cfg + } + cfg.Enabled = len(sqlQueryConfig.MaintenancePeriods) > 0 + if cfg.Enabled { + cfg.Periods = sqlQueryConfig.MaintenancePeriods.Copy() + } + return cfg +} + +// CheckSQLExecutionAllowed 检查SQL执行是否被运维时间管控允许 +// 参数: +// - userUid: 当前执行SQL的用户UID +// - sqlTypes: SQLE审核返回的sql_type列表(每条SQL对应一个) +// - currentTime: 当前时间(参数化便于测试) +// - sqlQueryConfig: 数据源上的 SQL 查询配置(含运维时间窗口) +// +// 返回值: +// - allowed: 是否允许执行 +// - message: 拦截时的提示消息(allowed=true时为空) +// - err: 内部错误 +func (m *MaintenanceTimeUsecase) CheckSQLExecutionAllowed( + ctx context.Context, + userUid string, + sqlTypes []string, + currentTime time.Time, + sqlQueryConfig *SQLQueryConfig, +) (allowed bool, message string, err error) { + // 1. 获取配置 + config := MaintenanceTimeConfigFromSQLQuery(sqlQueryConfig) + + // 2. 如果开关关闭,直接允许执行 + if !config.Enabled { + return true, "", nil + } + + // 3. 检查 sqlTypes 中是否有非DQL语句 + hasNonDQL := false + for _, sqlType := range sqlTypes { + if sqlType != "dql" { // 空字符串("")也视为非DQL(保守策略) + hasNonDQL = true + break + } + } + if !hasNonDQL { + return true, "", nil + } + + // 4. 检查用户是否为管理员 + isAdmin, err := m.opPermissionVerifyUsecase.CanOpGlobal(ctx, userUid) + if err != nil { + return false, "", fmt.Errorf("failed to check user admin permission: %v", err) + } + if isAdmin { + m.log.Warnf("user %s is admin, skip cloudbeaver maintenance time check", userUid) + return true, "", nil + } + + // 5. 检查当前时间是否在配置的运维时间段内 + if config.Periods.IsWithinScope(currentTime) { + return true, "", nil + } + + // 6. 构造拦截消息 + periodsStr := formatPeriodsToReadableString(config.Periods) + message = fmt.Sprintf(locale.Bundle.LocalizeMsgByCtx(ctx, locale.SqlWorkbenchMaintenanceTimeBlocked), periodsStr) + + // 7. 返回拦截结果 + return false, message, nil +} + +// formatPeriodsToReadableString 将时间段格式化为可读字符串 +// 例如: "01:00-06:00, 22:00-02:00" +func formatPeriodsToReadableString(ps pkgPeriods.Periods) string { + parts := make([]string, 0, len(ps)) + for _, p := range ps { + parts = append(parts, fmt.Sprintf("%02d:%02d-%02d:%02d", + p.StartHour, p.StartMinute, p.EndHour, p.EndMinute)) + } + return strings.Join(parts, ", ") +} From 35f8f5a9701b3c55705629ad36e4faf11bd8f3ca Mon Sep 17 00:00:00 2001 From: BugsGuru Date: Thu, 26 Mar 2026 14:52:21 +0800 Subject: [PATCH 4/5] feat(dms): integrate MaintenanceTimeUsecase into DMSService and CloudbeaverUsecase - Added MaintenanceTimeUsecase to manage maintenance time checks. - Updated CloudbeaverUsecase to include maintenance time in its initialization. - Refactored SQLQueryConfig handling to utilize new methods for maintenance time management. - Enhanced DMSService methods to convert and fill SQLQueryConfig with maintenance periods. --- internal/dms/service/cloudbeaver.go | 4 +- internal/dms/service/db_service.go | 89 +++++++++----------- internal/dms/service/db_service_sync_task.go | 24 ++---- internal/dms/service/service.go | 3 + 4 files changed, 49 insertions(+), 71 deletions(-) diff --git a/internal/dms/service/cloudbeaver.go b/internal/dms/service/cloudbeaver.go index 412fcb9b..0c340dcf 100644 --- a/internal/dms/service/cloudbeaver.go +++ b/internal/dms/service/cloudbeaver.go @@ -70,6 +70,8 @@ func NewAndInitCloudbeaverService(logger utilLog.Logger, opts *conf.DMSOptions) dmsConfigUseCase := biz.NewDMSConfigUseCase(logger, dmsConfigRepo) cbOperationLogUsecase := biz.NewCbOperationLogUsecase(logger, storage.NewCbOperationLogRepo(logger, st), opPermissionVerifyUsecase, dmsProxyTargetRepo, biz.NewSystemVariableUsecase(logger, storage.NewSystemVariableRepo(logger, st))) + maintenanceTimeUsecase := biz.NewMaintenanceTimeUsecase(logger, opPermissionVerifyUsecase) + var cfg *biz.CloudbeaverCfg if opts.CloudbeaverOpts != nil { cfg = &biz.CloudbeaverCfg{ @@ -81,7 +83,7 @@ func NewAndInitCloudbeaverService(logger utilLog.Logger, opts *conf.DMSOptions) } } - cloudbeaverUsecase := biz.NewCloudbeaverUsecase(logger, cfg, userUsecase, dbServiceUseCase, opPermissionVerifyUsecase, dmsConfigUseCase, dataMaskingUsecase, cloudbeaverRepo, dmsProxyTargetRepo, cbOperationLogUsecase, projectUsecase) + cloudbeaverUsecase := biz.NewCloudbeaverUsecase(logger, cfg, userUsecase, dbServiceUseCase, opPermissionVerifyUsecase, dmsConfigUseCase, dataMaskingUsecase, cloudbeaverRepo, dmsProxyTargetRepo, cbOperationLogUsecase, projectUsecase, maintenanceTimeUsecase) proxyUsecase := biz.NewCloudbeaverProxyUsecase(logger, cloudbeaverUsecase) return &CloudbeaverService{ diff --git a/internal/dms/service/db_service.go b/internal/dms/service/db_service.go index 816dfc0f..12affb80 100644 --- a/internal/dms/service/db_service.go +++ b/internal/dms/service/db_service.go @@ -73,15 +73,7 @@ func (d *DMSService) UpdateDBService(ctx context.Context, req *dmsV2.UpdateDBSer args.DataExportRuleTemplateName = sqleConfig.DataExportRuleTemplateName args.DataExportRuleTemplateID = sqleConfig.DataExportRuleTemplateID if sqleConfig.SQLQueryConfig != nil { - args.SQLQueryConfig = &biz.SQLQueryConfig{ - MaxPreQueryRows: sqleConfig.SQLQueryConfig.MaxPreQueryRows, - QueryTimeoutSecond: sqleConfig.SQLQueryConfig.QueryTimeoutSecond, - AuditEnabled: sqleConfig.SQLQueryConfig.AuditEnabled, - WorkflowExecEnabled: sqleConfig.SQLQueryConfig.WorkflowExecEnabled, - AllowQueryWhenLessThanAuditLevel: string(sqleConfig.SQLQueryConfig.AllowQueryWhenLessThanAuditLevel), - RuleTemplateID: sqleConfig.SQLQueryConfig.RuleTemplateID, - RuleTemplateName: sqleConfig.SQLQueryConfig.RuleTemplateName, - } + args.SQLQueryConfig = d.bizSQLQueryConfigFromAPI(sqleConfig.SQLQueryConfig) } } if err := d.DBServiceUsecase.UpdateDBServiceByArgs(ctx, req.DBServiceUid, args, currentUserUid); err != nil { @@ -284,15 +276,7 @@ func (d *DMSService) AddDBService(ctx context.Context, req *dmsV1.AddDBServiceRe args.DataExportRuleTemplateName = sqleConfig.DataExportRuleTemplateName args.DataExportRuleTemplateID = sqleConfig.DataExportRuleTemplateID if sqleConfig.SQLQueryConfig != nil { - args.SQLQueryConfig = &biz.SQLQueryConfig{ - MaxPreQueryRows: sqleConfig.SQLQueryConfig.MaxPreQueryRows, - QueryTimeoutSecond: sqleConfig.SQLQueryConfig.QueryTimeoutSecond, - AuditEnabled: sqleConfig.SQLQueryConfig.AuditEnabled, - WorkflowExecEnabled: sqleConfig.SQLQueryConfig.WorkflowExecEnabled, - AllowQueryWhenLessThanAuditLevel: string(sqleConfig.SQLQueryConfig.AllowQueryWhenLessThanAuditLevel), - RuleTemplateID: sqleConfig.SQLQueryConfig.RuleTemplateID, - RuleTemplateName: sqleConfig.SQLQueryConfig.RuleTemplateName, - } + args.SQLQueryConfig = d.bizSQLQueryConfigFromAPI(sqleConfig.SQLQueryConfig) } } uid, err := d.DBServiceUsecase.CreateDBService(ctx, args, currentUserUid) @@ -351,15 +335,7 @@ func (d *DMSService) AddDBServiceV2(ctx context.Context, req *dmsV2.AddDBService args.DataExportRuleTemplateName = sqleConfig.DataExportRuleTemplateName args.DataExportRuleTemplateID = sqleConfig.DataExportRuleTemplateID if sqleConfig.SQLQueryConfig != nil { - args.SQLQueryConfig = &biz.SQLQueryConfig{ - MaxPreQueryRows: sqleConfig.SQLQueryConfig.MaxPreQueryRows, - QueryTimeoutSecond: sqleConfig.SQLQueryConfig.QueryTimeoutSecond, - AuditEnabled: sqleConfig.SQLQueryConfig.AuditEnabled, - WorkflowExecEnabled: sqleConfig.SQLQueryConfig.WorkflowExecEnabled, - AllowQueryWhenLessThanAuditLevel: string(sqleConfig.SQLQueryConfig.AllowQueryWhenLessThanAuditLevel), - RuleTemplateID: sqleConfig.SQLQueryConfig.RuleTemplateID, - RuleTemplateName: sqleConfig.SQLQueryConfig.RuleTemplateName, - } + args.SQLQueryConfig = d.bizSQLQueryConfigFromAPI(sqleConfig.SQLQueryConfig) } } uid, err := d.DBServiceUsecase.CreateDBService(ctx, args, currentUserUid) @@ -375,6 +351,37 @@ func (d *DMSService) AddDBServiceV2(ctx context.Context, req *dmsV2.AddDBService }, nil } +func (d *DMSService) bizSQLQueryConfigFromAPI(src *dmsCommonV1.SQLQueryConfig) *biz.SQLQueryConfig { + if src == nil { + return nil + } + maintenancePeriods := d.convertMaintenanceTimeToPeriod(src.MaintenanceTimes) + return &biz.SQLQueryConfig{ + MaxPreQueryRows: src.MaxPreQueryRows, + QueryTimeoutSecond: src.QueryTimeoutSecond, + AuditEnabled: src.AuditEnabled, + WorkflowExecEnabled: src.WorkflowExecEnabled, + AllowQueryWhenLessThanAuditLevel: string(src.AllowQueryWhenLessThanAuditLevel), + RuleTemplateID: src.RuleTemplateID, + RuleTemplateName: src.RuleTemplateName, + MaintenancePeriods: maintenancePeriods, + } +} + +func (d *DMSService) fillAPISQLQueryConfig(dst *dmsCommonV1.SQLQueryConfig, src *biz.SQLQueryConfig) { + if src == nil { + return + } + dst.MaxPreQueryRows = src.MaxPreQueryRows + dst.QueryTimeoutSecond = src.QueryTimeoutSecond + dst.AuditEnabled = src.AuditEnabled + dst.WorkflowExecEnabled = src.WorkflowExecEnabled + dst.AllowQueryWhenLessThanAuditLevel = dmsCommonV1.SQLAllowQueryAuditLevel(src.AllowQueryWhenLessThanAuditLevel) + dst.RuleTemplateID = src.RuleTemplateID + dst.RuleTemplateName = src.RuleTemplateName + dst.MaintenanceTimes = d.convertPeriodToMaintenanceTime(src.MaintenancePeriods) +} + func (d *DMSService) convertMaintenanceTimeToPeriod(mt []*dmsCommonV1.MaintenanceTime) periods.Periods { ps := make(periods.Periods, len(mt)) for i, time := range mt { @@ -446,15 +453,8 @@ func (d *DMSService) convertBizDBServiceArgs2ImportDBService(dbs []*biz.BizDBSer } if u.SQLQueryConfig != nil { - ret[i].SQLEConfig.SQLQueryConfig = &dmsCommonV1.SQLQueryConfig{ - MaxPreQueryRows: u.SQLQueryConfig.MaxPreQueryRows, - QueryTimeoutSecond: u.SQLQueryConfig.QueryTimeoutSecond, - AuditEnabled: u.SQLQueryConfig.AuditEnabled, - WorkflowExecEnabled: u.SQLQueryConfig.WorkflowExecEnabled, - AllowQueryWhenLessThanAuditLevel: dmsCommonV1.SQLAllowQueryAuditLevel(u.SQLQueryConfig.AllowQueryWhenLessThanAuditLevel), - RuleTemplateID: u.SQLQueryConfig.RuleTemplateID, - RuleTemplateName: u.SQLQueryConfig.RuleTemplateName, - } + ret[i].SQLEConfig.SQLQueryConfig = &dmsCommonV1.SQLQueryConfig{} + d.fillAPISQLQueryConfig(ret[i].SQLEConfig.SQLQueryConfig, u.SQLQueryConfig) } } @@ -508,16 +508,9 @@ func (d *DMSService) convertImportDBService2BizDBService(ctx context.Context, im RuleTemplateID: u.SQLEConfig.RuleTemplateID, DataExportRuleTemplateName: u.SQLEConfig.DataExportRuleTemplateName, DataExportRuleTemplateID: u.SQLEConfig.DataExportRuleTemplateID, - SQLQueryConfig: &biz.SQLQueryConfig{}, } if u.SQLEConfig.SQLQueryConfig != nil { - sqlConfig.SQLQueryConfig.AllowQueryWhenLessThanAuditLevel = string(u.SQLEConfig.SQLQueryConfig.AllowQueryWhenLessThanAuditLevel) - sqlConfig.SQLQueryConfig.AuditEnabled = u.SQLEConfig.SQLQueryConfig.AuditEnabled - sqlConfig.SQLQueryConfig.WorkflowExecEnabled = u.SQLEConfig.SQLQueryConfig.WorkflowExecEnabled - sqlConfig.SQLQueryConfig.MaxPreQueryRows = u.SQLEConfig.SQLQueryConfig.MaxPreQueryRows - sqlConfig.SQLQueryConfig.QueryTimeoutSecond = u.SQLEConfig.SQLQueryConfig.QueryTimeoutSecond - sqlConfig.SQLQueryConfig.RuleTemplateID = u.SQLEConfig.SQLQueryConfig.RuleTemplateID - sqlConfig.SQLQueryConfig.RuleTemplateName = u.SQLEConfig.SQLQueryConfig.RuleTemplateName + sqlConfig.SQLQueryConfig = d.bizSQLQueryConfigFromAPI(u.SQLEConfig.SQLQueryConfig) } ret[i].SQLEConfig = sqlConfig } @@ -714,13 +707,7 @@ func (d *DMSService) ListDBServices(ctx context.Context, req *dmsCommonV2.ListDB SQLQueryConfig: &dmsCommonV1.SQLQueryConfig{}, } if u.SQLEConfig.SQLQueryConfig != nil { - sqlConfig.SQLQueryConfig.AllowQueryWhenLessThanAuditLevel = dmsCommonV1.SQLAllowQueryAuditLevel(u.SQLEConfig.SQLQueryConfig.AllowQueryWhenLessThanAuditLevel) - sqlConfig.SQLQueryConfig.AuditEnabled = u.SQLEConfig.SQLQueryConfig.AuditEnabled - sqlConfig.SQLQueryConfig.WorkflowExecEnabled = u.SQLEConfig.SQLQueryConfig.WorkflowExecEnabled - sqlConfig.SQLQueryConfig.MaxPreQueryRows = u.SQLEConfig.SQLQueryConfig.MaxPreQueryRows - sqlConfig.SQLQueryConfig.QueryTimeoutSecond = u.SQLEConfig.SQLQueryConfig.QueryTimeoutSecond - sqlConfig.SQLQueryConfig.RuleTemplateID = u.SQLEConfig.SQLQueryConfig.RuleTemplateID - sqlConfig.SQLQueryConfig.RuleTemplateName = u.SQLEConfig.SQLQueryConfig.RuleTemplateName + d.fillAPISQLQueryConfig(sqlConfig.SQLQueryConfig, u.SQLEConfig.SQLQueryConfig) } ret[i].SQLEConfig = sqlConfig } diff --git a/internal/dms/service/db_service_sync_task.go b/internal/dms/service/db_service_sync_task.go index 2b10bb1a..e177313d 100644 --- a/internal/dms/service/db_service_sync_task.go +++ b/internal/dms/service/db_service_sync_task.go @@ -10,7 +10,7 @@ import ( ) func (d *DMSService) AddDBServiceSyncTask(ctx context.Context, req *v1.AddDBServiceSyncTaskReq, currentUserId string) (reply *v1.AddDBServiceSyncTaskReply, err error) { - syncTask := toBizDBServiceSyncTask(&req.DBServiceSyncTask) + syncTask := d.toBizDBServiceSyncTask(&req.DBServiceSyncTask) uid, err := d.DBServiceSyncTaskUsecase.AddDBServiceSyncTask(ctx, syncTask, currentUserId) if err != nil { @@ -24,7 +24,7 @@ func (d *DMSService) AddDBServiceSyncTask(ctx context.Context, req *v1.AddDBServ }, nil } -func toBizDBServiceSyncTask(syncTask *v1.DBServiceSyncTask) *biz.DBServiceSyncTask { +func (d *DMSService) toBizDBServiceSyncTask(syncTask *v1.DBServiceSyncTask) *biz.DBServiceSyncTask { ret := &biz.DBServiceSyncTask{ Name: syncTask.Name, Source: syncTask.Source, @@ -42,15 +42,7 @@ func toBizDBServiceSyncTask(syncTask *v1.DBServiceSyncTask) *biz.DBServiceSyncTa DataExportRuleTemplateID: syncTask.SQLEConfig.DataExportRuleTemplateID, } if syncTask.SQLEConfig.SQLQueryConfig != nil { - ret.SQLEConfig.SQLQueryConfig = &biz.SQLQueryConfig{ - MaxPreQueryRows: syncTask.SQLEConfig.SQLQueryConfig.MaxPreQueryRows, - QueryTimeoutSecond: syncTask.SQLEConfig.SQLQueryConfig.QueryTimeoutSecond, - AuditEnabled: syncTask.SQLEConfig.SQLQueryConfig.AuditEnabled, - WorkflowExecEnabled: syncTask.SQLEConfig.SQLQueryConfig.WorkflowExecEnabled, - AllowQueryWhenLessThanAuditLevel: string(syncTask.SQLEConfig.SQLQueryConfig.AllowQueryWhenLessThanAuditLevel), - RuleTemplateID: syncTask.SQLEConfig.SQLQueryConfig.RuleTemplateID, - RuleTemplateName: syncTask.SQLEConfig.SQLQueryConfig.RuleTemplateName, - } + ret.SQLEConfig.SQLQueryConfig = d.bizSQLQueryConfigFromAPI(syncTask.SQLEConfig.SQLQueryConfig) } } if syncTask.AdditionalParam != nil { @@ -60,7 +52,7 @@ func toBizDBServiceSyncTask(syncTask *v1.DBServiceSyncTask) *biz.DBServiceSyncTa } func (svc *DMSService) UpdateDBServiceSyncTask(ctx context.Context, req *v1.UpdateDBServiceSyncTaskReq, currentUserId string) error { - syncTask := toBizDBServiceSyncTask(&req.DBServiceSyncTask) + syncTask := svc.toBizDBServiceSyncTask(&req.DBServiceSyncTask) err := svc.DBServiceSyncTaskUsecase.UpdateDBServiceSyncTask(ctx, req.DBServiceSyncTaskUid, syncTask, currentUserId) if err != nil { return fmt.Errorf("update db_service_sync_task failed: %w", err) @@ -115,13 +107,7 @@ func (d *DMSService) buildReplySqleConfig(params *biz.SQLEConfig) *dmsCommonV1.S SQLQueryConfig: &dmsCommonV1.SQLQueryConfig{}, } if params.SQLQueryConfig != nil { - sqlConfig.SQLQueryConfig.AllowQueryWhenLessThanAuditLevel = dmsCommonV1.SQLAllowQueryAuditLevel(params.SQLQueryConfig.AllowQueryWhenLessThanAuditLevel) - sqlConfig.SQLQueryConfig.AuditEnabled = params.SQLQueryConfig.AuditEnabled - sqlConfig.SQLQueryConfig.WorkflowExecEnabled = params.SQLQueryConfig.WorkflowExecEnabled - sqlConfig.SQLQueryConfig.MaxPreQueryRows = params.SQLQueryConfig.MaxPreQueryRows - sqlConfig.SQLQueryConfig.QueryTimeoutSecond = params.SQLQueryConfig.QueryTimeoutSecond - sqlConfig.SQLQueryConfig.RuleTemplateID = params.SQLQueryConfig.RuleTemplateID - sqlConfig.SQLQueryConfig.RuleTemplateName = params.SQLQueryConfig.RuleTemplateName + d.fillAPISQLQueryConfig(sqlConfig.SQLQueryConfig, params.SQLQueryConfig) } return sqlConfig diff --git a/internal/dms/service/service.go b/internal/dms/service/service.go index fd738309..2a02498f 100644 --- a/internal/dms/service/service.go +++ b/internal/dms/service/service.go @@ -49,6 +49,7 @@ type DMSService struct { GatewayUsecase *biz.GatewayUsecase SystemVariableUsecase *biz.SystemVariableUsecase OperationRecordUsecase *biz.OperationRecordUsecase + MaintenanceTimeUsecase *biz.MaintenanceTimeUsecase log *utilLog.Helper shutdownCallback func() error } @@ -143,6 +144,7 @@ func NewAndInitDMSService(logger utilLog.Logger, opts *conf.DMSOptions) (*DMSSer swaggerUseCase := biz.NewSwaggerUseCase(logger, dmsProxyUsecase) systemVariableUsecase := biz.NewSystemVariableUsecase(logger, storage.NewSystemVariableRepo(logger, st)) + maintenanceTimeUsecase := biz.NewMaintenanceTimeUsecase(logger, opPermissionVerifyUsecase) operationRecordRepo := storage.NewOperationRecordRepo(logger, st) operationRecordUsecase := biz.NewOperationRecordUsecase(logger, operationRecordRepo, systemVariableUsecase) cbOperationRepo := storage.NewCbOperationLogRepo(logger, st) @@ -199,6 +201,7 @@ func NewAndInitDMSService(logger utilLog.Logger, opts *conf.DMSOptions) (*DMSSer GatewayUsecase: gatewayUsecase, SystemVariableUsecase: systemVariableUsecase, OperationRecordUsecase: operationRecordUsecase, + MaintenanceTimeUsecase: maintenanceTimeUsecase, log: utilLog.NewHelper(logger, utilLog.WithMessageKey("dms.service")), shutdownCallback: func() error { if err := st.Close(); nil != err { From e720440c6ad8be13acb4614253f1275cb9f78fb8 Mon Sep 17 00:00:00 2001 From: BugsGuru Date: Thu, 26 Mar 2026 15:07:05 +0800 Subject: [PATCH 5/5] refactor(api): update swagger definitions and remove DateTime type - Removed the DateTime definition from swagger.json and swagger.yaml. - Updated x-go-package references to point to the new common API path. - Added maintenance_times property to relevant definitions for enhanced maintenance time management. --- api/swagger.json | 34 ++++++++++++++-------------------- api/swagger.yaml | 31 +++++++++++-------------------- 2 files changed, 25 insertions(+), 40 deletions(-) diff --git a/api/swagger.json b/api/swagger.json index 7a173d16..b3a6b8ca 100644 --- a/api/swagger.json +++ b/api/swagger.json @@ -8702,12 +8702,6 @@ }, "x-go-package": "github.com/actiontech/dms/api/dms/service/v1" }, - "DateTime": { - "description": "DateTime is a time but it serializes to ISO8601 format with millis\nIt knows how to read 3 different variations of a RFC3339 date time.\nMost APIs we encounter want either millisecond or second precision times.\nThis just tries to make it worry-free.", - "type": "string", - "format": "date-time", - "x-go-package": "github.com/go-openapi/strfmt" - }, "DbServiceConnections": { "type": "object", "properties": { @@ -9355,7 +9349,7 @@ "x-go-name": "Message" } }, - "x-go-package": "github.com/actiontech/dms/api/dms/service/v1" + "x-go-package": "github.com/actiontech/dms/pkg/dms-common/api/dms/v1" }, "GetOauth2ConfigurationResData": { "type": "object", @@ -10006,6 +10000,10 @@ "x-go-package": "github.com/actiontech/dms/api/dms/service/v1" }, "I18nStr": { + "type": "object", + "additionalProperties": { + "type": "string" + }, "x-go-package": "github.com/actiontech/dms/pkg/dms-common/i18nPkg" }, "ImportDBService": { @@ -11891,17 +11889,6 @@ "ListMemberRoleWithOpRange": { "type": "object", "properties": { - "member_group": { - "$ref": "#/definitions/ProjectMemberGroup" - }, - "op_permissions": { - "description": "member op permissions", - "type": "array", - "items": { - "$ref": "#/definitions/UidWithName" - }, - "x-go-name": "OpPermissions" - }, "op_range_type": { "description": "op permission range type, only support db service now\nunknown OpRangeTypeUnknown\nglobal OpRangeTypeGlobal 全局权限: 该权限只能被用户使用\nproject OpRangeTypeProject 项目权限: 该权限只能被成员使用\ndb_service OpRangeTypeDBService 项目内的数据源权限: 该权限只能被成员使用", "type": "string", @@ -11926,7 +11913,7 @@ "$ref": "#/definitions/UidWithName" } }, - "x-go-package": "github.com/actiontech/dms/api/dms/service/v1" + "x-go-package": "github.com/actiontech/dms/pkg/dms-common/api/dms/v1" }, "ListMemberTipsItem": { "type": "object", @@ -13862,6 +13849,13 @@ "type": "boolean", "x-go-name": "AuditEnabled" }, + "maintenance_times": { + "type": "array", + "items": { + "$ref": "#/definitions/MaintenanceTime" + }, + "x-go-name": "MaintenanceTimes" + }, "max_pre_query_rows": { "type": "integer", "format": "int64", @@ -14311,7 +14305,7 @@ "x-go-name": "Uid" } }, - "x-go-package": "github.com/actiontech/dms/api/dms/service/v1" + "x-go-package": "github.com/actiontech/dms/pkg/dms-common/api/dms/v1" }, "UpdateBusinessTagReq": { "type": "object", diff --git a/api/swagger.yaml b/api/swagger.yaml index 77dac93e..faeb0c25 100644 --- a/api/swagger.yaml +++ b/api/swagger.yaml @@ -1389,15 +1389,6 @@ definitions: x-go-name: Params type: object x-go-package: github.com/actiontech/dms/api/dms/service/v1 - DateTime: - description: |- - DateTime is a time but it serializes to ISO8601 format with millis - It knows how to read 3 different variations of a RFC3339 date time. - Most APIs we encounter want either millisecond or second precision times. - This just tries to make it worry-free. - format: date-time - type: string - x-go-package: github.com/go-openapi/strfmt DbServiceConnections: properties: db_service_uid: @@ -1889,7 +1880,7 @@ definitions: type: string x-go-name: Message type: object - x-go-package: github.com/actiontech/dms/api/dms/service/v1 + x-go-package: github.com/actiontech/dms/pkg/dms-common/api/dms/v1 GetOauth2ConfigurationResData: properties: access_token_tag: @@ -2417,6 +2408,9 @@ definitions: type: object x-go-package: github.com/actiontech/dms/api/dms/service/v1 I18nStr: + additionalProperties: + type: string + type: object x-go-package: github.com/actiontech/dms/pkg/dms-common/i18nPkg ImportDBService: properties: @@ -3891,14 +3885,6 @@ definitions: x-go-package: github.com/actiontech/dms/api/dms/service/v1 ListMemberRoleWithOpRange: properties: - member_group: - $ref: '#/definitions/ProjectMemberGroup' - op_permissions: - description: member op permissions - items: - $ref: '#/definitions/UidWithName' - type: array - x-go-name: OpPermissions op_range_type: description: |- op permission range type, only support db service now @@ -3927,7 +3913,7 @@ definitions: role_uid: $ref: '#/definitions/UidWithName' type: object - x-go-package: github.com/actiontech/dms/api/dms/service/v1 + x-go-package: github.com/actiontech/dms/pkg/dms-common/api/dms/v1 ListMemberTipsItem: properties: user_id: @@ -5599,6 +5585,11 @@ definitions: audit_enabled: type: boolean x-go-name: AuditEnabled + maintenance_times: + items: + $ref: '#/definitions/MaintenanceTime' + type: array + x-go-name: MaintenanceTimes max_pre_query_rows: format: int64 type: integer @@ -5928,7 +5919,7 @@ definitions: type: string x-go-name: Uid type: object - x-go-package: github.com/actiontech/dms/api/dms/service/v1 + x-go-package: github.com/actiontech/dms/pkg/dms-common/api/dms/v1 UpdateBusinessTagReq: properties: business_tag: