Quellcode durchsuchen

Fix: 修复域名、IP重复判断逻辑及字段校验

lwh vor 1 Tag
Ursprung
Commit
a205b05aff

+ 2 - 0
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/common/BaseDomainDTO.java

@@ -1,6 +1,7 @@
 package com.pig4cloud.pig.marketing.api.dto.common;
 
 
+import com.pig4cloud.pig.marketing.api.valid.ValueRange;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.constraints.NotNull;
 import jakarta.validation.constraints.Size;
@@ -20,6 +21,7 @@ public class BaseDomainDTO implements Serializable {
 	private static final long serialVersionUID = 1L;
 
 	@NotNull(message = "来源类型不能为空")
+	@ValueRange(values = {1, 2}, message = "来源类型不合法(1-来自分组,2-具体域名)")
 	@Schema(description = "来源类型,1-来自分组,2-具体域名")
 	private Integer sourceType;
 

+ 5 - 1
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/common/BaseIpDTO.java

@@ -1,6 +1,7 @@
 package com.pig4cloud.pig.marketing.api.dto.common;
 
 
+import com.pig4cloud.pig.marketing.api.valid.ValueRange;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.constraints.NotNull;
 import jakarta.validation.constraints.Size;
@@ -20,11 +21,13 @@ public class BaseIpDTO implements Serializable {
 	private static final long serialVersionUID = 1L;
 
 	@NotNull(message = "ipType不能为空")
+	@ValueRange(values = {1, 2}, message = "IP类型值不合法(1-白名单,2-黑名单)")
 	@Schema(description = "ip类型,1-白名单,2-黑名单")
 	private Integer ipType;
 
 	@NotNull(message = "sourceType不能为空")
-	@Schema(description = "来源类型,1-来自分组,2-具体IP")
+	@Schema(description = "来源类型值不合法(1-来自分组,2-具体IP)")
+	@ValueRange(values = {1, 2}, message = "来源类型只能是1或2")
 	private Integer sourceType;
 
 	@Schema(description = "分组ID")
@@ -35,6 +38,7 @@ public class BaseIpDTO implements Serializable {
 	private String groupName;
 
 	@Schema(description = "ip模式,1-单IP,2-IP段")
+	@ValueRange(values = {1, 2}, message = "IP模式值不合法(1-单IP,2-IP段)")
 	private Integer ipMode;
 
 	@Schema(description = "起始IP")

+ 2 - 0
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/config/AddMarketingGroupDTO.java

@@ -1,6 +1,7 @@
 package com.pig4cloud.pig.marketing.api.dto.config;
 
 
+import com.pig4cloud.pig.marketing.api.valid.ValueRange;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.constraints.NotEmpty;
 import jakarta.validation.constraints.NotNull;
@@ -28,6 +29,7 @@ public class AddMarketingGroupDTO implements Serializable {
 	private String groupName;
 
 	@Schema(description = "分组类型,1-ip分组,2-域名分组",example = "1")
+	@ValueRange(values = {1, 2}, message = "分组类型值不合法(1-ip分组,2-域名分组)")
 	@NotNull(message = "分组类型不能为空")
 	private Integer groupType;
 

+ 3 - 1
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/config/DelMarketingGroupDTO.java

@@ -1,6 +1,7 @@
 package com.pig4cloud.pig.marketing.api.dto.config;
 
 
+import com.pig4cloud.pig.marketing.api.valid.ValueRange;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.constraints.NotEmpty;
 import jakarta.validation.constraints.NotNull;
@@ -25,8 +26,9 @@ public class DelMarketingGroupDTO implements Serializable {
 	/**
 	 * 分组类型
 	 */
-	@Schema(description = "分组类型,1-ip分组,2-域名分组",example = "1")
 	@NotNull(message = "分组类型不能为空")
+	@Schema(description = "分组类型,1-ip分组,2-域名分组",example = "1")
+	@ValueRange(values = {1, 2}, message = "分组类型值不合法(1-ip分组,2-域名分组)")
 	private Integer groupType;
 
 	/**

+ 3 - 1
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/dto/config/MarketingGroupIPDTO.java

@@ -1,6 +1,7 @@
 package com.pig4cloud.pig.marketing.api.dto.config;
 
 
+import com.pig4cloud.pig.marketing.api.valid.ValueRange;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.constraints.NotNull;
 import lombok.Data;
@@ -29,8 +30,9 @@ public class MarketingGroupIPDTO implements Serializable {
 	/**
 	 * ip模式,1-单IP,2-IP段
 	 */
-	@Schema(description = "ip模式,1-单IP,2-IP段")
 	@NotNull(message = "ip模式不能为空")
+	@Schema(description = "ip模式,1-单IP,2-IP段")
+	@ValueRange(values = {1, 2}, message = "IP模式值不合法(1-单IP,2-IP段)")
 	private Integer ipMode;
 
 	/**

+ 76 - 6
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/util/DomainValidationUtil.java

@@ -10,23 +10,93 @@ import java.util.regex.Pattern;
  */
 
 public class DomainValidationUtil {
-	// 简单域名正则(支持字母、数字、下划线、横线、点,且点不能连续)
+	/**
+	 * 严格的域名正则表达式
+	 * 规则:
+	 * 1. 由字母、数字、连字符组成
+	 * 2. 不能以连字符开头或结尾
+	 * 3. 各部分长度不超过63个字符
+	 * 4. 总长度不超过255个字符
+	 * 5. 至少包含一个点(.)
+	 * 6. 顶级域名至少2个字符
+	 */
 	private static final Pattern DOMAIN_PATTERN = Pattern.compile(
-			"^[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)*$"
+			"^(?!-)[a-zA-Z0-9-]{1,63}(?<!-)\\." +  // 主域名部分
+					"+(?!-)[a-zA-Z0-9-]{1,63}(?<!-)$"     // 顶级域名部分
 	);
 
 	/**
 	 * 验证域名格式是否合法
+	 * @param domain 待验证的域名
+	 * @return 合法返回true,否则返回false
 	 */
 	public static boolean isValidDomain(String domain) {
+		// 空值检查
 		if (domain == null || domain.trim().isEmpty()) {
 			return false;
 		}
-		String trimDomain = domain.trim();
-		// 长度限制
-		if (trimDomain.length() < 1 || trimDomain.length() > 255) {
+
+		String trimDomain = domain.trim().toLowerCase();
+
+		// 长度限制检查
+		if (trimDomain.length() > 255) {
+			return false;
+		}
+
+		// 正则匹配检查
+		if (!DOMAIN_PATTERN.matcher(trimDomain).matches()) {
 			return false;
 		}
-		return DOMAIN_PATTERN.matcher(trimDomain).matches();
+
+		// 检查每个部分的长度(通过点分割)
+		String[] parts = trimDomain.split("\\.");
+		for (String part : parts) {
+			if (part.length() < 1 || part.length() > 63) {
+				return false;
+			}
+		}
+
+		// 检查顶级域名至少有2个字符
+		String tld = parts[parts.length - 1];
+		if (tld.length() < 2) {
+			return false;
+		}
+
+		return true;
+	}
+
+	/**
+	 * 验证域名并返回具体错误信息
+	 * @param domain 待验证的域名
+	 * @return 验证通过返回null,否则返回错误信息
+	 */
+	public static String getValidationMessage(String domain) {
+		if (domain == null || domain.trim().isEmpty()) {
+			return "域名不能为空";
+		}
+
+		String trimDomain = domain.trim().toLowerCase();
+
+		if (trimDomain.length() > 255) {
+			return "域名长度不能超过255个字符";
+		}
+
+		if (!DOMAIN_PATTERN.matcher(trimDomain).matches()) {
+			return "域名格式不正确,只能包含字母、数字和连字符,且不能以连字符开头或结尾";
+		}
+
+		String[] parts = trimDomain.split("\\.");
+		for (String part : parts) {
+			if (part.isEmpty() || part.length() > 63) {
+				return "域名各部分长度必须在1-63个字符之间";
+			}
+		}
+
+		String tld = parts[parts.length - 1];
+		if (tld.length() < 2) {
+			return "顶级域名长度不能少于2个字符";
+		}
+
+		return null;
 	}
 }

+ 1 - 1
pig-marketing/pig-marketing-api/src/main/java/com/pig4cloud/pig/marketing/api/valid/DomainValidator.java

@@ -56,7 +56,7 @@ public class DomainValidator implements ConstraintValidator<DomainValidation, Ob
 			}
 			// 校验域名格式
 			if (!DomainValidationUtil.isValidDomain(domain)) {
-				setMessage(context, "域名格式不合法(支持字母、数字、下划线、横线、点)");
+				setMessage(context, "域名格式不合法");
 				return false;
 			}
 			return true;

+ 34 - 33
pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/service/impl/MarketingAppsServiceImpl.java

@@ -676,41 +676,42 @@ public class MarketingAppsServiceImpl implements MarketingAppsService {
 			query.eq("app_id", appId);
 		}
 
-		// 单IP模式检查
-		if (ipDto.getIpMode() == 1) {
-			String targetIp = ipDto.getStartIp();
-			// 检查是否有相同单IP
-			query.and(wrapper -> wrapper
-					.eq("ip_mode", 1)
-					.eq("start_ip", targetIp));
-
-			// 检查是否被IP段包含
-			query.or(wrapper -> wrapper
-					.eq("ip_mode", 2)
-					.apply("INET_ATON({0}) BETWEEN INET_ATON(start_ip) AND INET_ATON(end_ip)", targetIp));
-
-		}
+		query.and(wrapper -> {
+			// 单IP模式检查
+			if (ipDto.getIpMode() == 1) {
+				String targetIp = ipDto.getStartIp();
+				// 检查是否有相同单IP
+				wrapper.and(w -> w
+						.eq("ip_mode", 1)
+						.eq("start_ip", targetIp));
+
+				// 检查是否被IP段包含
+				wrapper.or(w -> w
+						.eq("ip_mode", 2)
+						.apply("INET_ATON({0}) BETWEEN INET_ATON(start_ip) AND INET_ATON(end_ip)", targetIp));
 
-		// IP段模式检查
-		if (ipDto.getIpMode() == 2) {
-			String startIp = ipDto.getStartIp();
-			String endIp = ipDto.getEndIp();
-
-			// 检查是否与单IP重叠:单IP在输入IP段范围内
-			query.and(wrapper -> wrapper
-					.eq("ip_mode", 1)
-					.apply("INET_ATON(start_ip) BETWEEN INET_ATON({0}) AND INET_ATON({1})", startIp, endIp));
-			// 检查是否与IP段重叠:两个IP段有交集
-			query.or(wrapper -> wrapper
-					.eq("ip_mode", 2)
-					.and(w2 -> w2
-							.apply("INET_ATON(start_ip) BETWEEN INET_ATON({0}) AND INET_ATON({1})", startIp, endIp)
-							.or().apply("INET_ATON(end_ip) BETWEEN INET_ATON({0}) AND INET_ATON({1})", startIp, endIp)
-							.or().apply("INET_ATON({0}) BETWEEN INET_ATON(start_ip) AND INET_ATON(end_ip)", startIp)
-					)
-			);
-		}
+			}
 
+			// IP段模式检查
+			if (ipDto.getIpMode() == 2) {
+				String startIp = ipDto.getStartIp();
+				String endIp = ipDto.getEndIp();
+
+				// 检查是否与单IP重叠:单IP在输入IP段范围内
+				wrapper.and(w -> w
+						.eq("ip_mode", 1)
+						.apply("INET_ATON(start_ip) BETWEEN INET_ATON({0}) AND INET_ATON({1})", startIp, endIp));
+				// 检查是否与IP段重叠:两个IP段有交集
+				wrapper.or(w -> w
+						.eq("ip_mode", 2)
+						.and(w2 -> w2
+								.apply("INET_ATON(start_ip) BETWEEN INET_ATON({0}) AND INET_ATON({1})", startIp, endIp)
+								.or().apply("INET_ATON(end_ip) BETWEEN INET_ATON({0}) AND INET_ATON({1})", startIp, endIp)
+								.or().apply("INET_ATON({0}) BETWEEN INET_ATON(start_ip) AND INET_ATON(end_ip)", startIp)
+						)
+				);
+			}
+		});
 		return appsIpMapper.selectCount(query) > 0;
 	}
 

+ 4 - 2
pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/service/impl/MarketingConfigServiceImpl.java

@@ -208,9 +208,11 @@ public class MarketingConfigServiceImpl implements MarketingConfigService {
 
 			// 新增、修改
 			MarketingGroupDomain domainExist = groupDomainMapper.selectOne(Wrappers.<MarketingGroupDomain>lambdaQuery()
-					.eq(MarketingGroupDomain::getDomain, domainDto.getDomain()));
+					.eq(MarketingGroupDomain::getDomain, domainDto.getDomain())
+					.eq(MarketingGroupDomain::getGroupId, reqDto.getId())
+			);
 			if (domainExist != null && !domainExist.getId().equals(domainDto.getId())){
-				return R.failed("域名已存在");
+				return R.failed("域名:"+domainDto.getDomain()+"已存在");
 			}
 
 			if (domainDto.getId() == null){