From 9584815d4f35073214d7893704ff4bf6729a3155 Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Wed, 17 Apr 2013 12:02:09 -0700 Subject: [PATCH] CLOUDSTACK-1941: introduced "default" flag to account/user objects. Admin/System accounts that come with the CS install are default, and can never be removed. All accounts created by the CS admin, have default flag set to false, and can be removed at any time. --- api/src/com/cloud/user/Account.java | 4 ++++ api/src/com/cloud/user/User.java | 2 ++ core/src/com/cloud/user/AccountVO.java | 7 +++++++ core/src/com/cloud/user/UserVO.java | 11 ++++++++++- .../cloud/server/ConfigurationServerImpl.java | 17 +++++++++++------ .../src/com/cloud/user/AccountManagerImpl.java | 15 ++++++++------- setup/db/db/schema-410to420.sql | 6 ++++++ 7 files changed, 48 insertions(+), 14 deletions(-) diff --git a/api/src/com/cloud/user/Account.java b/api/src/com/cloud/user/Account.java index 5d32fb23253..940a0eb2667 100755 --- a/api/src/com/cloud/user/Account.java +++ b/api/src/com/cloud/user/Account.java @@ -22,6 +22,7 @@ import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; + public interface Account extends ControlledEntity, InternalIdentity, Identity { public enum Type { Normal, @@ -64,4 +65,7 @@ public interface Account extends ControlledEntity, InternalIdentity, Identity { public Long getDefaultZoneId(); public String getUuid(); + + boolean isDefault(); + } diff --git a/api/src/com/cloud/user/User.java b/api/src/com/cloud/user/User.java index 3742c7bf3e2..dcf27a0de69 100644 --- a/api/src/com/cloud/user/User.java +++ b/api/src/com/cloud/user/User.java @@ -72,5 +72,7 @@ public interface User extends OwnedBy, InternalIdentity { String getRegistrationToken(); boolean isRegistered(); + + boolean isDefault(); } diff --git a/core/src/com/cloud/user/AccountVO.java b/core/src/com/cloud/user/AccountVO.java index 5e939c52173..77110aedb95 100644 --- a/core/src/com/cloud/user/AccountVO.java +++ b/core/src/com/cloud/user/AccountVO.java @@ -65,6 +65,9 @@ public class AccountVO implements Account { @Column(name="default_zone_id") private Long defaultZoneId = null; + + @Column(name = "default") + boolean isDefault; public AccountVO() { this.uuid = UUID.randomUUID().toString(); @@ -179,4 +182,8 @@ public class AccountVO implements Account { this.uuid = uuid; } + @Override + public boolean isDefault() { + return isDefault; + } } diff --git a/core/src/com/cloud/user/UserVO.java b/core/src/com/cloud/user/UserVO.java index 8b7c4e3f1e1..2a857580506 100644 --- a/core/src/com/cloud/user/UserVO.java +++ b/core/src/com/cloud/user/UserVO.java @@ -29,10 +29,11 @@ import javax.persistence.Id; import javax.persistence.Table; import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + import com.cloud.user.Account.State; import com.cloud.utils.db.Encrypt; import com.cloud.utils.db.GenericDao; -import org.apache.cloudstack.api.InternalIdentity; /** * A bean representing a user @@ -92,6 +93,9 @@ public class UserVO implements User, Identity, InternalIdentity { @Column(name="uuid") private String uuid; + + @Column(name = "default") + boolean isDefault; public UserVO() { this.uuid = UUID.randomUUID().toString(); @@ -262,4 +266,9 @@ public class UserVO implements User, Identity, InternalIdentity { this.uuid = uuid; } + @Override + public boolean isDefault() { + return isDefault; + } + } diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java index 852c00b4c5d..06b787172d1 100755 --- a/server/src/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/com/cloud/server/ConfigurationServerImpl.java @@ -333,21 +333,24 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio @DB protected void saveUser() { // insert system account - String insertSql = "INSERT INTO `cloud`.`account` (id, uuid, account_name, type, domain_id) VALUES (1, UUID(), 'system', '1', '1')"; + String insertSql = "INSERT INTO `cloud`.`account` (id, uuid, account_name, type, domain_id, account.default) VALUES (1, UUID(), 'system', '1', '1', 1)"; Transaction txn = Transaction.currentTxn(); try { PreparedStatement stmt = txn.prepareAutoCloseStatement(insertSql); stmt.executeUpdate(); } catch (SQLException ex) { + s_logger.warn("Failed to system account due to ", ex); + } // insert system user - insertSql = "INSERT INTO `cloud`.`user` (id, uuid, username, password, account_id, firstname, lastname, created)" + - " VALUES (1, UUID(), 'system', RAND(), 1, 'system', 'cloud', now())"; + insertSql = "INSERT INTO `cloud`.`user` (id, uuid, username, password, account_id, firstname, lastname, created, user.default)" + + " VALUES (1, UUID(), 'system', RAND(), 1, 'system', 'cloud', now(), 1)"; txn = Transaction.currentTxn(); try { PreparedStatement stmt = txn.prepareAutoCloseStatement(insertSql); stmt.executeUpdate(); } catch (SQLException ex) { + s_logger.warn("Failed to create system user due to ", ex); } // insert admin user, but leave the account disabled until we set a @@ -358,23 +361,25 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio String lastname = "cloud"; // create an account for the admin user first - insertSql = "INSERT INTO `cloud`.`account` (id, uuid, account_name, type, domain_id) VALUES (" + id + ", UUID(), '" + username + "', '1', '1')"; + insertSql = "INSERT INTO `cloud`.`account` (id, uuid, account_name, type, domain_id, account.default) VALUES (" + id + ", UUID(), '" + username + "', '1', '1', 1)"; txn = Transaction.currentTxn(); try { PreparedStatement stmt = txn.prepareAutoCloseStatement(insertSql); stmt.executeUpdate(); } catch (SQLException ex) { + s_logger.warn("Failed to create admin account due to ", ex); } // now insert the user - insertSql = "INSERT INTO `cloud`.`user` (id, uuid, username, password, account_id, firstname, lastname, created, state) " + - "VALUES (" + id + ", UUID(), '" + username + "', RAND(), 2, '" + firstname + "','" + lastname + "',now(), 'disabled')"; + insertSql = "INSERT INTO `cloud`.`user` (id, uuid, username, password, account_id, firstname, lastname, created, state, user.default) " + + "VALUES (" + id + ", UUID(), '" + username + "', RAND(), 2, '" + firstname + "','" + lastname + "',now(), 'disabled', 1)"; txn = Transaction.currentTxn(); try { PreparedStatement stmt = txn.prepareAutoCloseStatement(insertSql); stmt.executeUpdate(); } catch (SQLException ex) { + s_logger.warn("Failed to create admin user due to ", ex); } try { diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index e74c49124f7..8de73fbd582 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -37,7 +37,6 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; -import com.cloud.event.ActionEventUtils; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker; @@ -53,7 +52,6 @@ import org.apache.log4j.Logger; import com.cloud.api.ApiDBUtils; import com.cloud.api.query.dao.UserAccountJoinDao; import com.cloud.api.query.vo.ControlledViewEntity; - import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.ResourceLimit; @@ -65,6 +63,7 @@ import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; import com.cloud.event.ActionEvent; +import com.cloud.event.ActionEventUtils; import com.cloud.event.EventTypes; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.CloudAuthenticationException; @@ -1178,8 +1177,9 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M checkAccess(caller, null, true, account); - if (account.getId() == Account.ACCOUNT_ID_SYSTEM) { - throw new PermissionDeniedException("Account id : " + accountId + " is a system account, delete is not allowed"); + //don't allow to delete default account (system and admin) + if (account.isDefault()) { + throw new InvalidParameterValueException("The account is default and can't be removed"); } // Account that manages project(s) can't be removed @@ -1384,9 +1384,10 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) { throw new InvalidParameterValueException("The specified user doesn't exist in the system"); } - - if (account.getId() == Account.ACCOUNT_ID_SYSTEM) { - throw new InvalidParameterValueException("Account id : " + user.getAccountId() + " is a system account, delete for user associated with this account is not allowed"); + + //don't allow to delete default user (system and admin users) + if (user.isDefault()) { + throw new InvalidParameterValueException("The user is default and can't be removed"); } checkAccess(UserContext.current().getCaller(), null, true, account); diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index 6a7a72c5d2d..bd145cb82f2 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -720,3 +720,9 @@ ALTER TABLE `cloud`.`network_offerings` ADD COLUMN `eip_associate_public_ip` int -- Re-enable foreign key checking, at the end of the upgrade path SET foreign_key_checks = 1; + +-- Add "default" field to account/user tables +ALTER TABLE `cloud`.`account` ADD COLUMN `default` int(1) unsigned NOT NULL DEFAULT '0' COMMENT '1 if account is default'; +ALTER TABLE `cloud`.`user` ADD COLUMN `default` int(1) unsigned NOT NULL DEFAULT '0' COMMENT '1 if user is default'; +UPDATE `cloud`.`account` SET `cloud`.`account`.`default`=1 WHERE id IN (1,2); +UPDATE `cloud`.`user` SET `cloud`.`user`.`default`=1 WHERE id IN (1,2);