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

org.bonitasoft.engine.identity.ImportOrganization Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (C) 2016 Bonitasoft S.A.
 * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble
 * This library is free software; you can redistribute it and/or modify it under the terms
 * of the GNU Lesser General Public License as published by the Free Software Foundation
 * version 2.1 of the License.
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public License along with this
 * program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
 * Floor, Boston, MA 02110-1301, USA.
 **/
package org.bonitasoft.engine.identity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.bind.JAXBException;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bonitasoft.engine.api.impl.SCustomUserInfoValueAPI;
import org.bonitasoft.engine.api.impl.SessionInfos;
import org.bonitasoft.engine.builder.BuilderFactory;
import org.bonitasoft.engine.commons.exceptions.SBonitaException;
import org.bonitasoft.engine.identity.model.SCustomUserInfoDefinition;
import org.bonitasoft.engine.identity.model.SGroup;
import org.bonitasoft.engine.identity.model.SRole;
import org.bonitasoft.engine.identity.model.SUser;
import org.bonitasoft.engine.identity.model.SUserMembership;
import org.bonitasoft.engine.identity.model.builder.SUserUpdateBuilderFactory;
import org.bonitasoft.engine.identity.xml.ExportedCustomUserInfoDefinition;
import org.bonitasoft.engine.identity.xml.ExportedGroup;
import org.bonitasoft.engine.identity.xml.ExportedRole;
import org.bonitasoft.engine.identity.xml.ExportedUser;
import org.bonitasoft.engine.identity.xml.ExportedUserMembership;
import org.bonitasoft.engine.identity.xml.Organization;
import org.bonitasoft.engine.service.ModelConvertor;

/**
 * @author Matthieu Chaffotte
 */
@Slf4j
public class ImportOrganization {

    private static final String LEGACY_NS = "xmlns:organization=\"http://documentation.bonitasoft.com/organization-xml-schema\"";

    private static final String VERSIONED_NS = "xmlns:organization=\"http://documentation.bonitasoft.com/organization-xml-schema/1.1\"";

    final IdentityService identityService;
    private final String organizationContent;

    private final List warnings;

    private final ImportOrganizationStrategy strategy;

    private final SCustomUserInfoValueAPI userInfoValueAPI;

    public ImportOrganization(IdentityService identityService, final String organizationContent,
            final ImportPolicy policy, final SCustomUserInfoValueAPI userInfoValueAPI)
            throws OrganizationImportException {
        this.userInfoValueAPI = userInfoValueAPI;
        this.identityService = identityService;
        this.organizationContent = updateNamespace(organizationContent);
        warnings = new ArrayList<>();
        switch (policy) {
            case FAIL_ON_DUPLICATES:
                strategy = new ImportOrganizationFailOnDuplicatesStrategy();
                break;
            case IGNORE_DUPLICATES:
                strategy = new ImportOrganizationIgnoreDuplicatesStrategy();
                break;
            case MERGE_DUPLICATES:
                strategy = new ImportOrganizationMergeDuplicatesStrategy(identityService, userInfoValueAPI);
                break;
            default:
                throw new OrganizationImportException("No import strategy found for " + policy);
        }

    }

    private void excludeGroupsWithInvalidCharactersInName(List groups)
            throws OrganizationImportException {
        for (ExportedGroup group : groups) {
            String groupName = group.getName();
            if (groupName.contains("/")) {
                groups.remove(group);
                warnings.add("The group name " + groupName
                        + " contains the character '/' which is not supported. The group has not been imported");
            }
        }
    }

    private String updateNamespace(String content) {
        if (content != null) {
            if (content.contains(LEGACY_NS)) {
                content = content.replace(LEGACY_NS, VERSIONED_NS);
            }
        }
        return content;
    }

    public List execute() throws SBonitaException, JAXBException {
        try {
            final Organization organization = new OrganizationParser().convert(organizationContent);
            final List users = organization.getUsers();
            final List roles = organization.getRoles();
            final List groups = organization.getGroups();
            //checking if the Group names contain illegal characters
            excludeGroupsWithInvalidCharactersInName(groups);
            final List memberships = organization.getMemberships();

            long importDate = System.currentTimeMillis();
            // custom user info definitions
            final Map customUserInfoDefinitions = importCustomUserInfoDefinitions(
                    organization.getCustomUserInfoDefinition());
            // Users
            final Map userNameToSUsers = importUsers(users, customUserInfoDefinitions);
            updateManagerId(users, userNameToSUsers, importDate);
            // Roles
            final Map roleNameToIdMap = importRoles(roles);
            // Groups
            final Map groupPathToIdMap = importGroups(groups);
            // UserMemberships
            importMemberships(memberships, userNameToSUsers, roleNameToIdMap, groupPathToIdMap);
            return warnings;
        } catch (final SBonitaException | JAXBException e) {
            throw e;
        } catch (final Exception e) {
            throw new SImportOrganizationException(e);
        }
    }

    private Map importCustomUserInfoDefinitions(
            final List customUserInfoDefinitionCreators)
            throws SIdentityException, ImportDuplicateInOrganizationException {
        final CustomUserInfoDefinitionImporter importer = new CustomUserInfoDefinitionImporter(identityService,
                strategy);
        return importer.importCustomUserInfoDefinitions(customUserInfoDefinitionCreators);
    }

    private void importMemberships(final List memberships,
            final Map userNameToSUsers,
            final Map roleNameToIdMap,
            final Map groupPathToIdMap)
            throws SIdentityException, ImportDuplicateInOrganizationException {
        for (final ExportedUserMembership newMembership : memberships) {
            final Long userId = getUserId(userNameToSUsers, newMembership);
            final Long groupId = getGroupId(groupPathToIdMap, newMembership);
            final Long roleId = getRoleId(roleNameToIdMap, newMembership);
            if (userId != null && groupId != null && roleId != null) {
                try {
                    final SUserMembership sUserMembership = identityService.getUserMembership(userId, groupId, roleId);
                    strategy.foundExistingMembership(sUserMembership);
                } catch (final SIdentityException e) {
                    final Long assignedBy = getAssignedBy(userNameToSUsers, newMembership);
                    addMembership(newMembership, userId, groupId, roleId, assignedBy);
                }
            } else {
                log.warn("The membership " + newMembership
                        + " could not be imported because the user, group or role can't be found\n userId=" +
                        userId + " groupId=" + groupId + " roleId=" + roleId);
            }
        }
    }

    private Long getUserId(final Map userNameToSUsers, final ExportedUserMembership newMembership) {
        final String username = newMembership.getUserName();
        if (username == null || username.isEmpty()) {
            return -1L;
        }
        final SUser sUser = userNameToSUsers.get(username);
        if (sUser != null) {
            return sUser.getId();
        }
        return null;

    }

    private Long getGroupId(final Map groupPathToIdMap, final ExportedUserMembership newMembership) {
        final String groupParentPath = newMembership.getGroupParentPath();
        final String groupFullPath = (groupParentPath == null ? '/' : groupParentPath + '/')
                + newMembership.getGroupName();
        return groupPathToIdMap.get(groupFullPath);
    }

    private Long getRoleId(final Map roleNameToIdMap, final ExportedUserMembership newMembership) {
        final String roleName = newMembership.getRoleName();
        if (roleName == null || roleName.isEmpty()) {
            return -1L;
        }
        final Long roleId = roleNameToIdMap.get(roleName);
        if (roleId != null) {
            return roleId;
        }
        return null;
    }

    private Long getAssignedBy(final Map userNameToSUsers, final ExportedUserMembership newMembership) {
        final String assignedByName = newMembership.getAssignedBy();
        if (assignedByName == null || assignedByName.isEmpty()) {
            return -1L;
        }
        final SUser sUserAssigned = userNameToSUsers.get(assignedByName);
        if (sUserAssigned != null) {
            return sUserAssigned.getId();
        }
        return -1L;
    }

    private Map importGroups(final List groupCreators)
            throws ImportDuplicateInOrganizationException, SIdentityException {
        final Map groupPathToIdMap = new HashMap<>(groupCreators.size());
        for (final ExportedGroup groupCreator : groupCreators) {
            SGroup sGroup;
            try {
                final String groupPath = getGroupPath(groupCreator);
                sGroup = identityService.getGroupByPath(groupPath);
                strategy.foundExistingGroup(sGroup, groupCreator);
            } catch (final SGroupNotFoundException e) {
                sGroup = addGroup(groupCreator);
            }
            groupPathToIdMap.put(sGroup.getPath(), sGroup.getId());
        }
        return groupPathToIdMap;
    }

    private String getGroupPath(final ExportedGroup exportedGroup) {
        final String name = exportedGroup.getName();
        final String parentPath = exportedGroup.getParentPath();
        if (parentPath == null) {
            return "/" + name;
        }
        return parentPath + "/" + name;
    }

    private Map importRoles(final List roleCreators)
            throws ImportDuplicateInOrganizationException, SIdentityException {
        final Map roleNameToIdMap = new HashMap<>(roleCreators.size());
        for (final ExportedRole roleCreator : roleCreators) {
            SRole sRole;
            try {
                sRole = identityService.getRoleByName(roleCreator.getName());
                strategy.foundExistingRole(sRole, roleCreator);
            } catch (final SRoleNotFoundException e) {
                sRole = addRole(roleCreator);
            }
            roleNameToIdMap.put(sRole.getName(), sRole.getId());
        }
        return roleNameToIdMap;
    }

    private void updateManagerId(final List users, final Map userNameToSUsers,
            long importDate)
            throws SUserUpdateException {
        for (final ExportedUser user : users) {
            //Skip the update of the manager if user was already present before the import
            // and the strategy says to skip it in that case
            if (strategy.shouldSkipUpdateManagerOfExistingUser()
                    && wasUserAlreadyPresent(userNameToSUsers, importDate, user)) {
                continue;
            }

            if (StringUtils.isNotBlank(user.getManagerUserName())) {
                final String managerUserName = user.getManagerUserName().trim();
                SUser manager = userNameToSUsers.get(managerUserName);
                if (manager != null) {
                    identityService.updateUser(userNameToSUsers.get(user.getUserName()),
                            BuilderFactory.get(SUserUpdateBuilderFactory.class).createNewInstance()
                                    .updateManagerUserId(manager.getId()).done());
                } else {
                    log.warn("The user " + user.getUserName() + " has a manager with username "
                            + managerUserName + ", but this one does not exist. Please set it manually.");
                }
            }
        }
    }

    private boolean wasUserAlreadyPresent(Map userNameToSUsers, long importDate, ExportedUser user) {
        return userNameToSUsers.get(user.getUserName()).getCreationDate() < importDate;
    }

    private Map importUsers(final List users,
            final Map customUserInfoDefinitions)
            throws SBonitaException {
        final CustomUserInfoValueImporter userInfoValueImporter = new CustomUserInfoValueImporter(userInfoValueAPI,
                customUserInfoDefinitions);
        final UserImporter userImporter = new UserImporter(identityService, strategy,
                SessionInfos.getUserIdFromSession(), userInfoValueImporter);
        return userImporter.importUsers(users);
    }

    private void addMembership(final ExportedUserMembership newMembership, final Long userId, final Long groupId,
            final Long roleId, final Long assignedBy)
            throws SUserMembershipCreationException {
        final long assignedDateAsLong = getAssignedDate(newMembership);
        final SUserMembership sUserMembership = SUserMembership.builder().userId(userId).groupId(groupId).roleId(roleId)
                .assignedBy(assignedBy).assignedDate(assignedDateAsLong).build();
        identityService.createUserMembership(sUserMembership);
    }

    private long getAssignedDate(final ExportedUserMembership newMembership) {
        final Long assignedDate = newMembership.getAssignedDate();
        if (assignedDate != null) {
            return assignedDate;
        }
        return 0;
    }

    private SGroup addGroup(final ExportedGroup exportedGroup) throws SGroupCreationException {
        final SGroup sGroup = ModelConvertor.constructSGroup(exportedGroup);
        identityService.createGroup(sGroup, null, null);
        return sGroup;
    }

    private SRole addRole(final ExportedRole exportedRole) throws SIdentityException {
        final SRole sRole = ModelConvertor.constructSRole(exportedRole);
        identityService.createRole(sRole, null, null);
        return sRole;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy