diff --git a/api/src/org/apache/cloudstack/acl/AclPermission.java b/api/src/org/apache/cloudstack/acl/AclPolicyPermission.java
similarity index 92%
rename from api/src/org/apache/cloudstack/acl/AclPermission.java
rename to api/src/org/apache/cloudstack/acl/AclPolicyPermission.java
index aff15034a84..02d557e1b93 100644
--- a/api/src/org/apache/cloudstack/acl/AclPermission.java
+++ b/api/src/org/apache/cloudstack/acl/AclPolicyPermission.java
@@ -19,10 +19,12 @@ package org.apache.cloudstack.acl;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.api.InternalIdentity;
-public interface AclPermission extends InternalIdentity {
+public interface AclPolicyPermission extends InternalIdentity {
String getAction();
+ long getAclPolicyId();
+
String getEntityType();
AccessType getAccessType();
diff --git a/api/src/org/apache/cloudstack/api/response/AclPermissionResponse.java b/api/src/org/apache/cloudstack/api/response/AclPermissionResponse.java
index 9329b249036..ad928dc4e40 100644
--- a/api/src/org/apache/cloudstack/api/response/AclPermissionResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/AclPermissionResponse.java
@@ -19,7 +19,7 @@ package org.apache.cloudstack.api.response;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.acl.AclEntityType;
-import org.apache.cloudstack.acl.AclPermission;
+import org.apache.cloudstack.acl.AclPolicyPermission;
import org.apache.cloudstack.acl.PermissionScope;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
@@ -46,7 +46,7 @@ public class AclPermissionResponse extends BaseResponse {
@SerializedName(ApiConstants.ACL_ALLOW_DENY)
@Param(description = "allow or deny of this permission")
- private AclPermission.Permission permission;
+ private AclPolicyPermission.Permission permission;
public AclEntityType getEntityType() {
return entityType;
@@ -80,11 +80,11 @@ public class AclPermissionResponse extends BaseResponse {
this.scopeId = scopeId;
}
- public AclPermission.Permission getPermission() {
+ public AclPolicyPermission.Permission getPermission() {
return permission;
}
- public void setPermission(AclPermission.Permission permission) {
+ public void setPermission(AclPolicyPermission.Permission permission) {
this.permission = permission;
}
diff --git a/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml b/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml
index 24da2306384..0d2dedbdb5d 100644
--- a/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml
+++ b/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml
@@ -325,7 +325,8 @@
-
+
+
diff --git a/engine/schema/src/org/apache/cloudstack/acl/AclPermissionVO.java b/engine/schema/src/org/apache/cloudstack/acl/AclPolicyPermissionVO.java
similarity index 88%
rename from engine/schema/src/org/apache/cloudstack/acl/AclPermissionVO.java
rename to engine/schema/src/org/apache/cloudstack/acl/AclPolicyPermissionVO.java
index ef8cfc48d47..0b23b0bc944 100644
--- a/engine/schema/src/org/apache/cloudstack/acl/AclPermissionVO.java
+++ b/engine/schema/src/org/apache/cloudstack/acl/AclPolicyPermissionVO.java
@@ -32,14 +32,17 @@ import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import com.cloud.utils.db.GenericDao;
@Entity
-@Table(name = ("acl_permission"))
-public class AclPermissionVO implements AclPermission {
+@Table(name = ("acl_policy_permission"))
+public class AclPolicyPermissionVO implements AclPolicyPermission {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
+ @Column(name = "policy_id")
+ private long aclPolicyId;
+
@Column(name = "action")
private String action;
@@ -67,12 +70,14 @@ public class AclPermissionVO implements AclPermission {
@Column(name = GenericDao.CREATED_COLUMN)
private Date created;
- public AclPermissionVO() {
+ public AclPolicyPermissionVO() {
}
- public AclPermissionVO(String action, String entityType, AccessType accessType, PermissionScope scope,
+ public AclPolicyPermissionVO(long aclPolicyId, String action, String entityType, AccessType accessType,
+ PermissionScope scope,
Long scopeId, Permission permission) {
+ this.aclPolicyId = aclPolicyId;
this.action = action;
this.entityType = entityType;
this.accessType = accessType;
@@ -86,6 +91,11 @@ public class AclPermissionVO implements AclPermission {
return id;
}
+ @Override
+ public long getAclPolicyId() {
+ return aclPolicyId;
+ }
+
@Override
public String getEntityType() {
diff --git a/engine/schema/src/org/apache/cloudstack/acl/dao/AclPermissionDao.java b/engine/schema/src/org/apache/cloudstack/acl/dao/AclPolicyPermissionDao.java
similarity index 85%
rename from engine/schema/src/org/apache/cloudstack/acl/dao/AclPermissionDao.java
rename to engine/schema/src/org/apache/cloudstack/acl/dao/AclPolicyPermissionDao.java
index d24b0445166..f8d3cb5c220 100644
--- a/engine/schema/src/org/apache/cloudstack/acl/dao/AclPermissionDao.java
+++ b/engine/schema/src/org/apache/cloudstack/acl/dao/AclPolicyPermissionDao.java
@@ -16,9 +16,11 @@
// under the License.
package org.apache.cloudstack.acl.dao;
-import org.apache.cloudstack.acl.AclPermissionVO;
+
+import org.apache.cloudstack.acl.AclPolicyPermissionVO;
+
import com.cloud.utils.db.GenericDao;
-public interface AclPermissionDao extends GenericDao {
+public interface AclPolicyPermissionDao extends GenericDao {
}
diff --git a/engine/schema/src/org/apache/cloudstack/acl/dao/AclPermissionDaoImpl.java b/engine/schema/src/org/apache/cloudstack/acl/dao/AclPolicyPermissionDaoImpl.java
similarity index 83%
rename from engine/schema/src/org/apache/cloudstack/acl/dao/AclPermissionDaoImpl.java
rename to engine/schema/src/org/apache/cloudstack/acl/dao/AclPolicyPermissionDaoImpl.java
index 1b5f63ecb86..1160d30c959 100644
--- a/engine/schema/src/org/apache/cloudstack/acl/dao/AclPermissionDaoImpl.java
+++ b/engine/schema/src/org/apache/cloudstack/acl/dao/AclPolicyPermissionDaoImpl.java
@@ -20,12 +20,14 @@ import java.util.Map;
import javax.naming.ConfigurationException;
-import org.apache.cloudstack.acl.AclPermissionVO;
+import org.apache.cloudstack.acl.AclPolicyPermissionVO;
+
import com.cloud.utils.db.GenericDaoBase;
-public class AclPermissionDaoImpl extends GenericDaoBase implements AclPermissionDao {
+public class AclPolicyPermissionDaoImpl extends GenericDaoBase implements
+ AclPolicyPermissionDao {
- public AclPermissionDaoImpl()
+ public AclPolicyPermissionDaoImpl()
{
}
diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java
index 1dfbd4511a1..5b0d7ccb6b5 100755
--- a/server/src/com/cloud/api/ApiServer.java
+++ b/server/src/com/cloud/api/ApiServer.java
@@ -52,14 +52,13 @@ import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.cloudstack.acl.APIChecker;
-import org.apache.cloudstack.acl.AclPermissionVO;
-import org.apache.cloudstack.acl.AclPolicyPermissionMapVO;
+import org.apache.cloudstack.acl.AclPolicyPermissionVO;
import org.apache.cloudstack.acl.PermissionScope;
import org.apache.cloudstack.acl.RoleType;
-import org.apache.cloudstack.acl.AclPermission.Permission;
+import org.apache.cloudstack.acl.AclPolicyPermission.Permission;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
-import org.apache.cloudstack.acl.dao.AclPermissionDao;
-import org.apache.cloudstack.acl.dao.AclPolicyPermissionMapDao;
+import org.apache.cloudstack.acl.dao.AclPolicyPermissionDao;
+import org.apache.cloudstack.affinity.AffinityGroupVMMapVO;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;
@@ -149,12 +148,14 @@ import com.cloud.user.UserAccount;
import com.cloud.user.UserVO;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
+import com.cloud.utils.PropertiesUtil;
import com.cloud.utils.StringUtils;
import com.cloud.utils.component.ComponentContext;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.component.PluggableService;
import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.EntityManager;
+import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.TransactionLegacy;
import com.cloud.utils.exception.CloudRuntimeException;
@@ -180,9 +181,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
List _pluggableServices;
List _apiAccessCheckers;
@Inject
- private AclPermissionDao _aclPermissionDao;
- @Inject
- private AclPolicyPermissionMapDao _aclPolicyPermissionMapDao;
+ private AclPolicyPermissionDao _aclPermissionDao;
@Inject
protected ApiAsyncJobDispatcher _asyncDispatcher;
@@ -190,6 +189,10 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
private static final DateFormat _dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
private static Map>> _apiNameCmdClassMap = new HashMap>>();
+ private static Set commandsPropertiesOverrides = new HashSet();
+ private static Map> commandsPropertiesRoleBasedApisMap = new HashMap>();
+
+
private static ExecutorService _executor = new ThreadPoolExecutor(10, 150, 60, TimeUnit.SECONDS, new LinkedBlockingQueue(), new NamedThreadFactory("ApiServer"));
public ApiServer() {
@@ -197,6 +200,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
@Override
public boolean configure(String name, Map params) throws ConfigurationException {
+ processMapping(PropertiesUtil.processConfigFile(new String[] { "commands.properties" }));
return true;
}
@@ -233,6 +237,40 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
}
}
+ // drop all default policy api permissions - we reload them every time
+ // to include any chanegs done to the @APICommand or
+ // commands.properties.
+ SearchBuilder sb = _aclPermissionDao.createSearchBuilder();
+ sb.and("policyId", sb.entity().getAclPolicyId(), SearchCriteria.Op.EQ);
+ sb.and("resourceType", sb.entity().getEntityType(), SearchCriteria.Op.NULL);
+ sb.and("scope", sb.entity().getScope(), SearchCriteria.Op.EQ);
+ sb.done();
+
+ SearchCriteria permissionSC = sb.create();
+
+ for (RoleType role : RoleType.values()) {
+ permissionSC.setParameters("policyId", role.ordinal() + 1);
+ switch (role) {
+ case User:
+ permissionSC.setParameters("scope", PermissionScope.ACCOUNT.toString());
+ break;
+
+ case Admin:
+ permissionSC.setParameters("scope", PermissionScope.ALL.toString());
+ break;
+
+ case DomainAdmin:
+ permissionSC.setParameters("scope", PermissionScope.DOMAIN.toString());
+ break;
+
+ case ResourceAdmin:
+ permissionSC.setParameters("scope", PermissionScope.DOMAIN.toString());
+ break;
+ }
+ _aclPermissionDao.expunge(permissionSC);
+
+ }
+
for(Class> cmdClass: cmdClasses) {
APICommand at = cmdClass.getAnnotation(APICommand.class);
if (at == null) {
@@ -246,52 +284,27 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
}
apiCmdList.add(cmdClass);
- boolean isReadCommand = false;
- BaseCmd cmdObj;
- try {
- cmdObj = (BaseCmd) cmdClass.newInstance();
- if (cmdObj instanceof BaseListCmd) {
- isReadCommand = true;
- }
- } catch (Exception e) {
- }
-
- for (RoleType role : at.authorized()) {
- AclPermissionVO apiPermission = null;
- switch (role) {
- case User:
- apiPermission = new AclPermissionVO(apiName, null, null, PermissionScope.ACCOUNT, null,
- Permission.Allow);
- break;
-
- case Admin:
- apiPermission = new AclPermissionVO(apiName, null, null, PermissionScope.ALL, null,
- Permission.Allow);
- break;
-
- case DomainAdmin:
- apiPermission = new AclPermissionVO(apiName, null, null, PermissionScope.DOMAIN, null,
- Permission.Allow);
- break;
-
- case ResourceAdmin:
- apiPermission = new AclPermissionVO(apiName, null, null, PermissionScope.DOMAIN, null,
- Permission.Allow);
- break;
- }
-
- if (apiPermission != null) {
- if (isReadCommand) {
- apiPermission.setAccessType(AccessType.ListEntry);
- }
- _aclPermissionDao.persist(apiPermission);
- AclPolicyPermissionMapVO policyPermMapEntry = new AclPolicyPermissionMapVO(role.ordinal() + 1,
- apiPermission.getId());
- _aclPolicyPermissionMapDao.persist(policyPermMapEntry);
+ if (!commandsPropertiesOverrides.contains(apiName)) {
+ for (RoleType role : at.authorized()) {
+ addDefaultAclPolicyPermission(apiName, cmdClass, role);
}
}
}
+ // read commands.properties and load api acl permissions -
+ // commands.properties overrides any @APICommand authorization
+
+ for (String apiName : commandsPropertiesOverrides) {
+ Class> cmdClass = getCmdClass(apiName);
+ for (RoleType role : RoleType.values()) {
+ if (commandsPropertiesRoleBasedApisMap.get(role).contains(apiName)) {
+ // insert permission for this role for this api
+ addDefaultAclPolicyPermission(apiName, cmdClass, role);
+ }
+ }
+ }
+
+
encodeApiResponse = Boolean.valueOf(_configDao.getValue(Config.EncodeApiResponse.key()));
String jsonType = _configDao.getValue(Config.JavaScriptDefaultContentType.key());
if (jsonType != null) {
@@ -306,6 +319,74 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
return true;
}
+ private void processMapping(Map configMap) {
+ for (RoleType roleType : RoleType.values()) {
+ commandsPropertiesRoleBasedApisMap.put(roleType, new HashSet());
+ }
+
+ for (Map.Entry entry : configMap.entrySet()) {
+ String apiName = entry.getKey();
+ String roleMask = entry.getValue();
+ commandsPropertiesOverrides.add(apiName);
+ try {
+ short cmdPermissions = Short.parseShort(roleMask);
+ for (RoleType roleType : RoleType.values()) {
+ if ((cmdPermissions & roleType.getValue()) != 0)
+ commandsPropertiesRoleBasedApisMap.get(roleType).add(apiName);
+ }
+ } catch (NumberFormatException nfe) {
+ s_logger.info("Malformed key=value pair for entry: " + entry.toString());
+ }
+ }
+ }
+
+ private void addDefaultAclPolicyPermission(String apiName, Class> cmdClass, RoleType role) {
+
+ boolean isReadCommand = false;
+ if (cmdClass != null) {
+ BaseCmd cmdObj;
+ try {
+ cmdObj = (BaseCmd) cmdClass.newInstance();
+ if (cmdObj instanceof BaseListCmd) {
+ isReadCommand = true;
+ }
+ } catch (Exception e) {
+ throw new CloudRuntimeException(String.format(
+ "%s is claimed as an API command, but it cannot be instantiated", cmdClass.getName()));
+ }
+ }
+
+ AclPolicyPermissionVO apiPermission = null;
+ switch (role) {
+ case User:
+ apiPermission = new AclPolicyPermissionVO(role.ordinal() + 1, apiName, null, null, PermissionScope.ACCOUNT,
+ null, Permission.Allow);
+ break;
+
+ case Admin:
+ apiPermission = new AclPolicyPermissionVO(role.ordinal() + 1, apiName, null, null, PermissionScope.ALL,
+ null, Permission.Allow);
+ break;
+
+ case DomainAdmin:
+ apiPermission = new AclPolicyPermissionVO(role.ordinal() + 1, apiName, null, null, PermissionScope.DOMAIN,
+ null, Permission.Allow);
+ break;
+
+ case ResourceAdmin:
+ apiPermission = new AclPolicyPermissionVO(role.ordinal() + 1, apiName, null, null, PermissionScope.DOMAIN,
+ null, Permission.Allow);
+ break;
+ }
+
+ if (apiPermission != null) {
+ if (isReadCommand) {
+ apiPermission.setAccessType(AccessType.ListEntry);
+ }
+ _aclPermissionDao.persist(apiPermission);
+ }
+ }
+
// NOTE: handle() only handles over the wire (OTW) requests from integration.api.port 8096
// If integration api port is not configured, actual OTW requests will be received by ApiServlet
@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -945,7 +1026,8 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
else {
// determine the cmd class based on calling context
ResponseView view = ResponseView.Restricted;
- if (_accountMgr.isRootAdmin(CallContext.current().getCallingAccount().getId())) {
+ if (CallContext.current() != null
+ && _accountMgr.isRootAdmin(CallContext.current().getCallingAccount().getId())) {
view = ResponseView.Full;
}
for (Class> cmdClass : cmdList) {
diff --git a/server/src/com/cloud/api/query/vo/AclPolicyJoinVO.java b/server/src/com/cloud/api/query/vo/AclPolicyJoinVO.java
index a94ef012e77..3f6eff09dde 100644
--- a/server/src/com/cloud/api/query/vo/AclPolicyJoinVO.java
+++ b/server/src/com/cloud/api/query/vo/AclPolicyJoinVO.java
@@ -28,7 +28,7 @@ import javax.persistence.Id;
import javax.persistence.Table;
import org.apache.cloudstack.acl.AclEntityType;
-import org.apache.cloudstack.acl.AclPermission;
+import org.apache.cloudstack.acl.AclPolicyPermission;
import org.apache.cloudstack.acl.PermissionScope;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
@@ -95,7 +95,7 @@ public class AclPolicyJoinVO extends BaseViewVO implements ControlledViewEntity
@Column(name = "permission_allow_deny")
@Enumerated(value = EnumType.STRING)
- private AclPermission.Permission permissionAllowDeny;
+ private AclPolicyPermission.Permission permissionAllowDeny;
@Column(name = GenericDao.REMOVED_COLUMN)
private Date removed;
@@ -206,7 +206,7 @@ public class AclPolicyJoinVO extends BaseViewVO implements ControlledViewEntity
return permissionAccessType;
}
- public AclPermission.Permission getPermissionAllowDeny() {
+ public AclPolicyPermission.Permission getPermissionAllowDeny() {
return permissionAllowDeny;
}
diff --git a/setup/db/db/schema-421to430.sql b/setup/db/db/schema-421to430.sql
index 7d78c9e5686..01c2daf42c5 100644
--- a/setup/db/db/schema-421to430.sql
+++ b/setup/db/db/schema-421to430.sql
@@ -355,32 +355,23 @@ CREATE TABLE `acl_group_policy_map` (
CONSTRAINT `fk_acl_group_policy_map__policy_id` FOREIGN KEY (`policy_id`) REFERENCES `acl_policy` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-CREATE TABLE `acl_permission` (
+CREATE TABLE `acl_policy_permission` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `policy_id` bigint(20) unsigned NOT NULL,
`action` varchar(100) NOT NULL,
- `resource_type` varchar(100) NOT NULL,
- `scope_id` bigint(20) unsigned NOT NULL,
+ `resource_type` varchar(100) DEFAULT NULL,
+ `scope_id` bigint(20) unsigned,
`scope` varchar(40) DEFAULT NULL,
- `access_type` varchar(40) NOT NULL,
+ `access_type` varchar(40) DEFAULT NULL,
`permission` varchar(40) NOT NULL COMMENT 'Allow or Deny',
`removed` datetime DEFAULT NULL COMMENT 'date the permission was revoked',
`created` datetime DEFAULT NULL COMMENT 'date the permission was granted',
PRIMARY KEY (`id`),
- UNIQUE KEY `id` (`id`)
+ UNIQUE KEY `id` (`id`),
+ KEY `fk_acl_policy_permission__policy_id` (`policy_id`),
+ CONSTRAINT `fk_acl_policy_permission__policy_id` FOREIGN KEY (`policy_id`) REFERENCES `acl_policy` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
-CREATE TABLE `acl_policy_permission_map` (
- `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
- `policy_id` bigint(20) unsigned NOT NULL,
- `permission_id` bigint(20) unsigned NOT NULL,
- `removed` datetime DEFAULT NULL COMMENT 'date the permission was removed from the policy',
- `created` datetime DEFAULT NULL COMMENT 'date the permission was added to the policy',
- PRIMARY KEY (`id`),
- KEY `fk_acl_policy_permission_map__policy_id` (`policy_id`),
- KEY `fk_acl_policy_permission_map__permission_id` (`permission_id`),
- CONSTRAINT `fk_acl_policy_permission_map__policy_id` FOREIGN KEY (`policy_id`) REFERENCES `acl_policy` (`id`) ON DELETE CASCADE,
- CONSTRAINT `fk_acl_policy_permission_map__permission_id` FOREIGN KEY (`permission_id`) REFERENCES `acl_permission` (`id`) ON DELETE CASCADE
-) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
INSERT IGNORE INTO `cloud`.`acl_policy` (id, name, description, uuid, domain_id, account_id, created, policy_type) VALUES (1, 'NORMAL', 'Domain user role', UUID(), 1, 1, Now(), 'Static');
INSERT IGNORE INTO `cloud`.`acl_policy` (id, name, description, uuid, domain_id, account_id, created, policy_type) VALUES (2, 'ADMIN', 'Root admin role', UUID(), 1, 1, Now(), 'Static');
@@ -412,12 +403,12 @@ CREATE OR REPLACE VIEW `cloud`.`acl_policy_view` AS
account.uuid account_uuid,
account.account_name account_name,
account.type account_type,
- acl_permission.action permission_action,
- acl_permission.resource_type permission_entity_type,
- acl_permission.scope permission_scope,
- acl_permission.scope_id permission_scope_id,
- acl_permission.access_type permission_access_type,
- acl_permission.permission permission_allow_deny
+ acl_policy_permission.action permission_action,
+ acl_policy_permission.resource_type permission_entity_type,
+ acl_policy_permission.scope permission_scope,
+ acl_policy_permission.scope_id permission_scope_id,
+ acl_policy_permission.access_type permission_access_type,
+ acl_policy_permission.permission permission_allow_deny
from
`cloud`.`acl_policy`
inner join
@@ -425,9 +416,7 @@ CREATE OR REPLACE VIEW `cloud`.`acl_policy_view` AS
inner join
`cloud`.`account` ON acl_policy.account_id = account.id
left join
- `cloud`.`acl_policy_permission_map` ON acl_policy.id = acl_policy_permission_map.policy_id
- left join
- `cloud`.`acl_permission` ON acl_permission.id = acl_policy_permission_map.permission_id;
+ `cloud`.`acl_policy_permission` ON acl_policy.id = acl_policy_permission.policy_id;
CREATE OR REPLACE VIEW `cloud`.`acl_group_view` AS
@@ -463,8 +452,6 @@ CREATE OR REPLACE VIEW `cloud`.`acl_group_view` AS
left join
`cloud`.`acl_policy` ON acl_group_policy_map.policy_id = acl_policy.id
left join
- `cloud`.`acl_policy_permission_map` ON acl_group.id = acl_policy_permission_map.policy_id
- left join
`cloud`.`acl_group_account_map` ON acl_group.id = acl_group_account_map.group_id
left join
`cloud`.`account` member_account ON acl_group_account_map.account_id = member_account.id;