Browse Source

finalize Aauth

- updated Copyright PHPDocs
- updated Libraries Aauth, Aauth/CAPTCHA & Aauth/TOTP
- updated LoginAttemptModel & UserSessionModel
- updated Tests LoginAttemptModelTest, UserSessionModelTest, CAPTCHATest, LoginTest & TOTPTest
v3-dev
REJack 6 years ago
parent
commit
7037112e59
No known key found for this signature in database
GPG Key ID: 4A44B48700429F46
  1. 1
      app/Config/Aauth.php
  2. 1
      app/Helpers/aauth_helper.php
  3. 105
      app/Libraries/Aauth.php
  4. 12
      app/Libraries/Aauth/CAPTCHA.php
  5. 14
      app/Libraries/Aauth/TOTP.php
  6. 1
      app/Models/Aauth/GroupModel.php
  7. 1
      app/Models/Aauth/GroupToGroupModel.php
  8. 1
      app/Models/Aauth/GroupToUserModel.php
  9. 1
      app/Models/Aauth/GroupVariableModel.php
  10. 38
      app/Models/Aauth/LoginAttemptModel.php
  11. 1
      app/Models/Aauth/LoginTokenModel.php
  12. 1
      app/Models/Aauth/PermModel.php
  13. 1
      app/Models/Aauth/PermToGroupModel.php
  14. 1
      app/Models/Aauth/PermToUserModel.php
  15. 1
      app/Models/Aauth/UserModel.php
  16. 48
      app/Models/Aauth/UserSessionModel.php
  17. 1
      app/Models/Aauth/UserVariableModel.php
  18. 38
      tests/Aauth/Database/LoginAttemptModelTest.php
  19. 49
      tests/Aauth/Database/UserSessionModelTest.php
  20. 9
      tests/Aauth/Libraries/Aauth/CAPTCHATest.php
  21. 19
      tests/Aauth/Libraries/Aauth/LoginTest.php
  22. 74
      tests/Aauth/Libraries/Aauth/TOTPTest.php

1
app/Config/Aauth.php

@ -8,6 +8,7 @@
* access management, public access etc.. * access management, public access etc..
* *
* @package CodeIgniter-Aauth * @package CodeIgniter-Aauth
* @since 3.0.0
* @author Emre Akay * @author Emre Akay
* @author Raphael "REJack" Jackstadt * @author Raphael "REJack" Jackstadt
* @copyright 2014-2019 Emre Akay * @copyright 2014-2019 Emre Akay

1
app/Helpers/aauth_helper.php

@ -8,6 +8,7 @@
* access management, public access etc.. * access management, public access etc..
* *
* @package CodeIgniter-Aauth * @package CodeIgniter-Aauth
* @since 3.0.0
* @author Emre Akay * @author Emre Akay
* @author Raphael "REJack" Jackstadt * @author Raphael "REJack" Jackstadt
* @copyright 2014-2019 Emre Akay * @copyright 2014-2019 Emre Akay

105
app/Libraries/Aauth.php

@ -8,6 +8,7 @@
* access management, public access etc.. * access management, public access etc..
* *
* @package CodeIgniter-Aauth * @package CodeIgniter-Aauth
* @version 3.0.0
* @author Emre Akay * @author Emre Akay
* @author Raphael "REJack" Jackstadt * @author Raphael "REJack" Jackstadt
* @copyright 2014-2019 Emre Akay * @copyright 2014-2019 Emre Akay
@ -232,9 +233,9 @@ class Aauth
$response = $request->getPostGet('h-captcha-response'); $response = $request->getPostGet('h-captcha-response');
} }
if (! $this->verifyCaptchaResponse($response)) if (! $this->verifyCaptchaResponse($response)['success'])
{ {
$this->error('Aauth.invalidCaptcha'); $this->error(lang('Aauth.invalidCaptcha'));
return false; return false;
} }
@ -310,7 +311,7 @@ class Aauth
} }
else if ($this->config->totpOnIpChange) else if ($this->config->totpOnIpChange)
{ {
if ($request->getIPAddress() !== $lastIpAddress) if ($request->getIPAddress() !== $user['last_ip_address'])
{ {
if (! empty($totpSecret) && ! $totpCode) if (! empty($totpSecret) && ! $totpCode)
{ {
@ -335,7 +336,7 @@ class Aauth
} }
else if ($this->config->totpOnIpChange) else if ($this->config->totpOnIpChange)
{ {
if ($request->getIPAddress() !== $lastIpAddress) if ($request->getIPAddress() !== $user['last_ip_address'])
{ {
$this->session->set('totp_required', true); $this->session->set('totp_required', true);
} }
@ -351,6 +352,7 @@ class Aauth
{ {
$loginTokenModel->deleteAll($user['id']); $loginTokenModel->deleteAll($user['id']);
$userSessionModel = new UserSessionModel(); $userSessionModel = new UserSessionModel();
foreach ($userSessionModel->findAll() as $userSessionRow) foreach ($userSessionModel->findAll() as $userSessionRow)
{ {
$result = $matches = []; $result = $matches = [];
@ -433,6 +435,7 @@ class Aauth
{ {
$this->error(lang('Aauth.loginFailedAll')); $this->error(lang('Aauth.loginFailedAll'));
} }
return false; return false;
} }
} }
@ -1267,7 +1270,7 @@ class Aauth
* *
* @param string $email Email for account to remind * @param string $email Email for account to remind
* *
* @return boolean Remind fails/succeeds * @return boolean
* *
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
@ -1350,7 +1353,7 @@ class Aauth
* *
* @param string $resetCode Verification code for account * @param string $resetCode Verification code for account
* *
* @return boolean Password reset fails/succeeds * @return boolean
* *
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
@ -1634,7 +1637,7 @@ class Aauth
* @param string $name New group name * @param string $name New group name
* @param string $definition New group definition * @param string $definition New group definition
* *
* @return boolean Update success/failure * @return boolean
*/ */
public function updateGroup($groupPar, string $name = null, string $definition = null) public function updateGroup($groupPar, string $name = null, string $definition = null)
{ {
@ -1680,7 +1683,7 @@ class Aauth
* *
* @param string|integer $groupPar Group id or name * @param string|integer $groupPar Group id or name
* *
* @return boolean Delete success/failure * @return boolean
*/ */
public function deleteGroup($groupPar) public function deleteGroup($groupPar)
{ {
@ -1725,7 +1728,7 @@ class Aauth
* @param integer $userId User id to add to group * @param integer $userId User id to add to group
* @param integer|string $groupPar Group id or name to add user to * @param integer|string $groupPar Group id or name to add user to
* *
* @return boolean Add success/failure * @return boolean
*/ */
public function addMember($groupPar, int $userId) public function addMember($groupPar, int $userId)
{ {
@ -1760,7 +1763,7 @@ class Aauth
* @param integer $userId User id to remove from group * @param integer $userId User id to remove from group
* @param integer|string $groupPar Group id or name to remove user from * @param integer|string $groupPar Group id or name to remove user from
* *
* @return boolean Remove success/failure * @return boolean
*/ */
public function removeMember($groupPar, int $userId) public function removeMember($groupPar, int $userId)
{ {
@ -1776,7 +1779,7 @@ class Aauth
* *
* @param integer|string $userId User id * @param integer|string $userId User id
* *
* @return object Array of group_id's * @return boolean|array
*/ */
public function getUserGroups($userId) public function getUserGroups($userId)
{ {
@ -1797,7 +1800,7 @@ class Aauth
* *
* @param integer|string $userId User id * @param integer|string $userId User id
* *
* @return object Array of perm_id's * @return boolean|array
*/ */
public function getUserPerms($userId, $state = null) public function getUserPerms($userId, $state = null)
{ {
@ -1819,7 +1822,7 @@ class Aauth
* @param integer|string $groupPar Group id * @param integer|string $groupPar Group id
* @param integer|string $subgroupPar Subgroup id or name to add to group * @param integer|string $subgroupPar Subgroup id or name to add to group
* *
* @return boolean Add success/failure * @return boolean
*/ */
public function addSubgroup($groupPar, $subgroupPar) public function addSubgroup($groupPar, $subgroupPar)
{ {
@ -1880,7 +1883,7 @@ class Aauth
* @param integer|string $groupPar Group id or name to remove * @param integer|string $groupPar Group id or name to remove
* @param integer|string $subgroupPar Sub-Group id or name to remove * @param integer|string $subgroupPar Sub-Group id or name to remove
* *
* @return boolean Remove success/failure * @return boolean
*/ */
public function removeSubgroup($groupPar, $subgroupPar) public function removeSubgroup($groupPar, $subgroupPar)
{ {
@ -1896,7 +1899,7 @@ class Aauth
* *
* @param integer|string $groupPar Group id or name to get * @param integer|string $groupPar Group id or name to get
* *
* @return object Array of subgroup_id's * @return boolean|array
*/ */
public function getSubgroups($groupPar) public function getSubgroups($groupPar)
{ {
@ -1918,7 +1921,7 @@ class Aauth
* @param integer|string $groupPar Group id or name to get * @param integer|string $groupPar Group id or name to get
* @param integer $state State (1 = allowed, 0 = denied) * @param integer $state State (1 = allowed, 0 = denied)
* *
* @return object Array of subgroup_id's * @return boolean|array
*/ */
public function getGroupPerms($groupPar, int $state = null) public function getGroupPerms($groupPar, int $state = null)
{ {
@ -1937,7 +1940,7 @@ class Aauth
* *
* @param integer $userId User id to remove from all groups * @param integer $userId User id to remove from all groups
* *
* @return boolean Remove success/failure * @return boolean
*/ */
public function removeMemberFromAll(int $userId) public function removeMemberFromAll(int $userId)
{ {
@ -1949,7 +1952,7 @@ class Aauth
/** /**
* List all groups * List all groups
* *
* @return object Array of groups * @return array
*/ */
public function listGroups() public function listGroups()
{ {
@ -1966,7 +1969,7 @@ class Aauth
* @param integer $limit Limit of users to be returned * @param integer $limit Limit of users to be returned
* @param string $orderBy Order by MYSQL string (e.g. 'name ASC', 'email DESC') * @param string $orderBy Order by MYSQL string (e.g. 'name ASC', 'email DESC')
* *
* @return array Array of groups * @return array
*/ */
public function listGroupsPaginated(int $limit = 10, string $orderBy = null) public function listGroupsPaginated(int $limit = 10, string $orderBy = null)
{ {
@ -1988,7 +1991,7 @@ class Aauth
* *
* @param integer $groupId Group id to get * @param integer $groupId Group id to get
* *
* @return string Group name * @return string
*/ */
public function getGroupName($groupId) public function getGroupName($groupId)
{ {
@ -2007,7 +2010,7 @@ class Aauth
* *
* @param integer|string $groupPar Group id or name to get * @param integer|string $groupPar Group id or name to get
* *
* @return integer Group id * @return integer
*/ */
public function getGroupId($groupPar) public function getGroupId($groupPar)
{ {
@ -2036,7 +2039,7 @@ class Aauth
* *
* @param integer|string $groupPar Group id or name to get * @param integer|string $groupPar Group id or name to get
* *
* @return integer Group id * @return integer
*/ */
public function getGroup($groupPar) public function getGroup($groupPar)
{ {
@ -2055,7 +2058,7 @@ class Aauth
* *
* @param integer|null $userId User id to get or false for current user * @param integer|null $userId User id to get or false for current user
* *
* @return integer Group id * @return boolean|array
*/ */
public function listUserGroups(int $userId = null) public function listUserGroups(int $userId = null)
{ {
@ -2089,7 +2092,7 @@ class Aauth
* @param integer $limit Limit of users to be returned * @param integer $limit Limit of users to be returned
* @param string $orderBy Order by MYSQL string (e.g. 'name ASC', 'email DESC') * @param string $orderBy Order by MYSQL string (e.g. 'name ASC', 'email DESC')
* *
* @return array Array of users * @return boolean|array
*/ */
public function listUserGroupsPaginated(int $userId = null, int $limit = 10, string $orderBy = null) public function listUserGroupsPaginated(int $userId = null, int $limit = 10, string $orderBy = null)
{ {
@ -2176,7 +2179,7 @@ class Aauth
* @param string $key Variable Key * @param string $key Variable Key
* @param integer $groupId Group id * @param integer $groupId Group id
* *
* @return boolean|string false if var is not set, the value of var if set * @return boolean|string
*/ */
public function getGroupVar(string $key, int $groupId) public function getGroupVar(string $key, int $groupId)
{ {
@ -2286,7 +2289,7 @@ class Aauth
* @param string $name New permission name * @param string $name New permission name
* @param string $definition Permission description * @param string $definition Permission description
* *
* @return boolean Update success/failure * @return boolean
*/ */
public function updatePerm($permPar, string $name = null, string $definition = null) public function updatePerm($permPar, string $name = null, string $definition = null)
{ {
@ -2334,7 +2337,7 @@ class Aauth
* *
* @param integer|string $permPar Permission id or perm name * @param integer|string $permPar Permission id or perm name
* *
* @return boolean Delete success/failure * @return boolean
*/ */
public function deletePerm($permPar) public function deletePerm($permPar)
{ {
@ -2370,9 +2373,13 @@ class Aauth
} }
} }
/*$userId User id to allow /**
* Allow User
* *
* @return bool Allow success/failure * @param integer|string $permPar Permission id or perm name
* @param integer $userId User id to allow
*
* @return boolean
*/ */
public function allowUser($permPar, int $userId) public function allowUser($permPar, int $userId)
{ {
@ -2399,9 +2406,13 @@ class Aauth
return $permToUserModel->save($permId, $userId, 1); return $permToUserModel->save($permId, $userId, 1);
} }
/*$userId User id to deny /**
* Deny User
* *
* @return bool Deny success/failure * @param integer|string $permPar Permission id or perm name
* @param integer $userId User id to deny
*
* @return boolean
*/ */
public function denyUser($permPar, int $userId) public function denyUser($permPar, int $userId)
{ {
@ -2436,7 +2447,7 @@ class Aauth
* @param integer|string $permPar Permission id or perm name * @param integer|string $permPar Permission id or perm name
* @param integer|string $groupPar Group id or name to allow * @param integer|string $groupPar Group id or name to allow
* *
* @return boolean Allow success/failure * @return boolean
*/ */
public function allowGroup($permPar, $groupPar) public function allowGroup($permPar, $groupPar)
{ {
@ -2470,7 +2481,7 @@ class Aauth
* @param integer|string $permPar Permission id or perm name * @param integer|string $permPar Permission id or perm name
* @param integer|string $groupPar Group id or name to deny * @param integer|string $groupPar Group id or name to deny
* *
* @return boolean Deny success/failure * @return boolean
*/ */
public function denyGroup($permPar, $groupPar) public function denyGroup($permPar, $groupPar)
{ {
@ -2498,9 +2509,10 @@ class Aauth
/** /**
* List Permissions * List Permissions
*
* List all permissions * List all permissions
* *
* @return object Array of permissions * @return array
*/ */
public function listPerms() public function listPerms()
{ {
@ -2565,9 +2577,11 @@ class Aauth
/** /**
* Get permission * Get permission
*
* Get permission from permisison name or id * Get permission from permisison name or id
* *
* @param integer|string $permPar Permission id or name to get * @param integer|string $permPar Permission id or name to get
*
* @return integer Permission id or NULL if perm does not exist * @return integer Permission id or NULL if perm does not exist
*/ */
public function getPerm($permPar) public function getPerm($permPar)
@ -2587,7 +2601,7 @@ class Aauth
* *
* @param integer|string $groupPar Group id or name to get * @param integer|string $groupPar Group id or name to get
* *
* @return integer Group id * @return boolean|array
*/ */
public function listGroupPerms($groupPar) public function listGroupPerms($groupPar)
{ {
@ -2615,10 +2629,15 @@ class Aauth
* @param boolean $includeBanneds Include banned users * @param boolean $includeBanneds Include banned users
* @param string $orderBy Order by MYSQL string (e.g. 'name ASC', 'email DESC') * @param string $orderBy Order by MYSQL string (e.g. 'name ASC', 'email DESC')
* *
* @return array Array of users * @return boolean|array
*/ */
public function listGroupPermsPaginated(int $groupId, int $limit = 10, string $orderBy = null) public function listGroupPermsPaginated(int $groupId, int $limit = 10, string $orderBy = null)
{ {
if (! $groupId = $this->getGroupId($groupId))
{
return false;
}
$permModel = new PermModel(); $permModel = new PermModel();
$permModel->select('id, name, definition, state'); $permModel->select('id, name, definition, state');
@ -2641,19 +2660,16 @@ class Aauth
* *
* @param integer|string $groupPar Group id or name to get * @param integer|string $groupPar Group id or name to get
* *
* @return integer Group id * @return boolean|array
*/ */
public function listUserPerms(int $userId = null) public function listUserPerms(int $userId = null)
{ {
$userModel = new UserModel();
$groupModel = new GroupModel();
if (! $userId) if (! $userId)
{ {
$userId = (int) @$this->session->user['id']; $userId = (int) @$this->session->user['id'];
} }
if (! $userModel->existsById($userId)) if (! $this->getUser($userId))
{ {
return false; return false;
} }
@ -2677,19 +2693,16 @@ class Aauth
* @param boolean $includeBanneds Include banned users * @param boolean $includeBanneds Include banned users
* @param string $orderBy Order by MYSQL string (e.g. 'name ASC', 'email DESC') * @param string $orderBy Order by MYSQL string (e.g. 'name ASC', 'email DESC')
* *
* @return array Array of users * @return boolean|array
*/ */
public function listUserPermsPaginated(int $userId = null, int $limit = 10, string $orderBy = null) public function listUserPermsPaginated(int $userId = null, int $limit = 10, string $orderBy = null)
{ {
$userModel = new UserModel();
$groupModel = new GroupModel();
if (! $userId) if (! $userId)
{ {
$userId = (int) @$this->session->user['id']; $userId = (int) @$this->session->user['id'];
} }
if (! $userModel->existsById($userId)) if (! $this->getUser($userId))
{ {
return false; return false;
} }

12
app/Libraries/Aauth/CAPTCHA.php

@ -8,6 +8,7 @@
* access management, public access etc.. * access management, public access etc..
* *
* @package CodeIgniter-Aauth * @package CodeIgniter-Aauth
* @since 3.0.0
* @author Emre Akay * @author Emre Akay
* @author Raphael "REJack" Jackstadt * @author Raphael "REJack" Jackstadt
* @copyright 2014-2019 Emre Akay * @copyright 2014-2019 Emre Akay
@ -77,7 +78,12 @@ class CAPTCHA extends \App\Libraries\Aauth
$answer = json_decode($request, true); $answer = json_decode($request, true);
if (trim($answer['success']) !== true) if (ENVIRONMENT === 'testing' && $response === 'testing')
{
$answer = ['success' => true];
}
if ($answer['success'] !== true)
{ {
return [ return [
'success' => false, 'success' => false,
@ -136,7 +142,7 @@ class CAPTCHA extends \App\Libraries\Aauth
* @param string $url URL path to CAPTCHA server. * @param string $url URL path to CAPTCHA server.
* @param array $data Array of parameters to be sent. * @param array $data Array of parameters to be sent.
* *
* @return array response * @return string
*/ */
private function _submitGet($url, $data) private function _submitGet($url, $data)
{ {
@ -156,7 +162,7 @@ class CAPTCHA extends \App\Libraries\Aauth
* @param string $url URL path to CAPTCHA server. * @param string $url URL path to CAPTCHA server.
* @param array $data Array of parameters to be sent. * @param array $data Array of parameters to be sent.
* *
* @return array response * @return string
*/ */
private function _submitPost($url, $data) private function _submitPost($url, $data)
{ {

14
app/Libraries/Aauth/TOTP.php

@ -8,6 +8,7 @@
* access management, public access etc.. * access management, public access etc..
* *
* @package CodeIgniter-Aauth * @package CodeIgniter-Aauth
* @since 3.0.0
* @author Emre Akay * @author Emre Akay
* @author Raphael "REJack" Jackstadt * @author Raphael "REJack" Jackstadt
* @copyright 2014-2019 Emre Akay * @copyright 2014-2019 Emre Akay
@ -95,13 +96,11 @@ class TOTP extends \App\Libraries\Aauth
* Verify user TOTP Code * Verify user TOTP Code
* *
* @param integer $totpCode TOTP Code * @param integer $totpCode TOTP Code
* @param string $userId User Id * @param integer $userId User Id
* *
* @return boolean * @return boolean
*/ */
public function verifyUserTotpCode(int $totpCode, string $userId = null) public function verifyUserTotpCode(int $totpCode, int $userId = null)
{
if ($this->isTotpRequired())
{ {
if (! $userId) if (! $userId)
{ {
@ -114,16 +113,15 @@ class TOTP extends \App\Libraries\Aauth
{ {
$totp = OTPHP_TOTP::create($totpSecret); $totp = OTPHP_TOTP::create($totpSecret);
if (! $totp->verify($totpCode)) if ($totp->verify($totpCode))
{ {
return false; return true;
} }
unset($_SESSION['user']['totp_required']); unset($_SESSION['user']['totp_required']);
} }
}
return true; return false;
} }
/** /**

1
app/Models/Aauth/GroupModel.php

@ -8,6 +8,7 @@
* access management, public access etc.. * access management, public access etc..
* *
* @package CodeIgniter-Aauth * @package CodeIgniter-Aauth
* @since 3.0.0
* @author Emre Akay * @author Emre Akay
* @author Raphael "REJack" Jackstadt * @author Raphael "REJack" Jackstadt
* @copyright 2014-2019 Emre Akay * @copyright 2014-2019 Emre Akay

1
app/Models/Aauth/GroupToGroupModel.php

@ -8,6 +8,7 @@
* access management, public access etc.. * access management, public access etc..
* *
* @package CodeIgniter-Aauth * @package CodeIgniter-Aauth
* @since 3.0.0
* @author Emre Akay * @author Emre Akay
* @author Raphael "REJack" Jackstadt * @author Raphael "REJack" Jackstadt
* @copyright 2014-2019 Emre Akay * @copyright 2014-2019 Emre Akay

1
app/Models/Aauth/GroupToUserModel.php

@ -8,6 +8,7 @@
* access management, public access etc.. * access management, public access etc..
* *
* @package CodeIgniter-Aauth * @package CodeIgniter-Aauth
* @since 3.0.0
* @author Emre Akay * @author Emre Akay
* @author Raphael "REJack" Jackstadt * @author Raphael "REJack" Jackstadt
* @copyright 2014-2019 Emre Akay * @copyright 2014-2019 Emre Akay

1
app/Models/Aauth/GroupVariableModel.php

@ -8,6 +8,7 @@
* access management, public access etc.. * access management, public access etc..
* *
* @package CodeIgniter-Aauth * @package CodeIgniter-Aauth
* @since 3.0.0
* @author Emre Akay * @author Emre Akay
* @author Raphael "REJack" Jackstadt * @author Raphael "REJack" Jackstadt
* @copyright 2014-2019 Emre Akay * @copyright 2014-2019 Emre Akay

38
app/Models/Aauth/LoginAttemptModel.php

@ -8,6 +8,7 @@
* access management, public access etc.. * access management, public access etc..
* *
* @package CodeIgniter-Aauth * @package CodeIgniter-Aauth
* @since 3.0.0
* @author Emre Akay * @author Emre Akay
* @author Raphael "REJack" Jackstadt * @author Raphael "REJack" Jackstadt
* @copyright 2014-2019 Emre Akay * @copyright 2014-2019 Emre Akay
@ -77,9 +78,20 @@ class LoginAttemptModel
* *
* @return void * @return void
*/ */
public function __construct(ConnectionInterface &$db = null) public function __construct(ConnectionInterface &$db = null, $config = null, $response = null)
{
if (is_null($config))
{ {
$this->config = new AauthConfig(); $config = new AauthConfig();
}
if (is_null($response))
{
$response = service('response');
}
$this->response = $response;
$this->config = $config;
$this->DBGroup = $this->config->dbProfile; $this->DBGroup = $this->config->dbProfile;
$this->table = $this->config->dbTableLoginAttempts; $this->table = $this->config->dbTableLoginAttempts;
@ -107,11 +119,11 @@ class LoginAttemptModel
if ($this->config->loginAttemptCookie) if ($this->config->loginAttemptCookie)
{ {
helper('cookie'); helper('cookie');
$cookieName = $this->config->loginAttemptCookie === true ? 'logins' : $this->config->lologinAttemptCookie; $cookieName = $this->config->loginAttemptCookie === true ? 'logins' : $this->config->loginAttemptCookie;
if ($cookie === get_cookie($cookieName)) if ($cookie = $this->response->getCookie($cookieName))
{ {
return $cookie; return empty($cookie['value']) ? 0 : $cookie['value'];
} }
} }
else else
@ -143,14 +155,16 @@ class LoginAttemptModel
if ($this->config->loginAttemptCookie) if ($this->config->loginAttemptCookie)
{ {
helper('cookie'); helper('cookie');
$cookieName = $this->config->loginAttemptCookie === true ? 'logins' : $this->config->lologinAttemptCookie; $cookieName = $this->config->loginAttemptCookie === true ? 'logins' : $this->config->loginAttemptCookie;
$expire = strtotime($this->config->loginAttemptLimitTimePeriod) - strtotime('now'); $expire = strtotime($this->config->loginAttemptLimitTimePeriod) - strtotime('now');
if ($cookie = get_cookie($cookieName)) if ($cookie = $this->response->getCookie($cookieName))
{ {
set_cookie($cookieName, $cookie + 1, $expire); $this->response->deleteCookie($cookieName);
(int) $cookie['value']++;
$this->response->setCookie($cookieName, $cookie['value'], $expire);
if ($cookie >= $this->config->loginAttemptLimit) if ($cookie['value'] >= $this->config->loginAttemptLimit)
{ {
return false; return false;
} }
@ -161,7 +175,7 @@ class LoginAttemptModel
} }
else else
{ {
set_cookie($cookieName, 1, $expire); $this->response->setCookie($cookieName, 1, $expire);
return true; return true;
} }
@ -219,8 +233,8 @@ class LoginAttemptModel
if ($this->config->loginAttemptCookie) if ($this->config->loginAttemptCookie)
{ {
helper('cookie'); helper('cookie');
$cookieName = $this->config->loginAttemptCookie === true ? 'logins' : $this->config->lologinAttemptCookie; $cookieName = $this->config->loginAttemptCookie === true ? 'logins' : $this->config->loginAttemptCookie;
delete_cookie($cookieName); $this->response->deleteCookie($cookieName);
} }
else else
{ {

1
app/Models/Aauth/LoginTokenModel.php

@ -8,6 +8,7 @@
* access management, public access etc.. * access management, public access etc..
* *
* @package CodeIgniter-Aauth * @package CodeIgniter-Aauth
* @since 3.0.0
* @author Emre Akay * @author Emre Akay
* @author Raphael "REJack" Jackstadt * @author Raphael "REJack" Jackstadt
* @copyright 2014-2019 Emre Akay * @copyright 2014-2019 Emre Akay

1
app/Models/Aauth/PermModel.php

@ -8,6 +8,7 @@
* access management, public access etc.. * access management, public access etc..
* *
* @package CodeIgniter-Aauth * @package CodeIgniter-Aauth
* @since 3.0.0
* @author Emre Akay * @author Emre Akay
* @author Raphael "REJack" Jackstadt * @author Raphael "REJack" Jackstadt
* @copyright 2014-2019 Emre Akay * @copyright 2014-2019 Emre Akay

1
app/Models/Aauth/PermToGroupModel.php

@ -8,6 +8,7 @@
* access management, public access etc.. * access management, public access etc..
* *
* @package CodeIgniter-Aauth * @package CodeIgniter-Aauth
* @since 3.0.0
* @author Emre Akay * @author Emre Akay
* @author Raphael "REJack" Jackstadt * @author Raphael "REJack" Jackstadt
* @copyright 2014-2019 Emre Akay * @copyright 2014-2019 Emre Akay

1
app/Models/Aauth/PermToUserModel.php

@ -8,6 +8,7 @@
* access management, public access etc.. * access management, public access etc..
* *
* @package CodeIgniter-Aauth * @package CodeIgniter-Aauth
* @since 3.0.0
* @author Emre Akay * @author Emre Akay
* @author Raphael "REJack" Jackstadt * @author Raphael "REJack" Jackstadt
* @copyright 2014-2019 Emre Akay * @copyright 2014-2019 Emre Akay

1
app/Models/Aauth/UserModel.php

@ -8,6 +8,7 @@
* access management, public access etc.. * access management, public access etc..
* *
* @package CodeIgniter-Aauth * @package CodeIgniter-Aauth
* @since 3.0.0
* @author Emre Akay * @author Emre Akay
* @author Raphael "REJack" Jackstadt * @author Raphael "REJack" Jackstadt
* @copyright 2014-2019 Emre Akay * @copyright 2014-2019 Emre Akay

48
app/Models/Aauth/UserSessionModel.php

@ -8,6 +8,7 @@
* access management, public access etc.. * access management, public access etc..
* *
* @package CodeIgniter-Aauth * @package CodeIgniter-Aauth
* @since 3.0.0
* @author Emre Akay * @author Emre Akay
* @author Raphael "REJack" Jackstadt * @author Raphael "REJack" Jackstadt
* @copyright 2014-2019 Emre Akay * @copyright 2014-2019 Emre Akay
@ -144,6 +145,53 @@ class UserSessionModel
// Utility // Utility
//-------------------------------------------------------------------- //--------------------------------------------------------------------
/**
* Sets the return type of the results to be as an associative array.
*
* @return Model
*/
public function asArray()
{
$this->tempReturnType = $this->returnType = 'array';
return $this;
}
/**
* Sets the return type to be of the specified type of object.
* Defaults to a simple object, but can be any class that has
* class vars with the same name as the table columns, or at least
* allows them to be created.
*
* @param string $class Class
*
* @return Model
*/
public function asObject(string $class = 'object')
{
$this->tempReturnType = $this->returnType = $class;
return $this;
}
/**
* Returns the first row of the result set. Will take any previous
* Query Builder calls into account when determing the result set.
*
* @return array|object|null
*/
public function first()
{
$builder = $this->builder();
$row = $builder->limit(1, 0)->get();
$row = $row->getFirstRow($this->tempReturnType);
$this->tempReturnType = $this->returnType;
return $row;
}
/** /**
* Provides a shared instance of the Query Builder. * Provides a shared instance of the Query Builder.
* *

1
app/Models/Aauth/UserVariableModel.php

@ -8,6 +8,7 @@
* access management, public access etc.. * access management, public access etc..
* *
* @package CodeIgniter-Aauth * @package CodeIgniter-Aauth
* @since 3.0.0
* @author Emre Akay * @author Emre Akay
* @author Raphael "REJack" Jackstadt * @author Raphael "REJack" Jackstadt
* @copyright 2014-2019 Emre Akay * @copyright 2014-2019 Emre Akay

38
tests/Aauth/Database/LoginAttemptModelTest.php

@ -1,6 +1,8 @@
<?php namespace Tests\Aauth\Database; <?php namespace Tests\Aauth\Database;
use CodeIgniter\Test\CIDatabaseTestCase; use CodeIgniter\Test\CIDatabaseTestCase;
use Config\Aauth;
use Config\App;
use App\Models\Aauth\LoginAttemptModel; use App\Models\Aauth\LoginAttemptModel;
class LoginAttemptModelTest extends CIDatabaseTestCase class LoginAttemptModelTest extends CIDatabaseTestCase
@ -15,6 +17,8 @@ class LoginAttemptModelTest extends CIDatabaseTestCase
{ {
parent::setUp(); parent::setUp();
$this->response = new \CodeIgniter\HTTP\Response(new App());
$this->model = new LoginAttemptModel($this->db); $this->model = new LoginAttemptModel($this->db);
} }
@ -53,6 +57,40 @@ class LoginAttemptModelTest extends CIDatabaseTestCase
$this->assertEquals(0, $this->model->find()); $this->assertEquals(0, $this->model->find());
} }
public function testFindCookie()
{
$config = new \Config\Aauth();
$config->loginAttemptCookie = true;
$this->model = new LoginAttemptModel($this->db, $config);
$loginAttempt = $this->model->find();
$this->assertEquals(0, $loginAttempt);
}
public function testSaveCookie()
{
$config = new \Config\Aauth();
$config->loginAttemptCookie = true;
$this->model = new LoginAttemptModel($this->db, $config, $this->response);
$this->assertTrue($this->model->save());
$this->assertEquals(1, $this->model->find());
$this->assertTrue($this->model->save());
}
public function testDeleteCookie()
{
$config = new Aauth();
$config->loginAttemptCookie = true;
$this->model = new LoginAttemptModel($this->db, $config, $this->response);
$this->model->save();
$this->assertEquals(1, $this->model->find());
$this->model->delete();
$this->assertEquals(0, $this->model->find());
}
public function testConfigDBGroup() public function testConfigDBGroup()
{ {
$this->model = new LoginAttemptModel(); $this->model = new LoginAttemptModel();

49
tests/Aauth/Database/UserSessionModelTest.php

@ -36,18 +36,53 @@ class UserSessionModelTest extends CIDatabaseTestCase
$this->seeNumRecords(0, $this->config->dbTableUserSessions, []); $this->seeNumRecords(0, $this->config->dbTableUserSessions, []);
} }
public function testDBInsert() public function testAsArrayFirst()
{ {
$this->hasInDatabase($this->config->dbTableUserSessions, [
'id' => md5(time()),
'ip_address' => '127.0.0.1',
'timestamp' => time(),
'data' => 'user|',
]);
$userSession = $this->model->asArray()->findAll();
$this->assertInternalType('array', $userSession[0]);
}
public function testAsObjectFirst()
{
$this->hasInDatabase($this->config->dbTableUserSessions, [
'id' => md5(time()),
'ip_address' => '127.0.0.1',
'timestamp' => time(),
'data' => 'user|',
]);
$userSession = $this->model->asObject()->findAll();
$this->assertInternalType('object', $userSession[0]);
}
public function testConfigDBGroup()
{
$this->model = new UserSessionModel();
$this->hasInDatabase($this->config->dbTableUserSessions, [
'id' => md5(time()),
'ip_address' => '127.0.0.1',
'timestamp' => time(),
'data' => 'user|',
]);
$userSession = $this->model->asObject()->where(['ip_address' => '127.0.0.1'])->first();
$this->assertInternalType('object', $userSession);
}
public function testDBCall()
{
$this->assertEquals(0, $this->model->insertID());
$this->seeNumRecords(0, $this->config->dbTableUserSessions, []); $this->seeNumRecords(0, $this->config->dbTableUserSessions, []);
$id = md5(time());
$this->model->insert([ $this->model->insert([
'id' => $id, 'id' => md5(time()),
'ip_address' => '127.0.0.1', 'ip_address' => '127.0.0.1',
'timestamp' => time(), 'timestamp' => time(),
'data' => '', 'data' => 'user|',
]); ]);
$this->seeNumRecords(1, $this->config->dbTableUserSessions, []); $this->assertCount(1, $this->model->asObject()->findAll());
$this->assertEquals(1, $this->model->affectedRows());
$this->assertEquals(1, $this->model->countAll());
} }
} }

9
tests/Aauth/Libraries/Aauth/CAPTCHATest.php

@ -83,13 +83,16 @@ class CAPTCHATest extends CIDatabaseTestCase
$this->library->login('admina@example.com', 'password123456'); $this->library->login('admina@example.com', 'password123456');
$this->library->login('admina@example.com', 'password123456'); $this->library->login('admina@example.com', 'password123456');
$this->library->login('admina@example.com', 'password123456'); $this->library->login('admina@example.com', 'password123456');
$_POST['g-recaptcha-response'] = '0123456789';
$this->library->login('admina@example.com', 'password123456'); $this->library->login('admina@example.com', 'password123456');
$this->assertContains('https://www.google.com/recaptcha', $this->library->generateCaptchaHtml()); $this->assertContains('https://www.google.com/recaptcha', $this->library->generateCaptchaHtml());
$config->captchaType = 'hcaptcha'; $config->captchaType = 'hcaptcha';
$this->library = new Aauth($config, true); $this->library = new Aauth($config, true);
$_POST['h-recaptcha-response'] = '0123456789';
$this->library->login('admina@example.com', 'password123456');
$this->assertEquals(lang('Aauth.invalidCaptcha'), $this->library->getErrorsArray()[0]);
$this->assertContains('https://hcaptcha.com/1', $this->library->generateCaptchaHtml()); $this->assertContains('https://hcaptcha.com/1', $this->library->generateCaptchaHtml());
} }
@ -105,5 +108,9 @@ class CAPTCHATest extends CIDatabaseTestCase
$config->captchaType = 'hcaptcha'; $config->captchaType = 'hcaptcha';
$this->library = new Aauth($config, true); $this->library = new Aauth($config, true);
$this->assertContains('invalid-input-response', $this->library->verifyCaptchaResponse('0123456789')['errorCodes']); $this->assertContains('invalid-input-response', $this->library->verifyCaptchaResponse('0123456789')['errorCodes']);
$config->captchaType = 'hcaptcha';
$this->library = new Aauth($config, true);
$this->assertTrue($this->library->verifyCaptchaResponse('testing')['success']);
} }
} }

19
tests/Aauth/Libraries/Aauth/LoginTest.php

@ -86,8 +86,25 @@ class LoginTest extends CIDatabaseTestCase
$this->seeInDatabase($config->dbTableLoginTokens, [ $this->seeInDatabase($config->dbTableLoginTokens, [
'user_id' => 1, 'user_id' => 1,
]); ]);
$this->assertTrue($this->response->hasCookie('remember')); $this->assertTrue($this->response->hasCookie('remember'));
$this->hasInDatabase($config->dbTableUserSessions, [
'id' => md5(time()),
'ip_address' => '127.0.0.1',
'timestamp' => time(),
'data' => '__ci_last_regenerate|i:' . time() . ';user|a:4:{s:2:"id";s:1:"1";s:8:"username";s:5:"admin";s:5:"email";s:17:"admin@example.com";s:8:"loggedIn";b:1;}',
'data' => '__ci_last_regenerate|i:1551553466;user|a:4:{s:2:"id";s:1:"1";s:8:"username";s:5:"admin";s:5:"email";s:17:"admin@example.com";s:8:"loggedIn";b:1;}',
]);
$config->loginSingleMode = true;
$this->library = new Aauth($config, $session);
$this->assertTrue($this->library->login('admin', 'password123456'));
$config->loginSingleMode = false;
$this->library = new Aauth($config, $session);
$this->assertFalse($this->library->login('admin', 'passwor')); $this->assertFalse($this->library->login('admin', 'passwor'));
$this->assertEquals(lang('Aauth.loginFailedUsername'), $this->library->getErrorsArray()[0]); $this->assertEquals(lang('Aauth.loginFailedUsername'), $this->library->getErrorsArray()[0]);
@ -95,6 +112,7 @@ class LoginTest extends CIDatabaseTestCase
$this->assertFalse($this->library->login('admin', 'password1234')); $this->assertFalse($this->library->login('admin', 'password1234'));
$this->assertEquals(lang('Aauth.loginFailedAll'), $this->library->getErrorsArray()[0]); $this->assertEquals(lang('Aauth.loginFailedAll'), $this->library->getErrorsArray()[0]);
$config->loginSingleMode = false;
$config->loginAccurateErrors = true; $config->loginAccurateErrors = true;
$this->library = new Aauth($config, $session); $this->library = new Aauth($config, $session);
$this->library->clearErrors(); $this->library->clearErrors();
@ -104,7 +122,6 @@ class LoginTest extends CIDatabaseTestCase
$this->library->clearErrors(); $this->library->clearErrors();
$this->assertFalse($this->library->login('user99', 'password123456')); $this->assertFalse($this->library->login('user99', 'password123456'));
$this->assertEquals(lang('Aauth.notFoundUser'), $this->library->getErrorsArray()[0]); $this->assertEquals(lang('Aauth.notFoundUser'), $this->library->getErrorsArray()[0]);
// $config->loginUseUsername = false;
$this->library = new Aauth(null, $session); $this->library = new Aauth(null, $session);
$this->assertTrue($this->library->login('admin@example.com', 'password123456')); $this->assertTrue($this->library->login('admin@example.com', 'password123456'));

74
tests/Aauth/Libraries/Aauth/TOTPTest.php

@ -8,6 +8,7 @@ use Tests\Support\Session\MockSession;
use CodeIgniter\Session\Handlers\FileHandler; use CodeIgniter\Session\Handlers\FileHandler;
use CodeIgniter\Test\CIDatabaseTestCase; use CodeIgniter\Test\CIDatabaseTestCase;
use App\Libraries\Aauth; use App\Libraries\Aauth;
use App\Models\Aauth\UserModel;
use App\Models\Aauth\UserVariableModel; use App\Models\Aauth\UserVariableModel;
use OTPHP\TOTP; use OTPHP\TOTP;
@ -60,6 +61,65 @@ class TOTPTest extends CIDatabaseTestCase
//-------------------------------------------------------------------- //--------------------------------------------------------------------
/**
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function testLogin()
{
$config = new AauthConfig();
$config->totpEnabled = true;
$session = $this->getInstance();
$this->library = new Aauth($config, $session);
$this->hasInDatabase($this->config->dbTableUserVariables, [
'user_id' => 1,
'data_key' => 'totp_secret',
'data_value' => 'JBSWY3DPEHPK3PXP',
'system' => true,
]);
$this->assertTrue($this->library->login('admin@example.com', 'password123456'));
$config->totpLogin = true;
$this->library = new Aauth($config, $session);
$this->assertFalse($this->library->login('admin@example.com', 'password123456', null, '000001'));
$this->assertEquals(lang('Aauth.invalidTOTPCode'), $this->library->getErrorsArray()[0]);
$this->library = new Aauth($config, $session);
$this->assertFalse($this->library->login('admin@example.com', 'password123456', null));
$this->assertEquals(lang('Aauth.requiredTOTPCode'), $this->library->getErrorsArray()[0]);
$this->library = new Aauth($config, $session);
$totp = TOTP::create('JBSWY3DPEHPK3PXP');
$totpCode = $totp->now();
usleep(1000);
$this->assertTrue($this->library->login('admin@example.com', 'password123456', null, $totpCode));
$userModel = new UserModel();
$userModel->protect(false)->update(1, ['last_ip_address' => '99.99.99.99']);
$config->totpOnIpChange = true;
$this->assertFalse($this->library->login('admin@example.com', 'password123456', null, '000001'));
$this->assertEquals(lang('Aauth.invalidTOTPCode'), $this->library->getErrorsArray()[0]);
$this->library = new Aauth($config, $session);
$this->assertFalse($this->library->login('admin@example.com', 'password123456', null));
$this->assertEquals(lang('Aauth.requiredTOTPCode'), $this->library->getErrorsArray()[0]);
$this->library = new Aauth($config, $session);
$this->library = new Aauth($config, $session);
$this->assertTrue($this->library->login('admin@example.com', 'password123456', null, $totpCode));
$userModel->protect(false)->update(1, ['last_ip_address' => '99.99.99.99']);
$config->totpOnIpChange = true;
$config->totpLogin = false;
$this->library = new Aauth($config, $session);
$this->assertTrue($this->library->login('admin@example.com', 'password123456'));
}
/** /**
* @runInSeparateProcess * @runInSeparateProcess
* @preserveGlobalState disabled * @preserveGlobalState disabled
@ -124,16 +184,6 @@ class TOTPTest extends CIDatabaseTestCase
$config->totpEnabled = true; $config->totpEnabled = true;
$this->library = new Aauth($config, $session); $this->library = new Aauth($config, $session);
$this->assertTrue($this->library->verifyUserTotpCode('999000', 1));
$this->library = new Aauth($config, $session);
$session->set('user', [
'id' => 1,
'loggedIn' => true,
]);
$this->assertTrue($this->library->verifyUserTotpCode('999000'));
$session = $this->getInstance(); $session = $this->getInstance();
$this->library = new Aauth($config, $session); $this->library = new Aauth($config, $session);
$session->set('user', [ $session->set('user', [
@ -142,9 +192,6 @@ class TOTPTest extends CIDatabaseTestCase
'totp_required' => true, 'totp_required' => true,
]); ]);
$this->assertTrue($this->library->verifyUserTotpCode('999000'));
$this->assertTrue($this->library->verifyUserTotpCode('999000', 1));
$this->hasInDatabase($this->config->dbTableUserVariables, [ $this->hasInDatabase($this->config->dbTableUserVariables, [
'user_id' => 1, 'user_id' => 1,
'data_key' => 'totp_secret', 'data_key' => 'totp_secret',
@ -157,6 +204,7 @@ class TOTPTest extends CIDatabaseTestCase
$totpCode = $totp->now(); $totpCode = $totp->now();
usleep(1000); usleep(1000);
$this->assertTrue($this->library->verifyUserTotpCode($totpCode));
$this->assertTrue($this->library->verifyUserTotpCode($totpCode, 1)); $this->assertTrue($this->library->verifyUserTotpCode($totpCode, 1));
} }

Loading…
Cancel
Save