gt:         if (!loggedInUser.hasRole(RoleFactory.ORG_ADMIN)) {
context: /**
   * Copyright (c) 2009--2014 Red Hat, Inc.
   *
   * This software is licensed to you under the GNU General Public License,
   * version 2 (GPLv2). There is NO WARRANTY for this software, express or
   * implied, including the implied warranties of MERCHANTABILITY or FITNESS
   * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
   * along with this software; if not, see
   * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
   *
   * Red Hat trademarks are not licensed under GPLv2. No permission is
   * granted to use or replicate Red Hat trademarks that are incorporated
   * in this software or its documentation.
   */
  package com.redhat.rhn.manager.user;
  
  import java.sql.Types;
  import java.util.Collections;
  import java.util.Date;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.LinkedHashSet;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  
  import javax.security.auth.login.LoginException;
  
  import org.apache.log4j.Logger;
  
  import com.redhat.rhn.common.db.datasource.CallableMode;
  import com.redhat.rhn.common.db.datasource.DataResult;
  import com.redhat.rhn.common.db.datasource.ModeFactory;
  import com.redhat.rhn.common.db.datasource.SelectMode;
  import com.redhat.rhn.common.db.datasource.WriteMode;
  import com.redhat.rhn.common.hibernate.LookupException;
  import com.redhat.rhn.common.localization.LocalizationService;
  import com.redhat.rhn.common.security.PermissionException;
  import com.redhat.rhn.common.security.user.StateChangeException;
  import com.redhat.rhn.domain.channel.Channel;
  import com.redhat.rhn.domain.common.SatConfigFactory;
  import com.redhat.rhn.domain.org.Org;
  import com.redhat.rhn.domain.org.OrgFactory;
  import com.redhat.rhn.domain.role.Role;
  import com.redhat.rhn.domain.role.RoleFactory;
  import com.redhat.rhn.domain.server.ManagedServerGroup;
  import com.redhat.rhn.domain.server.Server;
  import com.redhat.rhn.domain.server.ServerGroup;
  import com.redhat.rhn.domain.user.Address;
  import com.redhat.rhn.domain.user.RhnTimeZone;
  import com.redhat.rhn.domain.user.User;
  import com.redhat.rhn.domain.user.UserFactory;
  import com.redhat.rhn.domain.user.UserServerPreference;
  import com.redhat.rhn.frontend.dto.SystemGroupOverview;
  import com.redhat.rhn.frontend.dto.SystemSearchResult;
  import com.redhat.rhn.frontend.dto.UserOverview;
  import com.redhat.rhn.frontend.listview.PageControl;
  import com.redhat.rhn.frontend.taglibs.list.decorators.PageSizeDecorator;
  import com.redhat.rhn.manager.BaseManager;
  import com.redhat.rhn.manager.SatManager;
  import com.redhat.rhn.manager.system.ServerGroupManager;
  
  /**
   * UserManager - the singleton class used to provide Business Operations
   * on Users where those operations interact with other top tier Business Objects.
   *
   * Operations that require the User make changes to
   * @version $Rev: 903 $
   */
  public class UserManager extends BaseManager {
  
      private static Logger log = Logger.getLogger(UserManager.class);
      private static final String ORG_ADMIN_LABEL = "org_admin";
  
      private UserManager() {
      }
  
      /**
       * Returns a list of roles that are assignable by a given user
       * i.e. the list of roles that the passed in user can assign
       * @param user the user for whom the check is being done
       * @return the list of roles assignable by this user.
       */
      public static Set<Role> listRolesAssignableBy(User user) {
          Set <Role> assignable = new LinkedHashSet<Role>();
          if (user.hasRole(RoleFactory.SAT_ADMIN)) {
              assignable.add(RoleFactory.SAT_ADMIN);
          }
          if (user.hasRole(RoleFactory.ORG_ADMIN)) {
              assignable.add(RoleFactory.ORG_ADMIN);
              assignable.addAll(UserFactory.IMPLIEDROLES);
          }
          return assignable;
      }
      /**
       * Verifies that a given org has access to a given package.
       * @param org The org in question
       * @param packageId The id of the package in question
       * @return Returns true if the org has access to the package, false otherwise.
       */
      public static boolean verifyPackageAccess(Org org, Long packageId) {
          SelectMode m = ModeFactory.getMode("Package_queries", "package_available_to_user");
          Map<String, Object> params = new HashMap<String, Object>();
          params.put("pid", packageId);
          params.put("org_id", org.getId());
          DataResult dr = m.execute(params);
  
          /*
           * Ok... this query will result in returning a single row containing '1' if the
           * org has access to this channel. If the org *does not* have access to the given
           * package (org the package doesn't exist), nothing will be returned from the query
           * and we will end up with an empty DataResult object.
           */
          return (!dr.isEmpty());
      }
  
      /**
       * Verifies that the passed in user has admin over the passed in channel.
       * @param user The user to check.
       * @param channel The channel to check.
       * @return Returns true if the user has admin access to this channel, false otherwise.
       */
      public static boolean verifyChannelAdmin(User user, Channel channel) {
         return verifyChannelRole(user.getId(), channel, "manage");
      }
  
      /**
       * Verifies that the passed in user id has admin over the passed in channel.
       * @param userId The user id to check.
       * @param channel The channel to check.
       * @return Returns true if the user id has admin access to this channel
       */
      public static boolean verifyChannelAdmin(Long userId, Channel channel) {
         return verifyChannelRole(userId, channel, "manage");
      }
  
      /**
       * Verifies that the passed in user has subscribe access to passed in channel.
       * @param user The user to check.
       * @param channel The channel to check.
       * @return Returns true if the user has subscribe access to this channel,
       *     false otherwise.
       */
      public static boolean verifyChannelSubscribable(User user, Channel channel) {
          return verifyChannelRole(user.getId(), channel, "subscribe");
      }
  
      private static boolean verifyChannelRole(Long userId, Channel channel, String role) {
          CallableMode m = ModeFactory.getCallableMode(
                  "Channel_queries", "verify_channel_role");
  
          Map inParams = new HashMap();
          inParams.put("cid", channel.getId());
          inParams.put("user_id", userId);
          inParams.put("role", role);
  
          Map outParams = new HashMap();
          outParams.put("result", new Integer(Types.VARCHAR));
          Map result = m.execute(inParams, outParams);
  
          return result.get("result") == null;
      }
  
  
  
  
  
      /**
       * Enables a user.
       * @param enabledBy The user doing the enabling
       * @param userToEnable The user to enable
       */
      public static void enableUser(User enabledBy, User userToEnable) {
          //Make sure both users are in the same org
          if (!userToEnable.getOrg().equals(enabledBy.getOrg())) {
              throw new StateChangeException("userenable.error.sameorg");
          }
  
          //Make sure user we're trying to enable is disabled
          if (!userToEnable.isDisabled()) {
              return;
          }
  
          //Make sure enabledBy is an OrgAdmin
          if (!enabledBy.hasRole(RoleFactory.ORG_ADMIN)) {
              throw new StateChangeException("userenable.error.orgadmin");
          }
  
          //If we make it here everything must be ok
          UserFactory.getInstance().enable(userToEnable, enabledBy);
      }
  
      /**
       * Disables userToDisable.
       * @param disabledBy The user doing the disabling
       * @param userToDisable The user to disable
       */
      public static void disableUser(User disabledBy, User userToDisable) {
          //Are both users in same org?
          if (!userToDisable.getOrg().equals(disabledBy.getOrg())) {
              throw new StateChangeException("userdisable.error.sameorg");
          }
  
          //Make sure user we're trying to disable is currently enabled
          if (userToDisable.isDisabled()) {
              return;
          }
          if (!userToDisable.isReadOnly()) {
              if (userToDisable.hasRole(RoleFactory.ORG_ADMIN) &&
                  userToDisable.getOrg().numActiveOrgAdmins() < 2) {
  
                  // Is user is the last active orgadmin in org on a satellite?
                  // bugzilla: 173542 removed org admin restriction for hosted.
                  throw new StateChangeException("userdisable.error.onlyuser");
              }
          }
  
          //If not deleting self, make sure userToDisable is a normal user and
          //disabledBy is an org admin
          if (!userToDisable.equals(disabledBy)) {
              //Normal users can't disable other users
              if (!disabledBy.hasRole(RoleFactory.ORG_ADMIN)) {
                  throw new StateChangeException("userdisable.error.otheruser");
              }
  
              //Can't disable other org admins
              if (userToDisable.hasRole(RoleFactory.ORG_ADMIN)) {
                  throw new StateChangeException("userdisable.error.orgadmin");
              }
          }
  
          //If we get here things must be ok :)
          UserFactory.getInstance().disable(userToDisable, disabledBy);
      }
  
      /**
       * Revokes permission from the given User to the ServerGroup whose id is sgid.
       * @param uid Id of user who no longer needs permission
       * @param sgid ServerGroup ID
       */
      public static void revokeServerGroupPermission(final Long uid,
              final long sgid) {
          SelectMode sm = ModeFactory.getMode("User_queries",
                  "check_server_group_permissions_for_revoke");
          CallableMode m = ModeFactory.getCallableMode("User_queries",
                  "remove_server_group_permissions");
  
          Map<String, Object> params = new HashMap<String, Object>();
          params.put("user_id", uid);
          params.put("server_group_id", new Long(sgid));
  
          DataResult dr = sm.execute(params);
          for (Iterator itr = dr.iterator(); itr.hasNext();) {
              Map row = (Map)itr.next();
              long ruid = ((Long)row.get("user_id")).longValue();
              if (ruid == uid.longValue()) {
                  m.execute(params, new HashMap());
              }
          }
      }
  
      /**
       * Revokes permission from the given User to the ServerGroup whose id is sgid.
       * @param usr User who no longer needs permission
       * @param sgid ServerGroup ID
       */
      public static void revokeServerGroupPermission(final User usr,
              final long sgid) {
          revokeServerGroupPermission(usr.getId(), sgid);
      }
  
      /**
       * Grants the given User permission to the ServerGroup whose id is sgid.
       * @param uid Id of user who needs permission
       * @param sgid ServerGroup ID
       */
      public static void grantServerGroupPermission(final Long uid,
              final long sgid) {
          SelectMode sm = ModeFactory.getMode("User_queries",
                  "check_server_group_permissions");
          CallableMode m = ModeFactory.getCallableMode("User_queries",
                  "set_server_group_permissions");
  
          Map<String, Object> params = new HashMap<String, Object>();
          params.put("user_id", uid);
          params.put("server_group_id", new Long(sgid));
  
          DataResult dr = sm.execute(params);
          if (dr.size() > 0) {
              m.execute(params, new HashMap());
          }
      }
  
      /**
       * Grants the given User permission to the ServerGroup whose id is sgid.
       * @param usr User who needs permission
       * @param sgid ServerGroup ID
       */
      public static void grantServerGroupPermission(final User usr,
              final long sgid) {
          grantServerGroupPermission(usr.getId(), sgid);
      }
  
      /**
      * Add and remove the specified roles from the user.
      *
      * @param usr The User who's Roles you want to update
      * @param rolesToAdd List of role labels to add.
      * @param rolesToRemove List of role labels to remove.
      */
      public static void addRemoveUserRoles(User usr, List<String> rolesToAdd,
              List<String> rolesToRemove) {
  
          log.debug("UserManager.updateUserRolesFromRoleLabels()");
  
          if (!usr.isReadOnly()) {
              // Make sure last org admin isn't trying to remove his own org admin role:
              if (rolesToRemove.contains(ORG_ADMIN_LABEL)) {
                  if (usr.getOrg().numActiveOrgAdmins() <= 1) {
                      LocalizationService ls = LocalizationService.getInstance();
                      PermissionException pex = new PermissionException("Last org admin");
                      pex.setLocalizedTitle(ls.getMessage("permission.jsp.title.removerole"));
                      pex.setLocalizedSummary(
                              ls.getMessage("permission.jsp.summary.removerole",
                              ls.getMessage(ORG_ADMIN_LABEL)));
                      throw pex;
                  }
              }
          }
  
          // ORG admin role needs to be added last so that others don't get skipped
          if (rolesToAdd.remove(ORG_ADMIN_LABEL)) {
              rolesToAdd.add(ORG_ADMIN_LABEL);
          }
  
          for (String removeLabel : rolesToRemove) {
              Role removeMe = RoleFactory.lookupByLabel(removeLabel);
              log.debug("Removing role: " + removeMe.getName());
              usr.removePermanentRole(removeMe);
          }
  
          for (String addLabel : rolesToAdd) {
              Role r = RoleFactory.lookupByLabel(addLabel);
              log.debug("Adding role: " + r.getName());
              usr.addPermanentRole(r);
          }
      }
  
      /**
       * Create brand new personal user using the information found in the
       * User object.
       * @param user Filled out user to create.
       * @param org Org to associate with the user.
       * @param addr Address to associate with the user.
       * @return User Freshly created user.
       */
      public static User createUser(User user, Org org, Address addr) {
          /*
           * Ok, this is a bloody ugly hack, but since the pl/sql used by
           * UserFactory.saveNewUser() is shared and the use pam authentication seems to be
           * the only thing affected by it, we are going to work around it here.
           *
           * The Create_New_User function in the db creates an entry in rhnUserInfo with the
           * default values. This means that anything stored in User.personalInfo gets
           * reset. We need to be able to update the use_pam_authentication column in this
           * table, so save the value, save the user, then set the attribute back to what it
           * was before we called UserManager.createUser(). This will ensure that what was
           * selected on the form is what gets stored with the user (since hibernate will
           * then be taking care of the db values).
           *
           * We really need to a) divorce ourselves from www and oracle apps b) get rid of the
           * application/business logic stored in pl/sql functions in the db and c) clean up
           * the dirty hacks like this that are throughout our code. We shouldn't have to work
           * around the db in our code.
           */
          boolean usePam = user.getUsePamAuthentication(); //save what we got from the form
          org = OrgFactory.save(org);
  
          user = UserFactory.saveNewUser(user, addr, org.getId());
  
          user.setUsePamAuthentication(usePam); //set it back
  
          //Set default page size also :)
          user.setPageSize(PageSizeDecorator.getDefaultPageSize());
          storeUser(user); //save the user via hibernate
  
          return user;
      }
  
      /**
       * Get the set of default system groups for this user
       * @param usr User for which to get the default system groups.
       * @return groupSet Set of default system groups IDs for the user.
       */
      public static Set getDefaultSystemGroupIds(User usr) {
          SelectMode prefixMode = ModeFactory.getMode("User_queries",
                                                      "default_system_groups");
  
          Map<String, Object> params = new HashMap<String, Object>();
          params.put("user_id", usr.getId());
          DataResult dr = prefixMode.execute(params);
  
          Set groupSet = new HashSet();
          Iterator i = dr.iterator();
          while (i.hasNext()) {
              Map row = (Map)i.next();
              groupSet.add(row.get("system_group_id"));
          }
          return groupSet;
      }
  
      /**
       * Set the defaultSystemGroups for the specified User.  This method first
       * deletes all current groups and then adds all of the specified groups.
       * The assumption is that we never add a lot of default system groups at
       * one time, so it is cheaper to just delete and re-add than to compute
       * the difference and commit just the changes.
       * @param usr User for which to set the default groups.
       * @param groups Set of groups to associate with the user.
       */
      public static void setDefaultSystemGroupIds(final User usr, final Set groups) {
          WriteMode m = ModeFactory.getWriteMode("User_queries",
                  "delete_all_system_groups_for_user");
          Map<String, Object> params = new HashMap<String, Object>();
          params.put("user_id", usr.getId());
          m.executeUpdate(params);
  
          m = ModeFactory.getWriteMode("User_queries", "set_system_group");
          Iterator i = groups.iterator();
          while (i.hasNext()) {
              Long sgid = (Long)i.next();
              params.put("sgid", sgid);
              m.executeUpdate(params);
          }
      }
  
      private static User performLoginActions(User user) {
          user.setLastLoggedIn(new Date());
          if (!SatConfigFactory.getSatConfigBooleanValue(
                  SatConfigFactory.EXT_AUTH_KEEP_ROLES)) {
              // delete all temporary roles
              UserManager.resetTemporaryRoles(user, new HashSet<Role>());
          }
          // need to disable OAI_SYNC during login
          storeUser(user);
          return user;
      }
  
  
      /**
       * Login the user with the given username and password.
       * @param username User's login name
       * @param password User's unencrypted password.
       * @return Returns the user if login is successful, or null othewise.
       * @throws LoginException if login fails.  The message is a string resource key.
       */
      public static User loginUser(String username, String password) throws LoginException {
          String exceptionType = null;
          try {
              User user = UserFactory.lookupByLogin(username);
              if (!user.authenticate(password)) {
                  exceptionType = "error.invalid_login";
              }
              else if (user.isDisabled()) {
                  exceptionType = "account.disabled";
              }
              else if (user.isReadOnly()) { // KEEP LAST!!
                  exceptionType = "error.user_readonly";
              }
              else {
                  return performLoginActions(user);
              }
          }
          catch (LookupException le) {
              exceptionType = "error.invalid_login";
          }
          // invalid login/password; set timeout to baffle
          // brute force password guessing attacks (BZ 672163)
          try {
              Thread.sleep(2000);
          }
          catch (InterruptedException ie) {
              log.warn("Failed to set timeout: " + ie.getMessage());
          }
          throw new LoginException(exceptionType);
      }
  
      /**
       * This method should be ONLY called when we need to authenticate read-only user
       * e.g. for purpose of the API calls
       * Login the user with the given username and password.
       * @param username User's login name
       * @param password User's unencrypted password.
       * @return Returns the user if login is successful, or null othewise.
       * @throws LoginException if login fails.  The message is a string resource key.
       */
      public static User loginReadOnlyUser(String username,
              String password) throws LoginException {
          try {
              loginUser(username, password);
          }
          catch (LoginException e) {
              // if exception type is error.user_readonly everything else went well
              // and we can safely log the read-only user
              if (!e.getMessage().equals("error.user_readonly")) {
                  throw e;
              }
          }
          User user = UserFactory.lookupByLogin(username);
          user.authenticate(password);
          return performLoginActions(user);
      }
  
      /**
       * Updates the Users to the database
       * @param user User to store.
       */
      public static void storeUser(User user) {
          UserFactory.save(user);
      }
  
  
      /**
       * Deletes a User
       * @param loggedInUser The user doing the deleting
       * @param targetUid The id for the user we're deleting
       */
      public static void deleteUser(User loggedInUser, Long targetUid) {
  