mirror of
https://github.com/apache/cloudstack
synced 2026-08-02 05:26:35 +00:00
This allows admins to create roles with names of previously deleted roles. Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
271 lines
11 KiB
Java
271 lines
11 KiB
Java
// 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 com.cloud.event.ActionEvent;
|
|
import com.cloud.event.EventTypes;
|
|
import com.cloud.exception.PermissionDeniedException;
|
|
import com.cloud.user.Account;
|
|
import com.cloud.user.dao.AccountDao;
|
|
import com.cloud.utils.ListUtils;
|
|
import com.cloud.utils.PropertiesUtil;
|
|
import com.cloud.utils.component.ManagerBase;
|
|
import com.cloud.utils.component.PluggableService;
|
|
import com.cloud.utils.db.Transaction;
|
|
import com.cloud.utils.db.TransactionCallback;
|
|
import com.cloud.utils.db.TransactionStatus;
|
|
import com.google.common.base.Strings;
|
|
import org.apache.cloudstack.acl.dao.RoleDao;
|
|
import org.apache.cloudstack.acl.dao.RolePermissionsDao;
|
|
import org.apache.cloudstack.api.ApiErrorCode;
|
|
import org.apache.cloudstack.api.ServerApiException;
|
|
import org.apache.cloudstack.api.command.admin.acl.CreateRoleCmd;
|
|
import org.apache.cloudstack.api.command.admin.acl.CreateRolePermissionCmd;
|
|
import org.apache.cloudstack.api.command.admin.acl.DeleteRoleCmd;
|
|
import org.apache.cloudstack.api.command.admin.acl.DeleteRolePermissionCmd;
|
|
import org.apache.cloudstack.api.command.admin.acl.ListRolePermissionsCmd;
|
|
import org.apache.cloudstack.api.command.admin.acl.ListRolesCmd;
|
|
import org.apache.cloudstack.api.command.admin.acl.UpdateRoleCmd;
|
|
import org.apache.cloudstack.api.command.admin.acl.UpdateRolePermissionCmd;
|
|
import org.apache.cloudstack.context.CallContext;
|
|
import org.apache.cloudstack.framework.config.ConfigKey;
|
|
import org.apache.cloudstack.framework.config.Configurable;
|
|
|
|
import javax.ejb.Local;
|
|
import javax.inject.Inject;
|
|
import java.io.File;
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.Date;
|
|
import java.util.List;
|
|
|
|
@Local(value = {RoleService.class})
|
|
public class RoleManagerImpl extends ManagerBase implements RoleService, Configurable, PluggableService {
|
|
@Inject
|
|
private AccountDao accountDao;
|
|
@Inject
|
|
private RoleDao roleDao;
|
|
@Inject
|
|
private RolePermissionsDao rolePermissionsDao;
|
|
|
|
private void checkCallerAccess() {
|
|
if (!isEnabled()) {
|
|
throw new PermissionDeniedException("Dynamic api checker is not enabled, aborting role operation");
|
|
}
|
|
Account caller = CallContext.current().getCallingAccount();
|
|
if (caller == null || caller.getRoleId() == null) {
|
|
throw new PermissionDeniedException("Restricted API called by an invalid user account");
|
|
}
|
|
Role callerRole = findRole(caller.getRoleId());
|
|
if (callerRole == null || callerRole.getRoleType() != RoleType.Admin) {
|
|
throw new PermissionDeniedException("Restricted API called by an user account of non-Admin role type");
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean isEnabled() {
|
|
File apiCmdFile = PropertiesUtil.findConfigFile(PropertiesUtil.getDefaultApiCommandsFileName());
|
|
return RoleService.EnableDynamicApiChecker.value() && (apiCmdFile == null || !apiCmdFile.exists());
|
|
}
|
|
|
|
@Override
|
|
public Role findRole(final Long id) {
|
|
if (id == null || id < 1L) {
|
|
return null;
|
|
}
|
|
return roleDao.findById(id);
|
|
}
|
|
|
|
@Override
|
|
public RolePermission findRolePermission(final Long id) {
|
|
if (id == null) {
|
|
return null;
|
|
}
|
|
return rolePermissionsDao.findById(id);
|
|
}
|
|
|
|
@Override
|
|
public RolePermission findRolePermissionByUuid(final String uuid) {
|
|
if (Strings.isNullOrEmpty(uuid)) {
|
|
return null;
|
|
}
|
|
return rolePermissionsDao.findByUuid(uuid);
|
|
}
|
|
|
|
@Override
|
|
@ActionEvent(eventType = EventTypes.EVENT_ROLE_CREATE, eventDescription = "creating Role")
|
|
public Role createRole(final String name, final RoleType roleType, final String description) {
|
|
checkCallerAccess();
|
|
if (roleType == null || roleType == RoleType.Unknown) {
|
|
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Invalid role type provided");
|
|
}
|
|
return Transaction.execute(new TransactionCallback<RoleVO>() {
|
|
@Override
|
|
public RoleVO doInTransaction(TransactionStatus status) {
|
|
return roleDao.persist(new RoleVO(name, roleType, description));
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
@ActionEvent(eventType = EventTypes.EVENT_ROLE_UPDATE, eventDescription = "updating Role")
|
|
public boolean updateRole(final Role role, final String name, final RoleType roleType, final String description) {
|
|
checkCallerAccess();
|
|
if (role == null) {
|
|
return false;
|
|
}
|
|
if (roleType != null && roleType == RoleType.Unknown) {
|
|
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unknown is not a valid role type");
|
|
}
|
|
RoleVO roleVO = (RoleVO) role;
|
|
if (!Strings.isNullOrEmpty(name)) {
|
|
roleVO.setName(name);
|
|
}
|
|
if (roleType != null) {
|
|
if (role.getId() <= RoleType.User.getId()) {
|
|
throw new PermissionDeniedException("The role type of default roles cannot be changed");
|
|
}
|
|
List<? extends Account> accounts = accountDao.findAccountsByRole(role.getId());
|
|
if (accounts == null || accounts.isEmpty()) {
|
|
roleVO.setRoleType(roleType);
|
|
} else {
|
|
throw new PermissionDeniedException("Found accounts that have role in use, won't allow to change role type");
|
|
}
|
|
}
|
|
if (!Strings.isNullOrEmpty(description)) {
|
|
roleVO.setDescription(description);
|
|
}
|
|
return roleDao.update(role.getId(), roleVO);
|
|
}
|
|
|
|
@Override
|
|
@ActionEvent(eventType = EventTypes.EVENT_ROLE_DELETE, eventDescription = "deleting Role")
|
|
public boolean deleteRole(final Role role) {
|
|
checkCallerAccess();
|
|
if (role == null) {
|
|
return false;
|
|
}
|
|
if (role.getId() <= RoleType.User.getId()) {
|
|
throw new PermissionDeniedException("Default roles cannot be deleted");
|
|
}
|
|
List<? extends Account> accounts = accountDao.findAccountsByRole(role.getId());
|
|
if (accounts == null || accounts.size() == 0) {
|
|
return Transaction.execute(new TransactionCallback<Boolean>() {
|
|
@Override
|
|
public Boolean doInTransaction(TransactionStatus status) {
|
|
List<? extends RolePermission> rolePermissions = rolePermissionsDao.findAllByRoleIdSorted(role.getId());
|
|
if (rolePermissions != null && !rolePermissions.isEmpty()) {
|
|
for (RolePermission rolePermission : rolePermissions) {
|
|
rolePermissionsDao.remove(rolePermission.getId());
|
|
}
|
|
}
|
|
if (roleDao.remove(role.getId())) {
|
|
RoleVO roleVO = roleDao.findByIdIncludingRemoved(role.getId());
|
|
roleVO.setName(role.getName() + "-deleted-" + new Date());
|
|
return roleDao.update(role.getId(), roleVO);
|
|
}
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
throw new PermissionDeniedException("Found accounts that have role in use, won't allow to delete role");
|
|
}
|
|
|
|
@Override
|
|
@ActionEvent(eventType = EventTypes.EVENT_ROLE_PERMISSION_CREATE, eventDescription = "creating Role Permission")
|
|
public RolePermission createRolePermission(final Role role, final Rule rule, final RolePermission.Permission permission, final String description) {
|
|
checkCallerAccess();
|
|
return Transaction.execute(new TransactionCallback<RolePermissionVO>() {
|
|
@Override
|
|
public RolePermissionVO doInTransaction(TransactionStatus status) {
|
|
return rolePermissionsDao.persist(new RolePermissionVO(role.getId(), rule.toString(), permission, description));
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
@ActionEvent(eventType = EventTypes.EVENT_ROLE_PERMISSION_UPDATE, eventDescription = "updating Role Permission order")
|
|
public boolean updateRolePermission(final Role role, final List<RolePermission> newOrder) {
|
|
checkCallerAccess();
|
|
return role != null && newOrder != null && rolePermissionsDao.update(role, newOrder);
|
|
}
|
|
|
|
@Override
|
|
@ActionEvent(eventType = EventTypes.EVENT_ROLE_PERMISSION_DELETE, eventDescription = "deleting Role Permission")
|
|
public boolean deleteRolePermission(final RolePermission rolePermission) {
|
|
checkCallerAccess();
|
|
return rolePermission != null && rolePermissionsDao.remove(rolePermission.getId());
|
|
}
|
|
|
|
@Override
|
|
public List<Role> findRolesByName(final String name) {
|
|
List<? extends Role> roles = null;
|
|
if (!Strings.isNullOrEmpty(name)) {
|
|
roles = roleDao.findAllByName(name);
|
|
}
|
|
return ListUtils.toListOfInterface(roles);
|
|
}
|
|
|
|
@Override
|
|
public List<Role> findRolesByType(final RoleType roleType) {
|
|
List<? extends Role> roles = null;
|
|
if (roleType != null) {
|
|
roles = roleDao.findAllByRoleType(roleType);
|
|
}
|
|
return ListUtils.toListOfInterface(roles);
|
|
}
|
|
|
|
@Override
|
|
public List<Role> listRoles() {
|
|
List<? extends Role> roles = roleDao.listAll();
|
|
return ListUtils.toListOfInterface(roles);
|
|
}
|
|
|
|
@Override
|
|
public List<RolePermission> findAllPermissionsBy(final Long roleId) {
|
|
List<? extends RolePermission> permissions = rolePermissionsDao.findAllByRoleIdSorted(roleId);
|
|
if (permissions != null) {
|
|
return new ArrayList<>(permissions);
|
|
}
|
|
return Collections.emptyList();
|
|
}
|
|
|
|
@Override
|
|
public String getConfigComponentName() {
|
|
return RoleService.class.getSimpleName();
|
|
}
|
|
|
|
@Override
|
|
public ConfigKey<?>[] getConfigKeys() {
|
|
return new ConfigKey<?>[]{RoleService.EnableDynamicApiChecker};
|
|
}
|
|
|
|
@Override
|
|
public List<Class<?>> getCommands() {
|
|
final List<Class<?>> cmdList = new ArrayList<>();
|
|
cmdList.add(CreateRoleCmd.class);
|
|
cmdList.add(ListRolesCmd.class);
|
|
cmdList.add(UpdateRoleCmd.class);
|
|
cmdList.add(DeleteRoleCmd.class);
|
|
cmdList.add(CreateRolePermissionCmd.class);
|
|
cmdList.add(ListRolePermissionsCmd.class);
|
|
cmdList.add(UpdateRolePermissionCmd.class);
|
|
cmdList.add(DeleteRolePermissionCmd.class);
|
|
return cmdList;
|
|
}
|
|
}
|