Jump to content

Restrict Employee Login Based on Time & Day in Prestashop 1.7


Eutanasio

Recommended Posts

Hi!

I'd like to share a small code tweak to control when specific employees can log in to your back office based on the day and time. This can be especially useful if you wish to limit access for particular profiles during non-working hours.

Code Overview:

  • Extending Employee Class: We extend the core Employee.php class without modifying the core file.
  • Password Check Alteration: We override the checkPassword function to incorporate our logic. If an employee with a specific profile (e.g., id_profile = 5) attempts to log in outside the allowed hours, they're denied access, and the attempt is logged.
  • Timezone Handling: Before checking login timings, we set the timezone to the shop's timezone.
  • Defining Working Hours: We've defined working hours for each day. By default, weekdays (Mon-Fri) are from 10 am to 7 pm, Saturdays from 12 pm to 6 pm, and Sundays are restricted completely.
<?php

if (!defined('_PS_VERSION_')) {
    exit;
}

class Employee extends EmployeeCore
{
public static function checkPassword($id_employee, $passwd, $id_profile = null)
{
    $restrictedProfiles = [5, 13]; // Adjust the profile IDs as needed

    if (in_array($id_profile, $restrictedProfiles) && !$this->canEmployeeLogin()) {
        // Log the failed login attempt for administrative purposes
        PrestaShopLogger::addLog("Employee with ID {$id_employee} attempted to log in outside the working hours.", 1, null, 'Employee', $id_employee);
        
        return false;
    }

    return parent::checkPassword($id_employee, $passwd, $id_profile);
}

    private function canEmployeeLogin()
    {
        $originalTimezone = date_default_timezone_get();

        $shopTimezone = Configuration::get('PS_TIMEZONE');
        if (!in_array($shopTimezone, timezone_identifiers_list())) {
            PrestaShopLogger::addLog("Invalid timezone set in PrestaShop configuration: {$shopTimezone}.", 3, null, 'Configuration', null);
            return false;
        }

        date_default_timezone_set($shopTimezone);

        $currentHour = date('G');
        $currentDay  = date('N'); 

        $canLogin = $this->isLoginTime($currentDay, $currentHour);

        date_default_timezone_set($originalTimezone);

        return $canLogin;
    }

    private function isLoginTime($currentDay, $currentHour)
    {
        $defaultWeekdayHours = ['start' => 9, 'end' => 21];
        
        $loginHours = [
            1 => $defaultWeekdayHours,  // Monday
            2 => $defaultWeekdayHours,  // Tuesday
            3 => $defaultWeekdayHours,  // Wednesday
            4 => $defaultWeekdayHours,  // Thursday
            5 => $defaultWeekdayHours,  // Friday
            6 => ['start' => 10, 'end' => 20],  // Saturday
            7 => ['start' => 0, 'end' => 0],    // Sunday
        ];

        return $currentHour >= $loginHours[$currentDay]['start'] && $currentHour < $loginHours[$currentDay]['end'];
    }
}

Adapting for Your Needs:

  • Employee Profile ID: Change the $id_profile === 5 condition if you want to apply restrictions for other profiles.
  • Modify Working Hours: Adjust the $loginHours array to define your working hours per day.
$loginHours = [
    1 => ['start' => 10, 'end' => 19],  // Monday
    // ... add or modify days as needed
];

Note: Ensure that the timezone set in your Prestashop configuration is valid. Invalid timezones will be logged and restrict access.

Feedback and suggestions are always welcome! ūüöÄ

Edited by Eutanasio
function must be static as required by Prestashop, so fixed the code (see edit history)
  • Like 1
Link to comment
Share on other sites

18 hours ago, ventura said:

I am not sure that modifying the class is the best method. It is possible that it can be done by using the hook

actionAdminLoginControllerLoginBefore.

or by modifying/override the controllers/admin/AdminLoginController.php

Well, your approach of using hooks or modifying the controller is generally considered more "correct" in the context of PrestaShop development as it adheres to the platform's design philosophy of allowing extensions without directly modifying or extending core classes. It's more update-safe and aligns better with best practices for modular and maintainable code.

But if you're looking for a quick solution and are aware of the potential issues with updates, my approach might be suitable. On the other hand, if you're aiming for long-term maintainability and flexibility, Ventura's approach is recommended.

Link to comment
Share on other sites

  • 2 months later...

Well, my first solution didn't work, so I modified AdminLoginController.php as @ventura suggested. This code modification prevents users (with profile ID's 5 & 13) from login on the specified schedule, but what I didn't get to make work are:
- The error message the user gets when not allowed to login
- The logout redirection that should reload the admin login page

// Add the restricted profiles array and the time-based restriction methods
protected $restrictedProfiles = [5, 13]; // Adjust the profile IDs as needed

protected function canEmployeeLogin($employee)
{
    $originalTimezone = date_default_timezone_get();
    $shopTimezone = Configuration::get('PS_TIMEZONE');
    if (!in_array($shopTimezone, timezone_identifiers_list())) {
        PrestaShopLogger::addLog("Invalid timezone set in PrestaShop configuration: {$shopTimezone}.", 3, null, 'Configuration', null);
        return false;
    }

    date_default_timezone_set($shopTimezone);

    $currentHour = date('G');
    $currentDay  = date('N');

    $canLogin = $this->isLoginTime($currentDay, $currentHour);

    date_default_timezone_set($originalTimezone);

    return $canLogin;
}

protected function isLoginTime($currentDay, $currentHour)
{
    $defaultWeekdayHours = ['start' => 9, 'end' => 21];

    $loginHours = [
        1 => $defaultWeekdayHours,  // Monday
        2 => $defaultWeekdayHours,  // Tuesday
        3 => $defaultWeekdayHours,  // Wednesday
        4 => $defaultWeekdayHours,  // Thursday
        5 => $defaultWeekdayHours,  // Friday
        6 => ['start' => 10, 'end' => 20],  // Saturday
        7 => ['start' => 0, 'end' => 0],    // Sunday
    ];

    return $currentHour >= $loginHours[$currentDay]['start'] && $currentHour < $loginHours[$currentDay]['end'];
}


public function processLogin()
{
    // ... (previous code for field validity checks)

    if (!count($this->errors)) {
        // ... (any existing code right before the employee validation)

        // Time-based restriction logic starts here
        // Find employee
        $this->context->employee = new Employee();
        $is_employee_loaded = $this->context->employee->getByEmail($email, $passwd);

        if ($is_employee_loaded && in_array($this->context->employee->id_profile, $this->restrictedProfiles)) {
            if (!$this->canEmployeeLogin($this->context->employee)) {
                // Log the failed login attempt for administrative purposes
                PrestaShopLogger::addLog(
                    "Employee with ID {$this->context->employee->id} attempted to log in outside the working hours.",
                    1,
                    null,
                    'Employee',
                    $this->context->employee->id
                );
                
                // Add an error to prevent login
                $this->errors[] = $this->trans(
                    'You cannot log in at this time.',
                    array(),
                    'Admin.Login.Notification'
                );

                // Log out the employee immediately to prevent session from continuing
                $this->context->employee->logout();

                // No need to redirect as the logout method should take care of this
                return;
            }
        }
        // Time-based restriction logic ends here

        // ... (rest of the login process, if no errors)
    }

    // ... (any other code that should run regardless of whether there are errors or not)
}

 

Link to comment
Share on other sites

On 11/4/2023 at 8:44 PM, dnk.hack said:

The best way is to create a module with the following features.
- Database table for Employee scheduling
- ObjectModel Class for that table
- GRID Controller for ObjectModel in questions
- Hook to auth or override directly in the module Symfony Controller method to handle the Employee schedule

Very easy!
 

of course, thanks for sharing! but I have no clue how to properly create a module. I've been customizing code for Prestashop for more than 10 years on a very basic level and trying to do it myself and with the help of the community, so others may also profit from what we achieve together and not to always rely on external programmers for every single tweak we need.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...