You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2013/10/21 10:12:08 UTC

svn commit: r1534058 - in /sling/trunk/bundles/extensions/webconsolesecurityprovider: ./ src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/ src/main/resources/

Author: cziegeler
Date: Mon Oct 21 08:12:07 2013
New Revision: 1534058

URL: http://svn.apache.org/r1534058
Log:
SLING-3193 : Implement WebConsoleSecurityProvider2 for integration with Sling Authenticator

Added:
    sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/AbstractWebConsoleSecurityProvider.java   (with props)
    sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/Activator.java   (with props)
    sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/ServicesListener.java   (with props)
    sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/SlingWebConsoleSecurityProvider2.java   (with props)
Removed:
    sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/resources/
Modified:
    sling/trunk/bundles/extensions/webconsolesecurityprovider/pom.xml
    sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/SlingWebConsoleSecurityProvider.java

Modified: sling/trunk/bundles/extensions/webconsolesecurityprovider/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/webconsolesecurityprovider/pom.xml?rev=1534058&r1=1534057&r2=1534058&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/webconsolesecurityprovider/pom.xml (original)
+++ sling/trunk/bundles/extensions/webconsolesecurityprovider/pom.xml Mon Oct 21 08:12:07 2013
@@ -56,6 +56,13 @@
                 <groupId>org.apache.felix</groupId>
                 <artifactId>maven-bundle-plugin</artifactId>
                 <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-Activator>
+                            org.apache.sling.extensions.webconsolesecurityprovider.internal.Activator
+                        </Bundle-Activator>
+                    </instructions>                
+                </configuration>
             </plugin>
         </plugins>
     </build>
@@ -74,19 +81,43 @@
 
     <dependencies>
         <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.apache.felix</groupId>
             <artifactId>org.apache.felix.webconsole</artifactId>
-            <version>3.1.0</version>
+            <version>4.2.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.api</artifactId>
+            <version>2.4.0</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.auth.core</artifactId>
+            <version>1.0.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+        </dependency>
+        <dependency>
             <groupId>javax.jcr</groupId>
             <artifactId>jcr</artifactId>
         </dependency>
         <dependency>
             <groupId>org.apache.jackrabbit</groupId>
             <artifactId>jackrabbit-api</artifactId>
-            <version>1.5.0</version>
+            <version>2.6.0</version>
             <scope>provided</scope>
         </dependency>
         <dependency>

Added: sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/AbstractWebConsoleSecurityProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/AbstractWebConsoleSecurityProvider.java?rev=1534058&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/AbstractWebConsoleSecurityProvider.java (added)
+++ sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/AbstractWebConsoleSecurityProvider.java Mon Oct 21 08:12:07 2013
@@ -0,0 +1,88 @@
+/*
+ * 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.extensions.webconsolesecurityprovider.internal;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.felix.webconsole.WebConsoleSecurityProvider;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This is the common base class for the two provider implementations.
+ * It handles the configuration of the service.
+ */
+public abstract class AbstractWebConsoleSecurityProvider
+    implements WebConsoleSecurityProvider, ManagedService {
+
+    // name of the property providing list of authorized users
+    private static final String PROP_USERS = "users";
+
+    // default user being authorized
+    public static final String PROP_GROUPS_DEFAULT_USER = "admin";
+
+    // name of the property providing list of groups whose members are
+    // authorized
+    private static final String PROP_GROUPS = "groups";
+
+    /** default logger */
+    protected final Logger logger = LoggerFactory.getLogger(getClass());
+
+    protected Set<String> users = Collections.singleton(PROP_GROUPS_DEFAULT_USER);
+
+    protected Set<String> groups = Collections.emptySet();
+
+    /**
+     * Handle configuration
+     * @see org.osgi.service.cm.ManagedService#updated(java.util.Dictionary)
+     */
+    public void updated(final Dictionary properties)
+            throws ConfigurationException {
+        this.users = toSet(properties == null ? null : properties.get(PROP_USERS), PROP_GROUPS_DEFAULT_USER);
+        this.groups = toSet(properties == null ? null : properties.get(PROP_GROUPS), null);
+    }
+
+    private Set<String> toSet(final Object configObj, final String defaultUser) {
+        final Set<String> groups = new HashSet<String>();
+        if (configObj instanceof String) {
+            groups.add((String) configObj);
+        } else if (configObj instanceof Collection<?>) {
+            for (Object obj : ((Collection<?>) configObj)) {
+                if (obj instanceof String) {
+                    groups.add((String) obj);
+                }
+            }
+        } else if (configObj instanceof String[]) {
+            for (String string : ((String[]) configObj)) {
+                if (string != null) {
+                    groups.add(string);
+                }
+            }
+        } else if (configObj == null && defaultUser != null) {
+            groups.add(defaultUser);
+        }
+        return groups;
+    }
+}

Propchange: sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/AbstractWebConsoleSecurityProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/AbstractWebConsoleSecurityProvider.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/AbstractWebConsoleSecurityProvider.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/Activator.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/Activator.java?rev=1534058&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/Activator.java (added)
+++ sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/Activator.java Mon Oct 21 08:12:07 2013
@@ -0,0 +1,42 @@
+/*
+ * 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.extensions.webconsolesecurityprovider.internal;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class Activator implements BundleActivator {
+
+    private ServicesListener listener;
+
+    /**
+     * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+     */
+    public void start(final BundleContext context) throws Exception {
+        listener = new ServicesListener(context);
+    }
+
+    /**
+     * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+     */
+    public void stop(final BundleContext context) throws Exception {
+        if ( listener != null ) {
+            listener.deactivate();
+            listener = null;
+        }
+    }
+}

Propchange: sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/Activator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/Activator.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/Activator.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/ServicesListener.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/ServicesListener.java?rev=1534058&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/ServicesListener.java (added)
+++ sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/ServicesListener.java Mon Oct 21 08:12:07 2013
@@ -0,0 +1,275 @@
+package org.apache.sling.extensions.webconsolesecurityprovider.internal;
+/*
+ * 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.
+ */
+
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import javax.jcr.Repository;
+
+import org.apache.felix.webconsole.WebConsoleSecurityProvider;
+import org.apache.sling.auth.core.AuthenticationSupport;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ManagedService;
+
+/**
+ * The <code>ServicesListener</code> listens for the required services
+ * and registers the security provider when required services are available
+ */
+public class ServicesListener {
+
+    /** The bundle context. */
+    private final BundleContext bundleContext;
+
+    /** The listener for the repository. */
+    private final Listener repositoryListener;
+
+    /** The listener for the authentication support. */
+    private final Listener authSupportListener;
+
+    private final SlingWebConsoleSecurityProvider provider = new SlingWebConsoleSecurityProvider();
+
+    private final SlingWebConsoleSecurityProvider2 provider2 = new SlingWebConsoleSecurityProvider2();
+
+    private enum State {
+        NONE,
+        PROVIDER,
+        PROVIDER2
+    };
+
+    /** State */
+    private volatile State registrationState = State.NONE;
+
+    /** The registration for the provider */
+    private ServiceRegistration providerReg;
+
+    /** The registration for the provider2 */
+    private ServiceRegistration provider2Reg;
+
+
+    /**
+     * Start listeners
+     */
+    public ServicesListener(final BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+        this.authSupportListener = new Listener(AuthenticationSupport.class.getName());
+        this.repositoryListener = new Listener(Repository.class.getName());
+        this.authSupportListener.start();
+        this.repositoryListener.start();
+    }
+
+    /**
+     * Notify of service changes from the listeners.
+     */
+    public synchronized void notifyChange() {
+        // check if all services are available
+        final AuthenticationSupport authSupport = (AuthenticationSupport)this.authSupportListener.getService();
+        final Repository repository = (Repository)this.repositoryListener.getService();
+        if ( registrationState == State.NONE ) {
+            if ( authSupport != null ) {
+                registerProvider2(authSupport);
+            } else if ( repository != null ) {
+                registerProvider(repository);
+            }
+        } else if ( registrationState == State.PROVIDER ) {
+            if ( authSupport != null ) {
+                registerProvider2(authSupport);
+                unregisterProvider();
+            } else if ( repository == null ) {
+                unregisterProvider();
+                this.registrationState = State.NONE;
+            } else {
+                this.provider.setService(repository);
+            }
+        } else {
+            if ( authSupport == null ) {
+                if ( repository != null ) {
+                    registerProvider(repository);
+                } else {
+                    this.registrationState = State.NONE;
+                }
+                unregisterProvider2();
+            } else {
+                this.provider2.setService(authSupport);
+            }
+        }
+    }
+
+    private void unregisterProvider2() {
+        if ( this.provider2Reg != null ) {
+            this.provider2Reg.unregister();
+            this.provider2Reg = null;
+        }
+        this.provider2.setService(null);
+    }
+
+    private void unregisterProvider() {
+        if ( this.providerReg != null ) {
+            this.providerReg.unregister();
+            this.providerReg = null;
+        }
+        this.provider.setService(null);
+    }
+
+    private void registerProvider2(final AuthenticationSupport authSupport) {
+        this.provider2.setService(authSupport);
+        final Dictionary<String, Object> props = new Hashtable<String, Object>();
+        props.put(Constants.SERVICE_PID, SlingWebConsoleSecurityProvider.class.getName());
+        props.put(Constants.SERVICE_DESCRIPTION, "Apache Sling Web Console Security Provider 2");
+        props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
+        this.provider2Reg = this.bundleContext.registerService(
+            new String[] {ManagedService.class.getName(), WebConsoleSecurityProvider.class.getName()}, this.provider2, props);
+        this.registrationState = State.PROVIDER2;
+    }
+
+    private void registerProvider(final Repository repository) {
+        this.provider.setService(repository);
+        final Dictionary<String, Object> props = new Hashtable<String, Object>();
+        props.put(Constants.SERVICE_PID, SlingWebConsoleSecurityProvider.class.getName());
+        props.put(Constants.SERVICE_DESCRIPTION, "Apache Sling Web Console Security Provider");
+        props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
+        this.providerReg = this.bundleContext.registerService(
+            new String[] {ManagedService.class.getName(), WebConsoleSecurityProvider.class.getName()}, this.provider, props);
+        this.registrationState = State.PROVIDER;
+    }
+
+    /**
+     * Deactivate this listener.
+     */
+    public void deactivate() {
+        this.repositoryListener.deactivate();
+        this.authSupportListener.deactivate();
+        this.unregisterProvider();
+        this.unregisterProvider2();
+    }
+
+    /**
+     * Helper class listening for service events for a defined service.
+     */
+    protected final class Listener implements ServiceListener {
+
+        /** The name of the service. */
+        private final String serviceName;
+
+        /** The service reference. */
+        private volatile ServiceReference reference;
+
+        /** The service. */
+        private volatile Object service;
+
+        /**
+         * Constructor
+         */
+        public Listener(final String serviceName) {
+            this.serviceName = serviceName;
+        }
+
+        /**
+         * Start the listener.
+         * First register a service listener and then check for the service.
+         */
+        public void start() {
+            try {
+                bundleContext.addServiceListener(this, "("
+                        + Constants.OBJECTCLASS + "=" + serviceName + ")");
+            } catch (final InvalidSyntaxException ise) {
+                // this should really never happen
+                throw new RuntimeException("Unexpected exception occured.", ise);
+            }
+            final ServiceReference ref = bundleContext.getServiceReference(serviceName);
+            if ( ref != null ) {
+                this.retainService(ref);
+            }
+        }
+
+        /**
+         * Unregister the listener.
+         */
+        public void deactivate() {
+            bundleContext.removeServiceListener(this);
+        }
+
+        /**
+         * Return the service (if available)
+         */
+        public synchronized Object getService() {
+            return this.service;
+        }
+
+        /**
+         * Try to get the service and notify the change.
+         */
+        private synchronized void retainService(final ServiceReference ref) {
+            boolean hadService = this.service != null;
+            boolean getService = this.reference == null;
+            if ( !getService ) {
+                final int result = this.reference.compareTo(ref);
+                if ( result < 0 ) {
+                    bundleContext.ungetService(this.reference);
+                    this.service = null;
+                    getService = true;
+                }
+            }
+            if ( getService ) {
+                this.reference = ref;
+                this.service = bundleContext.getService(this.reference);
+                if ( this.service == null ) {
+                    this.reference = null;
+                } else {
+                    notifyChange();
+                }
+            }
+            if ( hadService && this.service == null ) {
+                notifyChange();
+            }
+        }
+
+        /**
+         * Try to release the service and notify the change.
+         */
+        private synchronized void releaseService(final ServiceReference ref) {
+            if ( this.reference != null && this.reference.compareTo(ref) == 0) {
+                this.service = null;
+                bundleContext.ungetService(this.reference);
+                this.reference = null;
+                notifyChange();
+            }
+        }
+
+        /**
+         * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent)
+         */
+        public void serviceChanged(final ServiceEvent event) {
+            if (event.getType() == ServiceEvent.REGISTERED) {
+                this.retainService(event.getServiceReference());
+            } else if ( event.getType() == ServiceEvent.UNREGISTERING ) {
+                this.releaseService(event.getServiceReference());
+            } else if ( event.getType() == ServiceEvent.MODIFIED ) {
+                notifyChange();
+            }
+        }
+    }
+}

Propchange: sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/ServicesListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/ServicesListener.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/ServicesListener.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/SlingWebConsoleSecurityProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/SlingWebConsoleSecurityProvider.java?rev=1534058&r1=1534057&r2=1534058&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/SlingWebConsoleSecurityProvider.java (original)
+++ sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/SlingWebConsoleSecurityProvider.java Mon Oct 21 08:12:07 2013
@@ -18,33 +18,22 @@
  */
 package org.apache.sling.extensions.webconsolesecurityprovider.internal;
 
-import java.util.Collection;
-import java.util.HashSet;
 import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
 
 import javax.jcr.Credentials;
 import javax.jcr.LoginException;
 import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.SimpleCredentials;
 
-import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Modified;
+import org.apache.felix.scr.annotations.Properties;
 import org.apache.felix.scr.annotations.Property;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.Service;
-import org.apache.felix.webconsole.WebConsoleSecurityProvider;
 import org.apache.jackrabbit.api.JackrabbitSession;
 import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.jackrabbit.api.security.user.Group;
 import org.apache.jackrabbit.api.security.user.User;
 import org.apache.jackrabbit.api.security.user.UserManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * The <code>SlingWebConsoleSecurityProvider</code> is security provider for the
@@ -58,42 +47,35 @@ import org.slf4j.LoggerFactory;
  * only registered as a security provider service once such a JCR Repository is
  * available.
  */
-@Component(specVersion = "1.1", metatype = true)
-@Service(WebConsoleSecurityProvider.class)
-public class SlingWebConsoleSecurityProvider implements
-        WebConsoleSecurityProvider {
+@Component(ds=false, metatype=true,
+           label="Apache Sling Web Console Security Provider",
+           description="Configuration for the security provider used to verfiy user " +
+                       "credentials and grant access to the Apache Felix Web Console " +
+                       "based on registered JCR Repository users.")
+@Properties({
+    @Property(name = "users", value=AbstractWebConsoleSecurityProvider.PROP_GROUPS_DEFAULT_USER, cardinality=20,
+              label="User Names",
+              description="Names of users granted full access to the Apache Felix " +
+                          "Web Console. By default this lists the \"admin\" user. A maximum of 20 users" +
+                          " may be configured. Administrators are encouraged to create a group whose" +
+                          " members are to be granted access to Web Console instead of allowing access" +
+                          " to individual users."),
+    @Property(name = "groups", cardinality=20,
+             label="Group Names",
+             description="Names of groups whose members are granted full access to the Apache Felix " +
+                         "Web Console. The default lists no groups. Administrators are encouraged to " +
+                         "create a group whose members are to be granted access to the Web Console." +
+                         " A maximum of 20 groups may be configured. Using groups to control" +
+                         " access requires a Jackrabbit based repository.")
+})
+public class SlingWebConsoleSecurityProvider extends AbstractWebConsoleSecurityProvider {
 
-    // name of the property providing list of authorized users
-    private static final String PROP_USERS = "users";
-
-    // default user being authorized
-    private static final String PROP_GROUPS_DEFAULT_USER = "admin";
-
-    // name of the property providing list of groups whose members are
-    // authorized
-    private static final String PROP_GROUPS = "groups";
-
-    /** default log */
-    private final Logger log = LoggerFactory.getLogger(getClass());
-
-    @Reference
     private Repository repository;
 
-    @Property(name = PROP_USERS, cardinality = 20, value = PROP_GROUPS_DEFAULT_USER)
-    private Set<String> users;
-
-    @Property(name = PROP_GROUPS, cardinality = 20)
-    private Set<String> groups;
-
-    // ---------- SCR integration
-
-    @SuppressWarnings("unused")
-    @Activate
-    @Modified
-    private void configure(Map<String, Object> config) {
-        this.users = toSet(config.get(PROP_USERS));
-        this.groups = toSet(config.get(PROP_GROUPS));
+    public void setService(final Repository repo) {
+        this.repository = repo;
     }
+    // ---------- SCR integration
 
     /**
      * Authenticates and authorizes the user identified by the user name and
@@ -148,27 +130,27 @@ public class SlingWebConsoleSecurityProv
                         }
                     }
 
-                    log.info(
-                        "authenticate: User {} is granted Web Console access",
+                    logger.debug(
+                        "authenticate: User {} is denied Web Console access",
                         userName);
                 } else {
-                    log.error(
+                    logger.error(
                         "authenticate: Expected user ID {} to refer to a user",
                         userId);
                 }
             } else {
-                log.info(
+                logger.info(
                     "authenticate: Jackrabbit Session required to grant access to the Web Console for {}; got {}",
                     userName, session.getClass());
             }
-        } catch (LoginException re) {
-            log.info(
+        } catch (final LoginException re) {
+            logger.info(
                 "authenticate: User "
                     + userName
                     + " failed to authenticate with the repository for Web Console access",
                 re);
-        } catch (Exception re) {
-            log.info("authenticate: Generic problem trying grant User "
+        } catch (final Exception re) {
+            logger.info("authenticate: Generic problem trying grant User "
                 + userName + " access to the Web Console", re);
         } finally {
             if (session != null) {
@@ -185,27 +167,7 @@ public class SlingWebConsoleSecurityProv
      * authorized groups are granted access for all roles in the Web Console.
      */
     public boolean authorize(Object user, String role) {
-        log.info("authorize: Grant user {} access for role {}", user, role);
+        logger.debug("authorize: Grant user {} access for role {}", user, role);
         return true;
     }
-
-    private Set<String> toSet(final Object configObj) {
-        final HashSet<String> groups = new HashSet<String>();
-        if (configObj instanceof String) {
-            groups.add((String) configObj);
-        } else if (configObj instanceof Collection<?>) {
-            for (Object obj : ((Collection<?>) configObj)) {
-                if (obj instanceof String) {
-                    groups.add((String) obj);
-                }
-            }
-        } else if (configObj instanceof String[]) {
-            for (String string : ((String[]) configObj)) {
-                if (string != null) {
-                    groups.add(string);
-                }
-            }
-        }
-        return groups;
-    }
 }

Added: sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/SlingWebConsoleSecurityProvider2.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/SlingWebConsoleSecurityProvider2.java?rev=1534058&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/SlingWebConsoleSecurityProvider2.java (added)
+++ sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/SlingWebConsoleSecurityProvider2.java Mon Oct 21 08:12:07 2013
@@ -0,0 +1,145 @@
+/*
+ * 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.extensions.webconsolesecurityprovider.internal;
+
+import java.util.Iterator;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.felix.webconsole.WebConsoleSecurityProvider2;
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.auth.core.AuthenticationSupport;
+
+/**
+ * The <code>SlingWebConsoleSecurityProvider</code> is security provider for the
+ * Apache Felix Web Console which validates the user name and password by loging
+ * into the repository and the checking whether the user is allowed access.
+ * Access granted by the {@link #authenticate(String, String)} method applies to
+ * all of the Web Console since the {@link #authorize(Object, String)} method
+ * always returns <code>true</code>.
+ * <p>
+ * This security provider requires a JCR Repository to operate. Therefore it is
+ * only registered as a security provider service once such a JCR Repository is
+ * available.
+ */
+public class SlingWebConsoleSecurityProvider2
+    extends AbstractWebConsoleSecurityProvider
+    implements WebConsoleSecurityProvider2 {
+
+    private AuthenticationSupport authenticator;
+
+    public void setService(final AuthenticationSupport support) {
+        this.authenticator = support;
+    }
+
+    private void invokeAuthenticator(final HttpServletRequest request, final HttpServletResponse response) {
+        final AuthenticationSupport localAuthenticator = this.authenticator;
+        if (localAuthenticator != null) {
+            localAuthenticator.handleSecurity(request, response);
+        }
+    }
+
+    /**
+     * @see org.apache.felix.webconsole.WebConsoleSecurityProvider2#authenticate(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+     */
+    public boolean authenticate(final HttpServletRequest request,
+            final HttpServletResponse response) {
+        invokeAuthenticator(request, response);
+        // get ResourceResolver (set by AuthenticationSupport)
+        Object resolverObject = request.getAttribute(AuthenticationSupport.REQUEST_ATTRIBUTE_RESOLVER);
+        final ResourceResolver resolver = (resolverObject instanceof ResourceResolver)
+                ? (ResourceResolver) resolverObject
+                : null;
+        if ( resolver != null ) {
+            final Session session = resolver.adaptTo(Session.class);
+            if ( session != null ) {
+                try {
+                    final User u = this.authenticate(session);
+                    if ( u != null ) {
+                        request.setAttribute(USER_ATTRIBUTE, u);
+                        return true;
+                    }
+                    return false;
+                } catch (final Exception re) {
+                    logger.info("authenticate: Generic problem trying grant User "
+                        + " access to the Web Console", re);
+                }
+            }
+        }
+        return false;
+    }
+
+    public User authenticate(String userName, String password) {
+        return null; // this method is never invoked
+    }
+
+    private User authenticate(final Session session) throws RepositoryException {
+        String userId = session.getUserID();
+        if (session instanceof JackrabbitSession) {
+            UserManager umgr = ((JackrabbitSession) session).getUserManager();
+            Authorizable a = umgr.getAuthorizable(userId);
+            if (a instanceof User) {
+
+                // check users
+                if (users.contains(userId)) {
+                    return (User)a;
+                }
+
+                // check groups
+                @SuppressWarnings("unchecked")
+                Iterator<Group> gi = a.memberOf();
+                while (gi.hasNext()) {
+                    if (groups.contains(gi.next().getID())) {
+                        return (User)a;
+                    }
+                }
+
+                logger.info(
+                    "authenticate: User {} is denied Web Console access",
+                    userId);
+            } else {
+                logger.error(
+                    "authenticate: Expected user ID {} to refer to a user",
+                    userId);
+            }
+        } else {
+            logger.info(
+                "authenticate: Jackrabbit Session required to grant access to the Web Console for {}; got {}",
+                userId, session.getClass());
+        }
+        return null;
+    }
+
+    /**
+     * All users authenticated with the repository and being a member of the
+     * authorized groups are granted access for all roles in the Web Console.
+     */
+    public boolean authorize(Object user, String role) {
+        logger.debug("authorize: Grant user {} access for role {}", user, role);
+        return true;
+    }
+}

Propchange: sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/SlingWebConsoleSecurityProvider2.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/SlingWebConsoleSecurityProvider2.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/trunk/bundles/extensions/webconsolesecurityprovider/src/main/java/org/apache/sling/extensions/webconsolesecurityprovider/internal/SlingWebConsoleSecurityProvider2.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain