diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/entity/authorization/DataAccessEntity.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/entity/authorization/DataAccessEntity.java index 8ec5d0720..0b05d6348 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/entity/authorization/DataAccessEntity.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/entity/authorization/DataAccessEntity.java @@ -3,8 +3,6 @@ import org.hswebframework.web.commons.entity.CloneableEntity; /** - * TODO 完成注释 - * * @author zhouhao */ public class DataAccessEntity implements CloneableEntity { diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-starter/src/test/groovy/org/hswebframework/web/authorization/starter/UserSettingControllerTest.groovy b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-starter/src/test/groovy/org/hswebframework/web/authorization/starter/UserSettingControllerTest.groovy index 41be44131..2efcb0252 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-starter/src/test/groovy/org/hswebframework/web/authorization/starter/UserSettingControllerTest.groovy +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-starter/src/test/groovy/org/hswebframework/web/authorization/starter/UserSettingControllerTest.groovy @@ -3,6 +3,8 @@ package org.hswebframework.web.authorization.starter import com.alibaba.fastjson.JSON import org.hswebframework.web.authorization.Authentication import org.hswebframework.web.authorization.AuthenticationInitializeService +import org.hswebframework.web.authorization.access.DataAccessConfig +import org.hswebframework.web.tests.HswebCrudWebApiSpecification import org.junit.runner.RunWith import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest @@ -27,32 +29,26 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. /** * @author zhouhao - * @since + * @since 3.0 */ -@WebAppConfiguration -@ContextConfiguration -@SpringBootTest(classes = [TestApplication.class], properties = ["classpath:application.yml"]) -class UserSettingControllerTest extends Specification { - @Autowired - private ConfigurableApplicationContext context; - - @Shared - private MockMvc mockMvc; +class UserSettingControllerTest extends HswebCrudWebApiSpecification { @Autowired private AuthenticationInitializeService initializeService; - void setup() { - mockMvc = MockMvcBuilders.webAppContextSetup(context).build(); + @Override + protected String getBaseApi() { + return "/autz-setting" } + def "Add Permission"() { def permissions = [ [ - "id" : "user", - "name" : "用户管理", - "actions": [["action": "query", "describe": "查询"], ["action": "update", "describe": "修改"]] - + "id" : "user", + "name" : "用户管理", + "actions" : [["action": "query", "describe": "查询"], ["action": "update", "describe": "修改"]], + "supportDataAccessTypes": [DataAccessConfig.DefaultType.DENY_FIELDS] ], [ "id" : "role", @@ -99,45 +95,52 @@ class UserSettingControllerTest extends Specification { "Add Permission"() def userId = "Add User"() //添加用户权限 - mockMvc.perform( - post("/autz-setting") - .contentType(MediaType.APPLICATION_JSON) - .content(JSON.toJSONString - ([ - type : "user", //设置类型:user - settingFor: userId, //设置给具体的user - describe : "测试", - details : + doAddRequest(JSON.toJSONString + ([ + type : "user", //设置类型:user + settingFor: userId, //设置给具体的user + describe : "测试", + details : + [ [ - [ - permissionId: "user", //赋予user权限 - actions : ["query", "update"], - status : 1 - ], - [ - permissionId: "role", //赋予role权限 - actions : ["query", "get"], - status : 1 + permissionId: "user", //赋予user权限 + actions : ["query", "update"], + status : 1, + dataAccesses: [ //数据权限,控制查询的时候不能查询password字段 + [ + type : DataAccessConfig.DefaultType.DENY_FIELDS, + action: "query", + config: """{"fields": ["password"]}""" + ] ] ], - menus : [ - [ - menuId: "user-menu" - ], - [ - menuId: "role-menu" - ] + permissionId: "role", //赋予role权限 + actions : ["query", "get"], + status : 1 ] - ]) - )).andDo({ result -> println result.response.contentAsString }) -// .andExpect(status().is(201)) + ], + menus : + [ + [ + menuId: "user-menu" + ], + [ + menuId: "role-menu" + ] + ] + ])) + expect: userId != null def autz = initializeService.initUserAuthorization(userId) autz != null autz.hasPermission("user", "query") autz.hasPermission("role", "query", "get") - + autz.getPermission("user") + .map({ per -> per.findDenyFields("query") }) + .map({ fields -> fields.contains("password") }) + .orElse(false) } + } diff --git a/hsweb-tests/src/main/groovy/org/hswebframework/web/tests/HswebCrudWebApiSpecification.groovy b/hsweb-tests/src/main/groovy/org/hswebframework/web/tests/HswebCrudWebApiSpecification.groovy new file mode 100644 index 000000000..9bdb9480d --- /dev/null +++ b/hsweb-tests/src/main/groovy/org/hswebframework/web/tests/HswebCrudWebApiSpecification.groovy @@ -0,0 +1,121 @@ +package org.hswebframework.web.tests + +import com.alibaba.fastjson.JSON +import org.hswebframework.ezorm.core.dsl.Query +import org.hswebframework.web.WebUtil +import org.hswebframework.web.commons.entity.param.QueryParamEntity +import org.springframework.http.MediaType +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.* + + +/** + * @author zhouhao + * @since 3.0.2 + */ +abstract class HswebCrudWebApiSpecification extends HswebSpecification { + + protected abstract String getBaseApi(); + + def doAddRequest(String requestBody) { + def response = mockMvc.perform(post(getBaseApi()) + .content(requestBody) + .contentType(MediaType.APPLICATION_JSON)) + .andReturn() + .response + .contentAsString; + return JSON.parseObject(response); + } + + def doUpdateRequest(String id, String requestBody) { + def response = mockMvc.perform(put("${getBaseApi()}/{id}", id) + .content(requestBody) + .contentType(MediaType.APPLICATION_JSON)) + .andReturn() + .response + .contentAsString; + return JSON.parseObject(response); + } + + def doDeleteRequest(String id) { + def response = mockMvc + .perform(delete("${getBaseApi()}/{id}", id)) + .andReturn() + .response + .contentAsString; + return JSON.parseObject(response); + } + + def doGetRequest(String id) { + def response = mockMvc + .perform(get("${getBaseApi()}/{id}", id)) + .andReturn() + .response + .contentAsString; + return JSON.parseObject(response); + } + + + Query createQuery() { + return Query.empty(new QueryParamEntity()); + } + + def doQueryRequest(Query query) { + MockHttpServletRequestBuilder get = get("${getBaseApi()}") + WebUtil.objectToHttpParameters(query.param) + .forEach({ k, v -> get.param(k, v) }) + def response = mockMvc + .perform(get) + .andReturn() + .response + .contentAsString; + return JSON.parseObject(response); + } + + def doQueryByIdsRequest(String ids) { + def response = mockMvc + .perform(get("${getBaseApi()}/ids").param("ids", ids)) + .andReturn() + .response + .contentAsString; + return JSON.parseObject(response); + } + + def doTotalRequest(Query query) { + MockHttpServletRequestBuilder get = get("${getBaseApi()}/total") + WebUtil.objectToHttpParameters(query.param) + .forEach({ k, v -> get.param(k, v) }) + + def response = mockMvc + .perform(get) + .andReturn() + .response + .contentAsString; + return JSON.parseObject(response); + } + + def doCountRequest(Query query) { + MockHttpServletRequestBuilder get = get("${getBaseApi()}/count") + WebUtil.objectToHttpParameters(query.param) + .forEach({ k, v -> get.param(k, v) }) + def response = mockMvc + .perform(get) + .andReturn() + .response + .contentAsString; + return JSON.parseObject(response); + } + + def doNoPagingRequest(Query query) { + MockHttpServletRequestBuilder get = get("${getBaseApi()}/no-paging") + WebUtil.objectToHttpParameters(query.param) + .forEach({ k, v -> get.param(k, v) }) + def response = mockMvc + .perform(get) + .andReturn() + .response + .contentAsString; + return JSON.parseObject(response); + } +} diff --git a/hsweb-tests/src/main/groovy/org/hswebframework/web/tests/HswebSpecification.groovy b/hsweb-tests/src/main/groovy/org/hswebframework/web/tests/HswebSpecification.groovy new file mode 100644 index 000000000..750aec1a2 --- /dev/null +++ b/hsweb-tests/src/main/groovy/org/hswebframework/web/tests/HswebSpecification.groovy @@ -0,0 +1,31 @@ +package org.hswebframework.web.tests + +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.context.ConfigurableApplicationContext +import org.springframework.test.context.ContextConfiguration +import org.springframework.test.context.web.WebAppConfiguration +import org.springframework.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.setup.MockMvcBuilders +import spock.lang.Shared +import spock.lang.Specification + +/** + * @author zhouhao + * @since 3.0.2 + */ +@WebAppConfiguration +@ContextConfiguration +@SpringBootTest(classes = [HswebTestApplication.class], properties = ["classpath:application.yml"]) +class HswebSpecification extends Specification { + @Autowired + protected ConfigurableApplicationContext context; + + @Shared + protected MockMvc mockMvc; + + void setup() { + mockMvc = MockMvcBuilders.webAppContextSetup(context).build(); + } + +} diff --git a/hsweb-tests/src/main/groovy/org/hswebframework/web/tests/HswebTestApplication.groovy b/hsweb-tests/src/main/groovy/org/hswebframework/web/tests/HswebTestApplication.groovy new file mode 100644 index 000000000..90455765c --- /dev/null +++ b/hsweb-tests/src/main/groovy/org/hswebframework/web/tests/HswebTestApplication.groovy @@ -0,0 +1,15 @@ +package org.hswebframework.web.tests; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.web.WebAppConfiguration; + +/** + * @author zhouhao + * @since 3.0.2 + */ +@SpringBootApplication +@WebAppConfiguration +@Configuration +class HswebTestApplication { +} diff --git a/hsweb-tests/src/main/java/org/hswebframework/web/tests/SimpleWebApplicationTests.java b/hsweb-tests/src/main/java/org/hswebframework/web/tests/SimpleWebApplicationTests.java index fbf1b9441..b9f4e6510 100644 --- a/hsweb-tests/src/main/java/org/hswebframework/web/tests/SimpleWebApplicationTests.java +++ b/hsweb-tests/src/main/java/org/hswebframework/web/tests/SimpleWebApplicationTests.java @@ -41,12 +41,13 @@ import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup; /** - * TODO 完成注释 + * 已弃用,请使用 {@link HswebSpecification} {@link HswebCrudWebApiSpecification } * * @author zhouhao */ @RunWith(SpringRunner.class) @SpringBootTest(classes = SimpleWebApplicationTests.Config.class) +@Deprecated public class SimpleWebApplicationTests extends AbstractTransactionalJUnit4SpringContextTests { protected MockMvc mvc; diff --git a/hsweb-tests/src/test/groovy/org/hswebframework/web/tests/HswebCrudWebApiSpecificationTest.groovy b/hsweb-tests/src/test/groovy/org/hswebframework/web/tests/HswebCrudWebApiSpecificationTest.groovy new file mode 100644 index 000000000..82d8c681f --- /dev/null +++ b/hsweb-tests/src/test/groovy/org/hswebframework/web/tests/HswebCrudWebApiSpecificationTest.groovy @@ -0,0 +1,88 @@ +package org.hswebframework.web.tests + +import com.alibaba.fastjson.JSONObject +import spock.lang.Specification + +/** + * @author zhouhao + * @since 3.0.2 + */ +class HswebCrudWebApiSpecificationTest extends HswebCrudWebApiSpecification { + + @Override + protected String getBaseApi() { + return "/test" + } + + def "测试初始化"() { + expect: + mockMvc != null + context != null + } + + def "测试新增"() { + given: + def response = doAddRequest(JSONObject.toJSONString([name: "test"])); + expect: + response != null + response.status == 200 || response.status == 201 + } + + def "测试修改"() { + given: + def response = doUpdateRequest("test", JSONObject.toJSONString([name: "test"])); + expect: + response != null + response.status == 200 + } + + def "测试删除"() { + given: + def response = doDeleteRequest("test"); + expect: + response != null + response.status == 200 + } + + def "测试查询"() { + given: + def response = doQueryRequest(createQuery().where("id", "1234")); + expect: + response != null + response.status == 200 + } + + def "测试根据id查询"() { + given: + def response = doGetRequest("1"); + expect: + response != null + response.status == 200 + } + + def "测试根据id集合查询"() { + given: + def response = doQueryByIdsRequest("1,2,3,4"); + expect: + response != null + response.status == 200 + } + + def "测试查询总数"() { + given: + def response = doCountRequest(createQuery().where("id", "1234")); + expect: + response != null + response.status == 200 + } + + + def "测试不分页查询"() { + given: + def response = doNoPagingRequest(createQuery().where("id", "1234")); + expect: + response != null + response.status == 200 + } + +} diff --git a/hsweb-tests/src/test/groovy/org/hswebframework/web/tests/TestController.java b/hsweb-tests/src/test/groovy/org/hswebframework/web/tests/TestController.java new file mode 100644 index 000000000..647f5de88 --- /dev/null +++ b/hsweb-tests/src/test/groovy/org/hswebframework/web/tests/TestController.java @@ -0,0 +1,101 @@ +package org.hswebframework.web.tests; + +import org.hswebframework.web.commons.entity.Entity; +import org.hswebframework.web.commons.entity.PagerResult; +import org.hswebframework.web.commons.entity.param.QueryParamEntity; +import org.hswebframework.web.controller.SimpleGenericEntityController; +import org.hswebframework.web.service.CrudService; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Collections; +import java.util.List; + +/** + * @author zhouhao + * @since 3.0.2 + */ +@RestController +@RequestMapping("/test") +public class TestController implements SimpleGenericEntityController { + + @Override + public CrudService getService() { + return new CrudService() { + @Override + public TestEntity createEntity() { + return new TestEntity(); + } + + @Override + public Class getEntityInstanceType() { + return TestEntity.class; + } + + @Override + public TestEntity deleteByPk(String s) { + return new TestEntity(); + } + + @Override + public String insert(TestEntity data) { + return data.getId(); + } + + @Override + public PagerResult selectPager(Entity param) { + return PagerResult.empty(); + } + + @Override + public List select(Entity param) { + return Collections.emptyList(); + } + + @Override + public int count(Entity param) { + return 0; + } + + @Override + public TestEntity selectSingle(Entity param) { + return null; + } + + @Override + public TestEntity selectByPk(String id) { + return new TestEntity(); + } + + @Override + public List selectByPk(List id) { + return Collections.emptyList(); + } + + @Override + public List select() { + return Collections.emptyList(); + } + + @Override + public int count() { + return 0; + } + + @Override + public int updateByPk(String id, TestEntity data) { + return 0; + } + + @Override + public int updateByPk(List data) { + return 0; + } + + @Override + public String saveOrUpdate(TestEntity testEntity) { + return testEntity.getId(); + } + }; + } +} diff --git a/hsweb-tests/src/test/groovy/org/hswebframework/web/tests/TestEntity.java b/hsweb-tests/src/test/groovy/org/hswebframework/web/tests/TestEntity.java new file mode 100644 index 000000000..244466453 --- /dev/null +++ b/hsweb-tests/src/test/groovy/org/hswebframework/web/tests/TestEntity.java @@ -0,0 +1,10 @@ +package org.hswebframework.web.tests; + +import org.hswebframework.web.commons.entity.SimpleGenericEntity; + +/** + * @author zhouhao + * @since 3.0.2 + */ +public class TestEntity extends SimpleGenericEntity { +} diff --git a/hsweb-tests/src/test/resources/application.yml b/hsweb-tests/src/test/resources/application.yml new file mode 100644 index 000000000..027075c17 --- /dev/null +++ b/hsweb-tests/src/test/resources/application.yml @@ -0,0 +1,19 @@ +spring: + aop: + auto: true + datasource: + url : jdbc:h2:mem:permission_test_mem + username : sa + password : + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name : org.h2.Driver +hsweb: + app: + name: 测试 + version: 3.0.0 + +logging: + level: + org.springframework: WARN + org.hswebframework: WARN + org.hswebframework.web: DEBUG \ No newline at end of file