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