Browse Source

Allow authorities to be overridden in UserBuilder

Issue gh-12533
Dmitry Korotych 2 years ago
parent
commit
4def405067

+ 1 - 0
core/src/main/java/org/springframework/security/core/userdetails/User.java

@@ -441,6 +441,7 @@ public class User implements UserDetails, CredentialsContainer {
 		 */
 		public UserBuilder authorities(Collection<? extends GrantedAuthority> authorities) {
 			Assert.notNull(authorities, "authorities cannot be null");
+			this.authorities.clear();
 			this.authorities.addAll(authorities);
 			return this;
 		}

+ 27 - 5
core/src/test/java/org/springframework/security/core/userdetails/UserTests.java

@@ -18,18 +18,19 @@ package org.springframework.security.core.userdetails;
 
 import java.io.ByteArrayOutputStream;
 import java.io.ObjectOutputStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 import java.util.function.Function;
+import java.util.stream.Stream;
 
 import org.junit.jupiter.api.Test;
 
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.authority.AuthorityUtils;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.util.CollectionUtils;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@@ -45,6 +46,14 @@ public class UserTests {
 
 	private static final List<GrantedAuthority> ROLE_12 = AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO");
 
+	public static Stream<Arguments> testNewAuthoritiesShouldReplacePreviousAuthorities() {
+		return Stream.of(
+				Arguments.of((Object) new String[0]),
+				Arguments.of((Object) new String[]{"B7", "C12", "role"}),
+				Arguments.of((Object) new String[]{"A1"})
+		);
+	}
+
 	@Test
 	public void equalsReturnsTrueIfUsernamesAreTheSame() {
 		User user1 = new User("rod", "koala", true, true, true, true, ROLE_12);
@@ -98,6 +107,19 @@ public class UserTests {
 				.authorities(new String[] { null, null }).build());
 	}
 
+	@ParameterizedTest
+	@MethodSource
+	public void testNewAuthoritiesShouldReplacePreviousAuthorities(String[] authorities) {
+		UserDetails parent = User.builder().username("user").password("password").authorities("A1", "A2", "B1").build();
+		User.UserBuilder builder = User.withUserDetails(parent).authorities(authorities);
+		UserDetails user = builder.build();
+		assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())).containsOnly(authorities);
+		user = builder.authorities(AuthorityUtils.createAuthorityList(authorities)).build();
+		assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())).containsOnly(authorities);
+		user = builder.authorities(AuthorityUtils.createAuthorityList(authorities).toArray(GrantedAuthority[]::new)).build();
+		assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())).containsOnly(authorities);
+	}
+
 	@Test
 	public void testNullValuesRejected() {
 		assertThatIllegalArgumentException().isThrownBy(() -> new User(null, "koala", true, true, true, true, ROLE_12));