/* * Copyright (c) 2010 Lockheed Martin Corporation * * 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 org.eurekastreams.server.action.validation.settings; import java.io.Serializable; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; import org.eurekastreams.commons.actions.ValidationStrategy; import org.eurekastreams.commons.actions.context.ActionContext; import org.eurekastreams.commons.exceptions.ValidationException; import org.eurekastreams.server.domain.MembershipCriteria; import org.eurekastreams.server.domain.Person; import org.eurekastreams.server.domain.SystemSettings; import org.eurekastreams.server.persistence.mappers.DomainMapper; import org.eurekastreams.server.search.modelview.PersonModelView; /** * Validate UpdateSystemSettingsExecution input. * */ public class UpdateSystemSettingsValidation implements ValidationStrategy<ActionContext> { // TODO: When reactoring, consider using MapParameterValidator so keys and messages are // pushed out into config file rather than hard coded. /** * Last part of a message for too many characters. */ public static final String INPUT_TOO_LONG_MESSAGE = " supports up to " + SystemSettings.MAX_INPUT + " characters"; /** * Site Label Required Error Message. */ public static final String SITE_LABEL_REQUIRED_ERROR_MESSAGE = "Site Label is required"; /** * Site Label Length Error Message. */ public static final String SITE_LABEL_LENGTH_ERROR_MESSAGE = "Site label supports up to " + SystemSettings.MAX_SITELABEL_INPUT + " characters"; /** * Plugin Configuration Warning Required Error Message. */ public static final String PLUGIN_WARNING_REQUIRED_ERROR_MESSAGE = "Plugin Configuration Warning is required"; /** * Terms of Service Required Error Message. */ public static final String TOS_REQUIRED_ERROR_MESSAGE = "Terms of Service is required"; /** * Terms of Service Prompt Interval Invalid Input Error Message. */ public static final String TOS_PROMPT_INTERVAL_INVALID_ERROR_MESSAGE = "Prompt Interval for Terms of " + "Service supports up to 5 numeric characters"; /** * Terms of Service Prompt Interval Minimal Value Error Message. */ public static final String MIN_TOS_PROMPT_INTERVAL_ERROR_MESSAGE = "Prompt Interval for Terms of " + "Service must be " + (SystemSettings.MIN_TOS_PROMPT_INTERVAL) + " or greater"; /** * Content Warning Required Error Message. */ public static final String CONTENT_WARNING_REQUIRED_ERROR_MESSAGE = "Content Warning is required"; /** * Content Warning Length Error Message. */ public static final String CONTENT_WARNING_LENGTH_ERROR_MESSAGE = "Content Warning" + INPUT_TOO_LONG_MESSAGE; /** * Content Expiration Required Error Message. */ public static final String CONTENT_EXPIRATION_REQUIRED_ERROR_MESSAGE = "Activity Expiration is required"; /** * Content Expiration Value Error Message. */ public static final String CONTENT_EXPIRATION_ERROR_MESSAGE = "Activity Expiration must be a number between " + (SystemSettings.MIN_CONTENT_EXPIRATION + 1) + " and " + SystemSettings.MAX_CONTENT_EXPIRATION; /** * System administrators missing error message. */ public static final String SYSTEM_ADMINISTRATORS_EMPTY_ERROR_MESSAGE = "At least one System " + "Administrator required."; /** * At least one of the system admins is locked error message. */ public static final String SYSTEM_ADMINISTRATOR_LOCKED_OUT_ERROR_MESSAGE = // "At least one of the requested administrators is currently locked out of the system: "; /** * * At least one of the system admins is locked error message. */ public static final String SYSTEM_ADMINISTRATOR_NOTFOUND_ERROR_MESSAGE = // "At least one of the requested administrators is not found in the system: "; /** * Mapper to get people by ids. */ private DomainMapper<List<Long>, List<PersonModelView>> peopleByIdsMapper; /** * Constructor. * * @param inPeopleByIdsMapper * mapper to get people by ids */ public UpdateSystemSettingsValidation(final DomainMapper<List<Long>, List<PersonModelView>> inPeopleByIdsMapper) { peopleByIdsMapper = inPeopleByIdsMapper; } /** * Validate UpdateSystemSettingsExecution input. * * @param inActionContext * {@link ActionContext}. * @throws ValidationException * If input is invalid. */ @Override @SuppressWarnings("unchecked") public void validate(final ActionContext inActionContext) throws ValidationException { /* * This is hacky. We are using a unexpected but legal value as our case for if a field is required but not * filled in. For String based fields we are using a return of null to signify they are required and are blank * For Integer based ones we are returning false. * * This is mainly hacky since we know on the front end they are in valid inputs but we send a cryptic message to * the backend (see above) that it in turn alerts the user that it is invalid input. But with out a very decent * sized refactoring this is the best way. */ // TODO: refactor to get better validation. Map<String, Serializable> fields = (Map<String, Serializable>) inActionContext.getParams(); if (fields == null) { throw new ValidationException("UpdateSystemSettings requires Map of form data"); } ValidationException ve = new ValidationException(); if (fields.containsKey("ldapGroups") && ((List<MembershipCriteria>) fields.get("ldapGroups")).size() == 0) { ve.addError("ldapGroups", "At least one entry is required in the access list"); } if (fields.containsKey("contentWarningText") && fields.get("contentWarningText") == null) { ve.addError("contentWarningText", CONTENT_WARNING_REQUIRED_ERROR_MESSAGE); } else if (fields.containsKey("contentWarningText") && ((String) fields.get("contentWarningText")).length() > SystemSettings.MAX_INPUT) { ve.addError("contentWarningText", CONTENT_WARNING_LENGTH_ERROR_MESSAGE); } if (fields.containsKey("siteLabel") && fields.get("siteLabel") == null) { ve.addError("siteLabel", SITE_LABEL_REQUIRED_ERROR_MESSAGE); } else if (fields.containsKey("siteLabel") && ((String) fields.get("siteLabel")).length() > SystemSettings.MAX_SITELABEL_INPUT) { ve.addError("siteLabel", SITE_LABEL_LENGTH_ERROR_MESSAGE); } if (fields.containsKey("termsOfService") && fields.get("termsOfService") == null) { ve.addError("termsOfService", TOS_REQUIRED_ERROR_MESSAGE); } if (fields.containsKey("pluginWarning") && fields.get("pluginWarning") == null) { ve.addError("pluginWarning", PLUGIN_WARNING_REQUIRED_ERROR_MESSAGE); } if (fields.containsKey("contentExpiration") && fields.get("contentExpiration") == null) { ve.addError("contentExpiration", CONTENT_EXPIRATION_REQUIRED_ERROR_MESSAGE); } else if (fields.containsKey("contentExpiration") && !(fields.get("contentExpiration") instanceof Integer)) { ve.addError("contentExpiration", CONTENT_EXPIRATION_ERROR_MESSAGE); } else if (fields.containsKey("contentExpiration") && fields.get("contentExpiration") != null && fields.get("contentExpiration") instanceof Integer && ((Integer) fields.get("contentExpiration") < SystemSettings.MIN_CONTENT_EXPIRATION // || (Integer) fields.get("contentExpiration") > SystemSettings.MAX_CONTENT_EXPIRATION)) { ve.addError("contentExpiration", CONTENT_EXPIRATION_ERROR_MESSAGE); } if (fields.containsKey("tosPromptInterval") && !(fields.get("tosPromptInterval") instanceof Integer)) { ve.addError("tosPromptInterval", TOS_PROMPT_INTERVAL_INVALID_ERROR_MESSAGE); } else if (fields.containsKey("tosPromptInterval") && (Integer) fields.get("tosPromptInterval") < SystemSettings.MIN_TOS_PROMPT_INTERVAL) { ve.addError("tosPromptInterval", MIN_TOS_PROMPT_INTERVAL_ERROR_MESSAGE); } if (!fields.containsKey("admins") || fields.get("admins") == null || ((HashSet<Person>) fields.get("admins")).size() == 0) { ve.addError("admins", SYSTEM_ADMINISTRATORS_EMPTY_ERROR_MESSAGE); } else { boolean adminErrorOccurred = false; // see if the people exist HashSet<Person> requestedAdmins = (HashSet<Person>) fields.get("admins"); List<Long> adminIds = new ArrayList<Long>(); // convert the list of people to people ids for (Person person : requestedAdmins) { adminIds.add(person.getId()); } // get the people from db/cache List<PersonModelView> foundPeople = peopleByIdsMapper.execute(adminIds); // check for locked users String lockedUsers = ""; for (PersonModelView foundPerson : foundPeople) { if (foundPerson.isAccountLocked()) { if (lockedUsers.length() > 0) { lockedUsers += ", "; } lockedUsers += foundPerson.getAccountId(); } } if (lockedUsers.length() > 0) { // some of the users are locked users ve.addError("admins", SYSTEM_ADMINISTRATOR_LOCKED_OUT_ERROR_MESSAGE + lockedUsers); adminErrorOccurred = true; } if (!adminErrorOccurred) { // check for missing users String missingUsers = ""; for (Person requestedAdmin : requestedAdmins) { if (!isPersonIdInPersonList(foundPeople, requestedAdmin.getId())) { // missing person if (missingUsers.length() > 0) { missingUsers += ", "; } missingUsers += requestedAdmin.getAccountId(); } } if (missingUsers.length() > 0) { // some of the users weren't found ve.addError("admins", SYSTEM_ADMINISTRATOR_NOTFOUND_ERROR_MESSAGE + missingUsers); } } } if (!ve.getErrors().isEmpty()) { throw ve; } } /** * Check whether the input person account id is found in the list of people. * * @param inPeople * the list of people to look through * @param inPersonId * the person id to search for * @return whether the person id is found in the input person list */ private boolean isPersonIdInPersonList(final List<PersonModelView> inPeople, final Long inPersonId) { for (PersonModelView person : inPeople) { if (person.getId() == inPersonId) { return true; } } return false; } /** * @param inEmailToTest * email to test. * @return if email is valid. */ private boolean isValidEmailAddress(final String inEmailToTest) { boolean result = true; try { InternetAddress emailAddr = new InternetAddress(inEmailToTest); if (!fullAddress(inEmailToTest)) { result = false; } } catch (AddressException ex) { result = false; } return result; } /** * @param inEmailAddress * email to test. * @return checks to see if email has a domain. */ private boolean fullAddress(final String inEmailAddress) { String[] addressTokens = inEmailAddress.split("@"); return addressTokens.length == 2; } }