Search code examples
javascriptphpajaxpostsession-timeout

db table not getting updated when forcing logout using ajax


As stated in the title, db table trace_users is not getting updated when no activity happens for 30 mins but its get updated when its 6 mins.

The following code (both JS and PHP) is inside the same php file mno.php.

I am storing the last activity of user through this line let lastActivity = <?php echo time(); ?> ; present in the script below.

<?php
session_start();     
if (isset($_GET['action']) && $_GET['action'] == "logout")
{
    session_destroy(); // destroy session data in storage
    !isset($_SESSION['admin']);
    $open = "false";
    $write = "0";
    $stmt = $connect->prepare("UPDATE trace_users SET open=?, write=? WHERE user_name=?");
    $usname = !empty($_SESSION['user_name']) ? $_SESSION['user_name'] : '';
    $stmt->bind_param('sss', $open, $write, $usname);
    $stmt->execute();
}
?>
<script>
    jQuery(document).ready(function($) {

        let lastActivity = <?php echo time(); ?> ;  // storing last activity of user

        let now = <?php echo time(); ?> ;

        let logoutAfter = 360;

        let timer = setInterval(function() {
            now++;
            let delta = now - lastActivity;
            console.log(delta);
            if (delta > logoutAfter) {
                clearInterval(timer);
                //DO AJAX REQUEST TO close.php
                $.ajax({
                    url: "/abc/mno.php",
                    type: 'GET',
                    data: {
                        action: 'logout'
                    }, // Line A
                    success: function(data) {
                        console.log(data); // Line B
                    },
                    error: function(jqXHR, textStatus, errorThrown) {
                        alert(textStatus);
                    }
                });
            }
        }, 1000);
    }); 
</script>

Problem Statement:

I am wondering what changes I should make in the code above so that when no activity happens for 30 mins (1800 seconds) then the db table should also get updated.

Case1 (Not Working) : 1800 seconds (page logs out, db doesn't update)
Case2 (Working) : 360 seconds (page logs out, db gets updated)

The values inside session.gc_maxlifetime are 1440(Local Value) 1440(Master Value)

This is what I have tried/debugged:

On the network tab, I am getting Request Method GET when session timeout is set 6 mins and 60 mins.


Solution

  • You need to pass to the javascript some sort of permanent UID that identifies the user even after the session expires.

    For the sake of simplification, I'm using user_name that already exists in your code. But you can also assign an UUID for each user, so that one can't guess another user's name and can't modify their stats.


    First, you'll pass the $_SESSION['user_name'] from PHP to the JS closure.

    let userName = "<?php echo $_SESSION['user_name']; ?>";  // don't forget to wrap the JS string value in quotes or apostrophes
    

    Then, you'll pass it in the AJAX request payload.

    data: {
        action: 'logout',
        user_name: userName  // added param
    },
    

    Finally, you'll overwrite the value that is sent to DB (if it's sent with the payload)

    $usname = !empty($_SESSION['user_name']) ? $_SESSION['user_name'] : '';  // original line
    if (isset($_GET['user_name']) && !empty($_GET['user_name'])) {
        $usname = $_GET['user_name'];
    }
    $stmt->bind_param('sss', $open, $write, $usname);  // original line
    

    Complete updated code:

    <?php
    if (isset($_GET['action']) && $_GET['action'] == "logout")
    {
        session_destroy(); // destroy session data in storage
        !isset($_SESSION['pageadmin']);
        $open = "false";
        $write = "0";
        $stmt = $connect->prepare("UPDATE trace_users SET open=?, write=? WHERE user_name=?");
        $usname = !empty($_SESSION['user_name']) ? $_SESSION['user_name'] : '';
        if (isset($_GET['user_name']) && !empty($_GET['user_name'])) {
            $usname = $_GET['user_name'];
        }
        $stmt->bind_param('sss', $open, $write, $usname);
        $stmt->execute();
    }
    ?>
    <script>
        jQuery(document).ready(function($) {
    
            let lastActivity = <?php echo time(); ?> ;  // storing last activity of user
    
            let now = <?php echo time(); ?> ;
    
            let logoutAfter = 10;
    
            let userName = "<?php echo $_SESSION['user_name']; ?>";
    
            let timer = setInterval(function() {
                now++;
                let delta = now - lastActivity;
                console.log(delta);
                if (delta > logoutAfter) {
                    clearInterval(timer);
                    //DO AJAX REQUEST TO close.php
                    $.ajax({
                        url: "/abc/mno.php",
                        type: 'GET',
                        data: {
                            action: 'logout',
                            user_name: userName
                        }, // Line A
                        success: function(data) {
                            console.log(data); // Line B
                        },
                        error: function(jqXHR, textStatus, errorThrown) {
                            alert(textStatus);
                        }
                    });
                }
            }, 1000);
        }); 
    </script>
    

    Few notes at the end:

    • It's bad practice to combine PHP, HTML and JS altogether in one file.
    • There are some parts of your code that are not easily reproducible and I had to guess from the context (e.g. i guessed that the session is already set, jQuery is used but there's no <script src="...jquery.js">, there's a DB query but no separate SQL import to try it quickly). Please read and apply the knowledge from How to create a Minimal, Reproducible Example in your next question, so that more people are able or willing to help you with it.