Author: pauls Date: Mon Jul 10 15:46:19 2017 New Revision: 1801483 URL: http://svn.apache.org/viewvc?rev=1801483&view=rev Log: SLING-6973: Adjust AbstractSlingRepository2 to reflect SLING-6963 - patch provided by Angela Schreiber.
Modified: sling/trunk/bundles/jcr/base/pom.xml sling/trunk/bundles/jcr/base/src/main/java/org/apache/sling/jcr/base/AbstractSlingRepository2.java sling/trunk/bundles/jcr/base/src/main/java/org/apache/sling/jcr/base/package-info.java sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/MockSlingRepository2.java sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/internal/WhitelistWiringTest.java Modified: sling/trunk/bundles/jcr/base/pom.xml URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/base/pom.xml?rev=1801483&r1=1801482&r2=1801483&view=diff ============================================================================== --- sling/trunk/bundles/jcr/base/pom.xml (original) +++ sling/trunk/bundles/jcr/base/pom.xml Mon Jul 10 15:46:19 2017 @@ -111,7 +111,7 @@ <dependency> <groupId>org.apache.sling</groupId> <artifactId>org.apache.sling.serviceusermapper</artifactId> - <version>1.0.0</version> + <version>1.3.3-SNAPSHOT</version> <scope>provided</scope> </dependency> Modified: sling/trunk/bundles/jcr/base/src/main/java/org/apache/sling/jcr/base/AbstractSlingRepository2.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/base/src/main/java/org/apache/sling/jcr/base/AbstractSlingRepository2.java?rev=1801483&r1=1801482&r2=1801483&view=diff ============================================================================== --- sling/trunk/bundles/jcr/base/src/main/java/org/apache/sling/jcr/base/AbstractSlingRepository2.java (original) +++ sling/trunk/bundles/jcr/base/src/main/java/org/apache/sling/jcr/base/AbstractSlingRepository2.java Mon Jul 10 15:46:19 2017 @@ -18,6 +18,12 @@ */ package org.apache.sling.jcr.base; +import java.security.Principal; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; import javax.jcr.Credentials; import javax.jcr.GuestCredentials; import javax.jcr.LoginException; @@ -27,6 +33,7 @@ import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.SimpleCredentials; import javax.jcr.Value; +import javax.security.auth.Subject; import org.apache.sling.jcr.api.SlingRepository; import org.apache.sling.serviceusermapping.ServiceUserMapper; @@ -90,7 +97,7 @@ public abstract class AbstractSlingRepos if(usingBundle == null) { throw new IllegalArgumentException("usingBundle is null"); } - } + } /** * @return The {@link AbstractSlingRepositoryManager} controlling this @@ -138,6 +145,35 @@ public abstract class AbstractSlingRepos */ protected abstract Session createAdministrativeSession(final String workspace) throws RepositoryException; + + /** + * Creates a new service-session. This method is used by {@link #loginService(String, String)} + * and {@link #impersonateFromService(String, Credentials, String)} to avoid + * code duplication. + * + * @param usingBundle The bundle using a service session. + * @param subServiceName The optional name of the subservice. + * @param workspaceName The JCR workspace name or {@code null}. + * @return A new service session or {@code null} if neither a user-name nor a + * principal names mapping has been defined. + * @throws RepositoryException If an error occurs while creating the service session. + */ + private Session createServiceSession(Bundle usingBundle, String subServiceName, String workspaceName) throws RepositoryException { + final ServiceUserMapper serviceUserMapper = this.getSlingRepositoryManager().getServiceUserMapper(); + if (serviceUserMapper != null) { + final Iterable<String> principalNames = serviceUserMapper.getServicePrincipalNames(usingBundle, subServiceName); + if (principalNames != null) { + return createServiceSession(principalNames, workspaceName); + } + + final String userName = serviceUserMapper.getServiceUserID(usingBundle, subServiceName); + if (userName != null) { + return createServiceSession(userName, workspaceName); + } + } + return null; + } + /** * Creates a service-session for the service's {@code serviceUserName} by * impersonating the user from an administrative session. @@ -170,6 +206,44 @@ public abstract class AbstractSlingRepos } } + /** + * Creates a service-session for the service's {@code servicePrincipalNames} + * using a pre-authenticated {@link Subject}. + * <p> + * Implementations of this class may overwrite this method to meet additional + * needs wrt the the nature of the principals, the {@code Subject} or additional + * attributes passed to the repository login. + * + * @param servicePrincipalNames The names of the service principals to create the session for + * @param workspace The workspace to access or {@code null} to access the {@link #getDefaultWorkspace() default workspace} + * @return A new service session + * @throws RepositoryException If a general error occurs while creating the session. + */ + protected Session createServiceSession(final Iterable<String> servicePrincipalNames, final String workspaceName) throws RepositoryException { + Set<Principal> principals = new HashSet<>(); + for (final String pName : servicePrincipalNames) { + if (pName != null && !pName.isEmpty()) { + principals.add(new Principal() { + @Override + public String getName() { + return pName; + } + }); + } + }; + Subject subject = new Subject(true, principals, Collections.emptySet(), Collections.emptySet()); + try { + return Subject.doAsPrivileged(subject, new PrivilegedExceptionAction<Session>() { + @Override + public Session run() throws Exception { + return AbstractSlingRepository2.this.getRepository().login(null, workspaceName); + } + }, null); + } catch (PrivilegedActionException e) { + throw new RepositoryException("failed to retrieve service session.", e); + } + } + // login implementations (may be overwritten) /** @@ -250,7 +324,7 @@ public abstract class AbstractSlingRepos */ @Override public Session login(Credentials credentials, String workspace) - throws LoginException, NoSuchWorkspaceException, RepositoryException { + throws LoginException, NoSuchWorkspaceException, RepositoryException { if (credentials == null) { credentials = new GuestCredentials(); @@ -303,15 +377,13 @@ public abstract class AbstractSlingRepos */ @Override public final Session loginService(final String subServiceName, final String workspace) - throws LoginException, RepositoryException { - final ServiceUserMapper serviceUserMapper = this.getSlingRepositoryManager().getServiceUserMapper(); - final String userName = (serviceUserMapper != null) ? serviceUserMapper.getServiceUserID(this.usingBundle, - subServiceName) : null; - if (userName == null) { - throw new LoginException("Cannot derive user name for bundle " + usingBundle + " and sub service " - + subServiceName); + throws LoginException, RepositoryException { + Session s = createServiceSession(usingBundle, subServiceName, workspace); + if (s != null) { + return s; + } else { + throw new LoginException("Can neither derive user name nor principal names for bundle " + usingBundle + " and sub service " + subServiceName); } - return createServiceSession(userName, workspace); } /** @@ -337,15 +409,12 @@ public abstract class AbstractSlingRepos @Override public Session impersonateFromService(final String subServiceName, final Credentials credentials, final String workspaceName) throws LoginException, RepositoryException { - final ServiceUserMapper serviceUserMapper = this.getSlingRepositoryManager().getServiceUserMapper(); - final String userName = (serviceUserMapper != null) ? serviceUserMapper.getServiceUserID(this.usingBundle, - subServiceName) : null; - if (userName == null) { - throw new LoginException("Cannot derive user name for bundle " + usingBundle + " and sub service " + subServiceName); - } Session serviceSession = null; try { - serviceSession = createServiceSession(userName, workspaceName); + serviceSession = createServiceSession(usingBundle, subServiceName, workspaceName); + if (serviceSession == null) { + throw new LoginException("Cannot create service session for bundle " + usingBundle + " and sub service " + subServiceName); + } return serviceSession.impersonate(credentials); } finally { if (serviceSession != null) { Modified: sling/trunk/bundles/jcr/base/src/main/java/org/apache/sling/jcr/base/package-info.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/base/src/main/java/org/apache/sling/jcr/base/package-info.java?rev=1801483&r1=1801482&r2=1801483&view=diff ============================================================================== --- sling/trunk/bundles/jcr/base/src/main/java/org/apache/sling/jcr/base/package-info.java (original) +++ sling/trunk/bundles/jcr/base/src/main/java/org/apache/sling/jcr/base/package-info.java Mon Jul 10 15:46:19 2017 @@ -25,7 +25,7 @@ * {@link org.apache.sling.jcr.base.AbstractSlingRepository2} being the * basis for the repository service instance handed to using bundles. */ -@org.osgi.annotation.versioning.Version("3.2.0") +@org.osgi.annotation.versioning.Version("3.3.0") package org.apache.sling.jcr.base; Modified: sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/MockSlingRepository2.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/MockSlingRepository2.java?rev=1801483&r1=1801482&r2=1801483&view=diff ============================================================================== --- sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/MockSlingRepository2.java (original) +++ sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/MockSlingRepository2.java Mon Jul 10 15:46:19 2017 @@ -35,4 +35,9 @@ class MockSlingRepository2 extends Abstr // Assuming we run on a test repo with no access control return getRepository().login(); } + + @Override + protected Session createServiceSession(Iterable<String> principalNames, String workspace) throws RepositoryException { + return getRepository().login(); + } } \ No newline at end of file Modified: sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/internal/WhitelistWiringTest.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/internal/WhitelistWiringTest.java?rev=1801483&r1=1801482&r2=1801483&view=diff ============================================================================== --- sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/internal/WhitelistWiringTest.java (original) +++ sling/trunk/bundles/jcr/base/src/test/java/org/apache/sling/jcr/base/internal/WhitelistWiringTest.java Mon Jul 10 15:46:19 2017 @@ -89,6 +89,11 @@ public class WhitelistWiringTest { protected Session createAdministrativeSession(String workspace) throws RepositoryException { return Mockito.mock(Session.class); } + + @Override + protected Session createServiceSession(Iterable<String> principalNames, String workspace) { + return Mockito.mock(Session.class); + } }; }