浏览代码

Polish RoleHierarchyUtils and add tests

Joe Grandja 9 年之前
父节点
当前提交
c75a5b7279

+ 29 - 58
core/src/main/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyUtils.java

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2012-2016 the original author or authors.
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -15,84 +15,55 @@
  */
  */
 package org.springframework.security.access.hierarchicalroles;
 package org.springframework.security.access.hierarchicalroles;
 
 
+import org.springframework.util.Assert;
+
 import java.io.PrintWriter;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.io.StringWriter;
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
 
 
 /**
 /**
- * Utility method for working with {@link RoleHierarchy}.
+ * Utility methods for {@link RoleHierarchy}.
  *
  *
  * @author Thomas Darimont
  * @author Thomas Darimont
- * @since
+ * @since 4.2.0
  */
  */
-public class RoleHierarchyUtils {
+public final class RoleHierarchyUtils {
+
+	private RoleHierarchyUtils() {
+	}
 
 
 	/**
 	/**
-	 * Builds a {@link RoleHierarchy} representation from the given {@link Map} of role name to implied roles.
-	 * The map key is the role name and the map value is a {@link List} of implied role names.
+	 * Converts the supplied {@link Map} of role name to implied role name(s) to a string
+	 * representation understood by {@link RoleHierarchyImpl#setHierarchy(String)}.
+	 * The map key is the role name and the map value is a {@link List} of implied role name(s).
 	 *
 	 *
-	 * <p>
-	 *     Here is an example configuration of a role hierarchy configured via yaml.
-	 *     wich follows the pattern:
-	 *     {@code ROLE_NAME: List of implied role names}
-	 * </p>
-	 * <pre>
-	 * <code>
+	 * @param roleHierarchyMap the mapping(s) of role name to implied role name(s)
+	 * @return a string representation of a role hierarchy
+	 * @throws IllegalArgumentException if roleHierarchyMap is null or empty or if a role name is null or
+	 * empty or if an implied role name(s) is null or empty
 	 *
 	 *
-	 * security:
-	 *   roles:
-	 *     hierarchy:
-	 *       ROLE_ALL: ROLE_A, ROLE_C
-	 *       ROLE_A: ROLE_B
-	 *       ROLE_B: ROLE_AUTHENTICATED
-	 *       ROLE_C: ROLE_AUTHENTICATED
-	 *       ROLE_AUTHENTICATED: ROLE_UNAUTHENTICATED
-	 * </code>
-	 * </pre>
-	 * <p>This yaml configuration could then be mapped by the following {@literal ConfigurationProperties}</p>
-	 * <pre>
-	 * <code>
-	 *   {@literal @}ConfigurationProperties("security.roles")
-	 *   class SecurityPropertiesExtension {
-	 *     Map<String, List<String>> hierarchy = new LinkedHashMap<>();
-	 *
-	 *     //getter | setter
-	 *   }
-	 * </code>
-	 * </pre>
-	 * <p>To define the role hierarchy just declare a {@link org.springframework.context.annotation.Bean} of
-	 * type {@link RoleHierarchy} as follows:</p>
-	 * <pre>
-	 * <code>
-	 *   {@literal @}Bean
-	 *   RoleHierarchy roleHierarchy(SecurityPropertiesExtension spe) {
-	 *     return RoleHierarchyUtils.roleHierarchyFromMap(spe.getHierarchy());
-	 *   }
-	 * </code>
-	 * </pre>
-	 *
-	 * @param roleHierarchyMapping the role name to implied role names mapping
-	 * @return
 	 */
 	 */
-	public static RoleHierarchy roleHierarchyFromMap(Map<String, List<String>> roleHierarchyMapping) {
+	public static String roleHierarchyFromMap(Map<String, List<String>> roleHierarchyMap) {
+		Assert.notEmpty(roleHierarchyMap, "roleHierarchyMap cannot be empty");
 
 
-		StringWriter roleHierachyDescriptionBuffer = new StringWriter();
-		PrintWriter roleHierarchyDescriptionWriter = new PrintWriter(roleHierachyDescriptionBuffer);
+		StringWriter roleHierarchyBuffer = new StringWriter();
+		PrintWriter roleHierarchyWriter = new PrintWriter(roleHierarchyBuffer);
 
 
-		for (Map.Entry<String, List<String>> entry : roleHierarchyMapping.entrySet()) {
+		for (Map.Entry<String, List<String>> roleHierarchyEntry : roleHierarchyMap.entrySet()) {
+			String role = roleHierarchyEntry.getKey();
+			List<String> impliedRoles = roleHierarchyEntry.getValue();
 
 
-			String currentRole = entry.getKey();
-			List<String> impliedRoles = entry.getValue();
+			Assert.hasLength(role, "role name must be supplied");
+			Assert.notEmpty(impliedRoles, "implied role name(s) cannot be empty");
 
 
 			for (String impliedRole : impliedRoles) {
 			for (String impliedRole : impliedRoles) {
-				String roleMapping = currentRole + " > " + impliedRole;
-				roleHierarchyDescriptionWriter.println(roleMapping);
+				String roleMapping = role + " > " + impliedRole;
+				roleHierarchyWriter.println(roleMapping);
 			}
 			}
 		}
 		}
 
 
-		RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
-		roleHierarchy.setHierarchy(roleHierachyDescriptionBuffer.toString());
-		return roleHierarchy;
+		return roleHierarchyBuffer.toString();
 	}
 	}
+
 }
 }

+ 37 - 216
core/src/test/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyUtilsTests.java

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2012-2016 the original author or authors.
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -16,251 +16,72 @@
 package org.springframework.security.access.hierarchicalroles;
 package org.springframework.security.access.hierarchicalroles;
 
 
 import org.junit.Test;
 import org.junit.Test;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.AuthorityUtils;
 
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
+import java.util.*;
 
 
 import static java.util.Arrays.asList;
 import static java.util.Arrays.asList;
-import static java.util.Collections.singletonList;
-import static java.util.Collections.singletonMap;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.fail;
-import static org.springframework.security.access.hierarchicalroles.RoleHierarchyUtils.roleHierarchyFromMap;
 
 
 /**
 /**
  * Tests for {@link RoleHierarchyUtils}.
  * Tests for {@link RoleHierarchyUtils}.
  *
  *
- * Copied from {@link RoleHierarchyImplTests} with adaptations for {@link RoleHierarchyUtils}.
- *
- * @author Thomas Darimont
+ * @author Joe Grandja
  */
  */
 public class RoleHierarchyUtilsTests {
 public class RoleHierarchyUtilsTests {
 
 
 	@Test
 	@Test
-	public void testRoleHierarchyWithNullOrEmptyAuthorities() {
+	public void roleHierarchyFromMapWhenMapValidThenConvertsCorrectly() throws Exception {
+		String expectedRoleHierarchy = "ROLE_A > ROLE_B\nROLE_A > ROLE_C\nROLE_B > ROLE_D\nROLE_C > ROLE_D\n";
 
 
-		List<GrantedAuthority> authorities0 = null;
-		List<GrantedAuthority> authorities1 = new ArrayList<GrantedAuthority>();
+		Map<String, List<String>> roleHierarchyMap = new TreeMap<String, List<String>>();
+		roleHierarchyMap.put("ROLE_A", asList("ROLE_B", "ROLE_C"));
+		roleHierarchyMap.put("ROLE_B", asList("ROLE_D"));
+		roleHierarchyMap.put("ROLE_C", asList("ROLE_D"));
 
 
-		RoleHierarchy roleHierarchy = roleHierarchyFromMap(singletonMap("ROLE_A", singletonList("ROLE_B")));
+		String roleHierarchy = RoleHierarchyUtils.roleHierarchyFromMap(roleHierarchyMap);
 
 
-		assertThat(roleHierarchy.getReachableGrantedAuthorities(
-				authorities0)).isNotNull();
-		assertThat(
-				roleHierarchy.getReachableGrantedAuthorities(authorities0)).isEmpty();
-		;
-		assertThat(roleHierarchy.getReachableGrantedAuthorities(
-				authorities1)).isNotNull();
-		assertThat(
-				roleHierarchy.getReachableGrantedAuthorities(authorities1)).isEmpty();
-		;
+		assertThat(roleHierarchy).isEqualTo(expectedRoleHierarchy);
 	}
 	}
 
 
-	@Test
-	public void testSimpleRoleHierarchy() {
-
-		List<GrantedAuthority> authorities0 = AuthorityUtils.createAuthorityList(
-				"ROLE_0");
-		List<GrantedAuthority> authorities1 = AuthorityUtils.createAuthorityList(
-				"ROLE_A");
-		List<GrantedAuthority> authorities2 = AuthorityUtils.createAuthorityList("ROLE_A",
-				"ROLE_B");
-
-		RoleHierarchy roleHierarchy = roleHierarchyFromMap(singletonMap("ROLE_A", singletonList("ROLE_B")));
-
-		assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(
-			roleHierarchy.getReachableGrantedAuthorities(authorities0),
-				authorities0)).isTrue();
-		assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(
-			roleHierarchy.getReachableGrantedAuthorities(authorities1),
-				authorities2)).isTrue();
-		assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(
-			roleHierarchy.getReachableGrantedAuthorities(authorities2),
-				authorities2)).isTrue();
+	@Test(expected = IllegalArgumentException.class)
+	public void roleHierarchyFromMapWhenMapNullThenThrowsIllegalArgumentException() throws Exception {
+		RoleHierarchyUtils.roleHierarchyFromMap(null);
 	}
 	}
 
 
-	@Test
-	public void testTransitiveRoleHierarchies() {
-		List<GrantedAuthority> authorities1 = AuthorityUtils.createAuthorityList(
-				"ROLE_A");
-		List<GrantedAuthority> authorities2 = AuthorityUtils.createAuthorityList("ROLE_A",
-				"ROLE_B", "ROLE_C");
-		List<GrantedAuthority> authorities3 = AuthorityUtils.createAuthorityList("ROLE_A",
-				"ROLE_B", "ROLE_C", "ROLE_D");
-
-		RoleHierarchy roleHierarchy2Levels = roleHierarchyFromMap(new HashMap<String, List<String>>(){
-			{
-				put("ROLE_A", asList("ROLE_B"));
-				put("ROLE_B", asList("ROLE_C"));
-			}
-		});
-
-		assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(
-			roleHierarchy2Levels.getReachableGrantedAuthorities(authorities1),
-				authorities2)).isTrue();
-
-		RoleHierarchy roleHierarchy3Levels = roleHierarchyFromMap(new HashMap<String, List<String>>(){
-			{
-				put("ROLE_A", asList("ROLE_B"));
-				put("ROLE_B", asList("ROLE_C"));
-				put("ROLE_C", asList("ROLE_D"));
-			}
-		});
-
-		assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(
-			roleHierarchy3Levels.getReachableGrantedAuthorities(authorities1),
-				authorities3)).isTrue();
+	@Test(expected = IllegalArgumentException.class)
+	public void roleHierarchyFromMapWhenMapEmptyThenThrowsIllegalArgumentException() throws Exception {
+		RoleHierarchyUtils.roleHierarchyFromMap(Collections.<String, List<String>>emptyMap());
 	}
 	}
 
 
-	@Test
-	public void testComplexRoleHierarchy() {
-		List<GrantedAuthority> authoritiesInput1 = AuthorityUtils.createAuthorityList(
-				"ROLE_A");
-		List<GrantedAuthority> authoritiesOutput1 = AuthorityUtils.createAuthorityList(
-				"ROLE_A", "ROLE_B", "ROLE_C", "ROLE_D");
-		List<GrantedAuthority> authoritiesInput2 = AuthorityUtils.createAuthorityList(
-				"ROLE_B");
-		List<GrantedAuthority> authoritiesOutput2 = AuthorityUtils.createAuthorityList(
-				"ROLE_B", "ROLE_D");
-		List<GrantedAuthority> authoritiesInput3 = AuthorityUtils.createAuthorityList(
-				"ROLE_C");
-		List<GrantedAuthority> authoritiesOutput3 = AuthorityUtils.createAuthorityList(
-				"ROLE_C", "ROLE_D");
-		List<GrantedAuthority> authoritiesInput4 = AuthorityUtils.createAuthorityList(
-				"ROLE_D");
-		List<GrantedAuthority> authoritiesOutput4 = AuthorityUtils.createAuthorityList(
-				"ROLE_D");
-
+	@Test(expected = IllegalArgumentException.class)
+	public void roleHierarchyFromMapWhenRoleNullThenThrowsIllegalArgumentException() throws Exception {
+		Map<String, List<String>> roleHierarchyMap = new HashMap<String, List<String>>();
+		roleHierarchyMap.put(null, asList("ROLE_B", "ROLE_C"));
 
 
-		RoleHierarchy roleHierarchy3LevelsMultipleRoles = roleHierarchyFromMap(new HashMap<String, List<String>>(){
-			{
-				put("ROLE_A", asList("ROLE_B","ROLE_C"));
-				put("ROLE_B", asList("ROLE_D"));
-				put("ROLE_C", asList("ROLE_D"));
-			}
-		});
-
-		assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(
-			roleHierarchy3LevelsMultipleRoles.getReachableGrantedAuthorities(authoritiesInput1),
-				authoritiesOutput1)).isTrue();
-		assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(
-			roleHierarchy3LevelsMultipleRoles.getReachableGrantedAuthorities(authoritiesInput2),
-				authoritiesOutput2)).isTrue();
-		assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(
-			roleHierarchy3LevelsMultipleRoles.getReachableGrantedAuthorities(authoritiesInput3),
-				authoritiesOutput3)).isTrue();
-		assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(
-			roleHierarchy3LevelsMultipleRoles.getReachableGrantedAuthorities(authoritiesInput4),
-				authoritiesOutput4)).isTrue();
+		RoleHierarchyUtils.roleHierarchyFromMap(roleHierarchyMap);
 	}
 	}
 
 
-	@Test
-	public void testCyclesInRoleHierarchy() {
-
-		try {
-			roleHierarchyFromMap(singletonMap("ROLE_A", singletonList("ROLE_A")));
-			fail("Cycle in role hierarchy was not detected!");
-		}
-		catch (CycleInRoleHierarchyException e) {
-		}
+	@Test(expected = IllegalArgumentException.class)
+	public void roleHierarchyFromMapWhenRoleEmptyThenThrowsIllegalArgumentException() throws Exception {
+		Map<String, List<String>> roleHierarchyMap = new HashMap<String, List<String>>();
+		roleHierarchyMap.put("", asList("ROLE_B", "ROLE_C"));
 
 
-		try {
-
-			roleHierarchyFromMap(new HashMap<String, List<String>>(){
-				{
-					put("ROLE_A", asList("ROLE_B"));
-					put("ROLE_B", asList("ROLE_A"));
-				}
-			});
-
-			fail("Cycle in role hierarchy was not detected!");
-		}
-		catch (CycleInRoleHierarchyException e) {
-		}
-
-		try {
-
-			roleHierarchyFromMap(new HashMap<String, List<String>>(){
-				{
-					put("ROLE_A", asList("ROLE_B"));
-					put("ROLE_B", asList("ROLE_C"));
-					put("ROLE_C", asList("ROLE_A"));
-				}
-			});
-
-			fail("Cycle in role hierarchy was not detected!");
-		}
-		catch (CycleInRoleHierarchyException e) {
-		}
-
-		try {
-
-			roleHierarchyFromMap(new HashMap<String, List<String>>(){
-				{
-					put("ROLE_A", asList("ROLE_B"));
-					put("ROLE_B", asList("ROLE_C"));
-					put("ROLE_C", asList("ROLE_E"));
-					put("ROLE_E", asList("ROLE_D"));
-					put("ROLE_D", asList("ROLE_B"));
-				}
-			});
-
-
-			fail("Cycle in role hierarchy was not detected!");
-		}
-		catch (CycleInRoleHierarchyException e) {
-		}
+		RoleHierarchyUtils.roleHierarchyFromMap(roleHierarchyMap);
 	}
 	}
 
 
-	@Test
-	public void testNoCyclesInRoleHierarchy() {
-		RoleHierarchyImpl roleHierarchyImpl = new RoleHierarchyImpl();
-
-		try {
-			roleHierarchyImpl.setHierarchy(
-					"ROLE_A > ROLE_B\nROLE_A > ROLE_C\nROLE_C > ROLE_D\nROLE_B > ROLE_D");
-
-			roleHierarchyFromMap(new HashMap<String, List<String>>(){
-				{
-					put("ROLE_A", asList("ROLE_B"));
-					put("ROLE_A", asList("ROLE_C"));
-					put("ROLE_C", asList("ROLE_D"));
-					put("ROLE_B", asList("ROLE_D"));
-				}
-			});
+	@Test(expected = IllegalArgumentException.class)
+	public void roleHierarchyFromMapWhenImpliedRolesNullThenThrowsIllegalArgumentException() throws Exception {
+		Map<String, List<String>> roleHierarchyMap = new HashMap<String, List<String>>();
+		roleHierarchyMap.put("ROLE_A", null);
 
 
-		}
-		catch (CycleInRoleHierarchyException e) {
-			fail("A cycle in role hierarchy was incorrectly detected!");
-		}
+		RoleHierarchyUtils.roleHierarchyFromMap(roleHierarchyMap);
 	}
 	}
 
 
-	@Test
-	public void testSimpleRoleHierarchyWithCustomGrantedAuthorityImplementation() {
-
-		List<GrantedAuthority> authorities0 = HierarchicalRolesTestHelper.createAuthorityList(
-				"ROLE_0");
-		List<GrantedAuthority> authorities1 = HierarchicalRolesTestHelper.createAuthorityList(
-				"ROLE_A");
-		List<GrantedAuthority> authorities2 = HierarchicalRolesTestHelper.createAuthorityList(
-				"ROLE_A", "ROLE_B");
-
-		RoleHierarchy roleHierarchy = roleHierarchyFromMap(singletonMap("ROLE_A", singletonList("ROLE_B")));
+	@Test(expected = IllegalArgumentException.class)
+	public void roleHierarchyFromMapWhenImpliedRolesEmptyThenThrowsIllegalArgumentException() throws Exception {
+		Map<String, List<String>> roleHierarchyMap = new HashMap<String, List<String>>();
+		roleHierarchyMap.put("ROLE_A", Collections.<String>emptyList());
 
 
-		assertThat(
-				HierarchicalRolesTestHelper.containTheSameGrantedAuthoritiesCompareByAuthorityString(
-					roleHierarchy.getReachableGrantedAuthorities(authorities0),
-						authorities0)).isTrue();
-		assertThat(
-				HierarchicalRolesTestHelper.containTheSameGrantedAuthoritiesCompareByAuthorityString(
-					roleHierarchy.getReachableGrantedAuthorities(authorities1),
-						authorities2)).isTrue();
-		assertThat(
-				HierarchicalRolesTestHelper.containTheSameGrantedAuthoritiesCompareByAuthorityString(
-					roleHierarchy.getReachableGrantedAuthorities(authorities2),
-						authorities2)).isTrue();
+		RoleHierarchyUtils.roleHierarchyFromMap(roleHierarchyMap);
 	}
 	}
 }
 }