WIP For APIs related to ACL Roles.

This commit is contained in:
Min Chen 2013-09-26 11:22:43 -07:00
parent 4294005142
commit fce2aad23d
31 changed files with 1739 additions and 54 deletions

View File

@ -24,6 +24,7 @@ import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.api.command.admin.user.RegisterCmd;
import com.cloud.domain.Domain;
import com.cloud.domain.PartOf;
import com.cloud.exception.PermissionDeniedException;
public interface AccountService {
@ -102,4 +103,6 @@ public interface AccountService {
void checkAccess(Account account, AccessType accessType, boolean sameOwner, ControlledEntity... entities) throws PermissionDeniedException;
//TO be implemented, to check accessibility for an entity owned by domain
void checkAccess(Account account, AccessType accessType, boolean sameOwner, PartOf... entities) throws PermissionDeniedException;
}

View File

@ -19,10 +19,11 @@ package org.apache.cloudstack.acl;
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
public interface AclGroup extends InternalIdentity, Identity {
import com.cloud.domain.PartOf;
public interface AclGroup extends PartOf, InternalIdentity, Identity {
String getName();
String getDescription();
}

View File

@ -19,11 +19,13 @@ package org.apache.cloudstack.acl;
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
public interface AclRole extends InternalIdentity, Identity {
import com.cloud.domain.PartOf;
public interface AclRole extends PartOf, InternalIdentity, Identity {
String getName();
String getDescription();
long getParentRoleId();
Long getParentRoleId();
}

View File

@ -0,0 +1,103 @@
// 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 org.apache.cloudstack.acl;
import java.util.List;
import com.cloud.utils.Pair;
public interface AclService {
/**
* Creates an acl role for the given domain.
*
* @param domainId
* @param name
* @param description
* @return AclRole
*/
AclRole createAclRole(Long domainId, String aclRoleName, String description);
/**
* Delete an acl role.
*
* @param aclRoleId
*/
boolean deleteAclRole(long aclRoleId);
/** Lists Acl roles for a domain
* @param domainId
* @param aclRoleId
* @param aclRoleName
* @param startIndex
* @param pageSize
* @return
*/
Pair<List<? extends AclRole>, Integer> listAclRoles(Long aclRoleId, String aclRoleName,
Long domainId, Long startIndex, Long pageSize);
/**
* Get the acl role for the given role id.
* @param roleId
* @return AclRole
*/
AclRole getAclRole(Long roleId);
AclGroup addAclRolesToGroup(List<Long> roleIds, Long groupId);
AclGroup removeAclRolesFromGroup(List<Long> roleIds, Long groupId);
/**
* Creates an acl group for the given domain.
*
* @param domainId
* @param name
* @param description
* @return AclGroup
*/
AclGroup createAclGroup(Long domainId, String aclGroupName, String description);
/**
* Delete an acl group.
*
* @param aclGroupId
*/
boolean deleteAclGroup(Long aclGroupId);
/** Lists Acl groups for a domain
* @param domainId
* @param aclGroupId
* @param aclGroupName
* @param startIndex
* @param pageSize
* @return
*/
Pair<List<? extends AclRole>, Integer> listAclGroups(Long aclRoleId, String aclRoleName,
Long domainId, Long startIndex, Long pageSize);
/**
* Get the acl group for the given group id.
* @param groupId
* @return AclGroup
*/
AclRole getAclGroup(Long groupId);
}

View File

@ -48,5 +48,7 @@ public enum ApiCommandJobType {
LoadBalancerRule,
AffinityGroup,
InternalLbVm,
DedicatedGuestVlanRange
DedicatedGuestVlanRange,
AclRole,
AclGroup
}

View File

@ -248,7 +248,7 @@ public class ApiConstants {
public static final String IS_VOLATILE = "isvolatile";
public static final String VOLUME_ID = "volumeid";
public static final String ZONE_ID = "zoneid";
public static final String ZONE_NAME = "zonename";
public static final String ZONE_NAME = "zonename";
public static final String NETWORK_TYPE = "networktype";
public static final String PAGE = "page";
public static final String PAGE_SIZE = "pagesize";
@ -518,6 +518,12 @@ public class ApiConstants {
public static final String ROUTING = "isrouting";
public static final String MAX_CONNECTIONS = "maxconnections";
public static final String SERVICE_STATE = "servicestate";
public static final String ACL_ACCOUNT_IDS = "accountids";
public static final String ACL_PARENT_ROLE_ID = "parentroleid";
public static final String ACL_PARENT_ROLE_NAME = "parentrolename";
public static final String ACL_ROLES = "roles";
public static final String ACL_ROLE_IDS = "roleids";
public static final String ACL_ALLOWED_APIS = "allowedapis";
public enum HostDetails {
all, capacity, events, stats, min;
}

View File

@ -27,18 +27,16 @@ import java.util.regex.Pattern;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.AclService;
import org.apache.cloudstack.affinity.AffinityGroupService;
import com.cloud.server.ResourceMetaDataService;
import org.apache.cloudstack.network.element.InternalLoadBalancerElementService;
import org.apache.cloudstack.network.lb.ApplicationLoadBalancerService;
import org.apache.cloudstack.network.lb.InternalLoadBalancerVMService;
import org.apache.cloudstack.query.QueryService;
import org.apache.cloudstack.usage.UsageService;
import org.apache.log4j.Logger;
import com.cloud.configuration.ConfigurationService;
import com.cloud.domain.Domain;
import com.cloud.exception.ConcurrentOperationException;
@ -55,10 +53,10 @@ import com.cloud.network.StorageNetworkService;
import com.cloud.network.VpcVirtualNetworkApplianceService;
import com.cloud.network.as.AutoScaleService;
import com.cloud.network.firewall.FirewallService;
import com.cloud.network.vpc.NetworkACLService;
import com.cloud.network.lb.LoadBalancingRulesService;
import com.cloud.network.rules.RulesService;
import com.cloud.network.security.SecurityGroupService;
import com.cloud.network.vpc.NetworkACLService;
import com.cloud.network.vpc.VpcProvisioningService;
import com.cloud.network.vpc.VpcService;
import com.cloud.network.vpn.RemoteAccessVpnService;
@ -67,6 +65,7 @@ import com.cloud.projects.Project;
import com.cloud.projects.ProjectService;
import com.cloud.resource.ResourceService;
import com.cloud.server.ManagementService;
import com.cloud.server.ResourceMetaDataService;
import com.cloud.server.TaggedResourceService;
import com.cloud.storage.DataStoreProviderApiService;
import com.cloud.storage.StorageService;
@ -150,6 +149,8 @@ public abstract class BaseCmd {
@Inject public ApplicationLoadBalancerService _newLbSvc;
@Inject public ApplicationLoadBalancerService _appLbService;
@Inject public AffinityGroupService _affinityGroupService;
@Inject
public AclService _aclService;
@Inject public InternalLoadBalancerElementService _internalLbElementSvc;
@Inject public InternalLoadBalancerVMService _internalLbSvc;
@Inject public NetworkModel _ntwkModel;
@ -474,11 +475,11 @@ public abstract class BaseCmd {
}
public void setFullUrlParams(Map<String, String> map) {
this.fullUrlParams = map;
fullUrlParams = map;
}
public Map<String, String> getFullUrlParams() {
return this.fullUrlParams;
return fullUrlParams;
}
public Long finalyzeAccountId(String accountName, Long domainId, Long projectId, boolean enabledOnly) {

View File

@ -22,12 +22,16 @@ import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import org.apache.cloudstack.acl.AclGroup;
import org.apache.cloudstack.acl.AclRole;
import org.apache.cloudstack.affinity.AffinityGroup;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.api.ApiConstants.HostDetails;
import org.apache.cloudstack.api.ApiConstants.VMDetails;
import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd;
import org.apache.cloudstack.api.response.AccountResponse;
import org.apache.cloudstack.api.response.AclGroupResponse;
import org.apache.cloudstack.api.response.AclRoleResponse;
import org.apache.cloudstack.api.response.ApplicationLoadBalancerResponse;
import org.apache.cloudstack.api.response.AsyncJobResponse;
import org.apache.cloudstack.api.response.AutoScalePolicyResponse;
@ -446,4 +450,8 @@ public interface ResponseGenerator {
IsolationMethodResponse createIsolationMethodResponse(IsolationType method);
AclRoleResponse createAclRoleResponse(AclRole role);
AclGroupResponse createAclGroupResponse(AclGroup group);
}

View File

@ -0,0 +1,105 @@
// 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 org.apache.cloudstack.api.command.admin.acl;
import java.util.List;
import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.AclGroup;
import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.AclGroupResponse;
import org.apache.cloudstack.api.response.AclRoleResponse;
import org.apache.cloudstack.context.CallContext;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.Account;
@APICommand(name = "addAclRoleToAclGroup", description = "add acl role to an acl group", responseObject = AclGroupResponse.class)
public class AddAclRoleToAclGroupCmd extends BaseCmd {
public static final Logger s_logger = Logger.getLogger(AddAclRoleToAclGroupCmd.class.getName());
private static final String s_name = "addaclroletoaclgroupresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@ACL
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = AclGroupResponse.class,
required = true, description = "The ID of the acl group")
private Long id;
@ACL
@Parameter(name = ApiConstants.ACL_ROLES, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = AclRoleResponse.class, description = "comma separated list of acl role id that are going to be applied to the acl group.")
private List<Long> roleIdList;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getId() {
return id;
}
public List<Long> getRoleIdList() {
return roleIdList;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
}
@Override
public void execute() throws ResourceUnavailableException,
InsufficientCapacityException, ServerApiException {
CallContext.current().setEventDetails("Acl group Id: " + getId());
AclGroup result = _aclService.addAclRolesToGroup(roleIdList, id);
if (result != null){
AclGroupResponse response = _responseGenerator.createAclGroupResponse(result);
response.setResponseName(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add roles to acl group");
}
}
}

View File

@ -0,0 +1,98 @@
// 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 org.apache.cloudstack.api.command.admin.acl;
import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.AclRole;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.AclRoleResponse;
import org.apache.cloudstack.api.response.DomainResponse;
import com.cloud.user.Account;
@APICommand(name = "createAclRole", responseObject = AclRoleResponse.class, description = "Creates an acl role")
public class CreateAclRoleCmd extends BaseCmd {
public static final Logger s_logger = Logger.getLogger(CreateAclRoleCmd.class.getName());
private static final String s_name = "createaclroleresponse";
// ///////////////////////////////////////////////////
// ////////////// API parameters /////////////////////
// ///////////////////////////////////////////////////
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, description = "domainId of the account owning the acl role", entityType = DomainResponse.class)
private Long domainId;
@Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "optional description of the acl role")
private String description;
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "name of the acl group")
private String name;
// ///////////////////////////////////////////////////
// ///////////////// Accessors ///////////////////////
// ///////////////////////////////////////////////////
public String getDescription() {
return description;
}
public Long getDomainId() {
return domainId;
}
public String getName() {
return name;
}
// ///////////////////////////////////////////////////
// ///////////// API Implementation///////////////////
// ///////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM;
}
@Override
public void execute() {
AclRole role = _aclService.createAclRole(domainId, name, description);
if (role != null) {
AclRoleResponse response = _responseGenerator.createAclRoleResponse(role);
response.setResponseName(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create acl role:" + name);
}
}
}

View File

@ -0,0 +1,79 @@
// 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 org.apache.cloudstack.api.command.admin.acl;
import org.apache.log4j.Logger;
import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.AclRoleResponse;
import org.apache.cloudstack.api.response.SuccessResponse;
import com.cloud.user.Account;
@APICommand(name = "deleteAclRole", description = "Deletes acl role", responseObject = SuccessResponse.class)
public class DeleteAclRoleCmd extends BaseCmd {
public static final Logger s_logger = Logger.getLogger(DeleteAclRoleCmd.class.getName());
private static final String s_name = "deleteaclroleresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@ACL
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, description = "The ID of the acl role.", required = true, entityType = AclRoleResponse.class)
private Long id;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getId() {
return id;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM;
}
@Override
public void execute(){
boolean result = _aclService.deleteAclRole(id);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete acl role");
}
}
}

View File

@ -0,0 +1,82 @@
// 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 org.apache.cloudstack.api.command.admin.acl;
import org.apache.log4j.Logger;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseListDomainResourcesCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.AclRoleResponse;
import org.apache.cloudstack.api.response.ListResponse;
@APICommand(name = "listAclRoles", description = "Lists acl roles", responseObject = AclRoleResponse.class)
public class ListAclRolesCmd extends BaseListDomainResourcesCmd {
public static final Logger s_logger = Logger.getLogger(ListAclRolesCmd.class.getName());
private static final String s_name = "listaclrolesresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "lists acl roles by name")
private String aclRoleName;
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, description = "list the acl role by the id provided", entityType = AclRoleResponse.class)
private Long id;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public String getAclRoleName() {
return aclRoleName;
}
public Long getId(){
return id;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public void execute(){
ListResponse<AclRoleResponse> response = _queryService.listAclRoles(id, aclRoleName, getDomainId(),
getStartIndex(), getPageSizeVal());
response.setResponseName(getCommandName());
setResponseObject(response);
}
@Override
public ApiCommandJobType getInstanceType() {
return ApiCommandJobType.AclRole;
}
}

View File

@ -0,0 +1,105 @@
// 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 org.apache.cloudstack.api.command.admin.acl;
import java.util.List;
import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.AclGroup;
import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.AclGroupResponse;
import org.apache.cloudstack.api.response.AclRoleResponse;
import org.apache.cloudstack.context.CallContext;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.Account;
@APICommand(name = "removeAclRoleFromAclGroup", description = "remove acl role to an acl group", responseObject = AclGroupResponse.class)
public class RemoveAclRoleFromAclGroupCmd extends BaseCmd {
public static final Logger s_logger = Logger.getLogger(RemoveAclRoleFromAclGroupCmd.class.getName());
private static final String s_name = "removeaclroletoaclgroupresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@ACL
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = AclGroupResponse.class,
required = true, description = "The ID of the acl group")
private Long id;
@ACL
@Parameter(name = ApiConstants.ACL_ROLES, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = AclRoleResponse.class, description = "comma separated list of acl role id that are going to be applied to the acl group.")
private List<Long> roleIdList;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getId() {
return id;
}
public List<Long> getRoleIdList() {
return roleIdList;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
}
@Override
public void execute() throws ResourceUnavailableException,
InsufficientCapacityException, ServerApiException {
CallContext.current().setEventDetails("Acl group Id: " + getId());
AclGroup result = _aclService.removeAclRolesFromGroup(roleIdList, id);
if (result != null){
AclGroupResponse response = _responseGenerator.createAclGroupResponse(result);
response.setResponseName(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add roles to acl group");
}
}
}

View File

@ -0,0 +1,149 @@
// 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 org.apache.cloudstack.api.response;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.acl.AclGroup;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.EntityReference;
import com.cloud.serializer.Param;
@SuppressWarnings("unused")
@EntityReference(value = AclGroup.class)
public class AclGroupResponse extends BaseResponse {
@SerializedName(ApiConstants.ID)
@Param(description = "the ID of the acl group")
private String id;
@SerializedName(ApiConstants.NAME)
@Param(description = "the name of the acl group")
private String name;
@SerializedName(ApiConstants.DESCRIPTION)
@Param(description = "the description of the acl group")
private String description;
@SerializedName(ApiConstants.DOMAIN_ID)
@Param(description = "the domain ID of the acl group")
private String domainId;
@SerializedName(ApiConstants.DOMAIN)
@Param(description = "the domain name of the acl role")
private String domainName;
@SerializedName(ApiConstants.ACL_ACCOUNT_IDS)
@Param(description = "account Ids assigned to this acl group ")
private List<String> accountIdList;
@SerializedName(ApiConstants.ACL_ROLES)
@Param(description = "acl roles granted to this acl group ")
private Set<AclRoleResponse> roleList;
public AclGroupResponse() {
roleList = new LinkedHashSet<AclRoleResponse>();
}
@Override
public String getObjectId() {
return getId();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setDescription(String description) {
this.description = description;
}
public void setDomainId(String domainId) {
this.domainId = domainId;
}
public void setDomainName(String domainName) {
this.domainName = domainName;
}
public void setAccountIdList(List<String> acctIdList) {
accountIdList = acctIdList;
}
public void addAccountId(String acctId) {
if (accountIdList == null) {
accountIdList = new ArrayList<String>();
}
accountIdList.add(acctId);
}
public void setRoleList(Set<AclRoleResponse> roles) {
roleList = roles;
}
public void addRole(AclRoleResponse role) {
roleList.add(role);
}
public Set<AclRoleResponse> getRoleList() {
return roleList;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AclGroupResponse other = (AclGroupResponse)obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
}

View File

@ -0,0 +1,149 @@
// 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 org.apache.cloudstack.api.response;
import java.util.ArrayList;
import java.util.List;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.acl.AclRole;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.EntityReference;
import com.cloud.serializer.Param;
@SuppressWarnings("unused")
@EntityReference(value = AclRole.class)
public class AclRoleResponse extends BaseResponse {
@SerializedName(ApiConstants.ID)
@Param(description = "the ID of the acl role")
private String id;
@SerializedName(ApiConstants.NAME)
@Param(description = "the name of the acl role")
private String name;
@SerializedName(ApiConstants.DESCRIPTION)
@Param(description = "the description of the acl role")
private String description;
@SerializedName(ApiConstants.ACL_PARENT_ROLE_ID)
@Param(description = "parent role id that this acl role is inherited from ")
private String parentRoleId;
@SerializedName(ApiConstants.ACL_PARENT_ROLE_NAME)
@Param(description = "parent role name that this acl role is inherited from ")
private String parentRoleName;
@SerializedName(ApiConstants.DOMAIN_ID)
@Param(description = "the domain ID of the acl role")
private String domainId;
@SerializedName(ApiConstants.DOMAIN)
@Param(description = "the domain name of the acl role")
private String domainName;
@SerializedName(ApiConstants.ACL_ALLOWED_APIS)
@Param(description = "allowed apis for the acl role ")
private List<String> apiList;
public AclRoleResponse() {
apiList = new ArrayList<String>();
}
@Override
public String getObjectId() {
return getId();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setDescription(String description) {
this.description = description;
}
public void setParentRoleId(String parentId) {
parentRoleId = parentId;
}
public void setParentRoleName(String parentRoleName) {
this.parentRoleName = parentRoleName;
}
public void setDomainId(String domainId) {
this.domainId = domainId;
}
public void setDomainName(String domainName) {
this.domainName = domainName;
}
public List<String> getApiList() {
return apiList;
}
public void setApiList(List<String> apiList) {
this.apiList = apiList;
}
public void addApi(String api) {
apiList.add(api);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AclRoleResponse other = (AclRoleResponse) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
}

View File

@ -16,12 +16,14 @@
// under the License.
package org.apache.cloudstack.query;
import java.util.List;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.api.command.admin.host.ListHostsCmd;
import org.apache.cloudstack.api.command.admin.internallb.ListInternalLBVMsCmd;
import org.apache.cloudstack.api.command.admin.router.ListRoutersCmd;
import org.apache.cloudstack.api.command.admin.storage.ListSecondaryStagingStoresCmd;
import org.apache.cloudstack.api.command.admin.storage.ListImageStoresCmd;
import org.apache.cloudstack.api.command.admin.storage.ListSecondaryStagingStoresCmd;
import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolsCmd;
import org.apache.cloudstack.api.command.admin.user.ListUsersCmd;
import org.apache.cloudstack.api.command.user.account.ListAccountsCmd;
@ -41,12 +43,32 @@ import org.apache.cloudstack.api.command.user.vmgroup.ListVMGroupsCmd;
import org.apache.cloudstack.api.command.user.volume.ListResourceDetailsCmd;
import org.apache.cloudstack.api.command.user.volume.ListVolumesCmd;
import org.apache.cloudstack.api.command.user.zone.ListZonesByCmd;
import org.apache.cloudstack.api.response.*;
import org.apache.cloudstack.api.response.AccountResponse;
import org.apache.cloudstack.api.response.AclRoleResponse;
import org.apache.cloudstack.api.response.AsyncJobResponse;
import org.apache.cloudstack.api.response.DiskOfferingResponse;
import org.apache.cloudstack.api.response.DomainRouterResponse;
import org.apache.cloudstack.api.response.EventResponse;
import org.apache.cloudstack.api.response.HostResponse;
import org.apache.cloudstack.api.response.ImageStoreResponse;
import org.apache.cloudstack.api.response.InstanceGroupResponse;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.ProjectAccountResponse;
import org.apache.cloudstack.api.response.ProjectInvitationResponse;
import org.apache.cloudstack.api.response.ProjectResponse;
import org.apache.cloudstack.api.response.ResourceDetailResponse;
import org.apache.cloudstack.api.response.ResourceTagResponse;
import org.apache.cloudstack.api.response.SecurityGroupResponse;
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
import org.apache.cloudstack.api.response.StoragePoolResponse;
import org.apache.cloudstack.api.response.TemplateResponse;
import org.apache.cloudstack.api.response.UserResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.VolumeResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import com.cloud.exception.PermissionDeniedException;
import java.util.List;
/**
* Service used for list api query.
*
@ -104,4 +126,7 @@ public interface QueryService {
ListResponse<DomainRouterResponse> searchForInternalLbVms(ListInternalLBVMsCmd cmd);
public ListResponse<AclRoleResponse> listAclRoles(Long aclRoleId, String aclRoleName,
Long domainId, Long startIndex, Long pageSize);
}

View File

@ -45,6 +45,9 @@ public class AclGroupVO implements AclGroup {
@Column(name = "uuid")
private String uuid;
@Column(name = "domain_id")
private long domainId;
@Column(name = GenericDao.REMOVED_COLUMN)
private Date removed;
@ -76,6 +79,10 @@ public class AclGroupVO implements AclGroup {
return description;
}
@Override
public long getDomainId() {
return domainId;
}
@Override
public String getUuid() {

View File

@ -46,7 +46,10 @@ public class AclRoleVO implements AclRole {
private String uuid;
@Column(name = "parent_role_id")
private long parentRoleId;
private Long parentRoleId;
@Column(name = "domain_id")
private long domainId;
@Column(name = GenericDao.REMOVED_COLUMN)
private Date removed;
@ -97,7 +100,8 @@ public class AclRoleVO implements AclRole {
return created;
}
public long getParentRoleId() {
@Override
public Long getParentRoleId() {
return parentRoleId;
}
@ -105,4 +109,13 @@ public class AclRoleVO implements AclRole {
this.parentRoleId = parentRoleId;
}
@Override
public long getDomainId() {
return domainId;
}
public void setDomainId(long domainId) {
this.domainId = domainId;
}
}

View File

@ -23,6 +23,6 @@ import com.cloud.utils.db.GenericDao;
public interface AclRoleDao extends GenericDao<AclRoleVO, Long> {
AclRole findByName(String roleName);
AclRole findByName(Long domainId, String roleName);
}

View File

@ -39,6 +39,7 @@ public class AclRoleDaoImpl extends GenericDaoBase<AclRoleVO, Long> implements A
nameSearch = createSearchBuilder();
nameSearch.and("name", nameSearch.entity().getName(), SearchCriteria.Op.EQ);
nameSearch.and("domainId", nameSearch.entity().getDomainId(), SearchCriteria.Op.EQ);
nameSearch.done();
@ -46,9 +47,12 @@ public class AclRoleDaoImpl extends GenericDaoBase<AclRoleVO, Long> implements A
}
@Override
public AclRole findByName(String name) {
public AclRole findByName(Long domainId, String name) {
SearchCriteria<AclRoleVO> sc = nameSearch.create();
sc.setParameters("name", name);
if (domainId != null) {
sc.setParameters("domainId", domainId);
}
return findOneBy(sc);
}

View File

@ -32,6 +32,7 @@ import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants.HostDetails;
import org.apache.cloudstack.api.ApiConstants.VMDetails;
import org.apache.cloudstack.api.response.AccountResponse;
import org.apache.cloudstack.api.response.AclRoleResponse;
import org.apache.cloudstack.api.response.AsyncJobResponse;
import org.apache.cloudstack.api.response.DiskOfferingResponse;
import org.apache.cloudstack.api.response.DomainRouterResponse;
@ -63,6 +64,7 @@ import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import com.cloud.api.query.dao.AccountJoinDao;
import com.cloud.api.query.dao.AclRoleJoinDao;
import com.cloud.api.query.dao.AffinityGroupJoinDao;
import com.cloud.api.query.dao.AsyncJobJoinDao;
import com.cloud.api.query.dao.DataCenterJoinDao;
@ -83,6 +85,7 @@ import com.cloud.api.query.dao.UserAccountJoinDao;
import com.cloud.api.query.dao.UserVmJoinDao;
import com.cloud.api.query.dao.VolumeJoinDao;
import com.cloud.api.query.vo.AccountJoinVO;
import com.cloud.api.query.vo.AclRoleJoinVO;
import com.cloud.api.query.vo.AffinityGroupJoinVO;
import com.cloud.api.query.vo.AsyncJobJoinVO;
import com.cloud.api.query.vo.DataCenterJoinVO;
@ -400,6 +403,7 @@ public class ApiDBUtils {
static NetworkACLDao _networkACLDao;
static ServiceOfferingDetailsDao _serviceOfferingDetailsDao;
static AccountService _accountService;
static AclRoleJoinDao _aclRoleJoinDao;
@Inject
@ -515,6 +519,8 @@ public class ApiDBUtils {
@Inject private AccountService accountService;
@Inject
private ConfigurationManager configMgr;
@Inject
private AclRoleJoinDao aclRoleJoinDao;
@PostConstruct
void init() {
@ -626,6 +632,7 @@ public class ApiDBUtils {
_networkACLDao = networkACLDao;
_serviceOfferingDetailsDao = serviceOfferingDetailsDao;
_accountService = accountService;
_aclRoleJoinDao = aclRoleJoinDao;
}
// ///////////////////////////////////////////////////////////
@ -1671,6 +1678,14 @@ public class ApiDBUtils {
return _affinityGroupJoinDao.setAffinityGroupResponse(resp, group);
}
public static AclRoleResponse newAclRoleResponse(AclRoleJoinVO role) {
return _aclRoleJoinDao.newAclRoleResponse(role);
}
public static AclRoleResponse fillAclRoleDetails(AclRoleResponse resp, AclRoleJoinVO role) {
return _aclRoleJoinDao.setAclRoleResponse(resp, role);
}
public static List<? extends LoadBalancer> listSiteLoadBalancers(long gslbRuleId) {
return _gslbService.listSiteLoadBalancers(gslbRuleId);
}

View File

@ -33,6 +33,8 @@ import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.AclGroup;
import org.apache.cloudstack.acl.AclRole;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.affinity.AffinityGroup;
@ -42,6 +44,8 @@ import org.apache.cloudstack.api.ApiConstants.VMDetails;
import org.apache.cloudstack.api.ResponseGenerator;
import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd;
import org.apache.cloudstack.api.response.AccountResponse;
import org.apache.cloudstack.api.response.AclGroupResponse;
import org.apache.cloudstack.api.response.AclRoleResponse;
import org.apache.cloudstack.api.response.ApplicationLoadBalancerInstanceResponse;
import org.apache.cloudstack.api.response.ApplicationLoadBalancerResponse;
import org.apache.cloudstack.api.response.ApplicationLoadBalancerRuleResponse;
@ -3668,6 +3672,46 @@ public class ApiResponseHelper implements ResponseGenerator {
}
}
@Override
public AclRoleResponse createAclRoleResponse(AclRole role) {
AclRoleResponse response = new AclRoleResponse();
response.setId(role.getUuid());
response.setName(role.getName());
response.setDescription(role.getDescription());
Domain domain = _entityMgr.findById(Domain.class, role.getDomainId());
if (domain != null) {
response.setDomainId(domain.getUuid());
response.setDomainName(domain.getName());
}
if (role.getParentRoleId() != null ){
AclRole parRole = _entityMgr.findById(AclRole.class, role.getParentRoleId());
if (parRole != null) {
response.setParentRoleId(parRole.getUuid());
}
}
response.setObjectName("aclrole");
return response;
}
@Override
public AclGroupResponse createAclGroupResponse(AclGroup group) {
AclGroupResponse response = new AclGroupResponse();
response.setId(group.getUuid());
response.setName(group.getName());
response.setDescription(group.getDescription());
Domain domain = _entityMgr.findById(Domain.class, group.getDomainId());
if (domain != null) {
response.setDomainId(domain.getUuid());
response.setDomainName(domain.getName());
}
response.setObjectName("aclgroup");
return response;
}
@Override
public PortableIpRangeResponse createPortableIPRangeResponse(PortableIpRange ipRange) {
PortableIpRangeResponse response = new PortableIpRangeResponse();

View File

@ -29,7 +29,10 @@ import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import org.apache.cloudstack.acl.AclRole;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.acl.dao.AclRoleDao;
import org.apache.cloudstack.affinity.AffinityGroupDomainMapVO;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.affinity.AffinityGroupVMMapVO;
@ -61,6 +64,7 @@ import org.apache.cloudstack.api.command.user.volume.ListResourceDetailsCmd;
import org.apache.cloudstack.api.command.user.volume.ListVolumesCmd;
import org.apache.cloudstack.api.command.user.zone.ListZonesByCmd;
import org.apache.cloudstack.api.response.AccountResponse;
import org.apache.cloudstack.api.response.AclRoleResponse;
import org.apache.cloudstack.api.response.AsyncJobResponse;
import org.apache.cloudstack.api.response.DiskOfferingResponse;
import org.apache.cloudstack.api.response.DomainRouterResponse;
@ -88,6 +92,7 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.query.QueryService;
import com.cloud.api.query.dao.AccountJoinDao;
import com.cloud.api.query.dao.AclRoleJoinDao;
import com.cloud.api.query.dao.AffinityGroupJoinDao;
import com.cloud.api.query.dao.AsyncJobJoinDao;
import com.cloud.api.query.dao.DataCenterJoinDao;
@ -108,6 +113,7 @@ import com.cloud.api.query.dao.UserAccountJoinDao;
import com.cloud.api.query.dao.UserVmJoinDao;
import com.cloud.api.query.dao.VolumeJoinDao;
import com.cloud.api.query.vo.AccountJoinVO;
import com.cloud.api.query.vo.AclRoleJoinVO;
import com.cloud.api.query.vo.AffinityGroupJoinVO;
import com.cloud.api.query.vo.AsyncJobJoinVO;
import com.cloud.api.query.vo.DataCenterJoinVO;
@ -139,8 +145,6 @@ import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.ha.HighAvailabilityManager;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.dao.NetworkDomainVO;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.security.SecurityGroupVMMapVO;
import com.cloud.network.security.dao.SecurityGroupVMMapDao;
import com.cloud.org.Grouping;
@ -327,6 +331,12 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
@Inject
AffinityGroupDomainMapDao _affinityGroupDomainMapDao;
@Inject
AclRoleJoinDao _aclRoleJoinDao;
@Inject
AclRoleDao _aclRoleDao;
/*
* (non-Javadoc)
*
@ -3248,4 +3258,108 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
}
@Override
public ListResponse<AclRoleResponse> listAclRoles(Long aclRoleId, String aclRoleName, Long domainId, Long startIndex, Long pageSize) {
Pair<List<AclRoleJoinVO>, Integer> result = listAclRolesInternal(aclRoleId, aclRoleName, domainId, true, true, startIndex, pageSize);
ListResponse<AclRoleResponse> response = new ListResponse<AclRoleResponse>();
List<AclRoleResponse> roleResponses = ViewResponseHelper.createAclRoleResponses(result.first());
response.setResponses(roleResponses, result.second());
return response;
}
private Pair<List<AclRoleJoinVO>, Integer> listAclRolesInternal(Long aclRoleId, String aclRoleName, Long domainId, boolean isRecursive, boolean listAll, Long startIndex,
Long pageSize) {
Account caller = CallContext.current().getCallingAccount();
Boolean listForDomain = false;
if (aclRoleId != null) {
AclRole role = _aclRoleDao.findById(aclRoleId);
if (role == null) {
throw new InvalidParameterValueException("Unable to find acl role by id " + aclRoleId);
}
_accountMgr.checkAccess(caller, null, true, role);
}
if (domainId != null) {
Domain domain = _domainDao.findById(domainId);
if (domain == null) {
throw new InvalidParameterValueException("Domain id=" + domainId + " doesn't exist");
}
_accountMgr.checkAccess(caller, domain);
if (aclRoleName != null) {
AclRole role = _aclRoleDao.findByName(domainId, aclRoleName);
if (role == null) {
throw new InvalidParameterValueException("Unable to find acl role by name " + aclRoleName
+ " in domain " + domainId);
}
_accountMgr.checkAccess(caller, null, true, role);
}
}
if (aclRoleId == null) {
if (_accountMgr.isAdmin(caller.getType()) && listAll && domainId == null) {
listForDomain = true;
isRecursive = true;
if (domainId == null) {
domainId = caller.getDomainId();
}
} else if (_accountMgr.isAdmin(caller.getType()) && domainId != null) {
listForDomain = true;
}
}
Filter searchFilter = new Filter(AccountJoinVO.class, "id", true, startIndex, pageSize);
SearchBuilder<AclRoleJoinVO> sb = _aclRoleJoinDao.createSearchBuilder();
sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ);
sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
if (listForDomain && isRecursive) {
sb.and("path", sb.entity().getDomainPath(), SearchCriteria.Op.LIKE);
}
SearchCriteria<AclRoleJoinVO> sc = sb.create();
if (aclRoleName != null) {
sc.setParameters("name", aclRoleName);
}
if (aclRoleId != null) {
sc.setParameters("id", aclRoleId);
}
if (listForDomain) {
if (isRecursive) {
Domain domain = _domainDao.findById(domainId);
sc.setParameters("path", domain.getPath() + "%");
} else {
sc.setParameters("domainId", domainId);
}
}
// search role details by ids
Pair<List<AclRoleJoinVO>, Integer> uniqueRolePair = _aclRoleJoinDao.searchAndCount(sc, searchFilter);
Integer count = uniqueRolePair.second();
if (count.intValue() == 0) {
// empty result
return uniqueRolePair;
}
List<AclRoleJoinVO> uniqueRoles = uniqueRolePair.first();
Long[] vrIds = new Long[uniqueRoles.size()];
int i = 0;
for (AclRoleJoinVO v : uniqueRoles) {
vrIds[i++] = v.getId();
}
List<AclRoleJoinVO> vrs = _aclRoleJoinDao.searchByIds(vrIds);
return new Pair<List<AclRoleJoinVO>, Integer>(vrs, count);
}
}

View File

@ -16,40 +16,26 @@
// under the License.
package com.cloud.api.query;
import com.cloud.api.ApiDBUtils;
import com.cloud.api.query.vo.AccountJoinVO;
import com.cloud.api.query.vo.AffinityGroupJoinVO;
import com.cloud.api.query.vo.AsyncJobJoinVO;
import com.cloud.api.query.vo.DataCenterJoinVO;
import com.cloud.api.query.vo.DiskOfferingJoinVO;
import com.cloud.api.query.vo.DomainRouterJoinVO;
import com.cloud.api.query.vo.EventJoinVO;
import com.cloud.api.query.vo.HostJoinVO;
import com.cloud.api.query.vo.InstanceGroupJoinVO;
import com.cloud.api.query.vo.ProjectAccountJoinVO;
import com.cloud.api.query.vo.ProjectInvitationJoinVO;
import com.cloud.api.query.vo.ProjectJoinVO;
import com.cloud.api.query.vo.ResourceTagJoinVO;
import com.cloud.api.query.vo.SecurityGroupJoinVO;
import com.cloud.api.query.vo.ServiceOfferingJoinVO;
import com.cloud.api.query.vo.StoragePoolJoinVO;
import com.cloud.api.query.vo.UserAccountJoinVO;
import com.cloud.api.query.vo.UserVmJoinVO;
import com.cloud.api.query.vo.VolumeJoinVO;
import com.cloud.user.Account;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.Hashtable;
import java.util.List;
import org.apache.log4j.Logger;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.api.ApiConstants.HostDetails;
import org.apache.cloudstack.api.ApiConstants.VMDetails;
import org.apache.cloudstack.api.response.AccountResponse;
import org.apache.cloudstack.api.response.AclRoleResponse;
import org.apache.cloudstack.api.response.AsyncJobResponse;
import org.apache.cloudstack.api.response.DiskOfferingResponse;
import org.apache.cloudstack.api.response.DomainRouterResponse;
import org.apache.cloudstack.api.response.EventResponse;
import org.apache.cloudstack.api.response.HostForMigrationResponse;
import org.apache.cloudstack.api.response.HostResponse;
import org.apache.cloudstack.api.response.InstanceGroupResponse;
import org.apache.cloudstack.api.response.ImageStoreResponse;
import org.apache.cloudstack.api.response.InstanceGroupResponse;
import org.apache.cloudstack.api.response.ProjectAccountResponse;
import org.apache.cloudstack.api.response.ProjectInvitationResponse;
import org.apache.cloudstack.api.response.ProjectResponse;
@ -64,15 +50,30 @@ import org.apache.cloudstack.api.response.VolumeResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.log4j.Logger;
import com.cloud.api.ApiDBUtils;
import com.cloud.api.query.vo.AccountJoinVO;
import com.cloud.api.query.vo.AclRoleJoinVO;
import com.cloud.api.query.vo.AffinityGroupJoinVO;
import com.cloud.api.query.vo.AsyncJobJoinVO;
import com.cloud.api.query.vo.DataCenterJoinVO;
import com.cloud.api.query.vo.DiskOfferingJoinVO;
import com.cloud.api.query.vo.DomainRouterJoinVO;
import com.cloud.api.query.vo.EventJoinVO;
import com.cloud.api.query.vo.HostJoinVO;
import com.cloud.api.query.vo.ImageStoreJoinVO;
import com.cloud.api.query.vo.InstanceGroupJoinVO;
import com.cloud.api.query.vo.ProjectAccountJoinVO;
import com.cloud.api.query.vo.ProjectInvitationJoinVO;
import com.cloud.api.query.vo.ProjectJoinVO;
import com.cloud.api.query.vo.ResourceTagJoinVO;
import com.cloud.api.query.vo.SecurityGroupJoinVO;
import com.cloud.api.query.vo.ServiceOfferingJoinVO;
import com.cloud.api.query.vo.StoragePoolJoinVO;
import com.cloud.api.query.vo.TemplateJoinVO;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.Hashtable;
import java.util.List;
import com.cloud.api.query.vo.UserAccountJoinVO;
import com.cloud.api.query.vo.UserVmJoinVO;
import com.cloud.api.query.vo.VolumeJoinVO;
import com.cloud.user.Account;
/**
* Helper class to generate response from DB view VO objects.
@ -436,4 +437,20 @@ public class ViewResponseHelper {
}
return new ArrayList<AffinityGroupResponse>(vrDataList.values());
}
public static List<AclRoleResponse> createAclRoleResponses(List<AclRoleJoinVO> roles) {
Hashtable<Long, AclRoleResponse> vrDataList = new Hashtable<Long, AclRoleResponse>();
for (AclRoleJoinVO vr : roles) {
AclRoleResponse vrData = vrDataList.get(vr.getId());
if (vrData == null) {
// first time encountering this Acl role
vrData = ApiDBUtils.newAclRoleResponse(vr);
} else {
// update vms
vrData = ApiDBUtils.fillAclRoleDetails(vrData, vr);
}
vrDataList.put(vr.getId(), vrData);
}
return new ArrayList<AclRoleResponse>(vrDataList.values());
}
}

View File

@ -0,0 +1,36 @@
// 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.api.query.dao;
import java.util.List;
import org.apache.cloudstack.acl.AclRole;
import org.apache.cloudstack.api.response.AclRoleResponse;
import com.cloud.api.query.vo.AclRoleJoinVO;
import com.cloud.utils.db.GenericDao;
public interface AclRoleJoinDao extends GenericDao<AclRoleJoinVO, Long> {
AclRoleResponse newAclRoleResponse(AclRoleJoinVO role);
AclRoleResponse setAclRoleResponse(AclRoleResponse response, AclRoleJoinVO os);
List<AclRoleJoinVO> newAclRoleView(AclRole role);
List<AclRoleJoinVO> searchByIds(Long... ids);
}

View File

@ -0,0 +1,147 @@
// 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.api.query.dao;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Local;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import org.apache.cloudstack.acl.AclRole;
import org.apache.cloudstack.api.response.AclRoleResponse;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import com.cloud.api.query.vo.AclRoleJoinVO;
import com.cloud.user.AccountManager;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
@Component
@Local(value = {AclRoleJoinDao.class})
public class AclRoleJoinDaoImpl extends GenericDaoBase<AclRoleJoinVO, Long> implements AclRoleJoinDao {
public static final Logger s_logger = Logger.getLogger(AclRoleJoinDaoImpl.class);
private final SearchBuilder<AclRoleJoinVO> roleIdSearch;
private final SearchBuilder<AclRoleJoinVO> roleSearch;
@Inject
public AccountManager _accountMgr;
@Inject
public ConfigurationDao _configDao;
protected AclRoleJoinDaoImpl() {
roleSearch = createSearchBuilder();
roleSearch.and("idIN", roleSearch.entity().getId(), SearchCriteria.Op.IN);
roleSearch.done();
roleIdSearch = createSearchBuilder();
roleIdSearch.and("id", roleIdSearch.entity().getId(), SearchCriteria.Op.EQ);
roleIdSearch.done();
_count = "select count(distinct id) from acl_role_view WHERE ";
}
@Override
public AclRoleResponse newAclRoleResponse(AclRoleJoinVO role) {
AclRoleResponse response = new AclRoleResponse();
response.setId(role.getUuid());
response.setName(role.getName());
response.setDescription(role.getDescription());
response.setParentRoleId(role.getParentRoleUuid());
response.setParentRoleName(role.getParentRoleName());
response.setDomainId(role.getDomainUuid());
response.setDomainName(role.getName());
if (role.getApiName() != null) {
response.addApi(role.getApiName());
}
response.setObjectName("aclrole");
return response;
}
@Override
public AclRoleResponse setAclRoleResponse(AclRoleResponse response, AclRoleJoinVO role) {
if (role.getApiName() != null) {
response.addApi(role.getApiName());
}
return response;
}
@Override
public List<AclRoleJoinVO> newAclRoleView(AclRole role) {
SearchCriteria<AclRoleJoinVO> sc = roleIdSearch.create();
sc.setParameters("id", role.getId());
return searchIncludingRemoved(sc, null, null, false);
}
@Override
public List<AclRoleJoinVO> searchByIds(Long... roleIds) {
// set detail batch query size
int DETAILS_BATCH_SIZE = 2000;
String batchCfg = _configDao.getValue("detail.batch.query.size");
if (batchCfg != null) {
DETAILS_BATCH_SIZE = Integer.parseInt(batchCfg);
}
// query details by batches
List<AclRoleJoinVO> uvList = new ArrayList<AclRoleJoinVO>();
// query details by batches
int curr_index = 0;
if (roleIds.length > DETAILS_BATCH_SIZE) {
while ((curr_index + DETAILS_BATCH_SIZE) <= roleIds.length) {
Long[] ids = new Long[DETAILS_BATCH_SIZE];
for (int k = 0, j = curr_index; j < curr_index + DETAILS_BATCH_SIZE; j++, k++) {
ids[k] = roleIds[j];
}
SearchCriteria<AclRoleJoinVO> sc = roleSearch.create();
sc.setParameters("idIN", ids);
List<AclRoleJoinVO> vms = searchIncludingRemoved(sc, null, null, false);
if (vms != null) {
uvList.addAll(vms);
}
curr_index += DETAILS_BATCH_SIZE;
}
}
if (curr_index < roleIds.length) {
int batch_size = (roleIds.length - curr_index);
// set the ids value
Long[] ids = new Long[batch_size];
for (int k = 0, j = curr_index; j < curr_index + batch_size; j++, k++) {
ids[k] = roleIds[j];
}
SearchCriteria<AclRoleJoinVO> sc = roleSearch.create();
sc.setParameters("idIN", ids);
List<AclRoleJoinVO> vms = searchIncludingRemoved(sc, null, null, false);
if (vms != null) {
uvList.addAll(vms);
}
}
return uvList;
}
}

View File

@ -0,0 +1,142 @@
// 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.api.query.vo;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import com.cloud.utils.db.GenericDao;
@Entity
@Table(name = ("acl_role_view"))
public class AclRoleJoinVO extends BaseViewVO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@Column(name = "name")
private String name;
@Column(name = "description")
private String description;
@Column(name = "uuid")
private String uuid;
@Column(name = "parent_role_id")
private Long parentRoleId;
@Column(name = "parent_role_uuid")
private String parentRoleUuid;
@Column(name = "parent_role_name")
private String parentRoleName;
@Column(name = "domain_id")
private long domainId;
@Column(name = "domain_uuid")
private String domainUuid;
@Column(name = "domain_name")
private String domainName;
@Column(name = "domain_path")
private String domainPath;
@Column(name = "api_name")
private String apiName;
@Column(name = GenericDao.REMOVED_COLUMN)
private Date removed;
@Column(name = GenericDao.CREATED_COLUMN)
private Date created;
public AclRoleJoinVO() {
}
@Override
public long getId() {
return id;
}
@Override
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public String getUuid() {
return uuid;
}
public Long getParentRoleId() {
return parentRoleId;
}
public long getDomainId() {
return domainId;
}
public String getDomainUuid() {
return domainUuid;
}
public String getDomainName() {
return domainName;
}
public String getDomainPath() {
return domainPath;
}
public String getApiName() {
return apiName;
}
public Date getRemoved() {
return removed;
}
public Date getCreated() {
return created;
}
public String getParentRoleUuid() {
return parentRoleUuid;
}
public String getParentRoleName() {
return parentRoleName;
}
}

View File

@ -39,6 +39,7 @@ import javax.naming.ConfigurationException;
import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.AclGroupAccountMapVO;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.acl.RoleType;
@ -73,6 +74,7 @@ import com.cloud.dc.dao.DataCenterVnetDao;
import com.cloud.dc.dao.DedicatedResourceDao;
import com.cloud.domain.Domain;
import com.cloud.domain.DomainVO;
import com.cloud.domain.PartOf;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEvent;
import com.cloud.event.ActionEventUtils;
@ -388,6 +390,14 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to " + domain);
}
@Override
public void checkAccess(Account account, AccessType accessType, boolean sameOwner, PartOf... entities) throws PermissionDeniedException {
// TODO Auto-generated method stub
//TO BE IMPLEMENTED
}
@Override
public void checkAccess(Account caller, AccessType accessType, boolean sameOwner, ControlledEntity... entities) {

View File

@ -0,0 +1,180 @@
// 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 org.apache.cloudstack.acl;
import java.util.List;
import javax.ejb.Local;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.dao.AclApiPermissionDao;
import org.apache.cloudstack.acl.dao.AclEntityPermissionDao;
import org.apache.cloudstack.acl.dao.AclGroupAccountMapDao;
import org.apache.cloudstack.acl.dao.AclGroupRoleMapDao;
import org.apache.cloudstack.acl.dao.AclRoleDao;
import org.apache.cloudstack.context.CallContext;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.utils.Pair;
import com.cloud.utils.component.Manager;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.DB;
@Local(value = {AclService.class})
public class AclServiceImpl extends ManagerBase implements AclService, Manager {
public static final Logger s_logger = Logger.getLogger(AclServiceImpl.class);
private String _name;
@Inject
AccountManager _accountMgr;
@Inject
AclRoleDao _aclRoleDao;
@Inject
AclGroupRoleMapDao _aclGroupRoleMapDao;
@Inject
AclGroupAccountMapDao _aclGroupAccountMapDao;
@Inject
AclApiPermissionDao _apiPermissionDao;
@Inject
AclEntityPermissionDao _entityPermissionDao;
@DB
@Override
public AclRole createAclRole(Long domainId, String aclRoleName, String description) {
Account caller = CallContext.current().getCallingAccount();
if (!_accountMgr.isRootAdmin(caller.getAccountId())) {
// domain admin can only create role for his domain
if (domainId != null && caller.getDomainId() != domainId.longValue()) {
throw new PermissionDeniedException("Can't create acl role in domain " + domainId + ", permission denied");
}
}
// check if the role is already existing
AclRole ro = _aclRoleDao.findByName(domainId, aclRoleName);
if (ro != null) {
throw new InvalidParameterValueException(
"Unable to create acl role with name " + aclRoleName
+ " already exisits for domain " + domainId);
}
AclRoleVO rvo = new AclRoleVO(aclRoleName, description);
if (domainId != null) {
rvo.setDomainId(domainId);
}
return _aclRoleDao.persist(rvo);
}
@DB
@Override
public boolean deleteAclRole(long aclRoleId) {
Account caller = CallContext.current().getCallingAccount();
// get the Acl Role entity
AclRole role = _aclRoleDao.findById(aclRoleId);
if (role == null) {
throw new InvalidParameterValueException("Unable to find acl role: " + aclRoleId
+ "; failed to delete acl role.");
}
// check permissions
if (!_accountMgr.isRootAdmin(caller.getAccountId())) {
// domain admin can only delete role for his domain
if (caller.getDomainId() != role.getDomainId()) {
throw new PermissionDeniedException("Can't delete acl role in domain " + role.getDomainId() + ", permission denied");
}
}
// remove this role related entry in acl_group_role_map
List<AclGroupRoleMapVO> groupRoleMap = _aclGroupRoleMapDao.listByRoleId(role.getId());
if (groupRoleMap != null) {
for (AclGroupRoleMapVO gr : groupRoleMap) {
_aclGroupRoleMapDao.remove(gr.getId());
}
}
// remove this role related entry in acl_api_permission table
List<AclApiPermissionVO> roleApiMap = _apiPermissionDao.listByRoleId(role.getId());
if (roleApiMap != null) {
for (AclApiPermissionVO roleApi : roleApiMap) {
_apiPermissionDao.remove(roleApi.getId());
}
}
// remove this role from acl_role table
_aclRoleDao.remove(aclRoleId);
return true;
}
@Override
public Pair<List<? extends AclRole>, Integer> listAclRoles(Long aclRoleId, String aclRoleName, Long domainId, Long startIndex, Long pageSize) {
// TODO Auto-generated method stub
return null;
}
@Override
public AclRole getAclRole(Long roleId) {
// TODO Auto-generated method stub
return null;
}
@Override
public AclGroup addAclRolesToGroup(List<Long> roleIds, Long groupId) {
// TODO Auto-generated method stub
return null;
}
@Override
public AclGroup removeAclRolesFromGroup(List<Long> roleIds, Long groupId) {
// TODO Auto-generated method stub
return null;
}
@Override
public AclGroup createAclGroup(Long domainId, String aclGroupName, String description) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean deleteAclGroup(Long aclGroupId) {
// TODO Auto-generated method stub
return false;
}
@Override
public Pair<List<? extends AclRole>, Integer> listAclGroups(Long aclRoleId, String aclRoleName, Long domainId, Long startIndex, Long pageSize) {
// TODO Auto-generated method stub
return null;
}
@Override
public AclRole getAclGroup(Long groupId) {
// TODO Auto-generated method stub
return null;
}
}

View File

@ -22,6 +22,8 @@ import java.util.Map;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import org.springframework.stereotype.Component;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
@ -29,10 +31,10 @@ 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.RegisterCmd;
import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd;
import org.springframework.stereotype.Component;
import com.cloud.api.query.vo.ControlledViewEntity;
import com.cloud.domain.Domain;
import com.cloud.domain.PartOf;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceUnavailableException;
@ -225,6 +227,12 @@ public class MockAccountManagerImpl extends ManagerBase implements Manager, Acco
// TODO Auto-generated method stub
}
@Override
public void checkAccess(Account account, AccessType accessType, boolean sameOwner, PartOf... entities) throws PermissionDeniedException {
// TODO Auto-generated method stub
}
@Override
public void logoutUser(long userId) {
// TODO Auto-generated method stub

View File

@ -288,6 +288,7 @@ CREATE TABLE `cloud`.`acl_group` (
`name` varchar(255) NOT NULL,
`description` varchar(255) default NULL,
`uuid` varchar(40),
`domain_id` bigint unsigned NOT NULL,
`removed` datetime COMMENT 'date the group was removed',
`created` datetime COMMENT 'date the group was created',
PRIMARY KEY (`id`),
@ -312,6 +313,7 @@ CREATE TABLE `cloud`.`acl_role` (
`description` varchar(255) default NULL,
`uuid` varchar(40),
`parent_role_id` bigint unsigned DEFAULT 0,
`domain_id` bigint unsigned NOT NULL,
`removed` datetime COMMENT 'date the role was removed',
`created` datetime COMMENT 'date the role was created',
PRIMARY KEY (`id`),
@ -365,3 +367,31 @@ CREATE TABLE `cloud`.`acl_entity_permission` (
PRIMARY KEY (`id`),
CONSTRAINT `fk_acl_entity_permission__group_id` FOREIGN KEY(`group_id`) REFERENCES `acl_group` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP VIEW IF EXISTS `cloud`.`acl_role_view`;
CREATE VIEW `cloud`.`acl_role_view` AS
select
acl_role.id id,
acl_role.uuid uuid,
acl_role.name name,
acl_role.description description,
parent_role.id parent_role_id,
parent_role.uuid parent_role_uuid,
parent_role.name parent_role_name,
acl_role.removed removed,
acl_role.created created,
domain.id domain_id,
domain.uuid domain_uuid,
domain.name domain_name,
domain.path domain_path,
acl_api_permission.api api_name
from
`cloud`.`acl_role`
inner join
`cloud`.`domain` ON acl_role.domain_id = domain.id
left join
`cloud`.`acl_role` parent_role on parent_role.id = acl_role.parent_role_id
left join
`cloud`.`acl_api_permission` ON acl_role.id = acl_api_permission.role_id;