/*
* Copyright Siemens AG, 2013-2015. Part of the SW360 Portal Project.
*
* 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.portlets.admin;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableSet;
import com.liferay.portal.kernel.dao.orm.QueryUtil;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.portlet.PortletResponseUtil;
import com.liferay.portal.kernel.upload.UploadPortletRequest;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.model.*;
import com.liferay.portal.model.User;
import com.liferay.portal.service.*;
import com.liferay.portal.theme.ThemeDisplay;
import com.liferay.portal.util.PortalUtil;
import org.eclipse.sw360.datahandler.common.CommonUtils;
import org.eclipse.sw360.datahandler.thrift.SW360Exception;
import org.eclipse.sw360.datahandler.thrift.users.UserGroup;
import org.eclipse.sw360.datahandler.thrift.users.UserService;
import org.eclipse.sw360.portal.common.PortalConstants;
import org.eclipse.sw360.portal.common.UsedAsLiferayAction;
import org.eclipse.sw360.portal.portlets.Sw360Portlet;
import org.eclipse.sw360.portal.users.UserCSV;
import org.eclipse.sw360.portal.users.UserCacheHolder;
import org.eclipse.sw360.portal.users.UserUtils;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVPrinter;
import org.apache.commons.csv.CSVRecord;
import org.apache.log4j.Logger;
import org.apache.thrift.TException;
import javax.portlet.*;
import java.io.*;
import java.util.*;
import static com.google.common.base.Strings.isNullOrEmpty;
import static org.eclipse.sw360.portal.users.UserUtils.getRoleConstantFromUserGroup;
/**
* Created by jn on 06.03.15.
*
* @author johannes.najjar@tngtech.com
*/
public class UserPortlet extends Sw360Portlet {
private static final Logger log = Logger.getLogger(UserPortlet.class);
@Override
public void doView(RenderRequest request, RenderResponse response) throws IOException, PortletException {
List<org.eclipse.sw360.datahandler.thrift.users.User> missingUsers = new ArrayList<>();
List<org.eclipse.sw360.datahandler.thrift.users.User> backEndUsers;
List<User> liferayUsers;
List<User> liferayUsers2;
try {
liferayUsers2 = UserLocalServiceUtil.getUsers(QueryUtil.ALL_POS, QueryUtil.ALL_POS);
} catch (SystemException e) {
log.error("Could not get user List from liferay", e);
liferayUsers2 = Collections.emptyList();
}
liferayUsers = FluentIterable.from(liferayUsers2).filter(new Predicate<User>() {
@Override
public boolean apply(User liferayUser) {
String firstName = liferayUser.getFirstName();
String lastName = liferayUser.getLastName();
String emailAddress = liferayUser.getEmailAddress();
List<Organization> organizations;
try {
organizations = liferayUser.getOrganizations();
} catch (PortalException | SystemException e) {
return false;
}
String department = "";
if (organizations != null && organizations.size() > 0) {
department = organizations.get(0).getName();
}
String userGroup = "";
List<Role> roles;
try {
roles = liferayUser.getRoles();
} catch (SystemException e) {
return false;
}
List<String> roleNames = new ArrayList<>();
for (Role role : roles) {
roleNames.add(role.getName());
}
for (UserGroup group : UserGroup.values()) {
String roleConstantFromUserGroup = getRoleConstantFromUserGroup(group);
if (roleNames.contains(roleConstantFromUserGroup)) {
userGroup = group.toString();
break;
}
}
String gid = liferayUser.getOpenId();
String passwordHash = liferayUser.getPassword();
return !(isNullOrEmpty(firstName) || isNullOrEmpty(lastName) || isNullOrEmpty(emailAddress) || isNullOrEmpty(department) || isNullOrEmpty(userGroup) || isNullOrEmpty(gid) || isNullOrEmpty(passwordHash));
}
}).toList();
try {
UserService.Iface client = thriftClients.makeUserClient();
backEndUsers = CommonUtils.nullToEmptyList(client.searchUsers(null));
} catch (TException e) {
log.error("Problem with user client", e);
backEndUsers = Collections.emptyList();
}
if (backEndUsers.size() > 0) {
final ImmutableSet<String> lifeRayMails = FluentIterable.from(liferayUsers).transform(new Function<User, String>() {
@Override
public String apply(User input) {
return input.getEmailAddress();
}
}).toSet();
missingUsers = FluentIterable.from(backEndUsers).filter(new Predicate<org.eclipse.sw360.datahandler.thrift.users.User>() {
@Override
public boolean apply(org.eclipse.sw360.datahandler.thrift.users.User input) {
return !lifeRayMails.contains(input.getEmail());
}
}).toList();
}
request.setAttribute(PortalConstants.USER_LIST, liferayUsers);
request.setAttribute(PortalConstants.MISSING_USER_LIST, missingUsers);
// Proceed with page rendering
super.doView(request, response);
}
@Override
public void serveResource(ResourceRequest request, ResourceResponse response) throws IOException, PortletException {
String action = request.getParameter(PortalConstants.ACTION);
if (PortalConstants.USER_LIST.equals(action)) {
try {
backUpUsers(request, response);
} catch (SystemException | PortalException e) {
log.error("Something went wrong with the user backup", e);
}
}
}
public void backUpUsers(ResourceRequest request, ResourceResponse response) throws PortletException, IOException, SystemException, PortalException {
List<User> liferayUsers;
try {
liferayUsers = UserLocalServiceUtil.getUsers(QueryUtil.ALL_POS, QueryUtil.ALL_POS);
} catch (SystemException e) {
log.error("Could not get user List from liferay", e);
liferayUsers = Collections.emptyList();
}
final ByteArrayOutputStream outB = new ByteArrayOutputStream();
Writer out = new BufferedWriter(new OutputStreamWriter(outB));
CSVPrinter csvPrinter = new CSVPrinter(out, CommonUtils.sw360CsvFormat);
csvPrinter.printRecord("GivenName", "Lastname", "Email", "Department", "UserGroup", "GID", "isMale", "PasswdHash","wantsMailNotification");
for (User liferayUser : liferayUsers) {
String firstName = liferayUser.getFirstName();
String lastName = liferayUser.getLastName();
String emailAddress = liferayUser.getEmailAddress();
List<Organization> organizations = liferayUser.getOrganizations();
String department = "";
if (organizations != null && organizations.size() > 0) {
department = organizations.get(0).getName();
}
String gid = liferayUser.getOpenId();
boolean isMale = liferayUser.isMale();
String passwordHash = liferayUser.getPassword();
if (isNullOrEmpty(emailAddress) || isNullOrEmpty(department)) {
continue;
}
org.eclipse.sw360.datahandler.thrift.users.User sw360user = UserCacheHolder.getUserFromEmail(emailAddress);
boolean wantsMailNotification =
sw360user.isSetWantsMailNotification() ? sw360user.wantsMailNotification : true;
String userGroup = sw360user.getUserGroup().toString();
csvPrinter.printRecord(firstName, lastName, emailAddress, department, userGroup, gid, isMale, passwordHash, wantsMailNotification);
}
csvPrinter.flush();
csvPrinter.close();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(outB.toByteArray());
PortletResponseUtil.sendFile(request, response, "Users.csv", byteArrayInputStream, "text/csv");
}
@UsedAsLiferayAction
public void updateUsers(ActionRequest request, ActionResponse response) throws PortletException, IOException {
List<UserCSV> users;
try {
users = getUsersFromRequest(request, "file");
} catch (TException e) {
log.error("Error processing csv file", e);
users = Collections.emptyList();
}
try {
createOrganizations(request, users);
} catch (SW360Exception | SystemException | PortalException e) {
log.error("Error creating organizations", e);
}
for (UserCSV user : users) {
dealWithUser(request, user);
}
}
private String extractHeadDept(String input) {
String[] split = input.split(" ");
if (split.length > 1) {
return split[0] + " " + split[1];
} else return split[0];
}
private void createOrganizations(PortletRequest request, List<UserCSV> users) throws SW360Exception, SystemException, PortalException {
/* Find the departments of the users, create the head departments and then create the organizations */
ImmutableSet<String> departments = FluentIterable.from(users).transform(input -> input.getDepartment()).toSet();
createOrganizations(request, departments);
}
public void createOrganizations(PortletRequest request, Iterable<String> departments) throws PortalException, SystemException {
ImmutableSet<String> headDepartments = FluentIterable.from(departments).transform(department -> extractHeadDept(department)).toSet();
Map<String, Long> organizationIds = new HashMap<>();
ServiceContext serviceContext = ServiceContextFactory.getInstance(request);
ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);
long companyId = themeDisplay.getCompanyId();
for (String headDepartment : headDepartments) {
long organizationId;
try {
organizationId = OrganizationLocalServiceUtil.getOrganizationId(companyId, headDepartment);
} catch (SystemException e) {
organizationId = 0;
}
if (organizationId == 0) { // The organization does not yet exist
Organization organization = createOrganization(serviceContext, headDepartment, OrganizationConstants.DEFAULT_PARENT_ORGANIZATION_ID);
organizationId = organization.getOrganizationId();
}
organizationIds.put(headDepartment, organizationId);
}
for (String department : departments) {
long organizationId;
try {
organizationId = OrganizationLocalServiceUtil.getOrganizationId(companyId, department);
} catch (SystemException e) {
organizationId = 0;
}
if (organizationId == 0) { // The organization does not yet exist
createOrganization(serviceContext, department, organizationIds.get(extractHeadDept(department)).intValue());
}
}
}
private Organization createOrganization(ServiceContext serviceContext, String headDepartment, int parentId) throws PortalException, SystemException {
return OrganizationServiceUtil.addOrganization(
parentId,
headDepartment,
OrganizationConstants.TYPE_REGULAR_ORGANIZATION,
RegionConstants.DEFAULT_REGION_ID,
CountryConstants.DEFAULT_COUNTRY_ID,
ListTypeConstants.ORGANIZATION_STATUS_DEFAULT,
"",
false,
serviceContext
);
}
private User getCurrentUser(PortletRequest request) throws SW360Exception {
User user;
ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);
if (themeDisplay.isSignedIn())
user = themeDisplay.getUser();
else {
throw new SW360Exception("Broken portlet!");
}
return user;
}
private List<UserCSV> getUsersFromRequest(PortletRequest request, String fileUploadFormId) throws IOException, TException {
final UploadPortletRequest uploadPortletRequest = PortalUtil.getUploadPortletRequest(request);
final InputStream stream = uploadPortletRequest.getFileAsStream(fileUploadFormId);
Reader reader = new InputStreamReader(stream);
CSVFormat format = CommonUtils.sw360CsvFormat;
CSVParser parser = new CSVParser(reader, format);
List<CSVRecord> records;
records = parser.getRecords();
if (records.size() > 0) {
records.remove(0); // Remove header
}
return getUsersFromCSV(records);
}
private List<UserCSV> getUsersFromCSV(List<CSVRecord> records) {
List<UserCSV> users = new ArrayList<>();
for (CSVRecord record : records) {
try {
UserCSV user = new UserCSV(record);
users.add(user);
} catch (IndexOutOfBoundsException e) {
log.error("Broken csv record");
}
}
return users;
}
private User dealWithUser(PortletRequest request, UserCSV userRec) {
User user = null;
try {
user = userRec.addLifeRayUser(request);
if (user != null) {
UserUtils.synchronizeUserWithDatabase(userRec, thriftClients, userRec::getEmail, UserUtils::fillThriftUserFromUserCSV);
}
} catch (SystemException | PortalException e) {
log.error("Error creating a new user", e);
}
return user;
}
}