Skip to content

Commit 000ee36

Browse files
dcarboneyadvr
authored andcommitted
CLOUDSTACK-9971: Bugfix/listaccounts parameter consistency (#2156)
Ran into an issue today where we passed both the "id" and "domainid" parameters into "listAccounts" and received a response despite the account id passed not belonging to the domainid passed. Allow usage of "domainid" AND "id" in "listAccounts" - Adding "AccountDoa::findActiveAccountById" - Adding "AccountDaoImpl::findActiveAccountById" - Removing seemingly pointless "listForDomain" parameter - Updating "typeNEQ" value from "5" to "Account.ACCOUNT_TYPE_PROJECT" (which is "5") - Only attempt to load domain for "path" query parameter once "searchForAccountsInternal" input validation logic pseudo-code: - If "domainid" set, check immediately - If "id" not set: - and user is admin and "listall" is true - if "domainid" not set, use caller domain id - force "isrecursive" true - else use caller account id - Else if "domainid" and "name" set - verify existence of account and that user has access - Else: - if "domainid" not set, locate account by "id" - else, locate account by "id" and "domainid" - verify account found and caller has access rights
1 parent c436bc3 commit 000ee36

3 files changed

Lines changed: 66 additions & 45 deletions

File tree

engine/schema/src/com/cloud/user/dao/AccountDao.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,16 @@
1616
// under the License.
1717
package com.cloud.user.dao;
1818

19-
import java.util.Date;
20-
import java.util.List;
21-
2219
import com.cloud.user.Account;
2320
import com.cloud.user.AccountVO;
2421
import com.cloud.user.User;
2522
import com.cloud.utils.Pair;
2623
import com.cloud.utils.db.Filter;
2724
import com.cloud.utils.db.GenericDao;
2825

26+
import java.util.Date;
27+
import java.util.List;
28+
2929
public interface AccountDao extends GenericDao<AccountVO, Long> {
3030
Pair<User, Account> findUserAccountByApiKey(String apiKey);
3131

@@ -62,6 +62,8 @@ public interface AccountDao extends GenericDao<AccountVO, Long> {
6262
//returns only non-removed account
6363
Account findActiveAccount(String accountName, Long domainId);
6464

65+
Account findActiveAccountById(Long accountId, Long domainId);
66+
6567
Account findActiveNonProjectAccount(String accountName, Long domainId);
6668

6769
List<Long> getAccountIdsForDomains(List<Long> ids);

engine/schema/src/com/cloud/user/dao/AccountDaoImpl.java

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,6 @@
1616
// under the License.
1717
package com.cloud.user.dao;
1818

19-
import java.sql.PreparedStatement;
20-
import java.sql.ResultSet;
21-
import java.util.Date;
22-
import java.util.List;
23-
24-
25-
import org.apache.log4j.Logger;
26-
import org.springframework.stereotype.Component;
27-
2819
import com.cloud.user.Account;
2920
import com.cloud.user.Account.State;
3021
import com.cloud.user.AccountVO;
@@ -39,6 +30,13 @@
3930
import com.cloud.utils.db.SearchCriteria;
4031
import com.cloud.utils.db.SearchCriteria.Op;
4132
import com.cloud.utils.db.TransactionLegacy;
33+
import org.apache.log4j.Logger;
34+
import org.springframework.stereotype.Component;
35+
36+
import java.sql.PreparedStatement;
37+
import java.sql.ResultSet;
38+
import java.util.Date;
39+
import java.util.List;
4240

4341
@Component
4442
public class AccountDaoImpl extends GenericDaoBase<AccountVO, Long> implements AccountDao {
@@ -188,6 +186,13 @@ public Account findActiveAccount(String accountName, Long domainId) {
188186
return findOneBy(sc);
189187
}
190188

189+
@Override
190+
public Account findActiveAccountById(Long accountId, Long domainId) {
191+
SearchCriteria<AccountVO> sc = AllFieldsSearch.create("id", accountId);
192+
sc.setParameters("domainId", domainId);
193+
return findOneBy(sc);
194+
}
195+
191196
@Override
192197
public Account findActiveNonProjectAccount(String accountName, Long domainId) {
193198
SearchCriteria<AccountVO> sc = NonProjectAccountSearch.create("accountName", accountName);

server/src/com/cloud/api/query/QueryManagerImpl.java

Lines changed: 47 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1982,47 +1982,58 @@ private Pair<List<AccountJoinVO>, Integer> searchForAccountsInternal(ListAccount
19821982
String accountName = cmd.getSearchName();
19831983
boolean isRecursive = cmd.isRecursive();
19841984
boolean listAll = cmd.listAll();
1985-
Boolean listForDomain = false;
1986-
1987-
if (accountId != null) {
1988-
Account account = _accountDao.findById(accountId);
1989-
if (account == null || account.getId() == Account.ACCOUNT_ID_SYSTEM) {
1990-
throw new InvalidParameterValueException("Unable to find account by id " + accountId);
1991-
}
1992-
1993-
_accountMgr.checkAccess(caller, null, true, account);
1994-
}
1985+
boolean callerIsAdmin = _accountMgr.isAdmin(caller.getId());
1986+
Account account;
1987+
Domain domain = null;
19951988

1989+
// if "domainid" specified, perform validation
19961990
if (domainId != null) {
1997-
Domain domain = _domainDao.findById(domainId);
1991+
// ensure existence...
1992+
domain = _domainDao.findById(domainId);
19981993
if (domain == null) {
19991994
throw new InvalidParameterValueException("Domain id=" + domainId + " doesn't exist");
20001995
}
2001-
1996+
// ... and check access rights.
20021997
_accountMgr.checkAccess(caller, domain);
2003-
2004-
if (accountName != null) {
2005-
Account account = _accountDao.findActiveAccount(accountName, domainId);
2006-
if (account == null || account.getId() == Account.ACCOUNT_ID_SYSTEM) {
2007-
throw new InvalidParameterValueException("Unable to find account by name " + accountName
2008-
+ " in domain " + domainId);
2009-
}
2010-
_accountMgr.checkAccess(caller, null, true, account);
2011-
}
20121998
}
20131999

2000+
// if no "id" specified...
20142001
if (accountId == null) {
2015-
if (_accountMgr.isAdmin(caller.getId()) && listAll && domainId == null) {
2016-
listForDomain = true;
2017-
isRecursive = true;
2002+
// listall only has significance if they are an admin
2003+
if (listAll && callerIsAdmin) {
2004+
// if no domain id specified, use caller's domain
20182005
if (domainId == null) {
20192006
domainId = caller.getDomainId();
20202007
}
2021-
} else if (_accountMgr.isAdmin(caller.getId()) && domainId != null) {
2022-
listForDomain = true;
2023-
} else {
2008+
// mark recursive
2009+
isRecursive = true;
2010+
} else if (!callerIsAdmin || domainId == null) {
20242011
accountId = caller.getAccountId();
20252012
}
2013+
} else if (domainId != null && accountName != null) {
2014+
// if they're looking for an account by name
2015+
account = _accountDao.findActiveAccount(accountName, domainId);
2016+
if (account == null || account.getId() == Account.ACCOUNT_ID_SYSTEM) {
2017+
throw new InvalidParameterValueException(
2018+
"Unable to find account by name " + accountName + " in domain " + domainId
2019+
);
2020+
}
2021+
_accountMgr.checkAccess(caller, null, true, account);
2022+
} else {
2023+
// if they specified an "id"...
2024+
if (domainId == null) {
2025+
account = _accountDao.findById(accountId);
2026+
} else {
2027+
account = _accountDao.findActiveAccountById(accountId, domainId);
2028+
}
2029+
if (account == null || account.getId() == Account.ACCOUNT_ID_SYSTEM) {
2030+
throw new InvalidParameterValueException(
2031+
"Unable to find account by id "
2032+
+ accountId
2033+
+ (domainId == null ? "" : " in domain " + domainId)
2034+
);
2035+
}
2036+
_accountMgr.checkAccess(caller, null, true, account);
20262037
}
20272038

20282039
Filter searchFilter = new Filter(AccountJoinVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
@@ -2042,12 +2053,15 @@ private Pair<List<AccountJoinVO>, Integer> searchForAccountsInternal(ListAccount
20422053
sb.and("typeNEQ", sb.entity().getType(), SearchCriteria.Op.NEQ);
20432054
sb.and("idNEQ", sb.entity().getId(), SearchCriteria.Op.NEQ);
20442055

2045-
if (listForDomain && isRecursive) {
2056+
if (domainId != null && isRecursive) {
20462057
sb.and("path", sb.entity().getDomainPath(), SearchCriteria.Op.LIKE);
20472058
}
20482059

20492060
SearchCriteria<AccountJoinVO> sc = sb.create();
20502061

2062+
// don't return account of type project to the end user
2063+
sc.setParameters("typeNEQ", Account.ACCOUNT_TYPE_PROJECT);
2064+
// don't return system account...
20512065
sc.setParameters("idNEQ", Account.ACCOUNT_ID_SYSTEM);
20522066

20532067
if (keyword != null) {
@@ -2073,16 +2087,16 @@ private Pair<List<AccountJoinVO>, Integer> searchForAccountsInternal(ListAccount
20732087
sc.setParameters("accountName", accountName);
20742088
}
20752089

2076-
// don't return account of type project to the end user
2077-
sc.setParameters("typeNEQ", 5);
2078-
20792090
if (accountId != null) {
20802091
sc.setParameters("id", accountId);
20812092
}
20822093

2083-
if (listForDomain) {
2094+
if (domainId != null) {
20842095
if (isRecursive) {
2085-
Domain domain = _domainDao.findById(domainId);
2096+
// will happen if no "domainid" was specified in the request...
2097+
if (domain == null) {
2098+
domain = _domainDao.findById(domainId);
2099+
}
20862100
sc.setParameters("path", domain.getPath() + "%");
20872101
} else {
20882102
sc.setParameters("domainId", domainId);

0 commit comments

Comments
 (0)