feat(系统设置): 创建用户接口参数更改

This commit is contained in:
song-tianyang 2023-06-14 15:32:37 +08:00 committed by f2c-ci-robot[bot]
parent a59c805f22
commit 3ba24d93a4
23 changed files with 1089 additions and 535 deletions

View File

@ -3,9 +3,7 @@ package io.metersphere.system.domain;
import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
@ -15,7 +13,7 @@ import java.io.Serializable;
public class User implements Serializable {
@Schema(title = "用户ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{user.id.not_blank}", groups = {Updated.class})
@Size(min = 1, max = 50, message = "{user.id.length_range}", groups = {Created.class, Updated.class})
@Size(min = 1, max = 50, message = "{user.id.length_range}", groups = {Updated.class})
private String id;
@Schema(title = "用户名", requiredMode = Schema.RequiredMode.REQUIRED)
@ -24,16 +22,14 @@ public class User implements Serializable {
private String name;
@Schema(title = "用户邮箱", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{user.email.not_blank}", groups = {Created.class, Updated.class})
@NotBlank(message = "{user.email.not_blank}", groups = {Created.class})
@Size(min = 1, max = 64, message = "{user.email.length_range}", groups = {Created.class, Updated.class})
@Email(message = "{user.email.invalid}", groups = {Created.class, Updated.class})
private String email;
@Schema(title = "用户密码")
private String password;
@Schema(title = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "{user.enable.not_blank}", groups = {Updated.class})
@Schema(title = "是否启用")
private Boolean enable;
@Schema(title = "创建时间")

View File

@ -1,11 +1,15 @@
package io.metersphere.system.domain;
import io.metersphere.validation.groups.*;
import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.*;
import java.io.Serializable;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.io.Serializable;
@Data
public class UserRole implements Serializable {
@Schema(title = "组ID", requiredMode = Schema.RequiredMode.REQUIRED)

View File

@ -0,0 +1,16 @@
package io.metersphere.sdk.constants;
public enum UserRoleEnum {
GLOBAL("global");
private String value;
UserRoleEnum(String value) {
this.value = value;
}
@Override
public String toString() {
return this.value;
}
}

View File

@ -1,3 +1,5 @@
role.not.global.system=Role is not global system role
role.not.contains.member=Role not contains member
user.not.login=User not login
auth_source.id.not_blank=Auth source id must not be blank
auth_source.status.length_range=Auth source status must be between {min} and {max} characters long

View File

@ -1,149 +1,149 @@
user.not.login=\u672A\u83B7\u53D6\u5230\u767B\u5F55\u7528\u6237
auth_source.id.not_blank=\u8BA4\u8BC1\u6E90ID\u4E0D\u80FD\u4E3A\u7A7A
auth_source.status.length_range=\u8BA4\u8BC1\u6E90\u72B6\u6001\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
auth_source.status.not_blank=\u8BA4\u8BC1\u6E90\u72B6\u6001\u4E0D\u80FD\u4E3A\u7A7A
license.id.not_blank=License ID\u4E0D\u80FD\u4E3A\u7A7A
message_task.id.not_blank=\u6D88\u606F\u901A\u77E5\u4EFB\u52A1ID\u4E0D\u80FD\u4E3A\u7A7A
message_task.type.not_blank=\u6D88\u606F\u901A\u77E5\u4EFB\u52A1\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A
message_task.type.length_range=\u6D88\u606F\u901A\u77E5\u4EFB\u52A1\u7C7B\u578B\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
message_task.event.not_blank=\u6D88\u606F\u901A\u77E5\u4EFB\u52A1\u4E8B\u4EF6\u4E0D\u80FD\u4E3A\u7A7A
message_task.event.length_range=\u6D88\u606F\u901A\u77E5\u4EFB\u52A1\u4E8B\u4EF6\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
message_task.receiver.not_blank=\u6D88\u606F\u901A\u77E5\u4EFB\u52A1\u63A5\u6536\u8005\u4E0D\u80FD\u4E3A\u7A7A
message_task.receiver.length_range=\u6D88\u606F\u901A\u77E5\u4EFB\u52A1\u63A5\u6536\u8005\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
message_task.task_type.not_blank=\u6D88\u606F\u901A\u77E5\u4EFB\u52A1\u4EFB\u52A1\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A
message_task.task_type.length_range=\u6D88\u606F\u901A\u77E5\u4EFB\u52A1\u4EFB\u52A1\u7C7B\u578B\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
message_task.test_id.not_blank=\u6D88\u606F\u901A\u77E5\u4EFB\u52A1\u6D4B\u8BD5ID\u4E0D\u80FD\u4E3A\u7A7A
message_task.test_id.length_range=\u6D88\u606F\u901A\u77E5\u4EFB\u52A1\u6D4B\u8BD5ID\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
message_task.project_id.not_blank=\u6D88\u606F\u901A\u77E5\u4EFB\u52A1\u9879\u76EEID\u4E0D\u80FD\u4E3A\u7A7A
message_task.project_id.length_range=\u6D88\u606F\u901A\u77E5\u4EFB\u52A1\u9879\u76EEID\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
message_task_blob.id.not_blank=\u6D88\u606F\u901A\u77E5\u4EFB\u52A1ID\u4E0D\u80FD\u4E3A\u7A7A
notification.id.not_blank=\u6D88\u606F\u901A\u77E5ID\u4E0D\u80FD\u4E3A\u7A7A
notification.type.not_blank=\u6D88\u606F\u901A\u77E5\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A
notification.type.length_range=\u6D88\u606F\u901A\u77E5\u7C7B\u578B\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
notification.receiver.not_blank=\u6D88\u606F\u901A\u77E5\u63A5\u6536\u8005\u4E0D\u80FD\u4E3A\u7A7A
notification.receiver.length_range=\u6D88\u606F\u901A\u77E5\u63A5\u6536\u8005\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
notification.title.not_blank=\u6D88\u606F\u901A\u77E5\u6807\u9898\u4E0D\u80FD\u4E3A\u7A7A
notification.title.length_range=\u6D88\u606F\u901A\u77E5\u6807\u9898\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
notification.status.not_blank=\u6D88\u606F\u901A\u77E5\u72B6\u6001\u4E0D\u80FD\u4E3A\u7A7A
notification.status.length_range=\u6D88\u606F\u901A\u77E5\u72B6\u6001\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
notification.operator.not_blank=\u6D88\u606F\u901A\u77E5\u64CD\u4F5C\u8005\u4E0D\u80FD\u4E3A\u7A7A
notification.operator.length_range=\u6D88\u606F\u901A\u77E5\u64CD\u4F5C\u8005\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
notification.operation.not_blank=\u6D88\u606F\u901A\u77E5\u64CD\u4F5C\u4E0D\u80FD\u4E3A\u7A7A
notification.operation.length_range=\u6D88\u606F\u901A\u77E5\u64CD\u4F5C\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
notification.resource_id.not_blank=\u6D88\u606F\u901A\u77E5\u8D44\u6E90ID\u4E0D\u80FD\u4E3A\u7A7A
notification.resource_id.length_range=\u6D88\u606F\u901A\u77E5\u8D44\u6E90ID\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
notification.resource_type.not_blank=\u6D88\u606F\u901A\u77E5\u8D44\u6E90\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A
notification.resource_type.length_range=\u6D88\u606F\u901A\u77E5\u8D44\u6E90\u7C7B\u578B\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
notification.resource_name.not_blank=\u6D88\u606F\u901A\u77E5\u8D44\u6E90\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
notification.resource_name.length_range=\u6D88\u606F\u901A\u77E5\u8D44\u6E90\u540D\u79F0\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
novice_statistics.id.not_blank=\u65B0\u624B\u6751ID\u4E0D\u80FD\u4E3A\u7A7A
novice_statistics.guide_step.not_blank=\u65B0\u624B\u6751\u6B65\u9AA4\u4E0D\u80FD\u4E3A\u7A7A
novice_statistics.guide_step.length_range=\u65B0\u624B\u6751\u6B65\u9AA4\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
operating_log.id.not_blank=\u64CD\u4F5C\u65E5\u5FD7ID\u4E0D\u80FD\u4E3A\u7A7A
operating_log.project_id.not_blank=\u64CD\u4F5C\u65E5\u5FD7\u9879\u76EEID\u4E0D\u80FD\u4E3A\u7A7A
operating_log.project_id.length_range=\u64CD\u4F5C\u65E5\u5FD7\u9879\u76EEID\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
operating_log_resource.id.not_blank=\u64CD\u4F5C\u65E5\u5FD7\u8D44\u6E90ID\u4E0D\u80FD\u4E3A\u7A7A
operating_log_resource.operating_log_id.not_blank=\u64CD\u4F5C\u65E5\u5FD7\u8D44\u6E90\u64CD\u4F5C\u65E5\u5FD7ID\u4E0D\u80FD\u4E3A\u7A7A
operating_log_resource.operating_log_id.length_range=\u64CD\u4F5C\u65E5\u5FD7\u8D44\u6E90\u64CD\u4F5C\u65E5\u5FD7ID\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
operating_log_resource.source_id.not_blank=\u64CD\u4F5C\u65E5\u5FD7\u8D44\u6E90\u6765\u6E90ID\u4E0D\u80FD\u4E3A\u7A7A
operating_log_resource.source_id.length_range=\u64CD\u4F5C\u65E5\u5FD7\u8D44\u6E90\u6765\u6E90ID\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
plugin.id.not_blank=\u63D2\u4EF6\u4E3B\u952E\u4E0D\u80FD\u4E3A\u7A7A
plugin.plugin_id.not_blank=\u63D2\u4EF6ID\u4E0D\u80FD\u4E3A\u7A7A
plugin.plugin_id.length_range=\u63D2\u4EF6ID\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
plugin.script_id.not_blank=\u63D2\u4EF6\u811A\u672CID\u4E0D\u80FD\u4E3A\u7A7A
plugin.script_id.length_range=\u63D2\u4EF6\u811A\u672CID\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
plugin.clazz_name.not_blank=\u63D2\u4EF6\u7C7B\u540D\u4E0D\u80FD\u4E3A\u7A7A
plugin.clazz_name.length_range=\u63D2\u4EF6\u7C7B\u540D\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
plugin.jmeter_clazz.not_blank=\u63D2\u4EF6jmeter\u7C7B\u540D\u4E0D\u80FD\u4E3A\u7A7A
plugin.jmeter_clazz.length_range=\u63D2\u4EF6jmeter\u7C7B\u540D\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
plugin.source_path.not_blank=\u63D2\u4EF6\u6E90\u8DEF\u5F84\u4E0D\u80FD\u4E3A\u7A7A
plugin.source_path.length_range=\u63D2\u4EF6\u6E90\u8DEF\u5F84\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
plugin.source_name.not_blank=\u63D2\u4EF6\u6E90\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
plugin.source_name.length_range=\u63D2\u4EF6\u6E90\u540D\u79F0\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
plugin.scenario.not_blank=\u63D2\u4EF6\u573A\u666F\u4E0D\u80FD\u4E3A\u7A7A
plugin.scenario.length_range=\u63D2\u4EF6\u573A\u666F\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
plugin_blob.id.not_blank=\u63D2\u4EF6ID\u4E0D\u80FD\u4E3A\u7A7A
quota.id.not_blank=\u914D\u989DID\u4E0D\u80FD\u4E3A\u7A7A
schedule.id.not_blank=\u5B9A\u65F6\u4EFB\u52A1ID\u4E0D\u80FD\u4E3A\u7A7A
schedule.type.not_blank=\u5B9A\u65F6\u4EFB\u52A1\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A
schedule.type.length_range=\u5B9A\u65F6\u4EFB\u52A1\u7C7B\u578B\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
schedule.value.not_blank=\u5B9A\u65F6\u4EFB\u52A1\u503C\u4E0D\u80FD\u4E3A\u7A7A
schedule.value.length_range=\u5B9A\u65F6\u4EFB\u52A1\u503C\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
schedule.job.not_blank=\u5B9A\u65F6\u4EFB\u52A1\u4E0D\u80FD\u4E3A\u7A7A
schedule.job.length_range=\u5B9A\u65F6\u4EFB\u52A1\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
schedule.create_user.not_blank=\u5B9A\u65F6\u4EFB\u52A1\u521B\u5EFA\u4EBA\u4E0D\u80FD\u4E3A\u7A7A
schedule.create_user.length_range=\u5B9A\u65F6\u4EFB\u52A1\u521B\u5EFA\u4EBA\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
service_integration.id.not_blank=\u670D\u52A1\u96C6\u6210ID\u4E0D\u80FD\u4E3A\u7A7A
service_integration.platform.not_blank=\u670D\u52A1\u96C6\u6210\u5E73\u53F0\u4E0D\u80FD\u4E3A\u7A7A
service_integration.platform.length_range=\u670D\u52A1\u96C6\u6210\u5E73\u53F0\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
system_parameter.param_key.not_blank=\u7CFB\u7EDF\u53C2\u6570Key\u4E0D\u80FD\u4E3A\u7A7A
system_parameter.type.not_blank=\u7CFB\u7EDF\u53C2\u6570\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A
system_parameter.type.length_range=\u7CFB\u7EDF\u53C2\u6570\u7C7B\u578B\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
test_resource.id.not_blank=\u8D44\u6E90\u6C60\u8282\u70B9ID\u4E0D\u80FD\u4E3A\u7A7A
test_resource.test_resource_pool_id.not_blank=\u8D44\u6E90\u6C60ID\u4E0D\u80FD\u4E3A\u7A7A
test_resource.test_resource_pool_id.length_range=\u8D44\u6E90\u6C60ID\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
test_resource.status.not_blank=\u8D44\u6E90\u6C60\u8282\u70B9\u72B6\u6001\u4E0D\u80FD\u4E3A\u7A7A
test_resource.status.length_range=\u8D44\u6E90\u6C60\u8282\u70B9\u72B6\u6001\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
test_resource_pool.id.not_blank=\u8D44\u6E90\u6C60ID\u4E0D\u80FD\u4E3A\u7A7A
test_resource_pool.name.not_blank=\u8D44\u6E90\u6C60\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
test_resource_pool.name.length_range=\u8D44\u6E90\u6C60\u540D\u79F0\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
test_resource_pool.type.not_blank=\u8D44\u6E90\u6C60\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A
test_resource_pool.type.length_range=\u8D44\u6E90\u6C60\u7C7B\u578B\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
test_resource_pool.status.not_blank=\u8D44\u6E90\u6C60\u72B6\u6001\u4E0D\u80FD\u4E3A\u7A7A
test_resource_pool.status.length_range=\u8D44\u6E90\u6C60\u72B6\u6001\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
user.id.not_blank=\u7528\u6237ID\u4E0D\u80FD\u4E3A\u7A7A
user.name.not_blank=\u7528\u6237\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
user.name.length_range=\u7528\u6237\u540D\u79F0\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
user.email.not_blank=\u7528\u6237email\u4E0D\u80FD\u4E3A\u7A7A
user.email.length_range=\u7528\u6237email\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
user.email.repeat=\u7528\u6237email\u5DF2\u5B58\u5728
user.email.invalid=\u7528\u6237email\u683C\u5F0F\u4E0D\u6B63\u786E
user.status.not_blank=\u7528\u6237\u72B6\u6001\u4E0D\u80FD\u4E3A\u7A7A
user.status.length_range=\u7528\u6237\u72B6\u6001\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
user.source.not_blank=\u7528\u6237\u6765\u6E90\u4E0D\u80FD\u4E3A\u7A7A
user.source.length_range=\u7528\u6237\u6765\u6E90\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
user.create_user.not_blank=\u7528\u6237\u521B\u5EFA\u4EBA\u4E0D\u80FD\u4E3A\u7A7A
user.create_user.length_range=\u7528\u6237\u521B\u5EFA\u4EBA\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
user_extend.id.not_blank=\u7528\u6237ID\u4E0D\u80FD\u4E3A\u7A7A
user_key.id.not_blank=\u7528\u6237ApiKey ID\u4E0D\u80FD\u4E3A\u7A7A
user_key.create_user.not_blank=\u7528\u6237ApiKey\u521B\u5EFA\u4EBA\u4E0D\u80FD\u4E3A\u7A7A
user_key.create_user.length_range=\u7528\u6237ApiKey\u521B\u5EFA\u4EBA\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
user_key.access_key.not_blank=\u7528\u6237ApiKey access key\u4E0D\u80FD\u4E3A\u7A7A
user_key.access_key.length_range=\u7528\u6237ApiKey access key\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
user_key.secret_key.not_blank=\u7528\u6237ApiKey secret key\u4E0D\u80FD\u4E3A\u7A7A
user_key.secret_key.length_range=\u7528\u6237ApiKey secret key\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
user.info.not_empty=\u7528\u6237\u4FE1\u606F\u4E0D\u80FD\u4E3A\u7A7A
user.organizationId.not_blank=\u7528\u6237\u7EC4\u7EC7\u4E0D\u80FD\u4E3A\u7A7A
user.projectId.not_blank=\u7528\u6237\u9879\u76EE\u4E0D\u80FD\u4E3A\u7A7A
user_role.id.not_blank=\u7528\u6237\u7EC4ID\u4E0D\u80FD\u4E3A\u7A7A
user_role.name.not_blank=\u7528\u6237\u7EC4\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
user_role.name.length_range=\u7528\u6237\u7EC4\u540D\u79F0\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
user_role.system.not_blank=\u662F\u5426\u662F\u7CFB\u7EDF\u7528\u6237\u7EC4\u4E0D\u80FD\u4E3A\u7A7A
user_role.system.length_range=\u662F\u5426\u662F\u7CFB\u7EDF\u7528\u6237\u7EC4\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
user_role.type.not_blank=\u7528\u6237\u7EC4\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A
user_role.type.length_range=\u7528\u6237\u7EC4\u7C7B\u578B\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
user_role.create_user.not_blank=\u7528\u6237\u7EC4\u521B\u5EFA\u4EBA\u4E0D\u80FD\u4E3A\u7A7A
user_role.create_user.length_range=\u7528\u6237\u7EC4\u521B\u5EFA\u4EBA\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
user_role.scope_id.not_blank=\u7528\u6237\u7EC4\u5E94\u7528\u8303\u56F4\u4E0D\u80FD\u4E3A\u7A7A
user_role.scope_id.length_range=\u7528\u6237\u7EC4\u5E94\u7528\u8303\u56F4\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
user_role_permission.id.not_blank=\u7528\u6237\u7EC4\u6743\u9650ID\u4E0D\u80FD\u4E3A\u7A7A
user_role_permission.role_id.not_blank=\u7528\u6237\u7EC4\u6743\u9650\u7528\u6237\u7EC4ID\u4E0D\u80FD\u4E3A\u7A7A
user_role_permission.role_id.length_range=\u7528\u6237\u7EC4\u6743\u9650\u7528\u6237\u7EC4ID\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
user_role_permission.permission_id.not_blank=\u7528\u6237\u7EC4\u6743\u9650\u6743\u9650ID\u4E0D\u80FD\u4E3A\u7A7A
user_role_permission.permission_id.length_range=\u7528\u6237\u7EC4\u6743\u9650\u6743\u9650ID\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
user_role_permission.module_id.not_blank=\u7528\u6237\u7EC4\u6743\u9650\u6A21\u5757ID\u4E0D\u80FD\u4E3A\u7A7A
user_role_permission.module_id.length_range=\u7528\u6237\u7EC4\u6743\u9650\u6A21\u5757ID\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
user_role_relation.id.not_blank=\u7528\u6237\u7EC4\u5173\u7CFBID\u4E0D\u80FD\u4E3A\u7A7A
user_role_relation.user_id.not_blank=\u7528\u6237\u7EC4\u5173\u7CFB\u7528\u6237ID\u4E0D\u80FD\u4E3A\u7A7A
user_role_relation.user_id.length_range=\u7528\u6237\u7EC4\u5173\u7CFB\u7528\u6237ID\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
user_role_relation.role_id.not_blank=\u7528\u6237\u7EC4\u5173\u7CFB\u7528\u6237\u7EC4ID\u4E0D\u80FD\u4E3A\u7A7A
user_role_relation.role_id.length_range=\u7528\u6237\u7EC4\u5173\u7CFB\u7528\u6237\u7EC4ID\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
user_role_relation.source_id.not_blank=\u7528\u6237\u7EC4\u5173\u7CFB\u6765\u6E90ID\u4E0D\u80FD\u4E3A\u7A7A
user_role_relation.source_id.length_range=\u7528\u6237\u7EC4\u5173\u7CFB\u6765\u6E90ID\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
organization.id.not_blank=\u5DE5\u4F5C\u7A7A\u95F4ID\u4E0D\u80FD\u4E3A\u7A7A
organization.name.not_blank=\u5DE5\u4F5C\u7A7A\u95F4\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
organization.name.length_range=\u5DE5\u4F5C\u7A7A\u95F4\u540D\u79F0\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
organization.create_user.not_blank=\u5DE5\u4F5C\u7A7A\u95F4\u521B\u5EFA\u4EBA\u4E0D\u80FD\u4E3A\u7A7A
organization.create_user.length_range=\u5DE5\u4F5C\u7A7A\u95F4\u521B\u5EFA\u4EBA\u957F\u5EA6\u5FC5\u987B\u5728{min}\u548C{max}\u4E4B\u95F4
role.not.global.system=角色不是全局系统角色
role.not.contains.member=角色不包含系统成员角色
user.not.login=未获取到登录用户
auth_source.id.not_blank=认证源ID不能为空
auth_source.status.length_range=认证源状态长度必须在{min}和{max}之间
auth_source.status.not_blank=认证源状态不能为空
license.id.not_blank=License ID不能为空
message_task.id.not_blank=消息通知任务ID不能为空
message_task.type.not_blank=消息通知任务类型不能为空
message_task.type.length_range=消息通知任务类型长度必须在{min}和{max}之间
message_task.event.not_blank=消息通知任务事件不能为空
message_task.event.length_range=消息通知任务事件长度必须在{min}和{max}之间
message_task.receiver.not_blank=消息通知任务接收者不能为空
message_task.receiver.length_range=消息通知任务接收者长度必须在{min}和{max}之间
message_task.task_type.not_blank=消息通知任务任务类型不能为空
message_task.task_type.length_range=消息通知任务任务类型长度必须在{min}和{max}之间
message_task.test_id.not_blank=消息通知任务测试ID不能为空
message_task.test_id.length_range=消息通知任务测试ID长度必须在{min}和{max}之间
message_task.project_id.not_blank=消息通知任务项目ID不能为空
message_task.project_id.length_range=消息通知任务项目ID长度必须在{min}和{max}之间
message_task_blob.id.not_blank=消息通知任务ID不能为空
notification.id.not_blank=消息通知ID不能为空
notification.type.not_blank=消息通知类型不能为空
notification.type.length_range=消息通知类型长度必须在{min}和{max}之间
notification.receiver.not_blank=消息通知接收者不能为空
notification.receiver.length_range=消息通知接收者长度必须在{min}和{max}之间
notification.title.not_blank=消息通知标题不能为空
notification.title.length_range=消息通知标题长度必须在{min}和{max}之间
notification.status.not_blank=消息通知状态不能为空
notification.status.length_range=消息通知状态长度必须在{min}和{max}之间
notification.operator.not_blank=消息通知操作者不能为空
notification.operator.length_range=消息通知操作者长度必须在{min}和{max}之间
notification.operation.not_blank=消息通知操作不能为空
notification.operation.length_range=消息通知操作长度必须在{min}和{max}之间
notification.resource_id.not_blank=消息通知资源ID不能为空
notification.resource_id.length_range=消息通知资源ID长度必须在{min}和{max}之间
notification.resource_type.not_blank=消息通知资源类型不能为空
notification.resource_type.length_range=消息通知资源类型长度必须在{min}和{max}之间
notification.resource_name.not_blank=消息通知资源名称不能为空
notification.resource_name.length_range=消息通知资源名称长度必须在{min}和{max}之间
novice_statistics.id.not_blank=新手村ID不能为空
novice_statistics.guide_step.not_blank=新手村步骤不能为空
novice_statistics.guide_step.length_range=新手村步骤长度必须在{min}和{max}之间
operating_log.id.not_blank=操作日志ID不能为空
operating_log.project_id.not_blank=操作日志项目ID不能为空
operating_log.project_id.length_range=操作日志项目ID长度必须在{min}和{max}之间
operating_log_resource.id.not_blank=操作日志资源ID不能为空
operating_log_resource.operating_log_id.not_blank=操作日志资源操作日志ID不能为空
operating_log_resource.operating_log_id.length_range=操作日志资源操作日志ID长度必须在{min}和{max}之间
operating_log_resource.source_id.not_blank=操作日志资源来源ID不能为空
operating_log_resource.source_id.length_range=操作日志资源来源ID长度必须在{min}和{max}之间
plugin.id.not_blank=插件主键不能为空
plugin.plugin_id.not_blank=插件ID不能为空
plugin.plugin_id.length_range=插件ID长度必须在{min}和{max}之间
plugin.script_id.not_blank=插件脚本ID不能为空
plugin.script_id.length_range=插件脚本ID长度必须在{min}和{max}之间
plugin.clazz_name.not_blank=插件类名不能为空
plugin.clazz_name.length_range=插件类名长度必须在{min}和{max}之间
plugin.jmeter_clazz.not_blank=插件jmeter类名不能为空
plugin.jmeter_clazz.length_range=插件jmeter类名长度必须在{min}和{max}之间
plugin.source_path.not_blank=插件源路径不能为空
plugin.source_path.length_range=插件源路径长度必须在{min}和{max}之间
plugin.source_name.not_blank=插件源名称不能为空
plugin.source_name.length_range=插件源名称长度必须在{min}和{max}之间
plugin.scenario.not_blank=插件场景不能为空
plugin.scenario.length_range=插件场景长度必须在{min}和{max}之间
plugin_blob.id.not_blank=插件ID不能为空
quota.id.not_blank=配额ID不能为空
schedule.id.not_blank=定时任务ID不能为空
schedule.type.not_blank=定时任务类型不能为空
schedule.type.length_range=定时任务类型长度必须在{min}和{max}之间
schedule.value.not_blank=定时任务值不能为空
schedule.value.length_range=定时任务值长度必须在{min}和{max}之间
schedule.job.not_blank=定时任务不能为空
schedule.job.length_range=定时任务长度必须在{min}和{max}之间
schedule.create_user.not_blank=定时任务创建人不能为空
schedule.create_user.length_range=定时任务创建人长度必须在{min}和{max}之间
service_integration.id.not_blank=服务集成ID不能为空
service_integration.platform.not_blank=服务集成平台不能为空
service_integration.platform.length_range=服务集成平台长度必须在{min}和{max}之间
system_parameter.param_key.not_blank=系统参数Key不能为空
system_parameter.type.not_blank=系统参数类型不能为空
system_parameter.type.length_range=系统参数类型长度必须在{min}和{max}之间
test_resource.id.not_blank=资源池节点ID不能为空
test_resource.test_resource_pool_id.not_blank=资源池ID不能为空
test_resource.test_resource_pool_id.length_range=资源池ID长度必须在{min}和{max}之间
test_resource.status.not_blank=资源池节点状态不能为空
test_resource.status.length_range=资源池节点状态长度必须在{min}和{max}之间
test_resource_pool.id.not_blank=资源池ID不能为空
test_resource_pool.name.not_blank=资源池名称不能为空
test_resource_pool.name.length_range=资源池名称长度必须在{min}和{max}之间
test_resource_pool.type.not_blank=资源池类型不能为空
test_resource_pool.type.length_range=资源池类型长度必须在{min}和{max}之间
test_resource_pool.status.not_blank=资源池状态不能为空
test_resource_pool.status.length_range=资源池状态长度必须在{min}和{max}之间
user.id.not_blank=用户ID不能为空
user.name.not_blank=用户名称不能为空
user.name.length_range=用户名称长度必须在{min}和{max}之间
user.email.not_blank=用户email不能为空
user.email.length_range=用户email长度必须在{min}和{max}之间
user.email.repeat=用户email已存在
user.email.invalid=用户email格式不正确
user.status.not_blank=用户状态不能为空
user.status.length_range=用户状态长度必须在{min}和{max}之间
user.source.not_blank=用户来源不能为空
user.source.length_range=用户来源长度必须在{min}和{max}之间
user.create_user.not_blank=用户创建人不能为空
user.create_user.length_range=用户创建人长度必须在{min}和{max}之间
user_extend.id.not_blank=用户ID不能为空
user_key.id.not_blank=用户ApiKey ID不能为空
user_key.create_user.not_blank=用户ApiKey创建人不能为空
user_key.create_user.length_range=用户ApiKey创建人长度必须在{min}和{max}之间
user_key.access_key.not_blank=用户ApiKey access key不能为空
user_key.access_key.length_range=用户ApiKey access key长度必须在{min}和{max}之间
user_key.secret_key.not_blank=用户ApiKey secret key不能为空
user_key.secret_key.length_range=用户ApiKey secret key长度必须在{min}和{max}之间
user.info.not_empty=用户信息不能为空
user.organizationId.not_blank=用户组织不能为空
user.projectId.not_blank=用户项目不能为空
user_role.id.not_blank=用户组ID不能为空
user_role.name.not_blank=用户组名称不能为空
user_role.name.length_range=用户组名称长度必须在{min}和{max}之间
user_role.system.not_blank=是否是系统用户组不能为空
user_role.system.length_range=是否是系统用户组长度必须在{min}和{max}之间
user_role.type.not_blank=用户组类型不能为空
user_role.type.length_range=用户组类型长度必须在{min}和{max}之间
user_role.create_user.not_blank=用户组创建人不能为空
user_role.create_user.length_range=用户组创建人长度必须在{min}和{max}之间
user_role.scope_id.not_blank=用户组应用范围不能为空
user_role.scope_id.length_range=用户组应用范围长度必须在{min}和{max}之间
user_role_permission.id.not_blank=用户组权限ID不能为空
user_role_permission.role_id.not_blank=用户组权限用户组ID不能为空
user_role_permission.role_id.length_range=用户组权限用户组ID长度必须在{min}和{max}之间
user_role_permission.permission_id.not_blank=用户组权限权限ID不能为空
user_role_permission.permission_id.length_range=用户组权限权限ID长度必须在{min}和{max}之间
user_role_permission.module_id.not_blank=用户组权限模块ID不能为空
user_role_permission.module_id.length_range=用户组权限模块ID长度必须在{min}和{max}之间
user_role_relation.id.not_blank=用户组关系ID不能为空
user_role_relation.user_id.not_blank=用户组关系用户ID不能为空
user_role_relation.user_id.length_range=用户组关系用户ID长度必须在{min}和{max}之间
user_role_relation.role_id.not_blank=用户组关系用户组ID不能为空
user_role_relation.role_id.length_range=用户组关系用户组ID长度必须在{min}和{max}之间
user_role_relation.source_id.not_blank=用户组关系来源ID不能为空
user_role_relation.source_id.length_range=用户组关系来源ID长度必须在{min}和{max}之间
organization.id.not_blank=工作空间ID不能为空
organization.name.not_blank=工作空间名称不能为空
organization.name.length_range=工作空间名称长度必须在{min}和{max}之间
organization.create_user.not_blank=工作空间创建人不能为空
organization.create_user.length_range=工作空间创建人长度必须在{min}和{max}之间

View File

@ -1,147 +1,149 @@
user.not.login=\u672A\u7372\u53D6\u5230\u767B\u9304\u7528\u6236
auth_source.id.not_blank=\u8A8D\u8B49\u6E90ID\u4E0D\u80FD\u70BA\u7A7A
auth_source.status.length_range=\u8A8D\u8B49\u6E90\u72C0\u614B\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
auth_source.status.not_blank=\u8A8D\u8B49\u6E90\u72C0\u614B\u4E0D\u80FD\u70BA\u7A7A
license.id.not_blank=License ID\u4E0D\u80FD\u70BA\u7A7A
message_task.id.not_blank=\u6D88\u606F\u901A\u77E5\u4EFB\u52D9ID\u4E0D\u80FD\u70BA\u7A7A
message_task.type.not_blank=\u6D88\u606F\u901A\u77E5\u4EFB\u52D9\u985E\u578B\u4E0D\u80FD\u70BA\u7A7A
message_task.type.length_range=\u6D88\u606F\u901A\u77E5\u4EFB\u52D9\u985E\u578B\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
message_task.event.not_blank=\u6D88\u606F\u901A\u77E5\u4EFB\u52D9\u4E8B\u4EF6\u4E0D\u80FD\u70BA\u7A7A
message_task.event.length_range=\u6D88\u606F\u901A\u77E5\u4EFB\u52D9\u4E8B\u4EF6\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
message_task.receiver.not_blank=\u6D88\u606F\u901A\u77E5\u4EFB\u52D9\u63A5\u6536\u8005\u4E0D\u80FD\u70BA\u7A7A
message_task.receiver.length_range=\u6D88\u606F\u901A\u77E5\u4EFB\u52D9\u63A5\u6536\u8005\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
message_task.task_type.not_blank=\u6D88\u606F\u901A\u77E5\u4EFB\u52D9\u4EFB\u52D9\u985E\u578B\u4E0D\u80FD\u70BA\u7A7A
message_task.task_type.length_range=\u6D88\u606F\u901A\u77E5\u4EFB\u52D9\u4EFB\u52D9\u985E\u578B\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
message_task.test_id.not_blank=\u6D88\u606F\u901A\u77E5\u4EFB\u52D9\u6E2C\u8A66ID\u4E0D\u80FD\u70BA\u7A7A
message_task.test_id.length_range=\u6D88\u606F\u901A\u77E5\u4EFB\u52D9\u6E2C\u8A66ID\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
message_task.project_id.not_blank=\u6D88\u606F\u901A\u77E5\u4EFB\u52D9\u9805\u76EEID\u4E0D\u80FD\u70BA\u7A7A
message_task.project_id.length_range=\u6D88\u606F\u901A\u77E5\u4EFB\u52D9\u9805\u76EEID\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
message_task_blob.id.not_blank=\u6D88\u606F\u901A\u77E5\u4EFB\u52D9ID\u4E0D\u80FD\u70BA\u7A7A
notification.id.not_blank=\u6D88\u606F\u901A\u77E5ID\u4E0D\u80FD\u70BA\u7A7A
notification.type.not_blank=\u6D88\u606F\u901A\u77E5\u985E\u578B\u4E0D\u80FD\u70BA\u7A7A
notification.type.length_range=\u6D88\u606F\u901A\u77E5\u985E\u578B\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
notification.receiver.not_blank=\u6D88\u606F\u901A\u77E5\u63A5\u6536\u8005\u4E0D\u80FD\u70BA\u7A7A
notification.receiver.length_range=\u6D88\u606F\u901A\u77E5\u63A5\u6536\u8005\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
notification.title.not_blank=\u6D88\u606F\u901A\u77E5\u6A19\u984C\u4E0D\u80FD\u70BA\u7A7A
notification.title.length_range=\u6D88\u606F\u901A\u77E5\u6A19\u984C\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
notification.status.not_blank=\u6D88\u606F\u901A\u77E5\u72C0\u614B\u4E0D\u80FD\u70BA\u7A7A
notification.status.length_range=\u6D88\u606F\u901A\u77E5\u72C0\u614B\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
notification.operator.not_blank=\u6D88\u606F\u901A\u77E5\u64CD\u4F5C\u8005\u4E0D\u80FD\u70BA\u7A7A
notification.operator.length_range=\u6D88\u606F\u901A\u77E5\u64CD\u4F5C\u8005\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
notification.operation.not_blank=\u6D88\u606F\u901A\u77E5\u64CD\u4F5C\u4E0D\u80FD\u70BA\u7A7A
notification.operation.length_range=\u6D88\u606F\u901A\u77E5\u64CD\u4F5C\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
notification.resource_id.not_blank=\u6D88\u606F\u901A\u77E5\u8CC7\u6E90ID\u4E0D\u80FD\u70BA\u7A7A
notification.resource_id.length_range=\u6D88\u606F\u901A\u77E5\u8CC7\u6E90ID\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
notification.resource_type.not_blank=\u6D88\u606F\u901A\u77E5\u8CC7\u6E90\u985E\u578B\u4E0D\u80FD\u70BA\u7A7A
notification.resource_type.length_range=\u6D88\u606F\u901A\u77E5\u8CC7\u6E90\u985E\u578B\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
notification.resource_name.not_blank=\u6D88\u606F\u901A\u77E5\u8CC7\u6E90\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A
notification.resource_name.length_range=\u6D88\u606F\u901A\u77E5\u8CC7\u6E90\u540D\u7A31\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
novice_statistics.id.not_blank=\u65B0\u624B\u6751ID\u4E0D\u80FD\u70BA\u7A7A
novice_statistics.guide_step.not_blank=\u65B0\u624B\u6751\u6B65\u9A5F\u4E0D\u80FD\u70BA\u7A7A
novice_statistics.guide_step.length_range=\u65B0\u624B\u6751\u6B65\u9A5F\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
operating_log.id.not_blank=\u64CD\u4F5C\u65E5\u8A8CID\u4E0D\u80FD\u70BA\u7A7A
operating_log.project_id.not_blank=\u64CD\u4F5C\u65E5\u8A8C\u9805\u76EEID\u4E0D\u80FD\u70BA\u7A7A
operating_log.project_id.length_range=\u64CD\u4F5C\u65E5\u8A8C\u9805\u76EEID\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
operating_log_resource.id.not_blank=\u64CD\u4F5C\u65E5\u8A8C\u8CC7\u6E90ID\u4E0D\u80FD\u70BA\u7A7A
operating_log_resource.operating_log_id.not_blank=\u64CD\u4F5C\u65E5\u8A8C\u8CC7\u6E90\u64CD\u4F5C\u65E5\u8A8CID\u4E0D\u80FD\u70BA\u7A7A
operating_log_resource.operating_log_id.length_range=\u64CD\u4F5C\u65E5\u8A8C\u8CC7\u6E90\u64CD\u4F5C\u65E5\u8A8CID\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
operating_log_resource.source_id.not_blank=\u64CD\u4F5C\u65E5\u8A8C\u8CC7\u6E90\u4F86\u6E90ID\u4E0D\u80FD\u70BA\u7A7A
operating_log_resource.source_id.length_range=\u64CD\u4F5C\u65E5\u8A8C\u8CC7\u6E90\u4F86\u6E90ID\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
plugin.id.not_blank=\u63D2\u4EF6\u4E3B\u9375\u4E0D\u80FD\u70BA\u7A7A
plugin.plugin_id.not_blank=\u63D2\u4EF6ID\u4E0D\u80FD\u70BA\u7A7A
plugin.plugin_id.length_range=\u63D2\u4EF6ID\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
plugin.script_id.not_blank=\u63D2\u4EF6\u8173\u672CID\u4E0D\u80FD\u70BA\u7A7A
plugin.script_id.length_range=\u63D2\u4EF6\u8173\u672CID\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
plugin.clazz_name.not_blank=\u63D2\u4EF6\u985E\u540D\u4E0D\u80FD\u70BA\u7A7A
plugin.clazz_name.length_range=\u63D2\u4EF6\u985E\u540D\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
plugin.jmeter_clazz.not_blank=\u63D2\u4EF6jmeter\u985E\u540D\u4E0D\u80FD\u70BA\u7A7A
plugin.jmeter_clazz.length_range=\u63D2\u4EF6jmeter\u985E\u540D\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
plugin.source_path.not_blank=\u63D2\u4EF6\u6E90\u8DEF\u5F91\u4E0D\u80FD\u70BA\u7A7A
plugin.source_path.length_range=\u63D2\u4EF6\u6E90\u8DEF\u5F91\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
plugin.source_name.not_blank=\u63D2\u4EF6\u6E90\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A
plugin.source_name.length_range=\u63D2\u4EF6\u6E90\u540D\u7A31\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
plugin.scenario.not_blank=\u63D2\u4EF6\u5834\u666F\u4E0D\u80FD\u70BA\u7A7A
plugin.scenario.length_range=\u63D2\u4EF6\u5834\u666F\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
plugin_blob.id.not_blank=\u63D2\u4EF6ID\u4E0D\u80FD\u70BA\u7A7A
quota.id.not_blank=\u914D\u984DID\u4E0D\u80FD\u70BA\u7A7A
schedule.id.not_blank=\u5B9A\u6642\u4EFB\u52D9ID\u4E0D\u80FD\u70BA\u7A7A
schedule.type.not_blank=\u5B9A\u6642\u4EFB\u52D9\u985E\u578B\u4E0D\u80FD\u70BA\u7A7A
schedule.type.length_range=\u5B9A\u6642\u4EFB\u52D9\u985E\u578B\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
schedule.value.not_blank=\u5B9A\u6642\u4EFB\u52D9\u503C\u4E0D\u80FD\u70BA\u7A7A
schedule.value.length_range=\u5B9A\u6642\u4EFB\u52D9\u503C\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
schedule.job.not_blank=\u5B9A\u6642\u4EFB\u52D9\u4E0D\u80FD\u70BA\u7A7A
schedule.job.length_range=\u5B9A\u6642\u4EFB\u52D9\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
schedule.create_user.not_blank=\u5B9A\u6642\u4EFB\u52D9\u5275\u5EFA\u4EBA\u4E0D\u80FD\u70BA\u7A7A
schedule.create_user.length_range=\u5B9A\u6642\u4EFB\u52D9\u5275\u5EFA\u4EBA\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
service_integration.id.not_blank=\u670D\u52D9\u96C6\u6210ID\u4E0D\u80FD\u70BA\u7A7A
service_integration.platform.not_blank=\u670D\u52D9\u96C6\u6210\u5E73\u53F0\u4E0D\u80FD\u70BA\u7A7A
service_integration.platform.length_range=\u670D\u52D9\u96C6\u6210\u5E73\u53F0\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
system_parameter.param_key.not_blank=\u7CFB\u7D71\u53C3\u6578Key\u4E0D\u80FD\u70BA\u7A7A
system_parameter.type.not_blank=\u7CFB\u7D71\u53C3\u6578\u985E\u578B\u4E0D\u80FD\u70BA\u7A7A
system_parameter.type.length_range=\u7CFB\u7D71\u53C3\u6578\u985E\u578B\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
test_resource.id.not_blank=\u8CC7\u6E90\u6C60\u7BC0\u9EDEID\u4E0D\u80FD\u70BA\u7A7A
test_resource.test_resource_pool_id.not_blank=\u8CC7\u6E90\u6C60ID\u4E0D\u80FD\u70BA\u7A7A
test_resource.test_resource_pool_id.length_range=\u8CC7\u6E90\u6C60ID\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
test_resource.status.not_blank=\u8CC7\u6E90\u6C60\u7BC0\u9EDE\u72C0\u614B\u4E0D\u80FD\u70BA\u7A7A
test_resource.status.length_range=\u8CC7\u6E90\u6C60\u7BC0\u9EDE\u72C0\u614B\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
test_resource_pool.id.not_blank=\u8CC7\u6E90\u6C60ID\u4E0D\u80FD\u70BA\u7A7A
test_resource_pool.name.not_blank=\u8CC7\u6E90\u6C60\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A
test_resource_pool.name.length_range=\u8CC7\u6E90\u6C60\u540D\u7A31\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
test_resource_pool.type.not_blank=\u8CC7\u6E90\u6C60\u985E\u578B\u4E0D\u80FD\u70BA\u7A7A
test_resource_pool.type.length_range=\u8CC7\u6E90\u6C60\u985E\u578B\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
test_resource_pool.status.not_blank=\u8CC7\u6E90\u6C60\u72C0\u614B\u4E0D\u80FD\u70BA\u7A7A
test_resource_pool.status.length_range=\u8CC7\u6E90\u6C60\u72C0\u614B\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
user.id.not_blank=\u7528\u6236ID\u4E0D\u80FD\u70BA\u7A7A
user.name.not_blank=\u7528\u6236\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A
user.name.length_range=\u7528\u6236\u540D\u7A31\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
user.email.not_blank=\u7528\u6236email\u4E0D\u80FD\u70BA\u7A7A
user.email.length_range=\u7528\u6236email\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
user.email.repeat=\u7528\u6236email\u5DF2\u5B58\u5728
user.email.invalid=\u7528\u6236email\u683C\u5F0F\u4E0D\u6B63\u78BA
user.status.not_blank=\u7528\u6236\u72C0\u614B\u4E0D\u80FD\u70BA\u7A7A
user.status.length_range=\u7528\u6236\u72C0\u614B\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
user.source.not_blank=\u7528\u6236\u4F86\u6E90\u4E0D\u80FD\u70BA\u7A7A
user.source.length_range=\u7528\u6236\u4F86\u6E90\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
user.create_user.not_blank=\u7528\u6236\u5275\u5EFA\u4EBA\u4E0D\u80FD\u70BA\u7A7A
user.create_user.length_range=\u7528\u6236\u5275\u5EFA\u4EBA\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
user_extend.id.not_blank=\u7528\u6236ID\u4E0D\u80FD\u70BA\u7A7A
user_key.id.not_blank=\u7528\u6236ApiKey ID\u4E0D\u80FD\u70BA\u7A7A
user_key.create_user.not_blank=\u7528\u6236ApiKey\u5275\u5EFA\u4EBA\u4E0D\u80FD\u70BA\u7A7A
user_key.create_user.length_range=\u7528\u6236ApiKey\u5275\u5EFA\u4EBA\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
user_key.access_key.not_blank=\u7528\u6236ApiKey access key\u4E0D\u80FD\u70BA\u7A7A
user_key.access_key.length_range=\u7528\u6236ApiKey access key\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
user_key.secret_key.not_blank=\u7528\u6236ApiKey secret key\u4E0D\u80FD\u70BA\u7A7A
user_key.secret_key.length_range=\u7528\u6236ApiKey secret key\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
user.info.not_empty=\u7528\u6236\u4FE1\u606F\u4E0D\u80FD\u70BA\u7A7A
user.organizationId.not_blank=\u7528\u6236\u7D44\u7E54\u4E0D\u80FD\u70BA\u7A7A
user.projectId.not_blank=\u7528\u6236\u9805\u76EE\u4E0D\u80FD\u70BA\u7A7A
user_role.id.not_blank=\u7528\u6236\u7D44ID\u4E0D\u80FD\u70BA\u7A7A
user_role.name.not_blank=\u7528\u6236\u7D44\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A
user_role.name.length_range=\u7528\u6236\u7D44\u540D\u7A31\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
user_role.system.not_blank=\u662F\u5426\u662F\u7CFB\u7D71\u7528\u6236\u7D44\u4E0D\u80FD\u70BA\u7A7A
user_role.system.length_range=\u662F\u5426\u662F\u7CFB\u7D71\u7528\u6236\u7D44\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
user_role.type.not_blank=\u7528\u6236\u7D44\u985E\u578B\u4E0D\u80FD\u70BA\u7A7A
user_role.type.length_range=\u7528\u6236\u7D44\u985E\u578B\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
user_role.create_user.not_blank=\u7528\u6236\u7D44\u5275\u5EFA\u4EBA\u4E0D\u80FD\u70BA\u7A7A
user_role.create_user.length_range=\u7528\u6236\u7D44\u5275\u5EFA\u4EBA\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
user_role.scope_id.not_blank=\u7528\u6236\u7D44\u61C9\u7528\u7BC4\u570D\u4E0D\u80FD\u70BA\u7A7A
user_role.scope_id.length_range=\u7528\u6236\u7D44\u61C9\u7528\u7BC4\u570D\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
user_role_permission.id.not_blank=\u7528\u6236\u7D44\u6B0A\u9650ID\u4E0D\u80FD\u70BA\u7A7A
user_role_permission.role_id.not_blank=\u7528\u6236\u7D44\u6B0A\u9650\u7528\u6236\u7D44ID\u4E0D\u80FD\u70BA\u7A7A
user_role_permission.role_id.length_range=\u7528\u6236\u7D44\u6B0A\u9650\u7528\u6236\u7D44ID\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
user_role_permission.permission_id.not_blank=\u7528\u6236\u7D44\u6B0A\u9650\u6B0A\u9650ID\u4E0D\u80FD\u70BA\u7A7A
user_role_permission.permission_id.length_range=\u7528\u6236\u7D44\u6B0A\u9650\u6B0A\u9650ID\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
user_role_permission.module_id.not_blank=\u7528\u6236\u7D44\u6B0A\u9650\u6A21\u584AID\u4E0D\u80FD\u70BA\u7A7A
user_role_permission.module_id.length_range=\u7528\u6236\u7D44\u6B0A\u9650\u6A21\u584AID\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
user_role_relation.id.not_blank=\u7528\u6236\u7D44\u95DC\u4FC2ID\u4E0D\u80FD\u70BA\u7A7A
user_role_relation.user_id.not_blank=\u7528\u6236\u7D44\u95DC\u4FC2\u7528\u6236ID\u4E0D\u80FD\u70BA\u7A7A
user_role_relation.user_id.length_range=\u7528\u6236\u7D44\u95DC\u4FC2\u7528\u6236ID\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
user_role_relation.role_id.not_blank=\u7528\u6236\u7D44\u95DC\u4FC2\u7528\u6236\u7D44ID\u4E0D\u80FD\u70BA\u7A7A
user_role_relation.role_id.length_range=\u7528\u6236\u7D44\u95DC\u4FC2\u7528\u6236\u7D44ID\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
user_role_relation.source_id.not_blank=\u7528\u6236\u7D44\u95DC\u4FC2\u4F86\u6E90ID\u4E0D\u80FD\u70BA\u7A7A
user_role_relation.source_id.length_range=\u7528\u6236\u7D44\u95DC\u4FC2\u4F86\u6E90ID\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
organization.id.not_blank=\u5DE5\u4F5C\u7A7A\u9593ID\u4E0D\u80FD\u70BA\u7A7A
organization.name.not_blank=\u5DE5\u4F5C\u7A7A\u9593\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A
organization.name.length_range=\u5DE5\u4F5C\u7A7A\u9593\u540D\u7A31\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
organization.create_user.not_blank=\u5DE5\u4F5C\u7A7A\u9593\u5275\u5EFA\u4EBA\u4E0D\u80FD\u70BA\u7A7A
organization.create_user.length_range=\u5DE5\u4F5C\u7A7A\u9593\u5275\u5EFA\u4EBA\u9577\u5EA6\u5FC5\u9808\u5728{min}\u548C{max}\u4E4B\u9593
role.not.global.system=角色不是為全局系統角色
role.not.contains.member=角色不包含系統成員角色
user.not.login=未獲取到登錄用戶
auth_source.id.not_blank=認證源ID不能為空
auth_source.status.length_range=認證源狀態長度必須在{min}和{max}之間
auth_source.status.not_blank=認證源狀態不能為空
license.id.not_blank=License ID不能為空
message_task.id.not_blank=消息通知任務ID不能為空
message_task.type.not_blank=消息通知任務類型不能為空
message_task.type.length_range=消息通知任務類型長度必須在{min}和{max}之間
message_task.event.not_blank=消息通知任務事件不能為空
message_task.event.length_range=消息通知任務事件長度必須在{min}和{max}之間
message_task.receiver.not_blank=消息通知任務接收者不能為空
message_task.receiver.length_range=消息通知任務接收者長度必須在{min}和{max}之間
message_task.task_type.not_blank=消息通知任務任務類型不能為空
message_task.task_type.length_range=消息通知任務任務類型長度必須在{min}和{max}之間
message_task.test_id.not_blank=消息通知任務測試ID不能為空
message_task.test_id.length_range=消息通知任務測試ID長度必須在{min}和{max}之間
message_task.project_id.not_blank=消息通知任務項目ID不能為空
message_task.project_id.length_range=消息通知任務項目ID長度必須在{min}和{max}之間
message_task_blob.id.not_blank=消息通知任務ID不能為空
notification.id.not_blank=消息通知ID不能為空
notification.type.not_blank=消息通知類型不能為空
notification.type.length_range=消息通知類型長度必須在{min}和{max}之間
notification.receiver.not_blank=消息通知接收者不能為空
notification.receiver.length_range=消息通知接收者長度必須在{min}和{max}之間
notification.title.not_blank=消息通知標題不能為空
notification.title.length_range=消息通知標題長度必須在{min}和{max}之間
notification.status.not_blank=消息通知狀態不能為空
notification.status.length_range=消息通知狀態長度必須在{min}和{max}之間
notification.operator.not_blank=消息通知操作者不能為空
notification.operator.length_range=消息通知操作者長度必須在{min}和{max}之間
notification.operation.not_blank=消息通知操作不能為空
notification.operation.length_range=消息通知操作長度必須在{min}和{max}之間
notification.resource_id.not_blank=消息通知資源ID不能為空
notification.resource_id.length_range=消息通知資源ID長度必須在{min}和{max}之間
notification.resource_type.not_blank=消息通知資源類型不能為空
notification.resource_type.length_range=消息通知資源類型長度必須在{min}和{max}之間
notification.resource_name.not_blank=消息通知資源名稱不能為空
notification.resource_name.length_range=消息通知資源名稱長度必須在{min}和{max}之間
novice_statistics.id.not_blank=新手村ID不能為空
novice_statistics.guide_step.not_blank=新手村步驟不能為空
novice_statistics.guide_step.length_range=新手村步驟長度必須在{min}和{max}之間
operating_log.id.not_blank=操作日誌ID不能為空
operating_log.project_id.not_blank=操作日誌項目ID不能為空
operating_log.project_id.length_range=操作日誌項目ID長度必須在{min}和{max}之間
operating_log_resource.id.not_blank=操作日誌資源ID不能為空
operating_log_resource.operating_log_id.not_blank=操作日誌資源操作日誌ID不能為空
operating_log_resource.operating_log_id.length_range=操作日誌資源操作日誌ID長度必須在{min}和{max}之間
operating_log_resource.source_id.not_blank=操作日誌資源來源ID不能為空
operating_log_resource.source_id.length_range=操作日誌資源來源ID長度必須在{min}和{max}之間
plugin.id.not_blank=插件主鍵不能為空
plugin.plugin_id.not_blank=插件ID不能為空
plugin.plugin_id.length_range=插件ID長度必須在{min}和{max}之間
plugin.script_id.not_blank=插件腳本ID不能為空
plugin.script_id.length_range=插件腳本ID長度必須在{min}和{max}之間
plugin.clazz_name.not_blank=插件類名不能為空
plugin.clazz_name.length_range=插件類名長度必須在{min}和{max}之間
plugin.jmeter_clazz.not_blank=插件jmeter類名不能為空
plugin.jmeter_clazz.length_range=插件jmeter類名長度必須在{min}和{max}之間
plugin.source_path.not_blank=插件源路徑不能為空
plugin.source_path.length_range=插件源路徑長度必須在{min}和{max}之間
plugin.source_name.not_blank=插件源名稱不能為空
plugin.source_name.length_range=插件源名稱長度必須在{min}和{max}之間
plugin.scenario.not_blank=插件場景不能為空
plugin.scenario.length_range=插件場景長度必須在{min}和{max}之間
plugin_blob.id.not_blank=插件ID不能為空
quota.id.not_blank=配額ID不能為空
schedule.id.not_blank=定時任務ID不能為空
schedule.type.not_blank=定時任務類型不能為空
schedule.type.length_range=定時任務類型長度必須在{min}和{max}之間
schedule.value.not_blank=定時任務值不能為空
schedule.value.length_range=定時任務值長度必須在{min}和{max}之間
schedule.job.not_blank=定時任務不能為空
schedule.job.length_range=定時任務長度必須在{min}和{max}之間
schedule.create_user.not_blank=定時任務創建人不能為空
schedule.create_user.length_range=定時任務創建人長度必須在{min}和{max}之間
service_integration.id.not_blank=服務集成ID不能為空
service_integration.platform.not_blank=服務集成平台不能為空
service_integration.platform.length_range=服務集成平台長度必須在{min}和{max}之間
system_parameter.param_key.not_blank=系統參數Key不能為空
system_parameter.type.not_blank=系統參數類型不能為空
system_parameter.type.length_range=系統參數類型長度必須在{min}和{max}之間
test_resource.id.not_blank=資源池節點ID不能為空
test_resource.test_resource_pool_id.not_blank=資源池ID不能為空
test_resource.test_resource_pool_id.length_range=資源池ID長度必須在{min}和{max}之間
test_resource.status.not_blank=資源池節點狀態不能為空
test_resource.status.length_range=資源池節點狀態長度必須在{min}和{max}之間
test_resource_pool.id.not_blank=資源池ID不能為空
test_resource_pool.name.not_blank=資源池名稱不能為空
test_resource_pool.name.length_range=資源池名稱長度必須在{min}和{max}之間
test_resource_pool.type.not_blank=資源池類型不能為空
test_resource_pool.type.length_range=資源池類型長度必須在{min}和{max}之間
test_resource_pool.status.not_blank=資源池狀態不能為空
test_resource_pool.status.length_range=資源池狀態長度必須在{min}和{max}之間
user.id.not_blank=用戶ID不能為空
user.name.not_blank=用戶名稱不能為空
user.name.length_range=用戶名稱長度必須在{min}和{max}之間
user.email.not_blank=用戶email不能為空
user.email.length_range=用戶email長度必須在{min}和{max}之間
user.email.repeat=用戶email已存在
user.email.invalid=用戶email格式不正確
user.status.not_blank=用戶狀態不能為空
user.status.length_range=用戶狀態長度必須在{min}和{max}之間
user.source.not_blank=用戶來源不能為空
user.source.length_range=用戶來源長度必須在{min}和{max}之間
user.create_user.not_blank=用戶創建人不能為空
user.create_user.length_range=用戶創建人長度必須在{min}和{max}之間
user_extend.id.not_blank=用戶ID不能為空
user_key.id.not_blank=用戶ApiKey ID不能為空
user_key.create_user.not_blank=用戶ApiKey創建人不能為空
user_key.create_user.length_range=用戶ApiKey創建人長度必須在{min}和{max}之間
user_key.access_key.not_blank=用戶ApiKey access key不能為空
user_key.access_key.length_range=用戶ApiKey access key長度必須在{min}和{max}之間
user_key.secret_key.not_blank=用戶ApiKey secret key不能為空
user_key.secret_key.length_range=用戶ApiKey secret key長度必須在{min}和{max}之間
user.info.not_empty=用戶信息不能為空
user.organizationId.not_blank=用戶組織不能為空
user.projectId.not_blank=用戶項目不能為空
user_role.id.not_blank=用戶組ID不能為空
user_role.name.not_blank=用戶組名稱不能為空
user_role.name.length_range=用戶組名稱長度必須在{min}和{max}之間
user_role.system.not_blank=是否是系統用戶組不能為空
user_role.system.length_range=是否是系統用戶組長度必須在{min}和{max}之間
user_role.type.not_blank=用戶組類型不能為空
user_role.type.length_range=用戶組類型長度必須在{min}和{max}之間
user_role.create_user.not_blank=用戶組創建人不能為空
user_role.create_user.length_range=用戶組創建人長度必須在{min}和{max}之間
user_role.scope_id.not_blank=用戶組應用範圍不能為空
user_role.scope_id.length_range=用戶組應用範圍長度必須在{min}和{max}之間
user_role_permission.id.not_blank=用戶組權限ID不能為空
user_role_permission.role_id.not_blank=用戶組權限用戶組ID不能為空
user_role_permission.role_id.length_range=用戶組權限用戶組ID長度必須在{min}和{max}之間
user_role_permission.permission_id.not_blank=用戶組權限權限ID不能為空
user_role_permission.permission_id.length_range=用戶組權限權限ID長度必須在{min}和{max}之間
user_role_permission.module_id.not_blank=用戶組權限模塊ID不能為空
user_role_permission.module_id.length_range=用戶組權限模塊ID長度必須在{min}和{max}之間
user_role_relation.id.not_blank=用戶組關係ID不能為空
user_role_relation.user_id.not_blank=用戶組關係用戶ID不能為空
user_role_relation.user_id.length_range=用戶組關係用戶ID長度必須在{min}和{max}之間
user_role_relation.role_id.not_blank=用戶組關係用戶組ID不能為空
user_role_relation.role_id.length_range=用戶組關係用戶組ID長度必須在{min}和{max}之間
user_role_relation.source_id.not_blank=用戶組關係來源ID不能為空
user_role_relation.source_id.length_range=用戶組關係來源ID長度必須在{min}和{max}之間
organization.id.not_blank=工作空間ID不能為空
organization.name.not_blank=工作空間名稱不能為空
organization.name.length_range=工作空間名稱長度必須在{min}和{max}之間
organization.create_user.not_blank=工作空間創建人不能為空
organization.create_user.length_range=工作空間創建人長度必須在{min}和{max}之間

View File

@ -6,11 +6,17 @@ import com.github.pagehelper.PageHelper;
import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.sdk.dto.BasePageRequest;
import io.metersphere.sdk.dto.UserDTO;
import io.metersphere.sdk.log.annotation.RequestLog;
import io.metersphere.sdk.log.constants.OperationLogModule;
import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.util.PageUtils;
import io.metersphere.sdk.util.Pager;
import io.metersphere.sdk.util.SessionUtils;
import io.metersphere.system.dto.UserBatchCreateDTO;
import io.metersphere.system.dto.response.UserInfo;
import io.metersphere.system.dto.UserEditRequest;
import io.metersphere.system.dto.UserInfo;
import io.metersphere.system.dto.UserRoleOption;
import io.metersphere.system.service.GlobalUserRoleService;
import io.metersphere.system.service.UserService;
import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated;
@ -23,33 +29,43 @@ import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/user")
@RequestMapping("/system/user")
public class UserController {
@Resource
private UserService userService;
@Resource
private GlobalUserRoleService globalUserRoleService;
@GetMapping("/get/{email}")
@RequiresPermissions(PermissionConstants.SYSTEM_USER_READ)
public UserDTO getUser(@PathVariable String email) {
return userService.getByEmail(email);
return userService.getUserDTOByEmail(email);
}
@GetMapping("/get/global/system/role")
@RequiresPermissions(PermissionConstants.SYSTEM_USER_READ_ADD)
public List<UserRoleOption> getGlobalSystemRole() {
return globalUserRoleService.getGlobalSystemRoleList();
}
@PostMapping("/add")
@RequiresPermissions(PermissionConstants.SYSTEM_USER_READ_ADD)
public UserBatchCreateDTO addUser(@Validated({Created.class}) @RequestBody UserBatchCreateDTO userCreateDTO) {
userCreateDTO.setCreateUserToList(SessionUtils.getSessionId());
return userService.add(userCreateDTO);
return userService.addBatch(userCreateDTO);
}
@PostMapping("/update")
@RequiresPermissions(PermissionConstants.SYSTEM_USER_READ_UPDATE)
public UserBatchCreateDTO updateUser(@Validated({Updated.class}) @RequestBody UserBatchCreateDTO userCreateDTO) {
userCreateDTO.setCreateUserToList(SessionUtils.getSessionId());
return userService.add(userCreateDTO);
@RequestLog(type = OperationLogType.UPDATE, module = OperationLogModule.SYSTEM_USER,
sourceId = "#request.id", projectId = "#request.projectId", details = "#request.name")
public UserEditRequest updateUser(@Validated({Updated.class}) @RequestBody UserEditRequest userEditRequest) {
userEditRequest.setUpdateUser(SessionUtils.getSessionId());
return userService.updateUser(userEditRequest);
}
@PostMapping("/page")
@RequiresPermissions(PermissionConstants.SYSTEM_USER_READ_ADD)
@RequiresPermissions(PermissionConstants.SYSTEM_USER_READ)
public Pager<List<UserInfo>> list(@Validated @RequestBody BasePageRequest request) {
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "create_time desc");

View File

@ -1,6 +1,5 @@
package io.metersphere.system.dto;
import io.metersphere.system.domain.User;
import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated;
import io.swagger.v3.oas.annotations.media.Schema;
@ -16,11 +15,7 @@ public class UserBatchCreateDTO {
@Schema(title = "用户信息集合", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(groups = {Created.class, Updated.class}, message = "{user.info.not_empty}")
List<@Valid User> userInfoList;
@Schema(title = "组织Id", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(groups = {Created.class, Updated.class}, message = "{user.organizationId.not_blank}")
List<@Valid @NotBlank(message = "{user.organizationId.not_blank}", groups = {Created.class, Updated.class}) String> organizationIdList;
List<@Valid UserInfo> userInfoList;
@Schema(title = "用户组", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(groups = {Created.class, Updated.class}, message = "{user_role.id.not_blank}")

View File

@ -0,0 +1,18 @@
package io.metersphere.system.dto;
import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import java.util.List;
@Data
public class UserEditRequest extends UserInfo {
@Schema(title = "用户组", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(groups = {Created.class, Updated.class}, message = "{user_role.id.not_blank}")
List<@Valid @NotBlank(message = "{user_role.id.not_blank}", groups = {Created.class, Updated.class}) String> userRoleIdList;
}

View File

@ -0,0 +1,59 @@
package io.metersphere.system.dto;
import io.metersphere.system.domain.Organization;
import io.metersphere.system.domain.UserRole;
import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
public class UserInfo {
@Schema(title = "用户ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{user.id.not_blank}", groups = {Updated.class})
@Size(min = 1, max = 50, message = "{user.id.length_range}", groups = {Updated.class})
private String id;
@Schema(title = "用户名", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{user.name.not_blank}", groups = {Created.class})
@Size(min = 1, max = 255, message = "{user.name.length_range}", groups = {Created.class, Updated.class})
private String name;
@Schema(title = "用户邮箱", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{user.email.not_blank}", groups = {Created.class})
@Size(min = 1, max = 64, message = "{user.email.length_range}", groups = {Created.class, Updated.class})
@Email(message = "{user.email.invalid}", groups = {Created.class, Updated.class})
private String email;
@Schema(title = "创建时间")
private Long createTime;
@Schema(title = "更新时间")
private Long updateTime;
@Schema(title = "手机号")
private String phone;
@Schema(title = "来源LOCAL OIDC CAS OAUTH2", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{user.source.not_blank}", groups = {Created.class})
@Size(min = 1, max = 50, message = "{user.source.length_range}", groups = {Created.class, Updated.class})
private String source;
@Schema(title = "创建人")
private String createUser;
@Schema(title = "修改人")
private String updateUser;
@Schema(title = "用户所属组织")
private List<Organization> organizationList = new ArrayList<>();
@Schema(title = "用户所属用户组")
private List<UserRole> userRoleList = new ArrayList<>();
}

View File

@ -0,0 +1,11 @@
package io.metersphere.system.dto;
import lombok.Data;
@Data
public class UserRoleOption {
private String id;
private String name;
private boolean selected = false;
private boolean closeable = true;
}

View File

@ -1,17 +0,0 @@
package io.metersphere.system.dto.response;
import io.metersphere.system.domain.Organization;
import io.metersphere.system.domain.User;
import io.metersphere.system.domain.UserRole;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Data
public class UserInfo extends User {
@Schema(title = "用户所属组织")
List<Organization> organizationList;
@Schema(title = "用户所属用户组")
List<UserRole> userRoleList;
}

View File

@ -0,0 +1,9 @@
package io.metersphere.system.mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface ExtUserRoleMapper {
public List<String> selectGlobalRoleList(@Param("roleIdList") List<String> roleIdList, @Param("isSystem") boolean isSystem);
}

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="io.metersphere.system.mapper.ExtUserRoleMapper">
<select id="selectGlobalRoleList" resultType="java.lang.String">
SELECT id FROM user_role WHERE id IN
<foreach collection="roleIdList" item="item" index="index" open="(" separator="," close=")">
#{item}
</foreach>
<if test="isSystem ">
AND type = 'SYSTEM'
</if>
</select>
</mapper>

View File

@ -0,0 +1,12 @@
package io.metersphere.system.mapper;
import io.metersphere.system.domain.UserRoleRelation;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface ExtUserRoleRelationMapper {
List<UserRoleRelation> listByUserIdAndScope(@Param("userIds") List<String> userIdList);
List<UserRoleRelation> selectGlobalRoleByUserId(String userId);
}

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="io.metersphere.system.mapper.ExtUserRoleRelationMapper">
<select id="listByUserIdAndScope" resultType="io.metersphere.system.domain.UserRoleRelation">
SELECT * FROM
user_role_relation
WHERE
<foreach collection="userIds" item="userId" open="(" close=")" separator="OR">
user_id = #{userId}
</foreach>
</select>
<select id="selectGlobalRoleByUserId" resultType="io.metersphere.system.domain.UserRoleRelation">
SELECT * FROM
user_role_relation
WHERE
user_id = #{userId}
AND role_id IN (
SELECT id FROM user_role WHERE type = 'SYSTEM' AND scope_id = 'global'
)
</select>
</mapper>

View File

@ -1,15 +1,23 @@
package io.metersphere.system.service;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.system.domain.UserRole;
import io.metersphere.system.domain.UserRoleExample;
import io.metersphere.system.dto.UserRoleOption;
import io.metersphere.system.mapper.ExtUserRoleMapper;
import io.metersphere.system.mapper.UserRoleMapper;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* 系统设置的接口增删改查都是针对全局用户组
*
* @author jianxing
* @date : 2023-6-8
*/
@ -20,6 +28,8 @@ public class GlobalUserRoleService {
@Resource
private UserRoleMapper userRoleMapper;
@Resource
private ExtUserRoleMapper extUserRoleMapper;
public List<UserRole> list() {
UserRoleExample example = new UserRoleExample();
@ -49,4 +59,29 @@ public class GlobalUserRoleService {
userRoleMapper.deleteByPrimaryKey(id);
return id;
}
public void checkRoleIsGlobalAndHaveMember(@Valid @NotEmpty List<String> roleIdList, boolean isSystem) {
List<String> globalRoleList = extUserRoleMapper.selectGlobalRoleList(roleIdList, isSystem);
if (globalRoleList.size() != roleIdList.size()) {
throw new MSException("role.not.global");
}
if (!globalRoleList.contains("member")) {
throw new MSException("role.not.contains.member");
}
}
public List<UserRoleOption> getGlobalSystemRoleList() {
UserRoleExample example = new UserRoleExample();
example.createCriteria().andScopeIdEqualTo("global").andTypeEqualTo("SYSTEM");
List<UserRoleOption> returnList = new ArrayList<>();
userRoleMapper.selectByExample(example).forEach(userRole -> {
UserRoleOption userRoleOption = new UserRoleOption();
userRoleOption.setId(userRole.getId());
userRoleOption.setName(userRole.getName());
userRoleOption.setSelected(StringUtils.equals(userRole.getId(), "member"));
userRoleOption.setCloseable(!StringUtils.equals(userRole.getId(), "member"));
returnList.add(userRoleOption);
});
return returnList;
}
}

View File

@ -1,7 +1,14 @@
package io.metersphere.system.service;
import io.metersphere.system.domain.User;
import io.metersphere.system.domain.UserRoleRelation;
import io.metersphere.sdk.constants.UserRoleEnum;
import io.metersphere.sdk.log.constants.OperationLogModule;
import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.log.service.OperationLogService;
import io.metersphere.system.domain.*;
import io.metersphere.system.dto.UserInfo;
import io.metersphere.system.mapper.ExtUserRoleRelationMapper;
import io.metersphere.system.mapper.OrganizationMapper;
import io.metersphere.system.mapper.UserRoleMapper;
import io.metersphere.system.mapper.UserRoleRelationMapper;
import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated;
@ -9,6 +16,8 @@ import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
@ -17,55 +26,183 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.*;
import java.util.stream.Collectors;
@Service
@Transactional(rollbackFor = Exception.class)
public class UserRoleRelationService {
@Resource
private SqlSessionFactory sqlSessionFactory;
@Resource
private UserRoleRelationMapper userRoleRelationMapper;
@Resource
private ExtUserRoleRelationMapper extUserRoleRelationMapper;
@Resource
private UserRoleMapper userRoleMapper;
@Resource
private OrganizationMapper organizationMapper;
@Resource
private OperationLogService operationLogService;
//批量添加用户记录日志
public List<OperationLog> getBatchLogs(@Valid @NotEmpty List<String> userRoleId,
@Valid User user,
@Valid @NotEmpty String operationMethod,
@Valid @NotEmpty String operator,
@Valid @NotEmpty String operationType) {
long operationTime = System.currentTimeMillis();
List<OperationLog> logs = new ArrayList<>();
UserRoleExample example = new UserRoleExample();
example.createCriteria().andIdIn(userRoleId);
List<UserRole> userRoleList = userRoleMapper.selectByExample(example);
userRoleList.forEach(userRole -> {
OperationLog log = new OperationLog();
log.setId(UUID.randomUUID().toString());
log.setProjectId("system");
log.setType(operationType);
log.setCreateUser(operator);
log.setModule(OperationLogModule.SYSTEM_USER);
log.setMethod(operationMethod);
log.setCreateTime(operationTime);
log.setSourceId(user.getId());
log.setDetails(user.getName() + StringUtils.SPACE
+ operationType + StringUtils.SPACE
+ "UserRole" + StringUtils.SPACE
+ userRole.getName());
logs.add(log);
});
return logs;
}
public void batchSave(@Validated({Created.class, Updated.class})
@NotEmpty(groups = {Created.class, Updated.class}, message = "{user.organizationId.not_blank}")
List<@Valid @NotBlank(message = "{user.organizationId.not_blank}", groups = {Created.class, Updated.class}) String> organizationIdList,
@NotEmpty(groups = {Created.class, Updated.class}, message = "{user_role.id.not_blank}")
List<@Valid @NotBlank(message = "{user_role.id.not_blank}", groups = {Created.class, Updated.class}) String> userRoleIdList,
@NotEmpty(groups = {Created.class, Updated.class}, message = "{user.info.not_empty}")
List<@Valid User> userInfoList) {
List<@Valid User> userList) {
long operationTime = System.currentTimeMillis();
List<UserRoleRelation> userRoleRelationSaveList = new ArrayList<>();
//添加用户组织关系
for (String orgId : organizationIdList) {
for (String userRoleId : userRoleIdList) {
for (User user : userInfoList) {
UserRoleRelation userRoleRelation = new UserRoleRelation();
userRoleRelation.setId(UUID.randomUUID().toString());
userRoleRelation.setUserId(user.getId());
userRoleRelation.setRoleId(userRoleId);
userRoleRelation.setSourceId(orgId);
userRoleRelation.setCreateTime(operationTime);
userRoleRelation.setCreateUser(user.getCreateUser());
userRoleRelationSaveList.add(userRoleRelation);
}
for (String userRoleId : userRoleIdList) {
for (User user : userList) {
UserRoleRelation userRoleRelation = new UserRoleRelation();
userRoleRelation.setId(UUID.randomUUID().toString());
userRoleRelation.setUserId(user.getId());
userRoleRelation.setRoleId(userRoleId);
userRoleRelation.setSourceId("system");
userRoleRelation.setCreateTime(operationTime);
userRoleRelation.setCreateUser(user.getCreateUser());
userRoleRelationSaveList.add(userRoleRelation);
}
}
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
UserRoleRelationMapper batchSaveMapper = sqlSession.getMapper(UserRoleRelationMapper.class);
try {
int insertIndex = 0;
for (UserRoleRelation userRoleRelation : userRoleRelationSaveList) {
batchSaveMapper.insert(userRoleRelation);
insertIndex++;
if (insertIndex % 50 == 0) {
sqlSession.flushStatements();
}
int insertIndex = 0;
for (UserRoleRelation userRoleRelation : userRoleRelationSaveList) {
batchSaveMapper.insert(userRoleRelation);
insertIndex++;
if (insertIndex % 50 == 0) {
sqlSession.flushStatements();
}
sqlSession.flushStatements();
} finally {
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
}
sqlSession.flushStatements();
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
//记录添加日志
for (User user : userList) {
operationLogService.batchAdd(this.getBatchLogs(userRoleIdList, user, "addUser", user.getCreateUser(), OperationLogType.ADD.name()));
}
}
public Map<String, UserInfo> selectGlobalUserRoleAndOrganization(@Valid @NotEmpty List<String> userIdList) {
List<UserRoleRelation> userRoleRelationList = extUserRoleRelationMapper.listByUserIdAndScope(userIdList);
List<String> userRoleIdList = userRoleRelationList.stream().map(UserRoleRelation::getRoleId).collect(Collectors.toList());
List<String> sourceIdList = userRoleRelationList.stream().map(UserRoleRelation::getSourceId).collect(Collectors.toList());
Map<String, UserRole> userRoleMap = new HashMap<>();
Map<String, Organization> organizationMap = new HashMap<>();
if (CollectionUtils.isNotEmpty(userRoleIdList)) {
UserRoleExample userRoleExample = new UserRoleExample();
userRoleExample.createCriteria().andIdIn(userRoleIdList).andScopeIdEqualTo(UserRoleEnum.GLOBAL.toString());
userRoleMap = userRoleMapper.selectByExample(userRoleExample).stream()
.collect(Collectors.toMap(UserRole::getId, item -> item));
}
if (CollectionUtils.isNotEmpty(sourceIdList)) {
OrganizationExample organizationExample = new OrganizationExample();
organizationExample.createCriteria().andIdIn(sourceIdList);
organizationMap = organizationMapper.selectByExample(organizationExample).stream()
.collect(Collectors.toMap(Organization::getId, item -> item));
}
Map<String, UserInfo> returnMap = new HashMap<>();
for (UserRoleRelation userRoleRelation : userRoleRelationList) {
UserInfo userInfo = returnMap.get(userRoleRelation.getUserId());
if (userInfo == null) {
userInfo = new UserInfo();
userInfo.setId(userRoleRelation.getUserId());
returnMap.put(userRoleRelation.getUserId(), userInfo);
}
UserRole userRole = userRoleMap.get(userRoleRelation.getRoleId());
Organization organization = organizationMap.get(userRoleRelation.getSourceId());
userInfo.getUserRoleList().add(userRole);
userInfo.getOrganizationList().add(organization);
}
return returnMap;
}
public List<UserRoleRelation> selectGlobalRoleByUserId(String userId) {
return extUserRoleRelationMapper.selectGlobalRoleByUserId(userId);
}
public void updateUserSystemGlobalRole(@Valid User user, @Valid @NotEmpty List<String> roleList) {
//更新用户权限
List<String> deleteRoleList = new ArrayList<>();
List<UserRoleRelation> saveList = new ArrayList<>();
List<UserRoleRelation> userRoleRelationList = this.selectGlobalRoleByUserId(user.getId());
List<String> userSavedRoleIdList = userRoleRelationList.stream().map(UserRoleRelation::getRoleId).collect(Collectors.toList());
//获取要移除的权限
for (String userSavedRoleId : userSavedRoleIdList) {
if (!roleList.contains(userSavedRoleId)) {
deleteRoleList.add(userSavedRoleId);
}
}
//获取要添加的权限
for (String roleId : roleList) {
if (!userSavedRoleIdList.contains(roleId)) {
UserRoleRelation userRoleRelation = new UserRoleRelation();
userRoleRelation.setId(UUID.randomUUID().toString());
userRoleRelation.setUserId(user.getId());
userRoleRelation.setRoleId(roleId);
userRoleRelation.setSourceId("system");
userRoleRelation.setCreateTime(System.currentTimeMillis());
userRoleRelation.setCreateUser(user.getCreateUser());
saveList.add(userRoleRelation);
}
}
if (CollectionUtils.isNotEmpty(deleteRoleList)) {
List<String> deleteIdList = new ArrayList<>();
userRoleRelationList.forEach(item -> {
if (deleteRoleList.contains(item.getRoleId())) {
deleteIdList.add(item.getId());
}
});
UserRoleRelationExample deleteExample = new UserRoleRelationExample();
deleteExample.createCriteria().andIdIn(deleteIdList);
userRoleRelationMapper.deleteByExample(deleteExample);
//记录删除日志
operationLogService.batchAdd(this.getBatchLogs(deleteRoleList, user, "updateUser", user.getCreateUser(), OperationLogType.DELETE.name()));
}
if (CollectionUtils.isNotEmpty(saveList)) {
//系统级权限不会太多所以暂时不分批处理
saveList.forEach(item -> userRoleRelationMapper.insert(item));
//记录添加日志
operationLogService.batchAdd(this.getBatchLogs(saveList.stream().map(UserRoleRelation::getRoleId).toList(),
user, "updateUser", user.getCreateUser(), OperationLogType.ADD.name()));
}
}
public List<UserRoleRelation> selectByUserId(String id) {
UserRoleRelationExample example = new UserRoleRelationExample();
example.createCriteria().andUserIdEqualTo(id);
return userRoleRelationMapper.selectByExample(example);
}
}

View File

@ -0,0 +1,32 @@
package io.metersphere.system.service;
import io.metersphere.system.domain.UserRole;
import io.metersphere.system.domain.UserRoleExample;
import io.metersphere.system.domain.UserRoleRelation;
import io.metersphere.system.mapper.UserRoleMapper;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Service
@Transactional(rollbackFor = Exception.class)
public class UserRoleService {
@Resource
private UserRoleMapper userRoleMapper;
public List<UserRole> selectByUserRoleRelations(List<UserRoleRelation> userRoleRelations) {
if (CollectionUtils.isNotEmpty(userRoleRelations)) {
List<String> userRoleIds = userRoleRelations.stream().map(UserRoleRelation::getRoleId).collect(Collectors.toList());
UserRoleExample example = new UserRoleExample();
example.createCriteria().andIdIn(userRoleIds);
return userRoleMapper.selectByExample(example);
} else {
return new ArrayList<>();
}
}
}

View File

@ -3,21 +3,28 @@ package io.metersphere.system.service;
import io.metersphere.sdk.dto.BasePageRequest;
import io.metersphere.sdk.dto.UserDTO;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.log.constants.OperationLogModule;
import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.log.service.OperationLogService;
import io.metersphere.sdk.mapper.BaseUserMapper;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.CodingUtil;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.domain.OperationLog;
import io.metersphere.system.domain.User;
import io.metersphere.system.dto.UserBatchCreateDTO;
import io.metersphere.system.dto.response.UserInfo;
import io.metersphere.system.dto.UserEditRequest;
import io.metersphere.system.dto.UserInfo;
import io.metersphere.system.mapper.UserMapper;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
@ -30,15 +37,40 @@ public class UserService {
private UserMapper userMapper;
@Resource
private UserRoleRelationService userRoleRelationService;
@Resource
private OperationLogService operationLogService;
@Resource
private GlobalUserRoleService globalUserRoleService;
@Resource
private UserRoleService userRoleService;
private void validateUserInfo(List<User> userList) {
//批量添加用户记录日志
public List<OperationLog> getBatchAddLogs(@Valid List<User> userList) {
List<OperationLog> logs = new ArrayList<>();
userList.forEach(user -> {
OperationLog log = new OperationLog();
log.setId(UUID.randomUUID().toString());
log.setCreateUser(user.getCreateUser());
log.setProjectId("system");
log.setType(OperationLogType.ADD.name());
log.setModule(OperationLogModule.SYSTEM_USER);
log.setMethod("addUser");
log.setCreateTime(user.getCreateTime());
log.setSourceId(user.getId());
log.setDetails(user.getName() + "(" + user.getEmail() + ")");
logs.add(log);
});
return logs;
}
private void validateUserInfo(List<UserInfo> userList) {
//判断参数内是否含有重复邮箱
List<String> emailList = new ArrayList<>();
List<String> repeatEmailList = new ArrayList<>();
var userInDbMap = baseUserMapper.selectUserIdByEmailList(
userList.stream().map(User::getEmail).collect(Collectors.toList()))
userList.stream().map(UserInfo::getEmail).collect(Collectors.toList()))
.stream().collect(Collectors.toMap(User::getEmail, User::getId));
for (User user : userList) {
for (UserInfo user : userList) {
if (emailList.contains(user.getEmail())) {
repeatEmailList.add(user.getEmail());
} else {
@ -55,42 +87,72 @@ public class UserService {
}
}
private void validateOrgAndProject(List<String> orgIdList, List<String> userRoleIdList) {
// todo 判断组织和用户组是否合法
}
public UserBatchCreateDTO add(UserBatchCreateDTO userCreateDTO) {
public UserBatchCreateDTO addBatch(UserBatchCreateDTO userCreateDTO) {
this.validateUserInfo(userCreateDTO.getUserInfoList());
this.validateOrgAndProject(userCreateDTO.getOrganizationIdList(), userCreateDTO.getUserRoleIdList());
globalUserRoleService.checkRoleIsGlobalAndHaveMember(userCreateDTO.getUserRoleIdList(), true);
long createTime = System.currentTimeMillis();
List<User> saveUserList = new ArrayList<>();
//添加用户
for (User user : userCreateDTO.getUserInfoList()) {
user.setId(UUID.randomUUID().toString());
for (UserInfo userInfo : userCreateDTO.getUserInfoList()) {
userInfo.setId(UUID.randomUUID().toString());
userInfo.setCreateTime(createTime);
userInfo.setUpdateTime(createTime);
User user = new User();
BeanUtils.copyBean(user, userInfo);
user.setPassword(CodingUtil.md5(user.getEmail()));
user.setCreateTime(createTime);
user.setUpdateTime(createTime);
userMapper.insertSelective(user);
saveUserList.add(user);
}
userRoleRelationService.batchSave(
userCreateDTO.getOrganizationIdList(), userCreateDTO.getUserRoleIdList(), userCreateDTO.getUserInfoList());
userRoleRelationService.batchSave(userCreateDTO.getUserRoleIdList(), saveUserList);
//写入操作日志
operationLogService.batchAdd(this.getBatchAddLogs(saveUserList));
return userCreateDTO;
}
public UserDTO getByEmail(String email) {
return baseUserMapper.selectByEmail(email);
public UserDTO getUserDTOByEmail(String email) {
UserDTO userDTO = baseUserMapper.selectByEmail(email);
if (userDTO != null) {
userDTO.setUserRoleRelations(
userRoleRelationService.selectByUserId(userDTO.getId())
);
userDTO.setUserRoles(
userRoleService.selectByUserRoleRelations(userDTO.getUserRoleRelations())
);
}
return userDTO;
}
public List<UserInfo> list(BasePageRequest request) {
List<UserInfo> returnList = new ArrayList<>();
List<User> userList = baseUserMapper.selectByKeyword(request.getKeyword());
List<String> userIdList = userList.stream().map(User::getId).collect(Collectors.toList());
Map<String, UserInfo> roleAndOrganizationMap = userRoleRelationService.selectGlobalUserRoleAndOrganization(userIdList);
for (User user : userList) {
UserInfo userInfo = new UserInfo();
BeanUtils.copyBean(userInfo, user);
UserInfo roleOrgModel = roleAndOrganizationMap.get(user.getId());
if (roleOrgModel != null) {
userInfo.setUserRoleList(roleOrgModel.getUserRoleList());
userInfo.setOrganizationList(roleOrgModel.getOrganizationList());
}
returnList.add(userInfo);
}
return returnList;
}
public UserEditRequest updateUser(UserEditRequest userEditRequest) {
//检查用户组合法性
globalUserRoleService.checkRoleIsGlobalAndHaveMember(userEditRequest.getUserRoleIdList(), true);
User user = new User();
BeanUtils.copyBean(user, userEditRequest);
user.setUpdateTime(System.currentTimeMillis());
userMapper.updateByPrimaryKeySelective(user);
userRoleRelationService.updateUserSystemGlobalRole(user, userEditRequest.getUserRoleIdList());
return userEditRequest;
}
}

View File

@ -8,7 +8,10 @@ import io.metersphere.system.dto.ResourcePoolTypeEnum;
import io.metersphere.system.dto.TestResourcePoolDTO;
import io.metersphere.system.request.QueryResourcePoolRequest;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
@ -17,12 +20,14 @@ import org.springframework.test.context.jdbc.SqlConfig;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
@ -59,16 +64,16 @@ class TestResourcePoolControllerTest extends BaseTest {
@Order(2)
void addUiTestResourcePoolFiled() throws Exception {
//资源池名称为空
TestResourcePoolDTO testResourcePoolDTO = generatorDto(true,false,false,false);
TestResourcePoolDTO testResourcePoolDTO = generatorDto(true, false, false, false);
this.requestPost(TEST_RESOURCE_POOL_ADD, testResourcePoolDTO, ERROR_REQUEST_MATCHER);
//资源池类型为空
testResourcePoolDTO = generatorDto(false,true,false,false);
testResourcePoolDTO = generatorDto(false, true, false, false);
this.requestPost(TEST_RESOURCE_POOL_ADD, testResourcePoolDTO, ERROR_REQUEST_MATCHER);
//资源池节点集合为空
testResourcePoolDTO = generatorDto(false,false,true,false);
testResourcePoolDTO = generatorDto(false, false, true, false);
this.requestPost(TEST_RESOURCE_POOL_ADD, testResourcePoolDTO, ERROR_REQUEST_MATCHER);
//UI的grid为空
testResourcePoolDTO = generatorDto(true,true,true,false);
testResourcePoolDTO = generatorDto(true, true, true, false);
this.requestPost(TEST_RESOURCE_POOL_ADD, testResourcePoolDTO, ERROR_REQUEST_MATCHER);
}
@ -119,16 +124,16 @@ class TestResourcePoolControllerTest extends BaseTest {
@Test
@Order(5)
void updateTestResourcePoolFiled() throws Exception {
TestResourcePoolDTO testResourcePoolDTO = generatorDto(true,false,false,false);
TestResourcePoolDTO testResourcePoolDTO = generatorDto(true, false, false, false);
this.requestPost(TEST_RESOURCE_POOL_UPDATE, testResourcePoolDTO, ERROR_REQUEST_MATCHER);
//资源池类型为空
testResourcePoolDTO = generatorDto(false,true,false,false);
testResourcePoolDTO = generatorDto(false, true, false, false);
this.requestPost(TEST_RESOURCE_POOL_UPDATE, testResourcePoolDTO, ERROR_REQUEST_MATCHER);
//资源池节点集合为空
testResourcePoolDTO = generatorDto(false,false,true,false);
testResourcePoolDTO = generatorDto(false, false, true, false);
this.requestPost(TEST_RESOURCE_POOL_UPDATE, testResourcePoolDTO, ERROR_REQUEST_MATCHER);
//UI的grid为空
testResourcePoolDTO = generatorDto(true,true,true,false);
testResourcePoolDTO = generatorDto(true, true, true, false);
this.requestPost(TEST_RESOURCE_POOL_UPDATE, testResourcePoolDTO, ERROR_REQUEST_MATCHER);
}
@ -156,7 +161,7 @@ class TestResourcePoolControllerTest extends BaseTest {
.andExpect(content().contentType(MediaType.APPLICATION_JSON));
}
private TestResourcePoolDTO generatorDto(boolean noName, boolean noType, boolean noResources, boolean noUiGrid ){
private TestResourcePoolDTO generatorDto(boolean noName, boolean noType, boolean noResources, boolean noUiGrid) {
TestResourcePoolDTO testResourcePoolDTO = new TestResourcePoolDTO();
//没名字
if (!noName) {

View File

@ -1,6 +1,6 @@
package io.metersphere.system.controller;
import com.jayway.jsonpath.JsonPath;
import base.BaseTest;
import io.metersphere.api.domain.ApiDefinition;
import io.metersphere.sdk.constants.SessionConstants;
import io.metersphere.sdk.controller.handler.ResultHolder;
@ -8,9 +8,10 @@ import io.metersphere.sdk.dto.BasePageRequest;
import io.metersphere.sdk.dto.UserDTO;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.Pager;
import io.metersphere.system.domain.User;
import io.metersphere.system.dto.UserBatchCreateDTO;
import io.metersphere.system.dto.response.UserInfo;
import io.metersphere.system.dto.UserEditRequest;
import io.metersphere.system.dto.UserInfo;
import io.metersphere.system.dto.UserRoleOption;
import io.metersphere.system.utils.UserTestUtils;
import io.metersphere.utils.JsonUtils;
import jakarta.annotation.Resource;
@ -25,6 +26,7 @@ import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -38,34 +40,43 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
@SpringBootTest
@AutoConfigureMockMvc
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class UserControllerTests {
public class UserControllerTests extends BaseTest {
@Resource
private MockMvc mockMvc;
private static String sessionId;
private static String csrfToken;
private static final String URL_USER_CREATE = "/user/add";
private static final String URL_USER_GET = "/user/get/";
private static final String URL_USER_PAGE = "/user/page";
//涉及到的url
private static final String URL_USER_CREATE = "/system/user/add";
private static final String URL_USER_UPDATE = "/system/user/update";
private static final String URL_USER_GET = "/system/user/get/%s";
private static final String URL_USER_PAGE = "/system/user/page";
private static final String URL_GET_GLOBAL_SYSTEM = "/system/user/get/global/system/role";
//失败请求返回编码
private static final ResultMatcher BAD_REQUEST_MATCHER = status().isBadRequest();
private static final ResultMatcher ERROR_REQUEST_MATCHER = status().is5xxServerError();
//测试过程中需要用到的数据
private static final List<UserInfo> USER_LIST = new ArrayList<>();
private static List<UserRoleOption> defaultUserRoleList = new ArrayList<>();
//默认数据
public static final String USER_DEFAULT_NAME = "tianyang.no.1";
public static final String USER_DEFAULT_EMAIL = "tianyang.no.1@126.com";
private static final List<User> USER_LIST = new ArrayList<>();
//成功入库的用户保存内存中其他用例会使用到
private void addUser2List(MvcResult mvcResult) throws Exception {
String returnData = mvcResult.getResponse().getContentAsString();
//记录查询到的组织信息
private void setDefaultUserRoleList(MvcResult mvcResult) throws Exception {
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder resultHolder = JsonUtils.parseObject(returnData, ResultHolder.class);
//返回请求正常
Assertions.assertNotNull(resultHolder);
List<UserRoleOption> userRoleList = JSON.parseArray(JSON.toJSONString(resultHolder.getData()), UserRoleOption.class);
//返回值不为空
Assertions.assertTrue(CollectionUtils.isNotEmpty(userRoleList));
defaultUserRoleList.addAll(userRoleList);
}
UserBatchCreateDTO userMaintainRequest = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), UserBatchCreateDTO.class);
//成功入库的用户保存内存中其他用例会使用到
private void addUser2List(MvcResult mvcResult) {
UserBatchCreateDTO userMaintainRequest = UserTestUtils.parseObjectFromMvcResult(mvcResult, UserBatchCreateDTO.class);
//返回值不为空
Assertions.assertNotNull(userMaintainRequest);
USER_LIST.addAll(userMaintainRequest.getUserInfoList());
}
@ -76,20 +87,6 @@ public class UserControllerTests {
}
}
@BeforeEach
public void login() throws Exception {
if (StringUtils.isAnyBlank(sessionId, csrfToken)) {
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/login")
.content("{\"username\":\"admin\",\"password\":\"metersphere\"}")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andReturn();
sessionId = JsonPath.read(mvcResult.getResponse().getContentAsString(), "$.data.sessionId");
csrfToken = JsonPath.read(mvcResult.getResponse().getContentAsString(), "$.data.csrfToken");
}
}
private void requestPost(String url, Object param, ResultMatcher resultMatcher) throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post(url)
.header(SessionConstants.HEADER_TOKEN, sessionId)
@ -107,7 +104,8 @@ public class UserControllerTests {
.content(JSON.toJSONString(param))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()).andDo(print())
.andExpect(content().contentType(MediaType.APPLICATION_JSON)).andReturn();
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andReturn();
}
private MvcResult responseGet(String url) throws Exception {
@ -119,25 +117,49 @@ public class UserControllerTests {
.andExpect(content().contentType(MediaType.APPLICATION_JSON)).andReturn();
}
@Test
@Order(0)
public void testGetGlobalSystemUserRoleSuccess() throws Exception {
MvcResult mvcResult = this.responseGet(URL_GET_GLOBAL_SYSTEM);
this.setDefaultUserRoleList(mvcResult);
}
@Test
@Order(1)
public void testAddSuccess() throws Exception {
if (CollectionUtils.isEmpty(defaultUserRoleList)) {
this.testGetGlobalSystemUserRoleSuccess();
}
//模拟前台批量添加用户
UserBatchCreateDTO userMaintainRequest = UserTestUtils.getSimpleUserCreateDTO();
UserBatchCreateDTO userMaintainRequest = UserTestUtils.getUserCreateDTO(
defaultUserRoleList,
new ArrayList<>() {{
add(new UserInfo() {{
setName(USER_DEFAULT_NAME);
setEmail(USER_DEFAULT_EMAIL);
setSource("LOCAL");
}});
add(new UserInfo() {{
setName("tianyang.no.2");
setEmail("tianyang.no.2@126.com");
setSource("LOCAL");
}});
}}
);
MvcResult mvcResult = this.responsePost(URL_USER_CREATE, userMaintainRequest);
this.addUser2List(mvcResult);
//含有重复的用户名称
userMaintainRequest = UserTestUtils.getSimpleUserCreateDTO();
userMaintainRequest.setUserInfoList(
userMaintainRequest = UserTestUtils.getUserCreateDTO(
defaultUserRoleList,
new ArrayList<>() {{
add(new User() {{
add(new UserInfo() {{
setName("tianyang.repeat");
setEmail("tianyang.repeat.name.1@126.com");
setSource("LOCAL");
}});
add(new User() {{
add(new UserInfo() {{
setName("tianyang.repeat");
setEmail("tianyang.repeat.name.2@126.com");
setSource("LOCAL");
@ -149,63 +171,87 @@ public class UserControllerTests {
}
@Test
@Order(2)
@Order(1)
public void testAddError() throws Exception {
if (CollectionUtils.isEmpty(defaultUserRoleList)) {
this.testGetGlobalSystemUserRoleSuccess();
}
UserBatchCreateDTO userMaintainRequest;
boolean roleIsEmpty = true;
boolean organizationIsEmpty = true;
boolean userIsEmpty = true;
List<UserInfo> errorUserList = new ArrayList<>() {{
add(new UserInfo() {{
setName("tianyang.error.1");
setEmail("tianyang.error.name.1@126.com");
setSource("LOCAL");
}});
add(new UserInfo() {{
setName("tianyang.error.2");
setEmail("tianyang.error.name.2@126.com");
setSource("LOCAL");
}});
}};
/*
* 校验参数不合法的反例
* 每一次校验使用getErrorUserCreateDTO方法重新获取参数避免上一步的参数干扰
*/
//所有参数都为空
userMaintainRequest = UserTestUtils.getErrorUserCreateDTO(organizationIsEmpty, roleIsEmpty, userIsEmpty);
this.requestPost(URL_USER_CREATE, userMaintainRequest, BAD_REQUEST_MATCHER);
//组织ID为空
userMaintainRequest = UserTestUtils.getErrorUserCreateDTO(organizationIsEmpty, !roleIsEmpty, !userIsEmpty);
userMaintainRequest = UserTestUtils.getUserCreateDTO(null, null);
this.requestPost(URL_USER_CREATE, userMaintainRequest, BAD_REQUEST_MATCHER);
//用户组ID为空
userMaintainRequest = UserTestUtils.getErrorUserCreateDTO(!organizationIsEmpty, roleIsEmpty, !userIsEmpty);
userMaintainRequest = UserTestUtils.getUserCreateDTO(
null,
errorUserList);
this.requestPost(URL_USER_CREATE, userMaintainRequest, BAD_REQUEST_MATCHER);
//没有用户
userMaintainRequest = UserTestUtils.getErrorUserCreateDTO(!organizationIsEmpty, !roleIsEmpty, userIsEmpty);
this.requestPost(URL_USER_CREATE, userMaintainRequest, BAD_REQUEST_MATCHER);
//含有不存在的组织
userMaintainRequest = UserTestUtils.getErrorUserCreateDTO(!organizationIsEmpty, !roleIsEmpty, !userIsEmpty);
userMaintainRequest.getOrganizationIdList().add(null);
userMaintainRequest.getOrganizationIdList().add("");
userMaintainRequest = UserTestUtils.getUserCreateDTO(
defaultUserRoleList,
null);
this.requestPost(URL_USER_CREATE, userMaintainRequest, BAD_REQUEST_MATCHER);
//含有不存在的用户组
userMaintainRequest = UserTestUtils.getErrorUserCreateDTO(!organizationIsEmpty, !roleIsEmpty, !userIsEmpty);
userMaintainRequest = UserTestUtils.getUserCreateDTO(
defaultUserRoleList,
errorUserList);
userMaintainRequest.getUserRoleIdList().add(null);
userMaintainRequest.getUserRoleIdList().add("");
this.requestPost(URL_USER_CREATE, userMaintainRequest, BAD_REQUEST_MATCHER);
//含有用户名称为空的数据
userMaintainRequest = UserTestUtils.getSimpleUserCreateDTO();
userMaintainRequest.getUserInfoList().add(new User() {{
userMaintainRequest = UserTestUtils.getUserCreateDTO(
defaultUserRoleList,
new ArrayList<>()
);
userMaintainRequest.getUserInfoList().add(new UserInfo() {{
setEmail("tianyang.name.empty@126.com");
setSource("LOCAL");
}});
this.requestPost(URL_USER_CREATE, userMaintainRequest, BAD_REQUEST_MATCHER);
//含有用户邮箱为空的数据
userMaintainRequest = UserTestUtils.getSimpleUserCreateDTO();
userMaintainRequest.getUserInfoList().add(new User() {{
userMaintainRequest = UserTestUtils.getUserCreateDTO(
defaultUserRoleList,
new ArrayList<>()
);
userMaintainRequest.getUserInfoList().add(new UserInfo() {{
setName("tianyang.email.empty");
setSource("LOCAL");
}});
this.requestPost(URL_USER_CREATE, userMaintainRequest, BAD_REQUEST_MATCHER);
//用户邮箱不符合标准
userMaintainRequest = UserTestUtils.getSimpleUserCreateDTO();
userMaintainRequest.getUserInfoList().add(new User() {{
userMaintainRequest = UserTestUtils.getUserCreateDTO(
defaultUserRoleList,
new ArrayList<>()
);
userMaintainRequest.getUserInfoList().add(new UserInfo() {{
setName("用户邮箱放飞自我");
setEmail("用户邮箱放飞自我");
setSource("LOCAL");
}});
this.requestPost(URL_USER_CREATE, userMaintainRequest, BAD_REQUEST_MATCHER);
//用户来源为空
userMaintainRequest = UserTestUtils.getSimpleUserCreateDTO();
userMaintainRequest.getUserInfoList().add(new User() {{
userMaintainRequest = UserTestUtils.getUserCreateDTO(
defaultUserRoleList,
new ArrayList<>()
);
userMaintainRequest.getUserInfoList().add(new UserInfo() {{
setName("tianyang.source.empty");
setEmail("tianyang.source.empty@126.com");
}});
@ -216,22 +262,33 @@ public class UserControllerTests {
* 需要保证数据库有正常数据
*/
this.checkUserList();
//不含有系统成员用户组
userMaintainRequest = UserTestUtils.getUserCreateDTO(
defaultUserRoleList.stream().filter(item -> !StringUtils.equals(item.getId(), "member")).toList(),
errorUserList);
this.requestPost(URL_USER_CREATE, userMaintainRequest, ERROR_REQUEST_MATCHER);
//含有重复的用户邮箱
userMaintainRequest = UserTestUtils.getErrorUserCreateDTO(!organizationIsEmpty, !roleIsEmpty, !userIsEmpty);
userMaintainRequest = UserTestUtils.getUserCreateDTO(
defaultUserRoleList,
errorUserList
);
String firstUserEmail = userMaintainRequest.getUserInfoList().get(0).getEmail();
userMaintainRequest.getUserInfoList().add(new User() {{
userMaintainRequest.getUserInfoList().add(new UserInfo() {{
setName("tianyang.no.error4");
setEmail(firstUserEmail);
setSource("LOCAL");
}});
this.requestPost(URL_USER_CREATE, userMaintainRequest, ERROR_REQUEST_MATCHER);
//测试请求参数中含有数据库中已存在的邮箱情况
userMaintainRequest = UserTestUtils.getErrorUserCreateDTO(!organizationIsEmpty, !roleIsEmpty, userIsEmpty);
userMaintainRequest = UserTestUtils.getUserCreateDTO(
defaultUserRoleList,
errorUserList
);
userMaintainRequest.setUserInfoList(
new ArrayList<>() {{
add(new User() {{
add(new UserInfo() {{
setName("tianyang.repeat.email.db");
setEmail(UserTestUtils.USER_DEFAULT_EMAIL);
setEmail(USER_DEFAULT_EMAIL);
setSource("LOCAL");
}});
}}
@ -240,36 +297,31 @@ public class UserControllerTests {
}
@Test
@Order(3)
@Order(2)
public void testGetByEmailSuccess() throws Exception {
this.checkUserList();
String url = URL_USER_GET + UserTestUtils.USER_DEFAULT_EMAIL;
MvcResult mvcResult = this.responseGet(url);
String returnData = mvcResult.getResponse().getContentAsString();
ResultHolder resultHolder = JsonUtils.parseObject(returnData, ResultHolder.class);
//返回请求正常
Assertions.assertNotNull(resultHolder);
UserDTO userDTO = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), UserDTO.class);
UserDTO userDTO = this.getUserByEmail(USER_DEFAULT_EMAIL);
//返回值不为空
Assertions.assertNotNull(userDTO);
//返回邮箱等于参数邮箱且用户名合法
Assertions.assertEquals(userDTO.getEmail(), UserTestUtils.USER_DEFAULT_EMAIL);
Assertions.assertEquals(userDTO.getEmail(), USER_DEFAULT_EMAIL);
Assertions.assertNotNull(userDTO.getName());
}
private UserDTO getUserByEmail(String email) throws Exception {
String url = String.format(URL_USER_GET, email);
return UserTestUtils.parseObjectFromMvcResult(this.responseGet(url), UserDTO.class);
}
@Test
@Order(3)
@Order(2)
public void testGetByEmailError() throws Exception {
//测试使用任意参数不能获取到任何用户信息
this.checkUserList();
String url = URL_USER_GET + UUID.randomUUID();
MvcResult mvcResult = this.responseGet(url);
String returnData = mvcResult.getResponse().getContentAsString();
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder resultHolder = JsonUtils.parseObject(returnData, ResultHolder.class);
//返回请求正常
Assertions.assertNotNull(resultHolder);
@ -278,11 +330,12 @@ public class UserControllerTests {
}
@Test
@Order(4)
@Order(3)
public void testPageSuccess() throws Exception {
this.checkUserList();
BasePageRequest basePageRequest = UserTestUtils.getDefaultPageRequest();
MvcResult mvcResult = this.responsePost(URL_USER_PAGE, basePageRequest);
String returnData = mvcResult.getResponse().getContentAsString();
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder resultHolder = JsonUtils.parseObject(returnData, ResultHolder.class);
//返回请求正常
Assertions.assertNotNull(resultHolder);
@ -293,10 +346,26 @@ public class UserControllerTests {
Assertions.assertEquals(returnPager.getCurrent(), basePageRequest.getCurrent());
//返回的数据量不超过规定要返回的数据量相同
Assertions.assertTrue(((List<ApiDefinition>) returnPager.getList()).size() <= basePageRequest.getPageSize());
//测试根据创建时间倒叙排列
basePageRequest = UserTestUtils.getDefaultPageRequest();
basePageRequest.setSort(new HashMap<>() {{
put("createTime", "desc");
}});
mvcResult = this.responsePost(URL_USER_PAGE, basePageRequest);
returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
resultHolder = JsonUtils.parseObject(returnData, ResultHolder.class);
returnPager = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), Pager.class);
//第一个数据的createTime是最大的
List<UserInfo> userInfoList = JSON.parseArray(JSON.toJSONString(returnPager.getList()), UserInfo.class);
long firstCreateTime = userInfoList.get(0).getCreateTime();
for (UserInfo userInfo : userInfoList) {
Assertions.assertFalse(userInfo.getCreateTime() > firstCreateTime);
}
}
@Test
@Order(4)
@Order(3)
public void testPageError() throws Exception {
//当前页码不大于0
BasePageRequest basePageRequest = new BasePageRequest();
@ -315,4 +384,46 @@ public class UserControllerTests {
}});
this.requestPost(URL_USER_PAGE, basePageRequest, BAD_REQUEST_MATCHER);
}
@Test
@Order(3)
public void testUserUpdateSuccess() throws Exception {
this.checkUserList();
UserInfo user = USER_LIST.get(0);
UserEditRequest userMaintainRequest;
UserEditRequest response;
UserDTO checkDTO;
//更改名字
user.setName("TEST-UPDATE");
userMaintainRequest = UserTestUtils.getUserUpdateDTO(user, defaultUserRoleList);
response = UserTestUtils.parseObjectFromMvcResult(this.responsePost(URL_USER_UPDATE, userMaintainRequest), UserEditRequest.class);
checkDTO = this.getUserByEmail(user.getEmail());
UserTestUtils.compareUserDTO(response, checkDTO);
//更改邮箱
user.setEmail("songtianyang-test-email@12138.com");
userMaintainRequest = UserTestUtils.getUserUpdateDTO(user, defaultUserRoleList);
response = UserTestUtils.parseObjectFromMvcResult(this.responsePost(URL_USER_UPDATE, userMaintainRequest), UserEditRequest.class);
checkDTO = this.getUserByEmail(user.getEmail());
UserTestUtils.compareUserDTO(response, checkDTO);
//更改手机号
user.setPhone("18511112222");
userMaintainRequest = UserTestUtils.getUserUpdateDTO(user, defaultUserRoleList);
response = UserTestUtils.parseObjectFromMvcResult(this.responsePost(URL_USER_UPDATE, userMaintainRequest), UserEditRequest.class);
checkDTO = this.getUserByEmail(user.getEmail());
UserTestUtils.compareUserDTO(response, checkDTO);
//更改用户组(这里只改成用户成员权限)
userMaintainRequest = UserTestUtils.getUserUpdateDTO(user,
defaultUserRoleList.stream().filter(item -> StringUtils.equals(item.getId(), "member")).toList()
);
response = UserTestUtils.parseObjectFromMvcResult(this.responsePost(URL_USER_UPDATE, userMaintainRequest), UserEditRequest.class);
checkDTO = this.getUserByEmail(user.getEmail());
UserTestUtils.compareUserDTO(response, checkDTO);
//更改用户组(把上面的情况添加别的权限)
userMaintainRequest = UserTestUtils.getUserUpdateDTO(user,
defaultUserRoleList
);
response = UserTestUtils.parseObjectFromMvcResult(this.responsePost(URL_USER_UPDATE, userMaintainRequest), UserEditRequest.class);
checkDTO = this.getUserByEmail(user.getEmail());
UserTestUtils.compareUserDTO(response, checkDTO);
}
}

View File

@ -1,68 +1,59 @@
package io.metersphere.system.utils;
import io.metersphere.sdk.controller.handler.ResultHolder;
import io.metersphere.sdk.dto.BasePageRequest;
import io.metersphere.system.domain.User;
import io.metersphere.sdk.dto.UserDTO;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.domain.UserRole;
import io.metersphere.system.dto.UserBatchCreateDTO;
import io.metersphere.system.dto.UserEditRequest;
import io.metersphere.system.dto.UserInfo;
import io.metersphere.system.dto.UserRoleOption;
import io.metersphere.utils.JsonUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.Assertions;
import org.springframework.test.web.servlet.MvcResult;
import java.util.ArrayList;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.stream.Collectors;
public class UserTestUtils {
public static final String USER_DEFAULT_NAME = "tianyang.no.1";
public static final String USER_DEFAULT_EMAIL = "tianyang.no.1@126.com";
public static final String ORGANIZATION_ID = "ms-organization";
public static final String USER_ROLE_ID = "ms-user-role";
public static <T> T parseObjectFromMvcResult(MvcResult mvcResult, Class<T> parseClass) {
try {
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder resultHolder = JsonUtils.parseObject(returnData, ResultHolder.class);
//返回请求正常
Assertions.assertNotNull(resultHolder);
return JSON.parseObject(JSON.toJSONString(resultHolder.getData()), parseClass);
} catch (Exception ignore) {
}
return null;
}
public static UserBatchCreateDTO getSimpleUserCreateDTO() {
public static UserBatchCreateDTO getUserCreateDTO(
List<UserRoleOption> userRoleList,
List<UserInfo> userInfoList) {
UserBatchCreateDTO userMaintainRequest = new UserBatchCreateDTO();
userMaintainRequest.setOrganizationIdList(new ArrayList<>() {{
add(ORGANIZATION_ID);
}});
userMaintainRequest.setUserRoleIdList(new ArrayList<>() {{
add(USER_ROLE_ID);
}});
userMaintainRequest.setUserInfoList(new ArrayList<>() {{
add(new User() {{
setName(USER_DEFAULT_NAME);
setEmail(USER_DEFAULT_EMAIL);
setSource("LOCAL");
}});
add(new User() {{
setName("tianyang.no.2");
setEmail("tianyang.no.2@126.com");
setSource("LOCAL");
}});
}});
if (CollectionUtils.isNotEmpty(userRoleList)) {
userMaintainRequest.setUserRoleIdList(
userRoleList.stream().map(UserRoleOption::getId).collect(Collectors.toList()));
}
userMaintainRequest.setUserInfoList(userInfoList);
return userMaintainRequest;
}
public static UserBatchCreateDTO getErrorUserCreateDTO(boolean organizationIsEmpty, boolean roleIsEmpty, boolean userIsEmpty) {
UserBatchCreateDTO userMaintainRequest = new UserBatchCreateDTO();
if (!organizationIsEmpty) {
userMaintainRequest.setOrganizationIdList(new ArrayList<>() {{
add(ORGANIZATION_ID);
}});
public static UserEditRequest getUserUpdateDTO(UserInfo user, List<UserRoleOption> userRoleList) {
UserEditRequest returnDTO = new UserEditRequest();
BeanUtils.copyBean(returnDTO, user);
if (CollectionUtils.isNotEmpty(userRoleList)) {
returnDTO.setUserRoleIdList(
userRoleList.stream().map(UserRoleOption::getId).collect(Collectors.toList()));
}
if (!roleIsEmpty) {
userMaintainRequest.setUserRoleIdList(new ArrayList<>() {{
add(USER_ROLE_ID);
}});
}
if (!userIsEmpty) {
userMaintainRequest.setUserInfoList(new ArrayList<>() {{
add(new User() {{
setName("tianyang.error.1");
setEmail("tianyang.error.1@126.com");
setSource("LOCAL");
}});
add(new User() {{
setName("tianyang.error.2");
setEmail("tianyang.error.2@126.com");
setSource("LOCAL");
}});
}});
}
return userMaintainRequest;
return returnDTO;
}
public static BasePageRequest getDefaultPageRequest() {
@ -71,4 +62,26 @@ public class UserTestUtils {
this.setPageSize(10);
}};
}
public static void compareUserDTO(UserEditRequest editRequest, UserDTO selectUserDTO) {
Assertions.assertNotNull(editRequest);
Assertions.assertNotNull(selectUserDTO);
//判断ID是否一样
Assertions.assertTrue(StringUtils.equals(editRequest.getId(), selectUserDTO.getId()));
//判断名称是否一样
Assertions.assertTrue(StringUtils.equals(editRequest.getName(), selectUserDTO.getName()));
//判断邮箱是否一样
Assertions.assertTrue(StringUtils.equals(editRequest.getEmail(), selectUserDTO.getEmail()));
//判断电话号码是否一样
Assertions.assertTrue(StringUtils.equals(editRequest.getPhone(), selectUserDTO.getPhone()));
//判断系统权限是否一样
List<String> selectUserSystemRoleId
= selectUserDTO.getUserRoles().stream()
.filter(item -> (StringUtils.equals(item.getType(), "SYSTEM")
&& StringUtils.equals(item.getScopeId(), "global")))
.map(UserRole::getId).collect(Collectors.toList());
Assertions.assertTrue(
editRequest.getUserRoleIdList().containsAll(selectUserSystemRoleId)
&& selectUserSystemRoleId.containsAll(editRequest.getUserRoleIdList()));
}
}