This is an automated email from the ASF dual-hosted git repository.
apkhmv pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new d32ef2e80c IGNITE-23100 Improve semantic of authenticateAsync (#4306)
d32ef2e80c is described below
commit d32ef2e80cac654dea8fe26b0c75cd5d4ae62766
Author: Vadim Pakhnushev <[email protected]>
AuthorDate: Thu Aug 29 14:11:46 2024 +0300
IGNITE-23100 Improve semantic of authenticateAsync (#4306)
---
.../authentication/AuthenticationManagerImpl.java | 43 +++++++++-------------
.../authentication/basic/BasicAuthenticator.java | 7 ++--
.../AuthenticationManagerImplTest.java | 30 ++++++++-------
.../authentication/UserDetailsMatcher.java | 43 ++++++++++++++++++++++
.../basic/BasicAuthenticatorTest.java | 41 ++++++++++-----------
5 files changed, 101 insertions(+), 63 deletions(-)
diff --git
a/modules/security/src/main/java/org/apache/ignite/internal/security/authentication/AuthenticationManagerImpl.java
b/modules/security/src/main/java/org/apache/ignite/internal/security/authentication/AuthenticationManagerImpl.java
index bbb6141d89..153d1a9ea9 100644
---
a/modules/security/src/main/java/org/apache/ignite/internal/security/authentication/AuthenticationManagerImpl.java
+++
b/modules/security/src/main/java/org/apache/ignite/internal/security/authentication/AuthenticationManagerImpl.java
@@ -180,34 +180,27 @@ public class AuthenticationManagerImpl
AuthenticationRequest<?, ?> authenticationRequest
) {
try {
- var fut = authenticator.authenticateAsync(authenticationRequest);
-
- fut.thenAccept(userDetails -> {
- if (userDetails != null) {
- logUserAuthenticated(userDetails);
- }
- });
-
- return fut.handle((userDetails, throwable) -> {
- if (throwable != null) {
- if (!(throwable instanceof InvalidCredentialsException
- || throwable instanceof
UnsupportedAuthenticationTypeException)) {
- LOG.error("Unexpected exception during
authentication", throwable);
- }
-
- logAuthenticationFailure(authenticationRequest);
- return null;
- }
-
- return userDetails;
- });
- } catch (InvalidCredentialsException |
UnsupportedAuthenticationTypeException exception) {
- logAuthenticationFailure(authenticationRequest);
- return completedFuture(null);
+ return authenticator.authenticateAsync(authenticationRequest)
+ .handle((userDetails, throwable) -> {
+ if (throwable != null) {
+ if (!(throwable instanceof
InvalidCredentialsException
+ || throwable instanceof
UnsupportedAuthenticationTypeException)) {
+ LOG.error("Unexpected exception during
authentication", throwable);
+ }
+
+ logAuthenticationFailure(authenticationRequest);
+ return null;
+ }
+
+ if (userDetails != null) {
+ logUserAuthenticated(userDetails);
+ }
+ return userDetails;
+ });
} catch (Exception e) {
logAuthenticationFailure(authenticationRequest);
LOG.error("Unexpected exception during authentication", e);
- return completedFuture(null);
+ return nullCompletedFuture();
}
}
diff --git
a/modules/security/src/main/java/org/apache/ignite/internal/security/authentication/basic/BasicAuthenticator.java
b/modules/security/src/main/java/org/apache/ignite/internal/security/authentication/basic/BasicAuthenticator.java
index 0e43fcd35b..677a3eaf51 100644
---
a/modules/security/src/main/java/org/apache/ignite/internal/security/authentication/basic/BasicAuthenticator.java
+++
b/modules/security/src/main/java/org/apache/ignite/internal/security/authentication/basic/BasicAuthenticator.java
@@ -18,6 +18,7 @@
package org.apache.ignite.internal.security.authentication.basic;
import static java.util.concurrent.CompletableFuture.completedFuture;
+import static java.util.concurrent.CompletableFuture.failedFuture;
import static java.util.function.Function.identity;
import java.util.List;
@@ -51,9 +52,9 @@ public class BasicAuthenticator implements Authenticator {
@Override
public CompletableFuture<UserDetails>
authenticateAsync(AuthenticationRequest<?, ?> authenticationRequest) {
if (!(authenticationRequest instanceof UsernamePasswordRequest)) {
- throw new UnsupportedAuthenticationTypeException(
+ return failedFuture(new UnsupportedAuthenticationTypeException(
"Unsupported authentication type: " +
authenticationRequest.getClass().getName()
- );
+ ));
}
Object requestUsername = authenticationRequest.getIdentity();
@@ -66,6 +67,6 @@ public class BasicAuthenticator implements Authenticator {
}
}
- throw new InvalidCredentialsException("Invalid credentials");
+ return failedFuture(new InvalidCredentialsException("Invalid
credentials"));
}
}
diff --git
a/modules/security/src/test/java/org/apache/ignite/internal/security/authentication/AuthenticationManagerImplTest.java
b/modules/security/src/test/java/org/apache/ignite/internal/security/authentication/AuthenticationManagerImplTest.java
index a3d0cd6b08..0424a97465 100644
---
a/modules/security/src/test/java/org/apache/ignite/internal/security/authentication/AuthenticationManagerImplTest.java
+++
b/modules/security/src/test/java/org/apache/ignite/internal/security/authentication/AuthenticationManagerImplTest.java
@@ -17,16 +17,20 @@
package org.apache.ignite.internal.security.authentication;
+import static java.util.concurrent.CompletableFuture.completedFuture;
+import static java.util.concurrent.CompletableFuture.failedFuture;
+import static
org.apache.ignite.internal.security.authentication.UserDetailsMatcher.username;
import static
org.apache.ignite.internal.security.authentication.event.AuthenticationEvent.AUTHENTICATION_DISABLED;
import static
org.apache.ignite.internal.security.authentication.event.AuthenticationEvent.AUTHENTICATION_ENABLED;
import static
org.apache.ignite.internal.security.authentication.event.AuthenticationEvent.AUTHENTICATION_PROVIDER_REMOVED;
import static
org.apache.ignite.internal.security.authentication.event.AuthenticationEvent.AUTHENTICATION_PROVIDER_UPDATED;
+import static
org.apache.ignite.internal.testframework.matchers.CompletableFutureExceptionMatcher.willThrow;
+import static
org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willBe;
import static
org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully;
import static
org.apache.ignite.internal.util.CompletableFutures.falseCompletedFuture;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertInstanceOf;
-import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
@@ -35,7 +39,6 @@ import static org.mockito.Mockito.verify;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CompletionException;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Consumer;
import org.apache.ignite.configuration.annotation.ConfigurationType;
@@ -281,7 +284,7 @@ class AuthenticationManagerImplTest extends
BaseIgniteAbstractTest {
// then
// successful authentication with valid credentials
- assertEquals(USERNAME,
manager.authenticateAsync(USERNAME_PASSWORD_REQUEST).join().username());
+ assertThat(manager.authenticateAsync(USERNAME_PASSWORD_REQUEST),
willBe(username(is(USERNAME))));
}
@Test
@@ -291,10 +294,9 @@ class AuthenticationManagerImplTest extends
BaseIgniteAbstractTest {
// then
// failed authentication with invalid credentials
- CompletionException ex = assertThrows(CompletionException.class,
- () -> manager.authenticateAsync(new
UsernamePasswordRequest(USERNAME, "invalid-password")).join());
-
- assertInstanceOf(InvalidCredentialsException.class, ex.getCause());
+ assertThat(
+ manager.authenticateAsync(new
UsernamePasswordRequest(USERNAME, "invalid-password")),
+ willThrow(InvalidCredentialsException.class));
}
@Test
@@ -303,7 +305,7 @@ class AuthenticationManagerImplTest extends
BaseIgniteAbstractTest {
disableAuthentication();
// then
- assertEquals(UserDetails.UNKNOWN,
manager.authenticateAsync(USERNAME_PASSWORD_REQUEST).join());
+ assertThat(manager.authenticateAsync(USERNAME_PASSWORD_REQUEST),
willBe(UserDetails.UNKNOWN));
}
@Test
@@ -311,21 +313,23 @@ class AuthenticationManagerImplTest extends
BaseIgniteAbstractTest {
UsernamePasswordRequest credentials = new
UsernamePasswordRequest("admin", "password");
Authenticator authenticator1 = mock(Authenticator.class);
- doThrow(new InvalidCredentialsException("Invalid
credentials")).when(authenticator1).authenticateAsync(credentials);
+ doReturn(failedFuture(new InvalidCredentialsException("Invalid
credentials")))
+ .when(authenticator1).authenticateAsync(credentials);
Authenticator authenticator2 = mock(Authenticator.class);
- doThrow(new UnsupportedAuthenticationTypeException("Unsupported
type")).when(authenticator2).authenticateAsync(credentials);
+ doReturn(failedFuture(new
UnsupportedAuthenticationTypeException("Unsupported type")))
+ .when(authenticator2).authenticateAsync(credentials);
Authenticator authenticator3 = mock(Authenticator.class);
doThrow(new RuntimeException("Test
exception")).when(authenticator3).authenticateAsync(credentials);
Authenticator authenticator4 = mock(Authenticator.class);
- doReturn(CompletableFuture.completedFuture(new UserDetails("admin",
"mock")))
+ doReturn(completedFuture(new UserDetails("admin", "mock")))
.when(authenticator4).authenticateAsync(credentials);
manager.authenticators(List.of(authenticator1, authenticator2,
authenticator3, authenticator4));
- assertEquals("admin",
manager.authenticateAsync(credentials).join().username());
+ assertThat(manager.authenticateAsync(credentials),
willBe(username(is("admin"))));
verify(authenticator1).authenticateAsync(credentials);
verify(authenticator2).authenticateAsync(credentials);
diff --git
a/modules/security/src/test/java/org/apache/ignite/internal/security/authentication/UserDetailsMatcher.java
b/modules/security/src/test/java/org/apache/ignite/internal/security/authentication/UserDetailsMatcher.java
new file mode 100644
index 0000000000..2733608039
--- /dev/null
+++
b/modules/security/src/test/java/org/apache/ignite/internal/security/authentication/UserDetailsMatcher.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.ignite.internal.security.authentication;
+
+import org.hamcrest.FeatureMatcher;
+import org.hamcrest.Matcher;
+
+/**
+ * Matchers for {@link UserDetails}.
+ */
+public class UserDetailsMatcher {
+
+ /**
+ * Constructs a matcher for {@link UserDetails} with matching username.
+ *
+ * @param subMatcher The matcher to apply to the username.
+ * @return Matcher for {@link UserDetails} with matching username.
+ */
+ public static FeatureMatcher<UserDetails, String> username(Matcher<? super
String> subMatcher) {
+ return new FeatureMatcher<>(subMatcher, "UserDetails with username",
"username") {
+
+ @Override
+ protected String featureValueOf(UserDetails actual) {
+ return actual.username();
+ }
+ };
+ }
+}
diff --git
a/modules/security/src/test/java/org/apache/ignite/internal/security/authentication/basic/BasicAuthenticatorTest.java
b/modules/security/src/test/java/org/apache/ignite/internal/security/authentication/basic/BasicAuthenticatorTest.java
index 46fd945362..d7e10286fb 100644
---
a/modules/security/src/test/java/org/apache/ignite/internal/security/authentication/basic/BasicAuthenticatorTest.java
+++
b/modules/security/src/test/java/org/apache/ignite/internal/security/authentication/basic/BasicAuthenticatorTest.java
@@ -17,12 +17,14 @@
package org.apache.ignite.internal.security.authentication.basic;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
+import static
org.apache.ignite.internal.security.authentication.UserDetailsMatcher.username;
+import static
org.apache.ignite.internal.testframework.matchers.CompletableFutureExceptionMatcher.willThrow;
+import static
org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willBe;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
import java.util.List;
import org.apache.ignite.internal.security.authentication.AnonymousRequest;
-import org.apache.ignite.internal.security.authentication.UserDetails;
import
org.apache.ignite.internal.security.authentication.UsernamePasswordRequest;
import org.apache.ignite.security.exception.InvalidCredentialsException;
import
org.apache.ignite.security.exception.UnsupportedAuthenticationTypeException;
@@ -36,33 +38,28 @@ class BasicAuthenticatorTest {
@Test
void authenticate() {
- // when
- UserDetails userDetails = authenticator.authenticateAsync(new
UsernamePasswordRequest("admin", "password")).join();
-
- // then
- assertEquals("admin", userDetails.username());
+ assertThat(
+ authenticator.authenticateAsync(new
UsernamePasswordRequest("admin", "password")),
+ willBe(username(is("admin")))
+ );
}
@Test
void authenticateInvalidCredentials() {
- // when
- InvalidCredentialsException exception =
assertThrows(InvalidCredentialsException.class, () -> {
- authenticator.authenticateAsync(new
UsernamePasswordRequest("admin", "invalid"));
- });
-
- // then
- assertEquals("Invalid credentials", exception.getMessage());
+ assertThat(
+ authenticator.authenticateAsync(new
UsernamePasswordRequest("admin", "invalid")),
+ willThrow(InvalidCredentialsException.class, "Invalid
credentials")
+ );
}
@Test
void authenticateUnsupportedAuthenticationType() {
- // when
- UnsupportedAuthenticationTypeException exception = assertThrows(
- UnsupportedAuthenticationTypeException.class,
- () -> authenticator.authenticateAsync(new AnonymousRequest())
+ assertThat(
+ authenticator.authenticateAsync(new AnonymousRequest()),
+ willThrow(
+ UnsupportedAuthenticationTypeException.class,
+ "Unsupported authentication type: " +
AnonymousRequest.class.getName()
+ )
);
-
- // then
- assertEquals("Unsupported authentication type: " +
AnonymousRequest.class.getName(), exception.getMessage());
}
}