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.