mirror of
https://github.com/PowerJob/PowerJob.git
synced 2025-07-17 00:00:04 +08:00
fix: [auth] Extracting PwjbUserInfo to resolve user contamination
This commit is contained in:
parent
c350607762
commit
6539c66226
@ -3,6 +3,7 @@ package tech.powerjob.common.serialize;
|
|||||||
import com.fasterxml.jackson.core.JsonParser;
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
import com.fasterxml.jackson.databind.MapperFeature;
|
import com.fasterxml.jackson.databind.MapperFeature;
|
||||||
import com.fasterxml.jackson.databind.json.JsonMapper;
|
import com.fasterxml.jackson.databind.json.JsonMapper;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -28,6 +29,7 @@ public class JsonUtils {
|
|||||||
.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true)
|
.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true)
|
||||||
.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true)
|
.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true)
|
||||||
.configure(JsonParser.Feature.IGNORE_UNDEFINED, true)
|
.configure(JsonParser.Feature.IGNORE_UNDEFINED, true)
|
||||||
|
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
private static final TypeReference<Map<String, Object>> MAP_TYPE_REFERENCE = new TypeReference<Map<String, Object>> () {};
|
private static final TypeReference<Map<String, Object>> MAP_TYPE_REFERENCE = new TypeReference<Map<String, Object>> () {};
|
||||||
|
@ -8,6 +8,26 @@ package tech.powerjob.server.auth.common;
|
|||||||
*/
|
*/
|
||||||
public class AuthConstants {
|
public class AuthConstants {
|
||||||
|
|
||||||
|
/* ********** 账号体系唯一标识,推荐开发者接入第三方登录体系时也使用4位编码,便于前端统一做样式 ********** */
|
||||||
|
/**
|
||||||
|
* PowerJob自建账号体系
|
||||||
|
*/
|
||||||
|
public static final String ACCOUNT_TYPE_POWER_JOB = "PWJB";
|
||||||
|
/**
|
||||||
|
* 钉钉
|
||||||
|
*/
|
||||||
|
public static final String ACCOUNT_TYPE_DING = "DING";
|
||||||
|
/**
|
||||||
|
* 企业微信(预留,蹲一个 contributor)
|
||||||
|
*/
|
||||||
|
public static final String ACCOUNT_TYPE_WX = "QYWX";
|
||||||
|
/**
|
||||||
|
* 飞书(预留,蹲一个 contributor +1)
|
||||||
|
*/
|
||||||
|
public static final String ACCOUNT_LARK = "LARK";
|
||||||
|
|
||||||
|
/* ********** 账号体系 ********** */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JWT key
|
* JWT key
|
||||||
* 前端 header 默认首字母大写,保持一致方便处理
|
* 前端 header 默认首字母大写,保持一致方便处理
|
||||||
|
@ -22,7 +22,9 @@ public enum AuthErrorCode {
|
|||||||
/**
|
/**
|
||||||
* 无效请求,一般是参数问题
|
* 无效请求,一般是参数问题
|
||||||
*/
|
*/
|
||||||
INVALID_REQUEST("-300", "INVALID_REQUEST")
|
INVALID_REQUEST("-300", "INVALID_REQUEST"),
|
||||||
|
|
||||||
|
INCORRECT_PASSWORD("-400", "INCORRECT_PASSWORD")
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -31,6 +31,10 @@ public class ThirdPartyUser {
|
|||||||
* 邮箱地址
|
* 邮箱地址
|
||||||
*/
|
*/
|
||||||
private String email;
|
private String email;
|
||||||
|
/**
|
||||||
|
* web 回调地址
|
||||||
|
*/
|
||||||
|
private String webHook;
|
||||||
/**
|
/**
|
||||||
* 扩展字段
|
* 扩展字段
|
||||||
*/
|
*/
|
||||||
|
@ -11,6 +11,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import tech.powerjob.common.exception.PowerJobException;
|
import tech.powerjob.common.exception.PowerJobException;
|
||||||
|
import tech.powerjob.server.auth.common.AuthConstants;
|
||||||
import tech.powerjob.server.auth.login.*;
|
import tech.powerjob.server.auth.login.*;
|
||||||
import tech.powerjob.server.common.Loggers;
|
import tech.powerjob.server.common.Loggers;
|
||||||
|
|
||||||
@ -56,13 +57,11 @@ public class DingTalkLoginService implements ThirdPartyLoginService {
|
|||||||
@Value("${oms.auth.dingtalk.callbackUrl:#{null}}")
|
@Value("${oms.auth.dingtalk.callbackUrl:#{null}}")
|
||||||
private String dingTalkCallbackUrl;
|
private String dingTalkCallbackUrl;
|
||||||
|
|
||||||
private static final String DING_TALK = "DingTalk";
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LoginTypeInfo loginType() {
|
public LoginTypeInfo loginType() {
|
||||||
return new LoginTypeInfo()
|
return new LoginTypeInfo()
|
||||||
.setType(DING_TALK)
|
.setType(AuthConstants.ACCOUNT_TYPE_DING)
|
||||||
.setName("钉钉登录")
|
.setName("DingTalkLogin")
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +78,7 @@ public class DingTalkLoginService implements ThirdPartyLoginService {
|
|||||||
"&response_type=code" +
|
"&response_type=code" +
|
||||||
"&client_id=" + dingTalkAppKey +
|
"&client_id=" + dingTalkAppKey +
|
||||||
"&scope=openid" +
|
"&scope=openid" +
|
||||||
"&state=" + DING_TALK +
|
"&state=" + AuthConstants.ACCOUNT_TYPE_DING +
|
||||||
"&prompt=consent";
|
"&prompt=consent";
|
||||||
Loggers.WEB.info("[DingTalkBizLoginService] login url: {}", url);
|
Loggers.WEB.info("[DingTalkBizLoginService] login url: {}", url);
|
||||||
return url;
|
return url;
|
||||||
|
@ -14,8 +14,8 @@ import tech.powerjob.server.auth.login.ThirdPartyLoginService;
|
|||||||
import tech.powerjob.server.auth.login.ThirdPartyUser;
|
import tech.powerjob.server.auth.login.ThirdPartyUser;
|
||||||
import tech.powerjob.server.common.Loggers;
|
import tech.powerjob.server.common.Loggers;
|
||||||
import tech.powerjob.server.common.utils.DigestUtils;
|
import tech.powerjob.server.common.utils.DigestUtils;
|
||||||
import tech.powerjob.server.persistence.remote.model.UserInfoDO;
|
import tech.powerjob.server.persistence.remote.model.PwjbUserInfoDO;
|
||||||
import tech.powerjob.server.persistence.remote.repository.UserInfoRepository;
|
import tech.powerjob.server.persistence.remote.repository.PwjbUserInfoRepository;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
@ -33,9 +33,7 @@ import java.util.Optional;
|
|||||||
public class PowerJobThirdPartyLoginService implements ThirdPartyLoginService {
|
public class PowerJobThirdPartyLoginService implements ThirdPartyLoginService {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private UserInfoRepository userInfoRepository;
|
private PwjbUserInfoRepository pwjbUserInfoRepository;
|
||||||
|
|
||||||
private static final String POWER_JOB_LOGIN_SERVICE = "PowerJob";
|
|
||||||
|
|
||||||
private static final String KEY_USERNAME = "username";
|
private static final String KEY_USERNAME = "username";
|
||||||
private static final String KEY_PASSWORD = "password";
|
private static final String KEY_PASSWORD = "password";
|
||||||
@ -45,8 +43,8 @@ public class PowerJobThirdPartyLoginService implements ThirdPartyLoginService {
|
|||||||
@Override
|
@Override
|
||||||
public LoginTypeInfo loginType() {
|
public LoginTypeInfo loginType() {
|
||||||
return new LoginTypeInfo()
|
return new LoginTypeInfo()
|
||||||
.setType(POWER_JOB_LOGIN_SERVICE)
|
.setType(AuthConstants.ACCOUNT_TYPE_POWER_JOB)
|
||||||
.setName("PowerJob")
|
.setName("PowerJob Built-in Login")
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,17 +72,30 @@ public class PowerJobThirdPartyLoginService implements ThirdPartyLoginService {
|
|||||||
throw new PowerJobAuthException(AuthErrorCode.INVALID_REQUEST);
|
throw new PowerJobAuthException(AuthErrorCode.INVALID_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Optional<UserInfoDO> userInfoOpt = userInfoRepository.findByUsername(username);
|
final Optional<PwjbUserInfoDO> userInfoOpt = pwjbUserInfoRepository.findByUsername(username);
|
||||||
if (!userInfoOpt.isPresent()) {
|
if (!userInfoOpt.isPresent()) {
|
||||||
Loggers.WEB.debug("[PowerJobLoginService] can't find user by username: {}", username);
|
Loggers.WEB.debug("[PowerJobLoginService] can't find user by username: {}", username);
|
||||||
throw new PowerJobAuthException(AuthErrorCode.USER_NOT_EXIST);
|
throw new PowerJobAuthException(AuthErrorCode.USER_NOT_EXIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
final UserInfoDO dbUser = userInfoOpt.get();
|
final PwjbUserInfoDO dbUser = userInfoOpt.get();
|
||||||
|
|
||||||
if (DigestUtils.rePassword(password, username).equals(dbUser.getPassword())) {
|
if (DigestUtils.rePassword(password, username).equals(dbUser.getPassword())) {
|
||||||
ThirdPartyUser bizUser = new ThirdPartyUser();
|
ThirdPartyUser bizUser = new ThirdPartyUser();
|
||||||
bizUser.setUsername(username);
|
bizUser.setUsername(username);
|
||||||
|
|
||||||
|
// 回填第一次创建的信息
|
||||||
|
String extra = dbUser.getExtra();
|
||||||
|
if (StringUtils.isNotEmpty(extra)) {
|
||||||
|
ThirdPartyUser material = JsonUtils.parseObjectIgnoreException(extra, ThirdPartyUser.class);
|
||||||
|
if (material != null) {
|
||||||
|
bizUser.setEmail(material.getEmail());
|
||||||
|
bizUser.setNick(material.getNick());
|
||||||
|
bizUser.setPhone(material.getPhone());
|
||||||
|
bizUser.setWebHook(material.getWebHook());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return bizUser;
|
return bizUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import tech.powerjob.server.auth.LoginUserHolder;
|
||||||
import tech.powerjob.server.auth.PowerJobUser;
|
import tech.powerjob.server.auth.PowerJobUser;
|
||||||
import tech.powerjob.server.auth.common.AuthConstants;
|
import tech.powerjob.server.auth.common.AuthConstants;
|
||||||
import tech.powerjob.server.auth.common.AuthErrorCode;
|
import tech.powerjob.server.auth.common.AuthErrorCode;
|
||||||
@ -91,6 +92,16 @@ public class PowerJobLoginServiceImpl implements PowerJobLoginService {
|
|||||||
if (!powerJobUserOpt.isPresent()) {
|
if (!powerJobUserOpt.isPresent()) {
|
||||||
UserInfoDO newUser = new UserInfoDO();
|
UserInfoDO newUser = new UserInfoDO();
|
||||||
newUser.setUsername(dbUserName);
|
newUser.setUsername(dbUserName);
|
||||||
|
// 写入账号体系类型
|
||||||
|
newUser.setAccountType(loginType);
|
||||||
|
|
||||||
|
// 同步素材
|
||||||
|
newUser.setEmail(bizUser.getEmail());
|
||||||
|
newUser.setPhone(bizUser.getPhone());
|
||||||
|
newUser.setNick(bizUser.getNick());
|
||||||
|
newUser.setWebHook(bizUser.getWebHook());
|
||||||
|
newUser.setExtra(bizUser.getExtra());
|
||||||
|
|
||||||
Loggers.WEB.info("[PowerJobLoginService] sync user to PowerJobUserSystem: {}", dbUserName);
|
Loggers.WEB.info("[PowerJobLoginService] sync user to PowerJobUserSystem: {}", dbUserName);
|
||||||
userInfoRepository.saveAndFlush(newUser);
|
userInfoRepository.saveAndFlush(newUser);
|
||||||
|
|
||||||
@ -117,6 +128,10 @@ public class PowerJobLoginServiceImpl implements PowerJobLoginService {
|
|||||||
return userNameOpt.flatMap(uname -> userInfoRepository.findByUsername(uname).map(userInfoDO -> {
|
return userNameOpt.flatMap(uname -> userInfoRepository.findByUsername(uname).map(userInfoDO -> {
|
||||||
PowerJobUser powerJobUser = new PowerJobUser();
|
PowerJobUser powerJobUser = new PowerJobUser();
|
||||||
BeanUtils.copyProperties(userInfoDO, powerJobUser);
|
BeanUtils.copyProperties(userInfoDO, powerJobUser);
|
||||||
|
|
||||||
|
// 兼容某些直接通过 ifLogin 判断登录的场景
|
||||||
|
LoginUserHolder.set(powerJobUser);
|
||||||
|
|
||||||
return powerJobUser;
|
return powerJobUser;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,13 @@
|
|||||||
package tech.powerjob.server.core.service;
|
package tech.powerjob.server.core.service;
|
||||||
|
|
||||||
import tech.powerjob.common.utils.CommonUtils;
|
|
||||||
import tech.powerjob.server.common.utils.DigestUtils;
|
|
||||||
import tech.powerjob.server.persistence.remote.model.UserInfoDO;
|
|
||||||
import tech.powerjob.server.persistence.remote.repository.UserInfoRepository;
|
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import tech.powerjob.server.persistence.remote.model.UserInfoDO;
|
||||||
|
import tech.powerjob.server.persistence.remote.repository.UserInfoRepository;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@ -27,26 +24,6 @@ public class UserService {
|
|||||||
@Resource
|
@Resource
|
||||||
private UserInfoRepository userInfoRepository;
|
private UserInfoRepository userInfoRepository;
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存/修改 用户
|
|
||||||
* @param userInfoDO user
|
|
||||||
*/
|
|
||||||
public void save(UserInfoDO userInfoDO) {
|
|
||||||
|
|
||||||
CommonUtils.requireNonNull(userInfoDO.getUsername(), "userName can't be null or empty!");
|
|
||||||
|
|
||||||
userInfoDO.setGmtCreate(new Date());
|
|
||||||
userInfoDO.setGmtModified(userInfoDO.getGmtCreate());
|
|
||||||
|
|
||||||
// 二次加密密码
|
|
||||||
final String password = userInfoDO.getPassword();
|
|
||||||
if (StringUtils.isNotEmpty(password)) {
|
|
||||||
userInfoDO.setPassword(DigestUtils.rePassword(password, userInfoDO.getUsername()));
|
|
||||||
}
|
|
||||||
|
|
||||||
userInfoRepository.saveAndFlush(userInfoDO);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据用户ID字符串获取用户信息详细列表
|
* 根据用户ID字符串获取用户信息详细列表
|
||||||
* @param userIds 逗号分割的用户ID信息
|
* @param userIds 逗号分割的用户ID信息
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
package tech.powerjob.server.persistence.remote.model;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.hibernate.annotations.GenericGenerator;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PowerJob 自建登录体系的用户表,只存储使用 PowerJob 自带登录方式登录的用户信息
|
||||||
|
*
|
||||||
|
* @author tjq
|
||||||
|
* @since 2024/2/13
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Entity
|
||||||
|
@Table(uniqueConstraints = {
|
||||||
|
@UniqueConstraint(name = "uidx01_username", columnNames = {"username"})
|
||||||
|
})
|
||||||
|
public class PwjbUserInfoDO {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.AUTO, generator = "native")
|
||||||
|
@GenericGenerator(name = "native", strategy = "native")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
private String extra;
|
||||||
|
|
||||||
|
private Date gmtCreate;
|
||||||
|
|
||||||
|
private Date gmtModified;
|
||||||
|
}
|
@ -8,6 +8,7 @@ import java.util.Date;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户信息表
|
* 用户信息表
|
||||||
|
* PowerJob 自身维护的全部用户体系数据
|
||||||
* 5.0.0 可能不兼容改动:为了支持第三方登录,需要通过 username 与第三方登录系统做匹配,该列需要声明为唯一索引,确保全局唯一
|
* 5.0.0 可能不兼容改动:为了支持第三方登录,需要通过 username 与第三方登录系统做匹配,该列需要声明为唯一索引,确保全局唯一
|
||||||
*
|
*
|
||||||
* @author tjq
|
* @author tjq
|
||||||
@ -28,6 +29,11 @@ public class UserInfoDO {
|
|||||||
@GenericGenerator(name = "native", strategy = "native")
|
@GenericGenerator(name = "native", strategy = "native")
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 账号类型
|
||||||
|
*/
|
||||||
|
private String accountType;
|
||||||
|
|
||||||
private String username;
|
private String username;
|
||||||
/**
|
/**
|
||||||
* since 5.0.0
|
* since 5.0.0
|
||||||
|
@ -8,6 +8,7 @@ import org.springframework.data.jpa.repository.Query;
|
|||||||
import org.springframework.data.repository.query.Param;
|
import org.springframework.data.repository.query.Param;
|
||||||
import tech.powerjob.server.persistence.remote.model.AppInfoDO;
|
import tech.powerjob.server.persistence.remote.model.AppInfoDO;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@ -34,4 +35,6 @@ public interface AppInfoRepository extends JpaRepository<AppInfoDO, Long>, JpaSp
|
|||||||
|
|
||||||
List<AppInfoDO> findAllByNamespaceId(Long namespaceId);
|
List<AppInfoDO> findAllByNamespaceId(Long namespaceId);
|
||||||
|
|
||||||
|
|
||||||
|
List<AppInfoDO> findAllByIdIn(Collection<Long> ids);
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ import org.springframework.data.jpa.repository.JpaRepository;
|
|||||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||||
import tech.powerjob.server.persistence.remote.model.NamespaceDO;
|
import tech.powerjob.server.persistence.remote.model.NamespaceDO;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -15,4 +17,6 @@ import java.util.Optional;
|
|||||||
public interface NamespaceRepository extends JpaRepository<NamespaceDO, Long>, JpaSpecificationExecutor<NamespaceDO> {
|
public interface NamespaceRepository extends JpaRepository<NamespaceDO, Long>, JpaSpecificationExecutor<NamespaceDO> {
|
||||||
|
|
||||||
Optional<NamespaceDO> findByCode(String code);
|
Optional<NamespaceDO> findByCode(String code);
|
||||||
|
|
||||||
|
List<NamespaceDO> findAllByIdIn(Collection<Long> ids);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
package tech.powerjob.server.persistence.remote.repository;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import tech.powerjob.server.persistence.remote.model.PwjbUserInfoDO;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PwjbUserInfoRepository
|
||||||
|
*
|
||||||
|
* @author tjq
|
||||||
|
* @since 2024/2/13
|
||||||
|
*/
|
||||||
|
public interface PwjbUserInfoRepository extends JpaRepository<PwjbUserInfoDO, Long> {
|
||||||
|
|
||||||
|
Optional<PwjbUserInfoDO> findByUsername(String username);
|
||||||
|
}
|
@ -1,10 +1,12 @@
|
|||||||
package tech.powerjob.server.auth.service;
|
package tech.powerjob.server.auth.service;
|
||||||
|
|
||||||
import tech.powerjob.server.auth.Permission;
|
import tech.powerjob.server.auth.Permission;
|
||||||
|
import tech.powerjob.server.auth.Role;
|
||||||
import tech.powerjob.server.auth.RoleScope;
|
import tech.powerjob.server.auth.RoleScope;
|
||||||
import tech.powerjob.server.web.request.ComponentUserRoleInfo;
|
import tech.powerjob.server.web.request.ComponentUserRoleInfo;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Web Auth 服务
|
* Web Auth 服务
|
||||||
@ -41,5 +43,5 @@ public interface WebAuthService {
|
|||||||
*/
|
*/
|
||||||
boolean hasPermission(RoleScope roleScope, Long target, Permission permission);
|
boolean hasPermission(RoleScope roleScope, Long target, Permission permission);
|
||||||
|
|
||||||
Set<Long> fetchMyPermissionTargets(RoleScope roleScope);
|
Map<Role, List<Long>> fetchMyPermissionTargets(RoleScope roleScope);
|
||||||
}
|
}
|
||||||
|
@ -62,20 +62,15 @@ public class WebAuthServiceImpl implements WebAuthService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Long> fetchMyPermissionTargets(RoleScope roleScope) {
|
public Map<Role, List<Long>> fetchMyPermissionTargets(RoleScope roleScope) {
|
||||||
|
|
||||||
PowerJobUser powerJobUser = LoginUserHolder.get();
|
PowerJobUser powerJobUser = LoginUserHolder.get();
|
||||||
if (powerJobUser == null) {
|
if (powerJobUser == null) {
|
||||||
throw new PowerJobAuthException(AuthErrorCode.USER_NOT_LOGIN);
|
throw new PowerJobAuthException(AuthErrorCode.USER_NOT_LOGIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<Role, List<Long>> role2TargetIds = powerJobPermissionService.fetchUserHadPermissionTargets(roleScope, powerJobUser.getId());
|
|
||||||
|
|
||||||
Set<Long> targetIds = Sets.newHashSet();
|
|
||||||
role2TargetIds.values().forEach(targetIds::addAll);
|
|
||||||
|
|
||||||
// 展示不考虑穿透权限的问题(即拥有 namespace 权限也可以看到全部的 apps)
|
// 展示不考虑穿透权限的问题(即拥有 namespace 权限也可以看到全部的 apps)
|
||||||
return targetIds;
|
return powerJobPermissionService.fetchUserHadPermissionTargets(roleScope, powerJobUser.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void diffGrant(RoleScope roleScope, Long target, Role role, List<Long> uids, Map<Role, List<Long>> originRole2Uids) {
|
private void diffGrant(RoleScope roleScope, Long target, Role role, List<Long> uids, Map<Role, List<Long>> originRole2Uids) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package tech.powerjob.server.web.controller;
|
package tech.powerjob.server.web.controller;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@ -109,7 +110,9 @@ public class AppInfoController {
|
|||||||
Set<Long> queryAppIds;
|
Set<Long> queryAppIds;
|
||||||
Boolean showMyRelated = queryAppInfoRequest.getShowMyRelated();
|
Boolean showMyRelated = queryAppInfoRequest.getShowMyRelated();
|
||||||
if (BooleanUtils.isTrue(showMyRelated)) {
|
if (BooleanUtils.isTrue(showMyRelated)) {
|
||||||
queryAppIds = webAuthService.fetchMyPermissionTargets(RoleScope.APP);
|
Set<Long> targetIds = Sets.newHashSet();
|
||||||
|
webAuthService.fetchMyPermissionTargets(RoleScope.APP).values().forEach(targetIds::addAll);
|
||||||
|
queryAppIds = targetIds;
|
||||||
} else {
|
} else {
|
||||||
queryAppIds = Collections.emptySet();
|
queryAppIds = Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,97 @@
|
|||||||
|
package tech.powerjob.server.web.controller;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import tech.powerjob.common.response.ResultDTO;
|
||||||
|
import tech.powerjob.common.serialize.JsonUtils;
|
||||||
|
import tech.powerjob.common.utils.CommonUtils;
|
||||||
|
import tech.powerjob.server.auth.common.AuthErrorCode;
|
||||||
|
import tech.powerjob.server.auth.common.PowerJobAuthException;
|
||||||
|
import tech.powerjob.server.common.utils.DigestUtils;
|
||||||
|
import tech.powerjob.server.persistence.remote.model.PwjbUserInfoDO;
|
||||||
|
import tech.powerjob.server.persistence.remote.repository.PwjbUserInfoRepository;
|
||||||
|
import tech.powerjob.server.web.request.ChangePasswordRequest;
|
||||||
|
import tech.powerjob.server.web.request.ModifyUserInfoRequest;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PowerJob 自带的登录体系
|
||||||
|
* (同样视为第三方服务,与主框架没有任何关系)
|
||||||
|
*
|
||||||
|
* @author tjq
|
||||||
|
* @since 2024/2/13
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/pwjbUser")
|
||||||
|
public class PwjbUserInfoController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private PwjbUserInfoRepository pwjbUserInfoRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建第三方登录体系(PowerJob) 的账户,不允许修改
|
||||||
|
* @param request 请求(此处复用了主框架请求,便于用户一次性把所有参数都填入)
|
||||||
|
* @return 创建结果
|
||||||
|
*/
|
||||||
|
@PostMapping("/create")
|
||||||
|
public ResultDTO<Void> save(@RequestBody ModifyUserInfoRequest request) {
|
||||||
|
|
||||||
|
String username = request.getUsername();
|
||||||
|
CommonUtils.requireNonNull(username, "userName can't be null or empty!");
|
||||||
|
Optional<PwjbUserInfoDO> oldUserOpt = pwjbUserInfoRepository.findByUsername(username);
|
||||||
|
if (oldUserOpt.isPresent()) {
|
||||||
|
throw new IllegalArgumentException("username already exist, please change one!");
|
||||||
|
}
|
||||||
|
|
||||||
|
PwjbUserInfoDO pwjbUserInfoDO = new PwjbUserInfoDO();
|
||||||
|
|
||||||
|
pwjbUserInfoDO.setUsername(username);
|
||||||
|
pwjbUserInfoDO.setGmtCreate(new Date());
|
||||||
|
pwjbUserInfoDO.setGmtModified(new Date());
|
||||||
|
|
||||||
|
// 二次加密密码
|
||||||
|
final String password = pwjbUserInfoDO.getPassword();
|
||||||
|
if (StringUtils.isNotEmpty(password)) {
|
||||||
|
pwjbUserInfoDO.setPassword(DigestUtils.rePassword(password, pwjbUserInfoDO.getUsername()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其他参数存入 extra,在回调创建真正的内部 USER 时回填
|
||||||
|
request.setPassword(null);
|
||||||
|
pwjbUserInfoDO.setExtra(JsonUtils.toJSONString(request));
|
||||||
|
|
||||||
|
pwjbUserInfoRepository.save(pwjbUserInfoDO);
|
||||||
|
return ResultDTO.success(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/changePassword")
|
||||||
|
public ResultDTO<Void> changePassword(@RequestBody ChangePasswordRequest changePasswordRequest) {
|
||||||
|
|
||||||
|
if (StringUtils.equals(changePasswordRequest.getNewPassword(), changePasswordRequest.getNewPassword2())) {
|
||||||
|
throw new IllegalArgumentException("Inconsistent passwords");
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<PwjbUserInfoDO> userOpt = pwjbUserInfoRepository.findById(changePasswordRequest.getUserId());
|
||||||
|
if (!userOpt.isPresent()) {
|
||||||
|
throw new IllegalArgumentException("can't find user by userId: " + changePasswordRequest.getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
PwjbUserInfoDO dbUser = userOpt.get();
|
||||||
|
String oldPasswordInDb = dbUser.getPassword();
|
||||||
|
String oldPasswordInReq = DigestUtils.rePassword(changePasswordRequest.getOldPassword(), dbUser.getUsername());
|
||||||
|
if (!StringUtils.equals(oldPasswordInDb, oldPasswordInReq)) {
|
||||||
|
throw new PowerJobAuthException(AuthErrorCode.INCORRECT_PASSWORD);
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUser.setPassword(DigestUtils.rePassword(changePasswordRequest.getNewPassword(), dbUser.getUsername()));
|
||||||
|
dbUser.setGmtModified(new Date());
|
||||||
|
pwjbUserInfoRepository.saveAndFlush(dbUser);
|
||||||
|
|
||||||
|
return ResultDTO.success(null);
|
||||||
|
}
|
||||||
|
}
|
@ -1,20 +1,44 @@
|
|||||||
package tech.powerjob.server.web.controller;
|
package tech.powerjob.server.web.controller;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import tech.powerjob.common.response.ResultDTO;
|
import tech.powerjob.common.response.ResultDTO;
|
||||||
|
import tech.powerjob.common.serialize.JsonUtils;
|
||||||
|
import tech.powerjob.server.auth.PowerJobUser;
|
||||||
|
import tech.powerjob.server.auth.Role;
|
||||||
|
import tech.powerjob.server.auth.RoleScope;
|
||||||
|
import tech.powerjob.server.auth.common.AuthErrorCode;
|
||||||
|
import tech.powerjob.server.auth.common.PowerJobAuthException;
|
||||||
|
import tech.powerjob.server.auth.service.WebAuthService;
|
||||||
|
import tech.powerjob.server.auth.service.login.PowerJobLoginService;
|
||||||
import tech.powerjob.server.core.service.UserService;
|
import tech.powerjob.server.core.service.UserService;
|
||||||
|
import tech.powerjob.server.persistence.remote.model.AppInfoDO;
|
||||||
|
import tech.powerjob.server.persistence.remote.model.NamespaceDO;
|
||||||
import tech.powerjob.server.persistence.remote.model.UserInfoDO;
|
import tech.powerjob.server.persistence.remote.model.UserInfoDO;
|
||||||
|
import tech.powerjob.server.persistence.remote.repository.AppInfoRepository;
|
||||||
|
import tech.powerjob.server.persistence.remote.repository.NamespaceRepository;
|
||||||
import tech.powerjob.server.persistence.remote.repository.UserInfoRepository;
|
import tech.powerjob.server.persistence.remote.repository.UserInfoRepository;
|
||||||
|
import tech.powerjob.server.web.converter.NamespaceConverter;
|
||||||
import tech.powerjob.server.web.converter.UserConverter;
|
import tech.powerjob.server.web.converter.UserConverter;
|
||||||
import tech.powerjob.server.web.request.ModifyUserInfoRequest;
|
import tech.powerjob.server.web.response.AppBaseVO;
|
||||||
|
import tech.powerjob.server.web.response.NamespaceBaseVO;
|
||||||
import tech.powerjob.server.web.response.UserBaseVO;
|
import tech.powerjob.server.web.response.UserBaseVO;
|
||||||
|
import tech.powerjob.server.web.response.UserDetailVO;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,16 +54,16 @@ public class UserInfoController {
|
|||||||
private UserService userService;
|
private UserService userService;
|
||||||
@Resource
|
@Resource
|
||||||
private UserInfoRepository userInfoRepository;
|
private UserInfoRepository userInfoRepository;
|
||||||
|
@Resource
|
||||||
|
private PowerJobLoginService powerJobLoginService;
|
||||||
|
@Resource
|
||||||
|
private WebAuthService webAuthService;
|
||||||
|
@Resource
|
||||||
|
private NamespaceRepository namespaceRepository;
|
||||||
|
@Resource
|
||||||
|
private AppInfoRepository appInfoRepository;
|
||||||
|
|
||||||
@PostMapping("save")
|
@GetMapping("/list")
|
||||||
public ResultDTO<Void> save(@RequestBody ModifyUserInfoRequest request) {
|
|
||||||
UserInfoDO userInfoDO = new UserInfoDO();
|
|
||||||
BeanUtils.copyProperties(request, userInfoDO);
|
|
||||||
userService.save(userInfoDO);
|
|
||||||
return ResultDTO.success(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("list")
|
|
||||||
public ResultDTO<List<UserBaseVO>> list(@RequestParam(required = false) String name) {
|
public ResultDTO<List<UserBaseVO>> list(@RequestParam(required = false) String name) {
|
||||||
|
|
||||||
List<UserInfoDO> result;
|
List<UserInfoDO> result;
|
||||||
@ -51,10 +75,76 @@ public class UserInfoController {
|
|||||||
return ResultDTO.success(convert(result));
|
return ResultDTO.success(convert(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/detail")
|
||||||
|
public ResultDTO<UserDetailVO> getUserDetail(HttpServletRequest httpServletRequest) {
|
||||||
|
Optional<PowerJobUser> powerJobUserOpt = powerJobLoginService.ifLogin(httpServletRequest);
|
||||||
|
if (!powerJobUserOpt.isPresent()) {
|
||||||
|
throw new PowerJobAuthException(AuthErrorCode.USER_NOT_LOGIN);
|
||||||
|
}
|
||||||
|
Optional<UserInfoDO> userinfoDoOpt = userInfoRepository.findById(powerJobUserOpt.get().getId());
|
||||||
|
if (!userinfoDoOpt.isPresent()) {
|
||||||
|
throw new IllegalArgumentException("can't find user by id: " + powerJobUserOpt.get().getId());
|
||||||
|
}
|
||||||
|
UserDetailVO userDetailVO = new UserDetailVO();
|
||||||
|
BeanUtils.copyProperties(userinfoDoOpt.get(), userDetailVO);
|
||||||
|
|
||||||
|
// 权限信息
|
||||||
|
Map<Role, List<Long>> globalPermissions = webAuthService.fetchMyPermissionTargets(RoleScope.GLOBAL);
|
||||||
|
userDetailVO.setGlobalRoles(globalPermissions.keySet().stream().map(Enum::name).collect(Collectors.toList()));
|
||||||
|
|
||||||
|
Map<Role, List<Long>> namespacePermissions = webAuthService.fetchMyPermissionTargets(RoleScope.NAMESPACE);
|
||||||
|
List<NamespaceDO> nsList = namespaceRepository.findAllByIdIn(mergeIds(namespacePermissions));
|
||||||
|
Map<Long, NamespaceDO> id2NamespaceDo = Maps.newHashMap();
|
||||||
|
nsList.forEach(x -> id2NamespaceDo.put(x.getId(), x));
|
||||||
|
Map<String, List<NamespaceBaseVO>> role2NamespaceBaseVo = Maps.newHashMap();
|
||||||
|
namespacePermissions.forEach((k, v) -> {
|
||||||
|
List<NamespaceBaseVO> namespaceBaseVOS = Lists.newArrayList();
|
||||||
|
role2NamespaceBaseVo.put(k.name(), namespaceBaseVOS);
|
||||||
|
v.forEach(nId -> {
|
||||||
|
NamespaceDO namespaceDO = id2NamespaceDo.get(nId);
|
||||||
|
if (namespaceDO == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NamespaceBaseVO namespaceBaseVO = JsonUtils.parseObjectIgnoreException(JsonUtils.toJSONString(NamespaceConverter.do2BaseVo(namespaceDO)), NamespaceBaseVO.class);
|
||||||
|
namespaceBaseVO.genFrontName();
|
||||||
|
namespaceBaseVOS.add(namespaceBaseVO);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
userDetailVO.setRole2NamespaceList(role2NamespaceBaseVo);
|
||||||
|
|
||||||
|
Map<Role, List<Long>> appPermissions = webAuthService.fetchMyPermissionTargets(RoleScope.APP);
|
||||||
|
List<AppInfoDO> appList = appInfoRepository.findAllByIdIn(mergeIds(appPermissions));
|
||||||
|
Map<Long, AppInfoDO> id2AppInfo = Maps.newHashMap();
|
||||||
|
appList.forEach(x -> id2AppInfo.put(x.getId(), x));
|
||||||
|
Map<String, List<AppBaseVO>> role2AppBaseVo = Maps.newHashMap();
|
||||||
|
appPermissions.forEach((k, v) -> {
|
||||||
|
List<AppBaseVO> appBaseVOS = Lists.newArrayList();
|
||||||
|
role2AppBaseVo.put(k.name(), appBaseVOS);
|
||||||
|
v.forEach(nId -> {
|
||||||
|
AppInfoDO appInfoDO = id2AppInfo.get(nId);
|
||||||
|
if (appInfoDO == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
AppBaseVO appBaseVO = new AppBaseVO();
|
||||||
|
BeanUtils.copyProperties(appInfoDO, appBaseVO);
|
||||||
|
appBaseVOS.add(appBaseVO);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
userDetailVO.setRole2AppList(role2AppBaseVo);
|
||||||
|
|
||||||
|
return ResultDTO.success(userDetailVO);
|
||||||
|
}
|
||||||
|
|
||||||
private static List<UserBaseVO> convert(List<UserInfoDO> data) {
|
private static List<UserBaseVO> convert(List<UserInfoDO> data) {
|
||||||
if (CollectionUtils.isEmpty(data)) {
|
if (CollectionUtils.isEmpty(data)) {
|
||||||
return Lists.newLinkedList();
|
return Lists.newLinkedList();
|
||||||
}
|
}
|
||||||
return data.stream().map(UserConverter::do2BaseVo).collect(Collectors.toList());
|
return data.stream().map(UserConverter::do2BaseVo).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Set<Long> mergeIds(Map<?, List<Long>> map) {
|
||||||
|
Set<Long> ids = Sets.newHashSet();
|
||||||
|
map.values().forEach(ids::addAll);
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
package tech.powerjob.server.web.request;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改密码
|
||||||
|
*
|
||||||
|
* @author tjq
|
||||||
|
* @since 2024/2/13
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ChangePasswordRequest implements Serializable {
|
||||||
|
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
private String oldPassword;
|
||||||
|
|
||||||
|
private String newPassword;
|
||||||
|
|
||||||
|
private String newPassword2;
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package tech.powerjob.server.web.response;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AppBaseVO
|
||||||
|
*
|
||||||
|
* @author tjq
|
||||||
|
* @since 2024/2/13
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class AppBaseVO implements Serializable {
|
||||||
|
|
||||||
|
protected Long id;
|
||||||
|
|
||||||
|
protected String appName;
|
||||||
|
|
||||||
|
protected Long namespaceId;
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*/
|
||||||
|
protected String title;
|
||||||
|
}
|
@ -1,9 +1,10 @@
|
|||||||
package tech.powerjob.server.web.response;
|
package tech.powerjob.server.web.response;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
import tech.powerjob.server.web.request.ComponentUserRoleInfo;
|
import tech.powerjob.server.web.request.ComponentUserRoleInfo;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -12,19 +13,10 @@ import java.util.Date;
|
|||||||
* @author tjq
|
* @author tjq
|
||||||
* @since 2024/2/12
|
* @since 2024/2/12
|
||||||
*/
|
*/
|
||||||
@Data
|
@Getter
|
||||||
public class AppInfoVO implements Serializable {
|
@Setter
|
||||||
|
@ToString
|
||||||
private Long id;
|
public class AppInfoVO extends AppBaseVO {
|
||||||
|
|
||||||
private String appName;
|
|
||||||
|
|
||||||
private Long namespaceId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 描述
|
|
||||||
*/
|
|
||||||
private String title;
|
|
||||||
|
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ import lombok.Setter;
|
|||||||
@Setter
|
@Setter
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class UserBaseVO {
|
public class UserBaseVO {
|
||||||
private Long id;
|
protected Long id;
|
||||||
private String username;
|
protected String username;
|
||||||
private String nick;
|
protected String nick;
|
||||||
}
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
package tech.powerjob.server.web.response;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户详细信息
|
||||||
|
*
|
||||||
|
* @author tjq
|
||||||
|
* @since 2024/2/13
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
public class UserDetailVO extends UserBaseVO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 账户类型
|
||||||
|
*/
|
||||||
|
private String accountType;
|
||||||
|
/**
|
||||||
|
* 密码
|
||||||
|
*/
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号
|
||||||
|
*/
|
||||||
|
private String phone;
|
||||||
|
/**
|
||||||
|
* 邮箱地址
|
||||||
|
*/
|
||||||
|
private String email;
|
||||||
|
/**
|
||||||
|
* webHook
|
||||||
|
*/
|
||||||
|
private String webHook;
|
||||||
|
/**
|
||||||
|
* 扩展字段
|
||||||
|
*/
|
||||||
|
private String extra;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拥有的全局权限
|
||||||
|
*/
|
||||||
|
private List<String> globalRoles;
|
||||||
|
/**
|
||||||
|
* 拥有的 namespace 权限
|
||||||
|
*/
|
||||||
|
private Map<String, List<NamespaceBaseVO>> role2NamespaceList;
|
||||||
|
/**
|
||||||
|
* 拥有的 app 权限
|
||||||
|
*/
|
||||||
|
private Map<String, List<AppBaseVO>> role2AppList;
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user