From 0c18cc2b85b67578edbd1e94e3ff7bb9f6049874 Mon Sep 17 00:00:00 2001 From: Xu Zerui <154111660+amikecoXu@users.noreply.github.com> Date: Thu, 1 Feb 2024 20:11:56 +0900 Subject: [PATCH] feat: Add test function (#5) feat: Add test function --- .github/workflows/maven-ci.yml | 23 ++++ examples/casbin/model.conf | 15 +++ examples/casbin/policy.csv | 19 +++ .../java/org/casbin/ApplicationTests.java | 26 ---- .../java/org/casbin/MenuControllerTests.java | 117 ++++++++++++++++++ src/test/resources/application.yml | 3 + 6 files changed, 177 insertions(+), 26 deletions(-) create mode 100644 .github/workflows/maven-ci.yml create mode 100644 examples/casbin/model.conf create mode 100644 examples/casbin/policy.csv delete mode 100644 src/test/java/org/casbin/ApplicationTests.java create mode 100644 src/test/java/org/casbin/MenuControllerTests.java create mode 100644 src/test/resources/application.yml diff --git a/.github/workflows/maven-ci.yml b/.github/workflows/maven-ci.yml new file mode 100644 index 0000000..e454ea5 --- /dev/null +++ b/.github/workflows/maven-ci.yml @@ -0,0 +1,23 @@ +name: Build and Test Menu Permission + +on: [push, pull_request] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + distribution: 'temurin' + cache: maven + - name: Build with Maven + run: mvn -B package --file pom.xml + + #Run Tests + - name: Run Tests + run: mvn -B test \ No newline at end of file diff --git a/examples/casbin/model.conf b/examples/casbin/model.conf new file mode 100644 index 0000000..56f3596 --- /dev/null +++ b/examples/casbin/model.conf @@ -0,0 +1,15 @@ +[request_definition] +r = sub, obj, act + +[policy_definition] +p = sub, obj, act, eft + +[role_definition] +g = _, _ +g2 = _, _ + +[policy_effect] +e = some(where (p.eft == allow)) && !some(where (p.eft == deny)) + +[matchers] +m = g(r.sub, p.sub) && r.act == p.act && (g2(r.obj, p.obj) || r.obj == p.obj) \ No newline at end of file diff --git a/examples/casbin/policy.csv b/examples/casbin/policy.csv new file mode 100644 index 0000000..0718e0a --- /dev/null +++ b/examples/casbin/policy.csv @@ -0,0 +1,19 @@ +p, ROLE_ROOT, OtherMenu, read, allow +p, ROLE_ROOT, AdminMenu, read, allow +p, ROLE_ROOT, UserMenu, read, deny +p, ROLE_ADMIN, UserMenu, read, allow +p, ROLE_ADMIN, AdminMenu, read, allow +p, ROLE_ADMIN, AdminSubMenu_deny, read, deny +p, ROLE_USER, UserSubMenu_allow, read, allow + +g, user, ROLE_USER +g, admin, ROLE_ADMIN +g, root, ROLE_ROOT +g, ROLE_ADMIN, ROLE_USER + +g2, UserSubMenu_allow, UserMenu +g2, UserSubMenu_deny, UserMenu +g2, UserSubSubMenu, UserSubMenu_allow +g2, AdminSubMenu_allow, AdminMenu +g2, AdminSubMenu_deny, AdminMenu +g2, (NULL), OtherMenu \ No newline at end of file diff --git a/src/test/java/org/casbin/ApplicationTests.java b/src/test/java/org/casbin/ApplicationTests.java deleted file mode 100644 index c7d1c43..0000000 --- a/src/test/java/org/casbin/ApplicationTests.java +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2024 The casbin Authors. All Rights Reserved. -// -// 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.casbin; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class ApplicationTests { - - @Test - void contextLoads() { - } -} diff --git a/src/test/java/org/casbin/MenuControllerTests.java b/src/test/java/org/casbin/MenuControllerTests.java new file mode 100644 index 0000000..703be5e --- /dev/null +++ b/src/test/java/org/casbin/MenuControllerTests.java @@ -0,0 +1,117 @@ +// Copyright 2024 The casbin Authors. All Rights Reserved. +// +// 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.casbin; + +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.casbin.entity.MenuEntity; +import org.casbin.service.MenuService; +import org.casbin.util.MenuUtil; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.mock.web.MockHttpSession; +import org.springframework.test.web.servlet.MockMvc; + +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +@SpringBootTest(classes = {Application.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@AutoConfigureMockMvc +@Slf4j +public class MenuControllerTests { + @Resource + private MockMvc mockMvc; + @Resource + private MenuService menuService; + + private Map menuMap; + + @Value("${test.menu.filePath}") + private String filePath; + + @BeforeEach + public void setUp() throws IOException { + menuMap = MenuUtil.parseCsvFile(filePath); + } + + @ParameterizedTest + @ValueSource(strings = {"root", "admin", "user"}) + public void testAccessForDifferentUsers(String username) throws Exception { + testMenuAccess(username); + } + + public void testMenuAccess(String username) throws Exception { + MockHttpSession session = createSessionForUser(username); + List accessibleMenus = menuService.findAccessibleMenus(username); + for (MenuEntity menu : menuMap.values()) { + if(menu.getParents() == null){ + testMenuAndSubMenus(menu, session, accessibleMenus); + } + } + } + + private void testMenuAndSubMenus(MenuEntity menu, MockHttpSession session, List accessibleMenus) throws Exception { + boolean isAccessible = isMenuAccessibleForUser(menu, accessibleMenus); + String url = menu.getUrl(); + if (!url.startsWith("/")) { + url = "/" + url; + } + mockMvc.perform(MockMvcRequestBuilders.get(url).session(session)) + .andExpect(isAccessible ? MockMvcResultMatchers.status().isOk() : MockMvcResultMatchers.status().isFound()) + .andDo(mvcResult -> { + String username = (String) session.getAttribute("username"); + log.info("Username: {}", username); + log.info("Menu Name: {}", menu.getName()); + log.info("Is Accessible: {}", isAccessible); + log.info("Status: {}", mvcResult.getResponse().getStatus()); + }); + + for (MenuEntity subMenu : menu.getSubMenus()) { + testMenuAndSubMenus(subMenu, session, accessibleMenus); + } + } + + private boolean isMenuAccessibleForUser(MenuEntity menuTarget, List accessibleMenus) { + for (MenuEntity menu : accessibleMenus) { + if (menuMatches(menu, menuTarget)) { return true; } + } + return false; + } + + private boolean menuMatches(MenuEntity menu, MenuEntity menuTarget) { + if (menu.equals(menuTarget)) { + return true; + } + for (MenuEntity subMenu : menu.getSubMenus()) { + if (menuMatches(subMenu, menuTarget)) { return true; } + } + return false; + } + + private MockHttpSession createSessionForUser(String username) { + MockHttpSession session = new MockHttpSession(); + session.setAttribute("username", username); + return session; + } + +} diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml new file mode 100644 index 0000000..80d63ba --- /dev/null +++ b/src/test/resources/application.yml @@ -0,0 +1,3 @@ +test: + menu: + filePath: examples/casbin/policy.csv