Skip to content

Commit

Permalink
Merge branch 'develop' into gli-1879
Browse files Browse the repository at this point in the history
  • Loading branch information
vishal-singh-webkul committed Jun 27, 2024
2 parents 3b1c34d + 560c152 commit d1e5504
Show file tree
Hide file tree
Showing 50 changed files with 7,651 additions and 7,142 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,7 @@
<dl class="list-detail col-sm-12">
<label class="label-title">{l s='Guest info'}</label>

<dd><i class="icon-user"></i> &nbsp;<b><a href="?tab=AdminCustomers&amp;id_customer={$customer->id}&amp;viewcustomer&amp;token={getAdminToken tab='AdminCustomers'}">{$customer->firstname} {$customer->lastname}</a></b></dd>
<dd><i class="icon-envelope"></i> &nbsp;<b><a href="mailto:{$customer->email}">{$customer->email}</a></b></dd>
{if $addresses.invoice->phone_mobile || $addresses.invoice->phone}
<dd><i class="icon-phone"></i> &nbsp;<b><a href="tel:{if $addresses.invoice->phone_mobile}{$addresses.invoice->phone_mobile}{else}{$addresses.invoice->phone}{/if}">{if $addresses.invoice->phone_mobile}{$addresses.invoice->phone_mobile}{else}{$addresses.invoice->phone}{/if}</a></b></dd>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -446,24 +446,21 @@
{if isset($product->id) && $product->id}
<div class="form-group">
<label class="control-label col-lg-3" id="category_position" for="category_position">
<span class="label-tooltip" data-toggle="tooltip" title="{l s='Set position of the room type when hotel search results are displayed.'}">
<span class="label-tooltip" data-toggle="tooltip" title="{l s='Set display position of room type on the search results page.'}">
{l s='Position'}
</span>
</label>
<div class="col-lg-9">
<input type="text" id="category_position" class="form-control fixed-width-lg" name="category_position" value="{$category_position}" />
<p class="help-block">{l s='Please note that position numbering starts from 0. A position of 0 means room type will be displayed at the topmost.'}</p>
<p class="help-block">{l s='Please note that position numbering starts from 0. A position of 0 means room type will be displayed at the topmost position.'}</p>
<div class="alert alert-info">
{l s='You can manage positions of the room types of this hotel from'}
<a href="{$link->getAdminLink('AdminProducts')}&id_category={$htl_full_info['id_category']}">{l s='here.'}</a>
</div>
</div>
</div>
{/if}

{if isset($product->id) && $product->id}
<div class="alert alert-info">
{l s='You can change positions of room types of this hotel from '}
<a href="{$link->getAdminLink('AdminProducts')}&id_category={$htl_full_info['id_category']}">{l s='here.'}</a>
</div>
{/if}

{* <div class="form-group">
<label class="control-label col-lg-3" for="tags_{$id_lang}">
<span class="label-tooltip" data-toggle="tooltip"
Expand Down
11 changes: 6 additions & 5 deletions admin/themes/default/template/controllers/products/occupancy.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

<div class="alert alert-info">
{l s='Below, enter the base occupancy of this room type.'}
<p><b>{l s='Note'}</b>: {l s='Minimum 1 adult is madatory in the base occupancy of the room type'}</p>
</div>

<div class="form-group">
Expand All @@ -35,7 +36,7 @@
</span>
</label>
<div class="col-sm-3">
<input id="base_adults" type="text" name="base_adults" class="form-control" value="{if isset($roomTypeInfo)}{$roomTypeInfo['adults']|escape:'htmlall':'UTF-8'}{else}2{/if}">
<input id="base_adults" type="text" name="base_adults" class="form-control" value="{if isset($smarty.post.base_adults)}{$smarty.post.base_adults|escape:'html':'UTF-8'}{elseif isset($roomTypeInfo['adults'])}{$roomTypeInfo['adults']|escape:'html':'UTF-8'}{else}2{/if}">
</div>
</div>
<div class="form-group">
Expand All @@ -46,7 +47,7 @@
</span>
</label>
<div class="col-sm-3">
<input id="base_children" type="text" name="base_children" class="form-control" {if isset($roomTypeInfo)}value="{$roomTypeInfo['children']|escape:'htmlall':'UTF-8'}"{/if}>
<input id="base_children" type="text" name="base_children" class="form-control" value="{if isset($smarty.post.base_children)}{$smarty.post.base_children|escape:'html':'UTF-8'}{elseif isset($roomTypeInfo['children'])}{$roomTypeInfo['children']|escape:'html':'UTF-8'}{else}0{/if}">
</div>
</div>
<input id="is_occupancy_submit" type="hidden" name="is_occupancy_submit" class="form-control" value="0">
Expand All @@ -67,7 +68,7 @@
</span>
</label>
<div class="col-sm-3">
<input id="max_adults" type="text" name="max_adults" class="form-control" {if isset($roomTypeInfo)}value="{$roomTypeInfo['max_adults']|escape:'htmlall':'UTF-8'}"{/if}>
<input id="max_adults" type="text" name="max_adults" class="form-control" value="{if isset($smarty.post.max_adults)}{$smarty.post.max_adults|escape:'html':'UTF-8'}{elseif isset($roomTypeInfo['max_adults'])}{$roomTypeInfo['max_adults']|escape:'html':'UTF-8'}{/if}">
</div>
</div>
<div class="form-group">
Expand All @@ -78,7 +79,7 @@
</span>
</label>
<div class="col-sm-3">
<input id="max_children" type="text" name="max_children" class="form-control" {if isset($roomTypeInfo)}value="{$roomTypeInfo['max_children']|escape:'htmlall':'UTF-8'}"{/if}>
<input id="max_children" type="text" name="max_children" class="form-control" value="{if isset($smarty.post.max_children)}{$smarty.post.max_children|escape:'html':'UTF-8'}{elseif isset($roomTypeInfo['max_children'])}{$roomTypeInfo['max_children']|escape:'html':'UTF-8'}{/if}">
</div>
</div>
<div class="form-group">
Expand All @@ -89,7 +90,7 @@
</span>
</label>
<div class="col-sm-3">
<input id="max_guests" type="text" name="max_guests" class="form-control" {if isset($roomTypeInfo)}value="{$roomTypeInfo['max_guests']|escape:'htmlall':'UTF-8'}"{/if}>
<input id="max_guests" type="text" name="max_guests" class="form-control" value="{if isset($smarty.post.max_guests)}{$smarty.post.max_guests|escape:'html':'UTF-8'}{elseif isset($roomTypeInfo['max_guests'])}{$roomTypeInfo['max_guests']|escape:'html':'UTF-8'}{/if}">
</div>
</div>

Expand Down
77 changes: 29 additions & 48 deletions classes/MaintenanceAccess.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,15 @@
* @license https://store.webkul.com/license.html
*/

class MaintenanceAccessCore extends ObjectModel
class MaintenanceAccessCore extends ObjectModel
{

public $id_maintenance_access;
public $ip_address;
public $email;
public $date_add;
const USERNAME_ATTEMPTS_PER_QUARTER_HOUR = 3;
const IP_ATTEMPTS_QUARTER_HOUR = 12;
const USERNAME_ATTEMPTS_PER_HOUR = 6;
const IP_ATTEMPTS_PER_HOUR = 24;
const QUARTER_HOUR = 60*15;
const HOUR = 60*60;

/**
* @see ObjectModel::$definition
*/
const LOGIN_ATTEMPTS_WINDOW = 30; /* in minutes */

public static $definition = array(
'table' => 'maintenance_access',
'primary' => 'id_maintenance_access',
Expand All @@ -46,51 +38,40 @@ class MaintenanceAccessCore extends ObjectModel
),
);

public function cleanData()
public function removeFailedAttempts($email, $ipAddress)
{
$time = (time() - (self::HOUR*2));
Db::getInstance()->execute(
'DELETE FROM `' . _DB_PREFIX_ .'maintenance_access`
WHERE `date_add` < "' . pSQL(date("Y-m-d H:i:s", $time)) . '"'
'DELETE FROM `' . _DB_PREFIX_ .'maintenance_access` ma
WHERE (ma.`email` = "'.pSQL($email).'" AND ma.`ip_address` = "'.pSQL($ipAddress).'")'
);
}

public function getUserFailedCount($time, $email=false, $ip_address=false, $attempts)
public function getFailedAttemptsCount($email, $ipAddress)
{
$sql = "SELECT COUNT(`id_maintenance_access`) FROM `". _DB_PREFIX_ ."maintenance_access` WHERE `date_add` > '"
. pSQL(date('Y-m-d H:i:s', $time)) ."'";

if ($email) {
$sql .= " AND `email` = '".pSQL($email)."'";
}

if ($ip_address) {
$sql .= " AND `ip_address` = '".pSQL($ip_address)."'";
}
$sql = 'SELECT COUNT(ma.`id_maintenance_access`)
FROM `'._DB_PREFIX_.'maintenance_access` ma
WHERE (ma.`email` = "'.pSQL($email).'" OR ma.`ip_address` = "'.pSQL($ipAddress).'")
AND TIMESTAMPDIFF(
MINUTE,
ma.`date_add`,
(
SELECT MAX(ma.`date_add`)
FROM `'._DB_PREFIX_.'maintenance_access` ma
WHERE (ma.`email` = "'.pSQL($email).'" OR ma.`ip_address` = "'.pSQL($ipAddress).'")
AND TIMESTAMPDIFF(MINUTE, ma.`date_add`, NOW()) < '.(int) MaintenanceAccess::LOGIN_ATTEMPTS_WINDOW.'
)
) < '.(int) MaintenanceAccess::LOGIN_ATTEMPTS_WINDOW;

return Db::getInstance()->getValue($sql) >= $attempts;
return Db::getInstance()->getValue($sql);
}

public function checkLimit($email)
public function getLastAttempt($email, $ipAddress)
{
$has_error = false;
$minutes_ago = time() - self::QUARTER_HOUR;
$hours_ago = time() - self::HOUR;
$ip_address = Tools::getRemoteAddr();

$has_error |= $this->getUserFailedCount(
$minutes_ago, $email, false, self::USERNAME_ATTEMPTS_PER_QUARTER_HOUR
)? true : $has_error;
$has_error |= $this->getUserFailedCount(
$minutes_ago, false, $ip_address, self::IP_ATTEMPTS_QUARTER_HOUR
)? true : $has_error;
$has_error |= $this->getUserFailedCount(
$hours_ago, $email, false, self::USERNAME_ATTEMPTS_PER_HOUR
)? true : $has_error;
$has_error |= $this->getUserFailedCount(
$hours_ago, false, $ip_address, self::IP_ATTEMPTS_PER_HOUR
)? true : $has_error;

return $has_error;
return Db::getInstance()->getRow(
'SELECT *
FROM `'._DB_PREFIX_.'maintenance_access` ma
WHERE (ma.`email` = "'.pSQL($email).'" OR ma.`ip_address` = "'.pSQL($ipAddress).'")
ORDER BY ma.`date_add` DESC'
);
}
}
}
2 changes: 1 addition & 1 deletion classes/Product.php
Original file line number Diff line number Diff line change
Expand Up @@ -5369,7 +5369,7 @@ public function setPositionInCategory($position)

$currentPosition = $this->getPositionInCategory();

if ($currentPosition && isset($result[$currentPosition])) {
if ($currentPosition !== false && isset($result[$currentPosition])) {
$save = $result[$currentPosition];
unset($result[$currentPosition]);
array_splice($result, (int)$position, 0, $save);
Expand Down
127 changes: 87 additions & 40 deletions classes/controller/FrontController.php
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,7 @@ protected function displayMaintenancePage()
}

if (Tools::isSubmit('SubmitLogin')
&& !Configuration::get('PS_SHOP_ENABLE')
&& Configuration::get('PS_ALLOW_EMP')
&& !Context::getContext()->cookie->enable_maintenance_view
) {
Expand Down Expand Up @@ -812,56 +813,102 @@ protected function displayMaintenancePage()

protected function processLogin($email, $passwd)
{
$result = false;
$objMaintenanceAccess = new MaintenanceAccess();

/* Check fields validity */
if (empty($email)) {
$this->errors[] = Tools::displayError('Email is empty.');
} elseif (!Validate::isEmail($email)) {
$this->errors[] = Tools::displayError('Invalid email address.');
$remoteIpAddress = Tools::getRemoteAddr();
$maxAttempts = Configuration::get('PS_ALLOW_EMP_MAX_ATTEMPTS');

if ($maxAttempts) {
$objMaintenanceAccess = new MaintenanceAccess();
$attemptsCount = $objMaintenanceAccess->getFailedAttemptsCount($email, $remoteIpAddress); // does not include the current one
if ($attemptsCount >= $maxAttempts) {
if ($lastAttempt = $objMaintenanceAccess->getLastAttempt($email, $remoteIpAddress)) {
$minutesElapsed = (int) ((time() - strtotime($lastAttempt['date_add'])) / 60);

if ($minutesElapsed <= MaintenanceAccess::LOGIN_ATTEMPTS_WINDOW) {
$minutesLeft = MaintenanceAccess::LOGIN_ATTEMPTS_WINDOW - $minutesElapsed;
if ($minutesLeft > 1) {
$this->errors[] = Tools::displayError(sprintf('You have reached the limit of login attempts, please try after %d minutes.', $minutesLeft));
} elseif ($minutesLeft == 1) {
$this->errors[] = Tools::displayError(sprintf('You have reached the limit of login attempts, please try after %d minute.', $minutesLeft));
}
}
}
}
}

if (empty($passwd)) {
$this->errors[] = Tools::displayError('The password field is blank.');
} elseif (!Validate::isPasswd($passwd)) {
$this->errors[] = Tools::displayError('Invalid password.');
}
if (!count($this->errors)) {
if (empty($email)) {
$this->errors[] = Tools::displayError('The Email address field is blank.');
} elseif (!Validate::isEmail($email)) {
$this->errors[] = Tools::displayError('Invalid Email address.');
}

if ($objMaintenanceAccess->checkLimit($email)) {
$this->errors[] =Tools::displayError('You have exceeded the limit of login attempts, please try after some time');
}
if (empty($passwd)) {
$this->errors[] = Tools::displayError('The Password field is blank.');
} elseif (!Validate::isPasswd($passwd)) {
$this->errors[] = Tools::displayError('Invalid Password.');
}

if (!count($this->errors)) {
// Find employee
$this->context->employee = new Employee();
$is_employee_loaded = $this->context->employee->getByEmail($email, $passwd);
$employee_associated_shop = $this->context->employee->getAssociatedShops();
if (!$is_employee_loaded) {
$this->errors[] = Tools::displayError('The Employee does not exist, or the password provided is incorrect.');
$this->context->employee->logout();
} elseif (empty($employee_associated_shop) && !$this->context->employee->isSuperAdmin()) {
$this->errors[] = Tools::displayError('This employee does not manage the shop anymore (Either the shop has been deleted or permissions have been revoked).');
$this->context->employee->logout();
if (!count($this->errors)) {
// Find employee
$this->context->employee = new Employee();
$is_employee_loaded = $this->context->employee->getByEmail($email, $passwd);
$employee_associated_shop = $this->context->employee->getAssociatedShops();

if (!$is_employee_loaded) {
$this->errors[] = Tools::displayError('The employee does not exist, or the password provided is incorrect.');
$this->context->employee->logout();
} elseif (empty($employee_associated_shop) && !$this->context->employee->isSuperAdmin()) {
$this->errors[] = Tools::displayError('This employee does not manage the website anymore (either the website has been deleted or permissions have been revoked).');
$this->context->employee->logout();
} else {
// Login successful
// Update cookie
$cookie = Context::getContext()->cookie;
$cookie->enable_maintenance_view = $this->context->employee->id;
$cookie->remote_addr = ip2long($remoteIpAddress);
$cookie->write();

// Reset attempts count on successful login
$objMaintenanceAccess->removeFailedAttempts($email, $remoteIpAddress);
}

if (count($this->errors)) {
// Save only if attempts limit is set
if ($maxAttempts) {
$objMaintenanceAccess = new MaintenanceAccess();
$objMaintenanceAccess->email = $email;
$objMaintenanceAccess->ip_address = $remoteIpAddress;
$objMaintenanceAccess->save();

if ($attemptsCount < $maxAttempts) {
$attemptsLeft = $maxAttempts - $attemptsCount - 1;

if ($attemptsLeft > 0) {
if ($attemptsLeft > 1) {
$this->errors[] = Tools::displayError(sprintf('%d attempts left.', ($maxAttempts - $attemptsCount - 1)));
} else {
$this->errors[] = Tools::displayError(sprintf('%d attempt left.', ($maxAttempts - $attemptsCount - 1)));
}
} else {
if (MaintenanceAccess::LOGIN_ATTEMPTS_WINDOW > 1) {
$this->errors[] = Tools::displayError(sprintf('You have reached the limit of login attempts, please try after %d minutes.', MaintenanceAccess::LOGIN_ATTEMPTS_WINDOW));
} else {
$this->errors[] = Tools::displayError(sprintf('You have reached the limit of login attempts, please try after %d minute.', MaintenanceAccess::LOGIN_ATTEMPTS_WINDOW));
}
}
}
}

$this->context->smarty->assign('errors', $this->errors);
} else {
Tools::redirect('index.php');
}
} else {
// Update cookie
$cookie = Context::getContext()->cookie;
$cookie->enable_maintenance_view = $this->context->employee->id;
$cookie->remote_addr = ip2long(Tools::getRemoteAddr());
$cookie->write();
}
if (count($this->errors)) {
$this->context->smarty->assign('errors', $this->errors);
$objMaintenanceAccess->email = $email;
$objMaintenanceAccess->ip_address = Tools::getRemoteAddr();
$objMaintenanceAccess->save();
} else {
Tools::redirect('index.php');
}
} else {
$this->context->smarty->assign('errors', $this->errors);
}
return $result;
}

/**
Expand Down
Loading

0 comments on commit d1e5504

Please sign in to comment.