All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.flowcentraltech.flowcentral.organization.business.OrganizationModuleServiceImpl Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2021-2024 FlowCentral Technologies Limited.
 * 
 * Licensed 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.flowcentraltech.flowcentral.organization.business;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import com.flowcentraltech.flowcentral.application.constants.ApplicationPrivilegeConstants;
import com.flowcentraltech.flowcentral.common.business.AbstractFlowCentralService;
import com.flowcentraltech.flowcentral.common.business.ApplicationPrivilegeManager;
import com.flowcentraltech.flowcentral.common.business.PostBootSetup;
import com.flowcentraltech.flowcentral.common.business.RolePrivilegeBackupAgent;
import com.flowcentraltech.flowcentral.common.business.StudioProvider;
import com.flowcentraltech.flowcentral.common.constants.ConfigType;
import com.flowcentraltech.flowcentral.common.constants.WfItemVersionType;
import com.flowcentraltech.flowcentral.configuration.constants.DefaultApplicationConstants;
import com.flowcentraltech.flowcentral.configuration.data.ModuleInstall;
import com.flowcentraltech.flowcentral.configuration.xml.util.ConfigurationUtils;
import com.flowcentraltech.flowcentral.organization.constants.OrganizationModuleNameConstants;
import com.flowcentraltech.flowcentral.organization.entities.Branch;
import com.flowcentraltech.flowcentral.organization.entities.BranchQuery;
import com.flowcentraltech.flowcentral.organization.entities.Department;
import com.flowcentraltech.flowcentral.organization.entities.DepartmentQuery;
import com.flowcentraltech.flowcentral.organization.entities.MappedBranch;
import com.flowcentraltech.flowcentral.organization.entities.MappedBranchQuery;
import com.flowcentraltech.flowcentral.organization.entities.MappedDepartment;
import com.flowcentraltech.flowcentral.organization.entities.MappedDepartmentQuery;
import com.flowcentraltech.flowcentral.organization.entities.Privilege;
import com.flowcentraltech.flowcentral.organization.entities.PrivilegeCategory;
import com.flowcentraltech.flowcentral.organization.entities.PrivilegeCategoryQuery;
import com.flowcentraltech.flowcentral.organization.entities.PrivilegeQuery;
import com.flowcentraltech.flowcentral.organization.entities.Role;
import com.flowcentraltech.flowcentral.organization.entities.RolePrivilege;
import com.flowcentraltech.flowcentral.organization.entities.RolePrivilegeQuery;
import com.flowcentraltech.flowcentral.organization.entities.RoleQuery;
import com.tcdng.unify.core.UnifyException;
import com.tcdng.unify.core.annotation.Broadcast;
import com.tcdng.unify.core.annotation.Component;
import com.tcdng.unify.core.annotation.Configurable;
import com.tcdng.unify.core.annotation.Synchronized;
import com.tcdng.unify.core.annotation.Transactional;
import com.tcdng.unify.core.data.FactoryMap;
import com.tcdng.unify.core.util.DataUtils;

/**
 * Implementation of organization module service.
 * 
 * @author FlowCentral Technologies Limited
 * @since 1.0
 */
@Transactional
@Component(OrganizationModuleNameConstants.ORGANIZATION_MODULE_SERVICE)
public class OrganizationModuleServiceImpl extends AbstractFlowCentralService
        implements OrganizationModuleService, ApplicationPrivilegeManager, PostBootSetup {

    private static final String ASSIGN_PRIVILEGE_LOCK = "org::assignprivtorole";

    private static final String DEVOPS_DEPARTMENT_CODE = "DEVOPS";

    private static final String DEVOPS_DEVELOPER_CODE = "DEVELOPER";

    private static final String DEVOPS_JUNIOR_DEVELOPER_CODE = "JDEVELOPER";

    private final FactoryMap tenantRolePrivileges;

    private final Map> privilegeBackup;

    private List roleBackupAgentList;

    @Configurable
    private StudioProvider studioProvider;

    public OrganizationModuleServiceImpl() {
        this.tenantRolePrivileges = new FactoryMap()
            {
                @Override
                protected TenantRolePrivileges create(Long tenantId, Object... arg2) throws Exception {
                    return new TenantRolePrivileges(tenantId);
                }
            };

        this.privilegeBackup = new ConcurrentHashMap>();
    }

    @Override
    public void clearDefinitionsCache() throws UnifyException {
        logDebug("Clearing definitions cache...");
        tenantRolePrivileges.clear();
        logDebug("Definitions cache clearing successfully completed.");
    }

    @Override
    public FactoryMap getMappedBranchCodeFactoryMap() throws UnifyException {
        return new FactoryMap()
            {
                @Override
                protected String create(Long branchId, Object... arg2) throws Exception {
                    return environment().value(String.class, "code", new MappedBranchQuery().id(branchId));
                }
            };
    }

    @Override
    public FactoryMap getMappedDepartmentCodeFactoryMap() throws UnifyException {
        return new FactoryMap()
            {
                @Override
                protected String create(Long departmentId, Object... arg2) throws Exception {
                    return environment().value(String.class, "code", new MappedDepartmentQuery().id(departmentId));
                }
            };
    }

    @Override
    public String getMappedDepartmentCode(Long departmentId) throws UnifyException {
        return environment().value(String.class, "code", new MappedDepartmentQuery().id(departmentId));
    }

    @Override
    public String getMappedBranchCode(Long branchId) throws UnifyException {
        return environment().value(String.class, "code", new MappedBranchQuery().id(branchId));
    }

    @Override
    public List findMappedDepartments(MappedDepartmentQuery query) throws UnifyException {
        return environment().listAll(query);
    }

    @Override
    public List findMappedBranches(MappedBranchQuery query) throws UnifyException {
        return environment().listAll(query);
    }

    @Override
    public Department findDepartment(DepartmentQuery query) throws UnifyException {
        return environment().find(query);
    }

    @Override
    public List findRoles(RoleQuery query) throws UnifyException {
        return environment().listAll(query);
    }

    @Override
    public String getRoleCode(Long roleId) throws UnifyException {
        return environment().value(String.class, "code", new RoleQuery().id(roleId));
    }

    @Override
    public List findPrivilegeCategories(PrivilegeCategoryQuery query) throws UnifyException {
        return environment().listAll(query);
    }

    @Override
    public List findPrivileges(PrivilegeQuery query) throws UnifyException {
        return environment().listAll(query);
    }

    @Override
    public void registerPrivilege(ConfigType configType, Long applicationId, String privilegeCategoryCode,
            String privilegeCode, String privilegeDesc) throws UnifyException {
        Long privilegeCategoryId = environment().value(Long.class, "id",
                new PrivilegeCategoryQuery().code(privilegeCategoryCode));
        Privilege oldPrivilege = environment().find(new PrivilegeQuery().privilegeCategoryId(privilegeCategoryId)
                .code(privilegeCode).applicationId(applicationId));
        if (oldPrivilege == null) {
            Privilege privilege = new Privilege();
            privilege.setApplicationId(applicationId);
            privilege.setPrivilegeCategoryId(privilegeCategoryId);
            privilege.setCode(privilegeCode);
            privilege.setDescription(privilegeDesc);
            privilege.setConfigType(configType);
            environment().create(privilege);
        } else {
            oldPrivilege.setDescription(privilegeDesc);
            oldPrivilege.setConfigType(configType);
            environment().updateByIdVersion(oldPrivilege);
        }
    }

    @Override
    public boolean unregisterPrivilege(Long applicationId, String privilegeCategoryCode, String privilegeCode)
            throws UnifyException {
        Privilege oldPrivilege = environment().find(new PrivilegeQuery().privilegeCatCode(privilegeCategoryCode)
                .code(privilegeCode).applicationId(applicationId));
        if (oldPrivilege != null) {
            environment().deleteAll(new RolePrivilegeQuery().privilegeId(oldPrivilege.getId()));
            environment().deleteByIdVersion(oldPrivilege);
            return true;
        }

        return false;
    }

    @Override
    public void unregisterApplicationPrivileges(Long applicationId) throws UnifyException {
        environment().deleteAll(new RolePrivilegeQuery().applicationId(applicationId));
        environment().deleteAll(new PrivilegeQuery().applicationId(applicationId));

        if (!DataUtils.isBlank(roleBackupAgentList)) {
            for (RolePrivilegeBackupAgent rolePrivilegeBackupAgent : roleBackupAgentList) {
                rolePrivilegeBackupAgent.unregisterApplicationRolePrivileges(applicationId);
            }
        }
    }

    @Override
    public void unregisterCustomApplicationPrivileges(Long applicationId) throws UnifyException {
        environment().deleteAll(new RolePrivilegeQuery().applicationId(applicationId).isCustom());
        environment().deleteAll(new PrivilegeQuery().applicationId(applicationId).isCustom());

        if (!DataUtils.isBlank(roleBackupAgentList)) {
            for (RolePrivilegeBackupAgent rolePrivilegeBackupAgent : roleBackupAgentList) {
                rolePrivilegeBackupAgent.unregisterCustomApplicationRolePrivileges(applicationId);
            }
        }
    }

    @Override
    public boolean isRegisteredPrivilege(String privilegeCategoryCode, String privilegeCode) throws UnifyException {
        return environment()
                .countAll(new PrivilegeQuery().privilegeCatCode(privilegeCategoryCode).code(privilegeCode)) > 0;
    }

    @Override
    public void backupApplicationRolePrivileges(Long applicationId) throws UnifyException {
        List rolePrivilegeList = environment()
                .listAll(new RolePrivilegeQuery().applicationId(applicationId).addSelect("roleCode", "privilegeCode"));
        for (RolePrivilege rolePrivilege : rolePrivilegeList) {
            Set privilegeCodes = privilegeBackup.get(rolePrivilege.getRoleCode());
            if (privilegeCodes == null) {
                privilegeCodes = new HashSet();
                privilegeBackup.put(rolePrivilege.getRoleCode(), privilegeCodes);
            }

            privilegeCodes.add(rolePrivilege.getPrivilegeCode());
        }

        if (!DataUtils.isBlank(roleBackupAgentList)) {
            for (RolePrivilegeBackupAgent rolePrivilegeBackupAgent : roleBackupAgentList) {
                rolePrivilegeBackupAgent.backupApplicationRolePrivileges(applicationId);
            }
        }
    }

    @Override
    public void restoreApplicationRolePrivileges() throws UnifyException {
        RolePrivilege rolePrivilege = new RolePrivilege();
        for (Map.Entry> entry : privilegeBackup.entrySet()) {
            final Long roleId = environment().value(Long.class, "id", new RoleQuery().code(entry.getKey()));
            for (String privilegeCode : entry.getValue()) {
                Optional privilegeId = environment().valueOptional(Long.class, "id",
                        new PrivilegeQuery().code(privilegeCode));
                if (privilegeId.isPresent()) {
                    if (environment()
                            .countAll(new RolePrivilegeQuery().privilegeId(privilegeId.get()).roleId(roleId)) == 0) {
                        rolePrivilege.setId(null);
                        rolePrivilege.setRoleId(roleId);
                        rolePrivilege.setPrivilegeId(privilegeId.get());
                        environment().create(rolePrivilege);
                    }
                }
            }
        }

        if (!DataUtils.isBlank(roleBackupAgentList)) {
            for (RolePrivilegeBackupAgent rolePrivilegeBackupAgent : roleBackupAgentList) {
                rolePrivilegeBackupAgent.restoreApplicationRolePrivileges();
            }
        }

        privilegeBackup.clear();
    }

    @Override
    public List findRolePrivileges(String privilegeCategoryCode, String roleCode) throws UnifyException {
        if (getUserToken().isReservedUser()) {
            return environment().valueList(String.class, "code",
                    new PrivilegeQuery().privilegeCatCode(privilegeCategoryCode));
        }

        return environment().valueList(String.class, "privilegeCode",
                new RolePrivilegeQuery().roleWfItemVersionType(WfItemVersionType.ORIGINAL)
                        .privilegeCatCode(privilegeCategoryCode).roleCode(roleCode));
    }

    @Override
    @Synchronized(ASSIGN_PRIVILEGE_LOCK)
    public boolean assignPrivilegeToRole(String roleCode, String privilegeCode) throws UnifyException {
        if (!isRoleWithPrivilege(roleCode, privilegeCode)) {
            Long roleId = environment().value(Long.class, "id", new RoleQuery().code(roleCode));
            Long privilegeId = environment().value(Long.class, "id", new PrivilegeQuery().code(privilegeCode));
            RolePrivilege rolePrivilege = new RolePrivilege();
            rolePrivilege.setRoleId(roleId);
            rolePrivilege.setPrivilegeId(privilegeId);
            environment().create(rolePrivilege);

            invalidateRolePrivilegesCache(roleCode);
            return true;
        }

        return false;
    }

    @Override
    public boolean isRoleWithPrivilege(String roleCode, String privilegeCode) throws UnifyException {
        return (roleCode == null && getUserToken().isReservedUser())
                || tenantRolePrivileges.get(getUserTenantId()).getRolePrivileges(roleCode).isPrivilege(privilegeCode);
    }

    @Override
    public Branch getBranch(Long branchId) throws UnifyException {
        return environment().list(Branch.class, branchId);
    }

    @Override
    public Branch findBranch(BranchQuery query) throws UnifyException {
        return environment().list(query);
    }

    @Override
    public List findBranches(BranchQuery query) throws UnifyException {
        return environment().listAll(query);
    }

    @Override
    public Long getBranchId(String branchCode) throws UnifyException {
        return environment().value(Long.class, "id", new BranchQuery().code(branchCode));
    }

    @Override
    public Optional getBranchId(BranchQuery query) throws UnifyException {
        return environment().valueOptional(Long.class, "id", query);
    }

    @Override
    public Long getDepartmentId(String departmentCode) throws UnifyException {
        return environment().value(Long.class, "id", new DepartmentQuery().code(departmentCode));
    }

    @Broadcast
    public synchronized void invalidateRolePrivilegesCache(String... roleCodes) throws UnifyException {
        for (TenantRolePrivileges tenantRolePrivileges : tenantRolePrivileges.values()) {
            tenantRolePrivileges.invalidate(roleCodes);
        }
    }

    @Override
    public void performPostBootSetup(final boolean isInstallationPerformed) throws UnifyException {
        if (studioProvider != null && studioProvider.isInstallDefaultDeveloperRoles()) {
            // Ensure DevOps department
            Department department = environment().find(new DepartmentQuery().code(DEVOPS_DEPARTMENT_CODE));
            if (department == null) {
                department = new Department();
                department.setId(DefaultApplicationConstants.DEVOPS_DEPARTMENT_ID);
                department.setCode(DEVOPS_DEPARTMENT_CODE);
                department.setDescription(resolveApplicationMessage("$m{organization.default.department.devops.desc}"));
                environment().create(department);
            }

            // Ensure developer role
            Role role = environment().findLean(new RoleQuery().code(DEVOPS_DEVELOPER_CODE));
            if (role == null) {
                role = new Role();
                role.setDepartmentId(department.getId());
                role.setCode(DEVOPS_DEVELOPER_CODE);
                role.setDescription(resolveApplicationMessage("$m{organization.default.department.developer.desc}"));
                Long roleId = (Long) environment().create(role);

                List privilegeCodeList = ConfigurationUtils.readStringList(
                        "data/organization-privileges-developer.dat", getUnifyComponentContext().getWorkingPath());
                RolePrivilege rolePrivilege = new RolePrivilege();
                rolePrivilege.setRoleId(roleId);
                for (Long privilegeId : environment().valueList(Long.class, "id",
                        new PrivilegeQuery().codeIn(privilegeCodeList))) {
                    rolePrivilege.setPrivilegeId(privilegeId);
                    environment().create(rolePrivilege);
                }
            } else { // TODO Remove
                if (environment().countAll(new RolePrivilegeQuery().roleId(role.getId())) == 0) {
                    List privilegeCodeList = ConfigurationUtils.readStringList(
                            "data/organization-privileges-developer.dat", getUnifyComponentContext().getWorkingPath());
                    RolePrivilege rolePrivilege = new RolePrivilege();
                    rolePrivilege.setRoleId(role.getId());
                    for (Long privilegeId : environment().valueList(Long.class, "id",
                            new PrivilegeQuery().codeIn(privilegeCodeList))) {
                        rolePrivilege.setPrivilegeId(privilegeId);
                        environment().create(rolePrivilege);
                    }
                }
            }

            // Ensure junior developer role
            role = environment().findLean(new RoleQuery().code(DEVOPS_JUNIOR_DEVELOPER_CODE));
            if (role == null) {
                role = new Role();
                role.setDepartmentId(department.getId());
                role.setCode(DEVOPS_JUNIOR_DEVELOPER_CODE);
                role.setDescription(
                        resolveApplicationMessage("$m{organization.default.department.juniordeveloper.desc}"));
                Long roleId = (Long) environment().create(role);

                List privilegeCodeList = ConfigurationUtils.readStringList(
                        "data/organization-privileges-juniordeveloper.dat",
                        getUnifyComponentContext().getWorkingPath());
                RolePrivilege rolePrivilege = new RolePrivilege();
                rolePrivilege.setRoleId(roleId);
                for (Long privilegeId : environment().valueList(Long.class, "id",
                        new PrivilegeQuery().codeIn(privilegeCodeList))) {
                    rolePrivilege.setPrivilegeId(privilegeId);
                    environment().create(rolePrivilege);
                }
            }
        }
    }

    @Override
    protected void doInstallModuleFeatures(ModuleInstall moduleInstall) throws UnifyException {
        installPrivilegeCategories(moduleInstall);
    }

    @Override
    protected void onInitialize() throws UnifyException {
        super.onInitialize();
        roleBackupAgentList = getComponents(RolePrivilegeBackupAgent.class);
    }

    private void installPrivilegeCategories(ModuleInstall moduleInstall) throws UnifyException {
        if (OrganizationModuleNameConstants.ORGANIZATION_MODULE_NAME
                .equals(moduleInstall.getModuleConfig().getName())) {
            installPrivilegeCategory(ApplicationPrivilegeConstants.APPLICATION_CATEGORY_CODE,
                    "organization.privilegecategory.applications");
            installPrivilegeCategory(ApplicationPrivilegeConstants.APPLICATION_APPLET_CATEGORY_CODE,
                    "organization.privilegecategory.applets");
            installPrivilegeCategory(ApplicationPrivilegeConstants.APPLICATION_ENTITY_CATEGORY_CODE,
                    "organization.privilegecategory.entities");
            installPrivilegeCategory(ApplicationPrivilegeConstants.APPLICATION_REPORTABLE_CATEGORY_CODE,
                    "organization.privilegecategory.reportableentities");
            installPrivilegeCategory(ApplicationPrivilegeConstants.APPLICATION_REPORTCONFIG_CATEGORY_CODE,
                    "organization.privilegecategory.configuredreport");
            installPrivilegeCategory(ApplicationPrivilegeConstants.APPLICATION_FORMACTION_CATEGORY_CODE,
                    "organization.privilegecategory.formaction");
            installPrivilegeCategory(ApplicationPrivilegeConstants.APPLICATION_FEATURE_CATEGORY_CODE,
                    "organization.privilegecategory.feature");
            installPrivilegeCategory(ApplicationPrivilegeConstants.APPLICATION_WORKFLOW_WIZARD_CATEGORY_CODE,
                    "organization.privilegecategory.workflowwizards");
            installPrivilegeCategory(ApplicationPrivilegeConstants.APPLICATION_DASHBOARD_CATEGORY_CODE,
                    "organization.privilegecategory.dashboards");
            installPrivilegeCategory(ApplicationPrivilegeConstants.APPLICATION_WORKSPACE_CATEGORY_CODE,
                    "organization.privilegecategory.workspaces");
        }
    }

    private void installPrivilegeCategory(String privilegeCategoryCode, String descriptionKey) throws UnifyException {
        PrivilegeCategory oldPrivilegeCategory = environment()
                .find(new PrivilegeCategoryQuery().code(privilegeCategoryCode));
        String description = getApplicationMessage(descriptionKey);
        if (oldPrivilegeCategory == null) {
            PrivilegeCategory privilegeCategory = new PrivilegeCategory();
            privilegeCategory.setCode(privilegeCategoryCode);
            privilegeCategory.setDescription(description);
            environment().create(privilegeCategory);
        } else {
            oldPrivilegeCategory.setDescription(description);
            environment().updateByIdVersion(oldPrivilegeCategory);
        }
    }

    private class TenantRolePrivileges {

        private final FactoryMap privilegesByRole;

        private final Long tenantId;

        public TenantRolePrivileges(Long _tenantId) {
            this.tenantId = _tenantId;
            this.privilegesByRole = new FactoryMap(true)
                {
                    @Override
                    protected boolean stale(String roleCode, RolePrivileges rolePrivileges) throws Exception {
                        return rolePrivileges.getVersion() < environment().value(Long.class, "versionNo",
                                new RoleQuery().code(roleCode).tenantId(tenantId));
                    }

                    @Override
                    protected RolePrivileges create(String roleCode, Object... arg2) throws Exception {
                        Set privileges = environment().valueSet(String.class, "privilegeCode",
                                new RolePrivilegeQuery().roleWfItemVersionType(WfItemVersionType.ORIGINAL)
                                        .roleCode(roleCode).tenantId(tenantId));
                        long version = environment().value(Long.class, "versionNo",
                                new RoleQuery().code(roleCode).tenantId(tenantId));
                        return new RolePrivileges(privileges, version);
                    }
                };
        }

        public RolePrivileges getRolePrivileges(String roleCode) throws UnifyException {
            return privilegesByRole.get(roleCode);
        }

        public void invalidate(String... roleCodes) throws UnifyException {
            for (String roleCode : roleCodes) {
                if (privilegesByRole.isKey(roleCode)) {
                    privilegesByRole.get(roleCode).invalidate();
                }
            }
        }

    }

    private class RolePrivileges {

        private Set privileges;

        private long version;

        public RolePrivileges(Set privileges, long version) {
            this.privileges = privileges;
            this.version = version;
        }

        public boolean isPrivilege(String privilege) {
            return privileges.contains(privilege);
        }

        public long getVersion() {
            return version;
        }

        public void invalidate() {
            version = 0;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy