org.openmrs.module.personalhr.web.controller.ForgotPasswordFormController.java Source code

Java tutorial

Introduction

Here is the source code for org.openmrs.module.personalhr.web.controller.ForgotPasswordFormController.java

Source

/**
 * The contents of this file are subject to the OpenMRS Public License
 * Version 1.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://license.openmrs.org
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 *
 * Copyright (C) OpenMRS, LLC.  All Rights Reserved.
 */
package org.openmrs.module.personalhr.web.controller;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openmrs.User;
import org.openmrs.api.context.Context;
import org.openmrs.util.OpenmrsConstants;
import org.openmrs.web.WebConstants;
import org.springframework.validation.BindException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;
import org.springframework.web.servlet.view.RedirectView;

/**
 * Controls the forgotten password form Initially a form with just a username box is shown Then a
 * box for the answer to the secret question is shown
 */
public class ForgotPasswordFormController extends SimpleFormController {

    /** Logger for this class and subclasses */
    protected static final Log log = LogFactory.getLog(ForgotPasswordFormController.class);

    /**
     * Not used with the forgot password form controller.
     * 
     * @see org.springframework.web.servlet.mvc.AbstractFormController#formBackingObject(javax.servlet.http.HttpServletRequest)
     */
    protected Object formBackingObject(HttpServletRequest request) throws ServletException {

        return "";
    }

    /**
     * The mapping from user's IP address to the number of attempts at logging in from that IP
     */
    private Map<String, Integer> loginAttemptsByIP = new HashMap<String, Integer>();

    /**
     * The mapping from user's IP address to the time that they were locked out
     */
    private Map<String, Date> lockoutDateByIP = new HashMap<String, Date>();

    /**
     * This takes in the form twice. The first time when the input their username and the second
     * when they submit both their username and their secret answer
     * 
     * @see org.springframework.web.servlet.mvc.SimpleFormController#onSubmit(javax.servlet.http.HttpServletRequest,
     *      javax.servlet.http.HttpServletResponse, java.lang.Object,
     *      org.springframework.validation.BindException)
     */
    protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object obj,
            BindException errors) throws Exception {

        HttpSession httpSession = request.getSession();

        String username = request.getParameter("uname");

        String ipAddress = request.getLocalAddr();
        Integer forgotPasswordAttempts = loginAttemptsByIP.get(ipAddress);
        if (forgotPasswordAttempts == null)
            forgotPasswordAttempts = 1;

        boolean lockedOut = false;

        if (forgotPasswordAttempts > 5) {
            lockedOut = true;

            Date lockedOutTime = lockoutDateByIP.get(ipAddress);
            if (lockedOutTime != null && new Date().getTime() - lockedOutTime.getTime() > 300000) {
                lockedOut = false;
                forgotPasswordAttempts = 0;
                lockoutDateByIP.put(ipAddress, null);
            } else {
                // they haven't been locked out before, or they're trying again
                // within the time limit.  Set the locked-out date to right now
                lockoutDateByIP.put(ipAddress, new Date());
            }

        }

        if (lockedOut) {
            httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, "auth.forgotPassword.tooManyAttempts");
        } else {
            // if the previous logic didn't determine that the user should be locked out,
            // then continue with the check

            forgotPasswordAttempts++;

            String secretAnswer = request.getParameter("secretAnswer");
            if (secretAnswer == null) {
                // if they are seeing this page for the first time

                User user = null;

                try {
                    Context.addProxyPrivilege(OpenmrsConstants.PRIV_VIEW_USERS);

                    // only search if they actually put in a username
                    if (username != null && username.length() > 0)
                        user = Context.getUserService().getUserByUsername(username);
                } finally {
                    Context.removeProxyPrivilege(OpenmrsConstants.PRIV_VIEW_USERS);
                }

                if (user == null || user.getSecretQuestion() == null || user.getSecretQuestion().equals("")) {
                    httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, "auth.question.empty");
                } else {
                    httpSession.setAttribute(WebConstants.OPENMRS_MSG_ATTR, "auth.question.fill");
                    request.setAttribute("secretQuestion", user.getSecretQuestion());

                    // reset the forgotPasswordAttempts because they have a right user.
                    // they will now have 5 more chances to get the question right
                    forgotPasswordAttempts = 0;
                }

            } else if (secretAnswer != null) {
                // if they've filled in the username and entered their secret answer

                User user = null;

                try {
                    Context.addProxyPrivilege(OpenmrsConstants.PRIV_VIEW_USERS);
                    user = Context.getUserService().getUserByUsername(username);
                } finally {
                    Context.removeProxyPrivilege(OpenmrsConstants.PRIV_VIEW_USERS);
                }

                // check the secret question again in case the user got here "illegally"
                if (user == null || user.getSecretQuestion() == null || user.getSecretQuestion().equals("")) {
                    httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, "auth.question.empty");
                } else if (user.getSecretQuestion() != null
                        && Context.getUserService().isSecretAnswer(user, secretAnswer)) {

                    String randomPassword = "";
                    for (int i = 0; i < 8; i++) {
                        randomPassword += String.valueOf((Math.random() * (127 - 48) + 48));
                    }

                    try {
                        Context.addProxyPrivilege(OpenmrsConstants.PRIV_EDIT_USER_PASSWORDS);
                        Context.getUserService().changePassword(user, randomPassword);
                    } finally {
                        Context.removeProxyPrivilege(OpenmrsConstants.PRIV_EDIT_USER_PASSWORDS);
                    }

                    httpSession.setAttribute("resetPassword", randomPassword);
                    httpSession.setAttribute(WebConstants.OPENMRS_MSG_ATTR, "personalhr.auth.password.reset");
                    Context.authenticate(username, randomPassword);
                    httpSession.setAttribute("loginAttempts", 0);
                    return new ModelAndView(
                            new RedirectView(request.getContextPath() + "/phr/options.form#Change Login Info"));
                } else {
                    httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, "auth.answer.invalid");
                    httpSession.setAttribute(WebConstants.OPENMRS_MSG_ATTR, "auth.question.fill");
                    request.setAttribute("secretQuestion", user.getSecretQuestion());
                }
            }
        }

        loginAttemptsByIP.put(ipAddress, forgotPasswordAttempts);
        request.setAttribute("uname", username);
        return showForm(request, response, errors);
    }

}