public void setUserRoles(
      Session session, final ITenant theTenant, final String userName, final String[] roles)
      throws RepositoryException, NotFoundException {
    if (hasAdminRole(getUserRoles(theTenant, userName)) && (roles.length == 0)) {
      throw new RepositoryException(
          Messages.getInstance()
              .getString("AbstractJcrBackedUserRoleDao.ERROR_0005_LAST_ADMIN_USER", userName));
    }

    Set<String> roleSet = new HashSet<String>();
    if (roles != null) {
      roleSet.addAll(Arrays.asList(roles));
    }
    roleSet.add(authenticatedRoleName);

    User jackrabbitUser = getJackrabbitUser(theTenant, userName, session);

    if ((jackrabbitUser == null)
        || !TenantUtils.isAccessibleTenant(
            theTenant == null
                ? tenantedUserNameUtils.getTenant(jackrabbitUser.getID())
                : theTenant)) {
      throw new NotFoundException(
          Messages.getInstance()
              .getString("AbstractJcrBackedUserRoleDao.ERROR_0003_USER_NOT_FOUND"));
    }
    HashMap<String, Group> currentlyAssignedGroups = new HashMap<String, Group>();
    Iterator<Group> currentGroups = jackrabbitUser.memberOf();
    while (currentGroups.hasNext()) {
      Group currentGroup = currentGroups.next();
      currentlyAssignedGroups.put(currentGroup.getID(), currentGroup);
    }

    HashMap<String, Group> finalCollectionOfAssignedGroups = new HashMap<String, Group>();
    ITenant tenant = theTenant == null ? JcrTenantUtils.getTenant(userName, true) : theTenant;
    for (String role : roleSet) {
      Group jackrabbitGroup = getJackrabbitGroup(tenant, role, session);
      if (jackrabbitGroup != null) {
        finalCollectionOfAssignedGroups.put(
            tenantedRoleNameUtils.getPrincipleId(tenant, role), jackrabbitGroup);
      }
    }

    ArrayList<String> groupsToRemove = new ArrayList<String>(currentlyAssignedGroups.keySet());
    groupsToRemove.removeAll(finalCollectionOfAssignedGroups.keySet());

    ArrayList<String> groupsToAdd = new ArrayList<String>(finalCollectionOfAssignedGroups.keySet());
    groupsToAdd.removeAll(currentlyAssignedGroups.keySet());

    for (String groupId : groupsToRemove) {
      currentlyAssignedGroups.get(groupId).removeMember(jackrabbitUser);
    }

    for (String groupId : groupsToAdd) {
      finalCollectionOfAssignedGroups.get(groupId).addMember(jackrabbitUser);
    }

    // Purge the UserDetails cache
    purgeUserFromCache(userName);
  }
 @Override
 protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response)
     throws ServletException, IOException {
   String paramUser = request.getParameter(SiteService.SiteEvent.USER);
   logger.info("Request to add user " + paramUser);
   String paramGroup = "";
   try {
     Node requestedNode = request.getResource().adaptTo(Node.class);
     Value[] authorizables = requestedNode.getProperty("sakai:authorizables").getValues();
     paramGroup = authorizables[1].getString();
     request.setAttribute(JoinRequestConstants.PARAM_SITENODE, requestedNode);
     Session session = slingRepository.loginAdministrative(null);
     UserManager userManager = AccessControlUtil.getUserManager(session);
     Authorizable userAuth = userManager.getAuthorizable(paramUser);
     Group groupAuth = (Group) userManager.getAuthorizable(paramGroup);
     if (siteJoinIsAuthorized(request)) {
       groupAuth.addMember(userAuth);
       logger.info(paramUser + " added as member of group " + paramGroup);
     } else {
       response.sendError(403, "Not authorized to add member to site.");
     }
     if (session.hasPendingChanges()) {
       session.save();
     }
   } catch (Exception e) {
     response.sendError(500, e.getMessage());
   }
 }
  /**
   * KERN-1026 changed the results of this to be the authz's that are members of the managers group
   * associated to a group rather than the group managers associated to the group.
   *
   * <p><del>Get the managers for a group. These should be stored in the {@link
   * UserConstants#PROP_GROUP_MANAGERS}.</del>
   *
   * @param request
   * @param group
   * @param writer
   * @throws RepositoryException
   * @throws JSONException
   */
  protected TreeMap<String, Authorizable> getManagers(
      SlingHttpServletRequest request, Group group, Comparator<String> comparator)
      throws RepositoryException, JSONException {
    TreeMap<String, Authorizable> map = new TreeMap<String, Authorizable>(comparator);

    // KERN-949 will probably change this.
    // note above was made before this was changed to retrieving members of the managers
    // group and may not apply.
    Session session = request.getResourceResolver().adaptTo(Session.class);
    UserManager um = AccessControlUtil.getUserManager(session);
    Value[] managersGroup = group.getProperty(UserConstants.PROP_MANAGERS_GROUP);
    if (managersGroup != null && managersGroup.length == 1) {
      String mgrGroupName = managersGroup[0].getString();

      Group mgrGroup = (Group) um.getAuthorizable(mgrGroupName);

      Iterator<Authorizable> members = mgrGroup.getMembers();
      while (members.hasNext()) {
        Authorizable member = members.next();
        String prinName = member.getPrincipal().getName();
        Authorizable mau = um.getAuthorizable(prinName);
        String name = getName(mau);
        map.put(name, mau);
      }
    }
    return map;
  }
 public IPentahoRole getRole(Session session, final ITenant tenant, final String name)
     throws RepositoryException {
   Group jackrabbitGroup = getJackrabbitGroup(tenant, name, session);
   return jackrabbitGroup != null
           && TenantUtils.isAccessibleTenant(
               tenant == null ? tenantedRoleNameUtils.getTenant(jackrabbitGroup.getID()) : tenant)
       ? convertToPentahoRole(jackrabbitGroup)
       : null;
 }
 public void deleteRole(Session session, final IPentahoRole role)
     throws NotFoundException, RepositoryException {
   if (canDeleteRole(session, role)) {
     Group jackrabbitGroup = getJackrabbitGroup(role.getTenant(), role.getName(), session);
     if (jackrabbitGroup != null
         && TenantUtils.isAccessibleTenant(
             tenantedRoleNameUtils.getTenant(jackrabbitGroup.getID()))) {
       jackrabbitGroup.remove();
     } else {
       throw new NotFoundException(""); // $NON-NLS-1$
     }
   } else {
     throw new RepositoryException(
         Messages.getInstance()
             .getString("AbstractJcrBackedUserRoleDao.ERROR_0007_ATTEMPTED_SYSTEM_ROLE_DELETE"));
   }
 }
 @Override
 protected TreeMap<String, Group> getGroups(Authorizable member, UserManager userManager)
     throws RepositoryException {
   TreeMap<String, Group> managedGroups = new TreeMap<String, Group>();
   Iterator<Group> allGroupsIter = member.memberOf();
   while (allGroupsIter.hasNext()) {
     Group group = allGroupsIter.next();
     if (group.hasProperty(UserConstants.PROP_MANAGED_GROUP)) {
       Value[] values = group.getProperty(UserConstants.PROP_MANAGED_GROUP);
       if ((values != null) && (values.length == 1)) {
         String managedGroupId = values[0].getString();
         Group managedGroup = (Group) userManager.getAuthorizable(managedGroupId);
         managedGroups.put(managedGroupId, managedGroup);
       }
     }
   }
   return managedGroups;
 }
  private IPentahoRole convertToPentahoRole(Group jackrabbitGroup) throws RepositoryException {
    IPentahoRole role = null;
    Value[] propertyValues = null;

    String description = null;
    try {
      propertyValues = jackrabbitGroup.getProperty("description"); // $NON-NLS-1$
      description = propertyValues.length > 0 ? propertyValues[0].getString() : null;
    } catch (Exception ex) {
    }

    role =
        new PentahoRole(
            tenantedRoleNameUtils.getTenant(jackrabbitGroup.getID()),
            tenantedRoleNameUtils.getPrincipleName(jackrabbitGroup.getID()),
            description);
    return role;
  }
 public List<IPentahoUser> getRoleMembers(
     Session session, final ITenant theTenant, final String roleName) throws RepositoryException {
   List<IPentahoUser> users = new ArrayList<IPentahoUser>();
   Group jackrabbitGroup = getJackrabbitGroup(theTenant, roleName, session);
   if ((jackrabbitGroup != null)
       && TenantUtils.isAccessibleTenant(
           theTenant == null
               ? tenantedRoleNameUtils.getTenant(jackrabbitGroup.getID())
               : theTenant)) {
     Iterator<Authorizable> authorizables = jackrabbitGroup.getMembers();
     while (authorizables.hasNext()) {
       Authorizable authorizable = authorizables.next();
       if (authorizable instanceof User) {
         users.add(convertToPentahoUser((User) authorizable));
       }
     }
   }
   return users;
 }
 public void setRoleDescription(
     Session session, final ITenant theTenant, final String roleName, final String description)
     throws NotFoundException, RepositoryException {
   Group jackrabbitGroup = getJackrabbitGroup(theTenant, roleName, session);
   if (jackrabbitGroup != null
       && TenantUtils.isAccessibleTenant(
           theTenant == null
               ? tenantedRoleNameUtils.getTenant(jackrabbitGroup.getID())
               : theTenant)) {
     if (description == null) {
       jackrabbitGroup.removeProperty("description"); // $NON-NLS-1$
     } else {
       jackrabbitGroup.setProperty(
           "description", session.getValueFactory().createValue(description)); // $NON-NLS-1$
     }
   } else {
     throw new NotFoundException(
         Messages.getInstance()
             .getString("AbstractJcrBackedUserRoleDao.ERROR_0002_ROLE_NOT_FOUND"));
   }
 }
  @Test
  public void testGetEmailAddrs_Group() throws Exception {

    // mock group and users
    String groupPath = "/home/users/g/group";
    List<Authorizable> groupMembers = new ArrayList<Authorizable>();

    Authorizable user1 = mock(Authorizable.class);
    Authorizable user2 = mock(Authorizable.class);

    when(user1.hasProperty(PN_EMAIL)).thenReturn(true);
    when(user1.getProperty(PN_EMAIL))
        .thenReturn(new MockValue[] {new MockValue("*****@*****.**")});

    when(user2.hasProperty(PN_EMAIL)).thenReturn(true);
    when(user2.getProperty(PN_EMAIL))
        .thenReturn(new MockValue[] {new MockValue("*****@*****.**")});

    groupMembers.add(user1);
    groupMembers.add(user2);

    ResourceResolver resolver = mock(ResourceResolver.class);
    Resource groupRes = mock(Resource.class);
    Authorizable groupAuth = mock(Authorizable.class);
    Group userGroup = mock(Group.class);

    when(resolver.getResource(groupPath)).thenReturn(groupRes);
    when(groupRes.adaptTo(Authorizable.class)).thenReturn(groupAuth);

    when(groupAuth.isGroup()).thenReturn(true);
    when(groupRes.adaptTo(Group.class)).thenReturn(userGroup);
    when(userGroup.getMembers()).thenReturn(groupMembers.iterator());

    String[] emails = SendTemplatedEmailUtils.getEmailAddrsFromUserPath(resolver, groupPath);
    assertEquals(2, emails.length);
    assertEquals("*****@*****.**", emails[0]);
    assertEquals("*****@*****.**", emails[1]);
  }
  /**
   * @param request
   * @param group
   * @param writer
   * @throws RepositoryException
   * @throws JSONException
   */
  protected TreeMap<String, Authorizable> getMembers(
      SlingHttpServletRequest request, Group group, Comparator<String> comparator)
      throws RepositoryException, JSONException {
    TreeMap<String, Authorizable> map = new TreeMap<String, Authorizable>(comparator);

    // Only the direct members are required.
    // If we would do group.getMembers() that would also retrieve all the indirect ones.
    Iterator<Authorizable> members = group.getDeclaredMembers();
    while (members.hasNext()) {
      Authorizable member = members.next();
      String name = getName(member);
      map.put(name, member);
    }
    return map;
  }
  public void setRoleMembers(
      Session session,
      final ITenant theTenant,
      final String roleName,
      final String[] memberUserNames)
      throws RepositoryException, NotFoundException {
    List<IPentahoUser> currentRoleMembers = getRoleMembers(session, theTenant, roleName);
    if (tenantAdminRoleName.equals(roleName)
        && (currentRoleMembers != null && currentRoleMembers.size() > 0)
        && memberUserNames.length == 0) {
      throw new RepositoryException(
          Messages.getInstance()
              .getString(
                  "AbstractJcrBackedUserRoleDao.ERROR_0001_LAST_ADMIN_ROLE", tenantAdminRoleName));
    }
    Group jackrabbitGroup = getJackrabbitGroup(theTenant, roleName, session);

    if ((jackrabbitGroup == null)
        || !TenantUtils.isAccessibleTenant(
            theTenant == null
                ? tenantedRoleNameUtils.getTenant(jackrabbitGroup.getID())
                : theTenant)) {
      throw new NotFoundException(
          Messages.getInstance()
              .getString("AbstractJcrBackedUserRoleDao.ERROR_0002_ROLE_NOT_FOUND"));
    }
    HashMap<String, User> currentlyAssignedUsers = new HashMap<String, User>();
    Iterator<Authorizable> currentMembers = jackrabbitGroup.getMembers();
    while (currentMembers.hasNext()) {
      Authorizable member = currentMembers.next();
      if (member instanceof User) {
        currentlyAssignedUsers.put(member.getID(), (User) member);
      }
    }

    HashMap<String, User> finalCollectionOfAssignedUsers = new HashMap<String, User>();
    if (memberUserNames != null) {
      ITenant tenant = theTenant == null ? JcrTenantUtils.getTenant(roleName, false) : theTenant;
      for (String user : memberUserNames) {
        User jackrabbitUser = getJackrabbitUser(tenant, user, session);
        if (jackrabbitUser != null) {
          finalCollectionOfAssignedUsers.put(
              tenantedRoleNameUtils.getPrincipleId(tenant, user), jackrabbitUser);
        }
      }
    }

    ArrayList<String> usersToRemove = new ArrayList<String>(currentlyAssignedUsers.keySet());
    usersToRemove.removeAll(finalCollectionOfAssignedUsers.keySet());

    ArrayList<String> usersToAdd = new ArrayList<String>(finalCollectionOfAssignedUsers.keySet());
    usersToAdd.removeAll(currentlyAssignedUsers.keySet());

    for (String userId : usersToRemove) {
      jackrabbitGroup.removeMember(currentlyAssignedUsers.get(userId));
    }

    for (String userId : usersToAdd) {
      jackrabbitGroup.addMember(finalCollectionOfAssignedUsers.get(userId));

      // Purge the UserDetails cache
      purgeUserFromCache(userId);
    }
  }
  /*
   * (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);
    }
  }