mirror of
http://192.168.1.205:9980/cf_devdept2/cf_imes_server.git
synced 2026-08-12 12:52:07 +08:00
Merge branch 'main' of ssh://192.168.1.205:9922/cf_devdept2/cf_imes_server
This commit is contained in:
+13
@@ -66,4 +66,17 @@ public class StrUtils {
|
||||
.collect(Collectors.joining("\n"));
|
||||
}
|
||||
|
||||
/**
|
||||
* a字符串是否包含b
|
||||
*
|
||||
* @param a
|
||||
* @param b
|
||||
* @return
|
||||
*/
|
||||
public static boolean contains(String a, String b) {
|
||||
if (CharSequenceUtil.isEmpty(a) || CharSequenceUtil.isEmpty(b)) {
|
||||
return false;
|
||||
}
|
||||
return a.contains(b);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,12 +25,6 @@
|
||||
<artifactId>cf-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- IP地址检索 -->
|
||||
<dependency>
|
||||
<groupId>org.lionsoul</groupId>
|
||||
<artifactId>ip2region</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
@@ -48,6 +42,16 @@
|
||||
<artifactId>cf-spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package com.cf.imes.framework.ip.config;
|
||||
|
||||
import com.cf.imes.framework.ip.core.property.IPQueryProperties;
|
||||
import com.cf.imes.framework.ip.core.service.IPQueryService;
|
||||
import com.cf.imes.framework.ip.core.service.imp.IPQueryServiceImpl;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
/**
|
||||
* ip自动注册配置
|
||||
*
|
||||
* @author 晨丰科技
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@EnableConfigurationProperties(IPQueryProperties.class)
|
||||
public class ChenfengIPAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public IPQueryService ipQueryService() {
|
||||
return new IPQueryServiceImpl();
|
||||
}
|
||||
}
|
||||
-55
@@ -1,55 +0,0 @@
|
||||
package com.cf.imes.framework.ip.core;
|
||||
|
||||
import com.cf.imes.framework.ip.core.enums.AreaTypeEnum;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 区域节点,包括国家、省份、城市、地区等信息
|
||||
*
|
||||
* 数据可见 resources/area.csv 文件
|
||||
*
|
||||
* @author 晨丰科技
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class Area {
|
||||
|
||||
/**
|
||||
* 编号 - 全球,即根目录
|
||||
*/
|
||||
public static final Integer ID_GLOBAL = 0;
|
||||
/**
|
||||
* 编号 - 中国
|
||||
*/
|
||||
public static final Integer ID_CHINA = 1;
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 类型
|
||||
*
|
||||
* 枚举 {@link AreaTypeEnum}
|
||||
*/
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 父节点
|
||||
*/
|
||||
private Area parent;
|
||||
/**
|
||||
* 子节点
|
||||
*/
|
||||
private List<Area> children;
|
||||
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.cf.imes.framework.ip.core.enums;
|
||||
|
||||
import com.cf.imes.framework.common.exception.ErrorCode;
|
||||
|
||||
/**
|
||||
* ip查询 错误码枚举类
|
||||
*
|
||||
* 使用 1-008-000-000 段
|
||||
*/
|
||||
public class ErrorCodeConstants {
|
||||
|
||||
public static final ErrorCode IP_QUERY_ERROR = new ErrorCode(1_008_000_000, "IP归属地查询异常,请联系客服处理");
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
package com.cf.imes.framework.ip.core.property;
|
||||
|
||||
import com.cf.imes.framework.common.util.encrypt.AesUtils;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
|
||||
/**
|
||||
* ip查询服务配置
|
||||
* @author Gqr
|
||||
* @since 2024/10/30 9:59
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "chenfeng.ipquery")
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class IPQueryProperties {
|
||||
|
||||
@Value("${chenfeng.encrypt.publicKey:}")
|
||||
private String publicKey;
|
||||
|
||||
/**
|
||||
* 开关
|
||||
*/
|
||||
private boolean enable;
|
||||
|
||||
/**
|
||||
* 接口地址
|
||||
*/
|
||||
private String apiUrl;
|
||||
|
||||
/**
|
||||
* 接口认证编码
|
||||
*/
|
||||
private String appCode;
|
||||
|
||||
public boolean isEnable() {
|
||||
return enable;
|
||||
}
|
||||
|
||||
public void setEnable(boolean enable) {
|
||||
this.enable = enable;
|
||||
}
|
||||
|
||||
public String getAppCode() {
|
||||
return appCode;
|
||||
}
|
||||
|
||||
public IPQueryProperties setAppCode(String appCode) {
|
||||
this.appCode = AesUtils.decrypt(appCode, publicKey);
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getApiUrl() {
|
||||
return apiUrl;
|
||||
}
|
||||
|
||||
public void setApiUrl(String apiUrl) {
|
||||
this.apiUrl = apiUrl;
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package com.cf.imes.framework.ip.core.service;
|
||||
|
||||
import com.cf.imes.framework.ip.core.service.dto.IPQueryDataRespDTO;
|
||||
|
||||
/**
|
||||
* ip查询服务
|
||||
*
|
||||
* @author Gqr
|
||||
* @since 2024/10/30 10:54
|
||||
*/
|
||||
public interface IPQueryService {
|
||||
|
||||
/**
|
||||
* 服务是否开启
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean serviceEnable();
|
||||
|
||||
/**
|
||||
* 查询ip归属地
|
||||
*
|
||||
* @param ip
|
||||
* @return
|
||||
*/
|
||||
IPQueryDataRespDTO querySource(String ip);
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
package com.cf.imes.framework.ip.core.service.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* ip来源查询明细
|
||||
*
|
||||
* @author Gqr
|
||||
* @since 2024/10/30 11:00
|
||||
*/
|
||||
@Data
|
||||
public class IPQueryDataRespDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 3403763102169461000L;
|
||||
|
||||
/**
|
||||
* ip
|
||||
*/
|
||||
private String ip;
|
||||
|
||||
/**
|
||||
* 国家
|
||||
*/
|
||||
private String country;
|
||||
|
||||
/**
|
||||
* 国家编号
|
||||
*/
|
||||
private String countryCode;
|
||||
|
||||
/**
|
||||
* 省份
|
||||
*/
|
||||
private String prov;
|
||||
|
||||
/**
|
||||
* 城市
|
||||
*/
|
||||
private String city;
|
||||
|
||||
/**
|
||||
* 城市编号
|
||||
*/
|
||||
private String cityCode;
|
||||
|
||||
/**
|
||||
* 城市编号缩写
|
||||
*/
|
||||
private String cityShortCode;
|
||||
|
||||
/**
|
||||
* 区域
|
||||
*/
|
||||
private String area;
|
||||
|
||||
/**
|
||||
* 邮编
|
||||
*/
|
||||
private String postCode;
|
||||
|
||||
/**
|
||||
* 区域编码
|
||||
*/
|
||||
private String areaCode;
|
||||
|
||||
/**
|
||||
* 运营商
|
||||
*/
|
||||
private String isp;
|
||||
|
||||
/**
|
||||
* 经度
|
||||
*/
|
||||
private String lng;
|
||||
|
||||
/**
|
||||
* 纬度
|
||||
*/
|
||||
private String lat;
|
||||
|
||||
/**
|
||||
* 大区
|
||||
*/
|
||||
private String bigArea;
|
||||
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package com.cf.imes.framework.ip.core.service.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* ip来源查询结果
|
||||
*
|
||||
* @author Gqr
|
||||
* @since 2024/10/30 10:59
|
||||
*/
|
||||
@Data
|
||||
public class IPQueryRespDTO implements Serializable {
|
||||
private static final long serialVersionUID = -5526001196829386416L;
|
||||
|
||||
/**
|
||||
* 响应码,200:正常、400:ip参数不正确
|
||||
*/
|
||||
private int ret;
|
||||
|
||||
/**
|
||||
* ip来源信息
|
||||
*/
|
||||
private IPQueryDataRespDTO data;
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
package com.cf.imes.framework.ip.core.service.imp;
|
||||
|
||||
import cn.hutool.core.net.NetUtil;
|
||||
import cn.hutool.core.text.CharSequenceUtil;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.http.HttpStatus;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.cf.imes.framework.common.exception.ErrorCode;
|
||||
import com.cf.imes.framework.common.exception.ServiceException;
|
||||
import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil;
|
||||
import com.cf.imes.framework.ip.core.enums.ErrorCodeConstants;
|
||||
import com.cf.imes.framework.ip.core.property.IPQueryProperties;
|
||||
import com.cf.imes.framework.ip.core.service.IPQueryService;
|
||||
import com.cf.imes.framework.ip.core.service.dto.IPQueryDataRespDTO;
|
||||
import com.cf.imes.framework.ip.core.service.dto.IPQueryRespDTO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* @author Gqr
|
||||
* @since 2024/10/30 11:02
|
||||
*/
|
||||
@Slf4j
|
||||
public class IPQueryServiceImpl implements IPQueryService {
|
||||
|
||||
@Resource
|
||||
private IPQueryProperties ipQueryProperties;
|
||||
|
||||
|
||||
@Override
|
||||
public boolean serviceEnable() {
|
||||
return ipQueryProperties.isEnable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPQueryDataRespDTO querySource(String ip) {
|
||||
// 校验是否内部ip
|
||||
if (NetUtil.isInnerIP(ip)) {
|
||||
return new IPQueryDataRespDTO().setIp(ip).setProv("未知");
|
||||
}
|
||||
ErrorCode queryError = ErrorCodeConstants.IP_QUERY_ERROR;
|
||||
try {
|
||||
String apiUrl = ipQueryProperties.getApiUrl();
|
||||
String appCode = ipQueryProperties.getAppCode();
|
||||
if (CharSequenceUtil.isEmpty(apiUrl)) {
|
||||
log.error("[IPQueryService][querySource]request apiUrl为空");
|
||||
throw ServiceExceptionUtil.exception(queryError);
|
||||
}
|
||||
if (CharSequenceUtil.isEmpty(appCode)) {
|
||||
log.error("[IPQueryService][querySource]request appCode为空");
|
||||
throw ServiceExceptionUtil.exception(queryError);
|
||||
}
|
||||
log.info("[IPQueryService][querySource]request url:{}", apiUrl);
|
||||
log.info("[IPQueryService][querySource]request param, appCode: {}, ip: {}", appCode, ip);
|
||||
HttpResponse execute = HttpRequest.get(apiUrl).header("Authorization", "APPCODE " + appCode).form("ip", ip).execute();
|
||||
log.info("[IPQueryService][querySource]request status:{}, response: {}", execute.getStatus(), execute.body());
|
||||
String respBody = execute.body();
|
||||
IPQueryRespDTO ipQueryRespDTO = JSON.parseObject(execute.body(), IPQueryRespDTO.class);
|
||||
if (HttpStatus.HTTP_OK == ipQueryRespDTO.getRet()) {
|
||||
IPQueryDataRespDTO data = ipQueryRespDTO.getData();
|
||||
data.setIp(ip);
|
||||
return data;
|
||||
} else {
|
||||
ServiceException serviceException = ServiceExceptionUtil.exception(queryError);
|
||||
log.error(serviceException.getMessage() + ",状态【{}】,异常:{}", ipQueryRespDTO.getRet(), respBody);
|
||||
return null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(queryError.getMsg(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
-162
@@ -1,162 +0,0 @@
|
||||
package com.cf.imes.framework.ip.core.utils;
|
||||
|
||||
import cn.hutool.core.io.resource.ResourceUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.text.csv.CsvRow;
|
||||
import cn.hutool.core.text.csv.CsvUtil;
|
||||
import com.cf.imes.framework.common.util.object.ObjectUtils;
|
||||
import com.cf.imes.framework.ip.core.Area;
|
||||
import com.cf.imes.framework.ip.core.enums.AreaTypeEnum;
|
||||
import lombok.NonNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static com.cf.imes.framework.common.util.collection.CollectionUtils.convertList;
|
||||
|
||||
/**
|
||||
* 区域工具类
|
||||
*
|
||||
* @author 晨丰科技
|
||||
*/
|
||||
@Slf4j
|
||||
public class AreaUtils {
|
||||
|
||||
/**
|
||||
* 初始化 SEARCHER
|
||||
*/
|
||||
@SuppressWarnings("InstantiationOfUtilityClass")
|
||||
private final static AreaUtils INSTANCE = new AreaUtils();
|
||||
|
||||
/**
|
||||
* Area 内存缓存,提升访问速度
|
||||
*/
|
||||
private static Map<Integer, Area> areas;
|
||||
|
||||
private AreaUtils() {
|
||||
long now = System.currentTimeMillis();
|
||||
areas = new HashMap<>();
|
||||
areas.put(Area.ID_GLOBAL, new Area(Area.ID_GLOBAL, "全球", 0,
|
||||
null, new ArrayList<>()));
|
||||
// 从 csv 中加载数据
|
||||
List<CsvRow> rows = CsvUtil.getReader().read(ResourceUtil.getUtf8Reader("area.csv")).getRows();
|
||||
rows.remove(0); // 删除 header
|
||||
for (CsvRow row : rows) {
|
||||
// 创建 Area 对象
|
||||
Area area = new Area(Integer.valueOf(row.get(0)), row.get(1), Integer.valueOf(row.get(2)),
|
||||
null, new ArrayList<>());
|
||||
// 添加到 areas 中
|
||||
areas.put(area.getId(), area);
|
||||
}
|
||||
|
||||
// 构建父子关系:因为 Area 中没有 parentId 字段,所以需要重复读取
|
||||
for (CsvRow row : rows) {
|
||||
Area area = areas.get(Integer.valueOf(row.get(0))); // 自己
|
||||
Area parent = areas.get(Integer.valueOf(row.get(3))); // 父
|
||||
Assert.isTrue(area != parent, "{}:父子节点相同", area.getName());
|
||||
area.setParent(parent);
|
||||
parent.getChildren().add(area);
|
||||
}
|
||||
log.info("启动加载 AreaUtils 成功,耗时 ({}) 毫秒", System.currentTimeMillis() - now);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得指定编号对应的区域
|
||||
*
|
||||
* @param id 区域编号
|
||||
* @return 区域
|
||||
*/
|
||||
public static Area getArea(Integer id) {
|
||||
return areas.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化区域
|
||||
*
|
||||
* @param id 区域编号
|
||||
* @return 格式化后的区域
|
||||
*/
|
||||
public static String format(Integer id) {
|
||||
return format(id, " ");
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化区域
|
||||
*
|
||||
* 例如说:
|
||||
* 1. id = “静安区”时:上海 上海市 静安区
|
||||
* 2. id = “上海市”时:上海 上海市
|
||||
* 3. id = “上海”时:上海
|
||||
* 4. id = “美国”时:美国
|
||||
* 当区域在中国时,默认不显示中国
|
||||
*
|
||||
* @param id 区域编号
|
||||
* @param separator 分隔符
|
||||
* @return 格式化后的区域
|
||||
*/
|
||||
public static String format(Integer id, String separator) {
|
||||
// 获得区域
|
||||
Area area = areas.get(id);
|
||||
if (area == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 格式化
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < AreaTypeEnum.values().length; i++) { // 避免死循环
|
||||
sb.insert(0, area.getName());
|
||||
// “递归”父节点
|
||||
area = area.getParent();
|
||||
if (area == null
|
||||
|| ObjectUtils.equalsAny(area.getId(), Area.ID_GLOBAL, Area.ID_CHINA)) { // 跳过父节点为中国的情况
|
||||
break;
|
||||
}
|
||||
sb.insert(0, separator);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定类型的区域列表
|
||||
*
|
||||
* @param type 区域类型
|
||||
* @param func 转换函数
|
||||
* @param <T> 结果类型
|
||||
* @return 区域列表
|
||||
*/
|
||||
public static <T> List<T> getByType(AreaTypeEnum type, Function<Area, T> func) {
|
||||
return convertList(areas.values(), func, area -> type.getType().equals(area.getType()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据区域编号、上级区域类型,获取上级区域编号
|
||||
*
|
||||
* @param id 区域编号
|
||||
* @param type 区域类型
|
||||
* @return 上级区域编号
|
||||
*/
|
||||
public static Integer getParentIdByType(Integer id, @NonNull AreaTypeEnum type) {
|
||||
for (int i = 0; i < Byte.MAX_VALUE; i++) {
|
||||
Area area = AreaUtils.getArea(id);
|
||||
if (area == null) {
|
||||
return null;
|
||||
}
|
||||
// 情况一:匹配到,返回它
|
||||
if (type.getType().equals(area.getType())) {
|
||||
return area.getId();
|
||||
}
|
||||
// 情况二:找到根节点,返回空
|
||||
if (area.getParent() == null || area.getParent().getId() == null) {
|
||||
return null;
|
||||
}
|
||||
// 其它:继续向上查找
|
||||
id = area.getParent().getId();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
-87
@@ -1,87 +0,0 @@
|
||||
package com.cf.imes.framework.ip.core.utils;
|
||||
|
||||
import cn.hutool.core.io.resource.ResourceUtil;
|
||||
import com.cf.imes.framework.ip.core.Area;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.lionsoul.ip2region.xdb.Searcher;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* IP 工具类
|
||||
*
|
||||
* IP 数据源来自 ip2region.xdb 精简版,基于 <a href="https://gitee.com/zhijiantianya/ip2region"/> 项目
|
||||
*
|
||||
* @author wanglhup
|
||||
*/
|
||||
@Slf4j
|
||||
public class IPUtils {
|
||||
|
||||
/**
|
||||
* 初始化 SEARCHER
|
||||
*/
|
||||
@SuppressWarnings("InstantiationOfUtilityClass")
|
||||
private final static IPUtils INSTANCE = new IPUtils();
|
||||
|
||||
/**
|
||||
* IP 查询器,启动加载到内存中
|
||||
*/
|
||||
private static Searcher SEARCHER;
|
||||
|
||||
/**
|
||||
* 私有化构造
|
||||
*/
|
||||
private IPUtils() {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
byte[] bytes = ResourceUtil.readBytes("ip2region.xdb");
|
||||
SEARCHER = Searcher.newWithBuffer(bytes);
|
||||
log.info("启动加载 IPUtils 成功,耗时 ({}) 毫秒", System.currentTimeMillis() - now);
|
||||
} catch (IOException e) {
|
||||
log.error("启动加载 IPUtils 失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询 IP 对应的地区编号
|
||||
*
|
||||
* @param ip IP 地址,格式为 127.0.0.1
|
||||
* @return 地区id
|
||||
*/
|
||||
@SneakyThrows
|
||||
public static Integer getAreaId(String ip) {
|
||||
return Integer.parseInt(SEARCHER.search(ip.trim()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询 IP 对应的地区编号
|
||||
*
|
||||
* @param ip IP 地址的时间戳,格式参考{@link Searcher#checkIP(String)} 的返回
|
||||
* @return 地区编号
|
||||
*/
|
||||
@SneakyThrows
|
||||
public static Integer getAreaId(long ip) {
|
||||
return Integer.parseInt(SEARCHER.search(ip));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询 IP 对应的地区
|
||||
*
|
||||
* @param ip IP 地址,格式为 127.0.0.1
|
||||
* @return 地区
|
||||
*/
|
||||
public static Area getArea(String ip) {
|
||||
return AreaUtils.getArea(getAreaId(ip));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询 IP 对应的地区
|
||||
*
|
||||
* @param ip IP 地址的时间戳,格式参考{@link Searcher#checkIP(String)} 的返回
|
||||
* @return 地区
|
||||
*/
|
||||
public static Area getArea(long ip) {
|
||||
return AreaUtils.getArea(getAreaId(ip));
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
com.cf.imes.framework.ip.config.ChenfengIPAutoConfiguration
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
-36
@@ -1,36 +0,0 @@
|
||||
package com.cf.imes.framework.ip.core.utils;
|
||||
|
||||
|
||||
import com.cf.imes.framework.ip.core.Area;
|
||||
import com.cf.imes.framework.ip.core.enums.AreaTypeEnum;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
/**
|
||||
* {@link AreaUtils} 的单元测试
|
||||
*
|
||||
* @author 晨丰科技
|
||||
*/
|
||||
public class AreaUtilsTest {
|
||||
|
||||
@Test
|
||||
public void testGetArea() {
|
||||
// 调用:北京
|
||||
Area area = AreaUtils.getArea(110100);
|
||||
// 断言
|
||||
assertEquals(area.getId(), 110100);
|
||||
assertEquals(area.getName(), "北京市");
|
||||
assertEquals(area.getType(), AreaTypeEnum.CITY.getType());
|
||||
assertEquals(area.getParent().getId(), 110000);
|
||||
assertEquals(area.getChildren().size(), 16);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFormat() {
|
||||
assertEquals(AreaUtils.format(110105), "北京 北京市 朝阳区");
|
||||
assertEquals(AreaUtils.format(1), "中国");
|
||||
assertEquals(AreaUtils.format(2), "蒙古");
|
||||
}
|
||||
|
||||
}
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
package com.cf.imes.framework.ip.core.utils;
|
||||
|
||||
import com.cf.imes.framework.ip.core.Area;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.lionsoul.ip2region.xdb.Searcher;
|
||||
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
/**
|
||||
* {@link IPUtils} 的单元测试
|
||||
*
|
||||
* @author wanglhup
|
||||
*/
|
||||
public class IPUtilsTest {
|
||||
|
||||
@Test
|
||||
public void testGetAreaId_string() {
|
||||
// 120.202.4.0|120.202.4.255|420600
|
||||
Integer areaId = IPUtils.getAreaId("120.202.4.50");
|
||||
assertEquals(420600, areaId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAreaId_long() throws Exception {
|
||||
// 120.203.123.0|120.203.133.255|360900
|
||||
long ip = Searcher.checkIP("120.203.123.250");
|
||||
Integer areaId = IPUtils.getAreaId(ip);
|
||||
assertEquals(360900, areaId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetArea_string() {
|
||||
// 120.202.4.0|120.202.4.255|420600
|
||||
Area area = IPUtils.getArea("120.202.4.50");
|
||||
assertEquals("襄阳市", area.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetArea_long() throws Exception {
|
||||
// 120.203.123.0|120.203.133.255|360900
|
||||
long ip = Searcher.checkIP("120.203.123.252");
|
||||
Area area = IPUtils.getArea(ip);
|
||||
assertEquals("宜春市", area.getName());
|
||||
}
|
||||
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
package com.cf.imes.framework.ip.service;
|
||||
|
||||
import com.cf.imes.framework.common.exception.ServiceException;
|
||||
import com.cf.imes.framework.ip.config.ChenfengIPAutoConfiguration;
|
||||
import com.cf.imes.framework.ip.core.service.IPQueryService;
|
||||
import com.cf.imes.framework.ip.core.service.dto.IPQueryDataRespDTO;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import static com.cf.imes.framework.test.core.util.RandomUtils.randomString;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
/**
|
||||
* {@link IPQueryService} 的单元测试
|
||||
*
|
||||
* @author gaoqr
|
||||
*/
|
||||
@SpringBootTest(classes = {ChenfengIPAutoConfiguration.class}, webEnvironment = SpringBootTest.WebEnvironment.NONE)
|
||||
@ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件
|
||||
public class IPQueryServiceTest {
|
||||
@Resource
|
||||
private IPQueryService ipQueryService;
|
||||
|
||||
|
||||
@Test
|
||||
public void testQuerySourceFail() {
|
||||
assertThrows(ServiceException.class, () -> ipQueryService.querySource(randomString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQuerySourceSuccess() {
|
||||
IPQueryDataRespDTO ipQueryDataRespDTO = ipQueryService.querySource("220.250.48.74");
|
||||
assertNotNull(ipQueryDataRespDTO);
|
||||
assertEquals(ipQueryDataRespDTO.getProv(), "福建");
|
||||
assertEquals(ipQueryDataRespDTO.getCity(), "福州");
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
# 晨丰配置项,设置当前项目所有自定义的配置
|
||||
chenfeng:
|
||||
encrypt:
|
||||
publicKey: cfimes
|
||||
ipquery:
|
||||
apiUrl: https://ipquery.market.alicloudapi.com/query
|
||||
appCode: zAE0h8wOBZbwIwDob1tXJfJsdxpQ2QYzIgie7oSozCLHXsdD8hhkot6UBs55Vhm35KYrqGj+t0W4IOSr
|
||||
+17
-1
@@ -1,5 +1,6 @@
|
||||
package com.cf.imes.framework.organ.core.redis;
|
||||
|
||||
import cn.hutool.core.text.CharSequenceUtil;
|
||||
import com.cf.imes.framework.redis.core.TimeoutRedisCacheManager;
|
||||
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -8,6 +9,9 @@ import org.springframework.data.redis.cache.RedisCacheConfiguration;
|
||||
import org.springframework.data.redis.cache.RedisCacheManager;
|
||||
import org.springframework.data.redis.cache.RedisCacheWriter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 多组织的 {@link RedisCacheManager} 实现类
|
||||
*
|
||||
@@ -18,6 +22,13 @@ import org.springframework.data.redis.cache.RedisCacheWriter;
|
||||
@Slf4j
|
||||
public class OrganRedisCacheManager extends TimeoutRedisCacheManager {
|
||||
|
||||
// 不需要拼接组织id的redis-key列表
|
||||
private static final List<String> ignoreOrganIdKeyList = new ArrayList<>();
|
||||
|
||||
static {
|
||||
ignoreOrganIdKeyList.add("tenant_package_menu_ids");
|
||||
}
|
||||
|
||||
public OrganRedisCacheManager(RedisCacheWriter cacheWriter,
|
||||
RedisCacheConfiguration defaultCacheConfiguration) {
|
||||
super(cacheWriter, defaultCacheConfiguration);
|
||||
@@ -25,9 +36,14 @@ public class OrganRedisCacheManager extends TimeoutRedisCacheManager {
|
||||
|
||||
@Override
|
||||
public Cache getCache(String name) {
|
||||
// key带#代表设置了ttl,只保留#前的部分作为key
|
||||
if (name.contains("#")) {
|
||||
name = CharSequenceUtil.subBefore(name, "#", false);
|
||||
}
|
||||
// 如果开启多组织,则 name 拼接组织后缀
|
||||
if (!OrganContextHolder.isIgnore()
|
||||
&& OrganContextHolder.getOrganId() != null) {
|
||||
&& OrganContextHolder.getOrganId() != null
|
||||
&& !ignoreOrganIdKeyList.contains(name)) {
|
||||
name = name + ":" + OrganContextHolder.getOrganId();
|
||||
}
|
||||
|
||||
|
||||
+6
-3
@@ -41,12 +41,15 @@ public class TimeoutRedisCacheManager extends RedisCacheManager {
|
||||
// 核心:通过修改 cacheConfig 的过期时间,实现自定义过期时间
|
||||
if (cacheConfig != null) {
|
||||
// 移除 # 后面的 : 以及后面的内容,避免影响解析
|
||||
names[1] = CharSequenceUtil.subBefore(names[1], StrPool.COLON, false);
|
||||
String ttlStr = CharSequenceUtil.subBefore(names[1], StrPool.COLON, false); // 获得 ttlStr 时间部分
|
||||
names[1] = CharSequenceUtil.subAfter(names[1], ttlStr, false); // 移除掉 ttlStr 时间部分
|
||||
// 解析时间
|
||||
Duration duration = parseDuration(names[1]);
|
||||
Duration duration = parseDuration(ttlStr);
|
||||
cacheConfig = cacheConfig.entryTtl(duration);
|
||||
}
|
||||
return super.createRedisCache(name, cacheConfig);
|
||||
|
||||
// 创建 RedisCache 对象,需要忽略掉 ttlStr
|
||||
return super.createRedisCache(names[0] + names[1], cacheConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
@@ -40,4 +40,7 @@ public class LoginLogCreateReqDTO {
|
||||
@Schema(description = "浏览器 UserAgent", requiredMode = Schema.RequiredMode.REQUIRED, example = "Mozilla/5.0")
|
||||
private String userAgent;
|
||||
|
||||
@Schema(description = "所属地区")
|
||||
@Size(max = 200, message = "所属地区长度不能超过200个字符")
|
||||
private String region;
|
||||
}
|
||||
|
||||
+4
@@ -17,6 +17,8 @@ public class ErrorCodeConstants {
|
||||
public static final ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1_002_000_006, "Token 已经过期");
|
||||
public static final ErrorCode AUTH_MOBILE_NOT_EXISTS = new ErrorCode(1_002_000_007, "手机号不存在");
|
||||
public static final ErrorCode AUTH_MOBILE_NO_CHANGE = new ErrorCode(1_002_000_008, "手机号未发生改变,无需修改");
|
||||
public static final ErrorCode AUTH_LOGIN_GEO_UNCORRECT = new ErrorCode(1_002_000_009, "登录失败,请前往机构登记地址登录系统");
|
||||
public static final ErrorCode AUTH_LOGIN_ORG_GEO_EMPTY = new ErrorCode(1_002_000_010, "当前组织地址未登记,请联系组织管理员");
|
||||
|
||||
// ========== 菜单模块 1-002-001-000 ==========
|
||||
public static final ErrorCode MENU_NAME_DUPLICATE = new ErrorCode(1_002_001_000, "已经存在该名字的菜单");
|
||||
@@ -35,6 +37,8 @@ public class ErrorCodeConstants {
|
||||
public static final ErrorCode ROLE_ADMIN_CODE_ERROR = new ErrorCode(1_002_002_005, "编码【{}】不能使用");
|
||||
public static final ErrorCode ROLE_ME_ERROR = new ErrorCode(1_002_002_006, "不可为自身分配角色");
|
||||
public static final ErrorCode ROLE_NOT_SUPERADMIN_NO_ORGAN_ID_OPER_ERROR = new ErrorCode(1_002_002_007, "非超管分配权限");
|
||||
public static final ErrorCode BUILDIN_ROLE_MODIFY_PERMISSION_ERROR = new ErrorCode(1_002_002_008, "修改内置角色下菜单权限的权限不足");
|
||||
public static final ErrorCode SELF_ROLE_MODIFY_PERMISSION_ERROR = new ErrorCode(1_002_002_009, "无法修改自身的角色菜单权限");
|
||||
|
||||
// ========== 用户模块 1-002-003-000 ==========
|
||||
public static final ErrorCode USER_USERNAME_EXISTS = new ErrorCode(1_002_003_000, "手机号已经存在");
|
||||
|
||||
+40
-8
@@ -1,12 +1,18 @@
|
||||
package com.cf.imes.module.system.controller.admin.auth;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.cf.imes.framework.common.enums.CommonStatusEnum;
|
||||
import com.cf.imes.framework.common.enums.UserTypeEnum;
|
||||
import com.cf.imes.framework.common.exception.ServiceException;
|
||||
import com.cf.imes.framework.common.exception.enums.GlobalErrorCodeConstants;
|
||||
import com.cf.imes.framework.common.pojo.CommonResult;
|
||||
import com.cf.imes.framework.common.validation.Mobile;
|
||||
import com.cf.imes.framework.ip.core.service.IPQueryService;
|
||||
import com.cf.imes.framework.ip.core.service.dto.IPQueryDataRespDTO;
|
||||
import com.cf.imes.framework.operatelog.core.annotations.OperateLog;
|
||||
import com.cf.imes.framework.security.config.SecurityProperties;
|
||||
import com.cf.imes.framework.security.core.LoginUser;
|
||||
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
|
||||
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
|
||||
import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginReqVO;
|
||||
@@ -14,11 +20,13 @@ import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginSmsCheckReqVO
|
||||
import com.cf.imes.module.system.controller.admin.auth.vo.AuthPermissionInfoRespVO;
|
||||
import com.cf.imes.module.system.controller.admin.auth.vo.AuthSocialLoginReqVO;
|
||||
import com.cf.imes.module.system.convert.auth.AuthConvert;
|
||||
import com.cf.imes.module.system.dal.dataobject.organ.OrganizationDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.permission.MenuDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.permission.RoleDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import com.cf.imes.module.system.enums.logger.LoginLogTypeEnum;
|
||||
import com.cf.imes.module.system.service.auth.AdminAuthService;
|
||||
import com.cf.imes.module.system.service.organ.OrganService;
|
||||
import com.cf.imes.module.system.service.permission.MenuService;
|
||||
import com.cf.imes.module.system.service.permission.PermissionService;
|
||||
import com.cf.imes.module.system.service.permission.RoleService;
|
||||
@@ -35,6 +43,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@@ -50,7 +59,6 @@ import java.util.Set;
|
||||
import static com.cf.imes.framework.common.pojo.CommonResult.success;
|
||||
import static com.cf.imes.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
import static com.cf.imes.framework.common.util.servlet.ServletUtils.getClientIP;
|
||||
import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
|
||||
@Tag(name = "管理后台 - 认证")
|
||||
@RestController
|
||||
@@ -78,11 +86,23 @@ public class AuthController {
|
||||
@Resource
|
||||
private SmsCodeService smsCodeService;
|
||||
|
||||
@Resource
|
||||
private OrganService organService;
|
||||
|
||||
@Resource
|
||||
private IPQueryService ipQueryService;
|
||||
|
||||
/**
|
||||
* ip服务开关,默认为 false不开启
|
||||
*/
|
||||
@Value("${chenfeng.ipquery.enable:false}")
|
||||
private boolean ipQueryEnable;
|
||||
|
||||
@PostMapping("/login")
|
||||
@PermitAll
|
||||
@Operation(summary = "使用账号密码登录")
|
||||
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志
|
||||
public CommonResult<AuthLoginRespVO> login(@Valid @RequestBody AuthLoginReqVO reqVO) {
|
||||
public CommonResult<AuthLoginRespVO> login(@Valid @RequestBody AuthLoginReqVO reqVO, HttpServletRequest request) {
|
||||
return success(authService.login(reqVO));
|
||||
}
|
||||
|
||||
@@ -128,28 +148,40 @@ public class AuthController {
|
||||
|
||||
@GetMapping("/get-permission-info")
|
||||
@Operation(summary = "获取登录用户的权限信息")
|
||||
public CommonResult<AuthPermissionInfoRespVO> getPermissionInfo() {
|
||||
public CommonResult<AuthPermissionInfoRespVO> getPermissionInfo(HttpServletRequest request) {
|
||||
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
|
||||
if (ObjectUtil.isNull(loginUser)) {
|
||||
throw new ServiceException(GlobalErrorCodeConstants.UNAUTHORIZED);
|
||||
}
|
||||
Long userId = loginUser.getId();
|
||||
// 1.1 获得用户信息
|
||||
AdminUserDO user = userService.getUser(getLoginUserId());
|
||||
AdminUserDO user = userService.getUser(userId);
|
||||
if (user == null) {
|
||||
return null;
|
||||
}
|
||||
// 获取机构的有效期
|
||||
OrganizationDO organizationDO = organService.validOrgan(user.getOrganId());
|
||||
IPQueryDataRespDTO ipQueryDataRespDTO = null;
|
||||
if (ipQueryService.serviceEnable()) {
|
||||
// 从ip获取地域信息
|
||||
ipQueryDataRespDTO = ipQueryService.querySource(getClientIP(request));
|
||||
}
|
||||
|
||||
// 1.2 获得角色列表
|
||||
Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(getLoginUserId());
|
||||
Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(userId);
|
||||
if (CollUtil.isEmpty(roleIds)) {
|
||||
return success(AuthConvert.INSTANCE.convert(user, Collections.emptyList(), Collections.emptyList()));
|
||||
return success(AuthConvert.INSTANCE.convert(user, organizationDO, ipQueryDataRespDTO, Collections.emptyList(), Collections.emptyList()));
|
||||
}
|
||||
List<RoleDO> roles = roleService.getRoleList1(roleIds);
|
||||
roles.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色
|
||||
|
||||
// 1.3 获得菜单列表
|
||||
Set<Long> menuIds = permissionService.getRoleMenuListByRoleId2(convertSet(roles, RoleDO::getId));
|
||||
Set<Long> menuIds = permissionService.getRoleMenuListByRoleId2(convertSet(roles, RoleDO::getId), loginUser.getOrganId());
|
||||
List<MenuDO> menuList = menuService.getMenuList1(menuIds);
|
||||
menuList.removeIf(menu -> !CommonStatusEnum.ENABLE.getStatus().equals(menu.getStatus())); // 移除禁用的菜单
|
||||
|
||||
// 2. 拼接结果返回
|
||||
return success(AuthConvert.INSTANCE.convert(user, roles, menuList));
|
||||
return success(AuthConvert.INSTANCE.convert(user, organizationDO, ipQueryDataRespDTO, roles, menuList));
|
||||
}
|
||||
|
||||
// ========== 短信登录相关 ==========
|
||||
|
||||
+10
@@ -6,6 +6,7 @@ import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -49,6 +50,15 @@ public class AuthPermissionInfoRespVO {
|
||||
|
||||
@Schema(description = "是否需要设置密码")
|
||||
private boolean needSetPwd;
|
||||
|
||||
@Schema(description = "ip地址")
|
||||
private String ip;
|
||||
|
||||
@Schema(description = "所属区域")
|
||||
private String region;
|
||||
|
||||
@Schema(description = "有效期限")
|
||||
private LocalDateTime expireTime;
|
||||
}
|
||||
|
||||
@Schema(description = "管理后台 - 登录用户的菜单信息 Response VO")
|
||||
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
### 获得地区树
|
||||
GET {{baseUrl}}/system/area/tree
|
||||
Authorization: Bearer {{token}}
|
||||
organ-id: {{adminTenentId}}
|
||||
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
package com.cf.imes.module.system.controller.admin.ip;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import com.cf.imes.framework.common.pojo.CommonResult;
|
||||
import com.cf.imes.framework.common.util.object.BeanUtils;
|
||||
import com.cf.imes.framework.ip.core.Area;
|
||||
import com.cf.imes.framework.ip.core.utils.AreaUtils;
|
||||
import com.cf.imes.framework.ip.core.utils.IPUtils;
|
||||
import com.cf.imes.module.system.controller.admin.ip.vo.AreaNodeRespVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.cf.imes.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - 地区")
|
||||
@RestController
|
||||
@RequestMapping("/system/area")
|
||||
@Validated
|
||||
public class AreaController {
|
||||
|
||||
@GetMapping("/tree")
|
||||
@Operation(summary = "获得地区树")
|
||||
public CommonResult<List<AreaNodeRespVO>> getAreaTree() {
|
||||
Area area = AreaUtils.getArea(Area.ID_CHINA);
|
||||
Assert.notNull(area, "获取不到中国");
|
||||
return success(BeanUtils.toBean(area.getChildren(), AreaNodeRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/get-by-ip")
|
||||
@Operation(summary = "获得 IP 对应的地区名")
|
||||
@Parameter(name = "ip", description = "IP", required = true)
|
||||
public CommonResult<String> getAreaByIp(@RequestParam("ip") String ip) {
|
||||
// 获得城市
|
||||
Area area = IPUtils.getArea(ip);
|
||||
if (area == null) {
|
||||
return success("未知");
|
||||
}
|
||||
// 格式化返回
|
||||
return success(AreaUtils.format(area.getId()));
|
||||
}
|
||||
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
package com.cf.imes.module.system.controller.admin.ip.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 地区节点 Response VO")
|
||||
@Data
|
||||
public class AreaNodeRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "110000")
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "北京")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 子节点
|
||||
*/
|
||||
private List<AreaNodeRespVO> children;
|
||||
|
||||
}
|
||||
+4
@@ -54,4 +54,8 @@ public class LoginLogRespVO {
|
||||
@ExcelProperty("登录时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "所属地区")
|
||||
@ExcelProperty("所属地区")
|
||||
private String region;
|
||||
|
||||
}
|
||||
|
||||
+15
@@ -40,10 +40,25 @@ public class OrganPageReqVO extends PageParam {
|
||||
/**
|
||||
* 拼音首字母
|
||||
*/
|
||||
@Schema(hidden = true)
|
||||
private String pyFirstChar;
|
||||
|
||||
/**
|
||||
* 全拼
|
||||
*/
|
||||
@Schema(hidden = true)
|
||||
private String pyAll;
|
||||
|
||||
@Schema(description = "省")
|
||||
@Size(max = 64, message = "省名称长度不能超过64个字符")
|
||||
private String province;
|
||||
|
||||
@Schema(description = "市")
|
||||
@Size(max = 64, message = "市名称长度不能超过64个字符")
|
||||
private String city;
|
||||
|
||||
@Schema(description = "区")
|
||||
@Size(max = 64, message = "区名称长度不能超过64个字符")
|
||||
private String county;
|
||||
|
||||
}
|
||||
|
||||
+24
@@ -65,4 +65,28 @@ public class OrganRespVO {
|
||||
@ExcelProperty("备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "省")
|
||||
@ExcelProperty("省")
|
||||
private String province;
|
||||
|
||||
@Schema(description = "市")
|
||||
@ExcelProperty("市")
|
||||
private String city;
|
||||
|
||||
@Schema(description = "区")
|
||||
@ExcelProperty("区")
|
||||
private String county;
|
||||
|
||||
@Schema(description = "地区编码")
|
||||
@ExcelProperty("地区编码")
|
||||
private String areaCode;
|
||||
|
||||
@Schema(description = "经度")
|
||||
@ExcelProperty("经度")
|
||||
private String longitude;
|
||||
|
||||
@Schema(description = "纬度")
|
||||
@ExcelProperty("纬度")
|
||||
private String latitude;
|
||||
|
||||
}
|
||||
|
||||
+24
@@ -80,4 +80,28 @@ public class OrganSaveReqVO {
|
||||
@Size(max = 200, message = "备注长度不能超过200个字符")
|
||||
private String remark;
|
||||
|
||||
|
||||
@Schema(description = "省")
|
||||
@Size(max = 64, message = "省名称长度不能超过64个字符")
|
||||
private String province;
|
||||
|
||||
@Schema(description = "市")
|
||||
@Size(max = 64, message = "市名称长度不能超过64个字符")
|
||||
private String city;
|
||||
|
||||
@Schema(description = "区")
|
||||
@Size(max = 64, message = "区名称长度不能超过64个字符")
|
||||
private String county;
|
||||
|
||||
@Schema(description = "地区编码")
|
||||
@Size(max = 64, message = "地区编码长度不能超过64个字符")
|
||||
private String areaCode;
|
||||
|
||||
@Schema(description = "经度")
|
||||
@Size(max = 64, message = "经度长度不能超过64个字符")
|
||||
private String longitude;
|
||||
|
||||
@Schema(description = "纬度")
|
||||
@Size(max = 64, message = "纬度长度不能超过64个字符")
|
||||
private String latitude;
|
||||
}
|
||||
|
||||
+14
-7
@@ -1,7 +1,10 @@
|
||||
package com.cf.imes.module.system.controller.admin.permission;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.cf.imes.framework.common.enums.CommonStatusEnum;
|
||||
import com.cf.imes.framework.common.exception.ServiceException;
|
||||
import com.cf.imes.framework.common.exception.enums.GlobalErrorCodeConstants;
|
||||
import com.cf.imes.framework.common.pojo.CommonResult;
|
||||
import com.cf.imes.framework.common.util.object.BeanUtils;
|
||||
import com.cf.imes.framework.security.core.LoginUser;
|
||||
@@ -30,7 +33,6 @@ import java.util.*;
|
||||
import static com.cf.imes.framework.common.pojo.CommonResult.success;
|
||||
import static com.cf.imes.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getLoginUser;
|
||||
import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
|
||||
@Tag(name = "管理后台 - 菜单")
|
||||
@RestController
|
||||
@@ -79,24 +81,29 @@ public class MenuController {
|
||||
@Operation(summary = "获取菜单列表", description = "用于【菜单管理】界面")
|
||||
//@PreAuthorize("@ss.hasPermission('system:menu:query')")
|
||||
public CommonResult<List<MenuRespVO>> getMenuList(MenuListReqVO reqVO) {
|
||||
List <MenuDO> list = null;
|
||||
List <MenuDO> list;
|
||||
LoginUser loginUser = getLoginUser();
|
||||
if (ObjectUtil.isNull(loginUser)) {
|
||||
throw new ServiceException(GlobalErrorCodeConstants.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
if(loginUser.getIsSupAdmin()) {
|
||||
list = menuService.getMenuList(reqVO);
|
||||
}else {
|
||||
AdminUserDO user = userService.getUser(getLoginUserId());
|
||||
AdminUserDO user = userService.getUser(loginUser.getId());
|
||||
if (user == null) {
|
||||
return success(new ArrayList<>());
|
||||
}
|
||||
Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(getLoginUserId());
|
||||
// 获取登录用户所属角色
|
||||
Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(loginUser.getId());
|
||||
if (CollUtil.isEmpty(roleIds)) {
|
||||
return success(new ArrayList<>());
|
||||
}
|
||||
//List<RoleDO> roles = roleService.getRoleList(roleIds);
|
||||
// 查询角色并过滤无效的
|
||||
List<RoleDO> roles = roleService.getRoleList1(roleIds);
|
||||
roles.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色
|
||||
Set<Long> menuIds = permissionService.getRoleMenuListByRoleId2(convertSet(roles, RoleDO::getId));
|
||||
//List<MenuDO> menuList = menuService.getMenuList(menuIds);
|
||||
// 查询角色拥有权限的菜单id
|
||||
Set<Long> menuIds = permissionService.getRoleMenuListByRoleId2(convertSet(roles, RoleDO::getId), loginUser.getOrganId());
|
||||
list = menuService.getMenuList1(menuIds);
|
||||
list.removeIf(menu -> !CommonStatusEnum.ENABLE.getStatus().equals(menu.getStatus())); // 移除禁用的菜单
|
||||
}
|
||||
|
||||
+4
-3
@@ -11,6 +11,7 @@ import com.cf.imes.module.system.controller.admin.permission.vo.permission.Permi
|
||||
import com.cf.imes.module.system.controller.admin.permission.vo.permission.PermissionAssignRoleMenuReqVO;
|
||||
import com.cf.imes.module.system.controller.admin.permission.vo.permission.PermissionAssignRoleUserReqVO;
|
||||
import com.cf.imes.module.system.controller.admin.permission.vo.permission.PermissionAssignUserRoleReqVO;
|
||||
import com.cf.imes.module.system.enums.ErrorCodeConstants;
|
||||
import com.cf.imes.module.system.service.permission.PermissionService;
|
||||
import com.cf.imes.module.system.service.organ.OrganService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
@@ -59,14 +60,14 @@ public class PermissionController {
|
||||
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
|
||||
boolean isOrganRole = Objects.equals(reqVO.getRoleId(), InternalRoleConstants.ORGAN_ADMIN_ROLE_ID) || Objects.equals(reqVO.getRoleId(), InternalRoleConstants.ORGAN_STAFF_ROLE_ID);
|
||||
if(!loginUser.getIsSupAdmin() && (isOrganRole)) {
|
||||
throw new ServiceException(11541, "内置角色无权修改菜单权限");
|
||||
throw new ServiceException(ErrorCodeConstants.BUILDIN_ROLE_MODIFY_PERMISSION_ERROR);
|
||||
}
|
||||
if(Objects.equals(reqVO.getRoleId(), 1L)) {
|
||||
throw new ServiceException(11541, "内置角色无权修改菜单权限");
|
||||
throw new ServiceException(ErrorCodeConstants.BUILDIN_ROLE_MODIFY_PERMISSION_ERROR);
|
||||
}
|
||||
Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(loginUser.getId());
|
||||
if (roleIds.contains(reqVO.getRoleId())) {
|
||||
throw new ServiceException(11541, "无法修改自身的角色菜单权限");
|
||||
throw new ServiceException(ErrorCodeConstants.SELF_ROLE_MODIFY_PERMISSION_ERROR);
|
||||
}
|
||||
|
||||
if (!isOrganRole) {
|
||||
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
package com.cf.imes.module.system.controller.app.ip;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import com.cf.imes.framework.common.pojo.CommonResult;
|
||||
import com.cf.imes.framework.common.util.object.BeanUtils;
|
||||
import com.cf.imes.framework.ip.core.Area;
|
||||
import com.cf.imes.framework.ip.core.utils.AreaUtils;
|
||||
import com.cf.imes.module.system.controller.app.ip.vo.AppAreaNodeRespVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.cf.imes.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "用户 App - 地区")
|
||||
@RestController
|
||||
@RequestMapping("/system/area")
|
||||
@Validated
|
||||
public class AppAreaController {
|
||||
|
||||
@GetMapping("/tree")
|
||||
@Operation(summary = "获得地区树")
|
||||
public CommonResult<List<AppAreaNodeRespVO>> getAreaTree() {
|
||||
Area area = AreaUtils.getArea(Area.ID_CHINA);
|
||||
Assert.notNull(area, "获取不到中国");
|
||||
return success(BeanUtils.toBean(area.getChildren(), AppAreaNodeRespVO.class));
|
||||
}
|
||||
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
package com.cf.imes.module.system.controller.app.ip.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "用户 App - 地区节点 Response VO")
|
||||
@Data
|
||||
public class AppAreaNodeRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "110000")
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "北京")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 子节点
|
||||
*/
|
||||
private List<AppAreaNodeRespVO> children;
|
||||
|
||||
}
|
||||
+20
-2
@@ -1,6 +1,9 @@
|
||||
package com.cf.imes.module.system.convert.auth;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.text.CharSequenceUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.cf.imes.framework.ip.core.service.dto.IPQueryDataRespDTO;
|
||||
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
|
||||
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
|
||||
import com.cf.imes.module.system.api.social.dto.SocialUserBindReqDTO;
|
||||
@@ -10,6 +13,7 @@ import com.cf.imes.module.system.controller.admin.auth.vo.AuthSmsLoginReqVO;
|
||||
import com.cf.imes.module.system.controller.admin.auth.vo.AuthSmsSendReqVO;
|
||||
import com.cf.imes.module.system.controller.admin.auth.vo.AuthSocialLoginReqVO;
|
||||
import com.cf.imes.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.organ.OrganizationDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.permission.MenuDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.permission.RoleDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO;
|
||||
@@ -31,10 +35,24 @@ public interface AuthConvert {
|
||||
|
||||
AuthLoginRespVO convert(OAuth2AccessTokenDO bean);
|
||||
|
||||
default AuthPermissionInfoRespVO convert(AdminUserDO user, List<RoleDO> roleList, List<MenuDO> menuList) {
|
||||
default AuthPermissionInfoRespVO convert(AdminUserDO user, OrganizationDO organizationDO, IPQueryDataRespDTO ipQueryDataRespDTO, List<RoleDO> roleList, List<MenuDO> menuList) {
|
||||
boolean ipQuerySuccess = ObjectUtil.isNotNull(ipQueryDataRespDTO);
|
||||
String region = null;
|
||||
if (ipQuerySuccess) {
|
||||
String prov = ipQueryDataRespDTO.getProv();
|
||||
if (CharSequenceUtil.contains(prov, "未知")) {
|
||||
region = prov;
|
||||
} else {
|
||||
region = StringUtils.join(List.of(prov, ipQueryDataRespDTO.getCity(), ipQueryDataRespDTO.getArea()), "/");
|
||||
}
|
||||
}
|
||||
|
||||
return AuthPermissionInfoRespVO.builder()
|
||||
.user(AuthPermissionInfoRespVO.UserVO.builder()
|
||||
.id(user.getId()).nickname(user.getNickname()).avatar(user.getAvatar()).organId(user.getOrganId()).needSetPwd(StringUtils.isEmpty(user.getPassword())).build())
|
||||
.id(user.getId()).nickname(user.getNickname()).avatar(user.getAvatar()).organId(user.getOrganId()).needSetPwd(StringUtils.isEmpty(user.getPassword()))
|
||||
.expireTime(organizationDO.getExpireTime()).ip(ipQuerySuccess ? ipQueryDataRespDTO.getIp() : "")
|
||||
.region(region)
|
||||
.build())
|
||||
.roles(convertSet(roleList, RoleDO::getCode))
|
||||
// 权限标识信息
|
||||
.permissions(convertSet(menuList, MenuDO::getPermission))
|
||||
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
package com.cf.imes.module.system.convert.ip;
|
||||
|
||||
import com.cf.imes.framework.ip.core.Area;
|
||||
import com.cf.imes.module.system.controller.admin.ip.vo.AreaNodeRespVO;
|
||||
import com.cf.imes.module.system.controller.app.ip.vo.AppAreaNodeRespVO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface AreaConvert {
|
||||
|
||||
AreaConvert INSTANCE = Mappers.getMapper(AreaConvert.class);
|
||||
|
||||
List<AreaNodeRespVO> convertList(List<Area> list);
|
||||
|
||||
List<AppAreaNodeRespVO> convertList3(List<Area> list);
|
||||
|
||||
}
|
||||
+4
@@ -69,4 +69,8 @@ public class LoginLogDO extends BaseDO {
|
||||
*/
|
||||
private String userAgent;
|
||||
|
||||
/**
|
||||
* 所属地区
|
||||
*/
|
||||
private String region;
|
||||
}
|
||||
|
||||
+30
@@ -112,4 +112,34 @@ public class OrganizationDO extends BaseDO {
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 省份
|
||||
*/
|
||||
private String province;
|
||||
|
||||
/**
|
||||
* 市
|
||||
*/
|
||||
private String city;
|
||||
|
||||
/**
|
||||
* 区县
|
||||
*/
|
||||
private String county;
|
||||
|
||||
/**
|
||||
* 地区代码
|
||||
*/
|
||||
private String areaCode;
|
||||
|
||||
/**
|
||||
* 经度
|
||||
*/
|
||||
private String longitude;
|
||||
|
||||
/**
|
||||
* 纬度
|
||||
*/
|
||||
private String latitude;
|
||||
}
|
||||
|
||||
+3
@@ -31,6 +31,9 @@ public interface OrganMapper extends BaseMapperX<OrganizationDO> {
|
||||
.likeIfPresent(OrganizationDO::getContactMobile, reqVO.getContactMobile())
|
||||
.eqIfPresent(OrganizationDO::getStatus, reqVO.getStatus())
|
||||
.eqIfPresent(OrganizationDO::getName, reqVO.getExactName())
|
||||
.eqIfPresent(OrganizationDO::getProvince, reqVO.getProvince())
|
||||
.eqIfPresent(OrganizationDO::getCity, reqVO.getCity())
|
||||
.eqIfPresent(OrganizationDO::getCounty, reqVO.getCounty())
|
||||
.and(CharSequenceUtil.isNotBlank(reqVO.getName()), wrapper ->{
|
||||
wrapper.or(Boolean.TRUE).like(OrganizationDO::getName, reqVO.getName());
|
||||
wrapper.or(CharSequenceUtil.isNotBlank(reqVO.getPyAll())).like(OrganizationDO::getPinyinFull, reqVO.getPyAll());
|
||||
|
||||
+7
-1
@@ -108,4 +108,10 @@ public class RedisKeyConstants {
|
||||
* 短信验证码次数上限的缓存
|
||||
*/
|
||||
public static final String SMS_CAPTCHA_VERIFICATION_LIMIT = "sms_captcha_verification_limit:%s";
|
||||
}
|
||||
|
||||
/**
|
||||
* 套餐下的权限菜单id:12h代表key的ttl为12小时
|
||||
* !!!!注意同步修改OrganRedisCacheManager中的key字符串
|
||||
*/
|
||||
public static final String TENANT_PACKAGE_MENU_IDS = "tenant_package_menu_ids#12h";
|
||||
}
|
||||
+3
@@ -3,6 +3,7 @@ package com.cf.imes.module.system.dal.redis.listener;
|
||||
import com.cf.imes.framework.mq.redis.core.pubsub.AbstractRedisSimpleMessageListener;
|
||||
import com.cf.imes.framework.security.core.service.SecurityFrameworkService;
|
||||
import com.cf.imes.module.system.dal.redis.RedisRefreshChannelTopicConstants;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.connection.Message;
|
||||
import org.springframework.data.redis.listener.ChannelTopic;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -14,6 +15,7 @@ import org.springframework.stereotype.Component;
|
||||
* @since 2024/6/13 10:32
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class SystemPermissionRefreshRedisListener extends AbstractRedisSimpleMessageListener {
|
||||
|
||||
private final SecurityFrameworkService securityFrameworkService;
|
||||
@@ -25,6 +27,7 @@ public class SystemPermissionRefreshRedisListener extends AbstractRedisSimpleMes
|
||||
|
||||
@Override
|
||||
public void onMessage(Message message, byte[] bytes) {
|
||||
log.info("[SystemPermissionRefreshRedisListener][onMessage][{}收到刷新本地权限缓存]", message);
|
||||
securityFrameworkService.invalidateAllPermissionsCache();
|
||||
}
|
||||
}
|
||||
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package com.cf.imes.module.system.framework.operatelog.core;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.cf.imes.framework.ip.core.utils.AreaUtils;
|
||||
import com.mzt.logapi.service.IParseFunction;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 地名的 {@link IParseFunction} 实现类
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class AreaParseFunction implements IParseFunction {
|
||||
|
||||
public static final String NAME = "getArea";
|
||||
|
||||
@Override
|
||||
public boolean executeBefore() {
|
||||
return true; // 先转换值后对比
|
||||
}
|
||||
|
||||
@Override
|
||||
public String functionName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apply(Object value) {
|
||||
if (StrUtil.isEmptyIfStr(value)) {
|
||||
return "";
|
||||
}
|
||||
return AreaUtils.format(Integer.parseInt(value.toString()));
|
||||
}
|
||||
|
||||
}
|
||||
+21
-9
@@ -7,9 +7,10 @@ import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil;
|
||||
import com.cf.imes.framework.common.util.monitor.TracerUtils;
|
||||
import com.cf.imes.framework.common.util.servlet.ServletUtils;
|
||||
import com.cf.imes.framework.common.util.validation.ValidationUtils;
|
||||
import com.cf.imes.framework.ip.core.service.IPQueryService;
|
||||
import com.cf.imes.framework.ip.core.service.dto.IPQueryDataRespDTO;
|
||||
import com.cf.imes.module.system.api.logger.dto.LoginLogCreateReqDTO;
|
||||
import com.cf.imes.module.system.api.sms.SmsCodeApi;
|
||||
import com.cf.imes.module.system.api.social.dto.SocialUserBindReqDTO;
|
||||
import com.cf.imes.module.system.api.social.dto.SocialUserRespDTO;
|
||||
import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginReqVO;
|
||||
import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginRespVO;
|
||||
@@ -83,6 +84,9 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
||||
@Resource
|
||||
private SmsCodeService smsCodeService;
|
||||
|
||||
@Resource
|
||||
private IPQueryService ipQueryService;
|
||||
|
||||
/**
|
||||
* 验证码的开关,默认为 true
|
||||
*/
|
||||
@@ -116,6 +120,7 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
||||
return user;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public AuthLoginRespVO login(AuthLoginReqVO reqVO) {
|
||||
// 校验验证码
|
||||
@@ -124,11 +129,6 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
||||
// 使用账号密码,进行登录
|
||||
AdminUserDO user = authenticate(reqVO);
|
||||
|
||||
// 如果 socialType 非空,说明需要绑定社交用户
|
||||
if (reqVO.getSocialType() != null) {
|
||||
socialUserService.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(),
|
||||
reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState()));
|
||||
}
|
||||
Long organId = user.getOrganId();
|
||||
OrganizationDO organ = organService.getOrgan(organId);
|
||||
String dataSourceCode = organ.getDataSourceCode();
|
||||
@@ -203,6 +203,7 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
||||
|
||||
private void createLoginLog(Long userId, String username,
|
||||
LoginLogTypeEnum logTypeEnum, LoginResultEnum loginResult) {
|
||||
String clientIP = getClientIP();
|
||||
// 插入登录日志
|
||||
LoginLogCreateReqDTO reqDTO = new LoginLogCreateReqDTO();
|
||||
reqDTO.setLogType(logTypeEnum.getType());
|
||||
@@ -211,12 +212,17 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
||||
reqDTO.setUserType(getUserType().getValue());
|
||||
reqDTO.setUsername(username);
|
||||
reqDTO.setUserAgent(ServletUtils.getUserAgent());
|
||||
reqDTO.setUserIp(ServletUtils.getClientIP());
|
||||
reqDTO.setUserIp(clientIP);
|
||||
reqDTO.setResult(loginResult.getResult());
|
||||
IPQueryDataRespDTO ipQueryDataRespDTO = ipQueryService.querySource(clientIP);
|
||||
// 设置登录时通过ip云服务查询到的地域信息
|
||||
if (ipQueryService.serviceEnable() && ObjectUtil.isNotNull(ipQueryDataRespDTO)) {
|
||||
reqDTO.setRegion(StringUtils.join(ipQueryDataRespDTO.getProv(), ipQueryDataRespDTO.getCity(), ipQueryDataRespDTO.getArea()));
|
||||
}
|
||||
loginLogService.createLoginLog(reqDTO);
|
||||
// 更新最后登录时间
|
||||
if (userId != null && Objects.equals(LoginResultEnum.SUCCESS.getResult(), loginResult.getResult())) {
|
||||
userService.updateUserLogin(userId, ServletUtils.getClientIP());
|
||||
userService.updateUserLogin(userId, clientIP);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,6 +317,7 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
||||
}
|
||||
|
||||
private void createLogoutLog(Long userId, Integer userType, Integer logType) {
|
||||
String clientIP = getClientIP();
|
||||
LoginLogCreateReqDTO reqDTO = new LoginLogCreateReqDTO();
|
||||
reqDTO.setLogType(logType);
|
||||
reqDTO.setTraceId(TracerUtils.getTraceId());
|
||||
@@ -321,8 +328,13 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
||||
} else {
|
||||
reqDTO.setUsername(memberService.getMemberUserMobile(userId));
|
||||
}
|
||||
IPQueryDataRespDTO ipQueryDataRespDTO = ipQueryService.querySource(clientIP);
|
||||
// 设置登录时通过ip云服务查询到的地域信息
|
||||
if (ipQueryService.serviceEnable() && ObjectUtil.isNotNull(ipQueryDataRespDTO)) {
|
||||
reqDTO.setRegion(StringUtils.join(ipQueryDataRespDTO.getProv(), ipQueryDataRespDTO.getCity(), ipQueryDataRespDTO.getArea()));
|
||||
}
|
||||
reqDTO.setUserAgent(ServletUtils.getUserAgent());
|
||||
reqDTO.setUserIp(ServletUtils.getClientIP());
|
||||
reqDTO.setUserIp(clientIP);
|
||||
reqDTO.setResult(LoginResultEnum.SUCCESS.getResult());
|
||||
loginLogService.createLoginLog(reqDTO);
|
||||
}
|
||||
|
||||
+1
-1
@@ -131,7 +131,7 @@ public interface OrganService {
|
||||
*
|
||||
* @param id 组织编号
|
||||
*/
|
||||
void validOrgan(Long id);
|
||||
OrganizationDO validOrgan(Long id);
|
||||
|
||||
List<OrganSimpleRespVO> getSimpleOrganList(String name);
|
||||
|
||||
|
||||
+6
-2
@@ -101,7 +101,7 @@ public class OrganServiceImpl implements OrganService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validOrgan(Long id) {
|
||||
public OrganizationDO validOrgan(Long id) {
|
||||
OrganizationDO organizationDO = getOrgan(id);
|
||||
if (organizationDO == null) {
|
||||
throw exception(ORGAN_NOT_EXISTS);
|
||||
@@ -112,6 +112,10 @@ public class OrganServiceImpl implements OrganService {
|
||||
if (DateUtils.isExpired(organizationDO.getExpireTime())) {
|
||||
throw exception(ORGAN_EXPIRE, organizationDO.getName());
|
||||
}
|
||||
if (ObjectUtil.isNull(organizationDO.getPackageId())) {
|
||||
throw exception(TENANT_PACKAGE_NOT_EXISTS);
|
||||
}
|
||||
return organizationDO;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -216,7 +220,7 @@ public class OrganServiceImpl implements OrganService {
|
||||
organMapper.updateById(updateObj);
|
||||
// 如果套餐发生变化,则修改其角色的权限
|
||||
if (ObjectUtil.notEqual(tenant.getPackageId(), updateReqVO.getPackageId())) {
|
||||
updateOrganRoleMenu(tenant.getId(), tenantPackage.getMenuIds());
|
||||
permissionService.flushCacheWhenTenantPackageChange(List.of(tenant.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
@@ -7,6 +7,7 @@ import com.cf.imes.module.system.dal.dataobject.organ.TenantPackageDO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 组织套餐 Service 接口
|
||||
@@ -72,4 +73,11 @@ public interface TenantPackageService {
|
||||
*/
|
||||
List<TenantPackageDO> getTenantPackageListByStatus(Integer status);
|
||||
|
||||
/**
|
||||
* 获取组织套餐下的权限菜单id
|
||||
*
|
||||
* @param id 组织套餐id
|
||||
* @return
|
||||
*/
|
||||
Set<Long> getTenantPackageMenuIds(Long id);
|
||||
}
|
||||
|
||||
+24
-1
@@ -5,6 +5,7 @@ import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.cf.imes.framework.common.enums.CommonStatusEnum;
|
||||
import com.cf.imes.framework.common.pojo.PageResult;
|
||||
import com.cf.imes.framework.common.util.collection.CollectionUtils;
|
||||
import com.cf.imes.framework.common.util.object.BeanUtils;
|
||||
import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
|
||||
@@ -14,6 +15,10 @@ import com.cf.imes.module.system.dal.dataobject.organ.OrganizationDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.organ.TenantPackageDO;
|
||||
import com.cf.imes.module.system.dal.mysql.organ.TenantPackageMapper;
|
||||
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
|
||||
import com.cf.imes.module.system.dal.redis.RedisKeyConstants;
|
||||
import com.cf.imes.module.system.service.permission.PermissionService;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@@ -21,6 +26,7 @@ import org.springframework.validation.annotation.Validated;
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static com.cf.imes.module.system.enums.ErrorCodeConstants.*;
|
||||
@@ -41,7 +47,11 @@ public class TenantPackageServiceImpl implements TenantPackageService {
|
||||
@Lazy // 避免循环依赖的报错
|
||||
private OrganService organService;
|
||||
|
||||
@Resource
|
||||
private PermissionService permissionService;
|
||||
|
||||
@Override
|
||||
@CacheEvict(value = RedisKeyConstants.TENANT_PACKAGE_MENU_IDS, key = "#createReqVO.id")
|
||||
public Long createTenantPackage(TenantPackageSaveReqVO createReqVO) {
|
||||
// 唯一性校验
|
||||
validateTenantPackageUnique(createReqVO);
|
||||
@@ -54,6 +64,7 @@ public class TenantPackageServiceImpl implements TenantPackageService {
|
||||
|
||||
@Override
|
||||
@DSTransactional // 多数据源,使用 @DSTransactional 保证本地事务,以及数据源的切换
|
||||
@CacheEvict(value = RedisKeyConstants.TENANT_PACKAGE_MENU_IDS, key = "#updateReqVO.id")
|
||||
public void updateTenantPackage(TenantPackageSaveReqVO updateReqVO) {
|
||||
// 唯一性校验
|
||||
validateTenantPackageUnique(updateReqVO);
|
||||
@@ -70,11 +81,12 @@ public class TenantPackageServiceImpl implements TenantPackageService {
|
||||
// 如果菜单发生变化,则修改每个组织的菜单
|
||||
if (!CollUtil.isEqualList(tenantPackage.getMenuIds(), updateReqVO.getMenuIds())) {
|
||||
List<OrganizationDO> tenants = organService.getOrganListByPackageId(tenantPackage.getId());
|
||||
tenants.forEach(tenant -> organService.updateOrganRoleMenu(tenant.getId(), updateReqVO.getMenuIds()));
|
||||
permissionService.flushCacheWhenTenantPackageChange(CollectionUtils.convertList(tenants, OrganizationDO::getId));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@CacheEvict(value = RedisKeyConstants.TENANT_PACKAGE_MENU_IDS, key = "#id")
|
||||
public void deleteTenantPackage(Long id) {
|
||||
// 校验存在
|
||||
validateTenantPackageExists(id);
|
||||
@@ -144,4 +156,15 @@ public class TenantPackageServiceImpl implements TenantPackageService {
|
||||
return tenantPackageMapper.selectListByStatus(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(value = RedisKeyConstants.TENANT_PACKAGE_MENU_IDS, key = "#id", unless = "#result == null", cacheManager = "redisCacheManager")
|
||||
public Set<Long> getTenantPackageMenuIds(Long id) {
|
||||
validateTenantPackageExists(id);
|
||||
TenantPackageDO tenantPackageDO = tenantPackageMapper.selectOne(new LambdaQueryWrapper<TenantPackageDO>().eq(TenantPackageDO::getId, id).select(TenantPackageDO::getMenuIds));
|
||||
if (ObjectUtil.isNotNull(tenantPackageDO)) {
|
||||
return tenantPackageDO.getMenuIds();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-1
@@ -154,7 +154,14 @@ public interface PermissionService {
|
||||
*/
|
||||
DeptDataPermissionRespDTO getDeptDataPermission(Long userId);
|
||||
|
||||
Set<Long> getRoleMenuListByRoleId2(Set<Long> roleIds);
|
||||
/**
|
||||
* 查询角色id列表下所拥有的权限菜单,通过组织所配的菜单做过滤
|
||||
*
|
||||
* @param roleIds 角色id列表
|
||||
* @param organId 组织id
|
||||
* @return
|
||||
*/
|
||||
Set<Long> getRoleMenuListByRoleId2(Set<Long> roleIds,Long organId);
|
||||
|
||||
void bathAssignUserRole(List<PermissionAssignUserRoleReqVO> listReqVO);
|
||||
|
||||
@@ -181,4 +188,11 @@ public interface PermissionService {
|
||||
* 判断用户是否拥有相对应的权限
|
||||
*/
|
||||
Boolean hasPermission(Long userId, String permission);
|
||||
|
||||
/**
|
||||
* 组织套餐发生改变刷新缓存
|
||||
*
|
||||
* @param organIds 组织id列表
|
||||
*/
|
||||
void flushCacheWhenTenantPackageChange(List<Long> organIds);
|
||||
}
|
||||
|
||||
+82
-18
@@ -6,6 +6,7 @@ import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import com.cf.imes.framework.common.enums.CommonStatusEnum;
|
||||
import com.cf.imes.framework.common.exception.ServiceException;
|
||||
import com.cf.imes.framework.common.exception.enums.GlobalErrorCodeConstants;
|
||||
import com.cf.imes.framework.common.util.collection.CollectionUtils;
|
||||
import com.cf.imes.framework.common.util.json.JsonUtils;
|
||||
import com.cf.imes.framework.datapermission.core.annotation.DataPermission;
|
||||
@@ -19,10 +20,12 @@ import com.cf.imes.module.system.constants.permission.InternalRoleConstants;
|
||||
import com.cf.imes.module.system.controller.admin.permission.vo.permission.PermissionAssignRoleUserReqVO;
|
||||
import com.cf.imes.module.system.controller.admin.permission.vo.permission.PermissionAssignUserRoleReqVO;
|
||||
import com.cf.imes.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.organ.OrganizationDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.permission.MenuDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.permission.RoleDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.permission.RoleMenuDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.permission.UserRoleDO;
|
||||
import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import com.cf.imes.module.system.dal.mysql.permission.RoleMenuMapper;
|
||||
import com.cf.imes.module.system.dal.mysql.permission.UserRoleMapper;
|
||||
import com.cf.imes.module.system.dal.redis.RedisKeyConstants;
|
||||
@@ -30,6 +33,8 @@ import com.cf.imes.module.system.dal.redis.RedisRefreshChannelTopicConstants;
|
||||
import com.cf.imes.module.system.enums.ErrorCodeConstants;
|
||||
import com.cf.imes.module.system.enums.permission.DataScopeEnum;
|
||||
import com.cf.imes.module.system.service.dept.DeptService;
|
||||
import com.cf.imes.module.system.service.organ.OrganService;
|
||||
import com.cf.imes.module.system.service.organ.TenantPackageService;
|
||||
import com.cf.imes.module.system.service.user.AdminUserService;
|
||||
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
|
||||
import com.cf.imes.module.system.util.organ.OrganUtils;
|
||||
@@ -40,6 +45,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.redis.core.Cursor;
|
||||
import org.springframework.data.redis.core.ScanOptions;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
@@ -56,7 +62,7 @@ import java.util.stream.Collectors;
|
||||
import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static com.cf.imes.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
import static com.cf.imes.framework.common.util.json.JsonUtils.toJsonString;
|
||||
import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getLoginUser;
|
||||
import static com.cf.imes.module.system.dal.redis.RedisKeyConstants.OAUTH2_ACCESS_TOKEN;
|
||||
import static com.cf.imes.module.system.enums.ErrorCodeConstants.ROLE_ME_ERROR;
|
||||
|
||||
@@ -86,6 +92,14 @@ public class PermissionServiceImpl implements PermissionService {
|
||||
@Resource
|
||||
private StringRedisTemplate stringRedisTemplate;
|
||||
|
||||
@Resource
|
||||
@Lazy // 延迟,避免循环依赖报错
|
||||
private TenantPackageService tenantPackageService;
|
||||
|
||||
@Resource
|
||||
@Lazy // 延迟,避免循环依赖报错
|
||||
private OrganService organService;
|
||||
|
||||
@Override
|
||||
public boolean hasAnyPermissions(Long userId, String... permissions) {
|
||||
// 如果为空,说明已经有权限
|
||||
@@ -99,9 +113,15 @@ public class PermissionServiceImpl implements PermissionService {
|
||||
return false;
|
||||
}
|
||||
|
||||
AdminUserDO user = userService.getUser(userId);
|
||||
if (ObjectUtil.isNull(user)) {
|
||||
throw new ServiceException(ErrorCodeConstants.USER_NOT_EXISTS);
|
||||
}
|
||||
OrganizationDO organizationDO = organService.validOrgan(user.getOrganId());
|
||||
|
||||
// 情况一:遍历判断每个权限,如果有一满足,说明有权限
|
||||
for (String permission : permissions) {
|
||||
if (hasAnyPermission(roles, permission)) {
|
||||
if (hasAnyPermission(roles, permission, organizationDO.getPackageId())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -117,13 +137,16 @@ public class PermissionServiceImpl implements PermissionService {
|
||||
* @param permission 权限标识
|
||||
* @return 是否拥有
|
||||
*/
|
||||
private boolean hasAnyPermission(List<RoleDO> roles, String permission) {
|
||||
private boolean hasAnyPermission(List<RoleDO> roles, String permission, Long packageId) {
|
||||
List<Long> menuIds = menuService.getMenuIdListByPermissionFromCache(permission);
|
||||
// 采用严格模式,如果权限找不到对应的 Menu 的话,也认为没有权限
|
||||
if (CollUtil.isEmpty(menuIds)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 组织套餐下的菜单
|
||||
Set<Long> tenantPackageMenuIds = tenantPackageService.getTenantPackageMenuIds(packageId);
|
||||
|
||||
// 判断是否有权限
|
||||
Set<Long> roleIds = convertSet(roles, RoleDO::getId);
|
||||
for (Long menuId : menuIds) {
|
||||
@@ -131,7 +154,8 @@ public class PermissionServiceImpl implements PermissionService {
|
||||
//Set<Long> menuRoleIds = getSelf().getMenuRoleIdListByMenuIdFromCache(menuId);
|
||||
Set<Long> menuRoleIds = getSelf().getMenuRoleIdListByMenuIdFromCache1(menuId);
|
||||
// 如果有交集,说明有权限
|
||||
if (CollUtil.containsAny(menuRoleIds, roleIds)) {
|
||||
// 角色下菜单id和组织套餐内菜单id必须同时满足
|
||||
if (CollUtil.containsAny(menuRoleIds, roleIds) && tenantPackageMenuIds.contains(menuId)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -241,7 +265,9 @@ public class PermissionServiceImpl implements PermissionService {
|
||||
} else {
|
||||
userIds = userRoleMapper.selectOrgRoleUserIds(roleId).stream().map(UserRoleDO::getUserId).toList();
|
||||
}
|
||||
scanAndCompareUserAndDelKeys(String.format(OAUTH2_ACCESS_TOKEN, "*"), userIds);
|
||||
if (CollUtil.isNotEmpty(userIds)) {
|
||||
scanAndCompareUserAndDelKeys(String.format(OAUTH2_ACCESS_TOKEN, "*"), userIds);
|
||||
}
|
||||
})
|
||||
.exceptionally(e -> {
|
||||
log.error("[assignRoleMenu][flushRoleMenuCache]失败, 异常:{}", e);
|
||||
@@ -353,7 +379,7 @@ public class PermissionServiceImpl implements PermissionService {
|
||||
|
||||
@Override
|
||||
@OrganIgnore
|
||||
public Set<Long> getRoleMenuListByRoleId2(Set<Long> roleIds) {
|
||||
public Set<Long> getRoleMenuListByRoleId2(Set<Long> roleIds, Long organId) {
|
||||
if (CollUtil.isEmpty(roleIds)) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
@@ -361,17 +387,27 @@ public class PermissionServiceImpl implements PermissionService {
|
||||
// 如果是管理员的情况下,获取全部菜单编号
|
||||
if (roleService.hasAnySuperAdmin(roleIds)) {
|
||||
return convertSet(menuService.getMenuList(), MenuDO::getId);
|
||||
}
|
||||
List<Long> buildinRoleIdList = new ArrayList<>(){{
|
||||
add(InternalRoleConstants.ORGAN_ADMIN_ROLE_ID);
|
||||
add(InternalRoleConstants.ORGAN_STAFF_ROLE_ID);
|
||||
}};
|
||||
if (CollUtil.containsAny(roleIds, buildinRoleIdList)) {
|
||||
// 内置角色不限制组织id
|
||||
return convertSet(roleMenuMapper.selectListByRoleId(roleIds), RoleMenuDO::getMenuId);
|
||||
} else {
|
||||
// 普通成员只能看组织id下的菜单
|
||||
return convertSet(roleMenuMapper.selectListByRoleIdsAndOrganId(roleIds, OrganContextHolder.getOrganId()), RoleMenuDO::getMenuId);
|
||||
List<Long> buildinRoleIdList = new ArrayList<>(){{
|
||||
add(InternalRoleConstants.ORGAN_ADMIN_ROLE_ID);
|
||||
add(InternalRoleConstants.ORGAN_STAFF_ROLE_ID);
|
||||
}};
|
||||
|
||||
Set<Long> roleMenuIds;
|
||||
if (CollUtil.containsAny(roleIds, buildinRoleIdList)) {
|
||||
// 内置角色不限制组织id
|
||||
roleMenuIds = convertSet(roleMenuMapper.selectListByRoleId(roleIds), RoleMenuDO::getMenuId);
|
||||
} else {
|
||||
// 普通成员只能看组织id下的菜单
|
||||
roleMenuIds = convertSet(roleMenuMapper.selectListByRoleIdsAndOrganId(roleIds, OrganContextHolder.getOrganId()), RoleMenuDO::getMenuId);
|
||||
}
|
||||
|
||||
// 校验、获取可用的组织
|
||||
OrganizationDO organ = organService.validOrgan(organId);
|
||||
|
||||
Set<Long> tenantPackageMenuIds = tenantPackageService.getTenantPackageMenuIds(organ.getPackageId());
|
||||
|
||||
return Sets.intersection(roleMenuIds, tenantPackageMenuIds);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -677,8 +713,12 @@ public class PermissionServiceImpl implements PermissionService {
|
||||
*/
|
||||
@Override
|
||||
public Set<String> getUserPermissions(Long userId) {
|
||||
LoginUser loginUser = getLoginUser();
|
||||
if (ObjectUtil.isNull(loginUser)) {
|
||||
throw new ServiceException(GlobalErrorCodeConstants.UNAUTHORIZED);
|
||||
}
|
||||
// 1.2 获得角色列表
|
||||
Set<Long> roleIds = getUserRoleIdListByUserId(getLoginUserId());
|
||||
Set<Long> roleIds = getUserRoleIdListByUserId(loginUser.getId());
|
||||
if (CollUtil.isEmpty(roleIds)) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
@@ -686,7 +726,7 @@ public class PermissionServiceImpl implements PermissionService {
|
||||
roles.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色
|
||||
|
||||
// 1.3 获得菜单列表
|
||||
Set<Long> menuIds = getRoleMenuListByRoleId2(convertSet(roles, RoleDO::getId));
|
||||
Set<Long> menuIds = getRoleMenuListByRoleId2(convertSet(roles, RoleDO::getId), loginUser.getOrganId());
|
||||
List<MenuDO> menuList = menuService.getMenuList1(menuIds);
|
||||
menuList.removeIf(menu -> !CommonStatusEnum.ENABLE.getStatus().equals(menu.getStatus())); // 移除禁用的菜单
|
||||
|
||||
@@ -699,4 +739,28 @@ public class PermissionServiceImpl implements PermissionService {
|
||||
return permissions.contains(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushCacheWhenTenantPackageChange(List<Long> organIds) {
|
||||
if (CollUtil.isEmpty(organIds)) {
|
||||
return;
|
||||
}
|
||||
CompletableFuture.runAsync(() -> {
|
||||
for (Long organId : organIds) {
|
||||
// 清空机构下的用户的token缓存
|
||||
List<AdminUserDO> organUsers = userService.getOrganUsers(organId);
|
||||
if (CollUtil.isNotEmpty(organUsers)) {
|
||||
List<Long> userIds = CollectionUtils.convertList(organUsers, AdminUserDO::getId);
|
||||
scanAndCompareUserAndDelKeys(String.format(OAUTH2_ACCESS_TOKEN, "*"), userIds);
|
||||
}
|
||||
}
|
||||
})
|
||||
.thenRunAsync(() -> {
|
||||
//通知刷新本地权限缓存
|
||||
stringRedisTemplate.convertAndSend(RedisRefreshChannelTopicConstants.PERMISSION_REFRESH, "");
|
||||
})
|
||||
.exceptionally(e -> {
|
||||
log.error("[PermissionService][flushCacheWhenTenantPackageChange]失败, 异常:{}", e);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -281,4 +281,12 @@ public interface AdminUserService {
|
||||
* @param reqVO 用户个人信息
|
||||
*/
|
||||
void updateUserSecurityPhone(Long id, @Valid UserMobileUpdateReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 获取机构下的用户
|
||||
*
|
||||
* @param organId
|
||||
* @return
|
||||
*/
|
||||
List<AdminUserDO> getOrganUsers(Long organId);
|
||||
}
|
||||
|
||||
+7
@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.cf.imes.framework.common.enums.CommonStatusEnum;
|
||||
import com.cf.imes.framework.common.enums.UserTypeEnum;
|
||||
@@ -784,4 +785,10 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
// 将时间设置为 0 点
|
||||
return LocalDateTime.of(firstDayOfMonth, LocalTime.MIDNIGHT);
|
||||
}
|
||||
|
||||
@Override
|
||||
@OrganIgnore
|
||||
public List<AdminUserDO> getOrganUsers(Long organId) {
|
||||
return userMapper.selectList(new LambdaQueryWrapper<AdminUserDO>().eq(AdminUserDO::getOrganId, organId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,4 +213,8 @@ chenfeng:
|
||||
encrypt:
|
||||
enable: false
|
||||
publicKey: cfimes
|
||||
ipquery:
|
||||
enable: true
|
||||
apiUrl: https://ipquery.market.alicloudapi.com/query
|
||||
appCode: hBeRhmOnCR8f/XiD8zJ3lDaBSjbBA5ZZA2OEGswEOYQOK/hXVaT8E+AUOnEBcgFiw0R+39BvQ6TOVe2k
|
||||
debug: false
|
||||
|
||||
Reference in New Issue
Block a user