Sfoglia il codice sorgente

增加数据权限配置获取方法,获取配置更简单

zhou-hao 7 anni fa
parent
commit
b745244c3c
10 ha cambiato i file con 261 aggiunte e 28 eliminazioni
  1. 1 1
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/Authentication.java
  2. 108 5
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/Permission.java
  3. 17 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimplePermission.java
  4. 1 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/builder/SimpleAuthenticationBuilder.java
  5. 4 2
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/builder/SimpleDataAccessConfigBuilder.java
  6. 0 2
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/builder/SimpleDataAccessConfigBuilderFactory.java
  7. 35 4
      hsweb-authorization/hsweb-authorization-api/src/test/java/org/hswebframework/web/authorization/AuthenticationTests.java
  8. 93 12
      hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/DataAccessType.java
  9. 1 1
      hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/ScopeDataAccessConfigConvert.java
  10. 1 1
      hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/handler/DistrictScopeDataAccessHandler.java

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

@@ -94,7 +94,7 @@ public interface Authentication extends Serializable {
         if (null == id) {
             return Optional.empty();
         }
-        return getPermissions().parallelStream()
+        return getPermissions().stream()
                 .filter(permission -> permission.getId().equals(id))
                 .findAny();
     }

+ 108 - 5
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/Permission.java

@@ -18,9 +18,16 @@
 package org.hswebframework.web.authorization;
 
 import org.hswebframework.web.authorization.access.DataAccessConfig;
+import org.hswebframework.web.authorization.access.FieldFilterDataAccessConfig;
+import org.hswebframework.web.authorization.access.ScopeDataAccessConfig;
 
 import java.io.Serializable;
+import java.util.Collections;
+import java.util.Optional;
 import java.util.Set;
+import java.util.function.Predicate;
+
+import static org.hswebframework.web.authorization.access.DataAccessConfig.DefaultType.DENY_FIELDS;
 
 /**
  * 用户持有的权限信息,包含了权限基本信息、可操作范围(action)、行,列级权限控制规则。
@@ -34,15 +41,15 @@ public interface Permission extends Serializable {
     /**
      * 查询
      */
-    String ACTION_QUERY  = "query";
+    String ACTION_QUERY = "query";
     /**
      * 获取明细
      */
-    String ACTION_GET    = "get";
+    String ACTION_GET = "get";
     /**
      * 新增
      */
-    String ACTION_ADD    = "add";
+    String ACTION_ADD = "add";
     /**
      * 更新
      */
@@ -77,14 +84,110 @@ public interface Permission extends Serializable {
     String getId();
 
     /**
-     * @return 用户对此权限的可操作事件(按钮)
+     * 用户对此权限的可操作事件(按钮)
+     * <p>
+     * ⚠️:任何时候都不应该对返回对Set进行写操作
+     *
+     * @return 如果没有配置返回空{@link Collections#emptySet()},不会返回null.
      */
     Set<String> getActions();
 
     /**
-     * @return 用户对此权限持有的数据权限信息, 用于数据级别的控制
+     * 用户对此权限持有的数据权限信息, 用于数据级别的控制
+     * <p>
+     * ⚠️:任何时候都不应该对返回对Set进行写操作
+     *
+     * @return 如果没有配置返回空{@link Collections#emptySet()},不会返回null.
      * @see DataAccessConfig
      * @see org.hswebframework.web.authorization.access.DataAccessController
      */
     Set<DataAccessConfig> getDataAccesses();
+
+
+    /**
+     * 查找数据权限配置
+     *
+     * @param configPredicate 数据权限配置匹配规则
+     * @param <T>             数据权限配置类型
+     * @return {@link Optional}
+     * @see this#scope(String, String, String)
+     */
+    @SuppressWarnings("all")
+    default <T extends DataAccessConfig> Optional<T> findDataAccess(DataAccessPredicate<T> configPredicate) {
+        return (Optional) getDataAccesses().stream()
+                .filter(configPredicate)
+                .findFirst();
+    }
+
+    /**
+     * 查找字段过滤的数据权限配置(列级数据权限),比如:不查询某些字段
+     *
+     * @param action 权限操作类型 {@link Permission#ACTION_QUERY}
+     * @return {@link Optional}
+     * @see FieldFilterDataAccessConfig
+     * @see FieldFilterDataAccessConfig#getFields()
+     */
+    default Optional<FieldFilterDataAccessConfig> findFieldFilter(String action) {
+        return findDataAccess(conf -> FieldFilterDataAccessConfig.class.isInstance(conf) && conf.getAction().equals(action));
+    }
+
+
+    /**
+     * 获取不能执行操作的字段
+     *
+     * @param action 权限操作
+     * @return 未配置时返回空set, 不会返回null
+     */
+    default Set<String> findDenyFields(String action) {
+        return findFieldFilter(action)
+                .filter(conf -> conf.getType().equals(DENY_FIELDS))
+                .map(FieldFilterDataAccessConfig::getFields)
+                .orElseGet(Collections::emptySet);
+    }
+
+
+    /**
+     * 查找数据范围权限控制配置(行级数据权限),比如: 只能查询本机构的数据
+     *
+     * @param type      范围类型标识,由具体的实现定义,如: 机构范围
+     * @param scopeType 范围类型,由具体的实现定义,如: 只能查看自己所在机构
+     * @param action    权限操作 {@link Permission#ACTION_QUERY}
+     * @return 未配置时返回空set, 不会返回null
+     */
+    default Set<Object> findScope(String action, String type, String scopeType) {
+        return findScope(scope(action, type, scopeType));
+    }
+
+    default Set<Object> findScope(Permission.DataAccessPredicate<ScopeDataAccessConfig> predicate) {
+        return findDataAccess(predicate)
+                .map(ScopeDataAccessConfig::getScope)
+                .orElseGet(Collections::emptySet);
+    }
+
+    /**
+     * 构造一个数据范围权限控制配置查找逻辑
+     *
+     * @param type      范围类型标识,由具体的实现定义,如: 机构范围
+     * @param scopeType 范围类型,由具体的实现定义,如: 只能查看自己所在机构
+     * @param action    权限操作 {@link Permission#ACTION_QUERY}
+     * @return {@link DataAccessPredicate}
+     */
+    static Permission.DataAccessPredicate<ScopeDataAccessConfig> scope(String action, String type, String scopeType) {
+        return config ->
+                config instanceof ScopeDataAccessConfig
+                        && config.getAction().equals(action)
+                        && config.getType().equals(type)
+                        && ((ScopeDataAccessConfig) config).getScopeType().equals(scopeType);
+    }
+
+
+    /**
+     * 数据权限查找判断逻辑接口
+     *
+     * @param <T>
+     */
+    interface DataAccessPredicate<T extends DataAccessConfig> extends Predicate<DataAccessConfig> {
+        boolean test(DataAccessConfig config);
+    }
+
 }

+ 17 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimplePermission.java

@@ -4,6 +4,8 @@ import lombok.*;
 import org.hswebframework.web.authorization.Permission;
 import org.hswebframework.web.authorization.access.DataAccessConfig;
 
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.Set;
 
 /**
@@ -23,4 +25,19 @@ public class SimplePermission implements Permission {
     private Set<String> actions;
 
     private Set<DataAccessConfig> dataAccesses;
+
+
+    public Set<String> getActions() {
+        if (actions == null) {
+            actions = Collections.emptySet();
+        }
+        return actions;
+    }
+
+    public Set<DataAccessConfig> getDataAccesses() {
+        if (dataAccesses == null) {
+            dataAccesses = Collections.emptySet();
+        }
+        return dataAccesses;
+    }
 }

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

@@ -95,6 +95,7 @@ public class SimpleAuthenticationBuilder implements AuthenticationBuilder {
             if (null != dataAccess) {
                 permission.setDataAccesses(dataAccess.stream().map(JSONObject.class::cast)
                         .map(dataJson -> dataBuilderFactory.create().fromJson(dataJson.toJSONString()).build())
+                        .filter(Objects::nonNull)
                         .collect(Collectors.toSet()));
             }
             permissions.add(permission);

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

@@ -40,8 +40,10 @@ public class SimpleDataAccessConfigBuilder implements DataAccessConfigBuilder {
         Objects.requireNonNull(action);
 
 
-        return converts.stream().filter(convert -> convert.isSupport(type, action, config))
-                .findAny().map(convert -> convert.convert(type, action, config))
+        return converts.stream()
+                .filter(convert -> convert.isSupport(type, action, config))
+                .map(convert -> convert.convert(type, action, config))
+                .findFirst()
                 .orElse(null);
     }
 }

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

@@ -18,8 +18,6 @@ import static org.hswebframework.web.authorization.access.DataAccessConfig.Defau
 import static org.hswebframework.web.authorization.access.DataAccessConfig.DefaultType.OWN_CREATED;
 
 /**
- * TODO 完成注释
- *
  * @author zhouhao
  */
 public class SimpleDataAccessConfigBuilderFactory implements DataAccessConfigBuilderFactory {

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

@@ -1,18 +1,39 @@
 package org.hswebframework.web.authorization;
 
+import com.alibaba.fastjson.JSON;
+import org.hswebframework.web.authorization.access.DataAccessConfig;
+import org.hswebframework.web.authorization.access.FieldFilterDataAccessConfig;
+import org.hswebframework.web.authorization.access.ScopeDataAccessConfig;
 import org.hswebframework.web.authorization.builder.AuthenticationBuilder;
 import org.hswebframework.web.authorization.exception.UnAuthorizedException;
+import org.hswebframework.web.authorization.simple.SimpleFiledScopeDataAccessConfig;
 import org.hswebframework.web.authorization.simple.builder.SimpleAuthenticationBuilder;
 import org.hswebframework.web.authorization.simple.builder.SimpleDataAccessConfigBuilderFactory;
 import org.hswebframework.web.authorization.token.*;
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
 
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.hswebframework.web.authorization.Permission.scope;
 import static org.junit.Assert.*;
 
 public class AuthenticationTests {
 
-    private AuthenticationBuilder builder = new SimpleAuthenticationBuilder(new SimpleDataAccessConfigBuilderFactory());
+    private AuthenticationBuilder builder;
+
+    @Before
+    public void setup() {
+        SimpleDataAccessConfigBuilderFactory builderFactory = new SimpleDataAccessConfigBuilderFactory();
+
+        builderFactory.init();
+
+        builder = new SimpleAuthenticationBuilder(builderFactory);
+    }
 
     /**
      * 测试初始化基本的权限信息
@@ -21,7 +42,8 @@ public class AuthenticationTests {
     public void testInitUserRoleAndPermission() {
         Authentication authentication = builder.user("{\"id\":\"admin\",\"username\":\"admin\",\"name\":\"Administrator\",\"type\":\"default\"}")
                 .role("[{\"id\":\"admin-role\",\"name\":\"admin\"}]")
-                .permission("[{\"id\":\"user-manager\",\"actions\":[\"GET\",\"UPDATE\"]}]")
+                .permission("[{\"id\":\"user-manager\",\"actions\":[\"query\",\"get\",\"update\"]" +
+                        ",\"dataAccesses\":[{\"action\":\"query\",\"field\":\"test\",\"config\":{\"fields\":[\"1\",\"2\",\"3\"]},\"scopeType\":\"CUSTOM_SCOPE\",\"type\":\"DENY_FIELDS\"}]}]")
                 .build();
 
         //test user
@@ -39,8 +61,17 @@ public class AuthenticationTests {
         //test permission
         assertEquals(authentication.getPermissions().size(), 1);
         assertTrue(authentication.hasPermission("user-manager"));
-        assertTrue(authentication.hasPermission("user-manager", "GET"));
-        assertTrue(!authentication.hasPermission("user-manager", "DELETE"));
+        assertTrue(authentication.hasPermission("user-manager", "get"));
+        assertTrue(!authentication.hasPermission("user-manager", "delete"));
+
+        //获取数据权限配置
+        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);
+
     }
 
     /**

+ 93 - 12
hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/DataAccessType.java

@@ -1,6 +1,7 @@
 package org.hswebframework.web.organizational.authorization.access;
 
-import java.io.Serializable;
+import org.hswebframework.web.authorization.Permission;
+import org.hswebframework.web.authorization.access.ScopeDataAccessConfig;
 
 /**
  * 控制类型
@@ -8,38 +9,118 @@ import java.io.Serializable;
  * @author zhouhao
  * @since 3.0
  */
-public interface DataAccessType extends Serializable {
+public interface DataAccessType {
     /**
      * 控制地区
      */
-    String AREA_SCOPE           = "AREA_SCOPE";
+    String DISTRICT_SCOPE = "DISTRICT";
     /**
      * 控制机构
      */
-    String ORG_SCOPE            = "ORG_SCOPE";
+    String ORG_SCOPE = "ORG_SCOPE";
     /**
      * 控制部门
      */
-    String DEPARTMENT_SCOPE     = "DEPARTMENT_SCOPE";
+    String DEPARTMENT_SCOPE = "DEPARTMENT_SCOPE";
     /**
      * 控制职位
      */
-    String POSITION_SCOPE       = "POSITION_SCOPE";
+    String POSITION_SCOPE = "POSITION_SCOPE";
     /**
      * 控制人员
      */
-    String PERSON_SCOPE         = "PERSON_SCOPE";
+    String PERSON_SCOPE = "PERSON_SCOPE";
     /**
-     * 仅限本人
+     * 控制范围:仅限本人
      */
     String SCOPE_TYPE_ONLY_SELF = "ONLY_SELF";
     /**
-     * 包含子级
+     * 控制范围:包含子级
      */
-    String SCOPE_TYPE_CHILDREN  = "CHILDREN";
+    String SCOPE_TYPE_CHILDREN = "CHILDREN";
     /**
-     * 自定义范围
+     * 控制范围:自定义范围
      */
-    String SCOPE_TYPE_CUSTOM    = "CUSTOM_SCOPE";
+    String SCOPE_TYPE_CUSTOM = "CUSTOM_SCOPE";
 
+    /* ===========行政区============*/
+    static Permission.DataAccessPredicate<ScopeDataAccessConfig> districtScope(String action, String type) {
+        return Permission.scope(action, ORG_SCOPE, type);
+    }
+
+    static Permission.DataAccessPredicate<ScopeDataAccessConfig> selfDistrictScope(String action) {
+        return districtScope(action, SCOPE_TYPE_ONLY_SELF);
+    }
+
+    static Permission.DataAccessPredicate<ScopeDataAccessConfig> customDistrictScope(String action) {
+        return districtScope(action, SCOPE_TYPE_CUSTOM);
+    }
+
+    static Permission.DataAccessPredicate<ScopeDataAccessConfig> childrenDistrictScope(String action) {
+        return districtScope(action, SCOPE_TYPE_CHILDREN);
+    }
+
+    /* ===========机构============*/
+    static Permission.DataAccessPredicate<ScopeDataAccessConfig> orgScope(String action, String type) {
+        return Permission.scope(action, ORG_SCOPE, type);
+    }
+
+    static Permission.DataAccessPredicate<ScopeDataAccessConfig> selfOrgScope(String action) {
+        return orgScope(action, SCOPE_TYPE_ONLY_SELF);
+    }
+
+    static Permission.DataAccessPredicate<ScopeDataAccessConfig> customOrgScope(String action) {
+        return orgScope(action, SCOPE_TYPE_CUSTOM);
+    }
+
+    static Permission.DataAccessPredicate<ScopeDataAccessConfig> childrenOrgScope(String action) {
+        return orgScope(action, SCOPE_TYPE_CHILDREN);
+    }
+
+
+    /* ===========部门===========*/
+
+    static Permission.DataAccessPredicate<ScopeDataAccessConfig> departmentScope(String action, String type) {
+        return Permission.scope(action, DEPARTMENT_SCOPE, type);
+    }
+
+    static Permission.DataAccessPredicate<ScopeDataAccessConfig> selfDepartmentScope(String action) {
+        return departmentScope(action, SCOPE_TYPE_ONLY_SELF);
+    }
+
+    static Permission.DataAccessPredicate<ScopeDataAccessConfig> customDepartmentScope(String action) {
+        return departmentScope(action, SCOPE_TYPE_CUSTOM);
+    }
+
+    static Permission.DataAccessPredicate<ScopeDataAccessConfig> childrenDepartmentScope(String action) {
+        return departmentScope(action, SCOPE_TYPE_CHILDREN);
+    }
+
+     /* ===========岗位===========*/
+
+    static Permission.DataAccessPredicate<ScopeDataAccessConfig> positionScope(String action, String type) {
+        return Permission.scope(action, POSITION_SCOPE, type);
+    }
+
+    static Permission.DataAccessPredicate<ScopeDataAccessConfig> selfPositionScope(String action) {
+        return positionScope(action, SCOPE_TYPE_ONLY_SELF);
+    }
+
+    static Permission.DataAccessPredicate<ScopeDataAccessConfig> customPositionScope(String action) {
+        return positionScope(action, SCOPE_TYPE_CUSTOM);
+    }
+
+    static Permission.DataAccessPredicate<ScopeDataAccessConfig> childrenPositionScope(String action) {
+        return positionScope(action, SCOPE_TYPE_CHILDREN);
+    }
+
+    /* ===========人员===========*/
+
+    static Permission.DataAccessPredicate<ScopeDataAccessConfig> selfScope(String action) {
+        return personScope(action, SCOPE_TYPE_ONLY_SELF);
+    }
+
+    static Permission.DataAccessPredicate<ScopeDataAccessConfig> personScope(String action, String type) {
+        return Permission.scope(action, PERSON_SCOPE, type);
+    }
 }

+ 1 - 1
hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/ScopeDataAccessConfigConvert.java

@@ -15,7 +15,7 @@ import static org.hswebframework.web.organizational.authorization.access.DataAcc
  */
 public class ScopeDataAccessConfigConvert implements DataAccessConfigConvert {
     private static final List<String> supportTypes = Arrays.asList(
-            AREA_SCOPE, ORG_SCOPE, DEPARTMENT_SCOPE, POSITION_SCOPE, PERSON_SCOPE
+            DISTRICT_SCOPE, ORG_SCOPE, DEPARTMENT_SCOPE, POSITION_SCOPE, PERSON_SCOPE
     );
 
     @Override

+ 1 - 1
hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/handler/DistrictScopeDataAccessHandler.java

@@ -22,7 +22,7 @@ public class DistrictScopeDataAccessHandler extends AbstractScopeDataAccessHandl
 
     @Override
     protected String getSupportScope() {
-        return AREA_SCOPE;
+        return DISTRICT_SCOPE;
     }
 
     @Override