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