package com.brframework.commoncms.utils; import com.brframework.commoncms.annatotion.AdminMenu; import com.brframework.commoncms.annatotion.Panel; import com.brframework.commoncms.annatotion.layout.ListLayout; import com.brframework.commoncms.annatotion.layout.PageLayout; import com.brframework.commoncms.annatotion.option.CmsOption; import com.brframework.commoncms.core.UriProtocol; import com.brframework.commoncms.core.permission.Menu; import com.brframework.commoncms.core.permission.Permission; import com.brframework.commoncms.core.uri.PanelUri; import com.brframework.commoncms.utils.ControllerUtil; import com.brframework.commonweb.core.SpringContext; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import org.apache.commons.lang3.StringUtils; import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Service; import java.lang.reflect.Method; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; /** * 用户-角色-菜单 * * @author xu * @date 2019/11/6 16:12 */ public class MenuPermissionUtils { private static List holdMenus; private static List holdPermissions; /** * 获取所有的功能列表 * * @return */ public static List getMenus() { if (holdMenus != null) { return holdMenus; } holdMenus = getBeanByAdminMenu().stream().map(bean -> { AdminMenu annotation = AnnotationUtils.findAnnotation(bean.getClass(), AdminMenu.class); assert annotation != null; List childrenMenus = Lists.newArrayList(bean.getClass().getMethods()).stream().filter(method -> //过滤没有AdminMenu注解的Method AnnotationUtils.findAnnotation(method, AdminMenu.class) != null ).map(method -> { //Method to Menu AdminMenu menuChildren = AnnotationUtils.findAnnotation(method, AdminMenu.class); assert menuChildren != null; PreAuthorize authAnn = AnnotationUtils.findAnnotation(method, PreAuthorize.class); String role = authAnn != null ? getRoleName(authAnn.value()) : null; String url = StringUtils.isEmpty(menuChildren.url()) ? getMenuUriByMethod(method) : menuChildren.url(); return Menu.builder() .role(role) .title(menuChildren.menuName()) .url(url) .order(menuChildren.order()) .build(); }).collect(Collectors.toList()); return Menu.builder() .title(annotation.menuName()) .icon(annotation.icon()) .order(annotation.order()) .children(childrenMenus.stream().sorted(Comparator.comparing(Menu::getOrder)).collect(Collectors.toList())) .build(); }).sorted(Comparator.comparing(Menu::getOrder)).collect(Collectors.toList()); return holdMenus; } /** * 获取系统中的所有权限 * @return */ public static List getPermissions() { if (holdPermissions != null) { return holdPermissions; } holdPermissions = getBeanByAdminMenu().stream().map(bean -> { AdminMenu annotation = AnnotationUtils.findAnnotation(bean.getClass(), AdminMenu.class); assert annotation != null; List methods = Lists.newArrayList(bean.getClass().getMethods()); List methodPermissions = methods.stream().filter(method -> //过滤没有AdminMenu注解的Method AnnotationUtils.findAnnotation(method, AdminMenu.class) != null ).map(method -> { //Method to Permission AdminMenu menuChildren = AnnotationUtils.findAnnotation(method, AdminMenu.class); assert menuChildren != null; List options = getOptionByMenuMethod(method); Map childrenPermissions = Maps.newHashMap(); //处理uriMappingMethod相关的Option options.stream().filter(o -> StringUtils.isNotBlank(o.uriMappingMethod())) .map(o -> methods.stream().filter(m -> m.getName().equals(o.uriMappingMethod())) .filter(m -> AnnotationUtils.findAnnotation(m, PreAuthorize.class) != null) .map(MenuPermissionUtils::preAuthorizeToPermission).collect(Collectors.toList())) .flatMap(Collection::stream) .filter(p -> !childrenPermissions.containsKey(p.getRole())) .forEach(p -> childrenPermissions.put(p.getRole(), p)); //处理roleMappingMethod相关的Option options.stream().filter(o -> StringUtils.isNotBlank(o.roleMappingMethod())) .map(o -> methods.stream().filter(m -> m.getName().equals(o.roleMappingMethod())) .filter(m -> AnnotationUtils.findAnnotation(m, PreAuthorize.class) != null) .map(MenuPermissionUtils::preAuthorizeToPermission).collect(Collectors.toList())) .flatMap(Collection::stream) .filter(p -> !childrenPermissions.containsKey(p.getRole())) .forEach(p -> childrenPermissions.put(p.getRole(), p)); //处理role相关的Option options.stream().filter(o -> StringUtils.isNotBlank(o.role())) .filter(o -> !childrenPermissions.containsKey(o.role())) .forEach(o -> childrenPermissions.put(o.role(), Permission.builder() .title(o.roleName()) .role(o.role()) .build())); PreAuthorize authAnn = AnnotationUtils.findAnnotation(method, PreAuthorize.class); if (authAnn != null) { String childrenTitle = ControllerUtil.getTitle(method); String childrenPermission = getRoleName(authAnn.value()); if (childrenPermissions.containsKey(childrenPermission)) { } else { childrenPermissions.put(childrenPermission, Permission.builder() .title(childrenTitle) .role(childrenPermission) .build()); } } return Permission.builder() .title(menuChildren.menuName()) .children(Lists.newArrayList(childrenPermissions.values())) .build(); }).collect(Collectors.toList()); return Permission.builder() .title(annotation.menuName()) .children(methodPermissions) .build(); }).collect(Collectors.toList()); return holdPermissions; } /** * 截取权限字符串 * * @param roleString * @return */ public static String getRoleName(String roleString) { return StringUtils.substring(roleString, roleString.indexOf("'") + 1, roleString.lastIndexOf("'")).trim(); } private static String getMenuUriByMethod(Method method) { PanelUri path = new PanelUri(); path.setMethod(ControllerUtil.getHttpMethod(method)); path.setUrl(ControllerUtil.getControllerUrl(method)); return UriProtocol.builder() .protocol(UriProtocol.PANEL) .path(path.toString()) .build().toString(); } private static List getBeanByAdminMenu() { Map beansWithAnnotation = SpringContext.getApplicationContext().getBeansWithAnnotation(AdminMenu.class); return Lists.newArrayList(beansWithAnnotation.values()); } private static List getOptionByMenuMethod(Method method) { //权限粒度到每一个option PageLayout pageLayout = AnnotatedElementUtils.findMergedAnnotation(method, PageLayout.class); ListLayout listLayout = AnnotatedElementUtils.findMergedAnnotation(method, ListLayout.class); List optionList = Lists.newArrayList(); if (pageLayout != null) { optionList.addAll(Lists.newArrayList(pageLayout.options())); optionList.addAll(Lists.newArrayList(pageLayout.columnOptions())); } else if (listLayout != null) { optionList.addAll(Lists.newArrayList(listLayout.options())); optionList.addAll(Lists.newArrayList(listLayout.columnOptions())); } return optionList; } private static Permission preAuthorizeToPermission(Method method) { PreAuthorize annotation = AnnotationUtils.findAnnotation(method, PreAuthorize.class); String childrenTitle = ControllerUtil.getTitle(method); String role = getRoleName(annotation.value()); return Permission.builder() .title(childrenTitle) .role(role) .build(); } }