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