// 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.acl;

import java.util.List;

import javax.inject.Inject;

import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.acl.ProjectRole;
import org.apache.cloudstack.acl.ProjectRolePermission;
import org.apache.cloudstack.acl.ProjectRoleService;
import org.apache.cloudstack.acl.RolePermissionEntity;
import org.apache.cloudstack.acl.SecurityChecker;
import org.apache.cloudstack.affinity.AffinityGroup;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.query.QueryService;
import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao;
import org.springframework.stereotype.Component;

import com.cloud.dc.DataCenter;
import com.cloud.dc.DedicatedResourceVO;
import com.cloud.dc.dao.DedicatedResourceDao;
import com.cloud.domain.Domain;
import com.cloud.domain.dao.DomainDao;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.UnavailableCommandException;
import com.cloud.network.Network;
import com.cloud.network.NetworkModel;
import com.cloud.network.router.VirtualRouter;
import com.cloud.network.vpc.VpcOffering;
import com.cloud.network.vpc.dao.VpcOfferingDetailsDao;
import com.cloud.offering.DiskOffering;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.ServiceOffering;
import com.cloud.offerings.dao.NetworkOfferingDetailsDao;
import com.cloud.projects.Project;
import com.cloud.projects.ProjectAccount;
import com.cloud.projects.ProjectManager;
import com.cloud.projects.dao.ProjectAccountDao;
import com.cloud.projects.dao.ProjectDao;
import com.cloud.service.dao.ServiceOfferingDetailsDao;
import com.cloud.storage.LaunchPermissionVO;
import com.cloud.storage.dao.LaunchPermissionDao;
import com.cloud.template.VirtualMachineTemplate;
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.component.AdapterBase;
import com.cloud.utils.exception.CloudRuntimeException;

@Component
public class DomainChecker extends AdapterBase implements SecurityChecker {

    @Inject
    DomainDao _domainDao;
    @Inject
    AccountDao _accountDao;
    @Inject
    LaunchPermissionDao _launchPermissionDao;
    @Inject
    ProjectManager _projectMgr;
    @Inject
    ProjectAccountDao _projectAccountDao;
    @Inject
    NetworkModel _networkMgr;
    @Inject
    private DedicatedResourceDao _dedicatedDao;
    @Inject
    AccountService _accountService;
    @Inject
    DiskOfferingDetailsDao diskOfferingDetailsDao;
    @Inject
    ServiceOfferingDetailsDao serviceOfferingDetailsDao;
    @Inject
    NetworkOfferingDetailsDao networkOfferingDetailsDao;
    @Inject
    VpcOfferingDetailsDao vpcOfferingDetailsDao;
    @Inject
    private ProjectRoleService projectRoleService;
    @Inject
    private ProjectDao projectDao;
    @Inject
    private AccountService accountService;

    protected DomainChecker() {
        super();
    }

    /**
     *
     * public template can be used by other accounts in:
     *
     *  1. the same domain
     *  2. in sub-domains
     *  3. domain admin of parent domains
     *
     *  In addition to those, everyone can access the public templates in domains that set "share.public.templates.with.other.domains" config to true.
     *
     * @param template template object
     * @param owner owner of the template
     * @param caller who wants to access to the template
     */

    private void checkPublicTemplateAccess(VirtualMachineTemplate template, Account owner, Account caller){
        if (QueryService.SharePublicTemplatesWithOtherDomains.valueIn(owner.getDomainId()) ||
                caller.getDomainId() == owner.getDomainId() ||
                _domainDao.isChildDomain(owner.getDomainId(), caller.getDomainId())) {
            return;
        }

        if (caller.getType() == Account.Type.NORMAL || caller.getType() == Account.Type.PROJECT) {
            throw new PermissionDeniedException(caller + "is not allowed to access the template " + template);
        } else if (caller.getType() == Account.Type.DOMAIN_ADMIN || caller.getType() == Account.Type.RESOURCE_DOMAIN_ADMIN) {
            if (!_domainDao.isChildDomain(caller.getDomainId(), owner.getDomainId())) {
                throw new PermissionDeniedException(caller + "is not allowed to access the template " + template);
            }
        }
    }


    @Override
    public boolean checkAccess(Account caller, Domain domain) throws PermissionDeniedException {
        if (caller.getState() != Account.State.ENABLED) {
            throw new PermissionDeniedException(String.format("Account %s is disabled.", caller));
        }

        if (domain == null) {
            throw new PermissionDeniedException(String.format("Provided domain is NULL, cannot check access for account [%s]", caller));
        }

        long domainId = domain.getId();

        if (_accountService.isNormalUser(caller.getId())) {
            if (caller.getDomainId() != domainId) {
                throw new PermissionDeniedException(String.format("Account %s does not have permission to operate within domain id=%s", caller, domain.getUuid()));
            }
        } else if (!_domainDao.isChildDomain(caller.getDomainId(), domainId)) {
            throw new PermissionDeniedException(String.format("Account %s does not have permission to operate within domain id=%s", caller, domain.getUuid()));
        }

        return true;
    }

    @Override
    public boolean checkAccess(User user, Domain domain) throws PermissionDeniedException {
        if (user.getRemoved() != null) {
            throw new PermissionDeniedException(user + " is no longer active.");
        }

        Account account = _accountDao.findById(user.getAccountId());
        return checkAccess(account, domain);
    }

    @Override
    public boolean checkAccess(Account caller, ControlledEntity entity, AccessType accessType)
            throws PermissionDeniedException {
        if (entity instanceof VirtualMachineTemplate) {
            VirtualMachineTemplate template = (VirtualMachineTemplate)entity;
            Account owner = _accountDao.findById(template.getAccountId());
            // validate that the template is usable by the account
            if (!template.isPublicTemplate()) {
                if (_accountService.isRootAdmin(caller.getId()) || (owner.getId() == caller.getId())) {
                    return true;
                }
                //special handling for the project case
                if (owner.getType() == Account.Type.PROJECT && _projectMgr.canAccessProjectAccount(caller, owner.getId())) {
                    return true;
                }

                // since the current account is not the owner of the template, check the launch permissions table to see if the
                // account can launch a VM from this template
                LaunchPermissionVO permission = _launchPermissionDao.findByTemplateAndAccount(template.getId(), caller.getId());
                if (permission == null) {
                    throw new PermissionDeniedException(String.format("Account %s does not have permission to launch instances from template %s", caller, template));
                }
            } else {
                // Domain admin and regular user can delete/modify only templates created by them
                if (accessType != null && accessType == AccessType.OperateEntry) {
                    if (!_accountService.isRootAdmin(caller.getId()) && owner.getId() != caller.getId()) {
                        // For projects check if the caller account can access the project account
                        if (owner.getType() != Account.Type.PROJECT || !(_projectMgr.canAccessProjectAccount(caller, owner.getId()))) {
                            throw new PermissionDeniedException("Domain Admin and regular users can modify only their own Public Templates");
                        }
                    }
                } else if (caller.getType() != Account.Type.ADMIN) {
                    checkPublicTemplateAccess(template, owner, caller);
                }
            }

            return true;
        } else if (entity instanceof Network && accessType != null && accessType == AccessType.UseEntry) {
            _networkMgr.checkNetworkPermissions(caller, (Network) entity);
        } else if (entity instanceof Network && accessType != null && accessType == AccessType.OperateEntry) {
            _networkMgr.checkNetworkOperatePermissions(caller, (Network)entity);
        } else if (entity instanceof VirtualRouter) {
            _networkMgr.checkRouterPermissions(caller, (VirtualRouter)entity);
        } else if (entity instanceof AffinityGroup) {
            return false;
        } else {
            validateCallerHasAccessToEntityOwner(caller, entity, accessType);
        }
        return true;
    }

    protected void validateCallerHasAccessToEntityOwner(Account caller, ControlledEntity entity, AccessType accessType) {
        PermissionDeniedException exception = new PermissionDeniedException("Caller does not have permission to operate with provided resource.");

        if (_accountService.isRootAdmin(caller.getId())) {
            return;
        }

        if (caller.getId() == entity.getAccountId()) {
            return;
        }

        Account owner = _accountDao.findByIdIncludingRemoved(entity.getAccountId());
        String entityLog = String.format("entity [owner: %s, type: %s]", owner, entity.getEntityType().getSimpleName());
        if (owner == null) {
            logger.error(String.format("Owner not found for %s", entityLog));
            throw exception;
        }

        Account.Type callerAccountType = caller.getType();
        if ((callerAccountType == Account.Type.DOMAIN_ADMIN || callerAccountType == Account.Type.RESOURCE_DOMAIN_ADMIN) &&
                _domainDao.isChildDomain(caller.getDomainId(), owner.getDomainId())) {
            return;
        }

        if (owner.getType() == Account.Type.PROJECT) {
            // only project owner can delete/modify the project
            if (accessType == AccessType.ModifyProject) {
                if (!_projectMgr.canModifyProjectAccount(caller, owner.getId())) {
                    logger.error("Caller: {} does not have permission to modify project with " +
                            "owner: {}", caller, owner);
                    throw exception;
                }
            } else if (!_projectMgr.canAccessProjectAccount(caller, owner.getId())) {
                logger.error("Caller: {} does not have permission to access project with " +
                        "owner: {}", caller, owner);
                throw exception;
            }
            checkOperationPermitted(caller, entity);
            return;
        }

        logger.error("Caller: {} does not have permission to access {}", caller, entityLog);
        throw exception;
    }

    protected boolean checkOperationPermitted(Account caller, ControlledEntity entity) {
        User user = CallContext.current().getCallingUser();
        Project project = projectDao.findByProjectAccountId(entity.getAccountId());
        if (project == null) {
            throw new CloudRuntimeException("Unable to find project to which the entity belongs to");
        }
        ProjectAccount projectUser = _projectAccountDao.findByProjectIdUserId(project.getId(), user.getAccountId(), user.getId());
        String apiCommandName = CallContext.current().getApiName();

        if (accountService.isRootAdmin(caller.getId()) || accountService.isDomainAdmin(caller.getAccountId())) {
            return true;
        }

        if (projectUser != null) {
            if (projectUser.getAccountRole() == ProjectAccount.Role.Admin) {
                return true;
            } else {
                return isPermitted(project, projectUser, apiCommandName);
            }
        }

        ProjectAccount projectAccount = _projectAccountDao.findByProjectIdAccountId(project.getId(), caller.getAccountId());
        if (projectAccount != null) {
            if (projectAccount.getAccountRole() == ProjectAccount.Role.Admin) {
                return true;
            } else {
                return isPermitted(project, projectAccount, apiCommandName);
            }
        }
        throw new UnavailableCommandException("The given command '" + apiCommandName + "' either does not exist or is not available for the user");
    }

    private boolean isPermitted(Project project, ProjectAccount projectUser, String apiCommandName) {
        ProjectRole projectRole = null;
        if(projectUser.getProjectRoleId() != null) {
            projectRole = projectRoleService.findProjectRole(projectUser.getProjectRoleId(), project.getId());
        }

        if (projectRole == null) {
            return true;
        }

        for (ProjectRolePermission permission : projectRoleService.findAllProjectRolePermissions(project.getId(), projectRole.getId())) {
            if (permission.getRule().matches(apiCommandName)) {
                if (RolePermissionEntity.Permission.ALLOW.equals(permission.getPermission())) {
                    return true;
                } else {
                    throw new PermissionDeniedException("The given command '" + apiCommandName + "' either does not exist or is not available for the user");
                }
            }
        }
        return true;
    }
    @Override
    public boolean checkAccess(User user, ControlledEntity entity) throws PermissionDeniedException {
        Account account = _accountDao.findById(user.getAccountId());
        return checkAccess(account, entity, null);
    }

    @Override
    public boolean checkAccess(Account account, DiskOffering dof, DataCenter zone) throws PermissionDeniedException {
        boolean hasAccess = false;
        // Check for domains
        if (account == null || dof == null) {
            hasAccess = true;
        } else {
            //admin has all permissions
            if (_accountService.isRootAdmin(account.getId())) {
                hasAccess = true;
            }
            //if account is normal user or domain admin
            //check if account's domain is a child of offering's domain (Note: This is made consistent with the list command for disk offering)
            else if (_accountService.isNormalUser(account.getId())
                    || account.getType() == Account.Type.RESOURCE_DOMAIN_ADMIN
                    || _accountService.isDomainAdmin(account.getId())
                    || account.getType() == Account.Type.PROJECT) {
                final List<Long> doDomainIds = diskOfferingDetailsDao.findDomainIds(dof.getId());
                if (doDomainIds.isEmpty()) {
                    hasAccess = true;
                } else {
                    for (Long domainId : doDomainIds) {
                        if (_domainDao.isChildDomain(domainId, account.getDomainId())) {
                            hasAccess = true;
                            break;
                        }
                    }
                }
            }
        }
        // Check for zones
        if (hasAccess && dof != null && zone != null) {
            final List<Long> doZoneIds = diskOfferingDetailsDao.findZoneIds(dof.getId());
            hasAccess = doZoneIds.isEmpty() || doZoneIds.contains(zone.getId());
        }
        return hasAccess;
    }

    @Override
    public boolean checkAccess(Account account, ServiceOffering so, DataCenter zone) throws PermissionDeniedException {
        boolean hasAccess = false;
        // Check for domains
        if (account == null || so == null) {
            hasAccess = true;
        } else {
            //admin has all permissions
            if (_accountService.isRootAdmin(account.getId())) {
                hasAccess = true;
            }
            //if account is normal user or domain admin
            //check if account's domain is a child of offering's domain (Note: This is made consistent with the list command for service offering)
            else if (_accountService.isNormalUser(account.getId())
                    || account.getType() == Account.Type.RESOURCE_DOMAIN_ADMIN
                    || _accountService.isDomainAdmin(account.getId())
                    || account.getType() == Account.Type.PROJECT) {
                final List<Long> soDomainIds = serviceOfferingDetailsDao.findDomainIds(so.getId());
                if (soDomainIds.isEmpty()) {
                    hasAccess = true;
                } else {
                    for (Long domainId : soDomainIds) {
                        if (_domainDao.isChildDomain(domainId, account.getDomainId())) {
                            hasAccess = true;
                            break;
                        }
                    }
                }
            }
        }
        // Check for zones
        if (hasAccess && so != null && zone != null) {
            final List<Long> soZoneIds = serviceOfferingDetailsDao.findZoneIds(so.getId());
            hasAccess = soZoneIds.isEmpty() || soZoneIds.contains(zone.getId());
        }
        return hasAccess;
    }

    @Override
    public boolean checkAccess(Account account, NetworkOffering nof, DataCenter zone) throws PermissionDeniedException {
        boolean hasAccess = false;
        // Check for domains
        if (account == null || nof == null) {
            hasAccess = true;
        } else {
            //admin has all permissions
            if (_accountService.isRootAdmin(account.getId())) {
                hasAccess = true;
            }
            //if account is normal user or domain admin
            //check if account's domain is a child of offering's domain (Note: This is made consistent with the list command for disk offering)
            else if (_accountService.isNormalUser(account.getId())
                    || account.getType() == Account.Type.RESOURCE_DOMAIN_ADMIN
                    || _accountService.isDomainAdmin(account.getId())
                    || account.getType() == Account.Type.PROJECT) {
                final List<Long> noDomainIds = networkOfferingDetailsDao.findDomainIds(nof.getId());
                if (noDomainIds.isEmpty()) {
                    hasAccess = true;
                } else {
                    for (Long domainId : noDomainIds) {
                        if (_domainDao.isChildDomain(domainId, account.getDomainId())) {
                            hasAccess = true;
                            break;
                        }
                    }
                }
            }
        }
        // Check for zones
        if (hasAccess && nof != null && zone != null) {
            final List<Long> doZoneIds = networkOfferingDetailsDao.findZoneIds(nof.getId());
            hasAccess = doZoneIds.isEmpty() || doZoneIds.contains(zone.getId());
        }
        return hasAccess;
    }

    @Override
    public boolean checkAccess(Account account, VpcOffering vof, DataCenter zone) throws PermissionDeniedException {
        boolean hasAccess = false;
        // Check for domains
        if (account == null || vof == null) {
            hasAccess = true;
        } else {
            //admin has all permissions
            if (_accountService.isRootAdmin(account.getId())) {
                hasAccess = true;
            }
            //if account is normal user or domain admin
            //check if account's domain is a child of offering's domain (Note: This is made consistent with the list command for disk offering)
            else if (_accountService.isNormalUser(account.getId())
                    || account.getType() == Account.Type.RESOURCE_DOMAIN_ADMIN
                    || _accountService.isDomainAdmin(account.getId())
                    || account.getType() == Account.Type.PROJECT) {
                final List<Long> voDomainIds = vpcOfferingDetailsDao.findDomainIds(vof.getId());
                if (voDomainIds.isEmpty()) {
                    hasAccess = true;
                } else {
                    for (Long domainId : voDomainIds) {
                        if (_domainDao.isChildDomain(domainId, account.getDomainId())) {
                            hasAccess = true;
                            break;
                        }
                    }
                }
            }
        }
        // Check for zones
        if (hasAccess && vof != null && zone != null) {
            final List<Long> doZoneIds = vpcOfferingDetailsDao.findZoneIds(vof.getId());
            hasAccess = doZoneIds.isEmpty() || doZoneIds.contains(zone.getId());
        }
        return hasAccess;
    }

    @Override
    public boolean checkAccess(Account account, DataCenter zone) throws PermissionDeniedException {
        if (account == null || zone.getDomainId() == null) {//public zone
            return true;
        } else {
            //admin has all permissions
            if (_accountService.isRootAdmin(account.getId())) {
                return true;
            }
            //if account is normal user
            //check if account's domain is a child of zone's domain
            else if (_accountService.isNormalUser(account.getId()) || account.getType() == Account.Type.PROJECT) {
                // if zone is dedicated to an account check that the accountId
                // matches.
                DedicatedResourceVO dedicatedZone = _dedicatedDao.findByZoneId(zone.getId());
                if (dedicatedZone != null) {
                    if (dedicatedZone.getAccountId() != null) {
                        if (dedicatedZone.getAccountId() == account.getId()) {
                            return true;
                        } else {
                            return false;
                        }
                    }
                }
                if (account.getDomainId() == zone.getDomainId()) {
                    return true; //zone and account at exact node
                } else {
                    Domain domainRecord = _domainDao.findById(account.getDomainId());
                    if (domainRecord != null) {
                        while (true) {
                            if (domainRecord.getId() == zone.getDomainId()) {
                                //found as a child
                                return true;
                            }
                            if (domainRecord.getParent() != null) {
                                domainRecord = _domainDao.findById(domainRecord.getParent());
                            } else {
                                break;
                            }
                        }
                    }
                }
                //not found
                return false;
            }
            //if account is domain admin
            //check if the account's domain is either child of zone's domain, or if zone's domain is child of account's domain
            else if (_accountService.isDomainAdmin(account.getId())) {
                if (account.getDomainId() == zone.getDomainId()) {
                    return true; //zone and account at exact node
                } else {
                    Domain zoneDomainRecord = _domainDao.findById(zone.getDomainId());
                    Domain accountDomainRecord = _domainDao.findById(account.getDomainId());
                    if (accountDomainRecord != null) {
                        Domain localRecord = accountDomainRecord;
                        while (true) {
                            if (localRecord.getId() == zone.getDomainId()) {
                                //found as a child
                                return true;
                            }
                            if (localRecord.getParent() != null) {
                                localRecord = _domainDao.findById(localRecord.getParent());
                            } else {
                                break;
                            }
                        }
                    }
                    //didn't find in upper tree
                    if (zoneDomainRecord != null &&
                            accountDomainRecord != null &&
                            zoneDomainRecord.getPath().contains(accountDomainRecord.getPath())) {
                        return true;
                    }
                }
                //not found
                return false;
            }
        }
        return false;
    }

    @Override
    public boolean checkAccess(Account caller, ControlledEntity entity, AccessType accessType, String action)
            throws PermissionDeniedException {

        if (action != null && ("SystemCapability".equals(action))) {
            if (caller != null && caller.getType() == Account.Type.ADMIN) {
                return true;
            } else {
                return false;
            }
        } else if (action != null && ("DomainCapability".equals(action))) {
            if (caller != null && caller.getType() == Account.Type.DOMAIN_ADMIN) {
                return true;
            } else {
                return false;
            }
        } else if (action != null && ("DomainResourceCapability".equals(action))) {
            if (caller != null && caller.getType() == Account.Type.RESOURCE_DOMAIN_ADMIN) {
                return true;
            } else {
                return false;
            }
        }
        return checkAccess(caller, entity, accessType);
    }

    @Override
    public boolean checkAccess(Account caller, AccessType accessType, String action, ControlledEntity... entities)
            throws PermissionDeniedException {

        // returns true only if access to all entities is granted
        for (ControlledEntity entity : entities) {
            if (!checkAccess(caller, entity, accessType, action)) {
                return false;
            }
        }
        return true;
    }
}
