--- /dev/null
+package org.argeo.eclipse.ui.jcr.browser;
+
+import javax.jcr.Session;
+
+import org.argeo.eclipse.ui.jcr.SimpleNodeContentProvider;
+import org.argeo.jcr.JcrUtils;
+
+public class HomeContentProvider extends SimpleNodeContentProvider {
+
+ public HomeContentProvider(Session session) {
+ super(session, new String[] { JcrUtils.getUserHomePath(session) });
+ }
+
+}
--- /dev/null
+package org.argeo.eclipse.ui.jcr.views;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.jcr.SimpleNodeContentProvider;
+import org.argeo.eclipse.ui.jcr.browser.HomeContentProvider;
+import org.argeo.eclipse.ui.jcr.browser.NodeLabelProvider;
+import org.argeo.eclipse.ui.jcr.browser.RepositoryNode;
+import org.argeo.eclipse.ui.jcr.browser.WorkspaceNode;
+import org.argeo.eclipse.ui.jcr.utils.JcrFileProvider;
+import org.argeo.eclipse.ui.jcr.utils.NodeViewerComparer;
+import org.argeo.eclipse.ui.specific.FileHandler;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.ui.part.ViewPart;
+
+/** JCR browser organized around a user home node. */
+public class UserCentricJcrBrowser extends ViewPart {
+ // private final static Log log = LogFactory.getLog(UserBrowser.class);
+
+ private TreeViewer nodesViewer;
+
+ private Session session;
+
+ @Override
+ public void createPartControl(Composite parent) {
+
+ // Instantiate the generic object that fits for
+ // both RCP & RAP, must be final to be accessed in the double click
+ // listener.
+ // Not that in RAP, it registers a service handler that provide the
+ // access to the files.
+
+ final JcrFileProvider jfp = new JcrFileProvider();
+ final FileHandler fh = new FileHandler(jfp);
+
+ parent.setLayout(new FillLayout());
+
+ Composite top = new Composite(parent, SWT.NONE);
+ GridLayout gl = new GridLayout(1, false);
+ top.setLayout(gl);
+
+ // nodes viewer
+ nodesViewer = new TreeViewer(top, SWT.MULTI | SWT.H_SCROLL
+ | SWT.V_SCROLL);
+ nodesViewer.getTree().setLayoutData(
+ new GridData(SWT.FILL, SWT.FILL, true, true));
+
+ SimpleNodeContentProvider contentProvider = new HomeContentProvider(
+ session);
+ nodesViewer.setContentProvider(contentProvider);
+ nodesViewer.setLabelProvider(new NodeLabelProvider());
+
+ nodesViewer.addDoubleClickListener(new IDoubleClickListener() {
+ public void doubleClick(DoubleClickEvent event) {
+ if (event.getSelection() == null
+ || event.getSelection().isEmpty())
+ return;
+ Object obj = ((IStructuredSelection) event.getSelection())
+ .getFirstElement();
+ if (obj instanceof RepositoryNode) {
+ RepositoryNode rpNode = (RepositoryNode) obj;
+ rpNode.login();
+ // For the file provider to be able to browse the various
+ // repository.
+ // TODO : enhanced that.
+ jfp.setRepositoryNode(rpNode);
+ nodesViewer.refresh(obj);
+
+ } else if (obj instanceof WorkspaceNode) {
+ ((WorkspaceNode) obj).login();
+ nodesViewer.refresh(obj);
+ } else if (obj instanceof Node) {
+ Node node = (Node) obj;
+
+ // double clic on a file node triggers its opening
+ try {
+ if (node.isNodeType("nt:file")) {
+ String name = node.getName();
+ String id = node.getIdentifier();
+ fh.openFile(name, id);
+ }
+ } catch (RepositoryException re) {
+ throw new ArgeoException(
+ "Repository error while getting Node file info",
+ re);
+ }
+ }
+ }
+ });
+
+ // context menu
+ MenuManager menuManager = new MenuManager();
+ Menu menu = menuManager.createContextMenu(nodesViewer.getTree());
+ nodesViewer.getTree().setMenu(menu);
+ getSite().registerContextMenu(menuManager, nodesViewer);
+ getSite().setSelectionProvider(nodesViewer);
+
+ nodesViewer.setInput(session);
+
+ nodesViewer.setComparer(new NodeViewerComparer());
+
+ }
+
+ @Override
+ public void setFocus() {
+ nodesViewer.getTree().setFocus();
+ }
+
+ /**
+ * To be overidden to adapt size of form and result frames.
+ *
+ * @return
+ */
+ protected int[] getWeights() {
+ return new int[] { 70, 30 };
+ }
+
+ /*
+ * NOTIFICATION
+ */
+ public void refresh(Object obj) {
+ nodesViewer.refresh(obj);
+ }
+
+ public void nodeAdded(Node parentNode, Node newNode) {
+ nodesViewer.refresh(parentNode);
+ nodesViewer.expandToLevel(newNode, 0);
+ }
+
+ public void nodeRemoved(Node parentNode) {
+
+ IStructuredSelection newSel = new StructuredSelection(parentNode);
+ nodesViewer.setSelection(newSel, true);
+ // Force refresh
+ IStructuredSelection tmpSel = (IStructuredSelection) nodesViewer
+ .getSelection();
+ nodesViewer.refresh(tmpSel.getFirstElement());
+ }
+
+ public void setSession(Session session) {
+ this.session = session;
+ }
+
+}
<groupId>org.argeo.dep.osgi</groupId>
<artifactId>org.argeo.dep.osgi.jts</artifactId>
</dependency>
- <dependency>
- <groupId>org.argeo.dep.osgi</groupId>
- <artifactId>org.argeo.dep.osgi.geoapi</artifactId>
- </dependency>
<dependency>
<groupId>org.jdom</groupId>
<artifactId>com.springsource.org.jdom</artifactId>
Bundle-Version: 0.3.2.SNAPSHOT
Import-Package: javax.jcr;version="[2.0.0,3.0.0)",
org.argeo.security,
+ org.argeo.security.core,
org.argeo.security.jackrabbit.providers,
org.argeo.security.jcr,
+ org.springframework.beans.factory.config;specification-version="2.5.6.SEC01",
+ org.springframework.security;specification-version="2.0.6.RELEASE",
+ org.springframework.security.adapters;specification-version="2.0.6.RELEASE",
org.springframework.security.providers;specification-version="2.0.6.RELEASE"
Bundle-Name: Security DAO Jackrabbit
cardinality="0..1">\r
<listener ref="jcrAuthenticationProvider" bind-method="register"\r
unbind-method="unregister" />\r
-<!-- <listener ref="osJcrAuthenticationProvider" bind-method="register" -->\r
-<!-- unbind-method="unregister" /> -->\r
</reference>\r
-<!-- <reference id="systemExecutor" interface="org.argeo.security.SystemExecutionService" /> -->\r
+ <reference id="nodeRepository" interface="javax.jcr.Repository"\r
+ filter="(argeo.jcr.repository.alias=node)" cardinality="0..1">\r
+ <listener ref="osJcrAuthenticationProvider" bind-method="register"\r
+ unbind-method="unregister" />\r
+ </reference>\r
+\r
+ <reference id="systemExecutionServiceRef" interface="org.argeo.security.SystemExecutionService"\r
+ cardinality="0..1">\r
+ <listener ref="osJcrAuthenticationProvider" bind-method="register"\r
+ unbind-method="unregister" />\r
+ </reference>\r
\r
<!-- SERVICES -->\r
- <service ref="jcrAuthenticationProvider"\r
- interface="org.springframework.security.providers.AuthenticationProvider" />\r
-<!-- <service ref="osJcrAuthenticationProvider" -->\r
-<!-- interface="org.springframework.security.providers.AuthenticationProvider" /> -->\r
+ <service ref="systemExecutionService" interface="org.argeo.security.SystemExecutionService" />\r
+\r
+ <service ref="authenticationManager"\r
+ interface="org.springframework.security.AuthenticationManager" />\r
+\r
</beans:beans>
\ No newline at end of file
<bean id="jcrAuthenticationProvider"
class="org.argeo.security.jackrabbit.providers.JackrabbitAuthenticationProvider" />
-<!-- <bean id="osJcrAuthenticationProvider" class="org.argeo.security.jcr.OsJcrAuthenticationProvider"> -->
-<!-- <property name="systemExecutor" ref="systemExecutor" /> -->
-<!-- </bean> -->
+ <bean id="osJcrAuthenticationProvider" class="org.argeo.security.jcr.OsJcrAuthenticationProvider">
+ </bean>
</beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+ <bean
+ class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
+ <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
+ <property name="locations">
+ <value>osgibundle:security.properties</value>
+ </property>
+ </bean>
+
+ <bean id="systemExecutionService" class="org.argeo.security.core.KeyBasedSystemExecutionService">
+ <property name="systemAuthenticationKey" value="${argeo.security.systemKey}" />
+ <property name="authenticationManager" ref="authenticationManager" />
+ </bean>
+
+ <bean id="authenticationManager" class="org.springframework.security.providers.ProviderManager">
+ <property name="providers">
+ <bean factory-bean="authenticationProvidersRegister"
+ factory-method="getProviders" />
+ </property>
+ </bean>
+
+ <bean id="authenticationProvidersRegister" class="org.argeo.security.core.AuthenticationProvidersRegister">
+ <property name="defaultProviders">
+ <list>
+ <bean class="org.springframework.security.adapters.AuthByAdapterProvider">
+ <property name="key" value="${argeo.security.systemKey}" />
+ </bean>
+ <ref bean="jcrAuthenticationProvider" />
+ <ref bean="osJcrAuthenticationProvider" />
+ </list>
+ </property>
+ </bean>
+</beans>
\ No newline at end of file
--- /dev/null
+argeo.security.systemKey=argeo
+OS_SPRING {
+ org.eclipse.equinox.security.auth.module.ExtensionLoginModule required
+ extensionId="org.argeo.security.equinox.osSpringLoginModule";
+};
+
NIX {
org.eclipse.equinox.security.auth.module.ExtensionLoginModule requisite
extensionId="org.argeo.security.equinox.unixLoginModule";
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans:beans xmlns="http://www.springframework.org/schema/osgi"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"\r
+ xmlns:util="http://www.springframework.org/schema/util"\r
+ xsi:schemaLocation="http://www.springframework.org/schema/osgi \r
+ http://www.springframework.org/schema/osgi/spring-osgi-1.1.xsd\r
+ http://www.springframework.org/schema/beans \r
+ http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/util\r
+ http://www.springframework.org/schema/util/spring-util-2.5.xsd">\r
+\r
+ <!-- REFERENCE -->\r
+<!-- <reference id="authenticationManager" -->\r
+<!-- interface="org.springframework.security.AuthenticationManager" /> -->\r
+\r
+</beans:beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+ <bean id="secureUi" class="org.argeo.security.ui.rcp.SecureRcp">
+<!-- <property name="authenticationManager" ref="authenticationManager" /> -->
+ </bean>
+</beans>
\ No newline at end of file
thread="main"
visible="true">
<run
- class="org.argeo.security.ui.rcp.SecureRcp">
+ class="org.argeo.eclipse.spring.SpringExtensionFactory">
</run>
</application>
</extension>
final Display display = PlatformUI.createDisplay();
+ // login
Subject subject = null;
try {
loginContext.login();
osgi:default-timeout="30000">\r
\r
<reference id="userDetailsManager"\r
- interface="org.springframework.security.userdetails.UserDetailsManager" />\r
+ interface="org.springframework.security.userdetails.UserDetailsManager"\r
+ cardinality="0..1" />\r
</beans:beans>
\ No newline at end of file
package org.argeo.security.core;
+import java.security.AccessController;
import java.util.ArrayList;
import java.util.List;
+import javax.security.auth.Subject;
+
import org.argeo.security.OsAuthenticationToken;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationException;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.security.providers.AuthenticationProvider;
+import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
/** Validates an OS authentication. */
public class OsAuthenticationProvider implements AuthenticationProvider {
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
+ final OsAuthenticationToken oat;
+ // if (authentication instanceof UsernamePasswordAuthenticationToken) {
+ // Subject subject = Subject.getSubject(AccessController.getContext());
+ // if (subject == null)
+ // return null;
+ // oat = new OsAuthenticationToken();
+ // } else
if (authentication instanceof OsAuthenticationToken) {
- List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
- auths.add(new GrantedAuthorityImpl(osUserRole));
- auths.add(new GrantedAuthorityImpl(userRole));
- if (isAdmin)
- auths.add(new GrantedAuthorityImpl(adminRole));
- return new OsAuthenticationToken(
- auths.toArray(new GrantedAuthority[auths.size()]));
+ oat = (OsAuthenticationToken) authentication;
+ } else {
+ return null;
}
- return null;
+
+ // not OS authenticated
+// if (oat.getUser() == null)
+// return null;
+
+ List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
+ auths.add(new GrantedAuthorityImpl(osUserRole));
+ auths.add(new GrantedAuthorityImpl(userRole));
+ if (isAdmin)
+ auths.add(new GrantedAuthorityImpl(adminRole));
+ return new OsAuthenticationToken(
+ auths.toArray(new GrantedAuthority[auths.size()]));
}
@SuppressWarnings("rawtypes")
import java.util.concurrent.Executor;
import javax.jcr.Node;
+import javax.jcr.Repository;
import javax.jcr.RepositoryException;
-import javax.jcr.RepositoryFactory;
import javax.jcr.Session;
import org.argeo.ArgeoException;
import org.argeo.jcr.JcrUtils;
import org.argeo.security.OsAuthenticationToken;
+import org.argeo.security.SystemExecutionService;
import org.argeo.security.core.OsAuthenticationProvider;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationException;
import org.springframework.security.userdetails.UserDetails;
public class OsJcrAuthenticationProvider extends OsAuthenticationProvider {
- private RepositoryFactory repositoryFactory;
private Executor systemExecutor;
private String homeBasePath = "/home";
- private String repositoryAlias = "node";
+ private Repository repository;
private String workspace = null;
+ private Long timeout = 5 * 60 * 1000l;
+
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
final OsAuthenticationToken authen = (OsAuthenticationToken) super
.authenticate(authentication);
+ final Repository repository = getRepositoryBlocking();
systemExecutor.execute(new Runnable() {
public void run() {
try {
- Session session = JcrUtils.getRepositoryByAlias(
- repositoryFactory, repositoryAlias)
- .login(workspace);
- Node userHome = JcrUtils.getUserHome(session,
- authen.getName());
+ Session session = repository.login(workspace);
+ // WARNING: at this stage we assume that teh java properties
+ // will have the same value
+ String userName = System.getProperty("user.name");
+ Node userHome = JcrUtils.getUserHome(session, userName);
if (userHome == null)
- JcrUtils.createUserHome(session, homeBasePath,
- authen.getName());
- authen.setDetails(getUserDetails(userHome, authen));
+ userHome = JcrUtils.createUserHome(session,
+ homeBasePath, userName);
+ //authen.setDetails(getUserDetails(userHome, authen));
} catch (RepositoryException e) {
throw new ArgeoException(
"Unexpected exception when synchronizing OS and JCR security ",
return true;
}
- public void register(RepositoryFactory repositoryFactory,
+ protected Repository getRepositoryBlocking() {
+ long begin = System.currentTimeMillis();
+ while (repository == null) {
+ synchronized (this) {
+ try {
+ wait(500);
+ } catch (InterruptedException e) {
+ // silent
+ }
+ }
+ if (System.currentTimeMillis() - begin > timeout)
+ throw new ArgeoException("No repository registered after "
+ + timeout + " ms");
+ }
+ return repository;
+ }
+
+ public synchronized void register(Repository repository,
Map<String, String> parameters) {
- this.repositoryFactory = repositoryFactory;
+ this.repository = repository;
+ notifyAll();
}
- public void unregister(RepositoryFactory repositoryFactory,
+ public synchronized void unregister(Repository repository,
Map<String, String> parameters) {
- this.repositoryFactory = null;
+ this.repository = null;
+ notifyAll();
}
- public void setSystemExecutor(Executor systemExecutor) {
+ public void register(SystemExecutionService systemExecutor,
+ Map<String, String> parameters) {
this.systemExecutor = systemExecutor;
}
- public void setHomeBasePath(String homeBasePath) {
- this.homeBasePath = homeBasePath;
+ public void unregister(SystemExecutionService systemExecutor,
+ Map<String, String> parameters) {
+ this.systemExecutor = null;
}
- public void setRepositoryAlias(String repositoryAlias) {
- this.repositoryAlias = repositoryAlias;
+ public void setHomeBasePath(String homeBasePath) {
+ this.homeBasePath = homeBasePath;
}
public void setWorkspace(String workspace) {
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.argeo.jcr.ThreadBoundJcrSessionFactory;
-import org.springframework.beans.factory.DisposableBean;
-import org.springframework.beans.factory.FactoryBean;
-import org.springframework.beans.factory.InitializingBean;
+import org.argeo.jcr.spring.ThreadBoundSession;
import org.springframework.security.Authentication;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.userdetails.UserDetails;
* Thread bounded JCR session factory which checks authentication and is
* autoconfigured in Spring.
*/
-public class SecureThreadBoundSession extends ThreadBoundJcrSessionFactory
- implements FactoryBean, InitializingBean, DisposableBean {
+public class SecureThreadBoundSession extends ThreadBoundSession {
private final static Log log = LogFactory
.getLog(SecureThreadBoundSession.class);
- public void afterPropertiesSet() throws Exception {
- init();
- }
-
- public void destroy() throws Exception {
- dispose();
- }
-
@Override
protected Session preCall(Session session) {
Authentication authentication = SecurityContextHolder.getContext()
/** Intermediary class in order to have a consistent naming in config files. */
public class ArgeoSecurityManager extends DefaultSecurityManager {
+ public final static String HOME_BASE_PATH = "/home";
+
private Log log = LogFactory.getLog(ArgeoSecurityManager.class);
@Override
.toString(), authen, null);
log.info(userId + " added as " + user);
}
-
+
setHomeNodeAuthorizations(user);
// process groups
try {
userId = user.getID();
Node userHome = JcrUtils.getUserHome(getSystemSession(), userId);
+ // autocreate home node?
+// if (userHome == null)
+// userHome = JcrUtils.createUserHome(getSystemSession(),
+// HOME_BASE_PATH, userId);
+
if (userHome != null) {
String path = userHome.getPath();
AccessControlPolicy policy = null;
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"\r
osgi:default-timeout="30000">\r
\r
- <set id="repositories" interface="javax.jcr.Repository">\r
+ <set id="repositories" interface="javax.jcr.Repository" cardinality="0..N">\r
<listener ref="repositoryRegister" bind-method="register"\r
unbind-method="unregister" />\r
</set>\r
try {
NamespaceHelper namespaceHelper = new NamespaceHelper(session);
namespaceHelper.registerNamespaces(namespaces);
-
} catch (Exception e) {
throw new ArgeoException("Cannot process new session", e);
}
return getUserHome(session, userID);
}
+ /**
+ * Returns user home has path, embedding exceptions. Contrary to
+ * {@link #getUserHome(Session)}, it never returns null but throws and
+ * exception if not found.
+ */
+ public static String getUserHomePath(Session session) {
+ String userID = session.getUserID();
+ try {
+ Node userHome = getUserHome(session, userID);
+ if (userHome != null)
+ return userHome.getPath();
+ else
+ throw new ArgeoException("No home registered for " + userID);
+ } catch (RepositoryException e) {
+ throw new ArgeoException("Cannot find user home path", e);
+ }
+ }
+
/** Get the profile of the user attached to this session. */
public static Node getUserProfile(Session session) {
String userID = session.getUserID();
import org.argeo.ArgeoException;
/** Proxy JCR sessions and attach them to calling threads. */
-public class ThreadBoundJcrSessionFactory {
+public abstract class ThreadBoundJcrSessionFactory {
private final static Log log = LogFactory
.getLog(ThreadBoundJcrSessionFactory.class);
--- /dev/null
+package org.argeo.jcr.spring;
+
+import org.argeo.jcr.ThreadBoundJcrSessionFactory;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.InitializingBean;
+
+public class ThreadBoundSession extends ThreadBoundJcrSessionFactory implements FactoryBean, InitializingBean, DisposableBean{
+ public void afterPropertiesSet() throws Exception {
+ init();
+ }
+
+ public void destroy() throws Exception {
+ dispose();
+ }
+
+}