X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=jcr%2Forg.argeo.cms.jcr%2Fsrc%2Forg%2Fargeo%2Fcms%2Fjcr%2FCmsJcrUtils.java;fp=jcr%2Forg.argeo.cms.jcr%2Fsrc%2Forg%2Fargeo%2Fcms%2Fjcr%2FCmsJcrUtils.java;h=b5d9adfcaedbef28390945b1458c191a922b9588;hb=8282011b0e20e80704b209ad55fa9fb132e16280;hp=0000000000000000000000000000000000000000;hpb=633a8acd189cc22f06944d278879601189be1bc8;p=lgpl%2Fargeo-commons.git diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/CmsJcrUtils.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/CmsJcrUtils.java new file mode 100644 index 000000000..b5d9adfca --- /dev/null +++ b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/CmsJcrUtils.java @@ -0,0 +1,276 @@ +package org.argeo.cms.jcr; + +import java.security.PrivilegedAction; +import java.util.HashMap; +import java.util.Map; + +import javax.jcr.NoSuchWorkspaceException; +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.RepositoryFactory; +import javax.jcr.Session; +import javax.naming.InvalidNameException; +import javax.naming.ldap.LdapName; +import javax.security.auth.AuthPermission; +import javax.security.auth.Subject; +import javax.security.auth.login.LoginContext; +import javax.security.auth.login.LoginException; + +import org.argeo.api.cms.CmsAuth; +import org.argeo.api.cms.CmsConstants; + +/** Utilities related to Argeo model in JCR */ +public class CmsJcrUtils { + /** + * Wraps the call to the repository factory based on parameter + * {@link CmsConstants#CN} 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(CmsConstants.CN, alias); + return repositoryFactory.getRepository(parameters); + } catch (RepositoryException e) { + throw new RuntimeException("Unexpected exception when trying to retrieve repository with alias " + alias, + e); + } + } + + /** + * Wraps the call to the repository factory based on parameter + * {@link CmsConstants#LABELED_URI} in order to simplify it and protect against + * future API changes. + */ + public static Repository getRepositoryByUri(RepositoryFactory repositoryFactory, String uri) { + return getRepositoryByUri(repositoryFactory, uri, null); + } + + /** + * Wraps the call to the repository factory based on parameter + * {@link CmsConstants#LABELED_URI} in order to simplify it and protect against + * future API changes. + */ + public static Repository getRepositoryByUri(RepositoryFactory repositoryFactory, String uri, String alias) { + try { + Map parameters = new HashMap(); + parameters.put(CmsConstants.LABELED_URI, uri); + if (alias != null) + parameters.put(CmsConstants.CN, alias); + return repositoryFactory.getRepository(parameters); + } catch (RepositoryException e) { + throw new RuntimeException("Unexpected exception when trying to retrieve repository with uri " + uri, e); + } + } + + /** + * Returns the home node of the 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 { +// QueryObjectModelFactory qomf = session.getWorkspace().getQueryManager().getQOMFactory(); +// Selector sel = qomf.selector(NodeTypes.NODE_USER_HOME, "sel"); +// DynamicOperand dop = qomf.propertyValue(sel.getSelectorName(), NodeNames.LDAP_UID); +// StaticOperand sop = qomf.literal(session.getValueFactory().createValue(username)); +// Constraint constraint = qomf.comparison(dop, QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, sop); +// Query query = qomf.createQuery(sel, constraint, null, null); +// return querySingleNode(query); +// } catch (RepositoryException e) { +// throw new RuntimeException("Cannot find home for user " + username, e); +// } + + try { + checkUserWorkspace(session, username); + String homePath = getHomePath(username); + if (session.itemExists(homePath)) + return session.getNode(homePath); + // legacy + homePath = "/home/" + username; + if (session.itemExists(homePath)) + return session.getNode(homePath); + return null; + } catch (RepositoryException e) { + throw new RuntimeException("Cannot find home for user " + username, e); + } + } + + private static String getHomePath(String username) { + LdapName dn; + try { + dn = new LdapName(username); + } catch (InvalidNameException e) { + throw new IllegalArgumentException("Invalid name " + username, e); + } + String userId = dn.getRdn(dn.size() - 1).getValue().toString(); + return '/' + userId; + } + + private static void checkUserWorkspace(Session session, String username) { + String workspaceName = session.getWorkspace().getName(); + if (!CmsConstants.HOME_WORKSPACE.equals(workspaceName)) + throw new IllegalArgumentException(workspaceName + " is not the home workspace for user " + username); + } + + /** + * Returns the home node of the 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 groupname the name of the group + */ + public static Node getGroupHome(Session session, String groupname) { +// try { +// QueryObjectModelFactory qomf = session.getWorkspace().getQueryManager().getQOMFactory(); +// Selector sel = qomf.selector(NodeTypes.NODE_GROUP_HOME, "sel"); +// DynamicOperand dop = qomf.propertyValue(sel.getSelectorName(), NodeNames.LDAP_CN); +// StaticOperand sop = qomf.literal(session.getValueFactory().createValue(cn)); +// Constraint constraint = qomf.comparison(dop, QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, sop); +// Query query = qomf.createQuery(sel, constraint, null, null); +// return querySingleNode(query); +// } catch (RepositoryException e) { +// throw new RuntimeException("Cannot find home for group " + cn, e); +// } + + try { + checkGroupWorkspace(session, groupname); + String homePath = getGroupPath(groupname); + if (session.itemExists(homePath)) + return session.getNode(homePath); + // legacy + homePath = "/groups/" + groupname; + if (session.itemExists(homePath)) + return session.getNode(homePath); + return null; + } catch (RepositoryException e) { + throw new RuntimeException("Cannot find home for group " + groupname, e); + } + + } + + private static String getGroupPath(String groupname) { + String cn; + try { + LdapName dn = new LdapName(groupname); + cn = dn.getRdn(dn.size() - 1).getValue().toString(); + } catch (InvalidNameException e) { + cn = groupname; + } + return '/' + cn; + } + + private static void checkGroupWorkspace(Session session, String groupname) { + String workspaceName = session.getWorkspace().getName(); + if (!CmsConstants.SRV_WORKSPACE.equals(workspaceName)) + throw new IllegalArgumentException(workspaceName + " is not the group workspace for group " + groupname); + } + + /** + * Queries one single node. + * + * @return one single node or null if none was found + * @throws ArgeoJcrException if more than one node was found + */ +// private static Node querySingleNode(Query query) { +// NodeIterator nodeIterator; +// try { +// QueryResult queryResult = query.execute(); +// nodeIterator = queryResult.getNodes(); +// } catch (RepositoryException e) { +// throw new RuntimeException("Cannot execute query " + query, e); +// } +// Node node; +// if (nodeIterator.hasNext()) +// node = nodeIterator.nextNode(); +// else +// return null; +// +// if (nodeIterator.hasNext()) +// throw new RuntimeException("Query returned more than one node."); +// return node; +// } + + /** 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); + } + + /** Whether this node is the home of the user of the underlying session. */ + public static boolean isUserHome(Node node) { + try { + String userID = node.getSession().getUserID(); + return node.hasProperty(Property.JCR_ID) && node.getProperty(Property.JCR_ID).getString().equals(userID); + } catch (RepositoryException e) { + throw new IllegalStateException(e); + } + } + + /** + * Translate the path to this node into a path containing the name of the + * repository and the name of the workspace. + */ + public static String getDataPath(String cn, Node node) { + assert node != null; + StringBuilder buf = new StringBuilder(CmsConstants.PATH_DATA); + try { + return buf.append('/').append(cn).append('/').append(node.getSession().getWorkspace().getName()) + .append(node.getPath()).toString(); + } catch (RepositoryException e) { + throw new IllegalStateException("Cannot get data path for " + node + " in repository " + cn, e); + } + } + + /** + * Translate the path to this node into a path containing the name of the + * repository and the name of the workspace. + */ + public static String getDataPath(Node node) { + return getDataPath(CmsConstants.NODE, node); + } + + /** + * Open a JCR session with full read/write rights on the data, as + * {@link CmsConstants#ROLE_USER_ADMIN}, using the + * {@link CmsAuth#LOGIN_CONTEXT_DATA_ADMIN} login context. For security + * hardened deployement, use {@link AuthPermission} on this login context. + */ + public static Session openDataAdminSession(Repository repository, String workspaceName) { + ClassLoader currentCl = Thread.currentThread().getContextClassLoader(); + LoginContext loginContext; + try { + loginContext = new LoginContext(CmsAuth.LOGIN_CONTEXT_DATA_ADMIN); + loginContext.login(); + } catch (LoginException e1) { + throw new RuntimeException("Could not login as data admin", e1); + } finally { + Thread.currentThread().setContextClassLoader(currentCl); + } + return Subject.doAs(loginContext.getSubject(), new PrivilegedAction() { + + @Override + public Session run() { + try { + return repository.login(workspaceName); + } catch (NoSuchWorkspaceException e) { + throw new IllegalArgumentException("No workspace " + workspaceName + " available", e); + } catch (RepositoryException e) { + throw new RuntimeException("Cannot open data admin session", e); + } + } + + }); + } + + /** Singleton. */ + private CmsJcrUtils() { + } + +}