feat(个人中心): 个人信息以及密码的修改

This commit is contained in:
song-tianyang 2023-12-05 16:31:34 +08:00 committed by 建国
parent 991e2891a4
commit 06ba806ba7
23 changed files with 699 additions and 47 deletions

View File

@ -18,6 +18,12 @@ public class UserExtend implements Serializable {
@Schema(description = "UI本地调试地址")
private String seleniumServer;
@Schema(description = "api本地调试地址")
private String apiServer;
@Schema(description = "头像")
private String avatar;
@Schema(description = "其他平台对接信息")
private byte[] platformInfo;
@ -26,6 +32,8 @@ public class UserExtend implements Serializable {
public enum Column {
id("id", "id", "VARCHAR", false),
seleniumServer("selenium_server", "seleniumServer", "VARCHAR", false),
apiServer("api_server", "apiServer", "VARCHAR", false),
avatar("avatar", "avatar", "VARCHAR", false),
platformInfo("platform_info", "platformInfo", "LONGVARBINARY", false);
private static final String BEGINNING_DELIMITER = "`";

View File

@ -243,6 +243,146 @@ public class UserExtendExample {
addCriterion("selenium_server not between", value1, value2, "seleniumServer");
return (Criteria) this;
}
public Criteria andApiServerIsNull() {
addCriterion("api_server is null");
return (Criteria) this;
}
public Criteria andApiServerIsNotNull() {
addCriterion("api_server is not null");
return (Criteria) this;
}
public Criteria andApiServerEqualTo(String value) {
addCriterion("api_server =", value, "apiServer");
return (Criteria) this;
}
public Criteria andApiServerNotEqualTo(String value) {
addCriterion("api_server <>", value, "apiServer");
return (Criteria) this;
}
public Criteria andApiServerGreaterThan(String value) {
addCriterion("api_server >", value, "apiServer");
return (Criteria) this;
}
public Criteria andApiServerGreaterThanOrEqualTo(String value) {
addCriterion("api_server >=", value, "apiServer");
return (Criteria) this;
}
public Criteria andApiServerLessThan(String value) {
addCriterion("api_server <", value, "apiServer");
return (Criteria) this;
}
public Criteria andApiServerLessThanOrEqualTo(String value) {
addCriterion("api_server <=", value, "apiServer");
return (Criteria) this;
}
public Criteria andApiServerLike(String value) {
addCriterion("api_server like", value, "apiServer");
return (Criteria) this;
}
public Criteria andApiServerNotLike(String value) {
addCriterion("api_server not like", value, "apiServer");
return (Criteria) this;
}
public Criteria andApiServerIn(List<String> values) {
addCriterion("api_server in", values, "apiServer");
return (Criteria) this;
}
public Criteria andApiServerNotIn(List<String> values) {
addCriterion("api_server not in", values, "apiServer");
return (Criteria) this;
}
public Criteria andApiServerBetween(String value1, String value2) {
addCriterion("api_server between", value1, value2, "apiServer");
return (Criteria) this;
}
public Criteria andApiServerNotBetween(String value1, String value2) {
addCriterion("api_server not between", value1, value2, "apiServer");
return (Criteria) this;
}
public Criteria andAvatarIsNull() {
addCriterion("avatar is null");
return (Criteria) this;
}
public Criteria andAvatarIsNotNull() {
addCriterion("avatar is not null");
return (Criteria) this;
}
public Criteria andAvatarEqualTo(String value) {
addCriterion("avatar =", value, "avatar");
return (Criteria) this;
}
public Criteria andAvatarNotEqualTo(String value) {
addCriterion("avatar <>", value, "avatar");
return (Criteria) this;
}
public Criteria andAvatarGreaterThan(String value) {
addCriterion("avatar >", value, "avatar");
return (Criteria) this;
}
public Criteria andAvatarGreaterThanOrEqualTo(String value) {
addCriterion("avatar >=", value, "avatar");
return (Criteria) this;
}
public Criteria andAvatarLessThan(String value) {
addCriterion("avatar <", value, "avatar");
return (Criteria) this;
}
public Criteria andAvatarLessThanOrEqualTo(String value) {
addCriterion("avatar <=", value, "avatar");
return (Criteria) this;
}
public Criteria andAvatarLike(String value) {
addCriterion("avatar like", value, "avatar");
return (Criteria) this;
}
public Criteria andAvatarNotLike(String value) {
addCriterion("avatar not like", value, "avatar");
return (Criteria) this;
}
public Criteria andAvatarIn(List<String> values) {
addCriterion("avatar in", values, "avatar");
return (Criteria) this;
}
public Criteria andAvatarNotIn(List<String> values) {
addCriterion("avatar not in", values, "avatar");
return (Criteria) this;
}
public Criteria andAvatarBetween(String value1, String value2) {
addCriterion("avatar between", value1, value2, "avatar");
return (Criteria) this;
}
public Criteria andAvatarNotBetween(String value1, String value2) {
addCriterion("avatar not between", value1, value2, "avatar");
return (Criteria) this;
}
}
public static class Criteria extends GeneratedCriteria {

View File

@ -4,6 +4,8 @@
<resultMap id="BaseResultMap" type="io.metersphere.system.domain.UserExtend">
<id column="id" jdbcType="VARCHAR" property="id" />
<result column="selenium_server" jdbcType="VARCHAR" property="seleniumServer" />
<result column="api_server" jdbcType="VARCHAR" property="apiServer" />
<result column="avatar" jdbcType="VARCHAR" property="avatar" />
</resultMap>
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.system.domain.UserExtend">
<result column="platform_info" jdbcType="LONGVARBINARY" property="platformInfo" />
@ -67,7 +69,7 @@
</where>
</sql>
<sql id="Base_Column_List">
id, selenium_server
id, selenium_server, api_server, avatar
</sql>
<sql id="Blob_Column_List">
platform_info
@ -121,10 +123,10 @@
</if>
</delete>
<insert id="insert" parameterType="io.metersphere.system.domain.UserExtend">
insert into user_extend (id, selenium_server, platform_info
)
values (#{id,jdbcType=VARCHAR}, #{seleniumServer,jdbcType=VARCHAR}, #{platformInfo,jdbcType=LONGVARBINARY}
)
insert into user_extend (id, selenium_server, api_server,
avatar, platform_info)
values (#{id,jdbcType=VARCHAR}, #{seleniumServer,jdbcType=VARCHAR}, #{apiServer,jdbcType=VARCHAR},
#{avatar,jdbcType=VARCHAR}, #{platformInfo,jdbcType=LONGVARBINARY})
</insert>
<insert id="insertSelective" parameterType="io.metersphere.system.domain.UserExtend">
insert into user_extend
@ -135,6 +137,12 @@
<if test="seleniumServer != null">
selenium_server,
</if>
<if test="apiServer != null">
api_server,
</if>
<if test="avatar != null">
avatar,
</if>
<if test="platformInfo != null">
platform_info,
</if>
@ -146,6 +154,12 @@
<if test="seleniumServer != null">
#{seleniumServer,jdbcType=VARCHAR},
</if>
<if test="apiServer != null">
#{apiServer,jdbcType=VARCHAR},
</if>
<if test="avatar != null">
#{avatar,jdbcType=VARCHAR},
</if>
<if test="platformInfo != null">
#{platformInfo,jdbcType=LONGVARBINARY},
</if>
@ -166,6 +180,12 @@
<if test="record.seleniumServer != null">
selenium_server = #{record.seleniumServer,jdbcType=VARCHAR},
</if>
<if test="record.apiServer != null">
api_server = #{record.apiServer,jdbcType=VARCHAR},
</if>
<if test="record.avatar != null">
avatar = #{record.avatar,jdbcType=VARCHAR},
</if>
<if test="record.platformInfo != null">
platform_info = #{record.platformInfo,jdbcType=LONGVARBINARY},
</if>
@ -178,6 +198,8 @@
update user_extend
set id = #{record.id,jdbcType=VARCHAR},
selenium_server = #{record.seleniumServer,jdbcType=VARCHAR},
api_server = #{record.apiServer,jdbcType=VARCHAR},
avatar = #{record.avatar,jdbcType=VARCHAR},
platform_info = #{record.platformInfo,jdbcType=LONGVARBINARY}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
@ -186,7 +208,9 @@
<update id="updateByExample" parameterType="map">
update user_extend
set id = #{record.id,jdbcType=VARCHAR},
selenium_server = #{record.seleniumServer,jdbcType=VARCHAR}
selenium_server = #{record.seleniumServer,jdbcType=VARCHAR},
api_server = #{record.apiServer,jdbcType=VARCHAR},
avatar = #{record.avatar,jdbcType=VARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
@ -197,6 +221,12 @@
<if test="seleniumServer != null">
selenium_server = #{seleniumServer,jdbcType=VARCHAR},
</if>
<if test="apiServer != null">
api_server = #{apiServer,jdbcType=VARCHAR},
</if>
<if test="avatar != null">
avatar = #{avatar,jdbcType=VARCHAR},
</if>
<if test="platformInfo != null">
platform_info = #{platformInfo,jdbcType=LONGVARBINARY},
</if>
@ -206,21 +236,25 @@
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.system.domain.UserExtend">
update user_extend
set selenium_server = #{seleniumServer,jdbcType=VARCHAR},
api_server = #{apiServer,jdbcType=VARCHAR},
avatar = #{avatar,jdbcType=VARCHAR},
platform_info = #{platformInfo,jdbcType=LONGVARBINARY}
where id = #{id,jdbcType=VARCHAR}
</update>
<update id="updateByPrimaryKey" parameterType="io.metersphere.system.domain.UserExtend">
update user_extend
set selenium_server = #{seleniumServer,jdbcType=VARCHAR}
set selenium_server = #{seleniumServer,jdbcType=VARCHAR},
api_server = #{apiServer,jdbcType=VARCHAR},
avatar = #{avatar,jdbcType=VARCHAR}
where id = #{id,jdbcType=VARCHAR}
</update>
<insert id="batchInsert" parameterType="map">
insert into user_extend
(id, selenium_server, platform_info)
(id, selenium_server, api_server, avatar, platform_info)
values
<foreach collection="list" item="item" separator=",">
(#{item.id,jdbcType=VARCHAR}, #{item.seleniumServer,jdbcType=VARCHAR}, #{item.platformInfo,jdbcType=LONGVARBINARY}
)
(#{item.id,jdbcType=VARCHAR}, #{item.seleniumServer,jdbcType=VARCHAR}, #{item.apiServer,jdbcType=VARCHAR},
#{item.avatar,jdbcType=VARCHAR}, #{item.platformInfo,jdbcType=LONGVARBINARY})
</foreach>
</insert>
<insert id="batchInsertSelective" parameterType="map">
@ -239,6 +273,12 @@
<if test="'selenium_server'.toString() == column.value">
#{item.seleniumServer,jdbcType=VARCHAR}
</if>
<if test="'api_server'.toString() == column.value">
#{item.apiServer,jdbcType=VARCHAR}
</if>
<if test="'avatar'.toString() == column.value">
#{item.avatar,jdbcType=VARCHAR}
</if>
<if test="'platform_info'.toString() == column.value">
#{item.platformInfo,jdbcType=LONGVARBINARY}
</if>

View File

@ -318,17 +318,21 @@ CREATE INDEX idx_update_time ON organization (`update_time` desc);
CREATE INDEX idx_deleted ON organization (`deleted`);
CREATE INDEX idx_update_user ON organization(`update_user`);
CREATE TABLE IF NOT EXISTS user_extend
DROP TABLE IF EXISTS user_extend;
CREATE TABLE user_extend
(
`id` VARCHAR(50) NOT NULL COMMENT '用户ID',
`platform_info` BLOB COMMENT '其他平台对接信息',
`selenium_server` VARCHAR(255) COMMENT 'UI本地调试地址',
`api_server` VARCHAR(255) COMMENT 'api本地调试地址',
`avatar` VARCHAR(255) COMMENT '头像',
PRIMARY KEY (id)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT = '用户扩展';
CREATE TABLE IF NOT EXISTS test_resource_pool_organization
(
`id` VARCHAR(50) NOT NULL COMMENT '测试资源池项目关系ID',

View File

@ -39,6 +39,11 @@ INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'member', 'SYSTEM_PERSONAL_API_KEY_ADD:READ+UPDATE');
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'member', 'SYSTEM_PERSONAL_API_KEY_ADD:READ+DELETE');
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'member', 'SYSTEM_PERSONAL_API_KEY_ADD:READ');
INSERT INTO user_role_permission (id, role_id, permission_id)
VALUES (UUID_SHORT(), 'member', 'SYSTEM_PERSONAL:READ');
INSERT INTO user_role_permission (id, role_id, permission_id)
VALUES (UUID_SHORT(), 'member', 'SYSTEM_PERSONAL:READ+UPDATE');
-- 组织管理员权限
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'org_admin', 'ORGANIZATION_USER_ROLE:READ');
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'org_admin', 'ORGANIZATION_USER_ROLE:READ+ADD');

View File

@ -267,4 +267,6 @@ public class PermissionConstants {
public static final String SYSTEM_PERSONAL_API_KEY_DELETE = "SYSTEM_PERSONAL_API_KEY_DELETE:READ+DELETE";
public static final String SYSTEM_PERSONAL_API_KEY_READ = "SYSTEM_PERSONAL_API_KEY_READ:READ";
public static final String SYSTEM_PERSONAL_API_KEY_UPDATE = "SYSTEM_PERSONAL_API_KEY_UPDATE:READ+UPDATE";
public static final String SYSTEM_PERSONAL_READ = "SYSTEM_PERSONAL:READ";
public static final String SYSTEM_PERSONAL_READ_UPDATE = "SYSTEM_PERSONAL:READ+UPDATE";
}

View File

@ -5,6 +5,12 @@ role.not.contains.member=角色不包含系统成员角色
user.not.login=未获取到登录用户
user.not.empty=用户不呢为空
user.not.exist=用户不存在
personal.no.permission=无权操作非本人账户
personal.change.password=修改了密码
personal.change.info=修改了信息
personal.user.name=用户名称
personal.user.phone=手机号
personal.user.email=用户邮箱
auth_source.id.not_blank=认证源ID不能为空
auth_source.status.length_range=认证源状态长度必须在{min}和{max}之间
auth_source.status.not_blank=认证源状态不能为空
@ -91,6 +97,9 @@ user.not.disable=用户不能禁用
user.id.not_blank=用户ID不能为空
user.name.not_blank=用户名称不能为空
user.name.length_range=用户名称长度必须在{min}和{max}之间
user.phone.not_blank=用户手机号不能为空
user.password.error=验证用户密码失败
user.password.not.blank=用户密码不能为空
user.email.not_blank=用户email不能为空
user.email.length_range=用户email长度必须在{min}和{max}之间
user.email.hi=你好

View File

@ -4,6 +4,12 @@ role.not.global.system=Role is not global system role
role.not.contains.member=Role not contains member
user.not.login=User not login
user.not.exist=User not exist
personal.no.permission=No permission
personal.change.password=Changed password
personal.change.info=Changed information
personal.user.name=Name
personal.user.phone=Phone
personal.user.email=Email
default.module=Default module
user.not.empty=User can not empty
auth_source.id.not_blank=Auth source id must not be blank
@ -91,6 +97,9 @@ user.not.disable=User can't disable
user.id.not_blank=User id must not be blank
user.name.not_blank=Username must not be blank
user.name.length_range=Username must be between {min} and {max} characters long
user.phone.not_blank=User phone must not be blank
user.password.error=Validate password error
user.password.not.blank=User password must not be blank
user.email.not_blank=User email must not be blank
user.email.length_range=User email must be between {min} and {max} characters long
user.email.hi=Hi

View File

@ -5,6 +5,12 @@ role.not.contains.member=角色不包含系统成员角色
user.not.login=未获取到登录用户
user.not.empty=用户不呢为空
user.not.exist=用户不存在
personal.no.permission=无权操作非本人账户
personal.change.password=修改了密码
personal.change.info=修改了信息
personal.user.name=用户名称
personal.user.phone=手机号
personal.user.email=用户邮箱
default.module=默认模块
auth_source.id.not_blank=认证源ID不能为空
auth_source.status.length_range=认证源状态长度必须在{min}和{max}之间
@ -92,6 +98,9 @@ user.not.disable=用户不能禁用
user.id.not_blank=用户ID不能为空
user.name.not_blank=用户名称不能为空
user.name.length_range=用户名称长度必须在{min}和{max}之间
user.phone.not_blank=用户手机号不能为空
user.password.error=验证用户密码失败
user.password.not.blank=用户密码不能为空
user.email.not_blank=用户email不能为空
user.email.length_range=用户email长度必须在{min}和{max}之间
user.email.hi=你好

View File

@ -5,6 +5,12 @@ role.not.contains.member=角色不包含系統成員角色
user.not.login=未獲取到登錄用戶
user.not.empty=用戶不呢為空
user.not.exist=用戶不存在
personal.no.permission=無權操作非本人賬戶
personal.change.password=修改了密碼
personal.change.info=修改了信息
personal.user.name=用戶名稱
personal.user.phone=手機號
personal.user.email=用戶郵箱
default.module=默認模塊
auth_source.id.not_blank=認證源ID不能為空
auth_source.status.length_range=認證源狀態長度必須在{min}和{max}之間
@ -91,6 +97,9 @@ user.not.disable=用戶不能禁用
user.id.not_blank=用戶ID不能為空
user.name.not_blank=用戶名稱不能為空
user.name.length_range=用戶名稱長度必須在{min}和{max}之間
user.phone.not_blank=用戶手機號不能為空
user.password.error=驗證用戶密碼失敗
user.password.not.blank=用戶密碼不能為空
user.email.not_blank=用戶email不能為空
user.email.length_range=用戶email長度必須在{min}和{max}之間
user.email.hi=你好

View File

@ -51,7 +51,6 @@ public class FileRepositoryService extends FileModuleService {
public String addRepository(FileRepositoryCreateRequest request, String operator) {
this.connect(request.getUrl(), request.getToken(), request.getUserName());
this.checkPlatForm(request.getPlatform());
//记录模块节点数据
FileModule fileModule = new FileModule();
fileModule.setId(IDGenerator.nextStr());
@ -126,12 +125,6 @@ public class FileRepositoryService extends FileModuleService {
fileModuleLogService.saveUpdateRepositoryLog(oldLog, new FileRepositoryLog(fileModule, repository), operator);
}
private void checkPlatForm(String platform) {
if (!StringUtils.equalsAny(platform, ModuleConstants.NODE_TYPE_GITHUB, ModuleConstants.NODE_TYPE_GITEE, ModuleConstants.NODE_TYPE_GITLAB)) {
throw new MSException(Translator.get("file_repository.platform.error"));
}
}
public String addFile(RepositoryFileAddRequest request, String operator) {
FileModule fileModule = fileModuleMapper.selectByPrimaryKey(request.getModuleId());
FileModuleRepository repository = fileModuleRepositoryMapper.selectByPrimaryKey(request.getModuleId());

View File

@ -51,6 +51,9 @@ public class FileRepositoryControllerTest extends BaseTest {
private static final String GITEE_USERNAME = "testformetersphere";
private static final String GITEE_TOKEN = "4548d369bb595738d726512742e4478f";
private static final String GITEA_USERNAME = "meterspherecodetest";
private static final String GITEA_TOKEN = "f5e34c45e998291909e0897a76a1f1ae42095e3f";
private static final List<String> fileList = new ArrayList<>();
private static String repositoryId;

View File

@ -0,0 +1,60 @@
package io.metersphere.system.controller;
import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.system.dto.request.user.PersonalUpdatePasswordRequest;
import io.metersphere.system.dto.request.user.PersonalUpdateRequest;
import io.metersphere.system.dto.user.UserDTO;
import io.metersphere.system.log.annotation.Log;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.service.UserLogService;
import io.metersphere.system.service.UserService;
import io.metersphere.system.utils.SessionUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@RestController
@Tag(name = "个人中心")
@RequestMapping("/personal")
public class PersonalCenterController {
@Resource
private UserService userService;
@GetMapping("/get/{id}")
@Operation(summary = "个人中心-获取信息")
@RequiresPermissions(PermissionConstants.SYSTEM_PERSONAL_READ)
public UserDTO getInformation(@PathVariable String id) {
this.checkPermission(id);
return userService.getUserDTOByKeyword(id);
}
@PostMapping("/update-info")
@Operation(summary = "个人中心-修改信息")
@RequiresPermissions(PermissionConstants.SYSTEM_PERSONAL_READ_UPDATE)
@Log(type = OperationLogType.UPDATE, expression = "#msClass.updateAccountLog(#request)", msClass = UserLogService.class)
public boolean updateUser(@Validated @RequestBody PersonalUpdateRequest request) {
this.checkPermission(request.getId());
return userService.updateAccount(request, SessionUtils.getUserId());
}
@PostMapping("/update-password")
@Operation(summary = "个人中心-修改密码")
@RequiresPermissions(PermissionConstants.SYSTEM_PERSONAL_READ_UPDATE)
@Log(type = OperationLogType.UPDATE, expression = "#msClass.updatePasswordLog(#request)", msClass = UserLogService.class)
public boolean updateUser(@Validated @RequestBody PersonalUpdatePasswordRequest request) {
this.checkPermission(request.getId());
return userService.updatePassword(request);
}
private void checkPermission(String id) {
if (!StringUtils.equals(id, SessionUtils.getUserId())) {
throw new MSException("personal.no.permission");
}
}
}

View File

@ -6,13 +6,19 @@ import com.github.pagehelper.PageHelper;
import io.metersphere.project.domain.Project;
import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.sdk.constants.UserSource;
import io.metersphere.system.utils.PageUtils;
import io.metersphere.system.utils.Pager;
import io.metersphere.system.domain.Organization;
import io.metersphere.system.dto.UserBatchCreateDTO;
import io.metersphere.system.dto.request.OrganizationMemberBatchRequest;
import io.metersphere.system.dto.request.ProjectAddMemberBatchRequest;
import io.metersphere.system.dto.request.UserInviteRequest;
import io.metersphere.system.dto.request.UserRegisterRequest;
import io.metersphere.system.dto.request.user.UserChangeEnableRequest;
import io.metersphere.system.dto.request.user.UserEditRequest;
import io.metersphere.system.dto.request.user.UserRoleBatchRelationRequest;
import io.metersphere.system.dto.response.UserImportResponse;
import io.metersphere.system.dto.response.UserInviteResponse;
import io.metersphere.system.dto.response.UserSelectOption;
import io.metersphere.system.dto.response.UserTableResponse;
import io.metersphere.system.dto.sdk.BasePageRequest;
import io.metersphere.system.dto.sdk.BaseTreeNode;
import io.metersphere.system.dto.sdk.OptionDTO;
@ -21,15 +27,9 @@ import io.metersphere.system.dto.table.TableBatchProcessResponse;
import io.metersphere.system.dto.user.UserDTO;
import io.metersphere.system.log.annotation.Log;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.dto.request.OrganizationMemberBatchRequest;
import io.metersphere.system.dto.request.ProjectAddMemberBatchRequest;
import io.metersphere.system.dto.request.user.UserChangeEnableRequest;
import io.metersphere.system.dto.request.user.UserEditRequest;
import io.metersphere.system.dto.request.user.UserRoleBatchRelationRequest;
import io.metersphere.system.dto.response.UserImportResponse;
import io.metersphere.system.dto.response.UserSelectOption;
import io.metersphere.system.dto.response.UserTableResponse;
import io.metersphere.system.service.*;
import io.metersphere.system.utils.PageUtils;
import io.metersphere.system.utils.Pager;
import io.metersphere.system.utils.SessionUtils;
import io.metersphere.system.utils.TreeNodeParseUtils;
import io.metersphere.validation.groups.Created;
@ -186,14 +186,14 @@ public class UserController {
}
@PostMapping("/invite")
@Operation(summary = "系统设置-系统-用户-用户邀请")
@Operation(summary = "系统设置-系统-用户-邀请用户注册")
@RequiresPermissions(PermissionConstants.SYSTEM_USER_ADD)
public UserInviteResponse invite(@Validated @RequestBody UserInviteRequest request) {
return userService.saveInviteRecord(request, SessionUtils.getUser());
}
@PostMapping("/register-by-invite")
@Operation(summary = "系统设置-系统-用户-用户邀请")
@Operation(summary = "系统设置-系统-用户-用户接受注册邀请并创建账户")
public String registerByInvite(@Validated @RequestBody UserRegisterRequest request) throws Exception {
return userService.registerByInvite(request);
}

View File

@ -0,0 +1,22 @@
package io.metersphere.system.dto.request.user;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
@Data
public class PersonalUpdatePasswordRequest {
@Schema(description = "用户ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{user.id.not_blank}")
private String id;
@Schema(description = "旧密码", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{user.password.not.blank}")
private String oldPassword;
@Schema(description = "新密码", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{user.password.not.blank}")
private String newPassword;
}

View File

@ -0,0 +1,30 @@
package io.metersphere.system.dto.request.user;
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;
@Data
public class PersonalUpdateRequest {
@Schema(description = "用户ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{user.id.not_blank}")
private String id;
@Schema(description = "用户名", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{user.id.not_blank}")
private String username;
@Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{user.email.not_blank}")
private String phone;
@Schema(description = "邮箱", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{user.phone.not_blank}")
@Size(min = 1, max = 64, message = "{user.email.length_range}")
@Email(message = "{user.email.invalid}")
private String email;
}

View File

@ -21,6 +21,12 @@ public class UserDTO extends User {
@Schema(description = "其他平台对接信息", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
private byte[] platformInfo;
@Schema(description = "UI本地调试地址", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
@Schema(description = "UI本地调试地址")
private String seleniumServer;
@Schema(description = "API本地调试地址")
private String apiServer;
@Schema(description = "头像")
private String avatar;
}

View File

@ -5,21 +5,19 @@ import io.metersphere.project.domain.ProjectExample;
import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.sdk.constants.HttpMethodConstants;
import io.metersphere.sdk.constants.OperationLogConstants;
import io.metersphere.system.log.dto.LogDTO;
import io.metersphere.system.dto.table.TableBatchProcessDTO;
import io.metersphere.system.dto.builder.LogDTOBuilder;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.domain.*;
import io.metersphere.system.dto.builder.LogDTOBuilder;
import io.metersphere.system.dto.request.user.*;
import io.metersphere.system.dto.table.TableBatchProcessDTO;
import io.metersphere.system.log.constants.OperationLogModule;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.log.dto.LogDTO;
import io.metersphere.system.log.service.OperationLogService;
import io.metersphere.system.mapper.OrganizationMapper;
import io.metersphere.system.mapper.UserMapper;
import io.metersphere.system.mapper.UserRoleMapper;
import io.metersphere.system.dto.request.user.UserChangeEnableRequest;
import io.metersphere.system.dto.request.user.UserEditRequest;
import io.metersphere.system.dto.request.user.UserRoleBatchRelationRequest;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.apache.commons.lang3.StringUtils;
@ -86,6 +84,57 @@ public class UserLogService {
return null;
}
public LogDTO updatePasswordLog(PersonalUpdatePasswordRequest request) {
User user = userMapper.selectByPrimaryKey(request.getId());
if (user != null) {
LogDTO dto = LogDTOBuilder.builder()
.projectId(OperationLogConstants.SYSTEM)
.organizationId(OperationLogConstants.SYSTEM)
.type(OperationLogType.UPDATE.name())
.module(OperationLogModule.PERSONAL_INFORMATION_PERSONAL_SETTINGS)
.method(HttpMethodConstants.POST.name())
.path("/personal/update-password")
.sourceId(request.getId())
.content(user.getName() + StringUtils.SPACE + Translator.get("personal.change.password"))
.originalValue(JSON.toJSONBytes(user))
.build().getLogDTO();
return dto;
}
return null;
}
public LogDTO updateAccountLog(PersonalUpdateRequest request) {
User user = userMapper.selectByPrimaryKey(request.getId());
StringBuilder content = new StringBuilder();
if (user != null) {
if (!StringUtils.equals(user.getName(), request.getUsername())) {
content.append(Translator.get("personal.user.name")).append(":").append(user.getName()).append("->").append(request.getUsername()).append(";");
}
if (!StringUtils.equals(user.getEmail(), request.getEmail())) {
content.append(Translator.get("personal.user.email")).append(":").append(user.getEmail()).append("->").append(request.getEmail()).append(";");
}
if (!StringUtils.equals(user.getPhone(), request.getPhone())) {
content.append(Translator.get("personal.user.phone")).append(":").append(user.getPhone()).append("->").append(request.getPhone()).append(";");
}
LogDTO dto = LogDTOBuilder.builder()
.projectId(OperationLogConstants.SYSTEM)
.organizationId(OperationLogConstants.SYSTEM)
.type(OperationLogType.UPDATE.name())
.module(OperationLogModule.PERSONAL_INFORMATION_PERSONAL_SETTINGS)
.method(HttpMethodConstants.POST.name())
.path("/personal/update-info")
.sourceId(request.getId())
.content(user.getName() + StringUtils.SPACE + Translator.get("personal.change.info") + ". " + content)
.originalValue(JSON.toJSONBytes(user))
.build().getLogDTO();
return dto;
}
return null;
}
//批量开启和关闭
public List<LogDTO> batchUpdateEnableLog(UserChangeEnableRequest request) {
List<LogDTO> logDTOList = new ArrayList<>();

View File

@ -12,6 +12,8 @@ import io.metersphere.system.dto.excel.UserExcel;
import io.metersphere.system.dto.excel.UserExcelRowDTO;
import io.metersphere.system.dto.request.UserInviteRequest;
import io.metersphere.system.dto.request.UserRegisterRequest;
import io.metersphere.system.dto.request.user.PersonalUpdatePasswordRequest;
import io.metersphere.system.dto.request.user.PersonalUpdateRequest;
import io.metersphere.system.dto.request.user.UserChangeEnableRequest;
import io.metersphere.system.dto.request.user.UserEditRequest;
import io.metersphere.system.dto.response.UserImportResponse;
@ -172,6 +174,23 @@ public class UserService {
return returnList;
}
private void checkUserEmail(String id, String email) {
UserExample userExample = new UserExample();
userExample.createCriteria().andEmailEqualTo(email).andIdNotEqualTo(id);
if (userMapper.countByExample(userExample) > 0) {
throw new MSException(Translator.get("user_email_already_exists"));
}
}
private void checkOldPassword(String id, String password) {
UserExample userExample = new UserExample();
userExample.createCriteria().andPasswordEqualTo(password).andIdEqualTo(id);
if (userMapper.countByExample(userExample) != 1) {
throw new MSException(Translator.get("password_modification_failed"));
}
}
public UserEditRequest updateUser(UserEditRequest userEditRequest, String operator) {
//检查用户组合法性
globalUserRoleService.checkRoleIsGlobalAndHaveMember(userEditRequest.getUserRoleIdList(), true);
@ -495,4 +514,24 @@ public class UserService {
userLogService.addRegisterLog(user, userInvite);
return user.getId();
}
public boolean updateAccount(PersonalUpdateRequest request, String operator) {
this.checkUserEmail(request.getId(), request.getEmail());
User editUser = new User();
editUser.setId(request.getId());
editUser.setName(request.getUsername());
editUser.setPhone(request.getPhone());
editUser.setEmail(request.getEmail());
editUser.setUpdateUser(operator);
editUser.setUpdateTime(System.currentTimeMillis());
return userMapper.updateByPrimaryKeySelective(editUser) > 0;
}
public boolean updatePassword(PersonalUpdatePasswordRequest request) {
this.checkOldPassword(request.getId(), request.getOldPassword());
User editUser = new User();
editUser.setId(request.getId());
editUser.setPassword(request.getNewPassword());
return userMapper.updateByPrimaryKeySelective(editUser) > 0;
}
}

View File

@ -300,6 +300,12 @@
"id": "API_KEYS",
"name": "permission.api_keys",
"permissions": [
{
"id": "SYSTEM_PERSONAL:READ"
},
{
"id": "SYSTEM_PERSONAL:READ+UPDATE"
},
{
"id": "SYSTEM_PERSONAL_API_KEY_ADD:READ+ADD"
},

View File

@ -0,0 +1,197 @@
package io.metersphere.system.controller.user;
import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.sdk.util.CodingUtils;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.domain.UserExample;
import io.metersphere.system.dto.request.user.PersonalUpdatePasswordRequest;
import io.metersphere.system.dto.request.user.PersonalUpdateRequest;
import io.metersphere.system.dto.user.UserDTO;
import io.metersphere.system.mapper.UserMapper;
import io.metersphere.system.uid.IDGenerator;
import io.metersphere.system.utils.user.PersonalRequestUtils;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.*;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MvcResult;
import java.nio.charset.StandardCharsets;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class PersonalControllerTests extends BaseTest {
private static String loginUser = "admin";
@Resource
private UserMapper userMapper;
@Test
@Order(0)
void testPersonalGetId() throws Exception {
//查询自己的
this.requestGetWithOk(String.format(PersonalRequestUtils.URL_PERSONAL_GET, loginUser));
//查询非登录人
this.requestGet(String.format(PersonalRequestUtils.URL_PERSONAL_GET, IDGenerator.nextStr())).andExpect(status().is5xxServerError());
//权限校验
this.requestGetPermissionTest(PermissionConstants.SYSTEM_PERSONAL_READ, String.format(PersonalRequestUtils.URL_PERSONAL_GET, loginUser));
}
private UserDTO selectUserDTO(String id) throws Exception {
MvcResult result = this.requestGetAndReturn(String.format(PersonalRequestUtils.URL_PERSONAL_GET, loginUser));
ResultHolder resultHolder = JSON.parseObject(result.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class);
return JSON.parseObject(JSON.toJSONString(resultHolder.getData()), UserDTO.class);
}
@Test
@Order(1)
void testPersonalUpdateInfo() throws Exception {
PersonalUpdateRequest request = new PersonalUpdateRequest();
request.setId(loginUser);
request.setEmail("admin_update@metersphere.io");
request.setUsername("admin_update");
request.setPhone("1111111111");
this.requestPostWithOk(PersonalRequestUtils.URL_PERSONAL_UPDATE_INFO, request);
UserDTO userDTO = this.selectUserDTO(loginUser);
this.checkUserInformation(userDTO, request);
//修改回去
request = new PersonalUpdateRequest();
request.setId(loginUser);
request.setEmail("admin@metersphere.io");
request.setUsername("'Administrator'");
request.setPhone("12345678901");
this.requestPostWithOk(PersonalRequestUtils.URL_PERSONAL_UPDATE_INFO, request);
userDTO = this.selectUserDTO(loginUser);
this.checkUserInformation(userDTO, request);
//修改非登录人
request = new PersonalUpdateRequest();
request.setId(IDGenerator.nextStr());
request.setEmail("admin@metersphere.io");
request.setUsername("'Administrator'");
request.setPhone("12345678901");
this.requestPost(PersonalRequestUtils.URL_PERSONAL_UPDATE_INFO, request).andExpect(status().is5xxServerError());
//参数校验
request = new PersonalUpdateRequest();
request.setId(loginUser);
request.setEmail("admin@metersphere.io");
request.setUsername("'Administrator'");
this.requestPost(PersonalRequestUtils.URL_PERSONAL_UPDATE_INFO, request).andExpect(status().isBadRequest());
request = new PersonalUpdateRequest();
request.setId(loginUser);
request.setEmail("admin@metersphere.io");
request.setPhone("12345678901");
this.requestPost(PersonalRequestUtils.URL_PERSONAL_UPDATE_INFO, request).andExpect(status().isBadRequest());
request = new PersonalUpdateRequest();
request.setId(loginUser);
request.setUsername("'Administrator'");
request.setPhone("12345678901");
this.requestPost(PersonalRequestUtils.URL_PERSONAL_UPDATE_INFO, request).andExpect(status().isBadRequest());
request = new PersonalUpdateRequest();
request.setEmail("admin@metersphere.io");
request.setUsername("'Administrator'");
request.setPhone("12345678901");
this.requestPost(PersonalRequestUtils.URL_PERSONAL_UPDATE_INFO, request).andExpect(status().isBadRequest());
//权限校验
request = new PersonalUpdateRequest();
request.setId(loginUser);
request.setEmail("admin@metersphere.io");
request.setUsername("'Administrator'");
request.setPhone("12345678901");
this.requestPostPermissionTest(PermissionConstants.SYSTEM_PERSONAL_READ_UPDATE, PersonalRequestUtils.URL_PERSONAL_UPDATE_INFO, request);
}
private void checkUserInformation(UserDTO userDTO, PersonalUpdateRequest request) {
if (request.getId() != null) {
Assertions.assertEquals(request.getId(), userDTO.getId());
}
if (request.getEmail() != null) {
Assertions.assertEquals(request.getEmail(), userDTO.getEmail());
}
if (request.getUsername() != null) {
Assertions.assertEquals(request.getUsername(), userDTO.getName());
}
if (request.getPhone() != null) {
Assertions.assertEquals(request.getPhone(), userDTO.getPhone());
}
}
@Test
@Order(2)
void testPersonalUpdatePassword() throws Exception {
PersonalUpdatePasswordRequest request = new PersonalUpdatePasswordRequest();
request.setId(loginUser);
request.setOldPassword(CodingUtils.md5("metersphere"));
request.setNewPassword(CodingUtils.md5("metersphere222"));
this.requestPostWithOk(PersonalRequestUtils.URL_PERSONAL_UPDATE_PASSWORD, request);
UserExample example = new UserExample();
example.createCriteria().andIdEqualTo(loginUser).andPasswordEqualTo(CodingUtils.md5("metersphere222"));
Assertions.assertEquals(userMapper.countByExample(example), 1);
//修改回去
request = new PersonalUpdatePasswordRequest();
request.setId(loginUser);
request.setOldPassword(CodingUtils.md5("metersphere222"));
request.setNewPassword(CodingUtils.md5("metersphere"));
this.requestPostWithOk(PersonalRequestUtils.URL_PERSONAL_UPDATE_PASSWORD, request);
example.clear();
example.createCriteria().andIdEqualTo(loginUser).andPasswordEqualTo(CodingUtils.md5("metersphere"));
Assertions.assertEquals(userMapper.countByExample(example), 1L);
//密码错误
request = new PersonalUpdatePasswordRequest();
request.setId(loginUser);
request.setOldPassword(CodingUtils.md5("metersphere222"));
request.setNewPassword(CodingUtils.md5("metersphere"));
this.requestPost(PersonalRequestUtils.URL_PERSONAL_UPDATE_PASSWORD, request).andExpect(status().is5xxServerError());
//参数校验
request = new PersonalUpdatePasswordRequest();
request.setOldPassword(CodingUtils.md5("metersphere222"));
request.setNewPassword(CodingUtils.md5("metersphere"));
this.requestPost(PersonalRequestUtils.URL_PERSONAL_UPDATE_PASSWORD, request).andExpect(status().isBadRequest());
request = new PersonalUpdatePasswordRequest();
request.setId(loginUser);
request.setNewPassword(CodingUtils.md5("metersphere"));
this.requestPost(PersonalRequestUtils.URL_PERSONAL_UPDATE_PASSWORD, request).andExpect(status().isBadRequest());
request = new PersonalUpdatePasswordRequest();
request.setId(loginUser);
request.setOldPassword(CodingUtils.md5("metersphere222"));
this.requestPost(PersonalRequestUtils.URL_PERSONAL_UPDATE_PASSWORD, request).andExpect(status().isBadRequest());
//修改非当前人
request = new PersonalUpdatePasswordRequest();
request.setId(IDGenerator.nextStr());
request.setOldPassword(CodingUtils.md5("metersphere"));
request.setNewPassword(CodingUtils.md5("metersphere333"));
this.requestPost(PersonalRequestUtils.URL_PERSONAL_UPDATE_PASSWORD, request).andExpect(status().is5xxServerError());
//权限校验
request = new PersonalUpdatePasswordRequest();
request.setId(loginUser);
request.setOldPassword(CodingUtils.md5("metersphere222"));
request.setNewPassword(CodingUtils.md5("metersphere"));
this.requestPostPermissionTest(PermissionConstants.SYSTEM_PERSONAL_READ_UPDATE, PersonalRequestUtils.URL_PERSONAL_UPDATE_PASSWORD, request);
//最后检查密码是否回归原密码
example.clear();
example.createCriteria().andIdEqualTo(loginUser).andPasswordEqualTo(CodingUtils.md5("metersphere"));
Assertions.assertEquals(userMapper.countByExample(example), 1);
}
}

View File

@ -2,7 +2,10 @@ package io.metersphere.system.controller.user;
import io.metersphere.project.domain.Project;
import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.sdk.util.*;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.CodingUtils;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.RsaUtils;
import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.domain.User;
@ -14,7 +17,13 @@ import io.metersphere.system.dto.UserCreateInfo;
import io.metersphere.system.dto.excel.UserExcelRowDTO;
import io.metersphere.system.dto.request.UserInviteRequest;
import io.metersphere.system.dto.request.UserRegisterRequest;
import io.metersphere.system.dto.request.user.UserChangeEnableRequest;
import io.metersphere.system.dto.request.user.UserEditRequest;
import io.metersphere.system.dto.request.user.UserRoleBatchRelationRequest;
import io.metersphere.system.dto.response.UserImportResponse;
import io.metersphere.system.dto.response.UserInviteResponse;
import io.metersphere.system.dto.response.UserSelectOption;
import io.metersphere.system.dto.response.UserTableResponse;
import io.metersphere.system.dto.sdk.BasePageRequest;
import io.metersphere.system.dto.sdk.BaseTreeNode;
import io.metersphere.system.dto.sdk.ExcelParseDTO;
@ -25,12 +34,6 @@ import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.mapper.UserInviteMapper;
import io.metersphere.system.mapper.UserMapper;
import io.metersphere.system.mapper.UserRoleRelationMapper;
import io.metersphere.system.dto.request.user.UserChangeEnableRequest;
import io.metersphere.system.dto.request.user.UserEditRequest;
import io.metersphere.system.dto.request.user.UserRoleBatchRelationRequest;
import io.metersphere.system.dto.response.UserImportResponse;
import io.metersphere.system.dto.response.UserSelectOption;
import io.metersphere.system.dto.response.UserTableResponse;
import io.metersphere.system.service.GlobalUserRoleRelationService;
import io.metersphere.system.service.UserService;
import io.metersphere.system.service.UserToolService;

View File

@ -0,0 +1,9 @@
package io.metersphere.system.utils.user;
public class PersonalRequestUtils {
//用户管理URL
public static final String URL_PERSONAL_GET = "/personal/get/%s";
public static final String URL_PERSONAL_UPDATE_INFO = "/personal/update-info";
public static final String URL_PERSONAL_UPDATE_PASSWORD = "/personal/update-password";
}