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

import java.net.InetAddress;
import java.net.URLEncoder;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.inject.Inject;
import javax.naming.ConfigurationException;

import org.apache.cloudstack.acl.APIChecker;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.acl.InfrastructureEntity;
import org.apache.cloudstack.acl.QuerySelector;
import org.apache.cloudstack.acl.Role;
import org.apache.cloudstack.acl.RoleService;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.acl.SecurityChecker;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.affinity.AffinityGroup;
import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.command.admin.account.CreateAccountCmd;
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.GetUserKeysCmd;
import org.apache.cloudstack.api.command.admin.user.MoveUserCmd;
import org.apache.cloudstack.api.command.admin.user.RegisterUserKeyCmd;
import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd;
import org.apache.cloudstack.api.response.UserTwoFactorAuthenticationSetupResponse;
import org.apache.cloudstack.auth.UserAuthenticator;
import org.apache.cloudstack.auth.UserAuthenticator.ActionOnFailedAuthentication;
import org.apache.cloudstack.auth.UserTwoFactorAuthenticator;
import org.apache.cloudstack.config.ApiServiceConfiguration;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.framework.messagebus.MessageBus;
import org.apache.cloudstack.framework.messagebus.PublishScope;
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.cloudstack.network.RoutedIpv4Manager;
import org.apache.cloudstack.network.dao.NetworkPermissionDao;
import org.apache.cloudstack.region.gslb.GlobalLoadBalancerRuleDao;
import org.apache.cloudstack.resourcedetail.UserDetailVO;
import org.apache.cloudstack.resourcedetail.dao.UserDetailsDao;
import org.apache.cloudstack.utils.baremetal.BaremetalUtils;
import org.apache.cloudstack.webhook.WebhookHelper;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;

import com.cloud.api.ApiDBUtils;
import com.cloud.api.auth.SetupUserTwoFactorAuthenticationCmd;
import com.cloud.api.query.vo.ControlledViewEntity;
import com.cloud.configuration.Config;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.Resource.ResourceOwnerType;
import com.cloud.configuration.ResourceCountVO;
import com.cloud.configuration.ResourceLimit;
import com.cloud.configuration.dao.ResourceCountDao;
import com.cloud.configuration.dao.ResourceLimitDao;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.DedicatedResourceVO;
import com.cloud.dc.dao.DataCenterDao;
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.dao.DomainDao;
import com.cloud.event.ActionEvent;
import com.cloud.event.ActionEventUtils;
import com.cloud.event.ActionEvents;
import com.cloud.event.EventTypes;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.CloudAuthenticationException;
import com.cloud.exception.CloudTwoFactorAuthenticationException;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.OperationTimedoutException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.host.dao.HostDao;
import com.cloud.kubernetes.cluster.KubernetesServiceHelper;
import com.cloud.network.IpAddress;
import com.cloud.network.IpAddressManager;
import com.cloud.network.Network;
import com.cloud.network.NetworkModel;
import com.cloud.network.VpnUserVO;
import com.cloud.network.as.AutoScaleManager;
import com.cloud.network.dao.AccountGuestVlanMapDao;
import com.cloud.network.dao.AccountGuestVlanMapVO;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.IPAddressVO;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.dao.RemoteAccessVpnDao;
import com.cloud.network.dao.RemoteAccessVpnVO;
import com.cloud.network.dao.SslCertDao;
import com.cloud.network.dao.VpnUserDao;
import com.cloud.network.router.VirtualRouter;
import com.cloud.network.security.SecurityGroupManager;
import com.cloud.network.security.SecurityGroupService;
import com.cloud.network.security.SecurityGroupVO;
import com.cloud.network.security.dao.SecurityGroupDao;
import com.cloud.network.vpc.Vpc;
import com.cloud.network.vpc.VpcManager;
import com.cloud.network.vpc.VpcOffering;
import com.cloud.network.vpn.RemoteAccessVpnService;
import com.cloud.network.vpn.Site2SiteVpnManager;
import com.cloud.offering.DiskOffering;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.ServiceOffering;
import com.cloud.projects.Project;
import com.cloud.projects.Project.ListProjectResourcesCriteria;
import com.cloud.projects.ProjectInvitationVO;
import com.cloud.projects.ProjectManager;
import com.cloud.projects.ProjectVO;
import com.cloud.projects.dao.ProjectAccountDao;
import com.cloud.projects.dao.ProjectDao;
import com.cloud.region.ha.GlobalLoadBalancingRulesService;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VolumeApiService;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.snapshot.SnapshotManager;
import com.cloud.template.TemplateManager;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.user.Account.State;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.SSHKeyPairDao;
import com.cloud.user.dao.UserAccountDao;
import com.cloud.user.dao.UserDao;
import com.cloud.user.dao.UserDataDao;
import com.cloud.utils.ConstantTimeComparator;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.Ternary;
import com.cloud.utils.UuidUtils;
import com.cloud.utils.StringUtils;
import com.cloud.utils.component.ComponentContext;
import com.cloud.utils.component.Manager;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.component.PluggableService;
import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.GlobalLock;
import com.cloud.utils.db.JoinBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.db.TransactionCallback;
import com.cloud.utils.db.TransactionCallbackNoReturn;
import com.cloud.utils.db.TransactionStatus;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.InstanceGroupVO;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.ReservationContextImpl;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.dao.InstanceGroupDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
import com.cloud.vm.snapshot.VMSnapshot;
import com.cloud.vm.snapshot.VMSnapshotManager;
import com.cloud.vm.snapshot.VMSnapshotVO;
import com.cloud.vm.snapshot.dao.VMSnapshotDao;

public class AccountManagerImpl extends ManagerBase implements AccountManager, Manager {

    @Inject
    private AccountDao _accountDao;
    @Inject
    private ConfigurationDao _configDao;
    @Inject
    private ResourceCountDao _resourceCountDao;
    @Inject
    private UserDao _userDao;
    @Inject
    private UserDetailsDao _userDetailsDao;
    @Inject
    private InstanceGroupDao _vmGroupDao;
    @Inject
    private UserAccountDao userAccountDao;
    @Inject
    private VolumeDao _volumeDao;
    @Inject
    private UserVmDao _userVmDao;
    @Inject
    private VMTemplateDao _templateDao;
    @Inject
    private NetworkDao _networkDao;
    @Inject
    private SecurityGroupDao _securityGroupDao;
    @Inject
    private VMInstanceDao _vmDao;
    @Inject
    private SecurityGroupManager _networkGroupMgr;
    @Inject
    private NetworkOrchestrationService _networkMgr;
    @Inject
    private SnapshotManager _snapMgr;
    @Inject
    private VMSnapshotManager _vmSnapshotMgr;
    @Inject
    private VMSnapshotDao _vmSnapshotDao;
    @Inject
    private UserVmManager _vmMgr;
    @Inject
    private TemplateManager _tmpltMgr;
    @Inject
    private ConfigurationManager _configMgr;
    @Inject
    private VirtualMachineManager _itMgr;
    @Inject
    private RemoteAccessVpnDao _remoteAccessVpnDao;
    @Inject
    private RemoteAccessVpnService _remoteAccessVpnMgr;
    @Inject
    private VpnUserDao _vpnUser;
    @Inject
    private DataCenterDao _dcDao;
    @Inject
    private DomainManager _domainMgr;
    @Inject
    private ProjectManager _projectMgr;
    @Inject
    private ProjectDao _projectDao;
    @Inject
    private AccountDetailsDao _accountDetailsDao;
    @Inject
    private DomainDao _domainDao;
    @Inject
    private ProjectAccountDao _projectAccountDao;
    @Inject
    private IPAddressDao _ipAddressDao;
    @Inject
    private HostDao hostDao;
    @Inject
    private VpcManager _vpcMgr;
    @Inject
    private NetworkModel _networkModel;
    @Inject
    private Site2SiteVpnManager _vpnMgr;
    @Inject
    private AutoScaleManager _autoscaleMgr;
    @Inject
    private VolumeApiService volumeService;
    @Inject
    private AffinityGroupDao _affinityGroupDao;
    @Inject
    private AccountGuestVlanMapDao _accountGuestVlanMapDao;
    @Inject
    private DataCenterVnetDao _dataCenterVnetDao;
    @Inject
    private ResourceLimitService _resourceLimitMgr;
    @Inject
    private ResourceLimitDao _resourceLimitDao;
    @Inject
    private DedicatedResourceDao _dedicatedDao;
    @Inject
    private GlobalLoadBalancerRuleDao _gslbRuleDao;
    @Inject
    private SSHKeyPairDao _sshKeyPairDao;
    @Inject
    private UserDataDao userDataDao;
    @Inject
    private NetworkPermissionDao networkPermissionDao;
    @Inject
    private SslCertDao sslCertDao;

    private List<QuerySelector> _querySelectors;

    @Inject
    private MessageBus _messageBus;

    @Inject
    private GlobalLoadBalancingRulesService _gslbService;

    @Inject
    public AccountService _accountService;

    private List<UserAuthenticator> _userAuthenticators;
    private List<UserTwoFactorAuthenticator> _userTwoFactorAuthenticators;
    protected List<UserAuthenticator> _userPasswordEncoders;
    protected List<PluggableService> services;
    private List<APIChecker> apiAccessCheckers;

    @Inject
    private IpAddressManager _ipAddrMgr;
    @Inject
    private RoleService roleService;
    @Inject
    private RoutedIpv4Manager routedIpv4Manager;

    @Inject
    private PasswordPolicy passwordPolicy;

    private final ScheduledExecutorService _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("AccountChecker"));

    private int _allowedLoginAttempts;

    private UserVO _systemUser;
    private AccountVO _systemAccount;

    private List<SecurityChecker> _securityCheckers;
    private int _cleanupInterval;
    private static final String OAUTH2_PROVIDER_NAME = "oauth2";
    private List<String> apiNameList;

    protected static Map<String, UserTwoFactorAuthenticator> userTwoFactorAuthenticationProvidersMap = new HashMap<>();

    private List<UserTwoFactorAuthenticator> userTwoFactorAuthenticationProviders;

    private long validUserLastAuthTimeDurationInMs = 0L;
    private static final long DEFAULT_USER_AUTH_TIME_DURATION_MS = 350L;

    public static ConfigKey<Boolean> enableUserTwoFactorAuthentication = new ConfigKey<>("Advanced",
            Boolean.class,
            "enable.user.2fa",
            "false",
            "Determines whether two factor authentication is enabled or not. This can also be configured at domain level.",
            true,
            ConfigKey.Scope.Domain);

    public static ConfigKey<Boolean> mandateUserTwoFactorAuthentication = new ConfigKey<>("Advanced",
            Boolean.class,
            "mandate.user.2fa",
            "false",
            "Determines whether to make the two factor authentication mandatory or not. This setting is applicable only when enable.user.2fa is true. This can also be configured at domain level.",
            true,
            ConfigKey.Scope.Domain);

    public static final ConfigKey<String> userTwoFactorAuthenticationIssuer = new ConfigKey<>("Advanced",
            String.class,
            "user.2fa.issuer",
            "CloudStack",
            "Name of the issuer of two factor authentication",
            true,
            ConfigKey.Scope.Domain);

    static final ConfigKey<String> userTwoFactorAuthenticationDefaultProvider = new ConfigKey<>("Advanced", String.class,
            "user.2fa.default.provider",
            "totp",
            "The default user two factor authentication provider. Eg. totp, staticpin", true, ConfigKey.Scope.Domain);

    public static final ConfigKey<Boolean> apiKeyAccess = new ConfigKey<>(ConfigKey.CATEGORY_SYSTEM, Boolean.class,
            "api.key.access",
            "true",
            "Determines whether API (api-key/secret-key) access is allowed or not. Editable only by Root Admin.",
            true,
            ConfigKey.Scope.Domain);

    static ConfigKey<Boolean> userAllowMultipleAccounts = new ConfigKey<>("Advanced",
            Boolean.class,
            "user.allow.multiple.accounts",
            "false",
            "Determines if the same username can be added to more than one account in the same domain (SAML-only).",
            true,
            ConfigKey.Scope.Domain);

    public static ConfigKey<String> listOfRoleTypesAllowedForOperationsOfSameRoleType = new ConfigKey<>("Hidden",
            String.class,
            "role.types.allowed.for.operations.on.accounts.of.same.role.type",
            "Admin, ResourceAdmin, DomainAdmin",
            "Comma separated list of role types that are allowed to do operations on accounts or users of the same role type within a domain.",
            true,
            ConfigKey.Scope.Domain);

    public static ConfigKey<Boolean> allowOperationsOnUsersInSameAccount = new ConfigKey<>("Hidden",
            Boolean.class,
            "allow.operations.on.users.in.same.account",
            "true",
            "Allow operations on users among them in the same account",
            true,
            ConfigKey.Scope.Domain);

    protected AccountManagerImpl() {
        super();
    }

    public List<UserAuthenticator> getUserAuthenticators() {
        return _userAuthenticators;
    }

    public void setUserAuthenticators(List<UserAuthenticator> authenticators) {
        _userAuthenticators = authenticators;
    }

    public List<UserTwoFactorAuthenticator> getUserTwoFactorAuthenticators() {
        return _userTwoFactorAuthenticators;
    }

    public void setUserTwoFactorAuthenticators(List<UserTwoFactorAuthenticator> twoFactorAuthenticators) {
        _userTwoFactorAuthenticators = twoFactorAuthenticators;
    }

    public List<UserAuthenticator> getUserPasswordEncoders() {
        return _userPasswordEncoders;
    }

    public void setUserPasswordEncoders(List<UserAuthenticator> encoders) {
        _userPasswordEncoders = encoders;
    }

    public List<SecurityChecker> getSecurityCheckers() {
        return _securityCheckers;
    }

    public void setSecurityCheckers(List<SecurityChecker> securityCheckers) {
        _securityCheckers = securityCheckers;
    }

    public List<PluggableService> getServices() {
        return services;
    }

    public void setServices(List<PluggableService> services) {
        this.services = services;
    }

    public List<APIChecker> getApiAccessCheckers() {
        return apiAccessCheckers;
    }

    public void setApiAccessCheckers(List<APIChecker> apiAccessCheckers) {
        this.apiAccessCheckers = apiAccessCheckers;
    }

    public List<QuerySelector> getQuerySelectors() {
        return _querySelectors;
    }

    public void setQuerySelectors(List<QuerySelector> querySelectors) {
        _querySelectors = querySelectors;
    }

    protected void deleteWebhooksForAccount(long accountId) {
        try {
            WebhookHelper webhookService = ComponentContext.getDelegateComponentOfType(WebhookHelper.class);
            webhookService.deleteWebhooksForAccount(accountId);
        } catch (NoSuchBeanDefinitionException ignored) {
            logger.debug("No WebhookHelper bean found");
        }
    }

    @Override
    public List<String> getApiNameList() {
        return apiNameList;
    }

    @Override
    public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
        _systemAccount = _accountDao.findById(Account.ACCOUNT_ID_SYSTEM);
        if (_systemAccount == null) {
            throw new ConfigurationException("Unable to find the system account using " + Account.ACCOUNT_ID_SYSTEM);
        }

        _systemUser = _userDao.findById(User.UID_SYSTEM);
        if (_systemUser == null) {
            throw new ConfigurationException("Unable to find the system user using " + User.UID_SYSTEM);
        }

        Map<String, String> configs = _configDao.getConfiguration(params);

        String loginAttempts = configs.get(Config.IncorrectLoginAttemptsAllowed.key());
        _allowedLoginAttempts = NumbersUtil.parseInt(loginAttempts, 5);

        String value = configs.get(Config.AccountCleanupInterval.key());
        _cleanupInterval = NumbersUtil.parseInt(value, 60 * 60 * 24); // 1 day.

        return true;
    }

    @Override
    public UserVO getSystemUser() {
        if (_systemUser == null) {
            _systemUser = _userDao.findById(User.UID_SYSTEM);
        }
        return _systemUser;
    }

    @Override
    public boolean start() {

        initializeUserTwoFactorAuthenticationProvidersMap();

        if (apiNameList == null) {
            long startTime = System.nanoTime();
            apiNameList = new ArrayList<>();
            Set<Class<?>> cmdClasses = new LinkedHashSet<>();
            for (PluggableService service : services) {
                logger.debug(String.format("getting api commands of service: %s", service.getClass().getName()));
                cmdClasses.addAll(service.getCommands());
            }
            apiNameList = createApiNameList(cmdClasses);
            long endTime = System.nanoTime();
            logger.info("Api Discovery Service: Annotation, docstrings, api relation graph processed in " + (endTime - startTime) / 1000000.0 + " ms");
        }
        _executor.scheduleAtFixedRate(new AccountCleanupTask(), _cleanupInterval, _cleanupInterval, TimeUnit.SECONDS);
        return true;
    }

    protected List<String> createApiNameList(Set<Class<?>> cmdClasses) {
        List<String> apiNameList = new ArrayList<>();

        for (Class<?> cmdClass : cmdClasses) {
            APICommand apiCmdAnnotation = cmdClass.getAnnotation(APICommand.class);
            if (apiCmdAnnotation == null) {
                apiCmdAnnotation = cmdClass.getSuperclass().getAnnotation(APICommand.class);
            }
            if (apiCmdAnnotation == null || !apiCmdAnnotation.includeInApiDoc() || apiCmdAnnotation.name().isEmpty()) {
                continue;
            }

            String apiName = apiCmdAnnotation.name();
            if (logger.isTraceEnabled()) {
                logger.trace("Found api: " + apiName);
            }

            apiNameList.add(apiName);
        }

        return apiNameList;
    }


    @Override
    public boolean stop() {
        return true;
    }

    @Override
    public AccountVO getSystemAccount() {
        if (_systemAccount == null) {
            _systemAccount = _accountDao.findById(Account.ACCOUNT_ID_SYSTEM);
        }
        return _systemAccount;
    }

    @Override
    public boolean isAdmin(Long accountId) {
        if (accountId != null) {
            AccountVO acct = _accountDao.findById(accountId);
            if (acct == null) {
                return false;  //account is deleted or does not exist
            }
            return (isRootAdmin(accountId)) || (isDomainAdmin(accountId)) || (isResourceDomainAdmin(accountId)) || (acct.getType() == Account.Type.READ_ONLY_ADMIN);

        }
        return false;
    }

    @Override
    public boolean isRootAdmin(Long accountId) {
        if (accountId != null) {
            AccountVO acct = _accountDao.findById(accountId);
            if (acct == null) {
                return false;  //account is deleted or does not exist
            }
            for (SecurityChecker checker : _securityCheckers) {
                try {
                    if (checker.checkAccess(acct, null, null, "SystemCapability")) {
                        if (logger.isTraceEnabled()) {
                            logger.trace("Root Access granted to " + acct + " by " + checker.getName());
                        }
                        return true;
                    }
                } catch (PermissionDeniedException ex) {
                    return false;
                }
            }
        }
        return false;
    }

    @Override
    public boolean isDomainAdmin(Long accountId) {
        if (accountId != null) {
            AccountVO acct = _accountDao.findById(accountId);
            if (acct == null) {
                return false;  //account is deleted or does not exist
            }
            for (SecurityChecker checker : _securityCheckers) {
                try {
                    if (checker.checkAccess(acct, null, null, "DomainCapability")) {
                        if (logger.isTraceEnabled()) {
                            logger.trace("DomainAdmin Access granted to " + acct + " by " + checker.getName());
                        }
                        return true;
                    }
                } catch (PermissionDeniedException ex) {
                    return false;
                }
            }
        }
        return false;
    }

    @Override
    public boolean isNormalUser(long accountId) {
        AccountVO acct = _accountDao.findById(accountId);
        return acct != null && acct.getType() == Account.Type.NORMAL;
    }

    @Override
    public boolean isResourceDomainAdmin(Long accountId) {
        if (accountId != null) {
            AccountVO acct = _accountDao.findById(accountId);
            if (acct == null) {
                return false;  //account is deleted or does not exist
            }
            for (SecurityChecker checker : _securityCheckers) {
                try {
                    if (checker.checkAccess(acct, null, null, "DomainResourceCapability")) {
                        if (logger.isTraceEnabled()) {
                            logger.trace("ResourceDomainAdmin Access granted to " + acct + " by " + checker.getName());
                        }
                        return true;
                    }
                } catch (PermissionDeniedException ex) {
                    return false;
                }
            }
        }
        return false;
    }

    public boolean isInternalAccount(long accountId) {
        Account account = _accountDao.findById(accountId);
        if (account == null) {
            return false;  //account is deleted or does not exist
        }
        return isRootAdmin(accountId) || (account.getType() == Account.Type.ADMIN);
    }

    @Override
    public void checkAccess(Account caller, Domain domain) throws PermissionDeniedException {
        for (SecurityChecker checker : _securityCheckers) {
            if (checker.checkAccess(caller, domain)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Access granted to " + caller + " to " + domain + " by " + checker.getName());
                }
                return;
            }
        }
        throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to " + domain);
    }

    @Override
    public void checkAccess(Account caller, AccessType accessType, boolean sameOwner, ControlledEntity... entities) {
        checkAccess(caller, accessType, sameOwner, null, entities);
    }

    @Override
    public void checkAccess(Account caller, AccessType accessType, boolean sameOwner, String apiName, ControlledEntity... entities) {

        //check for the same owner
        Long ownerId = null;
        ControlledEntity prevEntity = null;
        if (sameOwner) {
            for (ControlledEntity entity : entities) {
                if (ownerId == null) {
                    ownerId = entity.getAccountId();
                } else if (! ownerId.equals(entity.getAccountId())) {
                    throw new PermissionDeniedException("Entity " + entity + " and entity " + prevEntity + " belong to different accounts");
                }
                prevEntity = entity;
            }
        }

        if (caller.getId() == Account.ACCOUNT_ID_SYSTEM || isRootAdmin(caller.getId())) {
            // no need to make permission checks if the system/root admin makes the call
            if (logger.isTraceEnabled()) {
                logger.trace("No need to make permission check for System/RootAdmin account, returning true");
            }

            return;
        }

        HashMap<Long, List<ControlledEntity>> domains = new HashMap<>();

        for (ControlledEntity entity : entities) {
            long domainId = entity.getDomainId();
            if (entity.getAccountId() != -1 && domainId == -1) { // If account exists domainId should too so calculate
                // it. This condition might be hit for templates or entities which miss domainId in their tables
                Account account = ApiDBUtils.findAccountById(entity.getAccountId());
                domainId = account != null ? account.getDomainId() : -1;
            }
            if (entity.getAccountId() != -1 && domainId != -1 && !(entity instanceof VirtualMachineTemplate)
                    && !(entity instanceof Network && (accessType == AccessType.UseEntry || accessType == AccessType.OperateEntry))
                    && !(entity instanceof AffinityGroup) && !(entity instanceof VirtualRouter)) {
                List<ControlledEntity> toBeChecked = domains.get(entity.getDomainId());
                // for templates, we don't have to do cross domains check
                if (toBeChecked == null) {
                    toBeChecked = new ArrayList<>();
                    domains.put(domainId, toBeChecked);
                }
                toBeChecked.add(entity);
            }
            boolean granted = false;
            for (SecurityChecker checker : _securityCheckers) {
                if (checker.checkAccess(caller, entity, accessType, apiName)) {
                    if (logger.isDebugEnabled()) {
                        User user = CallContext.current().getCallingUser();
                        String userName = "";
                        if (user != null)
                            userName = user.getUsername();
                        logger.debug("Access to {} granted to {} by {} on behalf of user {}", entity, caller, checker.getName(), userName);
                    }
                    granted = true;
                    break;
                }
            }

            if (!granted) {
                assert false : "How can all of the security checkers pass on checking this check: " + entity;
            throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to " + entity);
            }
        }

        for (Map.Entry<Long, List<ControlledEntity>> domain : domains.entrySet()) {
            for (SecurityChecker checker : _securityCheckers) {
                Domain d = _domainMgr.getDomain(domain.getKey());
                if (d == null || d.getRemoved() != null) {
                    throw new PermissionDeniedException("Domain is not found.", caller, domain.getValue());
                }
                try {
                    checker.checkAccess(caller, d);
                } catch (PermissionDeniedException e) {
                    e.addDetails(caller, domain.getValue());
                    throw e;
                }
            }
        }

        // check that resources belong to the same account

    }

    @Override
    public void validateAccountHasAccessToResource(Account account, AccessType accessType, Object resource) {
        Class<?> resourceClass = resource.getClass();
        if (ControlledEntity.class.isAssignableFrom(resourceClass)) {
            checkAccess(account, accessType, true, (ControlledEntity) resource);
        } else if (Domain.class.isAssignableFrom(resourceClass)) {
            checkAccess(account, (Domain) resource);
        } else if (InfrastructureEntity.class.isAssignableFrom(resourceClass)) {
            logger.trace("Validation of access to infrastructure entity has been disabled in CloudStack version 4.4.");
        }
        logger.debug("Account [{}] has access to resource.", account);
    }

    @Override
    public Long checkAccessAndSpecifyAuthority(Account caller, Long zoneId) {
        // We just care for resource domain admins for now, and they should be permitted to see only their zone.
        if (isResourceDomainAdmin(caller.getAccountId())) {
            if (zoneId == null) {
                return getZoneIdForAccount(caller);
            } else if (zoneId.compareTo(getZoneIdForAccount(caller)) != 0) {
                throw new PermissionDeniedException("Caller " + caller + "is not allowed to access the zone " + zoneId);
            } else {
                return zoneId;
            }
        } else {
            return zoneId;
        }
    }

    private Long getZoneIdForAccount(Account account) {

        // Currently just for resource domain admin
        List<DataCenterVO> dcList = _dcDao.findZonesByDomainId(account.getDomainId());
        if (CollectionUtils.isNotEmpty(dcList)) {
            return dcList.get(0).getId();
        } else {
            throw new CloudRuntimeException("Failed to find any private zone for Resource domain admin.");
        }

    }

    @DB
    public void updateLoginAttempts(final Long id, final int attempts, final boolean toDisable) {
        try {
            Transaction.execute(new TransactionCallbackNoReturn() {
                @Override
                public void doInTransactionWithoutResult(TransactionStatus status) {
                    UserAccountVO user = null;
                    user = userAccountDao.lockRow(id, true);
                    user.setLoginAttempts(attempts);
                    if (toDisable) {
                        user.setState(State.DISABLED.toString());
                    }
                    userAccountDao.update(id, user);
                }
            });
        } catch (Exception e) {
            logger.error("Failed to update login attempts for user {}", () -> userAccountDao.findById(id));
        }
    }

    private boolean doSetUserStatus(long userId, State state) {
        UserVO userForUpdate = _userDao.createForUpdate();
        userForUpdate.setState(state);
        return _userDao.update(userId, userForUpdate);
    }

    @Override
    public boolean enableAccount(long accountId) {
        boolean success = false;
        AccountVO acctForUpdate = _accountDao.createForUpdate();
        acctForUpdate.setState(State.ENABLED);
        acctForUpdate.setNeedsCleanup(false);
        success = _accountDao.update(accountId, acctForUpdate);
        return success;
    }

    protected boolean lockAccount(long accountId) {
        boolean success = false;
        Account account = _accountDao.findById(accountId);
        if (account != null) {
            if (account.getState().equals(State.LOCKED)) {
                return true; // already locked, no-op
            } else if (account.getState().equals(State.ENABLED)) {
                AccountVO acctForUpdate = _accountDao.createForUpdate();
                acctForUpdate.setState(State.LOCKED);
                success = _accountDao.update(accountId, acctForUpdate);
            } else {
                if (logger.isInfoEnabled()) {
                    logger.info("Attempting to lock a non-enabled account {}, current state is {}, locking failed.", account, account.getState());
                }
            }
        } else {
            logger.warn("Failed to lock account " + accountId + ", account not found.");
        }
        return success;
    }

    @Override
    public boolean deleteAccount(AccountVO account, long callerUserId, Account caller) {
        long accountId = account.getId();

        // delete the account record
        if (!_accountDao.remove(accountId)) {
            logger.error("Unable to delete account {}", account);
            return false;
        }

        account.setState(State.REMOVED);
        _accountDao.update(accountId, account);

        if (logger.isDebugEnabled()) {
            logger.debug("Removed account {}", account);
        }

        return cleanupAccount(account, callerUserId, caller);
    }

    protected void cleanupPluginsResourcesIfNeeded(Account account) {
        try {
            KubernetesServiceHelper kubernetesServiceHelper =
                    ComponentContext.getDelegateComponentOfType(KubernetesServiceHelper.class);
            kubernetesServiceHelper.cleanupForAccount(account);
        } catch (NoSuchBeanDefinitionException ignored) {
            logger.debug("No KubernetesServiceHelper bean found");
        }
    }

    protected boolean cleanupAccount(AccountVO account, long callerUserId, Account caller) {
        long accountId = account.getId();
        boolean accountCleanupNeeded = false;

        try {
            // cleanup the users from the account
            List<UserVO> users = _userDao.listByAccount(accountId);
            for (UserVO user : users) {
                if (!_userDao.remove(user.getId())) {
                    logger.error("Unable to delete user: " + user + " as a part of account " + account + " cleanup");
                    accountCleanupNeeded = true;
                }
            }

            // delete autoscaling VM groups
            if (!_autoscaleMgr.deleteAutoScaleVmGroupsByAccount(account)) {
                accountCleanupNeeded = true;
            }


            // delete global load balancer rules for the account.
            List<org.apache.cloudstack.region.gslb.GlobalLoadBalancerRuleVO> gslbRules = _gslbRuleDao.listByAccount(accountId);
            if (gslbRules != null && !gslbRules.isEmpty()) {
                _gslbService.revokeAllGslbRulesForAccount(caller, account);
            }

            // delete the account from project accounts
            _projectAccountDao.removeAccountFromProjects(accountId);

            // Delete account's network permissions
            networkPermissionDao.removeAccountPermissions(accountId);

            if (account.getType() != Account.Type.PROJECT) {
                // delete the account from group
                _messageBus.publish(_name, MESSAGE_REMOVE_ACCOUNT_EVENT, PublishScope.LOCAL, accountId);
            }

            // delete all vm groups belonging to account
            List<InstanceGroupVO> groups = _vmGroupDao.listByAccountId(accountId);
            for (InstanceGroupVO group : groups) {
                if (!_vmMgr.deleteVmGroup(group.getId())) {
                    logger.error("Unable to delete group: {}", group);
                    accountCleanupNeeded = true;
                }
            }

            // Delete the snapshots dir for the account. Have to do this before destroying the VMs.
            boolean success = _snapMgr.deleteSnapshotDirsForAccount(account);
            if (success) {
                logger.debug("Successfully deleted snapshots directories for all volumes under account {} across all zones", account);
            }

            // clean up templates
            List<VMTemplateVO> userTemplates = _templateDao.listByAccountId(accountId);
            boolean allTemplatesDeleted = true;
            for (VMTemplateVO template : userTemplates) {
                if (template.getRemoved() == null) {
                    try {
                        allTemplatesDeleted = _tmpltMgr.delete(callerUserId, template.getId(), null);
                    } catch (Exception e) {
                        logger.warn("Failed to delete template {} while removing account {} due to: ", template, account, e);
                        allTemplatesDeleted = false;
                    }
                }
            }

            if (!allTemplatesDeleted) {
                logger.warn("Failed to delete Templates while removing Account {}", account);
                accountCleanupNeeded = true;
            }

            // Destroy VM Snapshots
            List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.listByAccountId(accountId);
            for (VMSnapshot vmSnapshot : vmSnapshots) {
                try {
                    _vmSnapshotMgr.deleteVMSnapshot(vmSnapshot.getId());
                } catch (Exception e) {
                    logger.debug("Failed to cleanup Instance Snapshot {} due to {}", vmSnapshot, e.toString());
                }
            }

            cleanupPluginsResourcesIfNeeded(account);

            // Destroy the account's VMs
            List<UserVmVO> vms = _userVmDao.listByAccountId(accountId);
            if (logger.isDebugEnabled()) {
                logger.debug("Expunging # of Instances (Account={}): {}", account, vms.size());
            }

            for (UserVmVO vm : vms) {
                if (vm.getState() != VirtualMachine.State.Destroyed && vm.getState() != VirtualMachine.State.Expunging) {
                    try {
                        _vmMgr.destroyVm(vm.getId(), false);
                    } catch (Exception e) {
                        logger.warn("Failed destroying instance {} as part of account deletion.", vm, e);
                    }
                }
                // no need to catch exception at this place as expunging vm
                // should pass in order to perform further cleanup
                if (!_vmMgr.expunge(vm)) {
                    logger.error("Unable to expunge vm: {}", vm);
                    accountCleanupNeeded = true;
                }
            }

            // Mark the account's volumes as destroyed
            List<VolumeVO> volumes = _volumeDao.findDetachedByAccount(accountId);
            for (VolumeVO volume : volumes) {
                try {
                    volumeService.deleteVolume(volume.getId(), caller);
                } catch (Exception ex) {
                    logger.warn("Failed to cleanup volumes as a part of account {} cleanup due to Exception: ", account, ex);
                    accountCleanupNeeded = true;
                }
            }

            // delete remote access vpns and associated users
            List<RemoteAccessVpnVO> remoteAccessVpns = _remoteAccessVpnDao.findByAccount(accountId);
            List<VpnUserVO> vpnUsers = _vpnUser.listByAccount(accountId);

            for (VpnUserVO vpnUser : vpnUsers) {
                _remoteAccessVpnMgr.removeVpnUser(account, vpnUser.getUsername(), caller);
            }

            try {
                for (RemoteAccessVpnVO vpn : remoteAccessVpns) {
                    _remoteAccessVpnMgr.destroyRemoteAccessVpnForIp(vpn.getServerAddressId(), caller, false);
                }
            } catch (ResourceUnavailableException ex) {
                logger.warn("Failed to cleanup remote access vpn resources as a part of account {} cleanup due to Exception: ", account, ex);
                accountCleanupNeeded = true;
            }

            // Cleanup tungsten security groups
            List<SecurityGroupVO> securityGroupList = _securityGroupDao.listByAccountId(accountId);
            for(SecurityGroupVO securityGroupVO : securityGroupList) {
                _messageBus.publish(_name, SecurityGroupService.MESSAGE_DELETE_TUNGSTEN_SECURITY_GROUP_EVENT, PublishScope.LOCAL, securityGroupVO);
            }

            // Cleanup security groups
            int numRemoved = _securityGroupDao.removeByAccountId(accountId);
            logger.info("deleteAccount: Deleted {} network groups for account {}", numRemoved, account);

            // Cleanup affinity groups
            int numAGRemoved = _affinityGroupDao.removeByAccountId(accountId);
            logger.info("deleteAccount: Deleted {} affinity groups for account {}", numAGRemoved, account);

            // Delete all the networks
            boolean networksDeleted = true;
            logger.debug("Deleting networks for account {}", account);
            List<NetworkVO> networks = _networkDao.listByOwner(accountId);
            if (networks != null) {
                networks.sort(new Comparator<>() {
                    @Override
                    public int compare(NetworkVO network1, NetworkVO network2) {
                        if (network1.getGuestType() != network2.getGuestType() && Network.GuestType.Isolated.equals(network2.getGuestType())) {
                            return -1;
                        }
                        return 1;
                    }
                });
                for (NetworkVO network : networks) {
                    if (_networkModel.isPrivateGateway(network.getId())) {
                        continue;
                    }

                    ReservationContext context = new ReservationContextImpl(null, null, getActiveUser(callerUserId), caller);

                    if (!_networkMgr.destroyNetwork(network.getId(), context, false)) {
                        logger.warn("Unable to destroy network {} as a part of account {} cleanup.", network, account);
                        accountCleanupNeeded = true;
                        networksDeleted = false;
                    } else {
                        logger.debug("Network {} successfully deleted as a part of account {} cleanup.", network, account);
                    }
                }
            }

            // Delete all VPCs
            boolean vpcsDeleted = true;
            logger.debug("Deleting vpcs for account {}", account);
            List<? extends Vpc> vpcs = _vpcMgr.getVpcsForAccount(account.getId());
            for (Vpc vpc : vpcs) {

                if (!_vpcMgr.destroyVpc(vpc, caller, callerUserId)) {
                    logger.warn("Unable to destroy VPC {} as a part of account {} cleanup.", vpc, account);
                    accountCleanupNeeded = true;
                    vpcsDeleted = false;
                } else {
                    logger.debug("VPC {} successfully deleted as a part of account {} cleanup.", vpc, account);
                }
            }

            if (networksDeleted && vpcsDeleted) {
                // release ip addresses belonging to the account
                List<? extends IpAddress> ipsToRelease = _ipAddressDao.listByAccount(accountId);
                for (IpAddress ip : ipsToRelease) {
                    logger.debug("Releasing ip {} as a part of account {} cleanup", ip, account);
                    if (!_ipAddrMgr.disassociatePublicIpAddress(ip, callerUserId, caller)) {
                        logger.warn("Failed to release ip address {} as a part of account {} cleanup", ip, account);
                        accountCleanupNeeded = true;
                    }
                }
            }

            // Delete Site 2 Site VPN customer gateway
            logger.debug("Deleting site-to-site VPN customer gateways for account {}", account);
            if (!_vpnMgr.deleteCustomerGatewayByAccount(accountId)) {
                logger.warn("Fail to delete site-to-site VPN customer gateways for account {}", account);
            }

            // Delete autoscale resources if any
            try {
                _autoscaleMgr.cleanUpAutoScaleResources(account);
            } catch (CloudRuntimeException ex) {
                logger.warn("Failed to cleanup AutoScale resources as a part of account {} cleanup due to exception:", account, ex);
                accountCleanupNeeded = true;
            }

            // release account specific Virtual vlans (belong to system Public Network) - only when networks are cleaned
            // up successfully
            if (networksDeleted) {
                if (!_configMgr.releaseAccountSpecificVirtualRanges(account)) {
                    accountCleanupNeeded = true;
                } else {
                    logger.debug("Account specific Virtual IP ranges are successfully released as a part of account {} cleanup.", account);
                }
            }

            // remove dedicated IPv4 subnets
            routedIpv4Manager.removeIpv4SubnetsForZoneByAccountId(accountId);

            // remove dedicated BGP peers
            routedIpv4Manager.removeBgpPeersByAccountId(accountId);

            // release account specific guest vlans
            List<AccountGuestVlanMapVO> maps = _accountGuestVlanMapDao.listAccountGuestVlanMapsByAccount(accountId);
            for (AccountGuestVlanMapVO map : maps) {
                _dataCenterVnetDao.releaseDedicatedGuestVlans(map.getId());
            }
            int vlansReleased = _accountGuestVlanMapDao.removeByAccountId(accountId);
            logger.info("deleteAccount: Released {} dedicated guest vlan ranges from account {}", vlansReleased, account);

            // release account specific acquired portable IP's. Since all the portable IP's must have been already
            // disassociated with VPC/guest network (due to deletion), so just mark portable IP as free.
            List<? extends IpAddress> ipsToRelease = _ipAddressDao.listByAccount(accountId);
            for (IpAddress ip : ipsToRelease) {
                if (ip.isPortable()) {
                    logger.debug("Releasing portable ip {} as a part of account {} cleanup", ip, account);
                    _ipAddrMgr.releasePortableIpAddress(ip.getId());
                }
            }

            // release dedication if any
            List<DedicatedResourceVO> dedicatedResources = _dedicatedDao.listByAccountId(accountId);
            if (dedicatedResources != null && !dedicatedResources.isEmpty()) {
                logger.debug("Releasing dedicated resources for account {}", account);
                for (DedicatedResourceVO dr : dedicatedResources) {
                    if (!_dedicatedDao.remove(dr.getId())) {
                        logger.warn("Fail to release dedicated resources for account {}", account);
                    }
                }
            }

            // Updating and deleting the resourceLimit and resourceCount should be the last step in cleanupAccount
// process.
            // Update resource count for this account and for parent domains.
            List<ResourceCountVO> resourceCounts = _resourceCountDao.listByOwnerId(accountId, ResourceOwnerType.Account);
            for (ResourceCountVO resourceCount : resourceCounts) {
                _resourceLimitMgr.decrementResourceCount(accountId, resourceCount.getType(), resourceCount.getCount());
            }

            // Delete resource count and resource limits entries set for this account (if there are any).
            _resourceCountDao.removeEntriesByOwner(accountId, ResourceOwnerType.Account);
            _resourceLimitDao.removeEntriesByOwner(accountId, ResourceOwnerType.Account);

            // Delete ssh keypairs
            List<SSHKeyPairVO> sshkeypairs = _sshKeyPairDao.listKeyPairs(accountId, account.getDomainId());
            for (SSHKeyPairVO keypair : sshkeypairs) {
                _sshKeyPairDao.remove(keypair.getId());
            }

            // Delete registered UserData
            userDataDao.removeByAccountId(accountId);

            // Delete SSL certificates
            sslCertDao.removeByAccountId(accountId);

            // Delete Webhooks
            deleteWebhooksForAccount(accountId);

            return true;
        } catch (Exception ex) {
            logger.warn("Failed to cleanup account " + account + " due to ", ex);
            accountCleanupNeeded = true;
            return true;
        } finally {
            logger.info("Cleanup for account {} {}", account, accountCleanupNeeded ? "is needed." : "is not needed.");
            if (accountCleanupNeeded) {
                _accountDao.markForCleanup(accountId);
            } else {
                account.setNeedsCleanup(false);
                _accountDao.update(accountId, account);
            }
        }
    }

    @Override
    public boolean disableAccount(long accountId) throws ConcurrentOperationException, ResourceUnavailableException {
        boolean success = false;
        if (accountId <= 2) {
            if (logger.isInfoEnabled()) {
                logger.info("disableAccount -- invalid account id: " + accountId);
            }
            return false;
        }

        AccountVO account = _accountDao.findById(accountId);
        if ((account == null) || (account.getState().equals(State.DISABLED) && !account.getNeedsCleanup())) {
            success = true;
        } else {
            AccountVO acctForUpdate = _accountDao.createForUpdate();
            acctForUpdate.setState(State.DISABLED);
            success = _accountDao.update(accountId, acctForUpdate);

            if (success) {
                boolean disableAccountResult = false;
                try {
                    disableAccountResult = doDisableAccount(accountId);
                } finally {
                    if (!disableAccountResult) {
                        logger.warn("Failed to disable account " + account + " resources as a part of disableAccount call, marking the account for cleanup");
                        _accountDao.markForCleanup(accountId);
                    } else {
                        acctForUpdate = _accountDao.createForUpdate();
                        account.setNeedsCleanup(false);
                        _accountDao.update(accountId, account);
                    }
                }
            }
        }
        return success;
    }

    private boolean doDisableAccount(long accountId) throws ConcurrentOperationException, ResourceUnavailableException {
        List<VMInstanceVO> vms = _vmDao.listByAccountId(accountId);
        boolean success = true;
        for (VMInstanceVO vm : vms) {
            try {
                try {
                    _itMgr.advanceStop(vm.getUuid(), false);
                } catch (OperationTimedoutException ote) {
                    logger.warn("Operation for stopping vm timed out, unable to stop vm {}", vm, ote);
                    success = false;
                }
            } catch (AgentUnavailableException aue) {
                logger.warn("Agent running on host {} is unavailable, unable to stop vm {}", () -> hostDao.findById(vm.getHostId()), vm::toString, () -> aue);
                success = false;
            }
        }

        return success;
    }

    @Override
    @ActionEvents({@ActionEvent(eventType = EventTypes.EVENT_ACCOUNT_CREATE, eventDescription = "creating Account"),
            @ActionEvent(eventType = EventTypes.EVENT_USER_CREATE, eventDescription = "creating User")})
    public UserAccount createUserAccount(CreateAccountCmd accountCmd) {
        return createUserAccount(accountCmd.getUsername(), accountCmd.getPassword(), accountCmd.getFirstName(),
                accountCmd.getLastName(), accountCmd.getEmail(), accountCmd.getTimeZone(), accountCmd.getAccountName(),
                accountCmd.getAccountType(), accountCmd.getRoleId(), accountCmd.getDomainId(),
                accountCmd.getNetworkDomain(), accountCmd.getDetails(), accountCmd.getAccountUUID(),
                accountCmd.getUserUUID(), User.Source.UNKNOWN);
    }

    // ///////////////////////////////////////////////////
    // ////////////// API commands /////////////////////
    // ///////////////////////////////////////////////////

    @Override
    @DB
    @ActionEvents({@ActionEvent(eventType = EventTypes.EVENT_ACCOUNT_CREATE, eventDescription = "creating Account"),
        @ActionEvent(eventType = EventTypes.EVENT_USER_CREATE, eventDescription = "creating User")})
    public UserAccount createUserAccount(final String userName, final String password, final String firstName,
                                         final String lastName, final String email, final String timezone,
                                         String accountName, final Account.Type accountType, final Long roleId, Long domainId,
                                         final String networkDomain, final Map<String, String> details,
                                         String accountUUID, final String userUUID, final User.Source source) {

        if (accountName == null) {
            accountName = userName;
        }
        if (domainId == null) {
            domainId = Domain.ROOT_DOMAIN;
        }

        if (StringUtils.isEmpty(userName)) {
            throw new InvalidParameterValueException("Username is empty");
        }

        if (StringUtils.isEmpty(firstName)) {
            throw new InvalidParameterValueException("Firstname is empty");
        }

        if (StringUtils.isEmpty(lastName)) {
            throw new InvalidParameterValueException("Lastname is empty");
        }

        // Validate domain
        Domain domain = _domainMgr.getDomain(domainId);
        if (domain == null) {
            throw new InvalidParameterValueException("The domain " + domainId + " does not exist; unable to create account");
        }

        // Check permissions
        checkAccess(getCurrentCallingAccount(), domain);

        if (!userAllowMultipleAccounts.valueInScope(ConfigKey.Scope.Domain, domainId) && !userAccountDao.validateUsernameInDomain(userName, domainId)) {
            throw new InvalidParameterValueException(String.format("The user %s already exists in domain %s", userName, domain));
        }

        if (StringUtils.isNotEmpty(networkDomain)) {
            if (!NetUtils.verifyDomainName(networkDomain)) {
                throw new InvalidParameterValueException(
                        "Invalid network domain. Total length shouldn't exceed 190 chars. Each domain label must be between 1 and 63 characters long, can contain ASCII letters 'a' through 'z', the digits '0' through '9', "
                                + "and the hyphen ('-'); can't start or end with \"-\"");
            }
        }

        final String accountNameFinal = accountName;
        final Long domainIdFinal = domainId;
        final String resolvedAccountUUID = accountUUID != null ? accountUUID : UUID.randomUUID().toString();

        // Check role escalation before the transaction — this is a read-only check
        // that iterates all API commands and doesn't need a write transaction open.
        AccountVO requestedAccount = new AccountVO(accountNameFinal, domainIdFinal, networkDomain, accountType, roleId, resolvedAccountUUID);
        checkRoleEscalation(getCurrentCallingAccount(), requestedAccount);

        Pair<Long, Account> pair = Transaction.execute(new TransactionCallback<>() {
            @Override
            public Pair<Long, Account> doInTransaction(TransactionStatus status) {
                AccountVO account = createAccount(accountNameFinal, accountType, roleId, domainIdFinal, networkDomain, details, resolvedAccountUUID);
                long accountId = account.getId();

                // create the first user for the account
                UserVO user = createUser(accountId, userName, password, firstName, lastName, email, timezone, userUUID, source);

                if (accountType == Account.Type.RESOURCE_DOMAIN_ADMIN) {
                    // set registration token
                    byte[] bytes = (domainIdFinal + accountNameFinal + userName + System.currentTimeMillis()).getBytes();
                    String registrationToken = UuidUtils.nameUUIDFromBytes(bytes).toString();
                    user.setRegistrationToken(registrationToken);
                }

                return new Pair<>(user.getId(), account);
            }
        });

        long userId = pair.first();
        Account account = pair.second();

        // create correct account and group association based on accountType
        if (accountType != Account.Type.PROJECT) {
            Map<Long, Long> accountGroupMap = new HashMap<>();
            accountGroupMap.put(account.getId(), (long) (accountType.ordinal() + 1));
            _messageBus.publish(_name, MESSAGE_ADD_ACCOUNT_EVENT, PublishScope.LOCAL, accountGroupMap);
        }

        CallContext.current().putContextParameter(Account.class, account.getUuid());
        CallContext.current().putContextParameter(User.class, userId);

        // check success
        return userAccountDao.findById(userId);
    }

    /*
     Role change should follow the below conditions:
     - Caller should not be of Unknown role type
     - New role's type should not be Unknown
     - Caller should not be able to escalate or de-escalate an account's role which is of higher role type
     - New role should not be of type Admin with domain other than ROOT domain
     */
    protected void validateRoleChange(Account account, Role role, Account caller) {
        if (account.getRoleId() != null && account.getRoleId().equals(role.getId())) {
            return;
        }
        Role currentRole = roleService.findRole(account.getRoleId());
        Role callerRole = roleService.findRole(caller.getRoleId());
        String errorMsg = String.format("Unable to update account role to %s, ", role.getName());
        if (RoleType.Unknown.equals(callerRole.getRoleType())) {
            throw new PermissionDeniedException(String.format("%s as the caller privileges are unknown", errorMsg));
        }
        if (RoleType.Unknown.equals(role.getRoleType())) {
            throw new PermissionDeniedException(String.format("%s as the new role privileges are unknown", errorMsg));
        }
        if (!callerRole.getRoleType().equals(RoleType.Admin) &&
                (role.getRoleType().ordinal() < callerRole.getRoleType().ordinal() ||
                        currentRole.getRoleType().ordinal() < callerRole.getRoleType().ordinal())) {
            throw new PermissionDeniedException(String.format("%s as either current or new role has higher " +
                    "privileges than the caller", errorMsg));
        }
        if (account.isDefault()) {
            throw new PermissionDeniedException(String.format("%s as the account is a default account", errorMsg));
        }
        if (role.getRoleType().equals(RoleType.Admin) && account.getDomainId() != Domain.ROOT_DOMAIN) {
            throw new PermissionDeniedException(String.format("%s as the user does not belong to the ROOT domain",
                    errorMsg));
        }
    }

    /**
     * if there is any permission under the requested role that is not permitted for the caller, refuse
     */
    protected void checkRoleEscalation(Account caller, Account requested) {
        if (logger.isDebugEnabled()) {
            logger.debug(String.format("Checking if user of account %s [%s] with role-id [%d] can create an account of type %s [%s] with role-id [%d]",
                    caller.getAccountName(),
                    caller.getUuid(),
                    caller.getRoleId(),
                    requested.getAccountName(),
                    requested.getUuid(),
                    requested.getRoleId()));
        }
        List<APIChecker> apiCheckers = getEnabledApiCheckers();
        for (String command : apiNameList) {
            try {
                checkApiAccess(apiCheckers, requested, command);
            } catch (PermissionDeniedException pde) {
                if (logger.isTraceEnabled()) {
                    logger.trace(String.format(
                            "Checking for permission to \"%s\" is irrelevant as it is not requested for %s [%s]",
                            command,
                            requested.getAccountName(),
                            requested.getUuid()
                        )
                    );
                }
                continue;
            }
            // so requested can, now make sure caller can as well
            try {
                if (logger.isTraceEnabled()) {
                    logger.trace(String.format("permission to \"%s\" is requested",
                            command));
                }
                checkApiAccess(apiCheckers, caller, command);
            } catch (PermissionDeniedException pde) {
                String msg = String.format("User of Account %s and domain %s can not create an account with access to more privileges they have themself.",
                        caller, _domainMgr.getDomain(caller.getDomainId()));
                logger.warn(msg);
                throw new PermissionDeniedException(msg,pde);
            }
        }
    }

    private void checkApiAccess(List<APIChecker> apiCheckers, Account caller, String command) {
        for (final APIChecker apiChecker : apiCheckers) {
            apiChecker.checkAccess(caller, command);
        }
    }

    @Override
    public void checkApiAccess(Account caller, String command) {
        List<APIChecker> apiCheckers = getEnabledApiCheckers();
        checkApiAccess(apiCheckers, caller, command);
    }

    @NotNull
    private List<APIChecker> getEnabledApiCheckers() {
        // we are really only interested in the dynamic access checker
        List<APIChecker> usableApiCheckers = new ArrayList<>();
        for (APIChecker apiChecker : apiAccessCheckers) {
            if (apiChecker.isEnabled()) {
                usableApiCheckers.add(apiChecker);
                if (logger.isTraceEnabled()) {
                    logger.trace(String.format("using api checker \"%s\"",
                            apiChecker.getName()));
                }
            }
        }
        return usableApiCheckers;
    }

    @Override
    @ActionEvent(eventType = EventTypes.EVENT_USER_CREATE, eventDescription = "creating User")
    public UserVO createUser(String userName, String password, String firstName, String lastName, String email, String timeZone, String accountName, Long domainId, String userUUID,
            User.Source source) {
        // default domain to ROOT if not specified
        if (domainId == null) {
            domainId = Domain.ROOT_DOMAIN;
        }

        Domain domain = _domainMgr.getDomain(domainId);
        if (domain == null) {
            throw new CloudRuntimeException("The domain " + domainId + " does not exist; unable to create user");
        } else if (domain.getState().equals(Domain.State.Inactive)) {
            throw new CloudRuntimeException("The user cannot be created as domain " + domain.getName() + " is being deleted");
        }

        checkAccess(getCurrentCallingAccount(), domain);

        Account account = _accountDao.findEnabledAccount(accountName, domainId);
        if (account == null || account.getType() == Account.Type.PROJECT) {
            throw new InvalidParameterValueException(String.format("Unable to find account %s in domain %s to create user", accountName, domain));
        }

        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
            throw new PermissionDeniedException(String.format("Account: %s is a system account, can't add a user to it", account));
        }

        if (!userAllowMultipleAccounts.valueInScope(ConfigKey.Scope.Domain, domainId) && !userAccountDao.validateUsernameInDomain(userName, domainId)) {
            throw new CloudRuntimeException("The user " + userName + " already exists in domain " + domainId);
        }
        List<UserVO> duplicatedUsers = _userDao.findUsersByName(userName);
        for (UserVO duplicatedUser : duplicatedUsers) {
            // users can't exist in same account
            assertUserNotAlreadyInAccount(duplicatedUser, account);
        }

        verifyCallerPrivilegeForUserOrAccountOperations(account);
        UserVO user;
        user = createUser(account.getId(), userName, password, firstName, lastName, email, timeZone, userUUID, source);
        return user;
    }

    @Override
    @ActionEvent(eventType = EventTypes.EVENT_USER_CREATE, eventDescription = "creating User")
    public UserVO createUser(String userName, String password, String firstName, String lastName, String email, String timeZone, String accountName, Long domainId, String userUUID) {

        return createUser(userName, password, firstName, lastName, email, timeZone, accountName, domainId, userUUID, User.Source.UNKNOWN);
    }

    @Override
    @ActionEvent(eventType = EventTypes.EVENT_USER_UPDATE, eventDescription = "Updating User")
    public UserAccount updateUser(UpdateUserCmd updateUserCmd) {
        UserVO user = retrieveAndValidateUser(updateUserCmd);
        Account account = retrieveAndValidateAccount(user);
        User caller = CallContext.current().getCallingUser();
        checkAccess(caller, account);
        verifyCallerPrivilegeForUserOrAccountOperations(user);

        logger.debug("Updating user {}", user);

        validateAndUpdateApiAndSecretKeyIfNeeded(updateUserCmd, user);
        validateAndUpdateUserApiKeyAccess(updateUserCmd, user);

        validateAndUpdateFirstNameIfNeeded(updateUserCmd, user);
        validateAndUpdateLastNameIfNeeded(updateUserCmd, user);
        validateAndUpdateUsernameIfNeeded(updateUserCmd, user, account);

        validateUserPasswordAndUpdateIfNeeded(updateUserCmd.getPassword(), user, updateUserCmd.getCurrentPassword(), false);
        String email = updateUserCmd.getEmail();
        if (StringUtils.isNotBlank(email)) {
            user.setEmail(email);
        }
        String timezone = updateUserCmd.getTimezone();
        if (StringUtils.isNotBlank(timezone)) {
            user.setTimezone(timezone);
        }
        Boolean mandate2FA = updateUserCmd.getMandate2FA();
        if (mandate2FA != null && mandate2FA) {
            user.setUser2faEnabled(true);
        }
        _userDao.update(user.getId(), user);
        return userAccountDao.findById(user.getId());
    }

    @Override
    public void verifyCallerPrivilegeForUserOrAccountOperations(Account userAccount) {
        logger.debug(String.format("Verifying whether the caller has the correct privileges based on the user's role type and API permissions: %s", userAccount));

        if (!Account.Type.PROJECT.equals(userAccount.getType())) {
            checkCallerRoleTypeAllowedForUserOrAccountOperations(userAccount, null);
            checkCallerApiPermissionsForUserOrAccountOperations(userAccount);
        }
    }

    protected void verifyCallerPrivilegeForUserOrAccountOperations(User user) {
        logger.debug(String.format("Verifying whether the caller has the correct privileges based on the user's role type and API permissions: %s", user));

        Account userAccount = getAccount(user.getAccountId());
        if (!Account.Type.PROJECT.equals(userAccount.getType())) {
            checkCallerRoleTypeAllowedForUserOrAccountOperations(userAccount, user);
            checkCallerApiPermissionsForUserOrAccountOperations(userAccount);
        }
    }

    protected void checkCallerRoleTypeAllowedForUserOrAccountOperations(Account userAccount, User user) {
        Account callingAccount = getCurrentCallingAccount();
        RoleType callerRoleType = getRoleType(callingAccount);
        RoleType userAccountRoleType = getRoleType(userAccount);

        if (RoleType.Unknown == callerRoleType || RoleType.Unknown == userAccountRoleType) {
            String errMsg = String.format("The role type of caller account [%s, %s] or target account [%s, %s] is unknown",
                    callingAccount.getName(), callingAccount.getUuid(), userAccount.getName(), userAccount.getUuid());
            throw new PermissionDeniedException(errMsg);
        }

        boolean isCallerSystemOrDefaultAdmin = callingAccount.getId() == Account.ACCOUNT_ID_SYSTEM || callingAccount.getId() == Account.ACCOUNT_ID_ADMIN;
        if (isCallerSystemOrDefaultAdmin) {
            logger.trace(String.format("Admin account [%s, %s] performing this operation for user account [%s, %s] ", callingAccount.getName(), callingAccount.getUuid(), userAccount.getName(), userAccount.getUuid()));
        } else if (callerRoleType.getId() < userAccountRoleType.getId()) {
            logger.trace(String.format("The calling account [%s, %s] has a higher role type than the user account [%s, %s]",
                    callingAccount.getName(), callingAccount.getUuid(), userAccount.getName(), userAccount.getUuid()));
        } else if (callerRoleType.getId() == userAccountRoleType.getId()) {
            if (callingAccount.getId() != userAccount.getId()) {
                String allowedRoleTypes = listOfRoleTypesAllowedForOperationsOfSameRoleType.valueInScope(ConfigKey.Scope.Domain, callingAccount.getDomainId());
                boolean updateAllowed = allowedRoleTypes != null &&
                        Arrays.stream(allowedRoleTypes.split(","))
                                .map(String::trim)
                                .anyMatch(role -> role.equals(callerRoleType.toString()));
                if (BooleanUtils.isFalse(updateAllowed)) {
                    String errMsg = String.format("The calling account [%s, %s] is not allowed to perform this operation on users from other accounts " +
                            "of the same role type within the domain", callingAccount.getName(), callingAccount.getUuid());
                    logger.error(errMsg);
                    throw new PermissionDeniedException(errMsg);
                }
            } else if ((callingAccount.getId() == userAccount.getId()) && user != null) {
                Boolean allowOperationOnUsersinSameAccount = allowOperationsOnUsersInSameAccount.valueInScope(ConfigKey.Scope.Domain, callingAccount.getDomainId());
                User callingUser = CallContext.current().getCallingUser();
                if (callingUser.getId() != user.getId() && BooleanUtils.isFalse(allowOperationOnUsersinSameAccount)) {
                    String errMsg = "The user operations are not allowed by the users in the same account";
                    logger.error(errMsg);
                    throw new PermissionDeniedException(errMsg);
                }
            }
        } else {
            String errMsg = String.format("The calling account [%s, %s] has a lower role type than the user account [%s, %s]",
                    callingAccount.getName(), callingAccount.getUuid(), userAccount.getName(), userAccount.getUuid());
            throw new PermissionDeniedException(errMsg);
        }
    }

    protected void checkCallerApiPermissionsForUserOrAccountOperations(Account userAccount) {
        Account callingAccount = getCurrentCallingAccount();
        boolean isCallerRootAdmin = callingAccount.getId() == Account.ACCOUNT_ID_SYSTEM || isRootAdmin(callingAccount.getId());

        if (isCallerRootAdmin) {
            logger.trace(String.format("Admin account [%s, %s] performing this operation for user account [%s, %s] ", callingAccount.getName(), callingAccount.getUuid(), userAccount.getName(), userAccount.getUuid()));
        } else if (isRootAdmin(userAccount.getAccountId())) {
            String errMsg = String.format("Account [%s, %s] cannot perform this operation for user account [%s, %s] ", callingAccount.getName(), callingAccount.getUuid(), userAccount.getName(), userAccount.getUuid());
            logger.error(errMsg);
            throw new PermissionDeniedException(errMsg);
        } else {
            logger.debug(String.format("Checking calling account [%s, %s] permission to perform this operation for user account [%s, %s] ", callingAccount.getName(), callingAccount.getUuid(), userAccount.getName(), userAccount.getUuid()));
            checkRoleEscalation(callingAccount, userAccount);
            logger.debug(String.format("Calling account [%s, %s] is allowed to perform this operation for user account [%s, %s] ", callingAccount.getName(), callingAccount.getUuid(), userAccount.getName(), userAccount.getUuid()));
        }
    }

    /**
     * Updates the password in the user POJO if needed. If no password is provided, then the password is not updated.
     * The following validations are executed if 'password' is not null. Admins (root admins or domain admins) can execute password updates without entering the current password.
     * <ul>
     *  <li> If 'password' is blank, we throw an {@link InvalidParameterValueException};
     *  <li> If 'current password' is not provided and user is not an Admin, we throw an {@link InvalidParameterValueException};
     *  <li> If the user whose password is being changed has a source equal to {@link User.Source#SAML2}, {@link User.Source#SAML2DISABLED} or {@link User.Source#LDAP},
     *      we throw an {@link InvalidParameterValueException};
     *  <li> If a normal user is calling this method, we use {@link #validateCurrentPassword(UserVO, String)} to check if the provided old password matches the database one;
     * </ul>
     *
     * If all checks pass, we encode the given password with the most preferable password mechanism given in {@link #_userPasswordEncoders}.
     */
    public void validateUserPasswordAndUpdateIfNeeded(String newPassword, UserVO user, String currentPassword, boolean skipCurrentPassValidation) {
        if (newPassword == null) {
            logger.trace("No new password to update for user: {}", user);
            return;
        }
        if (StringUtils.isBlank(newPassword)) {
            throw new InvalidParameterValueException("Password cannot be empty or blank.");
        }

        User.Source userSource = user.getSource();
        if (userSource == User.Source.SAML2 || userSource == User.Source.SAML2DISABLED || userSource == User.Source.LDAP) {
            logger.warn("Unable to update the password for user [{}], as its source is [{}].", user, user.getSource().toString());
            throw new InvalidParameterValueException("CloudStack does not support updating passwords for SAML or LDAP users. Please contact your cloud administrator for assistance.");
        }

        passwordPolicy.verifyIfPasswordCompliesWithPasswordPolicies(newPassword, user.getUsername(), getAccount(user.getAccountId()).getDomainId());

        Account callingAccount = getCurrentCallingAccount();
        boolean isRootAdminExecutingPasswordUpdate = callingAccount.getId() == Account.ACCOUNT_ID_SYSTEM || isRootAdmin(callingAccount.getId());
        boolean isDomainAdmin = isDomainAdmin(callingAccount.getId());
        boolean isAdmin = isDomainAdmin || isRootAdminExecutingPasswordUpdate;
        boolean skipValidation = isAdmin || skipCurrentPassValidation;
        if (isAdmin) {
            logger.trace("Admin account [{}] executing password update for user [{}] ", callingAccount, user);
        }
        if (!skipValidation && StringUtils.isBlank(currentPassword)) {
            throw new InvalidParameterValueException("To set a new password the current password must be provided.");
        }
        if (CollectionUtils.isEmpty(_userPasswordEncoders)) {
            throw new CloudRuntimeException("No user authenticators configured!");
        }
        if (!skipValidation) {
            validateCurrentPassword(user, currentPassword);
        }
        UserAuthenticator userAuthenticator = _userPasswordEncoders.get(0);
        String newPasswordEncoded = userAuthenticator.encode(newPassword);
        user.setPassword(newPasswordEncoded);
    }

    /**
     * Iterates over all configured user authenticators and tries to authenticate the user using the current password.
     * If the user is authenticated with success, we have nothing else to do here; otherwise, an {@link InvalidParameterValueException} is thrown.
     */
    protected void validateCurrentPassword(UserVO user, String currentPassword) {
        AccountVO userAccount = _accountDao.findById(user.getAccountId());
        boolean currentPasswordMatchesDataBasePassword = false;
        for (UserAuthenticator userAuthenticator : _userPasswordEncoders) {
            Pair<Boolean, ActionOnFailedAuthentication> authenticationResult = userAuthenticator.authenticate(user.getUsername(), currentPassword, userAccount.getDomainId(), null);
            if (authenticationResult == null) {
                logger.trace(String.format("Authenticator [%s] is returning null for the authenticate method.", userAuthenticator.getClass()));
                continue;
            }
            if (BooleanUtils.toBoolean(authenticationResult.first())) {
                logger.debug("User [{}] re-authenticated [authenticator={}] during password update.", user, userAuthenticator.getName());
                currentPasswordMatchesDataBasePassword = true;
                break;
            }
        }
        if (!currentPasswordMatchesDataBasePassword) {
            throw new InvalidParameterValueException("Current password is incorrect.");
        }
    }

    /**
     * Validates the user 'username' if provided. The 'username' cannot be blank (when provided).
     * <ul>
     *  <li> If the 'username' is not provided, we do not update it (setting to null) in the User POJO.
     *  <li> If the 'username' is blank, we throw an {@link InvalidParameterValueException}.
     *  <li> The username must be unique in each domain. Therefore, if there is already another user with the same username, an {@link InvalidParameterValueException} is thrown.
     * </ul>
     */
    protected void validateAndUpdateUsernameIfNeeded(UpdateUserCmd updateUserCmd, UserVO newUser, Account newAccount) {
        String userName = updateUserCmd.getUsername();
        if (userName == null) {
            return;
        }
        if (StringUtils.isBlank(userName)) {
            throw new InvalidParameterValueException("Username cannot be empty.");
        }
        List<UserVO> existingUsers = _userDao.findUsersByName(userName);
        for (UserVO existingUser : existingUsers) {
            if (existingUser.getId() == newUser.getId()) {
                continue;
            }

            // duplicate usernames cannot exist in same domain unless explicitly configured
            if (!userAllowMultipleAccounts.valueInScope(ConfigKey.Scope.Domain, newAccount.getDomainId())) {
                assertUserNotAlreadyInDomain(existingUser, newAccount);
            }

            // can't rename a username to an existing one in the same account
            assertUserNotAlreadyInAccount(existingUser, newAccount);
        }
        newUser.setUsername(userName);
    }

    /**
     * Validates the user 'lastName' if provided. The 'lastName' cannot be blank (when provided).
     * <ul>
     *  <li> If the 'lastName' is not provided, we do not update it (setting to null) in the User POJO.
     *  <li> If the 'lastName' is blank, we throw an {@link InvalidParameterValueException}.
     * </ul>
     */
    protected void validateAndUpdateLastNameIfNeeded(UpdateUserCmd updateUserCmd, UserVO user) {
        String lastName = updateUserCmd.getLastname();
        if (lastName != null) {
            if (StringUtils.isBlank(lastName)) {
                throw new InvalidParameterValueException("Lastname cannot be empty.");
            }

            user.setLastname(lastName);
        }
    }

    /**
     * Validates the user 'firstName' if provided. The 'firstName' cannot be blank (when provided).
     * <ul>
     *  <li> If the 'firstName' is not provided, we do not update it (setting to null) in the User POJO.
     *  <li> If the 'firstName' is blank, we throw an {@link InvalidParameterValueException}.
     * </ul>
     */
    protected void validateAndUpdateFirstNameIfNeeded(UpdateUserCmd updateUserCmd, UserVO user) {
        String firstName = updateUserCmd.getFirstname();
        if (firstName != null) {
            if (StringUtils.isBlank(firstName)) {
                throw new InvalidParameterValueException("Firstname cannot be empty.");
            }
            user.setFirstname(firstName);
        }
    }

    /**
     * Searches an account for the given users. Then, we validate it as follows:
     * <ul>
     *  <li>If no account is found for the given user, we throw a {@link CloudRuntimeException}. There must be something wrong in the database for this case.
     *  <li>If the account is of {@link Account.Type#PROJECT}, we throw an {@link InvalidParameterValueException}.
     *  <li>If the account is of {@link Account#ACCOUNT_ID_SYSTEM}, we throw an {@link PermissionDeniedException}.
     * </ul>
     *
     * Afterwards, we check if the logged user has access to the user being updated via {@link #checkAccess(Account, AccessType, boolean, ControlledEntity...)}
     */
    protected Account retrieveAndValidateAccount(UserVO user) {
        Account account = _accountDao.findById(user.getAccountId());
        if (account == null) {
            throw new CloudRuntimeException("Unable to find user account with ID: " + user.getAccountId());
        }
        if (account.getType() == Account.Type.PROJECT) {
            throw new InvalidParameterValueException(String.format("Unable to find user with: %s", user));
        }
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
            throw new PermissionDeniedException(String.format("user: %s is a system account; update is not allowed.", user));
        }
        checkAccess(getCurrentCallingAccount(), AccessType.OperateEntry, true, account);
        return account;
    }

    /**
     * Returns the calling account using the method {@link CallContext#getCallingAccount()}.
     * We are introducing this method to avoid using 'PowerMockRunner' in unit tests. Then, we can mock the calls to this method, which facilitates the development of test cases.
     */
    protected Account getCurrentCallingAccount() {
        return CallContext.current().getCallingAccount();
    }

    /**
     * Validates user API and Secret keys. If a new pair of keys is provided, we update them in the user POJO.
     * <ul>
     * <li>When updating the keys, it must be provided a pair (API and Secret keys); otherwise, an {@link InvalidParameterValueException} is thrown.
     * <li>If a pair of keys is provided, we validate to see if there is an user already using the provided API key. If there is someone else using, we throw an {@link InvalidParameterValueException} because two users cannot have the same API key.
     * </ul>
     */
    protected void validateAndUpdateApiAndSecretKeyIfNeeded(UpdateUserCmd updateUserCmd, UserVO user) {
        String apiKey = updateUserCmd.getApiKey();
        String secretKey = updateUserCmd.getSecretKey();

        boolean isApiKeyBlank = StringUtils.isBlank(apiKey);
        boolean isSecretKeyBlank = StringUtils.isBlank(secretKey);
        if (isApiKeyBlank ^ isSecretKeyBlank) {
            throw new InvalidParameterValueException("Please provide a userApiKey/userSecretKey pair");
        }
        if (isApiKeyBlank && isSecretKeyBlank) {
            return;
        }
        UserAccount apiKeyOwner = userAccountDao.getUserByApiKey(apiKey);
        if (apiKeyOwner != null) {
            if (apiKeyOwner.getId() != user.getId()) {
                throw new InvalidParameterValueException(String.format("The API key [%s] already exists in the system. Please provide a unique key.", apiKey));
            }
        }
        user.setApiKey(apiKey);
        user.setSecretKey(secretKey);
    }

    protected void validateAndUpdateUserApiKeyAccess(UpdateUserCmd updateUserCmd, UserVO user) {
        if (updateUserCmd.getApiKeyAccess() != null) {
            try {
                ApiConstants.ApiKeyAccess access = ApiConstants.ApiKeyAccess.valueOf(updateUserCmd.getApiKeyAccess().toUpperCase());
                user.setApiKeyAccess(access.toBoolean());
                Long callingUserId = CallContext.current().getCallingUserId();
                Account callingAccount = CallContext.current().getCallingAccount();
                ActionEventUtils.onActionEvent(callingUserId, callingAccount.getAccountId(), callingAccount.getDomainId(),
                        EventTypes.API_KEY_ACCESS_UPDATE, "Api key access was changed for the User to " + access,
                        user.getId(), ApiCommandResourceType.User.toString());
            } catch (IllegalArgumentException ex) {
                throw new InvalidParameterValueException("ApiKeyAccess value can only be Enabled/Disabled/Inherit");
            }
        }
    }

    protected void validateAndUpdateAccountApiKeyAccess(UpdateAccountCmd updateAccountCmd, AccountVO account) {
        if (updateAccountCmd.getApiKeyAccess() != null) {
            try {
                ApiConstants.ApiKeyAccess access = ApiConstants.ApiKeyAccess.valueOf(updateAccountCmd.getApiKeyAccess().toUpperCase());
                account.setApiKeyAccess(access.toBoolean());
                Long callingUserId = CallContext.current().getCallingUserId();
                Account callingAccount = CallContext.current().getCallingAccount();
                ActionEventUtils.onActionEvent(callingUserId, callingAccount.getAccountId(), callingAccount.getDomainId(),
                        EventTypes.API_KEY_ACCESS_UPDATE, "Api key access was changed for the Account to " + access,
                        account.getId(), ApiCommandResourceType.Account.toString());
            } catch (IllegalArgumentException ex) {
                throw new InvalidParameterValueException("ApiKeyAccess value can only be Enabled/Disabled/Inherit");
            }
        }
    }

    /**
     * Searches for a user with the given userId. If no user is found we throw an {@link InvalidParameterValueException}.
     */
    protected UserVO retrieveAndValidateUser(UpdateUserCmd updateUserCmd) {
        Long userId = updateUserCmd.getId();

        UserVO user = _userDao.getUser(userId);
        if (user == null) {
            throw new InvalidParameterValueException("Unable to find user with id: " + userId);
        }
        return user;
    }

    @Override
    @ActionEvent(eventType = EventTypes.EVENT_USER_DISABLE, eventDescription = "disabling User", async = true)
    public UserAccount disableUser(long userId) {
        Account caller = getCurrentCallingAccount();

        // Check if user exists in the system
        User user = _userDao.findById(userId);
        if (user == null || user.getRemoved() != null) {
            throw new InvalidParameterValueException("Unable to find active user by id " + userId);
        }

        Account account = _accountDao.findById(user.getAccountId());
        if (account == null) {
            throw new InvalidParameterValueException("unable to find user account " + user.getAccountId());
        }

        // don't allow disabling user belonging to project's account
        if (account.getType() == Account.Type.PROJECT) {
            throw new InvalidParameterValueException(String.format("Unable to find active user %s", user));
        }

        // If the user is a System user, return an error
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
            throw new InvalidParameterValueException(String.format("User: %s is a system user, disabling is not allowed", user));
        }

        checkAccess(caller, AccessType.OperateEntry, true, account);
        verifyCallerPrivilegeForUserOrAccountOperations(user);

        boolean success = doSetUserStatus(userId, State.DISABLED);
        if (success) {

            CallContext.current().putContextParameter(User.class, user.getUuid());

            // user successfully disabled
            return userAccountDao.findById(userId);
        } else {
            throw new CloudRuntimeException(String.format("Unable to disable user %s", user));
        }
    }

    @Override
    @DB
    @ActionEvent(eventType = EventTypes.EVENT_USER_ENABLE, eventDescription = "enabling User")
    public UserAccount enableUser(final long userId) {

        Account caller = getCurrentCallingAccount();

        // Check if user exists in the system
        final User user = _userDao.findById(userId);
        if (user == null || user.getRemoved() != null) {
            throw new InvalidParameterValueException("Unable to find active user by id " + userId);
        }

        Account account = _accountDao.findById(user.getAccountId());
        if (account == null) {
            throw new InvalidParameterValueException("unable to find user account " + user.getAccountId());
        }

        if (account.getType() == Account.Type.PROJECT) {
            throw new InvalidParameterValueException(String.format("Unable to find active user %s", user));
        }

        // If the user is a System user, return an error
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
            throw new InvalidParameterValueException(String.format("User: %s is a system user, enabling is not allowed", user));
        }

        checkAccess(caller, AccessType.OperateEntry, true, account);
        verifyCallerPrivilegeForUserOrAccountOperations(user);

        boolean success = Transaction.execute(new TransactionCallback<>() {
            @Override
            public Boolean doInTransaction(TransactionStatus status) {
                boolean success = doSetUserStatus(userId, State.ENABLED);

                // make sure the account is enabled too
                success = success && enableAccount(user.getAccountId());

                return success;
            }
        });

        if (success) {
            // whenever the user is successfully enabled, reset the login attempts to zero
            updateLoginAttempts(userId, 0, false);

            CallContext.current().putContextParameter(User.class, user.getUuid());

            return userAccountDao.findById(userId);
        } else {
            throw new CloudRuntimeException(String.format("Unable to enable user %s", user));
        }
    }

    @Override
    @ActionEvent(eventType = EventTypes.EVENT_USER_LOCK, eventDescription = "locking User")
    public UserAccount lockUser(long userId) {
        Account caller = getCurrentCallingAccount();

        // Check if user with id exists in the system
        User user = _userDao.findById(userId);
        if (user == null || user.getRemoved() != null) {
            throw new InvalidParameterValueException("Unable to find user by id");
        }

        Account account = _accountDao.findById(user.getAccountId());
        if (account == null) {
            throw new InvalidParameterValueException("unable to find user account " + user.getAccountId());
        }

        // don't allow to lock user of the account of type Project
        if (account.getType() == Account.Type.PROJECT) {
            throw new InvalidParameterValueException("Unable to find user by id");
        }

        // If the user is a System user, return an error. We do not allow this
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
            throw new PermissionDeniedException(String.format("user: %s is a system user, locking is not allowed", user));
        }

        checkAccess(caller, AccessType.OperateEntry, true, account);
        verifyCallerPrivilegeForUserOrAccountOperations(user);

        // make sure the account is enabled too
        // if the user is either locked already or disabled already, don't change state...only lock currently enabled
        // users
        boolean success;
        if (user.getState().equals(State.LOCKED)) {
            // already locked...no-op
            return userAccountDao.findById(userId);
        } else if (user.getState().equals(State.ENABLED)) {
            success = doSetUserStatus(user.getId(), State.LOCKED);

            boolean lockAccount = true;
            List<UserVO> allUsersByAccount = _userDao.listByAccount(user.getAccountId());
            for (UserVO oneUser : allUsersByAccount) {
                if (oneUser.getState().equals(State.ENABLED)) {
                    lockAccount = false;
                    break;
                }
            }

            if (lockAccount) {
                success = (success && lockAccount(user.getAccountId()));
            }
        } else {
            if (logger.isInfoEnabled()) {
                logger.info("Attempting to lock a non-enabled user {}, current state is {}, locking failed.", user, user.getState());
            }
            success = false;
        }

        if (success) {

            CallContext.current().putContextParameter(User.class, user.getUuid());

            return userAccountDao.findById(userId);
        } else {
            throw new CloudRuntimeException(String.format("Unable to lock user %s", user));
        }
    }

    @Override
    @ActionEvent(eventType = EventTypes.EVENT_ACCOUNT_DELETE, eventDescription = "deleting account", async = true)
    public boolean deleteUserAccount(long accountId) {

        CallContext ctx = CallContext.current();
        long callerUserId = ctx.getCallingUserId();
        Account caller = ctx.getCallingAccount();

        // If the user is a System user, return an error. We do not allow this
        AccountVO account = _accountDao.findById(accountId);

        if (caller.getId() == accountId) {
            Domain domain = _domainDao.findById(account.getDomainId());
            throw new InvalidParameterValueException(String.format("Deletion of your own account is not allowed. To delete account %s (ID: %s, Domain: %s), " +
                            "request to another user with permissions to perform the operation.",
                    account.getAccountName(), account.getUuid(), domain.getUuid()));
        }

        if (!isDeleteNeeded(account, accountId, caller)) {
            return true;
        }

        checkIfAccountManagesProjects(accountId);
        verifyCallerPrivilegeForUserOrAccountOperations(account);
        validateNoDeleteProtectedVmsForAccount(account);

        CallContext.current().putContextParameter(Account.class, account.getUuid());

        return deleteAccount(account, callerUserId, caller);
    }

    protected void checkIfAccountManagesProjects(long accountId) {
        List<Long> managedProjectIds = _projectAccountDao.listAdministratedProjectIds(accountId);
        if (!CollectionUtils.isEmpty(managedProjectIds)) {
            throw new InvalidParameterValueException(String.format(
                    "Unable to delete account [%s], because it manages the following project(s): %s. Please, remove the account from these projects or demote it to a regular project role first.",
                    accountId, managedProjectIds
            ));
        }
    }

    protected boolean isDeleteNeeded(AccountVO account, long accountId, Account caller) {
        if (account == null) {
            logger.info(String.format("The account, identified by id %d, doesn't exist", accountId ));
            return false;
        }
        if (account.getRemoved() != null) {
            logger.info("The account:{} is already removed", account);
            return false;
        }
        // don't allow removing Project account
        if (account.getType() == Account.Type.PROJECT) {
            throw new InvalidParameterValueException("The specified account does not exist in the system");
        }

        checkAccess(caller, null, true, account);

        // don't allow to delete default account (system and admin)
        if (account.isDefault()) {
            throw new InvalidParameterValueException("The account is default and can't be removed");
        }
        return true;
    }

    private void validateNoDeleteProtectedVmsForAccount(Account account) {
        long accountId = account.getId();
        List<VMInstanceVO> deleteProtectedVms = _vmDao.listDeleteProtectedVmsByAccountId(accountId);
        if (CollectionUtils.isEmpty(deleteProtectedVms)) {
            return;
        }

        if (logger.isDebugEnabled()) {
            List<String> vmUuids = deleteProtectedVms.stream().map(VMInstanceVO::getUuid).collect(Collectors.toList());
            logger.debug("Cannot delete Account {}, delete protection enabled for Instances: {}", account, vmUuids);
        }

        throw new InvalidParameterValueException(
                String.format("Cannot delete Account '%s'. One or more Instances have delete protection enabled.",
                        account.getAccountName()));
    }

    @Override
    @ActionEvent(eventType = EventTypes.EVENT_ACCOUNT_ENABLE, eventDescription = "enabling account", async = true)
    public AccountVO enableAccount(String accountName, Long domainId, Long accountId) {

        // Check if account exists
        Account account;
        if (accountId != null) {
            account = _accountDao.findById(accountId);
        } else {
            account = _accountDao.findActiveAccount(accountName, domainId);
        }

        if (account == null || account.getType() == Account.Type.PROJECT) {
            throw new InvalidParameterValueException(String.format("Unable to find account by accountId: %d OR by name: %s in domain %s", accountId, accountName, _domainMgr.getDomain(domainId)));
        }

        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
            throw new PermissionDeniedException(String.format("Account: %s is a system account, enable is not allowed", account));
        }

        // Check if user performing the action is allowed to modify this account
        Account caller = getCurrentCallingAccount();
        checkAccess(caller, AccessType.OperateEntry, true, account);
        verifyCallerPrivilegeForUserOrAccountOperations(account);

        boolean success = enableAccount(account.getId());
        if (success) {

            CallContext.current().putContextParameter(Account.class, account.getUuid());

            return _accountDao.findById(account.getId());
        } else {
            throw new CloudRuntimeException(String.format("Unable to enable account %s[%s] in domain %s", accountName, account.getUuid(), _domainMgr.getDomain(domainId)));
        }
    }

    @Override
    @ActionEvent(eventType = EventTypes.EVENT_ACCOUNT_DISABLE, eventDescription = "locking account", async = true)
    public AccountVO lockAccount(String accountName, Long domainId, Long accountId) {
        Account caller = getCurrentCallingAccount();

        Account account;
        if (accountId != null) {
            account = _accountDao.findById(accountId);
        } else {
            account = _accountDao.findActiveAccount(accountName, domainId);
        }

        if (account == null || account.getType() == Account.Type.PROJECT) {
            throw new InvalidParameterValueException("Unable to find active account by accountId: " + accountId + " OR by name: " + accountName + " in domain " + domainId);
        }

        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
            throw new PermissionDeniedException(String.format("Account: %s is a system account, lock is not allowed", account));
        }

        checkAccess(caller, AccessType.OperateEntry, true, account);
        verifyCallerPrivilegeForUserOrAccountOperations(account);

        if (lockAccount(account.getId())) {
            CallContext.current().putContextParameter(Account.class, account.getUuid());
            return _accountDao.findById(account.getId());
        } else {
            throw new CloudRuntimeException(String.format("Unable to lock account %s by accountId: %d OR by name: %s in domain %s", account, accountId, accountName, _domainMgr.getDomain(domainId)));
        }
    }

    @Override
    @ActionEvent(eventType = EventTypes.EVENT_ACCOUNT_DISABLE, eventDescription = "disabling account", async = true)
    public AccountVO disableAccount(String accountName, Long domainId, Long accountId) throws ConcurrentOperationException, ResourceUnavailableException {
        Account caller = getCurrentCallingAccount();

        Account account;
        if (accountId != null) {
            account = _accountDao.findById(accountId);
        } else {
            account = _accountDao.findActiveAccount(accountName, domainId);
        }

        if (account == null || account.getType() == Account.Type.PROJECT) {
            throw new InvalidParameterValueException(String.format("Unable to find account by accountId: %d OR by name: %s in domain %s", accountId, accountName, _domainMgr.getDomain(domainId)));
        }

        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
            throw new PermissionDeniedException(String.format("Account: %s is a system account, disable is not allowed", account));
        }

        checkAccess(caller, AccessType.OperateEntry, true, account);
        verifyCallerPrivilegeForUserOrAccountOperations(account);

        if (disableAccount(account.getId())) {
            CallContext.current().putContextParameter(Account.class, account.getUuid());
            return _accountDao.findById(account.getId());
        } else {
            throw new CloudRuntimeException(String.format("Unable to update account %s by accountId: %d OR by name: %s in domain %s", account, accountId, accountName, _domainMgr.getDomain(domainId)));
        }
    }

    @Override
    @DB
    @ActionEvent(eventType = EventTypes.EVENT_ACCOUNT_UPDATE, eventDescription = "updating account", async = true)
    public AccountVO updateAccount(UpdateAccountCmd cmd) {
        Long accountId = cmd.getId();
        Long domainId = cmd.getDomainId();
        Long roleId = cmd.getRoleId();
        String accountName = cmd.getAccountName();
        String newAccountName = cmd.getNewName();
        String networkDomain = cmd.getNetworkDomain();
        final Map<String, String> details = cmd.getDetails();

        boolean success;
        Account account;
        if (accountId != null) {
            account = _accountDao.findById(accountId);
        } else {
            account = _accountDao.findEnabledAccount(accountName, domainId);
        }

        final AccountVO acctForUpdate = _accountDao.findById(account.getId());

        // Check if account exists
        if (account == null || account.getType() == Account.Type.PROJECT) {
            logger.error("Unable to find account by accountId: {} OR by name: {} in domain {}", accountId, accountName, _domainMgr.getDomain(domainId));
            throw new InvalidParameterValueException(String.format("Unable to find account by accountId: %d OR by name: %s in domain %s", accountId, accountName, _domainMgr.getDomain(domainId)));
        }

        // Don't allow to modify system account
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
            throw new InvalidParameterValueException("Can not modify system account");
        }

        // Check if user performing the action is allowed to modify this account
        Account caller = getCurrentCallingAccount();
        checkAccess(caller, _domainMgr.getDomain(account.getDomainId()));
        verifyCallerPrivilegeForUserOrAccountOperations(account);

        validateAndUpdateAccountApiKeyAccess(cmd, acctForUpdate);

        if(newAccountName != null) {

            if (newAccountName.isEmpty()) {
                throw new InvalidParameterValueException(String.format("The new account name for " +
                        "account '%s' within domain '%s' is empty string. Account will be not renamed.",
                        account, _domainMgr.getDomain(domainId)));
            }

            // check if the new proposed account name is absent in the domain
            Account existingAccount = _accountDao.findActiveAccount(newAccountName, domainId);
            if (existingAccount != null && existingAccount.getId() != account.getId()) {
                throw new InvalidParameterValueException(String.format("The account with the " +
                                "proposed name '%s' exists in the domain '%s' with existing account %s",
                        newAccountName, _domainMgr.getDomain(domainId), existingAccount));
            }

            acctForUpdate.setAccountName(newAccountName);
        }

        if (networkDomain != null && !networkDomain.isEmpty()) {
            if (!NetUtils.verifyDomainName(networkDomain)) {
                throw new InvalidParameterValueException("Invalid network domain or format. " +
                        "Total length shouldn't exceed 190 chars. Every domain part must be between 1 and 63 " +
                        "characters long, can contain ASCII letters 'a' through 'z', the digits '0' through '9', "
                                + "and the hyphen ('-'); can't start or end with \"-\"");
            }
        }


        if (roleId != null) {
            final List<Role> roles = cmd.roleService.listRoles();
            final boolean roleNotFound = roles.stream().filter(r -> r.getId() == roleId).count() == 0;
            if (roleNotFound) {
                throw new InvalidParameterValueException(String.format("Role with ID '%s' is not " +
                        "found or not available for the account '%s' in the domain '%s'.",
                        roleId, account, _domainMgr.getDomain(domainId)));
            }

            Role role = roleService.findRole(roleId);
            validateRoleChange(account, role, caller);
            acctForUpdate.setRoleId(roleId);
            acctForUpdate.setType(role.getRoleType().getAccountType());
            checkRoleEscalation(getCurrentCallingAccount(), acctForUpdate);
        }

        if (networkDomain != null) {
            if (networkDomain.isEmpty()) {
                acctForUpdate.setNetworkDomain(null);
            } else {
                acctForUpdate.setNetworkDomain(networkDomain);
            }
        }

        final Account accountFinal = account;
        success = Transaction.execute((TransactionCallback<Boolean>) status -> {
            boolean success1 = _accountDao.update(accountFinal.getId(), acctForUpdate);

            if (details != null && success1) {
                _accountDetailsDao.update(accountFinal.getId(), details);
            }

            return success1;
        });

        if (success) {
            CallContext.current().putContextParameter(Account.class, account.getUuid());
            return _accountDao.findById(account.getId());
        } else {
            throw new CloudRuntimeException(String.format("Unable to update account %s by accountId: %d OR by name: %s in domain %d", account, accountId, accountName, domainId));
        }
    }

    @Override
    @ActionEvent(eventType = EventTypes.EVENT_USER_DELETE, eventDescription = "deleting User")
    public boolean deleteUser(DeleteUserCmd deleteUserCmd) {
        final Long id = deleteUserCmd.getId();
        User caller = CallContext.current().getCallingUser();
        UserVO user = getValidUserVO(id);
        Account account = _accountDao.findById(user.getAccountId());

        if (caller.getId() == id) {
            Domain domain = _domainDao.findById(account.getDomainId());
            throw new InvalidParameterValueException(String.format("The caller is requesting to delete itself. As a security measure, ACS will not allow this operation." +
                    " To delete user %s (ID: %s, Domain: %s), request to another user with permission to execute the operation.", user.getUsername(), user.getUuid(), domain.getUuid()));
        }

        // don't allow to delete the user from the account of type Project
        checkAccountAndAccess(user, account);
        verifyCallerPrivilegeForUserOrAccountOperations(user);
        return _userDao.remove(id);
    }

    @Override
    @ActionEvent(eventType = EventTypes.EVENT_USER_MOVE, eventDescription = "moving User to a new account")
    public boolean moveUser(MoveUserCmd cmd) {
        final Long id = cmd.getId();
        UserVO user = getValidUserVO(id);
        Account oldAccount = _accountDao.findById(user.getAccountId());
        checkAccountAndAccess(user, oldAccount);
        verifyCallerPrivilegeForUserOrAccountOperations(user);
        long domainId = oldAccount.getDomainId();

        long newAccountId = getNewAccountId(domainId, cmd.getAccountName(), cmd.getAccountId());

        return moveUser(user, newAccountId);
    }

    @Override
    public boolean moveUser(long id, Long domainId, Account newAccount) {
        UserVO user = getValidUserVO(id);
        Account oldAccount = _accountDao.findById(user.getAccountId());
        checkAccountAndAccess(user, oldAccount);
        checkIfNotMovingAcrossDomains(domainId, newAccount);
        return moveUser(user, newAccount.getId());
    }

    private boolean moveUser(UserVO user, long newAccountId) {
        if (newAccountId == user.getAccountId()) {
            // could do a not silent fail but the objective of the user is reached
            return true; // no need to create a new user object for this user
        }

        return Transaction.execute(new TransactionCallback<>() {
            @Override
            public Boolean doInTransaction(TransactionStatus status) {
                UserVO newUser = new UserVO(user);
                user.setExternalEntity(user.getUuid());
                user.setUuid(UUID.randomUUID().toString());
                user.setApiKey(null);
                user.setSecretKey(null);
                _userDao.update(user.getId(), user);
                newUser.setAccountId(newAccountId);
                boolean success = _userDao.remove(user.getId());
                UserVO persisted = _userDao.persist(newUser);
                return success && persisted.getUuid().equals(user.getExternalEntity());
            }
        });
    }

    private long getNewAccountId(long domainId, String accountName, Long accountId) {
        Account newAccount = null;
        if (StringUtils.isNotBlank(accountName)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Getting id for account by name '" + accountName + "' in domain " + domainId);
            }
            newAccount = _accountDao.findEnabledAccount(accountName, domainId);
        }
        if (newAccount == null && accountId != null) {
            newAccount = _accountDao.findById(accountId);
        }
        if (newAccount == null) {
            throw new CloudRuntimeException("no account name or account id. this should have been caught before this point");
        }

        checkIfNotMovingAcrossDomains(domainId, newAccount);
        return newAccount.getAccountId();
    }

    private void checkIfNotMovingAcrossDomains(long domainId, Account newAccount) {
        if (newAccount.getDomainId() != domainId) {
            // not in scope
            throw new InvalidParameterValueException("moving a user from an account in one domain to an account in another domain is not supported!");
        }
    }

    protected void checkAccountAndAccess(UserVO user, Account account) {
        // don't allow to delete the user from the account of type Project
        if (account.getType() == Account.Type.PROJECT) {
            throw new InvalidParameterValueException("Project users cannot be deleted or moved.");
        }

        checkAccess(getCurrentCallingAccount(), AccessType.OperateEntry, true, account);
        CallContext.current().putContextParameter(User.class, user.getUuid());
    }

    protected UserVO getValidUserVO(long id) {
        UserVO user = _userDao.findById(id);

        if (user == null || user.getRemoved() != null) {
            throw new InvalidParameterValueException("The specified user doesn't exist in the system");
        }

        // don't allow to delete default user (system and admin users)
        if (user.isDefault()) {
            throw new InvalidParameterValueException("The user is default and can't be (re)moved");
        }

        return user;
    }

    protected class AccountCleanupTask extends ManagedContextRunnable {
        @Override
        protected void runInContext() {
            try {
                GlobalLock lock = GlobalLock.getInternLock("AccountCleanup");
                if (lock == null) {
                    logger.debug("Couldn't get the global lock");
                    return;
                }

                if (!lock.lock(30)) {
                    logger.debug("Couldn't lock the db");
                    return;
                }

                try {
                    // Cleanup removed accounts
                    List<AccountVO> removedAccounts = _accountDao.findCleanupsForRemovedAccounts(null);
                    logger.info("Found " + removedAccounts.size() + " removed accounts to cleanup");
                    for (AccountVO account : removedAccounts) {
                        logger.debug("Cleaning up {}", account);
                        cleanupAccount(account, getSystemUser().getId(), getSystemAccount());
                    }

                    // cleanup disabled accounts
                    List<AccountVO> disabledAccounts = _accountDao.findCleanupsForDisabledAccounts();
                    logger.info("Found " + disabledAccounts.size() + " disabled accounts to cleanup");
                    for (AccountVO account : disabledAccounts) {
                        logger.debug("Disabling account {}", account);
                        try {
                            disableAccount(account.getId());
                        } catch (Exception e) {
                            logger.error("Skipping due to error on account {}", account, e);
                        }
                    }

                    // cleanup inactive domains
                    List<? extends Domain> inactiveDomains = _domainMgr.findInactiveDomains();
                    logger.info("Found " + inactiveDomains.size() + " inactive domains to cleanup");
                    for (Domain inactiveDomain : inactiveDomains) {
                        long domainId = inactiveDomain.getId();
                        try {
                            List<AccountVO> accountsForCleanupInDomain = _accountDao.findCleanupsForRemovedAccounts(domainId);
                            if (accountsForCleanupInDomain.isEmpty()) {
                                // release dedication if any, before deleting the domain
                                List<DedicatedResourceVO> dedicatedResources = _dedicatedDao.listByDomainId(domainId);
                                if (dedicatedResources != null && !dedicatedResources.isEmpty()) {
                                    logger.debug("Releasing dedicated resources for domain {}", inactiveDomain);
                                    for (DedicatedResourceVO dr : dedicatedResources) {
                                        if (!_dedicatedDao.remove(dr.getId())) {
                                            logger.warn("Fail to release dedicated resources for domain {}", inactiveDomain);
                                        }
                                    }
                                }
                                logger.debug("Removing inactive domain {}", inactiveDomain);
                                _domainMgr.removeDomain(domainId);
                            } else {
                                logger.debug("Can't remove inactive domain {} as it has accounts that need cleanup", inactiveDomain);
                            }
                        } catch (Exception e) {
                            logger.error("Skipping due to error on domain {}", inactiveDomain, e);
                        }
                    }

                    // cleanup inactive projects
                    List<ProjectVO> inactiveProjects = _projectDao.listByState(Project.State.Disabled);
                    logger.info("Found " + inactiveProjects.size() + " disabled projects to cleanup");
                    for (ProjectVO project : inactiveProjects) {
                        try {
                            Account projectAccount = getAccount(project.getProjectAccountId());
                            if (projectAccount == null) {
                                logger.debug("Removing inactive project {}", project);
                                _projectMgr.deleteProject(CallContext.current().getCallingAccount(), CallContext.current().getCallingUserId(), project);
                            } else {
                                logger.debug("Can't remove disabled project {} as it has non removed account {}", project, projectAccount);
                            }
                        } catch (Exception e) {
                            logger.error("Skipping due to error on project " + project, e);
                        }
                    }

                } catch (Exception e) {
                    logger.error("Exception ", e);
                } finally {
                    lock.unlock();
                }
            } catch (Exception e) {
                logger.error("Exception ", e);
            }
        }
    }

    @Override
    public Account finalizeOwner(Account caller, String accountName, Long domainId, Long projectId) {
        // don't default the owner to the system account
        if (caller.getId() == Account.ACCOUNT_ID_SYSTEM && ((accountName == null || domainId == null) && projectId == null)) {
            throw new InvalidParameterValueException("Account and domainId are needed for resource creation");
        }

        // projectId and account/domainId can't be specified together
        if ((accountName != null && domainId != null) && projectId != null) {
            throw new InvalidParameterValueException("ProjectId and account/domainId can't be specified together");
        }

        if (projectId != null) {
            Project project = _projectMgr.getProject(projectId);
            if (project == null) {
                throw new InvalidParameterValueException("Unable to find project by id=" + projectId);
            }

            if (!_projectMgr.canAccessProjectAccount(caller, project.getProjectAccountId())) {
                throw new PermissionDeniedException("Account " + caller + " is unauthorised to use project id=" + projectId);
            }

            return getAccount(project.getProjectAccountId());
        }

        if (isAdmin(caller.getId()) && accountName != null && domainId != null) {
            Domain domain = _domainMgr.getDomain(domainId);
            if (domain == null) {
                throw new InvalidParameterValueException("Unable to find the domain by id=" + domainId);
            }

            Account owner = _accountDao.findActiveAccount(accountName, domainId);
            if (owner == null) {
                throw new InvalidParameterValueException(String.format("Unable to find account %s in domain %s", accountName, domain));
            }
            checkAccess(caller, domain);

            return owner;
        } else if (!isAdmin(caller.getId()) && accountName != null && domainId != null) {
            if (!accountName.equals(caller.getAccountName()) || domainId != caller.getDomainId()) {
                throw new PermissionDeniedException("Can't create/list resources for account " + accountName + " in domain " + domainId + ", permission denied");
            } else {
                return caller;
            }
        } else {
            if (accountName != null && domainId == null) {
                throw new InvalidParameterValueException("AccountName and domainId must be specified together");
            }
            // regular user can't create/list resources for other people
            return caller;
        }
    }

    @Override
    public Account getActiveAccountByName(String accountName, Long domainId) {
        if (accountName == null || domainId == null) {
            throw new InvalidParameterValueException("Both accountName and domainId are required for finding active account in the system");
        } else {
            return _accountDao.findActiveAccount(accountName, domainId);
        }
    }

    @Override
    public UserAccount getActiveUserAccount(String username, Long domainId) {
        return userAccountDao.getUserAccount(username, domainId);
    }

    @Override
    public List<UserAccount> getActiveUserAccountByEmail(String email, Long domainId) {
        List<UserAccountVO> userAccountByEmail = userAccountDao.getUserAccountByEmail(email, domainId);
        List<UserAccount> userAccounts = userAccountByEmail.stream()
                .map(userAccountVO -> (UserAccount) userAccountVO)
                .collect(Collectors.toList());
        return userAccounts;
    }

    @Override
    public Account getActiveAccountById(long accountId) {
        return _accountDao.findById(accountId);
    }

    @Override
    public Account getAccount(long accountId) {
        return _accountDao.findByIdIncludingRemoved(accountId);
    }

    @Override
    public RoleType getRoleType(Account account) {
        if (account == null) {
            return RoleType.Unknown;
        }
        return RoleType.getByAccountType(account.getType());
    }

    @Override
    public User getActiveUser(long userId) {
        return _userDao.findById(userId);
    }

    @Override
    public User getUserIncludingRemoved(long userId) {
        return _userDao.findByIdIncludingRemoved(userId);
    }

    @Override
    public User getActiveUserByRegistrationToken(String registrationToken) {
        return _userDao.findUserByRegistrationToken(registrationToken);
    }

    @Override
    public void markUserRegistered(long userId) {
        UserVO userForUpdate = _userDao.createForUpdate();
        userForUpdate.setRegistered(true);
        _userDao.update(userId, userForUpdate);
    }

    @Override
    @DB
    public AccountVO createAccount(final String accountName, final Account.Type accountType, final Long roleId, final Long domainId, final String networkDomain, final Map<String, String> details, final String uuid) {
        // Validate domain
        Domain domain = _domainMgr.getDomain(domainId);
        if (domain == null) {
            throw new InvalidParameterValueException("The domain " + domainId + " does not exist; unable to create account");
        }

        if (domain.getState().equals(Domain.State.Inactive)) {
            throw new CloudRuntimeException("The account cannot be created as domain " + domain.getName() + " is being deleted");
        }

        if ((domainId != Domain.ROOT_DOMAIN) && (accountType == Account.Type.ADMIN)) {
            throw new InvalidParameterValueException(String.format("Invalid account type %s given for " +
                    "an account in domain %s; unable to create user of admin role type in non-ROOT domain.", accountType, domain));
        }

        // Validate account/user/domain settings
        if (_accountDao.findActiveAccount(accountName, domainId) != null) {
            throw new InvalidParameterValueException("The specified account: " + accountName + " already exists");
        }

        if (networkDomain != null) {
            if (!NetUtils.verifyDomainName(networkDomain)) {
                throw new InvalidParameterValueException(
                        "Invalid network domain. Total length shouldn't exceed 190 chars. Each domain label must be between 1 and 63 characters long, can contain ASCII letters 'a' through 'z', the digits '0' through '9', "
                                + "and the hyphen ('-'); can't start or end with \"-\"");
            }
        }


        if (accountType == Account.Type.RESOURCE_DOMAIN_ADMIN) {
            List<DataCenterVO> dc = _dcDao.findZonesByDomainId(domainId);
            if (dc.isEmpty()) {
                throw new InvalidParameterValueException(String.format("The account cannot be created as domain %s is not associated with any private Zone", domain));
            }
        }

        AccountVO newAccount = new AccountVO(accountName, domainId, networkDomain, accountType, roleId, uuid);
        verifyCallerPrivilegeForUserOrAccountOperations(newAccount);

        // Create the account
        return Transaction.execute(new TransactionCallback<>() {
            @Override
            public AccountVO doInTransaction(TransactionStatus status) {
                AccountVO account = _accountDao.persist(new AccountVO(accountName, domainId, networkDomain, accountType, roleId, uuid));

                if (account == null) {
                    throw new CloudRuntimeException(String.format("Failed to create account name %s in domain id=%s", accountName, _domainMgr.getDomain(domainId)));
                }

                long accountId = account.getId();

                if (details != null) {
                    _accountDetailsDao.persist(accountId, details);
                }

                // Create resource count records for the account
                _resourceCountDao.createResourceCounts(accountId, ResourceLimit.ResourceOwnerType.Account);

                // Create default security group
                _networkGroupMgr.createDefaultSecurityGroup(accountId);

                return account;
            }
        });
    }

    protected UserVO createUser(long accountId, String userName, String password, String firstName, String lastName, String email, String timezone, String userUUID, User.Source source) {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating user: " + userName + ", accountId: " + accountId + " timezone:" + timezone);
        }

        Account callingAccount = getCurrentCallingAccount();
        if (callingAccount.getId() != Account.ACCOUNT_ID_SYSTEM) {
            passwordPolicy.verifyIfPasswordCompliesWithPasswordPolicies(password, userName, getAccount(accountId).getDomainId());
        }

        String encodedPassword = null;
        for (UserAuthenticator authenticator : _userPasswordEncoders) {
            encodedPassword = authenticator.encode(password);
            if (encodedPassword != null) {
                break;
            }
        }
        if (encodedPassword == null) {
            throw new CloudRuntimeException("Failed to encode password");
        }

        if (userUUID == null) {
            userUUID = UUID.randomUUID().toString();
        }

        UserVO user = _userDao.persist(new UserVO(accountId, userName, encodedPassword, firstName, lastName, email, timezone, userUUID, source));
        CallContext.current().putContextParameter(User.class, user.getUuid());
        return user;
    }

    @Override
    public void logoutUser(long userId) {
        UserAccount userAcct = userAccountDao.findById(userId);
        if (userAcct != null) {
            ActionEventUtils.onActionEvent(userId, userAcct.getAccountId(), userAcct.getDomainId(), EventTypes.EVENT_USER_LOGOUT, "user has logged out", userId, ApiCommandResourceType.User.toString());
        } // else log some kind of error event? This likely means the user doesn't exist, or has been deleted...
    }

    @Override
    public UserAccount authenticateUser(final String username, final String password, final Long domainId, final InetAddress loginIpAddress, final Map<String, Object[]> requestParameters) {
        long authStartTimeInMs = System.currentTimeMillis();
        UserAccount user = null;
        final String[] oAuthProviderArray = (String[])requestParameters.get(ApiConstants.PROVIDER);
        final String[] secretCodeArray = (String[])requestParameters.get(ApiConstants.SECRET_CODE);
        String oauthProvider = ((oAuthProviderArray == null) ? null : oAuthProviderArray[0]);
        String secretCode = ((secretCodeArray == null) ? null : secretCodeArray[0]);

        if ((password != null && !password.isEmpty()) || (oauthProvider != null && secretCode != null)) {
            user = getUserAccount(username, password, domainId, requestParameters);
        } else {
            user = getUserAccountForSSO(username, domainId, requestParameters);
        }

        if (user != null) {
            // don't allow to authenticate system user
            if (user.getId() == User.UID_SYSTEM) {
                logger.error("Failed to authenticate user: " + username + " in domain " + domainId);
                return null;
            }
            // don't allow baremetal system user
            if (BaremetalUtils.BAREMETAL_SYSTEM_ACCOUNT_NAME.equals(user.getUsername())) {
                logger.error("Won't authenticate user: " + username + " in domain " + domainId);
                return null;
            }

            // We authenticated successfully by now, let's check if we are allowed to login from the ip address the reqest comes from
            final Account account = getAccount(user.getAccountId());
            final DomainVO domain = (DomainVO) _domainMgr.getDomain(account.getDomainId());

            // Get the CIDRs from where this account is allowed to make calls
            final String accessAllowedCidrs = ApiServiceConfiguration.ApiAllowedSourceCidrList.valueIn(account.getId()).replaceAll("\\s", "");
            final Boolean ApiSourceCidrChecksEnabled = ApiServiceConfiguration.ApiSourceCidrChecksEnabled.value();

            if (ApiSourceCidrChecksEnabled) {
                logger.debug("CIDRs from which account '{}' is allowed to perform API calls: {}", account.toString(), accessAllowedCidrs);

                // Block when is not in the list of allowed IPs
                if (!NetUtils.isIpInCidrList(loginIpAddress, accessAllowedCidrs.split(","))) {
                    logger.warn("Request by account '{}' was denied since {} does not match {}", account.toString(), loginIpAddress.toString().replace("/", ""), accessAllowedCidrs);
                    throw new CloudAuthenticationException("Failed to authenticate user '" + username + "' in domain '" + domain.getPath() + "' from ip "
                            + loginIpAddress.toString().replace("/", "") + "; please provide valid credentials");
                }
            }

            ActionEventUtils.onActionEvent(user.getId(), user.getAccountId(), user.getDomainId(), EventTypes.EVENT_USER_LOGIN, "user has logged in from IP Address " + loginIpAddress, user.getId(), ApiCommandResourceType.User.toString());

            validUserLastAuthTimeDurationInMs = System.currentTimeMillis() - authStartTimeInMs;
            // Here all is fine!
            if (logger.isDebugEnabled()) {
                logger.debug(String.format("User: %s in domain %d has successfully logged in, auth time duration - %d ms", username, domainId, validUserLastAuthTimeDurationInMs));
            }

            return user;
        } else {
            if (logger.isDebugEnabled()) {
                logger.debug("User: " + username + " in domain " + domainId + " has failed to log in");
            }

            long waitTimeDurationInMs;
            long invalidUserAuthTimeDurationInMs = System.currentTimeMillis() - authStartTimeInMs;
            if (validUserLastAuthTimeDurationInMs > 0) {
                waitTimeDurationInMs = validUserLastAuthTimeDurationInMs - invalidUserAuthTimeDurationInMs;
            } else {
                waitTimeDurationInMs = DEFAULT_USER_AUTH_TIME_DURATION_MS - invalidUserAuthTimeDurationInMs;
            }

            if (waitTimeDurationInMs > 0) {
                try {
                    Thread.sleep(waitTimeDurationInMs);
                } catch (final InterruptedException e) {
                    // ignored
                }
            }

            return null;
        }
    }

    private UserAccount getUserAccount(String username, String password, Long domainId, Map<String, Object[]> requestParameters) {
        if (logger.isDebugEnabled()) {
            logger.debug("Attempting to log in user: " + username + " in domain " + domainId);
        }
        UserAccount userAccount = userAccountDao.getUserAccount(username, domainId);

        boolean authenticated = false;
        HashSet<ActionOnFailedAuthentication> actionsOnFailedAuthenticaion = new HashSet<>();
        User.Source userSource = userAccount != null ? userAccount.getSource() : User.Source.UNKNOWN;
        for (UserAuthenticator authenticator : _userAuthenticators) {
            final String[] secretCodeArray = (String[])requestParameters.get(ApiConstants.SECRET_CODE);
            String secretCode = ((secretCodeArray == null) ? null : secretCodeArray[0]);
            if (userSource != User.Source.UNKNOWN && secretCode == null) {
                if (!authenticator.getName().equalsIgnoreCase(userSource.name())) {
                    continue;
                }
            }
            if ((secretCode != null && !authenticator.getName().equals(OAUTH2_PROVIDER_NAME))
                    || (secretCode == null && authenticator.getName().equals(OAUTH2_PROVIDER_NAME))) {
                continue;
            }
            Pair<Boolean, ActionOnFailedAuthentication> result = authenticator.authenticate(username, password, domainId, requestParameters);
            if (result.first()) {
                authenticated = true;
                break;
            } else if (result.second() != null) {
                actionsOnFailedAuthenticaion.add(result.second());
            }
        }

        boolean updateIncorrectLoginCount = actionsOnFailedAuthenticaion.contains(ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT);

        if (authenticated) {
            Domain domain = _domainMgr.getDomain(domainId);
            userAccount = userAccountDao.getUserAccount(username, domainId);

            if (!userAccount.getState().equalsIgnoreCase(Account.State.ENABLED.toString()) || !userAccount.getAccountState().equalsIgnoreCase(Account.State.ENABLED.toString())) {
                if (logger.isInfoEnabled()) {
                    logger.info("User {} in domain {} is disabled/locked (or account is disabled/locked)", userAccount, domain);
                }
                throw new CloudAuthenticationException(String.format("User %s (or their account) in domain %s is disabled/locked. Please contact the administrator.", userAccount, domain));
            }
            // Whenever the user is able to log in successfully, reset the login attempts to zero
            if (!isInternalAccount(userAccount.getId())) {
                updateLoginAttempts(userAccount.getId(), 0, false);
            }

            return userAccount;
        } else {
            if (logger.isDebugEnabled()) {
                logger.debug("Unable to authenticate user with username " + username + " in domain " + domainId);
            }

            if (userAccount == null) {
                logger.warn("Unable to find an user with username " + username + " in domain " + domainId);
                return null;
            }

            if (userAccount.getState().equalsIgnoreCase(Account.State.ENABLED.toString())) {
                if (!isInternalAccount(userAccount.getId())) {
                    // Internal accounts are not disabled
                    updateLoginAttemptsWhenIncorrectLoginAttemptsEnabled(userAccount, updateIncorrectLoginCount, _allowedLoginAttempts);
                }
            } else {
                logger.info("User " + userAccount.getUsername() + " is disabled/locked");
            }
            return null;
        }
    }

    private UserAccount getUserAccountForSSO(String username, Long domainId, Map<String, Object[]> requestParameters) {
        String key = _configDao.getValue("security.singlesignon.key");
        if (key == null) {
            // the SSO key is gone, don't authenticate
            return null;
        }

        String singleSignOnTolerance = _configDao.getValue("security.singlesignon.tolerance.millis");
        if (singleSignOnTolerance == null) {
            // the SSO tolerance is gone (how much time before/after system time we'll allow the login request to be
            // valid),
            // don't authenticate
            return null;
        }

        UserAccount user = null;
        long tolerance = Long.parseLong(singleSignOnTolerance);
        String signature = null;
        long timestamp = 0L;
        String unsignedRequest;
        StringBuffer unsignedRequestBuffer = new StringBuffer();

        // - build a request string with sorted params, make sure it's all lowercase
        // - sign the request, verify the signature is the same

        // put the name in a list that we'll sort later
        List<String> parameterNames = new ArrayList<>(requestParameters.keySet());

        Collections.sort(parameterNames);

        try {
            for (String paramName : parameterNames) {
                // parameters come as name/value pairs in the form String/String[]
                String paramValue = ((String[])requestParameters.get(paramName))[0];

                if ("signature".equalsIgnoreCase(paramName)) {
                    signature = paramValue;
                } else {
                    if ("timestamp".equalsIgnoreCase(paramName)) {
                        String timestampStr = paramValue;
                        try {
                            // If the timestamp is in a valid range according to our tolerance, verify the request
                            // signature, otherwise return null to indicate authentication failure
                            timestamp = Long.parseLong(timestampStr);
                            long currentTime = System.currentTimeMillis();
                            if (Math.abs(currentTime - timestamp) > tolerance) {
                                logger.debug("Expired timestamp passed in to login, current time = {}, timestamp = {}", currentTime, timestamp);
                                return null;
                            }
                        } catch (NumberFormatException nfe) {
                            logger.debug("Invalid timestamp passed in to login: {}", timestampStr);
                            return null;
                        }
                    }

                    if (unsignedRequestBuffer.length() != 0) {
                        unsignedRequestBuffer.append("&");
                    }
                    unsignedRequestBuffer.append(paramName).append("=").append(URLEncoder.encode(paramValue, com.cloud.utils.StringUtils.getPreferredCharset()));
                }
            }

            if ((signature == null) || (timestamp == 0L)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Missing parameters in login request, signature = " + signature + ", timestamp = " + timestamp);
                }
                return null;
            }

            unsignedRequest = unsignedRequestBuffer.toString().toLowerCase().replaceAll("\\+", "%20");

            Mac mac = Mac.getInstance("HmacSHA1");
            SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacSHA1");
            mac.init(keySpec);
            mac.update(unsignedRequest.getBytes());
            byte[] encryptedBytes = mac.doFinal();
            String computedSignature = new String(Base64.encodeBase64(encryptedBytes));
            boolean equalSig = ConstantTimeComparator.compareStrings(signature, computedSignature);
            if (!equalSig) {
                logger.info("User signature: " + signature + " is not equaled to computed signature: " + computedSignature);
            } else {
                user = userAccountDao.getUserAccount(username, domainId);
            }
        } catch (Exception ex) {
            logger.error("Exception authenticating user", ex);
            return null;
        }

        return user;
    }

    protected void updateLoginAttemptsWhenIncorrectLoginAttemptsEnabled(UserAccount account, boolean updateIncorrectLoginCount,
                                                                      int allowedLoginAttempts) {
        int attemptsMade = account.getLoginAttempts() + 1;
        if (allowedLoginAttempts <= 0 || !updateIncorrectLoginCount) {
            return;
        }
        if (attemptsMade < allowedLoginAttempts) {
            updateLoginAttempts(account.getId(), attemptsMade, false);
            logger.warn("Login attempt failed. You have " +
                    (allowedLoginAttempts - attemptsMade) + " attempt(s) remaining");
        } else {
            updateLoginAttempts(account.getId(), allowedLoginAttempts, true);
            logger.warn("User {} has been disabled due to multiple failed login attempts. Please contact admin.", account);
        }
    }

    @Override
    public Pair<User, Account> findUserByApiKey(String apiKey) {
        UserAccount userAccount = userAccountDao.getUserByApiKey(apiKey);
        if (userAccount != null) {
            User user = _userDao.getUser(userAccount.getId());
            Account account = _accountDao.findById(userAccount.getAccountId());
            return new Pair<>(user, account);
        } else {
            return null;
        }
    }

    @Override
    public Pair<Boolean, Map<String, String>> getKeys(GetUserKeysCmd cmd) {
        final long userId = cmd.getID();
        return getKeys(userId);
    }

    @Override
    public Pair<Boolean, Map<String, String>> getKeys(Long userId) {
        User user = getActiveUser(userId);
        if (user == null) {
            throw new InvalidParameterValueException("Unable to find user by id");
        }
        final Account account = getAccount(getUserAccountById(userId).getAccountId()); //Extracting the Account from the userID of the requested user.
        User caller = CallContext.current().getCallingUser();
        checkAccess(caller, account);
        verifyCallerPrivilegeForUserOrAccountOperations(user);

        Map<String, String> keys = new HashMap<>();
        keys.put("apikey", user.getApiKey());
        keys.put("secretkey", user.getSecretKey());

        Boolean apiKeyAccess = user.getApiKeyAccess();
        if (apiKeyAccess == null) {
            apiKeyAccess = account.getApiKeyAccess();
            if (apiKeyAccess == null) {
                apiKeyAccess = AccountManagerImpl.apiKeyAccess.valueIn(account.getDomainId());
            }
        }

        return new Pair<>(apiKeyAccess, keys);
    }

    protected void preventRootDomainAdminAccessToRootAdminKeys(User caller, ControlledEntity account) {
        if (isDomainAdminForRootDomain(caller) && isRootAdmin(account.getAccountId())) {
            String msg = String.format("Caller Username %s does not have access to root admin keys", caller.getUsername());
            logger.error(msg);
            throw new PermissionDeniedException(msg);
        }
    }

    protected boolean isDomainAdminForRootDomain(User callingUser) {
        AccountVO caller = _accountDao.findById(callingUser.getAccountId());
        return caller.getType() == Account.Type.DOMAIN_ADMIN && caller.getDomainId() == Domain.ROOT_DOMAIN;
    }

    @Override
    public List<UserTwoFactorAuthenticator> listUserTwoFactorAuthenticationProviders() {
        return userTwoFactorAuthenticationProviders;
    }

    @Override
    public UserTwoFactorAuthenticator getUserTwoFactorAuthenticationProvider(Long domainId) {
        final String name = userTwoFactorAuthenticationDefaultProvider.valueIn(domainId);
        return getUserTwoFactorAuthenticationProvider(name);
    }

    public UserTwoFactorAuthenticator getUserTwoFactorAuthenticationProvider(final String name) {
        if (StringUtils.isEmpty(name)) {
            throw new CloudRuntimeException("Two factor authentication provider name is empty");
        }
        if (!userTwoFactorAuthenticationProvidersMap.containsKey(name.toLowerCase())) {
            throw new CloudRuntimeException(String.format("Failed to find two factor authentication provider by the name: %s.", name));
        }
        return userTwoFactorAuthenticationProvidersMap.get(name.toLowerCase());
    }

    @Override
    @DB
    @ActionEvent(eventType = EventTypes.EVENT_REGISTER_FOR_SECRET_API_KEY, eventDescription = "register for the developer API keys")
    public String[] createApiKeyAndSecretKey(RegisterUserKeyCmd cmd) {
        Account caller = getCurrentCallingAccount();
        final Long userId = cmd.getId();

        User user = getUserIncludingRemoved(userId);
        if (user == null) {
            throw new InvalidParameterValueException("unable to find user by id");
        }

        Account account = _accountDao.findById(user.getAccountId());
        checkAccess(caller, null, true, account);
        verifyCallerPrivilegeForUserOrAccountOperations(user);

        // don't allow updating system user
        if (user.getId() == User.UID_SYSTEM) {
            throw new PermissionDeniedException(String.format("user: %s is system account, update is not allowed", user));
        }
        // don't allow baremetal system user
        if (BaremetalUtils.BAREMETAL_SYSTEM_ACCOUNT_NAME.equals(user.getUsername())) {
            throw new PermissionDeniedException(String.format("user: %s is system account, update is not allowed", user));
        }

        // generate both an api key and a secret key, update the user table with the keys, return the keys to the user
        final String[] keys = new String[2];
        Transaction.execute(new TransactionCallbackNoReturn() {
            @Override
            public void doInTransactionWithoutResult(TransactionStatus status) {
                keys[0] = createUserApiKey(userId);
                keys[1] = createUserSecretKey(userId);
            }
        });

        return keys;
    }

    @Override
    @DB
    @ActionEvent(eventType = EventTypes.EVENT_REGISTER_FOR_SECRET_API_KEY, eventDescription = "register for the developer API keys")
    public String[] createApiKeyAndSecretKey(final long userId) {
        Account caller = getCurrentCallingAccount();
        User user = getUserIncludingRemoved(userId);
        if (user == null) {
            throw new InvalidParameterValueException("Unable to find user by id");
        }
        Account account = _accountDao.findById(user.getAccountId());
        checkAccess(caller, null, true, account);
        final String[] keys = new String[2];
        Transaction.execute(new TransactionCallbackNoReturn() {
            @Override
            public void doInTransactionWithoutResult(TransactionStatus status) {
                keys[0] = AccountManagerImpl.this.createUserApiKey(userId);
                keys[1] = AccountManagerImpl.this.createUserSecretKey(userId);
            }
        });
        return keys;
    }

    private String createUserApiKey(long userId) {
        try {
            UserVO updatedUser = _userDao.createForUpdate();

            String encodedKey;
            UserAccount userAcct;
            int retryLimit = 10;
            do {
                // FIXME: what algorithm should we use for API keys?
                KeyGenerator generator = KeyGenerator.getInstance("HmacSHA1");
                SecretKey key = generator.generateKey();
                encodedKey = Base64.encodeBase64URLSafeString(key.getEncoded());
                userAcct = userAccountDao.getUserByApiKey(encodedKey);
                retryLimit--;
            } while ((userAcct != null) && (retryLimit >= 0));

            if (userAcct != null) {
                return null;
            }
            updatedUser.setApiKey(encodedKey);
            _userDao.update(userId, updatedUser);
            return encodedKey;
        } catch (NoSuchAlgorithmException ex) {
            logger.error("error generating secret key for user {}", userAccountDao.findById(userId), ex);
        }
        return null;
    }

    private String createUserSecretKey(long userId) {
        try {
            UserVO updatedUser = _userDao.createForUpdate();
            String encodedKey;
            int retryLimit = 10;
            UserVO userBySecretKey;
            do {
                KeyGenerator generator = KeyGenerator.getInstance("HmacSHA1");
                SecretKey key = generator.generateKey();
                encodedKey = Base64.encodeBase64URLSafeString(key.getEncoded());
                userBySecretKey = _userDao.findUserBySecretKey(encodedKey);
                retryLimit--;
            } while ((userBySecretKey != null) && (retryLimit >= 0));

            if (userBySecretKey != null) {
                return null;
            }

            updatedUser.setSecretKey(encodedKey);
            _userDao.update(userId, updatedUser);
            return encodedKey;
        } catch (NoSuchAlgorithmException ex) {
            logger.error("error generating secret key for user {}", userAccountDao.findById(userId), ex);
        }
        return null;
    }

    @Override
    public void buildACLSearchBuilder(SearchBuilder<? extends ControlledEntity> sb, Long domainId, boolean isRecursive, List<Long> permittedAccounts,
            ListProjectResourcesCriteria listProjectResourcesCriteria) {

        if (sb.entity() instanceof IPAddressVO) {
            sb.and("accountIdIN", ((IPAddressVO)sb.entity()).getAllocatedToAccountId(), SearchCriteria.Op.IN);
            sb.and("domainId", ((IPAddressVO)sb.entity()).getAllocatedInDomainId(), SearchCriteria.Op.EQ);
        } else if (sb.entity() instanceof ProjectInvitationVO) {
            sb.and("accountIdIN", ((ProjectInvitationVO)sb.entity()).getForAccountId(), SearchCriteria.Op.IN);
            sb.and("domainId", ((ProjectInvitationVO)sb.entity()).getInDomainId(), SearchCriteria.Op.EQ);
        } else {
            sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN);
            sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        }

        if (((permittedAccounts.isEmpty()) && (domainId != null) && isRecursive)) {
            // if accountId isn't specified, we can do a domain match for the admin case if isRecursive is true
            SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder();
            domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);

            if (sb.entity() instanceof IPAddressVO) {
                sb.join("domainSearch", domainSearch, ((IPAddressVO)sb.entity()).getAllocatedInDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER);
            } else if (sb.entity() instanceof ProjectInvitationVO) {
                sb.join("domainSearch", domainSearch, ((ProjectInvitationVO)sb.entity()).getInDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER);
            } else {
                sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER);
            }

        }
        if (listProjectResourcesCriteria != null) {
            SearchBuilder<AccountVO> accountSearch = _accountDao.createSearchBuilder();
            if (listProjectResourcesCriteria == Project.ListProjectResourcesCriteria.ListProjectResourcesOnly) {
                accountSearch.and("type", accountSearch.entity().getType(), SearchCriteria.Op.EQ);
            } else if (listProjectResourcesCriteria == Project.ListProjectResourcesCriteria.SkipProjectResources) {
                accountSearch.and("type", accountSearch.entity().getType(), SearchCriteria.Op.NEQ);
            }

            if (sb.entity() instanceof IPAddressVO) {
                sb.join("accountSearch", accountSearch, ((IPAddressVO)sb.entity()).getAllocatedToAccountId(), accountSearch.entity().getId(), JoinBuilder.JoinType.INNER);
            } else if (sb.entity() instanceof ProjectInvitationVO) {
                sb.join("accountSearch", accountSearch, ((ProjectInvitationVO)sb.entity()).getForAccountId(), accountSearch.entity().getId(), JoinBuilder.JoinType.INNER);
            } else {
                sb.join("accountSearch", accountSearch, sb.entity().getAccountId(), accountSearch.entity().getId(), JoinBuilder.JoinType.INNER);
            }
        }
    }

    @Override
    public void buildACLSearchCriteria(SearchCriteria<? extends ControlledEntity> sc, Long domainId, boolean isRecursive, List<Long> permittedAccounts,
            ListProjectResourcesCriteria listProjectResourcesCriteria) {

        if (listProjectResourcesCriteria != null) {
            sc.setJoinParameters("accountSearch", "type", Account.Type.PROJECT);
        }

        if (!permittedAccounts.isEmpty()) {
            sc.setParameters("accountIdIN", permittedAccounts.toArray());
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            if (isRecursive) {
                sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            } else {
                sc.setParameters("domainId", domainId);
            }
        }
    }

    //TODO: deprecate this to use the new buildACLSearchParameters with permittedDomains, permittedAccounts, and permittedResources as return
    @Override
    public void buildACLSearchParameters(Account caller, Long id, String accountName, Long projectId, List<Long> permittedAccounts,
            Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject, boolean listAll, boolean forProjectInvitation) {
        Long domainId = domainIdRecursiveListProject.first();
        if (domainId != null) {
            Domain domain = _domainDao.findById(domainId);
            if (domain == null) {
                throw new InvalidParameterValueException("Unable to find domain by id " + domainId);
            }
            // check permissions
            checkAccess(caller, domain);
        }

        if (accountName != null) {
            if (projectId != null) {
                throw new InvalidParameterValueException("Account and projectId can't be specified together");
            }

            Account userAccount;
            Domain domain;
            if (domainId != null) {
                userAccount = _accountDao.findActiveAccount(accountName, domainId);
                domain = _domainDao.findById(domainId);
            } else {
                userAccount = _accountDao.findActiveAccount(accountName, caller.getDomainId());
                domain = _domainDao.findById(caller.getDomainId());
            }

            if (userAccount != null) {
                checkAccess(caller, null, false, userAccount);
                // check permissions
                permittedAccounts.add(userAccount.getId());
            } else {
                throw new InvalidParameterValueException("could not find account " + accountName + " in domain " + domain);
            }
        }

        // set project information
        if (projectId != null) {
            if (!forProjectInvitation) {
                if (projectId == -1L) {
                    domainIdRecursiveListProject.third(Project.ListProjectResourcesCriteria.ListProjectResourcesOnly);
                    if (caller.getType() != Account.Type.ADMIN) {
                        permittedAccounts.addAll(_projectMgr.listPermittedProjectAccounts(caller.getId()));
                        // permittedAccounts can be empty when the caller is not a part of any project (a domain account)
                        if (permittedAccounts.isEmpty() || listAll) {
                            permittedAccounts.add(caller.getId());
                        }
                    }
                    if (listAll) {
                        domainIdRecursiveListProject.third(ListProjectResourcesCriteria.ListAllIncludingProjectResources);
                    }
                } else {
                    Project project = _projectMgr.getProject(projectId);
                    if (project == null) {
                        throw new InvalidParameterValueException("Unable to find project by id " + projectId);
                    }
                    if (!_projectMgr.canAccessProjectAccount(caller, project.getProjectAccountId())) {
                        throw new PermissionDeniedException("Account " + caller + " can't access project id=" + projectId);
                    }
                    permittedAccounts.add(project.getProjectAccountId());
                }
            }
        } else {
            if (id == null) {
                domainIdRecursiveListProject.third(Project.ListProjectResourcesCriteria.SkipProjectResources);
            }
            if (permittedAccounts.isEmpty() && domainId == null) {
                if (caller.getType() == Account.Type.NORMAL) {
                    permittedAccounts.add(caller.getId());
                } else if (!listAll) {
                    if (id == null) {
                        permittedAccounts.add(caller.getId());
                    } else if (caller.getType() != Account.Type.ADMIN) {
                        domainIdRecursiveListProject.first(caller.getDomainId());
                        domainIdRecursiveListProject.second(true);
                    }
                } else if (domainId == null) {
                    if (caller.getType() == Account.Type.DOMAIN_ADMIN) {
                        domainIdRecursiveListProject.first(caller.getDomainId());
                        domainIdRecursiveListProject.second(true);
                    }
                }
            } else if (domainId != null) {
                if (caller.getType() == Account.Type.NORMAL) {
                    permittedAccounts.add(caller.getId());
                }
            }

        }

    }

    @Override
    public void buildACLViewSearchBuilder(SearchBuilder<? extends ControlledViewEntity> sb, Long domainId, boolean isRecursive, List<Long> permittedAccounts,
            ListProjectResourcesCriteria listProjectResourcesCriteria) {

        sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);

        if (((permittedAccounts.isEmpty()) && (domainId != null) && isRecursive)) {
            // if accountId isn't specified, we can do a domain match for the
            // admin case if isRecursive is true
            sb.and("domainPath", sb.entity().getDomainPath(), SearchCriteria.Op.LIKE);
        }

        if (listProjectResourcesCriteria != null) {
            if (listProjectResourcesCriteria == Project.ListProjectResourcesCriteria.ListProjectResourcesOnly) {
                sb.and("accountType", sb.entity().getAccountType(), SearchCriteria.Op.EQ);
            } else if (listProjectResourcesCriteria == Project.ListProjectResourcesCriteria.SkipProjectResources) {
                sb.and("accountType", sb.entity().getAccountType(), SearchCriteria.Op.NEQ);
            }
        }

    }

    @Override
    public void buildACLViewSearchCriteria(SearchCriteria<? extends ControlledViewEntity> sc, Long domainId, boolean isRecursive, List<Long> permittedAccounts,
            ListProjectResourcesCriteria listProjectResourcesCriteria) {
        if (listProjectResourcesCriteria != null) {
            sc.setParameters("accountType", Account.Type.PROJECT);
        }

        if (!permittedAccounts.isEmpty()) {
            sc.setParameters("accountIdIN", permittedAccounts.toArray());
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            if (isRecursive) {
                sc.setParameters("domainPath", domain.getPath() + "%");
            } else {
                sc.setParameters("domainId", domainId);
            }
        }

    }

    @Override
    public UserAccount getUserByApiKey(String apiKey) {
        return userAccountDao.getUserByApiKey(apiKey);
    }

    @Override
    public List<String> listAclGroupsByAccount(Long accountId) {
        if (CollectionUtils.isEmpty(_querySelectors)) {
            return new ArrayList<>();
        }

        QuerySelector qs = _querySelectors.get(0);
        return qs.listAclGroupsByAccount(accountId);
    }

    @Override
    public Long finalyzeAccountId(final String accountName, final Long domainId, final Long projectId, final boolean enabledOnly) {
        if (accountName != null) {
            if (domainId == null) {
                throw new InvalidParameterValueException("Account must be specified with domainId parameter");
            }

            final Domain domain = _domainMgr.getDomain(domainId);
            if (domain == null) {
                throw new InvalidParameterValueException("Unable to find domain by id");
            }

            final Account account = getActiveAccountByName(accountName, domainId);
            if (account != null && account.getType() != Account.Type.PROJECT) {
                if (!enabledOnly || account.getState() == Account.State.ENABLED) {
                    return account.getId();
                } else {
                    throw new PermissionDeniedException(String.format("Can't add resources to the account %s in state=%s as it's no longer active", account, account.getState()));
                }
            } else {
                // idList is not used anywhere, so removed it now
                // List<IdentityProxy> idList = new ArrayList<IdentityProxy>();
                // idList.add(new IdentityProxy("domain", domainId, "domainId"));
                throw new InvalidParameterValueException("Unable to find account by name " + accountName + " in domain with specified id");
            }
        }

        if (projectId != null) {
            final Project project = _projectMgr.getProject(projectId);
            if (project != null) {
                if (!enabledOnly || project.getState() == Project.State.Active) {
                    return project.getProjectAccountId();
                } else {
                    final PermissionDeniedException ex = new PermissionDeniedException(
                            "Can't add resources to the project with specified projectId in state=" + project.getState() + " as it's no longer active");
                    ex.addProxyObject(project.getUuid(), "projectId");
                    throw ex;
                }
            } else {
                throw new InvalidParameterValueException("Unable to find project by id");
            }
        }
        return null;
    }

    @Override
    public UserAccount getUserAccountById(Long userId) {
        UserAccount userAccount = userAccountDao.findById(userId);
        Map<String, String> details = _userDetailsDao.listDetailsKeyPairs(userId);
        userAccount.setDetails(details);

        return userAccount;
    }

    @Override
    public void checkAccess(Account account, ServiceOffering so, DataCenter zone) throws PermissionDeniedException {
        for (SecurityChecker checker : _securityCheckers) {
            if (checker.checkAccess(account, so, zone)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Access granted to " + account + " to " + so + " by " + checker.getName());
                }
                return;
            }
        }

        assert false : "How can all of the security checkers pass on checking this caller?";
        throw new PermissionDeniedException("There's no way to confirm " + account + " has access to " + so);
    }

    @Override
    public void checkAccess(Account account, DiskOffering dof, DataCenter zone) throws PermissionDeniedException {
        for (SecurityChecker checker : _securityCheckers) {
            if (checker.checkAccess(account, dof, zone)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Access granted to " + account + " to " + dof + " by " + checker.getName());
                }
                return;
            }
        }

        assert false : "How can all of the security checkers pass on checking this caller?";
        throw new PermissionDeniedException("There's no way to confirm " + account + " has access to " + dof);
    }

    @Override
    public void checkAccess(Account account, NetworkOffering nof, DataCenter zone) throws PermissionDeniedException {
        for (SecurityChecker checker : _securityCheckers) {
            if (checker.checkAccess(account, nof, zone)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Access granted to " + account + " to " + nof + " by " + checker.getName());
                }
                return;
            }
        }

        assert false : "How can all of the security checkers pass on checking this caller?";
        throw new PermissionDeniedException("There's no way to confirm " + account + " has access to " + nof);
    }

    @Override
    public void checkAccess(Account account, VpcOffering vof, DataCenter zone) throws PermissionDeniedException {
        for (SecurityChecker checker : _securityCheckers) {
            if (checker.checkAccess(account, vof, zone)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Access granted to " + account + " to " + vof + " by " + checker.getName());
                }
                return;
            }
        }

        assert false : "How can all of the security checkers pass on checking this caller?";
        throw new PermissionDeniedException("There's no way to confirm " + account + " has access to " + vof);
    }

    @Override
    public void checkAccess(User user, ControlledEntity entity) throws PermissionDeniedException {
        for (SecurityChecker checker : _securityCheckers) {
            if (checker.checkAccess(user, entity)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Access granted to " + user + "to " + entity + "by " + checker.getName());
                }
                return;
            }
        }
        throw new PermissionDeniedException("There's no way to confirm " + user + " has access to " + entity);
    }

    @Override
    public String getConfigComponentName() {
        return AccountManager.class.getSimpleName();
    }

    @Override
    public ConfigKey<?>[] getConfigKeys() {
        return new ConfigKey<?>[] {UseSecretKeyInResponse, enableUserTwoFactorAuthentication,
                userTwoFactorAuthenticationDefaultProvider, mandateUserTwoFactorAuthentication, userTwoFactorAuthenticationIssuer, apiKeyAccess,
                userAllowMultipleAccounts, listOfRoleTypesAllowedForOperationsOfSameRoleType, allowOperationsOnUsersInSameAccount};
    }

    public List<UserTwoFactorAuthenticator> getUserTwoFactorAuthenticationProviders() {
        return userTwoFactorAuthenticationProviders;
    }

    public void setUserTwoFactorAuthenticationProviders(final List<UserTwoFactorAuthenticator> userTwoFactorAuthenticationProviders) {
        this.userTwoFactorAuthenticationProviders = userTwoFactorAuthenticationProviders;
    }

    protected void initializeUserTwoFactorAuthenticationProvidersMap() {
        if (userTwoFactorAuthenticationProviders != null) {
            for (final UserTwoFactorAuthenticator userTwoFactorAuthenticator : userTwoFactorAuthenticationProviders) {
                userTwoFactorAuthenticationProvidersMap.put(userTwoFactorAuthenticator.getName().toLowerCase(), userTwoFactorAuthenticator);
            }
        }
    }

    @Override
    public void verifyUsingTwoFactorAuthenticationCode(final String code, final Long domainId, final Long userAccountId) {

        Account caller = CallContext.current().getCallingAccount();
        Account owner = _accountService.getActiveAccountById(caller.getId());

        checkAccess(caller, null, true, owner);

        UserAccount userAccount = _accountService.getUserAccountById(userAccountId);
        if (!userAccount.isUser2faEnabled()) {
            throw new CloudRuntimeException(String.format("Two factor authentication is not enabled on the user: %s", userAccount.getUsername()));
        }
        if (StringUtils.isBlank(userAccount.getUser2faProvider()) || StringUtils.isBlank(userAccount.getKeyFor2fa())) {
            throw new CloudRuntimeException(String.format("Two factor authentication is not setup for the user: %s, please setup 2FA before verifying", userAccount.getUsername()));
        }

        UserTwoFactorAuthenticator userTwoFactorAuthenticator = getUserTwoFactorAuthenticator(domainId, userAccountId);
        try {
            userTwoFactorAuthenticator.check2FA(code, userAccount);
            UserDetailVO userDetailVO = _userDetailsDao.findDetail(userAccountId, UserDetailVO.Setup2FADetail);
            if (userDetailVO != null) {
                userDetailVO.setValue(UserAccountVO.Setup2FAstatus.VERIFIED.name());
                _userDetailsDao.update(userDetailVO.getId(), userDetailVO);
            }
        } catch (CloudTwoFactorAuthenticationException e) {
            UserDetailVO userDetailVO = _userDetailsDao.findDetail(userAccountId, UserDetailVO.Setup2FADetail);
            if (userDetailVO != null && userDetailVO.getValue().equals(UserAccountVO.Setup2FAstatus.ENABLED.name())) {
                disableTwoFactorAuthentication(userAccountId, caller, owner);
            }
            throw e;
        }
    }

    @Override
    public UserTwoFactorAuthenticator getUserTwoFactorAuthenticator(Long domainId, Long userAccountId) {
        if (userAccountId != null) {
            UserAccount userAccount = _accountService.getUserAccountById(userAccountId);
            String user2FAProvider = userAccount.getUser2faProvider();
            if (user2FAProvider != null) {
                return getUserTwoFactorAuthenticator(user2FAProvider);
            }
        }
        final String name = userTwoFactorAuthenticationDefaultProvider.valueIn(domainId);
        return getUserTwoFactorAuthenticator(name);
    }

    @Override
    public UserTwoFactorAuthenticationSetupResponse setupUserTwoFactorAuthentication(SetupUserTwoFactorAuthenticationCmd cmd) {
        String providerName = cmd.getProvider();

        Account caller = CallContext.current().getCallingAccount();
        Account owner = _accountService.getActiveAccountById(caller.getId());

        if (Boolean.TRUE.equals(cmd.getEnable())) {
            checkAccess(caller, null, true, owner);
            Long userId = CallContext.current().getCallingUserId();

            return enableTwoFactorAuthentication(userId, providerName);
        }

        // Admin can disable 2FA of the users
        Long userId = cmd.getUserId();
        return disableTwoFactorAuthentication(userId, caller, owner);
    }

    protected UserTwoFactorAuthenticationSetupResponse enableTwoFactorAuthentication(Long userId, String providerName) {
        UserAccountVO userAccount = userAccountDao.findById(userId);
        UserVO userVO = _userDao.findById(userId);
        Long domainId = userAccount.getDomainId();
        if (Boolean.FALSE.equals(enableUserTwoFactorAuthentication.valueIn(domainId)) && Boolean.FALSE.equals(mandateUserTwoFactorAuthentication.valueIn(domainId))) {
            throw new CloudRuntimeException("2FA is not enabled for this domain or at global level");
        }

        if (StringUtils.isEmpty(providerName)) {
            providerName = userTwoFactorAuthenticationDefaultProvider.valueIn(domainId);
            logger.debug(String.format("Provider name is not given to setup 2FA, so using the default 2FA provider %s", providerName));
        }

        UserTwoFactorAuthenticator provider = getUserTwoFactorAuthenticationProvider(providerName);
        String code = provider.setup2FAKey(userAccount);
        UserVO user = _userDao.createForUpdate();
        user.setKeyFor2fa(code);
        user.setUser2faProvider(provider.getName());
        user.setUser2faEnabled(true);
        _userDao.update(userId, user);

        // 2FA setup will be complete only upon successful verification with 2FA code
        UserDetailVO setup2FAstatus = new UserDetailVO(userId, UserDetailVO.Setup2FADetail, UserAccountVO.Setup2FAstatus.ENABLED.name());
        _userDetailsDao.persist(setup2FAstatus);

        UserTwoFactorAuthenticationSetupResponse response = new UserTwoFactorAuthenticationSetupResponse();
        response.setId(userVO.getUuid());
        response.setUsername(userAccount.getUsername());
        response.setSecretCode(code);

        return response;
    }

    protected UserTwoFactorAuthenticationSetupResponse disableTwoFactorAuthentication(Long userId, Account caller, Account owner) {
        UserVO userVO;
        if (userId != null) {
            userVO = validateUser(userId);
            owner = _accountService.getActiveAccountById(userVO.getAccountId());
        } else {
            userId = CallContext.current().getCallingUserId();
            userVO = _userDao.findById(userId);
        }
        checkAccess(caller, null, true, owner);

        UserVO user = _userDao.createForUpdate();
        user.setKeyFor2fa(null);
        user.setUser2faProvider(null);
        user.setUser2faEnabled(false);
        _userDao.update(userVO.getId(), user);
        _userDetailsDao.removeDetail(userId, UserDetailVO.Setup2FADetail);

        UserTwoFactorAuthenticationSetupResponse response = new UserTwoFactorAuthenticationSetupResponse();
        response.setId(userVO.getUuid());
        response.setUsername(userVO.getUsername());

        return response;
    }

    private UserVO validateUser(Long userId) {
        UserVO user = null;
        if (userId != null) {
            user = _userDao.findById(userId);
            if (user == null) {
                throw new InvalidParameterValueException("Invalid user ID provided");
            }
        }
        return user;
    }

    public UserTwoFactorAuthenticator getUserTwoFactorAuthenticator(final String name) {
        if (StringUtils.isEmpty(name)) {
            throw new CloudRuntimeException("UserTwoFactorAuthenticator name provided is empty");
        }
        if (!userTwoFactorAuthenticationProvidersMap.containsKey(name.toLowerCase())) {
            throw new CloudRuntimeException(String.format("Failed to find UserTwoFactorAuthenticator by the name: %s.", name));
        }
        return userTwoFactorAuthenticationProvidersMap.get(name.toLowerCase());
    }

    @Override
    public UserAccount clearUserTwoFactorAuthenticationInSetupStateOnLogin(UserAccount user) {
        return Transaction.execute((TransactionCallback<UserAccount>) status -> {
            if (!user.isUser2faEnabled() && StringUtils.isBlank(user.getUser2faProvider())) {
                return user;
            }
            UserDetailVO userDetailVO = _userDetailsDao.findDetail(user.getId(), UserDetailVO.Setup2FADetail);
            if (userDetailVO != null && UserAccountVO.Setup2FAstatus.VERIFIED.name().equals(userDetailVO.getValue())) {
                return user;
            }
            logger.info("Clearing 2FA configurations for {} as it is still in setup on a new login request", user);
            if (userDetailVO != null) {
                _userDetailsDao.remove(userDetailVO.getId());
            }
            UserAccountVO userAccountVO = userAccountDao.findById(user.getId());
            userAccountVO.setUser2faEnabled(false);
            userAccountVO.setUser2faProvider(null);
            userAccountVO.setKeyFor2fa(null);
            userAccountDao.update(user.getId(), userAccountVO);
            return userAccountVO;
        });
    }

    void assertUserNotAlreadyInAccount(User existingUser, Account newAccount) {
        System.out.println(existingUser.getAccountId());
        System.out.println(newAccount.getId());
        if (existingUser.getAccountId() == newAccount.getId()) {
            AccountVO existingAccount = _accountDao.findById(newAccount.getId());
            throw new InvalidParameterValueException(String.format("Username [%s] already exists in account [id=%s,name=%s]", existingUser.getUsername(), existingAccount.getUuid(), existingAccount.getAccountName()));
        }
    }

    void assertUserNotAlreadyInDomain(User existingUser, Account originalAccount) {
        Account existingAccount = _accountDao.findById(existingUser.getAccountId());
        if (existingAccount.getDomainId() == originalAccount.getDomainId()) {
            DomainVO existingDomain = _domainDao.findById(existingAccount.getDomainId());
            throw new InvalidParameterValueException(String.format("Username [%s] already exists in domain [id=%s,name=%s] user account [id=%s,name=%s]", existingUser.getUsername(), existingDomain.getUuid(), existingDomain.getName(), existingAccount.getUuid(), existingAccount.getAccountName()));
        }
    }
}
