diff --git a/modules/core/src/main/java/com/jeesite/common/shiro/filter/FormFilter.java b/modules/core/src/main/java/com/jeesite/common/shiro/filter/FormFilter.java index 352ea8ec..dee5a9f6 100644 --- a/modules/core/src/main/java/com/jeesite/common/shiro/filter/FormFilter.java +++ b/modules/core/src/main/java/com/jeesite/common/shiro/filter/FormFilter.java @@ -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 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 getLoginData(HttpServletRequest request, HttpServletResponse response) { Map data = MapUtils.newHashMap(); - + // 获取登录参数 Map paramMap = ServletUtils.getExtParams(request); for (Entry 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 getLoginFailureData(HttpServletRequest request, HttpServletResponse response) { Map 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> 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> 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; } diff --git a/modules/core/src/main/java/com/jeesite/modules/sys/web/user/EmpUserController.java b/modules/core/src/main/java/com/jeesite/modules/sys/web/user/EmpUserController.java index 324cc838..68cabaf2 100644 --- a/modules/core/src/main/java/com/jeesite/modules/sys/web/user/EmpUserController.java +++ b/modules/core/src/main/java/com/jeesite/modules/sys/web/user/EmpUserController.java @@ -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 officeListData () { - Employee employee = EmpUtils.getEmployee(); - return employeeService.findEmployeeOfficeList(employee); + public List 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 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 postCodes = SetUtils.newHashSet(); + if (StringUtils.isNotBlank(officeCode)){ + // 查询用户关联的岗位 + AtomicReference officeCodeRef = new AtomicReference<>(); + AtomicReference officeNameRef = new AtomicReference<>(); + // 如果是当前用户主部门 Office office = EmpUtils.getOffice(); - EmpUtils.setCurrentOffice(office.getOfficeCode(), office.getOfficeName()); - return renderResult(Global.TRUE, text("部门切换成功!")); - } - List 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 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"; } } diff --git a/modules/core/src/main/resources/config/jeesite-core.yml b/modules/core/src/main/resources/config/jeesite-core.yml index 0586068c..81179cb3 100644 --- a/modules/core/src/main/resources/config/jeesite-core.yml +++ b/modules/core/src/main/resources/config/jeesite-core.yml @@ -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 diff --git a/modules/core/src/main/resources/views/include/sysIndex/topMenu.html b/modules/core/src/main/resources/views/include/sysIndex/topMenu.html index e112b0fa..305c2b64 100644 --- a/modules/core/src/main/resources/views/include/sysIndex/topMenu.html +++ b/modules/core/src/main/resources/views/include/sysIndex/topMenu.html @@ -10,6 +10,7 @@