old Debug\Logging is in Debug\LoggingLegacy and Debug\Logging extends Logging\Logging Logging\Logging is a new class with most of the functionality except there is no more print/outout to screen, but we use the default log levels (RFC5424) The plan is to be a frontend between the old type class and Monolog\Monolog Updated all other classes to use new class interface
2138 lines
57 KiB
PHP
2138 lines
57 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace tests;
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
use PHPUnit\Framework\MockObject\MockObject;
|
|
|
|
/*
|
|
Not yet covered tests:
|
|
- loginGetLocale
|
|
- loginGetHeaderColor
|
|
- loginGetPages
|
|
- loginGetEuid
|
|
*/
|
|
|
|
/**
|
|
* Test class for ACL\Login
|
|
* @coversDefaultClass \CoreLibs\ACL\Login
|
|
* @testdox \CoreLibs\ACL\Login method tests
|
|
*/
|
|
final class CoreLibsACLLoginTest extends TestCase
|
|
{
|
|
private static $db;
|
|
private static $log;
|
|
|
|
/**
|
|
* start DB conneciton, setup DB, etc
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function setUpBeforeClass(): void
|
|
{
|
|
if (!extension_loaded('pgsql')) {
|
|
self::markTestSkipped(
|
|
'The PgSQL extension is not available for ACL\Login test.'
|
|
);
|
|
}
|
|
// database/CoreLibsACLLogin_database_create_data.sql
|
|
$load_sql_file = __DIR__
|
|
. DIRECTORY_SEPARATOR
|
|
. 'database/CoreLibsACLLogin_database_create_data.sql';
|
|
if (!is_file($load_sql_file)) {
|
|
self::markTestIncomplete(
|
|
'Missing ACL\Login database load SQL file'
|
|
);
|
|
}
|
|
// ASSUME that DB is on Port 5432 and use DEFAULT in path postgresql
|
|
$db_user = "corelibs_acl_login_test";
|
|
$db_password = "corelibs_acl_login_test";
|
|
$db_name = "corelibs_acl_login_test";
|
|
$db_host = "localhost";
|
|
// run the drop restore script before connecting to the database
|
|
// check exit, if not null then abort
|
|
$command = __DIR__ . DIRECTORY_SEPARATOR
|
|
. "CoreLibsACLLogin_database_prepare.sh "
|
|
. "$load_sql_file "
|
|
. "$db_user "
|
|
. "$db_name "
|
|
. "$db_host ";
|
|
exec($command, $ouput, $result);
|
|
if ($result != 0 || !empty($output[0])) {
|
|
self::markTestIncomplete(
|
|
'Drop/Create ACL\Login database failed with: ' . $result
|
|
);
|
|
}
|
|
|
|
// logger is always needed
|
|
// define basic connection set valid and one invalid
|
|
self::$log = new \CoreLibs\Logging\Logging([
|
|
// 'log_folder' => __DIR__ . DIRECTORY_SEPARATOR . 'log',
|
|
'log_folder' => DIRECTORY_SEPARATOR . 'tmp',
|
|
'log_file_id' => 'CoreLibs-ACL-Login-Test',
|
|
]);
|
|
// test database we need to connect do, if not possible this test is skipped
|
|
self::$db = new \CoreLibs\DB\IO(
|
|
[
|
|
'db_name' => $db_name,
|
|
'db_user' => $db_user,
|
|
'db_pass' => $db_password,
|
|
'db_host' => $db_host,
|
|
'db_port' => 5432,
|
|
'db_schema' => 'public',
|
|
'db_type' => 'pgsql',
|
|
'db_encoding' => '',
|
|
'db_ssl' => 'allow', // allow, disable, require, prefer
|
|
'db_debug' => true,
|
|
],
|
|
self::$log
|
|
);
|
|
// ALWAYS drop DB and RECREATE DB
|
|
// dropdb -U corelibs_acl_login_test -h localhost corelibs_acl_login_test
|
|
// createdb -U corelibs_acl_login_test -O corelibs_acl_login_test -E utf8 corelibs_acl_login_test;
|
|
if (!self::$db->dbGetConnectionStatus()) {
|
|
self::markTestSkipped(
|
|
'Cannot connect to valid Test DB for ACL\Login test.'
|
|
);
|
|
}
|
|
// check that edit_user table exist, I assume if this one does,
|
|
// the rest does too
|
|
if (!self::$db->dbShowTableMetaData('edit_user') !== false) {
|
|
self::markTestIncomplete(
|
|
'Cannot find edit_user table in ACL\Login database for testing'
|
|
);
|
|
}
|
|
// always disable max query calls
|
|
self::$db->dbSetMaxQueryCall(-1);
|
|
// insert additional content for testing (locked user, etc)
|
|
$queries = [
|
|
"INSERT INTO edit_access_data "
|
|
. "(edit_access_id, name, value, enabled) VALUES "
|
|
. "((SELECT edit_access_id FROM edit_access WHERE uid = 'AdminAccess'), "
|
|
. "'test', 'value', 1)"
|
|
];
|
|
foreach ($queries as $query) {
|
|
self::$db->dbExec($query);
|
|
}
|
|
|
|
// define mandatory constant
|
|
// must set
|
|
// TARGET
|
|
define('TARGET', 'test');
|
|
// LOGIN DB SCHEMA
|
|
// define('LOGIN_DB_SCHEMA', '');
|
|
|
|
// SHOULD SET
|
|
// DEFAULT_ACL_LEVEL (d80)
|
|
|
|
// OPT:
|
|
// LOGOUT_TARGET
|
|
// PASSWORD_CHANGE
|
|
// PASSWORD_FORGOT
|
|
|
|
// LANG:
|
|
// SITE_LOCALE
|
|
// DEFAULT_LOCALE
|
|
// CONTENT_PATH (domain)
|
|
|
|
$_SESSION = [];
|
|
global $_SESSION;
|
|
}
|
|
|
|
/**
|
|
* close db
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function tearDownAfterClass(): void
|
|
{
|
|
if (self::$db->dbGetConnectionStatus()) {
|
|
self::$db->dbClose();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Undocumented function
|
|
*
|
|
* @return array
|
|
*/
|
|
public function loginProvider(): array
|
|
{
|
|
// 0[mock] : mock settings/override flag settings
|
|
// 1[get] : get array IN
|
|
// 2[post] : post array IN
|
|
// login_login, login_username, login_password, login_logout
|
|
// change_password, pw_username, pw_old_password, pw_new_password,
|
|
// pw_new_password_confirm
|
|
// 3[session]: override session set
|
|
// 4[error] : expected error code, 0 for all ok, 3000 for login page view
|
|
// note that 1000 (no db), 2000 (no session) must be tested too
|
|
// 5[return] : expected return array, eg login_error code,
|
|
// or other info data to match
|
|
$tests = [
|
|
'load, no login' => [
|
|
// error code, only for exceptions
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
],
|
|
[],
|
|
[],
|
|
[],
|
|
3000,
|
|
[
|
|
'login_error' => 0,
|
|
'error_string' => 'Success: <b>No error</b>',
|
|
'error_string_text' => 'Success: No error',
|
|
],
|
|
],
|
|
'load, no login, ajax flag' => [
|
|
// error code, only for exceptions
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
// for ajax
|
|
'ajax_page' => true,
|
|
'ajax_test_type' => 'parameter',
|
|
],
|
|
[],
|
|
[],
|
|
[],
|
|
3000,
|
|
[
|
|
'login_error' => 0,
|
|
'error_string' => 'Success: <b>No error</b>',
|
|
'error_string_text' => 'Success: No error',
|
|
// for ajax
|
|
'action' => 'login',
|
|
'ajax_get_count' => 0,
|
|
'ajax_post_count' => 5,
|
|
'ajax_post_action' => 'login',
|
|
],
|
|
],
|
|
'load, no login, ajax globals' => [
|
|
// error code, only for exceptions
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
// for ajax
|
|
'ajax_page' => true,
|
|
'ajax_test_type' => 'globals',
|
|
],
|
|
[],
|
|
[],
|
|
[],
|
|
3000,
|
|
[
|
|
'login_error' => 0,
|
|
'error_string' => 'Success: <b>No error</b>',
|
|
'error_string_text' => 'Success: No error',
|
|
// for ajax
|
|
'action' => 'login',
|
|
'ajax_get_count' => 0,
|
|
'ajax_post_count' => 5,
|
|
'ajax_post_action' => 'login',
|
|
],
|
|
],
|
|
'load, session euid set only, php error' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
],
|
|
[],
|
|
[],
|
|
[
|
|
'EUID' => 1,
|
|
],
|
|
2,
|
|
[],
|
|
],
|
|
'load, session euid set, all set' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
'edit_access_id' => 1,
|
|
'edit_access_uid' => 'AdminAccess',
|
|
'edit_access_data' => 'test',
|
|
'base_access' => 'list',
|
|
'page_access' => 'list',
|
|
],
|
|
[],
|
|
[],
|
|
[
|
|
'EUID' => 1,
|
|
'USER_NAME' => '',
|
|
'GROUP_NAME' => '',
|
|
'ADMIN' => 1,
|
|
'GROUP_ACL_LEVEL' => -1,
|
|
'PAGES_ACL_LEVEL' => [],
|
|
'USER_ACL_LEVEL' => -1,
|
|
'USER_ADDITIONAL_ACL' => [],
|
|
'GROUP_ADDITIONAL_ACL' => [],
|
|
'UNIT_UID' => [
|
|
'AdminAccess' => 1,
|
|
],
|
|
'UNIT' => [
|
|
1 => [
|
|
'acl_level' => 80,
|
|
'name' => 'Admin Access',
|
|
'uid' => 'AdminAccess',
|
|
'level' => -1,
|
|
'default' => 0,
|
|
'data' => [
|
|
'test' => 'value',
|
|
],
|
|
'additional_acl' => []
|
|
],
|
|
],
|
|
// 'UNIT_DEFAULT' => '',
|
|
// 'DEFAULT_ACL_LIST' => [],
|
|
],
|
|
0,
|
|
[
|
|
'login_error' => 0,
|
|
'admin_flag' => true,
|
|
'check_access' => true,
|
|
'check_access_id' => 1,
|
|
'check_access_data' => 'value',
|
|
'base_access' => true,
|
|
'page_access' => true,
|
|
],
|
|
],
|
|
// login: all missing
|
|
'login: failed: all missing' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
],
|
|
[],
|
|
[
|
|
'login_login' => 'Login',
|
|
'login_username' => '',
|
|
'login_password' => '',
|
|
],
|
|
[],
|
|
3000,
|
|
[
|
|
'login_error' => 102,
|
|
'error_string' => '<span style="color: red;">Fatal Error:</span> '
|
|
. '<b>Login Failed - Please enter username and password</b>',
|
|
'error_string_text' => 'Fatal Error: '
|
|
. 'Login Failed - Please enter username and password'
|
|
]
|
|
],
|
|
// login: missing username
|
|
'login: failed: missing username' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
],
|
|
[],
|
|
[
|
|
'login_login' => 'Login',
|
|
'login_username' => '',
|
|
'login_password' => 'abc',
|
|
],
|
|
[],
|
|
3000,
|
|
[
|
|
'login_error' => 102,
|
|
'error_string' => '<span style="color: red;">Fatal Error:</span> '
|
|
. '<b>Login Failed - Please enter username and password</b>',
|
|
'error_string_text' => 'Fatal Error: '
|
|
. 'Login Failed - Please enter username and password'
|
|
]
|
|
],
|
|
// login: missing password
|
|
'login: failed: missing password' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
],
|
|
[],
|
|
[
|
|
'login_login' => 'Login',
|
|
'login_username' => 'abc',
|
|
'login_password' => '',
|
|
],
|
|
[],
|
|
3000,
|
|
[
|
|
'login_error' => 102,
|
|
'error_string' => '<span style="color: red;">Fatal Error:</span> '
|
|
. '<b>Login Failed - Please enter username and password</b>',
|
|
'error_string_text' => 'Fatal Error: '
|
|
. 'Login Failed - Please enter username and password'
|
|
]
|
|
],
|
|
// login: user not found
|
|
'login: failed: user not found' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
],
|
|
[],
|
|
[
|
|
'login_login' => 'Login',
|
|
'login_username' => 'abc',
|
|
'login_password' => 'abc',
|
|
],
|
|
[],
|
|
3000,
|
|
[
|
|
'login_error' => 1010,
|
|
'error_string' => '<span style="color: red;">Fatal Error:</span> '
|
|
. '<b>Login Failed - Wrong Username or Password</b>',
|
|
'error_string_text' => 'Fatal Error: '
|
|
. 'Login Failed - Wrong Username or Password'
|
|
]
|
|
],
|
|
// login: invalid password
|
|
// 9999: not valid password encoding
|
|
// 1013: normal password failed
|
|
// 1012: plain password check failed
|
|
'login: failed: invalid password' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
],
|
|
[],
|
|
[
|
|
'login_login' => 'Login',
|
|
'login_username' => 'admin',
|
|
'login_password' => 'abc',
|
|
],
|
|
[],
|
|
3000,
|
|
[
|
|
// default password is plain text
|
|
'login_error' => 1012,
|
|
'error_string' => '<span style="color: red;">Fatal Error:</span> '
|
|
. '<b>Login Failed - Wrong Username or Password</b>',
|
|
'error_string_text' => 'Fatal Error: '
|
|
. 'Login Failed - Wrong Username or Password'
|
|
]
|
|
],
|
|
// login: ok (but deleted)
|
|
'login: ok -> failed: but deleted' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
'edit_access_id' => 1,
|
|
'base_access' => 'list',
|
|
'page_access' => 'list',
|
|
'test_deleted' => true
|
|
],
|
|
[],
|
|
[
|
|
'login_login' => 'Login',
|
|
'login_username' => 'admin',
|
|
'login_password' => 'admin',
|
|
],
|
|
[],
|
|
3000,
|
|
[
|
|
'login_error' => 106,
|
|
'error_string' => '<span style="color: red;">Fatal Error:</span> '
|
|
. '<b>Login Failed - User is deleted</b>',
|
|
'error_string_text' => 'Fatal Error: '
|
|
. 'Login Failed - User is deleted'
|
|
]
|
|
],
|
|
// login: ok (but not enabled)
|
|
'login: ok -> failed: but not enabled' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
'edit_access_id' => 1,
|
|
'base_access' => 'list',
|
|
'page_access' => 'list',
|
|
'test_enabled' => true
|
|
],
|
|
[],
|
|
[
|
|
'login_login' => 'Login',
|
|
'login_username' => 'admin',
|
|
'login_password' => 'admin',
|
|
],
|
|
[],
|
|
3000,
|
|
[
|
|
'login_error' => 104,
|
|
'error_string' => '<span style="color: red;">Fatal Error:</span> '
|
|
. '<b>Login Failed - User not enabled</b>',
|
|
'error_string_text' => 'Fatal Error: '
|
|
. 'Login Failed - User not enabled'
|
|
]
|
|
],
|
|
// login: ok (but locked)
|
|
'login: ok -> failed: but locked' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
'edit_access_id' => 1,
|
|
'base_access' => 'list',
|
|
'page_access' => 'list',
|
|
'test_locked' => true
|
|
],
|
|
[],
|
|
[
|
|
'login_login' => 'Login',
|
|
'login_username' => 'admin',
|
|
'login_password' => 'admin',
|
|
],
|
|
[],
|
|
3000,
|
|
[
|
|
'login_error' => 105,
|
|
'error_string' => '<span style="color: red;">Fatal Error:</span> '
|
|
. '<b>Login Failed - User is locked</b>',
|
|
'error_string_text' => 'Fatal Error: '
|
|
. 'Login Failed - User is locked'
|
|
]
|
|
],
|
|
// login: make user get locked strict
|
|
'login: ok -> failed: get locked, strict' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
'edit_access_id' => 1,
|
|
'base_access' => 'list',
|
|
'page_access' => 'list',
|
|
'test_get_locked' => true,
|
|
'max_login_error_count' => 2,
|
|
'test_locked_strict' => true,
|
|
],
|
|
[],
|
|
[
|
|
'login_login' => 'Login',
|
|
'login_username' => 'admin',
|
|
'login_password' => 'admin',
|
|
],
|
|
[],
|
|
0,
|
|
[
|
|
'lock_run_login_error' => 1012,
|
|
'login_error' => 105,
|
|
]
|
|
],
|
|
// login ok, but in locked period (until)
|
|
'login: ok -> failed: but locked period (until:on)' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
'edit_access_id' => 1,
|
|
'base_access' => 'list',
|
|
'page_access' => 'list',
|
|
'test_locked_period_until' => 'on'
|
|
],
|
|
[],
|
|
[
|
|
'login_login' => 'Login',
|
|
'login_username' => 'admin',
|
|
'login_password' => 'admin',
|
|
],
|
|
[],
|
|
3000,
|
|
[
|
|
'login_error' => 107,
|
|
'error_string' => '<span style="color: red;">Fatal Error:</span> '
|
|
. '<b>Login Failed - User in locked via date period</b>',
|
|
'error_string_text' => 'Fatal Error: '
|
|
. 'Login Failed - User in locked via date period'
|
|
]
|
|
],
|
|
// login ok, but in locked period (until)
|
|
'login: ok, but locked period (until:off)' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
'edit_access_id' => 1,
|
|
'edit_access_uid' => 'AdminAccess',
|
|
'edit_access_data' => 'test',
|
|
'base_access' => 'list',
|
|
'page_access' => 'list',
|
|
'test_locked_period_until' => 'off'
|
|
],
|
|
[],
|
|
[
|
|
'login_login' => 'Login',
|
|
'login_username' => 'admin',
|
|
'login_password' => 'admin',
|
|
],
|
|
[],
|
|
0,
|
|
[
|
|
'login_error' => 0,
|
|
'admin_flag' => true,
|
|
'check_access' => true,
|
|
'check_access_id' => 1,
|
|
'check_access_data' => 'value',
|
|
'base_access' => true,
|
|
'page_access' => true,
|
|
]
|
|
],
|
|
// login ok, but in locked period (after)
|
|
'login: ok -> failed: but locked period (after:on)' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
'edit_access_id' => 1,
|
|
'base_access' => 'list',
|
|
'page_access' => 'list',
|
|
'test_locked_period_after' => 'on'
|
|
],
|
|
[],
|
|
[
|
|
'login_login' => 'Login',
|
|
'login_username' => 'admin',
|
|
'login_password' => 'admin',
|
|
],
|
|
[],
|
|
3000,
|
|
[
|
|
'login_error' => 107,
|
|
'error_string' => '<span style="color: red;">Fatal Error:</span> '
|
|
. '<b>Login Failed - User in locked via date period</b>',
|
|
'error_string_text' => 'Fatal Error: '
|
|
. 'Login Failed - User in locked via date period'
|
|
]
|
|
],
|
|
// login ok, but in locked period (until, after)
|
|
'login: ok -> failed:, but locked period (until:on, after:on)' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
'edit_access_id' => 1,
|
|
'base_access' => 'list',
|
|
'page_access' => 'list',
|
|
'test_locked_period_until' => 'on',
|
|
'test_locked_period_after' => 'on'
|
|
],
|
|
[],
|
|
[
|
|
'login_login' => 'Login',
|
|
'login_username' => 'admin',
|
|
'login_password' => 'admin',
|
|
],
|
|
[],
|
|
3000,
|
|
[
|
|
'login_error' => 107,
|
|
'error_string' => '<span style="color: red;">Fatal Error:</span> '
|
|
. '<b>Login Failed - User in locked via date period</b>',
|
|
'error_string_text' => 'Fatal Error: '
|
|
. 'Login Failed - User in locked via date period'
|
|
]
|
|
],
|
|
// login ok, but login user id locked
|
|
'login: ok -> failed:, but loginUserId locked' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
'edit_access_id' => 1,
|
|
'base_access' => 'list',
|
|
'page_access' => 'list',
|
|
'test_login_user_id_locked' => true
|
|
],
|
|
[],
|
|
[
|
|
'login_login' => 'Login',
|
|
'login_username' => 'admin',
|
|
'login_password' => 'admin',
|
|
],
|
|
[],
|
|
3000,
|
|
[
|
|
'login_error' => 108,
|
|
'error_string' => '<span style="color: red;">Fatal Error:</span> '
|
|
. '<b>Login Failed - User is locked via Login User ID</b>',
|
|
'error_string_text' => 'Fatal Error: '
|
|
. 'Login Failed - User is locked via Login User ID'
|
|
]
|
|
],
|
|
// login: ok
|
|
'login: ok' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
'edit_access_id' => 1,
|
|
'edit_access_uid' => 'AdminAccess',
|
|
'edit_access_data' => 'test',
|
|
'base_access' => 'list',
|
|
'page_access' => 'list',
|
|
],
|
|
[],
|
|
[
|
|
'login_login' => 'Login',
|
|
'login_username' => 'admin',
|
|
'login_password' => 'admin',
|
|
],
|
|
[],
|
|
0,
|
|
[
|
|
'login_error' => 0,
|
|
'admin_flag' => true,
|
|
'check_access' => true,
|
|
'check_access_id' => 1,
|
|
'check_access_data' => 'value',
|
|
'base_access' => true,
|
|
'page_access' => true,
|
|
]
|
|
],
|
|
// login check via _GET loginUserId
|
|
'login: ok, _GET loginUserId' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
'edit_access_id' => 1,
|
|
'edit_access_uid' => 'AdminAccess',
|
|
'edit_access_data' => 'test',
|
|
'base_access' => 'list',
|
|
'page_access' => 'list',
|
|
'test_login_user_id' => true,
|
|
'test_username' => 'admin',
|
|
'loginUserId' => '1234567890ABCDEFG',
|
|
],
|
|
[
|
|
'loginUserId' => '1234567890ABCDEFG',
|
|
],
|
|
[],
|
|
[],
|
|
0,
|
|
[
|
|
'login_error' => 0,
|
|
'admin_flag' => true,
|
|
'check_access' => true,
|
|
'check_access_id' => 1,
|
|
'check_access_data' => 'value',
|
|
'base_access' => true,
|
|
'page_access' => true,
|
|
]
|
|
],
|
|
// login check via _POST loginUserId
|
|
'login: ok, _POST loginUserId' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
'edit_access_id' => 1,
|
|
'edit_access_uid' => 'AdminAccess',
|
|
'edit_access_data' => 'test',
|
|
'base_access' => 'list',
|
|
'page_access' => 'list',
|
|
'test_login_user_id' => true,
|
|
'test_username' => 'admin',
|
|
'loginUserId' => '1234567890ABCDEFG',
|
|
],
|
|
[],
|
|
[
|
|
'loginUserId' => '1234567890ABCDEFG',
|
|
],
|
|
[],
|
|
0,
|
|
[
|
|
'login_error' => 0,
|
|
'admin_flag' => true,
|
|
'check_access' => true,
|
|
'check_access_id' => 1,
|
|
'check_access_data' => 'value',
|
|
'base_access' => true,
|
|
'page_access' => true,
|
|
]
|
|
],
|
|
// login: wrong GET loginUserId
|
|
'login: ok, illegal chars in _GET loginUserId' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
'edit_access_id' => 1,
|
|
'edit_access_uid' => 'AdminAccess',
|
|
'edit_access_data' => 'test',
|
|
'base_access' => 'list',
|
|
'page_access' => 'list',
|
|
'test_login_user_id' => true,
|
|
'test_username' => 'admin',
|
|
'loginUserId' => '1234567890ABCDEFG'
|
|
],
|
|
[
|
|
'loginUserId' => '123$%_/45678¥\-^9~~0$AB&CDEFG',
|
|
],
|
|
[],
|
|
[],
|
|
0,
|
|
[
|
|
'login_error' => 0,
|
|
'admin_flag' => true,
|
|
'check_access' => true,
|
|
'check_access_id' => 1,
|
|
'check_access_data' => 'value',
|
|
'base_access' => true,
|
|
'page_access' => true,
|
|
]
|
|
],
|
|
'login: not matching _GET loginUserId' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
'test_login_user_id' => true,
|
|
'test_username' => 'admin',
|
|
'loginUserId' => '1234567890ABCDEFG'
|
|
],
|
|
[
|
|
'loginUserId' => 'ABC'
|
|
],
|
|
[],
|
|
[],
|
|
3000,
|
|
[
|
|
'login_error' => 1010,
|
|
'error_string' => '<span style="color: red;">Fatal Error:</span> '
|
|
. '<b>Login Failed - Wrong Username or Password</b>',
|
|
'error_string_text' => 'Fatal Error: '
|
|
. 'Login Failed - Wrong Username or Password'
|
|
]
|
|
],
|
|
// login ok with both _GET loginUserId and _POST login username/password
|
|
'login: ok, _GET loginUserId AND login post user data' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
'edit_access_id' => 1,
|
|
'edit_access_uid' => 'AdminAccess',
|
|
'edit_access_data' => 'test',
|
|
'base_access' => 'list',
|
|
'page_access' => 'list',
|
|
'test_login_user_id' => true,
|
|
'test_username' => 'admin',
|
|
'loginUserId' => '1234567890ABCDEFG',
|
|
],
|
|
[
|
|
'loginUserId' => '1234567890ABCDEFG',
|
|
],
|
|
[
|
|
'login_login' => 'Login',
|
|
'login_username' => 'admin',
|
|
'login_password' => 'admin',
|
|
],
|
|
[],
|
|
0,
|
|
[
|
|
'login_error' => 0,
|
|
'admin_flag' => true,
|
|
'check_access' => true,
|
|
'check_access_id' => 1,
|
|
'check_access_data' => 'value',
|
|
'base_access' => true,
|
|
'page_access' => true,
|
|
]
|
|
],
|
|
// login with invalid loginUserId but valid username/password
|
|
'login: ok, bad _GET loginUserId AND good login post user data' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
'edit_access_id' => 1,
|
|
'edit_access_uid' => 'AdminAccess',
|
|
'edit_access_data' => 'test',
|
|
'base_access' => 'list',
|
|
'page_access' => 'list',
|
|
'test_login_user_id' => true,
|
|
'test_username' => 'admin',
|
|
'loginUserId' => '1234567890ABCDEFG',
|
|
],
|
|
[
|
|
'loginUserId' => 'ABCS',
|
|
],
|
|
[
|
|
'login_login' => 'Login',
|
|
'login_username' => 'admin',
|
|
'login_password' => 'admin',
|
|
],
|
|
[],
|
|
0,
|
|
[
|
|
'login_error' => 0,
|
|
'admin_flag' => true,
|
|
'check_access' => true,
|
|
'check_access_id' => 1,
|
|
'check_access_data' => 'value',
|
|
'base_access' => true,
|
|
'page_access' => true,
|
|
]
|
|
],
|
|
// loginUserId check with revalidate on/off
|
|
'login: ok -> failed:, but revalidate trigger, _GET loginUserId' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
'edit_access_id' => 1,
|
|
'base_access' => 'list',
|
|
'page_access' => 'list',
|
|
'test_login_user_id_revalidate_after' => 'on',
|
|
'test_login_user_id' => true,
|
|
'test_username' => 'admin',
|
|
'loginUserId' => '1234567890ABCDEFG',
|
|
],
|
|
[
|
|
'loginUserId' => '1234567890ABCDEFG',
|
|
],
|
|
[],
|
|
[],
|
|
3000,
|
|
[
|
|
'login_error' => 1101,
|
|
'error_string' => '<span style="color: red;">Fatal Error:</span> '
|
|
. '<b>Login Failed - Login User ID must be validated</b>',
|
|
'error_string_text' => 'Fatal Error: '
|
|
. 'Login Failed - Login User ID must be validated'
|
|
]
|
|
],
|
|
// loginUserId check with revalidate on/off
|
|
'login: ok, revalidate set (outside), _GET loginUserId' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
'edit_access_id' => 1,
|
|
'edit_access_uid' => 'AdminAccess',
|
|
'edit_access_data' => 'test',
|
|
'base_access' => 'list',
|
|
'page_access' => 'list',
|
|
'test_login_user_id_revalidate_after' => 'off',
|
|
'test_login_user_id' => true,
|
|
'test_username' => 'admin',
|
|
'loginUserId' => '1234567890ABCDEFG',
|
|
],
|
|
[
|
|
'loginUserId' => '1234567890ABCDEFG',
|
|
],
|
|
[],
|
|
[],
|
|
0,
|
|
[
|
|
'login_error' => 0,
|
|
'admin_flag' => true,
|
|
'check_access' => true,
|
|
'check_access_id' => 1,
|
|
'check_access_data' => 'value',
|
|
'base_access' => true,
|
|
'page_access' => true,
|
|
]
|
|
],
|
|
// loginUserId check with active time from only
|
|
'login: ok -> failed:, _GET loginUserId, but outside valid (from:on) ' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
'edit_access_id' => 1,
|
|
'base_access' => 'list',
|
|
'page_access' => 'list',
|
|
'test_login_user_id_valid_from' => 'on',
|
|
'test_login_user_id' => true,
|
|
'test_username' => 'admin',
|
|
'loginUserId' => '1234567890ABCDEFG',
|
|
],
|
|
[
|
|
'loginUserId' => '1234567890ABCDEFG',
|
|
],
|
|
[],
|
|
[],
|
|
3000,
|
|
[
|
|
'login_error' => 1102,
|
|
'error_string' => '<span style="color: red;">Fatal Error:</span> '
|
|
. '<b>Login Failed - Login User ID is outside valid date range</b>',
|
|
'error_string_text' => 'Fatal Error: '
|
|
. 'Login Failed - Login User ID is outside valid date range'
|
|
]
|
|
],
|
|
// loginUserId check with inactive time from only
|
|
'login: ok, _GET loginUserId, but outside valid (from:off) ' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
'edit_access_id' => 1,
|
|
'edit_access_uid' => 'AdminAccess',
|
|
'edit_access_data' => 'test',
|
|
'base_access' => 'list',
|
|
'page_access' => 'list',
|
|
'test_login_user_id_valid_from' => 'off',
|
|
'test_login_user_id' => true,
|
|
'test_username' => 'admin',
|
|
'loginUserId' => '1234567890ABCDEFG',
|
|
],
|
|
[
|
|
'loginUserId' => '1234567890ABCDEFG',
|
|
],
|
|
[],
|
|
[],
|
|
0,
|
|
[
|
|
'login_error' => 0,
|
|
'admin_flag' => true,
|
|
'check_access' => true,
|
|
'check_access_id' => 1,
|
|
'check_access_data' => 'value',
|
|
'base_access' => true,
|
|
'page_access' => true,
|
|
]
|
|
],
|
|
// loginUserId check with active time until only
|
|
'login: ok -> failed:, _GET loginUserId, but outside valid (until:on) ' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
'edit_access_id' => 1,
|
|
'base_access' => 'list',
|
|
'page_access' => 'list',
|
|
'test_login_user_id_valid_until' => 'on',
|
|
'test_login_user_id' => true,
|
|
'test_username' => 'admin',
|
|
'loginUserId' => '1234567890ABCDEFG',
|
|
],
|
|
[
|
|
'loginUserId' => '1234567890ABCDEFG',
|
|
],
|
|
[],
|
|
[],
|
|
3000,
|
|
[
|
|
'login_error' => 1102,
|
|
'error_string' => '<span style="color: red;">Fatal Error:</span> '
|
|
. '<b>Login Failed - Login User ID is outside valid date range</b>',
|
|
'error_string_text' => 'Fatal Error: '
|
|
. 'Login Failed - Login User ID is outside valid date range'
|
|
]
|
|
],
|
|
// loginUserId check with active time from/until
|
|
'login: ok -> failed:, _GET loginUserId, but outside valid (from:on,until:on) ' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
'edit_access_id' => 1,
|
|
'base_access' => 'list',
|
|
'page_access' => 'list',
|
|
'test_login_user_id_valid_from' => 'on',
|
|
'test_login_user_id_valid_until' => 'on',
|
|
'test_login_user_id' => true,
|
|
'test_username' => 'admin',
|
|
'loginUserId' => '1234567890ABCDEFG',
|
|
],
|
|
[
|
|
'loginUserId' => '1234567890ABCDEFG',
|
|
],
|
|
[],
|
|
[],
|
|
3000,
|
|
[
|
|
'login_error' => 1102,
|
|
'error_string' => '<span style="color: red;">Fatal Error:</span> '
|
|
. '<b>Login Failed - Login User ID is outside valid date range</b>',
|
|
'error_string_text' => 'Fatal Error: '
|
|
. 'Login Failed - Login User ID is outside valid date range'
|
|
]
|
|
],
|
|
// TODO: Test that if we have n day check with login, that after login we can use parameter login again
|
|
'login: ok -> failed -> ok:, _GET loginUserId, but must revalidate, normal login, _GET loginUserId' => [
|
|
[
|
|
'page_name' => 'edit_users.php',
|
|
'edit_access_id' => 1,
|
|
'edit_access_uid' => 'AdminAccess',
|
|
'edit_access_data' => 'test',
|
|
'base_access' => 'list',
|
|
'page_access' => 'list',
|
|
'test_login_user_id_revalidate_reset' => true,
|
|
'test_login_user_id' => true,
|
|
'test_username' => 'admin',
|
|
'loginUserId' => '1234567890ABCDEFG',
|
|
// this error is thrown on first login round
|
|
'login_error' => 1101,
|
|
// get post as set sub arrays
|
|
'get' => [
|
|
'loginUserId' => '1234567890ABCDEFG',
|
|
],
|
|
'post' => [
|
|
'login_login' => 'Login',
|
|
'login_username' => 'admin',
|
|
'login_password' => 'admin',
|
|
],
|
|
],
|
|
// all empty get, post, session
|
|
[],
|
|
[],
|
|
[],
|
|
0,
|
|
[
|
|
'login_error' => 0,
|
|
'admin_flag' => true,
|
|
'check_access' => true,
|
|
'check_access_id' => 1,
|
|
'check_access_data' => 'value',
|
|
'base_access' => true,
|
|
'page_access' => true,
|
|
]
|
|
]
|
|
//
|
|
// other:
|
|
// login check edit access id of ID not null and not in array
|
|
// login OK, but during action user gets disabled/deleted/etc
|
|
];
|
|
|
|
return $tests;
|
|
}
|
|
|
|
/**
|
|
* main test for acl login
|
|
*
|
|
* @dataProvider loginProvider
|
|
* @testdox ACL\Login Class tests [$_dataName]
|
|
*
|
|
* @param array<string,mixed> $mock_settings
|
|
* @param array<string,string> $get
|
|
* @param array<string,string> $post
|
|
* @param array<string,mixed> $session
|
|
* @param int $error
|
|
* @param array<string,mixed> $expected
|
|
* @return void
|
|
*/
|
|
public function testACLLoginFlow(
|
|
array $mock_settings,
|
|
array $get,
|
|
array $post,
|
|
array $session,
|
|
int $error,
|
|
array $expected
|
|
): void {
|
|
// reset session
|
|
$_SESSION = [];
|
|
// reset post & get
|
|
$_GET = [];
|
|
$_POST = [];
|
|
// reset global ajax page call
|
|
unset($GLOBALS['AJAX_PAGE']);
|
|
// init session (as MOCK)
|
|
/** @var \CoreLibs\Create\Session&MockObject */
|
|
$session_mock = $this->createPartialMock(
|
|
\CoreLibs\Create\Session::class,
|
|
['startSession', 'checkActiveSession', 'sessionDestroy']
|
|
);
|
|
$session_mock->method('startSession')->willReturn('ACLLOGINTEST12');
|
|
$session_mock->method('checkActiveSession')->willReturn(true);
|
|
$session_mock->method('sessionDestroy')->will(
|
|
$this->returnCallback(function () {
|
|
global $_SESSION;
|
|
$_SESSION = [];
|
|
return true;
|
|
})
|
|
);
|
|
|
|
// set _GET data
|
|
foreach ($get as $get_var => $get_value) {
|
|
$_GET[$get_var] = $get_value;
|
|
}
|
|
|
|
// set _POST data
|
|
foreach ($post as $post_var => $post_value) {
|
|
$_POST[$post_var] = $post_value;
|
|
}
|
|
|
|
// set _SESSION data
|
|
foreach ($session as $session_var => $session_value) {
|
|
$_SESSION[$session_var] = $session_value;
|
|
}
|
|
|
|
/** @var \CoreLibs\ACL\Login&MockObject */
|
|
$login_mock = $this->getMockBuilder(\CoreLibs\ACL\Login::class)
|
|
->setConstructorArgs([
|
|
self::$db,
|
|
self::$log,
|
|
$session_mock,
|
|
[
|
|
'auto_login' => false,
|
|
'default_acl_level' => 80,
|
|
'logout_target' => '',
|
|
'site_locale' => 'en_US.UTF-8',
|
|
'site_domain' => 'admin',
|
|
'site_encoding' => 'UTF-8',
|
|
'locale_path' => __DIR__ . DIRECTORY_SEPARATOR
|
|
. 'includes' . DIRECTORY_SEPARATOR
|
|
. 'locale' . DIRECTORY_SEPARATOR,
|
|
]
|
|
])
|
|
->onlyMethods(['loginTerminate', 'loginReadPageName', 'loginPrintLogin'])
|
|
->getMock();
|
|
$login_mock->expects($this->any())
|
|
->method('loginTerminate')
|
|
->will(
|
|
$this->returnCallback(function ($code) {
|
|
throw new \Exception('', $code);
|
|
})
|
|
);
|
|
$login_mock->expects($this->any())
|
|
->method('loginReadPageName')
|
|
// set from mock settings, or empty if not set at all
|
|
->willReturn($mock_settings['page_name'] ?? '');
|
|
// do not echo out any string here
|
|
$login_mock->expects($this->any())
|
|
->method('loginPrintLogin')
|
|
->willReturnCallback(function () {
|
|
});
|
|
|
|
// if mock_settings: enabled OFF
|
|
// run DB update and set off
|
|
if (!empty($mock_settings['test_enabled'])) {
|
|
self::$db->dbExec(
|
|
"UPDATE edit_user SET enabled = 0 WHERE LOWER(username) = "
|
|
. self::$db->dbEscapeLiteral($post['login_username'])
|
|
);
|
|
}
|
|
if (!empty($mock_settings['test_deleted'])) {
|
|
self::$db->dbExec(
|
|
"UPDATE edit_user SET deleted = 1 WHERE LOWER(username) = "
|
|
. self::$db->dbEscapeLiteral($post['login_username'])
|
|
);
|
|
}
|
|
if (!empty($mock_settings['test_login_user_id_locked'])) {
|
|
self::$db->dbExec(
|
|
"UPDATE edit_user SET login_user_id_locked = 1 WHERE LOWER(username) = "
|
|
. self::$db->dbEscapeLiteral($post['login_username'])
|
|
);
|
|
}
|
|
if (
|
|
!empty($mock_settings['test_locked_period_until']) ||
|
|
!empty($mock_settings['test_locked_period_after'])
|
|
) {
|
|
$q_sub = '';
|
|
if (!empty($mock_settings['test_locked_period_until'])) {
|
|
if ($mock_settings['test_locked_period_until'] == 'on') {
|
|
$q_sub .= "lock_until = NOW() + '1 day'::interval ";
|
|
} elseif ($mock_settings['test_locked_period_until'] == 'off') {
|
|
$q_sub .= "lock_until = NOW() - '1 day'::interval ";
|
|
}
|
|
}
|
|
if (!empty($mock_settings['test_locked_period_after'])) {
|
|
if (!empty($q_sub)) {
|
|
$q_sub .= ", ";
|
|
}
|
|
if ($mock_settings['test_locked_period_after'] == 'on') {
|
|
$q_sub .= "lock_after = NOW() - '1 day'::interval ";
|
|
} elseif ($mock_settings['test_locked_period_after'] == 'off') {
|
|
$q_sub .= "lock_after = NOW() + '1 day'::interval ";
|
|
}
|
|
}
|
|
self::$db->dbExec(
|
|
"UPDATE edit_user SET "
|
|
. $q_sub
|
|
. "WHERE LOWER(username) = "
|
|
. self::$db->dbEscapeLiteral($post['login_username'])
|
|
);
|
|
}
|
|
// test locked already
|
|
if (!empty($mock_settings['test_locked'])) {
|
|
self::$db->dbExec(
|
|
"UPDATE edit_user SET locked = 1 WHERE LOWER(username) = "
|
|
. self::$db->dbEscapeLiteral($post['login_username'])
|
|
);
|
|
}
|
|
// test get locked
|
|
if (!empty($mock_settings['test_get_locked'])) {
|
|
// enable strict if needed
|
|
if (!empty($mock_settings['test_locked_strict'])) {
|
|
self::$db->dbExec(
|
|
"UPDATE edit_user SET strict = 1 WHERE LOWER(username) = "
|
|
. self::$db->dbEscapeLiteral($post['login_username'])
|
|
);
|
|
}
|
|
// reset any previous login error counts
|
|
self::$db->dbExec(
|
|
"UPDATE edit_user "
|
|
. "SET login_error_count = 0, login_error_date_last = NULL, "
|
|
. "login_error_date_first = NULL "
|
|
. "WHERE LOWER(username) = "
|
|
. self::$db->dbEscapeLiteral($post['login_username'])
|
|
);
|
|
// check the max login error count and try login until one time before
|
|
// on each run, check that lock count is matching
|
|
// next run (run test) should then fail with user locked IF strict,
|
|
// else fail as normal login
|
|
$login_mock->loginSetMaxLoginErrorCount($mock_settings['max_login_error_count']);
|
|
// temporary wrong password
|
|
$_POST['login_password'] = 'wrong';
|
|
for ($run = 1, $max_run = $login_mock->loginGetMaxLoginErrorCount(); $run <= $max_run; $run++) {
|
|
try {
|
|
$login_mock->loginMainCall();
|
|
} catch (\Exception $e) {
|
|
// print 'Expected error code: ' . $e->getCode()
|
|
// . ', M:' . $e->getMessage()
|
|
// . ', L:' . $e->getLine()
|
|
// . ', E: ' . $login_mock->loginGetLastErrorCode()
|
|
// . "\n";
|
|
$this->assertEquals(
|
|
$expected['lock_run_login_error'],
|
|
$login_mock->loginGetLastErrorCode(),
|
|
'Assert login error code, exit on lock run'
|
|
);
|
|
}
|
|
// check user error count
|
|
$res = self::$db->dbReturnRow(
|
|
"SELECT login_error_count FROM edit_user "
|
|
. "WHERE LOWER(username) = "
|
|
. self::$db->dbEscapeLiteral($post['login_username'])
|
|
);
|
|
$this->assertEquals(
|
|
$res['login_error_count'],
|
|
$run,
|
|
'Assert equal login error count'
|
|
);
|
|
}
|
|
// set correct password next locked login
|
|
$_POST['login_password'] = $post['login_password'];
|
|
}
|
|
if (!empty($mock_settings['test_login_user_id'])) {
|
|
self::$db->dbExec(
|
|
"UPDATE edit_user SET "
|
|
. "login_user_id = "
|
|
. self::$db->dbEscapeLiteral($mock_settings['loginUserId'])
|
|
. " "
|
|
. "WHERE LOWER(username) = "
|
|
. self::$db->dbEscapeLiteral($mock_settings['test_username'])
|
|
);
|
|
}
|
|
if (!empty($mock_settings['test_login_user_id_revalidate_after'])) {
|
|
$q_sub = '';
|
|
if ($mock_settings['test_login_user_id_revalidate_after'] == 'on') {
|
|
$q_sub = "login_user_id_last_revalidate = NOW() - '1 day'::interval, "
|
|
. "login_user_id_revalidate_after = '1 day'::interval ";
|
|
} else {
|
|
$q_sub = "login_user_id_last_revalidate = NOW(), "
|
|
. "login_user_id_revalidate_after = '6 day'::interval ";
|
|
}
|
|
self::$db->dbExec(
|
|
"UPDATE edit_user SET "
|
|
. $q_sub
|
|
. "WHERE LOWER(username) = "
|
|
. self::$db->dbEscapeLiteral($mock_settings['test_username'])
|
|
);
|
|
}
|
|
if (!empty($mock_settings['test_login_user_id_revalidate_reset'])) {
|
|
// init dates data for revalidate frame,
|
|
// set to last revalidate 3 days ago and set revalidate frame to
|
|
// three days
|
|
self::$db->dbExec(
|
|
"UPDATE edit_user SET "
|
|
. "login_user_id_last_revalidate = NOW() - '3 day'::interval, "
|
|
. "login_user_id_revalidate_after = '3 day'::interval "
|
|
. "WHERE LOWER(username) = "
|
|
. self::$db->dbEscapeLiteral($mock_settings['test_username'])
|
|
);
|
|
$_GET = $mock_settings['get'];
|
|
// login with loginUserId -> fail
|
|
try {
|
|
$login_mock->loginMainCall();
|
|
} catch (\Exception $e) {
|
|
$this->assertEquals(
|
|
$mock_settings['login_error'],
|
|
$login_mock->loginGetLastErrorCode(),
|
|
'loginUserId reset 1: Assert first loginUserId run failes'
|
|
);
|
|
}
|
|
$_GET = [];
|
|
// login with username and password -> reset -> ok
|
|
// set _POST data
|
|
$_POST = $mock_settings['post'];
|
|
try {
|
|
$login_mock->loginMainCall();
|
|
$this->assertEquals(
|
|
0,
|
|
$login_mock->loginGetLastErrorCode(),
|
|
'loginUserId reset 2: Assert username/password login is successful'
|
|
);
|
|
} catch (\Exception $e) {
|
|
// if we end up here we have an issue
|
|
$this->assertTrue(
|
|
false,
|
|
'loginUserId reset 2: FAILED successful login'
|
|
);
|
|
}
|
|
$_POST = [];
|
|
// logut and run normal login with loginUserId
|
|
$_GET = $mock_settings['get'];
|
|
}
|
|
if (
|
|
!empty($mock_settings['test_login_user_id_valid_from']) ||
|
|
!empty($mock_settings['test_login_user_id_valid_until'])
|
|
) {
|
|
$q_sub = '';
|
|
if (!empty($mock_settings['test_login_user_id_valid_from'])) {
|
|
if ($mock_settings['test_login_user_id_valid_from'] == 'on') {
|
|
$q_sub .= "login_user_id_valid_from = NOW() + '1 day'::interval ";
|
|
} elseif ($mock_settings['test_login_user_id_valid_from'] == 'off') {
|
|
$q_sub .= "login_user_id_valid_from = NOW() - '1 day'::interval ";
|
|
}
|
|
}
|
|
if (!empty($mock_settings['test_login_user_id_valid_until'])) {
|
|
if (!empty($q_sub)) {
|
|
$q_sub .= ", ";
|
|
}
|
|
if ($mock_settings['test_login_user_id_valid_until'] == 'on') {
|
|
$q_sub .= "login_user_id_valid_until = NOW() - '1 day'::interval ";
|
|
} elseif ($mock_settings['test_login_user_id_valid_until'] == 'off') {
|
|
$q_sub .= "login_user_id_valid_until = NOW() + '1 day'::interval ";
|
|
}
|
|
}
|
|
self::$db->dbExec(
|
|
"UPDATE edit_user SET "
|
|
. $q_sub
|
|
. "WHERE LOWER(username) = "
|
|
. self::$db->dbEscapeLiteral($mock_settings['test_username'])
|
|
);
|
|
}
|
|
|
|
// run test
|
|
try {
|
|
// if ajax call
|
|
// check if parameter, or globals (old type)
|
|
// else normal call
|
|
if (
|
|
!empty($mock_settings['ajax_test_type']) &&
|
|
$mock_settings['ajax_test_type'] == 'parameter'
|
|
) {
|
|
$login_mock->loginMainCall($mock_settings['ajax_page']);
|
|
} elseif (
|
|
!empty($mock_settings['ajax_test_type']) &&
|
|
$mock_settings['ajax_test_type'] == 'globals'
|
|
) {
|
|
$GLOBALS['AJAX_PAGE'] = $mock_settings['ajax_page'];
|
|
$login_mock->loginMainCall();
|
|
} else {
|
|
$login_mock->loginMainCall();
|
|
}
|
|
// on ok, do post login check based on expected return
|
|
// - loginGetLastErrorCode
|
|
$this->assertEquals(
|
|
$expected['login_error'],
|
|
$login_mock->loginGetLastErrorCode(),
|
|
'Assert login error code'
|
|
);
|
|
// - loginGetPageName
|
|
$this->assertEquals(
|
|
$mock_settings['page_name'],
|
|
$login_mock->loginGetPageName(),
|
|
'Assert page name'
|
|
);
|
|
// - loginCheckPermissions [duplicated from loginrun]
|
|
$this->assertTrue(
|
|
$login_mock->loginCheckPermissions(),
|
|
'Assert true for login permission ok'
|
|
);
|
|
// - loginCheckAccess [use Base, Page below]
|
|
$this->assertEquals(
|
|
$expected['base_access'],
|
|
$login_mock->loginCheckAccess('base', $mock_settings['base_access']),
|
|
'Assert base access, via main method'
|
|
);
|
|
$this->assertEquals(
|
|
$expected['base_access'],
|
|
$login_mock->loginCheckAccess('page', $mock_settings['base_access']),
|
|
'Assert page access, via main method'
|
|
);
|
|
// - loginCheckAccessBase
|
|
$this->assertEquals(
|
|
$expected['base_access'],
|
|
$login_mock->loginCheckAccessBase($mock_settings['base_access']),
|
|
'Assert base access'
|
|
);
|
|
// - loginCheckAccessPage
|
|
$this->assertEquals(
|
|
$expected['page_access'],
|
|
$login_mock->loginCheckAccessPage($mock_settings['page_access']),
|
|
'Assert page access'
|
|
);
|
|
// - loginCheckEditAccess
|
|
$this->assertEquals(
|
|
$expected['check_access'],
|
|
$login_mock->loginCheckEditAccess($mock_settings['edit_access_id']),
|
|
'Assert check access'
|
|
);
|
|
// - loginCheckEditAccessId
|
|
$this->assertEquals(
|
|
$expected['check_access_id'],
|
|
$login_mock->loginCheckEditAccessId((int)$mock_settings['edit_access_id']),
|
|
'Assert check access id valid'
|
|
);
|
|
// - loginGetEditAccessIdFromUid
|
|
$this->assertEquals(
|
|
$expected['check_access_id'],
|
|
$login_mock->loginGetEditAccessIdFromUid($mock_settings['edit_access_uid']),
|
|
'Assert check access uid to id valid'
|
|
);
|
|
// - loginGetEditAccessData
|
|
$this->assertEquals(
|
|
$expected['check_access_data'],
|
|
$login_mock->loginGetEditAccessData(
|
|
$mock_settings['edit_access_id'],
|
|
$mock_settings['edit_access_data']
|
|
),
|
|
'Assert check access id data value valid'
|
|
);
|
|
// - loginIsAdmin
|
|
$this->assertEquals(
|
|
$expected['admin_flag'],
|
|
$login_mock->loginIsAdmin(),
|
|
'Assert admin flag set'
|
|
);
|
|
// - loginGetAcl
|
|
$this->assertIsArray(
|
|
$login_mock->loginGetAcl(),
|
|
'Assert get acl is array'
|
|
);
|
|
// if loginUserId in _GET or _POST check that it is set
|
|
if (!empty($get['loginUserId']) || !empty($post['loginUserId'])) {
|
|
$this->assertNotEmpty(
|
|
$login_mock->loginGetLoginUserId(),
|
|
'Assert loginUserId is set'
|
|
);
|
|
}
|
|
// TODO: detail match of ACL array (loginGetAcl)
|
|
|
|
// .. end with: loginLogoutUser
|
|
// _POST['login_logout'] = 'lgogout
|
|
// $login_mock->loginMainCall();
|
|
// - loginCheckPermissions
|
|
// - loginGetPermissionOkay
|
|
} catch (\Exception $e) {
|
|
// print "[E]: " . $e->getCode() . ", ERROR: " . $login_mock->loginGetLastErrorCode() . "/"
|
|
// . ($expected['login_error'] ?? 0) . "\n";
|
|
// print "AJAX: " . $login_mock->loginGetAjaxFlag() . "\n";
|
|
// print "AJAX GLOBAL: " . ($GLOBALS['AJAX_PAGE'] ?? '{f}') . "\n";
|
|
// print "Login error expext: " . ($expected['login_error'] ?? '{0}') . "\n";
|
|
// if this is 3000, then we do further error checks
|
|
if (
|
|
$e->getCode() == 3000 ||
|
|
!empty($_POST['login_exit']) && $_POST['login_exit'] == 3000
|
|
) {
|
|
$this->assertEquals(
|
|
$expected['login_error'],
|
|
$login_mock->loginGetLastErrorCode(),
|
|
'Assert login error code, exit'
|
|
);
|
|
// - loginGetErrorMsg
|
|
$this->assertEquals(
|
|
$expected['error_string'],
|
|
$login_mock->loginGetErrorMsg($login_mock->loginGetLastErrorCode()),
|
|
'Assert error string, html'
|
|
);
|
|
$this->assertEquals(
|
|
$expected['error_string_text'],
|
|
$login_mock->loginGetErrorMsg($login_mock->loginGetLastErrorCode(), true),
|
|
'Assert error string, text'
|
|
);
|
|
// - loginGetLoginHTML
|
|
$this->assertStringContainsString(
|
|
'<html lang="',
|
|
$login_mock->loginGetLoginHTML(),
|
|
'Assert login html string exits'
|
|
);
|
|
// check that login script has above error message
|
|
if (!empty($login_mock->loginGetLastErrorCode())) {
|
|
$this->assertStringContainsString(
|
|
$login_mock->loginGetErrorMsg($login_mock->loginGetLastErrorCode()),
|
|
$login_mock->loginGetLoginHTML(),
|
|
'Assert login error string exits'
|
|
);
|
|
} else {
|
|
$this->assertStringNotContainsString(
|
|
$login_mock->loginGetErrorMsg($login_mock->loginGetLastErrorCode()),
|
|
$login_mock->loginGetLoginHTML(),
|
|
'Assert login error string does not exit'
|
|
);
|
|
}
|
|
// for ajax type, test post return values
|
|
if ($login_mock->loginGetAjaxFlag()) {
|
|
$this->assertCount(
|
|
$expected['ajax_get_count'],
|
|
$_GET,
|
|
'Assert ajax error _GET is valid count'
|
|
);
|
|
// post has only action, login_exit, login_error,
|
|
// login_error_text and login_html
|
|
// 5 entries
|
|
$this->assertCount(
|
|
$expected['ajax_post_count'],
|
|
$_POST,
|
|
'Assert ajax error _POST is valid count'
|
|
);
|
|
// test post entries
|
|
$this->assertEquals(
|
|
$expected['ajax_post_action'],
|
|
$_POST['action'],
|
|
'Assert ajax _POST action'
|
|
);
|
|
$this->assertEquals(
|
|
$login_mock->loginGetLastErrorCode(),
|
|
$_POST['login_error'],
|
|
'Assert ajax _POST error'
|
|
);
|
|
$this->assertEquals(
|
|
$login_mock->loginGetErrorMsg($login_mock->loginGetLastErrorCode(), true),
|
|
$_POST['login_error_text'],
|
|
'Assert ajax _POST error text'
|
|
);
|
|
// html login basic check only, content is the same as when
|
|
// read from loginGetLoginHTML()
|
|
$this->assertStringContainsString(
|
|
'<html lang="',
|
|
$_POST['login_html'],
|
|
'Assert ajax _POST html string exits'
|
|
);
|
|
}
|
|
}
|
|
// print "EXCEPTION: " . print_r($e, true) . "\n";
|
|
$this->assertEquals(
|
|
!$login_mock->loginGetAjaxFlag() ?
|
|
$e->getCode() :
|
|
$_POST['login_exit'] ?? 0,
|
|
$error,
|
|
'Expected error code: ' . $e->getCode()
|
|
. ', ' . $e->getMessage()
|
|
. ', ' . $e->getLine()
|
|
);
|
|
}
|
|
|
|
// if _POST login set check this is matching
|
|
if (!empty($post['login_login'])) {
|
|
$this->assertTrue(
|
|
$login_mock->loginActionRun(),
|
|
'Assert that post login_login was pressed'
|
|
);
|
|
}
|
|
|
|
// always check, even on error or not set
|
|
if (!$login_mock->loginGetLoginUserIdUnclean()) {
|
|
$this->assertEquals(
|
|
$_GET['loginUserId'] ?? $_POST['loginUserId'] ?? '',
|
|
$login_mock->loginGetLoginUserId(),
|
|
'Assert loginUserId matches'
|
|
);
|
|
} else {
|
|
$this->assertTrue(
|
|
$login_mock->loginGetLoginUserIdUnclean(),
|
|
'Assert loginUserId is unclear'
|
|
);
|
|
$this->assertNotEquals(
|
|
$_GET['loginUserId'] ?? $_POST['loginUserId'] ?? '',
|
|
$login_mock->loginGetLoginUserId(),
|
|
'Assert loginUserId does not matche _GET/_POST'
|
|
);
|
|
}
|
|
// check get/post login user id
|
|
$this->assertEquals(
|
|
(!empty($_GET['loginUserId']) ?
|
|
'GET' :
|
|
(!empty($_POST['loginUserId']) ?
|
|
'POST' : '')
|
|
),
|
|
$login_mock->loginGetLoginUserIdSource(),
|
|
'Assert loginUserId source matches'
|
|
);
|
|
|
|
// enable user again if flag set
|
|
if (!empty($mock_settings['test_enabled'])) {
|
|
self::$db->dbExec(
|
|
"UPDATE edit_user SET enabled = 1 "
|
|
. "WHERE LOWER(username) = "
|
|
. self::$db->dbEscapeLiteral($post['login_username'])
|
|
);
|
|
}
|
|
if (!empty($mock_settings['test_deleted'])) {
|
|
self::$db->dbExec(
|
|
"UPDATE edit_user SET deleted = 0 WHERE LOWER(username) = "
|
|
. self::$db->dbEscapeLiteral($post['login_username'])
|
|
);
|
|
}
|
|
if (!empty($mock_settings['test_login_user_id_locked'])) {
|
|
self::$db->dbExec(
|
|
"UPDATE edit_user SET login_user_id_locked = 0 WHERE LOWER(username) = "
|
|
. self::$db->dbEscapeLiteral($post['login_username'])
|
|
);
|
|
}
|
|
if (
|
|
!empty($mock_settings['test_locked_period_until']) ||
|
|
!empty($mock_settings['test_locked_period_after'])
|
|
) {
|
|
self::$db->dbExec(
|
|
"UPDATE edit_user SET "
|
|
. "lock_until = NULL, "
|
|
. "lock_after = NULL "
|
|
. "WHERE LOWER(username) = "
|
|
. self::$db->dbEscapeLiteral($post['login_username'])
|
|
);
|
|
}
|
|
// reset lock flag
|
|
if (!empty($mock_settings['test_locked'])) {
|
|
self::$db->dbExec(
|
|
"UPDATE edit_user SET locked = 0 "
|
|
. "WHERE LOWER(username) = "
|
|
. self::$db->dbEscapeLiteral($post['login_username'])
|
|
);
|
|
}
|
|
// rest the get locked flow
|
|
if (!empty($mock_settings['test_get_locked'])) {
|
|
self::$db->dbExec(
|
|
"UPDATE edit_user "
|
|
. "SET login_error_count = 0, login_error_date_last = NULL, "
|
|
. "login_error_date_first = NULL, locked = 0, strict = 0 "
|
|
. "WHERE LOWER(username) = "
|
|
. self::$db->dbEscapeLiteral($post['login_username'])
|
|
);
|
|
}
|
|
if (!empty($mock_settings['test_login_user_id'])) {
|
|
self::$db->dbExec(
|
|
"UPDATE edit_user SET "
|
|
. "login_user_id = NULL, "
|
|
// below to rows are automatcially reset
|
|
. "login_user_id_set_date = NULL, "
|
|
. "login_user_id_last_revalidate = NULL "
|
|
. "WHERE LOWER(username) = "
|
|
. self::$db->dbEscapeLiteral($mock_settings['test_username'])
|
|
);
|
|
}
|
|
if (!empty($mock_settings['test_login_user_id_revalidate_after'])) {
|
|
self::$db->dbExec(
|
|
"UPDATE edit_user SET "
|
|
. "login_user_id_last_revalidate = NULL, "
|
|
. "login_user_id_revalidate_after = NULL "
|
|
. "WHERE LOWER(username) = "
|
|
. self::$db->dbEscapeLiteral($mock_settings['test_username'])
|
|
);
|
|
}
|
|
if (
|
|
!empty($mock_settings['test_login_user_id_valid_from']) ||
|
|
!empty($mock_settings['test_login_user_id_valid_until'])
|
|
) {
|
|
self::$db->dbExec(
|
|
"UPDATE edit_user SET "
|
|
. "login_user_id_valid_from = NULL, "
|
|
. "login_user_id_valid_until = NULL "
|
|
. "WHERE LOWER(username) = "
|
|
. self::$db->dbEscapeLiteral($mock_settings['test_username'])
|
|
);
|
|
}
|
|
}
|
|
|
|
// - loginGetAclList (null, invalid,)
|
|
|
|
public function aclListProvider(): array
|
|
{
|
|
// 0: level (int|null)
|
|
// 2: type (string), null for skip (if 0 = null)
|
|
// 1: acl return from level (array)
|
|
// 2: level number to return (must match 0)
|
|
return [
|
|
'null, get full list' => [
|
|
null,
|
|
null,
|
|
[
|
|
0 => [
|
|
'type' => 'none',
|
|
'name' => 'No Access',
|
|
],
|
|
10 => [
|
|
'type' => 'list',
|
|
'name' => 'List',
|
|
],
|
|
20 => [
|
|
'type' => 'read',
|
|
'name' => 'Read',
|
|
],
|
|
30 => [
|
|
'type' => 'mod_trans',
|
|
'name' => 'Translator',
|
|
],
|
|
40 => [
|
|
'type' => 'mod',
|
|
'name' => 'Modify',
|
|
],
|
|
60 => [
|
|
'type' => 'write',
|
|
'name' => 'Create/Write',
|
|
],
|
|
80 => [
|
|
'type' => 'del',
|
|
'name' => 'Delete',
|
|
],
|
|
90 => [
|
|
'type' => 'siteadmin',
|
|
'name' => 'Site Admin',
|
|
],
|
|
100 => [
|
|
'type' => 'admin',
|
|
'name' => 'Admin',
|
|
],
|
|
],
|
|
null
|
|
],
|
|
'valid, search' => [
|
|
20,
|
|
'read',
|
|
[
|
|
'type' => 'read',
|
|
'name' => 'Read'
|
|
],
|
|
20
|
|
],
|
|
'invalid search' => [
|
|
12,
|
|
'foo',
|
|
[],
|
|
false,
|
|
]
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Undocumented function
|
|
*
|
|
* @dataProvider aclListProvider()
|
|
* @testdox ACL\Login list if $level and $type exepcted level is $expected_level [$_dataName]
|
|
*
|
|
* @param int|null $level
|
|
* @param string|null $type
|
|
* @param array $expected_list
|
|
* @param int|null|bool $expected_level
|
|
* @return void
|
|
*/
|
|
public function testAclLoginList(
|
|
?int $level,
|
|
?string $type,
|
|
array $expected_list,
|
|
$expected_level
|
|
): void {
|
|
$_SESSION = [];
|
|
// init session (as MOCK)
|
|
/** @var \CoreLibs\Create\Session&MockObject */
|
|
$session_mock = $this->createPartialMock(
|
|
\CoreLibs\Create\Session::class,
|
|
['startSession', 'checkActiveSession', 'sessionDestroy']
|
|
);
|
|
$session_mock->method('startSession')->willReturn('ACLLOGINTEST34');
|
|
$session_mock->method('checkActiveSession')->willReturn(true);
|
|
$session_mock->method('sessionDestroy')->will(
|
|
$this->returnCallback(function () {
|
|
global $_SESSION;
|
|
$_SESSION = [];
|
|
return true;
|
|
})
|
|
);
|
|
/** @var \CoreLibs\ACL\Login&MockObject */
|
|
$login_mock = $this->getMockBuilder(\CoreLibs\ACL\Login::class)
|
|
->setConstructorArgs([
|
|
self::$db,
|
|
self::$log,
|
|
$session_mock,
|
|
[
|
|
'auto_login' => false,
|
|
'default_acl_level' => 80,
|
|
'logout_target' => '',
|
|
'site_locale' => 'en_US.UTF-8',
|
|
'site_domain' => 'admin',
|
|
'site_encoding' => 'UTF-8',
|
|
'locale_path' => __DIR__ . DIRECTORY_SEPARATOR
|
|
. 'includes' . DIRECTORY_SEPARATOR
|
|
. 'locale' . DIRECTORY_SEPARATOR,
|
|
]
|
|
])
|
|
->onlyMethods(['loginTerminate'])
|
|
->getMock();
|
|
$login_mock->expects($this->any())
|
|
->method('loginTerminate')
|
|
->will(
|
|
$this->returnCallback(function ($code) {
|
|
throw new \Exception('', $code);
|
|
})
|
|
);
|
|
|
|
$list = $login_mock->loginGetAclList($level);
|
|
$this->assertIsArray(
|
|
$list,
|
|
'assert get acl list is array'
|
|
);
|
|
$this->assertEquals(
|
|
$expected_list,
|
|
$list
|
|
);
|
|
if ($type !== null) {
|
|
$this->assertEquals(
|
|
$expected_level,
|
|
$login_mock->loginGetAclListFromType($type),
|
|
'assert type is level'
|
|
);
|
|
// only back assert if found
|
|
if (isset($list['type'])) {
|
|
$this->assertEquals(
|
|
$list['type'],
|
|
$type,
|
|
'assert level read type is type'
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Undocumented function
|
|
*
|
|
* @return array
|
|
*/
|
|
public function minPasswordCheckProvider(): array
|
|
{
|
|
// 0: set length
|
|
// 1: expected return from set
|
|
// 2: expected set length
|
|
return [
|
|
'set new length' => [
|
|
12,
|
|
true,
|
|
12,
|
|
],
|
|
'set new length, too short' => [
|
|
5,
|
|
false,
|
|
9
|
|
],
|
|
'set new length, too long' => [
|
|
500,
|
|
false,
|
|
9
|
|
]
|
|
];
|
|
}
|
|
|
|
/**
|
|
* check setting minimum password length
|
|
*
|
|
* @covers ::loginSetPasswordMinLength
|
|
* @covers ::loginGetPasswordLenght
|
|
* @dataProvider minPasswordCheckProvider()
|
|
* @testdox ACL\Login password min length set $input is $expected_return and matches $expected [$_dataName]
|
|
*
|
|
* @param int $input
|
|
* @param bool $expected_return
|
|
* @param int $expected
|
|
* @return void
|
|
*/
|
|
public function testACLLoginPasswordMinLenght(int $input, bool $expected_return, int $expected): void
|
|
{
|
|
$_SESSION = [];
|
|
// init session (as MOCK)
|
|
/** @var \CoreLibs\Create\Session&MockObject */
|
|
$session_mock = $this->createPartialMock(
|
|
\CoreLibs\Create\Session::class,
|
|
['startSession', 'checkActiveSession', 'sessionDestroy']
|
|
);
|
|
$session_mock->method('startSession')->willReturn('ACLLOGINTEST34');
|
|
$session_mock->method('checkActiveSession')->willReturn(true);
|
|
$session_mock->method('sessionDestroy')->will(
|
|
$this->returnCallback(function () {
|
|
global $_SESSION;
|
|
$_SESSION = [];
|
|
return true;
|
|
})
|
|
);
|
|
/** @var \CoreLibs\ACL\Login&MockObject */
|
|
$login_mock = $this->getMockBuilder(\CoreLibs\ACL\Login::class)
|
|
->setConstructorArgs([
|
|
self::$db,
|
|
self::$log,
|
|
$session_mock,
|
|
[
|
|
'auto_login' => false,
|
|
'default_acl_level' => 80,
|
|
'logout_target' => '',
|
|
'site_locale' => 'en_US.UTF-8',
|
|
'site_domain' => 'admin',
|
|
'site_encoding' => 'UTF-8',
|
|
'locale_path' => __DIR__ . DIRECTORY_SEPARATOR
|
|
. 'includes' . DIRECTORY_SEPARATOR
|
|
. 'locale' . DIRECTORY_SEPARATOR,
|
|
]
|
|
])
|
|
->onlyMethods(['loginTerminate'])
|
|
->getMock();
|
|
$login_mock->expects($this->any())
|
|
->method('loginTerminate')
|
|
->will(
|
|
$this->returnCallback(function ($code) {
|
|
throw new \Exception('', $code);
|
|
})
|
|
);
|
|
|
|
// set new min password length
|
|
$this->assertEquals(
|
|
$expected_return,
|
|
$login_mock->loginSetPasswordMinLength($input),
|
|
'assert bool set password min length'
|
|
);
|
|
// check value
|
|
$this->assertEquals(
|
|
$expected,
|
|
$login_mock->loginGetPasswordLenght('min'),
|
|
'assert get password min length'
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Undocumented function
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getPasswordLengthProvider(): array
|
|
{
|
|
return [
|
|
'min' => ['min'],
|
|
'lower' => ['lower'],
|
|
'max' => ['max'],
|
|
'upper' => ['upper'],
|
|
'minimum_length' => ['minimum_length'],
|
|
'min_length' => ['min_length'],
|
|
'length' => ['length'],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* check all possible readable password length params
|
|
*
|
|
* @covers ::loginGetPasswordLenght
|
|
* @dataProvider getPasswordLengthProvider()
|
|
* @testdox ACL\Login get password length $input [$_dataName]
|
|
*
|
|
* @param string $input
|
|
* @return void
|
|
*/
|
|
public function testACLLoginGetPasswordLength(string $input): void
|
|
{
|
|
$_SESSION = [];
|
|
// init session (as MOCK)
|
|
/** @var \CoreLibs\Create\Session&MockObject */
|
|
$session_mock = $this->createPartialMock(
|
|
\CoreLibs\Create\Session::class,
|
|
['startSession', 'checkActiveSession', 'sessionDestroy']
|
|
);
|
|
$session_mock->method('startSession')->willReturn('ACLLOGINTEST34');
|
|
$session_mock->method('checkActiveSession')->willReturn(true);
|
|
$session_mock->method('sessionDestroy')->will(
|
|
$this->returnCallback(function () {
|
|
global $_SESSION;
|
|
$_SESSION = [];
|
|
return true;
|
|
})
|
|
);
|
|
/** @var \CoreLibs\ACL\Login&MockObject */
|
|
$login_mock = $this->getMockBuilder(\CoreLibs\ACL\Login::class)
|
|
->setConstructorArgs([
|
|
self::$db,
|
|
self::$log,
|
|
$session_mock,
|
|
[
|
|
'auto_login' => false,
|
|
'default_acl_level' => 80,
|
|
'logout_target' => '',
|
|
'site_locale' => 'en_US.UTF-8',
|
|
'site_domain' => 'admin',
|
|
'site_encoding' => 'UTF-8',
|
|
'locale_path' => __DIR__ . DIRECTORY_SEPARATOR
|
|
. 'includes' . DIRECTORY_SEPARATOR
|
|
. 'locale' . DIRECTORY_SEPARATOR,
|
|
]
|
|
])
|
|
->onlyMethods(['loginTerminate'])
|
|
->getMock();
|
|
$login_mock->expects($this->any())
|
|
->method('loginTerminate')
|
|
->will(
|
|
$this->returnCallback(function ($code) {
|
|
throw new \Exception('', $code);
|
|
})
|
|
);
|
|
|
|
$this->assertMatchesRegularExpression(
|
|
"/^\d+$/",
|
|
(string)$login_mock->loginGetPasswordLenght($input)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Undocumented function
|
|
*
|
|
* @return array
|
|
*/
|
|
public function loginMaxErrorProvider(): array
|
|
{
|
|
return [
|
|
'set valid max failed login' => [
|
|
10,
|
|
true,
|
|
10
|
|
],
|
|
'set valid unlimted' => [
|
|
-1,
|
|
true,
|
|
-1
|
|
],
|
|
'set invalid 0' => [
|
|
0,
|
|
false,
|
|
-1
|
|
],
|
|
'set invalid negative' => [
|
|
-5,
|
|
false,
|
|
-1
|
|
],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Undocumented function
|
|
*
|
|
* @covers ::loginSetMaxLoginErrorCount
|
|
* @covers ::loginGetMaxLoginErrorCount
|
|
* @dataProvider loginMaxErrorProvider()
|
|
* @testdox ACL\Login failed login set/get $input is $expected_return and matches $expected [$_dataName]
|
|
*
|
|
* @param int $input
|
|
* @param bool $expected_return
|
|
* @param int $expected
|
|
* @return void
|
|
*/
|
|
public function testACLLoginErrorCount(int $input, bool $expected_return, int $expected): void
|
|
{
|
|
$_SESSION = [];
|
|
// init session (as MOCK)
|
|
/** @var \CoreLibs\Create\Session&MockObject */
|
|
$session_mock = $this->createPartialMock(
|
|
\CoreLibs\Create\Session::class,
|
|
['startSession', 'checkActiveSession', 'sessionDestroy']
|
|
);
|
|
$session_mock->method('startSession')->willReturn('ACLLOGINTEST34');
|
|
$session_mock->method('checkActiveSession')->willReturn(true);
|
|
$session_mock->method('sessionDestroy')->will(
|
|
$this->returnCallback(function () {
|
|
global $_SESSION;
|
|
$_SESSION = [];
|
|
return true;
|
|
})
|
|
);
|
|
/** @var \CoreLibs\ACL\Login&MockObject */
|
|
$login_mock = $this->getMockBuilder(\CoreLibs\ACL\Login::class)
|
|
->setConstructorArgs([
|
|
self::$db,
|
|
self::$log,
|
|
$session_mock,
|
|
[
|
|
'auto_login' => false,
|
|
'default_acl_level' => 80,
|
|
'logout_target' => '',
|
|
'site_locale' => 'en_US.UTF-8',
|
|
'site_domain' => 'admin',
|
|
'site_encoding' => 'UTF-8',
|
|
'locale_path' => __DIR__ . DIRECTORY_SEPARATOR
|
|
. 'includes' . DIRECTORY_SEPARATOR
|
|
. 'locale' . DIRECTORY_SEPARATOR,
|
|
]
|
|
])
|
|
->onlyMethods(['loginTerminate'])
|
|
->getMock();
|
|
$login_mock->expects($this->any())
|
|
->method('loginTerminate')
|
|
->will(
|
|
$this->returnCallback(function ($code) {
|
|
throw new \Exception('', $code);
|
|
})
|
|
);
|
|
|
|
// set new min password length
|
|
$this->assertEquals(
|
|
$expected_return,
|
|
$login_mock->loginSetMaxLoginErrorCount($input),
|
|
'assert bool set max login errors'
|
|
);
|
|
// check value
|
|
$this->assertEquals(
|
|
$expected,
|
|
$login_mock->loginGetMaxLoginErrorCount(),
|
|
'assert get max login errors'
|
|
);
|
|
}
|
|
}
|
|
|
|
// __END__
|