blob: 01fc96473d239753bbebc0fed65c3de2ebbf1fdd [file] [log] [blame]
// 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.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.inject.Inject;
import org.apache.cloudstack.acl.dao.ProjectRoleDao;
import org.apache.cloudstack.acl.dao.ProjectRolePermissionsDao;
import org.apache.cloudstack.acl.RolePermissionEntity.Permission;
import org.apache.cloudstack.api.command.admin.acl.project.CreateProjectRoleCmd;
import org.apache.cloudstack.api.command.admin.acl.project.CreateProjectRolePermissionCmd;
import org.apache.cloudstack.api.command.admin.acl.project.DeleteProjectRoleCmd;
import org.apache.cloudstack.api.command.admin.acl.project.DeleteProjectRolePermissionCmd;
import org.apache.cloudstack.api.command.admin.acl.project.ListProjectRolePermissionsCmd;
import org.apache.cloudstack.api.command.admin.acl.project.ListProjectRolesCmd;
import org.apache.cloudstack.api.command.admin.acl.project.UpdateProjectRoleCmd;
import org.apache.cloudstack.api.command.admin.acl.project.UpdateProjectRolePermissionCmd;
import org.apache.cloudstack.context.CallContext;
import org.apache.commons.lang3.StringUtils;
import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.projects.Project;
import com.cloud.projects.ProjectAccount;
import com.cloud.projects.dao.ProjectAccountDao;
import com.cloud.projects.dao.ProjectDao;
import com.cloud.user.Account;
import com.cloud.user.AccountService;
import com.cloud.user.User;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.ListUtils;
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.cloud.utils.exception.CloudRuntimeException;
public class ProjectRoleManagerImpl extends ManagerBase implements ProjectRoleService, PluggableService {
@Inject
ProjectAccountDao projAccDao;
@Inject
ProjectRoleDao projRoleDao;
@Inject
ProjectDao projectDao;
@Inject
AccountDao accountDao;
@Inject
ProjectRolePermissionsDao projRolePermissionsDao;
@Inject
AccountService accountService;
private Project validateProjectId(Long projectId) {
Project project = projectDao.findById(projectId);
if (project == null) {
throw new CloudRuntimeException("Invalid project id provided");
}
return project;
}
private void checkAccess(Long projectId) {
Project project = validateProjectId(projectId);
CallContext.current().setProject(project);
if (!isEnabled()) {
throw new PermissionDeniedException("Dynamic api checker is not enabled, aborting role operation");
}
User user = getCurrentUser();
Account callerAcc = accountDao.findById(user.getAccountId());
if (callerAcc == null || callerAcc.getRoleId() == null) {
throw new PermissionDeniedException("Restricted API called by an invalid user account");
}
if (accountService.isRootAdmin(callerAcc.getId()) || accountService.isDomainAdmin(callerAcc.getAccountId())) {
return;
}
ProjectAccount projectAccount = projAccDao.findByProjectIdUserId(projectId, callerAcc.getAccountId(), user.getId());
if (projectAccount == null) {
projectAccount = projAccDao.findByProjectIdAccountId(projectId, callerAcc.getAccountId());
if (projectAccount == null) {
throw new PermissionDeniedException("User/Account not part of project");
}
}
if (ProjectAccount.Role.Admin != projectAccount.getAccountRole()) {
throw new PermissionDeniedException("User unauthorized to perform operation in the project");
}
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_PROJECT_ROLE_CREATE, eventDescription = "creating Project Role")
public ProjectRole createProjectRole(Long projectId, String name, String description) {
checkAccess(projectId);
return Transaction.execute(new TransactionCallback<ProjectRoleVO>() {
@Override
public ProjectRoleVO doInTransaction(TransactionStatus status) {
return projRoleDao.persist(new ProjectRoleVO(name, description, projectId));
}
});
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_PROJECT_ROLE_UPDATE, eventDescription = "updating Project Role")
public ProjectRole updateProjectRole(ProjectRole role, Long projectId, String name, String description) {
checkAccess(projectId);
ProjectRoleVO projectRoleVO = (ProjectRoleVO) role;
if (StringUtils.isNotEmpty(name)) {
projectRoleVO.setName(name);
}
if (StringUtils.isNotEmpty(description)) {
projectRoleVO.setDescription(description);
}
projRoleDao.update(role.getId(), projectRoleVO);
return projectRoleVO;
}
@Override
public boolean isEnabled() {
return RoleService.EnableDynamicApiChecker.value();
}
@Override
public ProjectRole findProjectRole(Long roleId, Long projectId) {
if (projectId == null || projectId < 1L || projectDao.findById(projectId) == null) {
logger.warn("Invalid project ID provided");
return null;
}
if (roleId != null && roleId < 1L) {
logger.warn(String.format("Project Role ID is invalid [%s]", roleId));
return null;
}
ProjectRoleVO role = projRoleDao.findById(roleId);
if (role == null) {
logger.warn(String.format("Project Role not found [id=%s]", roleId));
return null;
}
if (!(role.getProjectId().equals(projectId))) {
logger.warn(String.format("Project role : %s doesn't belong to the project" + role.getName()));
return null;
}
return role;
}
@Override
public List<ProjectRole> findProjectRoles(Long projectId, String keyword) {
if (projectId == null || projectId < 1L || projectDao.findById(projectId) == null) {
logger.warn("Invalid project ID provided");
return null;
}
return ListUtils.toListOfInterface(projRoleDao.findAllRoles(projectId, keyword));
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_PROJECT_ROLE_PERMISSION_CREATE, eventDescription = "Creating Project Role Permission")
public ProjectRolePermission createProjectRolePermission(CreateProjectRolePermissionCmd cmd) {
Long projectId = cmd.getProjectId();
Long projectRoleId = cmd.getProjectRoleId();
Rule rule = cmd.getRule();
Permission permission = cmd.getPermission();
String description = cmd.getDescription();
checkAccess(projectId);
return Transaction.execute(new TransactionCallback<ProjectRolePermissionVO>() {
@Override
public ProjectRolePermissionVO doInTransaction(TransactionStatus status) {
try {
return projRolePermissionsDao.persist(new ProjectRolePermissionVO(projectId, projectRoleId, rule.toString(), permission, description));
} catch (Exception e) {
throw new CloudRuntimeException("Project role permission for " + rule.toString()+ " seems to already exist.");
}
}
});
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_PROJECT_ROLE_PERMISSION_UPDATE, eventDescription = "updating Project Role Permission order")
public boolean updateProjectRolePermission(Long projectId, ProjectRole projectRole, List<ProjectRolePermission> rolePermissionsOrder) {
checkAccess(projectId);
return projectRole != null && rolePermissionsOrder != null && projRolePermissionsDao.update(projectRole, projectId, rolePermissionsOrder);
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_PROJECT_ROLE_PERMISSION_UPDATE, eventDescription = "updating Project Role Permission")
public boolean updateProjectRolePermission(Long projectId, ProjectRole projectRole, ProjectRolePermission projectRolePermission, Permission newPermission) {
checkAccess(projectId);
return projectRole != null && projRolePermissionsDao.update(projectRole, projectRolePermission, newPermission);
}
@Override
public ProjectRolePermission findProjectRolePermission(Long projRolePermissionId) {
if (projRolePermissionId == null) {
return null;
}
return projRolePermissionsDao.findById(projRolePermissionId);
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_PROJECT_ROLE_PERMISSION_DELETE, eventDescription = "deleting Project Role Permission")
public boolean deleteProjectRolePermission(ProjectRolePermission projectRolePermission) {
checkAccess(projectRolePermission.getProjectId());
return projRolePermissionsDao.remove(projectRolePermission.getId());
}
@Override
public List<ProjectRolePermission> findAllProjectRolePermissions(Long projectId, Long projectRoleId) {
List<? extends ProjectRolePermission> permissions = projRolePermissionsDao.findAllByRoleIdSorted(projectRoleId, projectId);
if (permissions != null) {
return new ArrayList<>(permissions);
}
return Collections.emptyList();
}
@Override
public List<ProjectRole> findProjectRolesByName(Long projectId, String roleName) {
List<? extends ProjectRole> roles = null;
if (StringUtils.isNotBlank(roleName)) {
roles = projRoleDao.findByName(roleName, projectId);
}
return ListUtils.toListOfInterface(roles);
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_PROJECT_ROLE_DELETE, eventDescription = "deleting Project Role")
public boolean deleteProjectRole(ProjectRole role, Long projectId) {
checkAccess(projectId);
if (role == null) {
return false;
}
Long roleProjectId = role.getProjectId();
if (role.getProjectId() != null && !roleProjectId.equals(projectId)) {
throw new PermissionDeniedException("Not authorized to delete the given project role");
}
List<? extends ProjectAccount> users = projAccDao.listUsersOrAccountsByRole(role.getId());
if (users != null && users.size() != 0) {
throw new PermissionDeniedException("Found users that have the project role in use, cannot delete the Project Role");
}
return Transaction.execute(new TransactionCallback<Boolean>() {
@Override
public Boolean doInTransaction(TransactionStatus status) {
List<? extends ProjectRolePermission> rolePermissions = projRolePermissionsDao.findAllByRoleIdSorted(role.getId(), projectId);
if (rolePermissions != null && !rolePermissions.isEmpty()) {
for (ProjectRolePermission rolePermission : rolePermissions) {
projRolePermissionsDao.remove(rolePermission.getId());
}
}
if (projRoleDao.remove(role.getId())) {
ProjectRoleVO projRoleVO = projRoleDao.findByIdIncludingRemoved(role.getId());
projRoleVO.setName(null);
return projRoleDao.update(role.getId(), projRoleVO);
}
return false;
}
});
}
protected Account getCurrentAccount() {
return CallContext.current().getCallingAccount();
}
private Long getProjectIdOfAccount() {
Project project = projectDao.findByProjectAccountId(getCurrentAccount().getAccountId());
if (project != null) {
return project.getId();
}
return null;
}
protected User getCurrentUser() {
return CallContext.current().getCallingUser();
}
@Override
public List<Class<?>> getCommands() {
List<Class<?>> cmdList = new ArrayList<Class<?>>();
cmdList.add(CreateProjectRoleCmd.class);
cmdList.add(ListProjectRolesCmd.class);
cmdList.add(UpdateProjectRoleCmd.class);
cmdList.add(DeleteProjectRoleCmd.class);
cmdList.add(CreateProjectRolePermissionCmd.class);
cmdList.add(ListProjectRolePermissionsCmd.class);
cmdList.add(UpdateProjectRolePermissionCmd.class);
cmdList.add(DeleteProjectRolePermissionCmd.class);
return cmdList;
}
}