package org.apereo.cas.pm.web.flow; import org.apache.commons.lang3.StringUtils; import org.apereo.cas.configuration.CasConfigurationProperties; import org.apereo.cas.configuration.model.support.pm.PasswordManagementProperties; import org.apereo.cas.pm.PasswordManagementService; import org.apereo.cas.util.io.CommunicationsManager; import org.apereo.cas.web.support.WebUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.webflow.action.AbstractAction; import org.springframework.webflow.execution.Event; import org.springframework.webflow.execution.RequestContext; import javax.servlet.http.HttpServletRequest; import static org.apereo.cas.pm.web.flow.PasswordManagementWebflowConfigurer.*; /** * This is {@link SendPasswordResetInstructionsAction}. * * @author Misagh Moayyed * @since 5.0.0 */ public class SendPasswordResetInstructionsAction extends AbstractAction { /** Param name for the token. */ public static final String PARAMETER_NAME_TOKEN = "t"; private static final Logger LOGGER = LoggerFactory.getLogger(SendPasswordResetInstructionsAction.class); @Autowired private CasConfigurationProperties casProperties; private final CommunicationsManager communicationsManager; private PasswordManagementService passwordManagementService; public SendPasswordResetInstructionsAction(final CommunicationsManager communicationsManager, final PasswordManagementService passwordManagementService) { this.communicationsManager = communicationsManager; this.passwordManagementService = passwordManagementService; } @Override protected Event doExecute(final RequestContext requestContext) throws Exception { if (!communicationsManager.isMailSenderDefined()) { LOGGER.warn("CAS is unable to send password-reset emails given no settings are defined to account for email servers"); return error(); } final PasswordManagementProperties pm = casProperties.getAuthn().getPm(); final HttpServletRequest request = WebUtils.getHttpServletRequest(requestContext); final String username = request.getParameter("username"); if (StringUtils.isBlank(username)) { LOGGER.warn("No username is provided"); return error(); } final String to = passwordManagementService.findEmail(username); if (StringUtils.isBlank(to)) { LOGGER.warn("No recipient is provided"); return error(); } final String token = passwordManagementService.createToken(username); final String url = casProperties.getServer().getPrefix() .concat('/' + FLOW_ID_PASSWORD_RESET + '?' + PARAMETER_NAME_TOKEN + '=').concat(token); LOGGER.debug("Generated password reset URL [{}]; Link is only active for the next [{}] minute(s)", url, pm.getReset().getExpirationMinutes()); if (sendPasswordResetEmailToAccount(to, url)) { return success(); } LOGGER.error("Failed to notify account [{}]", to); return error(); } /** * Send password reset email to account. * * @param to the to * @param url the url * @return true/false */ protected boolean sendPasswordResetEmailToAccount(final String to, final String url) { final PasswordManagementProperties.Reset reset = casProperties.getAuthn().getPm().getReset(); final String text = String.format(reset.getText(), url); return this.communicationsManager.email(text, reset.getFrom(), reset.getSubject(), to, null, null); } }