3636import org .apache .cloudstack .usage .Usage ;
3737import org .apache .cloudstack .usage .UsageService ;
3838import org .apache .cloudstack .usage .UsageTypes ;
39+ import org .apache .commons .lang3 .StringUtils ;
3940import org .apache .log4j .Logger ;
41+ import org .jetbrains .annotations .NotNull ;
4042import org .springframework .stereotype .Component ;
4143
4244import com .cloud .configuration .Config ;
@@ -166,46 +168,27 @@ public Pair<List<? extends Usage>, Integer> getUsageRecords(ListUsageRecordsCmd
166168 Long accountId = cmd .getAccountId ();
167169 Long domainId = cmd .getDomainId ();
168170 String accountName = cmd .getAccountName ();
169- Account userAccount = null ;
170171 Account caller = CallContext .current ().getCallingAccount ();
171172 Long usageType = cmd .getUsageType ();
172173 Long projectId = cmd .getProjectId ();
173174 String usageId = cmd .getUsageId ();
175+ boolean projectRequested = false ;
174176
175177 if (projectId != null ) {
176178 if (accountId != null ) {
177179 throw new InvalidParameterValueException ("Projectid and accountId can't be specified together" );
178180 }
179- Project project = _projectMgr .getProject (projectId );
180- if (project == null ) {
181- throw new InvalidParameterValueException ("Unable to find project by id " + projectId );
182- }
183- accountId = project .getProjectAccountId ();
184- }
185-
186- //if accountId is not specified, use accountName and domainId
187- if ((accountId == null ) && (accountName != null ) && (domainId != null )) {
188- if (_domainDao .isChildDomain (caller .getDomainId (), domainId )) {
189- Filter filter = new Filter (AccountVO .class , "id" , Boolean .FALSE , null , null );
190- List <AccountVO > accounts = _accountDao .listAccounts (accountName , domainId , filter );
191- if (accounts .size () > 0 ) {
192- userAccount = accounts .get (0 );
193- }
194- if (userAccount != null ) {
195- accountId = userAccount .getId ();
196- } else {
197- throw new InvalidParameterValueException ("Unable to find account " + accountName + " in domain " + domainId );
198- }
199- } else {
200- throw new PermissionDeniedException ("Invalid Domain Id or Account" );
201- }
181+ accountId = getAccountIdFromProject (projectId );
182+ projectRequested = true ;
183+ } else if ((accountId == null ) && (StringUtils .isNotBlank (accountName )) && (domainId != null )) {
184+ accountId = getAccountIdFromDomainPlusName (domainId , accountName , caller );
202185 }
203186
204187 boolean ignoreAccountId = false ;
205188 boolean isDomainAdmin = _accountService .isDomainAdmin (caller .getId ());
206189 boolean isNormalUser = _accountService .isNormalUser (caller .getId ());
207190
208- //If accountId couldn't be found using accountName and domainId, get it from userContext
191+ //If accountId couldn't be found using project or accountName and domainId, get it from userContext
209192 if (accountId == null ) {
210193 accountId = caller .getId ();
211194 //List records for all the accounts if the caller account is of type admin.
@@ -215,22 +198,7 @@ public Pair<List<? extends Usage>, Integer> getUsageRecords(ListUsageRecordsCmd
215198 }
216199
217200 // Check if a domain admin is allowed to access the requested domain id
218- if (isDomainAdmin ) {
219- if (domainId != null ) {
220- Account callerAccount = _accountService .getAccount (caller .getId ());
221- Domain domain = _domainDao .findById (domainId );
222- _accountService .checkAccess (callerAccount , domain );
223- } else {
224- // Domain admins can only access their own domain's usage records.
225- // Set the domain if not specified.
226- domainId = caller .getDomainId ();
227- }
228-
229- if (cmd .getAccountId () != null ) {
230- // Check if a domain admin is allowed to access the requested account info.
231- checkDomainAdminAccountAccess (accountId , domainId );
232- }
233- }
201+ domainId = getDomainScopeForQuery (cmd , accountId , domainId , caller , isDomainAdmin );
234202
235203 // By default users do not have access to this API.
236204 // Adding checks here in case someone changes the default access.
@@ -255,9 +223,7 @@ public Pair<List<? extends Usage>, Integer> getUsageRecords(ListUsageRecordsCmd
255223 SearchCriteria <UsageVO > sc = _usageDao .createSearchCriteria ();
256224
257225 if (accountId != -1 && accountId != Account .ACCOUNT_ID_SYSTEM && !ignoreAccountId ) {
258- // account exists and either domain on user role
259- // If not recursive and the account belongs to the user/domain admin, or the account was passed in, filter
260- if ((accountId == caller .getId () && !cmd .isRecursive ()) || cmd .getAccountId () != null ){
226+ if (!cmd .isRecursive () || cmd .getAccountId () != null || projectRequested ){
261227 sc .addAnd ("accountId" , SearchCriteria .Op .EQ , accountId );
262228 }
263229 }
@@ -397,6 +363,56 @@ public Pair<List<? extends Usage>, Integer> getUsageRecords(ListUsageRecordsCmd
397363 return new Pair <List <? extends Usage >, Integer >(usageRecords .first (), usageRecords .second ());
398364 }
399365
366+ private Long getDomainScopeForQuery (ListUsageRecordsCmd cmd , Long accountId , Long domainId , Account caller , boolean isDomainAdmin ) {
367+ if (isDomainAdmin ) {
368+ if (domainId != null ) {
369+ Account callerAccount = _accountService .getAccount (caller .getId ());
370+ Domain domain = _domainDao .findById (domainId );
371+ _accountService .checkAccess (callerAccount , domain );
372+ } else {
373+ domainId = caller .getDomainId ();
374+ }
375+
376+ if (cmd .getAccountId () != null ) {
377+ checkDomainAdminAccountAccess (accountId , domainId );
378+ }
379+ }
380+ return domainId ;
381+ }
382+
383+ @ NotNull
384+ private Long getAccountIdFromDomainPlusName (Long domainId , String accountName , Account caller ) {
385+ Long accountId ;
386+ Account userAccount = null ;
387+ if (! _domainDao .isChildDomain (caller .getDomainId (), domainId )) {
388+ throw new PermissionDeniedException ("Invalid Domain Id or Account" );
389+ }
390+ Filter filter = new Filter (AccountVO .class , "id" , Boolean .FALSE , null , null );
391+ List <AccountVO > accounts = _accountDao .listAccounts (accountName , domainId , filter );
392+ if (accounts .size () > 0 ) {
393+ userAccount = accounts .get (0 );
394+ }
395+ if (userAccount == null ) {
396+ throw new InvalidParameterValueException ("Unable to find account " + accountName + " in domain " + domainId );
397+ }
398+ return userAccount .getId ();
399+ }
400+
401+ @ NotNull
402+ private Long getAccountIdFromProject (Long projectId ) {
403+ Long accountId ;
404+ Project project = _projectMgr .getProject (projectId );
405+ if (project == null ) {
406+ throw new InvalidParameterValueException ("Unable to find project by id " + projectId );
407+ }
408+ final long projectAccountId = project .getProjectAccountId ();
409+ if (s_logger .isInfoEnabled ()) {
410+ s_logger .info (String .format ("Using projectAccountId %d for project %s [%s] as account id" , projectAccountId , project .getName (), project .getUuid ()));
411+ }
412+ accountId = projectAccountId ;
413+ return accountId ;
414+ }
415+
400416 private void checkUserAccess (ListUsageRecordsCmd cmd , Long accountId , Account caller , boolean isNormalUser ) {
401417 if (isNormalUser ) {
402418 // A user can only access their own account records
0 commit comments