--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.argeo.commons.demo</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ </buildSpec>
+ <natures>
+ </natures>
+</projectDescription>
org.springframework.osgi.extender,\
org.argeo.node.repofactory.jackrabbit,\
org.argeo.node.repo.jackrabbit,\
-org.argeo.security.dao.jackrabbit,\
+org.argeo.security.dao.os,\
org.argeo.security.equinox,\
org.argeo.security.ui.initialPerspective=org.argeo.osgi.ui.explorer.perspective
--- /dev/null
+argeo.osgi.start=\
+org.springframework.osgi.extender,\
+org.argeo.node.repofactory.jackrabbit,\
+org.argeo.node.repo.jackrabbit,\
+org.argeo.security.dao.jackrabbit,\
+org.argeo.security.equinox,\
+
+org.argeo.security.ui.initialPerspective=org.argeo.osgi.ui.explorer.perspective
+
+argeo.node.repo.uri=http://localhost:7070/org.argeo.jcr.webapp/remoting/node
+
+log4j.configuration=file:../../log4j.properties
+
+eclipse.application=org.argeo.security.ui.rcp.secureUi
<listener ref="jcrAuthenticationProvider" bind-method="register"\r
unbind-method="unregister" />\r
</reference>\r
- <reference id="nodeRepository" interface="javax.jcr.Repository"\r
- filter="(argeo.jcr.repository.alias=${argeo.node.repo.alias})" 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="systemExecutionService" interface="org.argeo.security.SystemExecutionService" />\r
<bean id="jcrAuthenticationProvider"
class="org.argeo.security.jackrabbit.providers.JackrabbitAuthenticationProvider" />
-
- <bean id="osJcrAuthenticationProvider" class="org.argeo.security.jcr.OsJcrAuthenticationProvider">
- </bean>
</beans>
\ No newline at end of file
<property name="key" value="${argeo.security.systemKey}" />
</bean>
<ref bean="jcrAuthenticationProvider" />
- <ref bean="osJcrAuthenticationProvider" />
</list>
</property>
</bean>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.argeo.security.dao.os</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+Manifest-Version: 1.0\r
+Private-Package: .\r
+Tool: Bnd-1.15.0\r
+Bundle-Name: Commons Security DAO OS\r
+Created-By: 1.6.0_20 (Sun Microsystems Inc.)\r
+Bundle-RequiredExecutionEnvironment: J2SE-1.5\r
+Bundle-Vendor: Argeo\r
+Bundle-Version: 0.3.4.SNAPSHOT-r20111029_170433\r
+Bundle-ManifestVersion: 2\r
+Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt\r
+Import-Package: javax.jcr,org.argeo.security,org.argeo.security.core,o\r
+ rg.argeo.security.jcr,org.springframework.beans.factory.config,org.sp\r
+ ringframework.security,org.springframework.security.adapters,org.spri\r
+ ngframework.security.providers\r
+Bundle-SymbolicName: org.argeo.security.dao.os\r
+Bundle-DocURL: http://www.argeo.org\r
+\r
--- /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="nodeRepository" interface="javax.jcr.Repository"\r
+ filter="(argeo.jcr.repository.alias=${argeo.node.repo.alias})" 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="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
--- /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="osJcrAuthenticationProvider" class="org.argeo.security.jcr.OsJcrAuthenticationProvider">
+ </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="osJcrAuthenticationProvider" />
+ </list>
+ </property>
+ </bean>
+
+</beans>
\ No newline at end of file
--- /dev/null
+bin.includes = META-INF/
--- /dev/null
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.argeo.commons.security</groupId>
+ <version>0.3.4-SNAPSHOT</version>
+ <artifactId>modules</artifactId>
+ <relativePath>..</relativePath>
+ </parent>
+ <artifactId>org.argeo.security.dao.os</artifactId>
+ <name>Commons Security DAO OS</name>
+</project>
\ No newline at end of file
--- /dev/null
+argeo.security.systemKey=argeo
+argeo.node.repo.alias=node
<packaging>pom</packaging>
<name>Commons Security Modules</name>
<modules>
+ <module>org.argeo.security.dao.os</module>
<module>org.argeo.security.dao.jackrabbit</module>
<module>org.argeo.security.dao.ldap</module>
<module>org.argeo.security.services</module>
<property name="authenticationManager" ref="authenticationManager" />
</bean>
+ <bean id="springLoginModuleRemote" class="org.argeo.security.equinox.SpringLoginModule"
+ scope="prototype">
+ <property name="remote" value="true" />
+ <property name="authenticationManager" ref="authenticationManager" />
+ </bean>
+
<bean id="osSpringLoginModule" class="org.argeo.security.equinox.OsSpringLoginModule"
scope="prototype">
<property name="authenticationManager" ref="authenticationManager" />
<loginModule class="org.argeo.eclipse.spring.SpringExtensionFactory" description="Argeo Spring Login Module"/>
</extension>
+ <extension id="springLoginModuleRemote" name="Argeo Spring" point="org.eclipse.equinox.security.loginModule">
+ <loginModule class="org.argeo.eclipse.spring.SpringExtensionFactory" description="Argeo Spring Login Module"/>
+ </extension>
+
<extension id="osSpringLoginModule" name="Argeo Spring OS" point="org.eclipse.equinox.security.loginModule">
<loginModule class="org.argeo.eclipse.spring.SpringExtensionFactory" description="Argeo Spring OS Login Module"/>
</extension>
/** Login module which caches one subject per thread. */
public class SpringLoginModule extends SecurityContextLoginModule {
+ final static String NODE_REPO_URI = "argeo.node.repo.uri";
+
private final static Log log = LogFactory.getLog(SpringLoginModule.class);
private AuthenticationManager authenticationManager;
private Long waitBetweenFailedLoginAttempts = 5 * 1000l;
+ private Boolean remote = false;
+
public SpringLoginModule() {
}
PasswordCallback passwordCallback = new PasswordCallback(
"Password", false);
- // NameCallback urlCallback = new NameCallback("Site URL");
+ NameCallback urlCallback = new NameCallback("Site URL");
if (callbackHandler == null)
throw new LoginException("No call back handler available");
- callbackHandler.handle(new Callback[] { nameCallback,
- passwordCallback });
+ if (remote)
+ callbackHandler.handle(new Callback[] { nameCallback,
+ passwordCallback, urlCallback });
+ else
+ callbackHandler.handle(new Callback[] { nameCallback,
+ passwordCallback });
// Set user name and password
String username = nameCallback.getName();
if (passwordCallback.getPassword() != null)
password = String.valueOf(passwordCallback.getPassword());
- // String url = urlCallback.getName();
+ String url = remote ? urlCallback.getName() : null;
+ if (remote && (url == null || url.trim().equals("")))
+ // for convenience, may be removed in the future
+ url = System.getProperty(NODE_REPO_URI);
+
// TODO: set it via system properties
String workspace = null;
SiteAuthenticationToken credentials = new SiteAuthenticationToken(
- username, password, null, workspace);
+ username, password, url, workspace);
Authentication authentication;
try {
AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
+
+ public void setRemote(Boolean remote) {
+ this.remote = remote;
+ }
}
protected void createFormContent(final IManagedForm mf) {
try {
ScrolledForm form = mf.getForm();
- form.setText(userProfile.getProperty(ARGEO_FIRST_NAME).getString()
- + " "
- + userProfile.getProperty(ARGEO_LAST_NAME).getString());
+ form.setText(getProperty(ARGEO_FIRST_NAME) + " "
+ + getProperty(ARGEO_LAST_NAME));
GridLayout mainLayout = new GridLayout(1, true);
// ColumnLayout mainLayout = new ColumnLayout();
// mainLayout.minNumColumns = 1;
// username = createLT(body, "Username", "");
// }
final Text firstName = createLT(body, "First name",
- userProfile.getProperty(ARGEO_FIRST_NAME));
+ getProperty(ARGEO_FIRST_NAME));
final Text lastName = createLT(body, "Last name",
- userProfile.getProperty(ARGEO_LAST_NAME));
+ getProperty(ARGEO_LAST_NAME));
final Text email = createLT(body, "Email",
- userProfile.getProperty(ARGEO_PRIMARY_EMAIL));
+ getProperty(ARGEO_PRIMARY_EMAIL));
final Text description = createLT(body, "Description",
- userProfile.getProperty(Property.JCR_DESCRIPTION));
+ getProperty(Property.JCR_DESCRIPTION));
// create form part (controller)
AbstractFormPart part = new SectionPart(section) {
getManagedForm().addPart(part);
}
+ /** @return the property, or teh empty string if not set */
+ protected String getProperty(String name) throws RepositoryException {
+ return userProfile.hasProperty(name) ? userProfile.getProperty(name)
+ .getString() : "";
+ }
+
/** Creates the password section */
protected void createPassworPart(Composite parent) {
FormToolkit tk = getManagedForm().getToolkit();
return text;
}
- protected Text createLT(Composite body, String label, Property value)
- throws RepositoryException {
- return createLT(body, label, value.getString());
- }
-
/** Creates label and password. */
protected Text createLP(Composite body, String label, String value) {
FormToolkit toolkit = getManagedForm().getToolkit();
public String getColumnText(Object element, int columnIndex) {
try {
Node userHome = (Node) element;
+ Node userProfile = userHome.getNode(ARGEO_PROFILE);
switch (columnIndex) {
case 0:
String userName = userHome.getProperty(ARGEO_USER_ID)
else
return userName;
case 1:
- return userHome.getNode(ARGEO_PROFILE)
- .getProperty(ARGEO_FIRST_NAME).getString();
+ return userProfile.hasProperty(ARGEO_FIRST_NAME) ? userProfile
+ .getProperty(ARGEO_FIRST_NAME).getString() : "";
case 2:
- return userHome.getNode(ARGEO_PROFILE)
- .getProperty(ARGEO_LAST_NAME).getString();
+ return userProfile.hasProperty(ARGEO_LAST_NAME) ? userProfile
+ .getProperty(ARGEO_LAST_NAME).getString() : "";
case 3:
- return userHome.getNode(ARGEO_PROFILE)
- .getProperty(ARGEO_PRIMARY_EMAIL).getString();
+ return userProfile.hasProperty(ARGEO_PRIMARY_EMAIL) ? userProfile
+ .getProperty(ARGEO_PRIMARY_EMAIL).getString() : "";
default:
throw new ArgeoException("Unmanaged column " + columnIndex);
}
</branding>
</extension>
+ <extension
+ point="org.eclipse.equinox.security.callbackHandlerMapping">
+ <callbackHandlerMapping
+ callbackHandlerId="org.argeo.security.ui.defaultLoginDialog"
+ configName="SPRING">
+ </callbackHandlerMapping>
+ </extension>
+ <extension
+ point="org.eclipse.equinox.security.callbackHandlerMapping">
+ <callbackHandlerMapping
+ callbackHandlerId="org.argeo.security.ui.defaultLoginDialog"
+ configName="NIX">
+ </callbackHandlerMapping>
+ </extension>
+ <extension
+ point="org.eclipse.equinox.security.callbackHandlerMapping">
+ <callbackHandlerMapping
+ callbackHandlerId="org.argeo.security.ui.defaultLoginDialog"
+ configName="SPRING_SECURITY_CONTEXT">
+ </callbackHandlerMapping>
+ </extension>
+
</plugin>
import org.eclipse.ui.application.WorkbenchWindowAdvisor;
public class SecureWorkbenchAdvisor extends WorkbenchAdvisor {
- //static final String DEFAULT_PERSPECTIVE_ID = "org.argeo.security.ui.adminSecurityPerspective"; //$NON-NLS-1$
public final static String INITIAL_PERSPECTIVE_PROPERTY = "org.argeo.security.ui.initialPerspective";
private String initialPerspective = System.getProperty(
INITIAL_PERSPECTIVE_PROPERTY, null);
extensionId="org.argeo.security.equinox.osSpringLoginModule";
};
+REMOTE {
+ org.eclipse.equinox.security.auth.module.ExtensionLoginModule sufficient
+ extensionId="org.argeo.security.equinox.springLoginModuleRemote";
+};
+
KEYRING {
org.argeo.util.crypto.KeyringLoginModule required;
};
</run>
</application>
</extension>
+
+ <extension
+ point="org.eclipse.equinox.security.callbackHandlerMapping">
+ <callbackHandlerMapping
+ callbackHandlerId="org.argeo.security.ui.defaultLoginDialog"
+ configName="REMOTE">
+ </callbackHandlerMapping>
+ </extension>
+
</plugin>
* RCP workbench initialization
*/
public abstract class AbstractSecureApplication implements IApplication {
+ final static String NODE_REPO_URI = "argeo.node.repo.uri";
+
private static final Log log = LogFactory
.getLog(AbstractSecureApplication.class);
public Object start(IApplicationContext context) throws Exception {
// wait for the system to be initialized
-// try {
-// Thread.sleep(3000);
-// } catch (Exception e2) {
-// // silent
-// }
+ // try {
+ // Thread.sleep(3000);
+ // } catch (Exception e2) {
+ // // silent
+ // }
+
+ boolean remote = System.getProperty(NODE_REPO_URI) != null;
// choose login context
final ILoginContext loginContext;
- if (OperatingSystem.os == OperatingSystem.WINDOWS)
+ if (remote) {
loginContext = SecureApplicationActivator
- .createLoginContext(SecureApplicationActivator.CONTEXT_WINDOWS);
- else
- loginContext = SecureApplicationActivator
- .createLoginContext(SecureApplicationActivator.CONTEXT_NIX);
+ .createLoginContext(SecureApplicationActivator.CONTEXT_REMOTE);
+ } else {
+ if (OperatingSystem.os == OperatingSystem.WINDOWS)
+ loginContext = SecureApplicationActivator
+ .createLoginContext(SecureApplicationActivator.CONTEXT_WINDOWS);
+ else
+ loginContext = SecureApplicationActivator
+ .createLoginContext(SecureApplicationActivator.CONTEXT_NIX);
+ }
final Display display = PlatformUI.createDisplay();
/** Activator able to create {@link ILoginContext} */
public class SecureApplicationActivator implements BundleActivator {
+ public final static String CONTEXT_REMOTE = "REMOTE";
public final static String CONTEXT_NIX = "NIX";
public final static String CONTEXT_WINDOWS = "WINDOWS";
private static final String JAAS_CONFIG_FILE = "/META-INF/jaas_default.txt";
package org.argeo.security.ui.rcp;
+import org.eclipse.ui.IPerspectiveDescriptor;
import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
import org.eclipse.ui.application.WorkbenchAdvisor;
import org.eclipse.ui.application.WorkbenchWindowAdvisor;
public class SecureWorkbenchAdvisor extends WorkbenchAdvisor {
- static final String DEFAULT_PERSPECTIVE_ID = "org.argeo.security.ui.adminSecurityPerspective"; //$NON-NLS-1$
public final static String INITIAL_PERSPECTIVE_PROPERTY = "org.argeo.security.ui.initialPerspective";
+ private String initialPerspective = System.getProperty(
+ INITIAL_PERSPECTIVE_PROPERTY, null);
private final String username;
- private String initialPerspective = System.getProperty(
- INITIAL_PERSPECTIVE_PROPERTY, DEFAULT_PERSPECTIVE_ID);
public SecureWorkbenchAdvisor(String username) {
- super();
this.username = username;
}
}
public String getInitialWindowPerspectiveId() {
+ if (initialPerspective != null) {
+ // check whether this user can see the declared perspective
+ // (typically the perspective won't be listed if this user doesn't
+ // have the right to see it)
+ IPerspectiveDescriptor pd = getWorkbenchConfigurer().getWorkbench()
+ .getPerspectiveRegistry()
+ .findPerspectiveWithId(initialPerspective);
+ if (pd == null)
+ return null;
+ }
return initialPerspective;
}
+
}
configurer.setShowProgressIndicator(true);
configurer.setShowPerspectiveBar(true);
- configurer.setTitle("Argeo UI - " + username); //$NON-NLS-1$
+ String remoteUri = System
+ .getProperty(AbstractSecureApplication.NODE_REPO_URI);
+ if (remoteUri != null)
+ configurer
+ .setTitle("Argeo UI - " + username + " (" + remoteUri + ")"); //$NON-NLS-1$
+ else
+ configurer.setTitle("Argeo UI - " + username); //$NON-NLS-1$
}
}
class="org.argeo.security.ui.dialogs.DefaultLoginDialog">
</callbackHandler>
</extension>
- <extension
- point="org.eclipse.equinox.security.callbackHandlerMapping">
- <callbackHandlerMapping
- callbackHandlerId="org.argeo.security.ui.defaultLoginDialog"
- configName="SPRING">
- </callbackHandlerMapping>
- </extension>
- <extension
- point="org.eclipse.equinox.security.callbackHandlerMapping">
- <callbackHandlerMapping
- callbackHandlerId="org.argeo.security.ui.defaultLoginDialog"
- configName="NIX">
- </callbackHandlerMapping>
- </extension>
- <extension
- point="org.eclipse.equinox.security.callbackHandlerMapping">
- <callbackHandlerMapping
- callbackHandlerId="org.argeo.security.ui.defaultLoginDialog"
- configName="SPRING_SECURITY_CONTEXT">
- </callbackHandlerMapping>
- </extension>
<extension
point="org.eclipse.ui.commands">
<command
package org.argeo.security.jcr;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import javax.jcr.Credentials;
import javax.jcr.Node;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.RepositoryFactory;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
+import javax.jcr.Value;
import org.argeo.ArgeoException;
import org.argeo.jcr.ArgeoJcrConstants;
+import org.argeo.jcr.ArgeoNames;
import org.argeo.jcr.JcrUtils;
import org.argeo.security.SiteAuthenticationToken;
import org.springframework.security.Authentication;
import org.springframework.security.providers.AuthenticationProvider;
import org.springframework.security.userdetails.UserDetails;
-/** Connects to a JCR repository and delegate authentication to it. */
+/** Connects to a JCR repository and delegates authentication to it. */
public class JcrAuthenticationProvider implements AuthenticationProvider {
public final static String ROLE_REMOTE_JCR_AUTHENTICATED = "ROLE_REMOTE_JCR_AUTHENTICATED";
return null;
try {
- Map<String, String> parameters = new HashMap<String, String>();
- parameters.put(ArgeoJcrConstants.JCR_REPOSITORY_URI, url);
-
- Repository repository = null;
- repository = repositoryFactory.getRepository(parameters);
+ SimpleCredentials sp = new SimpleCredentials(siteAuth.getName(),
+ siteAuth.getCredentials().toString().toCharArray());
+ // get repository
+ Repository repository = getRepository(url, sp);
if (repository == null)
return null;
- SimpleCredentials sp = new SimpleCredentials(siteAuth.getName(),
- siteAuth.getCredentials().toString().toCharArray());
String workspace = siteAuth.getWorkspace();
Session session;
if (workspace == null || workspace.trim().equals(""))
session = repository.login(sp);
else
session = repository.login(sp, workspace);
+
Node userHome = JcrUtils.getUserHome(session);
- if (userHome == null)
- throw new ArgeoException("No home found for user "
- + session.getUserID());
- GrantedAuthority[] authorities = {};
+
+ // retrieve remote roles
+ Node userProfile = JcrUtils.getUserProfile(session);
+ List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
+ if (userProfile.hasProperty(ArgeoNames.ARGEO_REMOTE_ROLES)) {
+ Value[] roles = userProfile.getProperty(
+ ArgeoNames.ARGEO_REMOTE_ROLES).getValues();
+ for (int i = 0; i < roles.length; i++)
+ authorities.add(new GrantedAuthorityImpl(roles[i]
+ .getString()));
+ }
JcrAuthenticationToken authen = new JcrAuthenticationToken(
- siteAuth.getPrincipal(), siteAuth.getCredentials(),
- authorities, url, userHome);
+ siteAuth.getPrincipal(),
+ siteAuth.getCredentials(),
+ authorities.toArray(new GrantedAuthority[authorities.size()]),
+ url, userHome);
authen.setDetails(getUserDetails(userHome, authen));
+
return authen;
} catch (RepositoryException e) {
throw new ArgeoException(
}
}
+ protected Repository getRepository(String url, Credentials credentials)
+ throws RepositoryException {
+ Map<String, String> parameters = new HashMap<String, String>();
+ parameters.put(ArgeoJcrConstants.JCR_REPOSITORY_URI, url);
+ return repositoryFactory.getRepository(parameters);
+ }
+
/**
* By default, assigns only the role {@value #ROLE_REMOTE_JCR_AUTHENTICATED}
* . Should typically be overridden in order to assign more relevant roles.
Session session = null;
try {
session = repository.login(workspace);
- // WARNING: at this stage we assume that teh java properties
+ // WARNING: at this stage we assume that the java properties
// will have the same value
String userName = System.getProperty("user.name");
Node userHome = JcrUtils.getUserHome(session, userName);
homeBasePath, userName);
// authen.setDetails(getUserDetails(userHome, authen));
} catch (RepositoryException e) {
+ JcrUtils.discardQuietly(session);
throw new ArgeoException(
"Unexpected exception when synchronizing OS and JCR security ",
e);
throws RepositoryException {
long begin = System.currentTimeMillis();
+ // skip Jackrabbit system user
if (!subject.getPrincipals(SystemPrincipal.class).isEmpty())
return super.getUserID(subject, workspaceName);
else
authen = authens.iterator().next();
+ // skip argeo system authenticated
+ // if (authen instanceof SystemAuthentication)
+ // return super.getUserID(subject, workspaceName);
+
UserManager systemUm = getSystemUserManager(workspaceName);
String userId = authen.getName();
log.info(userId + " added as " + user);
}
- setHomeNodeAuthorizations(user);
+ //setHomeNodeAuthorizations(user);
// process groups
List<String> userGroupIds = new ArrayList<String>();
if (!group.isMember(user))
group.addMember(user);
userGroupIds.add(ga.getAuthority());
-
}
// check if user has not been removed from some groups
group.removeMember(user);
}
+ // write roles in profile for easy access
+// if (!(authen instanceof SystemAuthentication)) {
+// Node userProfile = JcrUtils.getUserProfile(getSystemSession(),
+// userId);
+// boolean writeRoles = false;
+// if (userProfile.hasProperty(ArgeoNames.ARGEO_REMOTE_ROLES)) {
+// Value[] roles = userProfile.getProperty(ArgeoNames.ARGEO_REMOTE_ROLES)
+// .getValues();
+// if (roles.length != userGroupIds.size())
+// writeRoles = true;
+// else
+// for (int i = 0; i < roles.length; i++)
+// if (!roles[i].getString().equals(userGroupIds.get(i)))
+// writeRoles = true;
+// } else
+// writeRoles = true;
+//
+// if (writeRoles) {
+// userProfile.getSession().getWorkspace().getVersionManager()
+// .checkout(userProfile.getPath());
+// String[] roleIds = userGroupIds.toArray(new String[userGroupIds
+// .size()]);
+// userProfile.setProperty(ArgeoNames.ARGEO_REMOTE_ROLES, roleIds);
+// JcrUtils.updateLastModified(userProfile);
+// userProfile.getSession().save();
+// userProfile.getSession().getWorkspace().getVersionManager()
+// .checkin(userProfile.getPath());
+// }
+// }
+
if (log.isTraceEnabled())
log.trace("Spring and Jackrabbit Security synchronized for user "
+ userId + " in " + (System.currentTimeMillis() - begin)
Node userHome = null;
try {
userHome = JcrUtils.getUserHome(getSystemSession(), userId);
- if (userHome == null)
+ if (userHome == null) {
userHome = JcrUtils.createUserHome(getSystemSession(),
HOME_BASE_PATH, userId);
+ //log.warn("No home available for user "+userId);
+ return;
+ }
} catch (Exception e) {
// silent
}
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.Properties;
+import javax.jcr.Credentials;
import javax.jcr.Node;
+import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.apache.jackrabbit.api.security.user.User;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.argeo.ArgeoException;
+import org.argeo.jackrabbit.JackrabbitContainer;
+import org.argeo.jcr.ArgeoJcrConstants;
import org.argeo.security.jcr.JcrAuthenticationProvider;
+import org.osgi.framework.BundleContext;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
public class JackrabbitAuthenticationProvider extends JcrAuthenticationProvider {
+ // @Override
+ // protected Repository getRepository(String url, Credentials credentials)
+ // throws RepositoryException {
+ // JackrabbitContainer repository = new JackrabbitContainer();
+ // repository.setUri(url);
+ // repository.setRemoteSystemCredentials(credentials);
+ // repository.init();
+ // if (bundleContext != null) {
+ // // FIXME check if not already a node
+ // Properties properties = new Properties();
+ // properties.put(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS,
+ // ArgeoJcrConstants.ALIAS_NODE);
+ // bundleContext.registerService(Repository.class.getName(),
+ // repository, properties);
+ // }
+ // return repository;
+ // }
@Override
protected GrantedAuthority[] getGrantedAuthorities(Session session) {
try {
+ if (!(session instanceof JackrabbitSession))
+ return super.getGrantedAuthorities(session);
+
JackrabbitSession jackrabbitSession = (JackrabbitSession) session;
UserManager userManager = jackrabbitSession.getUserManager();
User user = (User) userManager.getAuthorizable(session.getUserID());
@Override
protected Boolean isEnabled(Node userHome) {
try {
+ if (!(userHome.getSession() instanceof JackrabbitSession))
+ return super.isEnabled(userHome);
+
UserManager userManager = ((JackrabbitSession) userHome
.getSession()).getUserManager();
User user = (User) userManager.getAuthorizable(userHome
try {
Node userHome = JcrUtils.getUserHome(session, username);
- if (userHome == null)
+ boolean justCreatedHome = false;
+ if (userHome == null) {
userHome = JcrUtils.createUserHome(session, homeBasePath,
username);
+ justCreatedHome = true;
+ }
String userHomePath = userHome.getPath();
Node userProfile; // = userHome.getNode(ARGEO_PROFILE);
if (userHome.hasNode(ARGEO_PROFILE)) {
userProfile = userHome.getNode(ARGEO_PROFILE);
- if (syncLatency != 0) {
+ if (syncLatency != 0 && !justCreatedHome) {
Calendar lastModified = userProfile.getProperty(
Property.JCR_LAST_MODIFIED).getDate();
long timeSinceLastUpdate = System.currentTimeMillis()
// userProfile.addMixin(NodeType.MIX_LAST_MODIFIED);
}
+ session.getWorkspace().getVersionManager()
+ .checkout(userProfile.getPath());
for (String jcrProperty : propertyToAttributes.keySet())
ldapToJcr(userProfile, jcrProperty, ctx);
+ userProfile.getProperty(ARGEO_LAST_NAME).getString());
JcrUtils.updateLastModified(userProfile);
session.save();
+ session.getWorkspace().getVersionManager()
+ .checkin(userProfile.getPath());
if (log.isTraceEnabled())
log.trace("Mapped " + ctx.getDn() + " to " + userProfile);
return userHomePath;
+ jcrProperty);
String value = ctx.getStringAttribute(ldapAttribute);
- if (value == null)
- return;
- userProfile.setProperty(jcrProperty, value);
+ String jcrValue = userProfile.hasProperty(jcrProperty) ? userProfile
+ .getProperty(jcrProperty).getString() : null;
+ if (value != null && jcrValue != null) {
+ if (!value.equals(jcrValue))
+ userProfile.setProperty(jcrProperty, value);
+ } else if (value != null && jcrValue == null) {
+ userProfile.setProperty(jcrProperty, value);
+ } else if (value == null && jcrValue != null) {
+ userProfile.setProperty(jcrProperty, value);
+ }
} catch (Exception e) {
throw new ArgeoException("Cannot map JCR property " + jcrProperty
+ " from LDAP", e);
<value>classpath:/org/argeo/jcr/argeo.cnd</value>
</list>
</property>
+ <property name="remoteSystemCredentials">
+ <bean class="javax.jcr.SimpleCredentials">
+ <constructor-arg value="root" />
+ <constructor-arg value="demo" />
+ </bean>
+ </property>
</bean>
<!-- Execute initialization with a system authentication -->
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
+ <Bundle-SymbolicName>${project.artifactId};singleton:=true</Bundle-SymbolicName>
<Import-Package>
*,
com.mysql.jdbc;version="[5.0.0,6.0.0)";resolution:=optional,
package org.argeo.jcr.ui.explorer.views;
-import java.util.Arrays;
import java.util.List;
import javax.jcr.Property;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
+import javax.jcr.Value;
import javax.jcr.observation.Event;
import javax.jcr.observation.EventListener;
import javax.jcr.observation.ObservationManager;
Property property = (Property) element;
if (property.getType() == PropertyType.BINARY)
return "<binary>";
- else if (property.isMultiple())
- return Arrays.asList(property.getValues()).toString();
- else
+ else if (property.isMultiple()) {
+ StringBuffer buf = new StringBuffer("[");
+ Value[] values = property.getValues();
+ for (int i = 0; i < values.length; i++) {
+ if (i != 0)
+ buf.append(", ");
+ buf.append(values[i].getString());
+ }
+ buf.append(']');
+ return buf.toString();
+ } else
return property.getValue().getString();
} catch (RepositoryException e) {
throw new ArgeoException(
<artifactId>org.argeo.server.core</artifactId>
<version>0.3.4-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>org.argeo.commons.security</groupId>
+ <artifactId>org.argeo.security.core</artifactId>
+ <version>0.3.4-SNAPSHOT</version>
+ </dependency>
<dependency>
<groupId>org.argeo.commons.server</groupId>
<artifactId>org.argeo.server.jcr.mvc</artifactId>
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
import javax.jcr.Value;
import org.apache.commons.io.FileUtils;
import org.argeo.ArgeoException;
import org.argeo.jcr.ArgeoNames;
import org.argeo.jcr.JcrUtils;
+import org.argeo.security.SystemAuthentication;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
+import org.springframework.security.Authentication;
+import org.springframework.security.context.SecurityContextHolder;
+import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.util.SystemPropertyUtils;
import org.xml.sax.InputSource;
private Resource variables;
private Boolean inMemory = false;
- private String uri = null;
// wrapped repository
private Repository repository;
private Executor systemExecutor;
- public void init() throws Exception {
+ // remote
+ private String uri = null;
+ private Credentials remoteSystemCredentials = null;
+
+ /**
+ * Empty constructor, {@link #init()} should be called after properties have
+ * been set
+ */
+ public JackrabbitContainer() {
+ }
+
+ /**
+ * Convenience constructor for remote, {@link #init()} is called in the
+ * constructor.
+ */
+ public JackrabbitContainer(String uri, Credentials remoteSystemCredentials) {
+ setUri(uri);
+ setRemoteSystemCredentials(remoteSystemCredentials);
+ init();
+ }
+
+ public void init() {
if (repository != null) {
// we are just wrapping another repository
- importNodeTypeDefinitions(repository);
+ importNodeTypeDefinitions();
return;
}
createJackrabbitRepository();
-
// migrate if needed
migrate();
// apply new CND files after migration
if (cndFiles != null && cndFiles.size() > 0)
- importNodeTypeDefinitions(repository);
+ importNodeTypeDefinitions();
}
/** Actually creates a new repository. */
// the
// remote repository has been properly configured
return;
+ } else {
+ // reset uri to null in order to optimize isRemote()
+ uri = null;
}
// local repository
* changed. In case of failures an error will be logged but no exception
* will be thrown.
*/
- protected void importNodeTypeDefinitions(final Repository repository) {
+ protected void importNodeTypeDefinitions() {
+ // importing node def on remote si currently not supported
+ if (isRemote())
+ return;
+
Runnable action = new Runnable() {
public void run() {
Reader reader = null;
Session session = null;
try {
- session = repository.login();
- processNewSession(session);
+ session = login();
+ // processNewSession(session);
// Load cnds as resources
for (String resUrl : cndFiles) {
Resource res = resourceLoader.getResource(resUrl);
return getRepository().getDescriptorKeys();
}
- public Session login() throws LoginException, RepositoryException {
- Session session = getRepository().login();
- processNewSession(session);
- return session;
- }
-
+ /** Central login method */
public Session login(Credentials credentials, String workspaceName)
throws LoginException, NoSuchWorkspaceException,
RepositoryException {
+
+ // retrieve credentials for remote
+ if (credentials == null && isRemote()) {
+ Authentication authentication = SecurityContextHolder.getContext()
+ .getAuthentication();
+ if (authentication != null) {
+ if (authentication instanceof UsernamePasswordAuthenticationToken) {
+ UsernamePasswordAuthenticationToken upat = (UsernamePasswordAuthenticationToken) authentication;
+ credentials = new SimpleCredentials(upat.getName(), upat
+ .getCredentials().toString().toCharArray());
+ } else if ((authentication instanceof SystemAuthentication)
+ && remoteSystemCredentials != null) {
+ credentials = remoteSystemCredentials;
+ }
+ }
+ }
+
Session session;
try {
session = getRepository().login(credentials, workspaceName);
} catch (NoSuchWorkspaceException e) {
- if (autocreateWorkspaces)
+ if (autocreateWorkspaces && workspaceName != null)
session = createWorkspaceAndLogsIn(credentials, workspaceName);
else
throw e;
return session;
}
+ public Session login() throws LoginException, RepositoryException {
+ return login(null, null);
+ }
+
public Session login(Credentials credentials) throws LoginException,
RepositoryException {
- Session session = getRepository().login(credentials);
- processNewSession(session);
- return session;
+ return login(credentials, null);
}
public Session login(String workspaceName) throws LoginException,
NoSuchWorkspaceException, RepositoryException {
- Session session;
- try {
- session = getRepository().login(workspaceName);
- } catch (NoSuchWorkspaceException e) {
- if (autocreateWorkspaces)
- session = createWorkspaceAndLogsIn(null, workspaceName);
- else
- throw e;
- }
- processNewSession(session);
- return session;
+ return login(null, workspaceName);
+ }
+
+ public Boolean isRemote() {
+ return uri != null;
}
/** Wraps access to the repository, making sure it is available. */
this.uri = uri;
}
+ public void setRemoteSystemCredentials(Credentials remoteSystemCredentials) {
+ this.remoteSystemCredentials = remoteSystemCredentials;
+ }
+
public void setSystemExecutor(Executor systemExecutor) {
this.systemExecutor = systemExecutor;
}
import org.argeo.jcr.ArgeoJcrConstants;
import org.argeo.jcr.DefaultRepositoryFactory;
+/** Repository factory which can access remote Jackrabbit repositories */
public class JackrabbitRepositoryFactory extends DefaultRepositoryFactory
implements RepositoryFactory, ArgeoJcrConstants {
private final static Log log = LogFactory
uri = parameters.get(JcrUtils.REPOSITORY_URI).toString();
else
return null;
-
+
Map<String, String> params = new HashMap<String, String>();
params.put(JcrUtils.REPOSITORY_URI, uri);
repository = new Jcr2davRepositoryFactory().getRepository(params);
package org.argeo.jackrabbit.remote;
import java.io.Serializable;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import javax.jcr.LoginException;
+import javax.jcr.Node;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
+import javax.jcr.Value;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.jackrabbit.api.JackrabbitSession;
+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.jackrabbit.server.SessionProvider;
import org.argeo.ArgeoException;
+import org.argeo.jcr.ArgeoNames;
import org.argeo.jcr.JcrUtils;
-/** To be injected, typically of scope="session" */
+/**
+ * To be injected, typically of scope="session". Implements an open session in
+ * view patter: a new JCR session is created for each request
+ */
public class SimpleSessionProvider implements SessionProvider, Serializable {
private static final long serialVersionUID = 2270957712453841368L;
RepositoryException {
if (openSessionInView) {
- return rep.login(workspace);
+ JackrabbitSession session = (JackrabbitSession) rep
+ .login(workspace);
+ writeRemoteRoles(session);
+ return session;
} else {
// since sessions is transient it can't be restored from the session
if (sessions == null)
if (!sessions.containsKey(workspace)) {
try {
- Session session = rep.login(null, workspace);
+ JackrabbitSession session = (JackrabbitSession) rep.login(
+ null, workspace);
+ writeRemoteRoles(session);
if (log.isTraceEnabled())
log.trace("User " + session.getUserID()
+ " logged into " + request.getServletPath());
}
}
+ protected void writeRemoteRoles(JackrabbitSession session)
+ throws RepositoryException {
+ // retrieve roles
+ String userId = session.getUserID();
+ UserManager userManager = session.getUserManager();
+ User user = (User) userManager.getAuthorizable(userId);
+ if (user == null) {
+ // anonymous
+ return;
+ }
+ List<String> userGroupIds = new ArrayList<String>();
+ if (user != null)
+ for (Iterator<Group> it = user.memberOf(); it.hasNext();)
+ userGroupIds.add(it.next().getID());
+
+ // write roles if needed
+ Node userProfile = JcrUtils.getUserProfile(session);
+ boolean writeRoles = false;
+ if (userProfile.hasProperty(ArgeoNames.ARGEO_REMOTE_ROLES)) {
+ Value[] roles = userProfile.getProperty(
+ ArgeoNames.ARGEO_REMOTE_ROLES).getValues();
+ if (roles.length != userGroupIds.size())
+ writeRoles = true;
+ else
+ for (int i = 0; i < roles.length; i++)
+ if (!roles[i].getString().equals(userGroupIds.get(i)))
+ writeRoles = true;
+ } else
+ writeRoles = true;
+
+ if (writeRoles) {
+ session.getWorkspace().getVersionManager()
+ .checkout(userProfile.getPath());
+ String[] roleIds = userGroupIds.toArray(new String[userGroupIds
+ .size()]);
+ userProfile.setProperty(ArgeoNames.ARGEO_REMOTE_ROLES, roleIds);
+ JcrUtils.updateLastModified(userProfile);
+ session.save();
+ session.getWorkspace().getVersionManager()
+ .checkin(userProfile.getPath());
+ }
+
+ }
+
public void releaseSession(Session session) {
if (log.isTraceEnabled())
log.trace("Releasing JCR session " + session);
- if (openSessionInView)
- JcrUtils.logoutQuietly(session);
+ if (openSessionInView) {
+ if (session.isLive()) {
+ session.logout();
+ if (log.isTraceEnabled())
+ log.trace("Logged out remote JCR session " + session);
+ }
+ }
}
public void init() {
if (session.isLive()) {
session.logout();
if (log.isDebugEnabled())
- log.debug("Logged out JCR session " + session);
+ log.debug("Logged out remote JCR session " + session);
}
}
}
public final static String ARGEO_REMOTE = "argeo:remote";
public final static String ARGEO_PASSWORD = "argeo:password";
+ public final static String ARGEO_REMOTE_ROLES = "argeo:remoteRoles";
// user profile
public final static String ARGEO_PROFILE = "argeo:profile";
relPath, p.getValue(), null);
diffs.put(relPath, pDiff);
} else {
- if (p.isMultiple())
- continue props;
- Value referenceValue = p.getValue();
- Value newValue = observed.getProperty(name).getValue();
- if (!referenceValue.equals(newValue)) {
- String relPath = propertyRelPath(baseRelPath, name);
- PropertyDiff pDiff = new PropertyDiff(
- PropertyDiff.MODIFIED, relPath, referenceValue,
- newValue);
- diffs.put(relPath, pDiff);
+ if (p.isMultiple()) {
+ // FIXME implement multiple
+ } else {
+ Value referenceValue = p.getValue();
+ Value newValue = observed.getProperty(name).getValue();
+ if (!referenceValue.equals(newValue)) {
+ String relPath = propertyRelPath(baseRelPath, name);
+ PropertyDiff pDiff = new PropertyDiff(
+ PropertyDiff.MODIFIED, relPath,
+ referenceValue, newValue);
+ diffs.put(relPath, pDiff);
+ }
}
}
}
if (name.startsWith("jcr:"))
continue props;
if (!reference.hasProperty(name)) {
- String relPath = propertyRelPath(baseRelPath, name);
- PropertyDiff pDiff = new PropertyDiff(PropertyDiff.ADDED,
- relPath, null, p.getValue());
- diffs.put(relPath, pDiff);
+ if (p.isMultiple()) {
+ // FIXME implement multiple
+ } else {
+ String relPath = propertyRelPath(baseRelPath, name);
+ PropertyDiff pDiff = new PropertyDiff(
+ PropertyDiff.ADDED, relPath, null, p.getValue());
+ diffs.put(relPath, pDiff);
+ }
}
}
} catch (RepositoryException e) {
Constraint constraint = qomf.comparison(userIdDop,
QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, userIdSop);
Query query = qomf.createQuery(sel, constraint, null, null);
- Node userHome = JcrUtils.querySingleNode(query);
- return userHome;
+ Node userProfile = JcrUtils.querySingleNode(query);
+ return userProfile;
} catch (RepositoryException e) {
throw new ArgeoException(
"Cannot find profile for user " + username, e);
} else {
userProfile = userHome.addNode(ArgeoNames.ARGEO_PROFILE);
userProfile.addMixin(ArgeoTypes.ARGEO_USER_PROFILE);
+ // session.getWorkspace().getVersionManager()
+ // .checkout(userProfile.getPath());
userProfile.setProperty(ArgeoNames.ARGEO_USER_ID, username);
session.save();
+ session.getWorkspace().getVersionManager()
+ .checkin(userProfile.getPath());
// we need to save the profile before adding the user home type
}
userHome.addMixin(ArgeoTypes.ARGEO_USER_HOME);
[argeo:userProfile] > mix:created, mix:lastModified, mix:title, mix:versionable
mixin
- argeo:userID (STRING) m
+- argeo:remoteRoles (STRING) *
[argeo:preferenceNode] > mix:lastModified, mix:versionable
mixin