first commit

This commit is contained in:
starrySky
2024-03-20 09:28:04 +08:00
commit 989f0210f2
286 changed files with 25129 additions and 0 deletions

73
play-admin/pom.xml Normal file
View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.starry</groupId>
<artifactId>play-with</artifactId>
<version>1.0</version>
</parent>
<artifactId>play-admin</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!--引入springboot-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--通用模块-->
<dependency>
<groupId>com.starry</groupId>
<artifactId>play-common</artifactId>
<version>1.0</version>
</dependency>
<!--代码生成模块-->
<dependency>
<groupId>com.starry</groupId>
<artifactId>play-generator</artifactId>
<version>1.0</version>
</dependency>
<!--JWT(Json Web Token)登录支持-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- easyexcel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
</dependency>
<!-- SpringBoot AOP 拦截器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.starry</groupId>
<artifactId>play-weichat</artifactId>
<version>1.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,18 @@
package com.starry.admin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
/**
* @author admin
*/
@SpringBootApplication
@ComponentScan("com.starry")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@@ -0,0 +1,146 @@
package com.starry.admin.common.aspect;
import cn.hutool.core.convert.Convert;
import com.starry.admin.common.domain.LoginUser;
import com.starry.admin.modules.system.entity.SysRoleEntity;
import com.starry.admin.modules.system.entity.SysUserEntity;
import com.starry.admin.utils.SecurityUtils;
import com.starry.common.annotation.DataScope;
import com.starry.common.context.SecurityContextHolder;
import com.starry.common.domain.BaseEntity;
import com.starry.common.utils.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
* 数据过滤处理
*
* @author vctgo
*/
@Aspect
@Component
public class DataScopeAspect {
/**
* 全部数据权限
*/
public static final String DATA_SCOPE_ALL = "1";
/**
* 自定数据权限
*/
public static final String DATA_SCOPE_CUSTOM = "2";
/**
* 部门数据权限
*/
public static final String DATA_SCOPE_DEPT = "3";
/**
* 部门及以下数据权限
*/
public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";
/**
* 仅本人数据权限
*/
public static final String DATA_SCOPE_SELF = "5";
/**
* 数据权限过滤关键字
*/
public static final String DATA_SCOPE = "dataScope";
/**
* 数据范围过滤
*
* @param joinPoint 切点
* @param user 用户
* @param deptAlias 部门别名
* @param userAlias 用户别名
* @param permission 权限字符
*/
public static void dataScopeFilter(JoinPoint joinPoint, SysUserEntity user, String deptAlias, String userAlias, String permission) {
StringBuilder sqlString = new StringBuilder();
List<String> conditions = new ArrayList<>();
for (SysRoleEntity role : user.getRoles()) {
String dataScope = role.getDataScope();
if (!DATA_SCOPE_CUSTOM.equals(dataScope) && conditions.contains(dataScope)) {
continue;
}
if (StringUtils.isNotEmpty(permission) && StringUtils.isNotEmpty(role.getPermissions())
&& !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission))) {
continue;
}
if (DATA_SCOPE_ALL.equals(dataScope)) {
sqlString = new StringBuilder();
break;
} else if (DATA_SCOPE_CUSTOM.equals(dataScope)) {
sqlString.append(StringUtils.format(
" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias,
role.getRoleId()));
} else if (DATA_SCOPE_DEPT.equals(dataScope)) {
sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId()));
} else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) {
sqlString.append(StringUtils.format(
" OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",
deptAlias, user.getDeptId(), user.getDeptId()));
} else if (DATA_SCOPE_SELF.equals(dataScope)) {
if (StringUtils.isNotBlank(userAlias)) {
sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId()));
} else {
// 数据权限为仅本人且没有userAlias别名不查询任何数据
sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
}
}
conditions.add(dataScope);
}
if (StringUtils.isNotBlank(sqlString.toString())) {
Object params = joinPoint.getArgs()[0];
if (StringUtils.isNotNull(params) && params instanceof BaseEntity) {
BaseEntity baseEntity = (BaseEntity) params;
baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
}
}
}
@Before("@annotation(controllerDataScope)")
public void doBefore(JoinPoint point, DataScope controllerDataScope) {
clearDataScope(point);
handleDataScope(point, controllerDataScope);
}
protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope) {
if (controllerDataScope == null) {
return;
}
// 获取当前的用户
LoginUser loginUser = SecurityUtils.getLoginUser();
if (StringUtils.isNotNull(loginUser)) {
SysUserEntity currentUser = loginUser.getUser();
// 如果是超级管理员,则不过滤数据
if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) {
String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), SecurityContextHolder.getPermission());
dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
controllerDataScope.userAlias(), permission);
}
}
}
/**
* 拼接权限sql前先清空params.dataScope参数防止注入
*/
private void clearDataScope(final JoinPoint joinPoint) {
Object params = joinPoint.getArgs()[0];
if (StringUtils.isNotNull(params) && params instanceof BaseEntity) {
BaseEntity baseEntity = (BaseEntity) params;
baseEntity.getParams().put(DATA_SCOPE, "");
}
}
}

View File

@@ -0,0 +1,168 @@
package com.starry.admin.common.aspect;
import cn.hutool.extra.servlet.ServletUtil;
import com.alibaba.fastjson2.JSON;
import com.starry.admin.common.domain.LoginUser;
import com.starry.admin.modules.system.entity.SysOperationLogEntity;
import com.starry.admin.modules.system.service.ISysOperationLogService;
import com.starry.admin.utils.SecurityUtils;
import com.starry.common.annotation.Log;
import com.starry.common.utils.ServletUtils;
import com.starry.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.HandlerMapping;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
/**
* @author admin
*/
@Aspect
@Component
@Slf4j
public class LogAspect {
@Resource
private ISysOperationLogService operLogService;
/**
* 处理完请求后执行
*
* @param joinPoint 切点
*/
@AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")
public void doAfterReturn(JoinPoint joinPoint, Log controllerLog, Object jsonResult) {
handleLog(joinPoint, controllerLog, jsonResult);
}
protected void handleLog(final JoinPoint joinPoint, Log controllerLog, Object jsonResult) {
try {
// 获取当前的用户
LoginUser loginUser = SecurityUtils.getLoginUser();
// 日志记录
SysOperationLogEntity operLog = new SysOperationLogEntity();
operLog.setStatus(0);
// 请求的IP地址
String iP = ServletUtil.getClientIP(ServletUtils.getRequest());
if ("0:0:0:0:0:0:0:1".equals(iP)) {
iP = "127.0.0.1";
}
operLog.setOperIp(iP);
operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
if (loginUser != null) {
operLog.setOperName(loginUser.getUsername());
}
if (null != null) {
operLog.setStatus(1);
operLog.setErrorMsg(StringUtils.substring(((Exception) null).getMessage(), 0, 2000));
}
// 设置方法名称
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
operLog.setMethod(className + "." + methodName + "()");
operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
operLog.setOperTime(new Date());
// 处理设置注解上的参数
getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);
// 保存数据库
operLogService.save(operLog);
} catch (Exception exp) {
log.error("异常信息:{}", exp.getMessage());
}
}
/**
* 获取注解中对方法的描述信息 用于Controller层注解
*
* @param log 日志
* @param operLog 操作日志
*/
public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperationLogEntity operLog, Object jsonResult) {
// 设置操作业务类型
operLog.setBusinessType(log.businessType().ordinal());
// 设置标题
operLog.setTitle(log.title());
// 是否需要保存request参数和值
if (log.isSaveRequestData()) {
// 设置参数的信息
setRequestValue(joinPoint, operLog);
}
// 是否需要保存response参数和值
if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult)) {
operLog.setJsonResult(StringUtils.substring(JSON.toJSONString(jsonResult), 0, 2000));
}
}
/**
* 获取请求的参数放到log中
*
* @param operLog 操作日志
*/
private void setRequestValue(JoinPoint joinPoint, SysOperationLogEntity operLog) {
String requsetMethod = operLog.getRequestMethod();
if (HttpMethod.PUT.name().equals(requsetMethod) || HttpMethod.POST.name().equals(requsetMethod)) {
String params = argsArrayToString(joinPoint.getArgs());
operLog.setOperParam(StringUtils.substring(params, 0, 2000));
} else {
Map<?, ?> paramsMap = (Map<?, ?>) ServletUtils.getRequest().getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
operLog.setOperParam(StringUtils.substring(paramsMap.toString(), 0, 2000));
}
}
/**
* 参数拼装
*/
private String argsArrayToString(Object[] paramsArray) {
StringBuilder params = new StringBuilder();
if (paramsArray != null) {
for (Object object : paramsArray) {
// 不为空 并且是不需要过滤的 对象
if (StringUtils.isNotNull(object) && !isFilterObject(object)) {
Object jsonObj = JSON.toJSON(object);
params.append(jsonObj.toString()).append(" ");
}
}
}
return params.toString().trim();
}
/**
* 判断是否需要过滤的对象。
*
* @param object 对象信息。
* @return 如果是需要过滤的对象则返回true否则返回false。
*/
@SuppressWarnings("rawtypes")
public boolean isFilterObject(final Object object) {
Class<?> clazz = object.getClass();
if (clazz.isArray()) {
return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
} else if (Collection.class.isAssignableFrom(clazz)) {
Collection collection = (Collection) object;
for (Object value : collection) {
return value instanceof MultipartFile;
}
} else if (Map.class.isAssignableFrom(clazz)) {
Map map = (Map) object;
for (Object value : map.entrySet()) {
Map.Entry entry = (Map.Entry) value;
return entry.getValue() instanceof MultipartFile;
}
}
return object instanceof MultipartFile || object instanceof HttpServletRequest || object instanceof HttpServletResponse || object instanceof BindingResult;
}
}

View File

@@ -0,0 +1,338 @@
package com.starry.admin.common.component;
import cn.hutool.core.util.IdUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.starry.admin.common.domain.LoginUser;
import com.starry.admin.common.security.entity.JwtUser;
import com.starry.common.constant.CacheConstants;
import com.starry.common.constant.Constants;
import com.starry.common.constant.SecurityConstants;
import com.starry.common.redis.RedisCache;
import com.starry.common.utils.ServletUtils;
import com.starry.common.utils.StringUtils;
import com.starry.common.utils.ip.AddressUtils;
import com.starry.common.utils.ip.IpUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* @author admin
* token 组件
* @since 2021/9/6
*/
@Slf4j
@Component
public class JwtToken {
private static final String CLAIM_KEY_USERNAME = "sub";
private static final String CLAIM_KEY_CREATED = "created";
private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expiration}")
private Long expire;
@Value("${jwt.tokenHeader}")
private String tokenHeader;
@Value("${jwt.tokenHead}")
private String tokenHead;
@Resource
private RedisCache redisCache;
/**
* 从token中获取登录用户名
*/
public String getUserNameFromToken(String token) {
String username;
try {
Claims claims = getClaimsFromToken(token);
username = claims.getSubject();
} catch (Exception e) {
username = null;
}
return username;
}
/**
* 校验token
*/
public boolean validateToken(String token, UserDetails userDetails) {
String username = getUserNameFromToken(token);
return username.equals(userDetails.getUsername()) && !isTokenExpired(token);
}
/**
* 根据用户信息生成token
*/
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
claims.put(CLAIM_KEY_USERNAME, userDetails.getUsername());
claims.put(CLAIM_KEY_CREATED, new Date());
return generateToken(claims);
}
/**
* 创建令牌
*
* @param jwtUser 用户信息
* @return 令牌
*/
public String createToken(JwtUser jwtUser) {
String token = IdUtil.fastSimpleUUID();
jwtUser.setToken(token);
setUserAgent(jwtUser);
refresToken(jwtUser);
Map<String, Object> claims = new HashMap<>();
claims.put(Constants.LOGIN_USER_KEY, token);
return createToken(claims);
}
/**
* 从数据声明生成令牌
*
* @param claims 数据声明
* @return 令牌
*/
private String createToken(Map<String, Object> claims) {
String token = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512, secret).compact();
return token;
}
/**
* 判断token是否已经失效
*/
private boolean isTokenExpired(String token) {
Date expiredDate = getClaimsFromToken(token).getExpiration();
return expiredDate.before(new Date());
}
private String generateToken(Map<String, Object> claims) {
return Jwts.builder().setClaims(claims).setExpiration(generateExpirationDate())
// 签名算法
.signWith(SignatureAlgorithm.HS512, secret).compact();
}
/**
* 生成token的过期时间
*/
private Date generateExpirationDate() {
return new Date(System.currentTimeMillis() + expire * 1000);
}
/**
* 从令牌中获取数据声明
*
* @param token 令牌
* @return 数据声明
*/
private Claims getClaimsFromToken(String token) {
Claims claims = null;
try {
claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
} catch (Exception e) {
log.info("JWT格式验证失败:{}", token);
}
return claims;
}
/**
* 设置用户代理信息
*
* @param jwtUser 登录信息
*/
public void setUserAgent(JwtUser jwtUser) {
UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent"));
String ip = ServletUtil.getClientIP(ServletUtils.getRequest());
jwtUser.setIpaddr(ip);
jwtUser.setLoginLocation(AddressUtils.getRealAddressByIp(ip));
jwtUser.setBrowser(userAgent.getBrowser().getName());
jwtUser.setOs(userAgent.getOs().getName());
}
public void refresToken(JwtUser jwtUser) {
jwtUser.setLoginTime(System.currentTimeMillis());
jwtUser.setExpireTime(jwtUser.getLoginTime() + expire * 1000);
String userKey = getTokenKey(jwtUser.getToken());
redisCache.setCacheObject(userKey, jwtUser, expire, TimeUnit.SECONDS);
}
private String getTokenKey(String uuid) {
return CacheConstants.LOGIN_TOKEN_KEY + uuid;
}
/**
* 获取登录用户身份信息
*
* @return 用户信息
*/
public JwtUser getLoginUser(HttpServletRequest request) {
String token = getToken(request);
if (StringUtils.isNotEmpty(token)) {
try {
Claims claims = getClaimsFromToken(token);
String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
String userKey = getTokenKey(uuid);
JwtUser user = redisCache.getCacheObject(userKey);
return user;
} catch (Exception e) {
}
}
return null;
}
/**
* 获取请求token
*
* @param request
* @return token
*/
private String getToken(HttpServletRequest request) {
// 获取请求头
String token = request.getHeader(tokenHeader);
if (StringUtils.isNotEmpty(token) && token.startsWith(tokenHead)) {
token = token.replace(tokenHead, "");
}
return token;
}
/**
* 验证令牌有效期相差不足20分钟自动刷新缓存
*
* @param jwtUser
* @return 令牌
*/
public void verifyToken(JwtUser jwtUser) {
long expireTime = jwtUser.getExpireTime();
long currentTime = System.currentTimeMillis();
if (expireTime - currentTime <= MILLIS_MINUTE_TEN) {
refresToken(jwtUser);
}
}
/**
* 删除用户身份信息
*/
public void removeJwtUser(String token) {
if (StringUtils.isNotEmpty(token)) {
String userKey = getTokenKey(token);
redisCache.deleteObject(userKey);
}
}
/**
* 创建令牌
*/
public Map<String, Object> createToken(LoginUser loginUser) {
String token = IdUtil.fastSimpleUUID();
String userId = loginUser.getUser().getUserId();
String userName = loginUser.getUser().getUserCode();
String tenantId = loginUser.getUser().getTenantId();
Long deptId = loginUser.getUser().getDeptId();
loginUser.setToken(token);
loginUser.setUserId(userId);
loginUser.setUserName(userName);
loginUser.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest()));
// 添加地址信息
setUserAgent(loginUser);
refreshToken(loginUser);
// Jwt存储信息
Map<String, Object> claimsMap = new HashMap<>(8);
claimsMap.put(SecurityConstants.USER_KEY, token);
claimsMap.put(SecurityConstants.DETAILS_USER_ID, userId);
claimsMap.put(SecurityConstants.DETAILS_USERNAME, userName);
// 租户id
claimsMap.put(SecurityConstants.DETAILS_TENANT_ID, tenantId);
// 部门id
claimsMap.put(SecurityConstants.DETAILS_DEPT_ID, deptId);
// 接口返回信息
Map<String, Object> rspMap = new HashMap<>();
rspMap.put("token", this.createToken(claimsMap));
rspMap.put("expires_in", expire);
rspMap.put("tenant_id", tenantId);
rspMap.put("tokenHead", tokenHead);
return rspMap;
}
/**
* 设置用户代理信息
*
* @param loginUser 登录信息
*/
public void setUserAgent(LoginUser loginUser) {
UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent"));
String ip = ServletUtil.getClientIP(ServletUtils.getRequest());
loginUser.setIpaddr(ip);
loginUser.setLoginLocation(AddressUtils.getRealAddressByIp(ip));
loginUser.setBrowser(userAgent.getBrowser().getName());
loginUser.setOs(userAgent.getOs().getName());
}
/**
* 刷新令牌有效期
*
* @param loginUser 登录信息
*/
public void refreshToken(LoginUser loginUser) {
loginUser.setLoginTime(System.currentTimeMillis());
loginUser.setExpireTime(loginUser.getLoginTime() + expire * 1000);
// 根据uuid将loginUser缓存
String userKey = getTokenKey(loginUser.getToken());
redisCache.setCacheObject(userKey, loginUser, expire, TimeUnit.MINUTES);
}
/**
* 获取登录用户身份信息
*
* @return 用户信息
*/
public LoginUser getNewLoginUser(HttpServletRequest request) {
String token = getToken(request);
if (StringUtils.isNotEmpty(token)) {
try {
Claims claims = getClaimsFromToken(token);
String uuid = (String) claims.get(SecurityConstants.USER_KEY);
String userKey = getTokenKey(uuid);
LoginUser loginUser = redisCache.getCacheObject(userKey);
com.starry.common.context.SecurityContextHolder.set(SecurityConstants.DETAILS_TENANT_ID, loginUser.getUser().getTenantId());
com.starry.common.context.SecurityContextHolder.set(SecurityConstants.LOGIN_USER, loginUser);
return loginUser;
} catch (Exception e) {
}
}
return null;
}
/**
* 验证令牌有效期相差不足20分钟自动刷新缓存
*
* @param loginUser
* @return 令牌
*/
public void verifyToken(LoginUser loginUser) {
long expireTime = loginUser.getExpireTime();
long currentTime = System.currentTimeMillis();
if (expireTime - currentTime <= MILLIS_MINUTE_TEN) {
refreshToken(loginUser);
}
}
}

View File

@@ -0,0 +1,149 @@
package com.starry.admin.common.component;
import com.starry.admin.common.domain.LoginUser;
import com.starry.admin.modules.system.entity.SysRoleEntity;
import com.starry.admin.utils.SecurityUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.Set;
/**
* 自定义权限实现ss取自SpringSecurity首字母
*
* @author admin
*/
@Service("customSs")
public class PermissionService {
/**
* 所有权限标识
*/
private static final String ALL_PERMISSION = "*:*:*";
/**
* 管理员角色权限标识
*/
private static final String SUPER_ADMIN = "admin";
private static final String ROLE_DELIMETER = ",";
private static final String PERMISSION_DELIMETER = ",";
/**
* 验证用户是否具备某权限
*
* @param permission 权限字符串
* @return 用户是否具备某权限
*/
public boolean hasPermi(String permission) {
if (StringUtils.isEmpty(permission)) {
return false;
}
LoginUser loginUser = SecurityUtils.getLoginUser();
if (loginUser == null || CollectionUtils.isEmpty(loginUser.getPermissions())) {
return false;
}
return hasPermissions(loginUser.getPermissions(), permission);
}
/**
* 验证用户是否不具备某权限,与 hasPermi逻辑相反
*
* @param permission 权限字符串
* @return 用户是否不具备某权限
*/
public boolean lacksPermi(String permission) {
return hasPermi(permission) != true;
}
/**
* 验证用户是否具有以下任意一个权限
*
* @param permissions 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表
* @return 用户是否具有以下任意一个权限
*/
public boolean hasAnyPermi(String permissions) {
if (StringUtils.isEmpty(permissions)) {
return false;
}
LoginUser loginUser = SecurityUtils.getLoginUser();
if (loginUser == null || CollectionUtils.isEmpty(loginUser.getPermissions())) {
return false;
}
Set<String> authorities = loginUser.getPermissions();
for (String permission : permissions.split(PERMISSION_DELIMETER)) {
if (permission != null && hasPermissions(authorities, permission)) {
return true;
}
}
return false;
}
/**
* 判断用户是否拥有某个角色
*
* @param role 角色字符串
* @return 用户是否具备某角色
*/
public boolean hasRole(String role) {
if (StringUtils.isEmpty(role)) {
return false;
}
LoginUser loginUser = SecurityUtils.getLoginUser();
if (loginUser == null || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) {
return false;
}
for (SysRoleEntity sysRoleEntity : loginUser.getUser().getRoles()) {
String roleKey = sysRoleEntity.getRoleKey();
if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role))) {
return true;
}
}
return false;
}
/**
* 验证用户是否不具备某角色,与 isRole逻辑相反。
*
* @param role 角色名称
* @return 用户是否不具备某角色
*/
public boolean lacksRole(String role) {
return hasRole(role) != true;
}
/**
* 验证用户是否具有以下任意一个角色
*
* @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表
* @return 用户是否具有以下任意一个角色
*/
public boolean hasAnyRoles(String roles) {
if (StringUtils.isEmpty(roles)) {
return false;
}
LoginUser loginUser = SecurityUtils.getLoginUser();
if (loginUser == null || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) {
return false;
}
for (String role : roles.split(ROLE_DELIMETER)) {
if (hasRole(role)) {
return true;
}
}
return false;
}
/**
* 判断是否包含权限
*
* @param permissions 权限列表
* @param permission 权限字符串
* @return 用户是否具备某权限
*/
private boolean hasPermissions(Set<String> permissions, String permission) {
return permissions.contains(ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission));
}
}

View File

@@ -0,0 +1,133 @@
package com.starry.admin.common.domain;
import com.starry.admin.modules.system.entity.SysUserEntity;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.Date;
import java.util.Set;
/**
* @author admin
*/
@Data
public class LoginUser implements UserDetails {
private static final long serialVersionUID = 1L;
/**
* 用户唯一标识
*/
private String token;
/**
* 用户名id
*/
private String userId;
/**
* 用户名
*/
private String userName;
/**
* 登录时间
*/
private Long loginTime;
/**
* 过期时间
*/
private Long expireTime;
/**
* 登录IP地址
*/
private String ipaddr;
/**
* 登录地点
*/
private String loginLocation;
/**
* 浏览器类型
*/
private String browser;
/**
* 操作系统
*/
private String os;
/**
* 权限列表
*/
private Set<String> permissions;
/**
* 角色列表
*/
private Set<String> roles;
/**
* 用户信息
*/
private SysUserEntity user;
/**
* 租户租赁截止日期--dhr
*/
private Date tenantEndDate;
/**
* 租户状态
*/
private Integer tenantStatus;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
@Override
public String getPassword() {
return user.getPassWord();
}
@Override
public String getUsername() {
return user.getUserCode();
}
/**
* 账户是否未过期
**/
@Override
public boolean isAccountNonExpired() {
return true;
}
/**
* 账户是否未锁定
**/
@Override
public boolean isAccountNonLocked() {
return true;
}
/**
* 密码是否未过期
**/
@Override
public boolean isCredentialsNonExpired() {
return true;
}
/**
* 账户是否激活
**/
@Override
public boolean isEnabled() {
return user.getStatus() == 0;
}
}

View File

@@ -0,0 +1,46 @@
package com.starry.admin.common.domain;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.starry.admin.modules.system.entity.SysDeptEntity;
import com.starry.admin.modules.system.entity.SysMenuEntity;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author Treeselect树结构实体类
* @since 2022/7/4
*/
@Data
public class TreeSelect implements Serializable {
/**
* 节点ID
*/
private Long id;
/**
* 节点名称
*/
private String label;
/**
* 子节点
*/
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private List<TreeSelect> children;
public TreeSelect(SysMenuEntity menu) {
this.id = menu.getMenuId();
this.label = menu.getMenuName();
this.children = menu.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
}
public TreeSelect(SysDeptEntity dept) {
this.id = dept.getDeptId();
this.label = dept.getDeptName();
this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,10 @@
package com.starry.admin.common.exception;
/**
* 自定义异常处理器 * * @author admin
*/
public class CustomException extends RuntimeException {
public CustomException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,63 @@
package com.starry.admin.common.exception;
/**
* @author 业务异常
* @since 2023/3/9
*/
public class ServiceException extends RuntimeException {
private static final long serialVersionUID = 1L;
/**
* 错误码
*/
private Integer code;
/**
* 错误提示
*/
private String message;
/**
* 错误明细,内部调试错误
*/
private String detailMessage;
/**
* 空构造方法,避免反序列化问题
*/
public ServiceException() {
}
public ServiceException(String message) {
this.message = message;
}
public ServiceException(String message, Integer code) {
this.message = message;
this.code = code;
}
public String getDetailMessage() {
return detailMessage;
}
public ServiceException setDetailMessage(String detailMessage) {
this.detailMessage = detailMessage;
return this;
}
@Override
public String getMessage() {
return message;
}
public ServiceException setMessage(String message) {
this.message = message;
return this;
}
public Integer getCode() {
return code;
}
}

View File

@@ -0,0 +1,71 @@
package com.starry.admin.common.exception.handler;
import com.starry.admin.common.exception.CustomException;
import com.starry.admin.common.exception.ServiceException;
import com.starry.common.result.R;
import com.starry.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
/**
* @author 全局异常处理
* @since 2023/3/9
*/
@RestControllerAdvice
public class GlobalExceptionHandler {
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
* 业务异常
*/
@ExceptionHandler(ServiceException.class)
public R handleServiceException(ServiceException e, HttpServletRequest request) {
log.error(e.getMessage(), e);
Integer code = e.getCode();
return StringUtils.isNotNull(code) ? R.error(code, e.getMessage()) : R.error(e.getMessage());
}
/**
* 拦截未知的运行时异常
*/
@ExceptionHandler(RuntimeException.class)
public R handleRuntimeException(RuntimeException e, HttpServletRequest request) {
String requestUrl = request.getRequestURI();
log.error("请求地址'{}',发生未知异常.", requestUrl, e);
return R.error("系统发生未知异常,请联系管理员");
}
/**
* 系统异常
*/
@ExceptionHandler(Exception.class)
public R handleException(Exception e, HttpServletRequest request) {
String requestUrl = request.getRequestURI();
log.error("请求地址'{}',发生系统异常.", requestUrl, e);
return R.error("系统出现内部错误,请联系管理员");
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public R methodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request) {
BindingResult bindingResult = e.getBindingResult();
StringBuilder errorMessageBuilder = new StringBuilder();
for (FieldError error : bindingResult.getFieldErrors()) {
errorMessageBuilder.append(error.getDefaultMessage());
}
return R.error("请求参数异常," + errorMessageBuilder);
}
@ExceptionHandler(CustomException.class)
public R customException(CustomException e, HttpServletRequest request) {
return R.error(e.getMessage());
}
}

View File

@@ -0,0 +1,79 @@
package com.starry.admin.common.mybatis.config;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import com.starry.admin.common.mybatis.handler.MyTenantLineHandler;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
/**
* @author admin
*/
@Configuration
@MapperScan("com.starry.**.mapper")
@EnableTransactionManagement
public class MybatisPlusConfig {
/**
* druid注入
*
* @return dataSource
*/
@Bean(name = "dataSource")
@ConfigurationProperties(prefix = "spring.datasource.druid")
public DataSource dataSource() {
return DruidDataSourceBuilder.create().build();
}
/**
* 配置事物管理器
*
* @return DataSourceTransactionManager
*/
@Bean(name = "transactionManager")
public DataSourceTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 租户插件
interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new MyTenantLineHandler()));
// 分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
// 乐观锁插件
interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor());
// 阻断插件
interceptor.addInnerInterceptor(blockAttackInnerInterceptor());
return interceptor;
}
/**
* 乐观锁
*/
@Bean
public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() {
return new OptimisticLockerInnerInterceptor();
}
/**
* 防止全表更新与删除
*/
@Bean
public BlockAttackInnerInterceptor blockAttackInnerInterceptor() {
return new BlockAttackInnerInterceptor();
}
}

View File

@@ -0,0 +1,45 @@
package com.starry.admin.common.mybatis.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.starry.admin.utils.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* @author admin
* 字段默认值处理类
* @since 2021/9/1
*/
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill ....");
this.setFieldValByName("createdTime", new Date(), metaObject);
this.setFieldValByName("deleted", false, metaObject);
this.setFieldValByName("version", 1L, metaObject);
Object createUser = this.getFieldValByName("createdBy", metaObject);
if (createUser == null) {
if (SecurityUtils.isLogin()) {
this.setFieldValByName("createdBy", SecurityUtils.getUserId(), metaObject);
}
}
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill ....");
this.setFieldValByName("updatedTime", new Date(), metaObject);
Object createUser = this.getFieldValByName("updatedBy", metaObject);
if (createUser == null) {
if (SecurityUtils.isLogin()) {
this.setFieldValByName("updatedBy", SecurityUtils.getUserId(), metaObject);
}
}
}
}

View File

@@ -0,0 +1,54 @@
package com.starry.admin.common.mybatis.handler;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.starry.admin.utils.SecurityUtils;
import com.starry.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.NullValue;
import org.springframework.stereotype.Component;
import java.util.Arrays;
/**
* @author admin
* 多租户处理器
* @since 2023/3/7
*/
@Slf4j
@Component
public class MyTenantLineHandler implements TenantLineHandler {
/**
* 排除过滤的表
*/
private static final String[] TABLE_FILTER = {"sys_menu", "sys_tenant_package", "sys_tenant", "sys_dict", "sys_dict_data"};
/**
* 排除过滤的表前缀
*/
private static final String[] TABLE_PRE = {"qrtz", "gen"};
@Override
public Expression getTenantId() {
// 取出当前请求的服务商ID通过解析器注入到SQL中。
Long tenantId = SecurityUtils.getTenantId();
if (tenantId == null) {
return new NullValue();
}
return new LongValue(tenantId);
}
/**
* 跳过不需要加多租户的表
*/
@Override
public boolean ignoreTable(String tableName) {
String prefix = StringUtils.substringBefore(tableName, "_");
if (Arrays.asList(TABLE_FILTER).contains(tableName) || Arrays.asList(TABLE_PRE).contains(prefix)) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,124 @@
package com.starry.admin.common.security.config;
import com.starry.admin.common.security.entity.JwtUser;
import com.starry.admin.common.security.filter.JwtAuthenticationTokenFilter;
import com.starry.admin.common.security.handler.CustomAccessDeniedHandler;
import com.starry.admin.common.security.handler.CustomAuthenticationEntryPoint;
import com.starry.admin.common.security.handler.CustomLogoutSuccessHandler;
import com.starry.admin.modules.system.entity.SysUserEntity;
import com.starry.admin.modules.system.service.SysMenuService;
import com.starry.admin.modules.system.service.SysUserService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.annotation.Resource;
import java.util.Set;
/**
* @author admin
*/
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
private CustomAccessDeniedHandler customAccessDeniedHandler;
@Resource
private CustomAuthenticationEntryPoint customAuthenticationEntryPoint;
@Resource
private SysUserService sysUserService;
@Resource
private SysMenuService menuService;
@Resource
private CustomLogoutSuccessHandler customLogoutSuccessHandler;
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable()// 由于使用的是JWT我们这里不需要csrf
.sessionManagement()// 基于token所以不需要session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
// 允许对于网站静态资源的无授权访问
.antMatchers(HttpMethod.GET,
"/",
"/*.html",
"/favicon.ico",
"/**/*.html",
"/**/*.css",
"/**/*.js",
"/swagger-resources/**",
"/v2/api-docs/**"
).permitAll()
// 对登录注册要允许匿名访问
.antMatchers("/login", "/captcha/get-captcha").permitAll()
// 跨域请求会先进行一次options请求
.antMatchers(HttpMethod.OPTIONS).permitAll()
.anyRequest()// 除上面外的所有请求全部需要鉴权认证
.authenticated();
// 禁用缓存
httpSecurity.headers().cacheControl();
// 添加Logout filter
httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(customLogoutSuccessHandler);
// 添加JWT filter
httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
// 添加自定义未授权和未登录结果返回
httpSecurity.exceptionHandling()
.accessDeniedHandler(customAccessDeniedHandler)
.authenticationEntryPoint(customAuthenticationEntryPoint);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService())
.passwordEncoder(passwordEncoder());
}
@Bean
@Override
public UserDetailsService userDetailsService() {
// 获取登录用户信息
return username -> {
SysUserEntity user = sysUserService.selectUserByUserName(username);
if (user != null) {
if (user.getStatus() == 1) {
throw new UsernameNotFoundException("对不起,您的账号:" + username + " 已停用");
}
// 获取菜单权限
Set<String> permissionList = menuService.selectMenuPermsByUserId(user.getUserId());
return new JwtUser(user, permissionList);
}
throw new UsernameNotFoundException("用户名或密码错误");
};
}
/**
* 装载BCrypt密码编码器
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/**
* JWT filter
*/
@Bean
public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() {
return new JwtAuthenticationTokenFilter();
}
}

View File

@@ -0,0 +1,202 @@
package com.starry.admin.common.security.entity;
import com.starry.admin.modules.system.entity.SysUserEntity;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.Set;
/**
* @author admin
*/
public class JwtUser implements UserDetails {
/**
* 用户ID
*/
private Long userId;
/**
* 登录时间
*/
private Long loginTime;
/**
* 用户唯一标识
*/
private String token;
/**
* 过期时间
*/
private Long expireTime;
/**
* 登录IP地址
*/
private String ipaddr;
/**
* 登录地点
*/
private String loginLocation;
/**
* 浏览器类型
*/
private String browser;
/**
* 操作系统
*/
private String os;
/**
* 用户信息
*/
private SysUserEntity user;
/**
* 权限列表
*/
private Set<String> permissions;
public JwtUser(SysUserEntity user, Set<String> permissions) {
this.user = user;
this.permissions = permissions;
}
public JwtUser(Long userId, SysUserEntity user, Set<String> permissions) {
this.userId = userId;
this.user = user;
this.permissions = permissions;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
@Override
public String getPassword() {
return user.getPassWord();
}
@Override
public String getUsername() {
return user.getUserCode();
}
/**
* 账户是否未过期
**/
@Override
public boolean isAccountNonExpired() {
return true;
}
/**
* 账户是否未锁定
**/
@Override
public boolean isAccountNonLocked() {
return true;
}
/**
* 密码是否未过期
**/
@Override
public boolean isCredentialsNonExpired() {
return true;
}
/**
* 账户是否激活
**/
@Override
public boolean isEnabled() {
return user.getStatus() == 0;
}
public Long getLoginTime() {
return loginTime;
}
public void setLoginTime(Long loginTime) {
this.loginTime = loginTime;
}
public Set<String> getPermissions() {
return permissions;
}
public void setPermissions(Set<String> permissions) {
this.permissions = permissions;
}
public SysUserEntity getUser() {
return user;
}
public void setUser(SysUserEntity user) {
this.user = user;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getIpaddr() {
return ipaddr;
}
public void setIpaddr(String ipaddr) {
this.ipaddr = ipaddr;
}
public String getLoginLocation() {
return loginLocation;
}
public void setLoginLocation(String loginLocation) {
this.loginLocation = loginLocation;
}
public String getBrowser() {
return browser;
}
public void setBrowser(String browser) {
this.browser = browser;
}
public String getOs() {
return os;
}
public void setOs(String os) {
this.os = os;
}
public Long getExpireTime() {
return expireTime;
}
public void setExpireTime(Long expireTime) {
this.expireTime = expireTime;
}
}

View File

@@ -0,0 +1,47 @@
package com.starry.admin.common.security.filter;
import com.starry.admin.common.component.JwtToken;
import com.starry.admin.common.domain.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author admin
* JWT登录授权过滤器
* @since 2021/9/6
*/
@Slf4j
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
@Value("${jwt.tokenHeader}")
private String tokenHeader;
@Value("${jwt.tokenHead}")
private String tokenHead;
@Resource
private JwtToken jwtToken;
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
LoginUser jwtUser = jwtToken.getNewLoginUser(httpServletRequest);
if (null != jwtUser && null == SecurityContextHolder.getContext().getAuthentication()) {
jwtToken.verifyToken(jwtUser);
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(jwtUser, null, jwtUser.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
}

View File

@@ -0,0 +1,30 @@
package com.starry.admin.common.security.handler;
import cn.hutool.json.JSONUtil;
import com.starry.common.result.R;
import com.starry.common.result.ResultCodeEnum;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author admin
* 当访问接口没有权限时,自定义的返回结果
* @since 2021/9/6
*/
@Component
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setContentType("application/json");
httpServletResponse.getWriter().println(JSONUtil.parse(R.error(ResultCodeEnum.FORBIDDEN.getCode(), ResultCodeEnum.FORBIDDEN.getMessage())));
httpServletResponse.getWriter().flush();
}
}

View File

@@ -0,0 +1,29 @@
package com.starry.admin.common.security.handler;
import cn.hutool.json.JSONUtil;
import com.starry.common.result.R;
import com.starry.common.result.ResultCodeEnum;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author admin
* 当未登录或者token失效访问接口时自定义的返回结果
* @since 2021/9/6
*/
@Component
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setContentType("application/json");
httpServletResponse.getWriter().println(JSONUtil.parse(R.error(ResultCodeEnum.UNAUTHORIZED.getCode(), ResultCodeEnum.UNAUTHORIZED.getMessage())));
httpServletResponse.getWriter().flush();
}
}

View File

@@ -0,0 +1,41 @@
package com.starry.admin.common.security.handler;
import com.alibaba.fastjson2.JSON;
import com.starry.admin.common.component.JwtToken;
import com.starry.admin.common.security.entity.JwtUser;
import com.starry.admin.manager.AsyncManager;
import com.starry.admin.manager.factory.AsyncFactory;
import com.starry.common.constant.Constants;
import com.starry.common.result.R;
import com.starry.common.utils.ServletUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author admin
* 自定义退出处理类 返回成功
* @since 2022/7/8
*/
@Component
public class CustomLogoutSuccessHandler implements LogoutSuccessHandler {
@Resource
private JwtToken jwtToken;
@Override
public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) {
JwtUser jwtUser = jwtToken.getLoginUser(httpServletRequest);
if (null != jwtUser) {
// 删除用户缓存记录
jwtToken.removeJwtUser(jwtUser.getToken());
// 记录用户退出日志
AsyncManager.me().execute(AsyncFactory.recordLoginLog(jwtUser.getUsername(), Constants.LOGOUT, "退出成功"));
}
ServletUtils.renderString(httpServletResponse, JSON.toJSONString(R.ok("退出成功")));
}
}

View File

@@ -0,0 +1,53 @@
package com.starry.admin.manager;
import com.starry.common.utils.SpringUtils;
import com.starry.common.utils.ThreadsUtils;
import java.util.TimerTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* @author admin
* 异步任务管理器
* @since 2022/7/25
*/
public class AsyncManager {
private static final AsyncManager me = new AsyncManager();
/**
* 操作延迟10毫秒
*/
private final int OPERATE_DELAY_TIME = 10;
/**
* 异步操作任务调度线程池
*/
private final ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");
/**
* 单例模式
*/
private AsyncManager() {
}
public static AsyncManager me() {
return me;
}
/**
* 执行任务
*
* @param task 任务
*/
public void execute(TimerTask task) {
executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
}
/**
* 停止任务线程池
*/
public void shutdown() {
ThreadsUtils.shutdownAndAwaitTermination(executor);
}
}

View File

@@ -0,0 +1,34 @@
package com.starry.admin.manager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.annotation.PreDestroy;
/**
* 确保应用退出时能关闭后台线程
*
* @author ruoyi
*/
@Component
public class ShutdownManager {
private static final Logger logger = LoggerFactory.getLogger("sys-user");
@PreDestroy
public void destroy() {
shutdownAsyncManager();
}
/**
* 停止异步执行任务
*/
private void shutdownAsyncManager() {
try {
logger.info("====关闭后台任务任务线程池====");
AsyncManager.me().shutdown();
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
}

View File

@@ -0,0 +1,67 @@
package com.starry.admin.manager.factory;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.starry.admin.modules.system.entity.SysLoginLogEntity;
import com.starry.admin.modules.system.service.ISysLoginLogService;
import com.starry.common.constant.Constants;
import com.starry.common.utils.ServletUtils;
import com.starry.common.utils.SpringUtils;
import com.starry.common.utils.ip.AddressUtils;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
import java.util.TimerTask;
/**
* @author admin
*/
@Slf4j
public class AsyncFactory {
/**
* 记录登录信息
*
* @param username 用户名
* @param status 状态
* @param message 消息
* @param args 列表
* @return 任务task
*/
public static TimerTask recordLoginLog(final String username, final String status, final String message, final Object... args) {
// 客户端操作系统、浏览器等信息
final UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent"));
// 请求的IP地址
final String ip = ServletUtil.getClientIP(ServletUtils.getRequest());
return new TimerTask() {
@Override
public void run() {
String address = AddressUtils.getRealAddressByIp(ip);
// 获取客户端操作系统
String os = userAgent.getOs().getName();
// 获取客户端浏览器
String browser = userAgent.getBrowser().getName();
// 封装对象
SysLoginLogEntity loginLog = new SysLoginLogEntity();
loginLog.setUserCode(username);
loginLog.setIpaddr(ip);
loginLog.setLoginLocation(address);
loginLog.setBrowser(browser);
loginLog.setOs(os);
loginLog.setMsg(message);
loginLog.setLoginTime(new Date());
// 日志状态
if (Constants.LOGIN_FAIL.equals(status)) {
loginLog.setStatus(Integer.valueOf(Constants.FAIL));
} else {
loginLog.setStatus(Integer.valueOf(Constants.SUCCESS));
}
// 插入数据
SpringUtils.getBean(ISysLoginLogService.class).create(loginLog);
}
};
}
}

View File

@@ -0,0 +1,101 @@
package com.starry.admin.modules.monitor.controller;
import com.starry.admin.modules.monitor.entity.Cache;
import com.starry.common.constant.CacheConstants;
import com.starry.common.result.R;
import com.starry.common.utils.StringUtils;
import org.springframework.data.redis.connection.RedisServerCommands;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.*;
/**
* @author huoqiang
* 缓存监控
* @since 2022/10/17
*/
@RestController
@RequestMapping("/monitor/cache")
public class CacheController {
private final static List<Cache> CACHES = new ArrayList<>();
@Resource
private RedisTemplate<String, String> redisTemplate;
{
CACHES.add(new Cache(CacheConstants.LOGIN_TOKEN_KEY, "用户信息"));
CACHES.add(new Cache(CacheConstants.SYS_DICT_KEY, "数据字典"));
CACHES.add(new Cache(CacheConstants.CAPTCHA_CODE_KEY, "验证码"));
}
@PreAuthorize("@customSs.hasPermi('monitor:cache:list')")
@GetMapping()
public R getInfo() throws Exception {
Properties info = (Properties) redisTemplate.execute((RedisCallback<Object>) RedisServerCommands::info);
Properties commandStats = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info("commandstats"));
Object dbSize = redisTemplate.execute((RedisCallback<Object>) RedisServerCommands::dbSize);
Map<String, Object> result = new HashMap<>(3);
result.put("info", info);
result.put("dbSize", dbSize);
List<Map<String, String>> pieList = new ArrayList<>();
commandStats.stringPropertyNames().forEach(key -> {
Map<String, String> data = new HashMap<>(2);
String property = commandStats.getProperty(key);
data.put("name", StringUtils.removeStart(key, "cmdstat_"));
data.put("value", StringUtils.substringBetween(property, "calls=", ",usec"));
pieList.add(data);
});
result.put("commandStats", pieList);
return R.ok(result);
}
@PreAuthorize("@customSs.hasPermi('monitor:cache:list')")
@GetMapping("/getNames")
public R cache() {
return R.ok(CACHES);
}
@PreAuthorize("@customSs.hasPermi('monitor:cache:list')")
@GetMapping("/getKeys/{cacheName}")
public R getCacheKeys(@PathVariable String cacheName) {
Set<String> cacheKeys = redisTemplate.keys(cacheName + "*");
return R.ok(cacheKeys);
}
@PreAuthorize("@customSs.hasPermi('monitor:cache:list')")
@GetMapping("/getValue/{cacheName}/{cacheKey}")
public R getCacheValue(@PathVariable String cacheName, @PathVariable String cacheKey) {
String cacheValue = redisTemplate.opsForValue().get(cacheKey);
Cache cache = new Cache(cacheName, cacheKey, cacheValue);
return R.ok(cache);
}
@PreAuthorize("@customSs.hasPermi('monitor:cache:list')")
@DeleteMapping("/clearCacheName/{cacheName}")
public R clearCacheName(@PathVariable String cacheName) {
Collection<String> cacheKeys = redisTemplate.keys(cacheName + "*");
redisTemplate.delete(cacheKeys);
return R.ok();
}
@PreAuthorize("@customSs.hasPermi('monitor:cache:list')")
@DeleteMapping("/clearCacheKey/{cacheKey}")
public R clearCacheKey(@PathVariable String cacheKey) {
redisTemplate.delete(cacheKey);
return R.ok();
}
@PreAuthorize("@customSs.hasPermi('monitor:cache:list')")
@DeleteMapping("/clearCacheAll")
public R clearCacheAll() {
Collection<String> cacheKeys = redisTemplate.keys("*");
redisTemplate.delete(cacheKeys);
return R.ok();
}
}

View File

@@ -0,0 +1,27 @@
package com.starry.admin.modules.monitor.controller;
import com.starry.admin.modules.monitor.entity.Server;
import com.starry.common.result.R;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author huoqiang
* 服务器监控
* @since 2022/10/17
*/
@RestController
@RequestMapping("/monitor/server")
public class ServerController {
@PreAuthorize("@customSs.hasPermi('monitor:server:list')")
@GetMapping()
public R getInfo() throws Exception {
Server server = new Server();
server.setServeInfo();
return R.ok(server);
}
}

View File

@@ -0,0 +1,76 @@
package com.starry.admin.modules.monitor.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.starry.admin.common.domain.LoginUser;
import com.starry.admin.modules.monitor.entity.UserOnline;
import com.starry.admin.modules.monitor.service.UserOnlineService;
import com.starry.common.annotation.Log;
import com.starry.common.constant.CacheConstants;
import com.starry.common.enums.BusinessType;
import com.starry.common.redis.RedisCache;
import com.starry.common.result.R;
import com.starry.common.utils.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* @author huoqiang
* 在线用户监控
* @since 2022/10/18
*/
@RestController
@RequestMapping("/monitor/online")
public class UserOnlineController {
@Resource
private RedisCache redisCache;
@Resource
private UserOnlineService userOnlineService;
@PreAuthorize("@customSs.hasPermi('monitor:online:list')")
@GetMapping("/list")
public R list(String ipaddr, String userName) {
Collection<String> keys = redisCache.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
List<UserOnline> userOnlineList = new ArrayList<>();
for (String key : keys) {
LoginUser user = redisCache.getCacheObject(key);
if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) {
if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername())) {
userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user));
}
} else if (StringUtils.isNotEmpty(ipaddr)) {
if (StringUtils.equals(ipaddr, user.getIpaddr())) {
userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user));
}
} else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser())) {
if (StringUtils.equals(userName, user.getUsername())) {
userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user));
}
} else {
userOnlineList.add(userOnlineService.setUserOnline(user));
}
}
IPage<UserOnline> page = new Page<>();
page.setRecords(userOnlineList);
page.setTotal(userOnlineList.size());
return R.ok(page);
}
/**
* 强退用户
*/
@PreAuthorize("@customSs.hasPermi('monitor:online:forceLogout')")
@Log(title = "在线用户", businessType = BusinessType.FORCE)
@DeleteMapping("/{tokenId}")
public R forceLogout(@PathVariable String tokenId) {
redisCache.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + tokenId);
return R.ok();
}
}

View File

@@ -0,0 +1,49 @@
package com.starry.admin.modules.monitor.entity;
import com.starry.common.utils.StringUtils;
import lombok.Data;
/**
* @author admin
* 缓存信息
* @since 2022/10/18
*/
@Data
public class Cache {
/**
* 缓存名称
*/
private String cacheName = "";
/**
* 缓存键名
*/
private String cacheKey = "";
/**
* 缓存内容
*/
private String cacheValue = "";
/**
* 备注
*/
private String remark = "";
public Cache() {
}
public Cache(String cacheName, String remark) {
this.cacheName = cacheName;
this.remark = remark;
}
public Cache(String cacheName, String cacheKey, String cacheValue) {
this.cacheName = StringUtils.replace(cacheName, ":", "");
this.cacheKey = StringUtils.replace(cacheKey, cacheName, "");
this.cacheValue = cacheValue;
}
}

View File

@@ -0,0 +1,91 @@
package com.starry.admin.modules.monitor.entity;
import com.starry.common.utils.Arith;
import lombok.Data;
/**
* @author admin
* cpu相关信息
* @since 2022/10/17
*/
@Data
public class Cpu {
/**
* 核心数
*/
private int cpuNum;
/**
* CPU总的使用率
*/
private double total;
/**
* CPU系统使用率
*/
private double sys;
/**
* CPU用户使用率
*/
private double used;
/**
* CPU当前等待率
*/
private double wait;
/**
* CPU当前空闲率
*/
private double free;
public int getCpuNum() {
return cpuNum;
}
public void setCpuNum(int cpuNum) {
this.cpuNum = cpuNum;
}
public double getTotal() {
return Arith.round(Arith.mul(total, 100), 2);
}
public void setTotal(double total) {
this.total = total;
}
public double getSys() {
return Arith.round(Arith.mul(sys / total, 100), 2);
}
public void setSys(double sys) {
this.sys = sys;
}
public double getUsed() {
return Arith.round(Arith.mul(used / total, 100), 2);
}
public void setUsed(double used) {
this.used = used;
}
public double getWait() {
return Arith.round(Arith.mul(wait / total, 100), 2);
}
public void setWait(double wait) {
this.wait = wait;
}
public double getFree() {
return Arith.round(Arith.mul(free / total, 100), 2);
}
public void setFree(double free) {
this.free = free;
}
}

View File

@@ -0,0 +1,117 @@
package com.starry.admin.modules.monitor.entity;
import cn.hutool.core.date.DateUtil;
import com.starry.common.utils.Arith;
import java.lang.management.ManagementFactory;
import java.util.Date;
/**
* @author admin
* 虚拟机相关信息
* @since 2022/10/17
*/
public class Jvm {
/**
* 当前JVM占用的内存总数(M)
*/
private double total;
/**
* JVM最大可用内存总数(M)
*/
private double max;
/**
* JVM空闲内存(M)
*/
private double free;
/**
* JDK版本
*/
private String version;
/**
* JDK路径
*/
private String home;
public double getTotal() {
return Arith.div(total, (1024 * 1024), 2);
}
public void setTotal(double total) {
this.total = total;
}
public double getMax() {
return Arith.div(max, (1024 * 1024), 2);
}
public void setMax(double max) {
this.max = max;
}
public double getFree() {
return Arith.div(free, (1024 * 1024), 2);
}
public void setFree(double free) {
this.free = free;
}
public double getUsed() {
return Arith.div(total - free, (1024 * 1024), 2);
}
public double getUsage() {
return Arith.mul(Arith.div(total - free, total, 4), 100);
}
/**
* 获取JDK名称
*/
public String getName() {
return ManagementFactory.getRuntimeMXBean().getVmName();
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getHome() {
return home;
}
public void setHome(String home) {
this.home = home;
}
/**
* JDK启动时间
*/
public String getStartTime() {
return DateUtil.format(new Date(ManagementFactory.getRuntimeMXBean().getStartTime()), "yyyy-MM-dd HH:mm:ss");
}
/**
* JDK运行时间
*/
public String getRunTime() {
return DateUtil.formatBetween(new Date(), new Date(ManagementFactory.getRuntimeMXBean().getStartTime()));
}
/**
* 运行参数
*/
public String getInputArgs() {
return ManagementFactory.getRuntimeMXBean().getInputArguments().toString();
}
}

View File

@@ -0,0 +1,56 @@
package com.starry.admin.modules.monitor.entity;
import com.starry.common.utils.Arith;
import lombok.Data;
/**
* @author admin
* 内存相关信息
* @since 2022/10/17
*/
@Data
public class Mem {
/**
* 内存总量
*/
private double total;
/**
* 已用内存
*/
private double used;
/**
* 剩余内存
*/
private double free;
public double getTotal() {
return Arith.div(total, (1024 * 1024 * 1024), 2);
}
public void setTotal(long total) {
this.total = total;
}
public double getUsed() {
return Arith.div(used, (1024 * 1024 * 1024), 2);
}
public void setUsed(long used) {
this.used = used;
}
public double getFree() {
return Arith.div(free, (1024 * 1024 * 1024), 2);
}
public void setFree(long free) {
this.free = free;
}
public double getUsage() {
return Arith.mul(Arith.div(used, total, 4), 100);
}
}

View File

@@ -0,0 +1,168 @@
package com.starry.admin.modules.monitor.entity;
import com.starry.common.utils.Arith;
import com.starry.common.utils.ip.IpUtils;
import lombok.Data;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.GlobalMemory;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.software.os.FileSystem;
import oshi.software.os.OSFileStore;
import oshi.software.os.OperatingSystem;
import oshi.util.Util;
import java.net.UnknownHostException;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
/**
* @author admin
* 服务器相关信息
* @since 2022/10/17
*/
@Data
public class Server {
/**
* CPU相关信息
*/
private Cpu cpu = new Cpu();
/**
* 內存相关信息
*/
private Mem mem = new Mem();
/**
* JVM相关信息
*/
private Jvm jvm = new Jvm();
/**
* 系统相关信息
*/
private Sys sys = new Sys();
/**
* 磁盘相关信息
*/
private List<SysFile> sysFiles = new LinkedList<>();
public void setServeInfo() throws Exception {
// 系统信息
SystemInfo si = new SystemInfo();
// 获取硬件抽象层
HardwareAbstractionLayer hal = si.getHardware();
setCpuInfo(hal.getProcessor());
setMemInfo(hal.getMemory());
setSysInfo();
setJvmInfo();
setSysFiles(si.getOperatingSystem());
}
/**
* 设置CPU信息
*/
private void setCpuInfo(CentralProcessor processor) {
// CPU信息
long[] prevTicks = processor.getSystemCpuLoadTicks();
Util.sleep(1000);
long[] ticks = processor.getSystemCpuLoadTicks();
long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
long cSys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()];
long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;
cpu.setCpuNum(processor.getLogicalProcessorCount());
cpu.setTotal(totalCpu);
cpu.setSys(cSys);
cpu.setUsed(user);
cpu.setWait(iowait);
cpu.setFree(idle);
}
/**
* 设置内存信息
*/
private void setMemInfo(GlobalMemory memory) {
mem.setTotal(memory.getTotal());
mem.setUsed(memory.getTotal() - memory.getAvailable());
mem.setFree(memory.getAvailable());
}
/**
* 设置服务器信息
*/
private void setSysInfo() {
Properties properties = System.getProperties();
sys.setComputerName(IpUtils.getHostName());
sys.setComputerIp(IpUtils.getHostIp());
sys.setOsName(properties.getProperty("os.name"));
sys.setOsArch(properties.getProperty("os.arch"));
sys.setUserDir(properties.getProperty("user.dir"));
}
/**
* 设置Java虚拟机
*/
private void setJvmInfo() throws UnknownHostException {
Properties props = System.getProperties();
jvm.setTotal(Runtime.getRuntime().totalMemory());
jvm.setMax(Runtime.getRuntime().maxMemory());
jvm.setFree(Runtime.getRuntime().freeMemory());
jvm.setVersion(props.getProperty("java.version"));
jvm.setHome(props.getProperty("java.home"));
}
/**
* 设置磁盘信息
*/
private void setSysFiles(OperatingSystem os) {
FileSystem fileSystem = os.getFileSystem();
List<OSFileStore> fsArray = fileSystem.getFileStores();
for (OSFileStore fs : fsArray) {
long free = fs.getUsableSpace();
long total = fs.getTotalSpace();
long used = total - free;
SysFile sysFile = new SysFile();
sysFile.setDirName(fs.getMount());
sysFile.setSysTypeName(fs.getType());
sysFile.setTypeName(fs.getName());
sysFile.setTotal(convertFileSize(total));
sysFile.setFree(convertFileSize(free));
sysFile.setUsed(convertFileSize(used));
sysFile.setUsage(Arith.mul(Arith.div(used, total, 4), 100));
sysFiles.add(sysFile);
}
}
/**
* 字节转换
*
* @param size 字节大小
* @return 转换后值
*/
public String convertFileSize(long size) {
long kb = 1024;
long mb = kb * 1024;
long gb = mb * 1024;
if (size >= gb) {
return String.format("%.1f GB", (float) size / gb);
} else if (size >= mb) {
float f = (float) size / mb;
return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f);
} else if (size >= kb) {
float f = (float) size / kb;
return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f);
} else {
return String.format("%d B", size);
}
}
}

View File

@@ -0,0 +1,37 @@
package com.starry.admin.modules.monitor.entity;
import lombok.Data;
/**
* @author admin
* 系统相关信息
* @since 2022/10/17
*/
@Data
public class Sys {
/**
* 服务器名称
*/
private String computerName;
/**
* 服务器Ip
*/
private String computerIp;
/**
* 项目路径
*/
private String userDir;
/**
* 操作系统
*/
private String osName;
/**
* 系统架构
*/
private String osArch;
}

View File

@@ -0,0 +1,46 @@
package com.starry.admin.modules.monitor.entity;
import lombok.Data;
/**
* @author admin
* 系统文件相关信息
*/
@Data
public class SysFile {
/**
* 盘符路径
*/
private String dirName;
/**
* 盘符类型
*/
private String sysTypeName;
/**
* 文件类型
*/
private String typeName;
/**
* 总大小
*/
private String total;
/**
* 剩余大小
*/
private String free;
/**
* 已经使用量
*/
private String used;
/**
* 资源的使用率
*/
private double usage;
}

View File

@@ -0,0 +1,50 @@
package com.starry.admin.modules.monitor.entity;
import lombok.Data;
/**
* @author admin
* 当前在线会话
*/
@Data
public class UserOnline {
/**
* 会话编号
*/
private String tokenId;
/**
* 部门名称
*/
private String deptName;
/**
* 用户名称
*/
private String userName;
/**
* 登录IP地址
*/
private String ipaddr;
/**
* 登录地址
*/
private String loginLocation;
/**
* 浏览器类型
*/
private String browser;
/**
* 操作系统
*/
private String os;
/**
* 登录时间
*/
private Long loginTime;
}

View File

@@ -0,0 +1,48 @@
package com.starry.admin.modules.monitor.service;
import com.starry.admin.common.domain.LoginUser;
import com.starry.admin.modules.monitor.entity.UserOnline;
/**
* @author admin
* @since 2022/10/18
*/
public interface UserOnlineService {
/**
* 通过登录地址/用户名称查询信息
*
* @param ipaddr 登录地址
* @param userName 用户名称
* @param user 用户信息
* @return 在线用户信息
*/
UserOnline selectOnlineByInfo(String ipaddr, String userName, LoginUser user);
/**
* 通过登录地址查询信息
*
* @param ipaddr 登录地址
* @param user 用户信息
* @return 在线用户信息
*/
UserOnline selectOnlineByIpaddr(String ipaddr, LoginUser user);
/**
* 通过用户名称查询信息
*
* @param userName 用户名称
* @param user 用户信息
* @return 在线用户信息
*/
UserOnline selectOnlineByUserName(String userName, LoginUser user);
/**
* 设置在线用户信息
*
* @param user 用户信息
* @return 在线用户
*/
UserOnline setUserOnline(LoginUser user);
}

View File

@@ -0,0 +1,59 @@
package com.starry.admin.modules.monitor.service.impl;
import com.starry.admin.common.domain.LoginUser;
import com.starry.admin.modules.monitor.entity.UserOnline;
import com.starry.admin.modules.monitor.service.UserOnlineService;
import com.starry.common.utils.StringUtils;
import org.springframework.stereotype.Service;
/**
* @author admin
* @since 2022/10/18
*/
@Service
public class UserOnlineServiceImpl implements UserOnlineService {
@Override
public UserOnline selectOnlineByInfo(String ipaddr, String userName, LoginUser user) {
if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername())) {
return setUserOnline(user);
}
return null;
}
@Override
public UserOnline selectOnlineByIpaddr(String ipaddr, LoginUser user) {
if (StringUtils.equals(ipaddr, user.getIpaddr())) {
return setUserOnline(user);
}
return null;
}
@Override
public UserOnline selectOnlineByUserName(String userName, LoginUser user) {
if (StringUtils.equals(userName, user.getUsername())) {
return setUserOnline(user);
}
return null;
}
@Override
public UserOnline setUserOnline(LoginUser user) {
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUser())) {
return null;
}
UserOnline userOnline = new UserOnline();
userOnline.setTokenId(user.getToken());
userOnline.setUserName(user.getUsername());
userOnline.setIpaddr(user.getIpaddr());
userOnline.setLoginLocation(user.getLoginLocation());
userOnline.setBrowser(user.getBrowser());
userOnline.setOs(user.getOs());
userOnline.setLoginTime(user.getLoginTime());
if (StringUtils.isNotNull(user.getUser().getDept())) {
userOnline.setDeptName(user.getUser().getDept().getDeptName());
}
return userOnline;
}
}

View File

@@ -0,0 +1,94 @@
package com.starry.admin.modules.platform.controller;
import com.starry.admin.modules.platform.entity.SysTenantEntity;
import com.starry.admin.modules.platform.service.ISysTenantService;
import com.starry.admin.modules.platform.vo.SysTenantAddVo;
import com.starry.admin.modules.platform.vo.SysTenantQueryVo;
import com.starry.admin.utils.ExcelUtils;
import com.starry.common.annotation.Log;
import com.starry.common.enums.BusinessType;
import com.starry.common.result.R;
import com.starry.common.utils.ConvertUtil;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
/**
* 租户表Controller
*
* @author admin
*/
@RestController
@RequestMapping("/platform/tenant")
public class SysTenantController {
@Resource
private ISysTenantService sysTenantService;
/**
* 新增租户表
*/
@PreAuthorize("@customSs.hasPermi('platform:tenant:create')")
@Log(title = "租户表", businessType = BusinessType.INSERT)
@PostMapping("/create")
public R create(@Valid @RequestBody SysTenantAddVo vo) {
SysTenantEntity entity = ConvertUtil.entityToVo(vo, SysTenantEntity.class);
return sysTenantService.addTenant(entity);
}
/**
* 查询租户表列表
*/
@PreAuthorize("@customSs.hasPermi('platform:tenant:list')")
@GetMapping("/list")
public R list(SysTenantQueryVo vo) {
return R.ok(sysTenantService.selectSysTenantList(vo));
}
/**
* 导出租户表列表
*/
@PreAuthorize("@customSs.hasPermi('platform:tenant:export')")
@Log(title = "租户表", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, SysTenantQueryVo sysTenantEntity) {
ExcelUtils.exportEasyExcel(response, SysTenantEntity.class, sysTenantService.selectSysTenantList(sysTenantEntity).getRecords(), "租户表数据");
}
/**
* 获取租户表详细信息
*/
@PreAuthorize("@customSs.hasPermi('platform:tenant:query')")
@GetMapping(value = "/{tenantId}")
public R getInfo(@PathVariable("tenantId") String tenantId) {
return R.ok(sysTenantService.selectSysTenantByTenantId(tenantId));
}
/**
* 修改租户表
*/
@PreAuthorize("@customSs.hasPermi('platform:tenant:edit')")
@Log(title = "租户表", businessType = BusinessType.UPDATE)
@PostMapping(value = "/update/{tenantId}")
public R update(@PathVariable String tenantId, @RequestBody SysTenantEntity sysTenantEntity) {
return sysTenantService.updateTenant(sysTenantEntity);
}
/**
* 删除租户表
*/
@PreAuthorize("@customSs.hasPermi('platform:tenant:remove')")
@Log(title = "租户表", businessType = BusinessType.DELETE)
@DeleteMapping("/{tenantIds}")
public R remove(@PathVariable String[] tenantIds) {
return R.ok(sysTenantService.deleteSysTenantByTenantIds(tenantIds));
}
}

View File

@@ -0,0 +1,108 @@
package com.starry.admin.modules.platform.controller;
import com.starry.admin.modules.platform.entity.SysTenantPackageEntity;
import com.starry.admin.modules.platform.service.ISysTenantPackageService;
import com.starry.admin.modules.platform.vo.SimplePackage;
import com.starry.admin.modules.platform.vo.SysTenantPackageVo;
import com.starry.admin.utils.ExcelUtils;
import com.starry.common.annotation.Log;
import com.starry.common.enums.BusinessType;
import com.starry.common.result.R;
import com.starry.common.utils.ConvertUtil;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
* 租户套餐表Controller
*
* @author admin
*/
@RestController
@RequestMapping("/platform/package")
public class SysTenantPackageController {
@Resource
private ISysTenantPackageService SysTenantPackageService;
/**
* 查询租户套餐表列表
*/
@PreAuthorize("@customSs.hasPermi('platform:package:list')")
@GetMapping("/list")
public R list(SysTenantPackageVo sysTenantPackageEntity) {
return R.ok(SysTenantPackageService.selectSysTenantPackageList(sysTenantPackageEntity));
}
/**
* 导出租户套餐表列表
*/
@PreAuthorize("@customSs.hasPermi('platform:package:export')")
@Log(title = "租户套餐表", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, SysTenantPackageVo sysTenantPackageEntity) {
ExcelUtils.exportEasyExcel(response, SysTenantPackageEntity.class, SysTenantPackageService.selectSysTenantPackageList(sysTenantPackageEntity).getRecords(), "租户套餐表数据");
}
/**
* 获取租户套餐表详细信息
*/
@PreAuthorize("@customSs.hasPermi('platform:package:query')")
@GetMapping(value = "/{packageId}")
public R getInfo(@PathVariable("packageId") String packageId) {
return R.ok(SysTenantPackageService.selectSysTenantPackageByPackageId(packageId));
}
/**
* 新增租户套餐表
*/
@PreAuthorize("@customSs.hasPermi('platform:package:create')")
@Log(title = "租户套餐表", businessType = BusinessType.INSERT)
@PostMapping("/create")
public R create(@RequestBody SysTenantPackageEntity vo) {
SysTenantPackageEntity entity = ConvertUtil.entityToVo(vo, SysTenantPackageEntity.class);
boolean success = SysTenantPackageService.create(entity);
if (success) {
return R.ok();
}
return R.error("添加失败");
}
/**
* 修改租户套餐表
*/
@PreAuthorize("@customSs.hasPermi('platform:package:edit')")
@Log(title = "租户套餐表", businessType = BusinessType.UPDATE)
@PostMapping(value = "/update/{packageId}")
public R update(@PathVariable String packageId, @RequestBody SysTenantPackageEntity sysTenantPackageEntity) {
sysTenantPackageEntity.setPackageId(packageId);
boolean success = SysTenantPackageService.update(sysTenantPackageEntity);
if (success) {
return R.ok();
}
return R.error("修改失败");
}
/**
* 删除租户套餐表
*/
@PreAuthorize("@customSs.hasPermi('platform:package:remove')")
@Log(title = "租户套餐表", businessType = BusinessType.DELETE)
@DeleteMapping("/{packageIds}")
public R remove(@PathVariable String[] packageIds) {
return R.ok(SysTenantPackageService.deleteSysTenantPackageByPackageIds(packageIds));
}
/**
* 查询租户套餐精简列表
*/
@GetMapping("/get-simple-list")
public R getSimpleList() {
List<SimplePackage> list = SysTenantPackageService.getSimpleList();
return R.ok(list);
}
}

View File

@@ -0,0 +1,135 @@
package com.starry.admin.modules.platform.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.starry.common.domain.BaseEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.util.Date;
/**
* 租户表对象 sys_tenant
*
* @author admin
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("sys_tenant")
public class SysTenantEntity extends BaseEntity<SysTenantEntity> {
private static final long serialVersionUID = 1L;
/**
* 租户ID
*/
@ApiModelProperty("主键ID")
@TableId(value = "tenant_id", type = IdType.AUTO)
private String tenantId;
/**
* 租户类型;0:公司;1:部门;2:个人;3:其他
*/
private String tenantType;
/**
* 用户状态;0:正常,1:停用
*/
private String tenantStatus;
/**
* 编码
*/
private String tenantCode;
/**
* 名称
*/
private String tenantName;
/**
* logo图
*/
private String tenantLogo;
/**
* 显示顺序
*/
private Long sortOrder;
/**
* 官方地址
*/
private String homeUrl;
/**
* 电话
*/
private String phone;
/**
* 传真
*/
private String fax;
/**
* 邮箱
*/
private String email;
/**
* 地址
*/
private String address;
/**
* 管理员账号
*/
private String userName;
/**
* 管理员密码
*/
private String userPwd;
/**
* 租户套餐
*/
private String packageId;
/**
* 租赁到期时间
*/
private Date tenantTime;
/**
* 微信公众号ID
*/
private String appId;
/**
* 微信公众号的app secret
*/
private String secret;
/**
* 设置微信公众号的token
*/
private String token;
/**
* 设置微信公众号的EncodingAESKey
*/
private String aesKey;
/**
* 备注
*/
private String remarks;
}

View File

@@ -0,0 +1,52 @@
package com.starry.admin.modules.platform.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.starry.common.domain.BaseEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 租户套餐表对象 sys_tenant_package
*
* @author admin
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("sys_tenant_package")
public class SysTenantPackageEntity extends BaseEntity<SysTenantPackageEntity> {
private static final long serialVersionUID = 1L;
/**
* 套餐id
*/
@ApiModelProperty("主键ID")
@TableId(value = "package_id", type = IdType.AUTO)
private String packageId;
/**
* 名称
*/
private String packageName;
/**
* 关联菜单id
*/
private String menuIds;
/**
* 状态;0:正常,1:停用
*/
private String status;
/**
* 备注
*/
private String remarks;
}

View File

@@ -0,0 +1,43 @@
package com.starry.admin.modules.platform.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.starry.admin.modules.platform.entity.SysTenantEntity;
import com.starry.admin.modules.platform.vo.SysTenantQueryVo;
import com.starry.admin.modules.platform.vo.TenantResultVo;
import org.apache.ibatis.annotations.Param;
/**
* 租户表Mapper接口
*
* @author admin
* @since 2023-03-03
*/
public interface SysTenantMapper extends BaseMapper<SysTenantEntity> {
/**
* 查询租户表
*
* @param tenantId 租户表主键
* @return 租户表
*/
SysTenantEntity selectSysTenantByTenantId(String tenantId);
/**
* 查询租户表列表
*
* @param page 分页参数
* @param sysTenantEntity 租户表
* @return 租户表集合
*/
IPage<TenantResultVo> selectSysTenantList(Page<TenantResultVo> page, @Param("vo") SysTenantQueryVo sysTenantEntity);
/**
* 批量删除租户管理
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
int deleteTenantByIds(String[] ids);
}

View File

@@ -0,0 +1,42 @@
package com.starry.admin.modules.platform.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.starry.admin.modules.platform.entity.SysTenantPackageEntity;
import com.starry.admin.modules.platform.vo.SimplePackage;
import com.starry.admin.modules.platform.vo.SysTenantPackageVo;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 租户套餐表Mapper接口
*
* @author admin
*/
public interface SysTenantPackageMapper extends BaseMapper<SysTenantPackageEntity> {
/**
* 查询租户套餐表
*
* @param packageId 租户套餐表主键
* @return 租户套餐表
*/
SysTenantPackageEntity selectSysTenantPackageByPackageId(String packageId);
/**
* 查询租户套餐表列表
*
* @param sysTenantPackageEntity 租户套餐表
* @return 租户套餐表集合
*/
IPage<SysTenantPackageEntity> selectSysTenantPackageList(Page<SysTenantPackageEntity> page, @Param("vo") SysTenantPackageVo sysTenantPackageEntity);
/**
* 查询租户套餐
*
* @return 租户套餐
*/
List<SimplePackage> getSimpleList();
}

View File

@@ -0,0 +1,74 @@
package com.starry.admin.modules.platform.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.starry.admin.modules.platform.entity.SysTenantPackageEntity;
import com.starry.admin.modules.platform.vo.SimplePackage;
import com.starry.admin.modules.platform.vo.SysTenantPackageVo;
import java.util.List;
/**
* 租户套餐表Service接口
*
* @author admin
*/
public interface ISysTenantPackageService extends IService<SysTenantPackageEntity> {
/**
* 查询租户套餐表
*
* @param packageId 租户套餐表主键
* @return 租户套餐表
*/
SysTenantPackageEntity selectSysTenantPackageByPackageId(String packageId);
/**
* 查询租户套餐表列表
*
* @param sysTenantPackageEntity 租户套餐表
* @return 租户套餐表集合
*/
IPage<SysTenantPackageEntity> selectSysTenantPackageList(SysTenantPackageVo sysTenantPackageEntity);
/**
* 新增租户套餐表
*
* @param sysTenantPackageEntity 租户套餐表
* @return 结果
*/
boolean create(SysTenantPackageEntity sysTenantPackageEntity);
/**
* 修改租户套餐表
*
* @param sysTenantPackageEntity 租户套餐表
* @return 结果
*/
boolean update(SysTenantPackageEntity sysTenantPackageEntity);
/**
* 批量删除租户套餐表
*
* @param packageIds 需要删除的租户套餐表主键集合
* @return 结果
*/
int deleteSysTenantPackageByPackageIds(String[] packageIds);
/**
* 删除租户套餐表信息
*
* @param packageId 租户套餐表主键
* @return 结果
*/
int deleteSysTenantPackageByPackageId(Long packageId);
/**
* 查询租户套餐
*
* @return 租户套餐
*/
List<SimplePackage> getSimpleList();
}

View File

@@ -0,0 +1,90 @@
package com.starry.admin.modules.platform.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.starry.admin.modules.platform.entity.SysTenantEntity;
import com.starry.admin.modules.platform.vo.SysTenantQueryVo;
import com.starry.admin.modules.platform.vo.TenantResultVo;
import com.starry.common.result.R;
import java.util.List;
/**
* 租户表Service接口
*
* @author admin
*/
public interface ISysTenantService extends IService<SysTenantEntity> {
/**
* 查询租户表
*
* @param tenantId 租户表主键
* @return 租户表
*/
SysTenantEntity selectSysTenantByTenantId(String tenantId);
/**
* 查询租户表列表
*
* @param sysTenantEntity 租户表
* @return 租户表集合
*/
IPage<TenantResultVo> selectSysTenantList(SysTenantQueryVo sysTenantEntity);
/**
* 新增租户表
*
* @param sysTenantEntity 租户表
* @return 结果
*/
boolean create(SysTenantEntity sysTenantEntity);
/**
* 修改租户表
*
* @param sysTenantEntity 租户表
* @return 结果
*/
boolean update(SysTenantEntity sysTenantEntity);
/**
* 批量删除租户表
*
* @param tenantIds 需要删除的租户表主键集合
* @return 结果
*/
int deleteSysTenantByTenantIds(String[] tenantIds);
/**
* 删除租户表信息
*
* @param tenantId 租户表主键
* @return 结果
*/
int deleteSysTenantByTenantId(Long tenantId);
/**
* 新增租户
*
* @param sysTenantEntity 租户表
* @return 结果
*/
R addTenant(SysTenantEntity sysTenantEntity);
/**
* 修改租户
*
* @param sysTenantEntity 租户表
* @return 结果
*/
R updateTenant(SysTenantEntity sysTenantEntity);
/**
* 根据套餐ID查询租户
* @param packageId 套餐ID
* @return
*/
List<SysTenantEntity> queryByPackage(String packageId);
}

View File

@@ -0,0 +1,114 @@
package com.starry.admin.modules.platform.service.impl;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.starry.admin.common.exception.CustomException;
import com.starry.admin.modules.platform.entity.SysTenantPackageEntity;
import com.starry.admin.modules.platform.mapper.SysTenantPackageMapper;
import com.starry.admin.modules.platform.service.ISysTenantPackageService;
import com.starry.admin.modules.platform.service.ISysTenantService;
import com.starry.admin.modules.platform.vo.SimplePackage;
import com.starry.admin.modules.platform.vo.SysTenantPackageVo;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
/**
* 租户套餐表Service业务层处理
*
* @author admin
*/
@Service
public class SysTenantPackageServiceImpl extends ServiceImpl<SysTenantPackageMapper, SysTenantPackageEntity> implements ISysTenantPackageService {
@Resource
private SysTenantPackageMapper sysTenantPackageMapper;
@Resource
private ISysTenantService tenantService;
/**
* 查询租户套餐表
*
* @param packageId 租户套餐表主键
* @return 租户套餐表
*/
@Override
public SysTenantPackageEntity selectSysTenantPackageByPackageId(String packageId) {
return this.baseMapper.selectById(packageId);
}
/**
* 查询租户套餐表列表
*
* @param sysTenantPackageEntity 租户套餐表
* @return 租户套餐表
*/
@Override
public IPage<SysTenantPackageEntity> selectSysTenantPackageList(SysTenantPackageVo sysTenantPackageEntity) {
return sysTenantPackageMapper.selectSysTenantPackageList(new Page<>(sysTenantPackageEntity.getPageNum(), sysTenantPackageEntity.getPageSize()), sysTenantPackageEntity);
}
/**
* 新增租户套餐表
*
* @param entity 租户套餐表
* @return 结果
*/
@Override
public boolean create(SysTenantPackageEntity entity) {
if (StrUtil.isBlankIfStr(entity.getPackageId())) {
entity.setPackageId(IdUtil.fastSimpleUUID());
}
return save(entity);
}
/**
* 修改租户套餐表
*
* @param sysTenantPackageEntity 租户套餐表
* @return 结果
*/
@Override
public boolean update(SysTenantPackageEntity sysTenantPackageEntity) {
return updateById(sysTenantPackageEntity);
}
/**
* 批量删除租户套餐表
*
* @param packageIds 需要删除的租户套餐表主键
* @return 结果
*/
@Override
public int deleteSysTenantPackageByPackageIds(String[] packageIds) {
//删除前,看套餐是否被租户引用
for (String packageId : packageIds) {
if (!tenantService.queryByPackage(packageId).isEmpty()) {
throw new CustomException("套餐背应用,无法删除");
}
}
return sysTenantPackageMapper.deleteBatchIds(Arrays.asList(packageIds));
}
/**
* 删除租户套餐表信息
*
* @param packageId 租户套餐表主键
* @return 结果
*/
@Override
public int deleteSysTenantPackageByPackageId(Long packageId) {
return sysTenantPackageMapper.deleteById(packageId);
}
@Override
public List<SimplePackage> getSimpleList() {
return sysTenantPackageMapper.getSimpleList();
}
}

View File

@@ -0,0 +1,288 @@
package com.starry.admin.modules.platform.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.starry.admin.common.domain.LoginUser;
import com.starry.admin.modules.platform.entity.SysTenantEntity;
import com.starry.admin.modules.platform.entity.SysTenantPackageEntity;
import com.starry.admin.modules.platform.mapper.SysTenantMapper;
import com.starry.admin.modules.platform.mapper.SysTenantPackageMapper;
import com.starry.admin.modules.platform.service.ISysTenantService;
import com.starry.admin.modules.platform.vo.SysTenantQueryVo;
import com.starry.admin.modules.platform.vo.TenantResultVo;
import com.starry.admin.modules.system.entity.*;
import com.starry.admin.modules.system.mapper.*;
import com.starry.admin.modules.system.service.SysRoleMenuService;
import com.starry.admin.utils.SecurityUtils;
import com.starry.common.constant.CacheConstants;
import com.starry.common.redis.RedisCache;
import com.starry.common.result.R;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
/**
* 租户表Service业务层处理
*
* @author admin
* @since 2023-03-03
*/
@Service
public class SysTenantServiceImpl extends ServiceImpl<SysTenantMapper, SysTenantEntity> implements ISysTenantService {
@Resource
private SysTenantMapper sysTenantMapper;
@Resource
private SysTenantPackageMapper tenantPackageMapper;
@Resource
private SysUserMapper sysUserMapper;
@Resource
private SysDeptMapper deptMapper;
@Resource
private SysRoleMapper roleMapper;
@Resource
private SysRoleMenuService roleMenuService;
@Resource
private SysUserRoleMapper userRoleMapper;
@Resource
private SysRoleMenuMapper sysRoleMenuMapper;
@Resource
private RedisCache redisCache;
/**
* 查询租户表
*
* @param tenantId 租户表主键
* @return 租户表
*/
@Override
public SysTenantEntity selectSysTenantByTenantId(String tenantId) {
return this.baseMapper.selectById(tenantId);
}
/**
* 查询租户表列表
*
* @param vo 租户表
* @return 租户表
*/
@Override
public IPage<TenantResultVo> selectSysTenantList(SysTenantQueryVo vo) {
LambdaQueryWrapper<SysTenantEntity> wrapper = new LambdaQueryWrapper<>();
if (StrUtil.isNotBlank(vo.getTenantStatus())) {
wrapper.eq(SysTenantEntity::getTenantStatus, vo.getTenantStatus());
}
if (StrUtil.isNotBlank(vo.getTenantName())) {
wrapper.like(SysTenantEntity::getTenantName, vo.getTenantName());
}
if (StrUtil.isNotBlank(vo.getBeginTime())) {
wrapper.ge(SysTenantEntity::getTenantTime, vo.getBeginTime());
}
if (StrUtil.isNotBlank(vo.getEndTime())) {
wrapper.le(SysTenantEntity::getTenantTime, vo.getEndTime());
}
return sysTenantMapper.selectSysTenantList(new Page<>(vo.getPageNum(), vo.getPageSize()), vo);
}
/**
* 新增租户表
*
* @param sysTenantEntity 租户表
* @return 结果
*/
@Override
public boolean create(SysTenantEntity sysTenantEntity) {
return save(sysTenantEntity);
}
/**
* 修改租户表
*
* @param sysTenantEntity 租户表
* @return 结果
*/
@Override
public boolean update(SysTenantEntity sysTenantEntity) {
return updateById(sysTenantEntity);
}
/**
* 批量删除租户表
*
* @param tenantIds 需要删除的租户表主键
* @return 结果
*/
@Transactional(rollbackFor = Exception.class)
@Override
public int deleteSysTenantByTenantIds(String[] tenantIds) {
int num = sysTenantMapper.deleteTenantByIds(tenantIds);
if (num > 0) {
// 下面才会进行子模块数据的删除
// 部门模块
deptMapper.deleteDeptByTenantId(tenantIds);
// 权限
roleMapper.deleteRoleByTenantId(tenantIds);
sysRoleMenuMapper.deleteRoleMenuByTenantIds(tenantIds);
// 账号
sysUserMapper.deleteUserByTenantId(tenantIds);
userRoleMapper.deleteUserRoleByTenantId(tenantIds);
} else {
throw new RuntimeException("当前租户已被删除不存在!");
}
return 1;
}
/**
* 删除租户表信息
*
* @param tenantId 租户表主键
* @return 结果
*/
@Override
public int deleteSysTenantByTenantId(Long tenantId) {
return sysTenantMapper.deleteById(tenantId);
}
@Transactional(rollbackFor = Exception.class)
@Override
public R addTenant(SysTenantEntity sysTenantEntity) {
if (StrUtil.isBlankIfStr(sysTenantEntity.getTenantId())) {
sysTenantEntity.setTenantId(IdUtil.fastSimpleUUID());
}
if (StrUtil.isBlankIfStr(sysTenantEntity.getTenantCode())) {
sysTenantEntity.setTenantCode(IdUtil.fastSimpleUUID());
}
// 判断账号是否存在
if (sysUserMapper.checkUserNameUnique(sysTenantEntity.getUserName()) > 0) {
return R.error("管理员账号已存在,请重新设置!");
}
// 创建租户
sysTenantMapper.insert(sysTenantEntity);
// 创建默认部门--部门默认名称以租户名称
Long deptId = createDept(sysTenantEntity);
// 创建默认角色--角色默认为租户名称+管理员
Long roleId = createRole(sysTenantEntity);
// 创建默认账号
createUser(sysTenantEntity, deptId, roleId);
return R.ok("租户创建成功!");
}
private Long createDept(SysTenantEntity sysTenantEntity) {
// 创建部门
SysDeptEntity dept = new SysDeptEntity();
dept.setParentId(0L);
dept.setAncestors("0");
dept.setDeptName(sysTenantEntity.getTenantName());
dept.setSort(0);
dept.setLeader(sysTenantEntity.getTenantName() + "管理员");
dept.setPhone(sysTenantEntity.getPhone());
dept.setEmail(sysTenantEntity.getEmail());
dept.setTenantId(sysTenantEntity.getTenantId());
deptMapper.insert(dept);
return dept.getDeptId();
}
private Long createRole(SysTenantEntity sysTenantEntity) {
// 创建角色
SysRoleEntity role = new SysRoleEntity();
role.setRoleName(sysTenantEntity.getTenantName() + "管理员");
role.setRoleKey("admin");
role.setDataScope("1");
role.setMenuCheckStrictly(true);
role.setDeptCheckStrictly(true);
role.setDescription("租户管理员");
role.setTenantId(sysTenantEntity.getTenantId());
roleMapper.insert(role);
// 根据租户套餐ids查出套餐编码塞入角色-菜单表
createRoleMenu(sysTenantEntity, role);
return role.getRoleId();
}
/**
* 目前为单套餐,跟租户绑定,解耦防止套餐变动影响多个租户
**/
private void createRoleMenu(SysTenantEntity sysTenantEntity, SysRoleEntity role) {
SysTenantPackageEntity sysTenantPackage = tenantPackageMapper.selectById(sysTenantEntity.getPackageId());
List<String> subMeuns = Arrays.asList(sysTenantPackage.getMenuIds().split(","));
List<SysRoleMenuEntity> roleMenuList = subMeuns.stream().map(menuid -> {
SysRoleMenuEntity entity = new SysRoleMenuEntity();
entity.setRoleId(role.getRoleId());
entity.setMenuId(Long.valueOf(menuid));
entity.setTenantId(sysTenantEntity.getTenantId());
return entity;
}).collect(Collectors.toList());
roleMenuService.saveBatch(roleMenuList);
}
private void createUser(SysTenantEntity sysTenant, Long deptId, Long roleId) {
SysUserEntity user = new SysUserEntity();
user.setDeptId(deptId);
user.setUserCode(sysTenant.getUserName());
user.setRealName(sysTenant.getTenantName());
user.setUserNickname(sysTenant.getTenantName());
user.setUserType(1);
user.setUserEmail(sysTenant.getEmail());
user.setMobile(sysTenant.getPhone());
String password = SecurityUtils.encryptPassword(sysTenant.getUserPwd());
user.setPassWord(password);
user.setTenantId(sysTenant.getTenantId());
user.setUserId(IdUtil.fastSimpleUUID());
sysUserMapper.insert(user);
createUserRole(sysTenant.getTenantId(), user.getUserId(), roleId);
}
private void createUserRole(String tenantId, String userId, Long roleId) {
SysUserRoleEntity userRole = new SysUserRoleEntity();
userRole.setUserId(userId);
userRole.setRoleId(roleId);
userRole.setTenantId(tenantId);
userRoleMapper.insert(userRole);
}
@Override
public R updateTenant(SysTenantEntity sysTenantEntity) {
// 判断最新的租户套餐是否改变 重新授权 租户二级管理员账号需重新分配三级账号权限
SysTenantEntity newTenant = sysTenantMapper.selectById(sysTenantEntity.getTenantId());
if (sysTenantEntity.getPackageId() != null && !sysTenantEntity.getPackageId().equals(newTenant.getPackageId())) {
List<SysRoleEntity> roleList = roleMapper.queryAdminRole(sysTenantEntity.getTenantId());
// 正常逻辑下每个租户只有一个二级管理员账号
SysRoleEntity tRole = roleList.get(0);
if (tRole != null) {
// 删除原租户下所有的角色-菜单信息
sysRoleMenuMapper.deleteRoleMenuByTenantId(sysTenantEntity.getTenantId());
// 新增默认角色-菜单信息
createRoleMenu(sysTenantEntity, tRole);
// 原登录租户账号退出重登
Collection<String> keys = redisCache.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
if (CollectionUtil.isNotEmpty(keys)) {
for (String key : keys) {
LoginUser onlineUser = redisCache.getCacheObject(key);
if (onlineUser.getUser().getTenantId() != null && onlineUser.getUser().getTenantId().equals(sysTenantEntity.getTenantId())) {
redisCache.deleteObject(key);
}
}
}
}
}
sysTenantMapper.updateById(sysTenantEntity);
return R.ok();
}
@Override
public List<SysTenantEntity> queryByPackage(String packageId) {
LambdaQueryWrapper<SysTenantEntity> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysTenantEntity::getTenantId, packageId);
return this.baseMapper.selectList(queryWrapper);
}
}

View File

@@ -0,0 +1,20 @@
package com.starry.admin.modules.platform.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author admin
* @since 2023/3/5 20:53
*/
@ApiModel("管理后台 - 租户套餐精简信息")
@Data
public class SimplePackage {
@ApiModelProperty(value = "套餐编号", required = true, example = "1024")
private String id;
@ApiModelProperty(value = "套餐名称", required = true, example = "希留")
private String name;
}

View File

@@ -0,0 +1,131 @@
package com.starry.admin.modules.platform.vo;
import com.starry.common.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.Date;
/**
* 租户表对象 sys_tenant
*
* @author admin
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class SysTenantAddVo extends BaseEntity<SysTenantAddVo> {
private static final long serialVersionUID = 1L;
/**
* 租户类型;0:公司;1:部门;2:个人;3:其他
*/
@NotBlank(message = "租户类型不能为空")
private String tenantType;
/**
* 用户状态;0:正常,1:停用
*/
@NotBlank(message = "租户状态不能为空")
private String tenantStatus;
/**
* 名称
*/
@NotBlank(message = "租户名称不能为空")
private String tenantName;
/**
* logo图
*/
private String tenantLogo;
/**
* 显示顺序
*/
private String sortOrder;
/**
* 官方地址
*/
private String homeUrl;
/**
* 电话
*/
@NotBlank(message = "手机号码不能为空")
private String phone;
/**
* 传真
*/
private String fax;
/**
* 邮箱
*/
private String email;
/**
* 地址
*/
private String address;
/**
* 管理员账号
*/
@NotBlank(message = "管理员账号不能为空")
private String userName;
/**
* 管理员密码
*/
@NotBlank(message = "管理员账号密码不能为空")
private String userPwd;
/**
* 租户套餐
*/
private String packageId;
/**
* 租赁到期时间
*/
@NotNull(message = "租赁到期时间不能为空")
private Date tenantTime;
/**
* 微信公众号ID
*/
@NotBlank(message = "微信公众号ID不能为空")
private String appId;
/**
* 微信公众号的app secret
*/
@NotBlank(message = "微信公众号secret不能为空")
private String secret;
/**
* 设置微信公众号的token
*/
@NotBlank(message = "微信公众号token不能为空")
private String token;
/**
* 设置微信公众号的EncodingAESKey
*/
@NotBlank(message = "微信公众号aesKey不能为空")
private String aesKey;
/**
* 备注
*/
private String remarks;
}

View File

@@ -0,0 +1,43 @@
package com.starry.admin.modules.platform.vo;
import com.starry.common.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
/**
* 租户套餐表对象 sys_tenant_package
*
* @author admin
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class SysTenantPackageAddVo extends BaseEntity<SysTenantPackageAddVo> {
private static final long serialVersionUID = 1L;
/**
* 名称
*/
@NotBlank(message = "套餐名称不能为空")
private String packageName;
/**
* 关联菜单id
*/
private String menuIds;
/**
* 状态;0:正常,1:停用
*/
@NotBlank(message = "套餐状态不能为空")
private String status;
/**
* 备注
*/
private String remarks;
}

View File

@@ -0,0 +1,48 @@
package com.starry.admin.modules.platform.vo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.starry.common.domain.BasePageEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 租户套餐表对象 sys_tenant_package
*
* @author admin
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class SysTenantPackageVo extends BasePageEntity {
private static final long serialVersionUID = 1L;
/**
* 套餐id
*/
@ApiModelProperty("主键ID")
@TableId(value = "package_id", type = IdType.AUTO)
private Long packageId;
/**
* 名称
*/
private String packageName;
/**
* 关联菜单id
*/
private String menuIds;
/**
* 状态;0:正常,1:停用
*/
private String status;
/**
* 备注
*/
private String remarks;
}

View File

@@ -0,0 +1,30 @@
package com.starry.admin.modules.platform.vo;
import com.starry.common.domain.BasePageEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 租户表对象 sys_tenant
*
* @author admin
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class SysTenantQueryVo extends BasePageEntity {
private static final long serialVersionUID = 1L;
/**
* 名称
*/
private String tenantName;
/**
* 用户状态;0:正常,1:停用
*/
private String tenantStatus;
}

View File

@@ -0,0 +1,53 @@
package com.starry.admin.modules.platform.vo;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import java.util.Date;
/**
* @author 租户列表返回结果VO
* @since 2023/3/7
*/
@ApiModel("管理后台 - 租户列表返回信息")
@Data
public class TenantResultVo {
private String tenantId;
/**
* 租户类型;0:公司;1:部门;2:个人;3:其他
*/
private String tenantType;
/**
* 用户状态;0:正常,1:停用
*/
private String tenantStatus;
/**
* 名称
*/
private String tenantName;
/**
* logo图
*/
private String tenantLogo;
/**
* 管理员账号
*/
private String userName;
/**
* 租户套餐Id
*/
private String packageId;
/**
* 租赁到期时间
*/
private Date tenantTime;
}

View File

@@ -0,0 +1,113 @@
package com.starry.admin.modules.system.controller;
import com.starry.admin.common.component.JwtToken;
import com.starry.admin.common.domain.LoginUser;
import com.starry.admin.modules.system.entity.SysMenuEntity;
import com.starry.admin.modules.system.entity.SysUserEntity;
import com.starry.admin.modules.system.service.LoginService;
import com.starry.admin.modules.system.service.SysMenuService;
import com.starry.admin.modules.system.vo.LoginVo;
import com.starry.admin.modules.system.vo.RouterVo;
import com.starry.admin.utils.SecurityUtils;
import com.starry.common.redis.CaptchaService;
import com.starry.common.result.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author admin
*/
@Api(tags = "登录管理")
@RestController
public class LoginController {
@Value("${jwt.tokenHead}")
private String tokenHead;
@Value(value = "${xl.login.authCode.enable}")
private boolean needAuthCode;
@Resource
private LoginService loginService;
@Resource
private SysMenuService menuService;
@Resource
private CaptchaService captchaService;
@Resource
private JwtToken jwtToken;
@ApiOperation(value = "登录")
@PostMapping(value = "old-login")
public R login(@RequestBody LoginVo loginVo) {
// 只有开启了验证码功能才需要验证
if (needAuthCode) {
String msg = captchaService.checkImageCode(loginVo.getNonceStr(), loginVo.getValue());
if (StringUtils.isNotBlank(msg)) {
return R.error(msg);
}
}
String token = loginService.login(loginVo.getUserName(), loginVo.getPassWord());
if (StringUtils.isBlank(token)) {
return R.error("用户名或密码错误");
}
Map<String, String> tokenMap = new HashMap<>();
tokenMap.put("token", token);
tokenMap.put("tokenHead", tokenHead);
return R.ok(tokenMap);
}
@ApiOperation(value = "登录后获取用户信息")
@GetMapping("get-info")
public R getInfo() {
SysUserEntity user = SecurityUtils.getLoginUser().getUser();
if (user == null) {
return R.unauthorized();
}
// 权限集合
Set<String> permissions = loginService.getMenuPermission(user);
// 角色集合
Set<String> roles = loginService.getRolePermission(user);
Map<String, Object> data = new HashMap<>();
data.put("userCode", user.getUserCode());
data.put("name", user.getRealName());
data.put("avatar", user.getAvatar());
data.put("roles", roles);
data.put("permissions", permissions);
return R.ok(data);
}
@ApiOperation(value = "登录后获取路由信息")
@GetMapping("get-routers")
public R getRoutes() {
List<SysMenuEntity> menus = menuService.selectMenuTreeByUserId(SecurityUtils.getUserId());
List<RouterVo> routerVos = menuService.buildMenus(menus);
return R.ok(routerVos);
}
@ApiOperation(value = "登录")
@PostMapping(value = "login")
public R newLogin(@RequestBody LoginVo loginVo) {
// 只有开启了验证码功能才需要验证
if (needAuthCode) {
String msg = captchaService.checkImageCode(loginVo.getNonceStr(), loginVo.getValue());
if (StringUtils.isNotBlank(msg)) {
return R.error(msg);
}
}
// 用户登录
LoginUser userInfo = loginService.newLogin(loginVo.getUserName(), loginVo.getPassWord());
Map<String, Object> tokenMap = jwtToken.createToken(userInfo);
return R.ok(tokenMap);
}
}

View File

@@ -0,0 +1,100 @@
package com.starry.admin.modules.system.controller;
import com.starry.admin.common.domain.TreeSelect;
import com.starry.admin.modules.system.entity.SysDeptEntity;
import com.starry.admin.modules.system.service.SysDeptService;
import com.starry.common.constant.UserConstants;
import com.starry.common.result.R;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
/**
* <p>
* 部门表 前端控制器
* </p>
*
* @author admin
* @since 2022-07-12
*/
@RestController
@RequestMapping("/ucenter/dept")
public class SysDeptController {
@Resource
private SysDeptService deptService;
@ApiOperation("获取部门列表")
@PreAuthorize("@customSs.hasPermi('system:dept:list')")
@GetMapping("/list")
public R list(SysDeptEntity dept) {
List<SysDeptEntity> depts = deptService.selectDeptList(dept);
return R.ok(depts);
}
@ApiOperation("添加部门")
@PreAuthorize("@customSs.hasPermi('system:dept:create')")
@PostMapping("/create")
public R creat(@RequestBody SysDeptEntity dept) {
if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) {
return R.error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在");
}
boolean success = deptService.create(dept);
if (success) {
return R.ok();
}
return R.error("添加失败");
}
@ApiOperation("修改部门")
@PreAuthorize("@customSs.hasPermi('system:dept:edit')")
@PostMapping("/update/{id}")
public R update(@PathVariable Long id, @RequestBody SysDeptEntity dept) {
dept.setDeptId(id);
if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) {
return R.error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在");
} else if (dept.getParentId().equals(id)) {
return R.error("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己");
}
boolean success = deptService.update(dept);
if (success) {
return R.ok();
}
return R.error("修改失败");
}
@ApiOperation("删除部门")
@PreAuthorize("@customSs.hasPermi('system:dept:delete')")
@PostMapping(value = "/delete/{id}")
public R delete(@PathVariable("id") Long deptId) {
if (deptService.hasChildByDeptId(deptId)) {
return R.error("存在下级部门,不允许删除");
}
boolean success = deptService.delete(Collections.singletonList(deptId));
if (success) {
return R.ok();
}
return R.error("删除失败");
}
@ApiOperation("获取部门下拉树列表")
@GetMapping("/treeselect")
public R treeselect(SysDeptEntity dept) {
List<SysDeptEntity> list = deptService.selectDeptList(dept);
List<TreeSelect> treeList = deptService.buildDeptTreeSelect(list);
return R.ok(treeList);
}
@ApiOperation("根据id获取详细信息")
@GetMapping(value = "/{deptId}")
public R getInfo(@PathVariable Long deptId) {
return R.ok(deptService.getById(deptId));
}
}

View File

@@ -0,0 +1,103 @@
package com.starry.admin.modules.system.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.starry.admin.modules.system.entity.SysDictEntity;
import com.starry.admin.modules.system.service.ISysDictService;
import com.starry.admin.modules.system.vo.SysDictVo;
import com.starry.common.annotation.Log;
import com.starry.common.enums.BusinessType;
import com.starry.common.result.R;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
* 字典表Controller
*
* @author admin
*/
@RestController
@RequestMapping("/system/dict")
public class SysDictController {
@Resource
private ISysDictService xlDictService;
/**
* 查询字典表列表
*/
@PreAuthorize("@customSs.hasPermi('system:dict:list')")
@GetMapping("/list")
public R list(SysDictVo dictVo) {
Page<SysDictEntity> list = xlDictService.selectXlDictList(dictVo);
return R.ok(list);
}
/**
* 获取字典表详细信息
*/
@PreAuthorize("@customSs.hasPermi('system:dict:query')")
@GetMapping(value = "/{dictId}")
public R getInfo(@PathVariable("dictId") Long dictId) {
return R.ok(xlDictService.selectXlDictByDictId(dictId));
}
/**
* 新增字典表
*/
@PreAuthorize("@customSs.hasPermi('system:dict:create')")
@Log(title = "字典表", businessType = BusinessType.INSERT)
@PostMapping("/create")
public R create(@RequestBody SysDictEntity sysDictEntity) {
boolean success = xlDictService.create(sysDictEntity);
if (success) {
return R.ok();
}
return R.error("添加失败");
}
/**
* 修改字典表
*/
@PreAuthorize("@customSs.hasPermi('system:dict:edit')")
@Log(title = "字典表", businessType = BusinessType.UPDATE)
@PostMapping(value = "/update/{dictId}")
public R update(@PathVariable Long dictId, @RequestBody SysDictEntity sysDictEntity) {
sysDictEntity.setDictId(dictId);
boolean success = xlDictService.update(sysDictEntity);
if (success) {
return R.ok();
}
return R.error("修改失败");
}
/**
* 删除字典表
*/
@PreAuthorize("@customSs.hasPermi('system:dict:remove')")
@Log(title = "字典表", businessType = BusinessType.DELETE)
@DeleteMapping("/{dictIds}")
public R remove(@PathVariable Long[] dictIds) {
return R.ok(xlDictService.deleteXlDictByDictIds(dictIds));
}
@GetMapping("/optionselect")
public R optionselect() {
List<SysDictEntity> list = xlDictService.selectDictTypeAll();
return R.ok(list);
}
/**
* 刷新字典缓存
*/
@PreAuthorize("@customSs.hasPermi('system:dict:remove')")
@Log(title = "字典类型", businessType = BusinessType.CLEAN)
@DeleteMapping("/refreshCache")
public R refreshCache() {
xlDictService.resetDictCache();
return R.ok();
}
}

View File

@@ -0,0 +1,98 @@
package com.starry.admin.modules.system.controller;
import cn.hutool.core.collection.CollectionUtil;
import com.starry.admin.modules.system.entity.SysDictDataEntity;
import com.starry.admin.modules.system.service.ISysDictDataService;
import com.starry.admin.modules.system.vo.SysDictDataVo;
import com.starry.common.annotation.Log;
import com.starry.common.enums.BusinessType;
import com.starry.common.result.R;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
* 字典数据表Controller
*
* @author admin
*/
@RestController
@RequestMapping("/system/dict/data")
public class SysDictDataController {
@Resource
private ISysDictDataService xlDictDataService;
/**
* 查询字典数据表列表
*/
@PreAuthorize("@customSs.hasPermi('system:dict:list')")
@GetMapping("/list")
public R list(SysDictDataVo sysDictDataEntity) {
return R.ok(xlDictDataService.selectXlDictDataList(sysDictDataEntity));
}
/**
* 获取字典数据表详细信息
*/
@PreAuthorize("@customSs.hasPermi('system:dict:query')")
@GetMapping(value = "/{dictDataId}")
public R getInfo(@PathVariable("dictDataId") Long dictDataId) {
return R.ok(xlDictDataService.selectXlDictDataByDictDataId(dictDataId));
}
/**
* 新增字典数据表
*/
@PreAuthorize("@customSs.hasPermi('system:dict:create')")
@Log(title = "字典数据表", businessType = BusinessType.INSERT)
@PostMapping("/create")
public R create(@RequestBody SysDictDataEntity sysDictDataEntity) {
boolean success = xlDictDataService.create(sysDictDataEntity);
if (success) {
return R.ok();
}
return R.error("添加失败");
}
/**
* 修改字典数据表
*/
@PreAuthorize("@customSs.hasPermi('system:dict:edit')")
@Log(title = "字典数据表", businessType = BusinessType.UPDATE)
@PostMapping(value = "/update/{dictDataId}")
public R update(@PathVariable Long dictDataId, @RequestBody SysDictDataEntity sysDictDataEntity) {
sysDictDataEntity.setDictDataId(dictDataId);
boolean success = xlDictDataService.update(sysDictDataEntity);
if (success) {
return R.ok();
}
return R.error("修改失败");
}
/**
* 删除字典数据表
*/
@PreAuthorize("@customSs.hasPermi('system:dict:remove')")
@Log(title = "字典数据表", businessType = BusinessType.DELETE)
@DeleteMapping("/{dictDataIds}")
public R remove(@PathVariable Long[] dictDataIds) {
return R.ok(xlDictDataService.deleteXlDictDataByDictDataIds(dictDataIds));
}
/**
* 根据字典类型查询字典数据信息
*/
@GetMapping(value = "/type/{dictType}")
public R getDictDataByType(@PathVariable String dictType) {
List<SysDictDataEntity> list = xlDictDataService.selectDictDataByType(dictType);
if (CollectionUtil.isEmpty(list)) {
list = new ArrayList<>();
}
return R.ok(list);
}
}

View File

@@ -0,0 +1,77 @@
package com.starry.admin.modules.system.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.starry.admin.modules.system.entity.SysLoginLogEntity;
import com.starry.admin.modules.system.entity.SysLoginLogVo;
import com.starry.admin.modules.system.service.ISysLoginLogService;
import com.starry.admin.utils.ExcelUtils;
import com.starry.common.annotation.Log;
import com.starry.common.enums.BusinessType;
import com.starry.common.result.R;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
/**
* 系统访问日志表Controller
*
* @author admin
*/
@RestController
@RequestMapping("/system/loginlog")
public class SysLoginLogController {
@Resource
private ISysLoginLogService xlLoginLogService;
/**
* 查询系统访问日志表列表
*/
@PreAuthorize("@customSs.hasPermi('system:loginlog:list')")
@GetMapping("/list")
public R list(SysLoginLogVo vo) {
IPage<SysLoginLogEntity> list = xlLoginLogService.selectXlLoginLogList(vo);
return R.ok(list);
}
/**
* 导出系统访问日志表列表
*/
@PreAuthorize("@customSs.hasPermi('system:loginlog:export')")
@Log(title = "登录日志", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, SysLoginLogVo vo) {
IPage<SysLoginLogEntity> list = xlLoginLogService.selectXlLoginLogList(vo);
ExcelUtils.exportEasyExcel(response, SysLoginLogEntity.class, list.getRecords(), "系统访问日志表数据");
}
/**
* 获取系统访问日志表详细信息
*/
@PreAuthorize("@customSs.hasPermi('system:log:query')")
@GetMapping(value = "/{loginId}")
public R getInfo(@PathVariable("loginId") Long loginId) {
return R.ok(xlLoginLogService.selectXlLoginLogByLoginId(loginId));
}
/**
* 删除系统访问日志表
*/
@PreAuthorize("@customSs.hasPermi('system:loginlog:remove')")
@Log(title = "登录日志", businessType = BusinessType.DELETE)
@DeleteMapping("/{loginIds}")
public R remove(@PathVariable Long[] loginIds) {
return R.ok(xlLoginLogService.deleteXlLoginLogByLoginIds(loginIds));
}
@PreAuthorize("@customSs.hasPermi('monitor:logininfor:clean')")
@Log(title = "登录日志", businessType = BusinessType.CLEAN)
@DeleteMapping("/clean")
public R clean() {
xlLoginLogService.cleanLoginlog();
return R.ok();
}
}

View File

@@ -0,0 +1,141 @@
package com.starry.admin.modules.system.controller;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.starry.admin.common.domain.TreeSelect;
import com.starry.admin.modules.system.entity.SysMenuEntity;
import com.starry.admin.modules.system.service.SysMenuService;
import com.starry.admin.modules.system.vo.SimpleMenu;
import com.starry.admin.utils.SecurityUtils;
import com.starry.common.constant.UserConstants;
import com.starry.common.result.R;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* <p>
* 菜单表 前端控制器
* </p>
*
* @author admin
* @since 2022-07-03
*/
@RestController
@RequestMapping("/ucenter/menu")
public class SysMenuController {
@Resource
private SysMenuService menuService;
@ApiOperation("获取菜单列表")
@PreAuthorize("@customSs.hasPermi('system:menu:list')")
@GetMapping("/list")
public R list(SysMenuEntity menu) {
// 获取登录人的userId;
String userId = SecurityUtils.getUserId();
List<SysMenuEntity> menus = menuService.selectMenuList(menu, userId);
return R.ok(menus);
}
@ApiOperation("分页获取菜单列表")
@GetMapping("/list-page")
public R listPage(@RequestParam(value = "menu", required = false) SysMenuEntity menu,
@RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize,
@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum) {
Page<SysMenuEntity> pageMenu = menuService.listPage(menu, SecurityUtils.getUserId(), pageSize, pageNum);
return R.ok(pageMenu);
}
@ApiOperation("添加菜单")
@PreAuthorize("@customSs.hasPermi('system:menu:create')")
@PostMapping("/create")
public R create(@RequestBody SysMenuEntity menu) {
if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu))) {
return R.error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
} else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StrUtil.startWithAny(menu.getPath(), "http://", "https://")) {
return R.error("新增菜单'" + menu.getMenuName() + "'失败地址必须以http(s)://开头");
}
boolean success = menuService.create(menu);
if (success) {
return R.ok();
}
return R.error("添加失败");
}
@ApiOperation("修改菜单")
@PreAuthorize("@customSs.hasPermi('system:menu:edit')")
@PostMapping("/update/{id}")
public R update(@PathVariable Long id, @RequestBody SysMenuEntity menu) {
menu.setMenuId(id);
if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu))) {
return R.error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
} else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StrUtil.startWithAny(menu.getPath(), "http://", "https://")) {
return R.error("修改菜单'" + menu.getMenuName() + "'失败地址必须以http(s)://开头");
} else if (menu.getMenuId().equals(menu.getParentId())) {
return R.error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
}
boolean success = menuService.updateById(menu);
if (success) {
return R.ok();
}
return R.error("修改失败");
}
@ApiOperation("删除菜单")
@PreAuthorize("@customSs.hasPermi('system:menu:delete')")
@PostMapping(value = "/delete/{id}")
public R delete(@PathVariable("id") Long menuId) {
if (menuService.hasChildByMenuId(menuId)) {
return R.error("存在子菜单,不允许删除");
}
boolean success = menuService.removeByIds(Collections.singletonList(menuId));
if (success) {
return R.ok();
}
return R.error("删除失败");
}
@ApiOperation("获取菜单下拉树列表")
@GetMapping("/treeselect")
public R treeselect(SysMenuEntity menu) {
List<SysMenuEntity> menus = menuService.selectMenuList(menu, SecurityUtils.getUserId());
List<TreeSelect> tree = menuService.buildMenuTreeSelect(menus);
return R.ok(tree);
}
@PreAuthorize("@customSs.hasPermi('system:menu:query')")
@ApiOperation("根据菜单编号获取详细信息")
@GetMapping(value = "/{menuId}")
public R getInfo(@PathVariable Long menuId) {
return R.ok(menuService.selectMenuById(menuId));
}
@ApiOperation("获取对应角色菜单列表树")
@GetMapping(value = "/roleMenuTreeselect/{roleId}")
public R roleMenuTreeselect(@PathVariable("roleId") Long roleId) {
List<SysMenuEntity> menus = menuService.selectMenuList(SecurityUtils.getUserId());
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("checkedKeys", menuService.selectMenuListByRoleId(roleId));
resultMap.put("menus", menuService.buildMenuTreeSelect(menus));
return R.ok(resultMap);
}
@GetMapping("/list-all-simple")
@ApiOperation(value = "获取菜单精简信息列表", notes = "只包含被开启的菜单,用于【角色分配菜单】功能的选项。" +
"在多租户的场景下,会只返回租户所在套餐有的菜单")
public R getSimpleMenus() {
// 获得菜单列表,只要开启状态的
List<SimpleMenu> menus = menuService.selectSimpleMenuList();
return R.ok(menus);
}
}

View File

@@ -0,0 +1,96 @@
package com.starry.admin.modules.system.controller;
import com.starry.admin.modules.system.entity.SysOperationLogEntity;
import com.starry.admin.modules.system.service.ISysOperationLogService;
import com.starry.admin.modules.system.vo.SysOperationLogVo;
import com.starry.admin.utils.ExcelUtils;
import com.starry.common.annotation.Log;
import com.starry.common.enums.BusinessType;
import com.starry.common.result.R;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
/**
* 操作日志表Controller
*
* @author admin
*/
@RestController
@RequestMapping("/system/operlog")
public class SysOperationLogController {
@Resource
private ISysOperationLogService xlOperLogService;
/**
* 查询操作日志表列表
*/
@PreAuthorize("@customSs.hasPermi('system:operlog:list')")
@GetMapping("/list")
public R list(SysOperationLogVo sysOperationLogEntity) {
return R.ok(xlOperLogService.selectXlOperLogList(sysOperationLogEntity));
}
/**
* 获取操作日志表详细信息
*/
@PreAuthorize("@customSs.hasPermi('system:operlog:query')")
@GetMapping(value = "/{operId}")
public R getInfo(@PathVariable("operId") Long operId) {
return R.ok(xlOperLogService.selectXlOperLogByOperId(operId));
}
/**
* 新增操作日志表
*/
@PreAuthorize("@customSs.hasPermi('system:operlog:create')")
@Log(title = "操作日志表", businessType = BusinessType.INSERT)
@PostMapping
public R create(@RequestBody SysOperationLogEntity sysOperationLogEntity) {
boolean success = xlOperLogService.create(sysOperationLogEntity);
if (success) {
return R.ok();
}
return R.error("添加失败");
}
/**
* 修改操作日志表
*/
@PreAuthorize("@customSs.hasPermi('system:operlog:edit')")
@Log(title = "操作日志表", businessType = BusinessType.UPDATE)
@PostMapping(value = "/update/{operId}")
public R update(@PathVariable Long operId, @RequestBody SysOperationLogEntity sysOperationLogEntity) {
sysOperationLogEntity.setOperId(operId);
boolean success = xlOperLogService.updateXlOperLog(sysOperationLogEntity);
if (success) {
return R.ok();
}
return R.error("修改失败");
}
/**
* 删除操作日志表
*/
@PreAuthorize("@customSs.hasPermi('system:operlog:remove')")
@Log(title = "操作日志表", businessType = BusinessType.DELETE)
@DeleteMapping("/{operIds}")
public R remove(@PathVariable Long[] operIds) {
return R.ok(xlOperLogService.deleteXlOperLogByOperIds(operIds));
}
/**
* 导出操作日志表
*/
@PreAuthorize("@customSs.hasPermi('system:operlog:export')")
@Log(title = "操作日志", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, SysOperationLogVo sysOperationLogEntity) {
ExcelUtils.exportEasyExcel(response, SysOperationLogEntity.class, xlOperLogService.selectXlOperLogList(sysOperationLogEntity).getRecords(), "系统操作日志表数据");
}
}

View File

@@ -0,0 +1,230 @@
package com.starry.admin.modules.system.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.starry.admin.modules.system.entity.SysDeptEntity;
import com.starry.admin.modules.system.entity.SysRoleEntity;
import com.starry.admin.modules.system.entity.SysUserRoleEntity;
import com.starry.admin.modules.system.service.SysDeptService;
import com.starry.admin.modules.system.service.SysRoleService;
import com.starry.admin.modules.system.service.SysUserService;
import com.starry.admin.modules.system.vo.RoleUserResultVo;
import com.starry.admin.modules.system.vo.SysRoleAddVo;
import com.starry.admin.modules.system.vo.SysUserQueryVo;
import com.starry.common.annotation.Log;
import com.starry.common.constant.UserConstants;
import com.starry.common.enums.BusinessType;
import com.starry.common.result.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* <p>
* 角色表 前端控制器
* </p>
*
* @author admin
* @since 2022-07-01
*/
@Api(tags = "角色管理")
@RestController
@RequestMapping("/ucenter/role")
public class SysRoleController {
@Resource
private SysRoleService roleService;
@Resource
private SysDeptService deptService;
@Resource
private SysUserService userService;
@ApiOperation("添加角色")
@PreAuthorize("@customSs.hasPermi('system:role:create')")
@PostMapping("/create")
public R create(@Valid @RequestBody SysRoleAddVo roleAddVo) {
SysRoleEntity role = new SysRoleEntity();
BeanUtils.copyProperties(roleAddVo, role);
if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) {
return R.error("新增角色'" + role.getRoleName() + "'失败,角色名称已存在");
} else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) {
return R.error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在");
}
boolean success = roleService.create(role);
if (success) {
return R.ok();
}
return R.error("添加失败");
}
@ApiOperation("修改角色")
@PreAuthorize("@customSs.hasPermi('system:role:edit')")
@PostMapping("/update/{id}")
public R update(@PathVariable Long id, @RequestBody SysRoleEntity role) {
role.setRoleId(id);
roleService.checkRoleAllowed(role);
roleService.checkRoleDataScope(role.getRoleId());
if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) {
return R.error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在");
} else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) {
return R.error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在");
}
boolean success = roleService.updateById(role);
if (success) {
return R.ok();
}
return R.error("修改失败");
}
@ApiOperation("批量删除角色")
@PreAuthorize("@customSs.hasPermi('system:role:remove')")
@DeleteMapping("/{roleIds}")
public R delete(@PathVariable Long[] roleIds) {
boolean success = roleService.delete(roleIds);
if (success) {
return R.ok();
}
return R.error("删除失败");
}
@ApiOperation("获取所有角色")
@GetMapping("/list-all")
public R listAll() {
List<SysRoleEntity> list = roleService.list();
return R.ok(list);
}
@ApiOperation("根据角色名称分页获取角色列表")
@GetMapping("/list-page")
public R listPage(@RequestParam(value = "keyword", required = false) String keyword, @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize, @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum) {
Page<SysRoleEntity> rolePage = roleService.list(keyword, pageSize, pageNum);
return R.ok(rolePage);
}
@ApiOperation("修改角色状态")
@PreAuthorize("@customSs.hasPermi('system:role:edit')")
@PostMapping("/update-status/{id}")
public R updateStatus(@PathVariable Long id, @RequestParam(value = "status") Integer status) {
SysRoleEntity role = new SysRoleEntity();
role.setRoleId(id);
role.setStatus(status);
boolean success = roleService.updateById(role);
if (success) {
return R.ok();
}
return R.error("修改失败");
}
@ApiOperation("分配菜单权限")
@PreAuthorize("@customSs.hasPermi('system:role:auth')")
@PostMapping("/auth-role-menu")
public R authRoleMenu(@RequestBody SysRoleEntity role) {
boolean success = roleService.authRoleMenu(role);
if (success) {
return R.ok();
}
return R.error("分配失败");
}
/**
* 根据角色编号获取详细信息
*/
@PreAuthorize("@customSs.hasPermi('system:role:query')")
@GetMapping(value = "/{roleId}")
public R getInfo(@PathVariable Long roleId) {
roleService.checkRoleDataScope(roleId);
return R.ok(roleService.getById(roleId));
}
/**
* 获取对应角色部门树列表
*/
@ApiOperation("获取对应角色部门树列表")
@PreAuthorize("@customSs.hasPermi('system:role:query')")
@GetMapping(value = "/deptTree/{roleId}")
public R deptTree(@PathVariable("roleId") Long roleId) {
Map<String, Object> resultMap = new HashMap<>(8);
resultMap.put("checkedKeys", deptService.selectDeptListByRoleId(roleId));
resultMap.put("depts", deptService.selectDeptTreeList(new SysDeptEntity()));
return R.ok(resultMap);
}
/**
* 修改保存数据权限
*/
@ApiOperation("修改保存数据权限")
@PreAuthorize("@customSs.hasPermi('system:role:query')")
@Log(title = "角色管理-保存数据权限", businessType = BusinessType.UPDATE)
@PostMapping("/dataScope")
public R dataScope(@RequestBody SysRoleEntity role) {
roleService.checkRoleAllowed(role);
roleService.checkRoleDataScope(role.getRoleId());
return R.ok(roleService.authDataScope(role));
}
/**
* 查询已分配用户角色列表
*/
@ApiOperation("查询已分配用户角色列表")
@PreAuthorize("@customSs.hasPermi('system:role:list')")
@GetMapping("/authUser/allocatedList")
public R allocatedList(SysUserQueryVo user) {
IPage<RoleUserResultVo> list = userService.selectAllocatedList(user);
return R.ok(list);
}
/**
* 查询未分配用户角色列表
*/
@ApiOperation("查询未分配用户角色列表")
@PreAuthorize("@customSs.hasPermi('system:role:list')")
@GetMapping("/authUser/unallocatedList")
public R unallocatedList(SysUserQueryVo user) {
return R.ok(userService.selectUnallocatedList(user));
}
/**
* 取消授权用户
*/
@ApiOperation("取消授权用户")
@PreAuthorize("@customSs.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.GRANT)
@PutMapping("/authUser/cancel")
public R cancelAuthUser(@RequestBody SysUserRoleEntity userRole) {
return R.ok(roleService.deleteAuthUser(userRole));
}
/**
* 批量取消授权用户
*/
@ApiOperation("批量取消授权用户")
@PreAuthorize("@customSs.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.GRANT)
@PutMapping("/authUser/cancelAll")
public R cancelAuthUserAll(Long roleId, String[] userIds) {
return R.ok(roleService.deleteAuthUsers(roleId, userIds));
}
/**
* 批量选择用户授权
*/
@ApiOperation("批量选择用户授权")
@PreAuthorize("@customSs.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.GRANT)
@PutMapping("/authUser/selectAll")
public R selectAuthUserAll(Long roleId, String[] userIds) {
roleService.checkRoleDataScope(roleId);
return R.ok(roleService.insertAuthUsers(roleId, userIds));
}
}

View File

@@ -0,0 +1,148 @@
package com.starry.admin.modules.system.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.starry.admin.common.component.JwtToken;
import com.starry.admin.common.domain.LoginUser;
import com.starry.admin.modules.system.entity.SysRoleEntity;
import com.starry.admin.modules.system.entity.SysUserEntity;
import com.starry.admin.modules.system.service.SysRoleService;
import com.starry.admin.modules.system.service.SysUserService;
import com.starry.admin.modules.system.vo.UserQueryVo;
import com.starry.admin.utils.SecurityUtils;
import com.starry.common.annotation.Log;
import com.starry.common.constant.UserConstants;
import com.starry.common.enums.BusinessType;
import com.starry.common.result.R;
import com.starry.common.utils.file.CosClientUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* <p>
* 后台用户表 前端控制器
* </p>
*
* @author admin
* @since 2021-09-03
*/
@Api(tags = "用户管理")
@RestController
@RequestMapping("/ucenter/user")
public class SysUserController {
@Resource
private SysUserService userService;
@Resource
private SysRoleService roleService;
@Resource
private JwtToken tokenService;
@ApiOperation(value = "注册用户")
@PostMapping(value = "register")
public R register(@RequestBody SysUserEntity user) {
SysUserEntity sysUserEntity = userService.register(user);
if (sysUserEntity == null) {
return R.error("注册失败,用户名已存在");
}
return R.ok(sysUserEntity);
}
@ApiOperation(value = "分页用户列表")
@GetMapping(value = "/list-page")
public R listPage(UserQueryVo queryVo) {
IPage<SysUserEntity> page = userService.listMemberPage(queryVo);
return R.ok(page);
}
@ApiOperation(value = "添加用户")
@PostMapping(value = "add")
public R add(@RequestBody SysUserEntity user) {
if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user.getUserCode()))) {
return R.error("新增用户'" + user.getUserCode() + "'失败,登录账号已存在");
}
boolean success = userService.create(user);
if (success) {
return R.ok();
}
return R.error("添加失败");
}
@ApiOperation(value = "修改用户")
@PostMapping(value = "/update/{id}")
public R update(@PathVariable("id") String id, @RequestBody SysUserEntity user) {
user.setUserId(id);
boolean flag = userService.update(user);
if (flag) {
return R.ok();
}
return R.error("修改失败");
}
@ApiOperation(value = "删除用户")
@PostMapping(value = "/delete/{id}")
public R delete(@PathVariable("id") String id) {
boolean flag = userService.delete(Collections.singletonList(id));
if (flag) {
return R.ok();
}
return R.error();
}
@ApiOperation(value = "登出功能")
@PostMapping(value = "logout")
public R logout() {
return R.ok();
}
@ApiOperation(value = "根据用户id获取详细信息")
@GetMapping(value = {"/", "/{userId}"})
public R getInfo(@PathVariable(value = "userId", required = false) String userId) {
Map<String, Object> map = new HashMap<>(8);
List<SysRoleEntity> roles = roleService.selectRoleList(new SysRoleEntity());
map.put("roles", SysUserEntity.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
if (userId != null) {
SysUserEntity user = userService.selectUserById(userId);
map.put("roleIds", user.getRoles().stream().map(SysRoleEntity::getRoleId).collect(Collectors.toList()));
map.put("user", user);
}
return R.ok(map);
}
@ApiOperation(value = "获取个人信息")
@GetMapping(value = "/profile")
public R getProfile() {
Map<String, Object> map = new HashMap<>(8);
SysUserEntity loginUser = userService.selectUserById(SecurityUtils.getUserId());
map.put("user", loginUser);
map.put("roleGroup", userService.selectUserRoleGroup(loginUser.getUserId()));
return R.ok(map);
}
@ApiOperation(value = "用户头像上传")
@Log(title = "用户头像上传", businessType = BusinessType.UPDATE)
@PostMapping("/profile/avatar")
public R uploadAvatar(@RequestParam("avatarfile") MultipartFile file) throws Exception {
if (!file.isEmpty()) {
String avatar = CosClientUtils.upload(file, "avatar");
if (userService.updateUserAvatar(SecurityUtils.getUserId(), avatar)) {
// 更新缓存用户头像
LoginUser loginUser = SecurityUtils.getLoginUser();
loginUser.getUser().setAvatar(avatar);
tokenService.refreshToken(loginUser);
return R.ok(avatar);
}
}
return R.error("上传头像异常,请联系管理员");
}
}

View File

@@ -0,0 +1,71 @@
package com.starry.admin.modules.system.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.starry.common.domain.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.ArrayList;
import java.util.List;
/**
* <p>
* 部门表
* </p>
*
* @author admin
* @since 2022-07-12
*/
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("sys_dept")
@ApiModel(value = "XlDept对象", description = "部门表")
public class SysDeptEntity extends BaseEntity<SysDeptEntity> {
private static final long serialVersionUID = 1L;
@ApiModelProperty("主键ID")
@TableId(value = "dept_id", type = IdType.AUTO)
private Long deptId;
@ApiModelProperty("父部门id")
private Long parentId;
@ApiModelProperty("祖级列表")
private String ancestors;
@ApiModelProperty("部门名称")
private String deptName;
@ApiModelProperty("显示顺序")
private Integer sort;
@ApiModelProperty("负责人")
private String leader;
@ApiModelProperty("联系电话")
private String phone;
@ApiModelProperty("邮箱")
private String email;
@ApiModelProperty("部门状态0正常 1停用")
private Integer status;
@ApiModelProperty("部门级别")
private Integer deptLevel;
@ApiModelProperty("租户ID")
private String tenantId;
/**
* 子部门
*/
@TableField(exist = false)
private List<SysDeptEntity> children = new ArrayList<>();
}

View File

@@ -0,0 +1,72 @@
package com.starry.admin.modules.system.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.starry.common.domain.BaseEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 字典数据表对象 sys_dict_data
*
* @author admin
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("sys_dict_data")
public class SysDictDataEntity extends BaseEntity<SysDictDataEntity> {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ApiModelProperty("主键ID")
@TableId(value = "dict_data_id", type = IdType.AUTO)
private Long dictDataId;
/**
* 字典类型
*/
private String dictType;
/**
* 字典名称
*/
private String dictLabel;
/**
* 字典值
*/
private String dictValue;
/**
* 显示顺序
*/
private Long sort;
/**
* 是否默认Y是 N否
*/
private String isDefault;
/**
* 表格回显样式
*/
private String listClass;
/**
* 状态0正常 1停用
*/
private Integer status;
/**
* 备注
*/
private String remark;
}

View File

@@ -0,0 +1,53 @@
package com.starry.admin.modules.system.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.starry.common.domain.BaseEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 字典表对象 sys_dict
*
* @author admin
* @since 2022-08-09
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("sys_dict")
public class SysDictEntity extends BaseEntity<SysDictEntity> {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ApiModelProperty("主键ID")
@TableId(value = "dict_id", type = IdType.AUTO)
private Long dictId;
/**
* 字典类型
*/
private String dictType;
/**
* 字典名称
*/
private String dictName;
/**
* 状态0正常 1停用
*/
private Integer status;
/**
* 备注
*/
private String remark;
}

View File

@@ -0,0 +1,86 @@
package com.starry.admin.modules.system.entity;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.starry.admin.modules.system.vo.StatusConverter;
import com.starry.common.domain.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
/**
* 系统访问日志表对象 sys_login_log
*
* @author admin
*/
@EqualsAndHashCode(callSuper = true)
@ExcelIgnoreUnannotated
@Data
@TableName("sys_login_log")
@ApiModel(value = "XlLoginLog对象", description = "登录日志表")
public class SysLoginLogEntity extends BaseEntity<SysLoginLogEntity> {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ApiModelProperty("主键ID")
@TableId(value = "login_id", type = IdType.AUTO)
private Long loginId;
/**
* 用户账号
*/
@ExcelProperty(value = "用户账号")
private String userCode;
/**
* 登录IP地址
*/
@ExcelProperty(value = "登录IP地址")
private String ipaddr;
/**
* 登录地点
*/
@ExcelProperty(value = "登录地点")
private String loginLocation;
/**
* 浏览器类型
*/
@ExcelProperty(value = "浏览器类型")
private String browser;
/**
* 操作系统
*/
@ExcelProperty(value = "操作系统")
private String os;
/**
* 提示消息
*/
private String msg;
/**
* 登录状态0成功 1失败
*/
@ExcelProperty(value = "登录状态", converter = StatusConverter.class)
private Integer status;
/**
* 访问时间
*/
private Date loginTime;
}

View File

@@ -0,0 +1,78 @@
package com.starry.admin.modules.system.entity;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.starry.admin.modules.system.vo.StatusConverter;
import com.starry.common.domain.BasePageEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
/**
* 系统访问日志表对象 sys_login_log
*
* @author admin
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class SysLoginLogVo extends BasePageEntity {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@TableId(value = "login_id", type = IdType.AUTO)
private Long loginId;
/**
* 用户账号
*/
@ExcelProperty(value = "用户账号")
private String userCode;
/**
* 登录IP地址
*/
@ExcelProperty(value = "登录IP地址")
private String ipaddr;
/**
* 登录地点
*/
@ExcelProperty(value = "登录地点")
private String loginLocation;
/**
* 浏览器类型
*/
@ExcelProperty(value = "浏览器类型")
private String browser;
/**
* 操作系统
*/
@ExcelProperty(value = "操作系统")
private String os;
/**
* 提示消息
*/
private String msg;
/**
* 登录状态0成功 1失败
*/
@ExcelProperty(value = "登录状态", converter = StatusConverter.class)
private Integer status;
/**
* 访问时间
*/
private Date loginTime;
}

View File

@@ -0,0 +1,86 @@
package com.starry.admin.modules.system.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.starry.common.domain.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.List;
/**
* <p>
* 菜单表
* </p>
*
* @author admin
* @since 2022-07-03
*/
@Getter
@Setter
@TableName("sys_menu")
@ApiModel(value = "XlMenu对象", description = "菜单表")
public class SysMenuEntity extends BaseEntity<SysMenuEntity> {
private static final long serialVersionUID = 1L;
@ApiModelProperty("菜单ID")
@TableId(value = "menu_id", type = IdType.AUTO)
private Long menuId;
@ApiModelProperty("菜单名")
private String menuName;
@ApiModelProperty("菜单编码")
private String menuCode;
@ApiModelProperty("权限字符串")
private String permission;
@ApiModelProperty("图标")
private String icon;
@ApiModelProperty("菜单级别")
private Long menuLevel;
@ApiModelProperty("排序")
private Integer sort;
@ApiModelProperty("父ID")
private Long parentId;
@ApiModelProperty("菜单类型;0:目录,1:菜单,2:按钮")
private String menuType;
@ApiModelProperty("菜单状态;0正常 1停用")
private Integer status;
@ApiModelProperty("备注")
private String remark;
@ApiModelProperty("路由地址")
private String path;
@ApiModelProperty("组件路径")
private String component;
@ApiModelProperty("路由参数")
private String routerQuery;
@ApiModelProperty("是否为外链0否 1是")
private Integer isFrame;
@ApiModelProperty("菜单状态;0:隐藏 1:显示")
private Integer visible;
/**
* 子菜单
*/
@TableField(exist = false)
private List<SysMenuEntity> children = new ArrayList<>();
}

View File

@@ -0,0 +1,131 @@
package com.starry.admin.modules.system.entity;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.starry.common.domain.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
/**
* 操作日志表对象 sys_operation_log
*
* @author admin
*/
@EqualsAndHashCode(callSuper = true)
@ExcelIgnoreUnannotated
@Data
@TableName("sys_operation_log")
@ApiModel(value = "SysOperationLog对象", description = "操作日志表")
public class SysOperationLogEntity extends BaseEntity<SysOperationLogEntity> {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ApiModelProperty("主键ID")
@TableId(value = "oper_id", type = IdType.AUTO)
private Long operId;
/**
* 模块标题
*/
@ExcelProperty(value = "系统模块")
private String title;
/**
* 业务类型0其它 1新增 2修改 3删除
*/
private Integer businessType;
/**
* 业务类型数组
*/
@TableField(exist = false)
private Integer[] businessTypes;
/**
* 方法名称
*/
@ExcelProperty(value = "方法名称")
private String method;
/**
* 请求方式
*/
private String requestMethod;
/**
* 操作类别0其它 1后台用户 2手机端用户
*/
private Integer operatorType;
/**
* 操作人员
*/
private String operName;
/**
* 请求URL
*/
private String operUrl;
/**
* 主机地址
*/
private String operIp;
/**
* 操作地点
*/
private String operLocation;
/**
* 请求参数
*/
private String operParam;
/**
* 返回参数
*/
private String jsonResult;
/**
* 操作状态0正常 1异常
*/
private Integer status;
/**
* 错误消息
*/
private String errorMsg;
/**
* 操作时间
*/
private Date operTime;
/**
* 部门名称
*/
private String deptName;
/**
* 部门id
*/
private Long deptId;
/**
* 租户ID
*/
private Long tenantId;
}

View File

@@ -0,0 +1,41 @@
package com.starry.admin.modules.system.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.starry.common.domain.BaseEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 角色部门表对象 sys_dict_data
*
* @author admin
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("sys_role_dept")
public class SysRoleDeptEntity extends BaseEntity<SysRoleDeptEntity> {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ApiModelProperty("主键ID")
@TableId(value = "role_dept_id", type = IdType.AUTO)
private Long roleDeptId;
@ApiModelProperty("角色ID")
private Long roleId;
@ApiModelProperty("菜单ID")
private Long deptId;
@ApiModelProperty("租户ID")
private Long tenantId;
}

View File

@@ -0,0 +1,90 @@
package com.starry.admin.modules.system.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.starry.common.domain.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.util.Set;
/**
* <p>
* 角色表
* </p>
*
* @author admin
* @since 2022-07-01
*/
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("sys_role")
@NoArgsConstructor
@ApiModel(value = "XlRole对象", description = "角色表")
public class SysRoleEntity extends BaseEntity<SysRoleEntity> {
private static final long serialVersionUID = 1L;
@ApiModelProperty("角色ID")
@TableId(value = "role_id", type = IdType.AUTO)
private Long roleId;
@ApiModelProperty("角色名称")
private String roleName;
@ApiModelProperty("角色描述")
private String description;
@ApiModelProperty("状态;0正常 1停用")
private Integer status;
@ApiModelProperty("数据范围1所有数据权限2自定义数据权限3本部门数据权限4本部门及以下数据权限5仅本人数据权限 ")
private String dataScope;
@ApiModelProperty("菜单树选择项是否关联显示( 0父子不互相关联显示 1父子互相关联显示")
private boolean menuCheckStrictly;
@ApiModelProperty("部门树选择项是否关联显示0父子不互相关联显示 1父子互相关联显示 ")
private boolean deptCheckStrictly;
@ApiModelProperty("角色权限")
private String roleKey;
@ApiModelProperty("租户ID")
private String tenantId;
/**
* 菜单组
*/
@TableField(exist = false)
private Long[] menuIds;
/**
* 部门组(数据权限)
*/
@TableField(exist = false)
private Long[] deptIds;
/**
* 角色菜单权限
*/
@TableField(exist = false)
private Set<String> permissions;
public SysRoleEntity(Long roleId) {
this.roleId = roleId;
}
public static boolean isAdmin(Long roleId) {
return roleId != null && 1L == roleId;
}
public boolean isAdmin() {
return isAdmin(this.roleId);
}
}

View File

@@ -0,0 +1,42 @@
package com.starry.admin.modules.system.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.starry.common.domain.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* 角色和菜单关联表
* </p>
*
* @author admin
* @since 2022-07-06
*/
@Getter
@Setter
@TableName("sys_role_menu")
@ApiModel(value = "SysRoleMenu对象", description = "角色和菜单关联表")
public class SysRoleMenuEntity extends BaseEntity<SysRoleMenuEntity> {
private static final long serialVersionUID = 1L;
@ApiModelProperty("主键id")
@TableId(value = "role_menu_id", type = IdType.AUTO)
private Long roleMenuId;
@ApiModelProperty("角色ID")
private Long roleId;
@ApiModelProperty("菜单ID")
private Long menuId;
@ApiModelProperty("租户ID")
private String tenantId;
}

View File

@@ -0,0 +1,115 @@
package com.starry.admin.modules.system.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.starry.common.domain.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.util.Date;
import java.util.List;
/**
* <p>
* 用户表
* </p>
*
* @author admin
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value = "SysUser对象", description = "用户表")
@TableName("sys_user")
public class SysUserEntity extends BaseEntity<SysUserEntity> {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "用户ID")
@TableId(value = "user_id", type = IdType.AUTO)
private String userId;
@ApiModelProperty(value = "用户类型;1:admin;2:会员")
private Integer userType;
@ApiModelProperty(value = "用户名")
private String userCode;
@ApiModelProperty(value = "密码")
private String passWord;
@ApiModelProperty(value = "姓名")
private String realName;
@ApiModelProperty(value = "用户昵称")
private String userNickname;
@ApiModelProperty(value = "邮箱")
private String userEmail;
@ApiModelProperty(value = "用户头像")
private String avatar;
@ApiModelProperty(value = "中国手机不带国家代码,国际手机号格式为:国家代码-手机号")
private String mobile;
@ApiModelProperty(value = "性别 0未知12")
private Integer sex;
@ApiModelProperty(value = "出生年月")
private Date birthday;
@ApiModelProperty(value = "用户状态;0正常 1停用")
private Integer status;
@ApiModelProperty(value = "最后登录时间")
private Date lastLoginTime;
@ApiModelProperty(value = "最后登录ip")
private String lastLoginIp;
@ApiModelProperty(value = "所属部门id")
private Long deptId;
@ApiModelProperty(value = "租户id")
private String tenantId;
/**
* 角色对象
*/
@TableField(exist = false)
private List<SysRoleEntity> roles;
/**
* 角色组
*/
@TableField(exist = false)
private Long[] roleIds;
/**
* 部门对象
*/
@TableField(exist = false)
private SysDeptEntity dept;
/**
* 角色ID
*/
@TableField(exist = false)
private Long roleId;
public static boolean isAdmin(String userId) {
return "6dcb2da45fef4768a6511f9c14e18072".equals(userId);
}
public boolean isAdmin() {
return isAdmin(this.userId);
}
}

View File

@@ -0,0 +1,40 @@
package com.starry.admin.modules.system.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.starry.common.domain.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* 用户角色关联表
* </p>
*
* @author admin
* @since 2022-07-08
*/
@Getter
@Setter
@TableName("sys_user_role")
@ApiModel(value = "SysUserRole对象", description = "用户角色关联表")
public class SysUserRoleEntity extends BaseEntity<SysUserRoleEntity> {
private static final long serialVersionUID = 1L;
@ApiModelProperty("主键ID")
@TableId(value = "user_role_id", type = IdType.AUTO)
private Long userRoleId;
@ApiModelProperty("用户ID")
private String userId;
@ApiModelProperty("角色ID")
private Long roleId;
@ApiModelProperty(value = "租户id")
private String tenantId;
}

View File

@@ -0,0 +1,55 @@
package com.starry.admin.modules.system.mapper;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.starry.admin.modules.system.entity.SysDeptEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* <p>
* 部门表 Mapper 接口
* </p>
*
* @author admin
* @since 2022-07-12
*/
@Mapper
public interface SysDeptMapper extends BaseMapper<SysDeptEntity> {
/**
* 查询部门管理数据
*
* @param dept 部门信息
* @return 部门信息集合
*/
List<SysDeptEntity> selectDeptList(@Param(value = "dept") SysDeptEntity dept);
/**
* 根据ID查询所有子部门
*
* @param deptId 部门ID
* @return 部门列表
*/
List<SysDeptEntity> selectChildrenDeptById(Long deptId);
/**
* 删除部门信息-根据租户ID
*
* @param ids 租户id
* @return 结果
*/
@InterceptorIgnore(tenantLine = "1")
int deleteDeptByTenantId(String[] ids);
/**
* 根据角色ID查询部门树信息
*
* @param roleId 角色ID
* @param deptCheckStrictly 部门树选择项是否关联显示
* @return 选中部门列表
*/
List<Long> selectDeptListByRoleId(@Param("roleId") Long roleId, @Param("deptCheckStrictly") boolean deptCheckStrictly);
}

View File

@@ -0,0 +1,43 @@
package com.starry.admin.modules.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.starry.admin.modules.system.entity.SysDictDataEntity;
import com.starry.admin.modules.system.vo.SysDictDataVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 字典数据表Mapper接口
*
* @author admin
*/
@Mapper
public interface SysDictDataMapper extends BaseMapper<SysDictDataEntity> {
/**
* 查询字典数据表
*
* @param dictDataId 字典数据表主键
* @return 字典数据表
*/
SysDictDataEntity selectXlDictDataByDictDataId(Long dictDataId);
/**
* 查询字典数据表列表
*
* @param sysDictDataEntity 字典数据表
* @return 字典数据表集合
*/
IPage<SysDictDataEntity> selectXlDictDataList(Page<SysDictDataEntity> page, @Param("vo") SysDictDataVo sysDictDataEntity);
/**
* 根据字典类型查询字典数据
*
* @param dictType 字典类型
* @return 字典数据集合信息
*/
List<SysDictDataEntity> selectDictDataByType(String dictType);
}

View File

@@ -0,0 +1,34 @@
package com.starry.admin.modules.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.starry.admin.modules.system.entity.SysDictEntity;
import com.starry.admin.modules.system.vo.SysDictVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* 字典表Mapper接口
*
* @author admin
*/
@Mapper
public interface SysDictMapper extends BaseMapper<SysDictEntity> {
/**
* 查询字典表
*
* @param dictId 字典表主键
* @return 字典表
*/
SysDictEntity selectXlDictByDictId(Long dictId);
/**
* 查询字典表列表
*
* @param sysDictEntity 字典表
* @return 字典表集合
*/
Page<SysDictEntity> selectXlDictList(IPage<SysDictEntity> page, @Param(value = "sysDictVo") SysDictVo sysDictEntity);
}

View File

@@ -0,0 +1,41 @@
package com.starry.admin.modules.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.starry.admin.modules.system.entity.SysLoginLogEntity;
import com.starry.admin.modules.system.entity.SysLoginLogVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* 系统访问日志表Mapper接口
*
* @author admin
*/
@Mapper
public interface SysLoginLogMapper extends BaseMapper<SysLoginLogEntity> {
/**
* 查询系统访问日志表
*
* @param loginId 系统访问日志表主键
* @return 系统访问日志表
*/
SysLoginLogEntity selectXlLoginLogByLoginId(Long loginId);
/**
* 查询系统访问日志表列表
*
* @param sysLoginLogEntity 系统访问日志表
* @return 系统访问日志表集合
*/
IPage<SysLoginLogEntity> selectXlLoginLogList(Page<SysLoginLogEntity> page, @Param("vo") SysLoginLogVo sysLoginLogEntity);
/**
* 清空系统登录日志
*
* @return 结果
*/
int cleanLoginlog();
}

View File

@@ -0,0 +1,75 @@
package com.starry.admin.modules.system.mapper;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.starry.admin.modules.system.entity.SysMenuEntity;
import com.starry.admin.modules.system.vo.SimpleMenu;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* <p>
* 菜单表 Mapper 接口
* </p>
*
* @author admin
* @since 2022-07-03
*/
@Mapper
public interface SysMenuMapper extends BaseMapper<SysMenuEntity> {
List<SysMenuEntity> selectMenuListByUserId(@Param(value = "menu") SysMenuEntity menu, @Param(value = "userId") String userId, Page page);
/**
* 查询系统菜单列表
*
* @param menu 菜单信息
* @return 菜单列表
*/
List<SysMenuEntity> selectMenuList(SysMenuEntity menu);
List<SysMenuEntity> selectMenuListByUserId(@Param(value = "menu") SysMenuEntity menu, @Param(value = "userId") String userId);
/**
* 根据角色ID查询菜单树信息
*
* @param roleId 角色ID
* @param menuCheckStrictly 菜单树选择项是否关联显示
* @return 选中菜单列表
*/
List<Long> selectMenuListByRoleId(@Param("roleId") Long roleId, @Param("menuCheckStrictly") boolean menuCheckStrictly);
/**
* 根据用户ID查询权限
*
* @param userId 用户ID
* @return 权限列表
*/
@InterceptorIgnore(tenantLine = "1")
List<String> selectMenuPermsByUserId(String userId);
/**
* 查询菜单
*
* @return 菜单列表
*/
List<SysMenuEntity> selectMenuTreeAll();
/**
* 根据用户ID查询菜单
*
* @param userId 用户ID
* @return 菜单列表
*/
List<SysMenuEntity> selectMenuTreeByUserId(String userId);
/**
* 查询所有开启状态菜单精简信息
*
* @return 菜单列表
*/
List<SimpleMenu> selectSimpleMenuList();
}

View File

@@ -0,0 +1,34 @@
package com.starry.admin.modules.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.starry.admin.modules.system.entity.SysOperationLogEntity;
import com.starry.admin.modules.system.vo.SysOperationLogVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* 操作日志表Mapper接口
*
* @author admin
*/
@Mapper
public interface SysOperationLogMapper extends BaseMapper<SysOperationLogEntity> {
/**
* 查询操作日志表
*
* @param operId 操作日志表主键
* @return 操作日志表
*/
SysOperationLogEntity selectXlOperLogByOperId(Long operId);
/**
* 查询操作日志表列表
*
* @param sysOperationLogEntity 操作日志表
* @return 操作日志表集合
*/
IPage<SysOperationLogEntity> selectXlOperLogList(Page<SysOperationLogEntity> page, @Param("vo") SysOperationLogVo sysOperationLogEntity);
}

View File

@@ -0,0 +1,54 @@
package com.starry.admin.modules.system.mapper;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.starry.admin.modules.system.entity.SysRoleDeptEntity;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* <p>
* 角色和部门关联表 Mapper 接口
* </p>
*
* @author admin
* @since 2022-07-06
*/
@Mapper
public interface SysRoleDeptMapper extends BaseMapper<SysRoleDeptEntity> {
/**
* 通过租户ID删除角色和部门关联
*
* @param tenantId 租户ID
* @return 结果
*/
@InterceptorIgnore(tenantLine = "1")
int deleteRoleDeptByTenantId(Long tenantId);
/**
* 通过角色ID删除角色和部门关联
*
* @param roleId 角色ID
* @return 结果
*/
int deleteRoleDeptByRoleId(Long roleId);
/**
* 批量新增角色部门信息
*
* @param roleDeptList 角色部门列表
* @return 结果
*/
int batchRoleDept(List<SysRoleDeptEntity> roleDeptList);
/**
* 批量删除角色部门关联信息
*
* @param ids 需要删除的数据ID
* @return 结果
*/
int deleteRoleDept(Long[] ids);
}

View File

@@ -0,0 +1,88 @@
package com.starry.admin.modules.system.mapper;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.starry.admin.modules.system.entity.SysRoleEntity;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* <p>
* 角色表 Mapper 接口
* </p>
*
* @author admin
* @since 2022-07-01
*/
@Mapper
public interface SysRoleMapper extends BaseMapper<SysRoleEntity> {
/**
* 通过角色ID查询角色
*
* @param roleId 角色ID
* @return 角色对象信息
*/
SysRoleEntity selectRoleById(Long roleId);
/**
* 校验角色名称是否唯一
*
* @param roleName 角色名称
* @return 角色信息
*/
SysRoleEntity checkRoleNameUnique(String roleName);
/**
* 校验角色权限是否唯一
*
* @param roleKey 角色权限
* @return 角色信息
*/
SysRoleEntity checkRoleKeyUnique(String roleKey);
/**
* 根据用户ID查询角色
*
* @param userId 用户ID
* @return 角色列表
*/
List<SysRoleEntity> selectRolePermissionByUserId(String userId);
/**
* 根据条件分页查询角色数据
*
* @param role 角色信息
* @return 角色数据集合信息
*/
List<SysRoleEntity> selectRoleList(SysRoleEntity role);
/**
* 根据租户ID查询默认管理员角色
*
* @param tenantId 租户ID
* @return 角色
*/
@InterceptorIgnore(tenantLine = "1")
List<SysRoleEntity> queryAdminRole(String tenantId);
/**
* 批量删除角色信息-根据租户
*
* @param ids 需要删除的租户id
* @return 结果
*/
@InterceptorIgnore(tenantLine = "1")
int deleteRoleByTenantId(String[] ids);
/**
* 通过角色ID查询角色使用数量
*
* @param roleId 角色ID
* @return 结果
*/
int countUserRoleByRoleId(Long roleId);
}

View File

@@ -0,0 +1,45 @@
package com.starry.admin.modules.system.mapper;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.starry.admin.modules.system.entity.SysRoleMenuEntity;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 角色和菜单关联表 Mapper 接口
* </p>
*
* @author admin
* @since 2022-07-06
*/
@Mapper
public interface SysRoleMenuMapper extends BaseMapper<SysRoleMenuEntity> {
/**
* 通过租户ID删除角色和菜单关联
*
* @param tenantId 租户ID
* @return 结果
*/
@InterceptorIgnore(tenantLine = "1")
int deleteRoleMenuByTenantId(String tenantId);
/**
* 通过租户ID删除角色和菜单关联
*
* @param ids 租户ID
* @return 结果
*/
@InterceptorIgnore(tenantLine = "1")
int deleteRoleMenuByTenantIds(String[] ids);
/**
* 批量删除角色菜单关联信息
*
* @param ids 需要删除的数据ID
* @return 结果
*/
int deleteRoleMenu(Long[] ids);
}

View File

@@ -0,0 +1,85 @@
package com.starry.admin.modules.system.mapper;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.starry.admin.modules.system.entity.SysUserEntity;
import com.starry.admin.modules.system.vo.RoleUserResultVo;
import com.starry.admin.modules.system.vo.SysUserQueryVo;
import com.starry.admin.modules.system.vo.UserQueryVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* <p>
* 后台用户表 Mapper 接口
* </p>
*
* @author admin
* @since 2021-09-03
*/
@Mapper
public interface SysUserMapper extends BaseMapper<SysUserEntity> {
/**
* 通过用户ID查询用户
*
* @param userId 用户ID
* @return 用户对象信息
*/
SysUserEntity selectUserById(String userId);
/**
* 根据条件分页查询用户列表
*
* @param queryVo 条件信息
* @param page 分页信息
* @return 用户信息集合信息
*/
IPage<SysUserEntity> selectUserList(IPage<SysUserEntity> page, @Param("user") UserQueryVo queryVo);
/**
* 通过用户名查询用户
*
* @param userName 用户名
* @return 用户对象信息
*/
@InterceptorIgnore(tenantLine = "1")
SysUserEntity selectUserByUserName(String userName);
/**
* 校验用户名称是否唯一
*
* @param userName 用户名称
* @return 结果
*/
@InterceptorIgnore(tenantLine = "1")
int checkUserNameUnique(String userName);
/**
* 批量删除用户信息-根据租户
*
* @param ids 需要删除的租户ID
* @return 结果
*/
@InterceptorIgnore(tenantLine = "1")
int deleteUserByTenantId(String[] ids);
/**
* 根据条件分页查询已配用户角色列表
*
* @param user 用户信息
* @return 用户信息集合信息
*/
IPage<RoleUserResultVo> selectAllocatedList(Page<RoleUserResultVo> page, @Param("query") SysUserQueryVo user);
/**
* 根据条件分页查询未配用户角色列表
*
* @param user 用户信息
* @return 用户信息集合信息
*/
IPage<RoleUserResultVo> selectUnallocatedList(Page<RoleUserResultVo> page, @Param("query") SysUserQueryVo user);
}

View File

@@ -0,0 +1,46 @@
package com.starry.admin.modules.system.mapper;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.starry.admin.modules.system.entity.SysUserRoleEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* <p>
* 用户角色关联表 Mapper 接口
* </p>
*
* @author admin
* @since 2022-07-08
*/
@Mapper
public interface SysUserRoleMapper extends BaseMapper<SysUserRoleEntity> {
/**
* 批量删除用户和角色关联-根据租户
*
* @param ids 需要删除的用户租户id
* @return 结果
*/
@InterceptorIgnore(tenantLine = "1")
int deleteUserRoleByTenantId(String[] ids);
/**
* 删除用户和角色关联信息
*
* @param userRole 用户和角色关联信息
* @return 结果
*/
int deleteUserRoleInfo(SysUserRoleEntity userRole);
/**
* 批量取消授权用户角色
*
* @param roleId 角色ID
* @param userIds 需要删除的用户数据ID
* @return 结果
*/
int deleteUserRoleInfos(@Param("roleId") Long roleId, @Param("userIds") String[] userIds);
}

View File

@@ -0,0 +1,71 @@
package com.starry.admin.modules.system.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.starry.admin.modules.system.entity.SysDictDataEntity;
import com.starry.admin.modules.system.vo.SysDictDataVo;
import java.util.List;
/**
* 字典数据表Service接口
*
* @author admin
*/
public interface ISysDictDataService extends IService<SysDictDataEntity> {
/**
* 查询字典数据表
*
* @param dictDataId 字典数据表主键
* @return 字典数据表
*/
SysDictDataEntity selectXlDictDataByDictDataId(Long dictDataId);
/**
* 查询字典数据表列表
*
* @param sysDictDataEntity 字典数据表
* @return 字典数据表集合
*/
IPage<SysDictDataEntity> selectXlDictDataList(SysDictDataVo sysDictDataEntity);
/**
* 新增字典数据表
*
* @param sysDictDataEntity 字典数据表
* @return 结果
*/
boolean create(SysDictDataEntity sysDictDataEntity);
/**
* 修改字典数据表
*
* @param sysDictDataEntity 字典数据表
* @return 结果
*/
boolean update(SysDictDataEntity sysDictDataEntity);
/**
* 批量删除字典数据表
*
* @param dictDataIds 需要删除的字典数据表主键集合
* @return 结果
*/
int deleteXlDictDataByDictDataIds(Long[] dictDataIds);
/**
* 删除字典数据表信息
*
* @param dictDataId 字典数据表主键
* @return 结果
*/
int deleteXlDictDataByDictDataId(Long dictDataId);
/**
* 根据字典类型查询字典数据
*
* @param dictType 字典类型
* @return 字典数据集合信息
*/
List<SysDictDataEntity> selectDictDataByType(String dictType);
}

View File

@@ -0,0 +1,87 @@
package com.starry.admin.modules.system.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.starry.admin.modules.system.entity.SysDictEntity;
import com.starry.admin.modules.system.vo.SysDictVo;
import java.util.List;
/**
* 字典表Service接口
*
* @author admin
* @since 2022-08-09
*/
public interface ISysDictService extends IService<SysDictEntity> {
/**
* 查询字典表
*
* @param dictId 字典表主键
* @return 字典表
*/
SysDictEntity selectXlDictByDictId(Long dictId);
/**
* 查询字典表列表
*
* @param sysDictVo 字典表
* @return 字典表集合
*/
Page<SysDictEntity> selectXlDictList(SysDictVo sysDictVo);
/**
* 新增字典表
*
* @param sysDictEntity 字典表
* @return 结果
*/
boolean create(SysDictEntity sysDictEntity);
/**
* 修改字典表
*
* @param sysDictEntity 字典表
* @return 结果
*/
boolean update(SysDictEntity sysDictEntity);
/**
* 批量删除字典表
*
* @param dictIds 需要删除的字典表主键集合
* @return 结果
*/
int deleteXlDictByDictIds(Long[] dictIds);
/**
* 删除字典表信息
*
* @param dictId 字典表主键
* @return 结果
*/
int deleteXlDictByDictId(Long dictId);
/**
* 根据所有字典类型
*
* @return 字典类型集合信息
*/
List<SysDictEntity> selectDictTypeAll();
/**
* 加载字典缓存数据
*/
void loadingDictCache();
/**
* 清空字典缓存数据
*/
void clearDictCache();
/**
* 重置字典缓存数据
*/
void resetDictCache();
}

View File

@@ -0,0 +1,66 @@
package com.starry.admin.modules.system.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.starry.admin.modules.system.entity.SysLoginLogEntity;
import com.starry.admin.modules.system.entity.SysLoginLogVo;
/**
* 系统访问日志表Service接口
*
* @author admin
*/
public interface ISysLoginLogService extends IService<SysLoginLogEntity> {
/**
* 查询系统访问日志表
*
* @param loginId 系统访问日志表主键
* @return 系统访问日志表
*/
SysLoginLogEntity selectXlLoginLogByLoginId(Long loginId);
/**
* 查询系统访问日志表列表
*
* @param sysLoginLogEntity 系统访问日志表
* @return 系统访问日志表集合
*/
IPage<SysLoginLogEntity> selectXlLoginLogList(SysLoginLogVo sysLoginLogEntity);
/**
* 新增系统访问日志表
*
* @param sysLoginLogEntity 系统访问日志表
* @return 结果
*/
boolean create(SysLoginLogEntity sysLoginLogEntity);
/**
* 修改系统访问日志表
*
* @param sysLoginLogEntity 系统访问日志表
* @return 结果
*/
boolean update(SysLoginLogEntity sysLoginLogEntity);
/**
* 批量删除系统访问日志表
*
* @param loginIds 需要删除的系统访问日志表主键集合
* @return 结果
*/
int deleteXlLoginLogByLoginIds(Long[] loginIds);
/**
* 删除系统访问日志表信息
*
* @param loginId 系统访问日志表主键
* @return 结果
*/
int deleteXlLoginLogByLoginId(Long loginId);
/**
* 清空系统登录日志
*/
void cleanLoginlog();
}

View File

@@ -0,0 +1,61 @@
package com.starry.admin.modules.system.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.starry.admin.modules.system.entity.SysOperationLogEntity;
import com.starry.admin.modules.system.vo.SysOperationLogVo;
/**
* 操作日志表Service接口
*
* @author admin
*/
public interface ISysOperationLogService extends IService<SysOperationLogEntity> {
/**
* 查询操作日志表
*
* @param operId 操作日志表主键
* @return 操作日志表
*/
SysOperationLogEntity selectXlOperLogByOperId(Long operId);
/**
* 查询操作日志表列表
*
* @param sysOperationLogEntity 操作日志表
* @return 操作日志表集合
*/
IPage<SysOperationLogEntity> selectXlOperLogList(SysOperationLogVo sysOperationLogEntity);
/**
* 新增操作日志表
*
* @param sysOperationLogEntity 操作日志表
* @return 结果
*/
boolean create(SysOperationLogEntity sysOperationLogEntity);
/**
* 修改操作日志表
*
* @param sysOperationLogEntity 操作日志表
* @return 结果
*/
boolean updateXlOperLog(SysOperationLogEntity sysOperationLogEntity);
/**
* 批量删除操作日志表
*
* @param operIds 需要删除的操作日志表主键集合
* @return 结果
*/
int deleteXlOperLogByOperIds(Long[] operIds);
/**
* 删除操作日志表信息
*
* @param operId 操作日志表主键
* @return 结果
*/
int deleteXlOperLogByOperId(Long operId);
}

View File

@@ -0,0 +1,55 @@
package com.starry.admin.modules.system.service;
import com.starry.admin.common.domain.LoginUser;
import com.starry.admin.modules.system.entity.SysUserEntity;
import java.util.Set;
/**
* @author admin
*/
public interface LoginService {
/**
* 登录功能
*
* @param username 用户名
* @param password 密码
* @return 生成的JWT的token
*/
String login(String username, String password);
/**
* 获取菜单数据权限
*
* @param user 用户信息
* @return 菜单权限信息
*/
Set<String> getMenuPermission(SysUserEntity user);
/**
* 获取角色数据权限
*
* @param user 用户信息
* @return 角色权限信息
*/
Set<String> getRolePermission(SysUserEntity user);
/**
* 登录功能
*
* @param username 用户名
* @param password 密码
* @return 生成的JWT的token
*/
LoginUser newLogin(String username, String password);
/**
* 新登录功能,增加租户相关
*
* @param userName 用户名
* @return 获取信息
*/
LoginUser getLoginUserInfo(String userName);
}

View File

@@ -0,0 +1,90 @@
package com.starry.admin.modules.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.starry.admin.common.domain.TreeSelect;
import com.starry.admin.modules.system.entity.SysDeptEntity;
import java.util.List;
/**
* <p>
* 部门表 服务类
* </p>
*
* @author admin
* @since 2022-07-12
*/
public interface SysDeptService extends IService<SysDeptEntity> {
/**
* 查询部门管理数据
*
* @param dept 部门信息
* @return 部门信息集合
*/
List<SysDeptEntity> selectDeptList(SysDeptEntity dept);
/**
* 校验部门名称是否唯一
*
* @param dept 部门信息
* @return 结果
*/
String checkDeptNameUnique(SysDeptEntity dept);
/**
* 添加部门
*
* @param dept
* @return boolean
**/
boolean create(SysDeptEntity dept);
/**
* 修改部门
*
* @param dept
* @return boolean
**/
boolean update(SysDeptEntity dept);
/**
* 批量删除部门
*
* @param ids
* @return boolean
**/
boolean delete(List<Long> ids);
/**
* 是否存在部门子节点
*
* @param deptId 部门ID
* @return 结果
*/
boolean hasChildByDeptId(Long deptId);
/**
* 构建前端所需要树结构
*
* @param depts 部门列表
* @return 树结构列表
*/
List<TreeSelect> buildDeptTreeSelect(List<SysDeptEntity> depts);
/**
* 根据角色ID查询部门树信息
*
* @param roleId 角色ID
* @return 选中部门列表
*/
List<Long> selectDeptListByRoleId(Long roleId);
/**
* 查询部门树结构信息
*
* @param dept 部门信息
* @return 部门树信息集合
*/
List<TreeSelect> selectDeptTreeList(SysDeptEntity dept);
}

View File

@@ -0,0 +1,130 @@
package com.starry.admin.modules.system.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.starry.admin.common.domain.TreeSelect;
import com.starry.admin.modules.system.entity.SysMenuEntity;
import com.starry.admin.modules.system.vo.RouterVo;
import com.starry.admin.modules.system.vo.SimpleMenu;
import java.util.List;
import java.util.Set;
/**
* <p>
* 菜单表 服务类
* </p>
*
* @author admin
* @since 2022-07-03
*/
public interface SysMenuService extends IService<SysMenuEntity> {
/**
* 添加菜单
*
* @param menu
* @return boolean
**/
boolean create(SysMenuEntity menu);
/**
* 根据用户查询系统菜单列表
*
* @param menu 菜单
* @param userId 用户ID
* @param pageSize 页大小
* @param pageNum 页数
* @return 分页菜单列表
*/
Page<SysMenuEntity> listPage(SysMenuEntity menu, String userId, Integer pageSize, Integer pageNum);
/**
* 根据用户查询系统菜单列表
*
* @param menu 菜单
* @param userId 用户ID
* @return 菜单列表
*/
List<SysMenuEntity> selectMenuList(SysMenuEntity menu, String userId);
/**
* 根据用户查询系统菜单列表
*
* @param userId 用户ID
* @return 菜单列表
*/
List<SysMenuEntity> selectMenuList(String userId);
/**
* 校验菜单名称是否唯一
*
* @param menu 菜单信息
* @return 结果
*/
String checkMenuNameUnique(SysMenuEntity menu);
/**
* 是否存在菜单子节点
*
* @param menuId 菜单ID
* @return 结果 true 存在 false 不存在
*/
boolean hasChildByMenuId(Long menuId);
/**
* 构建前端所需要下拉树结构
*
* @param menus 菜单列表
* @return 下拉树结构列表
*/
List<TreeSelect> buildMenuTreeSelect(List<SysMenuEntity> menus);
/**
* 根据菜单ID查询信息
*
* @param menuId 菜单ID
* @return 菜单信息
*/
SysMenuEntity selectMenuById(Long menuId);
/**
* 根据角色ID查询菜单树信息
*
* @param roleId 角色ID
* @return 选中菜单列表
*/
List<Long> selectMenuListByRoleId(Long roleId);
/**
* 根据用户ID查询权限
*
* @param userId 用户ID
* @return 权限列表
*/
Set<String> selectMenuPermsByUserId(String userId);
/**
* 根据用户ID查询菜单树信息
*
* @param userId 用户ID
* @return 菜单列表
*/
List<SysMenuEntity> selectMenuTreeByUserId(String userId);
/**
* 构建前端路由所需要的菜单
*
* @param menus 菜单列表
* @return 路由列表
*/
List<RouterVo> buildMenus(List<SysMenuEntity> menus);
/**
* 查询所有开启状态菜单精简信息
*
* @return 菜单列表
*/
List<SimpleMenu> selectSimpleMenuList();
}

View File

@@ -0,0 +1,17 @@
package com.starry.admin.modules.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.starry.admin.modules.system.entity.SysRoleMenuEntity;
/**
* <p>
* 角色和菜单关联表 服务类
* </p>
*
* @author admin
* @since 2022-07-06
*/
public interface SysRoleMenuService extends IService<SysRoleMenuEntity> {
}

View File

@@ -0,0 +1,151 @@
package com.starry.admin.modules.system.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.starry.admin.modules.system.entity.SysRoleEntity;
import com.starry.admin.modules.system.entity.SysUserRoleEntity;
import java.util.List;
import java.util.Set;
/**
* <p>
* 角色表 服务类
* </p>
*
* @author admin
* @since 2022-07-01
*/
public interface SysRoleService extends IService<SysRoleEntity> {
/**
* 校验角色名称是否唯一
*
* @param role 角色信息
* @return 结果
*/
String checkRoleNameUnique(SysRoleEntity role);
/**
* 校验角色权限是否唯一
*
* @param role 角色信息
* @return 结果
*/
String checkRoleKeyUnique(SysRoleEntity role);
/**
* 添加角色
*
* @param role
* @return boolean
**/
boolean create(SysRoleEntity role);
/**
* 修改角色
*
* @param role
* @return boolean
**/
boolean updateRole(SysRoleEntity role);
/**
* 通过角色ID查询角色使用数量
*
* @param roleId 角色ID
* @return 结果
*/
int countUserRoleByRoleId(Long roleId);
/**
* 批量删除角色
*
* @param roleIds
* @return boolean
**/
boolean delete(Long[] roleIds);
/**
* 分页获取角色列表
*
* @param keyword
* @param pageSize
* @param pageNum
* @return Page
**/
Page<SysRoleEntity> list(String keyword, Integer pageSize, Integer pageNum);
/**
* 分配菜单权限信息
*
* @param role 角色信息
* @return 结果
*/
boolean authRoleMenu(SysRoleEntity role);
/**
* 根据用户ID查询角色权限
*
* @param userId 用户ID
* @return 权限列表
*/
Set<String> selectRolePermissionByUserId(String userId);
/**
* 根据条件分页查询角色数据
*
* @param role 角色信息
* @return 角色数据集合信息
*/
List<SysRoleEntity> selectRoleList(SysRoleEntity role);
/**
* 校验角色是否允许操作
*
* @param role 角色信息
*/
void checkRoleAllowed(SysRoleEntity role);
/**
* 校验角色是否有数据权限
*
* @param roleId 角色id
*/
void checkRoleDataScope(Long roleId);
/**
* 修改数据权限信息
*
* @param role 角色信息
* @return 结果
*/
int authDataScope(SysRoleEntity role);
/**
* 取消授权用户角色
*
* @param userRole 用户和角色关联信息
* @return 结果
*/
int deleteAuthUser(SysUserRoleEntity userRole);
/**
* 批量取消授权用户角色
*
* @param roleId 角色ID
* @param userIds 需要取消授权的用户数据ID
* @return 结果
*/
int deleteAuthUsers(Long roleId, String[] userIds);
/**
* 批量选择授权用户角色
*
* @param roleId 角色ID
* @param userIds 需要删除的用户数据ID
* @return 结果
*/
int insertAuthUsers(Long roleId, String[] userIds);
}

View File

@@ -0,0 +1,17 @@
package com.starry.admin.modules.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.starry.admin.modules.system.entity.SysUserRoleEntity;
/**
* <p>
* 用户角色关联表 服务类
* </p>
*
* @author admin
* @since 2022-07-08
*/
public interface SysUserRoleService extends IService<SysUserRoleEntity> {
}

View File

@@ -0,0 +1,126 @@
package com.starry.admin.modules.system.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.starry.admin.modules.system.entity.SysUserEntity;
import com.starry.admin.modules.system.vo.RoleUserResultVo;
import com.starry.admin.modules.system.vo.SysUserQueryVo;
import com.starry.admin.modules.system.vo.UserQueryVo;
import java.util.List;
/**
* <p>
* 后台用户表 服务类
* </p>
*
* @author admin
* @since 2021-09-03
*/
public interface SysUserService extends IService<SysUserEntity> {
/**
* 注册功能
*
* @param user
* @return SysUserEntity
*/
SysUserEntity register(SysUserEntity user);
/**
* 查询用户
*
* @param userCode
* @return SysUserEntity
*/
SysUserEntity getUserByCode(String userCode);
/**
* 通过用户名查询用户
*
* @param userName 用户名
* @return 用户对象信息
*/
SysUserEntity selectUserByUserName(String userName);
/**
* 获取列表。分页
*
* @param queryVo 查询参数
* @return page
*/
IPage<SysUserEntity> listMemberPage(UserQueryVo queryVo);
/**
* 校验用户名称是否唯一
*
* @param userName 用户名称
* @return 结果
*/
String checkUserNameUnique(String userName);
/**
* 添加用户
*
* @param user
* @return boolean
**/
boolean create(SysUserEntity user);
/**
* 修改用户
*
* @param user
* @return boolean
**/
boolean update(SysUserEntity user);
/**
* 批量删除用户
*
* @param ids
* @return boolean
**/
boolean delete(List<String> ids);
/**
* 通过用户ID查询用户
*
* @param userId 用户ID
* @return 用户对象信息
*/
SysUserEntity selectUserById(String userId);
/**
* 根据用户ID查询用户所属角色组
*
* @param userId 用户id
* @return 结果
*/
String selectUserRoleGroup(String userId);
/**
* 修改用户头像
*
* @param userId 用户id
* @param avatar 头像地址
* @return 结果
*/
boolean updateUserAvatar(String userId, String avatar);
/**
* 根据条件分页查询已配用户角色列表
*
* @param user 用户信息
* @return 用户信息集合信息
*/
IPage<RoleUserResultVo> selectAllocatedList(SysUserQueryVo user);
/**
* 根据条件分页查询已配用户角色列表
*
* @param user 用户信息
* @return 用户信息集合信息
*/
IPage<RoleUserResultVo> selectUnallocatedList(SysUserQueryVo user);
}

View File

@@ -0,0 +1,183 @@
package com.starry.admin.modules.system.service.impl;
import cn.hutool.core.convert.Convert;
import com.starry.admin.common.component.JwtToken;
import com.starry.admin.common.domain.LoginUser;
import com.starry.admin.common.exception.ServiceException;
import com.starry.admin.common.security.entity.JwtUser;
import com.starry.admin.manager.AsyncManager;
import com.starry.admin.manager.factory.AsyncFactory;
import com.starry.admin.modules.platform.entity.SysTenantEntity;
import com.starry.admin.modules.platform.service.ISysTenantService;
import com.starry.admin.modules.system.entity.SysUserEntity;
import com.starry.admin.modules.system.service.LoginService;
import com.starry.admin.modules.system.service.SysMenuService;
import com.starry.admin.modules.system.service.SysRoleService;
import com.starry.admin.modules.system.service.SysUserService;
import com.starry.admin.utils.SecurityUtils;
import com.starry.common.constant.Constants;
import com.starry.common.constant.UserConstants;
import com.starry.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
/**
* @author admin
*/
@Slf4j
@Service
public class LoginServiceImpl implements LoginService {
@Resource
private PasswordEncoder passwordEncoder;
@Resource
private UserDetailsService userDetailsService;
@Resource
private JwtToken jwtTokenUtil;
@Resource
private SysMenuService menuService;
@Resource
private SysRoleService roleService;
@Resource
private SysUserService sysUserService;
@Resource
private ISysTenantService SysTenantService;
@Override
public String login(String username, String password) {
String token = null;
try {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (!passwordEncoder.matches(password, userDetails.getPassword())) {
throw new BadCredentialsException("密码不正确");
}
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
// 登录成功记录日志
AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_SUCCESS, "登录成功"));
JwtUser jwtUser = (JwtUser) authentication.getPrincipal();
token = jwtTokenUtil.createToken(jwtUser);
} catch (AuthenticationException e) {
log.warn("登录异常:{}", e.getMessage());
// 登录失败记录日志
AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, e.getMessage()));
}
return token;
}
@Override
public Set<String> getMenuPermission(SysUserEntity user) {
Set<String> perms = new HashSet<>();
// 超级管理员拥有所有权限
if (SecurityUtils.isAdmin(user.getUserId())) {
perms.add("*:*:*");
} else {
perms = menuService.selectMenuPermsByUserId(user.getUserId());
}
return perms;
}
@Override
public Set<String> getRolePermission(SysUserEntity user) {
Set<String> roles = new HashSet<>();
// 超级管理员拥有所有权限
if (SecurityUtils.isAdmin(user.getUserId())) {
roles.add("admin");
} else {
roles = roleService.selectRolePermissionByUserId(user.getUserId());
}
return roles;
}
@Override
public LoginUser newLogin(String username, String password) {
// 用户名或密码为空 错误
if (StringUtils.isAnyBlank(username, password)) {
// 登录记录日志
AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, "用户名/密码必须填写"));
throw new ServiceException("用户/密码必须填写");
}
// 密码如果不在指定范围内 错误
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
// 登录记录日志
AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, "用户密码不在指定范围"));
throw new ServiceException("用户密码不在指定范围");
}
// 用户名不在指定范围内 错误
if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|| username.length() > UserConstants.USERNAME_MAX_LENGTH) {
// 登录记录日志
AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, "用户名不在指定范围"));
throw new ServiceException("用户名不在指定范围");
}
LoginUser userInfo = this.getLoginUserInfo(username);
if (userInfo == null) {
// 登录记录日志
AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, "用户名不存在"));
throw new ServiceException("用户名不存在");
}
SysUserEntity user = userInfo.getUser();
if (!SecurityUtils.matchesPassword(password, user.getPassWord())) {
// 登录记录日志
AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, "密码错误"));
throw new ServiceException("密码错误");
}
// 线程塞入租户ID
SecurityUtils.setTenantId(Convert.toStr(user.getTenantId()));
if (user.getStatus() == 1) {
// 登录记录日志
AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员"));
throw new ServiceException("对不起,您的账号:" + username + " 已停用,请联系管理员");
}
// 先查询是否被停用了租户
if (userInfo.getTenantStatus() != null && userInfo.getTenantStatus() == 1) {
// 登录记录日志
AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, "当前租户已经被停用,请联系管理员"));
throw new ServiceException("当前租户已经被停用,请联系管理员");
}
if (userInfo.getTenantEndDate() != null && userInfo.getTenantEndDate().compareTo(new Date()) < 0) {
// 登录记录日志
AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, "当前租户已超过租赁日期,请联系管理员"));
throw new ServiceException("当前租户已超过租赁日期,请联系管理员");
}
AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_SUCCESS, "登录成功"));
return userInfo;
}
@Override
public LoginUser getLoginUserInfo(String userName) {
SysUserEntity sysUser = sysUserService.selectUserByUserName(userName);
if (StringUtils.isNotNull(sysUser)) {
// 角色集合
Set<String> roles = this.getRolePermission(sysUser);
// 权限集合
Set<String> permissions = this.getMenuPermission(sysUser);
// 查询租户信息
SysTenantEntity tenant = SysTenantService.selectSysTenantByTenantId(sysUser.getTenantId());
LoginUser sysUserVo = new LoginUser();
sysUserVo.setUser(sysUser);
sysUserVo.setRoles(roles);
sysUserVo.setPermissions(permissions);
if (tenant != null) {
sysUserVo.setTenantEndDate(tenant.getTenantTime());
sysUserVo.setTenantStatus(Integer.valueOf(tenant.getTenantStatus()));
}
return sysUserVo;
}
return null;
}
}

View File

@@ -0,0 +1,195 @@
package com.starry.admin.modules.system.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.starry.admin.common.domain.TreeSelect;
import com.starry.admin.modules.system.entity.SysDeptEntity;
import com.starry.admin.modules.system.entity.SysRoleEntity;
import com.starry.admin.modules.system.mapper.SysDeptMapper;
import com.starry.admin.modules.system.mapper.SysRoleMapper;
import com.starry.admin.modules.system.service.SysDeptService;
import com.starry.common.annotation.DataScope;
import com.starry.common.constant.UserConstants;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
* 部门表 服务实现类
* </p>
*
* @author admin
* @since 2022-07-12
*/
@Service
public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDeptEntity> implements SysDeptService {
@Resource
private SysRoleMapper roleMapper;
@Override
@DataScope(deptAlias = "d")
public List<SysDeptEntity> selectDeptList(SysDeptEntity dept) {
return baseMapper.selectDeptList(dept);
}
@Override
public String checkDeptNameUnique(SysDeptEntity dept) {
Long deptId = dept.getDeptId() == null ? -1L : dept.getDeptId();
List<SysDeptEntity> infos = list(new LambdaQueryWrapper<SysDeptEntity>()
.eq(SysDeptEntity::getDeptName, dept.getDeptName())
.eq(SysDeptEntity::getParentId, dept.getParentId()));
// 查出有数据 并且不是自己,则不唯一
if (CollectionUtil.isNotEmpty(infos) && infos.get(0).getDeptId().longValue() != deptId.longValue()) {
return UserConstants.NOT_UNIQUE;
}
return UserConstants.UNIQUE;
}
@Override
public boolean create(SysDeptEntity dept) {
SysDeptEntity info = getById(dept.getParentId());
// 若父节点不为正常状态,则不允许新增子节点
if (!UserConstants.DEPT_NORMAL.equals(String.valueOf(info.getStatus()))) {
throw new RuntimeException("部门停用,不允许新增");
}
dept.setAncestors(info.getAncestors() + "," + dept.getParentId());
dept.setDeptLevel(info.getDeptLevel() == null ? 0 : info.getDeptLevel() + 1);
return save(dept);
}
@Override
public boolean update(SysDeptEntity dept) {
// 新的上级部门
SysDeptEntity newParentDept = getById(dept.getParentId());
// 当前部门
SysDeptEntity oldDept = getById(dept.getDeptId());
if (newParentDept != null && oldDept != null) {
String newAncestors = newParentDept.getAncestors() + "," + newParentDept.getDeptId();
String oldAncestors = oldDept.getAncestors();
dept.setAncestors(newAncestors);
updateDeptChildren(dept.getDeptId(), newAncestors, oldAncestors);
}
return updateById(dept);
}
@Override
public boolean delete(List<Long> ids) {
return removeBatchByIds(ids);
}
@Override
public boolean hasChildByDeptId(Long deptId) {
List<SysDeptEntity> list = baseMapper.selectList(new LambdaQueryWrapper<SysDeptEntity>().eq(SysDeptEntity::getParentId, deptId));
if (CollectionUtil.isNotEmpty(list)) {
return true;
}
return false;
}
@Override
public List<TreeSelect> buildDeptTreeSelect(List<SysDeptEntity> depts) {
List<SysDeptEntity> deptList = buildDeptTree(depts);
// 转换成树结构的list
return deptList.stream().map(TreeSelect::new).collect(Collectors.toList());
}
public List<SysDeptEntity> buildDeptTree(List<SysDeptEntity> depts) {
List<SysDeptEntity> returnList = new ArrayList<>();
// 所有部门id
List<Long> tempList = new ArrayList<>();
for (SysDeptEntity dept : depts) {
tempList.add(dept.getDeptId());
}
for (SysDeptEntity dept : depts) {
// 如若是顶级节点,遍历该父节点下的所有子节点
if (!tempList.contains(dept.getParentId())) {
recursionFn(depts, dept);
returnList.add(dept);
}
}
if (CollectionUtil.isEmpty(returnList)) {
returnList = depts;
}
return returnList;
}
/**
* 修改子元素关系
*
* @param deptId 被修改的部门ID
* @param newAncestors 新的父ID集合
* @param oldAncestors 旧的父ID集合
*/
public void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors) {
List<SysDeptEntity> childrens = baseMapper.selectChildrenDeptById(deptId);
if (CollectionUtil.isNotEmpty(childrens)) {
for (SysDeptEntity child : childrens) {
child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
updateById(child);
}
}
}
/**
* 递归列表
*/
private void recursionFn(List<SysDeptEntity> list, SysDeptEntity t) {
List<SysDeptEntity> childList = getChildList(list, t);
t.setChildren(childList);
for (SysDeptEntity tChild : childList) {
if (hasChild(list, tChild)) {
recursionFn(list, tChild);
}
}
}
/**
* 得到子节点列表
*/
private List<SysDeptEntity> getChildList(List<SysDeptEntity> list, SysDeptEntity t) {
List<SysDeptEntity> tList = new ArrayList<>();
for (SysDeptEntity n : list) {
if (n.getParentId() != null && n.getParentId().longValue() == t.getDeptId().longValue()) {
tList.add(n);
}
}
return tList;
}
/**
* 判断是否还有子节点
*/
private boolean hasChild(List<SysDeptEntity> list, SysDeptEntity t) {
return !getChildList(list, t).isEmpty();
}
/**
* 根据角色ID查询部门树信息
*
* @param roleId 角色ID
* @return 选中部门列表
*/
@Override
public List<Long> selectDeptListByRoleId(Long roleId) {
SysRoleEntity role = roleMapper.selectRoleById(roleId);
return baseMapper.selectDeptListByRoleId(roleId, role.isDeptCheckStrictly());
}
/**
* 查询部门树结构信息
*
* @param dept 部门信息
* @return 部门树信息集合
*/
@Override
public List<TreeSelect> selectDeptTreeList(SysDeptEntity dept) {
List<SysDeptEntity> depts = this.selectDeptList(dept);
return buildDeptTreeSelect(depts);
}
}

View File

@@ -0,0 +1,113 @@
package com.starry.admin.modules.system.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.starry.admin.modules.system.entity.SysDictDataEntity;
import com.starry.admin.modules.system.mapper.SysDictDataMapper;
import com.starry.admin.modules.system.service.ISysDictDataService;
import com.starry.admin.modules.system.vo.SysDictDataVo;
import com.starry.admin.utils.DictUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
/**
* 字典数据表Service业务层处理
*
* @author admin
*/
@Service
public class SysDictDataServiceImpl extends ServiceImpl<SysDictDataMapper, SysDictDataEntity> implements ISysDictDataService {
@Resource
private SysDictDataMapper sysDictDataMapper;
/**
* 查询字典数据表
*
* @param dictDataId 字典数据表主键
* @return 字典数据表
*/
@Override
public SysDictDataEntity selectXlDictDataByDictDataId(Long dictDataId) {
return sysDictDataMapper.selectXlDictDataByDictDataId(dictDataId);
}
/**
* 查询字典数据表列表
*
* @param sysDictDataEntity 字典数据表
* @return 字典数据表
*/
@Override
public IPage<SysDictDataEntity> selectXlDictDataList(SysDictDataVo sysDictDataEntity) {
return sysDictDataMapper.selectXlDictDataList(new Page<>(sysDictDataEntity.getPageNum(), sysDictDataEntity.getPageSize()), sysDictDataEntity);
}
/**
* 新增字典数据表
*
* @param sysDictDataEntity 字典数据表
* @return 结果
*/
@Override
public boolean create(SysDictDataEntity sysDictDataEntity) {
return save(sysDictDataEntity);
}
/**
* 修改字典数据表
*
* @param sysDictDataEntity 字典数据表
* @return 结果
*/
@Override
public boolean update(SysDictDataEntity sysDictDataEntity) {
return updateById(sysDictDataEntity);
}
/**
* 批量删除字典数据表
*
* @param dictDataIds 需要删除的字典数据表主键
* @return 结果
*/
@Override
public int deleteXlDictDataByDictDataIds(Long[] dictDataIds) {
return sysDictDataMapper.deleteBatchIds(Arrays.asList(dictDataIds));
}
/**
* 删除字典数据表信息
*
* @param dictDataId 字典数据表主键
* @return 结果
*/
@Override
public int deleteXlDictDataByDictDataId(Long dictDataId) {
return sysDictDataMapper.deleteById(dictDataId);
}
/**
* 根据字典类型查询字典数据
*
* @param dictType 字典类型
* @return 字典数据集合信息
*/
@Override
public List<SysDictDataEntity> selectDictDataByType(String dictType) {
List<SysDictDataEntity> dictDataList = DictUtils.getDictCache(dictType);
if (CollectionUtil.isNotEmpty(dictDataList)) {
return dictDataList;
}
dictDataList = sysDictDataMapper.selectDictDataByType(dictType);
if (CollectionUtil.isNotEmpty(dictDataList)) {
DictUtils.setDictCache(dictType, dictDataList);
return dictDataList;
}
return null;
}
}

View File

@@ -0,0 +1,138 @@
package com.starry.admin.modules.system.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.starry.admin.modules.system.entity.SysDictDataEntity;
import com.starry.admin.modules.system.entity.SysDictEntity;
import com.starry.admin.modules.system.mapper.SysDictDataMapper;
import com.starry.admin.modules.system.mapper.SysDictMapper;
import com.starry.admin.modules.system.service.ISysDictService;
import com.starry.admin.modules.system.vo.SysDictDataVo;
import com.starry.admin.modules.system.vo.SysDictVo;
import com.starry.admin.utils.DictUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 字典表Service业务层处理
*
* @author admin
*/
@Service
public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDictEntity> implements ISysDictService {
@Resource
private SysDictMapper sysDictMapper;
@Resource
private SysDictDataMapper sysDictDataMapper;
/**
* 查询字典表
*
* @param dictId 字典表主键
* @return 字典表
*/
@Override
public SysDictEntity selectXlDictByDictId(Long dictId) {
return sysDictMapper.selectXlDictByDictId(dictId);
}
/**
* 查询字典表列表
*
* @param sysDictVo 字典表
* @return 字典表
*/
@Override
public Page<SysDictEntity> selectXlDictList(SysDictVo sysDictVo) {
return sysDictMapper.selectXlDictList(new Page<>(sysDictVo.getPageNum(), sysDictVo.getPageSize()), sysDictVo);
}
/**
* 新增字典表
*
* @param sysDictEntity 字典表
* @return 结果
*/
@Override
public boolean create(SysDictEntity sysDictEntity) {
return save(sysDictEntity);
}
/**
* 修改字典表
*
* @param sysDictEntity 字典表
* @return 结果
*/
@Override
public boolean update(SysDictEntity sysDictEntity) {
return updateById(sysDictEntity);
}
/**
* 批量删除字典表
*
* @param dictIds 需要删除的字典表主键
* @return 结果
*/
@Override
public int deleteXlDictByDictIds(Long[] dictIds) {
return sysDictMapper.deleteBatchIds(Arrays.asList(dictIds));
}
/**
* 删除字典表信息
*
* @param dictId 字典表主键
* @return 结果
*/
@Override
public int deleteXlDictByDictId(Long dictId) {
return sysDictMapper.deleteById(dictId);
}
@Override
public List<SysDictEntity> selectDictTypeAll() {
return sysDictMapper.selectList(new LambdaQueryWrapper<>());
}
/**
* 加载字典缓存数据
*/
@Override
public void loadingDictCache() {
SysDictDataVo dictData = new SysDictDataVo();
dictData.setStatus(0);
// 按字典编码分组不分页size < 0
IPage<SysDictDataEntity> iPage = sysDictDataMapper.selectXlDictDataList(new Page<>(1, -1), dictData);
Map<String, List<SysDictDataEntity>> dictDataMap = iPage.getRecords().stream().collect(Collectors.groupingBy(SysDictDataEntity::getDictType));
for (Map.Entry<String, List<SysDictDataEntity>> entry : dictDataMap.entrySet()) {
DictUtils.setDictCache(entry.getKey(), entry.getValue().stream().sorted(Comparator.comparing(SysDictDataEntity::getSort)).collect(Collectors.toList()));
}
}
/**
* 清空字典缓存数据
*/
@Override
public void clearDictCache() {
DictUtils.clearDictCache();
}
/**
* 重置字典缓存数据
*/
@Override
public void resetDictCache() {
clearDictCache();
loadingDictCache();
}
}

View File

@@ -0,0 +1,95 @@
package com.starry.admin.modules.system.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.starry.admin.modules.system.entity.SysLoginLogEntity;
import com.starry.admin.modules.system.entity.SysLoginLogVo;
import com.starry.admin.modules.system.mapper.SysLoginLogMapper;
import com.starry.admin.modules.system.service.ISysLoginLogService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Arrays;
/**
* 系统访问日志表Service业务层处理
*
* @author admin
*/
@Service
public class SysLoginLogServiceImpl extends ServiceImpl<SysLoginLogMapper, SysLoginLogEntity> implements ISysLoginLogService {
@Resource
private SysLoginLogMapper xlLoginLogMapper;
/**
* 查询系统访问日志表
*
* @param loginId 系统访问日志表主键
* @return 系统访问日志表
*/
@Override
public SysLoginLogEntity selectXlLoginLogByLoginId(Long loginId) {
return xlLoginLogMapper.selectXlLoginLogByLoginId(loginId);
}
/**
* 查询系统访问日志表列表
*
* @param vo 系统访问日志表
* @return 系统访问日志表
*/
@Override
public IPage<SysLoginLogEntity> selectXlLoginLogList(SysLoginLogVo vo) {
return xlLoginLogMapper.selectXlLoginLogList(new Page<>(vo.getPageNum(), vo.getPageSize()), vo);
}
/**
* 新增系统访问日志表
*
* @param sysLoginLogEntity 系统访问日志表
* @return 结果
*/
@Override
public boolean create(SysLoginLogEntity sysLoginLogEntity) {
return save(sysLoginLogEntity);
}
/**
* 修改系统访问日志表
*
* @param sysLoginLogEntity 系统访问日志表
* @return 结果
*/
@Override
public boolean update(SysLoginLogEntity sysLoginLogEntity) {
return updateById(sysLoginLogEntity);
}
/**
* 批量删除系统访问日志表
*
* @param loginIds 需要删除的系统访问日志表主键
* @return 结果
*/
@Override
public int deleteXlLoginLogByLoginIds(Long[] loginIds) {
return xlLoginLogMapper.deleteBatchIds(Arrays.asList(loginIds));
}
/**
* 删除系统访问日志表信息
*
* @param loginId 系统访问日志表主键
* @return 结果
*/
@Override
public int deleteXlLoginLogByLoginId(Long loginId) {
return xlLoginLogMapper.deleteById(loginId);
}
@Override
public void cleanLoginlog() {
xlLoginLogMapper.cleanLoginlog();
}
}

Some files were not shown because too many files have changed in this diff Show More