You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ra...@apache.org on 2018/05/02 12:19:12 UTC

[cloudstack] branch master updated: [CLOUDSTACK-5235] ask users current password when they are executing a password update (#2574)

This is an automated email from the ASF dual-hosted git repository.

rafael pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/master by this push:
     new 3adc2b8  [CLOUDSTACK-5235] ask users current password when they are executing a password update (#2574)
3adc2b8 is described below

commit 3adc2b8485d8a56634a3d4c54074321431bf2fda
Author: Rafael Weingärtner <ra...@gmail.com>
AuthorDate: Wed May 2 09:19:06 2018 -0300

    [CLOUDSTACK-5235] ask users current password when they are executing a password update (#2574)
    
    * [CLOUDSTACK-5235] Force users to enter old password when updating password
    
    * Formatting for checkstyle
    
    * Remove an unused import in AccountManagerImpl
    
    * Apply Nitin's suggestions
    
    * Change 'oldPassword' to 'currentPassword'
    
    * Second review of Resmo
    
    * Fix typos found by Nitin
---
 .../main/java/com/cloud/user/AccountService.java   |  45 +-
 .../org/apache/cloudstack/api/ApiConstants.java    |   4 +-
 .../api/command/admin/user/UpdateUserCmd.java      |  30 +-
 .../contrail/management/MockAccountManager.java    |   7 -
 .../cloudstack/api/command/LdapImportUsersCmd.java |  52 +-
 .../main/java/com/cloud/user/AccountManager.java   |  90 +--
 .../java/com/cloud/user/AccountManagerImpl.java    | 444 ++++++++------
 .../com/cloud/user/AccountManagerImplTest.java     | 676 ++++++++++++++++++---
 .../AccountManagerImplVolumeDeleteEventTest.java   |  56 +-
 .../com/cloud/user/AccountManagetImplTestBase.java |  48 +-
 .../com/cloud/user/MockAccountManagerImpl.java     |   7 -
 .../java/com/cloud/user/MockDomainManagerImpl.java | 164 -----
 ui/l10n/ar.js                                      |   1 +
 ui/l10n/ca.js                                      |   1 +
 ui/l10n/de_DE.js                                   |   1 +
 ui/l10n/en.js                                      |   1 +
 ui/l10n/es.js                                      |   1 +
 ui/l10n/fr_FR.js                                   |   1 +
 ui/l10n/hu.js                                      |   1 +
 ui/l10n/it_IT.js                                   |   1 +
 ui/l10n/ja_JP.js                                   |   1 +
 ui/l10n/ko_KR.js                                   |   1 +
 ui/l10n/nb_NO.js                                   |   1 +
 ui/l10n/nl_NL.js                                   |   1 +
 ui/l10n/pl.js                                      |   1 +
 ui/l10n/pt_BR.js                                   |   1 +
 ui/l10n/ru_RU.js                                   |   1 +
 ui/l10n/zh_CN.js                                   |   1 +
 ui/scripts/accounts.js                             |  15 +-
 29 files changed, 998 insertions(+), 656 deletions(-)

diff --git a/api/src/main/java/com/cloud/user/AccountService.java b/api/src/main/java/com/cloud/user/AccountService.java
index 9683d9f..060861d 100644
--- a/api/src/main/java/com/cloud/user/AccountService.java
+++ b/api/src/main/java/com/cloud/user/AccountService.java
@@ -23,53 +23,28 @@ import org.apache.cloudstack.acl.RoleType;
 import org.apache.cloudstack.acl.SecurityChecker.AccessType;
 import org.apache.cloudstack.api.command.admin.user.GetUserKeysCmd;
 import org.apache.cloudstack.api.command.admin.user.RegisterCmd;
+import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd;
 
 import com.cloud.domain.Domain;
 import com.cloud.exception.PermissionDeniedException;
 import com.cloud.offering.DiskOffering;
 import com.cloud.offering.ServiceOffering;
 
-
 public interface AccountService {
 
     /**
      * Creates a new user and account, stores the password as is so encrypted passwords are recommended.
-     *
-     * @param userName
-     *            TODO
-     * @param password
-     *            TODO
-     * @param firstName
-     *            TODO
-     * @param lastName
-     *            TODO
-     * @param email
-     *            TODO
-     * @param timezone
-     *            TODO
-     * @param accountName
-     *            TODO
-     * @param accountType
-     *            TODO
-     * @param domainId
-     *            TODO
-     * @param networkDomain
-     *            TODO
-     *
      * @return the user if created successfully, null otherwise
      */
-    UserAccount createUserAccount(String userName, String password, String firstName, String lastName, String email, String timezone, String accountName,
-        short accountType, Long roleId, Long domainId, String networkDomain, Map<String, String> details, String accountUUID, String userUUID);
+    UserAccount createUserAccount(String userName, String password, String firstName, String lastName, String email, String timezone, String accountName, short accountType, Long roleId, Long domainId,
+            String networkDomain, Map<String, String> details, String accountUUID, String userUUID);
 
-    UserAccount createUserAccount(String userName, String password, String firstName, String lastName, String email, String timezone, String accountName, short accountType, Long roleId, Long domainId, String networkDomain,
-                                  Map<String, String> details, String accountUUID, String userUUID, User.Source source);
+    UserAccount createUserAccount(String userName, String password, String firstName, String lastName, String email, String timezone, String accountName, short accountType, Long roleId, Long domainId,
+            String networkDomain, Map<String, String> details, String accountUUID, String userUUID, User.Source source);
 
     /**
      * Locks a user by userId. A locked user cannot access the API, but will still have running VMs/IP addresses
      * allocated/etc.
-     *
-     * @param userId
-     * @return UserAccount object
      */
     UserAccount lockUser(long userId);
 
@@ -79,8 +54,7 @@ public interface AccountService {
 
     User createUser(String userName, String password, String firstName, String lastName, String email, String timeZone, String accountName, Long domainId, String userUUID);
 
-    User createUser(String userName, String password, String firstName, String lastName, String email, String timeZone, String accountName, Long domainId, String userUUID,
-                    User.Source source);
+    User createUser(String userName, String password, String firstName, String lastName, String email, String timeZone, String accountName, Long domainId, String userUUID, User.Source source);
 
     boolean isAdmin(Long accountId);
 
@@ -90,7 +64,7 @@ public interface AccountService {
 
     UserAccount getActiveUserAccount(String username, Long domainId);
 
-    UserAccount updateUser(Long userId, String firstName, String lastName, String email, String userName, String password, String apiKey, String secretKey, String timeZone);
+    UserAccount updateUser(UpdateUserCmd updateUserCmd);
 
     Account getActiveAccountById(long accountId);
 
@@ -128,15 +102,14 @@ public interface AccountService {
 
     void checkAccess(User user, ControlledEntity entity);
 
-    void checkAccess(Account account, AccessType accessType, boolean sameOwner, String apiName,
-            ControlledEntity... entities) throws PermissionDeniedException;
+    void checkAccess(Account account, AccessType accessType, boolean sameOwner, String apiName, ControlledEntity... entities) throws PermissionDeniedException;
 
     Long finalyzeAccountId(String accountName, Long domainId, Long projectId, boolean enabledOnly);
 
     /**
      * returns the user account object for a given user id
      * @param userId user id
-     * @return useraccount object if it exists else null
+     * @return {@link UserAccount} object if it exists else null
      */
     UserAccount getUserAccountById(Long userId);
 
diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
index 5cd069b..8886320 100644
--- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
@@ -215,8 +215,8 @@ public class ApiConstants {
     public static final String PARENT_DOMAIN_ID = "parentdomainid";
     public static final String PARENT_TEMPLATE_ID = "parenttemplateid";
     public static final String PASSWORD = "password";
+    public static final String CURRENT_PASSWORD = "currentpassword";
     public static final String SHOULD_UPDATE_PASSWORD = "update_passwd_on_host";
-    public static final String NEW_PASSWORD = "new_password";
     public static final String PASSWORD_ENABLED = "passwordenabled";
     public static final String SSHKEY_ENABLED = "sshkeyenabled";
     public static final String PATH = "path";
@@ -729,4 +729,4 @@ public class ApiConstants {
     public enum DomainDetails {
         all, resource, min;
     }
-}
+}
\ No newline at end of file
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java
index 91ccede..24624e2 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java
@@ -34,7 +34,7 @@ import com.cloud.user.User;
 import com.cloud.user.UserAccount;
 
 @APICommand(name = "updateUser", description = "Updates a user account", responseObject = UserResponse.class,
-        requestHasSensitiveInfo = true, responseHasSensitiveInfo = true)
+requestHasSensitiveInfo = true, responseHasSensitiveInfo = true)
 public class UpdateUserCmd extends BaseCmd {
     public static final Logger s_logger = Logger.getLogger(UpdateUserCmd.class.getName());
 
@@ -65,20 +65,22 @@ public class UpdateUserCmd extends BaseCmd {
             acceptedOnAdminPort = false)
     private String password;
 
+    @Parameter(name = ApiConstants.CURRENT_PASSWORD, type = CommandType.STRING, description = "Current password that was being used by the user. You must inform the current password when updating the password.", acceptedOnAdminPort = false)
+    private String currentPassword;
 
     @Parameter(name = ApiConstants.SECRET_KEY, type = CommandType.STRING, description = "The secret key for the user. Must be specified with userApiKey")
     private String secretKey;
 
     @Parameter(name = ApiConstants.TIMEZONE,
-               type = CommandType.STRING,
-               description = "Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format.")
+            type = CommandType.STRING,
+            description = "Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format.")
     private String timezone;
 
     @Parameter(name = ApiConstants.USERNAME, type = CommandType.STRING, description = "Unique username")
     private String username;
 
     @Inject
-    RegionService _regionService;
+    private RegionService _regionService;
 
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
@@ -108,6 +110,10 @@ public class UpdateUserCmd extends BaseCmd {
         return password;
     }
 
+    public String getCurrentPassword() {
+        return currentPassword;
+    }
+
     public String getSecretKey() {
         return secretKey;
     }
@@ -152,4 +158,20 @@ public class UpdateUserCmd extends BaseCmd {
             throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update user");
         }
     }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public void setFirstname(String firstname) {
+        this.firstname = firstname;
+    }
+
+    public void setLastname(String lastname) {
+        this.lastname = lastname;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
 }
diff --git a/plugins/network-elements/juniper-contrail/src/test/java/org/apache/cloudstack/network/contrail/management/MockAccountManager.java b/plugins/network-elements/juniper-contrail/src/test/java/org/apache/cloudstack/network/contrail/management/MockAccountManager.java
index 37ca2bc..100f380 100644
--- a/plugins/network-elements/juniper-contrail/src/test/java/org/apache/cloudstack/network/contrail/management/MockAccountManager.java
+++ b/plugins/network-elements/juniper-contrail/src/test/java/org/apache/cloudstack/network/contrail/management/MockAccountManager.java
@@ -168,13 +168,6 @@ public class MockAccountManager extends ManagerBase implements AccountManager {
     }
 
     @Override
-    public UserAccount updateUser(Long userId, String firstName, String lastName, String email, String userName, String password, String apiKey, String secretKey,
-                                  String timeZone) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
     public User getActiveUser(long arg0) {
         return _systemUser;
     }
diff --git a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/LdapImportUsersCmd.java b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/LdapImportUsersCmd.java
index 564c1d0..9011452 100644
--- a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/LdapImportUsersCmd.java
+++ b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/LdapImportUsersCmd.java
@@ -26,9 +26,6 @@ import java.util.UUID;
 
 import javax.inject.Inject;
 
-import com.cloud.user.Account;
-import com.cloud.user.User;
-import com.cloud.user.UserAccount;
 import org.apache.cloudstack.acl.RoleType;
 import org.apache.cloudstack.api.APICommand;
 import org.apache.cloudstack.api.ApiConstants;
@@ -36,6 +33,7 @@ import org.apache.cloudstack.api.ApiErrorCode;
 import org.apache.cloudstack.api.BaseListCmd;
 import org.apache.cloudstack.api.Parameter;
 import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd;
 import org.apache.cloudstack.api.response.DomainResponse;
 import org.apache.cloudstack.api.response.LdapUserResponse;
 import org.apache.cloudstack.api.response.ListResponse;
@@ -54,25 +52,23 @@ import com.cloud.exception.InvalidParameterValueException;
 import com.cloud.exception.NetworkRuleConflictException;
 import com.cloud.exception.ResourceAllocationException;
 import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.user.Account;
 import com.cloud.user.AccountService;
 import com.cloud.user.DomainService;
+import com.cloud.user.User;
+import com.cloud.user.UserAccount;
 
-@APICommand(name = "importLdapUsers", description = "Import LDAP users", responseObject = LdapUserResponse.class, since = "4.3.0",
-        requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
+@APICommand(name = "importLdapUsers", description = "Import LDAP users", responseObject = LdapUserResponse.class, since = "4.3.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
 public class LdapImportUsersCmd extends BaseListCmd {
 
     public static final Logger s_logger = Logger.getLogger(LdapImportUsersCmd.class.getName());
 
     private static final String s_name = "ldapuserresponse";
 
-    @Parameter(name = ApiConstants.TIMEZONE,
-               type = CommandType.STRING,
-               description = "Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format.")
+    @Parameter(name = ApiConstants.TIMEZONE, type = CommandType.STRING, description = "Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format.")
     private String timezone;
 
-    @Parameter(name = ApiConstants.ACCOUNT_TYPE,
-               type = CommandType.SHORT,
-               description = "Type of the account.  Specify 0 for user, 1 for root admin, and 2 for domain admin")
+    @Parameter(name = ApiConstants.ACCOUNT_TYPE, type = CommandType.SHORT, description = "Type of the account.  Specify 0 for user, 1 for root admin, and 2 for domain admin")
     private Short accountType;
 
     @Parameter(name = ApiConstants.ROLE_ID, type = CommandType.UUID, entityType = RoleResponse.class, description = "Creates the account under the specified role.")
@@ -81,16 +77,13 @@ public class LdapImportUsersCmd extends BaseListCmd {
     @Parameter(name = ApiConstants.ACCOUNT_DETAILS, type = CommandType.MAP, description = "details for account used to store specific parameters")
     private Map<String, String> details;
 
-    @Parameter(name = ApiConstants.DOMAIN_ID,
-               type = CommandType.UUID,
-               entityType = DomainResponse.class,
-               description = "Specifies the domain to which the ldap users are to be "
-                   + "imported. If no domain is specified, a domain will created using group parameter. If the group is also not specified, a domain name based on the OU information will be "
-                   + "created. If no OU hierarchy exists, will be defaulted to ROOT domain")
+    @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class, description = "Specifies the domain to which the ldap users are to be "
+            + "imported. If no domain is specified, a domain will created using group parameter. If the group is also not specified, a domain name based on the OU information will be "
+            + "created. If no OU hierarchy exists, will be defaulted to ROOT domain")
     private Long domainId;
 
     @Parameter(name = ApiConstants.GROUP, type = CommandType.STRING, description = "Specifies the group name from which the ldap users are to be imported. "
-        + "If no group is specified, all the users will be imported.")
+            + "If no group is specified, all the users will be imported.")
     private String groupName;
 
     private Domain _domain;
@@ -121,20 +114,27 @@ public class LdapImportUsersCmd extends BaseListCmd {
         } else {
 //            check if the user exists. if yes, call update
             UserAccount csuser = _accountService.getActiveUserAccount(user.getUsername(), domain.getId());
-            if(csuser == null) {
+            if (csuser == null) {
                 s_logger.debug("No user exists with name: " + user.getUsername() + " creating a user in the account: " + accountName);
                 _accountService.createUser(user.getUsername(), generatePassword(), user.getFirstname(), user.getLastname(), user.getEmail(), timezone, accountName, domain.getId(),
-                                           UUID.randomUUID().toString(), User.Source.LDAP);
+                        UUID.randomUUID().toString(), User.Source.LDAP);
             } else {
-                s_logger.debug("account with name: " + accountName + " exist and user with name: " + user.getUsername() + " exists in the account. Updating the account.");
-                _accountService.updateUser(csuser.getId(), user.getFirstname(), user.getLastname(), user.getEmail(), null, null, null, null, null);
+                s_logger.debug("Account [name=%s] and user [name=%s] already exist in CloudStack. Executing the user update.");
+
+                UpdateUserCmd updateUserCmd = new UpdateUserCmd();
+                updateUserCmd.setId(csuser.getId());
+                updateUserCmd.setFirstname(user.getFirstname());
+                updateUserCmd.setLastname(user.getLastname());
+                updateUserCmd.setEmail(user.getEmail());
+
+                _accountService.updateUser(updateUserCmd);
             }
         }
     }
 
     @Override
-    public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
-        ResourceAllocationException, NetworkRuleConflictException {
+    public void execute()
+            throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
         if (getAccountType() == null && getRoleId() == null) {
             throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Both account type and role ID are not provided");
         }
@@ -177,7 +177,7 @@ public class LdapImportUsersCmd extends BaseListCmd {
 
     private String getAccountName(LdapUser user) {
         String finalAccountName = accountName;
-        if(finalAccountName == null ) {
+        if (finalAccountName == null) {
             finalAccountName = user.getUsername();
         }
         return finalAccountName;
@@ -244,7 +244,7 @@ public class LdapImportUsersCmd extends BaseListCmd {
             final byte bytes[] = new byte[20];
             randomGen.nextBytes(bytes);
             return new String(Base64.encode(bytes), "UTF-8");
-        } catch ( NoSuchAlgorithmException | UnsupportedEncodingException e) {
+        } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
             throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to generate random password");
         }
     }
diff --git a/server/src/main/java/com/cloud/user/AccountManager.java b/server/src/main/java/com/cloud/user/AccountManager.java
index e708b04..de6dcca 100644
--- a/server/src/main/java/com/cloud/user/AccountManager.java
+++ b/server/src/main/java/com/cloud/user/AccountManager.java
@@ -16,15 +16,17 @@
 // under the License.
 package com.cloud.user;
 
+import java.net.InetAddress;
 import java.util.List;
 import java.util.Map;
-import java.net.InetAddress;
 
 import org.apache.cloudstack.acl.ControlledEntity;
 import org.apache.cloudstack.api.command.admin.account.UpdateAccountCmd;
 import org.apache.cloudstack.api.command.admin.user.DeleteUserCmd;
 import org.apache.cloudstack.api.command.admin.user.MoveUserCmd;
 import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd;
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.framework.config.Configurable;
 
 import com.cloud.api.query.vo.ControlledViewEntity;
 import com.cloud.exception.ConcurrentOperationException;
@@ -34,17 +36,14 @@ import com.cloud.utils.Pair;
 import com.cloud.utils.Ternary;
 import com.cloud.utils.db.SearchBuilder;
 import com.cloud.utils.db.SearchCriteria;
-import org.apache.cloudstack.framework.config.ConfigKey;
-import org.apache.cloudstack.framework.config.Configurable;
 
 /**
  * AccountManager includes logic that deals with accounts, domains, and users.
  *
  */
-public interface AccountManager extends AccountService, Configurable{
+public interface AccountManager extends AccountService, Configurable {
     /**
      * Disables an account by accountId
-     * @param accountId
      * @return true if disable was successful, false otherwise
      */
     boolean disableAccount(long accountId) throws ConcurrentOperationException, ResourceUnavailableException;
@@ -57,24 +56,23 @@ public interface AccountManager extends AccountService, Configurable{
 
     /**
      * Logs out a user
-     * @param userId
      */
     void logoutUser(long userId);
 
     /**
-      * Authenticates a user when s/he logs in.
-      *
-      * @param username
-      *            required username for authentication
-      * @param password
-      *            password to use for authentication, can be null for single sign-on case
-      * @param domainId
-      *            id of domain where user with username resides
-      * @param requestParameters
-      *            the request parameters of the login request, which should contain timestamp of when the request signature is
-      *            made, and the signature itself in the single sign-on case
-      * @return a user object, null if the user failed to authenticate
-      */
+     * Authenticates a user when s/he logs in.
+     *
+     * @param username
+     *            required username for authentication
+     * @param password
+     *            password to use for authentication, can be null for single sign-on case
+     * @param domainId
+     *            id of domain where user with username resides
+     * @param requestParameters
+     *            the request parameters of the login request, which should contain timestamp of when the request signature is
+     *            made, and the signature itself in the single sign-on case
+     * @return a user object, null if the user failed to authenticate
+     */
     UserAccount authenticateUser(String username, String password, Long domainId, InetAddress loginIpAddress, Map<String, Object[]> requestParameters);
 
     /**
@@ -88,23 +86,20 @@ public interface AccountManager extends AccountService, Configurable{
 
     boolean enableAccount(long accountId);
 
+    void buildACLSearchBuilder(SearchBuilder<? extends ControlledEntity> sb, Long domainId, boolean isRecursive, List<Long> permittedAccounts,
+            ListProjectResourcesCriteria listProjectResourcesCriteria);
 
-    void buildACLSearchBuilder(SearchBuilder<? extends ControlledEntity> sb, Long domainId,
-            boolean isRecursive, List<Long> permittedAccounts, ListProjectResourcesCriteria listProjectResourcesCriteria);
-
-    void buildACLViewSearchBuilder(SearchBuilder<? extends ControlledViewEntity> sb, Long domainId,
-            boolean isRecursive, List<Long> permittedAccounts, ListProjectResourcesCriteria listProjectResourcesCriteria);
-
-    void buildACLSearchCriteria(SearchCriteria<? extends ControlledEntity> sc,
-            Long domainId, boolean isRecursive, List<Long> permittedAccounts, ListProjectResourcesCriteria listProjectResourcesCriteria);
+    void buildACLViewSearchBuilder(SearchBuilder<? extends ControlledViewEntity> sb, Long domainId, boolean isRecursive, List<Long> permittedAccounts,
+            ListProjectResourcesCriteria listProjectResourcesCriteria);
 
-    void buildACLSearchParameters(Account caller, Long id,
-            String accountName, Long projectId, List<Long> permittedAccounts, Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject, boolean listAll,
-            boolean forProjectInvitation);
+    void buildACLSearchCriteria(SearchCriteria<? extends ControlledEntity> sc, Long domainId, boolean isRecursive, List<Long> permittedAccounts,
+            ListProjectResourcesCriteria listProjectResourcesCriteria);
 
-    void buildACLViewSearchCriteria(SearchCriteria<? extends ControlledViewEntity> sc,
-            Long domainId, boolean isRecursive, List<Long> permittedAccounts, ListProjectResourcesCriteria listProjectResourcesCriteria);
+    void buildACLSearchParameters(Account caller, Long id, String accountName, Long projectId, List<Long> permittedAccounts,
+            Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject, boolean listAll, boolean forProjectInvitation);
 
+    void buildACLViewSearchCriteria(SearchCriteria<? extends ControlledViewEntity> sc, Long domainId, boolean isRecursive, List<Long> permittedAccounts,
+            ListProjectResourcesCriteria listProjectResourcesCriteria);
 
     /**
      * Deletes a user by userId
@@ -127,10 +122,6 @@ public interface AccountManager extends AccountService, Configurable{
 
     /**
      * Disables an account by accountName and domainId
-     *
-     * @param accountName
-     * @param domainId
-     * @param accountId
      * @param disabled
      *            account if success
      * @return true if disable was successful, false otherwise
@@ -142,33 +133,21 @@ public interface AccountManager extends AccountService, Configurable{
      *
      * @param accountName
      *            - the enableAccount command defining the accountId to be deleted.
-     * @param domainId
-     *            TODO
-     * @param accountId
-     * @return account object
      */
     Account enableAccount(String accountName, Long domainId, Long accountId);
 
     /**
      * Deletes user by Id
-     * @param deleteUserCmd
-     * @return
      */
     boolean deleteUser(DeleteUserCmd deleteUserCmd);
 
     /**
      * moves a user to another account within the same domain
-     * @param moveUserCmd
      * @return true if the user was successfully moved
      */
     boolean moveUser(MoveUserCmd moveUserCmd);
 
-    /**
-     * Update a user by userId
-     *
-     * @param cmd
-     * @return UserAccount object
-     */
+    @Override
     UserAccount updateUser(UpdateUserCmd cmd);
 
     /**
@@ -196,10 +175,6 @@ public interface AccountManager extends AccountService, Configurable{
      *
      * @param accountName
      *            - the LockAccount command defining the accountId to be locked.
-     * @param domainId
-     *            TODO
-     * @param accountId
-     * @return account object
      */
     Account lockAccount(String accountName, Long domainId, Long accountId);
 
@@ -208,13 +183,8 @@ public interface AccountManager extends AccountService, Configurable{
     public static final String MESSAGE_ADD_ACCOUNT_EVENT = "Message.AddAccount.Event";
 
     public static final String MESSAGE_REMOVE_ACCOUNT_EVENT = "Message.RemoveAccount.Event";
-    public static final ConfigKey<Boolean> UseSecretKeyInResponse = new ConfigKey<Boolean>(
-            "Advanced",
-            Boolean.class,
-            "use.secret.key.in.response",
-            "false",
-            "This parameter allows the users to enable or disable of showing secret key as a part of response for various APIs. By default it is set to false.",
-            true);
+    public static final ConfigKey<Boolean> UseSecretKeyInResponse = new ConfigKey<Boolean>("Advanced", Boolean.class, "use.secret.key.in.response", "false",
+            "This parameter allows the users to enable or disable of showing secret key as a part of response for various APIs. By default it is set to false.", true);
 
     boolean moveUser(long id, Long domainId, long accountId);
 }
diff --git a/server/src/main/java/com/cloud/user/AccountManagerImpl.java b/server/src/main/java/com/cloud/user/AccountManagerImpl.java
index dc9fdc0..b44e280 100644
--- a/server/src/main/java/com/cloud/user/AccountManagerImpl.java
+++ b/server/src/main/java/com/cloud/user/AccountManagerImpl.java
@@ -23,7 +23,6 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
@@ -38,10 +37,6 @@ import javax.crypto.spec.SecretKeySpec;
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
-import org.apache.commons.codec.binary.Base64;
-import org.apache.commons.lang.StringUtils;
-import org.apache.log4j.Logger;
-
 import org.apache.cloudstack.acl.ControlledEntity;
 import org.apache.cloudstack.acl.QuerySelector;
 import org.apache.cloudstack.acl.RoleType;
@@ -55,6 +50,7 @@ import org.apache.cloudstack.api.command.admin.user.GetUserKeysCmd;
 import org.apache.cloudstack.api.command.admin.user.MoveUserCmd;
 import org.apache.cloudstack.api.command.admin.user.RegisterCmd;
 import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd;
+import org.apache.cloudstack.config.ApiServiceConfiguration;
 import org.apache.cloudstack.context.CallContext;
 import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
 import org.apache.cloudstack.framework.config.ConfigKey;
@@ -64,6 +60,11 @@ import org.apache.cloudstack.framework.messagebus.PublishScope;
 import org.apache.cloudstack.managed.context.ManagedContextRunnable;
 import org.apache.cloudstack.region.gslb.GlobalLoadBalancerRuleDao;
 import org.apache.cloudstack.utils.baremetal.BaremetalUtils;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.log4j.Logger;
 
 import com.cloud.api.ApiDBUtils;
 import com.cloud.api.query.vo.ControlledViewEntity;
@@ -172,8 +173,6 @@ import com.cloud.vm.snapshot.VMSnapshot;
 import com.cloud.vm.snapshot.VMSnapshotManager;
 import com.cloud.vm.snapshot.VMSnapshotVO;
 import com.cloud.vm.snapshot.dao.VMSnapshotDao;
-import org.apache.cloudstack.config.ApiServiceConfiguration;
-
 
 public class AccountManagerImpl extends ManagerBase implements AccountManager, Manager {
     public static final Logger s_logger = Logger.getLogger(AccountManagerImpl.class);
@@ -540,8 +539,8 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
                 Account account = ApiDBUtils.findAccountById(entity.getAccountId());
                 domainId = account != null ? account.getDomainId() : -1;
             }
-            if (entity.getAccountId() != -1 && domainId != -1 && !(entity instanceof VirtualMachineTemplate)
-                    && !(entity instanceof Network && accessType != null && accessType == AccessType.UseEntry) && !(entity instanceof AffinityGroup)) {
+            if (entity.getAccountId() != -1 && domainId != -1 && !(entity instanceof VirtualMachineTemplate) && !(entity instanceof Network && accessType != null && accessType == AccessType.UseEntry)
+                    && !(entity instanceof AffinityGroup)) {
                 List<ControlledEntity> toBeChecked = domains.get(entity.getDomainId());
                 // for templates, we don't have to do cross domains check
                 if (toBeChecked == null) {
@@ -563,7 +562,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
 
             if (!granted) {
                 assert false : "How can all of the security checkers pass on checking this check: " + entity;
-                throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to " + entity);
+            throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to " + entity);
             }
         }
 
@@ -590,26 +589,27 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
     public Long checkAccessAndSpecifyAuthority(Account caller, Long zoneId) {
         // We just care for resource domain admin for now. He should be permitted to see only his zone.
         if (isResourceDomainAdmin(caller.getAccountId())) {
-            if (zoneId == null)
+            if (zoneId == null) {
                 return getZoneIdForAccount(caller);
-            else if (zoneId.compareTo(getZoneIdForAccount(caller)) != 0)
+            } else if (zoneId.compareTo(getZoneIdForAccount(caller)) != 0) {
                 throw new PermissionDeniedException("Caller " + caller + "is not allowed to access the zone " + zoneId);
-            else
+            } else {
                 return zoneId;
-        }
-
-        else
+            }
+        } else {
             return zoneId;
+        }
     }
 
     private Long getZoneIdForAccount(Account account) {
 
         // Currently just for resource domain admin
         List<DataCenterVO> dcList = _dcDao.findZonesByDomainId(account.getDomainId());
-        if (dcList != null && dcList.size() != 0)
+        if (dcList != null && dcList.size() != 0) {
             return dcList.get(0).getId();
-        else
+        } else {
             throw new CloudRuntimeException("Failed to find any private zone for Resource domain admin.");
+        }
 
     }
 
@@ -1011,13 +1011,12 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
 
     @Override
     @ActionEvents({@ActionEvent(eventType = EventTypes.EVENT_ACCOUNT_CREATE, eventDescription = "creating Account"),
-            @ActionEvent(eventType = EventTypes.EVENT_USER_CREATE, eventDescription = "creating User")})
-    public UserAccount createUserAccount(final String userName, final String password, final String firstName, final String lastName, final String email, final String timezone,
-            String accountName, final short accountType, final Long roleId, Long domainId, final String networkDomain, final Map<String, String> details, String accountUUID,
-            final String userUUID) {
+        @ActionEvent(eventType = EventTypes.EVENT_USER_CREATE, eventDescription = "creating User")})
+    public UserAccount createUserAccount(final String userName, final String password, final String firstName, final String lastName, final String email, final String timezone, String accountName,
+            final short accountType, final Long roleId, Long domainId, final String networkDomain, final Map<String, String> details, String accountUUID, final String userUUID) {
 
-        return createUserAccount(userName, password, firstName, lastName, email, timezone, accountName, accountType, roleId, domainId, networkDomain, details, accountUUID,
-                userUUID, User.Source.UNKNOWN);
+        return createUserAccount(userName, password, firstName, lastName, email, timezone, accountName, accountType, roleId, domainId, networkDomain, details, accountUUID, userUUID,
+                User.Source.UNKNOWN);
     }
 
     // ///////////////////////////////////////////////////
@@ -1027,10 +1026,10 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
     @Override
     @DB
     @ActionEvents({@ActionEvent(eventType = EventTypes.EVENT_ACCOUNT_CREATE, eventDescription = "creating Account"),
-            @ActionEvent(eventType = EventTypes.EVENT_USER_CREATE, eventDescription = "creating User")})
-    public UserAccount createUserAccount(final String userName, final String password, final String firstName, final String lastName, final String email, final String timezone,
-            String accountName, final short accountType, final Long roleId, Long domainId, final String networkDomain, final Map<String, String> details, String accountUUID,
-            final String userUUID, final User.Source source) {
+        @ActionEvent(eventType = EventTypes.EVENT_USER_CREATE, eventDescription = "creating User")})
+    public UserAccount createUserAccount(final String userName, final String password, final String firstName, final String lastName, final String email, final String timezone, String accountName,
+            final short accountType, final Long roleId, Long domainId, final String networkDomain, final Map<String, String> details, String accountUUID, final String userUUID,
+            final User.Source source) {
 
         if (accountName == null) {
             accountName = userName;
@@ -1058,7 +1057,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
         }
 
         // Check permissions
-        checkAccess(CallContext.current().getCallingAccount(), domain);
+        checkAccess(getCurrentCallingAccount(), domain);
 
         if (!_userAccountDao.validateUsernameInDomain(userName, domainId)) {
             throw new InvalidParameterValueException("The user " + userName + " already exists in domain " + domainId);
@@ -1132,7 +1131,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
             throw new CloudRuntimeException("The user cannot be created as domain " + domain.getName() + " is being deleted");
         }
 
-        checkAccess(CallContext.current().getCallingAccount(), domain);
+        checkAccess(getCurrentCallingAccount(), domain);
 
         Account account = _accountDao.findEnabledAccount(accountName, domainId);
         if (account == null || account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
@@ -1153,157 +1152,246 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
 
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_USER_CREATE, eventDescription = "creating User")
-    public UserVO createUser(String userName, String password, String firstName, String lastName, String email, String timeZone, String accountName, Long domainId,
-            String userUUID) {
+    public UserVO createUser(String userName, String password, String firstName, String lastName, String email, String timeZone, String accountName, Long domainId, String userUUID) {
 
         return createUser(userName, password, firstName, lastName, email, timeZone, accountName, domainId, userUUID, User.Source.UNKNOWN);
     }
 
     @Override
-    @ActionEvent(eventType = EventTypes.EVENT_USER_UPDATE, eventDescription = "updating User")
-    public UserAccount updateUser(Long userId, String firstName, String lastName, String email, String userName, String password, String apiKey, String secretKey,
-            String timeZone) {
-        // Input validation
-        UserVO user = _userDao.getUser(userId);
+    @ActionEvent(eventType = EventTypes.EVENT_USER_UPDATE, eventDescription = "Updating User")
+    public UserAccount updateUser(UpdateUserCmd updateUserCmd) {
+        UserVO user = retrieveAndValidateUser(updateUserCmd);
+        s_logger.debug("Updating user with Id: " + user.getUuid());
 
-        if (user == null) {
-            throw new InvalidParameterValueException("unable to find user by id");
-        }
+        validateAndUpdatApiAndSecretKeyIfNeeded(updateUserCmd, user);
+        Account account = retrieveAndValidateAccount(user);
 
-        if ((apiKey == null && secretKey != null) || (apiKey != null && secretKey == null)) {
-            throw new InvalidParameterValueException("Please provide an userApiKey/userSecretKey pair");
-        }
+        validateAndUpdateFirstNameIfNeeded(updateUserCmd, user);
+        validateAndUpdateLastNameIfNeeded(updateUserCmd, user);
+        validateAndUpdateUsernameIfNeeded(updateUserCmd, user, account);
 
-        // If the account is an admin type, return an error. We do not allow this
-        Account account = _accountDao.findById(user.getAccountId());
-        if (account == null) {
-            throw new InvalidParameterValueException("unable to find user account " + user.getAccountId());
+        validateUserPasswordAndUpdateIfNeeded(updateUserCmd.getPassword(), user, updateUserCmd.getCurrentPassword());
+        String email = updateUserCmd.getEmail();
+        if (StringUtils.isNotBlank(email)) {
+            user.setEmail(email);
         }
-
-        // don't allow updating project account
-        if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
-            throw new InvalidParameterValueException("unable to find user by id");
+        String timezone = updateUserCmd.getTimezone();
+        if (StringUtils.isNotBlank(timezone)) {
+            user.setTimezone(timezone);
+        }
+        _userDao.update(user.getId(), user);
+        return _userAccountDao.findById(user.getId());
+    }
+
+    /**
+     * Updates the password in the user POJO if needed. If no password is provided, then the password is not updated.
+     * The following validations are executed if 'password' is not null. Admins (root admins or domain admins) can execute password updates without entering the current password.
+     * <ul>
+     *  <li> If 'password' is blank, we throw an {@link InvalidParameterValueException};
+     *  <li> If 'current password' is not provided and user is not an Admin, we throw an {@link InvalidParameterValueException};
+     *  <li> If a normal user is calling this method, we use {@link #validateCurrentPassword(UserVO, String)} to check if the provided old password matches the database one;
+     * </ul>
+     *
+     * If all checks pass, we encode the given password with the most preferable password mechanism given in {@link #_userPasswordEncoders}.
+     */
+    protected void validateUserPasswordAndUpdateIfNeeded(String newPassword, UserVO user, String currentPassword) {
+        if (newPassword == null) {
+            s_logger.trace("No new password to update for user: " + user.getUuid());
+            return;
         }
-
-        // don't allow updating system account
-        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
-            throw new PermissionDeniedException("user id : " + userId + " is system account, update is not allowed");
+        if (StringUtils.isBlank(newPassword)) {
+            throw new InvalidParameterValueException("Password cannot be empty or blank.");
+        }
+        Account callingAccount = getCurrentCallingAccount();
+        boolean isRootAdminExecutingPasswordUpdate = callingAccount.getId() == Account.ACCOUNT_ID_SYSTEM || isRootAdmin(callingAccount.getId());
+        boolean isDomainAdmin = isDomainAdmin(callingAccount.getId());
+        boolean isAdmin = isDomainAdmin || isRootAdminExecutingPasswordUpdate;
+        if (isAdmin) {
+            s_logger.trace(String.format("Admin account [uuid=%s] executing password update for user [%s] ", callingAccount.getUuid(), user.getUuid()));
+        }
+        if (!isAdmin && StringUtils.isBlank(currentPassword)) {
+            throw new InvalidParameterValueException("To set a new password the current password must be provided.");
+        }
+        if (CollectionUtils.isEmpty(_userPasswordEncoders)) {
+            throw new CloudRuntimeException("No user authenticators configured!");
+        }
+        if (!isAdmin) {
+            validateCurrentPassword(user, currentPassword);
+        }
+        UserAuthenticator userAuthenticator = _userPasswordEncoders.get(0);
+        String newPasswordEncoded = userAuthenticator.encode(newPassword);
+        user.setPassword(newPasswordEncoded);
+    }
+
+    /**
+     * Iterates over all configured user authenticators and tries to authenticate the user using the current password.
+     * If the user is authenticated with success, we have nothing else to do here; otherwise, an {@link InvalidParameterValueException} is thrown.
+     */
+    protected void validateCurrentPassword(UserVO user, String currentPassword) {
+        AccountVO userAccount = _accountDao.findById(user.getAccountId());
+        boolean currentPasswordMatchesDataBasePassword = false;
+        for (UserAuthenticator userAuthenticator : _userPasswordEncoders) {
+            Pair<Boolean, ActionOnFailedAuthentication> authenticationResult = userAuthenticator.authenticate(user.getUsername(), currentPassword, userAccount.getDomainId(), null);
+            if (authenticationResult == null) {
+                s_logger.trace(String.format("Authenticator [%s] is returning null for the authenticate mehtod.", userAuthenticator.getClass()));
+                continue;
+            }
+            if (BooleanUtils.toBoolean(authenticationResult.first())) {
+                s_logger.debug(String.format("User [id=%s] re-authenticated [authenticator=%s] during password update.", user.getUuid(), userAuthenticator.getName()));
+                currentPasswordMatchesDataBasePassword = true;
+                break;
+            }
         }
+        if (!currentPasswordMatchesDataBasePassword) {
+            throw new InvalidParameterValueException("Current password is incorrect.");
+        }
+    }
 
-        checkAccess(CallContext.current().getCallingAccount(), AccessType.OperateEntry, true, account);
-
-        if (firstName != null) {
-            if (firstName.isEmpty()) {
-                throw new InvalidParameterValueException("Firstname is empty");
+    /**
+     * Validates the user 'username' if provided. The 'username' cannot be blank (when provided).
+     * <ul>
+     *  <li> If the 'username' is not provided, we do not update it (setting to null) in the User POJO.
+     *  <li> If the 'username' is blank, we throw an {@link InvalidParameterValueException}.
+     *  <li> The username must be unique in each domain. Therefore, if there is already another user with the same username, an {@link InvalidParameterValueException} is thrown.
+     * </ul>
+     */
+    protected void validateAndUpdateUsernameIfNeeded(UpdateUserCmd updateUserCmd, UserVO user, Account account) {
+        String userName = updateUserCmd.getUsername();
+        if (userName == null) {
+            return;
+        }
+        if (StringUtils.isBlank(userName)) {
+            throw new InvalidParameterValueException("Username cannot be empty.");
+        }
+        List<UserVO> duplicatedUsers = _userDao.findUsersByName(userName);
+        for (UserVO duplicatedUser : duplicatedUsers) {
+            if (duplicatedUser.getId() == user.getId()) {
+                continue;
+            }
+            Account duplicatedUserAccountWithUserThatHasTheSameUserName = _accountDao.findById(duplicatedUser.getAccountId());
+            if (duplicatedUserAccountWithUserThatHasTheSameUserName.getDomainId() == account.getDomainId()) {
+                DomainVO domain = _domainDao.findById(duplicatedUserAccountWithUserThatHasTheSameUserName.getDomainId());
+                throw new InvalidParameterValueException(String.format("Username [%s] already exists in domain [id=%s,name=%s]", duplicatedUser.getUsername(), domain.getUuid(), domain.getName()));
             }
-
-            user.setFirstname(firstName);
         }
+        user.setUsername(userName);
+    }
+
+    /**
+     * Validates the user 'lastName' if provided. The 'lastName' cannot be blank (when provided).
+     * <ul>
+     *  <li> If the 'lastName' is not provided, we do not update it (setting to null) in the User POJO.
+     *  <li> If the 'lastName' is blank, we throw an {@link InvalidParameterValueException}.
+     * </ul>
+     */
+    protected void validateAndUpdateLastNameIfNeeded(UpdateUserCmd updateUserCmd, UserVO user) {
+        String lastName = updateUserCmd.getLastname();
         if (lastName != null) {
-            if (lastName.isEmpty()) {
-                throw new InvalidParameterValueException("Lastname is empty");
+            if (StringUtils.isBlank(lastName)) {
+                throw new InvalidParameterValueException("Lastname cannot be empty.");
             }
 
             user.setLastname(lastName);
         }
-        if (userName != null) {
-            if (userName.isEmpty()) {
-                throw new InvalidParameterValueException("Username is empty");
-            }
+    }
 
-            // don't allow to have same user names in the same domain
-            List<UserVO> duplicatedUsers = _userDao.findUsersByName(userName);
-            for (UserVO duplicatedUser : duplicatedUsers) {
-                if (duplicatedUser.getId() != user.getId()) {
-                    Account duplicatedUserAccount = _accountDao.findById(duplicatedUser.getAccountId());
-                    if (duplicatedUserAccount.getDomainId() == account.getDomainId()) {
-                        throw new InvalidParameterValueException("User with name " + userName + " already exists in domain " + duplicatedUserAccount.getDomainId());
-                    }
-                }
+    /**
+     * Validates the user 'firstName' if provided. The 'firstName' cannot be blank (when provided).
+     * <ul>
+     *  <li> If the 'firstName' is not provided, we do not update it (setting to null) in the User POJO.
+     *  <li> If the 'firstName' is blank, we throw an {@link InvalidParameterValueException}.
+     * </ul>
+     */
+    protected void validateAndUpdateFirstNameIfNeeded(UpdateUserCmd updateUserCmd, UserVO user) {
+        String firstName = updateUserCmd.getFirstname();
+        if (firstName != null) {
+            if (StringUtils.isBlank(firstName)) {
+                throw new InvalidParameterValueException("Firstname cannot be empty.");
             }
-
-            user.setUsername(userName);
+            user.setFirstname(firstName);
         }
+    }
 
-        if (password != null) {
-            if (password.isEmpty()) {
-                throw new InvalidParameterValueException("Password cannot be empty");
-            }
-            String encodedPassword = null;
-            for (Iterator<UserAuthenticator> en = _userPasswordEncoders.iterator(); en.hasNext();) {
-                UserAuthenticator authenticator = en.next();
-                encodedPassword = authenticator.encode(password);
-                if (encodedPassword != null) {
-                    break;
-                }
-            }
-            if (encodedPassword == null) {
-                throw new CloudRuntimeException("Failed to encode password");
-            }
-            user.setPassword(encodedPassword);
-        }
-        if (email != null) {
-            user.setEmail(email);
-        }
-        if (timeZone != null) {
-            user.setTimezone(timeZone);
+    /**
+     * Searches an account for the given users. Then, we validate it as follows:
+     * <ul>
+     *  <li>If no account is found for the given user, we throw a {@link CloudRuntimeException}. There must be something wrong in the database for this case.
+     *  <li>If the account is of {@link Account#ACCOUNT_TYPE_PROJECT}, we throw an {@link InvalidParameterValueException}.
+     *  <li>If the account is of {@link Account#ACCOUNT_ID_SYSTEM}, we throw an {@link InvalidParameterValueException}.
+     * </ul>
+     *
+     * Afterwards, we check if the logged user has access to the user being updated via {@link #checkAccess(Account, AccessType, boolean, ControlledEntity...)}
+     */
+    protected Account retrieveAndValidateAccount(UserVO user) {
+        Account account = _accountDao.findById(user.getAccountId());
+        if (account == null) {
+            throw new CloudRuntimeException("Unable to find user account with ID: " + user.getAccountId());
         }
-        if (apiKey != null) {
-            user.setApiKey(apiKey);
+        if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
+            throw new InvalidParameterValueException("Unable to find user with ID: " + user.getUuid());
         }
-        if (secretKey != null) {
-            user.setSecretKey(secretKey);
+        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
+            throw new PermissionDeniedException("user UUID : " + user.getUuid() + " is a system account; update is not allowed.");
         }
+        checkAccess(getCurrentCallingAccount(), AccessType.OperateEntry, true, account);
+        return account;
+    }
 
-        if (s_logger.isDebugEnabled()) {
-            s_logger.debug("updating user with id: " + userId);
+    /**
+     * Returns the calling account using the method {@link CallContext#getCallingAccount()}.
+     * We are introducing this method to avoid using 'PowerMockRunner' in unit tests. Then, we can mock the calls to this method, which facilitates the development of test cases.
+     */
+    protected Account getCurrentCallingAccount() {
+        return CallContext.current().getCallingAccount();
+    }
+
+    /**
+     * Validates user API and Secret keys. If a new pair of keys is provided, we update them in the user POJO.
+     * <ul>
+     * <li>When updating the keys, it must be provided a pair (API and Secret keys); otherwise, an {@link InvalidParameterValueException} is thrown.
+     * <li>If a pair of keys is provided, we validate to see if there is an user already using the provided API key. If there is someone else using, we throw an {@link InvalidParameterValueException} because two users cannot have the same API key.
+     * </ul>
+     */
+    protected void validateAndUpdatApiAndSecretKeyIfNeeded(UpdateUserCmd updateUserCmd, UserVO user) {
+        String apiKey = updateUserCmd.getApiKey();
+        String secretKey = updateUserCmd.getSecretKey();
+
+        boolean isApiKeyBlank = StringUtils.isBlank(apiKey);
+        boolean isSecretKeyBlank = StringUtils.isBlank(secretKey);
+        if (isApiKeyBlank ^ isSecretKeyBlank) {
+            throw new InvalidParameterValueException("Please provide a userApiKey/userSecretKey pair");
         }
-        try {
-            // check if the apiKey and secretKey are globally unique
-            if (apiKey != null && secretKey != null) {
-                Pair<User, Account> apiKeyOwner = _accountDao.findUserAccountByApiKey(apiKey);
-
-                if (apiKeyOwner != null) {
-                    User usr = apiKeyOwner.first();
-                    if (usr.getId() != userId) {
-                        throw new InvalidParameterValueException("The api key:" + apiKey + " exists in the system for user id:" + userId + " ,please provide a unique key");
-                    } else {
-                        // allow the updation to take place
-                    }
-                }
+        if (isApiKeyBlank && isSecretKeyBlank) {
+            return;
+        }
+        Pair<User, Account> apiKeyOwner = _accountDao.findUserAccountByApiKey(apiKey);
+        if (apiKeyOwner != null) {
+            User userThatHasTheProvidedApiKey = apiKeyOwner.first();
+            if (userThatHasTheProvidedApiKey.getId() != user.getId()) {
+                throw new InvalidParameterValueException(String.format("The API key [%s] already exists in the system. Please provide a unique key.", apiKey));
             }
-
-            _userDao.update(userId, user);
-        } catch (Throwable th) {
-            s_logger.error("error updating user", th);
-            throw new CloudRuntimeException("Unable to update user " + userId);
         }
-
-        CallContext.current().putContextParameter(User.class, user.getUuid());
-
-        return _userAccountDao.findById(userId);
+        user.setApiKey(apiKey);
+        user.setSecretKey(secretKey);
     }
 
-    @Override
-    @ActionEvent(eventType = EventTypes.EVENT_USER_UPDATE, eventDescription = "updating User")
-    public UserAccount updateUser(UpdateUserCmd cmd) {
-        Long id = cmd.getId();
-        String apiKey = cmd.getApiKey();
-        String firstName = cmd.getFirstname();
-        String email = cmd.getEmail();
-        String lastName = cmd.getLastname();
-        String password = cmd.getPassword();
-        String secretKey = cmd.getSecretKey();
-        String timeZone = cmd.getTimezone();
-        String userName = cmd.getUsername();
+    /**
+     * Searches for a user with the given userId. If no user is found we throw an {@link InvalidParameterValueException}.
+     */
+    protected UserVO retrieveAndValidateUser(UpdateUserCmd updateUserCmd) {
+        Long userId = updateUserCmd.getId();
 
-        return updateUser(id, firstName, lastName, email, userName, password, apiKey, secretKey, timeZone);
+        UserVO user = _userDao.getUser(userId);
+        if (user == null) {
+            throw new InvalidParameterValueException("Unable to find user with id: " + userId);
+        }
+        return user;
     }
 
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_USER_DISABLE, eventDescription = "disabling User", async = true)
     public UserAccount disableUser(long userId) {
-        Account caller = CallContext.current().getCallingAccount();
+        Account caller = getCurrentCallingAccount();
 
         // Check if user exists in the system
         User user = _userDao.findById(userId);
@@ -1345,7 +1433,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
     @ActionEvent(eventType = EventTypes.EVENT_USER_ENABLE, eventDescription = "enabling User")
     public UserAccount enableUser(final long userId) {
 
-        Account caller = CallContext.current().getCallingAccount();
+        Account caller = getCurrentCallingAccount();
 
         // Check if user exists in the system
         final User user = _userDao.findById(userId);
@@ -1396,7 +1484,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_USER_LOCK, eventDescription = "locking User")
     public UserAccount lockUser(long userId) {
-        Account caller = CallContext.current().getCallingAccount();
+        Account caller = getCurrentCallingAccount();
 
         // Check if user with id exists in the system
         User user = _userDao.findById(userId);
@@ -1462,7 +1550,6 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
 
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_ACCOUNT_DELETE, eventDescription = "deleting account", async = true)
-    // This method deletes the account
     public boolean deleteUserAccount(long accountId) {
 
         CallContext ctx = CallContext.current();
@@ -1528,7 +1615,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
         }
 
         // Check if user performing the action is allowed to modify this account
-        Account caller = CallContext.current().getCallingAccount();
+        Account caller = getCurrentCallingAccount();
         checkAccess(caller, AccessType.OperateEntry, true, account);
 
         boolean success = enableAccount(account.getId());
@@ -1545,7 +1632,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_ACCOUNT_DISABLE, eventDescription = "locking account", async = true)
     public AccountVO lockAccount(String accountName, Long domainId, Long accountId) {
-        Account caller = CallContext.current().getCallingAccount();
+        Account caller = getCurrentCallingAccount();
 
         Account account = null;
         if (accountId != null) {
@@ -1575,7 +1662,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_ACCOUNT_DISABLE, eventDescription = "disabling account", async = true)
     public AccountVO disableAccount(String accountName, Long domainId, Long accountId) throws ConcurrentOperationException, ResourceUnavailableException {
-        Account caller = CallContext.current().getCallingAccount();
+        Account caller = getCurrentCallingAccount();
 
         Account account = null;
         if (accountId != null) {
@@ -1633,16 +1720,11 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
         }
 
         // Check if user performing the action is allowed to modify this account
-        checkAccess(CallContext.current().getCallingAccount(), _domainMgr.getDomain(account.getDomainId()));
+        checkAccess(getCurrentCallingAccount(), _domainMgr.getDomain(account.getDomainId()));
 
         // check if the given account name is unique in this domain for updating
         Account duplicateAcccount = _accountDao.findActiveAccount(newAccountName, domainId);
-        if (duplicateAcccount != null && duplicateAcccount.getId() != account.getId()) {// allow
-                                                                                        // same
-                                                                                        // account
-                                                                                        // to
-                                                                                        // update
-                                                                                        // itself
+        if (duplicateAcccount != null && duplicateAcccount.getId() != account.getId()) {
             throw new InvalidParameterValueException(
                     "There already exists an account with the name:" + newAccountName + " in the domain:" + domainId + " with existing account id:" + duplicateAcccount.getId());
         }
@@ -1700,6 +1782,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
         return _userDao.remove(deleteUserCmd.getId());
     }
 
+    @Override
     @ActionEvent(eventType = EventTypes.EVENT_USER_MOVE, eventDescription = "moving User to a new account")
     public boolean moveUser(MoveUserCmd cmd) {
         final Long id = cmd.getId();
@@ -1713,17 +1796,18 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
         return moveUser(user, newAccountId);
     }
 
+    @Override
     public boolean moveUser(long id, Long domainId, long accountId) {
         UserVO user = getValidUserVO(id);
         Account oldAccount = _accountDao.findById(user.getAccountId());
         checkAccountAndAccess(user, oldAccount);
         Account newAccount = _accountDao.findById(accountId);
         checkIfNotMovingAcrossDomains(domainId, newAccount);
-        return moveUser(user , accountId);
+        return moveUser(user, accountId);
     }
 
     private boolean moveUser(UserVO user, long newAccountId) {
-        if(newAccountId == user.getAccountId()) {
+        if (newAccountId == user.getAccountId()) {
             // could do a not silent fail but the objective of the user is reached
             return true; // no need to create a new user object for this user
         }
@@ -1734,7 +1818,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
                 UserVO newUser = new UserVO(user);
                 user.setExternalEntity(user.getUuid());
                 user.setUuid(UUID.randomUUID().toString());
-                _userDao.update(user.getId(),user);
+                _userDao.update(user.getId(), user);
                 newUser.setAccountId(newAccountId);
                 boolean success = _userDao.remove(user.getId());
                 UserVO persisted = _userDao.persist(newUser);
@@ -1746,7 +1830,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
     private long getNewAccountId(long domainId, String accountName, Long accountId) {
         Account newAccount = null;
         if (StringUtils.isNotBlank(accountName)) {
-            if(s_logger.isDebugEnabled()) {
+            if (s_logger.isDebugEnabled()) {
                 s_logger.debug("Getting id for account by name '" + accountName + "' in domain " + domainId);
             }
             newAccount = _accountDao.findEnabledAccount(accountName, domainId);
@@ -1763,7 +1847,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
     }
 
     private void checkIfNotMovingAcrossDomains(long domainId, Account newAccount) {
-        if(newAccount.getDomainId() != domainId) {
+        if (newAccount.getDomainId() != domainId) {
             // not in scope
             throw new InvalidParameterValueException("moving a user from an account in one domain to an account in annother domain is not supported!");
         }
@@ -1775,7 +1859,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
             throw new InvalidParameterValueException("Project users cannot be deleted or moved.");
         }
 
-        checkAccess(CallContext.current().getCallingAccount(), AccessType.OperateEntry, true, account);
+        checkAccess(getCurrentCallingAccount(), AccessType.OperateEntry, true, account);
         CallContext.current().putContextParameter(User.class, user.getUuid());
     }
 
@@ -1995,8 +2079,8 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
 
     @Override
     @DB
-    public AccountVO createAccount(final String accountName, final short accountType, final Long roleId, final Long domainId, final String networkDomain,
-            final Map<String, String> details, final String uuid) {
+    public AccountVO createAccount(final String accountName, final short accountType, final Long roleId, final Long domainId, final String networkDomain, final Map<String, String> details,
+            final String uuid) {
         // Validate domain
         Domain domain = _domainMgr.getDomain(domainId);
         if (domain == null) {
@@ -2064,8 +2148,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
         });
     }
 
-    protected UserVO createUser(long accountId, String userName, String password, String firstName, String lastName, String email, String timezone, String userUUID,
-            User.Source source) {
+    protected UserVO createUser(long accountId, String userName, String password, String firstName, String lastName, String email, String timezone, String userUUID, User.Source source) {
         if (s_logger.isDebugEnabled()) {
             s_logger.debug("Creating user: " + userName + ", accountId: " + accountId + " timezone:" + timezone);
         }
@@ -2098,8 +2181,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
     }
 
     @Override
-    public UserAccount authenticateUser(final String username, final String password, final Long domainId, final InetAddress loginIpAddress, final Map<String, Object[]>
-            requestParameters) {
+    public UserAccount authenticateUser(final String username, final String password, final Long domainId, final InetAddress loginIpAddress, final Map<String, Object[]> requestParameters) {
         UserAccount user = null;
         if (password != null && !password.isEmpty()) {
             user = getUserAccount(username, password, domainId, requestParameters);
@@ -2211,10 +2293,10 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
 
             // We authenticated successfully by now, let's check if we are allowed to login from the ip address the reqest comes from
             final Account account = _accountMgr.getAccount(user.getAccountId());
-            final DomainVO domain = (DomainVO) _domainMgr.getDomain(account.getDomainId());
+            final DomainVO domain = (DomainVO)_domainMgr.getDomain(account.getDomainId());
 
             // Get the CIDRs from where this account is allowed to make calls
-            final String accessAllowedCidrs = ApiServiceConfiguration.ApiAllowedSourceCidrList.valueIn(account.getId()).replaceAll("\\s","");
+            final String accessAllowedCidrs = ApiServiceConfiguration.ApiAllowedSourceCidrList.valueIn(account.getId()).replaceAll("\\s", "");
             final Boolean ApiSourceCidrChecksEnabled = ApiServiceConfiguration.ApiSourceCidrChecksEnabled.value();
 
             if (ApiSourceCidrChecksEnabled) {
@@ -2222,10 +2304,9 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
 
                 // Block when is not in the list of allowed IPs
                 if (!NetUtils.isIpInCidrList(loginIpAddress, accessAllowedCidrs.split(","))) {
-                    s_logger.warn("Request by account '" + account.toString() + "' was denied since " + loginIpAddress.toString().replaceAll("/","")
-                            + " does not match " + accessAllowedCidrs);
+                    s_logger.warn("Request by account '" + account.toString() + "' was denied since " + loginIpAddress.toString().replaceAll("/", "") + " does not match " + accessAllowedCidrs);
                     throw new CloudAuthenticationException("Failed to authenticate user '" + username + "' in domain '" + domain.getPath() + "' from ip "
-                            + loginIpAddress.toString().replaceAll("/","") + "; please provide valid credentials");
+                            + loginIpAddress.toString().replaceAll("/", "") + "; please provide valid credentials");
                 }
             }
 
@@ -2234,8 +2315,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
                 s_logger.debug("User: " + username + " in domain " + domainId + " has successfully logged in");
             }
 
-            ActionEventUtils.onActionEvent(user.getId(), user.getAccountId(), user.getDomainId(), EventTypes.EVENT_USER_LOGIN,
-                    "user has logged in from IP Address " + loginIpAddress);
+            ActionEventUtils.onActionEvent(user.getId(), user.getAccountId(), user.getDomainId(), EventTypes.EVENT_USER_LOGIN, "user has logged in from IP Address " + loginIpAddress);
 
             return user;
         } else {
@@ -2285,12 +2365,12 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
                 if (s_logger.isInfoEnabled()) {
                     s_logger.info("User " + username + " in domain " + domainName + " is disabled/locked (or account is disabled/locked)");
                 }
-                throw new CloudAuthenticationException(
-                        "User " + username + " (or their account) in domain " + domainName + " is disabled/locked. Please contact the administrator.");
+                throw new CloudAuthenticationException("User " + username + " (or their account) in domain " + domainName + " is disabled/locked. Please contact the administrator.");
             }
             // Whenever the user is able to log in successfully, reset the login attempts to zero
-            if (!isInternalAccount(userAccount.getId()))
+            if (!isInternalAccount(userAccount.getId())) {
                 updateLoginAttempts(userAccount.getId(), 0, false);
+            }
 
             return userAccount;
         } else {
@@ -2351,7 +2431,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
     @DB
     @ActionEvent(eventType = EventTypes.EVENT_REGISTER_FOR_SECRET_API_KEY, eventDescription = "register for the developer API keys")
     public String[] createApiKeyAndSecretKey(RegisterCmd cmd) {
-        Account caller = CallContext.current().getCallingAccount();
+        Account caller = getCurrentCallingAccount();
         final Long userId = cmd.getId();
 
         User user = getUserIncludingRemoved(userId);
@@ -2668,8 +2748,9 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
 
     @Override
     public List<String> listAclGroupsByAccount(Long accountId) {
-        if (_querySelectors == null || _querySelectors.size() == 0)
+        if (_querySelectors == null || _querySelectors.size() == 0) {
             return new ArrayList<String>();
+        }
 
         QuerySelector qs = _querySelectors.get(0);
         return qs.listAclGroupsByAccount(accountId);
@@ -2692,8 +2773,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
                 if (!enabledOnly || account.getState() == Account.State.enabled) {
                     return account.getId();
                 } else {
-                    throw new PermissionDeniedException(
-                            "Can't add resources to the account id=" + account.getId() + " in state=" + account.getState() + " as it's no longer active");
+                    throw new PermissionDeniedException("Can't add resources to the account id=" + account.getId() + " in state=" + account.getState() + " as it's no longer active");
                 }
             } else {
                 // idList is not used anywhere, so removed it now
diff --git a/server/src/test/java/com/cloud/user/AccountManagerImplTest.java b/server/src/test/java/com/cloud/user/AccountManagerImplTest.java
index 9190cf8..fcb0c57 100644
--- a/server/src/test/java/com/cloud/user/AccountManagerImplTest.java
+++ b/server/src/test/java/com/cloud/user/AccountManagerImplTest.java
@@ -22,67 +22,100 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
-import com.cloud.acl.DomainChecker;
-import com.cloud.exception.PermissionDeniedException;
-import com.cloud.server.auth.UserAuthenticator;
-import com.cloud.utils.Pair;
-
+import org.apache.cloudstack.acl.ControlledEntity;
+import org.apache.cloudstack.acl.SecurityChecker.AccessType;
 import org.apache.cloudstack.api.command.admin.user.GetUserKeysCmd;
+import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd;
 import org.apache.cloudstack.context.CallContext;
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.Mockito;
-import org.apache.cloudstack.acl.ControlledEntity;
-import org.apache.cloudstack.acl.SecurityChecker.AccessType;
-import com.cloud.vm.snapshot.VMSnapshotVO;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import com.cloud.acl.DomainChecker;
 import com.cloud.domain.Domain;
 import com.cloud.domain.DomainVO;
 import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.PermissionDeniedException;
 import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.server.auth.UserAuthenticator;
+import com.cloud.server.auth.UserAuthenticator.ActionOnFailedAuthentication;
 import com.cloud.user.Account.State;
+import com.cloud.utils.Pair;
+import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.vm.UserVmManagerImpl;
 import com.cloud.vm.UserVmVO;
 import com.cloud.vm.VMInstanceVO;
+import com.cloud.vm.snapshot.VMSnapshotVO;
 
-
+@RunWith(MockitoJUnitRunner.class)
 public class AccountManagerImplTest extends AccountManagetImplTestBase {
 
+    @Mock
+    private UserVmManagerImpl _vmMgr;
+    @Mock
+    private AccountVO callingAccount;
+    @Mock
+    private DomainChecker domainChecker;
+    @Mock
+    private AccountService accountService;
+    @Mock
+    private GetUserKeysCmd _listkeyscmd;
+    @Mock
+    private User _user;
+    @Mock
+    private UserAccountVO userAccountVO;
+
+    @Mock
+    private UpdateUserCmd UpdateUserCmdMock;
+
+    private long userVoIdMock = 111l;
+    @Mock
+    private UserVO userVoMock;
 
+    private long accountMockId = 100l;
     @Mock
-    UserVmManagerImpl _vmMgr;
+    private Account accountMock;
+
+    @Before
+    public void beforeTest() {
+        Mockito.doReturn(accountMockId).when(accountMock).getId();
+        Mockito.doReturn(accountMock).when(accountManagerImpl).getCurrentCallingAccount();
+
+        Mockito.doReturn(accountMockId).when(userVoMock).getAccountId();
+
+        Mockito.doReturn(userVoIdMock).when(userVoMock).getId();
+    }
 
     @Test
-    public void disableAccountNotexisting()
-            throws ConcurrentOperationException, ResourceUnavailableException {
-        Mockito.when(_accountDao.findById(42l)).thenReturn(null);
-        Assert.assertTrue(accountManager.disableAccount(42));
+    public void disableAccountNotexisting() throws ConcurrentOperationException, ResourceUnavailableException {
+        Mockito.when(accountDaoMock.findById(42l)).thenReturn(null);
+        Assert.assertTrue(accountManagerImpl.disableAccount(42));
     }
 
     @Test
-    public void disableAccountDisabled() throws ConcurrentOperationException,
-    ResourceUnavailableException {
+    public void disableAccountDisabled() throws ConcurrentOperationException, ResourceUnavailableException {
         AccountVO disabledAccount = new AccountVO();
         disabledAccount.setState(State.disabled);
-        Mockito.when(_accountDao.findById(42l)).thenReturn(disabledAccount);
-        Assert.assertTrue(accountManager.disableAccount(42));
+        Mockito.when(accountDaoMock.findById(42l)).thenReturn(disabledAccount);
+        Assert.assertTrue(accountManagerImpl.disableAccount(42));
     }
 
     @Test
-    public void disableAccount() throws ConcurrentOperationException,
-    ResourceUnavailableException {
+    public void disableAccount() throws ConcurrentOperationException, ResourceUnavailableException {
         AccountVO account = new AccountVO();
         account.setState(State.enabled);
-        Mockito.when(_accountDao.findById(42l)).thenReturn(account);
-        Mockito.when(_accountDao.createForUpdate()).thenReturn(new AccountVO());
-        Mockito.when(
-                _accountDao.update(Mockito.eq(42l),
-                        Mockito.any(AccountVO.class))).thenReturn(true);
-        Mockito.when(_vmDao.listByAccountId(42l)).thenReturn(
-                Arrays.asList(Mockito.mock(VMInstanceVO.class)));
-        Assert.assertTrue(accountManager.disableAccount(42));
-        Mockito.verify(_accountDao, Mockito.atLeastOnce()).update(
-                Mockito.eq(42l), Mockito.any(AccountVO.class));
+        Mockito.when(accountDaoMock.findById(42l)).thenReturn(account);
+        Mockito.when(accountDaoMock.createForUpdate()).thenReturn(new AccountVO());
+        Mockito.when(accountDaoMock.update(Mockito.eq(42l), Mockito.any(AccountVO.class))).thenReturn(true);
+        Mockito.when(_vmDao.listByAccountId(42l)).thenReturn(Arrays.asList(Mockito.mock(VMInstanceVO.class)));
+        Assert.assertTrue(accountManagerImpl.disableAccount(42));
+        Mockito.verify(accountDaoMock, Mockito.atLeastOnce()).update(Mockito.eq(42l), Mockito.any(AccountVO.class));
     }
 
     @Test
@@ -90,20 +123,12 @@ public class AccountManagerImplTest extends AccountManagetImplTestBase {
         AccountVO account = new AccountVO();
         account.setId(42l);
         DomainVO domain = new DomainVO();
-        Mockito.when(_accountDao.findById(42l)).thenReturn(account);
-        Mockito.when(
-                securityChecker.checkAccess(Mockito.any(Account.class),
-                        Mockito.any(ControlledEntity.class), Mockito.any(AccessType.class),
-                        Mockito.anyString()))
-        .thenReturn(true);
-        Mockito.when(_accountDao.remove(42l)).thenReturn(true);
-        Mockito.when(_configMgr.releaseAccountSpecificVirtualRanges(42l))
-        .thenReturn(true);
+        Mockito.when(accountDaoMock.findById(42l)).thenReturn(account);
+        Mockito.when(securityChecker.checkAccess(Mockito.any(Account.class), Mockito.any(ControlledEntity.class), Mockito.any(AccessType.class), Mockito.anyString())).thenReturn(true);
+        Mockito.when(accountDaoMock.remove(42l)).thenReturn(true);
+        Mockito.when(_configMgr.releaseAccountSpecificVirtualRanges(42l)).thenReturn(true);
         Mockito.when(_domainMgr.getDomain(Mockito.anyLong())).thenReturn(domain);
-        Mockito.when(
-                securityChecker.checkAccess(Mockito.any(Account.class),
-                        Mockito.any(Domain.class)))
-        .thenReturn(true);
+        Mockito.when(securityChecker.checkAccess(Mockito.any(Account.class), Mockito.any(Domain.class))).thenReturn(true);
         Mockito.when(_vmSnapshotDao.listByAccountId(Mockito.anyLong())).thenReturn(new ArrayList<VMSnapshotVO>());
 
         List<SSHKeyPairVO> sshkeyList = new ArrayList<SSHKeyPairVO>();
@@ -113,10 +138,9 @@ public class AccountManagerImplTest extends AccountManagetImplTestBase {
         Mockito.when(_sshKeyPairDao.listKeyPairs(Mockito.anyLong(), Mockito.anyLong())).thenReturn(sshkeyList);
         Mockito.when(_sshKeyPairDao.remove(Mockito.anyLong())).thenReturn(true);
 
-        Assert.assertTrue(accountManager.deleteUserAccount(42));
+        Assert.assertTrue(accountManagerImpl.deleteUserAccount(42));
         // assert that this was a clean delete
-        Mockito.verify(_accountDao, Mockito.never()).markForCleanup(
-                Mockito.eq(42l));
+        Mockito.verify(accountDaoMock, Mockito.never()).markForCleanup(Mockito.eq(42l));
     }
 
     @Test
@@ -124,33 +148,20 @@ public class AccountManagerImplTest extends AccountManagetImplTestBase {
         AccountVO account = new AccountVO();
         account.setId(42l);
         DomainVO domain = new DomainVO();
-        Mockito.when(_accountDao.findById(42l)).thenReturn(account);
-        Mockito.when(
-                securityChecker.checkAccess(Mockito.any(Account.class),
-                        Mockito.any(ControlledEntity.class), Mockito.any(AccessType.class),
-                        Mockito.anyString()))
-        .thenReturn(true);
-        Mockito.when(_accountDao.remove(42l)).thenReturn(true);
-        Mockito.when(_configMgr.releaseAccountSpecificVirtualRanges(42l))
-        .thenReturn(true);
-        Mockito.when(_userVmDao.listByAccountId(42l)).thenReturn(
-                Arrays.asList(Mockito.mock(UserVmVO.class)));
-        Mockito.when(
-                _vmMgr.expunge(Mockito.any(UserVmVO.class), Mockito.anyLong(),
-                        Mockito.any(Account.class))).thenReturn(false);
+        Mockito.when(accountDaoMock.findById(42l)).thenReturn(account);
+        Mockito.when(securityChecker.checkAccess(Mockito.any(Account.class), Mockito.any(ControlledEntity.class), Mockito.any(AccessType.class), Mockito.anyString())).thenReturn(true);
+        Mockito.when(accountDaoMock.remove(42l)).thenReturn(true);
+        Mockito.when(_configMgr.releaseAccountSpecificVirtualRanges(42l)).thenReturn(true);
+        Mockito.when(_userVmDao.listByAccountId(42l)).thenReturn(Arrays.asList(Mockito.mock(UserVmVO.class)));
+        Mockito.when(_vmMgr.expunge(Mockito.any(UserVmVO.class), Mockito.anyLong(), Mockito.any(Account.class))).thenReturn(false);
         Mockito.when(_domainMgr.getDomain(Mockito.anyLong())).thenReturn(domain);
-        Mockito.when(
-                securityChecker.checkAccess(Mockito.any(Account.class),
-                        Mockito.any(Domain.class)))
-        .thenReturn(true);
+        Mockito.when(securityChecker.checkAccess(Mockito.any(Account.class), Mockito.any(Domain.class))).thenReturn(true);
 
-        Assert.assertTrue(accountManager.deleteUserAccount(42));
+        Assert.assertTrue(accountManagerImpl.deleteUserAccount(42));
         // assert that this was NOT a clean delete
-        Mockito.verify(_accountDao, Mockito.atLeastOnce()).markForCleanup(
-                Mockito.eq(42l));
+        Mockito.verify(accountDaoMock, Mockito.atLeastOnce()).markForCleanup(Mockito.eq(42l));
     }
 
-
     @Test
     public void testAuthenticateUser() throws UnknownHostException {
         Pair<Boolean, UserAuthenticator.ActionOnFailedAuthentication> successAuthenticationPair = new Pair<>(true, null);
@@ -160,21 +171,21 @@ public class AccountManagerImplTest extends AccountManagetImplTestBase {
         UserAccountVO userAccountVO = new UserAccountVO();
         userAccountVO.setSource(User.Source.UNKNOWN);
         userAccountVO.setState(Account.State.disabled.toString());
-        Mockito.when(_userAccountDao.getUserAccount("test", 1L)).thenReturn(userAccountVO);
+        Mockito.when(userAccountDaoMock.getUserAccount("test", 1L)).thenReturn(userAccountVO);
         Mockito.when(userAuthenticator.authenticate("test", "fail", 1L, null)).thenReturn(failureAuthenticationPair);
         Mockito.when(userAuthenticator.authenticate("test", null, 1L, null)).thenReturn(successAuthenticationPair);
         Mockito.when(userAuthenticator.authenticate("test", "", 1L, null)).thenReturn(successAuthenticationPair);
 
         //Test for incorrect password. authentication should fail
-        UserAccount userAccount = accountManager.authenticateUser("test", "fail", 1L, InetAddress.getByName("127.0.0.1"), null);
+        UserAccount userAccount = accountManagerImpl.authenticateUser("test", "fail", 1L, InetAddress.getByName("127.0.0.1"), null);
         Assert.assertNull(userAccount);
 
         //Test for null password. authentication should fail
-        userAccount = accountManager.authenticateUser("test", null, 1L, InetAddress.getByName("127.0.0.1"), null);
+        userAccount = accountManagerImpl.authenticateUser("test", null, 1L, InetAddress.getByName("127.0.0.1"), null);
         Assert.assertNull(userAccount);
 
         //Test for empty password. authentication should fail
-        userAccount = accountManager.authenticateUser("test", "", 1L, InetAddress.getByName("127.0.0.1"), null);
+        userAccount = accountManagerImpl.authenticateUser("test", "", 1L, InetAddress.getByName("127.0.0.1"), null);
         Assert.assertNull(userAccount);
 
         //Verifying that the authentication method is only called when password is specified
@@ -183,38 +194,509 @@ public class AccountManagerImplTest extends AccountManagetImplTestBase {
         Mockito.verify(userAuthenticator, Mockito.never()).authenticate("test", "", 1L, null);
     }
 
-    @Mock
-    AccountVO callingAccount;
-    @Mock
-    DomainChecker domainChecker;
-    @Mock
-    AccountService accountService;
-    @Mock
-    private GetUserKeysCmd _listkeyscmd;
-    @Mock
-    private Account _account;
-    @Mock
-    private User _user;
-    @Mock
-    private UserAccountVO userAccountVO;
-
-
-    @Test (expected = PermissionDeniedException.class)
-    public void testgetUserCmd(){
+    @Test(expected = PermissionDeniedException.class)
+    public void testgetUserCmd() {
         CallContext.register(callingUser, callingAccount); // Calling account is user account i.e normal account
         Mockito.when(_listkeyscmd.getID()).thenReturn(1L);
-        Mockito.when(accountManager.getActiveUser(1L)).thenReturn(_user);
-        Mockito.when(accountManager.getUserAccountById(1L)).thenReturn(userAccountVO);
+        Mockito.when(accountManagerImpl.getActiveUser(1L)).thenReturn(_user);
+        Mockito.when(accountManagerImpl.getUserAccountById(1L)).thenReturn(userAccountVO);
         Mockito.when(userAccountVO.getAccountId()).thenReturn(1L);
-        Mockito.when(accountManager.getAccount(Mockito.anyLong())).thenReturn(_account); // Queried account - admin account
+        Mockito.when(accountManagerImpl.getAccount(Mockito.anyLong())).thenReturn(accountMock); // Queried account - admin account
 
         Mockito.when(callingUser.getAccountId()).thenReturn(1L);
-        Mockito.when(_accountDao.findById(1L)).thenReturn(callingAccount);
+        Mockito.when(accountDaoMock.findById(1L)).thenReturn(callingAccount);
 
         Mockito.when(accountService.isNormalUser(Mockito.anyLong())).thenReturn(Boolean.TRUE);
-        Mockito.when(_account.getAccountId()).thenReturn(2L);
+        Mockito.when(accountMock.getAccountId()).thenReturn(2L);
+
+        accountManagerImpl.getKeys(_listkeyscmd);
+    }
+
+    @Test
+    public void updateUserTestTimeZoneAndEmailNull() {
+        prepareMockAndExecuteUpdateUserTest(0);
+    }
+
+    @Test
+    public void updateUserTestTimeZoneAndEmailNotNull() {
+        Mockito.when(UpdateUserCmdMock.getEmail()).thenReturn("email");
+        Mockito.when(UpdateUserCmdMock.getTimezone()).thenReturn("timezone");
+        prepareMockAndExecuteUpdateUserTest(1);
+    }
+
+    private void prepareMockAndExecuteUpdateUserTest(int numberOfExpectedCallsForSetEmailAndSetTimeZone) {
+        Mockito.doReturn(userVoMock).when(accountManagerImpl).retrieveAndValidateUser(UpdateUserCmdMock);
+        Mockito.doNothing().when(accountManagerImpl).validateAndUpdatApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
+        Mockito.doReturn(accountMock).when(accountManagerImpl).retrieveAndValidateAccount(userVoMock);
+
+        Mockito.doNothing().when(accountManagerImpl).validateAndUpdateFirstNameIfNeeded(UpdateUserCmdMock, userVoMock);
+        Mockito.doNothing().when(accountManagerImpl).validateAndUpdateLastNameIfNeeded(UpdateUserCmdMock, userVoMock);
+        Mockito.doNothing().when(accountManagerImpl).validateAndUpdateUsernameIfNeeded(UpdateUserCmdMock, userVoMock, accountMock);
+        Mockito.doNothing().when(accountManagerImpl).validateUserPasswordAndUpdateIfNeeded(Mockito.anyString(), Mockito.eq(userVoMock), Mockito.anyString());
+
+        Mockito.doReturn(true).when(userDaoMock).update(Mockito.anyLong(), Mockito.eq(userVoMock));
+        Mockito.doReturn(Mockito.mock(UserAccountVO.class)).when(userAccountDaoMock).findById(Mockito.anyLong());
+
+        accountManagerImpl.updateUser(UpdateUserCmdMock);
+
+        InOrder inOrder = Mockito.inOrder(userVoMock, accountManagerImpl, userDaoMock, userAccountDaoMock);
+
+        inOrder.verify(accountManagerImpl).retrieveAndValidateUser(UpdateUserCmdMock);
+        inOrder.verify(accountManagerImpl).validateAndUpdatApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
+        inOrder.verify(accountManagerImpl).retrieveAndValidateAccount(userVoMock);
+
+        inOrder.verify(accountManagerImpl).validateAndUpdateFirstNameIfNeeded(UpdateUserCmdMock, userVoMock);
+        inOrder.verify(accountManagerImpl).validateAndUpdateLastNameIfNeeded(UpdateUserCmdMock, userVoMock);
+        inOrder.verify(accountManagerImpl).validateAndUpdateUsernameIfNeeded(UpdateUserCmdMock, userVoMock, accountMock);
+        inOrder.verify(accountManagerImpl).validateUserPasswordAndUpdateIfNeeded(Mockito.anyString(), Mockito.eq(userVoMock), Mockito.anyString());
+
+        inOrder.verify(userVoMock, Mockito.times(numberOfExpectedCallsForSetEmailAndSetTimeZone)).setEmail(Mockito.anyString());
+        inOrder.verify(userVoMock, Mockito.times(numberOfExpectedCallsForSetEmailAndSetTimeZone)).setTimezone(Mockito.anyString());
+
+        inOrder.verify(userDaoMock).update(Mockito.anyLong(), Mockito.eq(userVoMock));
+        inOrder.verify(userAccountDaoMock).findById(Mockito.anyLong());
+    }
+
+    @Test(expected = InvalidParameterValueException.class)
+    public void retrieveAndValidateUserTestNoUserFound() {
+        Mockito.doReturn(null).when(userDaoMock).getUser(Mockito.anyLong());
+
+        accountManagerImpl.retrieveAndValidateUser(UpdateUserCmdMock);
+    }
+
+    @Test
+    public void retrieveAndValidateUserTestUserIsFound() {
+        Mockito.doReturn(userVoMock).when(userDaoMock).getUser(Mockito.anyLong());
+
+        UserVO receivedUser = accountManagerImpl.retrieveAndValidateUser(UpdateUserCmdMock);
+
+        Assert.assertEquals(userVoMock, receivedUser);
+    }
+
+    @Test
+    public void validateAndUpdatApiAndSecretKeyIfNeededTestNoKeys() {
+        accountManagerImpl.validateAndUpdatApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
+
+        Mockito.verify(accountDaoMock, Mockito.times(0)).findUserAccountByApiKey(Mockito.anyString());
+    }
+
+    @Test(expected = InvalidParameterValueException.class)
+    public void validateAndUpdatApiAndSecretKeyIfNeededTestOnlyApiKeyInformed() {
+        Mockito.doReturn("apiKey").when(UpdateUserCmdMock).getApiKey();
+
+        accountManagerImpl.validateAndUpdatApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
+    }
+
+    @Test(expected = InvalidParameterValueException.class)
+    public void validateAndUpdatApiAndSecretKeyIfNeededTestOnlySecretKeyInformed() {
+        Mockito.doReturn("secretKey").when(UpdateUserCmdMock).getSecretKey();
+
+        accountManagerImpl.validateAndUpdatApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
+    }
+
+    @Test(expected = InvalidParameterValueException.class)
+    public void validateAndUpdatApiAndSecretKeyIfNeededTestApiKeyAlreadyUsedBySomeoneElse() {
+        String apiKey = "apiKey";
+        Mockito.doReturn(apiKey).when(UpdateUserCmdMock).getApiKey();
+        Mockito.doReturn("secretKey").when(UpdateUserCmdMock).getSecretKey();
+
+        Mockito.doReturn(1L).when(userVoMock).getId();
+
+        User otherUserMock = Mockito.mock(User.class);
+        Mockito.doReturn(2L).when(otherUserMock).getId();
+
+        Pair<User, Account> pairUserAccountMock = new Pair<User, Account>(otherUserMock, Mockito.mock(Account.class));
+        Mockito.doReturn(pairUserAccountMock).when(accountDaoMock).findUserAccountByApiKey(apiKey);
+
+        accountManagerImpl.validateAndUpdatApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
+    }
+
+    @Test
+    public void validateAndUpdatApiAndSecretKeyIfNeededTest() {
+        String apiKey = "apiKey";
+        Mockito.doReturn(apiKey).when(UpdateUserCmdMock).getApiKey();
+
+        String secretKey = "secretKey";
+        Mockito.doReturn(secretKey).when(UpdateUserCmdMock).getSecretKey();
+
+        Mockito.doReturn(1L).when(userVoMock).getId();
+
+        User otherUserMock = Mockito.mock(User.class);
+        Mockito.doReturn(1L).when(otherUserMock).getId();
+
+        Pair<User, Account> pairUserAccountMock = new Pair<User, Account>(otherUserMock, Mockito.mock(Account.class));
+        Mockito.doReturn(pairUserAccountMock).when(accountDaoMock).findUserAccountByApiKey(apiKey);
+
+        accountManagerImpl.validateAndUpdatApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
+
+        Mockito.verify(accountDaoMock).findUserAccountByApiKey(apiKey);
+        Mockito.verify(userVoMock).setApiKey(apiKey);
+        Mockito.verify(userVoMock).setSecretKey(secretKey);
+    }
+
+    @Test(expected = CloudRuntimeException.class)
+    public void retrieveAndValidateAccountTestAccountNotFound() {
+        Mockito.doReturn(accountMockId).when(userVoMock).getAccountId();
+
+        Mockito.doReturn(null).when(accountDaoMock).findById(accountMockId);
+
+        accountManagerImpl.retrieveAndValidateAccount(userVoMock);
+    }
+
+    @Test(expected = InvalidParameterValueException.class)
+    public void retrieveAndValidateAccountTestAccountTypeEqualsProjectType() {
+        Mockito.doReturn(accountMockId).when(userVoMock).getAccountId();
+        Mockito.doReturn(Account.ACCOUNT_TYPE_PROJECT).when(accountMock).getType();
+        Mockito.doReturn(accountMock).when(accountDaoMock).findById(accountMockId);
+
+        accountManagerImpl.retrieveAndValidateAccount(userVoMock);
+    }
+
+    @Test(expected = PermissionDeniedException.class)
+    public void retrieveAndValidateAccountTestAccountTypeEqualsSystemType() {
+        Mockito.doReturn(Account.ACCOUNT_ID_SYSTEM).when(userVoMock).getAccountId();
+        Mockito.doReturn(Account.ACCOUNT_ID_SYSTEM).when(accountMock).getId();
+        Mockito.doReturn(accountMock).when(accountDaoMock).findById(Account.ACCOUNT_ID_SYSTEM);
+
+        accountManagerImpl.retrieveAndValidateAccount(userVoMock);
+    }
+
+    @Test
+    public void retrieveAndValidateAccountTest() {
+        Mockito.doReturn(accountMockId).when(userVoMock).getAccountId();
+        Mockito.doReturn(accountMock).when(accountDaoMock).findById(accountMockId);
+
+        Mockito.doNothing().when(accountManagerImpl).checkAccess(Mockito.eq(accountMock), Mockito.eq(AccessType.OperateEntry), Mockito.anyBoolean(), Mockito.any(Account.class));
+        accountManagerImpl.retrieveAndValidateAccount(userVoMock);
+
+        Mockito.verify(accountManagerImpl).getCurrentCallingAccount();
+        Mockito.verify(accountManagerImpl).checkAccess(Mockito.eq(accountMock), Mockito.eq(AccessType.OperateEntry), Mockito.anyBoolean(), Mockito.any(Account.class));
+    }
+
+    @Test(expected = InvalidParameterValueException.class)
+    public void validateAndUpdateFirstNameIfNeededTestFirstNameBlank() {
+        Mockito.doReturn("   ").when(UpdateUserCmdMock).getFirstname();
+
+        accountManagerImpl.validateAndUpdateFirstNameIfNeeded(UpdateUserCmdMock, userVoMock);
+    }
+
+    @Test
+    public void validateAndUpdateFirstNameIfNeededTestFirstNameNull() {
+        Mockito.doReturn(null).when(UpdateUserCmdMock).getFirstname();
+
+        accountManagerImpl.validateAndUpdateFirstNameIfNeeded(UpdateUserCmdMock, userVoMock);
+
+        Mockito.verify(userVoMock, Mockito.times(0)).setFirstname(Mockito.anyString());
+    }
 
-        accountManager.getKeys(_listkeyscmd);
+    @Test
+    public void validateAndUpdateFirstNameIfNeededTest() {
+        String firstname = "firstName";
+        Mockito.doReturn(firstname).when(UpdateUserCmdMock).getFirstname();
+
+        accountManagerImpl.validateAndUpdateFirstNameIfNeeded(UpdateUserCmdMock, userVoMock);
+
+        Mockito.verify(userVoMock).setFirstname(firstname);
+    }
+
+    @Test(expected = InvalidParameterValueException.class)
+    public void validateAndUpdateLastNameIfNeededTestLastNameBlank() {
+        Mockito.doReturn("   ").when(UpdateUserCmdMock).getLastname();
+
+        accountManagerImpl.validateAndUpdateLastNameIfNeeded(UpdateUserCmdMock, userVoMock);
+    }
+
+    @Test
+    public void validateAndUpdateLastNameIfNeededTestLastNameNull() {
+        Mockito.doReturn(null).when(UpdateUserCmdMock).getLastname();
+
+        accountManagerImpl.validateAndUpdateLastNameIfNeeded(UpdateUserCmdMock, userVoMock);
+
+        Mockito.verify(userVoMock, Mockito.times(0)).setLastname(Mockito.anyString());
+    }
+
+    @Test
+    public void validateAndUpdateLastNameIfNeededTest() {
+        String lastName = "lastName";
+        Mockito.doReturn(lastName).when(UpdateUserCmdMock).getLastname();
+
+        accountManagerImpl.validateAndUpdateLastNameIfNeeded(UpdateUserCmdMock, userVoMock);
+
+        Mockito.verify(userVoMock).setLastname(lastName);
+    }
+
+    @Test
+    public void validateAndUpdateUsernameIfNeededTestNullUsername() {
+        Mockito.doReturn(null).when(UpdateUserCmdMock).getUsername();
+
+        accountManagerImpl.validateAndUpdateUsernameIfNeeded(UpdateUserCmdMock, userVoMock, accountMock);
+
+        Mockito.verify(userVoMock, Mockito.times(0)).setUsername(Mockito.anyString());
+    }
+
+    @Test(expected = InvalidParameterValueException.class)
+    public void validateAndUpdateUsernameIfNeededTestBlankUsername() {
+        Mockito.doReturn("   ").when(UpdateUserCmdMock).getUsername();
+
+        accountManagerImpl.validateAndUpdateUsernameIfNeeded(UpdateUserCmdMock, userVoMock, accountMock);
+    }
+
+    @Test(expected = InvalidParameterValueException.class)
+    public void validateAndUpdateUsernameIfNeededTestDuplicatedUserSameDomainThisUser() {
+        long domanIdCurrentUser = 22l;
+
+        String userName = "username";
+        Mockito.doReturn(userName).when(UpdateUserCmdMock).getUsername();
+        Mockito.doReturn(userName).when(userVoMock).getUsername();
+        Mockito.doReturn(domanIdCurrentUser).when(accountMock).getDomainId();
+
+        long userVoDuplicatedMockId = 67l;
+        UserVO userVoDuplicatedMock = Mockito.mock(UserVO.class);
+        Mockito.doReturn(userName).when(userVoDuplicatedMock).getUsername();
+        Mockito.doReturn(userVoDuplicatedMockId).when(userVoDuplicatedMock).getId();
+
+        long accountIdUserDuplicated = 98l;
+        Mockito.doReturn(accountIdUserDuplicated).when(userVoDuplicatedMock).getAccountId();
+
+        Account accountUserDuplicatedMock = Mockito.mock(Account.class);
+        Mockito.doReturn(accountIdUserDuplicated).when(accountUserDuplicatedMock).getId();
+        Mockito.doReturn(domanIdCurrentUser).when(accountUserDuplicatedMock).getDomainId();
+
+        List<UserVO> usersWithSameUserName = new ArrayList<>();
+        usersWithSameUserName.add(userVoMock);
+        usersWithSameUserName.add(userVoDuplicatedMock);
+
+        Mockito.doReturn(usersWithSameUserName).when(userDaoMock).findUsersByName(userName);
+
+        Mockito.doReturn(accountMock).when(accountDaoMock).findById(accountMockId);
+        Mockito.doReturn(accountUserDuplicatedMock).when(accountDaoMock).findById(accountIdUserDuplicated);
+
+        Mockito.doReturn(Mockito.mock(DomainVO.class)).when(_domainDao).findById(Mockito.anyLong());
+
+        accountManagerImpl.validateAndUpdateUsernameIfNeeded(UpdateUserCmdMock, userVoMock, accountMock);
+    }
+
+    @Test
+    public void validateAndUpdateUsernameIfNeededTestDuplicatedUserButInDifferentDomains() {
+        long domanIdCurrentUser = 22l;
+
+        String userName = "username";
+        Mockito.doReturn(userName).when(UpdateUserCmdMock).getUsername();
+        Mockito.doReturn(userName).when(userVoMock).getUsername();
+        Mockito.doReturn(domanIdCurrentUser).when(accountMock).getDomainId();
+
+        long userVoDuplicatedMockId = 67l;
+        UserVO userVoDuplicatedMock = Mockito.mock(UserVO.class);
+        Mockito.doReturn(userName).when(userVoDuplicatedMock).getUsername();
+        Mockito.doReturn(userVoDuplicatedMockId).when(userVoDuplicatedMock).getId();
+
+        long accountIdUserDuplicated = 98l;
+        Mockito.doReturn(accountIdUserDuplicated).when(userVoDuplicatedMock).getAccountId();
+
+        Account accountUserDuplicatedMock = Mockito.mock(Account.class);
+        Mockito.doReturn(accountIdUserDuplicated).when(accountUserDuplicatedMock).getId();
+        Mockito.doReturn(45l).when(accountUserDuplicatedMock).getDomainId();
+
+        List<UserVO> usersWithSameUserName = new ArrayList<>();
+        usersWithSameUserName.add(userVoMock);
+        usersWithSameUserName.add(userVoDuplicatedMock);
+
+        Mockito.doReturn(usersWithSameUserName).when(userDaoMock).findUsersByName(userName);
+
+        Mockito.doReturn(accountMock).when(accountDaoMock).findById(accountMockId);
+        Mockito.doReturn(accountUserDuplicatedMock).when(accountDaoMock).findById(accountIdUserDuplicated);
+
+        accountManagerImpl.validateAndUpdateUsernameIfNeeded(UpdateUserCmdMock, userVoMock, accountMock);
+
+        Mockito.verify(userVoMock).setUsername(userName);
+    }
+
+    @Test
+    public void validateAndUpdateUsernameIfNeededTestNoDuplicatedUserNames() {
+        long domanIdCurrentUser = 22l;
+
+        String userName = "username";
+        Mockito.doReturn(userName).when(UpdateUserCmdMock).getUsername();
+        Mockito.doReturn(userName).when(userVoMock).getUsername();
+        Mockito.doReturn(domanIdCurrentUser).when(accountMock).getDomainId();
+
+        List<UserVO> usersWithSameUserName = new ArrayList<>();
+
+        Mockito.doReturn(usersWithSameUserName).when(userDaoMock).findUsersByName(userName);
+
+        Mockito.doReturn(accountMock).when(accountDaoMock).findById(accountMockId);
+
+        accountManagerImpl.validateAndUpdateUsernameIfNeeded(UpdateUserCmdMock, userVoMock, accountMock);
+
+        Mockito.verify(userVoMock).setUsername(userName);
+    }
+
+    @Test
+    public void valiateUserPasswordAndUpdateIfNeededTestPasswordNull() {
+        accountManagerImpl.validateUserPasswordAndUpdateIfNeeded(null, userVoMock, null);
+
+        Mockito.verify(userVoMock, Mockito.times(0)).setPassword(Mockito.anyString());
+    }
+
+    @Test(expected = InvalidParameterValueException.class)
+    public void valiateUserPasswordAndUpdateIfNeededTestBlankPassword() {
+        accountManagerImpl.validateUserPasswordAndUpdateIfNeeded("       ", userVoMock, null);
+    }
+
+    @Test(expected = InvalidParameterValueException.class)
+    public void valiateUserPasswordAndUpdateIfNeededTestNoAdminAndNoCurrentPasswordProvided() {
+        Mockito.doReturn(accountMock).when(accountManagerImpl).getCurrentCallingAccount();
+        Mockito.doReturn(false).when(accountManagerImpl).isRootAdmin(accountMockId);
+        Mockito.doReturn(false).when(accountManagerImpl).isDomainAdmin(accountMockId);
+        Mockito.doReturn(true).when(accountManagerImpl).isResourceDomainAdmin(accountMockId);
+
+        accountManagerImpl.validateUserPasswordAndUpdateIfNeeded("newPassword", userVoMock, "  ");
+    }
+
+    @Test(expected = CloudRuntimeException.class)
+    public void valiateUserPasswordAndUpdateIfNeededTestNoUserAuthenticatorsConfigured() {
+        Mockito.doReturn(accountMock).when(accountManagerImpl).getCurrentCallingAccount();
+        Mockito.doReturn(true).when(accountManagerImpl).isRootAdmin(accountMockId);
+        Mockito.doReturn(false).when(accountManagerImpl).isDomainAdmin(accountMockId);
+
+        Mockito.doNothing().when(accountManagerImpl).validateCurrentPassword(Mockito.eq(userVoMock), Mockito.anyString());
+
+        accountManagerImpl.validateUserPasswordAndUpdateIfNeeded("newPassword", userVoMock, null);
+    }
+
+    @Test
+    public void validateUserPasswordAndUpdateIfNeededTestRootAdminUpdatingUserPassword() {
+        Mockito.doReturn(accountMock).when(accountManagerImpl).getCurrentCallingAccount();
+        Mockito.doReturn(true).when(accountManagerImpl).isRootAdmin(accountMockId);
+        Mockito.doReturn(false).when(accountManagerImpl).isDomainAdmin(accountMockId);
+
+        String newPassword = "newPassword";
+
+        String expectedUserPasswordAfterEncoded = configureUserMockAuthenticators(newPassword);
+
+        Mockito.doNothing().when(accountManagerImpl).validateCurrentPassword(Mockito.eq(userVoMock), Mockito.anyString());
+
+        accountManagerImpl.validateUserPasswordAndUpdateIfNeeded(newPassword, userVoMock, null);
+
+        Mockito.verify(accountManagerImpl, Mockito.times(0)).validateCurrentPassword(Mockito.eq(userVoMock), Mockito.anyString());
+        Mockito.verify(userVoMock, Mockito.times(1)).setPassword(expectedUserPasswordAfterEncoded);
+    }
+
+    @Test
+    public void validateUserPasswordAndUpdateIfNeededTestDomainAdminUpdatingUserPassword() {
+        Mockito.doReturn(accountMock).when(accountManagerImpl).getCurrentCallingAccount();
+        Mockito.doReturn(false).when(accountManagerImpl).isRootAdmin(accountMockId);
+        Mockito.doReturn(true).when(accountManagerImpl).isDomainAdmin(accountMockId);
+
+        String newPassword = "newPassword";
+
+        String expectedUserPasswordAfterEncoded = configureUserMockAuthenticators(newPassword);
+
+        Mockito.doNothing().when(accountManagerImpl).validateCurrentPassword(Mockito.eq(userVoMock), Mockito.anyString());
+
+        accountManagerImpl.validateUserPasswordAndUpdateIfNeeded(newPassword, userVoMock, null);
+
+        Mockito.verify(accountManagerImpl, Mockito.times(0)).validateCurrentPassword(Mockito.eq(userVoMock), Mockito.anyString());
+        Mockito.verify(userVoMock, Mockito.times(1)).setPassword(expectedUserPasswordAfterEncoded);
+    }
+
+    @Test
+    public void validateUserPasswordAndUpdateIfNeededTestUserUpdatingHisPassword() {
+        Mockito.doReturn(accountMock).when(accountManagerImpl).getCurrentCallingAccount();
+        Mockito.doReturn(false).when(accountManagerImpl).isRootAdmin(accountMockId);
+        Mockito.doReturn(false).when(accountManagerImpl).isDomainAdmin(accountMockId);
+
+        String newPassword = "newPassword";
+        String expectedUserPasswordAfterEncoded = configureUserMockAuthenticators(newPassword);
+
+        Mockito.doNothing().when(accountManagerImpl).validateCurrentPassword(Mockito.eq(userVoMock), Mockito.anyString());
+
+        String currentPassword = "theCurrentPassword";
+        accountManagerImpl.validateUserPasswordAndUpdateIfNeeded(newPassword, userVoMock, currentPassword);
+
+        Mockito.verify(accountManagerImpl, Mockito.times(1)).validateCurrentPassword(userVoMock, currentPassword);
+        Mockito.verify(userVoMock, Mockito.times(1)).setPassword(expectedUserPasswordAfterEncoded);
+    }
+
+    private String configureUserMockAuthenticators(String newPassword) {
+        accountManagerImpl._userPasswordEncoders = new ArrayList<>();
+        UserAuthenticator authenticatorMock1 = Mockito.mock(UserAuthenticator.class);
+        String expectedUserPasswordAfterEncoded = "passwordEncodedByAuthenticator1";
+        Mockito.doReturn(expectedUserPasswordAfterEncoded).when(authenticatorMock1).encode(newPassword);
+
+        UserAuthenticator authenticatorMock2 = Mockito.mock(UserAuthenticator.class);
+        Mockito.doReturn("passwordEncodedByAuthenticator2").when(authenticatorMock2).encode(newPassword);
+
+        accountManagerImpl._userPasswordEncoders.add(authenticatorMock1);
+        accountManagerImpl._userPasswordEncoders.add(authenticatorMock2);
+        return expectedUserPasswordAfterEncoded;
+    }
+
+    @Test(expected = InvalidParameterValueException.class)
+    public void validateCurrentPasswordTestUserNotAuthenticatedWithProvidedCurrentPassword() {
+        Mockito.doReturn(Mockito.mock(AccountVO.class)).when(accountDaoMock).findById(accountMockId);
+        String newPassword = "newPassword";
+        configureUserMockAuthenticators(newPassword);
+
+        accountManagerImpl.validateCurrentPassword(userVoMock, "currentPassword");
+    }
+
+    @Test
+    public void validateCurrentPasswordTestUserAuthenticatedWithProvidedCurrentPasswordViaFirstAuthenticator() {
+        AccountVO accountVoMock = Mockito.mock(AccountVO.class);
+        long domainId = 14l;
+        Mockito.doReturn(domainId).when(accountVoMock).getDomainId();
+
+        Mockito.doReturn(accountVoMock).when(accountDaoMock).findById(accountMockId);
+        String username = "username";
+        Mockito.doReturn(username).when(userVoMock).getUsername();
+
+        accountManagerImpl._userPasswordEncoders = new ArrayList<>();
+        UserAuthenticator authenticatorMock1 = Mockito.mock(UserAuthenticator.class);
+        UserAuthenticator authenticatorMock2 = Mockito.mock(UserAuthenticator.class);
+
+        accountManagerImpl._userPasswordEncoders.add(authenticatorMock1);
+        accountManagerImpl._userPasswordEncoders.add(authenticatorMock2);
+
+        Pair<Boolean, ActionOnFailedAuthentication> authenticationResult = new Pair<Boolean, UserAuthenticator.ActionOnFailedAuthentication>(true,
+                UserAuthenticator.ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT);
+
+        String currentPassword = "currentPassword";
+        Mockito.doReturn(authenticationResult).when(authenticatorMock1).authenticate(username, currentPassword, domainId, null);
+
+        accountManagerImpl.validateCurrentPassword(userVoMock, currentPassword);
+
+        Mockito.verify(authenticatorMock1, Mockito.times(1)).authenticate(username, currentPassword, domainId, null);
+        Mockito.verify(authenticatorMock2, Mockito.times(0)).authenticate(username, currentPassword, domainId, null);
+    }
+
+    @Test
+    public void validateCurrentPasswordTestUserAuthenticatedWithProvidedCurrentPasswordViaSecondAuthenticator() {
+        AccountVO accountVoMock = Mockito.mock(AccountVO.class);
+        long domainId = 14l;
+        Mockito.doReturn(domainId).when(accountVoMock).getDomainId();
+
+        Mockito.doReturn(accountVoMock).when(accountDaoMock).findById(accountMockId);
+        String username = "username";
+        Mockito.doReturn(username).when(userVoMock).getUsername();
+
+        accountManagerImpl._userPasswordEncoders = new ArrayList<>();
+        UserAuthenticator authenticatorMock1 = Mockito.mock(UserAuthenticator.class);
+        UserAuthenticator authenticatorMock2 = Mockito.mock(UserAuthenticator.class);
+
+        accountManagerImpl._userPasswordEncoders.add(authenticatorMock1);
+        accountManagerImpl._userPasswordEncoders.add(authenticatorMock2);
+
+        Pair<Boolean, ActionOnFailedAuthentication> authenticationResult = new Pair<Boolean, UserAuthenticator.ActionOnFailedAuthentication>(true,
+                UserAuthenticator.ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT);
+
+        String currentPassword = "currentPassword";
+        Mockito.doReturn(authenticationResult).when(authenticatorMock2).authenticate(username, currentPassword, domainId, null);
+
+        accountManagerImpl.validateCurrentPassword(userVoMock, currentPassword);
+
+        Mockito.verify(authenticatorMock1, Mockito.times(1)).authenticate(username, currentPassword, domainId, null);
+        Mockito.verify(authenticatorMock2, Mockito.times(1)).authenticate(username, currentPassword, domainId, null);
+    }
 
-        }
 }
diff --git a/server/src/test/java/com/cloud/user/AccountManagerImplVolumeDeleteEventTest.java b/server/src/test/java/com/cloud/user/AccountManagerImplVolumeDeleteEventTest.java
index 2397713..48eb473 100644
--- a/server/src/test/java/com/cloud/user/AccountManagerImplVolumeDeleteEventTest.java
+++ b/server/src/test/java/com/cloud/user/AccountManagerImplVolumeDeleteEventTest.java
@@ -16,12 +16,12 @@
 // under the License.
 package com.cloud.user;
 
-import static org.mockito.Mockito.when;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyLong;
-import static org.mockito.Mockito.anyString;
-import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.when;
 
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
@@ -52,13 +52,12 @@ import com.cloud.exception.AgentUnavailableException;
 import com.cloud.exception.CloudException;
 import com.cloud.exception.ConcurrentOperationException;
 import com.cloud.service.ServiceOfferingVO;
-import com.cloud.storage.VolumeVO;
 import com.cloud.storage.Volume.Type;
+import com.cloud.storage.VolumeVO;
 import com.cloud.vm.UserVmManagerImpl;
 import com.cloud.vm.UserVmVO;
 import com.cloud.vm.VirtualMachine;
 
-
 public class AccountManagerImplVolumeDeleteEventTest extends AccountManagetImplTestBase {
 
     private static final Long ACCOUNT_ID = 1l;
@@ -70,12 +69,10 @@ public class AccountManagerImplVolumeDeleteEventTest extends AccountManagetImplT
     Map<String, Object> oldFields = new HashMap<>();
     UserVmVO vm = mock(UserVmVO.class);
 
-
     // Configures the static fields of the UsageEventUtils class, Storing the
     // previous values to be restored during the cleanup phase, to avoid
     // interference with other unit tests.
-    protected UsageEventUtils setupUsageUtils() throws NoSuchMethodException, SecurityException, IllegalAccessException,
-    IllegalArgumentException, InvocationTargetException {
+    protected UsageEventUtils setupUsageUtils() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
 
         _usageEventDao = new MockUsageEventDao();
         UsageEventUtils utils = new UsageEventUtils();
@@ -93,8 +90,7 @@ public class AccountManagerImplVolumeDeleteEventTest extends AccountManagetImplT
                 Field staticField = UsageEventUtils.class.getDeclaredField("s_" + fieldName);
                 staticField.setAccessible(true);
                 oldFields.put(f.getName(), staticField.get(null));
-                f.set(utils,
-                        this.getClass().getSuperclass().getDeclaredField("_" + fieldName).get(this));
+                f.set(utils, this.getClass().getSuperclass().getDeclaredField("_" + fieldName).get(this));
             } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
                 e.printStackTrace();
             }
@@ -106,14 +102,12 @@ public class AccountManagerImplVolumeDeleteEventTest extends AccountManagetImplT
         return utils;
     }
 
-
-    protected void defineMocksBehavior()
-            throws AgentUnavailableException, ConcurrentOperationException, CloudException {
+    protected void defineMocksBehavior() throws AgentUnavailableException, ConcurrentOperationException, CloudException {
 
         AccountVO account = new AccountVO();
         account.setId(ACCOUNT_ID);
-        when(_accountDao.remove(ACCOUNT_ID)).thenReturn(true);
-        when(_accountDao.findById(ACCOUNT_ID)).thenReturn(account);
+        when(accountDaoMock.remove(ACCOUNT_ID)).thenReturn(true);
+        when(accountDaoMock.findById(ACCOUNT_ID)).thenReturn(account);
 
         DomainVO domain = new DomainVO();
         VirtualMachineEntity vmEntity = mock(VirtualMachineEntity.class);
@@ -128,8 +122,7 @@ public class AccountManagerImplVolumeDeleteEventTest extends AccountManagetImplT
         List<VolumeVO> volumes = new ArrayList<>();
         volumes.add(vol);
 
-        when(securityChecker.checkAccess(any(Account.class), any(ControlledEntity.class), any(AccessType.class),
-                anyString())).thenReturn(true);
+        when(securityChecker.checkAccess(any(Account.class), any(ControlledEntity.class), any(AccessType.class), anyString())).thenReturn(true);
 
         when(_userVmDao.findById(anyLong())).thenReturn(vm);
         when(_userVmDao.listByAccountId(ACCOUNT_ID)).thenReturn(Arrays.asList(vm));
@@ -142,8 +135,7 @@ public class AccountManagerImplVolumeDeleteEventTest extends AccountManagetImplT
         when(offering.getId()).thenReturn(1l);
         when(offering.getCpu()).thenReturn(500);
         when(offering.getRamSize()).thenReturn(500);
-        when(_serviceOfferingDao.findByIdIncludingRemoved(anyLong(), anyLong()))
-        .thenReturn(offering);
+        when(_serviceOfferingDao.findByIdIncludingRemoved(anyLong(), anyLong())).thenReturn(offering);
 
         when(_domainMgr.getDomain(anyLong())).thenReturn(domain);
 
@@ -152,9 +144,8 @@ public class AccountManagerImplVolumeDeleteEventTest extends AccountManagetImplT
     }
 
     @Before
-    public void init()
-            throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException,
-            InvocationTargetException, AgentUnavailableException, ConcurrentOperationException, CloudException {
+    public void init() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, AgentUnavailableException,
+    ConcurrentOperationException, CloudException {
 
         setupUsageUtils();
         defineMocksBehavior();
@@ -175,22 +166,19 @@ public class AccountManagerImplVolumeDeleteEventTest extends AccountManagetImplT
         method.invoke(utils);
     }
 
-    @SuppressWarnings("unchecked")
-    protected List<UsageEventVO> deleteUserAccountRootVolumeUsageEvents(boolean vmDestroyedPrior)
-            throws AgentUnavailableException, ConcurrentOperationException, CloudException {
+    protected List<UsageEventVO> deleteUserAccountRootVolumeUsageEvents(boolean vmDestroyedPrior) throws AgentUnavailableException, ConcurrentOperationException, CloudException {
 
-        when(vm.getState())
-        .thenReturn(vmDestroyedPrior ? VirtualMachine.State.Destroyed : VirtualMachine.State.Running);
+        when(vm.getState()).thenReturn(vmDestroyedPrior ? VirtualMachine.State.Destroyed : VirtualMachine.State.Running);
         when(vm.getRemoved()).thenReturn(vmDestroyedPrior ? new Date() : null);
-        accountManager.deleteUserAccount(ACCOUNT_ID);
+        accountManagerImpl.deleteUserAccount(ACCOUNT_ID);
 
         return _usageEventDao.listAll();
     }
 
     @Test
     // If the VM is alerady destroyed, no events should get emitted
-    public void destroyedVMRootVolumeUsageEvent() throws SecurityException, IllegalArgumentException,
-    ReflectiveOperationException, AgentUnavailableException, ConcurrentOperationException, CloudException {
+    public void destroyedVMRootVolumeUsageEvent()
+            throws SecurityException, IllegalArgumentException, ReflectiveOperationException, AgentUnavailableException, ConcurrentOperationException, CloudException {
         List<UsageEventVO> emittedEvents = deleteUserAccountRootVolumeUsageEvents(true);
         Assert.assertEquals(0, emittedEvents.size());
     }
@@ -198,8 +186,8 @@ public class AccountManagerImplVolumeDeleteEventTest extends AccountManagetImplT
     @Test
     // If the VM is running, we should see one emitted event for the root
     // volume.
-    public void runningVMRootVolumeUsageEvent() throws SecurityException, IllegalArgumentException,
-    ReflectiveOperationException, AgentUnavailableException, ConcurrentOperationException, CloudException {
+    public void runningVMRootVolumeUsageEvent()
+            throws SecurityException, IllegalArgumentException, ReflectiveOperationException, AgentUnavailableException, ConcurrentOperationException, CloudException {
         List<UsageEventVO> emittedEvents = deleteUserAccountRootVolumeUsageEvents(false);
         Assert.assertEquals(1, emittedEvents.size());
         UsageEventVO event = emittedEvents.get(0);
diff --git a/server/src/test/java/com/cloud/user/AccountManagetImplTestBase.java b/server/src/test/java/com/cloud/user/AccountManagetImplTestBase.java
index 53b781a..885a23d 100644
--- a/server/src/test/java/com/cloud/user/AccountManagetImplTestBase.java
+++ b/server/src/test/java/com/cloud/user/AccountManagetImplTestBase.java
@@ -21,8 +21,6 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 
-import javax.inject.Inject;
-
 import org.apache.cloudstack.acl.SecurityChecker;
 import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
 import org.apache.cloudstack.context.CallContext;
@@ -34,9 +32,10 @@ import org.apache.cloudstack.region.gslb.GlobalLoadBalancerRuleDao;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.mockito.Spy;
 import org.mockito.runners.MockitoJUnitRunner;
-import org.springframework.test.util.ReflectionTestUtils;
 
 import com.cloud.configuration.ConfigurationManager;
 import com.cloud.configuration.dao.ResourceCountDao;
@@ -84,17 +83,17 @@ import com.cloud.vm.snapshot.dao.VMSnapshotDao;
 public class AccountManagetImplTestBase {
 
     @Mock
-    AccountDao _accountDao;
+    AccountDao accountDaoMock;
     @Mock
     ConfigurationDao _configDao;
     @Mock
     ResourceCountDao _resourceCountDao;
     @Mock
-    UserDao _userDao;
+    UserDao userDaoMock;
     @Mock
     InstanceGroupDao _vmGroupDao;
     @Mock
-    UserAccountDao _userAccountDao;
+    UserAccountDao userAccountDaoMock;
     @Mock
     VolumeDao _volumeDao;
     @Mock
@@ -193,27 +192,16 @@ public class AccountManagetImplTestBase {
     @Mock
     SSHKeyPairDao _sshKeyPairDao;
 
-    AccountManagerImpl accountManager;
-
-    UsageEventDao _usageEventDao = new MockUsageEventDao();
+    @Spy
+    @InjectMocks
+    AccountManagerImpl accountManagerImpl;
+    @Mock
+    UsageEventDao _usageEventDao;
 
     @Before
-    public void setup()
-            throws NoSuchFieldException, SecurityException,
-            IllegalArgumentException, IllegalAccessException {
-        accountManager = new AccountManagerImpl();
-        Map<String, Field> declaredFields = getInheritedFields(this.getClass());
-        for (Field field : AccountManagerImpl.class.getDeclaredFields()) {
-            if (field.getAnnotation(Inject.class) != null) {
-                field.setAccessible(true);
-                if (declaredFields.containsKey(field.getName())) {
-                    Field mockField = declaredFields.get(field.getName());
-                    field.set(accountManager, mockField.get(this));
-                }
-            }
-        }
-        ReflectionTestUtils.setField(accountManager, "_userAuthenticators", Arrays.asList(userAuthenticator));
-        accountManager.setSecurityCheckers(Arrays.asList(securityChecker));
+    public void setup() {
+        accountManagerImpl.setUserAuthenticators(Arrays.asList(userAuthenticator));
+        accountManagerImpl.setSecurityCheckers(Arrays.asList(securityChecker));
         CallContext.register(callingUser, callingAccount);
     }
 
@@ -231,14 +219,4 @@ public class AccountManagetImplTestBase {
         }
         return fields;
     }
-
-    public static Map<Class<?>, Field> getInheritedFieldsByClass(Class<?> type) {
-        Map<Class<?>, Field> fields = new HashMap<>();
-        for (Class<?> c = type; c != null; c = c.getSuperclass()) {
-            for (Field f : c.getDeclaredFields()) {
-                fields.put(f.getType(), f);
-            }
-        }
-        return fields;
-    }
 }
diff --git a/server/src/test/java/com/cloud/user/MockAccountManagerImpl.java b/server/src/test/java/com/cloud/user/MockAccountManagerImpl.java
index 0a92c14..4fbf752 100644
--- a/server/src/test/java/com/cloud/user/MockAccountManagerImpl.java
+++ b/server/src/test/java/com/cloud/user/MockAccountManagerImpl.java
@@ -158,13 +158,6 @@ public class MockAccountManagerImpl extends ManagerBase implements Manager, Acco
     }
 
     @Override
-    public UserAccount updateUser(Long userId, String firstName, String lastName, String email, String userName, String password, String apiKey, String secretKey,
-                                  String timeZone) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
     public Account getActiveAccountById(long accountId) {
         // TODO Auto-generated method stub
         return null;
diff --git a/server/src/test/java/com/cloud/user/MockDomainManagerImpl.java b/server/src/test/java/com/cloud/user/MockDomainManagerImpl.java
deleted file mode 100644
index 394c3e2..0000000
--- a/server/src/test/java/com/cloud/user/MockDomainManagerImpl.java
+++ /dev/null
@@ -1,164 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package com.cloud.user;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.naming.ConfigurationException;
-
-import org.springframework.stereotype.Component;
-
-import org.apache.cloudstack.api.command.admin.domain.ListDomainChildrenCmd;
-import org.apache.cloudstack.api.command.admin.domain.ListDomainsCmd;
-import org.apache.cloudstack.api.command.admin.domain.UpdateDomainCmd;
-
-import com.cloud.domain.Domain;
-import com.cloud.domain.DomainVO;
-import com.cloud.exception.PermissionDeniedException;
-import com.cloud.utils.Pair;
-import com.cloud.utils.component.ManagerBase;
-
-@Component
-public class MockDomainManagerImpl extends ManagerBase implements DomainManager, DomainService {
-
-    @Override
-    public Domain getDomain(long id) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Domain getDomain(String uuid) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Domain getDomainByName(String name, long parentId) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public boolean isChildDomain(Long parentId, Long childId) {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean deleteDomain(long domainId, Boolean cleanup) {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public Pair<List<? extends Domain>, Integer> searchForDomains(ListDomainsCmd cmd) throws PermissionDeniedException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<List<? extends Domain>, Integer> searchForDomainChildren(ListDomainChildrenCmd cmd) throws PermissionDeniedException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Set<Long> getDomainChildrenIds(String parentDomainPath) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public DomainVO findDomainByPath(String domainPath) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public DomainVO findDomainByIdOrPath(Long id, String domainPath) {
-        return null;
-    }
-
-    @Override
-    public Set<Long> getDomainParentIds(long domainId) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public boolean removeDomain(long domainId) {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public List<? extends Domain> findInactiveDomains() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public boolean deleteDomain(DomainVO domain, Boolean cleanup) {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
-        return true;
-    }
-
-    @Override
-    public boolean start() {
-        // TODO Auto-generated method stub
-        return true;
-    }
-
-    @Override
-    public boolean stop() {
-        // TODO Auto-generated method stub
-        return true;
-    }
-
-    @Override
-    public String getName() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Domain createDomain(String name, Long parentId, String networkDomain, String domainUUID) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Domain updateDomain(UpdateDomainCmd cmd) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Domain createDomain(String name, Long parentId, Long ownerId, String networkDomain, String domainUUID) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-}
diff --git a/ui/l10n/ar.js b/ui/l10n/ar.js
index 82317f4..87c1193 100644
--- a/ui/l10n/ar.js
+++ b/ui/l10n/ar.js
@@ -1151,6 +1151,7 @@ var dictionary = {
     "label.networks": "الشبكات",
     "label.new": "جديد",
     "label.new.password": "New Password",
+    "label.current.password": "Current Password",
     "label.new.project": "مشروع جديد",
     "label.new.ssh.key.pair": "New SSH Key Pair",
     "label.new.vm": "New VM",
diff --git a/ui/l10n/ca.js b/ui/l10n/ca.js
index 4eff532..2580301 100644
--- a/ui/l10n/ca.js
+++ b/ui/l10n/ca.js
@@ -1151,6 +1151,7 @@ var dictionary = {
     "label.networks": "Xarxes",
     "label.new": "Nou",
     "label.new.password": "New Password",
+    "label.current.password": "Current Password",
     "label.new.project": "Nou projecte",
     "label.new.ssh.key.pair": "New SSH Key Pair",
     "label.new.vm": "Nova MV",
diff --git a/ui/l10n/de_DE.js b/ui/l10n/de_DE.js
index 696f466..e09062f 100644
--- a/ui/l10n/de_DE.js
+++ b/ui/l10n/de_DE.js
@@ -1151,6 +1151,7 @@ var dictionary = {
     "label.networks": "Netzwerke",
     "label.new": "Neu",
     "label.new.password": "Neues Passwort",
+    "label.current.password": "Current Password",
     "label.new.project": "Neues Projekt",
     "label.new.ssh.key.pair": "Neues SSH-Schlüsselpaar",
     "label.new.vm": "Neue VM",
diff --git a/ui/l10n/en.js b/ui/l10n/en.js
index e647f9a..e16031d 100644
--- a/ui/l10n/en.js
+++ b/ui/l10n/en.js
@@ -1186,6 +1186,7 @@ var dictionary = {
 "label.networks":"Networks",
 "label.new":"New",
 "label.new.password":"New Password",
+"label.current.password": "Current Password",
 "label.new.project":"New Project",
 "label.new.ssh.key.pair":"New SSH Key Pair",
 "label.new.vm":"New VM",
diff --git a/ui/l10n/es.js b/ui/l10n/es.js
index 8713783..285df3d 100644
--- a/ui/l10n/es.js
+++ b/ui/l10n/es.js
@@ -1151,6 +1151,7 @@ var dictionary = {
     "label.networks": "Redes",
     "label.new": "Nuevo",
     "label.new.password": "Nueva contraseña",
+    "label.current.password": "Current Password",
     "label.new.project": "Nuevo Proyecto",
     "label.new.ssh.key.pair": "Nuevo Par de Claves SSH",
     "label.new.vm": "Nueva MV",
diff --git a/ui/l10n/fr_FR.js b/ui/l10n/fr_FR.js
index 2236457..8ecf80d 100644
--- a/ui/l10n/fr_FR.js
+++ b/ui/l10n/fr_FR.js
@@ -1151,6 +1151,7 @@ var dictionary = {
     "label.networks": "Réseaux",
     "label.new": "Nouveau",
     "label.new.password": "Nouveau mot de passe",
+    "label.current.password": "Current Password",
     "label.new.project": "Nouveau projet",
     "label.new.ssh.key.pair": "Nouvelle bi-clé SSH",
     "label.new.vm": "Nouvelle VM",
diff --git a/ui/l10n/hu.js b/ui/l10n/hu.js
index 49cfaaf..2ed1f34 100644
--- a/ui/l10n/hu.js
+++ b/ui/l10n/hu.js
@@ -1151,6 +1151,7 @@ var dictionary = {
     "label.networks": "Hálózatok",
     "label.new": "Új",
     "label.new.password": "Új jelszó",
+    "label.current.password": "Current Password",
     "label.new.project": "Új projekt",
     "label.new.ssh.key.pair": "Új SSH kulcspár",
     "label.new.vm": "Új VM",
diff --git a/ui/l10n/it_IT.js b/ui/l10n/it_IT.js
index 06d85a8..c2210ca 100644
--- a/ui/l10n/it_IT.js
+++ b/ui/l10n/it_IT.js
@@ -1151,6 +1151,7 @@ var dictionary = {
     "label.networks": "Reti",
     "label.new": "Nuovo",
     "label.new.password": "New Password",
+    "label.current.password": "Current Password",
     "label.new.project": "Nuovo Progetto",
     "label.new.ssh.key.pair": "New SSH Key Pair",
     "label.new.vm": "Nuova VM",
diff --git a/ui/l10n/ja_JP.js b/ui/l10n/ja_JP.js
index 674e8ed..db94ca8 100644
--- a/ui/l10n/ja_JP.js
+++ b/ui/l10n/ja_JP.js
@@ -1151,6 +1151,7 @@ var dictionary = {
     "label.networks": "ネットワーク",
     "label.new": "新規",
     "label.new.password": "新しいパスワード",
+    "label.current.password": "Current Password",
     "label.new.project": "新しいプロジェクト",
     "label.new.ssh.key.pair": "新しい SSH キーペア",
     "label.new.vm": "新しい VM",
diff --git a/ui/l10n/ko_KR.js b/ui/l10n/ko_KR.js
index 42d886f..52cd183 100644
--- a/ui/l10n/ko_KR.js
+++ b/ui/l10n/ko_KR.js
@@ -1151,6 +1151,7 @@ var dictionary = {
     "label.networks": "네트워크",
     "label.new": "신규",
     "label.new.password": "새로운 암호",
+    "label.current.password": "Current Password",
     "label.new.project": "새 프로젝트",
     "label.new.ssh.key.pair": "New SSH Key Pair",
     "label.new.vm": "새 VM",
diff --git a/ui/l10n/nb_NO.js b/ui/l10n/nb_NO.js
index df22f16..fbe3bba 100644
--- a/ui/l10n/nb_NO.js
+++ b/ui/l10n/nb_NO.js
@@ -1151,6 +1151,7 @@ var dictionary = {
     "label.networks": "Nettverk",
     "label.new": "Ny",
     "label.new.password": "Nytt passord",
+    "label.current.password": "Current Password",
     "label.new.project": "Nytt prosjekt",
     "label.new.ssh.key.pair": "Nytt SSH-nøkkelpar",
     "label.new.vm": "Ny VM",
diff --git a/ui/l10n/nl_NL.js b/ui/l10n/nl_NL.js
index cffcb62..d1a96da 100644
--- a/ui/l10n/nl_NL.js
+++ b/ui/l10n/nl_NL.js
@@ -1151,6 +1151,7 @@ var dictionary = {
     "label.networks": "Netwerken",
     "label.new": "Nieuw",
     "label.new.password": "Nieuw wachtwoord",
+    "label.current.password": "Current Password",
     "label.new.project": "Nieuw Project",
     "label.new.ssh.key.pair": "nieuw SSH sleutelpaar",
     "label.new.vm": "Nieuwe VM",
diff --git a/ui/l10n/pl.js b/ui/l10n/pl.js
index 3828cbc..ccac03c 100644
--- a/ui/l10n/pl.js
+++ b/ui/l10n/pl.js
@@ -1151,6 +1151,7 @@ var dictionary = {
     "label.networks": "Sieci",
     "label.new": "Nowy",
     "label.new.password": "New Password",
+    "label.current.password": "Current Password",
     "label.new.project": "Nowy projekt",
     "label.new.ssh.key.pair": "New SSH Key Pair",
     "label.new.vm": "New VM",
diff --git a/ui/l10n/pt_BR.js b/ui/l10n/pt_BR.js
index 0082736..06b8553 100644
--- a/ui/l10n/pt_BR.js
+++ b/ui/l10n/pt_BR.js
@@ -1151,6 +1151,7 @@ var dictionary = {
     "label.networks": "Redes",
     "label.new": "Novo",
     "label.new.password": "Nova Senha",
+    "label.current.password": "Senha Antiga",
     "label.new.project": "Novo Projeto",
     "label.new.ssh.key.pair": "Novo par de chaves SSH",
     "label.new.vm": "Nova VM",
diff --git a/ui/l10n/ru_RU.js b/ui/l10n/ru_RU.js
index 01d9821..a61fe1e 100644
--- a/ui/l10n/ru_RU.js
+++ b/ui/l10n/ru_RU.js
@@ -1151,6 +1151,7 @@ var dictionary = {
     "label.networks": "Сети",
     "label.new": "Создать",
     "label.new.password": "Новый пароль",
+    "label.current.password": "Current Password",
     "label.new.project": "Новый проект",
     "label.new.ssh.key.pair": "New SSH Key Pair",
     "label.new.vm": "Новая ВМ",
diff --git a/ui/l10n/zh_CN.js b/ui/l10n/zh_CN.js
index 9ddea35..6015f41 100644
--- a/ui/l10n/zh_CN.js
+++ b/ui/l10n/zh_CN.js
@@ -1151,6 +1151,7 @@ var dictionary = {
     "label.networks": "网络",
     "label.new": "新建",
     "label.new.password": "新密码",
+    "label.current.password": "Current Password",
     "label.new.project": "新建项目",
     "label.new.ssh.key.pair": "新SSH密钥对",
     "label.new.vm": "新建 VM",
diff --git a/ui/scripts/accounts.js b/ui/scripts/accounts.js
index 529e5e3..86efb3e 100644
--- a/ui/scripts/accounts.js
+++ b/ui/scripts/accounts.js
@@ -1476,6 +1476,14 @@
                                                 form: {
                                                     title: 'label.action.change.password',
                                                     fields: {
+                                                        currentPassword: {
+                                                            label: 'label.current.password',
+                                                            isPassword: true,
+                                                            validation: {
+                                                                required: !(isAdmin() || isDomainAdmin())
+                                                            },
+                                                            id: 'currentPassword'
+                                                        },
                                                         newPassword: {
                                                             label: 'label.new.password',
                                                             isPassword: true,
@@ -1496,13 +1504,13 @@
                                                 },
                                                 after: function(args) {
                                                     start();
-
+                                                    var currentPassword = args.data.currentPassword;
                                                     var password = args.data.newPassword;
-
                                                     $.ajax({
                                                         url: createURL('updateUser'),
                                                         data: {
                                                             id: context.users[0].id,
+                                                            currentPassword: currentPassword,
                                                             password: password
                                                         },
                                                         type: "POST",
@@ -1515,6 +1523,9 @@
                                                     });
                                                 }
                                             });
+                                            if(isAdmin() || isDomainAdmin()){
+                                                $('div[rel=currentPassword]').hide();
+                                            }
                                         } else {
                                             cloudStack.dialog.notice({ message: _l('error.could.not.change.your.password.because.non.native.user') });
                                         }

-- 
To stop receiving notification emails like this one, please contact
rafael@apache.org.