示例#1
0
  /**
   * Set-up minimal permissions for the workspace:
   *
   * <ul>
   *   <li>'adminstrators' principal -> all privileges
   *   <li>'everyone' -> read privilege
   * </ul>
   *
   * @param session to the workspace to set-up initial ACL to
   * @param editor for the specified session.
   * @throws RepositoryException If an error occurs.
   */
  private static void initRootACL(SessionImpl session, AccessControlEditor editor)
      throws RepositoryException {
    try {
      log.debug("Install initial ACL:...");
      String rootPath = session.getRootNode().getPath();
      AccessControlPolicy[] acls = editor.editAccessControlPolicies(rootPath);
      if (acls.length > 0) {
        ACLTemplate acl = (ACLTemplate) acls[0];

        PrincipalManager pMgr = session.getPrincipalManager();
        AccessControlManager acMgr = session.getAccessControlManager();

        String pName = SecurityConstants.ADMINISTRATORS_NAME;
        if (pMgr.hasPrincipal(pName)) {
          Principal administrators = pMgr.getPrincipal(pName);
          log.debug("... Privilege.ALL for administrators.");
          Privilege[] privs = new Privilege[] {acMgr.privilegeFromName(Privilege.JCR_ALL)};
          acl.addAccessControlEntry(administrators, privs);
        } else {
          log.info(
              "Administrators principal group is missing -> omitting initialization of default permissions.");
        }

        Principal everyone = pMgr.getEveryone();
        log.debug("... Privilege.READ for everyone.");
        Privilege[] privs = new Privilege[] {acMgr.privilegeFromName(Privilege.JCR_READ)};
        acl.addAccessControlEntry(everyone, privs);

        editor.setPolicy(rootPath, acl);
        session.save();
      } else {
        log.info(
            "No applicable ACL available for the root node -> skip initialization of the root node's ACL.");
      }
    } catch (RepositoryException e) {
      log.error(
          "Failed to set-up minimal access control for root node of workspace "
              + session.getWorkspace().getName());
      session.getRootNode().refresh(false);
    }
  }
  private Resource resolveMappedResource(ResourceResolver resourceResolver, String path)
      throws RepositoryException {
    String poolId = null;

    if (path.startsWith("/p/")) {
      poolId = path.substring("/p/".length());
    } else if (path.length() == 2) {
      try {
        poolId = generatePoolId();
        // we also need to create the node.
        Session adminSession = null;

        Session userSession = resourceResolver.adaptTo(Session.class);
        try {
          adminSession = slingRepository.loginAdministrative(null);

          String userId = userSession.getUserID();
          PrincipalManager principalManager = AccessControlUtil.getPrincipalManager(userSession);
          Principal userPrincipal = principalManager.getPrincipal(userId);

          Node node = JcrUtils.deepGetOrCreateNode(adminSession, hash(poolId));
          // make the node inherit the repository defaults for content, but admin for the user.

          String nodePath = node.getPath();
          AccessControlUtil.replaceAccessControlEntry(
              adminSession, nodePath, userPrincipal, new String[] {JCR_ALL}, null, null, null);

          // set some properties to make it possible to locate this pool file without having to use
          // the path.
          node.setProperty("sakai:pool-file", "1");
          node.setProperty("sakai:pool-file-owner", userId);

          // save so the resolver further down will find this file.
          if (adminSession.hasPendingChanges()) {
            adminSession.save();
          }
        } finally {
          adminSession.logout();
        }
      } catch (Exception e) {
        throw new RepositoryException("Unable to generate new pool ID " + e.getMessage(), e);
      }
    }
    if (poolId != null && poolId.length() > 0) {
      int i = poolId.indexOf('/');
      if (i > 0) {
        poolId = poolId.substring(0, i);
      }
      i = poolId.indexOf('.');
      String selectors = "";
      if (i > 0) {
        selectors = poolId.substring(i);
        poolId = poolId.substring(0, i);
      }
      if (LOGGER.isInfoEnabled()) {
        LOGGER.info("Pool ID is [{}]", poolId);
      }
      String poolPath = null;
      try {
        poolPath = hash(poolId) + selectors;
      } catch (Exception e) {
        throw new RepositoryException("Unable to hash pool ID " + e.getMessage(), e);
      }
      Resource r = resourceResolver.resolve(poolPath);
      if (r instanceof NonExistingResource) {
        LOGGER.info("Pool ID does not exist, reject and dont allow creation on POST {} ", poolPath);
        throw new SlingException(
            "Resources may not be created at /p by the user",
            new AccessDeniedException("Cant create user specified pool resoruce"));
      }
      LOGGER.info("Resolving [{}] to [{}] ", poolPath, r);
      if (r != null) {
        // are the last elements the same ?
        if (getLastElement(r.getPath()).equals("/" + poolId)) {
          r.getResourceMetadata().put(CONTENT_RESOURCE_PROVIDER, this);
          return r;
        } else {
          if (LOGGER.isInfoEnabled()) {
            LOGGER.info("Rejected [{}] != [{}] ", getLastElement(r.getPath()), "/" + poolId);
          }
        }
      }
    }
    return null;
  }
  /*
   * (non-Javadoc)
   *
   * @seeorg.apache.sling.jackrabbit.usermanager.post.AbstractAuthorizablePostServlet#
   * handleOperation(org.apache.sling.api.SlingHttpServletRequest,
   * org.apache.sling.api.servlets.HtmlResponse, java.util.List)
   */
  @Override
  @edu.umd.cs.findbugs.annotations.SuppressWarnings(
      justification = "If there is an exception, the user is certainly not admin",
      value = {"REC_CATCH_EXCEPTION"})
  protected void handleOperation(
      SlingHttpServletRequest request, HtmlResponse response, List<Modification> changes)
      throws RepositoryException {

    // KERN-432 dont allow anon users to access create group.
    if (SecurityConstants.ANONYMOUS_ID.equals(request.getRemoteUser())) {
      response.setStatus(403, "AccessDenied");
    }

    // check that the submitted parameter values have valid values.
    final String principalName = request.getParameter(SlingPostConstants.RP_NODE_NAME);
    if (principalName == null) {
      throw new RepositoryException("Group name was not submitted");
    }

    NameSanitizer san = new NameSanitizer(principalName, false);
    san.validate();

    // check for allow create Group
    boolean allowCreateGroup = false;
    User currentUser = null;

    try {
      Session currentSession = request.getResourceResolver().adaptTo(Session.class);
      UserManager um = AccessControlUtil.getUserManager(currentSession);
      currentUser = (User) um.getAuthorizable(currentSession.getUserID());
      if (currentUser.isAdmin()) {
        LOGGER.debug("User is an admin ");
        allowCreateGroup = true;
      } else {
        LOGGER.debug("Checking for membership of one of {} ", Arrays.toString(authorizedGroups));
        PrincipalManager principalManager = AccessControlUtil.getPrincipalManager(currentSession);
        PrincipalIterator pi =
            principalManager.getGroupMembership(
                principalManager.getPrincipal(currentSession.getUserID()));
        Set<String> groups = new HashSet<String>();
        for (; pi.hasNext(); ) {
          groups.add(pi.nextPrincipal().getName());
        }

        for (String groupName : authorizedGroups) {
          if (groups.contains(groupName)) {
            allowCreateGroup = true;
            break;
          }

          // TODO: move this nasty hack into the PrincipalManager dynamic groups need to
          // be in the principal manager for this to work.
          if ("authenticated".equals(groupName)
              && !SecurityConstants.ADMIN_ID.equals(currentUser.getID())) {
            allowCreateGroup = true;
            break;
          }

          // just check via the user manager for dynamic resolution.
          Group group = (Group) um.getAuthorizable(groupName);
          LOGGER.debug("Checking for group  {} {} ", groupName, group);
          if (group != null && group.isMember(currentUser)) {
            allowCreateGroup = true;
            LOGGER.debug("User is a member  of {} {} ", groupName, group);
            break;
          }
        }
      }
    } catch (Exception ex) {
      LOGGER.warn(
          "Failed to determin if the user is an admin, assuming not. Cause: " + ex.getMessage());
      allowCreateGroup = false;
    }

    if (!allowCreateGroup) {
      LOGGER.debug("User is not allowed to create groups ");
      response.setStatus(HttpServletResponse.SC_FORBIDDEN, "User is not allowed to create groups");
      return;
    }

    Session session = getSession();

    try {
      UserManager userManager = AccessControlUtil.getUserManager(session);
      Authorizable authorizable = userManager.getAuthorizable(principalName);

      if (authorizable != null) {
        // principal already exists!
        throw new RepositoryException(
            "A principal already exists with the requested name: " + principalName);
      } else {

        Group group =
            userManager.createGroup(
                new Principal() {
                  public String getName() {
                    return principalName;
                  }
                });
        String groupPath =
            AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PREFIX + group.getID();
        Map<String, RequestProperty> reqProperties = collectContent(request, response, groupPath);

        response.setPath(groupPath);
        response.setLocation(externalizePath(request, groupPath));
        response.setParentLocation(
            externalizePath(request, AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PATH));
        changes.add(Modification.onCreated(groupPath));

        // It is not allowed to touch the rep:group-managers property directly.
        String key = SYSTEM_USER_MANAGER_GROUP_PREFIX + principalName + "/";
        reqProperties.remove(key + PROP_GROUP_MANAGERS);
        reqProperties.remove(key + PROP_GROUP_VIEWERS);

        // write content from form
        writeContent(session, group, reqProperties, changes);

        // update the group memberships, although this uses session from the request, it
        // only
        // does so for finding authorizables, so its ok that we are using an admin session
        // here.
        updateGroupMembership(request, group, changes);
        updateOwnership(request, group, new String[] {currentUser.getID()}, changes);

        sakaiAuthorizableService.postprocess(group, session);

        // Launch an OSGi event for creating a group.
        try {
          Dictionary<String, String> properties = new Hashtable<String, String>();
          properties.put(UserConstants.EVENT_PROP_USERID, principalName);
          EventUtils.sendOsgiEvent(properties, UserConstants.TOPIC_GROUP_CREATED, eventAdmin);
        } catch (Exception e) {
          // Trap all exception so we don't disrupt the normal behaviour.
          LOGGER.error("Failed to launch an OSGi event for creating a user.", e);
        }
      }
    } catch (RepositoryException re) {
      throw new RepositoryException("Failed to create new group.", re);
    } finally {
      ungetSession(session);
    }
  }