Skip to content

Commit

Permalink
! Fixing a chicken and egg issue not allowing the update to proceed c…
Browse files Browse the repository at this point in the history
…orrectly

Signed-off-by: Nicholas K. Dionysopoulos <[email protected]>
  • Loading branch information
nikosdion committed Jul 23, 2024
1 parent e56f1e7 commit 25c414a
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 10 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
<?php die(); ?>
Akeeba Panopticon 1.2.1
================================================================================
! Fixing a chicken and egg issue not allowing the update to proceed correctly

Akeeba Panopticon 1.2.0
================================================================================
+ WordPress support [gh-38]
Expand Down
1 change: 1 addition & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Development of Akeeba Panopticon takes place _in public_. You can see what we're

## 📋 CHANGELOG

* ‼️ Fixing a chicken and egg issue not allowing the update to proceed correctly
* ✨ WordPress support [gh-38]
* ✨ Much improved Docker support [gh-697]
* ✨ Translatable dates
Expand Down
19 changes: 15 additions & 4 deletions src/Application/BootstrapUtilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -513,14 +513,25 @@ public static function evaluateIPBlocking()
/** @var Loginfailures $loginfailures */
$loginfailures = Factory::getContainer()->mvcFactory->makeModel('Loginfailures');

if ($loginfailures->isIPBlocked())
try
{
$isIPBlocked = $loginfailures->isIPBlocked();
}
catch (\Exception $e)
{
return;
}

if (!$isIPBlocked)
{
return;
}

header('HTTP/1.0 403 Forbidden');

@include APATH_THEMES . '/system/forbidden.html.php';
@include APATH_THEMES . '/system/forbidden.html.php';

exit();
}
exit();
}

/**
Expand Down
63 changes: 58 additions & 5 deletions src/Model/Loginfailures.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
*/
class Loginfailures extends Model
{
static ?bool $isAvailable = null;

/**
* Log a failed login attempt.
*
Expand All @@ -33,6 +35,11 @@ class Loginfailures extends Model
*/
public function logFailure(bool $autoBlock = true): void
{
if (!$this->isAvailable())
{
return;
}

// Is the feature enabled?
if (!((bool) $this->getContainer()->appConfig->get('login_failure_enable', 1)))
{
Expand Down Expand Up @@ -115,6 +122,11 @@ public function logFailure(bool $autoBlock = true): void
*/
public function cleanupOldFailures(): void
{
if (!$this->isAvailable())
{
return;
}

// Is the feature enabled?
if (!((bool) $this->getContainer()->appConfig->get('login_failure_enable', 1)))
{
Expand Down Expand Up @@ -142,7 +154,8 @@ public function cleanupOldFailures(): void
->where(
[
$db->quoteName('ip') . ' = INET6_ATON(' . $db->quote($ip) . ')',
$db->quoteName('mark') . ' < DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL ' . intval($maxSeconds) . ' SECOND)',
$db->quoteName('mark') . ' < DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL ' . intval($maxSeconds)
. ' SECOND)',
]
);

Expand Down Expand Up @@ -180,6 +193,11 @@ public function cleanupOldFailures(): void
*/
public function isIPBlocked(): bool
{
if (!$this->isAvailable())
{
return false;
}

// Is the feature enabled?
if (!((bool) $this->getContainer()->appConfig->get('login_failure_enable', 1)))
{
Expand Down Expand Up @@ -278,6 +296,11 @@ public function isIPBlocked(): bool
*/
public function blockIp(): void
{
if (!$this->isAvailable())
{
return;
}

// Is the feature enabled?
if (!((bool) $this->getContainer()->appConfig->get('login_failure_enable', 1)))
{
Expand Down Expand Up @@ -326,10 +349,12 @@ public function blockIp(): void
// Insert a record
$insertQuery = $db->getQuery(true)
->insert($db->quoteName('#__login_lockouts'))
->columns([
$db->quoteName('ip'),
$db->quoteName('until')
])
->columns(
[
$db->quoteName('ip'),
$db->quoteName('until'),
]
)
->values(
'INET6_ATON(' . $db->quote($ip) . '), DATE_ADD(CURRENT_TIMESTAMP(), INTERVAL '
. (int) $lockoutTime . ' SECOND)'
Expand Down Expand Up @@ -362,6 +387,11 @@ public function blockIp(): void
*/
public function mustBeBlocked(): bool
{
if (!$this->isAvailable())
{
return false;
}

// Is the feature enabled?
if (!((bool) $this->getContainer()->appConfig->get('login_failure_enable', 1)))
{
Expand Down Expand Up @@ -420,6 +450,29 @@ public function mustBeBlocked(): bool
return $failuresInWindow >= $maxAllowedFailures;
}

private function isAvailable(): bool
{
if (self::$isAvailable !== null)
{
return self::$isAvailable;
}

try
{
$db = $this->container->db;
$query = 'SHOW TABLES LIKE ' . $db->quote('#__login_failures');
$tables = $db->setQuery($query)->loadColumn();

self::$isAvailable = !empty($tables);
}
catch (\Throwable $e)
{
self::$isAvailable = false;
}

return self::$isAvailable;
}

/**
* Convert a MySQL binary IP address to a printable string (Network to Printable).
*
Expand Down
2 changes: 1 addition & 1 deletion src/Model/Task.php
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ public function check(): self
? $this->cron_expression
: new CronExpression($this->cron_expression);
// Warning! The last execution time is ALWAYS stored in UTC
$relativeTime = ($this->container->dateFactory($this->last_execution ?: 'now', 'UTC'))->toW3C();
$relativeTime = ($this->container->dateFactory($this->last_execution ?: 'now', 'UTC'))->format('Y-m-d\TH:i:sP', false, false);
// The call to getNextRunDate must use our local timezone because the CRON expression is in local time
$nextRun = $cron_expression->getNextRunDate($relativeTime, timeZone: $tz)->format(DATE_W3C);

Expand Down

0 comments on commit 25c414a

Please sign in to comment.