001/* 002 * Copyright 2012 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.core.userpref; 017 018import java.text.DateFormat; 019import java.text.ParseException; 020import java.text.SimpleDateFormat; 021import java.util.Collection; 022import java.util.Collections; 023import java.util.Date; 024import java.util.HashMap; 025import java.util.HashSet; 026import java.util.Map; 027import java.util.Set; 028 029import org.apache.avalon.framework.parameters.Parameters; 030import org.apache.avalon.framework.service.ServiceException; 031import org.apache.avalon.framework.service.ServiceManager; 032import org.apache.cocoon.environment.ObjectModelHelper; 033import org.apache.cocoon.environment.Redirector; 034import org.apache.cocoon.environment.Request; 035import org.apache.cocoon.environment.SourceResolver; 036import org.apache.commons.lang.StringUtils; 037 038import org.ametys.core.user.UserIdentity; 039import org.ametys.core.userpref.UserPreference; 040import org.ametys.core.userpref.UserPreferenceProvider; 041import org.ametys.core.userpref.UserPreferencesErrors; 042import org.ametys.core.userpref.UserPreferencesException; 043import org.ametys.core.userpref.UserPreferencesExtensionPoint; 044import org.ametys.core.userpref.UserPreferencesManager; 045import org.ametys.core.util.cocoon.AbstractCurrentUserProviderServiceableAction; 046import org.ametys.runtime.i18n.I18nizableText; 047import org.ametys.runtime.parameter.ParameterHelper; 048import org.ametys.runtime.parameter.ParameterHelper.ParameterType; 049import org.ametys.runtime.workspace.WorkspaceMatcher; 050 051/** 052 * Action which saves the user preferences values into the database. 053 */ 054public class SetUserPreferencesAction extends AbstractCurrentUserProviderServiceableAction 055{ 056 057 /** The input date format. */ 058 protected static final Set<DateFormat> _INPUT_DATE_FORMATS = new HashSet<>(); 059 static 060 { 061 _INPUT_DATE_FORMATS.add(new SimpleDateFormat("yyyy-MM-dd")); 062 _INPUT_DATE_FORMATS.add(new SimpleDateFormat("dd/MM/yyyy")); 063 } 064 065 /** The user preferences extension point. */ 066 protected UserPreferencesExtensionPoint _userPrefEP; 067 068 /** The user preferences manager. */ 069 protected UserPreferencesManager _userPrefManager; 070 071 @Override 072 public void service(ServiceManager serviceManager) throws ServiceException 073 { 074 super.service(serviceManager); 075 } 076 077 @SuppressWarnings("unchecked") 078 @Override 079 public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception 080 { 081 if (_userPrefEP == null) 082 { 083 _userPrefEP = (UserPreferencesExtensionPoint) manager.lookup(UserPreferencesExtensionPoint.ROLE); 084 _userPrefManager = (UserPreferencesManager) manager.lookup(UserPreferencesManager.ROLE); 085 } 086 087 Request request = ObjectModelHelper.getRequest(objectModel); 088 Map<String, Object> parentContext = (Map<String, Object>) objectModel.get(ObjectModelHelper.PARENT_CONTEXT); 089 090 String storageContext = getStorageContext(request, parameters); 091 UserIdentity user = getUser(request, parameters); 092 093 String submit = request.getParameter("submit"); 094 095 Map<String, String> results = new HashMap<>(); 096 097 if ("true".equals(submit)) 098 { 099 Collection<String> preferenceIds = getPreferenceIds(request, parentContext); 100 Map<String, String> contextVars = getContextVars(request); 101 102 results = setUserPreferences(request, storageContext, contextVars, user, preferenceIds); 103 } 104 105 return results; 106 } 107 108 /** 109 * Get the user 110 * @param request The request 111 * @param parameters The sitemap parameters 112 * @return the user 113 */ 114 protected UserIdentity getUser(Request request, Parameters parameters) 115 { 116 String username = parameters.getParameter("username", ""); 117 String userPopulation = parameters.getParameter("userpopulation", ""); 118 UserIdentity user; 119 if (StringUtils.isEmpty(username) || StringUtils.isEmpty(userPopulation)) 120 { 121 user = _getCurrentUser(); 122 } 123 else 124 { 125 user = new UserIdentity(username, userPopulation); 126 } 127 128 return user; 129 } 130 131 /** 132 * Get the context of user's preference storage 133 * @param request The request 134 * @param parameters The sitemap parameters 135 * @return the storage context 136 */ 137 protected String getStorageContext(Request request, Parameters parameters) 138 { 139 return parameters.getParameter("prefContext", request.getParameter("prefContext")); 140 } 141 142 /** 143 * Set user preferences. 144 * @param request the request. 145 * @param storageContext the preferences storage context. 146 * @param contextVars the preferences context map. 147 * @param user the user. 148 * @return the results. 149 * @throws UserPreferencesException if an error occurred 150 */ 151 protected Map<String, String> setUserPreferences(Request request, String storageContext, Map<String, String> contextVars, UserIdentity user) throws UserPreferencesException 152 { 153 return setUserPreferences(request, storageContext, contextVars, user, Collections.<String>emptySet()); 154 } 155 156 /** 157 * Set user preferences. 158 * @param request the request. 159 * @param storageContext the preferences context. 160 * @param contextVars the preferences context map. 161 * @param user the user. 162 * @param preferenceIds a collection of the IDs of preferences to set. 163 * @return the results. 164 * @throws UserPreferencesException if an error occurred 165 */ 166 protected Map<String, String> setUserPreferences(Request request, String storageContext, Map<String, String> contextVars, UserIdentity user, Collection<String> preferenceIds) throws UserPreferencesException 167 { 168 Map<String, String> results = new HashMap<>(); 169 170 results.put("status", "error"); 171 172 Map<String, String> values = _userPrefManager.getUnTypedUserPrefs(user, storageContext, contextVars); 173 174 UserPreferencesErrors errors = new UserPreferencesErrors(); 175 176 // Override the old values with the new ones, but keep old values when new preferences are not in the request. 177 values.putAll(_getValues(request, contextVars, user, preferenceIds, errors)); 178 179 // Validate the user preferences, filling in potential errors. 180 _userPrefEP.validatePreferences(contextVars, values, errors); 181 182 if (!errors.hasErrors()) 183 { 184 _userPrefManager.setUserPreferences(user, storageContext, contextVars, values); 185 results.put("status", "success"); 186 } 187 else 188 { 189 request.setAttribute("user-prefs-errors", errors); 190 } 191 192 return results; 193 } 194 195 /** 196 * Get the preferences values from the request. 197 * @param request the request. 198 * @param contextVars The context vars 199 * @param user the user. 200 * @param preferenceIds a collection of the IDs of preferences to set. 201 * @param errors the errors object to fill in. 202 * @return the user preferences values as a Map. 203 */ 204 protected Map<String, String> _getValues(Request request, Map<String, String> contextVars, UserIdentity user, Collection<String> preferenceIds, UserPreferencesErrors errors) 205 { 206 Map<String, String> preferences = new HashMap<>(); 207 208 for (UserPreference preference : _userPrefEP.getUserPreferences(contextVars).values()) 209 { 210 String id = preference.getId(); 211 if (preference.getType() == ParameterType.DATE) 212 { 213 String value = request.getParameter(id); 214 if (value != null) 215 { 216 if (StringUtils.isBlank(value)) 217 { 218 preferences.put(id, value); 219 } 220 else 221 { 222 Date date = _parseDate(value); 223 if (date != null) 224 { 225 preferences.put(id, ParameterHelper.valueToString(date)); 226 } 227 } 228 } 229 } 230 else if (preference.getType() == ParameterType.PASSWORD) 231 { 232 // Password: if no new value is provided, keep the old value. 233 String value = request.getParameter(id); 234 if (StringUtils.isNotBlank(value)) 235 { 236 // Check if the confirmation match. 237 String confirmationValue = request.getParameter(id + "-confirmation"); 238 if (!value.equals(confirmationValue)) 239 { 240 errors.addError(id, new I18nizableText("plugin.core", "PLUGINS_CORE_UI_USER_PREFERENCES_PWD_CONFIRMATION_DOESNT_MATCH")); 241 } 242 preferences.put(id, value); 243 } 244 } 245 else if (preference.getType() == ParameterType.BOOLEAN && preferenceIds.contains(id)) 246 { 247 // Boolean value: if the preference is set if in the request, it's true, if it's not, it's false. 248 // So, check that the preference was wanted (present in preferenceIds). 249 String value = request.getParameter(id); 250 String valueStr = String.valueOf("true".equals(value)); 251 preferences.put(id, valueStr); 252 } 253 else 254 { 255 String[] values = request.getParameterValues(id); 256 if (values != null) 257 { 258 String valuesStr = StringUtils.join(values, ','); 259 preferences.put(id, valuesStr); 260 } 261 } 262 } 263 264 return preferences; 265 } 266 267 /** 268 * Parse a user-submitted date. 269 * @param value the date value as a String. 270 * @return the Date. 271 */ 272 protected Date _parseDate(String value) 273 { 274 Date date = null; 275 for (DateFormat format : _INPUT_DATE_FORMATS) 276 { 277 try 278 { 279 date = format.parse(value); 280 return date; 281 } 282 catch (ParseException e) 283 { 284 // Ignore. 285 } 286 } 287 return date; 288 } 289 290 /** 291 * Get the preferences context variables. 292 * @param request the request. 293 * @return the preferences context as a Map. 294 */ 295 protected Map<String, String> getContextVars(Request request) 296 { 297 Map<String, String> contextVars = new HashMap<>(); 298 contextVars.put(UserPreferenceProvider.CONTEXT_VAR_WORKSPACE, (String) request.getAttribute(WorkspaceMatcher.WORKSPACE_NAME)); 299 return contextVars; 300 } 301 302 /** 303 * Get the preferences to set. 304 * @param request the request. 305 * @param parentContext the parent context. 306 * @return a collection of the IDs of preferences to set. 307 */ 308 protected Collection<String> getPreferenceIds(Request request, Map<String, Object> parentContext) 309 { 310 return Collections.emptySet(); 311 } 312 313}