Commit e8e8dfd5 authored by trumansdo's avatar trumansdo
Browse files

done------

完成动态路由,等后面填补一下数据库和前端的路由数据就可以进行下一步的页面代码开发
重写HTTPRequestLocal线程共享变量方法,使之责任明确
添加beetlsql的类型处理,使之可以用时间戳,更加通用
wait-----
在确定是不是要重构一下项目模块,使之更明确
parent 62046c00
*** Spring Boot 2 plus ${AnsiColor.BRIGHT_RED}
\ No newline at end of file
███████╗██████╗ ██████╗ ██╗███╗ ██╗ ██████╗ ██████╗ ██████╗ ██████╗ ████████╗ ██████╗ ██╗ ██╗ ██╗███████╗ ██╗ ██╗██╗ ██╗███████╗
██╔════╝██╔══██╗██╔══██╗██║████╗ ██║██╔════╝ ██╔══██╗██╔═══██╗██╔═══██╗╚══██╔══╝ ██╔══██╗██║ ██║ ██║██╔════╝ ██║ ██║██║ ██║██╔════╝
███████╗██████╔╝██████╔╝██║██╔██╗ ██║██║ ███╗██████╔╝██║ ██║██║ ██║ ██║█████╗██████╔╝██║ ██║ ██║███████╗ ██║ ██║██║ ██║█████╗
╚════██║██╔═══╝ ██╔══██╗██║██║╚██╗██║██║ ██║██╔══██╗██║ ██║██║ ██║ ██║╚════╝██╔═══╝ ██║ ██║ ██║╚════██║ ╚██╗ ██╔╝██║ ██║██╔══╝
███████║██║ ██║ ██║██║██║ ╚████║╚██████╔╝██████╔╝╚██████╔╝╚██████╔╝ ██║ ██║ ███████╗╚██████╔╝███████║ ╚████╔╝ ╚██████╔╝███████╗
╚══════╝╚═╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚══════╝ ╚═════╝ ╚══════╝ ╚═══╝ ╚═════╝ ╚══════╝
Spring Boot Version: ${spring-boot.version}${spring-boot.formatted-version}
\ No newline at end of file
package com.ibeetl.admin.core.conf; package com.ibeetl.admin.core.conf;
import java.io.UnsupportedEncodingException; import cn.hutool.core.convert.Convert;
import java.util.List; import cn.hutool.core.util.ObjectUtil;
import javax.servlet.http.HttpServletRequest;
import org.beetl.core.Context;
import org.beetl.core.Function;
import org.beetl.core.GroupTemplate;
import org.beetl.ext.simulate.WebSimulate;
import org.beetl.sql.core.InterceptorContext;
import org.beetl.sql.ext.DebugInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.ibeetl.admin.core.rbac.DataAccess; import com.ibeetl.admin.core.rbac.DataAccess;
import com.ibeetl.admin.core.rbac.DataAccessFactory; import com.ibeetl.admin.core.rbac.DataAccessFactory;
...@@ -36,6 +20,33 @@ import com.ibeetl.admin.core.util.beetl.XXSDefenderFormat; ...@@ -36,6 +20,33 @@ import com.ibeetl.admin.core.util.beetl.XXSDefenderFormat;
import com.ibeetl.admin.core.web.query.QueryParser; import com.ibeetl.admin.core.web.query.QueryParser;
import com.ibeetl.starter.BeetlTemplateCustomize; import com.ibeetl.starter.BeetlTemplateCustomize;
import com.ibeetl.starter.ObjectMapperJsonUtil; import com.ibeetl.starter.ObjectMapperJsonUtil;
import java.io.UnsupportedEncodingException;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.beetl.core.Context;
import org.beetl.core.Function;
import org.beetl.core.GroupTemplate;
import org.beetl.ext.simulate.WebSimulate;
import org.beetl.sql.core.InterceptorContext;
import org.beetl.sql.core.SQLManager;
import org.beetl.sql.core.mapping.type.JavaSqlTypeHandler;
import org.beetl.sql.core.mapping.type.TypeParameter;
import org.beetl.sql.ext.DebugInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
@Configuration @Configuration
@AutoConfigureAfter(JasonConfig.class) @AutoConfigureAfter(JasonConfig.class)
...@@ -75,81 +86,87 @@ public class BeetlConf { ...@@ -75,81 +86,87 @@ public class BeetlConf {
} }
@Bean @Bean
public BeetlTemplateCustomize beetlTemplateCustomize() { public SQLManager sqlManager(
return new BeetlTemplateCustomize() { @Qualifier("baseDataSourceSqlManagerFactoryBean") SQLManager sqlManager) {
public void customize(GroupTemplate groupTemplate) {
groupTemplate.registerFunctionPackage("platform", platFormService); Map<Class, JavaSqlTypeHandler> typeHandlerMap = sqlManager.getDefaultBeanProcessors().getHandlers();
groupTemplate.registerFunctionPackage("queryCondtion", new QueryParser()); /*Java bean的属性类型处理器,从数据库类型转化到属性Date类型*/
groupTemplate.registerFunction("core.orgName", orgFunction); typeHandlerMap.remove(Date.class);
groupTemplate.registerFunction("core.functionName", funFunction); typeHandlerMap.put(Date.class, new DateTypeHandler());
groupTemplate.registerFunction("core.funAccessUrl", funAccessUrlFunction); typeHandlerMap.put(ZonedDateTime.class, new ZonedDateTimeTypeHandler());
groupTemplate.registerFunction("core.menuName", menuFunction); return sqlManager;
groupTemplate.registerFunction("core.searchCondtion", searchCondtionFunction); }
groupTemplate.registerFunction("core.roles", roleFunction);
groupTemplate.registerFunction("core.file", fileFunction);
groupTemplate.registerFormat("xss", new XXSDefenderFormat());
groupTemplate.registerFunction("uuid", new UUIDFunction());
groupTemplate.registerFunctionPackage("dict", dictDownQueryFunction);
// 模板页面判断是否有按钮权限,比如canAccess
groupTemplate.registerFunction(
"canAccess",
new Function() {
@Override
public Boolean call(Object[] paras, Context ctx) {
Long userId = platFormService.getCurrentUser().getId();
Long orgId = platFormService.getCurrentOrgId();
String functionCode = (String) paras[0];
return platFormService.canAcessFunction(userId, orgId, functionCode);
}
});
groupTemplate.registerFunction(
"abcd",
new Function() {
@Override @Bean
public Boolean call(Object[] paras, Context ctx) { public BeetlTemplateCustomize beetlTemplateCustomize() {
return true; return groupTemplate -> {
groupTemplate.registerFunctionPackage("platform", platFormService);
groupTemplate.registerFunctionPackage("queryCondtion", new QueryParser());
groupTemplate.registerFunction("core.orgName", orgFunction);
groupTemplate.registerFunction("core.functionName", funFunction);
groupTemplate.registerFunction("core.funAccessUrl", funAccessUrlFunction);
groupTemplate.registerFunction("core.menuName", menuFunction);
groupTemplate.registerFunction("core.searchCondtion", searchCondtionFunction);
groupTemplate.registerFunction("core.roles", roleFunction);
groupTemplate.registerFunction("core.file", fileFunction);
groupTemplate.registerFormat("xss", new XXSDefenderFormat());
groupTemplate.registerFunction("uuid", new UUIDFunction());
groupTemplate.registerFunctionPackage("dict", dictDownQueryFunction);
// 模板页面判断是否有按钮权限,比如canAccess
groupTemplate.registerFunction(
"canAccess",
(paras, ctx) -> {
Long userId = platFormService.getCurrentUser().getId();
Long orgId = platFormService.getCurrentOrgId();
String functionCode = (String) paras[0];
return platFormService.canAcessFunction(userId, orgId, functionCode);
});
groupTemplate.registerFunction(
"abcd",
new Function() {
@Override
public Boolean call(Object[] paras, Context ctx) {
return true;
}
});
groupTemplate.registerFunction(
"env",
new Function() {
@Override
public String call(Object[] paras, Context ctx) {
String key = (String) paras[0];
String value = env.getProperty(key);
if (value != null) {
return getStr(value);
} }
}); if (paras.length == 2) {
return (String) paras[1];
groupTemplate.registerFunction(
"env",
new Function() {
@Override
public String call(Object[] paras, Context ctx) {
String key = (String) paras[0];
String value = env.getProperty(key);
if (value != null) {
return getStr(value);
}
if (paras.length == 2) {
return (String) paras[1];
}
return null;
} }
return null;
protected String getStr(String str) { }
try {
return new String(str.getBytes("iso8859-1"), "UTF-8"); protected String getStr(String str) {
} catch (UnsupportedEncodingException e) { try {
throw new RuntimeException(e); return new String(str.getBytes("iso8859-1"), "UTF-8");
} } catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
} }
}); }
});
groupTemplate.registerFunction(
"dataAccessList", groupTemplate.registerFunction(
new Function() { "dataAccessList",
new Function() {
@Override
public List<DataAccess> call(Object[] paras, Context ctx) { @Override
return dataAccessFactory.all(); public List<DataAccess> call(Object[] paras, Context ctx) {
} return dataAccessFactory.all();
}); }
} });
}; };
} }
...@@ -166,4 +183,43 @@ public class BeetlConf { ...@@ -166,4 +183,43 @@ public class BeetlConf {
return; return;
} }
} }
class DateTypeHandler extends JavaSqlTypeHandler {
@Override
public Object getValue(TypeParameter typePara) throws SQLException {
if (ObjectUtil.isNull(typePara.getRs().getObject(typePara.getIndex()))) {
return null;
}
int columnType = typePara.getColumnType();
if (Types.TIMESTAMP == columnType || Types.DATE == columnType) {
Timestamp timestamp = typePara.getRs().getTimestamp(typePara.getIndex());
return Date.from(Instant.ofEpochSecond(timestamp.getTime()));
} else if (Types.BIGINT == columnType) {
long timestamp = Convert.toLong(typePara.getRs().getLong(typePara.getIndex()), 0L);
return Date.from(Instant.ofEpochSecond(timestamp));
} else {
return null;
}
}
}
class ZonedDateTimeTypeHandler extends JavaSqlTypeHandler {
@Override
public Object getValue(TypeParameter typePara) throws SQLException {
if (ObjectUtil.isNull(typePara.getRs().getObject(typePara.getIndex()))) {
return null;
}
int columnType = typePara.getColumnType();
if (Types.TIMESTAMP == columnType || Types.DATE == columnType) {
Timestamp timestamp = typePara.getRs().getTimestamp(typePara.getIndex());
return ZonedDateTime
.ofInstant(Instant.ofEpochSecond(timestamp.getTime()), ZoneId.systemDefault());
} else if (Types.BIGINT == columnType) {
long timestamp = Convert.toLong(typePara.getRs().getLong(typePara.getIndex()), 0L);
return ZonedDateTime
.ofInstant(Instant.ofEpochSecond(timestamp), ZoneId.systemDefault());
} else {
return null;
}
}
}
} }
...@@ -44,7 +44,7 @@ public class JasonConfig { ...@@ -44,7 +44,7 @@ public class JasonConfig {
throws IOException { throws IOException {
gen.writeStartObject(); gen.writeStartObject();
gen.writeObjectField("code", Integer.parseInt(value.getCode())); gen.writeObjectField("code", Integer.parseInt(value.getCode()));
gen.writeStringField("msg", value.getMessage()); gen.writeStringField("message", value.getMessage());
Object data = value.getData(); Object data = value.getData();
if (data instanceof PageQuery) { if (data instanceof PageQuery) {
PageQuery query = (PageQuery) (data); PageQuery query = (PageQuery) (data);
......
package com.ibeetl.admin.core.conf; package com.ibeetl.admin.core.conf;
import static com.ibeetl.admin.core.util.HttpRequestLocal.ACCESS_CURRENT_USER;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ClassUtil; import cn.hutool.core.util.ClassUtil;
...@@ -69,8 +71,6 @@ public class MVCConf implements WebMvcConfigurer, InitializingBean { ...@@ -69,8 +71,6 @@ public class MVCConf implements WebMvcConfigurer, InitializingBean {
@Autowired private BeetlGroupUtilConfiguration beetlGroupUtilConfiguration; @Autowired private BeetlGroupUtilConfiguration beetlGroupUtilConfiguration;
@Autowired private HttpRequestLocal httpRequestLocal;
@Autowired private GroupTemplate groupTemplate; @Autowired private GroupTemplate groupTemplate;
@Autowired private RequestMappingHandlerAdapter adapter; @Autowired private RequestMappingHandlerAdapter adapter;
...@@ -78,7 +78,7 @@ public class MVCConf implements WebMvcConfigurer, InitializingBean { ...@@ -78,7 +78,7 @@ public class MVCConf implements WebMvcConfigurer, InitializingBean {
@Override @Override
public void addInterceptors(InterceptorRegistry registry) { public void addInterceptors(InterceptorRegistry registry) {
registry registry
.addInterceptor(new SessionInterceptor(httpRequestLocal, userService)) .addInterceptor(new SessionInterceptor(userService))
.addPathPatterns("/**"); .addPathPatterns("/**");
// super.addInterceptors(registry); // super.addInterceptors(registry);
} }
...@@ -116,40 +116,25 @@ class SessionInterceptor implements HandlerInterceptor { ...@@ -116,40 +116,25 @@ class SessionInterceptor implements HandlerInterceptor {
CoreUserService userService; CoreUserService userService;
HttpRequestLocal httpRequestLocal; public SessionInterceptor(CoreUserService userService) {
public SessionInterceptor(HttpRequestLocal httpRequestLocal, CoreUserService userService) {
this.userService = userService; this.userService = userService;
this.httpRequestLocal = httpRequestLocal;
} }
@Override @Override
public boolean preHandle( public boolean preHandle(
HttpServletRequest request, HttpServletResponse response, Object handler) { HttpServletRequest request, HttpServletResponse response, Object handler) {
httpRequestLocal.set(request); HttpRequestLocal.set(request);
if (StrUtil.containsAny(request.getRequestURI(), "/login", "/error", "/logout")) { if (StrUtil.containsAny(request.getRequestURI(), "/login", "/error", "/logout")) {
return true; return true;
} }
String token = request.getHeader(HttpHeaders.AUTHORIZATION); String token = HttpRequestLocal.getAuthorization();
Map<String, Object> payload = JoseJwtUtil.parsePayload(token); Map<String, Object> payload = JoseJwtUtil.parsePayload(token);
if (payload.isEmpty()) { if (payload.isEmpty()) {
/*验证失败,无效jwt*/ /*验证失败,无效jwt*/
return false; return false;
} }
Long uid = Convert.toLong(payload.get("uid"), -9999999999L);
HttpSession requestSession = request.getSession(true);
if (requestSession.getAttribute(CorePlatformService.ACCESS_CURRENT_USER) == null) {
// 模拟用户登录,用于快速开发,未来用rember么代替?
CoreUser user = userService.getUserById(uid);
Long orgId = user.getOrgId();
CoreOrg org = userService.getOrgById(orgId);
List<CoreOrg> orgs = userService.getUserOrg(uid, org.getId());
requestSession.setAttribute(CorePlatformService.ACCESS_CURRENT_USER, user);
requestSession.setAttribute(CorePlatformService.ACCESS_CURRENT_ORG, org);
requestSession.setAttribute(CorePlatformService.ACCESS_USER_ORGS, orgs);
requestSession.setAttribute("ip", httpRequestLocal.getRequestIP());
}
return true; return true;
} }
......
package com.ibeetl.admin.core.dao; package com.ibeetl.admin.core.dao;
import com.ibeetl.admin.core.entity.CoreRoute;
import java.util.List;
import org.beetl.sql.core.annotatoin.Param; import org.beetl.sql.core.annotatoin.Param;
import org.beetl.sql.core.annotatoin.Sql; import org.beetl.sql.core.annotatoin.Sql;
import org.beetl.sql.core.annotatoin.SqlResource; import org.beetl.sql.core.annotatoin.SqlResource;
...@@ -11,4 +13,6 @@ import com.ibeetl.admin.core.entity.CoreFunction; ...@@ -11,4 +13,6 @@ import com.ibeetl.admin.core.entity.CoreFunction;
public interface CoreFunctionDao extends BaseMapper<CoreFunction> { public interface CoreFunctionDao extends BaseMapper<CoreFunction> {
@Sql("select * from core_function where code = ?") @Sql("select * from core_function where code = ?")
CoreFunction getFunctionByCode(@Param(value = "code") String code); CoreFunction getFunctionByCode(@Param(value = "code") String code);
List<CoreRoute> getAllRoutes();
} }
package com.ibeetl.admin.core.entity;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import lombok.Data;
/**
* 对应前端页面的routes路由表。具体格式如下: { "path": "/profile", "name": "router-name", "meta": { "title":
* "Profile", "roles": ["admin", "editor"], "icon": "user" }, "children": [] }
*
* @author 一日看尽长安花
*/
@Data
public class CoreRoute extends BaseEntity implements Comparable<CoreRoute> {
private Long id;
private Long parentId;
/** 路由路径,完全参照vue router规范 */
private String path;
/** 路由名称,请确保唯一性 */
private String name;
/** 路由顺序 */
private Long seq = -999L;
/** 路由元数据信息 */
private CoreRouteMeta meta;
/** 子路由项 */
private List<CoreRoute> children = CollUtil.newArrayList();
public CoreRouteMeta getMeta() {
if (ObjectUtil.isNotEmpty(this.meta)) return this.meta;
Map<String, Object> metaMap = MapUtil.builder(getTails()).build();
this.meta = BeanUtil.mapToBean(metaMap, CoreRouteMeta.class, true);
return this.meta;
}
@Override
public boolean equals(Object o) {
if (o != null && o instanceof CoreRoute) {
CoreRoute othRoute = (CoreRoute) o;
if (this.getId().equals(othRoute.getId())) {
return true;
}
if (this.getParentId().equals(othRoute.getParentId())) {
return StrUtil.equals(this.getPath(), othRoute.getPath())
&& StrUtil.equals(this.getName(), othRoute.getName());
} else {
return false;
}
} else {
return false;
}
}
@Override
public int hashCode() {
return Objects.hash(id, parentId, path, name);
}
@Override
public int compareTo(CoreRoute o) {
if (null == o) return -1;
Long seq1 = this.getSeq() == null ? -999L : this.getSeq();
Long seq2 = o.getSeq() == null ? -999L : o.getSeq();
return seq1.compareTo(seq2);
}
}
package com.ibeetl.admin.core.entity;
import cn.hutool.core.collection.CollUtil;
import java.util.List;
import lombok.Data;
@Data
public class CoreRouteMeta {
/** 路由展示在菜单中显示的标题 */
private String title;
/** 在菜单中显示的图标 */
private String icon;
/** 当前路由可以访问的角色 */
private List<Long> roles = CollUtil.<Long>newArrayList();
}
package com.ibeetl.admin.core.entity; package com.ibeetl.admin.core.entity;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.util.Date; import java.util.Date;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
...@@ -29,6 +31,8 @@ public class CoreUserRole extends BaseEntity { ...@@ -29,6 +31,8 @@ public class CoreUserRole extends BaseEntity {
protected Date createTime; protected Date createTime;
protected ZonedDateTime updateTime;
public Long getId() { public Long getId() {
return id; return id;
} }
...@@ -68,4 +72,12 @@ public class CoreUserRole extends BaseEntity { ...@@ -68,4 +72,12 @@ public class CoreUserRole extends BaseEntity {
public void setCreateTime(Date createTime) { public void setCreateTime(Date createTime) {
this.createTime = createTime; this.createTime = createTime;
} }
public ZonedDateTime getUpdateTime() {
return updateTime;
}
public void setUpdateTime(ZonedDateTime updateTime) {
this.updateTime = updateTime;
}
} }
package com.ibeetl.admin.core.rbac;
import lombok.Data;
@Data
public class UserRoleInfo {
private String name;
private String avatar;
private Long[] roles;
private String introduction;
}
package com.ibeetl.admin.core.service; package com.ibeetl.admin.core.service;
import static com.ibeetl.admin.core.util.HttpRequestLocal.ACCESS_CURRENT_ORG;
import static com.ibeetl.admin.core.util.HttpRequestLocal.ACCESS_CURRENT_USER;
import static com.ibeetl.admin.core.util.HttpRequestLocal.ACCESS_USER_ORGS;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
...@@ -61,13 +65,6 @@ public class CorePlatformService { ...@@ -61,13 +65,6 @@ public class CorePlatformService {
public static final String USER_DATA_ACCESS_CACHE = "cache:core:userDataAccess"; public static final String USER_DATA_ACCESS_CACHE = "cache:core:userDataAccess";
public static final String USER_MENU_CACHE = "cache:core:userMenu"; public static final String USER_MENU_CACHE = "cache:core:userMenu";
/*当前用户会话*/
public static final String ACCESS_CURRENT_USER = "core:user";
/*当前登录用户所在部门*/
public static final String ACCESS_CURRENT_ORG = "core:currentOrg";
/*用户可选部门*/
public static final String ACCESS_USER_ORGS = "core:orgs";
public static final String ACCESS_SUPPER_ADMIN = "admin"; public static final String ACCESS_SUPPER_ADMIN = "admin";
@Autowired HttpRequestLocal httpRequestLocal; @Autowired HttpRequestLocal httpRequestLocal;
...@@ -112,7 +109,7 @@ public class CorePlatformService { ...@@ -112,7 +109,7 @@ public class CorePlatformService {
List<CoreOrg> orgs = this.getCurrentOrgs(); List<CoreOrg> orgs = this.getCurrentOrgs();
for (CoreOrg org : orgs) { for (CoreOrg org : orgs) {
if (org.getId().equals(orgId)) { if (org.getId().equals(orgId)) {
httpRequestLocal.setSessionValue(CorePlatformService.ACCESS_CURRENT_ORG, org); httpRequestLocal.setSessionValue(ACCESS_CURRENT_ORG, org);
} }
} }
} }
...@@ -142,9 +139,9 @@ public class CorePlatformService { ...@@ -142,9 +139,9 @@ public class CorePlatformService {
} }
public void setLoginUser(CoreUser user, CoreOrg currentOrg, List<CoreOrg> orgs) { public void setLoginUser(CoreUser user, CoreOrg currentOrg, List<CoreOrg> orgs) {
httpRequestLocal.setSessionValue(CorePlatformService.ACCESS_CURRENT_USER, user); httpRequestLocal.setSessionValue(ACCESS_CURRENT_USER, user);
httpRequestLocal.setSessionValue(CorePlatformService.ACCESS_CURRENT_ORG, currentOrg); httpRequestLocal.setSessionValue(ACCESS_CURRENT_ORG, currentOrg);
httpRequestLocal.setSessionValue(CorePlatformService.ACCESS_USER_ORGS, orgs); httpRequestLocal.setSessionValue(ACCESS_USER_ORGS, orgs);
} }
public MenuItem getMenuItem(long userId, long orgId) { public MenuItem getMenuItem(long userId, long orgId) {
......
package com.ibeetl.admin.core.service; package com.ibeetl.admin.core.service;
import com.ibeetl.admin.core.dao.CoreRoleDao;
import com.ibeetl.admin.core.entity.CoreRole;
import com.ibeetl.admin.core.entity.CoreUserRole;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import lombok.extern.log4j.Log4j2;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import com.ibeetl.admin.core.dao.CoreRoleDao;
import com.ibeetl.admin.core.entity.CoreRole;
/** /**
* 描述: 字典 service,包含常规字典和级联字典的操作。 * 描述: 字典 service,包含常规字典和级联字典的操作。
* *
* @author : xiandafu * @author : xiandafu
*/ */
@Slf4j
@Service @Service
@Transactional @Transactional
public class CoreRoleService extends CoreBaseService<CoreRole> { public class CoreRoleService extends CoreBaseService<CoreRole> {
private static final Logger LOGGER = LoggerFactory.getLogger(CoreRoleService.class);
@Autowired private CoreRoleDao roleDao; @Autowired private CoreRoleDao roleDao;
public List<CoreRole> getAllRoles(String type) { public List<CoreRole> getAllRoles(String type) {
......
package com.ibeetl.admin.core.service.vea;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import com.ibeetl.admin.core.dao.CoreFunctionDao;
import com.ibeetl.admin.core.dao.CoreRoleDao;
import com.ibeetl.admin.core.entity.CoreRoute;
import com.ibeetl.admin.core.entity.CoreUserRole;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Slf4j
@Service
@Transactional
public class RoleRoutesService {
@Autowired private CoreFunctionDao coreFunctionDao;
@Autowired private CoreRoleDao coreRoleDao;
public List<Long> getAllRoleIds(Long userId, Long orgId) {
return coreRoleDao.getSQLManager().lambdaQuery(CoreUserRole.class).andEq("user_id", userId)
.andEq("org_id", orgId).select(Long.class, "role_id").stream()
.distinct()
.collect(Collectors.toList());
}
/**
*
* 前端路由映射表中单个路由映射全部具有的信息:
* { <br/>
* "path": "/profile", <br/>
* "component": "Layout", <br/>
* "redirect": "/profile/index", <br/>
* "hidden": true, <br/>
* "alwaysShow": true, <br/>
* "name": "router-name", <br/>
* "meta": { <br/>
* "noCache": true, <br/>
* "affix": true, <br/>
* "breadcrumb": false, <br/>
* "activeMenu": "/example/list" <br/>
* }, <br/>
* "children": [] <br/>
* } <br/>
* 后端路由表中单个路由应该具有的信息: <br/>
* { <br/>
* "path": "/profile", <br/>
* "name": "router-name", <br/>
* "meta": { <br/>
* "title": "Profile", <br/>
* "roles": ["admin", "editor"], <br/>
* "icon": "user" <br/>
* }, <br/>
* "children": [] <br/>
* } <br/>
*
* @return 路由表格式
* */
public List<CoreRoute> getRoutes() {
List<CoreRoute> routesList = coreFunctionDao.getAllRoutes();
Map<Long, List<Long>> roleIdList =
routesList.stream()
.collect(
Collectors.groupingBy(
CoreRoute::getId,
Collectors.mapping(
coreRoute -> Convert.toLong(coreRoute.getTails().get("roleId")),
Collectors.toList())));
routesList = routesList.stream().distinct().sorted().collect(Collectors.toList());
for (CoreRoute coreRoute : routesList) {
coreRoute
.getMeta()
.getRoles()
.addAll(CollUtil.<Long>removeNull(roleIdList.get(coreRoute.getId())));
}
CoreRoute root = new CoreRoute();
root.setId(0L);
buildRoutesTree(root, routesList);
return root.getChildren();
}
/**
* 深度优先算法递归构建路由表
*
* @param root
* @param allRoutes
* @return
*/
private void buildRoutesTree(CoreRoute root, @NotNull List<CoreRoute> allRoutes) {
if (CollUtil.isEmpty(allRoutes)) return;
List<CoreRoute> childRoutes =
allRoutes.stream()
.filter(route -> route.getParentId().equals(root.getId()))
.collect(Collectors.toList());
root.setChildren(childRoutes);
allRoutes.removeAll(childRoutes);
Collections.sort(root.getChildren());
List<CoreRoute> rootChildrenList = root.getChildren();
for (int i = 0; i < rootChildrenList.size(); i++) {
buildRoutesTree(rootChildrenList.get(i), allRoutes);
}
}
}
package com.ibeetl.admin.core.util; package com.ibeetl.admin.core.util;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.ibeetl.admin.core.entity.CoreOrg;
import com.ibeetl.admin.core.entity.CoreUser;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.stream.Stream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ibeetl.admin.core.conf.MVCConf; import com.ibeetl.admin.core.conf.MVCConf;
...@@ -15,49 +27,114 @@ import com.ibeetl.admin.core.conf.MVCConf; ...@@ -15,49 +27,114 @@ import com.ibeetl.admin.core.conf.MVCConf;
* @author lijiazhi * @author lijiazhi
*/ */
@Component @Component
public class HttpRequestLocal { public final class HttpRequestLocal {
/*当前用户会话*/
public static final String ACCESS_CURRENT_USER = "core:user";
/*当前登录用户所在部门*/
public static final String ACCESS_CURRENT_ORG = "core:currentOrg";
/*用户可选部门*/
public static final String ACCESS_USER_ORGS = "core:orgs";
public HttpRequestLocal() {} public HttpRequestLocal() {}
private static final ThreadLocal<HttpServletRequest> requests = private static final ThreadLocal<HttpServletRequest> requests =
new ThreadLocal<HttpServletRequest>() { ThreadLocal.withInitial(() -> null);
@Override
protected HttpServletRequest initialValue() { public static void setAccessCurrentOrg(CoreOrg org) {
return null; getHttpSession().setAttribute(ACCESS_CURRENT_ORG, org);
} }
};
public static CoreOrg getAccessCurrentOrg() {
return (CoreOrg) getHttpSession().getAttribute(ACCESS_CURRENT_ORG);
}
public static void setAccessUserOrgs(List<CoreOrg> orgs) {
getHttpSession().setAttribute(ACCESS_USER_ORGS, orgs);
}
public Object getSessionValue(String attr) { public static List<CoreOrg> getAccessUserOrgs() {
return requests.get().getSession().getAttribute(attr); return Convert.toList(CoreOrg.class, getHttpSession().getAttribute(ACCESS_USER_ORGS));
} }
public void setSessionValue(String attr, Object obj) { public static void setAccessCurrentUser(CoreUser user) {
requests.get().getSession().setAttribute(attr, obj); getHttpSession().setAttribute(ACCESS_CURRENT_USER, user);
} }
public Object getRequestValue(String attr) { public static CoreUser getAccessCurrentUser() {
return requests.get().getAttribute(attr); return (CoreUser) getHttpSession().getAttribute(ACCESS_CURRENT_USER);
} }
public String getRequestURI() { public static void setLoginerInfo(CoreUser user, CoreOrg org, List<CoreOrg> orgs) {
return requests.get().getRequestURI(); setAccessCurrentUser(user);
setAccessCurrentOrg(org);
setAccessUserOrgs(orgs);
getHttpSession().setAttribute("clientIP", getIpAddr(get()));
} }
public String getRequestIP() { public static void clearAllSession() {
return getIpAddr(requests.get()); getHttpSession().removeAttribute(ACCESS_CURRENT_USER);
getHttpSession().removeAttribute(ACCESS_CURRENT_ORG);
getHttpSession().removeAttribute(ACCESS_USER_ORGS);
} }
public void set(HttpServletRequest request) { public static Cookie getCookieByName(String cookieName) {
Assert.notNull(cookieName);
Cookie[] cookies = get().getCookies();
return Arrays.stream(cookies)
.filter(cookie -> StrUtil.equals(cookie.getName(), cookieName))
.findFirst()
.orElse(null);
}
public static Object getSessionValue(String attr) {
return getHttpSession().getAttribute(attr);
}
public static void setSessionValue(String attr, Object obj) {
get().getSession().setAttribute(attr, obj);
}
public static String getAuthorization() {
return get().getHeader(HttpHeaders.AUTHORIZATION);
}
public static Object getRequestValue(String attr) {
return get().getAttribute(attr);
}
public static void setRequestValue(String attr, Object obj) {
get().setAttribute(attr, obj);
}
/** @return 请求的uri,域名与参数之间的那部分 */
public static String getRequestURI() {
return get().getRequestURI();
}
/** @return 获取客户端ip */
public static String getRequestIP() {
return getIpAddr(get());
}
public static void set(HttpServletRequest request) {
requests.set(request); requests.set(request);
} }
public static HttpServletRequest get() {
return requests.get();
}
public static HttpSession getHttpSession() {
return get().getSession();
}
/** /**
* 获取当前网络ip * 获取当前网络ip
* *
* @param request * @param request
* @return * @return
*/ */
public String getIpAddr(HttpServletRequest request) { public static String getIpAddr(HttpServletRequest request) {
String ipAddress = request.getHeader("x-forwarded-for"); String ipAddress = request.getHeader("x-forwarded-for");
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("Proxy-Client-IP"); ipAddress = request.getHeader("Proxy-Client-IP");
......
package com.ibeetl.admin.core.web; package com.ibeetl.admin.core.web;
import cn.hutool.core.map.MapUtil; import static com.ibeetl.admin.core.util.HttpRequestLocal.ACCESS_CURRENT_ORG;
import cn.hutool.core.util.StrUtil; import static com.ibeetl.admin.core.util.HttpRequestLocal.ACCESS_USER_ORGS;
import com.ibeetl.admin.core.annotation.RequestBodyPlus;
import com.ibeetl.admin.core.util.JoseJwtUtil;
import com.ibeetl.admin.core.util.PlatformException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ibeetl.admin.core.conf.PasswordConfig.PasswordEncryptService; import com.ibeetl.admin.core.conf.PasswordConfig.PasswordEncryptService;
import com.ibeetl.admin.core.entity.CoreOrg; import com.ibeetl.admin.core.entity.CoreOrg;
...@@ -31,7 +16,15 @@ import com.ibeetl.admin.core.util.HttpRequestLocal; ...@@ -31,7 +16,15 @@ import com.ibeetl.admin.core.util.HttpRequestLocal;
import com.ibeetl.admin.core.web.dto.FunctionNodeView; import com.ibeetl.admin.core.web.dto.FunctionNodeView;
import com.ibeetl.admin.core.web.dto.MenuNodeView; import com.ibeetl.admin.core.web.dto.MenuNodeView;
import com.ibeetl.admin.core.web.dto.SystemMenuView; import com.ibeetl.admin.core.web.dto.SystemMenuView;
import sun.swing.StringUIClientPropertyKey; import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller @Controller
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
...@@ -79,7 +72,7 @@ public class CoreUserController { ...@@ -79,7 +72,7 @@ public class CoreUserController {
@ResponseBody @ResponseBody
public JsonResult<List<CoreOrg>> myOrgs() { public JsonResult<List<CoreOrg>> myOrgs() {
List<CoreOrg> orgs = List<CoreOrg> orgs =
(List<CoreOrg>) httpRequestLocal.getSessionValue(CorePlatformService.ACCESS_USER_ORGS); (List<CoreOrg>) httpRequestLocal.getSessionValue(ACCESS_USER_ORGS);
return JsonResult.success(orgs); return JsonResult.success(orgs);
} }
...@@ -109,7 +102,7 @@ public class CoreUserController { ...@@ -109,7 +102,7 @@ public class CoreUserController {
return JsonResult.failMessage("切换到不存在的部门"); return JsonResult.failMessage("切换到不存在的部门");
} }
httpRequestLocal.setSessionValue(CorePlatformService.ACCESS_CURRENT_ORG, currentOrg); httpRequestLocal.setSessionValue(ACCESS_CURRENT_ORG, currentOrg);
return JsonResult.success(); return JsonResult.success();
} }
...@@ -257,45 +250,4 @@ public class CoreUserController { ...@@ -257,45 +250,4 @@ public class CoreUserController {
} }
return views; return views;
} }
@GetMapping("/user/info")
@ResponseBody
public JsonResult info(
@RequestBodyPlus("username") String username, @RequestBodyPlus("password") String password) {
Map<String, Object> resultMap =
MapUtil.<String, Object>builder()
.build();
return JsonResult.success(resultMap);
}
@PostMapping("/user/login")
@ResponseBody
public JsonResult loginEle(
@RequestBodyPlus("username") String username, @RequestBodyPlus("password") String password) {
UserLoginInfo info = userService.login(username, password);
if (info == null) {
throw new PlatformException("用户名密码错误");
}
CoreUser user = info.getUser();
CoreOrg currentOrg = info.getOrgs().stream().findFirst().orElse(null);
for (CoreOrg org : info.getOrgs()) {
if (org.getId().equals(user.getOrgId())) {
currentOrg = org;
break;
}
}
info.setCurrentOrg(currentOrg);
// 记录登录信息到session
this.platformService.setLoginUser(info.getUser(), info.getCurrentOrg(), info.getOrgs());
Map<String, Object> resultMap =
MapUtil.<String, Object>builder()
.put("token", JoseJwtUtil.generateJwtJson(String.valueOf(user.getId())))
.build();
return JsonResult.success(resultMap);
}
} }
package com.ibeetl.admin.core.web.vea;
import cn.hutool.core.map.MapUtil;
import com.ibeetl.admin.core.annotation.RequestBodyPlus;
import com.ibeetl.admin.core.entity.CoreOrg;
import com.ibeetl.admin.core.entity.CoreRoute;
import com.ibeetl.admin.core.entity.CoreUser;
import com.ibeetl.admin.core.rbac.UserLoginInfo;
import com.ibeetl.admin.core.rbac.UserRoleInfo;
import com.ibeetl.admin.core.service.vea.RoleRoutesService;
import com.ibeetl.admin.core.service.CoreUserService;
import com.ibeetl.admin.core.util.HttpRequestLocal;
import com.ibeetl.admin.core.util.JoseJwtUtil;
import com.ibeetl.admin.core.util.PlatformException;
import com.ibeetl.admin.core.web.JsonResult;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserRestController {
@Autowired private RoleRoutesService roleRoutesService;
@Autowired private CoreUserService coreUserService;
@GetMapping("/routes")
public JsonResult<List<CoreRoute>> routes() {
return JsonResult.success(roleRoutesService.getRoutes());
}
@GetMapping("/user/info")
public JsonResult info() {
CoreOrg currentOrg = HttpRequestLocal.getAccessCurrentOrg();
CoreUser currentUser = HttpRequestLocal.getAccessCurrentUser();
List<Long> roleIds = roleRoutesService.getAllRoleIds(currentUser.getId(), currentOrg.getId());
UserRoleInfo userRoleInfo = new UserRoleInfo();
userRoleInfo.setAvatar("avatar");
userRoleInfo.setIntroduction("introduction");
userRoleInfo.setName(currentUser.getName());
userRoleInfo.setRoles(roleIds.toArray(new Long[0]));
return JsonResult.success(userRoleInfo);
}
@PostMapping("/user/login")
public JsonResult loginEle(
@RequestBodyPlus("username") String username, @RequestBodyPlus("password") String password) {
UserLoginInfo info = coreUserService.login(username, password);
if (info == null) {
throw new PlatformException("用户名密码错误");
}
CoreUser user = info.getUser();
CoreOrg currentOrg = info.getOrgs().stream().findFirst().orElse(null);
for (CoreOrg org : info.getOrgs()) {
if (org.getId().equals(user.getOrgId())) {
currentOrg = org;
break;
}
}
info.setCurrentOrg(currentOrg);
// 记录登录信息到session
HttpRequestLocal.setLoginerInfo(info.getUser(), info.getCurrentOrg(), info.getOrgs());
Map<String, Object> resultMap =
MapUtil.<String, Object>builder()
.put("token", JoseJwtUtil.generateJwtJson(String.valueOf(user.getId())))
.build();
return JsonResult.success(resultMap);
}
@PostMapping("/user/logout")
public JsonResult logout() {
HttpRequestLocal.clearAllSession();
return JsonResult.success();
}
}
getAllRoutes
===
select router.id,
router.PARENT_ID,
ifnull(router.ACCESS_URL, '/error/404') path,
router.NAME,
menu.NAME title,
menu.ICON,
ifnull(menu.SEQ, 999999) seq,
crm.ROLE_ID
from core_function router
left join core_menu menu
on menu.FUNCTION_ID = router.ID
left join core_role_menu crm on crm.MENU_ID = menu.id;
This diff is collapsed.
...@@ -5,7 +5,8 @@ ENV = 'development' ...@@ -5,7 +5,8 @@ ENV = 'development'
# 在这里是webpack-dev-server启动的地址,然后通过webpack-dev-server的proxy代理到我们的后台服务器 # 在这里是webpack-dev-server启动的地址,然后通过webpack-dev-server的proxy代理到我们的后台服务器
# 仅限开发环境,生产环境要用NGINX仅限代理 # 仅限开发环境,生产环境要用NGINX仅限代理
VUE_APP_BASE_API = '/dev-api' VUE_APP_BASE_API = '/dev-api'
VUE_APP_SERVER_HOST = 'http://127.0.0.1:9527/mock' # VUE_APP_SERVER_HOST = 'http://127.0.0.1:9527/mock'
VUE_APP_SERVER_HOST = 'http://127.0.0.1:8080'
# vue-cli uses the VUE_CLI_BABEL_TRANSPILE_MODULES environment variable, # vue-cli uses the VUE_CLI_BABEL_TRANSPILE_MODULES environment variable,
# to control whether the babel-plugin-dynamic-import-node plugin is enabled. # to control whether the babel-plugin-dynamic-import-node plugin is enabled.
......
...@@ -55,6 +55,7 @@ ...@@ -55,6 +55,7 @@
"js-cookie": "2.2.0", "js-cookie": "2.2.0",
"jsonlint": "1.6.3", "jsonlint": "1.6.3",
"jszip": "3.2.1", "jszip": "3.2.1",
"lodash": "^4.17.15",
"normalize.css": "7.0.0", "normalize.css": "7.0.0",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"path-to-regexp": "2.4.0", "path-to-regexp": "2.4.0",
......
...@@ -54,7 +54,7 @@ export const constantRoutes = [ ...@@ -54,7 +54,7 @@ export const constantRoutes = [
path: 'dashboard', path: 'dashboard',
component: () => import('@/views/dashboard/index'), component: () => import('@/views/dashboard/index'),
name: 'Dashboard', name: 'Dashboard',
meta: { title: 'Dashboard', icon: 'dashboard', affix: true } meta: { title: 'Dashboard', icon: 'dashboard', affix: false }
} }
] ]
}, },
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment