fr.paris.lutece.plugins.mylutece.modules.database.authentication.BaseAuthentication.java Source code

Java tutorial

Introduction

Here is the source code for fr.paris.lutece.plugins.mylutece.modules.database.authentication.BaseAuthentication.java

Source

/*
 * Copyright (c) 2002-2014, Mairie de Paris
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice
 *     and the following disclaimer.
 *
 *  2. Redistributions in binary form must reproduce the above copyright notice
 *     and the following disclaimer in the documentation and/or other materials
 *     provided with the distribution.
 *
 *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * License 1.0
 */
package fr.paris.lutece.plugins.mylutece.modules.database.authentication;

import fr.paris.lutece.plugins.mylutece.authentication.PortalAuthentication;
import fr.paris.lutece.plugins.mylutece.authentication.logs.ConnectionLog;
import fr.paris.lutece.plugins.mylutece.authentication.logs.ConnectionLogHome;
import fr.paris.lutece.plugins.mylutece.modules.database.authentication.business.DatabaseHome;
import fr.paris.lutece.plugins.mylutece.modules.database.authentication.business.DatabaseUserHome;
import fr.paris.lutece.plugins.mylutece.modules.database.authentication.business.GroupRoleHome;
import fr.paris.lutece.plugins.mylutece.modules.database.authentication.business.parameter.DatabaseUserParameterHome;
import fr.paris.lutece.plugins.mylutece.modules.database.authentication.service.DatabaseAccountLifeTimeService;
import fr.paris.lutece.plugins.mylutece.modules.database.authentication.service.DatabasePlugin;
import fr.paris.lutece.plugins.mylutece.modules.database.authentication.service.DatabaseService;
import fr.paris.lutece.plugins.mylutece.modules.database.authentication.web.MyLuteceDatabaseApp;
import fr.paris.lutece.plugins.mylutece.service.MyLutecePlugin;
import fr.paris.lutece.plugins.mylutece.util.SecurityUtils;
import fr.paris.lutece.portal.business.template.DatabaseTemplateHome;
import fr.paris.lutece.portal.service.i18n.I18nService;
import fr.paris.lutece.portal.service.mail.MailService;
import fr.paris.lutece.portal.service.plugin.Plugin;
import fr.paris.lutece.portal.service.plugin.PluginService;
import fr.paris.lutece.portal.service.security.FailedLoginCaptchaException;
import fr.paris.lutece.portal.service.security.LuteceUser;
import fr.paris.lutece.portal.service.template.AppTemplateService;
import fr.paris.lutece.portal.service.util.AppLogService;
import fr.paris.lutece.portal.service.util.AppPathService;
import fr.paris.lutece.portal.service.util.AppPropertiesService;
import fr.paris.lutece.util.ReferenceItem;
import fr.paris.lutece.util.html.HtmlTemplate;
import fr.paris.lutece.util.http.SecurityUtil;

import org.apache.commons.lang.StringUtils;

import java.sql.Timestamp;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import javax.security.auth.login.FailedLoginException;
import javax.security.auth.login.LoginException;

import javax.servlet.http.HttpServletRequest;

/**
 * The Class provides an implementation of the inherited abstract class PortalAuthentication based on a database.
 *
 * @author Mairie de Paris
 * @version 2.0.0
 *
 * @since Lutece v2.0.0
 */
public class BaseAuthentication extends PortalAuthentication {
    // //////////////////////////////////////////////////////////////////////////////////////////////
    // Constants
    private static final String AUTH_SERVICE_NAME = AppPropertiesService
            .getProperty("mylutece-database.service.name");
    private static final String PLUGIN_JCAPTCHA = "jcaptcha";

    // PROPERTIES
    private static final String PROPERTY_MAX_ACCESS_FAILED = "access_failures_max";
    private static final String PROPERTY_ACCESS_FAILED_CAPTCHA = "access_failures_captcha";
    private static final String PROPERTY_INTERVAL_MINUTES = "access_failures_interval";
    private static final String PROPERTY_UNBLOCK_USER = "mylutece_database_unblock_user";
    private static final String PROPERTY_TOO_MANY_FAILURES = "mylutece.ip.labelTooManyLoginTrials";

    // PARAMETERS
    private static final String PARAMETER_UNBLOCK_USER_MAIL_SENDER = "unblock_user_mail_sender";
    private static final String PARAMETER_UNBLOCK_USER_MAIL_SUBJECT = "unblock_user_mail_subject";
    private static final String PARAMETER_ENABLE_UNBLOCK_IP = "enable_unblock_ip";

    // MARK
    private static final String MARK_URL = "url";
    private static final String MARK_SITE_LINK = "site_link";

    // Messages properties
    private static final String PROPERTY_MESSAGE_USER_NOT_FOUND_DATABASE = "module.mylutece.database.message.userNotFoundDatabase";
    private static final String CONSTANT_PATH_ICON = "images/local/skin/plugins/mylutece/modules/database/mylutece-database.png";

    /**
     * Constructor
     *
     */
    public BaseAuthentication() {
        super();
    }

    /**
     * Gets the Authentification service name
     * @return The name of the authentication service
     */
    @Override
    public String getAuthServiceName() {
        return AUTH_SERVICE_NAME;
    }

    /**
     * Gets the Authentification type
     * @param request The HTTP request
     * @return The type of authentication
     */
    @Override
    public String getAuthType(HttpServletRequest request) {
        return HttpServletRequest.BASIC_AUTH;
    }

    /**
     * This methods checks the login info in the database
     *
     * @param strUserName The username
     * @param strUserPassword The password
     * @param request The HttpServletRequest
     * @return A LuteceUser object corresponding to the login
     * @throws LoginException The LoginException
     */
    @Override
    public LuteceUser login(String strUserName, String strUserPassword, HttpServletRequest request)
            throws LoginException {
        DatabaseService databaseService = DatabaseService.getService();

        Plugin pluginMyLutece = PluginService.getPlugin(MyLutecePlugin.PLUGIN_NAME);
        Plugin plugin = PluginService.getPlugin(DatabasePlugin.PLUGIN_NAME);

        // Creating a record of connections log
        ConnectionLog connectionLog = new ConnectionLog();
        connectionLog.setIpAddress(SecurityUtil.getRealIp(request));
        connectionLog.setDateLogin(new java.sql.Timestamp(new java.util.Date().getTime()));

        // Test the number of errors during an interval of minutes
        int nMaxFailed = DatabaseUserParameterHome.getIntegerSecurityParameter(PROPERTY_MAX_ACCESS_FAILED, plugin);
        int nMaxFailedCaptcha = 0;
        int nIntervalMinutes = DatabaseUserParameterHome.getIntegerSecurityParameter(PROPERTY_INTERVAL_MINUTES,
                plugin);
        boolean bEnableCaptcha = false;

        if (PluginService.isPluginEnable(PLUGIN_JCAPTCHA)) {
            nMaxFailedCaptcha = DatabaseUserParameterHome
                    .getIntegerSecurityParameter(PROPERTY_ACCESS_FAILED_CAPTCHA, plugin);
        }

        Locale locale = request.getLocale();

        if (((nMaxFailed > 0) || (nMaxFailedCaptcha > 0)) && (nIntervalMinutes > 0)) {
            int nNbFailed = ConnectionLogHome.getLoginErrors(connectionLog, nIntervalMinutes, pluginMyLutece);

            if ((nMaxFailedCaptcha > 0) && (nNbFailed >= nMaxFailedCaptcha)) {
                bEnableCaptcha = true;
            }

            if ((nMaxFailed > 0) && (nNbFailed >= nMaxFailed)) {
                if (nNbFailed == nMaxFailed) {
                    ReferenceItem item = DatabaseUserParameterHome.findByKey(PARAMETER_ENABLE_UNBLOCK_IP, plugin);

                    if ((item != null) && item.isChecked()) {
                        sendUnlockLinkToUser(strUserName, nIntervalMinutes, request, plugin);
                    }
                }

                Object[] args = { Integer.toString(nIntervalMinutes) };
                String strMessage = I18nService.getLocalizedString(PROPERTY_TOO_MANY_FAILURES, args, locale);

                if (bEnableCaptcha) {
                    throw new FailedLoginCaptchaException(strMessage, bEnableCaptcha);
                } else {
                    throw new FailedLoginException(strMessage);
                }
            }
        }

        BaseUser user = DatabaseHome.findLuteceUserByLogin(strUserName, plugin, this);

        // Unable to find the user
        if ((user == null) || !databaseService.isUserActive(strUserName, plugin)) {
            AppLogService.info("Unable to find user in the database : " + strUserName);

            if (bEnableCaptcha) {
                throw new FailedLoginCaptchaException(
                        I18nService.getLocalizedString(PROPERTY_MESSAGE_USER_NOT_FOUND_DATABASE, locale),
                        bEnableCaptcha);
            } else {
                throw new FailedLoginException(
                        I18nService.getLocalizedString(PROPERTY_MESSAGE_USER_NOT_FOUND_DATABASE, locale));
            }
        }

        // Check password
        if (!databaseService.checkPassword(strUserName, strUserPassword, plugin)) {
            AppLogService.info("User login : Incorrect login or password" + strUserName);

            if (bEnableCaptcha) {
                throw new FailedLoginCaptchaException(
                        I18nService.getLocalizedString(PROPERTY_MESSAGE_USER_NOT_FOUND_DATABASE, locale),
                        bEnableCaptcha);
            } else {
                throw new FailedLoginException(
                        I18nService.getLocalizedString(PROPERTY_MESSAGE_USER_NOT_FOUND_DATABASE, locale));
            }
        }

        // Get roles
        List<String> arrayRoles = DatabaseHome.findUserRolesFromLogin(strUserName, plugin);

        if (!arrayRoles.isEmpty()) {
            user.setRoles(arrayRoles);
        }

        // Get groups
        List<String> arrayGroups = DatabaseHome.findUserGroupsFromLogin(strUserName, plugin);

        if (!arrayGroups.isEmpty()) {
            user.setGroups(arrayGroups);
        }

        // We update the status of the user if his password has become obsolete
        Timestamp passwordMaxValidDate = DatabaseHome.findPasswordMaxValideDateFromLogin(strUserName, plugin);

        if ((passwordMaxValidDate != null) && (passwordMaxValidDate.getTime() < new java.util.Date().getTime())) {
            DatabaseHome.updateResetPasswordFromLogin(strUserName, Boolean.TRUE, plugin);
        }

        int nUserId = DatabaseHome.findUserIdFromLogin(strUserName, plugin);
        databaseService.updateUserExpirationDate(nUserId, plugin);

        return user;
    }

    /**
     * This methods logout the user
     * @param user The user
     */
    @Override
    public void logout(LuteceUser user) {
    }

    /**
     * Find users by login
     * @param request The request
     * @param strLogin the login
     * @return DatabaseUser the user corresponding to the login
     */
    @Override
    public boolean findResetPassword(HttpServletRequest request, String strLogin) {
        Plugin plugin = PluginService.getPlugin(DatabasePlugin.PLUGIN_NAME);

        return DatabaseHome.findResetPasswordFromLogin(strLogin, plugin);
    }

    /**
     * This method returns an anonymous Lutece user
     *
     * @return An anonymous Lutece user
     */
    @Override
    public LuteceUser getAnonymousUser() {
        return new BaseUser(LuteceUser.ANONYMOUS_USERNAME, this);
    }

    /**
     * Checks that the current user is associated to a given role
     * @param user The user
     * @param request The HTTP request
     * @param strRole The role name
     * @return Returns true if the user is associated to the role, otherwise false
     */
    public boolean isUserInRole(LuteceUser user, HttpServletRequest request, String strRole) {
        String[] roles = getRolesByUser(user);

        if ((roles != null) && (strRole != null)) {
            for (String role : roles) {
                if (strRole.equals(role)) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Returns the View account page URL of the Authentication Service
     * @return The URL
     */
    @Override
    public String getViewAccountPageUrl() {
        return MyLuteceDatabaseApp.getViewAccountUrl();
    }

    /**
     * Returns the New account page URL of the Authentication Service
     * @return The URL
     */
    @Override
    public String getNewAccountPageUrl() {
        return MyLuteceDatabaseApp.getNewAccountUrl();
    }

    /**
     * Returns the Change password page URL of the Authentication Service
     * @return The URL
     */
    public String getChangePasswordPageUrl() {
        return MyLuteceDatabaseApp.getChangePasswordUrl();
    }

    /**
     * Returns the lost password URL of the Authentication Service
     * @return The URL
     */
    @Override
    public String getLostPasswordPageUrl() {
        return MyLuteceDatabaseApp.getLostPasswordUrl();
    }

    /**
     * {@inheritDoc}
    * @return
     */
    @Override
    public String getLostLoginPageUrl() {
        return MyLuteceDatabaseApp.getLostLoginUrl();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getResetPasswordPageUrl(HttpServletRequest request) {
        return AppPathService.getBaseUrl(request) + MyLuteceDatabaseApp.getMessageResetPasswordUrl();
    }

    /**
     * Returns all users managed by the authentication service if this feature is available.
     * @return A collection of Lutece users or null if the service doesn't provide a users list
     */
    @Override
    public Collection<LuteceUser> getUsers() {
        Plugin plugin = PluginService.getPlugin(DatabasePlugin.PLUGIN_NAME);

        Collection<BaseUser> baseUsers = DatabaseHome.findDatabaseUsersList(plugin, this);
        Collection<LuteceUser> luteceUsers = new ArrayList<LuteceUser>();

        for (BaseUser user : baseUsers) {
            luteceUsers.add(user);
        }

        return luteceUsers;
    }

    /**
     * Returns the user managed by the authentication service if this feature is available.
     * @param userLogin the user login
     * @return A Lutece users or null if the service doesn't provide a user
     */
    @Override
    public LuteceUser getUser(String userLogin) {
        Plugin plugin = PluginService.getPlugin(DatabasePlugin.PLUGIN_NAME);

        BaseUser user = DatabaseHome.findLuteceUserByLogin(userLogin, plugin, this);

        return user;
    }

    /**
     * get all roles for this user : - user's roles - user's groups roles
     *
     * @param user The user
     * @return Array of roles
     */
    @Override
    public String[] getRolesByUser(LuteceUser user) {
        Plugin plugin = PluginService.getPlugin(DatabasePlugin.PLUGIN_NAME);
        Set<String> setRoles = new HashSet<String>();
        String[] strGroups = user.getGroups();
        String[] strRoles = user.getRoles();

        if (strRoles != null) {
            for (String strRole : strRoles) {
                setRoles.add(strRole);
            }
        }

        if (strGroups != null) {
            for (String strGroupKey : strGroups) {
                Collection<String> arrayRolesGroup = GroupRoleHome.findGroupRoles(strGroupKey, plugin);

                for (String strRole : arrayRolesGroup) {
                    setRoles.add(strRole);
                }
            }
        }

        String[] strReturnRoles = new String[setRoles.size()];
        setRoles.toArray(strReturnRoles);

        return strReturnRoles;
    }

    /**
     *
     *{@inheritDoc}
     */
    @Override
    public String getIconUrl() {
        return CONSTANT_PATH_ICON;
    }

    /**
     *
     * Returns {@link DatabasePlugin#PLUGIN_NAME}.
     * @return {@link DatabasePlugin#PLUGIN_NAME}
     */
    @Override
    public String getName() {
        return DatabasePlugin.PLUGIN_NAME;
    }

    /**
     *{@inheritDoc}
     */
    @Override
    public String getPluginName() {
        return DatabasePlugin.PLUGIN_NAME;
    }

    /**
     *{@inheritDoc}
     */
    @Override
    public void updateDateLastLogin(LuteceUser user, HttpServletRequest request) {
        DatabaseService _databaseService = DatabaseService.getService();
        Plugin plugin = PluginService.getPlugin(DatabasePlugin.PLUGIN_NAME);
        _databaseService.updateUserLastLoginDate(user.getName(), plugin);
    }

    private void sendUnlockLinkToUser(String strLogin, int nIntervalMinutes, HttpServletRequest request,
            Plugin plugin) {
        int nIdUser = DatabaseUserHome.findDatabaseUserIdFromLogin(strLogin, plugin);

        if (nIdUser > 0) {
            ReferenceItem referenceItem = DatabaseUserParameterHome.findByKey(PARAMETER_UNBLOCK_USER_MAIL_SENDER,
                    plugin);
            String strSender = (referenceItem == null) ? StringUtils.EMPTY : referenceItem.getName();

            referenceItem = DatabaseUserParameterHome.findByKey(PARAMETER_UNBLOCK_USER_MAIL_SUBJECT, plugin);

            String strSubject = (referenceItem == null) ? StringUtils.EMPTY : referenceItem.getName();

            String strLink = SecurityUtils.buildResetConnectionLogUrl(nIntervalMinutes, request);

            Map<String, Object> model = new HashMap<String, Object>();
            model.put(MARK_URL, strLink);
            model.put(MARK_SITE_LINK, MailService.getSiteLink(AppPathService.getBaseUrl(request), true));

            String strTemplate = DatabaseTemplateHome.getTemplateFromKey(PROPERTY_UNBLOCK_USER);
            HtmlTemplate template = AppTemplateService.getTemplateFromStringFtl(strTemplate, request.getLocale(),
                    model);

            DatabaseAccountLifeTimeService accountLifeTimeService = new DatabaseAccountLifeTimeService();

            String strUserMail = accountLifeTimeService.getUserMainEmail(nIdUser);

            if ((strUserMail != null) && StringUtils.isNotBlank(strUserMail)) {
                MailService.sendMailHtml(strUserMail, strSender, strSender, strSubject, template.getHtml());
            }
        }
    }
}