001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.login.action;
016    
017    import com.liferay.portal.NoSuchUserException;
018    import com.liferay.portal.RequiredReminderQueryException;
019    import com.liferay.portal.SendPasswordException;
020    import com.liferay.portal.UserActiveException;
021    import com.liferay.portal.UserEmailAddressException;
022    import com.liferay.portal.UserLockoutException;
023    import com.liferay.portal.UserReminderQueryException;
024    import com.liferay.portal.kernel.captcha.CaptchaConfigurationException;
025    import com.liferay.portal.kernel.captcha.CaptchaException;
026    import com.liferay.portal.kernel.captcha.CaptchaTextException;
027    import com.liferay.portal.kernel.captcha.CaptchaUtil;
028    import com.liferay.portal.kernel.language.LanguageUtil;
029    import com.liferay.portal.kernel.servlet.SessionErrors;
030    import com.liferay.portal.kernel.util.ParamUtil;
031    import com.liferay.portal.kernel.util.Validator;
032    import com.liferay.portal.model.Company;
033    import com.liferay.portal.model.User;
034    import com.liferay.portal.security.auth.PrincipalException;
035    import com.liferay.portal.service.UserLocalServiceUtil;
036    import com.liferay.portal.struts.PortletAction;
037    import com.liferay.portal.theme.ThemeDisplay;
038    import com.liferay.portal.util.PortalUtil;
039    import com.liferay.portal.util.PropsValues;
040    import com.liferay.portal.util.WebKeys;
041    import com.liferay.portlet.login.util.LoginUtil;
042    
043    import javax.portlet.ActionRequest;
044    import javax.portlet.ActionResponse;
045    import javax.portlet.PortletConfig;
046    import javax.portlet.PortletPreferences;
047    import javax.portlet.PortletSession;
048    import javax.portlet.RenderRequest;
049    import javax.portlet.RenderResponse;
050    
051    import org.apache.struts.action.ActionForm;
052    import org.apache.struts.action.ActionForward;
053    import org.apache.struts.action.ActionMapping;
054    
055    /**
056     * @author Brian Wing Shun Chan
057     * @author Tibor Kovacs
058     */
059    public class ForgotPasswordAction extends PortletAction {
060    
061            @Override
062            public void processAction(
063                            ActionMapping actionMapping, ActionForm actionForm,
064                            PortletConfig portletConfig, ActionRequest actionRequest,
065                            ActionResponse actionResponse)
066                    throws Exception {
067    
068                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
069                            WebKeys.THEME_DISPLAY);
070    
071                    Company company = themeDisplay.getCompany();
072    
073                    if (!company.isSendPassword() && !company.isSendPasswordResetLink()) {
074                            throw new PrincipalException();
075                    }
076    
077                    try {
078                            if (PropsValues.USERS_REMINDER_QUERIES_ENABLED) {
079                                    checkReminderQueries(actionRequest, actionResponse);
080                            }
081                            else {
082                                    checkCaptcha(actionRequest);
083    
084                                    sendPassword(actionRequest, actionResponse);
085                            }
086                    }
087                    catch (Exception e) {
088                            if (e instanceof CaptchaConfigurationException ||
089                                    e instanceof CaptchaTextException ||
090                                    e instanceof UserEmailAddressException) {
091    
092                                    SessionErrors.add(actionRequest, e.getClass());
093                            }
094                            else if (e instanceof NoSuchUserException ||
095                                             e instanceof RequiredReminderQueryException ||
096                                             e instanceof SendPasswordException ||
097                                             e instanceof UserActiveException ||
098                                             e instanceof UserLockoutException ||
099                                             e instanceof UserReminderQueryException) {
100    
101                                    if (PropsValues.LOGIN_SECURE_FORGOT_PASSWORD) {
102                                            sendRedirect(actionRequest, actionResponse);
103                                    }
104                                    else {
105                                            SessionErrors.add(actionRequest, e.getClass(), e);
106                                    }
107                            }
108                            else {
109                                    PortalUtil.sendError(e, actionRequest, actionResponse);
110                            }
111                    }
112            }
113    
114            @Override
115            public ActionForward render(
116                            ActionMapping actionMapping, ActionForm actionForm,
117                            PortletConfig portletConfig, RenderRequest renderRequest,
118                            RenderResponse renderResponse)
119                    throws Exception {
120    
121                    ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.getAttribute(
122                            WebKeys.THEME_DISPLAY);
123    
124                    Company company = themeDisplay.getCompany();
125    
126                    if (!company.isSendPassword() && !company.isSendPasswordResetLink()) {
127                            return actionMapping.findForward("portlet.login.login");
128                    }
129    
130                    renderResponse.setTitle(themeDisplay.translate("forgot-password"));
131    
132                    return actionMapping.findForward("portlet.login.forgot_password");
133            }
134    
135            protected void checkCaptcha(ActionRequest actionRequest)
136                    throws CaptchaException {
137    
138                    if (PropsValues.CAPTCHA_CHECK_PORTAL_SEND_PASSWORD) {
139                            CaptchaUtil.check(actionRequest);
140                    }
141            }
142    
143            protected void checkReminderQueries(
144                            ActionRequest actionRequest, ActionResponse actionResponse)
145                    throws Exception {
146    
147                    PortletSession portletSession = actionRequest.getPortletSession();
148    
149                    int step = ParamUtil.getInteger(actionRequest, "step");
150    
151                    if (step == 1) {
152                            checkCaptcha(actionRequest);
153    
154                            portletSession.removeAttribute(
155                                    WebKeys.FORGOT_PASSWORD_REMINDER_ATTEMPTS);
156                            portletSession.removeAttribute(
157                                    WebKeys.FORGOT_PASSWORD_REMINDER_USER_EMAIL_ADDRESS);
158                    }
159    
160                    User user = getUser(actionRequest);
161    
162                    portletSession.setAttribute(
163                            WebKeys.FORGOT_PASSWORD_REMINDER_USER_EMAIL_ADDRESS,
164                            user.getEmailAddress());
165    
166                    actionRequest.setAttribute(WebKeys.FORGOT_PASSWORD_REMINDER_USER, user);
167    
168                    if (step == 2) {
169                            Integer reminderAttempts = (Integer)portletSession.getAttribute(
170                                    WebKeys.FORGOT_PASSWORD_REMINDER_ATTEMPTS);
171    
172                            if (reminderAttempts == null) {
173                                    reminderAttempts = 0;
174                            }
175                            else if (reminderAttempts > 2) {
176                                    checkCaptcha(actionRequest);
177                            }
178    
179                            reminderAttempts++;
180    
181                            portletSession.setAttribute(
182                                    WebKeys.FORGOT_PASSWORD_REMINDER_ATTEMPTS, reminderAttempts);
183    
184                            sendPassword(actionRequest, actionResponse);
185                    }
186            }
187    
188            protected User getUser(ActionRequest actionRequest) throws Exception {
189                    PortletSession portletSession = actionRequest.getPortletSession();
190    
191                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
192                            WebKeys.THEME_DISPLAY);
193    
194                    String sessionEmailAddress = (String)portletSession.getAttribute(
195                            WebKeys.FORGOT_PASSWORD_REMINDER_USER_EMAIL_ADDRESS);
196    
197                    User user = null;
198    
199                    if (Validator.isNotNull(sessionEmailAddress)) {
200                            user = UserLocalServiceUtil.getUserByEmailAddress(
201                                    themeDisplay.getCompanyId(), sessionEmailAddress);
202                    }
203                    else {
204                            long userId = ParamUtil.getLong(actionRequest, "userId");
205                            String screenName = ParamUtil.getString(
206                                    actionRequest, "screenName");
207                            String emailAddress = ParamUtil.getString(
208                                    actionRequest, "emailAddress");
209    
210                            if (Validator.isNotNull(emailAddress)) {
211                                    user = UserLocalServiceUtil.getUserByEmailAddress(
212                                            themeDisplay.getCompanyId(), emailAddress);
213                            }
214                            else if (Validator.isNotNull(screenName)) {
215                                    user = UserLocalServiceUtil.getUserByScreenName(
216                                            themeDisplay.getCompanyId(), screenName);
217                            }
218                            else if (userId > 0) {
219                                    user = UserLocalServiceUtil.getUserById(userId);
220                            }
221                            else {
222                                    throw new NoSuchUserException();
223                            }
224                    }
225    
226                    if (!user.isActive()) {
227                            throw new UserActiveException();
228                    }
229    
230                    UserLocalServiceUtil.checkLockout(user);
231    
232                    return user;
233            }
234    
235            @Override
236            protected boolean isCheckMethodOnProcessAction() {
237                    return _CHECK_METHOD_ON_PROCESS_ACTION;
238            }
239    
240            protected void sendPassword(
241                            ActionRequest actionRequest, ActionResponse actionResponse)
242                    throws Exception {
243    
244                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
245                            WebKeys.THEME_DISPLAY);
246    
247                    Company company = themeDisplay.getCompany();
248    
249                    User user = getUser(actionRequest);
250    
251                    if (PropsValues.USERS_REMINDER_QUERIES_ENABLED) {
252                            if (PropsValues.USERS_REMINDER_QUERIES_REQUIRED &&
253                                    !user.hasReminderQuery()) {
254    
255                                    throw new RequiredReminderQueryException(
256                                            "No reminder query or answer is defined for user " +
257                                                    user.getUserId());
258                            }
259    
260                            String answer = ParamUtil.getString(actionRequest, "answer");
261    
262                            if (!user.getReminderQueryAnswer().equals(answer)) {
263                                    throw new UserReminderQueryException();
264                            }
265                    }
266    
267                    PortletPreferences portletPreferences = actionRequest.getPreferences();
268    
269                    String languageId = LanguageUtil.getLanguageId(actionRequest);
270    
271                    String emailFromName = portletPreferences.getValue(
272                            "emailFromName", null);
273                    String emailFromAddress = portletPreferences.getValue(
274                            "emailFromAddress", null);
275                    String emailToAddress = user.getEmailAddress();
276    
277                    String emailParam = "emailPasswordSent";
278    
279                    if (company.isSendPasswordResetLink()) {
280                            emailParam = "emailPasswordReset";
281                    }
282    
283                    String subject = portletPreferences.getValue(
284                            emailParam + "Subject_" + languageId, null);
285                    String body = portletPreferences.getValue(
286                            emailParam + "Body_" + languageId, null);
287    
288                    LoginUtil.sendPassword(
289                            actionRequest, emailFromName, emailFromAddress, emailToAddress,
290                            subject, body);
291    
292                    sendRedirect(actionRequest, actionResponse);
293            }
294    
295            private static final boolean _CHECK_METHOD_ON_PROCESS_ACTION = false;
296    
297    }