소스 검색

Add AuthorizationManager factory methods

Factory methods to create AuthorizationManager with a configurable default AuthorizationDecision.

Closes gh-13085
Yuriy Savchenko 1 년 전
부모
커밋
e49ae096e6

+ 37 - 3
core/src/main/java/org/springframework/security/authorization/AuthorizationManagers.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2022 the original author or authors.
+ * Copyright 2002-2023 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -37,6 +37,23 @@ public final class AuthorizationManagers {
 	 */
 	@SafeVarargs
 	public static <T> AuthorizationManager<T> anyOf(AuthorizationManager<T>... managers) {
+		return anyOf(new AuthorizationDecision(false), managers);
+	}
+
+	/**
+	 * Creates an {@link AuthorizationManager} that grants access if at least one
+	 * {@link AuthorizationManager} granted, if <code>managers</code> are empty or
+	 * abstained, a default {@link AuthorizationDecision} is returned.
+	 * @param <T> the type of object that is being authorized
+	 * @param allAbstainDefaultDecision the default decision if all
+	 * {@link AuthorizationManager}s abstained
+	 * @param managers the {@link AuthorizationManager}s to use
+	 * @return the {@link AuthorizationManager} to use
+	 * @since 6.3
+	 */
+	@SafeVarargs
+	public static <T> AuthorizationManager<T> anyOf(AuthorizationDecision allAbstainDefaultDecision,
+			AuthorizationManager<T>... managers) {
 		return (authentication, object) -> {
 			List<AuthorizationDecision> decisions = new ArrayList<>();
 			for (AuthorizationManager<T> manager : managers) {
@@ -50,7 +67,7 @@ public final class AuthorizationManagers {
 				decisions.add(decision);
 			}
 			if (decisions.isEmpty()) {
-				return new AuthorizationDecision(false);
+				return allAbstainDefaultDecision;
 			}
 			return new CompositeAuthorizationDecision(false, decisions);
 		};
@@ -66,6 +83,23 @@ public final class AuthorizationManagers {
 	 */
 	@SafeVarargs
 	public static <T> AuthorizationManager<T> allOf(AuthorizationManager<T>... managers) {
+		return allOf(new AuthorizationDecision(true), managers);
+	}
+
+	/**
+	 * Creates an {@link AuthorizationManager} that grants access if all
+	 * {@link AuthorizationManager}s granted, if <code>managers</code> are empty or
+	 * abstained, a default {@link AuthorizationDecision} is returned.
+	 * @param <T> the type of object that is being authorized
+	 * @param allAbstainDefaultDecision the default decision if all
+	 * {@link AuthorizationManager}s abstained
+	 * @param managers the {@link AuthorizationManager}s to use
+	 * @return the {@link AuthorizationManager} to use
+	 * @since 6.3
+	 */
+	@SafeVarargs
+	public static <T> AuthorizationManager<T> allOf(AuthorizationDecision allAbstainDefaultDecision,
+			AuthorizationManager<T>... managers) {
 		return (authentication, object) -> {
 			List<AuthorizationDecision> decisions = new ArrayList<>();
 			for (AuthorizationManager<T> manager : managers) {
@@ -79,7 +113,7 @@ public final class AuthorizationManagers {
 				decisions.add(decision);
 			}
 			if (decisions.isEmpty()) {
-				return new AuthorizationDecision(true);
+				return allAbstainDefaultDecision;
 			}
 			return new CompositeAuthorizationDecision(true, decisions);
 		};

+ 135 - 1
core/src/test/java/org/springframework/security/authorization/AuthorizationManagersTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2022 the original author or authors.
+ * Copyright 2002-2023 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -36,6 +36,16 @@ class AuthorizationManagersTests {
 		assertThat(decision.isGranted()).isTrue();
 	}
 
+	@Test
+	void checkAnyOfWithAllAbstainDefaultDecisionWhenOneGrantedThenGrantedDecision() {
+		AuthorizationDecision allAbstainDefaultDecision = new AuthorizationDecision(false);
+		AuthorizationManager<?> composed = AuthorizationManagers.anyOf(allAbstainDefaultDecision,
+				(a, o) -> new AuthorizationDecision(false), (a, o) -> new AuthorizationDecision(true));
+		AuthorizationDecision decision = composed.check(null, null);
+		assertThat(decision).isNotNull();
+		assertThat(decision.isGranted()).isTrue();
+	}
+
 	// gh-13069
 	@Test
 	void checkAnyOfWhenAllNonAbstainingDeniesThenDeniedDecision() {
@@ -54,6 +64,58 @@ class AuthorizationManagersTests {
 		assertThat(decision.isGranted()).isFalse();
 	}
 
+	@Test
+	void checkAnyOfWithAllAbstainDefaultDecisionIsDeniedWhenEmptyThenDeniedDecision() {
+		AuthorizationDecision allAbstainDefaultDecision = new AuthorizationDecision(false);
+		AuthorizationManager<?> composed = AuthorizationManagers.anyOf(allAbstainDefaultDecision);
+		AuthorizationDecision decision = composed.check(null, null);
+		assertThat(decision).isNotNull();
+		assertThat(decision.isGranted()).isFalse();
+	}
+
+	@Test
+	void checkAnyOfWithAllAbstainDefaultDecisionIsGrantedWhenEmptyThenGrantedDecision() {
+		AuthorizationDecision allAbstainDefaultDecision = new AuthorizationDecision(true);
+		AuthorizationManager<?> composed = AuthorizationManagers.anyOf(allAbstainDefaultDecision);
+		AuthorizationDecision decision = composed.check(null, null);
+		assertThat(decision).isNotNull();
+		assertThat(decision.isGranted()).isTrue();
+	}
+
+	@Test
+	void checkAnyOfWithAllAbstainDefaultDecisionIsAbstainWhenEmptyThenAbstainDecision() {
+		AuthorizationDecision allAbstainDefaultDecision = null;
+		AuthorizationManager<?> composed = AuthorizationManagers.anyOf(allAbstainDefaultDecision);
+		AuthorizationDecision decision = composed.check(null, null);
+		assertThat(decision).isNull();
+	}
+
+	@Test
+	void checkAnyOfWhenAllAbstainDefaultDecisionIsGrantedAndAllManagersAbstainThenGrantedDecision() {
+		AuthorizationDecision allAbstainDefaultDecision = new AuthorizationDecision(true);
+		AuthorizationManager<?> composed = AuthorizationManagers.anyOf(allAbstainDefaultDecision, (a, o) -> null);
+		AuthorizationDecision decision = composed.check(null, null);
+		assertThat(decision).isNotNull();
+		assertThat(decision.isGranted()).isTrue();
+	}
+
+	@Test
+	void checkAnyOfWhenAllAbstainDefaultDecisionIsDeniedAndAllManagersAbstainThenDeniedDecision() {
+		AuthorizationDecision allAbstainDefaultDecision = new AuthorizationDecision(false);
+		AuthorizationManager<?> composed = AuthorizationManagers.anyOf(allAbstainDefaultDecision, (a, o) -> null);
+		AuthorizationDecision decision = composed.check(null, null);
+		assertThat(decision).isNotNull();
+		assertThat(decision.isGranted()).isFalse();
+	}
+
+	@Test
+	void checkAnyOfWhenAllAbstainDefaultDecisionIsAbstainAndAllManagersAbstainThenAbstainDecision() {
+		AuthorizationDecision allAbstainDefaultDecision = null;
+		AuthorizationManager<?> composed = AuthorizationManagers.anyOf(allAbstainDefaultDecision, (a, o) -> null);
+		AuthorizationDecision decision = composed.check(null, null);
+		assertThat(decision).isNull();
+	}
+
 	@Test
 	void checkAllOfWhenAllGrantedThenGrantedDecision() {
 		AuthorizationManager<?> composed = AuthorizationManagers.allOf((a, o) -> new AuthorizationDecision(true),
@@ -63,6 +125,16 @@ class AuthorizationManagersTests {
 		assertThat(decision.isGranted()).isTrue();
 	}
 
+	@Test
+	void checkAllOfWithAllAbstainDefaultDecisionWhenAllGrantedThenGrantedDecision() {
+		AuthorizationDecision allAbstainDefaultDecision = new AuthorizationDecision(false);
+		AuthorizationManager<?> composed = AuthorizationManagers.allOf(allAbstainDefaultDecision,
+				(a, o) -> new AuthorizationDecision(true), (a, o) -> new AuthorizationDecision(true));
+		AuthorizationDecision decision = composed.check(null, null);
+		assertThat(decision).isNotNull();
+		assertThat(decision.isGranted()).isTrue();
+	}
+
 	// gh-13069
 	@Test
 	void checkAllOfWhenAllNonAbstainingGrantsThenGrantedDecision() {
@@ -82,6 +154,16 @@ class AuthorizationManagersTests {
 		assertThat(decision.isGranted()).isFalse();
 	}
 
+	@Test
+	void checkAllOfWithAllAbstainDefaultDecisionWhenOneDeniedThenDeniedDecision() {
+		AuthorizationDecision allAbstainDefaultDecision = new AuthorizationDecision(true);
+		AuthorizationManager<?> composed = AuthorizationManagers.allOf(allAbstainDefaultDecision,
+				(a, o) -> new AuthorizationDecision(true), (a, o) -> new AuthorizationDecision(false));
+		AuthorizationDecision decision = composed.check(null, null);
+		assertThat(decision).isNotNull();
+		assertThat(decision.isGranted()).isFalse();
+	}
+
 	@Test
 	void checkAllOfWhenEmptyThenGrantedDecision() {
 		AuthorizationManager<?> composed = AuthorizationManagers.allOf();
@@ -90,4 +172,56 @@ class AuthorizationManagersTests {
 		assertThat(decision.isGranted()).isTrue();
 	}
 
+	@Test
+	void checkAllOfWithAllAbstainDefaultDecisionIsDeniedWhenEmptyThenDeniedDecision() {
+		AuthorizationDecision allAbstainDefaultDecision = new AuthorizationDecision(false);
+		AuthorizationManager<?> composed = AuthorizationManagers.allOf(allAbstainDefaultDecision);
+		AuthorizationDecision decision = composed.check(null, null);
+		assertThat(decision).isNotNull();
+		assertThat(decision.isGranted()).isFalse();
+	}
+
+	@Test
+	void checkAllOfWithAllAbstainDefaultDecisionIsGrantedWhenEmptyThenGrantedDecision() {
+		AuthorizationDecision allAbstainDefaultDecision = new AuthorizationDecision(true);
+		AuthorizationManager<?> composed = AuthorizationManagers.allOf(allAbstainDefaultDecision);
+		AuthorizationDecision decision = composed.check(null, null);
+		assertThat(decision).isNotNull();
+		assertThat(decision.isGranted()).isTrue();
+	}
+
+	@Test
+	void checkAllOfWithAllAbstainDefaultDecisionIsAbstainWhenEmptyThenAbstainDecision() {
+		AuthorizationDecision allAbstainDefaultDecision = null;
+		AuthorizationManager<?> composed = AuthorizationManagers.allOf(allAbstainDefaultDecision);
+		AuthorizationDecision decision = composed.check(null, null);
+		assertThat(decision).isNull();
+	}
+
+	@Test
+	void checkAllOfWhenAllAbstainDefaultDecisionIsDeniedAndAllManagersAbstainThenDeniedDecision() {
+		AuthorizationDecision allAbstainDefaultDecision = new AuthorizationDecision(false);
+		AuthorizationManager<?> composed = AuthorizationManagers.allOf(allAbstainDefaultDecision, (a, o) -> null);
+		AuthorizationDecision decision = composed.check(null, null);
+		assertThat(decision).isNotNull();
+		assertThat(decision.isGranted()).isFalse();
+	}
+
+	@Test
+	void checkAllOfWhenAllAbstainDefaultDecisionIsGrantedAndAllManagersAbstainThenGrantedDecision() {
+		AuthorizationDecision allAbstainDefaultDecision = new AuthorizationDecision(true);
+		AuthorizationManager<?> composed = AuthorizationManagers.allOf(allAbstainDefaultDecision, (a, o) -> null);
+		AuthorizationDecision decision = composed.check(null, null);
+		assertThat(decision).isNotNull();
+		assertThat(decision.isGranted()).isTrue();
+	}
+
+	@Test
+	void checkAllOfWhenAllAbstainDefaultDecisionIsAbstainAndAllManagersAbstainThenAbstainDecision() {
+		AuthorizationDecision allAbstainDefaultDecision = null;
+		AuthorizationManager<?> composed = AuthorizationManagers.allOf(allAbstainDefaultDecision, (a, o) -> null);
+		AuthorizationDecision decision = composed.check(null, null);
+		assertThat(decision).isNull();
+	}
+
 }