This is an automated email from the ASF dual-hosted git repository.
rombert pushed a commit to branch master
in repository
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-auth-oauth-client.git
The following commit(s) were added to refs/heads/master by this push:
new 3846f33 test: extract a test-only InMemoryOAuthTokenStore (#4)
3846f33 is described below
commit 3846f3353a8a71820733054cfd33146663f7e314
Author: Robert Munteanu <[email protected]>
AuthorDate: Mon Dec 9 15:50:21 2024 +0100
test: extract a test-only InMemoryOAuthTokenStore (#4)
---
.../auth/oauth_client/InMemoryOAuthTokenStore.java | 95 ++++++++++++++++++++++
.../impl/InMemoryOAuthTokenStoreTest.java | 36 ++++++++
.../impl/OAuthCallbackServletTest.java | 49 ++---------
3 files changed, 137 insertions(+), 43 deletions(-)
diff --git
a/src/test/java/org/apache/sling/auth/oauth_client/InMemoryOAuthTokenStore.java
b/src/test/java/org/apache/sling/auth/oauth_client/InMemoryOAuthTokenStore.java
new file mode 100644
index 0000000..cfdc16f
--- /dev/null
+++
b/src/test/java/org/apache/sling/auth/oauth_client/InMemoryOAuthTokenStore.java
@@ -0,0 +1,95 @@
+/*
+ * 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.sling.auth.oauth_client;
+
+import java.time.Instant;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import org.apache.sling.api.resource.ResourceResolver;
+
+/**
+ * In-memory, volatile token store implementation
+ *
+ * <p>This implementation exists for testing purposes only</p>
+ */
+public class InMemoryOAuthTokenStore implements OAuthTokenStore {
+
+ record Key(String connectionName, String userId) {}
+
+ record Value(OAuthTokens tokens, Instant expires) {
+
+ public Value(OAuthTokens tokens) {
+ this(tokens, tokens.expiresAt() != 0 ?
Instant.now().plusSeconds(tokens.expiresAt()) : null);
+ }
+
+ public boolean isValid() {
+ return expires == null || expires.isAfter(Instant.now());
+ }
+
+ }
+
+ private final Map<Key, Value> storage = new HashMap<>();
+
+ @Override
+ public void persistTokens(ClientConnection connection, ResourceResolver
resolver, OAuthTokens tokens)
+ throws OAuthException {
+ storage.put(new Key(connection.name(), resolver.getUserID()), new
Value(tokens));
+ }
+
+ @Override
+ public OAuthToken getRefreshToken(ClientConnection connection,
ResourceResolver resolver) throws OAuthException {
+ Value value = storage.get(new Key(connection.name(),
resolver.getUserID()));
+ if (value == null || value.tokens == null ||
value.tokens.refreshToken() == null)
+ return new OAuthToken(TokenState.MISSING, null);
+
+ return new OAuthToken(TokenState.VALID, value.tokens.refreshToken());
+ }
+
+ @Override
+ public OAuthToken getAccessToken(ClientConnection connection,
ResourceResolver resolver) throws OAuthException {
+ Value value = storage.get(new Key(connection.name(),
resolver.getUserID()));
+ if (value == null || value.tokens == null ||
value.tokens.accessToken() == null )
+ return new OAuthToken(TokenState.MISSING, null);
+
+ if (!value.isValid())
+ return new OAuthToken(TokenState.EXPIRED,
value.tokens.accessToken());
+
+ return new OAuthToken(TokenState.VALID, value.tokens.accessToken());
+
+ }
+
+ @Override
+ public void clearAccessToken(ClientConnection connection, ResourceResolver
resolver) throws OAuthException {
+ Key key = new Key(connection.name(), resolver.getUserID());
+ Value value = storage.get(key);
+
+ // preserve the refresh token is present
+ if ( value != null && value.tokens != null &&
value.tokens.refreshToken() != null ) {
+ OAuthTokens newTokens = new OAuthTokens(null, 0,
value.tokens.refreshToken());
+ storage.put(key, new Value(newTokens));
+ // remover all tokens if only the access token is present
+ } else if ( value != null ) {
+ storage.remove(key);
+ }
+ }
+
+ public Stream<OAuthTokens> allTokens() {
+ return storage.values().stream().map(Value::tokens);
+ }
+}
\ No newline at end of file
diff --git
a/src/test/java/org/apache/sling/auth/oauth_client/impl/InMemoryOAuthTokenStoreTest.java
b/src/test/java/org/apache/sling/auth/oauth_client/impl/InMemoryOAuthTokenStoreTest.java
new file mode 100644
index 0000000..3f6a7af
--- /dev/null
+++
b/src/test/java/org/apache/sling/auth/oauth_client/impl/InMemoryOAuthTokenStoreTest.java
@@ -0,0 +1,36 @@
+/*
+ * 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.sling.auth.oauth_client.impl;
+
+import org.apache.sling.auth.oauth_client.InMemoryOAuthTokenStore;
+import org.apache.sling.testing.mock.sling.ResourceResolverType;
+import org.apache.sling.testing.mock.sling.junit5.SlingContext;
+import org.testcontainers.junit.jupiter.Testcontainers;
+
+@Testcontainers
+public class InMemoryOAuthTokenStoreTest extends
TokenStoreTestSupport<InMemoryOAuthTokenStore> {
+
+
+ InMemoryOAuthTokenStoreTest() {
+ super(MockOidcConnection.DEFAULT_CONNECTION, new
SlingContext(ResourceResolverType.JCR_MOCK));
+ }
+
+ @Override
+ InMemoryOAuthTokenStore createTokenStore() {
+ return new InMemoryOAuthTokenStore();
+ }
+}
diff --git
a/src/test/java/org/apache/sling/auth/oauth_client/impl/OAuthCallbackServletTest.java
b/src/test/java/org/apache/sling/auth/oauth_client/impl/OAuthCallbackServletTest.java
index 807b423..f603fdc 100644
---
a/src/test/java/org/apache/sling/auth/oauth_client/impl/OAuthCallbackServletTest.java
+++
b/src/test/java/org/apache/sling/auth/oauth_client/impl/OAuthCallbackServletTest.java
@@ -32,15 +32,9 @@ import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
-import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.auth.oauth_client.ClientConnection;
-import org.apache.sling.auth.oauth_client.OAuthException;
-import org.apache.sling.auth.oauth_client.OAuthToken;
-import org.apache.sling.auth.oauth_client.OAuthTokenStore;
+import org.apache.sling.auth.oauth_client.InMemoryOAuthTokenStore;
import org.apache.sling.auth.oauth_client.OAuthTokens;
-import org.apache.sling.auth.oauth_client.impl.OAuthCallbackException;
-import org.apache.sling.auth.oauth_client.impl.OAuthCallbackServlet;
-import org.apache.sling.auth.oauth_client.impl.OAuthStateManager;
import org.apache.sling.testing.mock.sling.junit5.SlingContext;
import org.apache.sling.testing.mock.sling.junit5.SlingContextExtension;
import org.junit.jupiter.api.AfterEach;
@@ -52,39 +46,6 @@ import com.sun.net.httpserver.HttpServer;
@ExtendWith(SlingContextExtension.class)
class OAuthCallbackServletTest {
-
- static final class StubOAuthTokenStore implements OAuthTokenStore {
-
- private OAuthTokens tokens;
-
- @Override
- public void persistTokens(ClientConnection connection,
ResourceResolver resolver, OAuthTokens tokens)
- throws OAuthException {
- if ( this.tokens != null )
- throw new IllegalStateException("Tokens already set once");
- this.tokens = tokens;
-
- }
-
- @Override
- public OAuthToken getRefreshToken(ClientConnection connection,
ResourceResolver resolver) throws OAuthException {
- throw new IllegalStateException("Not implemented");
- }
-
- @Override
- public OAuthToken getAccessToken(ClientConnection connection,
ResourceResolver resolver) throws OAuthException {
- throw new IllegalStateException("Not implemented");
- }
-
- @Override
- public void clearAccessToken(ClientConnection connection,
ResourceResolver resolver) throws OAuthException {
- throw new IllegalStateException("Not implemented");
- }
-
- public OAuthTokens getTokens() {
- return tokens;
- }
- }
private static final String MOCK_OIDC_PARAM = "mock-oidc-param";
@@ -94,7 +55,7 @@ class OAuthCallbackServletTest {
private HttpServer tokenEndpointServer;
- private StubOAuthTokenStore tokenStore;
+ private InMemoryOAuthTokenStore tokenStore;
private OAuthCallbackServlet servlet;
@@ -113,7 +74,7 @@ class OAuthCallbackServletTest {
)
);
- tokenStore = new StubOAuthTokenStore();
+ tokenStore = new InMemoryOAuthTokenStore();
servlet = new OAuthCallbackServlet(connections, tokenStore, new
StubOAuthStateManager());
}
@@ -255,7 +216,9 @@ class OAuthCallbackServletTest {
servlet.service(context.request(), context.response());
- assertThat(tokenStore.getTokens())
+ assertThat(tokenStore.allTokens())
+ .hasSize(1)
+ .element(0)
.isNotNull()
.extracting( OAuthTokens::accessToken )
.isEqualTo("Token");