Skip to content
This repository has been archived by the owner on Jul 25, 2018. It is now read-only.

Commit

Permalink
Merge pull request #783 from sw360/dev/ssoAutoLogin
Browse files Browse the repository at this point in the history
feat(portal): make SSOAutoLogin actually work

review-by: [email protected]
tested-by: [email protected]
  • Loading branch information
maierthomas authored Apr 11, 2018
2 parents 7106580 + d324747 commit 3d33403
Show file tree
Hide file tree
Showing 11 changed files with 484 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,10 @@
*/
package org.eclipse.sw360.portal.portlets.signup;

import org.eclipse.sw360.datahandler.thrift.attachments.Attachment;
import org.eclipse.sw360.datahandler.thrift.components.Component;
import org.eclipse.sw360.datahandler.thrift.users.User;
import org.eclipse.sw360.portal.common.PortletUtils;

import javax.portlet.PortletRequest;
import java.util.HashSet;

/**
* Signup portlet utils
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright Siemens AG, 2018. Part of the SW360 Portal Project.
*
* SPDX-License-Identifier: EPL-1.0
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.sw360.portal.users;

import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.servlet.SessionMessages;
import com.liferay.portal.service.ServiceContext;
import com.liferay.portal.service.ServiceContextFactory;

import javax.servlet.http.HttpServletRequest;
import java.util.Optional;
import java.util.function.Consumer;

class HttpServletRequestAdapter implements RequestAdapter {
// this constant is supposed to be defined in WebKeys according to docs found online, but it's not
private static final String COMPANY_ID = "COMPANY_ID";

private HttpServletRequest request;

HttpServletRequestAdapter(HttpServletRequest request) {
this.request = request;
}

@Override
public long getCompanyId() {
return (long) request.getAttribute(COMPANY_ID);
}

@Override
public Consumer<String> getErrorMessagesConsumer() {
return msg -> SessionMessages.add(request, "request_processed", msg);
}

@Override
public Optional<ServiceContext> getServiceContext() {
try {
return Optional.of(ServiceContextFactory.getInstance(request));
} catch (PortalException | SystemException e ) {
return Optional.empty();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright Siemens AG, 2018. Part of the SW360 Portal Project.
*
* SPDX-License-Identifier: EPL-1.0
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.sw360.portal.users;

import com.liferay.portal.kernel.events.Action;
import com.liferay.portal.kernel.events.ActionException;
import com.liferay.portal.kernel.util.PropsUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

import static com.google.common.base.Strings.isNullOrEmpty;

/**
* @author [email protected]
*/
public class LandingPageAction extends Action {

private static final Logger log = LoggerFactory.getLogger(LandingPageAction.class);
private static final String DEFAULT_LANDING_PAGE_PATH_PROPERTY = "default.landing.page.path";
private static final String DEFAULT_LANDING_PAGE_PATH = "/group/guest/home";

private static String landingPage;

static {
landingPage = PropsUtil.get(DEFAULT_LANDING_PAGE_PATH_PROPERTY);
if (landingPage == null){
landingPage = DEFAULT_LANDING_PAGE_PATH;
}
log.info("loaded landing page path from properties: " + landingPage);
}

@Override
public void run(HttpServletRequest request, HttpServletResponse response) throws ActionException {
if (isNullOrEmpty(request.getContextPath())) {
try {
response.sendRedirect(landingPage);
} catch (IOException e) {
throw new ActionException(e);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/*
* Copyright Bosch Software Innovations GmbH, 2016.
* Copyright Siemens AG, 2016-2018.
* Part of the SW360 Portal Project.
*
* SPDX-License-Identifier: EPL-1.0
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.sw360.portal.users;

import com.liferay.portal.NoSuchOrganizationException;
import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.model.*;
import com.liferay.portal.security.membershippolicy.OrganizationMembershipPolicyUtil;
import com.liferay.portal.service.OrganizationLocalService;
import com.liferay.portal.service.OrganizationLocalServiceUtil;
import com.liferay.portal.service.UserLocalServiceUtil;
import org.apache.log4j.Logger;
import org.eclipse.sw360.datahandler.common.CommonUtils;

import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.LongStream;

/**
* Helper class to map organization from identity provider to sw360 internal org names and create
* organizations in Liferay if necessary
*
* Adapted from https://github.com/sw360/ldapOrganizationMappingExt/blob/master/ldapAdapterEXT-ext-impl/src/main/java/com/bosch/osmi/sw360/ldapAdapter/CustomPortalLDAPImporterImpl.java
*/
public class OrganizationHelper {
private static final String MAPPING_KEYS_PREFIX = "mapping.";
private static final String MAPPING_VALUES_SUFFIX = ".target";
private static boolean matchPrefix = false;
private static List<Map.Entry<String, String>> sortedOrganizationMappings;
private static boolean customMappingEnabled = false;
private static Logger log = Logger.getLogger(OrganizationHelper.class);
private static final String MATCH_PREFIX_KEY = "match.prefix";
private static final String ENABLE_CUSTOM_MAPPING_KEY = "enable.custom.mapping";
private static final String PROPERTIES_FILE_PATH = "/orgmapping.properties";

static {
loadOrganizationHelperSettings();
}

public void reassignUserToOrganizationIfNecessary(User user, Organization organization) throws PortalException, SystemException {
if (organization != null && userIsNotInOrganization(user, organization.getOrganizationId())) {
removeUserFromOtherOrganizations(user);
log.debug("OrganizationHelper adds user " + user.getEmailAddress() + " to the organization " + organization.getName());
UserLocalServiceUtil.addOrganizationUsers(organization.getOrganizationId(), Collections.singletonList(user));
}
}

private boolean userIsNotInOrganization(User user, long organizationId) throws SystemException, PortalException {
return LongStream.of(user.getOrganizationIds()).noneMatch(x -> x == organizationId);
}

private void removeUserFromOtherOrganizations(User user) throws SystemException, PortalException {
long[] usersOrganizations = user.getOrganizationIds();
for (long usersOrganization : usersOrganizations) {
log.info("remove user " + user.getEmailAddress() + " from organization with id: " + usersOrganization);
UserLocalServiceUtil.deleteOrganizationUser(usersOrganization, user);
}
}

public Organization addOrGetOrganization(String organizationName, long companyId) throws PortalException, SystemException {
Organization organization;
try {
organization = OrganizationLocalServiceUtil.getOrganization(companyId, organizationName);
log.info(String.format("Organization %s already exists", organizationName));
} catch (NoSuchOrganizationException e) {
User defaultUser = UserLocalServiceUtil.loadGetDefaultUser(companyId);
organization = addOrganization(organizationName, defaultUser);
}
return organization;
}

private Organization addOrganization(String organizationName, User user) throws SystemException {
log.info("OrganizationHelper adds the organization " + organizationName);
Organization organization = null;
try {
OrganizationLocalService organizationLocalService = (OrganizationLocalService) PortalBeanLocatorUtil.locate(OrganizationLocalService.class.getName());
organization = organizationLocalService
.addOrganization(
user.getUserId(),
OrganizationConstants.DEFAULT_PARENT_ORGANIZATION_ID,
organizationName,
OrganizationConstants.TYPE_REGULAR_ORGANIZATION,
RegionConstants.DEFAULT_REGION_ID,
CountryConstants.DEFAULT_COUNTRY_ID,
ListTypeConstants.ORGANIZATION_STATUS_DEFAULT,
"Automatically created during LDAP import",
false,
null
);

OrganizationMembershipPolicyUtil.verifyPolicy(organization);

log.info("added organization with name: " + organization.getName() + " and id:" + organization.getOrganizationId());
} catch (PortalException e) {
log.error("A creator or parent organization with the primary key could not be found or the organization's information was invalid", e);
}
return organization;
}

public String mapOrganizationName(String name) {
if (!customMappingEnabled) {
return name;
}

final Predicate<Map.Entry<String, String>> matcher;
if (matchPrefix) {
matcher = e -> name.startsWith(e.getKey());
} else { // match complete name
matcher = e -> name.equals(e.getKey());
}
return sortedOrganizationMappings.stream()
.filter(matcher)
.findFirst()
.map(Map.Entry::getValue)
.orElse(name);
}

private static void loadOrganizationHelperSettings() {
log.info("begin initialization");
Properties sw360Properties = CommonUtils.loadProperties(OrganizationHelper.class, PROPERTIES_FILE_PATH);
matchPrefix = Boolean.parseBoolean(sw360Properties.getProperty(MATCH_PREFIX_KEY, "false"));
customMappingEnabled = Boolean.parseBoolean(sw360Properties.getProperty(ENABLE_CUSTOM_MAPPING_KEY, "false"));

List<Object> mappingSourceKeys = sw360Properties
.keySet()
.stream()
.filter(p -> ((String) p).startsWith(MAPPING_KEYS_PREFIX) && !((String) p).endsWith(MAPPING_VALUES_SUFFIX))
.collect(Collectors.toList());

Map<String, String> tempOrgMappings = new HashMap<>();
for (Object sourceKey : mappingSourceKeys) {
String sourceOrg = sw360Properties.getProperty((String) sourceKey);
String targetOrg = sw360Properties.getProperty(sourceKey + MAPPING_VALUES_SUFFIX);
if (sourceOrg != null && targetOrg != null && sourceOrg.length() > 0 && targetOrg.length() > 0) {
tempOrgMappings.put(sourceOrg, targetOrg);
}
}
sortedOrganizationMappings = tempOrgMappings
.entrySet()
.stream()
.sorted(Comparator.comparingInt((Map.Entry<String, String> o) -> o.getKey().length())
.reversed())
.collect(Collectors.toList());
log.info(String.format("initialized with %d mappings", sortedOrganizationMappings.size()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright Siemens AG, 2018. Part of the SW360 Portal Project.
*
* SPDX-License-Identifier: EPL-1.0
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.sw360.portal.users;

import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.servlet.SessionMessages;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.service.ServiceContext;
import com.liferay.portal.service.ServiceContextFactory;
import com.liferay.portal.theme.ThemeDisplay;

import javax.portlet.PortletRequest;
import javax.servlet.http.HttpServletRequest;
import java.util.Optional;
import java.util.function.Consumer;

class PortletRequestAdapter implements RequestAdapter {

private PortletRequest request;

PortletRequestAdapter(PortletRequest request) {
this.request = request;
}

@Override
public long getCompanyId() {
ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);
return themeDisplay.getCompanyId();
}

@Override
public Consumer<String> getErrorMessagesConsumer() {
return msg -> SessionMessages.add(request, "request_processed", msg);
}

@Override
public Optional<ServiceContext> getServiceContext() {
try {
return Optional.of(ServiceContextFactory.getInstance(request));
} catch (PortalException | SystemException e ) {
return Optional.empty();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright Siemens AG, 2018. Part of the SW360 Portal Project.
*
* SPDX-License-Identifier: EPL-1.0
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.sw360.portal.users;

import com.liferay.portal.service.ServiceContext;

import java.util.Optional;
import java.util.function.Consumer;

interface RequestAdapter {
long getCompanyId();
Consumer<String> getErrorMessagesConsumer();
Optional<ServiceContext> getServiceContext();
}
Loading

0 comments on commit 3d33403

Please sign in to comment.