From fce2aad23d3a6656b4a2dfc9bebc487ea7a0150d Mon Sep 17 00:00:00 2001 From: Min Chen Date: Thu, 26 Sep 2013 11:22:43 -0700 Subject: [PATCH] WIP For APIs related to ACL Roles. --- api/src/com/cloud/user/AccountService.java | 3 + .../org/apache/cloudstack/acl/AclGroup.java | 5 +- .../org/apache/cloudstack/acl/AclRole.java | 6 +- .../org/apache/cloudstack/acl/AclService.java | 103 ++++++++++ .../cloudstack/api/ApiCommandJobType.java | 4 +- .../apache/cloudstack/api/ApiConstants.java | 8 +- .../org/apache/cloudstack/api/BaseCmd.java | 17 +- .../cloudstack/api/ResponseGenerator.java | 8 + .../admin/acl/AddAclRoleToAclGroupCmd.java | 105 ++++++++++ .../command/admin/acl/CreateAclRoleCmd.java | 98 ++++++++++ .../command/admin/acl/DeleteAclRoleCmd.java | 79 ++++++++ .../command/admin/acl/ListAclRolesCmd.java | 82 ++++++++ .../acl/RemoveAclRoleFromAclGroupCmd.java | 105 ++++++++++ .../api/response/AclGroupResponse.java | 149 +++++++++++++++ .../api/response/AclRoleResponse.java | 149 +++++++++++++++ .../apache/cloudstack/query/QueryService.java | 33 +++- .../org/apache/cloudstack/acl/AclGroupVO.java | 7 + .../org/apache/cloudstack/acl/AclRoleVO.java | 17 +- .../apache/cloudstack/acl/dao/AclRoleDao.java | 2 +- .../cloudstack/acl/dao/AclRoleDaoImpl.java | 6 +- server/src/com/cloud/api/ApiDBUtils.java | 15 ++ .../src/com/cloud/api/ApiResponseHelper.java | 44 +++++ .../com/cloud/api/query/QueryManagerImpl.java | 118 +++++++++++- .../cloud/api/query/ViewResponseHelper.java | 75 +++++--- .../cloud/api/query/dao/AclRoleJoinDao.java | 36 ++++ .../api/query/dao/AclRoleJoinDaoImpl.java | 147 ++++++++++++++ .../com/cloud/api/query/vo/AclRoleJoinVO.java | 142 ++++++++++++++ .../com/cloud/user/AccountManagerImpl.java | 10 + .../apache/cloudstack/acl/AclServiceImpl.java | 180 ++++++++++++++++++ .../cloud/user/MockAccountManagerImpl.java | 10 +- setup/db/db/schema-420to430.sql | 30 +++ 31 files changed, 1739 insertions(+), 54 deletions(-) create mode 100644 api/src/org/apache/cloudstack/acl/AclService.java create mode 100644 api/src/org/apache/cloudstack/api/command/admin/acl/AddAclRoleToAclGroupCmd.java create mode 100644 api/src/org/apache/cloudstack/api/command/admin/acl/CreateAclRoleCmd.java create mode 100644 api/src/org/apache/cloudstack/api/command/admin/acl/DeleteAclRoleCmd.java create mode 100644 api/src/org/apache/cloudstack/api/command/admin/acl/ListAclRolesCmd.java create mode 100644 api/src/org/apache/cloudstack/api/command/admin/acl/RemoveAclRoleFromAclGroupCmd.java create mode 100644 api/src/org/apache/cloudstack/api/response/AclGroupResponse.java create mode 100644 api/src/org/apache/cloudstack/api/response/AclRoleResponse.java create mode 100644 server/src/com/cloud/api/query/dao/AclRoleJoinDao.java create mode 100644 server/src/com/cloud/api/query/dao/AclRoleJoinDaoImpl.java create mode 100644 server/src/com/cloud/api/query/vo/AclRoleJoinVO.java create mode 100644 server/src/org/apache/cloudstack/acl/AclServiceImpl.java diff --git a/api/src/com/cloud/user/AccountService.java b/api/src/com/cloud/user/AccountService.java index 2101d1e525d..89bbbd8285e 100755 --- a/api/src/com/cloud/user/AccountService.java +++ b/api/src/com/cloud/user/AccountService.java @@ -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; } diff --git a/api/src/org/apache/cloudstack/acl/AclGroup.java b/api/src/org/apache/cloudstack/acl/AclGroup.java index bc4732da30d..f822e4c7250 100644 --- a/api/src/org/apache/cloudstack/acl/AclGroup.java +++ b/api/src/org/apache/cloudstack/acl/AclGroup.java @@ -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(); - } diff --git a/api/src/org/apache/cloudstack/acl/AclRole.java b/api/src/org/apache/cloudstack/acl/AclRole.java index bef859a8cdd..0aaed719b0a 100644 --- a/api/src/org/apache/cloudstack/acl/AclRole.java +++ b/api/src/org/apache/cloudstack/acl/AclRole.java @@ -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(); } diff --git a/api/src/org/apache/cloudstack/acl/AclService.java b/api/src/org/apache/cloudstack/acl/AclService.java new file mode 100644 index 00000000000..ff4fa2956e8 --- /dev/null +++ b/api/src/org/apache/cloudstack/acl/AclService.java @@ -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, 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 roleIds, Long groupId); + + AclGroup removeAclRolesFromGroup(List 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, 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); + +} diff --git a/api/src/org/apache/cloudstack/api/ApiCommandJobType.java b/api/src/org/apache/cloudstack/api/ApiCommandJobType.java index 204fe3ed8f4..c48e6494477 100644 --- a/api/src/org/apache/cloudstack/api/ApiCommandJobType.java +++ b/api/src/org/apache/cloudstack/api/ApiCommandJobType.java @@ -48,5 +48,7 @@ public enum ApiCommandJobType { LoadBalancerRule, AffinityGroup, InternalLbVm, - DedicatedGuestVlanRange + DedicatedGuestVlanRange, + AclRole, + AclGroup } \ No newline at end of file diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index f85784bbde0..7bb4276cf83 100755 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -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; } diff --git a/api/src/org/apache/cloudstack/api/BaseCmd.java b/api/src/org/apache/cloudstack/api/BaseCmd.java index d90fe7cda4d..84095546cec 100644 --- a/api/src/org/apache/cloudstack/api/BaseCmd.java +++ b/api/src/org/apache/cloudstack/api/BaseCmd.java @@ -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 map) { - this.fullUrlParams = map; + fullUrlParams = map; } public Map getFullUrlParams() { - return this.fullUrlParams; + return fullUrlParams; } public Long finalyzeAccountId(String accountName, Long domainId, Long projectId, boolean enabledOnly) { diff --git a/api/src/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/org/apache/cloudstack/api/ResponseGenerator.java index a8de31d8c2d..3f58158334f 100644 --- a/api/src/org/apache/cloudstack/api/ResponseGenerator.java +++ b/api/src/org/apache/cloudstack/api/ResponseGenerator.java @@ -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); + } diff --git a/api/src/org/apache/cloudstack/api/command/admin/acl/AddAclRoleToAclGroupCmd.java b/api/src/org/apache/cloudstack/api/command/admin/acl/AddAclRoleToAclGroupCmd.java new file mode 100644 index 00000000000..f700831bd52 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/acl/AddAclRoleToAclGroupCmd.java @@ -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 roleIdList; + + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + + public Long getId() { + return id; + } + + + public List 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"); + } + } + + +} diff --git a/api/src/org/apache/cloudstack/api/command/admin/acl/CreateAclRoleCmd.java b/api/src/org/apache/cloudstack/api/command/admin/acl/CreateAclRoleCmd.java new file mode 100644 index 00000000000..59bc7ae4c84 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/acl/CreateAclRoleCmd.java @@ -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); + } + } + + +} diff --git a/api/src/org/apache/cloudstack/api/command/admin/acl/DeleteAclRoleCmd.java b/api/src/org/apache/cloudstack/api/command/admin/acl/DeleteAclRoleCmd.java new file mode 100644 index 00000000000..3f1be71454f --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/acl/DeleteAclRoleCmd.java @@ -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"); + } + } +} diff --git a/api/src/org/apache/cloudstack/api/command/admin/acl/ListAclRolesCmd.java b/api/src/org/apache/cloudstack/api/command/admin/acl/ListAclRolesCmd.java new file mode 100644 index 00000000000..e9ebf78fad5 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/acl/ListAclRolesCmd.java @@ -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 response = _queryService.listAclRoles(id, aclRoleName, getDomainId(), + getStartIndex(), getPageSizeVal()); + response.setResponseName(getCommandName()); + setResponseObject(response); + + } + + @Override + public ApiCommandJobType getInstanceType() { + return ApiCommandJobType.AclRole; + } +} diff --git a/api/src/org/apache/cloudstack/api/command/admin/acl/RemoveAclRoleFromAclGroupCmd.java b/api/src/org/apache/cloudstack/api/command/admin/acl/RemoveAclRoleFromAclGroupCmd.java new file mode 100644 index 00000000000..11ea8c260ff --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/acl/RemoveAclRoleFromAclGroupCmd.java @@ -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 roleIdList; + + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + + public Long getId() { + return id; + } + + + public List 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"); + } + } + + +} diff --git a/api/src/org/apache/cloudstack/api/response/AclGroupResponse.java b/api/src/org/apache/cloudstack/api/response/AclGroupResponse.java new file mode 100644 index 00000000000..6e3562a6df9 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/response/AclGroupResponse.java @@ -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 accountIdList; + + @SerializedName(ApiConstants.ACL_ROLES) + @Param(description = "acl roles granted to this acl group ") + private Set roleList; + + public AclGroupResponse() { + roleList = new LinkedHashSet(); + } + + @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 acctIdList) { + accountIdList = acctIdList; + } + + public void addAccountId(String acctId) { + if (accountIdList == null) { + accountIdList = new ArrayList(); + } + + accountIdList.add(acctId); + } + + public void setRoleList(Set roles) { + roleList = roles; + } + + public void addRole(AclRoleResponse role) { + roleList.add(role); + } + + public Set 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; + } + +} diff --git a/api/src/org/apache/cloudstack/api/response/AclRoleResponse.java b/api/src/org/apache/cloudstack/api/response/AclRoleResponse.java new file mode 100644 index 00000000000..527261fd779 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/response/AclRoleResponse.java @@ -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 apiList; + + public AclRoleResponse() { + apiList = new ArrayList(); + } + + @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 getApiList() { + return apiList; + } + + public void setApiList(List 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; + } + + + +} diff --git a/api/src/org/apache/cloudstack/query/QueryService.java b/api/src/org/apache/cloudstack/query/QueryService.java index a203564418d..bfddcf3f808 100644 --- a/api/src/org/apache/cloudstack/query/QueryService.java +++ b/api/src/org/apache/cloudstack/query/QueryService.java @@ -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 searchForInternalLbVms(ListInternalLBVMsCmd cmd); + public ListResponse listAclRoles(Long aclRoleId, String aclRoleName, + Long domainId, Long startIndex, Long pageSize); + } diff --git a/engine/schema/src/org/apache/cloudstack/acl/AclGroupVO.java b/engine/schema/src/org/apache/cloudstack/acl/AclGroupVO.java index fbad6218795..3fbbfc10e0b 100644 --- a/engine/schema/src/org/apache/cloudstack/acl/AclGroupVO.java +++ b/engine/schema/src/org/apache/cloudstack/acl/AclGroupVO.java @@ -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() { diff --git a/engine/schema/src/org/apache/cloudstack/acl/AclRoleVO.java b/engine/schema/src/org/apache/cloudstack/acl/AclRoleVO.java index 584518b4f9e..34ff57c8494 100644 --- a/engine/schema/src/org/apache/cloudstack/acl/AclRoleVO.java +++ b/engine/schema/src/org/apache/cloudstack/acl/AclRoleVO.java @@ -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; + } + } diff --git a/engine/schema/src/org/apache/cloudstack/acl/dao/AclRoleDao.java b/engine/schema/src/org/apache/cloudstack/acl/dao/AclRoleDao.java index c44b4f39e75..e846ae234df 100644 --- a/engine/schema/src/org/apache/cloudstack/acl/dao/AclRoleDao.java +++ b/engine/schema/src/org/apache/cloudstack/acl/dao/AclRoleDao.java @@ -23,6 +23,6 @@ import com.cloud.utils.db.GenericDao; public interface AclRoleDao extends GenericDao { - AclRole findByName(String roleName); + AclRole findByName(Long domainId, String roleName); } diff --git a/engine/schema/src/org/apache/cloudstack/acl/dao/AclRoleDaoImpl.java b/engine/schema/src/org/apache/cloudstack/acl/dao/AclRoleDaoImpl.java index da84eabafad..f1e00476bff 100644 --- a/engine/schema/src/org/apache/cloudstack/acl/dao/AclRoleDaoImpl.java +++ b/engine/schema/src/org/apache/cloudstack/acl/dao/AclRoleDaoImpl.java @@ -39,6 +39,7 @@ public class AclRoleDaoImpl extends GenericDaoBase 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 implements A } @Override - public AclRole findByName(String name) { + public AclRole findByName(Long domainId, String name) { SearchCriteria sc = nameSearch.create(); sc.setParameters("name", name); + if (domainId != null) { + sc.setParameters("domainId", domainId); + } return findOneBy(sc); } diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java index 1afa90225fe..874e4c47355 100755 --- a/server/src/com/cloud/api/ApiDBUtils.java +++ b/server/src/com/cloud/api/ApiDBUtils.java @@ -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 listSiteLoadBalancers(long gslbRuleId) { return _gslbService.listSiteLoadBalancers(gslbRuleId); } diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index f698c2e5453..99c67eb8658 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -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(); diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java index 79a42522700..60cc7a7f103 100644 --- a/server/src/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/com/cloud/api/query/QueryManagerImpl.java @@ -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 listAclRoles(Long aclRoleId, String aclRoleName, Long domainId, Long startIndex, Long pageSize) { + Pair, Integer> result = listAclRolesInternal(aclRoleId, aclRoleName, domainId, true, true, startIndex, pageSize); + ListResponse response = new ListResponse(); + + List roleResponses = ViewResponseHelper.createAclRoleResponses(result.first()); + response.setResponses(roleResponses, result.second()); + return response; + } + + private Pair, 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 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 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, Integer> uniqueRolePair = _aclRoleJoinDao.searchAndCount(sc, searchFilter); + Integer count = uniqueRolePair.second(); + if (count.intValue() == 0) { + // empty result + return uniqueRolePair; + } + List uniqueRoles = uniqueRolePair.first(); + Long[] vrIds = new Long[uniqueRoles.size()]; + int i = 0; + for (AclRoleJoinVO v : uniqueRoles) { + vrIds[i++] = v.getId(); + } + List vrs = _aclRoleJoinDao.searchByIds(vrIds); + return new Pair, Integer>(vrs, count); + } + } diff --git a/server/src/com/cloud/api/query/ViewResponseHelper.java b/server/src/com/cloud/api/query/ViewResponseHelper.java index d97b033171d..7a35a28b7a6 100644 --- a/server/src/com/cloud/api/query/ViewResponseHelper.java +++ b/server/src/com/cloud/api/query/ViewResponseHelper.java @@ -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(vrDataList.values()); } + + public static List createAclRoleResponses(List roles) { + Hashtable vrDataList = new Hashtable(); + 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(vrDataList.values()); + } } diff --git a/server/src/com/cloud/api/query/dao/AclRoleJoinDao.java b/server/src/com/cloud/api/query/dao/AclRoleJoinDao.java new file mode 100644 index 00000000000..e35e66cbfba --- /dev/null +++ b/server/src/com/cloud/api/query/dao/AclRoleJoinDao.java @@ -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 { + + AclRoleResponse newAclRoleResponse(AclRoleJoinVO role); + + AclRoleResponse setAclRoleResponse(AclRoleResponse response, AclRoleJoinVO os); + + List newAclRoleView(AclRole role); + + List searchByIds(Long... ids); +} diff --git a/server/src/com/cloud/api/query/dao/AclRoleJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/AclRoleJoinDaoImpl.java new file mode 100644 index 00000000000..a5a3cb8c11a --- /dev/null +++ b/server/src/com/cloud/api/query/dao/AclRoleJoinDaoImpl.java @@ -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 implements AclRoleJoinDao { + public static final Logger s_logger = Logger.getLogger(AclRoleJoinDaoImpl.class); + + + private final SearchBuilder roleIdSearch; + private final SearchBuilder 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 newAclRoleView(AclRole role) { + SearchCriteria sc = roleIdSearch.create(); + sc.setParameters("id", role.getId()); + return searchIncludingRemoved(sc, null, null, false); + + } + + @Override + public List 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 uvList = new ArrayList(); + // 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 sc = roleSearch.create(); + sc.setParameters("idIN", ids); + List 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 sc = roleSearch.create(); + sc.setParameters("idIN", ids); + List vms = searchIncludingRemoved(sc, null, null, false); + if (vms != null) { + uvList.addAll(vms); + } + } + return uvList; + } + +} diff --git a/server/src/com/cloud/api/query/vo/AclRoleJoinVO.java b/server/src/com/cloud/api/query/vo/AclRoleJoinVO.java new file mode 100644 index 00000000000..52895847b9b --- /dev/null +++ b/server/src/com/cloud/api/query/vo/AclRoleJoinVO.java @@ -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; + } + +} diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index 3b0e87c4a85..cb0a65fd7d9 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -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) { diff --git a/server/src/org/apache/cloudstack/acl/AclServiceImpl.java b/server/src/org/apache/cloudstack/acl/AclServiceImpl.java new file mode 100644 index 00000000000..5ef9ed669d4 --- /dev/null +++ b/server/src/org/apache/cloudstack/acl/AclServiceImpl.java @@ -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 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 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, 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 roleIds, Long groupId) { + // TODO Auto-generated method stub + return null; + } + + @Override + public AclGroup removeAclRolesFromGroup(List 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, 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; + } + + +} diff --git a/server/test/com/cloud/user/MockAccountManagerImpl.java b/server/test/com/cloud/user/MockAccountManagerImpl.java index 7a8e1ee3efc..3638eb2111b 100644 --- a/server/test/com/cloud/user/MockAccountManagerImpl.java +++ b/server/test/com/cloud/user/MockAccountManagerImpl.java @@ -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 diff --git a/setup/db/db/schema-420to430.sql b/setup/db/db/schema-420to430.sql index 52bc6be015c..7afb0d1a167 100644 --- a/setup/db/db/schema-420to430.sql +++ b/setup/db/db/schema-420to430.sql @@ -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; + \ No newline at end of file