/*******************************************************************************
* Copyright (c) 2012-2015 Codenvy, S.A.
* 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
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.api.factory;
import org.eclipse.che.api.account.server.dao.AccountDao;
import org.eclipse.che.api.account.server.dao.Member;
import org.eclipse.che.api.core.ApiException;
import org.eclipse.che.api.core.ConflictException;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.factory.dto.Action;
import org.eclipse.che.api.factory.dto.Factory;
import org.eclipse.che.api.factory.dto.OnAppLoaded;
import org.eclipse.che.api.factory.dto.OnProjectOpened;
import org.eclipse.che.api.factory.dto.Policies;
import org.eclipse.che.api.factory.dto.Workspace;
import org.eclipse.che.api.user.server.dao.PreferenceDao;
import org.eclipse.che.api.user.server.dao.User;
import org.eclipse.che.api.user.server.dao.UserDao;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import static java.lang.Boolean.parseBoolean;
import static com.google.common.base.Strings.emptyToNull;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.lang.String.format;
/**
* Validates values of factory parameters.
*
* @author Alexander Garagatyi
* @author Valeriy Svydenko
*/
public abstract class FactoryBaseValidator {
private static final Pattern PROJECT_NAME_VALIDATOR = Pattern.compile("^[\\\\\\w\\\\\\d]+[\\\\\\w\\\\\\d_.-]*$");
private final AccountDao accountDao;
private final UserDao userDao;
private final PreferenceDao preferenceDao;
public FactoryBaseValidator(AccountDao accountDao,
UserDao userDao,
PreferenceDao preferenceDao) {
this.accountDao = accountDao;
this.userDao = userDao;
this.preferenceDao = preferenceDao;
}
/**
* Validates source parameter of factory.
* TODO for now validates only git source
*
* @param factory
* - factory to validate
* @throws ApiException
*/
protected void validateSource(Factory factory) throws ApiException {
String type = factory.getSource().getProject().getType();
String location = factory.getSource().getProject().getLocation();
String parameterTypeName = "source.project.type";
String parameterLocationName = "source.project.location";
// check that vcs value is correct
if (!("git".equals(type) || "esbwso2".equals(type))) {
throw new ConflictException("Parameter '" + parameterTypeName + "' has illegal value.");
}
if (isNullOrEmpty(location)) {
throw new ConflictException(
format(FactoryConstants.PARAMETRIZED_ILLEGAL_PARAMETER_VALUE_MESSAGE, parameterLocationName, location));
} else {
try {
URLDecoder.decode(location, "UTF-8");
} catch (IllegalArgumentException | UnsupportedEncodingException e) {
throw new ConflictException(
format(FactoryConstants.PARAMETRIZED_ILLEGAL_PARAMETER_VALUE_MESSAGE, parameterLocationName, location));
}
}
}
protected void validateProjectName(Factory factory) throws ApiException {
// validate project name
String projectName = null;
switch (factory.getV()) {
case "2.0":
case "2.1":
if (null != factory.getProject()) {
projectName = factory.getProject().getName();
}
break;
default:
// do nothing
}
if (null != projectName && !PROJECT_NAME_VALIDATOR.matcher(projectName).matches()) {
throw new ConflictException(
"Project name must contain only Latin letters, digits or these following special characters -._.");
}
}
protected void validateWorkspace(Factory factory) throws ApiException {
final Workspace workspace = factory.getWorkspace();
if (workspace == null) {
return;
}
if (workspace.getType() != null) {
if (!workspace.getType().equals("named") && !workspace.getType().equals("temp")) {
throw new ConflictException("workspace.type have only two possible values - named or temp");
}
}
if (workspace.getLocation() != null) {
if (!workspace.getLocation().equals("owner") && !workspace.getLocation().equals("acceptor")) {
throw new ConflictException("workspace.location have only two possible values - owner or acceptor");
}
}
}
protected void validateCreator(Factory factory) throws ApiException {
final Workspace workspace = factory.getWorkspace();
if (workspace == null || workspace.getLocation() == null) {
return;
}
if (workspace.getLocation().equals("owner")) {
String accountId = factory.getCreator() != null ? emptyToNull(factory.getCreator().getAccountId()) : null;
if (accountId == null) {
throw new ConflictException("current workspace location requires factory creator accountId to be set");
}
}
}
protected void validateAccountId(Factory factory) throws ApiException {
// TODO do we need check if user is temporary?
String accountId = factory.getCreator() != null ? emptyToNull(factory.getCreator().getAccountId()) : null;
String userId = factory.getCreator() != null ? factory.getCreator().getUserId() : null;
if (accountId == null || userId == null) {
return;
}
try {
Map<String, String> preferences = preferenceDao.getPreferences(userId);
if (parseBoolean(preferences.get("temporary"))) {
throw new ConflictException("Current user is not allowed for using this method.");
}
boolean isOwner = false;
List<Member> members = accountDao.getMembers(accountId);
if (members.isEmpty()) {
throw new ConflictException(String.format(FactoryConstants.PARAMETRIZED_ILLEGAL_ACCOUNTID_PARAMETER_MESSAGE, accountId));
}
User user = userDao.getById(userId);
for (Member accountMember : members) {
if (accountMember.getUserId().equals(user.getId()) && accountMember.getRoles().contains("account/owner")) {
isOwner = true;
break;
}
}
if (!isOwner) {
throw new ConflictException("You are not authorized to use this accountId.");
}
} catch (NotFoundException | ServerException e) {
throw new ConflictException("You are not authorized to use this accountId.");
}
}
protected void validateCurrentTimeBetweenSinceUntil(Factory factory) throws ConflictException {
final Policies policies = factory.getPolicies();
if (policies == null) {
return;
}
Long validSince = policies.getValidSince();
Long validUntil = policies.getValidUntil();
if (validSince != null && validSince != 0) {
if (new Date().before(new Date(validSince))) {
throw new ConflictException(FactoryConstants.ILLEGAL_FACTORY_BY_VALIDSINCE_MESSAGE);
}
}
if (validUntil != null && validUntil != 0) {
if (new Date().after(new Date(validUntil))) {
throw new ConflictException(FactoryConstants.ILLEGAL_FACTORY_BY_VALIDUNTIL_MESSAGE);
}
}
}
protected void validateCurrentTimeBeforeSinceUntil(Factory factory) throws ConflictException {
final Policies policies = factory.getPolicies();
if (policies == null) {
return;
}
Long validSince = policies.getValidSince();
Long validUntil = policies.getValidUntil();
if (validSince != null && validSince != 0 && validUntil != null && validUntil != 0 && validSince >= validUntil) {
throw new ConflictException(FactoryConstants.INVALID_VALIDSINCEUNTIL_MESSAGE);
}
if (validSince != null && validSince != 0 && new Date().after(new Date(validSince))) {
throw new ConflictException(FactoryConstants.INVALID_VALIDSINCE_MESSAGE);
}
if (validUntil != null && validUntil != 0 && new Date().after(new Date(validUntil))) {
throw new ConflictException(FactoryConstants.INVALID_VALIDUNTIL_MESSAGE);
}
}
protected void validateProjectActions(Factory factory) throws ConflictException {
if (!"2.1".equals(factory.getV()) || factory.getIde() == null) {
return;
}
List<Action> applicationActions = new ArrayList<>();
if (factory.getIde().getOnAppClosed() != null) {
applicationActions.addAll(factory.getIde().getOnAppClosed().getActions());
}
if (factory.getIde().getOnAppLoaded() != null) {
applicationActions.addAll(factory.getIde().getOnAppLoaded().getActions());
}
for (Action applicationAction : applicationActions) {
String id = applicationAction.getId();
if ("openFile".equals(id) || "findReplace".equals(id)) {
throw new ConflictException(String.format(FactoryConstants.INVALID_ACTION_SECTION, id));
}
}
final OnAppLoaded onAppLoaded = factory.getIde().getOnAppLoaded();
if (onAppLoaded != null) {
final List<Action> actions = onAppLoaded.getActions();
if (actions != null) {
for (Action action : actions) {
final Map<String, String> properties = action.getProperties();
if ("openWelcomePage".equals(action.getId()) && (isNullOrEmpty(properties.get("nonAuthenticatedContentUrl")) ||
isNullOrEmpty(properties.get("authenticatedContentUrl")))) {
throw new ConflictException(FactoryConstants.INVALID_WELCOME_PAGE_ACTION);
}
}
}
}
OnProjectOpened onOpened = factory.getIde().getOnProjectOpened();
if (onOpened != null) {
List<Action> onProjectOpenedActions = onOpened.getActions();
for (Action applicationAction : onProjectOpenedActions) {
String id = applicationAction.getId();
Map<String, String> properties = applicationAction.getProperties();
switch (id) {
case "openFile":
if (isNullOrEmpty(properties.get("file"))) {
throw new ConflictException(FactoryConstants.INVALID_OPENFILE_ACTION);
}
break;
case "findReplace":
if (isNullOrEmpty(properties.get("in")) ||
isNullOrEmpty(properties.get("find")) ||
isNullOrEmpty(properties.get("replace"))) {
throw new ConflictException(FactoryConstants.INVALID_FIND_REPLACE_ACTION);
}
break;
}
}
}
}
}