Apply updated Code Style
Closes gh-13881
This commit is contained in:
@@ -75,7 +75,7 @@ public class DefaultSpringSecurityContextSourceTests {
|
||||
ctxSrc.setPassword("password");
|
||||
ctxSrc.afterPropertiesSet();
|
||||
assertThat(ctxSrc.getAuthenticatedEnvForTest("manager", "password"))
|
||||
.containsKey(AbstractContextSource.SUN_LDAP_POOLING_FLAG);
|
||||
.containsKey(AbstractContextSource.SUN_LDAP_POOLING_FLAG);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -86,7 +86,7 @@ public class DefaultSpringSecurityContextSourceTests {
|
||||
ctxSrc.setPassword("password");
|
||||
ctxSrc.afterPropertiesSet();
|
||||
assertThat(ctxSrc.getAuthenticatedEnvForTest("user", "password"))
|
||||
.doesNotContainKey(AbstractContextSource.SUN_LDAP_POOLING_FLAG);
|
||||
.doesNotContainKey(AbstractContextSource.SUN_LDAP_POOLING_FLAG);
|
||||
}
|
||||
|
||||
// SEC-1145. Confirms that there is no issue here with pooling.
|
||||
@@ -96,8 +96,9 @@ public class DefaultSpringSecurityContextSourceTests {
|
||||
// com.sun.jndi.ldap.LdapPoolManager.showStats(System.out);
|
||||
// com.sun.jndi.ldap.LdapPoolManager.showStats(System.out);
|
||||
// Now get it gain, with wrong password. Should fail.
|
||||
assertThatExceptionOfType(AuthenticationException.class).isThrownBy(() -> this.contextSource
|
||||
.getContext("uid=Bob,ou=people,dc=springframework,dc=org", "wrongpassword").close());
|
||||
assertThatExceptionOfType(AuthenticationException.class).isThrownBy(
|
||||
() -> this.contextSource.getContext("uid=Bob,ou=people,dc=springframework,dc=org", "wrongpassword")
|
||||
.close());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -166,7 +167,7 @@ public class DefaultSpringSecurityContextSourceTests {
|
||||
// this url should be rejected because the root DN goes into a separate parameter
|
||||
serverUrls.add("ldap://bar:389/dc=foobar,dc=org");
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new DefaultSpringSecurityContextSource(serverUrls, "dc=springframework,dc=org"));
|
||||
.isThrownBy(() -> new DefaultSpringSecurityContextSource(serverUrls, "dc=springframework,dc=org"));
|
||||
}
|
||||
|
||||
static class EnvExposingDefaultSpringSecurityContextSource extends DefaultSpringSecurityContextSource {
|
||||
|
||||
@@ -91,9 +91,9 @@ public class SpringSecurityLdapTemplateITests {
|
||||
@Test
|
||||
public void namingExceptionIsTranslatedCorrectly() {
|
||||
assertThatExceptionOfType(UncategorizedLdapException.class)
|
||||
.isThrownBy(() -> this.template.executeReadOnly((ContextExecutor) (dirContext) -> {
|
||||
throw new NamingException();
|
||||
}));
|
||||
.isThrownBy(() -> this.template.executeReadOnly((ContextExecutor) (dirContext) -> {
|
||||
throw new NamingException();
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -73,14 +73,14 @@ public class BindAuthenticatorTests {
|
||||
DirContextOperations user = this.authenticator.authenticate(this.bob);
|
||||
assertThat(user.getStringAttribute("uid")).isEqualTo("bob");
|
||||
this.authenticator
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("mouse, jerry", "jerryspassword"));
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("mouse, jerry", "jerryspassword"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAuthenticationWithInvalidUserNameFails() {
|
||||
this.authenticator.setUserDnPatterns(new String[] { "uid={0},ou=people" });
|
||||
assertThatExceptionOfType(BadCredentialsException.class).isThrownBy(() -> this.authenticator
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("nonexistentsuser", "password")));
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("nonexistentsuser", "password")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -95,17 +95,17 @@ public class BindAuthenticatorTests {
|
||||
// SEC-1444
|
||||
this.authenticator.setUserSearch(new FilterBasedLdapUserSearch("ou=people", "(cn={0})", this.contextSource));
|
||||
this.authenticator
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("mouse, jerry", "jerryspassword"));
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("mouse, jerry", "jerryspassword"));
|
||||
this.authenticator
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("slash/guy", "slashguyspassword"));
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("slash/guy", "slashguyspassword"));
|
||||
// SEC-1661
|
||||
this.authenticator.setUserSearch(
|
||||
new FilterBasedLdapUserSearch("ou=\\\"quoted people\\\"", "(cn={0})", this.contextSource));
|
||||
this.authenticator
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("quote\"guy", "quoteguyspassword"));
|
||||
.setUserSearch(new FilterBasedLdapUserSearch("ou=\\\"quoted people\\\"", "(cn={0})", this.contextSource));
|
||||
this.authenticator
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("quote\"guy", "quoteguyspassword"));
|
||||
this.authenticator.setUserSearch(new FilterBasedLdapUserSearch("", "(cn={0})", this.contextSource));
|
||||
this.authenticator
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("quote\"guy", "quoteguyspassword"));
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("quote\"guy", "quoteguyspassword"));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -133,7 +133,7 @@ public class BindAuthenticatorTests {
|
||||
public void testAuthenticationWithWrongPasswordFails() {
|
||||
this.authenticator.setUserDnPatterns(new String[] { "uid={0},ou=people" });
|
||||
assertThatExceptionOfType(BadCredentialsException.class).isThrownBy(() -> this.authenticator
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("bob", "wrongpassword")));
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("bob", "wrongpassword")));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -78,11 +78,11 @@ public class PasswordComparisonAuthenticatorTests {
|
||||
public void testFailedSearchGivesUserNotFoundException() throws Exception {
|
||||
this.authenticator = new PasswordComparisonAuthenticator(this.contextSource);
|
||||
assertThat(this.authenticator.getUserDns("Bob")).withFailMessage("User DN matches shouldn't be available")
|
||||
.isEmpty();
|
||||
.isEmpty();
|
||||
this.authenticator.setUserSearch(new MockUserSearch(null));
|
||||
this.authenticator.afterPropertiesSet();
|
||||
assertThatExceptionOfType(UsernameNotFoundException.class).isThrownBy(() -> this.authenticator
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("Joe", "pass")));
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("Joe", "pass")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -90,7 +90,7 @@ public class PasswordComparisonAuthenticatorTests {
|
||||
// Don't retrieve the password
|
||||
this.authenticator.setUserAttributes(new String[] { "uid", "cn", "sn" });
|
||||
assertThatExceptionOfType(BadCredentialsException.class).isThrownBy(() -> this.authenticator
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("bob", "wrongpass")));
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("bob", "wrongpass")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -146,14 +146,14 @@ public class PasswordComparisonAuthenticatorTests {
|
||||
this.authenticator = new PasswordComparisonAuthenticator(this.contextSource);
|
||||
this.authenticator.setPasswordEncoder(NoOpPasswordEncoder.getInstance());
|
||||
assertThat(this.authenticator.getUserDns("Bob")).withFailMessage("User DN matches shouldn't be available")
|
||||
.isEmpty();
|
||||
.isEmpty();
|
||||
|
||||
DirContextAdapter ctx = new DirContextAdapter(new DistinguishedName("uid=Bob,ou=people"));
|
||||
ctx.setAttributeValue("userPassword", "bobspassword");
|
||||
|
||||
this.authenticator.setUserSearch(new MockUserSearch(ctx));
|
||||
this.authenticator
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("shouldntbeused", "bobspassword"));
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("shouldntbeused", "bobspassword"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ public class FilterBasedLdapUserSearchTests {
|
||||
public void searchFailsOnMultipleMatches() {
|
||||
FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("ou=people", "(cn=*)", this.contextSource);
|
||||
assertThatExceptionOfType(IncorrectResultSizeDataAccessException.class)
|
||||
.isThrownBy(() -> locator.searchForUser("Ignored"));
|
||||
.isThrownBy(() -> locator.searchForUser("Ignored"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -115,7 +115,7 @@ public class ApacheDSContainerTests {
|
||||
server.setPort(ports.get(0));
|
||||
server.setLdapOverSslEnabled(true);
|
||||
assertThatIllegalArgumentException().isThrownBy(server::afterPropertiesSet)
|
||||
.withMessage("When LdapOverSsl is enabled, the keyStoreFile property must be set.");
|
||||
.withMessage("When LdapOverSsl is enabled, the keyStoreFile property must be set.");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -137,7 +137,8 @@ public class ApacheDSContainerTests {
|
||||
server.setKeyStoreFile(temporaryKeyStoreFile);
|
||||
server.setCertificatePassord("incorrect-password");
|
||||
assertThatExceptionOfType(RuntimeException.class).isThrownBy(server::afterPropertiesSet)
|
||||
.withMessage("Server startup failed").withRootCauseInstanceOf(UnrecoverableKeyException.class);
|
||||
.withMessage("Server startup failed")
|
||||
.withRootCauseInstanceOf(UnrecoverableKeyException.class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -71,9 +71,9 @@ public class ApacheDSEmbeddedLdifTests {
|
||||
@Test // SEC-2387
|
||||
public void customAttributeTypesShouldBeProperlyCreatedWhenLoadedFromLdif() {
|
||||
assertThat(this.ldapTemplate.compare("uid=objectWithCustomAttribute1", "uid", "objectWithCustomAttribute1"))
|
||||
.isTrue();
|
||||
.isTrue();
|
||||
assertThat(this.ldapTemplate.compare("uid=objectWithCustomAttribute1", "customAttribute", "I am custom"))
|
||||
.isTrue();
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ public class UnboundIdContainerLdifTests {
|
||||
this.appCtx = new AnnotationConfigApplicationContext(CustomLdifConfig.class);
|
||||
|
||||
DefaultSpringSecurityContextSource contextSource = (DefaultSpringSecurityContextSource) this.appCtx
|
||||
.getBean(ContextSource.class);
|
||||
.getBean(ContextSource.class);
|
||||
|
||||
SpringSecurityLdapTemplate template = new SpringSecurityLdapTemplate(contextSource);
|
||||
assertThat(template.compare("uid=bob,ou=people", "uid", "bob")).isTrue();
|
||||
@@ -63,7 +63,7 @@ public class UnboundIdContainerLdifTests {
|
||||
this.appCtx = new AnnotationConfigApplicationContext(WildcardLdifConfig.class);
|
||||
|
||||
DefaultSpringSecurityContextSource contextSource = (DefaultSpringSecurityContextSource) this.appCtx
|
||||
.getBean(ContextSource.class);
|
||||
.getBean(ContextSource.class);
|
||||
|
||||
SpringSecurityLdapTemplate template = new SpringSecurityLdapTemplate(contextSource);
|
||||
assertThat(template.compare("uid=bob,ou=people", "uid", "bob")).isTrue();
|
||||
@@ -72,17 +72,17 @@ public class UnboundIdContainerLdifTests {
|
||||
@Test
|
||||
public void unboundIdContainerWhenMalformedLdifThenException() {
|
||||
assertThatExceptionOfType(Exception.class)
|
||||
.isThrownBy(() -> this.appCtx = new AnnotationConfigApplicationContext(MalformedLdifConfig.class))
|
||||
.withCauseInstanceOf(IllegalStateException.class)
|
||||
.withMessageContaining("Unable to load LDIF classpath:test-server-malformed.txt");
|
||||
.isThrownBy(() -> this.appCtx = new AnnotationConfigApplicationContext(MalformedLdifConfig.class))
|
||||
.withCauseInstanceOf(IllegalStateException.class)
|
||||
.withMessageContaining("Unable to load LDIF classpath:test-server-malformed.txt");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unboundIdContainerWhenMissingLdifThenException() {
|
||||
assertThatExceptionOfType(Exception.class)
|
||||
.isThrownBy(() -> this.appCtx = new AnnotationConfigApplicationContext(MissingLdifConfig.class))
|
||||
.withCauseInstanceOf(IllegalStateException.class)
|
||||
.withMessageContaining("Unable to load LDIF classpath:does-not-exist.ldif");
|
||||
.isThrownBy(() -> this.appCtx = new AnnotationConfigApplicationContext(MissingLdifConfig.class))
|
||||
.withCauseInstanceOf(IllegalStateException.class)
|
||||
.withMessageContaining("Unable to load LDIF classpath:does-not-exist.ldif");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -77,7 +77,7 @@ public class DefaultLdapAuthoritiesPopulatorTests {
|
||||
this.populator.setDefaultRole("ROLE_USER");
|
||||
|
||||
Collection<GrantedAuthority> authorities = this.populator
|
||||
.getGrantedAuthorities(new DirContextAdapter(new DistinguishedName("cn=notused")), "notused");
|
||||
.getGrantedAuthorities(new DirContextAdapter(new DistinguishedName("cn=notused")), "notused");
|
||||
assertThat(authorities).hasSize(1);
|
||||
assertThat(AuthorityUtils.authorityListToSet(authorities).contains("ROLE_USER")).isTrue();
|
||||
}
|
||||
@@ -112,7 +112,7 @@ public class DefaultLdapAuthoritiesPopulatorTests {
|
||||
new DistinguishedName("uid=ben,ou=people,dc=springframework,dc=org"));
|
||||
|
||||
Set<String> authorities = AuthorityUtils
|
||||
.authorityListToSet(this.populator.getGrantedAuthorities(ctx, "manager"));
|
||||
.authorityListToSet(this.populator.getGrantedAuthorities(ctx, "manager"));
|
||||
|
||||
assertThat(authorities).as("Should have 1 role").hasSize(1);
|
||||
assertThat(authorities.contains("ROLE_MANAGER")).isTrue();
|
||||
@@ -127,7 +127,7 @@ public class DefaultLdapAuthoritiesPopulatorTests {
|
||||
new DistinguishedName("uid=ben,ou=people,dc=springframework,dc=org"));
|
||||
|
||||
Set<String> authorities = AuthorityUtils
|
||||
.authorityListToSet(this.populator.getGrantedAuthorities(ctx, "manager"));
|
||||
.authorityListToSet(this.populator.getGrantedAuthorities(ctx, "manager"));
|
||||
|
||||
assertThat(authorities).as("Should have 2 roles").hasSize(2);
|
||||
assertThat(authorities.contains("ROLE_MANAGER")).isTrue();
|
||||
@@ -144,7 +144,7 @@ public class DefaultLdapAuthoritiesPopulatorTests {
|
||||
new DistinguishedName("uid=ben,ou=people,dc=springframework,dc=org"));
|
||||
|
||||
Set<String> authorities = AuthorityUtils
|
||||
.authorityListToSet(this.populator.getGrantedAuthorities(ctx, "manager"));
|
||||
.authorityListToSet(this.populator.getGrantedAuthorities(ctx, "manager"));
|
||||
|
||||
assertThat(authorities).as("Should have 3 roles").hasSize(3);
|
||||
assertThat(authorities.contains("ROLE_MANAGER")).isTrue();
|
||||
@@ -162,7 +162,7 @@ public class DefaultLdapAuthoritiesPopulatorTests {
|
||||
};
|
||||
|
||||
Collection<GrantedAuthority> authorities = this.populator
|
||||
.getGrantedAuthorities(new DirContextAdapter(new DistinguishedName("cn=notused")), "notused");
|
||||
.getGrantedAuthorities(new DirContextAdapter(new DistinguishedName("cn=notused")), "notused");
|
||||
assertThat(authorities).hasSize(1);
|
||||
assertThat(AuthorityUtils.authorityListToSet(authorities).contains("ROLE_EXTRA")).isTrue();
|
||||
}
|
||||
@@ -177,7 +177,7 @@ public class DefaultLdapAuthoritiesPopulatorTests {
|
||||
new DistinguishedName("cn=mouse\\, jerry,ou=people,dc=springframework,dc=org"));
|
||||
|
||||
Set<String> authorities = AuthorityUtils
|
||||
.authorityListToSet(this.populator.getGrantedAuthorities(ctx, "notused"));
|
||||
.authorityListToSet(this.populator.getGrantedAuthorities(ctx, "notused"));
|
||||
|
||||
assertThat(authorities).as("Should have 1 role").hasSize(1);
|
||||
assertThat(authorities.contains("ROLE_MANAGER")).isTrue();
|
||||
|
||||
@@ -63,7 +63,7 @@ public class LdapUserDetailsManagerModifyPasswordTests {
|
||||
@WithMockUser(username = "bob", password = "bobspassword", authorities = "ROLE_USER")
|
||||
public void changePasswordWhenOldPasswordIsIncorrectThenThrowsException() {
|
||||
assertThatExceptionOfType(BadCredentialsException.class)
|
||||
.isThrownBy(() -> this.userDetailsManager.changePassword("wrongoldpassword", "bobsnewpassword"));
|
||||
.isThrownBy(() -> this.userDetailsManager.changePassword("wrongoldpassword", "bobsnewpassword"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -76,7 +76,7 @@ public class LdapUserDetailsManagerModifyPasswordTests {
|
||||
|
||||
assertThat(template.compare("uid=bob,ou=people", "userPassword",
|
||||
"bobsshinynewandformidablylongandnearlyimpossibletorememberthoughdemonstrablyhardtocrackduetoitshighlevelofentropypasswordofjustice"))
|
||||
.isTrue();
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -197,13 +197,14 @@ public class LdapUserDetailsManagerTests {
|
||||
|
||||
this.mgr.createUser(p.createUserDetails());
|
||||
|
||||
SecurityContextHolder.getContext().setAuthentication(UsernamePasswordAuthenticationToken
|
||||
.authenticated("johnyossarian", "yossarianspassword", TEST_AUTHORITIES));
|
||||
SecurityContextHolder.getContext()
|
||||
.setAuthentication(UsernamePasswordAuthenticationToken.authenticated("johnyossarian", "yossarianspassword",
|
||||
TEST_AUTHORITIES));
|
||||
|
||||
this.mgr.changePassword("yossarianspassword", "yossariansnewpassword");
|
||||
|
||||
assertThat(this.template.compare("uid=johnyossarian,ou=test people", "userPassword", "yossariansnewpassword"))
|
||||
.isTrue();
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -220,13 +221,13 @@ public class LdapUserDetailsManagerTests {
|
||||
|
||||
SecurityContextHolderStrategy strategy = mock(SecurityContextHolderStrategy.class);
|
||||
given(strategy.getContext()).willReturn(new SecurityContextImpl(UsernamePasswordAuthenticationToken
|
||||
.authenticated("johnyossarian", "yossarianspassword", TEST_AUTHORITIES)));
|
||||
.authenticated("johnyossarian", "yossarianspassword", TEST_AUTHORITIES)));
|
||||
this.mgr.setSecurityContextHolderStrategy(strategy);
|
||||
|
||||
this.mgr.changePassword("yossarianspassword", "yossariansnewpassword");
|
||||
|
||||
assertThat(this.template.compare("uid=johnyossarian,ou=test people", "userPassword", "yossariansnewpassword"))
|
||||
.isTrue();
|
||||
.isTrue();
|
||||
verify(strategy).getContext();
|
||||
}
|
||||
|
||||
@@ -240,10 +241,11 @@ public class LdapUserDetailsManagerTests {
|
||||
p.setPassword("yossarianspassword");
|
||||
p.setAuthorities(TEST_AUTHORITIES);
|
||||
this.mgr.createUser(p.createUserDetails());
|
||||
SecurityContextHolder.getContext().setAuthentication(UsernamePasswordAuthenticationToken
|
||||
.authenticated("johnyossarian", "yossarianspassword", TEST_AUTHORITIES));
|
||||
SecurityContextHolder.getContext()
|
||||
.setAuthentication(UsernamePasswordAuthenticationToken.authenticated("johnyossarian", "yossarianspassword",
|
||||
TEST_AUTHORITIES));
|
||||
assertThatExceptionOfType(BadCredentialsException.class)
|
||||
.isThrownBy(() -> this.mgr.changePassword("wrongpassword", "yossariansnewpassword"));
|
||||
.isThrownBy(() -> this.mgr.changePassword("wrongpassword", "yossariansnewpassword"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ public class NestedLdapAuthoritiesPopulatorTests {
|
||||
assertThat(ldapAuthorities[0].getAttributes().get("member")).isNotNull();
|
||||
assertThat(ldapAuthorities[0].getAttributes().get("member")).hasSize(3);
|
||||
assertThat(ldapAuthorities[0].getFirstAttributeValue("member"))
|
||||
.isEqualTo("cn=groovy-developers,ou=jdeveloper,dc=springframework,dc=org");
|
||||
.isEqualTo("cn=groovy-developers,ou=jdeveloper,dc=springframework,dc=org");
|
||||
|
||||
// java group
|
||||
assertThat(ldapAuthorities[1].getAttributes().containsKey("member")).isTrue();
|
||||
@@ -140,7 +140,7 @@ public class NestedLdapAuthoritiesPopulatorTests {
|
||||
assertThat(ldapAuthorities[1].getAttributes().get("member")).hasSize(3);
|
||||
assertThat(this.groovyDevelopers.getDn()).isEqualTo(ldapAuthorities[1].getFirstAttributeValue("member"));
|
||||
assertThat(ldapAuthorities[2].getAttributes().get("member"))
|
||||
.contains("uid=closuredude,ou=people,dc=springframework,dc=org");
|
||||
.contains("uid=closuredude,ou=people,dc=springframework,dc=org");
|
||||
|
||||
// test non existent attribute
|
||||
assertThat(ldapAuthorities[2].getFirstAttributeValue("test")).isNull();
|
||||
|
||||
Reference in New Issue
Block a user