/*
 * Copyright 2001-2022 Geert Bevin (gbevin[remove] at uwyn dot com)
 * Licensed under the Apache License, Version 2.0 (the "License")
 */
package rife.authentication.sessionvalidators;

import rife.authentication.CredentialsManager;
import rife.authentication.RememberManager;
import rife.authentication.SessionAttributes;
import rife.authentication.SessionManager;
import rife.authentication.SessionValidator;
import rife.authentication.exceptions.SessionValidatorException;
import rife.authentication.sessionvalidators.exceptions.SessionValidityCheckErrorException;
import rife.database.Datasource;
import rife.database.DbPreparedStatement;
import rife.database.DbPreparedStatementHandler;
import rife.database.DbQueryManager;
import rife.database.exceptions.DatabaseException;
import rife.database.queries.Select;

public abstract class DatabaseSessionValidator extends DbQueryManager implements SessionValidator {
    public static final int SESSION_INVALID = 0;
    public static final int SESSION_VALID = 1;

    protected CredentialsManager credentialsManager_ = null;
    protected SessionManager sessionManager_ = null;
    protected RememberManager rememberManager_ = null;

    protected DatabaseSessionValidator(Datasource datasource) {
        super(datasource);
    }

    public void setCredentialsManager(CredentialsManager credentialsManager) {
        assert credentialsManager != null;

        credentialsManager_ = credentialsManager;
    }

    public CredentialsManager getCredentialsManager() {
        return credentialsManager_;
    }

    public void setSessionManager(SessionManager sessionManager) {
        assert sessionManager != null;

        sessionManager_ = sessionManager;
    }

    public void setRememberManager(RememberManager rememberManager) {
        assert rememberManager != null;

        rememberManager_ = rememberManager;
    }

    public RememberManager getRememberManager() {
        return rememberManager_;
    }

    public SessionManager getSessionManager() {
        return sessionManager_;
    }

    public boolean isAccessAuthorized(int id) {
        return SESSION_VALID == id;
    }

    protected int _validateSession(Select sessionValidityNoRole, Select sessionValidityNoRoleRestrictHostIp, Select sessionValidityRole, Select sessionValidityRoleRestrictHostIp, ProcessSessionValidity processSessionValidity, final String authId, final String hostIp, final SessionAttributes attributes)
    throws SessionValidatorException {
        if (null == authId ||
            0 == authId.length() ||
            null == hostIp ||
            0 == hostIp.length() ||
            null == attributes) {
            return SESSION_INVALID;
        }

        int result = SESSION_INVALID;

        Select query = null;

        // select which query to use according to the role attribute
        if (attributes.hasAttribute("role")) {
            if (sessionManager_.getRestrictHostIp()) {
                query = sessionValidityRoleRestrictHostIp;
            } else {
                query = sessionValidityRole;
            }
        } else {
            if (sessionManager_.getRestrictHostIp()) {
                query = sessionValidityNoRoleRestrictHostIp;
            } else {
                query = sessionValidityNoRole;
            }
        }

        // role has been specified, use optimized validity check to limit the amount of db queries
        try {
            executeFetchFirst(query, processSessionValidity, new DbPreparedStatementHandler() {
                public void setParameters(DbPreparedStatement statement) {
                    statement
                        .setString("authId", authId)
                        .setLong("sessStart", System.currentTimeMillis() - sessionManager_.getSessionDuration());

                    if (attributes.hasAttribute("role")) {
                        statement
                            .setString("role", attributes.getAttribute("role"));
                    }
                    if (sessionManager_.getRestrictHostIp()) {
                        statement
                            .setString("hostIp", hostIp);
                    }
                }
            });
            result = processSessionValidity.getValidity();
        } catch (DatabaseException e) {
            throw new SessionValidityCheckErrorException(authId, hostIp, e);
        }

        return result;
    }
}



