This commit is contained in:
2023-06-05 16:01:00 +08:00
parent 951a08a0a1
commit f2457ff1d8
20 changed files with 156 additions and 100 deletions

View File

@ -71,7 +71,7 @@ public interface SysConfigApiService {
* 根据参数键名查询参数值 * 根据参数键名查询参数值
* *
* @param configKey configKey * @param configKey configKey
* @return * @return value
*/ */
String selectConfigByKey(String configKey); String selectConfigByKey(String configKey);
} }

View File

@ -19,5 +19,5 @@ public interface SysDictApiService {
* @param dictType 字典类型 * @param dictType 字典类型
* @return 字典数据集合信息 * @return 字典数据集合信息
*/ */
List<SysDictData> selectByDictType(String dictType); List<SysDictData> selectFromCache(String dictType);
} }

View File

@ -51,7 +51,9 @@ springdoc:
- group: '租户管理' - group: '租户管理'
paths-to-match: '/**' paths-to-match: '/**'
packages-to-scan: com.qiaoba.module.tenant.controller packages-to-scan: com.qiaoba.module.tenant.controller
- group: '监控管理'
paths-to-match: '/**'
packages-to-scan: com.qiaoba.module.monitor.controller
# knife4j的增强配置不需要增强可以不配 # knife4j的增强配置不需要增强可以不配
knife4j: knife4j:
enable: true enable: true

View File

@ -1,6 +1,7 @@
package com.qiaoba.auth.service; package com.qiaoba.auth.service;
import com.qiaoba.auth.entity.OnlineUser; import com.qiaoba.auth.entity.OnlineUser;
import com.qiaoba.common.base.entity.BasePage;
import java.util.List; import java.util.List;
@ -62,4 +63,13 @@ public interface OnlineUserService {
*/ */
Boolean checkIsLastLogged(String username, String deviceSn); Boolean checkIsLastLogged(String username, String deviceSn);
/**
* 分页查询列表
*
* @param pageNum pageNum
* @param pageSize pageSize
* @param username username
* @return list
*/
BasePage selectPageList(Integer pageNum, Integer pageSize, String username);
} }

View File

@ -43,11 +43,13 @@ public class AuthConfigServiceImpl implements AuthConfigApiService {
if (StrUtil.isBlank(code) || StrUtil.isBlank(uuid)) { if (StrUtil.isBlank(code) || StrUtil.isBlank(uuid)) {
throw new ServiceException("验证码或uuid获取失败"); throw new ServiceException("验证码或uuid获取失败");
} }
String realCode = redisService.getObject(SecurityConstant.CAPTCHA_KEY + uuid, String.class);
try { try {
if (!redisService.hasKey(SecurityConstant.CAPTCHA_KEY + uuid)) { if (StrUtil.isBlank(realCode)) {
throw new ServiceException("验证码已经过期失效!"); throw new ServiceException("验证码已经过期失效!");
} else { } else {
if (!code.equalsIgnoreCase(redisService.get(SecurityConstant.CAPTCHA_KEY + uuid).toString())) { if (!code.equalsIgnoreCase(realCode)) {
throw new ServiceException("验证码输入错误!"); throw new ServiceException("验证码输入错误!");
} }
} }

View File

@ -1,5 +1,6 @@
package com.qiaoba.auth.service.impl; package com.qiaoba.auth.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.qiaoba.api.auth.service.SysUserDetailsApiService; import com.qiaoba.api.auth.service.SysUserDetailsApiService;
import com.qiaoba.auth.constants.SecurityConstant; import com.qiaoba.auth.constants.SecurityConstant;
@ -8,6 +9,7 @@ import com.qiaoba.auth.entity.dto.OnlineUserDto;
import com.qiaoba.auth.service.OnlineUserService; import com.qiaoba.auth.service.OnlineUserService;
import com.qiaoba.auth.utils.TokenUtil; import com.qiaoba.auth.utils.TokenUtil;
import com.qiaoba.common.base.constants.BaseConstant; import com.qiaoba.common.base.constants.BaseConstant;
import com.qiaoba.common.base.entity.BasePage;
import com.qiaoba.common.base.exceptions.ServiceException; import com.qiaoba.common.base.exceptions.ServiceException;
import com.qiaoba.common.redis.service.RedisService; import com.qiaoba.common.redis.service.RedisService;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -60,11 +62,7 @@ public class OnlineUserServiceImpl implements OnlineUserService {
@Override @Override
public OnlineUser selectOne(String username, String deviceSn) { public OnlineUser selectOne(String username, String deviceSn) {
String key = handleKey(username, deviceSn); return redisService.getObject(handleKey(username, deviceSn), OnlineUser.class);
if (redisService.hasKey(key)) {
return redisService.getObject(key, OnlineUser.class);
}
return null;
} }
@Override @Override
@ -88,6 +86,21 @@ public class OnlineUserServiceImpl implements OnlineUserService {
return deviceSn.equals(loggedDevice); return deviceSn.equals(loggedDevice);
} }
@Override
public BasePage<OnlineUser> selectPageList(Integer pageNum, Integer pageSize, String username) {
String key = SecurityConstant.ONLINE_USER_REDIS_KEY + "*";
if (StrUtil.isNotBlank(username)) {
key = key + username + "*";
}
List<String> allKeys = CollUtil.newArrayList(redisService.getKeys(key));
List<String> keys = CollUtil.page(pageNum - 1, pageSize, allKeys);
List<OnlineUser> users = new ArrayList<>();
for (String temp : keys) {
users.add(redisService.getObject(redisService.removeTenantPrefix(temp), OnlineUser.class));
}
return BasePage.build(((Integer) allKeys.size()).longValue(), users);
}
private String handleKey(String key, String deviceSn) { private String handleKey(String key, String deviceSn) {
return SecurityConstant.ONLINE_USER_REDIS_KEY + key + BaseConstant.COLON_JOIN_STR + deviceSn; return SecurityConstant.ONLINE_USER_REDIS_KEY + key + BaseConstant.COLON_JOIN_STR + deviceSn;
} }

View File

@ -59,18 +59,14 @@ public class BaseConstant {
*/ */
public static final String YES = "Y"; public static final String YES = "Y";
/**
* 否
*/
public static final String NO = "N";
/** /**
* 处理失败 个数 0 * 处理失败 个数 0
*/ */
public static final Integer HANDLE_ERROR = 0; public static final Integer HANDLE_ERROR = 0;
/**
* 租户 key 前缀
*/
public static final String TENANT_KEY_PREFIX = "tenant_";
/**
* header 租户 key
*/
public static final String HEADER_KEY_TENANT = "tenant";
} }

View File

@ -0,0 +1,16 @@
package com.qiaoba.common.base.constants;
/**
* 字典常量
*
* @author ailanyin
* @version 1.0
* @since 2023-04-23 15:37:43
*/
public class DictConstant {
/**
* 字典 redis key
*/
public static final String SYS_DICT_KEY = "sys_dict:";
}

View File

@ -0,0 +1,21 @@
package com.qiaoba.common.base.constants;
/**
* 租户常量
*
* @author ailanyin
* @version 1.0
* @since 2023-04-23 15:37:43
*/
public class TenantConstant {
/**
* 租户 key 前缀
*/
public static final String TENANT_KEY_PREFIX = "tenant_";
/**
* header 租户 key
*/
public static final String HEADER_KEY_TENANT = "tenant";
}

View File

@ -62,10 +62,20 @@ public class BasePage<T> implements Serializable {
return basePage; return basePage;
} }
public static <T> BasePage<T> build(Long total, List<T> list) {
BasePage<T> basePage = new BasePage<>();
basePage.setCode(HttpStatus.HTTP_OK);
basePage.setMsg("查询成功");
basePage.setRows(list);
basePage.setTotal(total);
return basePage;
}
public static <T> BasePage<T> build() { public static <T> BasePage<T> build() {
BasePage<T> basePage = new BasePage<>(); BasePage<T> basePage = new BasePage<>();
basePage.setCode(HttpStatus.HTTP_OK); basePage.setCode(HttpStatus.HTTP_OK);
basePage.setMsg("查询成功"); basePage.setMsg("查询成功");
return basePage; return basePage;
} }
} }

View File

@ -1,6 +1,7 @@
package com.qiaoba.common.database.filters; package com.qiaoba.common.database.filters;
import com.qiaoba.common.base.constants.BaseConstant; import com.qiaoba.common.base.constants.BaseConstant;
import com.qiaoba.common.base.constants.TenantConstant;
import com.qiaoba.common.base.context.BaseContext; import com.qiaoba.common.base.context.BaseContext;
import com.qiaoba.common.database.config.DynamicDataSourceContext; import com.qiaoba.common.database.config.DynamicDataSourceContext;
import com.qiaoba.common.database.constants.DynamicDatasourceConstant; import com.qiaoba.common.database.constants.DynamicDatasourceConstant;
@ -45,7 +46,7 @@ public class DynamicDataSourceFilter extends OncePerRequestFilter {
} }
private void before(HttpServletRequest request) { private void before(HttpServletRequest request) {
String tenantId = request.getHeader(BaseConstant.HEADER_KEY_TENANT); String tenantId = request.getHeader(TenantConstant.HEADER_KEY_TENANT);
// todo // todo
//设置当前租户对应的数据源 //设置当前租户对应的数据源
BaseContext.setDataSource(DynamicDatasourceConstant.DEFAULT_MASTER_DATASOURCE_KEY); BaseContext.setDataSource(DynamicDatasourceConstant.DEFAULT_MASTER_DATASOURCE_KEY);

View File

@ -1,51 +0,0 @@
package com.qiaoba.common.redis.constants;
/**
* 缓存的key 常量
*
* @author ailanyin
* @version 1.0
* @since 2021/10/2 0002 下午 17:41
*/
public class CacheConstant {
/**
* 登录用户 redis key
*/
public static final String LOGIN_USER_KEY = "login_users:";
/**
* 验证码 redis key
*/
public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
/**
* 参数管理 cache key
*/
public static final String SYS_CONFIG_KEY = "sys_config:";
/**
* 字典管理 cache key
*/
public static final String SYS_DICT_KEY = "sys_dict:";
/**
* 防重提交 redis key
*/
public static final String REPEAT_SUBMIT_KEY = "repeat_submit:";
/**
* 限流 redis key
*/
public static final String RATE_LIMIT_KEY = "rate_limit:";
/**
* 登录账户密码错误次数 redis key
*/
public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt:";
/**
* 角色拥有的权限Set
*/
public static final String ROLE_PERMS = "role_perms:role_";
}

View File

@ -2,6 +2,7 @@ package com.qiaoba.common.redis.service.impl;
import com.qiaoba.common.base.constants.BaseConstant; import com.qiaoba.common.base.constants.BaseConstant;
import com.qiaoba.common.base.constants.TenantConstant;
import com.qiaoba.common.base.context.BaseContext; import com.qiaoba.common.base.context.BaseContext;
import com.qiaoba.common.base.entity.BasePage; import com.qiaoba.common.base.entity.BasePage;
import com.qiaoba.common.redis.service.RedisService; import com.qiaoba.common.redis.service.RedisService;
@ -253,14 +254,14 @@ public class RedisServiceImpl implements RedisService {
@Override @Override
public String addTenantPrefix(String key) { public String addTenantPrefix(String key) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(BaseConstant.TENANT_KEY_PREFIX).append(BaseContext.getTenantId()).append(BaseConstant.COLON_JOIN_STR).append(key); sb.append(TenantConstant.TENANT_KEY_PREFIX).append(BaseContext.getTenantId()).append(BaseConstant.COLON_JOIN_STR).append(key);
return sb.toString(); return sb.toString();
} }
@Override @Override
public String removeTenantPrefix(String key) { public String removeTenantPrefix(String key) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(BaseConstant.TENANT_KEY_PREFIX).append(BaseContext.getTenantId()).append(BaseConstant.COLON_JOIN_STR); sb.append(TenantConstant.TENANT_KEY_PREFIX).append(BaseContext.getTenantId()).append(BaseConstant.COLON_JOIN_STR);
return key.replace(sb.toString(), ""); return key.replace(sb.toString(), "");
} }
} }

View File

@ -1,10 +1,8 @@
package com.qiaoba.module.monitor.controller; package com.qiaoba.module.monitor.controller;
import com.qiaoba.auth.entity.OnlineUser;
import com.qiaoba.auth.service.OnlineUserService; import com.qiaoba.auth.service.OnlineUserService;
import com.qiaoba.common.base.entity.BasePage; import com.qiaoba.common.base.entity.BasePage;
import com.qiaoba.common.base.result.AjaxResult; import com.qiaoba.common.base.result.AjaxResult;
import com.qiaoba.common.database.entity.TableDataInfo;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -30,8 +28,8 @@ public class OnlineUserController {
@PreAuthorize("hasAuthority('monitor:online:list')") @PreAuthorize("hasAuthority('monitor:online:list')")
@Operation(summary = "获取列表") @Operation(summary = "获取列表")
@GetMapping("/list") @GetMapping("/list")
public BasePage<OnlineUser> getList(String username) { public BasePage getList(Integer pageNum, Integer pageSize, @RequestParam(required = false) String username) {
return TableDataInfo.build(onlineUserService.selectList(username)); return onlineUserService.selectPageList(pageNum, pageSize, username);
} }
@PreAuthorize("hasAuthority('monitor:online:forceLogout')") @PreAuthorize("hasAuthority('monitor:online:forceLogout')")

View File

@ -50,7 +50,7 @@ public class SysDictDataController {
@GetMapping(value = "/type/{dictType}") @GetMapping(value = "/type/{dictType}")
public AjaxResult dictType(@PathVariable String dictType) { public AjaxResult dictType(@PathVariable String dictType) {
return AjaxResult.success(sysDictDataService.selectByDictType(dictType)); return AjaxResult.success(sysDictDataService.selectFromCache(dictType));
} }
@PreAuthorize("hasAuthority('system:dict:add')") @PreAuthorize("hasAuthority('system:dict:add')")

View File

@ -38,6 +38,7 @@ public interface SysDictDataService extends SysDictApiService {
* 批量删除字典数据信息 * 批量删除字典数据信息
* *
* @param ids 需要删除的字典数据ID * @param ids 需要删除的字典数据ID
* @return 结果
*/ */
int deleteByIds(List<String> ids); int deleteByIds(List<String> ids);
@ -74,6 +75,14 @@ public interface SysDictDataService extends SysDictApiService {
*/ */
List<SysDictData> selectList(SysDictDataParam param); List<SysDictData> selectList(SysDictDataParam param);
/**
* 根据字典类型查询字典数据
*
* @param dictType 字典类型
* @return 字典数据集合信息
*/
List<SysDictData> selectByDictType(String dictType);
/** /**
* 重置字典缓存数据 * 重置字典缓存数据
*/ */

View File

@ -111,11 +111,7 @@ public class SysConfigServiceImpl implements SysConfigService {
@Override @Override
public String selectConfigByKey(String configKey) { public String selectConfigByKey(String configKey) {
configKey = ConfigConstant.SYS_CONFIG_KEY_PREFIX + configKey; return redisService.getObject(ConfigConstant.SYS_CONFIG_KEY_PREFIX + configKey, String.class);
if (redisService.hasKey(configKey)) {
return redisService.getObject(configKey, String.class);
}
return null;
} }
private QueryWrapper<SysConfig> param2Wrapper(SysConfigParam param) { private QueryWrapper<SysConfig> param2Wrapper(SysConfigParam param) {

View File

@ -1,15 +1,18 @@
package com.qiaoba.module.system.service.impl; package com.qiaoba.module.system.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qiaoba.api.system.entity.SysDictData; import com.qiaoba.api.system.entity.SysDictData;
import com.qiaoba.api.system.entity.param.SysDictDataParam; import com.qiaoba.api.system.entity.param.SysDictDataParam;
import com.qiaoba.auth.utils.SecurityUtil; import com.qiaoba.auth.utils.SecurityUtil;
import com.qiaoba.common.base.constants.BaseConstant;
import com.qiaoba.common.base.constants.DictConstant;
import com.qiaoba.common.base.exceptions.ServiceException; import com.qiaoba.common.base.exceptions.ServiceException;
import com.qiaoba.common.database.entity.PageQuery; import com.qiaoba.common.database.entity.PageQuery;
import com.qiaoba.common.database.entity.TableDataInfo; import com.qiaoba.common.database.entity.TableDataInfo;
import com.qiaoba.common.redis.constants.CacheConstant; import com.qiaoba.common.redis.service.RedisService;
import com.qiaoba.module.system.mapper.SysDictDataMapper; import com.qiaoba.module.system.mapper.SysDictDataMapper;
import com.qiaoba.module.system.service.SysDictDataService; import com.qiaoba.module.system.service.SysDictDataService;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -18,11 +21,19 @@ import org.springframework.stereotype.Service;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/**
* 字典类型数据管理 服务层实现
*
* @author ailanyin
* @version 1.0
* @since 2022-09-22 04:20:28
*/
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor
public class SysDictDataServiceImpl implements SysDictDataService { public class SysDictDataServiceImpl implements SysDictDataService {
private final SysDictDataMapper sysDictDataMapper; private final SysDictDataMapper sysDictDataMapper;
private final RedisService redisService;
@Override @Override
public String selectDictLabel(String dictType, String dictValue) { public String selectDictLabel(String dictType, String dictValue) {
@ -41,7 +52,12 @@ public class SysDictDataServiceImpl implements SysDictDataService {
@Override @Override
public int deleteByIds(List<String> ids) { public int deleteByIds(List<String> ids) {
return sysDictDataMapper.deleteBatchIds(ids); SysDictData sysDictData = selectById(ids.get(0));
int result = sysDictDataMapper.deleteBatchIds(ids);
if (result > BaseConstant.HANDLE_ERROR) {
cacheDictData(sysDictData.getDictType());
}
return result;
} }
@Override @Override
@ -49,7 +65,11 @@ public class SysDictDataServiceImpl implements SysDictDataService {
checkAllowAddOrUpdate(sysDictData); checkAllowAddOrUpdate(sysDictData);
sysDictData.setCreateTime(new Date()); sysDictData.setCreateTime(new Date());
sysDictData.setCreateUser(SecurityUtil.getLoginUsername()); sysDictData.setCreateUser(SecurityUtil.getLoginUsername());
return sysDictDataMapper.insert(sysDictData); int result = sysDictDataMapper.insert(sysDictData);
if (result > BaseConstant.HANDLE_ERROR) {
cacheDictData(sysDictData.getDictType());
}
return result;
} }
@Override @Override
@ -57,7 +77,11 @@ public class SysDictDataServiceImpl implements SysDictDataService {
checkAllowAddOrUpdate(sysDictData); checkAllowAddOrUpdate(sysDictData);
sysDictData.setUpdateTime(new Date()); sysDictData.setUpdateTime(new Date());
sysDictData.setUpdateUser(SecurityUtil.getLoginUsername()); sysDictData.setUpdateUser(SecurityUtil.getLoginUsername());
return sysDictDataMapper.updateById(sysDictData); int result = sysDictDataMapper.updateById(sysDictData);
if (result > BaseConstant.HANDLE_ERROR) {
cacheDictData(sysDictData.getDictType());
}
return result;
} }
@Override @Override
@ -72,7 +96,11 @@ public class SysDictDataServiceImpl implements SysDictDataService {
@Override @Override
public void resetDictCache() { public void resetDictCache() {
redisService.del(redisService.getKeys(DictConstant.SYS_DICT_KEY + "*"));
Map<String, List<SysDictData>> dictDataMap = selectList(new SysDictDataParam()).stream().collect(Collectors.groupingBy(SysDictData::getDictType));
for (Map.Entry<String, List<SysDictData>> entry : dictDataMap.entrySet()) {
redisService.set(DictConstant.SYS_DICT_KEY + entry.getKey(), entry.getValue().stream().sorted(Comparator.comparing(SysDictData::getDictSort)).collect(Collectors.toList()));
}
} }
@Override @Override
@ -100,4 +128,18 @@ public class SysDictDataServiceImpl implements SysDictDataService {
throw new ServiceException("数据键值已存在"); throw new ServiceException("数据键值已存在");
} }
} }
private void cacheDictData(String dictType) {
List<SysDictData> dictData = selectByDictType(dictType);
if (CollUtil.isNotEmpty(dictData)) {
redisService.set(DictConstant.SYS_DICT_KEY + dictType, dictData.stream().sorted(Comparator.comparing(SysDictData::getDictSort)).collect(Collectors.toList()));
} else {
redisService.del(DictConstant.SYS_DICT_KEY + dictType);
}
}
@Override
public List<SysDictData> selectFromCache(String dictType) {
return redisService.getObjectList(DictConstant.SYS_DICT_KEY + dictType, SysDictData.class);
}
} }

View File

@ -2,26 +2,20 @@ package com.qiaoba.module.system.service.impl;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qiaoba.api.system.entity.SysDictData;
import com.qiaoba.api.system.entity.SysDictType; import com.qiaoba.api.system.entity.SysDictType;
import com.qiaoba.api.system.entity.param.SysDictDataParam;
import com.qiaoba.api.system.entity.param.SysDictTypeParam; import com.qiaoba.api.system.entity.param.SysDictTypeParam;
import com.qiaoba.auth.utils.SecurityUtil; import com.qiaoba.auth.utils.SecurityUtil;
import com.qiaoba.common.base.exceptions.ServiceException; import com.qiaoba.common.base.exceptions.ServiceException;
import com.qiaoba.common.database.entity.PageQuery; import com.qiaoba.common.database.entity.PageQuery;
import com.qiaoba.common.database.entity.TableDataInfo; import com.qiaoba.common.database.entity.TableDataInfo;
import com.qiaoba.common.redis.constants.CacheConstant;
import com.qiaoba.common.redis.service.RedisService; import com.qiaoba.common.redis.service.RedisService;
import com.qiaoba.module.system.mapper.SysDictTypeMapper; import com.qiaoba.module.system.mapper.SysDictTypeMapper;
import com.qiaoba.module.system.service.SysDictTypeService; import com.qiaoba.module.system.service.SysDictTypeService;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Comparator;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/** /**
* 字典类型管理 服务层实现 * 字典类型管理 服务层实现

View File

@ -42,12 +42,8 @@ public class SysUserDetailsServiceImpl implements UserDetailsService, SysUserDet
@Override @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if (redisService.hasKey(SecurityConstant.USER_DETAILS_REDIS_KEY + username)) { SecurityUser user = redisService.getObject(SecurityConstant.USER_DETAILS_REDIS_KEY + username, SecurityUser.class);
SecurityUser user = redisService.getObject(SecurityConstant.USER_DETAILS_REDIS_KEY + username, SecurityUser.class); return Objects.isNull(user) ? null : new LoginUser(user.getDeviceSn(), user.getUserId(), user.getDeptId(), user.getUsername(), user.getNickname(), user.getRoles(), user.getRoleKeys(), user.getPermissions());
return new LoginUser(user.getDeviceSn(), user.getUserId(), user.getDeptId(), user.getUsername(), user.getNickname(), user.getRoles(), user.getRoleKeys(), user.getPermissions());
}
return null;
} }