2026-04-05 22:28:38 +08:00
|
|
|
package rule
|
|
|
|
|
|
|
|
|
|
import (
|
2026-07-26 22:19:41 +08:00
|
|
|
"fmt"
|
|
|
|
|
"strconv"
|
|
|
|
|
|
2026-04-05 22:28:38 +08:00
|
|
|
"github.com/ssdomei232/goodBaby/handler/db"
|
2026-07-26 22:19:41 +08:00
|
|
|
"github.com/ssdomei232/goodBaby/internal/meta"
|
|
|
|
|
"github.com/ssdomei232/goodBaby/internal/ruleConfigChecker"
|
2026-04-05 22:28:38 +08:00
|
|
|
"github.com/ssdomei232/goodBaby/model"
|
|
|
|
|
)
|
|
|
|
|
|
2026-07-26 22:19:41 +08:00
|
|
|
func parseID(raw string) (uint, error) {
|
|
|
|
|
id, err := strconv.ParseUint(raw, 10, 64)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
return uint(id), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func boolOr(v *bool, fallback bool) bool {
|
|
|
|
|
if v == nil {
|
|
|
|
|
return fallback
|
|
|
|
|
}
|
|
|
|
|
return *v
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-12 15:32:27 +08:00
|
|
|
// findRule 查找属于该用户的定时器规则
|
2026-07-26 22:19:41 +08:00
|
|
|
func findRule(ruleID, uid uint) (*model.Rule, error) {
|
|
|
|
|
gormDB, err := db.GetGormDB()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var target model.Rule
|
|
|
|
|
if err := gormDB.Where("id = ? AND uid = ?", ruleID, uid).First(&target).Error; err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return &target, nil
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-12 15:32:27 +08:00
|
|
|
// findGatewayRule 查找属于该用户的消息网关规则
|
|
|
|
|
func findGatewayRule(ruleID, uid uint) (*model.GatewayRule, error) {
|
|
|
|
|
gormDB, err := db.GetGormDB()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var target model.GatewayRule
|
|
|
|
|
if err := gormDB.Where("id = ? AND uid = ?", ruleID, uid).First(&target).Error; err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return &target, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DeleteRuleByID 根据 ID 删除定时器规则
|
2026-04-05 22:28:38 +08:00
|
|
|
func DeleteRuleByID(id uint, uid uint) error {
|
|
|
|
|
gormDB, err := db.GetGormDB()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-26 22:19:41 +08:00
|
|
|
return gormDB.Where("id = ? AND uid = ?", id, uid).Delete(&model.Rule{}).Error
|
2026-04-05 22:28:38 +08:00
|
|
|
}
|
2026-06-19 18:47:36 +08:00
|
|
|
|
2026-09-12 15:32:27 +08:00
|
|
|
// DeleteGatewayRuleByID 根据 ID 删除消息网关规则
|
|
|
|
|
func DeleteGatewayRuleByID(id uint, uid uint) error {
|
|
|
|
|
gormDB, err := db.GetGormDB()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return gormDB.Where("id = ? AND uid = ?", id, uid).Delete(&model.GatewayRule{}).Error
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// checkTimerExists 检查关联的 Timer 是否存在且归属当前用户
|
|
|
|
|
func checkTimerExists(timerID, uid uint) error {
|
2026-06-19 18:47:36 +08:00
|
|
|
gormDB, err := db.GetGormDB()
|
|
|
|
|
if err != nil {
|
2026-07-26 22:19:41 +08:00
|
|
|
return err
|
2026-06-19 18:47:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var count int64
|
2026-09-12 15:32:27 +08:00
|
|
|
if err := gormDB.Model(&model.Timer{}).Where("id = ? AND uid = ?", timerID, uid).
|
|
|
|
|
Count(&count).Error; err != nil {
|
|
|
|
|
return err
|
2026-06-19 18:47:36 +08:00
|
|
|
}
|
2026-09-12 15:32:27 +08:00
|
|
|
if count == 0 {
|
|
|
|
|
return model.ErrValidation("关联的 Timer 不存在")
|
2026-06-19 18:47:36 +08:00
|
|
|
}
|
2026-07-26 22:19:41 +08:00
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-12 15:32:27 +08:00
|
|
|
// checkGatewayExists 检查关联的消息网关是否存在且归属当前用户
|
|
|
|
|
func checkGatewayExists(gatewayID, uid uint) error {
|
|
|
|
|
gormDB, err := db.GetGormDB()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
2026-07-26 22:19:41 +08:00
|
|
|
}
|
2026-09-12 15:32:27 +08:00
|
|
|
|
|
|
|
|
var count int64
|
|
|
|
|
if err := gormDB.Model(&model.MessageGateway{}).Where("id = ? AND uid = ?", gatewayID, uid).
|
|
|
|
|
Count(&count).Error; err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
if count == 0 {
|
|
|
|
|
return model.ErrValidation("关联的消息网关不存在")
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// checkAccount 校验规则关联的账号存在、归属当前用户且类型匹配。
|
|
|
|
|
//
|
|
|
|
|
// requiredType 为空表示该规则类型不需要账号,此时返回 0,调用方据此清掉 account_id。
|
|
|
|
|
func checkAccount(accountID, uid uint, requiredType string) (uint, error) {
|
|
|
|
|
if requiredType == "" {
|
|
|
|
|
return 0, nil
|
|
|
|
|
}
|
|
|
|
|
if accountID == 0 {
|
|
|
|
|
return 0, model.ErrValidation("该规则类型必须关联一个账号")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gormDB, err := db.GetGormDB()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var account model.Account
|
|
|
|
|
if err := gormDB.Where("id = ? AND uid = ?", accountID, uid).First(&account).Error; err != nil {
|
|
|
|
|
return 0, model.ErrValidation("关联的账号不存在")
|
|
|
|
|
}
|
|
|
|
|
if account.Type != requiredType {
|
|
|
|
|
return 0, model.ErrValidation(
|
|
|
|
|
fmt.Sprintf("规则需要 %s 类型的账号,但关联的是 %s", requiredType, account.Type))
|
|
|
|
|
}
|
|
|
|
|
return accountID, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ruleMetaOf 取规则类型的元数据,不支持的类型返回校验错误
|
|
|
|
|
func ruleMetaOf(ruleType string) (meta.RuleMeta, error) {
|
|
|
|
|
ruleMeta, ok := ruleConfigChecker.InitValidatorRegistry().MetaOf(ruleType)
|
|
|
|
|
if !ok {
|
|
|
|
|
return meta.RuleMeta{}, model.ErrValidation(fmt.Sprintf("不支持的规则类型: %s", ruleType))
|
|
|
|
|
}
|
|
|
|
|
return ruleMeta, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// validateRuleConfig 校验类型专属的规则配置
|
|
|
|
|
func validateRuleConfig(ruleType, configJSON string) error {
|
|
|
|
|
if err := ruleConfigChecker.InitValidatorRegistry().Validate(ruleType, configJSON); err != nil {
|
|
|
|
|
return model.ErrValidation(fmt.Sprintf("规则配置验证失败: %s", err.Error()))
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// maskRule 掩码定时器规则配置中的敏感字段
|
|
|
|
|
func maskRule(target model.Rule) model.Rule {
|
|
|
|
|
target.ConfigJson = maskConfig(target.Type, target.ConfigJson)
|
2026-07-26 22:19:41 +08:00
|
|
|
return target
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func maskRules(rules []model.Rule) []model.Rule {
|
|
|
|
|
masked := make([]model.Rule, 0, len(rules))
|
|
|
|
|
for _, r := range rules {
|
|
|
|
|
masked = append(masked, maskRule(r))
|
|
|
|
|
}
|
|
|
|
|
return masked
|
2026-06-19 18:47:36 +08:00
|
|
|
}
|
2026-08-30 17:47:53 +08:00
|
|
|
|
2026-09-12 15:32:27 +08:00
|
|
|
// maskGatewayRule 掩码消息网关规则配置中的敏感字段
|
|
|
|
|
func maskGatewayRule(target model.GatewayRule) model.GatewayRule {
|
|
|
|
|
target.ConfigJson = maskConfig(target.Type, target.ConfigJson)
|
|
|
|
|
return target
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func maskGatewayRules(rules []model.GatewayRule) []model.GatewayRule {
|
|
|
|
|
masked := make([]model.GatewayRule, 0, len(rules))
|
|
|
|
|
for _, r := range rules {
|
|
|
|
|
masked = append(masked, maskGatewayRule(r))
|
|
|
|
|
}
|
|
|
|
|
return masked
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// maskConfig 掩码规则配置中的敏感字段
|
|
|
|
|
func maskConfig(ruleType, configJSON string) string {
|
|
|
|
|
if ruleMeta, ok := ruleConfigChecker.InitValidatorRegistry().MetaOf(ruleType); ok {
|
|
|
|
|
return meta.Mask(configJSON, ruleMeta.Fields)
|
|
|
|
|
}
|
|
|
|
|
return configJSON
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// getRuleOwnerUID 获取定时器规则所属用户的 UID
|
2026-08-30 17:47:53 +08:00
|
|
|
func getRuleOwnerUID(ruleID uint) (uint, error) {
|
|
|
|
|
gormDB, err := db.GetGormDB()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-12 15:32:27 +08:00
|
|
|
var target model.Rule
|
|
|
|
|
if err := gormDB.Select("uid").Where("id = ?", ruleID).First(&target).Error; err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
return target.UID, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// getGatewayRuleOwnerUID 获取消息网关规则所属用户的 UID
|
|
|
|
|
func getGatewayRuleOwnerUID(ruleID uint) (uint, error) {
|
|
|
|
|
gormDB, err := db.GetGormDB()
|
|
|
|
|
if err != nil {
|
2026-08-30 17:47:53 +08:00
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-12 15:32:27 +08:00
|
|
|
var target model.GatewayRule
|
|
|
|
|
if err := gormDB.Select("uid").Where("id = ?", ruleID).First(&target).Error; err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
return target.UID, nil
|
2026-08-30 17:47:53 +08:00
|
|
|
}
|