新增 切换部门功能、多部门岗位权限

This commit is contained in:
thinkgem
2025-02-01 16:22:34 +08:00
parent fa8d88285f
commit a790e357c7
9 changed files with 145 additions and 48 deletions

View File

@@ -54,7 +54,10 @@ public class FormFilter extends org.apache.shiro.web.filter.authc.FormAuthentica
public static final String MESSAGE_PARAM = "message"; // 登录返回消息
public static final String REMEMBER_USERCODE_PARAM = "rememberUserCode"; // 记住用户名
public static final String EXCEPTION_ATTRIBUTE_NAME = "exception"; // 异常类属性名
public static final String LOGIN_PARAM = "__login"; // 支持GET方式登录的参数
public static final String LOGIN_PARAM = "__login"; // 支持GET方式登录的参数
public static final Boolean POST_ROLE_PERMI = Global.getConfigToBoolean("user.postRolePermi", "false");
public static final Boolean SWITCH_OFFICE = Global.getConfigToBoolean("user.switchOffice", "false");
private static final Logger logger = LoggerFactory.getLogger(FormFilter.class);
@@ -75,7 +78,7 @@ public class FormFilter extends org.apache.shiro.web.filter.authc.FormAuthentica
rememberUserCodeCookie.setMaxAge(Cookie.ONE_YEAR);
instance = this;
}
/**
* 创建登录授权令牌
*/
@@ -96,7 +99,7 @@ public class FormFilter extends org.apache.shiro.web.filter.authc.FormAuthentica
Map<String, Object> paramMap = ServletUtils.getExtParams(request); // 登录附加参数
return new FormToken(username, password.toCharArray(), rememberMe, host, captcha, paramMap);
}
/**
* 获取登录用户名
*/
@@ -125,7 +128,7 @@ public class FormFilter extends org.apache.shiro.web.filter.authc.FormAuthentica
}
return username;
}
/**
* 获取登录密码
*/
@@ -148,7 +151,7 @@ public class FormFilter extends org.apache.shiro.web.filter.authc.FormAuthentica
}
return password;
}
/**
* 获取记住我
*/
@@ -160,7 +163,7 @@ public class FormFilter extends org.apache.shiro.web.filter.authc.FormAuthentica
}
return ObjectUtils.toBoolean(isRememberMe);
}
/**
* 获取请求的客户端主机
*/
@@ -168,7 +171,7 @@ public class FormFilter extends org.apache.shiro.web.filter.authc.FormAuthentica
protected String getHost(ServletRequest request) {
return IpUtils.getRemoteAddr((HttpServletRequest)request);
}
/**
* 获取登录验证码
*/
@@ -187,7 +190,7 @@ public class FormFilter extends org.apache.shiro.web.filter.authc.FormAuthentica
}
return captcha;
}
/**
* 多次调用登录接口,允许改变登录身份,无需退出再登录
*/
@@ -250,7 +253,7 @@ public class FormFilter extends org.apache.shiro.web.filter.authc.FormAuthentica
protected void redirectToLogin(ServletRequest request, ServletResponse response) throws IOException {
PermissionsFilter.redirectToDefaultPath(request, response);
}
/**
* 执行登录方法
*/
@@ -332,20 +335,20 @@ public class FormFilter extends org.apache.shiro.web.filter.authc.FormAuthentica
ServletUtils.redirectUrl((HttpServletRequest)request, (HttpServletResponse)response, loginFailureUrl);
return false;
}
/**
* 获取登录页面数据
* @author ThinkGem
*/
public static Map<String, Object> getLoginData(HttpServletRequest request, HttpServletResponse response) {
Map<String, Object> data = MapUtils.newHashMap();
// 获取登录参数
Map<String, Object> paramMap = ServletUtils.getExtParams(request);
for (Entry<String, Object> entry : paramMap.entrySet()){
data.put(ServletUtils.EXT_PARAMS_PREFIX + entry.getKey(), entry.getValue());
}
// 如果已登录,再次访问主页,则退出原账号。
if (!Global.TRUE.equals(Global.getConfig("shiro.isAllowRefreshIndex"))){
CookieUtils.setCookie(response, "LOGINED", "false");
@@ -366,7 +369,7 @@ public class FormFilter extends org.apache.shiro.web.filter.authc.FormAuthentica
*/
public static Map<String, Object> getLoginFailureData(HttpServletRequest request, HttpServletResponse response) {
Map<String, Object> data = MapUtils.newHashMap();
String username = WebUtils.getCleanParam(request, DEFAULT_USERNAME_PARAM);
boolean rememberMe = WebUtils.isTrue(request, DEFAULT_REMEMBER_ME_PARAM);
boolean rememberUserCode = WebUtils.isTrue(request, REMEMBER_USERCODE_PARAM);
@@ -377,7 +380,7 @@ public class FormFilter extends org.apache.shiro.web.filter.authc.FormAuthentica
if (StringUtils.isNotBlank(secretKey)){
username = DesUtils.decode(username, secretKey);
}
data.put(DEFAULT_USERNAME_PARAM, username);
data.put(DEFAULT_REMEMBER_ME_PARAM, rememberMe);
data.put(REMEMBER_USERCODE_PARAM, rememberUserCode);
@@ -386,7 +389,7 @@ public class FormFilter extends org.apache.shiro.web.filter.authc.FormAuthentica
data.put(ServletUtils.EXT_PARAMS_PREFIX + entry.getKey(), entry.getValue());
}
data.put(MESSAGE_PARAM, message);
// 非授权异常,登录失败,验证码加 1。
if (!(exception instanceof UnauthorizedException)){
data.put("isValidCodeLogin", BaseAuthorizingRealm.isValidCodeLogin(username,
@@ -477,9 +480,9 @@ public class FormFilter extends org.apache.shiro.web.filter.authc.FormAuthentica
}
}
data.put("roleList", roleList);
List<Map<String, Object>> postList = ListUtils.newArrayList();
if (Global.getConfigToBoolean("user.postRolePermi", "false")
&& User.USER_TYPE_EMPLOYEE.equals(user.getUserType())) {
if (POST_ROLE_PERMI && User.USER_TYPE_EMPLOYEE.equals(user.getUserType())) {
List<Map<String, Object>> postList = ListUtils.newArrayList();
data.put("postRolePermi", "true");
Employee employee = user.getRefObj();
for (EmployeePost ep : EmpUtils.getEmployeePostList(employee.getEmpCode())){
Post post = ep.getPost();
@@ -490,8 +493,13 @@ public class FormFilter extends org.apache.shiro.web.filter.authc.FormAuthentica
postList.add(postMap);
}
}
data.put("postList", postList);
}
if (SWITCH_OFFICE && User.USER_TYPE_EMPLOYEE.equals(user.getUserType())) {
data.put("switchOffice", "true");
data.put("officeCode", EmpUtils.getCurrentOfficeCode());
data.put("officeName", EmpUtils.getCurrentOfficeName());
}
data.put("postList", postList);
data.put("desktopUrl", desktopUrl != null ? desktopUrl : Global.getConfig("sys.index.desktopUrl"));
return data;
}

View File

@@ -8,6 +8,7 @@ import com.alibaba.fastjson.JSONValidator;
import com.jeesite.common.codec.EncodeUtils;
import com.jeesite.common.collect.ListUtils;
import com.jeesite.common.collect.MapUtils;
import com.jeesite.common.collect.SetUtils;
import com.jeesite.common.config.Global;
import com.jeesite.common.entity.Page;
import com.jeesite.common.lang.DateUtils;
@@ -18,6 +19,7 @@ import com.jeesite.common.shiro.realm.AuthorizingRealm;
import com.jeesite.common.utils.excel.ExcelExport;
import com.jeesite.common.utils.excel.annotation.ExcelField.Type;
import com.jeesite.common.web.BaseController;
import com.jeesite.common.web.http.ServletUtils;
import com.jeesite.modules.sys.entity.*;
import com.jeesite.modules.sys.service.*;
import com.jeesite.modules.sys.utils.EmpUtils;
@@ -26,6 +28,7 @@ import com.jeesite.modules.sys.utils.UserUtils;
import io.swagger.annotations.Api;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -40,7 +43,8 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
/**
* 员工用户Controller
@@ -441,41 +445,89 @@ public class EmpUserController extends BaseController {
}
/**
* 获取当前用户附属部门
* @return
* 获取当前用户部门(包括附属部门) v5.10.1
*/
@RequiresPermissions("user")
@RequestMapping(value = "officeListData")
@ResponseBody
public List<EmployeeOffice> officeListData () {
Employee employee = EmpUtils.getEmployee();
return employeeService.findEmployeeOfficeList(employee);
public List<EmployeeOffice> officeListData() {
Office office = EmpUtils.getOffice();
EmployeeOffice employeeOffice = new EmployeeOffice();
employeeOffice.setOfficeCode(office.getOfficeCode());
employeeOffice.setViewCode(office.getViewCode());
employeeOffice.setOfficeName(office.getOfficeName());
employeeOffice.setFullName(office.getFullName());
employeeOffice.setTreeNames(office.getTreeNames());
List<EmployeeOffice> list = ListUtils.newArrayList(employeeOffice);
list.addAll(EmpUtils.getEmployeeOfficeList());
return list;
}
/**
* 切换当前用户到附属部门
* @param officeCode
* @return
* 切换部门菜单(用户->部门(含附属部门)->岗位->角色v5.10.1
*/
@RequiresPermissions("user")
@RequestMapping(value = "switchOffice/{officeCode}")
@ResponseBody
public String switchOffice(@PathVariable String officeCode) {
if (StringUtils.equals(officeCode, "default")) {
@RequestMapping(value = {"switchOffice","switchOffice/{officeCode}"})
public String switchOffice(@PathVariable(required=false) String officeCode, HttpServletRequest request, HttpServletResponse response) {
Session session = UserUtils.getSession();
Set<String> postCodes = SetUtils.newHashSet();
if (StringUtils.isNotBlank(officeCode)){
// 查询用户关联的岗位
AtomicReference<String> officeCodeRef = new AtomicReference<>();
AtomicReference<String> officeNameRef = new AtomicReference<>();
// 如果是当前用户主部门
Office office = EmpUtils.getOffice();
EmpUtils.setCurrentOffice(office.getOfficeCode(), office.getOfficeName());
return renderResult(Global.TRUE, text("部门切换成功!"));
}
List<EmployeeOffice> employeeOfficeList = EmpUtils.getEmployeeOfficeList().stream()
.filter(e -> StringUtils.equals(e.getOfficeCode(), officeCode)).collect(Collectors.toList());
if (!employeeOfficeList.isEmpty()) {
EmployeeOffice office = employeeOfficeList.get(0);
EmpUtils.setCurrentOffice(office.getOfficeCode(), office.getOfficeName());
return renderResult(Global.TRUE, text("部门切换成功!"));
if (StringUtils.equals(officeCode, office.getOfficeCode())) {
officeCodeRef.set(office.getOfficeCode());
officeNameRef.set(StringUtils.defaultIfBlank(office.getFullName(), office.getOfficeName()));
EmpUtils.getEmployeePostList().forEach(ep -> {
postCodes.add(ep.getPostCode());
});
}
// 如果是当前用户的附属部门
else {
EmpUtils.getEmployeeOfficeList().forEach(eo -> {
if (StringUtils.equals(officeCode, eo.getOfficeCode())) {
officeCodeRef.set(eo.getOfficeCode());
officeNameRef.set(StringUtils.defaultIfBlank(eo.getFullName(), eo.getOfficeName()));
postCodes.add(eo.getPostCode());
}
});
}
// 如果匹配不到,有权限切换的部门,则给于提示
if (StringUtils.isAnyBlank(officeCodeRef.get(), officeNameRef.get())) {
return renderResult(response, Global.FALSE, text("没有权限切换到该部门"));
}
EmpUtils.setCurrentOffice(session, officeCodeRef.get(), officeNameRef.get());
} else {
return renderResult(Global.FALSE, text("部门切换失败,所切换部门不是您的附属部门!"));
EmpUtils.removeCurrentOffice(session);
}
// 开启 user.postRolePermi 参数后,就可以使用岗位关联角色过滤菜单权限
if (Global.getConfigToBoolean("user.postRolePermi", "false")) {
if (!postCodes.isEmpty()) {
// 查询并设置岗位关联的角色
PostRole where = new PostRole();
where.setPostCode_in(postCodes.toArray(new String[0]));
where.sqlMap().loadJoinTableAlias("r");
List<String> roleCodes = ListUtils.newArrayList();
postService.findPostRoleList(where).forEach(e -> {
if (e.getRole() != null && PostRole.STATUS_NORMAL.equals(e.getRole().getStatus())) {
roleCodes.add(e.getRoleCode());
}
});
if (roleCodes.isEmpty()){
roleCodes.add("__none__");
}
session.setAttribute("roleCode", StringUtils.joinComma(roleCodes)); // 5.4.0+ 支持多个,逗号隔开
} else {
session.removeAttribute("roleCode");
}
}
UserUtils.removeCache(UserUtils.CACHE_AUTH_INFO+"_"+session.getId());
if (ServletUtils.isAjaxRequest(request)) {
return renderResult(response, Global.TRUE, text("部门切换成功"));
}
return REDIRECT + adminPath + "/index";
}
}

View File

@@ -153,8 +153,11 @@ user:
# 二级管理员的控制权限类型1拥有的权限 2管理的权限管理功能包括用户管理、组织机构、公司管理等v4.1.5+
adminCtrlPermi: 2
# 是否启用岗位角色,开启后将 用户->岗位->关联角色,纳入菜单和权限管理
# 是否启用岗位角色,开启后将 用户->岗位->关联角色,纳入菜单和权限管理 v5.9.2
postRolePermi: false
# 是否启用切换部门功能,再开启启用岗位角色后可支持 用户->附属部门->岗位->关联角色,纳入菜单和权限管理 v5.10.1
switchOffice: false
# 多租户模式SAAS模式专业版
useCorpModel: false

View File

@@ -10,6 +10,7 @@
<div class="navbar-custom-menu">
<ul class="nav navbar-nav">
<% include('/include/sysIndex/topMenuCorp.html'){} %>
<% include('/include/sysIndex/topMenuOffice.html'){} %>
<li><a href="javascript:" id="fullScreen" title="${text('全屏')}" data-placement="bottom" data-container="body"><i class="fa fa-arrows-alt"></i></a></li>
<li><a href="javascript:" id="switchSkin" title="${text('切换主题')}" style="margin-top:-1px;" data-placement="bottom" data-container="body" data-layer-width="600" data-layer-height="350"><i class="fa fa-dashboard"></i></a></li>
<% include('/include/sysIndex/topMenuLang.html'){} %>

View File

@@ -1,7 +1,7 @@
<% if(@Global.getConfigToBoolean('user.useCorpModel', 'false') && hasPermi('sys:corpAdmin:edit')){ %>
<li>
<a href="javascript:" id="switchCorp">
<i class="fa icon-home"></i> ${text('当前租户')}(${session.corpCode}) ${session.corpName}
<i class="fa icon-home"></i> ${text('当前租户')}${currentCorpName}
</a>
<div class="hide"><#form:treeselect id="switchCorpSelect" title="${text('租户切换')}" allowClear="false"
url="${ctx}/sys/corpAdmin/treeData?isShowCode=true" callbackFuncName="switchCorpSelectCallback"/>

View File

@@ -0,0 +1,27 @@
<% if(toBoolean(switchOffice!)){ %>
<li>
<a href="javascript:" id="switchOffice">
<i class="fa icon-grid" style="font-size:12px;"></i> ${officeName!}
</a>
<div class="hide"><#form:treeselect id="switchOfficeSelect" title="${text('部门切换')}" allowClear="false"
url="${ctx}/sys/empUser/officeListData?isShowCode=true" callbackFuncName="switchOfficeSelectCallback"
fieldNames="{'id':'officeCode','name':'fullName'}"/>
</div>
<script>
$('#switchOffice').click(function(){
$('#switchOfficeSelectButton').click();
});
function switchOfficeSelectCallback(id, act, index, layero, nodes){
if (act == 'ok'){
var officeCode = $('#switchOfficeSelectCode').val();
if (officeCode != ''){
js.ajaxSubmit("${ctx}/sys/empUser/switchOffice/"+officeCode, function(data){
js.showMessage(data.message);
js.window.location.reload();
});
}
}
}
</script>
</li>
<% } %>

View File

@@ -47,7 +47,7 @@
<% }else{ %>
<li class="mt10"></li>
<% } %>
<% if(postList.~size > 0){ %>
<% if(toBoolean(postRolePermi!) && postList.~size > 0){ %>
<li class="divider"></li>
<% var postCode = @ObjectUtils.toStringIgnoreNull(session.postCode, ''); %>
<li class="dropdown-header mb5">${text('选择岗位')}<% if(isNotBlank(postCode)){ %>

View File

@@ -347,8 +347,11 @@ user:
# # 二级管理员的控制权限类型1拥有的权限 2管理的权限管理功能包括用户管理、组织机构、公司管理等v4.1.5+
# adminCtrlPermi: 2
#
# # 是否启用岗位角色,开启后将 用户->岗位->关联角色,纳入菜单和权限管理
# # 是否启用岗位角色,开启后将 用户->岗位->关联角色,纳入菜单和权限管理 v5.9.2
# postRolePermi: false
#
# # 是否启用切换部门功能,再开启启用岗位角色后可支持 用户->附属部门->岗位->关联角色,纳入菜单和权限管理 v5.10.1
# switchOffice: false
# 多租户模式SAAS模式专业版
useCorpModel: false

View File

@@ -347,8 +347,11 @@ user:
# # 二级管理员的控制权限类型1拥有的权限 2管理的权限管理功能包括用户管理、组织机构、公司管理等v4.1.5+
# adminCtrlPermi: 2
#
# # 是否启用岗位角色,开启后将 用户->岗位->关联角色,纳入菜单和权限管理
# # 是否启用岗位角色,开启后将 用户->岗位->关联角色,纳入菜单和权限管理 v5.9.2
# postRolePermi: false
#
# # 是否启用切换部门功能,再开启启用岗位角色后可支持 用户->附属部门->岗位->关联角色,纳入菜单和权限管理 v5.10.1
# switchOffice: false
# 多租户模式SAAS模式专业版
useCorpModel: false