This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to branch issue/memory-token-store-for-tests
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-auth-oauth-client.git

commit e20215730bfad497236a833b17982ab03808afea
Author: Robert Munteanu <[email protected]>
AuthorDate: Mon Dec 9 14:42:47 2024 +0100

    test: extract a test-only InMemoryOAuthTokenStore
---
 .../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");

Reply via email to