@Transactional
  @Override
  public net.sourceforge.guacamole.net.auth.User get(String identifier) throws GuacamoleException {

    // Get user
    MySQLUser user = userService.retrieveUser(identifier);

    // Verify access is granted
    permissionCheckService.verifyUserAccess(
        this.user_id, user.getUserID(), MySQLConstants.USER_READ);

    // Return user
    return userService.retrieveUser(identifier);
  }
  @Override
  @Transactional
  public void update(net.sourceforge.guacamole.net.auth.User object) throws GuacamoleException {

    // If user not actually from this auth provider, we can't handle updated
    // permissions.
    if (!(object instanceof MySQLUser)) throw new GuacamoleException("User not from database.");

    MySQLUser mySQLUser = (MySQLUser) object;

    // Validate permission to update this user is granted
    permissionCheckService.verifyUserAccess(
        this.user_id, mySQLUser.getUserID(), MySQLConstants.USER_UPDATE);

    // Update the user in the database
    userService.updateUser(mySQLUser);

    // Update permissions in database
    createPermissions(mySQLUser.getUserID(), mySQLUser.getNewPermissions());
    removePermissions(mySQLUser.getUserID(), mySQLUser.getRemovedPermissions());

    // The appropriate permissions have been inserted and deleted, so
    // reset the new and removed permission sets.
    mySQLUser.resetPermissions();
  }
  @Override
  @Transactional
  public void remove(String identifier) throws GuacamoleException {

    // Get user pending deletion
    MySQLUser user = userService.retrieveUser(identifier);

    // Prevent self-deletion
    if (user.getUserID() == this.user_id)
      throw new GuacamoleClientException("Deleting your own user is not allowed.");

    // Validate current user has permission to remove the specified user
    permissionCheckService.verifyUserAccess(
        this.user_id, user.getUserID(), MySQLConstants.USER_DELETE);

    // Delete specified user
    userService.deleteUser(user.getUserID());
  }
  @Override
  @Transactional
  public void add(net.sourceforge.guacamole.net.auth.User object) throws GuacamoleException {

    String username = object.getUsername().trim();
    if (username.isEmpty()) throw new GuacamoleClientException("The username cannot be blank.");

    // Verify current user has permission to create users
    permissionCheckService.verifySystemAccess(this.user_id, MySQLConstants.SYSTEM_USER_CREATE);
    Preconditions.checkNotNull(object);

    // Verify that no user already exists with this username.
    MySQLUser previousUser = userService.retrieveUser(username);
    if (previousUser != null)
      throw new GuacamoleClientException("That username is already in use.");

    // Create new user
    MySQLUser user = userService.createUser(username, object.getPassword());

    // Create permissions of new user in database
    createPermissions(user.getUserID(), object.getPermissions());

    // Give the current user full access to the newly created user.
    UserPermissionKey newUserPermission = new UserPermissionKey();
    newUserPermission.setUser_id(this.user_id);
    newUserPermission.setAffected_user_id(user.getUserID());

    // READ permission on new user
    newUserPermission.setPermission(MySQLConstants.USER_READ);
    userPermissionDAO.insert(newUserPermission);

    // UPDATE permission on new user
    newUserPermission.setPermission(MySQLConstants.USER_UPDATE);
    userPermissionDAO.insert(newUserPermission);

    // DELETE permission on new user
    newUserPermission.setPermission(MySQLConstants.USER_DELETE);
    userPermissionDAO.insert(newUserPermission);

    // ADMINISTER permission on new user
    newUserPermission.setPermission(MySQLConstants.USER_ADMINISTER);
    userPermissionDAO.insert(newUserPermission);
  }
  /**
   * Delete permissions having to do with users for a given user.
   *
   * @param user_id The ID of the user to change the permissions of.
   * @param permissions The permissions the given user should no longer have when this operation
   *     completes.
   * @throws GuacamoleException If permission to alter the access permissions of affected objects is
   *     denied.
   */
  private void deleteUserPermissions(int user_id, Collection<UserPermission> permissions)
      throws GuacamoleException {

    // If no permissions given, stop now
    if (permissions.isEmpty()) return;

    // Get list of administerable user IDs
    List<Integer> administerableUserIDs =
        permissionCheckService.retrieveUserIDs(this.user_id, MySQLConstants.USER_ADMINISTER);

    // Get set of usernames corresponding to administerable users
    Map<String, Integer> administerableUsers =
        userService.translateUsernames(administerableUserIDs);

    // Delete requested permissions
    for (UserPermission permission : permissions) {

      // Get original ID
      Integer affected_id = administerableUsers.get(permission.getObjectIdentifier());

      // Verify that the user actually has permission to administrate
      // every one of these users
      if (affected_id == null)
        throw new GuacamoleSecurityException(
            "User #"
                + this.user_id
                + " does not have permission to administrate user "
                + permission.getObjectIdentifier());

      // Delete requested permission
      UserPermissionExample userPermissionExample = new UserPermissionExample();
      userPermissionExample
          .createCriteria()
          .andUser_idEqualTo(user_id)
          .andPermissionEqualTo(MySQLConstants.getUserConstant(permission.getType()))
          .andAffected_user_idEqualTo(affected_id);
      userPermissionDAO.deleteByExample(userPermissionExample);
    }
  }