浏览代码

重构权限

zhou-hao 5 年之前
父节点
当前提交
1e2ec16e6f
共有 78 个文件被更改,包括 1291 次插入1239 次删除
  1. 53 58
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/Authentication.java
  2. 3 3
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/AuthenticationPredicate.java
  3. 9 9
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/AuthenticationUtils.java
  4. 15 20
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/CompositeAuthentication.java
  5. 18 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/DefaultDimensionType.java
  6. 12 1
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/Dimension.java
  7. 8 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/DimensionType.java
  8. 11 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/Permission.java
  9. 12 2
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/Role.java
  10. 7 4
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/User.java
  11. 0 20
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/access/CustomDataAccessConfig.java
  12. 2 8
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/access/DataAccessConfig.java
  13. 9 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/access/DataAccessType.java
  14. 31 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/access/DefaultDataAccessType.java
  15. 0 23
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/access/FieldScopeDataAccessConfig.java
  16. 2 2
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/access/OwnCreatedDataAccessConfig.java
  17. 7 38
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/Authorize.java
  18. 17 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/CreateAction.java
  19. 18 17
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/RequiresExpression.java
  20. 23 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/DataAccessType.java
  21. 17 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/DeleteAction.java
  22. 20 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/Dimension.java
  23. 18 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/QueryAction.java
  24. 0 89
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/RequiresDataAccess.java
  25. 26 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/Resource.java
  26. 22 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/ResourceAction.java
  27. 17 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/SaveAction.java
  28. 16 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/UserOwnData.java
  29. 3 72
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/AuthorizeDefinition.java
  30. 15 12
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/DataAccessDefinition.java
  31. 18 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/DataAccessTypeDefinition.java
  32. 26 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/DimensionDefinition.java
  33. 46 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/DimensionsDefinition.java
  34. 18 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/ResourceActionDefinition.java
  35. 73 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/ResourceDefinition.java
  36. 79 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/ResourcesDefinition.java
  37. 0 26
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/Script.java
  38. 13 28
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleAuthentication.java
  39. 0 49
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleCustomDataAccessConfigConfig.java
  40. 29 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleDimension.java
  41. 4 2
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleFieldFilterDataAccessConfig.java
  42. 0 61
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleFiledScopeDataAccessConfig.java
  43. 14 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleRole.java
  44. 7 2
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleUser.java
  45. 4 6
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/builder/SimpleAuthenticationBuilder.java
  46. 1 9
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/builder/SimpleDataAccessConfigBuilderFactory.java
  47. 12 12
      hsweb-authorization/hsweb-authorization-api/src/test/java/org/hswebframework/web/authorization/AuthenticationTests.java
  48. 9 10
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/aop/AopAuthorizingController.java
  49. 10 58
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/aop/DefaultAopMethodAuthorizeDefinitionParser.java
  50. 156 67
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultBasicAuthorizeDefinition.java
  51. 0 26
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultDataAccessDefinition.java
  52. 0 38
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultScript.java
  53. 9 56
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/EmptyAuthorizeDefinition.java
  54. 2 3
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/embed/EmbedAuthenticationInfo.java
  55. 20 134
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/DefaultAuthorizingHandler.java
  56. 26 21
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/UserAllowPermissionHandler.java
  57. 0 44
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/access/CustomDataAccessHandler.java
  58. 2 3
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/access/DefaultDataAccessController.java
  59. 1 1
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/access/FieldFilterDataAccessHandler.java
  60. 0 143
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/access/FieldScopeDataAccessHandler.java
  61. 10 8
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/AuthorizationController.java
  62. 20 20
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/ReactiveUserTokenController.java
  63. 7 4
      hsweb-authorization/hsweb-authorization-basic/src/test/java/org/hswebframework/web/authorization/basic/aop/TestController.java
  64. 62 0
      hsweb-authorization/hsweb-authorization-basic/src/test/java/org/hswebframework/web/authorization/basic/define/DefaultBasicAuthorizeDefinitionTest.java
  65. 4 0
      hsweb-core/pom.xml
  66. 99 7
      hsweb-core/src/main/java/org/hswebframework/web/dict/EnumDict.java
  67. 3 1
      hsweb-core/src/main/java/org/hswebframework/web/exception/ValidationException.java
  68. 57 0
      hsweb-core/src/test/java/org/hswebframework/web/dict/EnumDictTest.java
  69. 19 0
      hsweb-core/src/test/java/org/hswebframework/web/dict/TestEnum.java
  70. 4 2
      hsweb-datasource/hsweb-datasource-web/src/main/java/org/hswebframework/web/datasource/web/DatasourceController.java
  71. 5 0
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml
  72. 5 2
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/PermissionDimension.java
  73. 0 4
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/PermissionDimensionProvider.java
  74. 2 10
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/UserPermissionDimensionProvider.java
  75. 1 1
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/configuration/AuthorizationServiceAutoConfiguration.java
  76. 1 1
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationInitializeService.java
  77. 1 1
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/webflux/WebFluxUserController.java
  78. 1 1
      pom.xml

+ 53 - 58
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/Authentication.java

@@ -21,6 +21,7 @@ import reactor.core.publisher.Mono;
 
 
 import java.io.Serializable;
 import java.io.Serializable;
 import java.util.*;
 import java.util.*;
+import java.util.stream.Collectors;
 
 
 /**
 /**
  * 用户授权信息,当前登录用户的权限信息,包括用户的基本信息,角色,权限集合等常用信息<br>
  * 用户授权信息,当前登录用户的权限信息,包括用户的基本信息,角色,权限集合等常用信息<br>
@@ -78,35 +79,63 @@ public interface Authentication extends Serializable {
     User getUser();
     User getUser();
 
 
     /**
     /**
-     * @return 用户持有的角色集合
+     * @return 用户所有维度
      */
      */
-    List<Role> getRoles();
-
-//    /**
-//     * @return 用户所有维度
-//     */
-//    List<Dimension> getDimensions();
+    List<Dimension> getDimensions();
 
 
     /**
     /**
      * @return 用户持有的权限集合
      * @return 用户持有的权限集合
      */
      */
     List<Permission> getPermissions();
     List<Permission> getPermissions();
 
 
-    /**
-     * 根据id获取角色,角色不存在则返回null
-     *
-     * @param id 角色id
-     * @return 角色信息
-     */
-    default Optional<Role> getRole(String id) {
-        if (null == id) {
-            return Optional.empty();
+
+    default boolean hasDimension(String type, String... id) {
+        return hasDimension(type, Arrays.asList(id));
+    }
+
+    default boolean hasDimension(String type, Collection<String> id) {
+        if (id.isEmpty()) {
+            return !getDimensions(type).isEmpty();
         }
         }
-        return getRoles().stream()
-                .filter(role -> role.getId().equals(id))
-                .findAny();
+        return getDimensions(type)
+                .stream()
+                .anyMatch(p -> id.contains(p.getId()));
+    }
+
+    default boolean hasDimension(DimensionType type, String id) {
+        return getDimension(type, id).isPresent();
+    }
+
+    default Optional<Dimension> getDimension(String type, String id) {
+        return getDimensions()
+                .stream()
+                .filter(dimension -> dimension.getId().equals(id) && type.equalsIgnoreCase(dimension.getType().getId()))
+                .findFirst();
+    }
+
+    default Optional<Dimension> getDimension(DimensionType type, String id) {
+        return getDimensions()
+                .stream()
+                .filter(dimension -> dimension.getId().equals(id) && type.isSameType(dimension.getType()))
+                .findFirst();
+    }
+
+
+    default List<Dimension> getDimensions(String type) {
+        return getDimensions()
+                .stream()
+                .filter(dimension -> dimension.getType().isSameType(type))
+                .collect(Collectors.toList());
+    }
+
+    default List<Dimension> getDimensions(DimensionType type) {
+        return getDimensions()
+                .stream()
+                .filter(dimension -> dimension.getType().isSameType(type))
+                .collect(Collectors.toList());
     }
     }
 
 
+
     /**
     /**
      * 根据权限id获取权限信息,权限不存在则返回null
      * 根据权限id获取权限信息,权限不存在则返回null
      *
      *
@@ -130,17 +159,13 @@ public interface Authentication extends Serializable {
      * @return 是否持有权限
      * @return 是否持有权限
      */
      */
     default boolean hasPermission(String permissionId, String... actions) {
     default boolean hasPermission(String permissionId, String... actions) {
-        return getPermission(permissionId)
-                .filter(permission -> actions.length == 0 || permission.getActions().containsAll(Arrays.asList(actions)))
-                .isPresent();
+        return hasPermission(permissionId, Arrays.asList(actions));
     }
     }
 
 
-    /**
-     * @param roleId 角色id {@link Role#getId()}
-     * @return 是否拥有某个角色
-     */
-    default boolean hasRole(String roleId) {
-        return getRole(roleId).isPresent();
+    default boolean hasPermission(String permissionId, Collection<String> actions) {
+        return getPermission(permissionId)
+                .filter(permission -> actions.isEmpty() || permission.getActions().containsAll(actions))
+                .isPresent();
     }
     }
 
 
     /**
     /**
@@ -154,36 +179,6 @@ public interface Authentication extends Serializable {
     <T extends Serializable> Optional<T> getAttribute(String name);
     <T extends Serializable> Optional<T> getAttribute(String name);
 
 
     /**
     /**
-     * 设置一个属性值,如果属性名称已经存在,则将其覆盖。<br>
-     * 注意:由于权限信息可能会被序列化,属性值必须实现{@link Serializable}接口
-     *
-     * @param name   属性名称
-     * @param object 属性值
-     * @see AuthenticationManager#sync(Authentication)
-     */
-    void setAttribute(String name, Serializable object);
-
-    /**
-     * 设置多个属性值,参数为map类型,key为属性名称,value为属性值
-     *
-     * @param attributes 属性值map
-     * @see AuthenticationManager#sync(Authentication)
-     */
-    void setAttributes(Map<String, Serializable> attributes);
-
-    /**
-     * 删除属性,并返回被删除的值
-     *
-     * @param name 属性名
-     * @param <T>  被删除的值类型
-     * @return 被删除的值
-     * @see AuthenticationManager#sync(Authentication)
-     */
-    <T extends Serializable> T removeAttributes(String name);
-
-    /**
-     * 获取全部属性,此属性为通过{@link this#setAttribute(String, Serializable)}或{@link this#setAttributes(Map)}设置的属性。
-     *
      * @return 全部属性集合
      * @return 全部属性集合
      */
      */
     Map<String, Serializable> getAttributes();
     Map<String, Serializable> getAttributes();

+ 3 - 3
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/AuthenticationPredicate.java

@@ -2,6 +2,7 @@ package org.hswebframework.web.authorization;
 
 
 import org.hswebframework.web.authorization.exception.AccessDenyException;
 import org.hswebframework.web.authorization.exception.AccessDenyException;
 
 
+import java.util.Arrays;
 import java.util.Objects;
 import java.util.Objects;
 import java.util.function.Predicate;
 import java.util.function.Predicate;
 
 
@@ -16,8 +17,8 @@ public interface AuthenticationPredicate extends Predicate<Authentication> {
         return AuthenticationUtils.createPredicate(permissionString);
         return AuthenticationUtils.createPredicate(permissionString);
     }
     }
 
 
-    static AuthenticationPredicate role(String role) {
-        return autz -> autz.hasRole(role);
+    static AuthenticationPredicate dimension(String dimension, String... id) {
+        return autz -> autz.hasDimension(dimension, Arrays.asList(id));
     }
     }
 
 
     static AuthenticationPredicate permission(String permissionId, String... actions) {
     static AuthenticationPredicate permission(String permissionId, String... actions) {
@@ -45,7 +46,6 @@ public interface AuthenticationPredicate extends Predicate<Authentication> {
     }
     }
 
 
 
 
-
     default void assertHas(Authentication authentication) {
     default void assertHas(Authentication authentication) {
         if (!test(authentication)) {
         if (!test(authentication)) {
             throw new AccessDenyException();
             throw new AccessDenyException();

+ 9 - 9
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/AuthenticationUtils.java

@@ -13,11 +13,11 @@ public class AuthenticationUtils {
             return (authentication -> false);
             return (authentication -> false);
         }
         }
         AuthenticationPredicate main = null;
         AuthenticationPredicate main = null;
-        // permission:user:add or update
+        // resource:user:add or update
         AuthenticationPredicate temp = null;
         AuthenticationPredicate temp = null;
         boolean lastAnd = true;
         boolean lastAnd = true;
         for (String conf : expression.split("[ ]")) {
         for (String conf : expression.split("[ ]")) {
-            if (conf.startsWith("permission:")) {
+            if (conf.startsWith("resource:")||conf.startsWith("permission:")) {
                 String[] permissionAndActions = conf.split("[:]", 2);
                 String[] permissionAndActions = conf.split("[:]", 2);
                 if (permissionAndActions.length < 2) {
                 if (permissionAndActions.length < 2) {
                     temp = authentication -> !authentication.getPermissions().isEmpty();
                     temp = authentication -> !authentication.getPermissions().isEmpty();
@@ -27,19 +27,19 @@ public class AuthenticationUtils {
                             AuthenticationPredicate.permission(real[0], real[1].split("[,]"))
                             AuthenticationPredicate.permission(real[0], real[1].split("[,]"))
                             : AuthenticationPredicate.permission(real[0]);
                             : AuthenticationPredicate.permission(real[0]);
                 }
                 }
-            } else if (conf.startsWith("role")) {
-                String[] real = conf.split("[:]", 2);
-                if (real.length < 2) {
-                    temp = authentication -> !authentication.getRoles().isEmpty();
-                } else {
-                    temp = AuthenticationPredicate.role(real[1]);
-                }
             } else if (main != null && conf.equalsIgnoreCase("and")) {
             } else if (main != null && conf.equalsIgnoreCase("and")) {
                 lastAnd = true;
                 lastAnd = true;
                 main = main.and(temp);
                 main = main.and(temp);
             } else if (main != null && conf.equalsIgnoreCase("or")) {
             } else if (main != null && conf.equalsIgnoreCase("or")) {
                 main = main.or(temp);
                 main = main.or(temp);
                 lastAnd = false;
                 lastAnd = false;
+            } else {
+                String[] real = conf.split("[:]", 2);
+                if (real.length < 2) {
+                    temp = AuthenticationPredicate.dimension(real[0]);
+                } else {
+                    temp = AuthenticationPredicate.dimension(real[0], real[1].split(","));
+                }
             }
             }
             if (main == null) {
             if (main == null) {
                 main = temp;
                 main = temp;

+ 15 - 20
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/CompositeAuthentication.java

@@ -1,10 +1,7 @@
 package org.hswebframework.web.authorization;
 package org.hswebframework.web.authorization;
 
 
 import java.io.Serializable;
 import java.io.Serializable;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
+import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.Function;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
@@ -31,6 +28,15 @@ public class CompositeAuthentication implements Authentication {
                 .getUser();
                 .getUser();
     }
     }
 
 
+    @Override
+    public List<Dimension> getDimensions() {
+        return userAuthentication.values()
+                .stream()
+                .map(Authentication::getDimensions)
+                .flatMap(Collection::stream)
+                .collect(Collectors.toList());
+    }
+
     @Override
     @Override
     public List<Role> getRoles() {
     public List<Role> getRoles() {
         return userAuthentication.values()
         return userAuthentication.values()
@@ -59,24 +65,13 @@ public class CompositeAuthentication implements Authentication {
                 .flatMap(Function.identity());
                 .flatMap(Function.identity());
     }
     }
 
 
-    @Override
-    public void setAttribute(String name, Serializable object) {
-
-    }
-
-    @Override
-    public void setAttributes(Map<String, Serializable> attributes) {
-
-    }
-
-    @Override
-    public <T extends Serializable> T removeAttributes(String name) {
-        return null;
-    }
-
     @Override
     @Override
     public Map<String, Serializable> getAttributes() {
     public Map<String, Serializable> getAttributes() {
-        return null;
+        return userAuthentication.values()
+                .stream()
+                .map(Authentication::getAttributes)
+                .filter(Objects::nonNull)
+                .reduce(new HashMap<>(),(r,s)->{r.putAll(s);return r;});
     }
     }
 
 
     public CompositeAuthentication merge(Authentication authentication) {
     public CompositeAuthentication merge(Authentication authentication) {

+ 18 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/DefaultDimensionType.java

@@ -0,0 +1,18 @@
+package org.hswebframework.web.authorization;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum DefaultDimensionType implements DimensionType {
+    user("用户"),
+    role("角色");
+
+    private String name;
+
+    @Override
+    public String getId() {
+        return name();
+    }
+}

+ 12 - 1
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/Dimension.java

@@ -1,10 +1,21 @@
 package org.hswebframework.web.authorization;
 package org.hswebframework.web.authorization;
 
 
-public interface Dimension {
+import java.io.Serializable;
+import java.util.Map;
+import java.util.Optional;
+
+public interface Dimension extends Serializable {
     String getId();
     String getId();
 
 
     String getName();
     String getName();
 
 
     DimensionType getType();
     DimensionType getType();
 
 
+    Map<String, Object> getOptions();
+
+    default <T> Optional<T> getOption(String key) {
+        return Optional.ofNullable(getOptions())
+                .map(ops -> ops.get(key))
+                .map(o -> (T) o);
+    }
 }
 }

+ 8 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/DimensionType.java

@@ -4,4 +4,12 @@ public interface DimensionType {
     String getId();
     String getId();
 
 
     String getName();
     String getName();
+
+    default boolean isSameType(DimensionType another) {
+        return this == another || isSameType(another.getId());
+    }
+
+    default boolean isSameType(String anotherId) {
+        return this.getId().equals(anotherId);
+    }
 }
 }

+ 11 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/Permission.java

@@ -28,6 +28,7 @@ import java.util.Objects;
 import java.util.Optional;
 import java.util.Optional;
 import java.util.Set;
 import java.util.Set;
 import java.util.function.Predicate;
 import java.util.function.Predicate;
+import java.util.stream.Collectors;
 
 
 import static org.hswebframework.web.authorization.access.DataAccessConfig.DefaultType.DENY_FIELDS;
 import static org.hswebframework.web.authorization.access.DataAccessConfig.DefaultType.DENY_FIELDS;
 
 
@@ -52,6 +53,10 @@ public interface Permission extends Serializable {
      * 新增
      * 新增
      */
      */
     String ACTION_ADD = "add";
     String ACTION_ADD = "add";
+    /**
+     * 保存
+     */
+    String ACTION_SAVE = "save";
     /**
     /**
      * 更新
      * 更新
      */
      */
@@ -108,6 +113,12 @@ public interface Permission extends Serializable {
     Set<DataAccessConfig> getDataAccesses();
     Set<DataAccessConfig> getDataAccesses();
 
 
 
 
+    default  Set<DataAccessConfig> getDataAccesses(String action){
+        return getDataAccesses()
+                .stream()
+                .filter(conf->conf.getAction().equals(action))
+                .collect(Collectors.toSet());
+    }
     /**
     /**
      * 查找数据权限配置
      * 查找数据权限配置
      *
      *

+ 12 - 2
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/Role.java

@@ -17,7 +17,8 @@
 
 
 package org.hswebframework.web.authorization;
 package org.hswebframework.web.authorization;
 
 
-import java.io.Serializable;
+
+import org.hswebframework.web.authorization.simple.SimpleRole;
 
 
 /**
 /**
  * 角色信息
  * 角色信息
@@ -25,7 +26,7 @@ import java.io.Serializable;
  * @author zhouhao
  * @author zhouhao
  * @since 3.0
  * @since 3.0
  */
  */
-public interface Role extends Serializable {
+public interface Role extends Dimension {
 
 
     /**
     /**
      * @return 角色ID
      * @return 角色ID
@@ -36,4 +37,13 @@ public interface Role extends Serializable {
      * @return 角色名
      * @return 角色名
      */
      */
     String getName();
     String getName();
+
+    @Override
+    default DimensionType getType() {
+        return DefaultDimensionType.role;
+    }
+
+    static Role fromDimension(Dimension dimension){
+        return SimpleRole.of(dimension);
+    }
 }
 }

+ 7 - 4
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/User.java

@@ -17,15 +17,13 @@
 
 
 package org.hswebframework.web.authorization;
 package org.hswebframework.web.authorization;
 
 
-import java.io.Serializable;
-
 /**
 /**
  * 用户信息
  * 用户信息
  *
  *
  * @author zhouhao
  * @author zhouhao
  * @since 3.0
  * @since 3.0
  */
  */
-public interface User extends Serializable {
+public interface User extends Dimension {
     /**
     /**
      * @return 用户ID
      * @return 用户ID
      */
      */
@@ -44,5 +42,10 @@ public interface User extends Serializable {
     /**
     /**
      * @return 用户类型
      * @return 用户类型
      */
      */
-    String getType();
+    String getUserType();
+
+    @Override
+    default DimensionType getType() {
+        return DefaultDimensionType.user;
+    }
 }
 }

+ 0 - 20
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/access/CustomDataAccessConfig.java

@@ -1,20 +0,0 @@
-package org.hswebframework.web.authorization.access;
-
-/**
- * 自定义控制器的数据级权限控制器
- *
- * @author zhouhao
- * @see DefaultType#CUSTOM
- */
-public interface CustomDataAccessConfig extends DataAccessConfig {
-
-    /**
-     * @return 自定义的控制器
-     */
-    DataAccessController getController();
-
-    @Override
-    default String getType() {
-        return DefaultType.CUSTOM;
-    }
-}

+ 2 - 8
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/access/DataAccessConfig.java

@@ -28,7 +28,6 @@ import java.io.Serializable;
  * 具体的控制逻辑由控制器{@link DataAccessController}实现
  * 具体的控制逻辑由控制器{@link DataAccessController}实现
  *
  *
  * @author zhouhao
  * @author zhouhao
- * @see CustomDataAccessConfig
  * @see OwnCreatedDataAccessConfig
  * @see OwnCreatedDataAccessConfig
  */
  */
 public interface DataAccessConfig extends Serializable {
 public interface DataAccessConfig extends Serializable {
@@ -51,7 +50,7 @@ public interface DataAccessConfig extends Serializable {
      * @return 控制方式
      * @return 控制方式
      * @see DefaultType
      * @see DefaultType
      */
      */
-    String getType();
+    DataAccessType getType();
 
 
     /**
     /**
      * 内置的控制方式
      * 内置的控制方式
@@ -77,11 +76,6 @@ public interface DataAccessConfig extends Serializable {
          */
          */
         String DENY_FIELDS = "DENY_FIELDS";
         String DENY_FIELDS = "DENY_FIELDS";
 
 
-        /**
-         * 自定义控制器
-         *
-         * @see CustomDataAccessConfig#getType()
-         */
-        String CUSTOM = "CUSTOM";
+
     }
     }
 }
 }

+ 9 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/access/DataAccessType.java

@@ -0,0 +1,9 @@
+package org.hswebframework.web.authorization.access;
+
+public interface DataAccessType {
+
+    String getId();
+
+    String getName();
+
+}

+ 31 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/access/DefaultDataAccessType.java

@@ -0,0 +1,31 @@
+package org.hswebframework.web.authorization.access;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.hswebframework.web.dict.EnumDict;
+
+@Getter
+@AllArgsConstructor
+public enum DefaultDataAccessType implements DataAccessType, EnumDict<String> {
+    USER_OWN_DATA("自己的数据"),
+    FIELD_DENY("禁止操作字段"),
+    DIMENSION_SCOPE("维度范围");
+
+    private final String name;
+
+    @Override
+    public String getText() {
+        return name;
+    }
+
+    @Override
+    public String getValue() {
+        return getId();
+    }
+
+    @Override
+    public String getId() {
+        return name().toLowerCase();
+    }
+
+}

+ 0 - 23
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/access/FieldScopeDataAccessConfig.java

@@ -1,23 +0,0 @@
-package org.hswebframework.web.authorization.access;
-
-
-import static org.hswebframework.web.authorization.access.DataAccessConfig.DefaultType.FIELD_SCOPE;
-
-/**
- * 范围数据权限控制配置,控制某个字段的值在范围内
- *
- * @author zhouhao
- * @see ScopeDataAccessConfig
- * @since 3.0
- */
-public interface FieldScopeDataAccessConfig extends ScopeDataAccessConfig {
-    /**
-     * @return 字段信息
-     */
-    String getField();
-
-    @Override
-    default String getType() {
-        return FIELD_SCOPE;
-    }
-}

+ 2 - 2
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/access/OwnCreatedDataAccessConfig.java

@@ -7,7 +7,7 @@ package org.hswebframework.web.authorization.access;
  */
  */
 public interface OwnCreatedDataAccessConfig extends DataAccessConfig {
 public interface OwnCreatedDataAccessConfig extends DataAccessConfig {
     @Override
     @Override
-    default String getType() {
-        return DefaultType.OWN_CREATED;
+    default DataAccessType getType() {
+        return DefaultDataAccessType.USER_OWN_DATA;
     }
     }
 }
 }

+ 7 - 38
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/Authorize.java

@@ -18,9 +18,6 @@
 
 
 package org.hswebframework.web.authorization.annotation;
 package org.hswebframework.web.authorization.annotation;
 
 
-import org.hswebframework.web.authorization.Permission;
-import org.hswebframework.web.authorization.Role;
-import org.hswebframework.web.authorization.User;
 import org.hswebframework.web.authorization.define.Phased;
 import org.hswebframework.web.authorization.define.Phased;
 
 
 import java.lang.annotation.*;
 import java.lang.annotation.*;
@@ -31,6 +28,10 @@ import java.lang.annotation.*;
  * @author zhouhao
  * @author zhouhao
  * @see org.hswebframework.web.authorization.Authentication
  * @see org.hswebframework.web.authorization.Authentication
  * @see org.hswebframework.web.authorization.define.AuthorizeDefinition
  * @see org.hswebframework.web.authorization.define.AuthorizeDefinition
+ * @see Resource
+ * @see ResourceAction
+ * @see Dimension
+ * @see DataAccess
  * @since 3.0
  * @since 3.0
  */
  */
 @Target({ElementType.TYPE, ElementType.METHOD})
 @Target({ElementType.TYPE, ElementType.METHOD})
@@ -39,44 +40,16 @@ import java.lang.annotation.*;
 @Documented
 @Documented
 public @interface Authorize {
 public @interface Authorize {
 
 
-    /**
-     * 对角色授权,当使用按角色授权时,对模块以及操作级别授权方式失效
-     *
-     * @return 进 role id array
-     * @see Role#getId()
-     */
-    String[] role() default {};
-
-    /**
-     * 对模块授权
-     *
-     * @return permission id array
-     * @see Permission#getId()
-     */
-    String[] permission() default {};
-
-    /**
-     * 如增删改查等
-     *
-     * @return action array
-     * @see Permission#getActions()
-     */
-    String[] action() default {};
+    Resource[] resources() default {};
 
 
-    /**
-     * 验证是否为指定user
-     *
-     * @return username array
-     * @see User#getUsername()
-     */
-    String[] user() default {};
+    Dimension[] dimension() default {};
 
 
     /**
     /**
      * 验证失败时返回的消息
      * 验证失败时返回的消息
      *
      *
      * @return 验证失败提示的消息
      * @return 验证失败提示的消息
      */
      */
-    String message() default "无权限";
+    String message() default "无访问权限";
 
 
     /**
     /**
      * 是否合并类上的注解
      * 是否合并类上的注解
@@ -102,10 +75,6 @@ public @interface Authorize {
      */
      */
     boolean ignore() default false;
     boolean ignore() default false;
 
 
-    /**
-     * @return 数据权限控制
-     */
-    RequiresDataAccess dataAccess() default @RequiresDataAccess(ignore = true);
 
 
     String[] description() default {};
     String[] description() default {};
 }
 }

+ 17 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/CreateAction.java

@@ -0,0 +1,17 @@
+package org.hswebframework.web.authorization.annotation;
+
+import org.hswebframework.web.authorization.Permission;
+import org.springframework.core.annotation.AliasFor;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+@Documented
+@ResourceAction(id = Permission.ACTION_ADD, name = "新增")
+public @interface CreateAction {
+
+    @AliasFor(annotation = ResourceAction.class,attribute = "dataAccess")
+    DataAccess dataAccess() default @DataAccess(ignore = true);
+}

+ 18 - 17
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/RequiresExpression.java

@@ -17,36 +17,37 @@
 
 
 package org.hswebframework.web.authorization.annotation;
 package org.hswebframework.web.authorization.annotation;
 
 
+import org.hswebframework.web.authorization.access.DataAccessController;
+
 import java.lang.annotation.*;
 import java.lang.annotation.*;
 
 
 /**
 /**
- * 使用表达式进行验证,默认支持spel,ognl表达式。
+ * 数据级权限控制注解,用于进行需要数据级别权限控制的声明.
+ * <p>
+ * 此注解仅用于声明此方法需要进行数据级权限控制,具体权限控制方式由控制器实{@link DataAccessController}现
+ * </p>
  *
  *
  * @author zhouhao
  * @author zhouhao
+ * @see DataAccessController
+ * @see Authorize#dataAccess()
  * @since 3.0
  * @since 3.0
  */
  */
-@Target({ElementType.TYPE, ElementType.METHOD})
+@Target({ElementType.ANNOTATION_TYPE,ElementType.METHOD})
 @Retention(RetentionPolicy.RUNTIME)
 @Retention(RetentionPolicy.RUNTIME)
 @Documented
 @Documented
-public @interface RequiresExpression {
+public @interface DataAccess {
+
+    DataAccessType[] type() default {};
 
 
     /**
     /**
-     * 表达式内容,表达式可以调用方法的参数值以及当前的用户信息和spring管理的bean
-     * 例如:
-     * <pre>
-     * &#064;RequestMapping
-     * &#064;RequiresExpression("#param!=null")
-     * public ResponseMessage requestHandle(String param){
-     *  return ok();
-     * }
-     * </pre>
-     *
-     * @return 表达式
+     * @return logical
      */
      */
-    String value();
+    Logical logical() default Logical.AND;
 
 
     /**
     /**
-     * @return 表达式语言 ,支持spel,ognl,groovy,javascript
+     * @return 是否忽略, 忽略后将不进行权限控制
      */
      */
-    String language() default "spel";
+    boolean ignore() default false;
+
+
 }
 }

+ 23 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/DataAccessType.java

@@ -0,0 +1,23 @@
+package org.hswebframework.web.authorization.annotation;
+
+import org.hswebframework.web.authorization.access.DataAccessController;
+
+import java.lang.annotation.*;
+
+@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+@Documented
+public @interface DataAccessType {
+
+    String id(); //标识
+
+    String name(); //名称
+
+    String[] description() default {};
+
+    /**
+     * @see DataAccessController
+     */
+    Class<? extends DataAccessController> controller() default  DataAccessController.class;
+}

+ 17 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/DeleteAction.java

@@ -0,0 +1,17 @@
+package org.hswebframework.web.authorization.annotation;
+
+import org.hswebframework.web.authorization.Permission;
+import org.springframework.core.annotation.AliasFor;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+@Documented
+@ResourceAction(id = Permission.ACTION_DELETE, name = "删除")
+public @interface DeleteAction {
+
+    @AliasFor(annotation = ResourceAction.class,attribute = "dataAccess")
+    DataAccess dataAccess() default @DataAccess(ignore = true);
+}

+ 20 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/Dimension.java

@@ -0,0 +1,20 @@
+package org.hswebframework.web.authorization.annotation;
+
+import java.lang.annotation.*;
+
+@Target({ElementType.ANNOTATION_TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+@Documented
+public @interface Dimension {
+
+    String type();
+
+    String[] id() default {};
+
+    Logical logical() default Logical.DEFAULT;
+
+    String[] description() default {};
+
+    boolean ignore() default false;
+}

+ 18 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/QueryAction.java

@@ -0,0 +1,18 @@
+package org.hswebframework.web.authorization.annotation;
+
+import org.hswebframework.web.authorization.Permission;
+import org.springframework.core.annotation.AliasFor;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+@Documented
+@ResourceAction(id = Permission.ACTION_QUERY, name = "查询")
+public @interface QueryAction {
+
+    @AliasFor(annotation = ResourceAction.class,attribute = "dataAccess")
+    DataAccess dataAccess() default @DataAccess(ignore = true);
+
+}

+ 0 - 89
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/RequiresDataAccess.java

@@ -1,89 +0,0 @@
-/*
- * Copyright 2019 http://www.hswebframework.org
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- */
-
-package org.hswebframework.web.authorization.annotation;
-
-import org.hswebframework.web.authorization.access.DataAccessConfig;
-import org.hswebframework.web.authorization.access.DataAccessController;
-import org.hswebframework.web.authorization.Permission;
-import org.hswebframework.web.authorization.define.Phased;
-
-import java.lang.annotation.*;
-
-/**
- * 数据级权限控制注解,用于进行需要数据级别权限控制的声明.
- * <p>
- * 此注解仅用于声明此方法需要进行数据级权限控制,具体权限控制方式由控制器实{@link DataAccessController}现
- * </p>
- *
- * @author zhouhao
- * @see DataAccessController
- * @see Authorize#dataAccess()
- * @since 3.0
- */
-@Target({ElementType.TYPE, ElementType.METHOD})
-@Retention(RetentionPolicy.RUNTIME)
-@Documented
-public @interface RequiresDataAccess {
-
-    /**
-     * @return permission id ,如果为空将继承 {@link Authorize#permission()}
-     * @see Permission#getId()
-     */
-    String permission() default "";
-
-    /**
-     * @return action array ,如果为空将继承 {@link Authorize#action()}
-     * @see DataAccessConfig#getAction()
-     */
-    String[] action() default {};
-
-    String[] supportType() default {};
-
-    /**
-     * @return logical
-     */
-    Logical logical() default Logical.AND;
-
-    /**
-     * @return 自定义控制器bean名称
-     */
-    String controllerBeanName() default "";
-
-    /**
-     * @return 自定义控制器类型
-     */
-    Class<DataAccessController> controllerClass() default DataAccessController.class;
-
-    Phased phased() default Phased.before;
-
-    /**
-     * @return id参数名称
-     */
-    String idParamName() default "id";
-
-    /**
-     * @return 是否忽略, 忽略后将不进行权限控制
-     */
-    boolean ignore() default false;
-
-    /**
-     * @return 进行控制的实体类类型
-     * @since 3.0.6
-     */
-    Class entityType() default Void.class;
-}

+ 26 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/Resource.java

@@ -0,0 +1,26 @@
+package org.hswebframework.web.authorization.annotation;
+
+
+import org.hswebframework.web.authorization.define.Phased;
+
+import java.lang.annotation.*;
+
+@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+@Documented
+public @interface Resource {
+    String id();
+
+    String name();
+
+    ResourceAction[] actions() default {};
+
+    Logical logical() default Logical.DEFAULT;
+
+    Phased phased() default Phased.before;
+
+    String[] description() default {};
+
+    boolean merge() default true;
+}

+ 22 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/ResourceAction.java

@@ -0,0 +1,22 @@
+package org.hswebframework.web.authorization.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * @see CreateAction
+ */
+@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+@Documented
+public @interface ResourceAction {
+    String id();
+
+    String name();
+
+    String[] description() default {};
+
+    Logical logical() default Logical.DEFAULT;
+
+    DataAccess[] dataAccess() default @DataAccess(ignore = true);
+}

+ 17 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/SaveAction.java

@@ -0,0 +1,17 @@
+package org.hswebframework.web.authorization.annotation;
+
+import org.hswebframework.web.authorization.Permission;
+import org.springframework.core.annotation.AliasFor;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+@Documented
+@ResourceAction(id = Permission.ACTION_SAVE, name = "保存")
+public @interface SaveAction {
+
+    @AliasFor(annotation = ResourceAction.class,attribute = "dataAccess")
+    DataAccess dataAccess() default @DataAccess(ignore = true);
+}

+ 16 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/UserOwnData.java

@@ -0,0 +1,16 @@
+package org.hswebframework.web.authorization.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 声明某个操作支持用户查看自己的数据
+ */
+@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+@Documented
+@DataAccess
+@DataAccessType(id = "user_own_data", name = "用户自己的数据")
+public @interface UserOwnData {
+
+}

+ 3 - 72
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/AuthorizeDefinition.java

@@ -1,11 +1,5 @@
 package org.hswebframework.web.authorization.define;
 package org.hswebframework.web.authorization.define;
 
 
-import org.hswebframework.web.authorization.Permission;
-import org.hswebframework.web.authorization.Role;
-import org.hswebframework.web.authorization.User;
-import org.hswebframework.web.authorization.annotation.Logical;
-
-import java.util.Set;
 
 
 /**
 /**
  * 权限控制定义,定义权限控制的方式
  * 权限控制定义,定义权限控制的方式
@@ -15,76 +9,13 @@ import java.util.Set;
  */
  */
 public interface AuthorizeDefinition {
 public interface AuthorizeDefinition {
 
 
-    /**
-     * @return 验证时机
-     */
-    Phased getPhased();
-
-    /**
-     * 优先级,如果获取到多个权限控制定义是,则先判断优先级高的
-     *
-     * @return 优先级
-     */
-    int getPriority();
-
-    /**
-     * @return 是否进行数据权限控制
-     * @see org.hswebframework.web.authorization.access.DataAccessController
-     */
-    boolean isDataAccessControl();
-
-    /**
-     * @return 要控制的权限
-     */
-    Set<String> getPermissions();
-
-    String[] getPermissionDescription();
+    ResourcesDefinition getResources();
 
 
-    String[] getActionDescription();
+    DimensionsDefinition getDimensions();
 
 
-    /**
-     * 要控制的权限事件,仅当{@link this#getPermissions()}不为空的时候生效
-     *
-     * @return 权限事件
-     * @see Permission#getActions()
-     */
-    Set<String> getActions();
-
-    /**
-     * 控制角色访问
-     *
-     * @return 要控制的角色id集合
-     * @see Role#getId()
-     * @see org.hswebframework.web.authorization.Authentication#hasRole(String)
-     */
-    Set<String> getRoles();
-
-    /**
-     * 控制用户访问
-     *
-     * @return 要控制的用户id集合
-     * @see User#getId()
-     */
-    Set<String> getUser();
-
-    /**
-     * 使用脚本进行控制
-     *
-     * @return 脚本
-     */
-    Script getScript();
-
-    /**
-     * @return 当无权限时, 返回的消息
-     */
     String getMessage();
     String getMessage();
 
 
-    /**
-     * @return 当存在多个配置, 如:配置了多个permission或者actions. 进行判断的逻辑(或者,并且)
-     */
-    Logical getLogical();
+    Phased getPhased();
 
 
     boolean isEmpty();
     boolean isEmpty();
-
-    DataAccessDefinition getDataAccessDefinition();
 }
 }

+ 15 - 12
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/DataAccessDefinition.java

@@ -1,20 +1,23 @@
 package org.hswebframework.web.authorization.define;
 package org.hswebframework.web.authorization.define;
 
 
+import lombok.Getter;
+import lombok.Setter;
 
 
-import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
 
 
-/**
- * @author zhouhao
- * @see org.hswebframework.web.authorization.annotation.RequiresDataAccess
- */
-public interface DataAccessDefinition extends Serializable {
+@Getter
+@Setter
+public class DataAccessDefinition {
 
 
-    String getController();
+    List<DataAccessTypeDefinition> dataAccessTypes=new ArrayList<>();
 
 
-    String getIdParameterName();
-
-    Class getEntityType();
-
-    Phased getPhased();
 
 
+    public Optional<DataAccessTypeDefinition> getType(String typeId){
+        return dataAccessTypes
+                .stream()
+                .filter(datd->datd.getId().equalsIgnoreCase(typeId))
+                .findAny();
+    }
 }
 }

+ 18 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/DataAccessTypeDefinition.java

@@ -0,0 +1,18 @@
+package org.hswebframework.web.authorization.define;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.hswebframework.web.authorization.access.DataAccessController;
+import org.hswebframework.web.authorization.access.DataAccessType;
+
+@Getter
+@Setter
+public class DataAccessTypeDefinition implements DataAccessType {
+    private String id;
+
+    private String name;
+
+    private String description;
+
+    private Class<? extends DataAccessController> controller;
+}

+ 26 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/DimensionDefinition.java

@@ -0,0 +1,26 @@
+package org.hswebframework.web.authorization.define;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.hswebframework.web.authorization.DimensionType;
+import org.hswebframework.web.authorization.annotation.Logical;
+
+import java.util.HashSet;
+import java.util.Set;
+
+@Getter
+@Setter
+public class DimensionDefinition {
+
+    private String typeId;
+
+    private String typeName;
+
+    private Set<String> dimensionId=new HashSet<>();
+
+    private Logical logical=Logical.DEFAULT;
+
+    public boolean hasDimension(String id){
+        return dimensionId.contains(id);
+    }
+}

+ 46 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/DimensionsDefinition.java

@@ -0,0 +1,46 @@
+package org.hswebframework.web.authorization.define;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.commons.collections.CollectionUtils;
+import org.hswebframework.web.authorization.Dimension;
+import org.hswebframework.web.authorization.annotation.Logical;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Getter
+@Setter
+public class DimensionsDefinition {
+
+    private List<DimensionDefinition> dimensions = new ArrayList<>();
+
+    private Logical logical = Logical.DEFAULT;
+
+    public void addDimension(DimensionDefinition definition) {
+        dimensions.add(definition);
+    }
+
+    public boolean hasDimension(Dimension dimension) {
+        return dimensions
+                .stream()
+                .anyMatch(def ->
+                        def.getTypeId().equals(dimension.getType().getId())
+                                && def.hasDimension(dimension.getId()));
+    }
+
+    public boolean hasDimension(List<Dimension> dimensions) {
+
+        if (CollectionUtils.isEmpty(this.dimensions)) {
+            return true;
+        }
+        if (CollectionUtils.isEmpty(this.dimensions)) {
+            return false;
+        }
+        if (logical == Logical.AND) {
+            return dimensions.stream().allMatch(this::hasDimension);
+        }
+
+        return dimensions.stream().anyMatch(this::hasDimension);
+    }
+}

+ 18 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/ResourceActionDefinition.java

@@ -0,0 +1,18 @@
+package org.hswebframework.web.authorization.define;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+@Getter
+@Setter
+public class ResourceActionDefinition {
+    private String id;
+
+    private String name;
+
+    private String description;
+
+    private DataAccessDefinition dataAccess = new DataAccessDefinition();
+}

+ 73 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/ResourceDefinition.java

@@ -0,0 +1,73 @@
+package org.hswebframework.web.authorization.define;
+
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.commons.collections.CollectionUtils;
+import org.hswebframework.web.authorization.annotation.Logical;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Getter
+@Setter
+public class ResourceDefinition {
+    private String id;
+
+    private String name;
+
+    private String description;
+
+    private List<ResourceActionDefinition> actions=new ArrayList<>();
+
+    @Setter(value = AccessLevel.PRIVATE)
+    private volatile Set<String> actionIds;
+
+    private Logical logical = Logical.DEFAULT;
+
+    public void addAction(ResourceActionDefinition action){
+        actions.add(action);
+    }
+
+    public Optional<ResourceActionDefinition> getAction(String action){
+        return actions.stream()
+                .filter(act->act.getId().equalsIgnoreCase(action))
+                .findAny();
+    }
+
+    public Set<String> getActionIds() {
+        if (actionIds == null) {
+            actionIds = this.actions
+                    .stream()
+                    .map(ResourceActionDefinition::getId)
+                    .collect(Collectors.toSet());
+        }
+        return actionIds;
+    }
+
+    public List<ResourceActionDefinition> getDataAccessAction(){
+        return actions.stream()
+                .filter(act->act.getDataAccess()!=null)
+                .collect(Collectors.toList());
+    }
+
+    public boolean hasDataAccessAction(){
+        return actions.stream()
+                .anyMatch(act->act.getDataAccess()!=null);
+    }
+
+    public boolean hasAction(Collection<String> actions) {
+        if (CollectionUtils.isEmpty(this.actions)) {
+            return true;
+        }
+
+        if (CollectionUtils.isEmpty(actions)) {
+            return false;
+        }
+
+        if (logical == Logical.AND) {
+            return getActionIds().containsAll(actions);
+        }
+        return getActionIds().stream().anyMatch(actions::contains);
+    }
+}

+ 79 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/ResourcesDefinition.java

@@ -0,0 +1,79 @@
+package org.hswebframework.web.authorization.define;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.commons.collections.CollectionUtils;
+import org.hswebframework.web.authorization.Permission;
+import org.hswebframework.web.authorization.annotation.Logical;
+
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+@Getter
+@Setter
+public class ResourcesDefinition {
+
+    private List<ResourceDefinition> resources = new ArrayList<>();
+
+    private Logical logical = Logical.DEFAULT;
+
+    private Phased phased = Phased.before;
+
+
+    public void addResource(ResourceDefinition resource, boolean merge) {
+        ResourceDefinition definition = getResource(resource.getId()).orElse(null);
+        if (definition != null) {
+            if (merge) {
+                resource.getActions().forEach(definition::addAction);
+            } else {
+                resources.remove(definition);
+            }
+        }
+        resources.add(resource);
+
+    }
+
+    public Optional<ResourceDefinition> getResource(String id) {
+        return resources
+                .stream()
+                .filter(resource -> resource.getId().equals(id))
+                .findAny();
+    }
+
+    public List<ResourceDefinition> getDataAccessResources() {
+        return resources
+                .stream()
+                .filter(ResourceDefinition::hasDataAccessAction)
+                .collect(Collectors.toList());
+    }
+
+    public boolean hasPermission(Permission permission) {
+        return getResource(permission.getId())
+                .filter(resource -> resource.hasAction(permission.getActions()))
+                .isPresent();
+    }
+
+    public boolean hasPermission(Collection<Permission> permissions) {
+        if (CollectionUtils.isEmpty(permissions)) {
+            return false;
+        }
+        if (permissions.size() == 1) {
+            return hasPermission(permissions.iterator().next());
+        }
+
+        Map<String, Permission> mappings = permissions.stream().collect(Collectors.toMap(Permission::getId, Function.identity()));
+
+        if (logical == Logical.AND) {
+            return resources.stream()
+                    .allMatch(resource -> Optional.ofNullable(mappings.get(resource.getId()))
+                            .map(per -> resource.hasAction(per.getActions()))
+                            .orElse(false));
+        }
+
+        return resources.stream()
+                .anyMatch(resource -> Optional.ofNullable(mappings.get(resource.getId()))
+                        .map(per -> resource.hasAction(per.getActions()))
+                        .orElse(false));
+    }
+}

+ 0 - 26
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/Script.java

@@ -1,26 +0,0 @@
-package org.hswebframework.web.authorization.define;
-
-
-/**
- * 使用脚本进行权限控制
- *
- * @author zhouhao
- * @since 3.0
- */
-public interface Script {
-    /**
-     * @return 脚本语言, js,groovy,spel等
-     */
-    String getLanguage();
-
-    /**
-     * js:
-     * <pre>
-     *    return auth.hasRole("admin");
-     * </pre>
-     *
-     * @return 脚本内容
-     */
-    String getScript();
-
-}

+ 13 - 28
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleAuthentication.java

@@ -17,6 +17,7 @@
 
 
 package org.hswebframework.web.authorization.simple;
 package org.hswebframework.web.authorization.simple;
 
 
+import lombok.Getter;
 import org.hswebframework.web.authorization.*;
 import org.hswebframework.web.authorization.*;
 
 
 import java.io.Serializable;
 import java.io.Serializable;
@@ -28,10 +29,11 @@ public class SimpleAuthentication implements Authentication {
 
 
     private User user;
     private User user;
 
 
-    private List<Role> roles;
-
     private List<Permission> permissions;
     private List<Permission> permissions;
 
 
+    private List<Dimension> dimensions;
+
+    @Getter
     private Map<String, Serializable> attributes = new HashMap<>();
     private Map<String, Serializable> attributes = new HashMap<>();
 
 
     @Override
     @Override
@@ -43,47 +45,30 @@ public class SimpleAuthentication implements Authentication {
         this.user = user;
         this.user = user;
     }
     }
 
 
-    public void setRoles(List<Role> roles) {
-        this.roles = roles;
-    }
-
     public void setPermissions(List<Permission> permissions) {
     public void setPermissions(List<Permission> permissions) {
         this.permissions = permissions;
         this.permissions = permissions;
     }
     }
 
 
-    @Override
-    public List<Role> getRoles() {
-        return new ArrayList<>(roles);
-    }
-
     @Override
     @Override
     public List<Permission> getPermissions() {
     public List<Permission> getPermissions() {
-        if(permissions==null){
-            return Collections.emptyList();
+        if (permissions == null) {
+            return permissions = new ArrayList<>();
         }
         }
         return new ArrayList<>(permissions);
         return new ArrayList<>(permissions);
     }
     }
 
 
     @Override
     @Override
-    @SuppressWarnings("unchecked")
-    public <T extends Serializable> Optional<T> getAttribute(String name) {
-        return Optional.ofNullable((T) attributes.get(name));
-    }
-
-    @Override
-    public void setAttribute(String name, Serializable object) {
-        attributes.put(name, object);
-    }
-
-    @Override
-    public void setAttributes(Map<String, Serializable> attributes) {
-        this.attributes.putAll(attributes);
+    public List<Dimension> getDimensions() {
+        if (dimensions == null) {
+            return dimensions = new ArrayList<>();
+        }
+        return dimensions;
     }
     }
 
 
     @Override
     @Override
     @SuppressWarnings("unchecked")
     @SuppressWarnings("unchecked")
-    public <T extends Serializable> T removeAttributes(String name) {
-        return (T) attributes.remove(name);
+    public <T extends Serializable> Optional<T> getAttribute(String name) {
+        return Optional.ofNullable((T) attributes.get(name));
     }
     }
 
 
     @Override
     @Override

+ 0 - 49
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleCustomDataAccessConfigConfig.java

@@ -1,49 +0,0 @@
-package org.hswebframework.web.authorization.simple;
-
-import org.hswebframework.web.authorization.access.CustomDataAccessConfig;
-import org.hswebframework.web.authorization.access.DataAccessController;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.util.ClassUtils;
-
-/**
- * @author zhouhao
- */
-public class SimpleCustomDataAccessConfigConfig extends AbstractDataAccessConfig implements CustomDataAccessConfig {
-
-    private static final long serialVersionUID = -8754634247843748887L;
-
-    private String classOrBeanName;
-
-    private static Logger logger = LoggerFactory.getLogger(CustomDataAccessConfig.class);
-
-    private transient DataAccessController instance;
-
-    public SimpleCustomDataAccessConfigConfig() {
-    }
-
-    public SimpleCustomDataAccessConfigConfig(String classOrBeanName) {
-        this.classOrBeanName = classOrBeanName;
-        try {
-            instance = (DataAccessController) ClassUtils.forName(getClassOrBeanName(), this.getClass().getClassLoader()).newInstance();
-        } catch (Exception e) {
-            logger.error("init CustomDataAccessConfig error", e);
-        }
-    }
-
-    @Override
-    public DataAccessController getController() {
-        if (instance == null) {
-            throw new UnsupportedOperationException(new ClassNotFoundException(classOrBeanName));
-        }
-        return instance;
-    }
-
-    public String getClassOrBeanName() {
-        return classOrBeanName;
-    }
-
-    public void setClassOrBeanName(String classOrBeanName) {
-        this.classOrBeanName = classOrBeanName;
-    }
-}

+ 29 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleDimension.java

@@ -0,0 +1,29 @@
+package org.hswebframework.web.authorization.simple;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.hswebframework.web.authorization.Dimension;
+import org.hswebframework.web.authorization.DimensionType;
+
+import java.util.Map;
+
+@Getter
+@Setter
+public class SimpleDimension implements Dimension {
+
+    private String id;
+
+    private String name;
+
+    private DimensionType type;
+
+    private Map<String,Object> options;
+
+    public boolean typeIs(DimensionType type) {
+        return this.type == type || this.type.getId().equals(type.getId());
+    }
+
+    public boolean typeIs(String type) {
+        return this.type.getId().equals(type);
+    }
+}

+ 4 - 2
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleFieldFilterDataAccessConfig.java

@@ -1,5 +1,7 @@
 package org.hswebframework.web.authorization.simple;
 package org.hswebframework.web.authorization.simple;
 
 
+import org.hswebframework.web.authorization.access.DataAccessType;
+import org.hswebframework.web.authorization.access.DefaultDataAccessType;
 import org.hswebframework.web.authorization.access.FieldFilterDataAccessConfig;
 import org.hswebframework.web.authorization.access.FieldFilterDataAccessConfig;
 
 
 import java.util.Arrays;
 import java.util.Arrays;
@@ -37,7 +39,7 @@ public class SimpleFieldFilterDataAccessConfig extends AbstractDataAccessConfig
     }
     }
 
 
     @Override
     @Override
-    public String getType() {
-        return DENY_FIELDS;
+    public DataAccessType getType() {
+        return DefaultDataAccessType.FIELD_DENY;
     }
     }
 }
 }

+ 0 - 61
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleFiledScopeDataAccessConfig.java

@@ -1,61 +0,0 @@
-package org.hswebframework.web.authorization.simple;
-
-import org.hswebframework.web.authorization.access.FieldScopeDataAccessConfig;
-
-import java.util.Set;
-
-/**
- * @author zhouhao
- * @since 3.0
- */
-public class SimpleFiledScopeDataAccessConfig extends AbstractDataAccessConfig implements FieldScopeDataAccessConfig {
-
-    private static final long serialVersionUID = -2562713900619774139L;
-
-    private String scopeType;
-
-    private Set<Object> scope;
-
-    private String field;
-
-    public SimpleFiledScopeDataAccessConfig() {
-    }
-
-    public SimpleFiledScopeDataAccessConfig(String field, Set<Object> scope) {
-        this.scope = scope;
-        this.field = field;
-    }
-
-    public SimpleFiledScopeDataAccessConfig(String field, String scopeType) {
-        this.scopeType = scopeType;
-        this.field = field;
-    }
-
-    @Override
-    public String getScopeType() {
-        return scopeType;
-    }
-
-    public void setScopeType(String scopeType) {
-        this.scopeType = scopeType;
-    }
-
-    @Override
-    public Set<Object> getScope() {
-        return scope;
-    }
-
-    public void setScope(Set<Object> scope) {
-        this.scope = scope;
-    }
-
-    @Override
-    public String getField() {
-        return field;
-    }
-
-    public void setField(String field) {
-        this.field = field;
-    }
-
-}

+ 14 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleRole.java

@@ -1,8 +1,12 @@
 package org.hswebframework.web.authorization.simple;
 package org.hswebframework.web.authorization.simple;
 
 
 import lombok.*;
 import lombok.*;
+import org.hswebframework.web.authorization.Dimension;
 import org.hswebframework.web.authorization.Role;
 import org.hswebframework.web.authorization.Role;
 
 
+import java.io.Serializable;
+import java.util.Map;
+
 /**
 /**
  * @author zhouhao
  * @author zhouhao
  */
  */
@@ -18,4 +22,14 @@ public class SimpleRole implements Role {
     private String id;
     private String id;
 
 
     private String name;
     private String name;
+
+    private Map<String, Object> options;
+
+    public static Role of(Dimension dimension) {
+        return SimpleRole.builder()
+                .name(dimension.getName())
+                .id(dimension.getId())
+                .options(dimension.getOptions())
+                .build();
+    }
 }
 }

+ 7 - 2
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleUser.java

@@ -3,6 +3,9 @@ package org.hswebframework.web.authorization.simple;
 import lombok.*;
 import lombok.*;
 import org.hswebframework.web.authorization.User;
 import org.hswebframework.web.authorization.User;
 
 
+import java.io.Serializable;
+import java.util.Map;
+
 /**
 /**
  * @author zhouhao
  * @author zhouhao
  */
  */
@@ -20,6 +23,8 @@ public class SimpleUser implements User {
     private String username;
     private String username;
 
 
     private String name;
     private String name;
-    
-    private String type;
+
+    private String userType;
+
+    private Map<String, Object> options;
 }
 }

+ 4 - 6
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/builder/SimpleAuthenticationBuilder.java

@@ -19,8 +19,6 @@ import java.util.*;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
 /**
 /**
- * TODO 完成注释
- *
  * @author zhouhao
  * @author zhouhao
  */
  */
 public class SimpleAuthenticationBuilder implements AuthenticationBuilder {
 public class SimpleAuthenticationBuilder implements AuthenticationBuilder {
@@ -55,14 +53,14 @@ public class SimpleAuthenticationBuilder implements AuthenticationBuilder {
                 .id(user.get("id"))
                 .id(user.get("id"))
                 .username(user.get("username"))
                 .username(user.get("username"))
                 .name(user.get("name"))
                 .name(user.get("name"))
-                .type(user.get("type"))
+                .userType(user.get("type"))
                 .build());
                 .build());
         return this;
         return this;
     }
     }
 
 
     @Override
     @Override
     public AuthenticationBuilder role(List<Role> role) {
     public AuthenticationBuilder role(List<Role> role) {
-        authentication.setRoles(role);
+        authentication.getDimensions().addAll(role);
         return this;
         return this;
     }
     }
 
 
@@ -106,13 +104,13 @@ public class SimpleAuthenticationBuilder implements AuthenticationBuilder {
 
 
     @Override
     @Override
     public AuthenticationBuilder attributes(String attributes) {
     public AuthenticationBuilder attributes(String attributes) {
-        authentication.setAttributes(JSON.<Map<String, Serializable>>parseObject(attributes, Map.class));
+        authentication.getAttributes().putAll(JSON.<Map<String, Serializable>>parseObject(attributes, Map.class));
         return this;
         return this;
     }
     }
 
 
     @Override
     @Override
     public AuthenticationBuilder attributes(Map<String, Serializable> permission) {
     public AuthenticationBuilder attributes(Map<String, Serializable> permission) {
-        authentication.setAttributes(permission);
+        authentication.getAttributes().putAll(permission);
         return this;
         return this;
     }
     }
 
 

+ 1 - 9
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/builder/SimpleDataAccessConfigBuilderFactory.java

@@ -14,7 +14,6 @@ import java.util.Objects;
 import java.util.function.BiFunction;
 import java.util.function.BiFunction;
 
 
 import static org.hswebframework.web.authorization.access.DataAccessConfig.DefaultType.*;
 import static org.hswebframework.web.authorization.access.DataAccessConfig.DefaultType.*;
-import static org.hswebframework.web.authorization.access.DataAccessConfig.DefaultType.CUSTOM;
 import static org.hswebframework.web.authorization.access.DataAccessConfig.DefaultType.OWN_CREATED;
 import static org.hswebframework.web.authorization.access.DataAccessConfig.DefaultType.OWN_CREATED;
 
 
 /**
 /**
@@ -23,7 +22,6 @@ import static org.hswebframework.web.authorization.access.DataAccessConfig.Defau
 public class SimpleDataAccessConfigBuilderFactory implements DataAccessConfigBuilderFactory {
 public class SimpleDataAccessConfigBuilderFactory implements DataAccessConfigBuilderFactory {
 
 
     private List<String> defaultSupportConvert = Arrays.asList(
     private List<String> defaultSupportConvert = Arrays.asList(
-            CUSTOM,
             OWN_CREATED,
             OWN_CREATED,
             FIELD_SCOPE,
             FIELD_SCOPE,
             DENY_FIELDS);
             DENY_FIELDS);
@@ -69,9 +67,7 @@ public class SimpleDataAccessConfigBuilderFactory implements DataAccessConfigBui
 
 
     @PostConstruct
     @PostConstruct
     public void init() {
     public void init() {
-        if (defaultSupportConvert.contains(FIELD_SCOPE)) {
-            converts.add(createJsonConfig(FIELD_SCOPE, SimpleFiledScopeDataAccessConfig.class));
-        }
+
 
 
         if (defaultSupportConvert.contains(DENY_FIELDS)) {
         if (defaultSupportConvert.contains(DENY_FIELDS)) {
             converts.add(createJsonConfig(DENY_FIELDS, SimpleFieldFilterDataAccessConfig.class));
             converts.add(createJsonConfig(DENY_FIELDS, SimpleFieldFilterDataAccessConfig.class));
@@ -81,10 +77,6 @@ public class SimpleDataAccessConfigBuilderFactory implements DataAccessConfigBui
             converts.add(createConfig(OWN_CREATED, (action, config) -> new SimpleOwnCreatedDataAccessConfig(action)));
             converts.add(createConfig(OWN_CREATED, (action, config) -> new SimpleOwnCreatedDataAccessConfig(action)));
         }
         }
 
 
-
-        if (defaultSupportConvert.contains(CUSTOM)) {
-            converts.add(createConfig(CUSTOM, (action, config) -> new SimpleCustomDataAccessConfigConfig(config)));
-        }
     }
     }
 
 
     @Override
     @Override

+ 12 - 12
hsweb-authorization/hsweb-authorization-api/src/test/java/org/hswebframework/web/authorization/AuthenticationTests.java

@@ -35,7 +35,7 @@ public class AuthenticationTests {
      */
      */
     @Test
     @Test
     public void testInitUserRoleAndPermission() {
     public void testInitUserRoleAndPermission() {
-        Authentication authentication = builder.user("{\"id\":\"admin\",\"username\":\"admin\",\"name\":\"Administrator\",\"type\":\"default\"}")
+        Authentication authentication = builder.user("{\"id\":\"admin\",\"username\":\"admin\",\"name\":\"Administrator\",\"userType\":\"default\"}")
                 .role("[{\"id\":\"admin-role\",\"name\":\"admin\"}]")
                 .role("[{\"id\":\"admin-role\",\"name\":\"admin\"}]")
                 .permission("[{\"id\":\"user-manager\",\"actions\":[\"query\",\"get\",\"update\"]" +
                 .permission("[{\"id\":\"user-manager\",\"actions\":[\"query\",\"get\",\"update\"]" +
                         ",\"dataAccesses\":[{\"action\":\"query\",\"field\":\"test\",\"fields\":[\"1\",\"2\",\"3\"],\"scopeType\":\"CUSTOM_SCOPE\",\"type\":\"DENY_FIELDS\"}]}]")
                         ",\"dataAccesses\":[{\"action\":\"query\",\"field\":\"test\",\"fields\":[\"1\",\"2\",\"3\"],\"scopeType\":\"CUSTOM_SCOPE\",\"type\":\"DENY_FIELDS\"}]}]")
@@ -45,12 +45,12 @@ public class AuthenticationTests {
         assertEquals(authentication.getUser().getId(), "admin");
         assertEquals(authentication.getUser().getId(), "admin");
         assertEquals(authentication.getUser().getUsername(), "admin");
         assertEquals(authentication.getUser().getUsername(), "admin");
         assertEquals(authentication.getUser().getName(), "Administrator");
         assertEquals(authentication.getUser().getName(), "Administrator");
-        assertEquals(authentication.getUser().getType(), "default");
+        assertEquals(authentication.getUser().getUserType(), "default");
 
 
         //test role
         //test role
-        assertNotNull(authentication.getRole("admin-role").orElse(null));
-        assertEquals(authentication.getRole("admin-role").get().getName(), "admin");
-        assertTrue(authentication.hasRole("admin-role"));
+        assertNotNull(authentication.getDimension("role","admin-role").orElse(null));
+        assertEquals(authentication.getDimension("role","admin-role").get().getName(), "admin");
+        assertTrue(authentication.hasDimension("role","admin-role"));
 
 
 
 
         //test permission
         //test permission
@@ -60,12 +60,12 @@ public class AuthenticationTests {
         assertFalse(authentication.hasPermission("user-manager", "delete"));
         assertFalse(authentication.hasPermission("user-manager", "delete"));
 
 
         boolean has = AuthenticationPredicate.has("permission:user-manager")
         boolean has = AuthenticationPredicate.has("permission:user-manager")
-                .or(AuthenticationPredicate.role("admin-role"))
+                .or(AuthenticationPredicate.dimension("role","admin-role"))
                 .test(authentication);
                 .test(authentication);
 
 
         Assert.assertTrue(has);
         Assert.assertTrue(has);
         has = AuthenticationPredicate.has("permission:user-manager:test")
         has = AuthenticationPredicate.has("permission:user-manager:test")
-                .and(AuthenticationPredicate.role("admin-role"))
+                .and(AuthenticationPredicate.dimension("role","admin-role"))
                 .test(authentication);
                 .test(authentication);
         Assert.assertFalse(has);
         Assert.assertFalse(has);
 
 
@@ -78,12 +78,12 @@ public class AuthenticationTests {
         Assert.assertTrue(has);
         Assert.assertTrue(has);
 
 
         //获取数据权限配置
         //获取数据权限配置
-        Set<String> fields = authentication.getPermission("user-manager")
-                .map(permission -> permission.findDenyFields(Permission.ACTION_QUERY))
-                .orElseGet(Collections::emptySet);
+//        Set<String> fields = authentication.getPermission("user-manager")
+//                .map(permission -> permission.findDenyFields(Permission.ACTION_QUERY))
+//                .orElseGet(Collections::emptySet);
 
 
-        Assert.assertEquals(fields.size(), 3);
-        System.out.println(fields);
+//        Assert.assertEquals(fields.size(), 3);
+//        System.out.println(fields);
 
 
     }
     }
 
 

+ 9 - 10
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/aop/AopAuthorizingController.java

@@ -56,12 +56,12 @@ public class AopAuthorizingController extends StaticMethodMatcherPointcutAdvisor
         return Authentication.currentReactive()
         return Authentication.currentReactive()
                 .switchIfEmpty(Mono.error(new UnAuthorizedException()))
                 .switchIfEmpty(Mono.error(new UnAuthorizedException()))
                 .flatMap(auth -> {
                 .flatMap(auth -> {
-                    DataAccessDefinition dataAccessDefinition = definition.getDataAccessDefinition();
+                    ResourcesDefinition resources = definition.getResources();
 
 
                     context.setAuthentication(auth);
                     context.setAuthentication(auth);
                     if (definition.getPhased() == Phased.before) {
                     if (definition.getPhased() == Phased.before) {
                         authorizingHandler.handRBAC(context);
                         authorizingHandler.handRBAC(context);
-                        if (dataAccessDefinition != null && dataAccessDefinition.getPhased() == Phased.before) {
+                        if (resources != null && resources.getPhased() == Phased.before) {
                             authorizingHandler.handleDataAccess(context);
                             authorizingHandler.handleDataAccess(context);
                         } else {
                         } else {
                             return mono.doOnNext(res -> {
                             return mono.doOnNext(res -> {
@@ -70,7 +70,7 @@ public class AopAuthorizingController extends StaticMethodMatcherPointcutAdvisor
                             });
                             });
                         }
                         }
                     } else {
                     } else {
-                        if (dataAccessDefinition != null && dataAccessDefinition.getPhased() == Phased.before) {
+                        if (resources != null && resources.getPhased() == Phased.before) {
                             authorizingHandler.handleDataAccess(context);
                             authorizingHandler.handleDataAccess(context);
                             return mono.doOnNext(res -> {
                             return mono.doOnNext(res -> {
                                 context.setParamContext(holder.createParamContext(res));
                                 context.setParamContext(holder.createParamContext(res));
@@ -93,12 +93,12 @@ public class AopAuthorizingController extends StaticMethodMatcherPointcutAdvisor
         return Authentication.currentReactive()
         return Authentication.currentReactive()
                 .switchIfEmpty(Mono.error(new UnAuthorizedException()))
                 .switchIfEmpty(Mono.error(new UnAuthorizedException()))
                 .flatMapMany(auth -> {
                 .flatMapMany(auth -> {
-                    DataAccessDefinition dataAccessDefinition = definition.getDataAccessDefinition();
+                    ResourcesDefinition resources = definition.getResources();
 
 
                     context.setAuthentication(auth);
                     context.setAuthentication(auth);
                     if (definition.getPhased() == Phased.before) {
                     if (definition.getPhased() == Phased.before) {
                         authorizingHandler.handRBAC(context);
                         authorizingHandler.handRBAC(context);
-                        if (dataAccessDefinition != null && dataAccessDefinition.getPhased() == Phased.before) {
+                        if (resources != null && resources.getPhased() == Phased.before) {
                             authorizingHandler.handleDataAccess(context);
                             authorizingHandler.handleDataAccess(context);
                         } else {
                         } else {
                             return flux.doOnNext(res -> {
                             return flux.doOnNext(res -> {
@@ -108,7 +108,7 @@ public class AopAuthorizingController extends StaticMethodMatcherPointcutAdvisor
                         }
                         }
                     } else {
                     } else {
 
 
-                        if (dataAccessDefinition != null && dataAccessDefinition.getPhased() == Phased.before) {
+                        if (resources != null && resources.getPhased() == Phased.before) {
                             authorizingHandler.handleDataAccess(context);
                             authorizingHandler.handleDataAccess(context);
                             return flux.doOnNext(res -> {
                             return flux.doOnNext(res -> {
                                 context.setParamContext(holder.createParamContext(res));
                                 context.setParamContext(holder.createParamContext(res));
@@ -155,9 +155,7 @@ public class AopAuthorizingController extends StaticMethodMatcherPointcutAdvisor
             isControl = true;
             isControl = true;
 
 
             Phased dataAccessPhased = null;
             Phased dataAccessPhased = null;
-            if (definition.getDataAccessDefinition() != null) {
-                dataAccessPhased = definition.getDataAccessDefinition().getPhased();
-            }
+            dataAccessPhased = definition.getResources().getPhased();
             if (definition.getPhased() == Phased.before) {
             if (definition.getPhased() == Phased.before) {
                 //RDAC before
                 //RDAC before
                 authorizingHandler.handRBAC(context);
                 authorizingHandler.handRBAC(context);
@@ -220,7 +218,8 @@ public class AopAuthorizingController extends StaticMethodMatcherPointcutAdvisor
     public void run(String... args) throws Exception {
     public void run(String... args) throws Exception {
         if (autoParse) {
         if (autoParse) {
             List<AuthorizeDefinition> definitions = defaultParser.getAllParsed()
             List<AuthorizeDefinition> definitions = defaultParser.getAllParsed()
-                    .stream().filter(def -> !def.isEmpty()).collect(Collectors.toList());
+                    .stream().filter(def -> !def.isEmpty())
+                    .collect(Collectors.toList());
             log.info("publish AuthorizeDefinitionInitializedEvent,definition size:{}", definitions.size());
             log.info("publish AuthorizeDefinitionInitializedEvent,definition size:{}", definitions.size());
             eventPublisher.publishEvent(new AuthorizeDefinitionInitializedEvent(definitions));
             eventPublisher.publishEvent(new AuthorizeDefinitionInitializedEvent(definitions));
 
 

+ 10 - 58
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/aop/DefaultAopMethodAuthorizeDefinitionParser.java

@@ -3,13 +3,15 @@ package org.hswebframework.web.authorization.basic.aop;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.hswebframework.web.aop.MethodInterceptorContext;
 import org.hswebframework.web.aop.MethodInterceptorContext;
 import org.hswebframework.web.authorization.annotation.Authorize;
 import org.hswebframework.web.authorization.annotation.Authorize;
-import org.hswebframework.web.authorization.annotation.RequiresDataAccess;
-import org.hswebframework.web.authorization.annotation.RequiresExpression;
+import org.hswebframework.web.authorization.annotation.DataAccess;
+import org.hswebframework.web.authorization.annotation.Dimension;
 import org.hswebframework.web.authorization.basic.define.DefaultBasicAuthorizeDefinition;
 import org.hswebframework.web.authorization.basic.define.DefaultBasicAuthorizeDefinition;
 import org.hswebframework.web.authorization.basic.define.EmptyAuthorizeDefinition;
 import org.hswebframework.web.authorization.basic.define.EmptyAuthorizeDefinition;
 import org.hswebframework.web.authorization.define.AuthorizeDefinition;
 import org.hswebframework.web.authorization.define.AuthorizeDefinition;
 import org.hswebframework.web.utils.AnnotationUtils;
 import org.hswebframework.web.utils.AnnotationUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.annotation.AnnotatedElementUtils;
+import org.springframework.core.type.AnnotationMetadata;
 import org.springframework.util.ClassUtils;
 import org.springframework.util.ClassUtils;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.CollectionUtils;
 
 
@@ -71,67 +73,17 @@ public class DefaultAopMethodAuthorizeDefinitionParser implements AopMethodAutho
                 return definition;
                 return definition;
             }
             }
         }
         }
-        Authorize classAuth = AnnotationUtils.findAnnotation(target, Authorize.class);
-        Authorize methodAuth = AnnotationUtils.findMethodAnnotation(target, method, Authorize.class);
 
 
-        RequiresDataAccess classDataAccess = AnnotationUtils.findAnnotation(target, RequiresDataAccess.class);
+        Authorize annotation = AnnotationUtils.findAnnotation(target, method, Authorize.class);
 
 
-        RequiresDataAccess methodDataAccess = AnnotationUtils.findMethodAnnotation(target, method, RequiresDataAccess.class);
-
-        RequiresExpression expression = AnnotationUtils.findAnnotation(target, RequiresExpression.class);
-
-        if (classAuth == null && methodAuth == null && classDataAccess == null && methodDataAccess == null && expression == null) {
-            cache.put(key, EmptyAuthorizeDefinition.instance);
-            return null;
-        }
-
-        if ((methodAuth != null && methodAuth.ignore()) || (classAuth != null && classAuth.ignore())) {
+        if (annotation != null && annotation.ignore()) {
             cache.put(key, EmptyAuthorizeDefinition.instance);
             cache.put(key, EmptyAuthorizeDefinition.instance);
             return null;
             return null;
         }
         }
         synchronized (cache) {
         synchronized (cache) {
-            DefaultBasicAuthorizeDefinition authorizeDefinition = new DefaultBasicAuthorizeDefinition();
-            authorizeDefinition.setTargetClass(target);
-            authorizeDefinition.setTargetMethod(method);
-            if (methodAuth == null || methodAuth.merge()) {
-                authorizeDefinition.put(classAuth);
-            }
-
-            authorizeDefinition.put(methodAuth);
-
-            authorizeDefinition.put(expression);
-
-            authorizeDefinition.put(classDataAccess);
-
-            authorizeDefinition.put(methodDataAccess);
-
-            if (authorizeDefinition.getPermissionDescription().length == 0) {
-                if (classAuth != null) {
-                    authorizeDefinition.put(classAuth.dataAccess());
-                    String[] desc = classAuth.description();
-                    if (desc.length > 0) {
-                        authorizeDefinition.setPermissionDescription(desc);
-                    }
-                }
-            }
-
-            if (authorizeDefinition.getActionDescription().length == 0) {
-                if (methodAuth != null) {
-                    if (methodAuth.description().length != 0) {
-                        authorizeDefinition.setActionDescription(methodAuth.description());
-                    }
-                }
-            }
-
-            log.info("parsed authorizeDefinition {}.{} => {}.{} permission:{} actions:{}",
-                    target.getSimpleName(),
-                    method.getName(),
-                    authorizeDefinition.getPermissionDescription(),
-                    authorizeDefinition.getActionDescription(),
-                    authorizeDefinition.getPermissions(),
-                    authorizeDefinition.getActions());
-            cache.put(key, authorizeDefinition);
-            return authorizeDefinition;
+            return cache.computeIfAbsent(key, (__) -> {
+                return DefaultBasicAuthorizeDefinition.from(target, method);
+            });
         }
         }
     }
     }
 
 
@@ -140,7 +92,7 @@ public class DefaultAopMethodAuthorizeDefinitionParser implements AopMethodAutho
     }
     }
 
 
     class CacheKey {
     class CacheKey {
-        private Class  type;
+        private Class type;
         private Method method;
         private Method method;
 
 
         public CacheKey(Class type, Method method) {
         public CacheKey(Class type, Method method) {

+ 156 - 67
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultBasicAuthorizeDefinition.java

@@ -1,18 +1,15 @@
 package org.hswebframework.web.authorization.basic.define;
 package org.hswebframework.web.authorization.basic.define;
 
 
 import lombok.*;
 import lombok.*;
-import org.hswebframework.web.authorization.access.DataAccessController;
-import org.hswebframework.web.authorization.annotation.Authorize;
-import org.hswebframework.web.authorization.annotation.Logical;
-import org.hswebframework.web.authorization.annotation.RequiresDataAccess;
-import org.hswebframework.web.authorization.annotation.RequiresExpression;
+import org.hswebframework.web.authorization.annotation.*;
 import org.hswebframework.web.authorization.define.*;
 import org.hswebframework.web.authorization.define.*;
+import org.springframework.core.annotation.AnnotatedElementUtils;
 
 
+import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
 import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.Set;
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 
 
 /**
 /**
  * 默认权限权限定义
  * 默认权限权限定义
@@ -26,91 +23,183 @@ import java.util.Set;
 @AllArgsConstructor
 @AllArgsConstructor
 @ToString
 @ToString
 public class DefaultBasicAuthorizeDefinition implements AopAuthorizeDefinition {
 public class DefaultBasicAuthorizeDefinition implements AopAuthorizeDefinition {
-    private boolean dataAccessControl;
 
 
-    private String[] permissionDescription = {};
-
-    private String[] actionDescription = {};
-
-    private Set<String> permissions = new LinkedHashSet<>();
-
-    private Set<String> actions = new LinkedHashSet<>();
-
-    private Set<String> roles = new LinkedHashSet<>();
+    private Class targetClass;
 
 
-    private Set<String> user = new LinkedHashSet<>();
+    private Method targetMethod;
 
 
-    private Script script;
+    private ResourcesDefinition resources = new ResourcesDefinition();
+    private DimensionsDefinition dimensions = new DimensionsDefinition();
 
 
-    private String message = "{un_authorized}";
+    private String message;
 
 
-    private Logical logical = Logical.DEFAULT;
+    private Phased phased;
 
 
-    private DataAccessDefinition dataAccessDefinition;
+    @Override
+    public boolean isEmpty() {
+        return resources.getResources().isEmpty() && dimensions.getDimensions().isEmpty();
+    }
 
 
-    private Phased phased = Phased.before;
+    private static final Set<Class<? extends Annotation>> types = new HashSet<>(Arrays.asList(
+            Authorize.class,
+            DataAccess.class,
+            Dimension.class,
+            Resource.class,
+            ResourceAction.class,
+            DataAccessType.class
+    ));
+
+    public static AopAuthorizeDefinition from(Class targetClass, Method method) {
+        DefaultBasicAuthorizeDefinition definition = new DefaultBasicAuthorizeDefinition();
+        definition.setTargetClass(targetClass);
+        definition.setTargetMethod(method);
+
+        Set<Annotation> annotations = AnnotatedElementUtils.findAllMergedAnnotations(method, types);
+
+        Set<Annotation> classAnnotation = AnnotatedElementUtils.findAllMergedAnnotations(targetClass, types);
+
+        Map<Class, Annotation> classAnnotationMap = classAnnotation
+                .stream()
+                .collect(Collectors.toMap(Annotation::annotationType, Function.identity()));
+
+        Map<Class, Annotation> mapping = annotations
+                .stream()
+                .collect(Collectors.toMap(Annotation::annotationType, Function.identity()));
+
+        for (Annotation annotation : classAnnotation) {
+            if (annotation instanceof Authorize) {
+                definition.putAnnotation(((Authorize) annotation));
+            }
+            if (annotation instanceof Resource) {
+                definition.putAnnotation(((Resource) annotation));
+            }
+        }
 
 
-    private Class targetClass;
+        for (Annotation annotation : annotations) {
+            if (annotation instanceof Authorize) {
+                definition.putAnnotation(((Authorize) annotation));
+            }
+            if (annotation instanceof Resource) {
+                definition.putAnnotation(((Resource) annotation));
+            }
+            if (annotation instanceof Dimension) {
+                definition.putAnnotation(((Dimension) annotation));
+            }
+        }
 
 
-    private Method targetMethod;
+        for (Annotation annotation : annotations) {
+
+            if (annotation instanceof ResourceAction) {
+                Optional.ofNullable(mapping.getOrDefault(Resource.class, classAnnotationMap.get(Resource.class)))
+                        .map(Resource.class::cast)
+                        .flatMap(res -> definition.getResources().getResource(res.id()))
+                        .ifPresent(res -> {
+
+                            ResourceAction ra = (ResourceAction) annotation;
+                            ResourceActionDefinition action = definition.putAnnotation(res, ra);
+
+                            Optional.ofNullable(mapping.get(DataAccessType.class))
+                                    .map(DataAccessType.class::cast)
+                                    .ifPresent(dat -> definition.putAnnotation(action, dat));
+                        });
+            }
+            if (annotation instanceof DataAccess) {
+                Optional.ofNullable(mapping.getOrDefault(Resource.class, classAnnotationMap.get(Resource.class)))
+                        .map(Resource.class::cast)
+                        .flatMap(res -> definition.getResources().getResource(res.id()))
+                        .flatMap(res -> Optional.ofNullable(mapping.get(ResourceAction.class))
+                                .map(ResourceAction.class::cast)
+                                .flatMap(ra -> res.getAction(ra.id())))
+                        .ifPresent(ra -> {
+                            definition.putAnnotation(ra, (DataAccess) annotation);
+                            Optional.ofNullable(mapping.get(DataAccessType.class))
+                                    .map(DataAccessType.class::cast)
+                                    .ifPresent(dat -> definition.putAnnotation(ra, dat));
+
+                        });
+            }
 
 
-    @Override
-    public Phased getPhased() {
-        return phased;
-    }
+        }
 
 
-    @Override
-    public int getPriority() {
-        return Integer.MIN_VALUE;
+        return definition;
     }
     }
 
 
-    @Override
-    public boolean isEmpty() {
-        return permissions.isEmpty() && roles.isEmpty() && user.isEmpty() && script == null && dataAccessDefinition == null;
+    public void putAnnotation(Authorize ann) {
+        if (!ann.merge()) {
+            getResources().getResources().clear();
+            getDimensions().getDimensions().clear();
+        }
+        getResources().setPhased(ann.phased());
+        for (Resource resource : ann.resources()) {
+            putAnnotation(resource);
+        }
+        for (Dimension dimension : ann.dimension()) {
+            putAnnotation(dimension);
+        }
     }
     }
 
 
-    public void put(Authorize authorize) {
-        if (null == authorize || authorize.ignore()) {
+    public void putAnnotation(Dimension ann) {
+        if (ann.ignore()) {
+            getDimensions().getDimensions().clear();
             return;
             return;
         }
         }
-        permissions.addAll(Arrays.asList(authorize.permission()));
-        actions.addAll(Arrays.asList(authorize.action()));
-        roles.addAll(Arrays.asList(authorize.role()));
-        user.addAll(Arrays.asList(authorize.user()));
-        if (authorize.logical() != Logical.DEFAULT) {
-            logical = authorize.logical();
+        DimensionDefinition definition = new DimensionDefinition();
+        definition.setTypeId(ann.type());
+        definition.setDimensionId(new HashSet<>(Arrays.asList(ann.id())));
+        definition.setLogical(ann.logical());
+        getDimensions().addDimension(definition);
+    }
+
+    public void putAnnotation(Resource ann) {
+        ResourceDefinition resource = new ResourceDefinition();
+        resource.setId(ann.id());
+        resource.setName(ann.name());
+        resource.setLogical(ann.logical());
+        resource.setDescription(String.join("\n", ann.description()));
+        for (ResourceAction action : ann.actions()) {
+            putAnnotation(resource, action);
         }
         }
-        message = authorize.message();
-        phased = authorize.phased();
-        put(authorize.dataAccess());
+        resources.addResource(resource, ann.merge());
     }
     }
 
 
-    public void put(RequiresExpression expression) {
-        if (null == expression) {
-            return;
+    public ResourceActionDefinition putAnnotation(ResourceDefinition definition, ResourceAction ann) {
+        ResourceActionDefinition actionDefinition = new ResourceActionDefinition();
+        actionDefinition.setId(ann.id());
+        actionDefinition.setName(ann.name());
+        actionDefinition.setDescription(String.join("\n", ann.description()));
+        for (DataAccess dataAccess : ann.dataAccess()) {
+            putAnnotation(actionDefinition, dataAccess);
         }
         }
-        script = new DefaultScript(expression.language(), expression.value());
+        definition.addAction(actionDefinition);
+        return actionDefinition;
     }
     }
 
 
-    public void put(RequiresDataAccess dataAccess) {
-        if (null == dataAccess || dataAccess.ignore()) {
+
+    public void putAnnotation(ResourceActionDefinition definition, DataAccess ann) {
+        if (ann.ignore()) {
             return;
             return;
         }
         }
-        if (!"".equals(dataAccess.permission())) {
-            permissions.add(dataAccess.permission());
-        }
-        actions.addAll(Arrays.asList(dataAccess.action()));
-        DefaultDataAccessDefinition definition = new DefaultDataAccessDefinition();
-        definition.setEntityType(dataAccess.entityType());
-        definition.setPhased(dataAccess.phased());
-        if (!"".equals(dataAccess.controllerBeanName())) {
-            definition.setController(dataAccess.controllerBeanName());
-        } else if (DataAccessController.class != dataAccess.controllerClass()) {
-            definition.setController(dataAccess.getClass().getName());
+        DataAccessTypeDefinition typeDefinition = new DataAccessTypeDefinition();
+        for (DataAccessType dataAccessType : ann.type()) {
+            typeDefinition.setId(dataAccessType.id());
+            typeDefinition.setName(dataAccessType.name());
+            typeDefinition.setController(dataAccessType.controller());
+            typeDefinition.setDescription(String.join("\n", dataAccessType.description()));
         }
         }
-        dataAccessDefinition = definition;
-        dataAccessControl = true;
+        definition.getDataAccess()
+                .getDataAccessTypes()
+                .add(typeDefinition);
     }
     }
 
 
+    public void putAnnotation(ResourceActionDefinition definition, DataAccessType dataAccessType) {
+        DataAccessTypeDefinition typeDefinition = new DataAccessTypeDefinition();
+        typeDefinition.setId(dataAccessType.id());
+        typeDefinition.setName(dataAccessType.name());
+        typeDefinition.setController(dataAccessType.controller());
+        typeDefinition.setDescription(String.join("\n", dataAccessType.description()));
+        definition.getDataAccess()
+                .getDataAccessTypes()
+                .add(typeDefinition);
+    }
 
 
 }
 }

+ 0 - 26
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultDataAccessDefinition.java

@@ -1,26 +0,0 @@
-package org.hswebframework.web.authorization.basic.define;
-
-import lombok.*;
-import org.hswebframework.web.authorization.define.DataAccessDefinition;
-import org.hswebframework.web.authorization.define.Phased;
-
-/**
- * @author zhouhao
- */
-@Getter
-@Setter
-@AllArgsConstructor
-@NoArgsConstructor
-@ToString
-public class DefaultDataAccessDefinition implements DataAccessDefinition {
-
-    private static final long serialVersionUID = 8285566729547666068L;
-
-    private String controller;
-
-    private String idParameterName = "id";
-
-    private Class entityType;
-
-    private Phased phased;
-}

+ 0 - 38
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultScript.java

@@ -1,38 +0,0 @@
-package org.hswebframework.web.authorization.basic.define;
-
-import org.hswebframework.web.authorization.define.Script;
-
-/**
- * @author zhouhao
- */
-public class DefaultScript implements Script {
-    private String language;
-
-    private String script;
-
-    public DefaultScript() {
-    }
-
-    public DefaultScript(String language, String script) {
-        this.language = language;
-        this.script = script;
-    }
-
-    @Override
-    public String getLanguage() {
-        return language;
-    }
-
-    @Override
-    public String getScript() {
-        return script;
-    }
-
-    public void setScript(String script) {
-        this.script = script;
-    }
-
-    public void setLanguage(String language) {
-        this.language = language;
-    }
-}

+ 9 - 56
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/EmptyAuthorizeDefinition.java

@@ -1,80 +1,38 @@
 package org.hswebframework.web.authorization.basic.define;
 package org.hswebframework.web.authorization.basic.define;
 
 
-import org.hswebframework.web.authorization.annotation.Logical;
-import org.hswebframework.web.authorization.define.AuthorizeDefinition;
-import org.hswebframework.web.authorization.define.DataAccessDefinition;
-import org.hswebframework.web.authorization.define.Phased;
-import org.hswebframework.web.authorization.define.Script;
-
-import java.util.Set;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.hswebframework.web.authorization.define.*;
 
 
 /**
 /**
  * @author zhouhao
  * @author zhouhao
  */
  */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
 public class EmptyAuthorizeDefinition implements AuthorizeDefinition {
 public class EmptyAuthorizeDefinition implements AuthorizeDefinition {
 
 
-    public static final EmptyAuthorizeDefinition instance = new EmptyAuthorizeDefinition();
-
-    private EmptyAuthorizeDefinition() {
-    }
-
-    @Override
-    public Phased getPhased() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public int getPriority() {
-        throw new UnsupportedOperationException();
-    }
+    public static EmptyAuthorizeDefinition instance = new EmptyAuthorizeDefinition();
 
 
-    @Override
-    public boolean isDataAccessControl() {
-        throw new UnsupportedOperationException();
-    }
 
 
     @Override
     @Override
-    public Set<String> getPermissions() {
+    public ResourcesDefinition getResources() {
         throw new UnsupportedOperationException();
         throw new UnsupportedOperationException();
     }
     }
 
 
     @Override
     @Override
-    public String[] getPermissionDescription() {
-        throw new UnsupportedOperationException();
-    }
+    public DimensionsDefinition getDimensions() {
 
 
-    @Override
-    public String[] getActionDescription() {
         throw new UnsupportedOperationException();
         throw new UnsupportedOperationException();
     }
     }
 
 
     @Override
     @Override
-    public Set<String> getActions() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public Set<String> getRoles() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public Set<String> getUser() {
-        throw new UnsupportedOperationException();
-    }
+    public String getMessage() {
 
 
-    @Override
-    public Script getScript() {
         throw new UnsupportedOperationException();
         throw new UnsupportedOperationException();
     }
     }
 
 
     @Override
     @Override
-    public String getMessage() {
-        throw new UnsupportedOperationException();
-    }
+    public Phased getPhased() {
 
 
-    @Override
-    public Logical getLogical() {
         throw new UnsupportedOperationException();
         throw new UnsupportedOperationException();
     }
     }
 
 
@@ -82,9 +40,4 @@ public class EmptyAuthorizeDefinition implements AuthorizeDefinition {
     public boolean isEmpty() {
     public boolean isEmpty() {
         return true;
         return true;
     }
     }
-
-    @Override
-    public DataAccessDefinition getDataAccessDefinition() {
-        throw new UnsupportedOperationException();
-    }
 }
 }

+ 2 - 3
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/embed/EmbedAuthenticationInfo.java

@@ -1,6 +1,5 @@
 package org.hswebframework.web.authorization.basic.embed;
 package org.hswebframework.web.authorization.basic.embed;
 
 
-import com.alibaba.fastjson.JSON;
 import lombok.Getter;
 import lombok.Getter;
 import lombok.Setter;
 import lombok.Setter;
 import org.hswebframework.web.authorization.Authentication;
 import org.hswebframework.web.authorization.Authentication;
@@ -77,9 +76,9 @@ public class EmbedAuthenticationInfo {
         user.setId(id);
         user.setId(id);
         user.setName(name);
         user.setName(name);
         user.setUsername(username);
         user.setUsername(username);
-        user.setType(type);
+        user.setUserType(type);
         authentication.setUser(user);
         authentication.setUser(user);
-        authentication.setRoles((List) roles);
+        authentication.getDimensions().addAll(roles);
         List<Permission> permissionList = new ArrayList<>();
         List<Permission> permissionList = new ArrayList<>();
 
 
         permissionList.addAll(permissions.stream()
         permissionList.addAll(permissions.stream()

+ 20 - 134
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/DefaultAuthorizingHandler.java

@@ -1,31 +1,19 @@
 package org.hswebframework.web.authorization.basic.handler;
 package org.hswebframework.web.authorization.basic.handler;
 
 
-import org.apache.commons.codec.digest.DigestUtils;
-import org.apache.commons.collections.CollectionUtils;
-import org.hswebframework.expands.script.engine.DynamicScriptEngine;
-import org.hswebframework.expands.script.engine.DynamicScriptEngineFactory;
-import org.hswebframework.web.aop.MethodInterceptorContext;
 import org.hswebframework.web.authorization.Authentication;
 import org.hswebframework.web.authorization.Authentication;
 import org.hswebframework.web.authorization.Permission;
 import org.hswebframework.web.authorization.Permission;
-import org.hswebframework.web.authorization.Role;
-import org.hswebframework.web.authorization.access.DataAccessConfig;
 import org.hswebframework.web.authorization.access.DataAccessController;
 import org.hswebframework.web.authorization.access.DataAccessController;
-import org.hswebframework.web.authorization.annotation.Logical;
 import org.hswebframework.web.authorization.define.AuthorizeDefinition;
 import org.hswebframework.web.authorization.define.AuthorizeDefinition;
 import org.hswebframework.web.authorization.define.AuthorizingContext;
 import org.hswebframework.web.authorization.define.AuthorizingContext;
 import org.hswebframework.web.authorization.define.HandleType;
 import org.hswebframework.web.authorization.define.HandleType;
-import org.hswebframework.web.authorization.exception.AccessDenyException;
+import org.hswebframework.web.authorization.define.ResourcesDefinition;
 import org.hswebframework.web.authorization.events.AuthorizingHandleBeforeEvent;
 import org.hswebframework.web.authorization.events.AuthorizingHandleBeforeEvent;
+import org.hswebframework.web.authorization.exception.AccessDenyException;
 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.context.ApplicationEventPublisher;
 import org.springframework.context.ApplicationEventPublisher;
 
 
-import java.util.*;
-import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-
 /**
 /**
  * @author zhouhao
  * @author zhouhao
  */
  */
@@ -60,8 +48,6 @@ public class DefaultAuthorizingHandler implements AuthorizingHandler {
         }
         }
         //进行rdac权限控制
         //进行rdac权限控制
         handleRBAC(context.getAuthentication(), context.getDefinition());
         handleRBAC(context.getAuthentication(), context.getDefinition());
-        //表达式权限控制
-        handleExpression(context.getAuthentication(), context.getDefinition(), context.getParamContext());
 
 
     }
     }
 
 
@@ -86,141 +72,41 @@ public class DefaultAuthorizingHandler implements AuthorizingHandler {
             logger.warn("dataAccessController is null,skip result access control!");
             logger.warn("dataAccessController is null,skip result access control!");
             return;
             return;
         }
         }
-        if (context.getDefinition().getDataAccessDefinition() == null) {
+        if (context.getDefinition().getResources() == null) {
             return;
             return;
         }
         }
         if (handleEvent(context, HandleType.DATA)) {
         if (handleEvent(context, HandleType.DATA)) {
             return;
             return;
         }
         }
 
 
-        List<Permission> permission = context.getAuthentication().getPermissions()
-                .stream()
-                .filter(per -> context.getDefinition().getPermissions().contains(per.getId()))
-                .collect(Collectors.toList());
-
         DataAccessController finalAccessController = dataAccessController;
         DataAccessController finalAccessController = dataAccessController;
+        Authentication autz = context.getAuthentication();
 
 
-        //取得当前登录用户持有的控制规则
-        Set<DataAccessConfig> accesses = permission
-                .stream().map(Permission::getDataAccesses)
-                .flatMap(Collection::stream)
-                .filter(access -> context.getDefinition().getActions().contains(access.getAction()))
-                .collect(Collectors.toSet());
-        //无规则,则代表不进行控制
-        if (accesses.isEmpty()) {
-            return;
-        }
-        //单个规则验证函数
-        Function<Predicate<DataAccessConfig>, Boolean> function = accesses.stream()::allMatch;
-        //调用控制器进行验证
-        boolean isAccess = function.apply(access -> finalAccessController.doAccess(access, context));
+        boolean isAccess = context.getDefinition()
+                .getResources()
+                .getDataAccessResources()
+                .stream()
+                .allMatch(resource -> {
+                    Permission permission = autz.getPermission(resource.getId()).orElseThrow(AccessDenyException::new);
+                    return resource.getDataAccessAction()
+                            .stream()
+                            .allMatch(act -> permission.getDataAccesses(act.getId())
+                                    .stream()
+                                    .allMatch(dataAccessConfig -> finalAccessController.doAccess(dataAccessConfig, context)));
+
+                });
         if (!isAccess) {
         if (!isAccess) {
             throw new AccessDenyException(context.getDefinition().getMessage());
             throw new AccessDenyException(context.getDefinition().getMessage());
         }
         }
-
     }
     }
 
 
-    protected void handleExpression(Authentication authentication, AuthorizeDefinition definition, MethodInterceptorContext paramContext) {
-        if (definition.getScript() != null) {
-            String scriptId = DigestUtils.md5Hex(definition.getScript().getScript());
-
-            DynamicScriptEngine engine = DynamicScriptEngineFactory.getEngine(definition.getScript().getLanguage());
-            if (null == engine) {
-                throw new AccessDenyException("{unknown_engine}:" + definition.getScript().getLanguage());
-            }
-            if (!engine.compiled(scriptId)) {
-                try {
-                    engine.compile(scriptId, definition.getScript().getScript());
-                } catch (Exception e) {
-                    logger.error("express compile error", e);
-                    throw new AccessDenyException("{expression_error}");
-                }
-            }
-            Map<String, Object> var = new HashMap<>(paramContext.getParams());
-            var.put("auth", authentication);
-            Object success = engine.execute(scriptId, var).get();
-            if (!(success instanceof Boolean) || !((Boolean) success)) {
-                throw new AccessDenyException(definition.getMessage());
-            }
-        }
-    }
 
 
     protected void handleRBAC(Authentication authentication, AuthorizeDefinition definition) {
     protected void handleRBAC(Authentication authentication, AuthorizeDefinition definition) {
-        boolean access = true;
-        //多个设置时的判断逻辑
-        Logical logical = definition.getLogical() == Logical.DEFAULT ? Logical.OR : definition.getLogical();
-        boolean logicalIsOr = logical == Logical.OR;
-
-        Set<String> permissionsDef = definition.getPermissions();
-        Set<String> actionsDef = definition.getActions();
-        Set<String> rolesDef = definition.getRoles();
-        Set<String> usersDef = definition.getUser();
-
-
-        // 控制权限
-        if (!definition.getPermissions().isEmpty()) {
-            if (logger.isInfoEnabled()) {
-                logger.info("执行权限控制:权限{}({}),操作{}.",
-                        definition.getPermissionDescription(),
-                        permissionsDef,
-                        actionsDef);
-            }
-            List<Permission> permissions = authentication.getPermissions().stream()
-                    .filter(permission -> {
-                        // 未持有任何一个权限
-                        if (!permissionsDef.contains(permission.getId())) {
-                            return false;
-                        }
-                        //未配置action
-                        if (actionsDef.isEmpty()) {
-                            return true;
-                        }
-                        //判断action
-                        List<String> actions = permission.getActions()
-                                .stream()
-                                .filter(actionsDef::contains)
-                                .collect(Collectors.toList());
-
-                        if (actions.isEmpty()) {
-                            return false;
-                        }
-
-                        //如果 控制逻辑是or,则只要过滤结果数量不为0.否则过滤结果数量必须和配置的数量相同
-                        return logicalIsOr || permission.getActions().containsAll(actions);
-                    }).collect(Collectors.toList());
-            access = logicalIsOr ?
-                    CollectionUtils.isNotEmpty(permissions) :
-                    //权限数量和配置的数量相同
-                    permissions.size() == permissionsDef.size();
-        }
-        //控制角色
-        if (!rolesDef.isEmpty()) {
-            if (logger.isInfoEnabled()) {
-                logger.info("do role access handle : roles{} , definition:{}", rolesDef, definition.getRoles());
-            }
-            Function<Predicate<Role>, Boolean> func = logicalIsOr
-                    ? authentication.getRoles().stream()::anyMatch
-                    : authentication.getRoles().stream()::allMatch;
 
 
-            access = logicalIsOr
-                    ? access || func.apply(role -> rolesDef.contains(role.getId()))
-                    : access && func.apply(role -> rolesDef.contains(role.getId()));
-        }
-        //控制用户
-        if (!usersDef.isEmpty()) {
-            if (logger.isInfoEnabled()) {
-                logger.info("do user access handle : users{} , definition:{} ", usersDef, definition.getUser());
-            }
-            Function<Predicate<String>, Boolean> func = logicalIsOr
-                    ? usersDef.stream()::anyMatch
-                    : usersDef.stream()::allMatch;
-            access = logicalIsOr
-                    ? access || func.apply(authentication.getUser().getUsername()::equals)
-                    : access && func.apply(authentication.getUser().getUsername()::equals);
+        ResourcesDefinition resources = definition.getResources();
 
 
-        }
-        if (!access) {
-            throw new AccessDenyException(definition.getMessage());
+        if (!resources.hasPermission(authentication.getPermissions())) {
+            throw new AccessDenyException();
         }
         }
     }
     }
 }
 }

+ 26 - 21
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/UserAllowPermissionHandler.java

@@ -12,16 +12,17 @@ import org.springframework.util.ClassUtils;
 import org.springframework.util.PathMatcher;
 import org.springframework.util.PathMatcher;
 
 
 import java.util.*;
 import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 
 /**
 /**
  * <pre>
  * <pre>
  *     hsweb:
  *     hsweb:
  *        authorize:
  *        authorize:
  *            allows:
  *            allows:
- *               users:
+ *               user:
  *                  admin: *
  *                  admin: *
  *                  guest: **.query*
  *                  guest: **.query*
- *               roles:
+ *               role:
  *                  admin: *
  *                  admin: *
  *
  *
  * </pre>
  * </pre>
@@ -53,26 +54,30 @@ public class UserAllowPermissionHandler {
                 .concat(context.getParamContext()
                 .concat(context.getParamContext()
                         .getMethod().getName());
                         .getMethod().getName());
 
 
-        String userId = context.getAuthentication().getUser().getId();
-        boolean allow;
-        allow = Optional.ofNullable(allows.get("users"))
-                .map(users -> users.get(userId))
-                .filter(pattern -> "*".equals(pattern) || pathMatcher.match(pattern, path))
-                .isPresent();
-        if (allow) {
-            event.setAllow(true);
-            return;
-        }
-        allow = context.getAuthentication()
-                .getRoles()
-                .stream()
-                .map(role -> allows.getOrDefault("roles", Collections.emptyMap()).get(role.getId()))
-                .filter(Objects::nonNull)
-                .anyMatch(pattern -> "*".equals(pattern) || pathMatcher.match(pattern, path));
-        if (allow) {
-            event.setAllow(true);
-            return;
+        AtomicBoolean allow = new AtomicBoolean();
+        for (Map.Entry<String, Map<String, String>> entry : allows.entrySet()) {
+            String dimension = entry.getKey();
+            if ("user".equals(dimension)) {
+                String userId = context.getAuthentication().getUser().getId();
+                allow.set(Optional.ofNullable(entry.getValue().get(userId))
+                        .filter(pattern -> "*".equals(pattern) || pathMatcher.match(pattern, path))
+                        .isPresent());
+            } else { //其他维度
+                for (Map.Entry<String, String> confEntry : entry.getValue().entrySet()) {
+                    context.getAuthentication()
+                            .getDimension(dimension, confEntry.getKey())
+                            .ifPresent(dim -> {
+                                String pattern = confEntry.getValue();
+                                allow.set("*".equals(pattern) || pathMatcher.match(confEntry.getValue(), path));
+                            });
+                }
+            }
+            if (allow.get()) {
+                event.setAllow(true);
+                return;
+            }
         }
         }
+
     }
     }
 
 
 }
 }

+ 0 - 44
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/access/CustomDataAccessHandler.java

@@ -1,44 +0,0 @@
-/*
- *  Copyright 2019 http://www.hswebframework.org
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- *
- */
-
-package org.hswebframework.web.authorization.basic.handler.access;
-
-import org.hswebframework.web.authorization.access.CustomDataAccessConfig;
-import org.hswebframework.web.authorization.access.DataAccessConfig;
-import org.hswebframework.web.authorization.access.DataAccessHandler;
-import org.hswebframework.web.authorization.define.AuthorizingContext;
-
-/**
- * 当配置为自定义处理器时(实现{@link CustomDataAccessConfig }接口),此处理器生效
- *
- * @author zhouhao
- * @see 3.0
- */
-public class CustomDataAccessHandler implements DataAccessHandler {
-
-    @Override
-    public boolean isSupport(DataAccessConfig access) {
-        return access instanceof CustomDataAccessConfig;
-    }
-
-    @Override
-    public boolean handle(DataAccessConfig access, AuthorizingContext context) {
-        CustomDataAccessConfig custom = ((CustomDataAccessConfig) access);
-        return custom.getController().doAccess(access, context);
-    }
-}

+ 2 - 3
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/access/DefaultDataAccessController.java

@@ -30,9 +30,8 @@ public final class DefaultDataAccessController implements DataAccessController {
             throw new UnsupportedOperationException();
             throw new UnsupportedOperationException();
         }
         }
         this.parent = parent;
         this.parent = parent;
-        addHandler(new CustomDataAccessHandler()).
-                addHandler(new FieldFilterDataAccessHandler()).
-                addHandler(new FieldScopeDataAccessHandler());
+
+                addHandler(new FieldFilterDataAccessHandler());
     }
     }
 
 
     @Override
     @Override

+ 1 - 1
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/access/FieldFilterDataAccessHandler.java

@@ -81,7 +81,7 @@ public class FieldFilterDataAccessHandler implements DataAccessHandler {
 
 
     @SuppressWarnings("all")
     @SuppressWarnings("all")
     protected boolean doQueryAccess(FieldFilterDataAccessConfig access, AuthorizingContext context) {
     protected boolean doQueryAccess(FieldFilterDataAccessConfig access, AuthorizingContext context) {
-        if (context.getDefinition().getDataAccessDefinition().getPhased() == Phased.before) {
+        if (context.getDefinition().getResources().getPhased() == Phased.before) {
             QueryParam entity = context.getParamContext().getParams()
             QueryParam entity = context.getParamContext().getParams()
                     .values().stream()
                     .values().stream()
                     .filter(QueryParam.class::isInstance)
                     .filter(QueryParam.class::isInstance)

+ 0 - 143
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/access/FieldScopeDataAccessHandler.java

@@ -1,143 +0,0 @@
-package org.hswebframework.web.authorization.basic.handler.access;
-
-import org.apache.commons.beanutils.BeanUtilsBean;
-import org.apache.commons.beanutils.PropertyUtilsBean;
-import org.hswebframework.ezorm.core.param.QueryParam;
-import org.hswebframework.ezorm.core.param.Term;
-import org.hswebframework.ezorm.core.param.TermType;
-import org.hswebframework.web.authorization.Permission;
-import org.hswebframework.web.authorization.access.DataAccessConfig;
-import org.hswebframework.web.authorization.access.DataAccessHandler;
-import org.hswebframework.web.authorization.access.FieldScopeDataAccessConfig;
-import org.hswebframework.web.authorization.define.AuthorizingContext;
-import org.hswebframework.web.authorization.define.Phased;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-
-/**
- * @author zhouhao
- */
-public class FieldScopeDataAccessHandler implements DataAccessHandler {
-    private PropertyUtilsBean propertyUtilsBean = BeanUtilsBean.getInstance().getPropertyUtils();
-
-    private final Logger logger = LoggerFactory.getLogger(this.getClass());
-
-    @Override
-    public boolean isSupport(DataAccessConfig access) {
-        return access instanceof FieldScopeDataAccessConfig;
-    }
-
-    @Override
-    public boolean handle(DataAccessConfig access, AuthorizingContext context) {
-        FieldScopeDataAccessConfig own = ((FieldScopeDataAccessConfig) access);
-        Object controller = context.getParamContext().getTarget();
-        if (controller != null) {
-            switch (access.getAction()) {
-                case Permission.ACTION_QUERY:
-                case Permission.ACTION_GET:
-                    return doQueryAccess(own, context);
-                case Permission.ACTION_DELETE:
-                case Permission.ACTION_UPDATE:
-                    return doRWAccess(own, context, controller);
-                case Permission.ACTION_ADD:
-                default:
-                    logger.warn("action: {} not support now!", access.getAction());
-            }
-        } else {
-            logger.warn("target is null!");
-        }
-        return true;
-    }
-
-    @SuppressWarnings("unchecked")
-    protected boolean doRWAccess(FieldScopeDataAccessConfig access, AuthorizingContext context, Object controller) {
-        //获取注解
-        Object id = context.getParamContext().<String>getParameter(context.getDefinition().getDataAccessDefinition().getIdParameterName()).orElse(null);
-        //通过QueryController获取QueryService
-        //然后调用selectByPk 查询旧的数据,进行对比
-//        if (controller instanceof QueryController) {
-//            QueryService queryService = (QueryService) ((QueryController) controller).getService();
-//            Object oldData = queryService.selectByPk(id);
-//            if (oldData != null) {
-//                try {
-//                    Object value = propertyUtilsBean.getProperty(oldData, access.getField());
-//                    return access.getScope().contains(value);
-//                } catch (Exception e) {
-//                    logger.error("can't read property {}", access.getField(), e);
-//                }
-//                return false;
-//            }
-//        } else {
-//            logger.warn("controller is not instanceof QueryController");
-//        }
-        return true;
-    }
-
-
-    @SuppressWarnings("all")
-    protected boolean doQueryAccess(FieldScopeDataAccessConfig access, AuthorizingContext context) {
-        if (context.getDefinition().getDataAccessDefinition().getPhased() == Phased.before) {
-            QueryParam entity = context.getParamContext().getParams()
-                    .values().stream()
-                    .filter(QueryParam.class::isInstance)
-                    .map(QueryParam.class::cast)
-                    .findAny().orElse(null);
-            if (entity == null) {
-                logger.warn("try validate query access, but query entity is null or not instance of org.hswebframework.web.commons.entity.Entity");
-                return true;
-            }
-            //重构查询条件
-            //如: 旧的条件为 where column =? or column = ?
-            //重构后为: where creatorId=? and (column = ? or column = ?)
-            List<Term> oldParam = entity.getTerms();
-            //清空旧的查询条件
-            entity.setTerms(new ArrayList<>());
-            //添加一个查询条件
-            entity.addTerm(createQueryTerm(access))
-                    //客户端提交的参数 作为嵌套参数
-                    .nest().setTerms(oldParam);
-        } else {
-            Object result = InvokeResultUtils.convertRealResult(context.getParamContext().getInvokeResult());
-            if (result == null) {
-                return true;
-            }
-            if (result instanceof Collection) {
-                return ((Collection) result).stream().allMatch(obj -> propertyInScope(obj, access.getField(), access.getScope()));
-            } else {
-                return propertyInScope(result, access.getField(), access.getScope());
-            }
-        }
-        return true;
-    }
-
-    protected boolean propertyInScope(Object obj, String property, Set<Object> scope) {
-        if (null == obj) {
-            return false;
-        }
-        try {
-            Object value = BeanUtilsBean.getInstance().getProperty(obj, property);
-            if (null != value) {
-                return scope.contains(value);
-            }
-        } catch (Exception ignore) {
-            logger.warn("can not get property {} from {},{}", property, obj, ignore.getMessage());
-        }
-        return true;
-
-    }
-
-    protected Term createQueryTerm(FieldScopeDataAccessConfig access) {
-        Term term = new Term();
-        term.setType(Term.Type.and);
-        term.setColumn(access.getField());
-        term.setTermType(TermType.in);
-        term.setValue(access.getScope());
-        return term;
-    }
-}

+ 10 - 8
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/AuthorizationController.java

@@ -26,6 +26,7 @@ import org.hswebframework.web.authorization.AuthenticationManager;
 import org.hswebframework.web.authorization.ReactiveAuthenticationManager;
 import org.hswebframework.web.authorization.ReactiveAuthenticationManager;
 import org.hswebframework.web.authorization.annotation.Authorize;
 import org.hswebframework.web.authorization.annotation.Authorize;
 import org.hswebframework.web.authorization.events.*;
 import org.hswebframework.web.authorization.events.*;
+import org.hswebframework.web.authorization.exception.UnAuthorizedException;
 import org.hswebframework.web.authorization.simple.PlainTextUsernamePasswordAuthenticationRequest;
 import org.hswebframework.web.authorization.simple.PlainTextUsernamePasswordAuthenticationRequest;
 import org.hswebframework.web.logging.AccessLogger;
 import org.hswebframework.web.logging.AccessLogger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -57,29 +58,30 @@ public class AuthorizationController {
     @GetMapping("/me")
     @GetMapping("/me")
     @Authorize
     @Authorize
     @ApiOperation("当前登录用户权限信息")
     @ApiOperation("当前登录用户权限信息")
-    public Mono<Authentication> me(@ApiParam(hidden = true) Mono<Authentication> authentication) {
-        return authentication;
+    public Mono<Authentication> me() {
+        return Authentication.currentReactive()
+                .switchIfEmpty(Mono.error(UnAuthorizedException::new));
     }
     }
 
 
     @PostMapping(value = "/login", consumes = MediaType.APPLICATION_JSON_VALUE)
     @PostMapping(value = "/login", consumes = MediaType.APPLICATION_JSON_VALUE)
     @ApiOperation("用户名密码登录,json方式")
     @ApiOperation("用户名密码登录,json方式")
     public Mono<Map<String, Object>> authorizeByJson(@ApiParam(example = "{\"username\":\"admin\",\"password\":\"admin\"}")
     public Mono<Map<String, Object>> authorizeByJson(@ApiParam(example = "{\"username\":\"admin\",\"password\":\"admin\"}")
-                                                     @RequestBody Map<String, Object> parameter) {
-        return doLogin(Mono.just(parameter));
+                                                     @RequestBody Mono<Map<String, Object>> parameter) {
+        return doLogin(parameter);
     }
     }
 
 
     @PostMapping(value = "/login", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
     @PostMapping(value = "/login", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
     @ApiOperation("用户名密码登录,参数方式")
     @ApiOperation("用户名密码登录,参数方式")
-    public Mono<Map<String, Object>> authorizeByUrlEncoded(@ApiParam(hidden = true) @RequestParam Mono<Map<String, Object>> parameter) {
+    public Mono<Map<String, Object>> authorizeByUrlEncoded(@ApiParam(hidden = true) @RequestParam Map<String, Object> parameter) {
 
 
-        return doLogin(parameter);
+        return doLogin(Mono.just(parameter));
     }
     }
 
 
     /**
     /**
-     * <img src="https://raw.githubusercontent.com/hs-web/hsweb-framework/3.0.x/hsweb-authorization/hsweb-authorization-basic/img/autz-flow.png">
+     * <img src="https://raw.githubusercontent.com/hs-web/hsweb-framework/4.0.x/hsweb-authorization/hsweb-authorization-basic/img/autz-flow.png">
      */
      */
     @SneakyThrows
     @SneakyThrows
-    protected Mono<Map<String, Object>> doLogin(Mono<Map<String, Object>> parameter) {
+    private Mono<Map<String, Object>> doLogin(Mono<Map<String, Object>> parameter) {
 
 
         return parameter.flatMap(parameters -> {
         return parameter.flatMap(parameters -> {
             String username = (String) parameters.get("username");
             String username = (String) parameters.get("username");

+ 20 - 20
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/ReactiveUserTokenController.java

@@ -1,12 +1,12 @@
 package org.hswebframework.web.authorization.basic.web;
 package org.hswebframework.web.authorization.basic.web;
 
 
-import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiOperation;
 import org.hswebframework.web.authorization.Authentication;
 import org.hswebframework.web.authorization.Authentication;
-import org.hswebframework.web.authorization.AuthenticationManager;
-import org.hswebframework.web.authorization.Permission;
 import org.hswebframework.web.authorization.ReactiveAuthenticationManager;
 import org.hswebframework.web.authorization.ReactiveAuthenticationManager;
 import org.hswebframework.web.authorization.annotation.Authorize;
 import org.hswebframework.web.authorization.annotation.Authorize;
+import org.hswebframework.web.authorization.annotation.QueryAction;
+import org.hswebframework.web.authorization.annotation.Resource;
+import org.hswebframework.web.authorization.annotation.SaveAction;
 import org.hswebframework.web.authorization.exception.UnAuthorizedException;
 import org.hswebframework.web.authorization.exception.UnAuthorizedException;
 import org.hswebframework.web.authorization.token.TokenState;
 import org.hswebframework.web.authorization.token.TokenState;
 import org.hswebframework.web.authorization.token.UserToken;
 import org.hswebframework.web.authorization.token.UserToken;
@@ -21,8 +21,8 @@ import reactor.core.publisher.Mono;
 
 
 @RestController
 @RestController
 @RequestMapping
 @RequestMapping
-@Authorize(permission = "user-token", description = "用户令牌信息管理")
-@Api(tags = "权限-用户令牌管理", value = "权限-用户令牌管理")
+@Authorize
+@Resource(id = "user-token", name = "用户令牌信息管理")
 public class ReactiveUserTokenController {
 public class ReactiveUserTokenController {
     private UserTokenManager userTokenManager;
     private UserTokenManager userTokenManager;
 
 
@@ -52,7 +52,7 @@ public class ReactiveUserTokenController {
 
 
     @PutMapping("/user-token/check")
     @PutMapping("/user-token/check")
     @ApiOperation("检查所有已过期的token并移除")
     @ApiOperation("检查所有已过期的token并移除")
-    @Authorize(action = Permission.ACTION_UPDATE)
+    @SaveAction
     public Mono<Boolean> checkExpiredToken() {
     public Mono<Boolean> checkExpiredToken() {
         return userTokenManager
         return userTokenManager
                 .checkExpiredToken()
                 .checkExpiredToken()
@@ -61,71 +61,71 @@ public class ReactiveUserTokenController {
 
 
     @GetMapping("/user-token/token/{token}")
     @GetMapping("/user-token/token/{token}")
     @ApiOperation("根据token获取令牌信息")
     @ApiOperation("根据token获取令牌信息")
-    @Authorize(action = Permission.ACTION_GET)
+    @QueryAction
     public Mono<UserToken> getByToken(@PathVariable String token) {
     public Mono<UserToken> getByToken(@PathVariable String token) {
         return userTokenManager.getByToken(token);
         return userTokenManager.getByToken(token);
     }
     }
 
 
     @GetMapping("/user-token/user/{userId}")
     @GetMapping("/user-token/user/{userId}")
     @ApiOperation("根据用户ID获取全部令牌信息")
     @ApiOperation("根据用户ID获取全部令牌信息")
-    @Authorize(action = Permission.ACTION_GET)
+    @QueryAction
     public Flux<UserToken> getByUserId(@PathVariable String userId) {
     public Flux<UserToken> getByUserId(@PathVariable String userId) {
         return userTokenManager.getByUserId(userId);
         return userTokenManager.getByUserId(userId);
     }
     }
 
 
     @GetMapping("/user-token/user/{userId}/logged")
     @GetMapping("/user-token/user/{userId}/logged")
     @ApiOperation("根据用户ID判断用户是否已经登录")
     @ApiOperation("根据用户ID判断用户是否已经登录")
-    @Authorize(action = Permission.ACTION_GET)
+    @QueryAction
     public Mono<Boolean> userIsLoggedIn(@PathVariable String userId) {
     public Mono<Boolean> userIsLoggedIn(@PathVariable String userId) {
         return userTokenManager.userIsLoggedIn(userId);
         return userTokenManager.userIsLoggedIn(userId);
     }
     }
 
 
     @GetMapping("/user-token/token/{token}/logged")
     @GetMapping("/user-token/token/{token}/logged")
     @ApiOperation("根据令牌判断用户是否已经登录")
     @ApiOperation("根据令牌判断用户是否已经登录")
-    @Authorize(action = Permission.ACTION_GET)
+    @QueryAction
     public Mono<Boolean> tokenIsLoggedIn(@PathVariable String token) {
     public Mono<Boolean> tokenIsLoggedIn(@PathVariable String token) {
         return userTokenManager.tokenIsLoggedIn(token);
         return userTokenManager.tokenIsLoggedIn(token);
     }
     }
 
 
     @GetMapping("/user-token/user/total")
     @GetMapping("/user-token/user/total")
     @ApiOperation("获取当前已经登录的用户数量")
     @ApiOperation("获取当前已经登录的用户数量")
-    @Authorize
+    @Authorize(merge = false)
     public Mono<Integer> totalUser() {
     public Mono<Integer> totalUser() {
         return userTokenManager.totalUser();
         return userTokenManager.totalUser();
     }
     }
 
 
     @GetMapping("/user-token/token/total")
     @GetMapping("/user-token/token/total")
     @ApiOperation("获取当前已经登录的令牌数量")
     @ApiOperation("获取当前已经登录的令牌数量")
-    @Authorize
+    @Authorize(merge = false)
     public Mono<Integer> totalToken() {
     public Mono<Integer> totalToken() {
         return userTokenManager.totalToken();
         return userTokenManager.totalToken();
     }
     }
 
 
     @GetMapping("/user-token")
     @GetMapping("/user-token")
     @ApiOperation("获取全部用户令牌信息")
     @ApiOperation("获取全部用户令牌信息")
-    @Authorize(action = Permission.ACTION_GET)
+    @QueryAction
     public Flux<UserToken> allLoggedUser() {
     public Flux<UserToken> allLoggedUser() {
         return userTokenManager.allLoggedUser();
         return userTokenManager.allLoggedUser();
     }
     }
 
 
     @DeleteMapping("/user-token/user/{userId}")
     @DeleteMapping("/user-token/user/{userId}")
     @ApiOperation("根据用户id将用户踢下线")
     @ApiOperation("根据用户id将用户踢下线")
-    @Authorize(action = Permission.ACTION_UPDATE)
+    @SaveAction
     public Mono<Void> signOutByUserId(@PathVariable String userId) {
     public Mono<Void> signOutByUserId(@PathVariable String userId) {
         return userTokenManager.signOutByUserId(userId);
         return userTokenManager.signOutByUserId(userId);
     }
     }
 
 
     @DeleteMapping("/user-token/token/{token}")
     @DeleteMapping("/user-token/token/{token}")
     @ApiOperation("根据令牌将用户踢下线")
     @ApiOperation("根据令牌将用户踢下线")
-    @Authorize(action = Permission.ACTION_UPDATE)
+    @SaveAction
     public Mono<Void> signOutByToken(@PathVariable String token) {
     public Mono<Void> signOutByToken(@PathVariable String token) {
         return userTokenManager.signOutByToken(token);
         return userTokenManager.signOutByToken(token);
 
 
     }
     }
 
 
+    @SaveAction
     @PutMapping("/user-token/user/{userId}/{state}")
     @PutMapping("/user-token/user/{userId}/{state}")
     @ApiOperation("根据用户id更新用户令牌状态")
     @ApiOperation("根据用户id更新用户令牌状态")
-    @Authorize(action = Permission.ACTION_UPDATE)
     public Mono<Void> changeUserState(@PathVariable String userId, @PathVariable TokenState state) {
     public Mono<Void> changeUserState(@PathVariable String userId, @PathVariable TokenState state) {
 
 
         return userTokenManager.changeUserState(userId, state);
         return userTokenManager.changeUserState(userId, state);
@@ -133,28 +133,28 @@ public class ReactiveUserTokenController {
 
 
     @PutMapping("/user-token/token/{token}/{state}")
     @PutMapping("/user-token/token/{token}/{state}")
     @ApiOperation("根据令牌更新用户令牌状态")
     @ApiOperation("根据令牌更新用户令牌状态")
-    @Authorize(action = Permission.ACTION_UPDATE)
+    @SaveAction
     public Mono<Void> changeTokenState(@PathVariable String token, @PathVariable TokenState state) {
     public Mono<Void> changeTokenState(@PathVariable String token, @PathVariable TokenState state) {
         return userTokenManager.changeTokenState(token, state);
         return userTokenManager.changeTokenState(token, state);
     }
     }
 
 
     @PostMapping("/user-token/{token}/{type}/{userId}/{maxInactiveInterval}")
     @PostMapping("/user-token/{token}/{type}/{userId}/{maxInactiveInterval}")
     @ApiOperation("将用户设置为登录")
     @ApiOperation("将用户设置为登录")
-    @Authorize(action = Permission.ACTION_ADD)
+    @SaveAction
     public Mono<UserToken> signIn(@PathVariable String token, @PathVariable String type, @PathVariable String userId, @PathVariable long maxInactiveInterval) {
     public Mono<UserToken> signIn(@PathVariable String token, @PathVariable String type, @PathVariable String userId, @PathVariable long maxInactiveInterval) {
         return userTokenManager.signIn(token, type, userId, maxInactiveInterval);
         return userTokenManager.signIn(token, type, userId, maxInactiveInterval);
     }
     }
 
 
     @GetMapping("/user-token/{token}/touch")
     @GetMapping("/user-token/{token}/touch")
     @ApiOperation("更新token有效期")
     @ApiOperation("更新token有效期")
-    @Authorize(action = Permission.ACTION_UPDATE)
+    @SaveAction
     public Mono<Void> touch(@PathVariable String token) {
     public Mono<Void> touch(@PathVariable String token) {
         return userTokenManager.touch(token);
         return userTokenManager.touch(token);
     }
     }
 
 
     @GetMapping("/user-auth/{userId}")
     @GetMapping("/user-auth/{userId}")
     @ApiOperation("根据用户id获取用户的权限信息")
     @ApiOperation("根据用户id获取用户的权限信息")
-    @Authorize(action = Permission.ACTION_GET)
+    @SaveAction
     public Mono<Authentication> userAuthInfo(@PathVariable String userId) {
     public Mono<Authentication> userAuthInfo(@PathVariable String userId) {
         return authenticationManager.getByUserId(userId);
         return authenticationManager.getByUserId(userId);
     }
     }

+ 7 - 4
hsweb-authorization/hsweb-authorization-basic/src/test/java/org/hswebframework/web/authorization/basic/aop/TestController.java

@@ -3,23 +3,26 @@ package org.hswebframework.web.authorization.basic.aop;
 import org.hswebframework.web.authorization.Authentication;
 import org.hswebframework.web.authorization.Authentication;
 import org.hswebframework.web.authorization.User;
 import org.hswebframework.web.authorization.User;
 import org.hswebframework.web.authorization.annotation.Authorize;
 import org.hswebframework.web.authorization.annotation.Authorize;
+import org.hswebframework.web.authorization.annotation.QueryAction;
+import org.hswebframework.web.authorization.annotation.Resource;
 import org.hswebframework.web.authorization.define.Phased;
 import org.hswebframework.web.authorization.define.Phased;
 import org.hswebframework.web.authorization.exception.UnAuthorizedException;
 import org.hswebframework.web.authorization.exception.UnAuthorizedException;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.bind.annotation.RestController;
 import reactor.core.publisher.Mono;
 import reactor.core.publisher.Mono;
 
 
 @RestController
 @RestController
+@Resource(id = "test", name = "测试")
 public class TestController {
 public class TestController {
 
 
-    @Authorize(permission = "test")
-    public Mono<User> getUser(){
+    @QueryAction
+    public Mono<User> getUser() {
         return Authentication.currentReactive()
         return Authentication.currentReactive()
                 .switchIfEmpty(Mono.error(new UnAuthorizedException()))
                 .switchIfEmpty(Mono.error(new UnAuthorizedException()))
                 .map(Authentication::getUser);
                 .map(Authentication::getUser);
     }
     }
 
 
-    @Authorize(permission = "test",phased = Phased.after)
-    public Mono<User> getUserAfter(){
+    @QueryAction
+    public Mono<User> getUserAfter() {
         return Authentication.currentReactive()
         return Authentication.currentReactive()
                 .switchIfEmpty(Mono.error(new UnAuthorizedException()))
                 .switchIfEmpty(Mono.error(new UnAuthorizedException()))
                 .map(Authentication::getUser);
                 .map(Authentication::getUser);

+ 62 - 0
hsweb-authorization/hsweb-authorization-basic/src/test/java/org/hswebframework/web/authorization/basic/define/DefaultBasicAuthorizeDefinitionTest.java

@@ -0,0 +1,62 @@
+package org.hswebframework.web.authorization.basic.define;
+
+import lombok.SneakyThrows;
+import org.hswebframework.web.authorization.annotation.*;
+import org.hswebframework.web.authorization.define.AopAuthorizeDefinition;
+import org.hswebframework.web.authorization.define.ResourceDefinition;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Arrays;
+
+public class DefaultBasicAuthorizeDefinitionTest {
+
+
+    @Test
+    @SneakyThrows
+    public void testCustomAnn() {
+        AopAuthorizeDefinition definition =
+                DefaultBasicAuthorizeDefinition.from(TestController.class, TestController.class.getMethod("test"));
+
+        ResourceDefinition resource = definition.getResources()
+                .getResource("test").orElseThrow(NullPointerException::new);
+
+        Assert.assertNotNull(resource);
+
+        Assert.assertTrue(resource.hasAction(Arrays.asList("add")));
+
+        Assert.assertTrue(resource.getAction("add")
+                .map(act->act.getDataAccess().getType("user_own"))
+                .isPresent());
+    }
+
+    @Test
+    @SneakyThrows
+    public void testNoMerge() {
+        AopAuthorizeDefinition definition =
+                DefaultBasicAuthorizeDefinition.from(TestController.class, TestController.class.getMethod("noMerge"));
+        Assert.assertTrue(definition.isEmpty());
+    }
+
+
+    @Resource(id = "test", name = "测试")
+    public class TestController implements GenericController {
+
+        @Authorize(merge = false)
+        public void noMerge(){
+
+        }
+
+    }
+
+    public interface GenericController {
+
+        @CreateAction
+        @UserOwnData
+        default void test(){
+
+        }
+    }
+
+
+}

+ 4 - 0
hsweb-core/pom.xml

@@ -20,6 +20,10 @@
             <artifactId>javassist</artifactId>
             <artifactId>javassist</artifactId>
             <version>3.22.0-GA</version>
             <version>3.22.0-GA</version>
         </dependency>
         </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
         <dependency>
         <dependency>
             <groupId>org.hswebframework</groupId>
             <groupId>org.hswebframework</groupId>
             <artifactId>hsweb-utils</artifactId>
             <artifactId>hsweb-utils</artifactId>

+ 99 - 7
hsweb-core/src/main/java/org/hswebframework/web/dict/EnumDict.java

@@ -9,12 +9,28 @@ import com.alibaba.fastjson.parser.JSONToken;
 import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
 import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
 import com.alibaba.fastjson.serializer.JSONSerializable;
 import com.alibaba.fastjson.serializer.JSONSerializable;
 import com.alibaba.fastjson.serializer.JSONSerializer;
 import com.alibaba.fastjson.serializer.JSONSerializer;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.deser.std.EnumDeserializer;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.fasterxml.jackson.databind.util.EnumResolver;
+import lombok.extern.slf4j.Slf4j;
+import org.hswebframework.web.exception.ValidationException;
+import org.springframework.beans.BeanUtils;
 
 
 import java.io.IOException;
 import java.io.IOException;
 import java.lang.reflect.Type;
 import java.lang.reflect.Type;
 import java.util.*;
 import java.util.*;
 import java.util.function.Predicate;
 import java.util.function.Predicate;
 import java.util.function.Supplier;
 import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 
 /**
 /**
  * 枚举字典,使用枚举来实现数据字典,可通过集成此接口来实现一些有趣的功能.
  * 枚举字典,使用枚举来实现数据字典,可通过集成此接口来实现一些有趣的功能.
@@ -28,6 +44,7 @@ import java.util.function.Supplier;
  * @see JSONSerializable
  * @see JSONSerializable
  */
  */
 @JSONType(deserializer = EnumDict.EnumDictJSONDeserializer.class)
 @JSONType(deserializer = EnumDict.EnumDictJSONDeserializer.class)
+@JsonDeserialize(contentUsing = EnumDict.EnumDictJSONDeserializer.class)
 public interface EnumDict<V> extends JSONSerializable {
 public interface EnumDict<V> extends JSONSerializable {
 
 
     /**
     /**
@@ -108,6 +125,13 @@ public interface EnumDict<V> extends JSONSerializable {
         return getText();
         return getText();
     }
     }
 
 
+    @JsonCreator
+    default EnumDict<V> fromJsonNode(Object val) {
+
+        return null;
+    }
+
+
     /**
     /**
      * 从指定的枚举类中查找想要的枚举,并返回一个{@link Optional},如果未找到,则返回一个{@link Optional#empty()}
      * 从指定的枚举类中查找想要的枚举,并返回一个{@link Optional},如果未找到,则返回一个{@link Optional#empty()}
      *
      *
@@ -127,6 +151,15 @@ public interface EnumDict<V> extends JSONSerializable {
         return Optional.empty();
         return Optional.empty();
     }
     }
 
 
+    static <T extends Enum & EnumDict> List<T> findList(Class<T> type, Predicate<T> predicate) {
+        if (type.isEnum()) {
+            return Arrays.stream(type.getEnumConstants())
+                    .filter(predicate)
+                    .collect(Collectors.toList());
+        }
+        return Collections.emptyList();
+    }
+
     /**
     /**
      * 根据枚举的{@link EnumDict#getValue()}来查找.
      * 根据枚举的{@link EnumDict#getValue()}来查找.
      *
      *
@@ -236,13 +269,18 @@ public interface EnumDict<V> extends JSONSerializable {
      * @return 最终序列化的值
      * @return 最终序列化的值
      * @see this#isWriteJSONObjectEnabled()
      * @see this#isWriteJSONObjectEnabled()
      */
      */
+    @JsonValue
     default Object getWriteJSONObject() {
     default Object getWriteJSONObject() {
-        JSONObject jsonObject = new JSONObject();
-        jsonObject.put("value", getValue());
-        jsonObject.put("text", getText());
-        jsonObject.put("index", index());
-        jsonObject.put("mask", getMask());
-        return jsonObject;
+        if (isWriteJSONObjectEnabled()) {
+            Map<String, Object> jsonObject = new HashMap<>();
+            jsonObject.put("value", getValue());
+            jsonObject.put("text", getText());
+            // jsonObject.put("index", index());
+            // jsonObject.put("mask", getMask());
+            return jsonObject;
+        }
+
+        return this.getValue();
     }
     }
 
 
     @Override
     @Override
@@ -257,7 +295,8 @@ public interface EnumDict<V> extends JSONSerializable {
     /**
     /**
      * 自定义fastJson枚举序列化
      * 自定义fastJson枚举序列化
      */
      */
-    class EnumDictJSONDeserializer implements ObjectDeserializer {
+    @Slf4j
+    class EnumDictJSONDeserializer extends JsonDeserializer implements ObjectDeserializer {
 
 
         @Override
         @Override
         @SuppressWarnings("all")
         @SuppressWarnings("all")
@@ -303,6 +342,59 @@ public interface EnumDict<V> extends JSONSerializable {
         public int getFastMatchToken() {
         public int getFastMatchToken() {
             return JSONToken.LITERAL_STRING;
             return JSONToken.LITERAL_STRING;
         }
         }
+
+        @Override
+        @SuppressWarnings("all")
+        public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
+            JsonNode node = jp.getCodec().readTree(jp);
+
+            String currentName = jp.currentName();
+            Object currentValue = jp.getCurrentValue();
+            Class findPropertyType;
+            if (currentName == null || currentValue == null) {
+                return null;
+            } else {
+                findPropertyType = BeanUtils.findPropertyType(currentName, currentValue.getClass());
+            }
+
+            if (EnumDict.class.isAssignableFrom(findPropertyType) && findPropertyType.isEnum()) {
+                if (node.isObject()) {
+                    return (EnumDict) EnumDict
+                            .findByValue(findPropertyType, node.get("value").textValue())
+                            .orElse(null);
+                }
+                if (node.isNumber()) {
+                    return (EnumDict) EnumDict
+                            .find(findPropertyType, node.numberValue())
+                            .orElse(null);
+                }
+                if (node.isTextual()) {
+                    return (EnumDict) EnumDict
+                            .find(findPropertyType, node.textValue())
+                            .orElse(null);
+                }
+                throw new ValidationException("参数[" + currentName + "]在选项中不存在", Arrays.asList(
+                        new ValidationException.Detail(currentName, "选项中不存在此值", null)
+                ));
+            }
+            if (findPropertyType.isEnum()) {
+                return Stream.of(findPropertyType.getEnumConstants())
+                        .filter(o -> {
+                            if (node.isTextual()) {
+                                return node.textValue().equalsIgnoreCase(((Enum) o).name());
+                            }
+                            if (node.isNumber()) {
+                                return node.intValue() == ((Enum) o).ordinal();
+                            }
+                            return false;
+                        })
+                        .findAny()
+                        .orElse(null);
+            }
+
+            log.warn("unsupported deserialize enum json : {}", node);
+            return null;
+        }
     }
     }
 
 
 }
 }

+ 3 - 1
hsweb-core/src/main/java/org/hswebframework/web/exception/ValidationException.java

@@ -29,7 +29,7 @@ public class ValidationException extends BusinessException {
         if (null != violations && !violations.isEmpty()) {
         if (null != violations && !violations.isEmpty()) {
             details = new ArrayList<>();
             details = new ArrayList<>();
             for (ConstraintViolation<?> violation : violations) {
             for (ConstraintViolation<?> violation : violations) {
-                details.add(new Detail(violation.getPropertyPath().toString(), violation.getMessage()));
+                details.add(new Detail(violation.getPropertyPath().toString(), violation.getMessage(), null));
             }
             }
         }
         }
     }
     }
@@ -41,5 +41,7 @@ public class ValidationException extends BusinessException {
         String property;
         String property;
 
 
         String message;
         String message;
+
+        Object detail;
     }
     }
 }
 }

+ 57 - 0
hsweb-core/src/test/java/org/hswebframework/web/dict/EnumDictTest.java

@@ -0,0 +1,57 @@
+package org.hswebframework.web.dict;
+
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.SneakyThrows;
+import org.junit.Assert;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class EnumDictTest {
+
+    @Test
+    @SneakyThrows
+    public void testJackson() {
+        ObjectMapper mapper = new ObjectMapper();
+        SimpleModule module = new SimpleModule();
+        JsonDeserializer<EnumDict> deserialize = new EnumDict.EnumDictJSONDeserializer();
+        module.addDeserializer(Enum.class, (JsonDeserializer) deserialize);
+        mapper.registerModule(module);
+
+
+        String val = mapper.writer().writeValueAsString(new TestEntity());
+
+
+        TestEntity testEntity = mapper.readerFor(TestEntity.class)
+                .readValue(val);
+
+        Assert.assertEquals(testEntity.testEnum, TestEnum.E1);
+        testEntity = mapper.readerFor(TestEntity.class)
+                .readValue("{\"testEnum\":\"E1\"}");
+        Assert.assertEquals(testEntity.testEnum, TestEnum.E1);
+
+        testEntity = mapper.readerFor(TestEntity.class)
+                .readValue("{\"testEnum\":\"e1\"}");
+        Assert.assertEquals(testEntity.testEnum, TestEnum.E1);
+
+        System.out.println((Object) mapper.readerFor(TestEnum.class).readValue("\"E1\""));
+
+    }
+
+    @Getter
+    @Setter
+    public static class TestEntity {
+        private TestEnum testEnum = TestEnum.E1;
+
+        private SimpleEnum simpleEnum = SimpleEnum.A;
+    }
+
+    public  enum SimpleEnum{
+        A,B
+    }
+
+}

+ 19 - 0
hsweb-core/src/test/java/org/hswebframework/web/dict/TestEnum.java

@@ -0,0 +1,19 @@
+package org.hswebframework.web.dict;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+@JsonDeserialize(contentUsing = EnumDict.EnumDictJSONDeserializer.class)
+public enum TestEnum implements EnumDict<String> {
+    E1("e1"), E2("e2");
+
+    private String text;
+
+    @Override
+    public String getValue() {
+        return name();
+    }
+}

+ 4 - 2
hsweb-datasource/hsweb-datasource-web/src/main/java/org/hswebframework/web/datasource/web/DatasourceController.java

@@ -16,7 +16,9 @@ import java.util.List;
 @RestController
 @RestController
 @RequestMapping("/datasource")
 @RequestMapping("/datasource")
 @Api(tags = "开发人员工具-数据源", value = "数据源")
 @Api(tags = "开发人员工具-数据源", value = "数据源")
-@Authorize(permission = "datasource", description = "数据源管理")
+@Authorize(permission =
+    @Authorize.Resource(value = "datasource", description = "数据源管理")
+)
 public class DatasourceController {
 public class DatasourceController {
 
 
     @Autowired
     @Autowired
@@ -25,7 +27,7 @@ public class DatasourceController {
     @GetMapping
     @GetMapping
     @Authorize(action = Permission.ACTION_QUERY)
     @Authorize(action = Permission.ACTION_QUERY)
     @ApiOperation("获取全部数据源信息")
     @ApiOperation("获取全部数据源信息")
-    public  List<? extends DynamicDataSourceConfig> getAllConfig() {
+    public List<? extends DynamicDataSourceConfig> getAllConfig() {
         return repository.findAll();
         return repository.findAll();
     }
     }
 
 

+ 5 - 0
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml

@@ -16,6 +16,11 @@
             <groupId>io.projectreactor</groupId>
             <groupId>io.projectreactor</groupId>
             <artifactId>reactor-core</artifactId>
             <artifactId>reactor-core</artifactId>
         </dependency>
         </dependency>
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-authorization-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
         <dependency>
             <groupId>org.hswebframework.web</groupId>
             <groupId>org.hswebframework.web</groupId>
             <artifactId>hsweb-commons-api</artifactId>
             <artifactId>hsweb-commons-api</artifactId>

+ 5 - 2
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/PermissionDimension.java

@@ -4,6 +4,7 @@ import lombok.AllArgsConstructor;
 import lombok.Getter;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
 import lombok.NoArgsConstructor;
 import lombok.Setter;
 import lombok.Setter;
+import org.hswebframework.web.authorization.DimensionType;
 
 
 import java.util.Map;
 import java.util.Map;
 
 
@@ -15,9 +16,11 @@ public class PermissionDimension {
 
 
     private String id;
     private String id;
 
 
+    private DimensionType dimensionType;
+
     private Map<String, Object> properties;
     private Map<String, Object> properties;
 
 
-    public static PermissionDimension of(String id) {
-        return of(id, null);
+    public static PermissionDimension of(String id, DimensionType dimensionType) {
+        return of(id, dimensionType, null);
     }
     }
 }
 }

+ 0 - 4
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/PermissionDimensionProvider.java

@@ -4,10 +4,6 @@ import reactor.core.publisher.Flux;
 
 
 public interface PermissionDimensionProvider {
 public interface PermissionDimensionProvider {
 
 
-    String getDimension();
-
-    String getName();
-
     Flux<PermissionDimension> getDimensionByUserId(String userId);
     Flux<PermissionDimension> getDimensionByUserId(String userId);
 
 
     Flux<String> getUserIdByDimensionId(String dimensionId);
     Flux<String> getUserIdByDimensionId(String dimensionId);

+ 2 - 10
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/UserPermissionDimensionProvider.java

@@ -1,22 +1,14 @@
 package org.hswebframework.web.system.authorization.api;
 package org.hswebframework.web.system.authorization.api;
 
 
+import org.hswebframework.web.authorization.DefaultDimensionType;
 import reactor.core.publisher.Flux;
 import reactor.core.publisher.Flux;
 
 
 public class UserPermissionDimensionProvider implements PermissionDimensionProvider {
 public class UserPermissionDimensionProvider implements PermissionDimensionProvider {
-    @Override
-    public String getDimension() {
-        return "user";
-    }
-
-    @Override
-    public String getName() {
-        return "用户";
-    }
 
 
     @Override
     @Override
     public Flux<PermissionDimension> getDimensionByUserId(String userId) {
     public Flux<PermissionDimension> getDimensionByUserId(String userId) {
         return Flux.just(userId)
         return Flux.just(userId)
-                .map(PermissionDimension::of);
+                .map(id -> PermissionDimension.of(userId, DefaultDimensionType.user));
     }
     }
 
 
     @Override
     @Override

+ 1 - 1
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/configuration/AuthorizationServiceAutoConfiguration.java

@@ -18,7 +18,7 @@ import org.springframework.context.annotation.Configuration;
 public class AuthorizationServiceAutoConfiguration {
 public class AuthorizationServiceAutoConfiguration {
 
 
 
 
-    // TODO: 2019-10-12 condition reactive enabled
+
     @Configuration
     @Configuration
     static class ReactiveAuthorizationServiceAutoConfiguration{
     static class ReactiveAuthorizationServiceAutoConfiguration{
         @ConditionalOnBean(ReactiveRepository.class)
         @ConditionalOnBean(ReactiveRepository.class)

+ 1 - 1
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationInitializeService.java

@@ -57,7 +57,7 @@ public class DefaultReactiveAuthenticationInitializeService
                     .id(user.getId())
                     .id(user.getId())
                     .name(user.getName())
                     .name(user.getName())
                     .username(user.getUsername())
                     .username(user.getUsername())
-                    .type(user.getType())
+                    .userType(user.getType())
                     .build());
                     .build());
             return initPermission(authentication);
             return initPermission(authentication);
         });
         });

+ 1 - 1
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/webflux/WebFluxUserController.java

@@ -6,7 +6,7 @@ import org.springframework.web.bind.annotation.RestController;
 
 
 @RestController
 @RestController
 @RequestMapping("/user")
 @RequestMapping("/user")
-@Authorize(permission = "user",description = "用户管理")
+@Authorize
 public class WebFluxUserController {
 public class WebFluxUserController {
 
 
 
 

+ 1 - 1
pom.xml

@@ -271,7 +271,7 @@
         <dependency>
         <dependency>
             <groupId>org.springframework</groupId>
             <groupId>org.springframework</groupId>
             <artifactId>spring-context-indexer</artifactId>
             <artifactId>spring-context-indexer</artifactId>
-            <scope>provided</scope>
+<!--            <scope>provided</scope>-->
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>org.codehaus.groovy</groupId>
             <groupId>org.codehaus.groovy</groupId>