LogonTools.java

package sk.iway.iwcm.common;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

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

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;

import sk.iway.Password;
import sk.iway.iwcm.Adminlog;
import sk.iway.iwcm.Cache;
import sk.iway.iwcm.Constants;
import sk.iway.iwcm.DB;
import sk.iway.iwcm.DBPool;
import sk.iway.iwcm.Identity;
import sk.iway.iwcm.Logger;
import sk.iway.iwcm.PageLng;
import sk.iway.iwcm.PathFilter;
import sk.iway.iwcm.Tools;
import sk.iway.iwcm.doc.GroupDetails;
import sk.iway.iwcm.doc.GroupsDB;
import sk.iway.iwcm.i18n.Prop;
import sk.iway.iwcm.stat.StatDB;
import sk.iway.iwcm.stripes.AfterLogonLogoffInterceptor;
import sk.iway.iwcm.system.multidomain.MultiDomainFilter;
import sk.iway.iwcm.system.spring.WebjetAuthentificationProvider;
import sk.iway.iwcm.users.PasswordSecurity;
import sk.iway.iwcm.users.PasswordsHistoryBean;
import sk.iway.iwcm.users.PermissionGroupBean;
import sk.iway.iwcm.users.UserDetails;
import sk.iway.iwcm.users.UserGroupsDB;
import sk.iway.iwcm.users.UsersDB;

public class LogonTools {

    protected LogonTools() {
        //utility class
    }

    /**
     * Skontroluje ci sa moze pouzivatel prihlasit vzhladom na zadane datumy mozneho prihlasenia
     * @param rs
     * @return
     */
    public static boolean checkAllowLoginDates(ResultSet rs)
    {
        try
        {
            java.sql.Date start = rs.getDate("allow_login_start");
            java.sql.Date end = rs.getDate("allow_login_end");

            long startL = 0;
            long endL = Long.MAX_VALUE;
            if (start != null) startL = start.getTime();
            if (end != null) endL = end.getTime() + (60*60*24 * 1000);

            long now = Tools.getNow();

            if (now > startL && now < endL) return(true);
        }
        catch (SQLException ex)
        {
            sk.iway.iwcm.Logger.error(ex);
        }
        return(false);
    }

    /**
     *  Description of the Method
     *
     *@param  username  Description of the Parameter
     *@param  password  Description of the Parameter
     *@param  user      Description of the Parameter
     *@param  errors    Description of the Parameter
     *@param  request   Description of the Parameter
     *@return           Description of the Return Value
     */
    public static String logon(String username, String password, Identity user, Map<String, String> errors, HttpServletRequest request, sk.iway.iwcm.i18n.Prop prop)
    {
        String forward = "logon_ok_admin";

        if (LogonTools.isLoginBlocked(request)) {
            request.setAttribute("logon.error.blocked", "1");
            errors.put("ERROR_KEY", prop.getText("logon.error.blocked"));
            return forward;
        }

        String logonMethod = Constants.getString("adminLogonMethod");
        String tryNormalLogon = null;
        String adminUsersAllowNormalLogon = Constants.getString("adminUsersAllowNormalLogon"); //moznost pre niektore loginy sa prihlasit normalne (ak pouzivame LDAP prihlasovanie)
        if (Constants.getBoolean("adminLogonMethodAllowNormalTry")) tryNormalLogon = request.getParameter("tryNormalLogon");

        if (Tools.isNotEmpty(logonMethod) && tryNormalLogon==null && (Tools.isEmpty(adminUsersAllowNormalLogon) ||
             Tools.containsOneItem(Tools.getTokens(adminUsersAllowNormalLogon, ",|"), new String[]{username}) == false))
        {
            int i = logonMethod.lastIndexOf('.');
            String beforePostClass = logonMethod.substring(0, i);
            logonMethod = logonMethod.substring(i+1);
            //String
            try
            {
                Class<?> c = Class.forName(beforePostClass);
                Object o = c.getDeclaredConstructor().newInstance();
                Method m;
                Class<?>[] parameterTypes = new Class<?>[] {String.class, String.class, Identity.class, Map.class, HttpServletRequest.class, sk.iway.iwcm.i18n.Prop.class};
                Object[] arguments = new Object[] {username, password, user, errors, request, prop};
                m = c.getMethod(logonMethod, parameterTypes);
                return((String)m.invoke(o, arguments));
            }
            catch (Exception ex)
            {
                sk.iway.iwcm.Logger.error(ex);
            }
        }

        if (username == null || password == null)
        {
            return ("");
        }
        StringBuilder err = new StringBuilder();
        //String user_name = "";
        //String user_pass ="";

        try
        {

            Connection db_conn = DBPool.getConnection();
            try
            {
                String sql = "";
                boolean hasEmailParam = false;

                if (request.getParameter("emailLogon") != null && "true".equalsIgnoreCase(request.getParameter("emailLogon")))
                {
                    sql = "SELECT * FROM users WHERE "+DB.fixAiCiCol("email")+"=?";
                }
                else
                {
                    hasEmailParam = true;
                    sql = "SELECT * FROM users WHERE "+DB.fixAiCiCol("login")+"=?"+" OR "+DB.fixAiCiCol("email")+"=?";
                }

                sql += UsersDB.getDomainIdSqlWhere(true);

                sql += "ORDER BY is_admin DESC, user_id ASC";

                PreparedStatement ps = db_conn.prepareStatement(sql);
                try
                {
                    ps.setString(1, DB.fixAiCiValue(username));
                    if (hasEmailParam) ps.setString(2, DB.fixAiCiValue(username));
                    ResultSet db_result = ps.executeQuery();
                    try
                    {
                        if (db_result.next())
                        {
                            //skontroluj ci je platny datum prihlasenia
                            boolean allowDateLogin = checkAllowLoginDates(db_result);
                            if (allowDateLogin == false)
                            {
                                err.append("<li>").append(prop.getText("logon.err.dateLoginDissabled", DB.getDbDate(db_result, "allow_login_start"), DB.getDbDate(db_result, "allow_login_end")));
                                request.setAttribute("logon.err.dateLoginDissabled", "true");

                                Adminlog.add(Adminlog.TYPE_USER_LOGON, "LogonAction - login date disabled: name= " + username, -1, -1);
                            }
                            else
                            {
                                //skontroluj heslo
                                boolean passok = false;
                                String salt = db_result.getString("password_salt");
                                String passwordInDb = db_result.getString("password");
                                sk.iway.Password pass = new sk.iway.Password();
                                //spatna kompatibilita je potrebna, ak admin zmeni passwordUseHash a zabudne zavolat update_passwords.jsp
                                if (pass.encrypt(password).equals(passwordInDb) || PasswordSecurity.isPasswordCorrect(password, salt, passwordInDb))
                                {
                                    passok = true;
                                }
                                if (passok==false)
                                {
                                    //skus overit mobiletoken, pre istotu znova kontroluj header, aby sa nedal pouzit na bezne prihlasenie
                                    if (Tools.isNotEmpty(request.getHeader(Constants.getString("logonTokenHeaderName"))))
                                    {
                                        try
                                        {
                                            String apiKey = db_result.getString("api_key");
                                            if (Tools.isNotEmpty(apiKey))
                                            {
                                                //splitni, je to vo formate salt|token
                                                int i = apiKey.indexOf("|");
                                                if (i > 0)
                                                {
                                                    salt = apiKey.substring(0, i);
                                                    passwordInDb = apiKey.substring(i+1);
                                                    if (PasswordSecurity.isPasswordCorrect(password, salt, passwordInDb)) passok = true;
                                                }

                                            }
                                        } catch (Exception ex) {
                                            //
                                        }
                                    }
                                }
                                if (passok)
                                {
                                    user.setAuthorized(db_result.getBoolean("authorized"));

                                    if (user.isAuthorized())
                                    {
                                        //je to ok, mozeme ho presunut do hlavneho menu
                                        UsersDB.fillUserDetails(user, db_result);

                                        //user_name = username;
                                        if (user.isAdmin())
                                        {
                                            if(request.getAttribute("isMobileVersion") != null || "true".equals(request.getParameter("isMobileVersion")))
                                            {
                                                forward = "logon_mobile";
                                            }
                                            else
                                            {
                                                forward = "logon_ok_admin";
                                            }
                                            Adminlog.add(Adminlog.TYPE_USER_LOGON, user.getUserId(), "LogonAction - user (ADMIN) successfully loged: name=" + username , -1, -1);
                                        }
                                        else
                                        {
                                            Logger.error(LogonTools.class,"user nie je administrator");
                                            //errors.add(ActionMessages.GLOBAL_ERROR, new ActionMessage("error.logon.noadmin"));
                                            err.append("<li>").append(prop.getText("logon.err.noadmin"));
                                            request.setAttribute("logon.err.noadmin", "true");
                                            //return (mapping.findForward(forward));

                                            if (Constants.getBoolean("auditDontLogUsrlogon")==false) Adminlog.add(Adminlog.TYPE_USER_LOGON, user.getUserId(), "LogonAction - user successfully loged: name=" + username , -1, -1);
                                        }

                                        setUserPerms(user);
                                    }
                                    else
                                    {
                                        err = new StringBuilder("<li>").append(prop.getText("logon.err.userUnknown"));
                                        request.setAttribute("logon.err.userUnknown", "true");

                                        Adminlog.add(Adminlog.TYPE_USER_LOGON, "LogonAction - user not authorized: name= " + username, -1, -1);
                                    }
                                }
                                else
                                {
                                    Logger.error(LogonTools.class,"zle heslo");
                                    //ma zle heslo, napis chybu
                                    //errors.add(ActionMessages.GLOBAL_ERROR, new ActionMessage("error.logon.wrong.pass"));
                                    err.append("<li>").append(prop.getText("logon.err.wrongPass"));
                                    request.setAttribute("logon.err.wrongPass", "true");

                                    Adminlog.add(Adminlog.TYPE_USER_LOGON, "LogonAction - wrong password: name= " + username, -1, -1);
                                }
                            }

                        }
                        else
                        {
                            Logger.error(LogonTools.class,"user neexistuje");
                            //zadany user neexistuje
                            //errors.add(ActionMessages.GLOBAL_ERROR, new ActionMessage("error.logon.user.unknown"));
                            err.append("<li>").append(prop.getText("logon.err.userUnknown"));
                            request.setAttribute("logon.err.userUnknown", "true");

                            Adminlog.add(Adminlog.TYPE_USER_LOGON, "LogonAction - user unknown: name= " + username, -1, -1);
                        }
                    }
                    finally { db_result.close(); }
                }
                finally { ps.close(); }
                if (user.getUserId()>0)
                {
                    if (user.isAuthorized()==false)
                    {
                        //Logger.println(this,"JE neautorizovany!!");
                        //ak nie je autorizovany, napis iba ze user neexistuje a nezaoberaj sa heslom
                        err = new StringBuilder("<li>").append(prop.getText("logon.err.userUnknown"));
                        request.setAttribute("logon.err.userUnknown", "true");

                        Adminlog.add(Adminlog.TYPE_USER_LOGON, "LogonAction - user unknown: name= " + username, -1, -1);
                    }
                    else
                    {
                        //nacitaj pristupove prava
                        UsersDB.setDisabledItems(user);

                        ps = db_conn.prepareStatement("UPDATE  users SET last_logon=? WHERE user_id=?");
                        try
                        {
                            ps.setTimestamp(1, new Timestamp( (new java.util.Date()).getTime()));
                            ps.setInt(2, user.getUserId());
                            ps.execute();
                        }
                        finally { ps.close(); }
                    }
                }
            }
            finally { db_conn.close(); }
        }
        catch (Exception ex)
        {
            Logger.error(LogonTools.class,"LogonAction: error");
            sk.iway.iwcm.Logger.error(ex);
        }

        if (err.toString().trim().length()>1)
        {
            errors.put("ERROR_KEY", prop.getText("approveAction.err.badPass"));
            //aby sa vzdy zobrazil dialog poslat heslo
            request.setAttribute("logon.err.wrongPass", "true");

            setLoginBlocked(request);
        }

        return (forward);
    }


    /**
     * Nastavi userovi prava na adresare (editable groups a pages)
     * @param user
     */
    public static void setUserPerms(Identity user)
    {
        try
        {
            if (user.getEditablePages().length()>0 && user.getEditableGroups().length()==0)
            {
                user.setEditableGroups(Integer.toString(Constants.getInt("systemPagesMyPages")));
            }

            //#23245
            StringBuilder permWritableFolders = new StringBuilder();
            List<PermissionGroupBean> permissionGroups = UserGroupsDB.getPermissionGroupsFor(user.getUserId());
            // pre kazdu skupinu prav pridame prava
            for (PermissionGroupBean permGroup : permissionGroups)
            {
                if(Tools.isNotEmpty(permGroup.getWritableFolders()))
                {
                    if(!permGroup.getWritableFolders().startsWith(" "))
                        permWritableFolders.append(" ");

                    permWritableFolders.append(permGroup.getWritableFolders());
                }
            }
            user.setWritableFolders(user.getWritableFolders()+permWritableFolders.toString());

            //#20460 uzivatelom sa nastavia rovnake prava na subory ako su nastavene vo na web strankach
            if(Constants.getBoolean("userPermsActualPageAutomatic") && user.getEditableGroups().length() > 0 && (Tools.isNotEmpty(user.getWritableFolders()) || Constants.getBoolean("defaultDisableUpload") == true ))
            {
                StringBuilder sb = new StringBuilder(user.getWritableFolders());
                int groupId = -1;
                GroupDetails groupDetails;
                String domainAlias = "";
                for(String group_id:Tools.getTokens(user.getEditableGroups(), ","))
                {
                    groupId = Tools.getIntValue(group_id,-1);
                    groupDetails = GroupsDB.getInstance().getGroup(groupId);
                    domainAlias = "";
                    if(Tools.isNotEmpty(groupDetails.getDomainName()))
                        domainAlias = MultiDomainFilter.getDomainAlias(groupDetails.getDomainName());
                    if(Tools.isNotEmpty(domainAlias))
                        domainAlias = "/"+domainAlias; //NOSONAR

                    for(String directory : new String[]{"/images","/files"})
                    {
                        String path = Tools.replace(UploadFileTools.getPageUploadSubDir(-1, groupId, null, directory+domainAlias), "//", "/");
                        //replace dvojiteho aliasu, niekedy sa to tam tak doplni a nemam energiu hladat preco a co by sa pokazilo potom
                        if (Tools.isNotEmpty(domainAlias))
                        {
                            path = Tools.replace(path, domainAlias+domainAlias, domainAlias);
                        }

                        if (user.isFolderWritable(path)) continue;

                        if (sb.isEmpty()==false) sb.append("\n");
                        sb.append(path);
                        if(path.endsWith("/"))
                            sb.append("*");
                        else
                            sb.append("/*");
                    }
                }
                Logger.debug(LogonTools.class, "Adding WritableFolders: "+Tools.replace(sb.toString(), user.getWritableFolders(), ""));
                if (sb.isEmpty()==false) sb.append("\n");
                user.setWritableFolders(sb.toString()+permWritableFolders);
            }

            //#23245
            //pridame mu prava na grupy z user perm. skupiny
            // pre kazdu skupinu prav pridame prava
            for (PermissionGroupBean permGroup : permissionGroups) {
                if (Tools.isNotEmpty(permGroup.getEditableGroups())) {
                    if (Tools.isEmpty(user.getEditableGroups()))
                        user.setEditableGroups(permGroup.getEditableGroups());
                    else
                        user.setEditableGroups(user.getEditableGroups() + "," + permGroup.getEditableGroups());
                }
            }
            //pridame mu prava na webstranky (documents) z user perm. skupiny
            // pre kazdu skupinu prav pridame prava
            for (PermissionGroupBean permGroup : permissionGroups) {
                if (Tools.isNotEmpty(permGroup.getEditablePages())) {
                    if (Tools.isEmpty(user.getEditablePages()))
                        user.setEditablePages(permGroup.getEditablePages());
                    else
                        user.setEditablePages(user.getEditablePages() + "," + permGroup.getEditablePages());
                }
            }
        } catch (Exception ex) {

        }
    }

	public static void auditLogon(List<String> errors, Identity user, String username, HttpServletRequest request) {
		if(errors.isEmpty() && user != null)
		{
			if (Constants.getBoolean("auditDontLogUsrlogon")==false) Adminlog.add(Adminlog.TYPE_USER_LOGON, user.getUserId(), "LogonTools - user "+(user.isAdmin() ? "(ADMIN) " : " ")+"successfully loged: name=" + username , -1, -1);
			StatDB.addAdmin(request);
		}
		else
		{
			String lng = PageLng.getUserLng(request);
			Prop prop = Prop.getInstance(lng);
			StringBuffer logErrors = new StringBuffer("");
			logErrors.append(" name=").append(username).append("\n");
            Iterator<String> iterator = errors.iterator();
            while(iterator.hasNext())
			{
				String errorKey = iterator.next();
				logErrors.append(prop.getText(errorKey));
				if(iterator.hasNext())
					logErrors.append("\n");
			}
			int userId = -1;
			if (user != null) userId = user.getUserId();
			Adminlog.add(Adminlog.TYPE_USER_LOGON, userId, "LogonTools - su nejake chyby v logovacom formulari:\n"+logErrors.toString(), -1, -1);
		}
	}

    @SuppressWarnings("unchecked")
    public static List<String> logonUser(HttpServletRequest request, String username, String password)
    {
        String logonMethod = Constants.getString("usrLogonMethod");
        if (Tools.isNotEmpty(logonMethod) && request.getParameter("tryNormalLogon")==null && request.getAttribute("tryNormalLogon")==null)
        {
            int i = logonMethod.lastIndexOf('.');
            String beforePostClass = logonMethod.substring(0, i);
            logonMethod = logonMethod.substring(i+1);
            //String
            try
            {
                //Adminlog.add(Adminlog.TYPE_USER_LOGON,"Logon attempt calling "+beforePostClass+"."+logonMethod+", username: " + username,-1,-1);

                Class<?> c = Class.forName(beforePostClass);
                Object o = c.getDeclaredConstructor().newInstance();
                Method m;
                Class<?>[] parameterTypes = new Class<?>[] {String.class, String.class, HttpServletRequest.class};
                Object[] arguments = new Object[] {username, password, request};
                m = c.getMethod(logonMethod, parameterTypes);
                Object result = m.invoke(o, arguments);
                List<String> errors = null;
                if (result instanceof List) {
                    try {
                        errors = (List<String>)result;
                    } catch (Exception ex) {
                        Logger.error(LogonTools.class, ex);
                    }
                }
                if (errors == null) errors = new ArrayList<>();

				auditLogon(errors, UsersDB.getCurrentUser(request), username, request);

				return errors;
            }
            catch (Exception ex)
            {
                Adminlog.add(Adminlog.TYPE_USER_LOGON,"Logon attempt calling "+beforePostClass+"."+logonMethod+", username: " + username + " failed, error="+ex.getMessage(),-1,-1);
                sk.iway.iwcm.Logger.error(ex);
            }
        }

        List<String> errors = new ArrayList<>();
        Identity user = new Identity();
        HttpSession session = request.getSession();
		/*
		 * potrebne pre kontrolu hesla, konkretne preto, aby som vedel zistit ci je uzivatel admin,
		 * alebo nie, kedze sa v user nastavuje admin na false a to je mozne nastavit len raz
		 */
        Identity passUser = new Identity();
        try
        {

            boolean passok = false;
            Connection db_conn = DBPool.getConnection(request);
            try
            {
                String sql = "";

                if ("true".equalsIgnoreCase(request.getParameter("emailLogon")))
                {
                    sql = "SELECT * FROM  users WHERE email=?";
                }
                else
                {
                    sql = "SELECT * FROM  users WHERE login=?";
                }

                sql += UsersDB.getDomainIdSqlWhere(true);

                PreparedStatement ps = db_conn.prepareStatement(sql);
                try
                {
                    ps.setString(1, username);
                    ResultSet db_result = ps.executeQuery();
                    try
                    {
                        if (db_result.next())
                        {
                            //skontroluj ci je platny datum prihlasenia
                            boolean allowDateLogin = LogonTools.checkAllowLoginDates(db_result);
                            if (allowDateLogin == false)
                            {
                                //ma zle heslo, napis chybu
                                errors.add("error.logon.wrong.pass");

                                request.setAttribute("error.logon.wrong.dateLoginDissabled", "true");
                                request.setAttribute("error.logon.wrong.dateLoginDissabled-start", DB.getDbDate(db_result, "allow_login_start"));
                                request.setAttribute("error.logon.wrong.dateLoginDissabled-end", DB.getDbDate(db_result, "allow_login_end"));

                                Adminlog.add(Adminlog.TYPE_USER_LOGON, "LogonAction - login date disabled: name= " + username, -1, -1);
                            }
                            else
                            {
                                String passwordInDb = db_result.getString("password");
                                String salt = db_result.getString("password_salt");

                                //skontroluj heslo
                                sk.iway.Password pass = new sk.iway.Password();
                                if (pass.encrypt(password).equals(db_result.getString("password")) || PasswordSecurity.isPasswordCorrect(password, salt, passwordInDb))
                                {
                                    passok = true;

                                    UsersDB.fillUserDetails(passUser, db_result);

                                    UsersDB.fillUserDetails(user, db_result);

                                    if (Constants.getBoolean("enableAdminInWebLogon") && user.isAdmin())
                                    {
                                        //kvoli blogom - nacitanie prav

                                        //nacitaj pristupove prava - pouziva sa napr. v module blog - nie je admin (isAdmin bude false, viz nizsie), mame ale jeho prava
                                        LogonTools.setUserPerms(user);
                                        LogonTools.setUserPerms(passUser);

                                        UsersDB.setDisabledItems(user);
                                        UsersDB.setDisabledItems(passUser);
                                    }
                                    else
                                    {
                                        //aby mu nefungovalo pristup do adminu (bezpecnost)
                                        user.setAdmin(false);
                                    }
                                }
                                else
                                {
                                    Logger.error(LogonTools.class,"zle heslo");
                                    //ma zle heslo, napis chybu
                                    errors.add("error.logon.wrong.pass");
                                    request.setAttribute("error.logon.wrong.pass", "true");
                                }

                                if (user.isAuthorized()==false)
                                {
                                    errors.add("error.logon.user.unknown");
                                    Logger.error(LogonTools.class,"neautorizovany");
                                    //ma zle heslo, napis chybu
                                    if (Constants.getBoolean("formLoginProtect"))
                                    {
                                        //nepiseme o aku chybu ide
                                        request.setAttribute("error.logon.wrong.pass", "true");
                                    }
                                    else
                                    {
                                        request.setAttribute("error.logon.user.unknown", "true");
                                        request.setAttribute("error.logon.user.unknown.notAuthorized", "true");
                                    }
                                }
                            }
                        }
                        else
                        {
                            //zadany user neexistuje
                            Logger.error(LogonTools.class,"user neexistuje");
                            errors.add("error.logon.user.unknown");
                            if (user != null && user.isAuthorized()==false)
                            {
                                //nepiseme o aku chybu ide
                                request.setAttribute("error.logon.wrong.pass", "true");
                            }
                            else
                            {
                                request.setAttribute("error.logon.user.unknown", "true");
                            }
                        }
                    }
                    finally { db_result.close(); }
                }
                finally { ps.close(); }
            }
            finally { db_conn.close(); }

            if (passok)
            {
                int checkForAlarmDocId = checkForAlarm(user);
                if(checkForAlarmDocId != 0)
                {
                    session.setAttribute("alarm_warning", Integer.toString(checkForAlarmDocId));
                }
                else
                {
                    session.setAttribute("alarm_warning", "0");
                }
            }

        }
        catch (Exception ex)
        {
            Logger.error(LogonTools.class,"LogonAction: error");
            sk.iway.iwcm.Logger.error(ex);
        }

        // Save our logged-in user in the session
        user.setPassword(password);
        user.setValid(true);

        if (user.isAuthorized())
        {
            LogonTools.setUserToSession(session, user);

            //kontrola hesla podla nastavenych podmienok

            //nastavi nove heslo na aktualne
            if(session.getAttribute(Constants.USER_KEY+"_changepassword") != null)
            {
                String newPassword = request.getParameter("newPassword");
                String retypeNewPassword = request.getParameter("retypeNewPassword");
                if(newPassword.equals(retypeNewPassword))
                {
                    password = newPassword;
                }
                else
                {
                    Logger.error(LogonTools.class,"nove heslo a opakovanie noveho hesla sa nezhoduju");
                    errors.add("passwordsNotMatch");
                    request.setAttribute("passwordsNotMatch", "true");

                    session.removeAttribute(Constants.USER_KEY);

                    Adminlog.add(Adminlog.TYPE_USER_CHANGE_PASSWORD, user.getUserId(), "LogonTools - user ("+user.getLogin()+") password to change not match", -1, -1);

                    return errors;
                }
            }
            //END nastavi nove heslo na aktualne

            if(Password.checkPassword(true, password, passUser.isAdmin(), passUser.getUserId(), session, null))
            {
                //updatnem heslo na nove
                if(session.getAttribute(Constants.USER_KEY+"_changepassword") != null)
                {

                    try
                    {
                        Password pass = new Password();
                        String encryptedPassword = "";
                        PasswordsHistoryBean passwordsHistoryBean = new PasswordsHistoryBean(user.getUserId(),"", UsersDB.getSalt(user.getUserId()));
                        if (Constants.getBoolean("passwordUseHash"))
                        {
                            encryptedPassword = PasswordSecurity.calculateHash(password, UsersDB.getSalt(user.getUserId()));
                        }
                        else
                        {
                            encryptedPassword = pass.encrypt(password);
                            passwordsHistoryBean.setSalt("");
                        }
                        passwordsHistoryBean.setPassword(encryptedPassword);
                        DB.execute("UPDATE users SET password=? WHERE user_id=?", encryptedPassword, Integer.valueOf(user.getUserId()));
                        passwordsHistoryBean.saveIfNotExistsAndDeleteOld();
                        Adminlog.add(Adminlog.TYPE_USER_CHANGE_PASSWORD, user.getUserId(), "LogonTools - user ("+user.getLogin()+") successfully changed password", -1, -1);
                    }
                    catch (Exception ex)
                    {
                        sk.iway.iwcm.Logger.error(ex);
                    }
                }
                session.removeAttribute(Constants.USER_KEY+"_changepassword");
            }
            else
            {
                session.removeAttribute(Constants.USER_KEY);
                session.setAttribute(Constants.USER_KEY+"_changepassword", passUser);
            }
            //END kontrola hesla

        }

        auditLogon(errors, user, username, request);

        if (errors.isEmpty()==false) {
            setLoginBlocked(request);
        }

        return errors;
    }

    public static List<String> logonUserWithAllChecks(HttpServletRequest request, String username, String password) {
        List<String> errors = new ArrayList<>();

        //15888 #11: akceptuje sa len submit cez HTTP POST
		if("post".equalsIgnoreCase(request.getMethod()) == false) {
            return null;
        }

        //session fixation ochrana
        LogonTools.invalidateSessionOnFirstPost(request);

        //pravdepodobne submit nejakeho robota
        if (username == null || password == null) return null;

        String url = PathFilter.getOrigPath(request);
        HttpSession session = request.getSession();
		Prop prop = Prop.getInstance(request);

        //nemoze sa prihlasit lebo sa zle predtym prihlasil
		if(isLoginBlocked(request))
		{
			Logger.error(LogonTools.class, prop.getText("logon.error.blocked"));
			request.setAttribute("logon_message",prop.getText("logon.error.blocked"));
			request.setAttribute("error.logon.user.blocked", "true");
			if (errors.contains("error.logon.user.blocked")==false) errors.add("error.logon.user.blocked");

			Adminlog.add(Adminlog.TYPE_USER_LOGON,"Logon attempt TIME BLOCKED, username: " + username,-1,-1);
			return errors;
		}

        if(session.getAttribute(Constants.USER_KEY+"_changepassword") != null)
		{
			String newPassword = request.getParameter("newPassword");
			String retypeNewPassword = request.getParameter("retypeNewPassword");

			if(Tools.isEmpty(newPassword) || Tools.isEmpty(retypeNewPassword))
			{
				errors.add("passwordsNotMatch");

				Adminlog.add(Adminlog.TYPE_USER_LOGON,"Logon attempt CHANGE PASSWORD REQUIRED, username: " + username,-1,-1);
				return errors;
			}
		}

        errors = LogonTools.logonUser(request, username, password);

        // Report any errors we have discovered back to the original form
		if (!errors.isEmpty())
		{
			Logger.error(LogonTools.class, "su nejake chyby v logovacom formulari: "+url);
			return errors;
		}

        if(session.getAttribute(Constants.USER_KEY+"_changepassword") != null) {
            return errors;
        }

        Identity user = UsersDB.getCurrentUser(request);
		if (user==null || user.isAuthorized()==false)
		{
            //there is allready logged user, so it means he doesnt' have permission to access this page
            errors.add("editor.permsDenied");
			request.setAttribute("unauthorized", "unauthorized");
			return errors;
		}

        callLogonLogoffInterceptor(user, request);

        return errors;
    }

    public static void afterLogon(Identity user, HttpServletRequest request, HttpServletResponse response)
	{
		String afterLogon = Constants.getString("afterLogonMethod");
		if (Tools.isNotEmpty(afterLogon))
		{
			int i = afterLogon.lastIndexOf('.');
			String customClass = afterLogon.substring(0, i);
			afterLogon = afterLogon.substring(i+1);
			//String
			try
			{
				Class<?> c = Class.forName(customClass);
				Object o = c.getDeclaredConstructor().newInstance();
				Method m;
				Class<?>[] parameterTypes = new Class<?>[] {Identity.class, HttpServletRequest.class, HttpServletResponse.class};
				Object[] arguments = new Object[] {user, request, response};
				m = c.getMethod(afterLogon, parameterTypes);
				m.invoke(o, arguments);
			}
			catch (Exception ex)
			{
				sk.iway.iwcm.Logger.error(ex);
			}
		}
	}

	private static void callLogonLogoffInterceptor(UserDetails user, HttpServletRequest request)
	{
		String interceptorClassName = Constants.getString("stripesLogonLogoffInterceptorClass");

		if (Tools.isEmpty(interceptorClassName) && request.getAttribute("afterSaveInterceptor") != null) {
			interceptorClassName = Tools.getStringValue((String) request.getAttribute("afterSaveInterceptor"), "");
		}

		if (Tools.isNotEmpty(interceptorClassName)) {
			try
			{
				@SuppressWarnings("unchecked")
				Class<? extends AfterLogonLogoffInterceptor> interceptorClass = (Class<? extends AfterLogonLogoffInterceptor>) Class.forName(interceptorClassName);
				AfterLogonLogoffInterceptor interceptor = interceptorClass.getDeclaredConstructor().newInstance();

				interceptor.logon(user, request);
			}
			catch (Exception e)
			{
				sk.iway.iwcm.Logger.error(e);
			}
		}
	}

    public static int checkForAlarm(Identity user)
    {
        int userId;
        int warning = -1;
        int docId = 0;

        int alarmId = 1;
        try
        {
            userId = user.getUserId();
            Connection db_conn = DBPool.getConnection();
            try
            {
                PreparedStatement ps = db_conn.prepareStatement("SELECT * FROM user_alarm WHERE user_id=?"); //NOSONAR
                try
                {
                    ps.setInt(1, userId);
                    ResultSet rs = ps.executeQuery();
                    try
                    {
                        if(rs.next())
                        {
                            warning = rs.getInt("warning");
                        }
                    }
                    finally { rs.close(); }
                }
                finally { ps.close(); }

                ps = db_conn.prepareStatement("SELECT * FROM alarm_action WHERE alarm_id=?"); //NOSONAR
                try
                {
                    ps.setInt(1, alarmId);
                    ResultSet rs = ps.executeQuery();
                    try
                    {
                        if(rs.next())
                        {
                            docId = rs.getInt("doc_id");
                        }
                    }
                    finally { rs.close(); }
                }
                finally { ps.close(); }
            }
            finally { db_conn.close(); }

            if(warning == 1)
            {
                return docId;

            }
            //Logger.println(this,"WARNING: "+ warning);
        }
        catch (Exception ex)
        {
            sk.iway.iwcm.Logger.error(ex);
        }
        return (0);
    }

    /**
     * Ochrana Session Fixation (MFSR pentesty) ktora zabezpeci pri PRVOM odoslani (POST) logon formularu invalidnutie session
     * @param request
     */
    public static void invalidateSessionOnFirstPost(HttpServletRequest request)
    {
        if("post".equalsIgnoreCase(request.getMethod()) == false) return;

        final String SESSION_KEY = "session_fixation_invalidated";
        //session fixation - pri prihlaseni vzdy generujeme novu session
        if (request.getSession().getAttribute(SESSION_KEY)==null)
        {
            //toto potrebujeme zachovat po destroyi session (session fixation)
            String[] preservedSessionObjectNames = Tools.getTokens(Constants.getStringExecuteMacro("logonPreservedSessionObjects"), ",");
            Map<String, Object> preservedSessionObjects = new Hashtable<>();
            for (String name : preservedSessionObjectNames)
            {
                Object o = request.getSession().getAttribute(name);
                if (o != null) preservedSessionObjects.put(name, o);
            }

            request.getSession(false).invalidate();
            request.getSession().setAttribute(SESSION_KEY, 1);

            //preserve atributov
            for (String name : preservedSessionObjectNames)
            {
                Object o = preservedSessionObjects.get(name);
                if (o != null) request.getSession().setAttribute(name, o);
            }
        }
    }

    /**
     * Ulozi URL pred zobrazenim logon formu na ktoru sa po prihlaseni presmeruje
     * @param request
     */
    public static void saveAfterLogonRedirect(HttpServletRequest request)
    {
        HttpSession session = request.getSession();

        Identity user = UsersDB.getCurrentUser(request);
        //ak uz je prihlaseny user, neulozime (asi len nema prava)
        if (user != null) return;

        //ak uz mame nieco ulozene neprepiseme to
        if (session.getAttribute("adminAfterLogonRedirect")!=null) return;

        //bereme orig_path, je potrebne toto volat zo vsetkych miest pred redirectom dalej
        //teoreticky by sa dal pouzit referer, ale skrz viacere presmerovania a bezpecnost to nemozeme pouzit
        String origPath = (String)request.getAttribute("path_filter_orig_path");

        Logger.debug(LogonTools.class, "adminAfterLogonRedirect="+session.getAttribute("adminAfterLogonRedirect"));

        if (origPath != null && origPath.indexOf("logon")==-1 && origPath.equals("/admin/")==false && origPath.equals("/admin")==false && origPath.indexOf("/admin/index.jsp")==-1 && origPath.indexOf("/admin/welcome.jsp")==-1 && session.getAttribute("adminAfterLogonRedirect")==null)
        {
            //ukladame iba taketo cesty, nech sa nam tam neulozi odkaz na css, js alebo nieco podobne
            if (origPath.endsWith(".do") || origPath.endsWith(".jsp") || origPath.endsWith("/") || origPath.endsWith(".action"))
            {
                Logger.debug(LogonTools.class, "mainLink=" + request.getParameter("mainLink"));
                if (request.getParameter("mainLink") != null)
                {
                    origPath = request.getParameter("mainLink");
                }
                else
                {
                    String QS = (String) request.getAttribute("path_filter_query_string");
                    if (Tools.isNotEmpty(QS)) origPath = origPath + "?" + QS;
                }

                Logger.debug(LogonTools.class, "origPath=" + origPath);
                if (Tools.isNotEmpty(origPath) &&
                        origPath.indexOf("welcome.jsp") == -1 && origPath.indexOf("refresher") == -1 &&
                        origPath.indexOf("FCKeditor") == -1 && origPath.indexOf("logon.jsp") == -1 &&
                        origPath.indexOf("ajax") == -1 && origPath.indexOf("/admin/todo/") == -1 &&
                        origPath.indexOf("combine.jsp") == -1 && origPath.indexOf("edituser.do") == -1 &&
                        origPath.equals("/admin/index.jsp") == false && origPath.equals("/admin/") == false)
                {
                    session.setAttribute("adminAfterLogonRedirect", origPath);
                }
            }
        }
    }

    /**
     * Nastavi usera do session a nastavi spring prava
     * @param session
     * @param user
     */
    public static Authentication setUserToSession(HttpSession session, Identity user)
    {
        if (session != null) session.setAttribute(Constants.USER_KEY, user);

        try
        {
            //prihlasenie pre SPRING / REST
            //RequestBean requestBean = SetCharacterEncodingFilter.getCurrentRequestBean();
            if (Constants.getServletContext().getAttribute("springContext")!=null)
            {
                //ApplicationContext context = (ApplicationContext) Constants.getServletContext().getAttribute("springContext");
                //AuthenticationManager authenticationManager = context.getBean("authenticationManagerBean", AuthenticationManager.class);
                final Authentication authentication = WebjetAuthentificationProvider.authenticate(user);
                SecurityContextHolder.getContext().setAuthentication(authentication);
                return authentication;
            }
        }
        catch (Exception ex)
        {
            sk.iway.iwcm.Logger.error(ex);
        }

        return null;
    }

    /**
     * Test if login is not time/IP blocked
     * @param request
     * @return
     */
    public static boolean isLoginBlocked(HttpServletRequest request) {
        Cache cache = Cache.getInstance();

        String ipAddress = Tools.getRemoteIP(request);
        String LOGON_BLOCKED_IP_CACHE_KEY = "logon_ip_"+ipAddress;
        String LOGON_BLOCKED_USERNAME_TIME_CACHE_KEY = "logon_blocked_"+ipAddress+"_time";
        String LOGON_BLOCKED_USERNAME_COUNT_CACHE_KEY = "logon_blocked_"+ipAddress+"_count";

		Calendar cal = (Calendar)cache.getObject(LOGON_BLOCKED_IP_CACHE_KEY);
        if (cal != null) {
            Logger.debug(LogonTools.class, "Mam cal: "+Tools.formatDateTimeSeconds(cal.getTimeInMillis()));
        }

        //#20489
		Calendar calDelay = (Calendar)cache.getObject(LOGON_BLOCKED_USERNAME_TIME_CACHE_KEY);
		if(Constants.getInt("logonBlockedAfterUnsuccessCount") > 0 && Constants.getInt("logonLoginBlockedDelay") > 0 &&
				(calDelay == null || calDelay.getTimeInMillis() < Tools.getNow()))
		{
			Integer userLogonCount = (Integer)cache.getObject(LOGON_BLOCKED_USERNAME_COUNT_CACHE_KEY);
			if(userLogonCount != null)
			{
				Logger.debug(LogonTools.class, "Pokus cislo : " + userLogonCount);
				//nastavime blokovanie na login (a je jedno, ze potom zada spravne heslo)
				if( userLogonCount.intValue() > Constants.getInt("logonBlockedAfterUnsuccessCount"))
				{
					Calendar cal3 = Calendar.getInstance();
					cal3.add(Calendar.SECOND, Constants.getInt("logonLoginBlockedDelay"));
					Logger.debug(LogonTools.class, "Blokujem ip "+ipAddress+" na " + (Constants.getInt("logonLoginBlockedDelay")/60)+" minut");
					cal = cal3;
				}
			}
		}
		if(calDelay != null && (cal == null || calDelay.getTimeInMillis() > cal.getTimeInMillis()))
		{
			cal = calDelay;
		}
        //nemoze sa prihlasit lebo sa zle predtym prihlasil
		if(cal != null && cal.getTimeInMillis() > Tools.getNow())
		{
            return true;
        }
        return false;
    }

    /**
     * Cache info about bad credentials/login to block for 10 seconds
     * @param request
     */
    public static void setLoginBlocked(HttpServletRequest request) {
        Cache cache = Cache.getInstance();

        String ipAddress = Tools.getRemoteIP(request);
        String LOGON_BLOCKED_IP_CACHE_KEY = "logon_ip_"+ipAddress;
        String LOGON_BLOCKED_USERNAME_TIME_CACHE_KEY = "logon_blocked_"+ipAddress+"_time";
        String LOGON_BLOCKED_USERNAME_COUNT_CACHE_KEY = "logon_blocked_"+ipAddress+"_count";

        if (Constants.getInt("logonBlockedDelay")>0)
        {
            Calendar cal2=Calendar.getInstance();
            cal2.add(Calendar.SECOND, Constants.getInt("logonBlockedDelay"));
            cache.setObjectSeconds(LOGON_BLOCKED_IP_CACHE_KEY, cal2, Constants.getInt("logonBlockedDelay")+10, false);
        }

        Integer userLogonCount = (Integer)cache.getObject(LOGON_BLOCKED_USERNAME_COUNT_CACHE_KEY);
        if(userLogonCount != null)
        {
            userLogonCount = Integer.valueOf(userLogonCount.intValue()+1);

            Logger.debug(LogonTools.class, "Pokus cislo : " + userLogonCount);
            cache.setObjectSeconds(LOGON_BLOCKED_USERNAME_COUNT_CACHE_KEY, userLogonCount, Constants.getInt("logonLoginBlockedDelay"), false);
            //nastavime blokovanie na login (a je jedno, ze potom zada spravne heslo)
            if( userLogonCount > Constants.getInt("logonBlockedAfterUnsuccessCount"))
            {
                Calendar cal3 = Calendar.getInstance();
                cal3.add(Calendar.SECOND, Constants.getInt("logonLoginBlockedDelay"));
                Logger.debug(LogonTools.class, "Blokujem ip "+ipAddress+" na " + Constants.getInt("logonLoginBlockedDelay")+" sekund");
                cache.setObjectSeconds(LOGON_BLOCKED_USERNAME_TIME_CACHE_KEY, cal3, Constants.getInt("logonLoginBlockedDelay"), false);
            }
        }
        else
        {
            //Logger.debug(UsrLogonAction.class, "Nastavujem pocet pokusov na : 1 a trvanie na "+(Constants.getInt("logonLoginBlockedDelay") / 60)+" minut");
            cache.setObjectSeconds(LOGON_BLOCKED_USERNAME_COUNT_CACHE_KEY, 1, Constants.getInt("logonLoginBlockedDelay"), false);
        }
    }
}