From 2c4852dcd20d4cde88776c527ae935f242ae1e77 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Wed, 22 Aug 2012 15:02:00 +0000 Subject: [PATCH] Refactor JCR utils and home usage git-svn-id: https://svn.argeo.org/commons/trunk@5535 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- .../eclipse/ui/jcr/JcrPreferenceStore.java | 3 +- .../META-INF/spring/security-jcr-osgi.xml | 2 - .../META-INF/spring/security-jcr-services.xml | 5 - .../META-INF/spring/security-ldap-osgi.xml | 1 - .../spring/security-ldap-services.xml | 5 - .../META-INF/spring/security-os-osgi.xml | 2 - .../META-INF/spring/security-os.xml | 5 - .../ui/admin/editors/ArgeoUserEditor.java | 4 +- .../ui/admin/wizards/NewUserWizard.java | 6 +- .../security/SystemExecutionService.java | 12 +- .../argeo/security/jcr/JcrUserDetails.java | 4 +- .../jcr/OsJcrAuthenticationProvider.java | 5 +- .../security/jcr/OsJcrUserAdminService.java | 3 +- .../jcr/RemoteJcrAuthenticationProvider.java | 4 +- .../jackrabbit/ArgeoSecurityManager.java | 127 +++++---- .../ldap/jcr/JcrLdapSynchronizer.java | 8 +- .../ldap/jcr/JcrUserDetailsContextMapper.java | 6 +- .../META-INF/spring/commands.xml | 1 - .../jcr/ui/explorer/JcrExplorerConstants.java | 2 - .../explorer/browser/NodeContentProvider.java | 4 +- .../commands/AddRemoteRepository.java | 44 +-- .../ui/explorer/model/RepositoriesNode.java | 4 +- .../jcr/ui/explorer/utils/JcrUiUtils.java | 8 +- .../remote/SimpleSessionProvider.java | 3 +- .../java/org/argeo/jcr/ArgeoJcrUtils.java | 103 +++++++ .../src/main/java/org/argeo/jcr/JcrUtils.java | 268 ------------------ .../org/argeo/jcr/security/JcrKeyring.java | 9 +- .../argeo/jcr/security/SecurityJcrUtils.java | 123 ++++++++ 28 files changed, 347 insertions(+), 424 deletions(-) create mode 100644 server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoJcrUtils.java create mode 100644 server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/security/SecurityJcrUtils.java diff --git a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrPreferenceStore.java b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrPreferenceStore.java index 709005597..93d0f0454 100644 --- a/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrPreferenceStore.java +++ b/base/runtime/org.argeo.eclipse.ui.jcr/src/main/java/org/argeo/eclipse/ui/jcr/JcrPreferenceStore.java @@ -29,6 +29,7 @@ import javax.jcr.version.VersionManager; import org.apache.commons.io.IOUtils; import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoJcrUtils; import org.argeo.jcr.ArgeoNames; import org.argeo.jcr.ArgeoTypes; import org.argeo.jcr.JcrUtils; @@ -52,7 +53,7 @@ public class JcrPreferenceStore extends PreferenceStore implements ArgeoNames { try { if (session.hasPendingChanges()) session.save(); - Node userHome = JcrUtils.getUserHome(session); + Node userHome = ArgeoJcrUtils.getUserHome(session); if (userHome == null) throw new ArgeoException("No user home for " + session.getUserID()); diff --git a/security/modules/org.argeo.security.dao.jackrabbit/META-INF/spring/security-jcr-osgi.xml b/security/modules/org.argeo.security.dao.jackrabbit/META-INF/spring/security-jcr-osgi.xml index 53f66d558..de60f22ea 100644 --- a/security/modules/org.argeo.security.dao.jackrabbit/META-INF/spring/security-jcr-osgi.xml +++ b/security/modules/org.argeo.security.dao.jackrabbit/META-INF/spring/security-jcr-osgi.xml @@ -13,8 +13,6 @@ - - diff --git a/security/modules/org.argeo.security.dao.jackrabbit/META-INF/spring/security-jcr-services.xml b/security/modules/org.argeo.security.dao.jackrabbit/META-INF/spring/security-jcr-services.xml index 49ace03d0..1a3d2eefe 100644 --- a/security/modules/org.argeo.security.dao.jackrabbit/META-INF/spring/security-jcr-services.xml +++ b/security/modules/org.argeo.security.dao.jackrabbit/META-INF/spring/security-jcr-services.xml @@ -12,11 +12,6 @@ - - - - - diff --git a/security/modules/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-osgi.xml b/security/modules/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-osgi.xml index 3af0501ed..aa3b67ac6 100644 --- a/security/modules/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-osgi.xml +++ b/security/modules/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-osgi.xml @@ -11,7 +11,6 @@ filter="(argeo.jcr.repository.alias=node)" /> - diff --git a/security/modules/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-services.xml b/security/modules/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-services.xml index 57686c888..36dedf389 100644 --- a/security/modules/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-services.xml +++ b/security/modules/org.argeo.security.dao.ldap/META-INF/spring/security-ldap-services.xml @@ -4,11 +4,6 @@ xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> - - - - - diff --git a/security/modules/org.argeo.security.dao.os/META-INF/spring/security-os-osgi.xml b/security/modules/org.argeo.security.dao.os/META-INF/spring/security-os-osgi.xml index 8c6977a68..5d827b4a5 100644 --- a/security/modules/org.argeo.security.dao.os/META-INF/spring/security-os-osgi.xml +++ b/security/modules/org.argeo.security.dao.os/META-INF/spring/security-os-osgi.xml @@ -17,8 +17,6 @@ - - - - - - - diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/ArgeoUserEditor.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/ArgeoUserEditor.java index 1c1a3788b..fab34323a 100644 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/ArgeoUserEditor.java +++ b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/ArgeoUserEditor.java @@ -20,8 +20,8 @@ import javax.jcr.RepositoryException; import javax.jcr.Session; import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoJcrUtils; import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.JcrUtils; import org.argeo.security.UserAdminService; import org.argeo.security.jcr.JcrUserDetails; import org.argeo.security.ui.admin.SecurityAdminPlugin; @@ -48,7 +48,7 @@ public class ArgeoUserEditor extends FormEditor { super.init(site, input); String username = ((ArgeoUserEditorInput) getEditorInput()) .getUsername(); - userHome = JcrUtils.getUserHome(session, username); + userHome = ArgeoJcrUtils.getUserHome(session, username); if (userAdminService.userExists(username)) { userDetails = (JcrUserDetails) userAdminService diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/NewUserWizard.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/NewUserWizard.java index f9a3024ea..a4cd0edb8 100644 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/NewUserWizard.java +++ b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/NewUserWizard.java @@ -22,7 +22,9 @@ import javax.jcr.Session; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.eclipse.ui.ErrorFeedback; +import org.argeo.jcr.ArgeoJcrUtils; import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.security.SecurityJcrUtils; import org.argeo.security.UserAdminService; import org.argeo.security.jcr.JcrUserDetails; import org.eclipse.jface.wizard.Wizard; @@ -55,7 +57,7 @@ public class NewUserWizard extends Wizard { String username = mainUserInfo.getUsername(); try { - Node userProfile = JcrUtils.createUserProfile(session, username); + Node userProfile = SecurityJcrUtils.createUserProfile(session, username); // session.getWorkspace().getVersionManager() // .checkout(userProfile.getPath()); mainUserInfo.mapToProfileNode(userProfile); @@ -70,7 +72,7 @@ public class NewUserWizard extends Wizard { return true; } catch (Exception e) { JcrUtils.discardQuietly(session); - Node userHome = JcrUtils.getUserHome(session, username); + Node userHome = ArgeoJcrUtils.getUserHome(session, username); if (userHome != null) { try { userHome.remove(); diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/SystemExecutionService.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/SystemExecutionService.java index 2d5bcb709..258a08e4c 100644 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/SystemExecutionService.java +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/SystemExecutionService.java @@ -21,22 +21,22 @@ import java.util.concurrent.Future; /** * Allows to execute code authenticated as a system user (that is not a real - * person). The {@link Executor} interface interface is not used directly in - * order to allow future extension of this interface and to simplify its - * publication (e.g. as an OSGi service) and interception. + * person). The {@link Executor} interface is not used directly in order to + * allow future extension of this interface and to simplify its publication + * (e.g. as an OSGi service) and interception. */ public interface SystemExecutionService extends Executor { /** * Executes this {@link Runnable} within a system authenticated context. * Implementations should make sure that this method is properly secured via - * Java permissions since it could access to everything without credentials. + * Java permissions since it could access everything without credentials. */ public void execute(Runnable runnable); - + /** * Executes this {@link Callable} within a system authenticated context. * Implementations should make sure that this method is properly secured via - * Java permissions since it could access to everything without credentials. + * Java permissions since it could access everything without credentials. */ public Future submit(Callable task); } diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/JcrUserDetails.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/JcrUserDetails.java index 88ea42590..1a19ecb20 100644 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/JcrUserDetails.java +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/JcrUserDetails.java @@ -24,7 +24,7 @@ import javax.jcr.RepositoryException; import javax.jcr.Session; import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.security.SecurityJcrUtils; import org.springframework.security.BadCredentialsException; import org.springframework.security.DisabledException; import org.springframework.security.GrantedAuthority; @@ -90,7 +90,7 @@ public class JcrUserDetails extends User implements ArgeoNames { */ public JcrUserDetails(Session session, String username, String password, GrantedAuthority[] authorities) throws RepositoryException { - this(JcrUtils.getUserProfile(session, username), + this(SecurityJcrUtils.getUserProfile(session, username), password != null ? password : "", authorities); } diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/OsJcrAuthenticationProvider.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/OsJcrAuthenticationProvider.java index 917733dbc..d304dc365 100644 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/OsJcrAuthenticationProvider.java +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/OsJcrAuthenticationProvider.java @@ -22,6 +22,7 @@ import javax.jcr.Session; import org.argeo.ArgeoException; import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.security.SecurityJcrUtils; import org.argeo.security.OsAuthenticationToken; import org.argeo.security.core.OsAuthenticationProvider; import org.springframework.security.Authentication; @@ -76,13 +77,13 @@ public class OsJcrAuthenticationProvider extends OsAuthenticationProvider { // WARNING: at this stage we assume that the java properties // will have the same value String username = System.getProperty("user.name"); - Node userProfile = JcrUtils.createUserProfileIfNeeded( + Node userProfile = SecurityJcrUtils.createUserProfileIfNeeded( securitySession, username); JcrUserDetails.checkAccountStatus(userProfile); // each user should have a writable area in the default // workspace of the node - JcrUtils.createUserHomeIfNeeded(nodeSession, username); + SecurityJcrUtils.createUserHomeIfNeeded(nodeSession, username); userDetails = new JcrUserDetails(userProfile, authen .getCredentials().toString(), getBaseAuthorities()); authen.setDetails(userDetails); diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/OsJcrUserAdminService.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/OsJcrUserAdminService.java index 483cc408d..80ef1e559 100644 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/OsJcrUserAdminService.java +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/OsJcrUserAdminService.java @@ -10,6 +10,7 @@ import javax.jcr.Session; import org.argeo.ArgeoException; import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.security.SecurityJcrUtils; import org.argeo.security.UserAdminService; import org.springframework.dao.DataAccessException; import org.springframework.security.userdetails.UserDetails; @@ -67,7 +68,7 @@ public class OsJcrUserAdminService implements UserAdminService { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { if (getSPropertyUsername().equals(username)) { - Node userProfile = JcrUtils.getUserProfile(securitySession, + Node userProfile = SecurityJcrUtils.getUserProfile(securitySession, username); JcrUserDetails userDetails; try { diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/RemoteJcrAuthenticationProvider.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/RemoteJcrAuthenticationProvider.java index 7087536a3..62dc98214 100644 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/RemoteJcrAuthenticationProvider.java +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/RemoteJcrAuthenticationProvider.java @@ -31,8 +31,8 @@ import javax.jcr.Value; import org.argeo.ArgeoException; import org.argeo.jcr.ArgeoJcrConstants; +import org.argeo.jcr.ArgeoJcrUtils; import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.JcrUtils; import org.argeo.security.NodeAuthenticationToken; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; @@ -65,7 +65,7 @@ public class RemoteJcrAuthenticationProvider implements AuthenticationProvider, String workspace = siteAuth.getSecurityWorkspace(); session = repository.login(sp, workspace); - Node userHome = JcrUtils.getUserHome(session); + Node userHome = ArgeoJcrUtils.getUserHome(session); if (userHome == null || !userHome.hasNode(ArgeoNames.ARGEO_PROFILE)) throw new ArgeoException("No profile for user " + siteAuth.getName() + " in security workspace " diff --git a/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSecurityManager.java b/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSecurityManager.java index 110998069..4af5d3f3d 100644 --- a/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSecurityManager.java +++ b/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSecurityManager.java @@ -17,26 +17,16 @@ package org.argeo.security.jackrabbit; import java.security.Principal; import java.util.ArrayList; -import java.util.HashMap; import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.Set; -import javax.jcr.Node; -import javax.jcr.PropertyType; import javax.jcr.RepositoryException; import javax.jcr.Session; -import javax.jcr.Value; -import javax.jcr.ValueFactory; -import javax.jcr.security.Privilege; import javax.security.auth.Subject; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.jackrabbit.api.security.JackrabbitAccessControlList; -import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager; -import org.apache.jackrabbit.api.security.JackrabbitAccessControlPolicy; import org.apache.jackrabbit.api.security.user.Group; import org.apache.jackrabbit.api.security.user.User; import org.apache.jackrabbit.api.security.user.UserManager; @@ -45,11 +35,10 @@ import org.apache.jackrabbit.core.security.AnonymousPrincipal; import org.apache.jackrabbit.core.security.SecurityConstants; import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager; import org.argeo.ArgeoException; -import org.argeo.jcr.JcrUtils; import org.springframework.security.Authentication; import org.springframework.security.GrantedAuthority; -/** Intermediary class in order to have a consistent naming in config files. */ +/** Integrates Spring Security and Jackrabbit Security user and roles. */ public class ArgeoSecurityManager extends DefaultSecurityManager { private Log log = LogFactory.getLog(ArgeoSecurityManager.class); @@ -61,8 +50,6 @@ public class ArgeoSecurityManager extends DefaultSecurityManager { @Override public String getUserID(Subject subject, String workspaceName) throws RepositoryException { - long begin = System.currentTimeMillis(); - if (log.isTraceEnabled()) log.trace(subject); // skip anonymous user (no rights) @@ -72,6 +59,8 @@ public class ArgeoSecurityManager extends DefaultSecurityManager { if (!subject.getPrincipals(ArgeoSystemPrincipal.class).isEmpty()) return super.getUserID(subject, workspaceName); + // retrieve Spring authentication from JAAS + // TODO? use Spring Security context holder Authentication authen; Set authens = subject .getPrincipals(Authentication.class); @@ -81,16 +70,32 @@ public class ArgeoSecurityManager extends DefaultSecurityManager { else authen = authens.iterator().next(); - UserManager systemUm = getSystemUserManager(workspaceName); + // sync Spring and Jackrabbit + syncSpringAndJackrabbitSecurity(authen); + + return authen.getName(); + } + + /** + * Make sure that the Jackrabbit security model contains this user and its + * granted authorities + */ + protected void syncSpringAndJackrabbitSecurity(Authentication authen) + throws RepositoryException { + long begin = System.currentTimeMillis(); + + // workspace is irrelevant here + UserManager systemUm = getSystemUserManager(null); String userId = authen.getName(); User user = (User) systemUm.getAuthorizable(userId); if (user == null) { user = systemUm.createUser(userId, authen.getCredentials() .toString(), authen, null); - JcrUtils.createUserHomeIfNeeded(getSystemSession(), userId); - getSystemSession().save(); - setSecurityHomeAuthorizations(user); + // SecurityJcrUtils.createUserHomeIfNeeded(getSystemSession(), + // userId); + // getSystemSession().save(); + // setSecurityHomeAuthorizations(user); log.info(userId + " added as " + user); } @@ -118,51 +123,51 @@ public class ArgeoSecurityManager extends DefaultSecurityManager { log.trace("Spring and Jackrabbit Security synchronized for user " + userId + " in " + (System.currentTimeMillis() - begin) + " ms"); - return userId; } - protected synchronized void setSecurityHomeAuthorizations(User user) { - // give read privileges on user security home - String userId = ""; - try { - userId = user.getID(); - Node userHome = JcrUtils.getUserHome(getSystemSession(), userId); - if (userHome == null) - throw new ArgeoException("No security home available for user " - + userId); - - String path = userHome.getPath(); - Principal principal = user.getPrincipal(); - - JackrabbitAccessControlManager acm = (JackrabbitAccessControlManager) getSystemSession() - .getAccessControlManager(); - JackrabbitAccessControlPolicy[] ps = acm - .getApplicablePolicies(principal); - if (ps.length == 0) { - // log.warn("No ACL found for " + user); - return; - } - - JackrabbitAccessControlList list = (JackrabbitAccessControlList) ps[0]; - - // add entry - Privilege[] privileges = new Privilege[] { acm - .privilegeFromName(Privilege.JCR_READ) }; - Map restrictions = new HashMap(); - ValueFactory vf = getSystemSession().getValueFactory(); - restrictions.put("rep:nodePath", - vf.createValue(path, PropertyType.PATH)); - restrictions.put("rep:glob", vf.createValue("*")); - list.addEntry(principal, privileges, true /* allow or deny */, - restrictions); - } catch (Exception e) { - e.printStackTrace(); - throw new ArgeoException( - "Cannot set authorization on security home for " + userId - + ": " + e.getMessage()); - } - - } + // protected synchronized void setSecurityHomeAuthorizations(User user) { + // // give read privileges on user security home + // String userId = ""; + // try { + // userId = user.getID(); + // Node userHome = SecurityJcrUtils.getUserHome(getSystemSession(), userId); + // if (userHome == null) + // throw new ArgeoException("No security home available for user " + // + userId); + // + // String path = userHome.getPath(); + // Principal principal = user.getPrincipal(); + // + // JackrabbitAccessControlManager acm = (JackrabbitAccessControlManager) + // getSystemSession() + // .getAccessControlManager(); + // JackrabbitAccessControlPolicy[] ps = acm + // .getApplicablePolicies(principal); + // if (ps.length == 0) { + // // log.warn("No ACL found for " + user); + // return; + // } + // + // JackrabbitAccessControlList list = (JackrabbitAccessControlList) ps[0]; + // + // // add entry + // Privilege[] privileges = new Privilege[] { acm + // .privilegeFromName(Privilege.JCR_READ) }; + // Map restrictions = new HashMap(); + // ValueFactory vf = getSystemSession().getValueFactory(); + // restrictions.put("rep:nodePath", + // vf.createValue(path, PropertyType.PATH)); + // restrictions.put("rep:glob", vf.createValue("*")); + // list.addEntry(principal, privileges, true /* allow or deny */, + // restrictions); + // } catch (Exception e) { + // e.printStackTrace(); + // throw new ArgeoException( + // "Cannot set authorization on security home for " + userId + // + ": " + e.getMessage()); + // } + // + // } @Override protected WorkspaceAccessManager createDefaultWorkspaceAccessManager() { diff --git a/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrLdapSynchronizer.java b/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrLdapSynchronizer.java index 11e8e8199..178785602 100644 --- a/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrLdapSynchronizer.java +++ b/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrLdapSynchronizer.java @@ -59,6 +59,7 @@ import org.argeo.ArgeoException; import org.argeo.jcr.ArgeoNames; import org.argeo.jcr.ArgeoTypes; import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.security.SecurityJcrUtils; import org.argeo.security.jcr.JcrUserDetails; import org.springframework.ldap.core.ContextExecutor; import org.springframework.ldap.core.ContextMapper; @@ -223,9 +224,10 @@ public class JcrLdapSynchronizer implements UserDetailsContextMapper, /** Called during authentication in order to retrieve user details */ public UserDetails mapUserFromContext(final DirContextOperations ctx, final String username, GrantedAuthority[] authorities) { + log.debug("mapUserFromContext"); if (ctx == null) throw new ArgeoException("No LDAP information for user " + username); - Node userProfile = JcrUtils.createUserProfileIfNeeded(securitySession, + Node userProfile = SecurityJcrUtils.createUserProfileIfNeeded(securitySession, username); JcrUserDetails.checkAccountStatus(userProfile); @@ -260,7 +262,7 @@ public class JcrLdapSynchronizer implements UserDetailsContextMapper, try { // process String username = ctx.getStringAttribute(usernameAttribute); - Node userHome = JcrUtils.createUserHomeIfNeeded(session, username); + Node userHome = SecurityJcrUtils.createUserHomeIfNeeded(session, username); Node userProfile; // = userHome.getNode(ARGEO_PROFILE); if (userHome.hasNode(ARGEO_PROFILE)) { userProfile = userHome.getNode(ARGEO_PROFILE); @@ -279,7 +281,7 @@ public class JcrLdapSynchronizer implements UserDetailsContextMapper, .checkin(userProfile.getPath()); } } else { - userProfile = JcrUtils.createUserProfile(securitySession, + userProfile = SecurityJcrUtils.createUserProfile(securitySession, username); userProfile.getSession().save(); userProfile.getSession().getWorkspace().getVersionManager() diff --git a/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrUserDetailsContextMapper.java b/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrUserDetailsContextMapper.java index 1db81167d..72c120728 100644 --- a/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrUserDetailsContextMapper.java +++ b/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrUserDetailsContextMapper.java @@ -23,6 +23,7 @@ import javax.jcr.RepositoryException; import javax.jcr.Session; import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoJcrUtils; import org.argeo.jcr.ArgeoNames; import org.argeo.jcr.JcrUtils; import org.argeo.security.jcr.JcrUserDetails; @@ -32,7 +33,8 @@ import org.springframework.security.GrantedAuthority; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.userdetails.ldap.UserDetailsContextMapper; -/** Read only mapping from LDAP to user details */ +/** @deprecated Read only mapping from LDAP to user details */ +@Deprecated public class JcrUserDetailsContextMapper implements UserDetailsContextMapper, ArgeoNames { /** Admin session on the security workspace */ @@ -59,7 +61,7 @@ public class JcrUserDetailsContextMapper implements UserDetailsContextMapper, final String username, GrantedAuthority[] authorities) { if (ctx == null) throw new ArgeoException("No LDAP information for user " + username); - Node userHome = JcrUtils.getUserHome(securitySession, username); + Node userHome = ArgeoJcrUtils.getUserHome(securitySession, username); if (userHome == null) throw new ArgeoException("No JCR information for user " + username); diff --git a/server/plugins/org.argeo.jcr.ui.explorer/META-INF/spring/commands.xml b/server/plugins/org.argeo.jcr.ui.explorer/META-INF/spring/commands.xml index d57c98974..e3bad2892 100644 --- a/server/plugins/org.argeo.jcr.ui.explorer/META-INF/spring/commands.xml +++ b/server/plugins/org.argeo.jcr.ui.explorer/META-INF/spring/commands.xml @@ -22,7 +22,6 @@ - diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerConstants.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerConstants.java index 8591a4d35..b4e3ca45c 100644 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerConstants.java +++ b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerConstants.java @@ -17,8 +17,6 @@ package org.argeo.jcr.ui.explorer; /** Constants used across the application. */ public interface JcrExplorerConstants { - public final static String PARAM_REPOSITORY_URI = "org.argeo.jcr.ui.explorer.repositoryUri"; - /* * MISCEALLENEOUS */ diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/NodeContentProvider.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/NodeContentProvider.java index 36c44d01d..a1aca2b20 100644 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/NodeContentProvider.java +++ b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/NodeContentProvider.java @@ -25,7 +25,7 @@ import javax.jcr.Session; import org.argeo.eclipse.ui.TreeParent; import org.argeo.jcr.ArgeoJcrConstants; -import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.ArgeoJcrUtils; import org.argeo.jcr.RepositoryRegister; import org.argeo.jcr.security.JcrKeyring; import org.argeo.jcr.ui.explorer.model.RepositoriesNode; @@ -72,7 +72,7 @@ public class NodeContentProvider implements ITreeContentProvider { return; if (userSession != null) { - Node userHome = JcrUtils.getUserHome(userSession); + Node userHome = ArgeoJcrUtils.getUserHome(userSession); if (userHome != null) { // TODO : find a way to dynamically get alias for the node if (homeNode != null) diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddRemoteRepository.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddRemoteRepository.java index 6b5dfa8b0..7f101b8bc 100644 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddRemoteRepository.java +++ b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddRemoteRepository.java @@ -27,10 +27,12 @@ import javax.jcr.SimpleCredentials; import org.argeo.ArgeoException; import org.argeo.eclipse.ui.ErrorFeedback; import org.argeo.jcr.ArgeoJcrConstants; +import org.argeo.jcr.ArgeoJcrUtils; import org.argeo.jcr.ArgeoNames; import org.argeo.jcr.ArgeoTypes; import org.argeo.jcr.JcrUtils; import org.argeo.jcr.security.JcrKeyring; +import org.argeo.jcr.security.SecurityJcrUtils; import org.argeo.jcr.ui.explorer.JcrExplorerConstants; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; @@ -52,7 +54,6 @@ import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; -import org.osgi.framework.BundleContext; /** * Connect to a remote repository and, if successful publish it as an OSGi @@ -62,37 +63,13 @@ public class AddRemoteRepository extends AbstractHandler implements JcrExplorerConstants, ArgeoNames { private RepositoryFactory repositoryFactory; - private BundleContext bundleContext; - private JcrKeyring keyring; public Object execute(ExecutionEvent event) throws ExecutionException { - String uri = null; - if (event.getParameters().containsKey(PARAM_REPOSITORY_URI)) { - // FIXME remove this - uri = event.getParameter(PARAM_REPOSITORY_URI); - if (uri == null) - return null; - - try { - Hashtable params = new Hashtable(); - params.put(ArgeoJcrConstants.JCR_REPOSITORY_URI, uri); - // by default we use the URI as alias - params.put(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS, uri); - Repository repository = repositoryFactory.getRepository(params); - bundleContext.registerService(Repository.class.getName(), - repository, params); - } catch (Exception e) { - ErrorFeedback.show("Cannot add remote repository " + uri, e); - } - } else { - RemoteRepositoryLoginDialog dlg = new RemoteRepositoryLoginDialog( - Display.getDefault().getActiveShell()); - if (dlg.open() == Dialog.OK) { - // uri = dlg.getUri(); - } + RemoteRepositoryLoginDialog dlg = new RemoteRepositoryLoginDialog( + Display.getDefault().getActiveShell()); + if (dlg.open() == Dialog.OK) { } - return null; } @@ -100,10 +77,6 @@ public class AddRemoteRepository extends AbstractHandler implements this.repositoryFactory = repositoryFactory; } - public void setBundleContext(BundleContext bundleContext) { - this.bundleContext = bundleContext; - } - public void setKeyring(JcrKeyring keyring) { this.keyring = keyring; } @@ -162,9 +135,6 @@ public class AddRemoteRepository extends AbstractHandler implements Hashtable params = new Hashtable(); params.put(ArgeoJcrConstants.JCR_REPOSITORY_URI, checkedUriStr); - // by default we use the URI as alias - params.put(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS, - checkedUriStr); Repository repository = repositoryFactory.getRepository(params); if (username.getText().trim().equals("")) {// anonymous session = repository.login(); @@ -190,11 +160,11 @@ public class AddRemoteRepository extends AbstractHandler implements protected void okPressed() { try { Session nodeSession = keyring.getSession(); - Node home = JcrUtils.getUserHome(nodeSession); + Node home = ArgeoJcrUtils.getUserHome(nodeSession); // FIXME better deal with non existing home dir if (home == null) - home = JcrUtils.createUserHomeIfNeeded(nodeSession, + home = SecurityJcrUtils.createUserHomeIfNeeded(nodeSession, nodeSession.getUserID()); Node remote = home.hasNode(ARGEO_REMOTE) ? home diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RepositoriesNode.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RepositoriesNode.java index 975c87cba..3289b420d 100644 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RepositoriesNode.java +++ b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RepositoriesNode.java @@ -29,8 +29,8 @@ import org.argeo.ArgeoException; import org.argeo.eclipse.ui.ErrorFeedback; import org.argeo.eclipse.ui.TreeParent; import org.argeo.jcr.ArgeoJcrConstants; +import org.argeo.jcr.ArgeoJcrUtils; import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.JcrUtils; import org.argeo.jcr.RepositoryRegister; import org.argeo.jcr.security.JcrKeyring; @@ -93,7 +93,7 @@ public class RepositoriesNode extends TreeParent implements ArgeoNames { protected void addRemoteRepositories(JcrKeyring jcrKeyring) throws RepositoryException { Session userSession = jcrKeyring.getSession(); - Node userHome = JcrUtils.getUserHome(userSession); + Node userHome = ArgeoJcrUtils.getUserHome(userSession); if (userHome != null && userHome.hasNode(ARGEO_REMOTE)) { NodeIterator it = userHome.getNode(ARGEO_REMOTE).getNodes(); while (it.hasNext()) { diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/JcrUiUtils.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/JcrUiUtils.java index af06ba220..e8c0cb7a2 100644 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/JcrUiUtils.java +++ b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/JcrUiUtils.java @@ -47,9 +47,11 @@ public class JcrUiUtils { doRefresh = true; else if (element instanceof RepositoryNode) { RepositoryNode rn = (RepositoryNode) element; - String[] wkpNames = rn.getAccessibleWorkspaceNames(); - if (element.getChildren().length != wkpNames.length) - doRefresh = true; + if (rn.isConnected()) { + String[] wkpNames = rn.getAccessibleWorkspaceNames(); + if (element.getChildren().length != wkpNames.length) + doRefresh = true; + } } else if (element instanceof RepositoriesNode) { RepositoriesNode rn = (RepositoriesNode) element; if (element.getChildren().length != rn.getRepositoryRegister() diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleSessionProvider.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleSessionProvider.java index 12315930b..54e12bd7d 100644 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleSessionProvider.java +++ b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleSessionProvider.java @@ -40,6 +40,7 @@ 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.ArgeoJcrUtils; import org.argeo.jcr.ArgeoNames; import org.argeo.jcr.JcrUtils; @@ -118,7 +119,7 @@ public class SimpleSessionProvider implements SessionProvider, Serializable { userGroupIds.add(it.next().getID()); // write roles if needed - Node userProfile = JcrUtils.getUserHome(session).getNode( + Node userProfile = ArgeoJcrUtils.getUserHome(session).getNode( ArgeoNames.ARGEO_PROFILE); boolean writeRoles = false; if (userProfile.hasProperty(ArgeoNames.ARGEO_REMOTE_ROLES)) { diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoJcrUtils.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoJcrUtils.java new file mode 100644 index 000000000..b0d775779 --- /dev/null +++ b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoJcrUtils.java @@ -0,0 +1,103 @@ +package org.argeo.jcr; + +import java.util.HashMap; +import java.util.Map; + +import javax.jcr.Node; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.RepositoryFactory; +import javax.jcr.Session; + +import org.argeo.ArgeoException; + +/** Utilities related to Argeo model in JCR */ +public class ArgeoJcrUtils implements ArgeoJcrConstants { + /** + * Returns the home node of the session user or null if none was found. + * + * @param session + * the session to use in order to perform the search, this can be + * a session with a different user ID than the one searched, + * typically when a system or admin session is used. + * @param username + * the username of the user + */ + public static Node getUserHome(Session session, String username) { + try { + String homePath = ArgeoJcrUtils.getUserHomePath(username); + return session.itemExists(homePath) ? session.getNode(homePath) + : null; + // kept for example of QOM queries + // QueryObjectModelFactory qomf = session.getWorkspace() + // .getQueryManager().getQOMFactory(); + // Selector userHomeSel = qomf.selector(ArgeoTypes.ARGEO_USER_HOME, + // "userHome"); + // DynamicOperand userIdDop = qomf.propertyValue("userHome", + // ArgeoNames.ARGEO_USER_ID); + // StaticOperand userIdSop = qomf.literal(session.getValueFactory() + // .createValue(username)); + // Constraint constraint = qomf.comparison(userIdDop, + // QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, userIdSop); + // Query query = qomf.createQuery(userHomeSel, constraint, null, + // null); + // Node userHome = JcrUtils.querySingleNode(query); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot find home for user " + username, e); + } + } + + /** Returns the home node of the session user or null if none was found. */ + public static Node getUserHome(Session session) { + String userID = session.getUserID(); + return getUserHome(session, userID); + } + + /** @deprecated Use {@link #getUserHome(Session, String)} directly */ + @Deprecated + public static String getUserHomePath(String username) { + String homeBasePath = DEFAULT_HOME_BASE_PATH; + return homeBasePath + '/' + JcrUtils.firstCharsToPath(username, 2) + + '/' + username; + } + + /** + * Wraps the call to the repository factory based on parameter + * {@link ArgeoJcrConstants#JCR_REPOSITORY_ALIAS} in order to simplify it + * and protect against future API changes. + */ + public static Repository getRepositoryByAlias( + RepositoryFactory repositoryFactory, String alias) { + try { + Map parameters = new HashMap(); + parameters.put(JCR_REPOSITORY_ALIAS, alias); + return repositoryFactory.getRepository(parameters); + } catch (RepositoryException e) { + throw new ArgeoException( + "Unexpected exception when trying to retrieve repository with alias " + + alias, e); + } + } + + /** + * Wraps the call to the repository factory based on parameter + * {@link ArgeoJcrConstants#JCR_REPOSITORY_URI} in order to simplify it and + * protect against future API changes. + */ + public static Repository getRepositoryByUri( + RepositoryFactory repositoryFactory, String uri) { + try { + Map parameters = new HashMap(); + parameters.put(JCR_REPOSITORY_URI, uri); + return repositoryFactory.getRepository(parameters); + } catch (RepositoryException e) { + throw new ArgeoException( + "Unexpected exception when trying to retrieve repository with uri " + + uri, e); + } + } + + private ArgeoJcrUtils() { + } + +} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java index e7b3656cf..3364ebfea 100644 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java +++ b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java @@ -31,7 +31,6 @@ import java.util.Calendar; import java.util.Collections; import java.util.Date; import java.util.GregorianCalendar; -import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -47,7 +46,6 @@ import javax.jcr.PropertyIterator; import javax.jcr.PropertyType; import javax.jcr.Repository; import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; import javax.jcr.Session; import javax.jcr.Value; import javax.jcr.Workspace; @@ -61,7 +59,6 @@ import javax.jcr.security.AccessControlManager; import javax.jcr.security.AccessControlPolicy; import javax.jcr.security.AccessControlPolicyIterator; import javax.jcr.security.Privilege; -import javax.jcr.version.VersionManager; import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; @@ -1046,42 +1043,6 @@ public class JcrUtils implements ArgeoJcrConstants { return path.toString(); } - /** - * Wraps the call to the repository factory based on parameter - * {@link ArgeoJcrConstants#JCR_REPOSITORY_ALIAS} in order to simplify it - * and protect against future API changes. - */ - public static Repository getRepositoryByAlias( - RepositoryFactory repositoryFactory, String alias) { - try { - Map parameters = new HashMap(); - parameters.put(JCR_REPOSITORY_ALIAS, alias); - return repositoryFactory.getRepository(parameters); - } catch (RepositoryException e) { - throw new ArgeoException( - "Unexpected exception when trying to retrieve repository with alias " - + alias, e); - } - } - - /** - * Wraps the call to the repository factory based on parameter - * {@link ArgeoJcrConstants#JCR_REPOSITORY_URI} in order to simplify it and - * protect against future API changes. - */ - public static Repository getRepositoryByUri( - RepositoryFactory repositoryFactory, String uri) { - try { - Map parameters = new HashMap(); - parameters.put(JCR_REPOSITORY_URI, uri); - return repositoryFactory.getRepository(parameters); - } catch (RepositoryException e) { - throw new ArgeoException( - "Unexpected exception when trying to retrieve repository with uri " - + uri, e); - } - } - /** * Discards the current changes in the session attached to this node. To be * used typically in a catch block. @@ -1176,235 +1137,6 @@ public class JcrUtils implements ArgeoJcrConstants { } } - /** Returns the home node of the session user or null if none was found. */ - public static Node getUserHome(Session session) { - String userID = session.getUserID(); - return getUserHome(session, userID); - } - - /** User home path is NOT configurable */ - public static String getUserHomePath(String username) { - String homeBasePath = DEFAULT_HOME_BASE_PATH; - return homeBasePath + '/' + firstCharsToPath(username, 2) + '/' - + username; - } - - /** - * Returns the home node of the session user or null if none was found. - * - * @param session - * the session to use in order to perform the search, this can be - * a session with a different user ID than the one searched, - * typically when a system or admin session is used. - * @param username - * the username of the user - */ - public static Node getUserHome(Session session, String username) { - try { - String homePath = getUserHomePath(username); - return session.itemExists(homePath) ? session.getNode(homePath) - : null; - // kept for example of QOM queries - // QueryObjectModelFactory qomf = session.getWorkspace() - // .getQueryManager().getQOMFactory(); - // Selector userHomeSel = qomf.selector(ArgeoTypes.ARGEO_USER_HOME, - // "userHome"); - // DynamicOperand userIdDop = qomf.propertyValue("userHome", - // ArgeoNames.ARGEO_USER_ID); - // StaticOperand userIdSop = qomf.literal(session.getValueFactory() - // .createValue(username)); - // Constraint constraint = qomf.comparison(userIdDop, - // QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, userIdSop); - // Query query = qomf.createQuery(userHomeSel, constraint, null, - // null); - // Node userHome = JcrUtils.querySingleNode(query); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot find home for user " + username, e); - } - } - - /** - * Creates an Argeo user home, does nothing if it already exists. Session is - * NOT saved. - */ - public static Node createUserHomeIfNeeded(Session session, String username) { - try { - String homePath = getUserHomePath(username); - if (session.itemExists(homePath)) - return session.getNode(homePath); - else { - Node userHome = JcrUtils.mkdirs(session, homePath); - userHome.addMixin(ArgeoTypes.ARGEO_USER_HOME); - userHome.setProperty(ArgeoNames.ARGEO_USER_ID, username); - return userHome; - } - } catch (RepositoryException e) { - discardQuietly(session); - throw new ArgeoException("Cannot create home for " + username - + " in workspace " + session.getWorkspace().getName(), e); - } - } - - /** - * Creates a user profile in the home of this user. Creates the home if - * needed, but throw an exception if a profile already exists. The session - * is not saved and the node is in a checkedOut state (that is, it requires - * a subsequent checkin after saving the session). - */ - public static Node createUserProfile(Session session, String username) { - try { - Node userHome = createUserHomeIfNeeded(session, username); - if (userHome.hasNode(ArgeoNames.ARGEO_PROFILE)) - throw new ArgeoException( - "There is already a user profile under " + userHome); - Node userProfile = userHome.addNode(ArgeoNames.ARGEO_PROFILE); - userProfile.addMixin(ArgeoTypes.ARGEO_USER_PROFILE); - userProfile.setProperty(ArgeoNames.ARGEO_USER_ID, username); - userProfile.setProperty(ArgeoNames.ARGEO_ENABLED, true); - userProfile.setProperty(ArgeoNames.ARGEO_ACCOUNT_NON_EXPIRED, true); - userProfile.setProperty(ArgeoNames.ARGEO_ACCOUNT_NON_LOCKED, true); - userProfile.setProperty(ArgeoNames.ARGEO_CREDENTIALS_NON_EXPIRED, - true); - return userProfile; - } catch (RepositoryException e) { - discardQuietly(session); - throw new ArgeoException("Cannot create user profile for " - + username + " in workspace " - + session.getWorkspace().getName(), e); - } - } - - /** - * Create user profile if needed, the session IS saved. - * - * @return the user profile - */ - public static Node createUserProfileIfNeeded(Session securitySession, - String username) { - try { - Node userHome = JcrUtils.createUserHomeIfNeeded(securitySession, - username); - Node userProfile = userHome.hasNode(ArgeoNames.ARGEO_PROFILE) ? userHome - .getNode(ArgeoNames.ARGEO_PROFILE) : JcrUtils - .createUserProfile(securitySession, username); - if (securitySession.hasPendingChanges()) - securitySession.save(); - VersionManager versionManager = securitySession.getWorkspace() - .getVersionManager(); - if (versionManager.isCheckedOut(userProfile.getPath())) - versionManager.checkin(userProfile.getPath()); - return userProfile; - } catch (RepositoryException e) { - discardQuietly(securitySession); - throw new ArgeoException("Cannot create user profile for " - + username + " in workspace " - + securitySession.getWorkspace().getName(), e); - } - } - - /** Creates an Argeo user home. */ - // public static Node createUserHome(Session session, String homeBasePath, - // String username) { - // try { - // if (session == null) - // throw new ArgeoException("Session is null"); - // if (session.hasPendingChanges()) - // throw new ArgeoException( - // "Session has pending changes, save them first"); - // - // String homePath = getUserHomePath(username); - // - // if (session.itemExists(homePath)) { - // try { - // throw new ArgeoException( - // "Trying to create a user home that already exists"); - // } catch (Exception e) { - // // we use this workaround to be sure to get the stack trace - // // to identify the sink of the bug. - // log.warn("trying to create an already existing userHome at path:" - // + homePath + ". Stack trace : "); - // e.printStackTrace(); - // } - // } - // - // Node userHome = JcrUtils.mkdirs(session, homePath); - // Node userProfile; - // if (userHome.hasNode(ArgeoNames.ARGEO_PROFILE)) { - // log.warn("userProfile node already exists for userHome path: " - // + homePath + ". We do not add a new one"); - // } 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); - // // see - // // - // http://jackrabbit.510166.n4.nabble.com/Jackrabbit-2-0-beta-6-Problem-adding-a-Mixin-type-with-mandatory-properties-after-setting-propertiesn-td1290332.html - // userHome.setProperty(ArgeoNames.ARGEO_USER_ID, username); - // session.save(); - // return userHome; - // } catch (RepositoryException e) { - // discardQuietly(session); - // throw new ArgeoException("Cannot create home node for user " - // + username, e); - // } - // } - - /** - * Returns user home has path, embedding exceptions. Contrary to - * {@link #getUserHome(Session)}, it never returns null but throws and - * exception if not found. - * - * @deprecated use getUserHome() instead, throwing an exception if it - * returns null - */ - @Deprecated - public static String getUserHomePath(Session session) { - String userID = session.getUserID(); - try { - String homePath = getUserHomePath(userID); - if (session.itemExists(homePath)) - return homePath; - else - throw new ArgeoException("No home registered for " + userID); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot find user home path", e); - } - } - - /** - * @return null if not found * - */ - public static Node getUserProfile(Session session, String username) { - try { - Node userHome = getUserHome(session, username); - if (userHome == null) - return null; - if (userHome.hasNode(ArgeoNames.ARGEO_PROFILE)) - return userHome.getNode(ArgeoNames.ARGEO_PROFILE); - else - return null; - } catch (RepositoryException e) { - throw new ArgeoException( - "Cannot find profile for user " + username, e); - } - } - - /** - * Get the profile of the user attached to this session. - */ - public static Node getUserProfile(Session session) { - String userID = session.getUserID(); - return getUserProfile(session, userID); - } - /** * Quietly unregisters an {@link EventListener} from the udnerlying * workspace of this node. diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/security/JcrKeyring.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/security/JcrKeyring.java index e10cccf60..91dd20201 100644 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/security/JcrKeyring.java +++ b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/security/JcrKeyring.java @@ -31,6 +31,7 @@ import javax.jcr.Session; import org.apache.commons.io.IOUtils; import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoJcrUtils; import org.argeo.jcr.ArgeoNames; import org.argeo.jcr.ArgeoTypes; import org.argeo.jcr.JcrUtils; @@ -62,7 +63,7 @@ public class JcrKeyring extends AbstractKeyring implements ArgeoNames { if (notYetSavedKeyring.get() != null) return true; - Node userHome = JcrUtils.getUserHome(session); + Node userHome = ArgeoJcrUtils.getUserHome(session); return userHome.hasNode(ARGEO_KEYRING); } catch (RepositoryException e) { throw new ArgeoException("Cannot check whether keyring is setup", e); @@ -74,7 +75,7 @@ public class JcrKeyring extends AbstractKeyring implements ArgeoNames { Binary binary = null; InputStream in = null; try { - Node userHome = JcrUtils.getUserHome(session); + Node userHome = ArgeoJcrUtils.getUserHome(session); if (userHome.hasNode(ARGEO_KEYRING)) throw new ArgeoException("Keyring already setup"); Node keyring = userHome.addNode(ARGEO_KEYRING); @@ -125,7 +126,7 @@ public class JcrKeyring extends AbstractKeyring implements ArgeoNames { @Override protected void handleKeySpecCallback(PBEKeySpecCallback pbeCallback) { try { - Node userHome = JcrUtils.getUserHome(session); + Node userHome = ArgeoJcrUtils.getUserHome(session); Node keyring; if (userHome.hasNode(ARGEO_KEYRING)) keyring = userHome.getNode(ARGEO_KEYRING); @@ -249,7 +250,7 @@ public class JcrKeyring extends AbstractKeyring implements ArgeoNames { protected Cipher createCipher() { try { - Node userHome = JcrUtils.getUserHome(session); + Node userHome = ArgeoJcrUtils.getUserHome(session); if (!userHome.hasNode(ARGEO_KEYRING)) throw new ArgeoException("Keyring not setup"); Node keyring = userHome.getNode(ARGEO_KEYRING); diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/security/SecurityJcrUtils.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/security/SecurityJcrUtils.java new file mode 100644 index 000000000..abf4347db --- /dev/null +++ b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/security/SecurityJcrUtils.java @@ -0,0 +1,123 @@ +package org.argeo.jcr.security; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.version.VersionManager; + +import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoJcrConstants; +import org.argeo.jcr.ArgeoJcrUtils; +import org.argeo.jcr.ArgeoNames; +import org.argeo.jcr.ArgeoTypes; +import org.argeo.jcr.JcrUtils; + +/** Utilities related to Argeo security model in JCR */ +public class SecurityJcrUtils implements ArgeoJcrConstants { + /** + * Creates an Argeo user home, does nothing if it already exists. Session is + * NOT saved. + */ + public static Node createUserHomeIfNeeded(Session session, String username) { + try { + String homePath = generateUserHomePath(username); + if (session.itemExists(homePath)) + return session.getNode(homePath); + else { + Node userHome = JcrUtils.mkdirs(session, homePath); + userHome.addMixin(ArgeoTypes.ARGEO_USER_HOME); + userHome.setProperty(ArgeoNames.ARGEO_USER_ID, username); + + //JcrUtils.addPrivilege(session, homePath, username, "jcr:all"); + return userHome; + } + } catch (RepositoryException e) { + JcrUtils.discardQuietly(session); + throw new ArgeoException("Cannot create home for " + username + + " in workspace " + session.getWorkspace().getName(), e); + } + } + + private static String generateUserHomePath(String username) { + String homeBasePath = DEFAULT_HOME_BASE_PATH; + return homeBasePath + '/' + JcrUtils.firstCharsToPath(username, 2) + + '/' + username; + } + + /** + * Creates a user profile in the home of this user. Creates the home if + * needed, but throw an exception if a profile already exists. The session + * is not saved and the node is in a checkedOut state (that is, it requires + * a subsequent checkin after saving the session). + */ + public static Node createUserProfile(Session session, String username) { + try { + Node userHome = createUserHomeIfNeeded(session, username); + if (userHome.hasNode(ArgeoNames.ARGEO_PROFILE)) + throw new ArgeoException( + "There is already a user profile under " + userHome); + Node userProfile = userHome.addNode(ArgeoNames.ARGEO_PROFILE); + userProfile.addMixin(ArgeoTypes.ARGEO_USER_PROFILE); + userProfile.setProperty(ArgeoNames.ARGEO_USER_ID, username); + userProfile.setProperty(ArgeoNames.ARGEO_ENABLED, true); + userProfile.setProperty(ArgeoNames.ARGEO_ACCOUNT_NON_EXPIRED, true); + userProfile.setProperty(ArgeoNames.ARGEO_ACCOUNT_NON_LOCKED, true); + userProfile.setProperty(ArgeoNames.ARGEO_CREDENTIALS_NON_EXPIRED, + true); + return userProfile; + } catch (RepositoryException e) { + JcrUtils.discardQuietly(session); + throw new ArgeoException("Cannot create user profile for " + + username + " in workspace " + + session.getWorkspace().getName(), e); + } + } + + /** + * Create user profile if needed, the session IS saved. + * + * @return the user profile + */ + public static Node createUserProfileIfNeeded(Session securitySession, + String username) { + try { + Node userHome = createUserHomeIfNeeded(securitySession, username); + Node userProfile = userHome.hasNode(ArgeoNames.ARGEO_PROFILE) ? userHome + .getNode(ArgeoNames.ARGEO_PROFILE) : createUserProfile( + securitySession, username); + if (securitySession.hasPendingChanges()) + securitySession.save(); + VersionManager versionManager = securitySession.getWorkspace() + .getVersionManager(); + if (versionManager.isCheckedOut(userProfile.getPath())) + versionManager.checkin(userProfile.getPath()); + return userProfile; + } catch (RepositoryException e) { + JcrUtils.discardQuietly(securitySession); + throw new ArgeoException("Cannot create user profile for " + + username + " in workspace " + + securitySession.getWorkspace().getName(), e); + } + } + + /** + * @return null if not found * + */ + public static Node getUserProfile(Session session, String username) { + try { + Node userHome = ArgeoJcrUtils.getUserHome(session, username); + if (userHome == null) + return null; + if (userHome.hasNode(ArgeoNames.ARGEO_PROFILE)) + return userHome.getNode(ArgeoNames.ARGEO_PROFILE); + else + return null; + } catch (RepositoryException e) { + throw new ArgeoException( + "Cannot find profile for user " + username, e); + } + } + + private SecurityJcrUtils() { + } +} -- 2.30.2