mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-12 07:02:14 +08:00
Merge branch 'develop' into registry-nacos
This commit is contained in:
@@ -41,13 +41,16 @@ import com.gitee.sop.adminserver.service.RoutePermissionService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -58,7 +61,15 @@ import java.util.stream.Collectors;
|
||||
@Slf4j
|
||||
public class IsvApi {
|
||||
|
||||
public static final int SIGN_TYPE_RSA2 = 1;
|
||||
public static final byte SIGN_TYPE_RSA = 1;
|
||||
public static final byte SIGN_TYPE_MD5 = 2;
|
||||
|
||||
static Map<String, Byte> SIGN_TYPE_MAP = new HashMap<>();
|
||||
static {
|
||||
SIGN_TYPE_MAP.put("rsa", (byte) SIGN_TYPE_RSA);
|
||||
SIGN_TYPE_MAP.put("md5", (byte) SIGN_TYPE_MD5);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
IsvInfoMapper isvInfoMapper;
|
||||
|
||||
@@ -74,6 +85,9 @@ public class IsvApi {
|
||||
@Autowired
|
||||
RoutePermissionService routePermissionService;
|
||||
|
||||
@Value("${sop.sign-type}")
|
||||
private String sopSignType;
|
||||
|
||||
@Api(name = "isv.info.page")
|
||||
@ApiDocMethod(description = "isv列表", results = {
|
||||
@ApiDocField(name = "pageIndex", description = "第几页", dataType = DataType.INT, example = "1"),
|
||||
@@ -118,6 +132,7 @@ public class IsvApi {
|
||||
CopyUtil.copyProperties(isvKeys, isvDetailVO);
|
||||
}
|
||||
isvDetailVO.setAppKey(appKey);
|
||||
isvDetailVO.setSignType(getSignType());
|
||||
return isvDetailVO;
|
||||
}
|
||||
|
||||
@@ -168,12 +183,17 @@ public class IsvApi {
|
||||
IsvKeysGenVO isvKeysGenVO = this.createIsvKeys();
|
||||
IsvKeys isvKeys = new IsvKeys();
|
||||
isvKeys.setAppKey(appKey);
|
||||
isvKeys.setSignType(getSignType());
|
||||
CopyUtil.copyPropertiesIgnoreNull(isvKeysGenVO, isvKeys);
|
||||
isvKeysMapper.saveIgnoreNull(isvKeys);
|
||||
|
||||
this.sendChannelMsg(rec.getAppKey());
|
||||
}
|
||||
|
||||
private byte getSignType() {
|
||||
return SIGN_TYPE_MAP.getOrDefault(sopSignType, SIGN_TYPE_RSA);
|
||||
}
|
||||
|
||||
@Api(name = "isv.info.update")
|
||||
@ApiDocMethod(description = "修改isv")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@@ -194,6 +214,7 @@ public class IsvApi {
|
||||
if (isvKeys == null) {
|
||||
isvKeys = new IsvKeys();
|
||||
CopyUtil.copyPropertiesIgnoreNull(param, isvKeys);
|
||||
isvKeys.setSignType(getSignType());
|
||||
isvKeysMapper.saveIgnoreNull(isvKeys);
|
||||
} else {
|
||||
CopyUtil.copyPropertiesIgnoreNull(param, isvKeys);
|
||||
@@ -279,7 +300,7 @@ public class IsvApi {
|
||||
routePermissionService.sendIsvRolePermissionToZookeeper(isvInfo.getAppKey(), roleCodeList);
|
||||
} catch (Exception e) {
|
||||
log.error("保存到zookeeper中失败,isvInfo:{}, roleCodeList:{}", isvInfo, roleCodeList);
|
||||
throw new BizException("保存失败,请查看日志");
|
||||
throw new BizException("同步zookeeper失败,请查看网关日志");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -7,7 +7,6 @@ import org.hibernate.validator.constraints.Length;
|
||||
import javax.validation.constraints.Max;
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
@@ -45,8 +44,4 @@ public class IsvKeysFormUpdate {
|
||||
/** 平台生成的私钥, 数据库字段:private_key_platform */
|
||||
@ApiDocField(description = "平台生成的私钥")
|
||||
private String privateKeyPlatform;
|
||||
|
||||
@ApiDocField(description = "签名类型:1:RSA2,2:MD5")
|
||||
@NotNull(message = "signType不能为空")
|
||||
private Byte signType;
|
||||
}
|
||||
|
@@ -6,7 +6,6 @@ import com.gitee.easyopen.annotation.ApiService;
|
||||
import com.gitee.easyopen.doc.annotation.ApiDoc;
|
||||
import com.gitee.easyopen.doc.annotation.ApiDocMethod;
|
||||
import com.gitee.easyopen.util.CopyUtil;
|
||||
import com.gitee.fastmybatis.core.query.Query;
|
||||
import com.gitee.sop.adminserver.api.isv.result.RoleVO;
|
||||
import com.gitee.sop.adminserver.api.service.param.RouteAddParam;
|
||||
import com.gitee.sop.adminserver.api.service.param.RouteDeleteParam;
|
||||
@@ -22,7 +21,6 @@ import com.gitee.sop.adminserver.common.ZookeeperPathExistException;
|
||||
import com.gitee.sop.adminserver.common.ZookeeperPathNotExistException;
|
||||
import com.gitee.sop.adminserver.entity.ConfigRouteBase;
|
||||
import com.gitee.sop.adminserver.entity.PermRole;
|
||||
import com.gitee.sop.adminserver.entity.PermRolePermission;
|
||||
import com.gitee.sop.adminserver.mapper.ConfigRouteBaseMapper;
|
||||
import com.gitee.sop.adminserver.mapper.PermRoleMapper;
|
||||
import com.gitee.sop.adminserver.mapper.PermRolePermissionMapper;
|
||||
@@ -30,14 +28,11 @@ import com.gitee.sop.adminserver.service.RouteConfigService;
|
||||
import com.gitee.sop.adminserver.service.RoutePermissionService;
|
||||
import com.gitee.sop.adminserver.service.RouteService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang.BooleanUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -188,6 +183,11 @@ public class RouteApi {
|
||||
return this.getRouteRole(param.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取路由对应的角色
|
||||
* @param id routeId
|
||||
* @return
|
||||
*/
|
||||
private List<RoleVO> getRouteRole(String id) {
|
||||
return permRolePermissionMapper.listByColumn("route_id", id)
|
||||
.stream()
|
||||
@@ -203,33 +203,28 @@ public class RouteApi {
|
||||
|
||||
@Api(name = "route.role.update")
|
||||
@ApiDocMethod(description = "更新路由对应的角色")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateRouteRole(RoutePermissionParam param) {
|
||||
String routeId = param.getRouteId();
|
||||
// 删除所有数据
|
||||
Query delQuery = new Query();
|
||||
delQuery.eq("route_id", routeId);
|
||||
permRolePermissionMapper.deleteByQuery(delQuery);
|
||||
|
||||
List<String> roleCodes = param.getRoleCode();
|
||||
if (CollectionUtils.isNotEmpty(roleCodes)) {
|
||||
List<PermRolePermission> tobeSave = new ArrayList<>(roleCodes.size());
|
||||
for (String roleCode : roleCodes) {
|
||||
PermRolePermission permRolePermission = new PermRolePermission();
|
||||
permRolePermission.setRoleCode(roleCode);
|
||||
permRolePermission.setRouteId(routeId);
|
||||
tobeSave.add(permRolePermission);
|
||||
}
|
||||
// 批量添加
|
||||
permRolePermissionMapper.saveBatch(tobeSave);
|
||||
}
|
||||
|
||||
RoutePermissionParam oldRoutePermission = this.buildOldRoutePermission(param.getRouteId());
|
||||
routePermissionService.updateRoutePermission(param);
|
||||
try {
|
||||
routePermissionService.sendRoutePermissionReloadMsg();
|
||||
routePermissionService.sendRoutePermissionReloadMsg(oldRoutePermission);
|
||||
} catch (Exception e) {
|
||||
log.info("消息推送--路由权限(reload)失败", e);
|
||||
throw new BizException("修改失败,请查看日志");
|
||||
log.error("消息推送--路由权限(reload)失败", e);
|
||||
// 回滚
|
||||
routePermissionService.updateRoutePermission(oldRoutePermission);
|
||||
throw new BizException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private RoutePermissionParam buildOldRoutePermission(String routeId) {
|
||||
List<RoleVO> routeRole = this.getRouteRole(routeId);
|
||||
List<String> roleCodeList = routeRole.stream()
|
||||
.map(RoleVO::getRoleCode)
|
||||
.collect(Collectors.toList());
|
||||
RoutePermissionParam routePermissionParam = new RoutePermissionParam();
|
||||
routePermissionParam.setRouteId(routeId);
|
||||
routePermissionParam.setRoleCode(roleCodeList);
|
||||
return routePermissionParam;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -13,4 +13,5 @@ public class IsvRoutePermission {
|
||||
private String appKey;
|
||||
private List<String> routeIdList;
|
||||
private String routeIdListMd5;
|
||||
private String listenPath;
|
||||
}
|
||||
|
@@ -14,4 +14,6 @@ public class SopAdminConstants {
|
||||
*/
|
||||
public static final String SOP_MSG_CHANNEL_PATH = "/com.gitee.sop.channel";
|
||||
|
||||
public static final String RELOAD_ROUTE_PERMISSION_PATH = "/com.gitee.sop.route.permission.reload";
|
||||
|
||||
}
|
||||
|
@@ -4,54 +4,67 @@ import com.gitee.sop.adminserver.common.ZookeeperOperationException;
|
||||
import com.gitee.sop.adminserver.common.ZookeeperPathExistException;
|
||||
import com.gitee.sop.adminserver.common.ZookeeperPathNotExistException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang.math.NumberUtils;
|
||||
import org.apache.curator.framework.CuratorFramework;
|
||||
import org.apache.curator.framework.CuratorFrameworkFactory;
|
||||
import org.apache.curator.framework.recipes.cache.ChildData;
|
||||
import org.apache.curator.framework.recipes.cache.NodeCache;
|
||||
import org.apache.curator.framework.recipes.cache.NodeCacheListener;
|
||||
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
|
||||
import org.apache.curator.retry.ExponentialBackoffRetry;
|
||||
import org.apache.zookeeper.CreateMode;
|
||||
import org.apache.zookeeper.data.Stat;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.io.Closeable;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static com.gitee.sop.adminserver.bean.SopAdminConstants.SOP_MSG_CHANNEL_PATH;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Configuration
|
||||
@Slf4j
|
||||
public class ZookeeperContext {
|
||||
|
||||
private static CuratorFramework client;
|
||||
|
||||
@Value("${spring.cloud.zookeeper.connect-string}")
|
||||
private String zookeeperServerAddr;
|
||||
private static Environment environment;
|
||||
|
||||
@Value("${spring.cloud.zookeeper.baseSleepTimeMs}")
|
||||
private String baseSleepTimeMs;
|
||||
|
||||
@Value("${spring.cloud.zookeeper.maxRetries}")
|
||||
private String maxRetries;
|
||||
|
||||
@PostConstruct
|
||||
protected void after() {
|
||||
if (StringUtils.isBlank(zookeeperServerAddr)) {
|
||||
throw new IllegalArgumentException("未指定spring.cloud.zookeeper.connect-string参数");
|
||||
public static void setEnvironment(Environment environment) {
|
||||
Assert.notNull(environment, "environment不能为null");
|
||||
ZookeeperContext.environment = environment;
|
||||
initZookeeperClient();
|
||||
}
|
||||
|
||||
public synchronized static void initZookeeperClient() {
|
||||
if (client != null) {
|
||||
return;
|
||||
}
|
||||
setClient(createClient());
|
||||
}
|
||||
|
||||
public static CuratorFramework createClient() {
|
||||
String zookeeperServerAddr = environment.getProperty("spring.cloud.zookeeper.connect-string");
|
||||
if (StringUtils.isBlank(zookeeperServerAddr)) {
|
||||
throw new RuntimeException("未指定spring.cloud.zookeeper.connect-string参数");
|
||||
}
|
||||
String baseSleepTimeMs = environment.getProperty("spring.cloud.zookeeper.baseSleepTimeMs");
|
||||
String maxRetries = environment.getProperty("spring.cloud.zookeeper.maxRetries");
|
||||
log.info("初始化zookeeper客户端,zookeeperServerAddr:{}, baseSleepTimeMs:{}, maxRetries:{}",
|
||||
zookeeperServerAddr, baseSleepTimeMs, maxRetries);
|
||||
CuratorFramework client = CuratorFrameworkFactory.builder()
|
||||
.connectString(zookeeperServerAddr)
|
||||
.retryPolicy(new ExponentialBackoffRetry(NumberUtils.toInt(baseSleepTimeMs, 3000), NumberUtils.toInt(maxRetries, 3)))
|
||||
.build();
|
||||
|
||||
client.start();
|
||||
|
||||
setClient(client);
|
||||
return client;
|
||||
}
|
||||
|
||||
public static String getSopRouteRootPath() {
|
||||
@@ -129,6 +142,7 @@ public class ZookeeperContext {
|
||||
|
||||
/**
|
||||
* 创建新的path,并赋值。如果path已存在抛异常
|
||||
*
|
||||
* @param path 待创建的path
|
||||
* @param data 值
|
||||
* @throws ZookeeperPathExistException
|
||||
@@ -137,10 +151,27 @@ public class ZookeeperContext {
|
||||
if (isPathExist(path)) {
|
||||
throw new ZookeeperPathExistException("path " + path + " 已存在");
|
||||
}
|
||||
try {
|
||||
return addPath(path, CreateMode.PERSISTENT, data);
|
||||
} catch (Exception e) {
|
||||
throw new ZookeeperOperationException("addPath error path=" + path, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加节点
|
||||
*
|
||||
* @param path 待创建的path
|
||||
* @param createMode 节点类型
|
||||
* @param data 节点数据
|
||||
* @return
|
||||
*/
|
||||
public static String addPath(String path, CreateMode createMode, String data) {
|
||||
try {
|
||||
return getClient().create()
|
||||
// 如果指定节点的父节点不存在,则Curator将会自动级联创建父节点
|
||||
.creatingParentContainersIfNeeded()
|
||||
.withMode(createMode)
|
||||
.forPath(path, data.getBytes());
|
||||
} catch (Exception e) {
|
||||
throw new ZookeeperOperationException("addPath error path=" + path, e);
|
||||
@@ -149,6 +180,7 @@ public class ZookeeperContext {
|
||||
|
||||
/**
|
||||
* 删除节点及子节点
|
||||
*
|
||||
* @param path
|
||||
*/
|
||||
public static void deletePathDeep(String path) {
|
||||
@@ -157,12 +189,13 @@ public class ZookeeperContext {
|
||||
.deletingChildrenIfNeeded()
|
||||
.forPath(path);
|
||||
} catch (Exception e) {
|
||||
throw new ZookeeperOperationException("deletePathDeep error path=" + path, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建新的path,并赋值。如果path已存在则不创建
|
||||
*
|
||||
* @param path 待创建的path
|
||||
* @param data 值
|
||||
*/
|
||||
@@ -171,10 +204,7 @@ public class ZookeeperContext {
|
||||
return path;
|
||||
}
|
||||
try {
|
||||
return getClient().create()
|
||||
// 如果指定节点的父节点不存在,则Curator将会自动级联创建父节点
|
||||
.creatingParentContainersIfNeeded()
|
||||
.forPath(path, data.getBytes());
|
||||
return addPath(path, data);
|
||||
} catch (Exception e) {
|
||||
throw new ZookeeperOperationException("addPathQuietly error path=" + path, e);
|
||||
}
|
||||
@@ -182,6 +212,7 @@ public class ZookeeperContext {
|
||||
|
||||
/**
|
||||
* 新建或保存节点
|
||||
*
|
||||
* @param path
|
||||
* @param data
|
||||
* @return
|
||||
@@ -201,6 +232,7 @@ public class ZookeeperContext {
|
||||
|
||||
/**
|
||||
* 获取节点内容
|
||||
*
|
||||
* @param path
|
||||
* @return
|
||||
* @throws ZookeeperPathNotExistException
|
||||
@@ -247,4 +279,54 @@ public class ZookeeperContext {
|
||||
return childrenCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听一个节点
|
||||
*
|
||||
* @param path
|
||||
* @param onChange 节点修改后触发
|
||||
* @return 返回path
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void listenTempPath(String path, Consumer<String> onChange) throws Exception {
|
||||
String initData = "{}";
|
||||
CuratorFramework client = createClient();
|
||||
client.create()
|
||||
// 如果指定节点的父节点不存在,则Curator将会自动级联创建父节点
|
||||
.creatingParentContainersIfNeeded()
|
||||
.withMode(CreateMode.EPHEMERAL)
|
||||
.forPath(path, initData.getBytes());
|
||||
|
||||
final NodeCache cache = new NodeCache(client, path, false);
|
||||
cache.getListenable().addListener(new NodeCacheListener() {
|
||||
@Override
|
||||
public void nodeChanged() throws Exception {
|
||||
byte[] nodeData = cache.getCurrentData().getData();
|
||||
String data = new String(nodeData);
|
||||
if (!initData.equals(data)) {
|
||||
onChange.accept(data);
|
||||
new Thread(new ZKClose(cache, client)).start();
|
||||
}
|
||||
}
|
||||
});
|
||||
cache.start();
|
||||
}
|
||||
|
||||
static class ZKClose implements Runnable {
|
||||
Closeable[] closes;
|
||||
|
||||
public ZKClose(Closeable ...closes) {
|
||||
this.closes = closes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
IOUtils.closeQuietly(closes);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -8,13 +8,17 @@ import com.gitee.easyopen.ApiParamParser;
|
||||
import com.gitee.easyopen.ParamNames;
|
||||
import com.gitee.easyopen.interceptor.ApiInterceptor;
|
||||
import com.gitee.easyopen.session.ApiSessionManager;
|
||||
import com.gitee.sop.adminserver.bean.ZookeeperContext;
|
||||
import com.gitee.sop.adminserver.interceptor.LoginInterceptor;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang.math.NumberUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
|
||||
@@ -29,6 +33,9 @@ public class WebConfig {
|
||||
@Value("${admin.access-token.timeout-minutes}")
|
||||
private String accessTokenTimeout;
|
||||
|
||||
@Autowired
|
||||
private Environment environment;
|
||||
|
||||
@Bean
|
||||
ApiConfig apiConfig() {
|
||||
ApiConfig apiConfig = new ApiConfig();
|
||||
@@ -59,4 +66,9 @@ public class WebConfig {
|
||||
return apiConfig;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void after() {
|
||||
ZookeeperContext.setEnvironment(environment);
|
||||
}
|
||||
|
||||
}
|
@@ -2,8 +2,10 @@ package com.gitee.sop.adminserver.service;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.gitee.fastmybatis.core.query.Query;
|
||||
import com.gitee.sop.adminserver.api.service.param.RoutePermissionParam;
|
||||
import com.gitee.sop.adminserver.bean.ChannelMsg;
|
||||
import com.gitee.sop.adminserver.bean.IsvRoutePermission;
|
||||
import com.gitee.sop.adminserver.bean.SopAdminConstants;
|
||||
import com.gitee.sop.adminserver.bean.ZookeeperContext;
|
||||
import com.gitee.sop.adminserver.entity.PermIsvRole;
|
||||
import com.gitee.sop.adminserver.entity.PermRolePermission;
|
||||
@@ -16,6 +18,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -93,12 +96,48 @@ public class RoutePermissionService {
|
||||
/**
|
||||
* 推送所有路由权限到zookeeper
|
||||
*/
|
||||
public void sendRoutePermissionReloadMsg() throws Exception {
|
||||
ChannelMsg channelMsg = new ChannelMsg("reload", null);
|
||||
public synchronized void sendRoutePermissionReloadMsg(RoutePermissionParam oldRoutePermission) throws Exception {
|
||||
String listenPath = SopAdminConstants.RELOAD_ROUTE_PERMISSION_PATH + "/" + System.currentTimeMillis();
|
||||
ZookeeperContext.listenTempPath(listenPath, code -> {
|
||||
// 0成功
|
||||
if (!"0".equals(code)) {
|
||||
log.error("推送所有路由权限到zookeeper失败,进行回滚,msg: {},oldRoutePermission:{}", code, JSON.toJSONString(oldRoutePermission));
|
||||
// 回滚
|
||||
this.updateRoutePermission(oldRoutePermission);
|
||||
}
|
||||
});
|
||||
IsvRoutePermission isvRoutePermission = new IsvRoutePermission();
|
||||
isvRoutePermission.setListenPath(listenPath);
|
||||
ChannelMsg channelMsg = new ChannelMsg("reload", isvRoutePermission);
|
||||
String jsonData = JSON.toJSONString(channelMsg);
|
||||
String path = ZookeeperContext.getIsvRoutePermissionChannelPath();
|
||||
log.info("消息推送--路由权限(reload), path:{}, data:{}", path, jsonData);
|
||||
ZookeeperContext.createOrUpdateData(path, jsonData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新路由权限
|
||||
*
|
||||
* @param param
|
||||
*/
|
||||
public synchronized void updateRoutePermission(RoutePermissionParam param) {
|
||||
String routeId = param.getRouteId();
|
||||
// 删除所有数据
|
||||
Query delQuery = new Query();
|
||||
delQuery.eq("route_id", routeId);
|
||||
permRolePermissionMapper.deleteByQuery(delQuery);
|
||||
|
||||
List<String> roleCodes = param.getRoleCode();
|
||||
if (org.apache.commons.collections.CollectionUtils.isNotEmpty(roleCodes)) {
|
||||
List<PermRolePermission> tobeSave = new ArrayList<>(roleCodes.size());
|
||||
for (String roleCode : roleCodes) {
|
||||
PermRolePermission permRolePermission = new PermRolePermission();
|
||||
permRolePermission.setRoleCode(roleCode);
|
||||
permRolePermission.setRouteId(routeId);
|
||||
tobeSave.add(permRolePermission);
|
||||
}
|
||||
// 批量添加
|
||||
permRolePermissionMapper.saveBatch(tobeSave);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -6,6 +6,10 @@ admin:
|
||||
access-token:
|
||||
timeout-minutes: 30
|
||||
|
||||
sop:
|
||||
# 签名方式,rsa:支付宝开放平台签名方式,md5:淘宝开放平台签名方式
|
||||
sign-type: rsa
|
||||
|
||||
# 不用改
|
||||
spring:
|
||||
application:
|
||||
|
@@ -1 +1 @@
|
||||
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><link rel=icon href=favicon.ico><title>SOP Admin</title><link href=static/css/chunk-elementUI.81cf475c.css rel=stylesheet><link href=static/css/chunk-libs.3dfb7769.css rel=stylesheet><link href=static/css/app.4f0872ef.css rel=stylesheet></head><body><noscript><strong>We're sorry but SOP Admin doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script>(function(e){function t(t){for(var r,c,o=t[0],i=t[1],f=t[2],l=0,d=[];l<o.length;l++)c=o[l],u[c]&&d.push(u[c][0]),u[c]=0;for(r in i)Object.prototype.hasOwnProperty.call(i,r)&&(e[r]=i[r]);h&&h(t);while(d.length)d.shift()();return a.push.apply(a,f||[]),n()}function n(){for(var e,t=0;t<a.length;t++){for(var n=a[t],r=!0,c=1;c<n.length;c++){var o=n[c];0!==u[o]&&(r=!1)}r&&(a.splice(t--,1),e=i(i.s=n[0]))}return e}var r={},c={runtime:0},u={runtime:0},a=[];function o(e){return i.p+"static/js/"+({}[e]||e)+"."+{"chunk-009073d4":"28312808","chunk-238a81e9":"5955f13d","chunk-25908fca":"e7e4b6d5","chunk-29e7142c":"994a3ac0","chunk-2d2085ef":"a63a74dc","chunk-2d22c2e3":"4a098244","chunk-37401378":"4e39ec9b","chunk-4a59cbe4":"a6360c68","chunk-6a68a33e":"15951b55","chunk-73b2dcec":"094bb2fa"}[e]+".js"}function i(t){if(r[t])return r[t].exports;var n=r[t]={i:t,l:!1,exports:{}};return e[t].call(n.exports,n,n.exports,i),n.l=!0,n.exports}i.e=function(e){var t=[],n={"chunk-009073d4":1,"chunk-238a81e9":1,"chunk-25908fca":1,"chunk-29e7142c":1,"chunk-37401378":1,"chunk-6a68a33e":1,"chunk-73b2dcec":1};c[e]?t.push(c[e]):0!==c[e]&&n[e]&&t.push(c[e]=new Promise(function(t,n){for(var r="static/css/"+({}[e]||e)+"."+{"chunk-009073d4":"0af16c7e","chunk-238a81e9":"e8e2beee","chunk-25908fca":"89ab33e8","chunk-29e7142c":"d10599db","chunk-2d2085ef":"31d6cfe0","chunk-2d22c2e3":"31d6cfe0","chunk-37401378":"a43114f3","chunk-4a59cbe4":"31d6cfe0","chunk-6a68a33e":"3b12267b","chunk-73b2dcec":"99cf6327"}[e]+".css",u=i.p+r,a=document.getElementsByTagName("link"),o=0;o<a.length;o++){var f=a[o],l=f.getAttribute("data-href")||f.getAttribute("href");if("stylesheet"===f.rel&&(l===r||l===u))return t()}var d=document.getElementsByTagName("style");for(o=0;o<d.length;o++){f=d[o],l=f.getAttribute("data-href");if(l===r||l===u)return t()}var h=document.createElement("link");h.rel="stylesheet",h.type="text/css",h.onload=t,h.onerror=function(t){var r=t&&t.target&&t.target.src||u,a=new Error("Loading CSS chunk "+e+" failed.\n("+r+")");a.code="CSS_CHUNK_LOAD_FAILED",a.request=r,delete c[e],h.parentNode.removeChild(h),n(a)},h.href=u;var s=document.getElementsByTagName("head")[0];s.appendChild(h)}).then(function(){c[e]=0}));var r=u[e];if(0!==r)if(r)t.push(r[2]);else{var a=new Promise(function(t,n){r=u[e]=[t,n]});t.push(r[2]=a);var f,l=document.createElement("script");l.charset="utf-8",l.timeout=120,i.nc&&l.setAttribute("nonce",i.nc),l.src=o(e),f=function(t){l.onerror=l.onload=null,clearTimeout(d);var n=u[e];if(0!==n){if(n){var r=t&&("load"===t.type?"missing":t.type),c=t&&t.target&&t.target.src,a=new Error("Loading chunk "+e+" failed.\n("+r+": "+c+")");a.type=r,a.request=c,n[1](a)}u[e]=void 0}};var d=setTimeout(function(){f({type:"timeout",target:l})},12e4);l.onerror=l.onload=f,document.head.appendChild(l)}return Promise.all(t)},i.m=e,i.c=r,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)i.d(n,r,function(t){return e[t]}.bind(null,r));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i.oe=function(e){throw console.error(e),e};var f=window["webpackJsonp"]=window["webpackJsonp"]||[],l=f.push.bind(f);f.push=t,f=f.slice();for(var d=0;d<f.length;d++)t(f[d]);var h=l;n()})([]);</script><script src=static/js/chunk-elementUI.8ebdfbab.js></script><script src=static/js/chunk-libs.9cf9cc40.js></script><script src=static/js/app.095e8b9c.js></script></body></html>
|
||||
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><link rel=icon href=favicon.ico><title>SOP Admin</title><link href=static/css/chunk-elementUI.81cf475c.css rel=stylesheet><link href=static/css/chunk-libs.3dfb7769.css rel=stylesheet><link href=static/css/app.4f0872ef.css rel=stylesheet></head><body><noscript><strong>We're sorry but SOP Admin doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script>(function(e){function t(t){for(var r,c,a=t[0],i=t[1],f=t[2],l=0,d=[];l<a.length;l++)c=a[l],u[c]&&d.push(u[c][0]),u[c]=0;for(r in i)Object.prototype.hasOwnProperty.call(i,r)&&(e[r]=i[r]);h&&h(t);while(d.length)d.shift()();return o.push.apply(o,f||[]),n()}function n(){for(var e,t=0;t<o.length;t++){for(var n=o[t],r=!0,c=1;c<n.length;c++){var a=n[c];0!==u[a]&&(r=!1)}r&&(o.splice(t--,1),e=i(i.s=n[0]))}return e}var r={},c={runtime:0},u={runtime:0},o=[];function a(e){return i.p+"static/js/"+({}[e]||e)+"."+{"chunk-009073d4":"28312808","chunk-238a81e9":"5955f13d","chunk-25908fca":"9d8bc0b6","chunk-29e7142c":"994a3ac0","chunk-2d2085ef":"a63a74dc","chunk-2d22c2e3":"4a098244","chunk-37401378":"4e39ec9b","chunk-4a59cbe4":"a6360c68","chunk-6a68a33e":"b6685cb9","chunk-73b2dcec":"14f248eb"}[e]+".js"}function i(t){if(r[t])return r[t].exports;var n=r[t]={i:t,l:!1,exports:{}};return e[t].call(n.exports,n,n.exports,i),n.l=!0,n.exports}i.e=function(e){var t=[],n={"chunk-009073d4":1,"chunk-238a81e9":1,"chunk-25908fca":1,"chunk-29e7142c":1,"chunk-37401378":1,"chunk-6a68a33e":1,"chunk-73b2dcec":1};c[e]?t.push(c[e]):0!==c[e]&&n[e]&&t.push(c[e]=new Promise(function(t,n){for(var r="static/css/"+({}[e]||e)+"."+{"chunk-009073d4":"0af16c7e","chunk-238a81e9":"e8e2beee","chunk-25908fca":"89ab33e8","chunk-29e7142c":"d10599db","chunk-2d2085ef":"31d6cfe0","chunk-2d22c2e3":"31d6cfe0","chunk-37401378":"a43114f3","chunk-4a59cbe4":"31d6cfe0","chunk-6a68a33e":"3b12267b","chunk-73b2dcec":"99cf6327"}[e]+".css",u=i.p+r,o=document.getElementsByTagName("link"),a=0;a<o.length;a++){var f=o[a],l=f.getAttribute("data-href")||f.getAttribute("href");if("stylesheet"===f.rel&&(l===r||l===u))return t()}var d=document.getElementsByTagName("style");for(a=0;a<d.length;a++){f=d[a],l=f.getAttribute("data-href");if(l===r||l===u)return t()}var h=document.createElement("link");h.rel="stylesheet",h.type="text/css",h.onload=t,h.onerror=function(t){var r=t&&t.target&&t.target.src||u,o=new Error("Loading CSS chunk "+e+" failed.\n("+r+")");o.code="CSS_CHUNK_LOAD_FAILED",o.request=r,delete c[e],h.parentNode.removeChild(h),n(o)},h.href=u;var s=document.getElementsByTagName("head")[0];s.appendChild(h)}).then(function(){c[e]=0}));var r=u[e];if(0!==r)if(r)t.push(r[2]);else{var o=new Promise(function(t,n){r=u[e]=[t,n]});t.push(r[2]=o);var f,l=document.createElement("script");l.charset="utf-8",l.timeout=120,i.nc&&l.setAttribute("nonce",i.nc),l.src=a(e),f=function(t){l.onerror=l.onload=null,clearTimeout(d);var n=u[e];if(0!==n){if(n){var r=t&&("load"===t.type?"missing":t.type),c=t&&t.target&&t.target.src,o=new Error("Loading chunk "+e+" failed.\n("+r+": "+c+")");o.type=r,o.request=c,n[1](o)}u[e]=void 0}};var d=setTimeout(function(){f({type:"timeout",target:l})},12e4);l.onerror=l.onload=f,document.head.appendChild(l)}return Promise.all(t)},i.m=e,i.c=r,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)i.d(n,r,function(t){return e[t]}.bind(null,r));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i.oe=function(e){throw console.error(e),e};var f=window["webpackJsonp"]=window["webpackJsonp"]||[],l=f.push.bind(f);f.push=t,f=f.slice();for(var d=0;d<f.length;d++)t(f[d]);var h=l;n()})([]);</script><script src=static/js/chunk-elementUI.8ebdfbab.js></script><script src=static/js/chunk-libs.9cf9cc40.js></script><script src=static/js/app.095e8b9c.js></script></body></html>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,45 @@
|
||||
package com.gitee.sop.adminserver;
|
||||
|
||||
import com.gitee.sop.adminserver.bean.SopAdminConstants;
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.curator.framework.CuratorFramework;
|
||||
import org.apache.curator.framework.CuratorFrameworkFactory;
|
||||
import org.apache.curator.retry.ExponentialBackoffRetry;
|
||||
import org.apache.zookeeper.data.Stat;
|
||||
|
||||
public class CuratorTest extends TestCase {
|
||||
|
||||
private static String zookeeperServerAddr = "localhost:2181";
|
||||
|
||||
static CuratorFramework client;
|
||||
|
||||
public CuratorTest() {
|
||||
client = CuratorFrameworkFactory.builder()
|
||||
.connectString(zookeeperServerAddr)
|
||||
.retryPolicy(new ExponentialBackoffRetry(1000, 3))
|
||||
.build();
|
||||
|
||||
client.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归删除节点,只能在测试环境用。
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testDel() {
|
||||
try {
|
||||
client.delete()
|
||||
.deletingChildrenIfNeeded()
|
||||
.forPath(SopAdminConstants.RELOAD_ROUTE_PERMISSION_PATH);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testCheck() throws Exception {
|
||||
String path = SopAdminConstants.RELOAD_ROUTE_PERMISSION_PATH + "/1562231019332";
|
||||
Stat stat = client.checkExists().forPath(path);
|
||||
System.out.println(path + (stat == null ? "不存在" : "存在"));
|
||||
}
|
||||
|
||||
}
|
@@ -141,10 +141,6 @@
|
||||
<el-form-item :label="selfLabel('appKey')">
|
||||
<span>{{ isvKeysFormData.appKey }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="签名方式">
|
||||
<span v-if="isvKeysFormData.signType === 1">RSA</span>
|
||||
<span v-if="isvKeysFormData.signType === 2">MD5</span>
|
||||
</el-form-item>
|
||||
<el-form-item v-show="showKeys()" label="秘钥格式">
|
||||
<span v-if="isvKeysFormData.keyFormat === 1">PKCS8(JAVA适用)</span>
|
||||
<span v-if="isvKeysFormData.keyFormat === 2">PKCS1(非JAVA适用)</span>
|
||||
|
@@ -19,12 +19,6 @@
|
||||
<el-form-item :label="selfLabel('appKey')">
|
||||
<div>{{ isvKeysFormData.appKey }}</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="签名方式">
|
||||
<el-radio-group v-model="isvKeysFormData.signType">
|
||||
<el-radio :label="1" name="status">RSA</el-radio>
|
||||
<el-radio :label="2" name="status">MD5</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-show="showKeys()" label="秘钥格式">
|
||||
<el-radio-group v-model="isvKeysFormData.keyFormat">
|
||||
<el-radio :label="1" name="keyFormat">PKCS8(JAVA适用)</el-radio>
|
||||
|
@@ -214,8 +214,8 @@
|
||||
label-width="120px"
|
||||
size="mini"
|
||||
>
|
||||
<el-form-item label="id">
|
||||
<el-input v-model="authDialogFormData.routeId" readonly="readonly" />
|
||||
<el-form-item label="路由ID">
|
||||
<span>{{ authDialogFormData.routeId }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="角色">
|
||||
<el-checkbox-group v-model="authDialogFormData.roleCode">
|
||||
|
@@ -14,5 +14,6 @@ public class IsvRoutePermission {
|
||||
private String appKey;
|
||||
private List<String> routeIdList = Collections.emptyList();
|
||||
private String routeIdListMd5;
|
||||
private String listenPath;
|
||||
|
||||
}
|
||||
|
@@ -28,15 +28,22 @@ public class ZookeeperContext {
|
||||
|
||||
private static CuratorFramework client;
|
||||
|
||||
private static Environment environment;
|
||||
|
||||
public static void setEnvironment(Environment environment) {
|
||||
Assert.notNull(environment, "environment不能为null");
|
||||
initZookeeperClient(environment);
|
||||
ZookeeperContext.environment = environment;
|
||||
initZookeeperClient();
|
||||
}
|
||||
|
||||
public synchronized static void initZookeeperClient(Environment environment) {
|
||||
public synchronized static void initZookeeperClient() {
|
||||
if (client != null) {
|
||||
return;
|
||||
}
|
||||
setClient(createClient());
|
||||
}
|
||||
|
||||
public static CuratorFramework createClient() {
|
||||
String zookeeperServerAddr = environment.getProperty("spring.cloud.zookeeper.connect-string");
|
||||
if (StringUtils.isBlank(zookeeperServerAddr)) {
|
||||
throw new RuntimeException("未指定spring.cloud.zookeeper.connect-string参数");
|
||||
@@ -51,8 +58,7 @@ public class ZookeeperContext {
|
||||
.build();
|
||||
|
||||
client.start();
|
||||
|
||||
setClient(client);
|
||||
return client;
|
||||
}
|
||||
|
||||
public static String getRouteRootPath() {
|
||||
@@ -100,6 +106,16 @@ public class ZookeeperContext {
|
||||
.forPath(path, data.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新节点
|
||||
* @param path
|
||||
* @param data
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void updatePath(String path, String data) throws Exception {
|
||||
getClient().setData().forPath(path, data.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建path,如果path存在不报错,静默返回path名称
|
||||
*
|
||||
|
@@ -17,7 +17,6 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
@@ -129,7 +128,19 @@ public class DbIsvRoutePermissionManager extends DefaultIsvRoutePermissionManage
|
||||
switch (channelMsg.getOperation()) {
|
||||
case "reload":
|
||||
log.info("重新加载路由权限信息,isvRoutePermission:{}", isvRoutePermission);
|
||||
String listenPath = isvRoutePermission.getListenPath();
|
||||
String code = "0";
|
||||
try {
|
||||
load();
|
||||
} catch (Exception e) {
|
||||
log.error("重新加载路由权限失败, channelMsg:{}", channelMsg, e);
|
||||
code = e.getMessage();
|
||||
}
|
||||
try {
|
||||
ZookeeperContext.updatePath(listenPath, code);
|
||||
} catch (Exception e1) {
|
||||
log.error("重新加载路由权限信息, zookeeper操作失败, path: {}", listenPath, e1);
|
||||
}
|
||||
break;
|
||||
case "update":
|
||||
log.info("更新ISV路由权限信息,isvRoutePermission:{}", isvRoutePermission);
|
||||
|
Reference in New Issue
Block a user