diff --git a/www/admin/class_test.login.php b/www/admin/class_test.login.php new file mode 100644 index 00000000..294a0d4a --- /dev/null +++ b/www/admin/class_test.login.php @@ -0,0 +1,61 @@ + BASE . LOG, + 'file_id' => $LOG_FILE_ID, + // add file date + 'print_file_date' => true, + // set debug and print flags + 'debug_all' => $DEBUG_ALL ?? false, + 'echo_all' => $ECHO_ALL ?? false, + 'print_all' => $PRINT_ALL ?? false, +]); +$db = new CoreLibs\DB\IO(DB_CONFIG, $log); +$login = new CoreLibs\ACL\Login($db, $log); +ob_end_flush(); + +print ""; +print "TEST CLASS: LOGIN"; +print ""; +print '
Class Test Master
'; + +echo "CHECK PERMISSION: " . ($login->loginCheckPermissions() ? 'OK' : 'BAD') . "
"; +echo "IS ADMIN: " . ($login->loginIsAdmin() ? 'OK' : 'BAD') . "
"; +echo "MIN ACCESS BASE: " . ($login->loginCheckAccessBase('admin') ? 'OK' : 'BAD') . "
"; +echo "MIN ACCESS PAGE: " . ($login->loginCheckAccessPage('admin') ? 'OK' : 'BAD') . "
"; + +echo "ACL: " . \CoreLibs\Debug\Support::printAr($login->loginGetAcl()) . "
"; +echo "ACL (MIN): " . \CoreLibs\Debug\Support::printAr($login->loginGetAcl()['min']) . "
"; + +// error message +print $log->printErrorMsg(); + +print ""; diff --git a/www/admin/class_test.php b/www/admin/class_test.php index ca90c81a..3ea4bb8f 100644 --- a/www/admin/class_test.php +++ b/www/admin/class_test.php @@ -82,6 +82,7 @@ print '
Class Test: OUTPUT FORMClass Test: BACKEND ADMIN CLASS
'; print '
Class Test: LANG/L10n
'; print '
Class Test: SMARTY
'; +print '
Class Test: LOGIN
'; print '
Class Test: AUTOLOADER
'; print '
Class Test: CONFIG LINK
'; print '
Class Test: CONFIG DIRECT
'; diff --git a/www/includes/edit_base.php b/www/includes/edit_base.php index 7439658d..2e5bbf7b 100644 --- a/www/includes/edit_base.php +++ b/www/includes/edit_base.php @@ -446,16 +446,15 @@ if ($form->my_page_name == 'edit_order') { $t_q = ''; foreach ($output as $output_file) { // split the ouput into folder and file - // eg ../admin/test.php is ../admin/ and test.php - preg_match("/([\.\/\w]+\/)+(\w+\.\w{1,})$/", $output_file, $matches); - // if named config.php, skip - if ($matches[2] != 'config.php') { - if ($t_q) { - $t_q .= ', '; - } - $t_q .= "('" . $form->dbEscapeString($matches[1]) . "', '" - . $form->dbEscapeString($matches[2]) . "')"; + $pathinfo = pathinfo($output_file); + if (!empty($pathinfo['dirname'])) { + $pathinfo['dirname'] .= DIRECTORY_SEPARATOR; } + if ($t_q) { + $t_q .= ', '; + } + $t_q .= "('" . $form->dbEscapeString($pathinfo['dirname']) . "', '" + . $form->dbEscapeString($pathinfo['basename']) . "')"; } $form->dbExec($q . $t_q, 'NULL'); $elements[] = $form->formCreateElement('filename'); diff --git a/www/lib/CoreLibs/ACL/Login.php b/www/lib/CoreLibs/ACL/Login.php index a8d0a868..c51fd0fb 100644 --- a/www/lib/CoreLibs/ACL/Login.php +++ b/www/lib/CoreLibs/ACL/Login.php @@ -164,7 +164,9 @@ class Login public $l; /** - * constructor, does ALL, opens db, works through connection checks, closes itself + * constructor, does ALL, opens db, works through connection checks, + * finishes itself + * * @param \CoreLibs\DB\IO $db Database connection class * @param \CoreLibs\Debug\Logging $log Logging class */ @@ -201,12 +203,10 @@ class Login // pre-check that password min/max lengths are inbetween 1 and 255; if ($this->password_max_length > 255) { - echo 'Settings problem PMaL
'; - exit; + $this->password_max_length = 255; } if ($this->password_min_length < 1) { - echo 'Settings problem PMiL
'; - exit; + $this->password_min_length = 1; } // set global is ajax page for if we show the data directly, @@ -268,7 +268,8 @@ class Login // init default ACL list array $_SESSION['DEFAULT_ACL_LIST'] = []; // read the current edit_access_right list into an array - $q = "SELECT level, type, name FROM edit_access_right WHERE level >= 0 ORDER BY level"; + $q = "SELECT level, type, name FROM edit_access_right " + . "WHERE level >= 0 ORDER BY level"; while (is_array($res = $this->db->dbReturn($q))) { // level to description format (numeric) $this->default_acl_list[$res['level']] = [ @@ -287,7 +288,10 @@ class Login $this->loginLogoutUser(); // ** LANGUAGE SET AFTER LOGIN ** // set the locale - if (Session::getSessionId() !== false && !empty($_SESSION['DEFAULT_LANG'])) { + if ( + Session::getSessionId() !== false && + !empty($_SESSION['DEFAULT_LANG']) + ) { $locale = $_SESSION['DEFAULT_LOCALE'] ?? ''; } else { $locale = defined('SITE_LOCALE') && !empty(SITE_LOCALE) ? @@ -315,7 +319,8 @@ class Login $this->login_html = $this->loginPrintLogin(); // closing all connections, depending on error status, exit if (!$this->loginCloseClass()) { - // if variable AJAX flag is not set, show output, else pass through for ajax work + // if variable AJAX flag is not set, show output + // else pass through for ajax work if ($this->login_is_ajax_page !== true) { // the login screen if we hav no login permission & login screen html data if ($this->login_html !== null) { @@ -361,8 +366,13 @@ class Login // NO OP } + // ************************************************************************* + // **** PRIVATE INTERNAL + // ************************************************************************* + /** * checks if password is valid, sets internal error login variable + * * @param string $hash password hash * @param string $password submitted password * @return bool true or false on password ok or not @@ -419,7 +429,9 @@ class Login } /** - * if user pressed login button this script is called, but only if there is no preview euid set] + * if user pressed login button this script is called, + * but only if there is no preview euid set + * * @return void has not return */ private function loginLoginUser(): void @@ -703,88 +715,6 @@ class Login } } - /** - * for every page the user access this script checks if he is allowed to do so - * @return bool permission okay as true/false - */ - public function loginCheckPermissions(): bool - { - if ($this->euid && $this->login_error != 103) { - $q = "SELECT filename " - . "FROM edit_page ep, edit_page_access epa, edit_group eg, edit_user eu " - . "WHERE ep.edit_page_id = epa.edit_page_id " - . "AND eg.edit_group_id = epa.edit_group_id " - . "AND eg.edit_group_id = eu.edit_group_id " - . "AND eu.edit_user_id = " . $this->euid . " " - . "AND filename = '" . $this->page_name . "' " - . "AND eg.enabled = 1 AND epa.enabled = 1"; - $res = $this->db->dbReturnRow($q); - if (!is_array($res)) { - $this->login_error = 109; - $this->permission_okay = false; - return $this->permission_okay; - } - if (isset($res['filename']) && $res['filename'] == $this->page_name) { - $this->permission_okay = true; - } else { - $this->login_error = 103; - $this->permission_okay = false; - } - } - // if called from public, so we can check if the permissions are ok - return $this->permission_okay; - } - - /** - * if a user pressed on logout, destroyes session and unsets all global vars - * @return void has no return - */ - public function loginLogoutUser(): void - { - // must be either logout or error - if (!$this->logout && !$this->login_error) { - return; - } - // unregister and destroy session vars - foreach ( - // TODO move this into some global array for easier update - [ - 'ADMIN', - 'BASE_ACL_LEVEL', - 'DB_DEBUG', - 'DEBUG_ALL', - 'DEFAULT_ACL_LIST', - 'DEFAULT_CHARSET', - 'DEFAULT_LANG', - 'DEFAULT_LOCALE', - 'EAID', - 'EUID', - 'GROUP_ACL_LEVEL', - 'GROUP_ACL_TYPE', - 'GROUP_NAME', - 'HEADER_COLOR', - 'LANG', - 'PAGES_ACL_LEVEL', - 'PAGES', - 'TEMPLATE', - 'UNIT_ACL_LEVEL', - 'UNIT_DEFAULT', - 'UNIT', - 'USER_ACL_LEVEL', - 'USER_ACL_TYPE', - 'USER_NAME', - ] as $session_var - ) { - unset($_SESSION[$session_var]); - } - // final unset all - session_unset(); - // final destroy session - session_destroy(); - // then prints the login screen again - $this->permission_okay = false; - } - /** * sets all the basic ACLs * init set the basic acl the user has, based on the following rules @@ -800,6 +730,7 @@ class Login * - if an account ACL is set, set this parallel, account ACL overrides user ACL if it applies * - if edit access ACL level is set, use this, else use page * set all base ACL levels as a list keyword -> ACL number + * * @return void has no return */ private function loginSetAcl(): void @@ -898,25 +829,32 @@ class Login } /** - * checks if this edit access id is valid - * @param int|null $edit_access_id access id pk to check - * @return bool true/false: if the edit access is not - * in the valid list: false + * Check if source (page, base) is matching to the given min access string + * min access string must be valid access level string (eg read, mod, write) + * This does not take in account admin flag set + * + * @param string $source a valid base level string eg base, page + * @param string $min_access a valid min level string, eg read, mod, siteadmin + * @return bool True for valid access, False for invalid */ - public function loginCheckEditAccess($edit_access_id): bool + public function loginCheckAccess(string $source, string $min_access): bool { - if ($edit_access_id === null) { + $source = 'base'; + if ( + empty($this->acl['min'][$min_access]) || + empty($this->acl[$source]) + ) { return false; } - if (array_key_exists($edit_access_id, $this->acl['unit'])) { + if ($this->acl[$source] >= $this->acl['min'][$min_access]) { return true; - } else { - return false; } + return false; } /** * checks if the password is in a valid format + * * @param string $password the new password * @return bool true or false if valid password or not */ @@ -940,6 +878,7 @@ class Login /** * dummy declare for password forget + * * @return void has no return */ private function loginPasswordForgot(): void @@ -947,25 +886,9 @@ class Login // will do some password recovert, eg send email } - /** - * sets the minium length and checks on valid - * @param int $length set the minimum length - * @return bool true/false on success - */ - public function loginSetPasswordMinLength(int $length): bool - { - // check that numeric, positive numeric, not longer than max input string lenght - // and not short than min password length - if (is_numeric($length) && $length >= PASSWORD_MIN_LENGTH && $length <= $this->password_max_length) { - $this->password_min_length = $length; - return true; - } else { - return false; - } - } - /** * changes a user password + * * @return void has no return */ private function loginPasswordChange(): void @@ -1066,6 +989,7 @@ class Login /** * prints out login html part if no permission (error) is set + * * @return string|null html data for login page, or null for nothing */ private function loginPrintLogin() @@ -1171,6 +1095,7 @@ class Login /** * last function called, writes log and prints out error msg and * exists script if permission 0 + * * @return bool true on permission ok, false on permission wrong */ private function loginCloseClass(): bool @@ -1209,6 +1134,7 @@ class Login /** * checks if there are external templates, if not uses internal fallback ones + * * @return void has no return */ private function loginSetTemplates(): void @@ -1390,6 +1316,7 @@ EOM; /** * writes detailed data into the edit user log table (keep log what user does) + * * @param string $event string of what has been done * @param string $data data information (id, etc) * @param string|int $error error id (mostly an int) @@ -1450,8 +1377,186 @@ EOM; $this->db->dbExec($q, 'NULL'); } + // ************************************************************************* + // **** PUBLIC INTERNAL + // ************************************************************************* + + /** + * sets the minium length and checks on valid + * + * @param int $length set the minimum length + * @return bool true/false on success + */ + public function loginSetPasswordMinLength(int $length): bool + { + // check that numeric, positive numeric, not longer than max input string lenght + // and not short than min password length + if (is_numeric($length) && $length >= PASSWORD_MIN_LENGTH && $length <= $this->password_max_length) { + $this->password_min_length = $length; + return true; + } + return false; + } + + /** + * if a user pressed on logout, destroyes session and unsets all global vars + * + * @return void has no return + */ + public function loginLogoutUser(): void + { + // must be either logout or error + if (!$this->logout && !$this->login_error) { + return; + } + // unregister and destroy session vars + foreach ( + // TODO move this into some global array for easier update + [ + 'ADMIN', + 'BASE_ACL_LEVEL', + 'DB_DEBUG', + 'DEBUG_ALL', + 'DEFAULT_ACL_LIST', + 'DEFAULT_CHARSET', + 'DEFAULT_LANG', + 'DEFAULT_LOCALE', + 'EAID', + 'EUID', + 'GROUP_ACL_LEVEL', + 'GROUP_ACL_TYPE', + 'GROUP_NAME', + 'HEADER_COLOR', + 'LANG', + 'PAGES_ACL_LEVEL', + 'PAGES', + 'TEMPLATE', + 'UNIT_ACL_LEVEL', + 'UNIT_DEFAULT', + 'UNIT', + 'USER_ACL_LEVEL', + 'USER_ACL_TYPE', + 'USER_NAME', + ] as $session_var + ) { + unset($_SESSION[$session_var]); + } + // final unset all + session_unset(); + // final destroy session + session_destroy(); + // then prints the login screen again + $this->permission_okay = false; + } + + /** + * for every page the user access this script checks if he is allowed to do so + * + * @return bool permission okay as true/false + */ + public function loginCheckPermissions(): bool + { + // start with not allowed + $this->permission_okay = false; + // bail for no euid (no login) + if (!$this->euid) { + return $this->permission_okay; + } + // bail for previous wrong page match, eg if method is called twice + if ($this->login_error == 103) { + return $this->permission_okay; + } + // if ($this->euid && $this->login_error != 103) { + $q = "SELECT filename " + . "FROM edit_page ep, edit_page_access epa, edit_group eg, edit_user eu " + . "WHERE ep.edit_page_id = epa.edit_page_id " + . "AND eg.edit_group_id = epa.edit_group_id " + . "AND eg.edit_group_id = eu.edit_group_id " + . "AND eu.edit_user_id = " . $this->euid . " " + . "AND filename = '" . $this->page_name . "' " + . "AND eg.enabled = 1 AND epa.enabled = 1"; + $res = $this->db->dbReturnRow($q); + if (!is_array($res)) { + $this->login_error = 109; + return $this->permission_okay; + } + if (isset($res['filename']) && $res['filename'] == $this->page_name) { + $this->permission_okay = true; + } else { + $this->login_error = 103; + } + // if called from public, so we can check if the permissions are ok + return $this->permission_okay; + } + + /** + * Return ACL array as is + * + * @return array + */ + public function loginGetAcl(): array + { + return $this->acl; + } + + /** + * checks if this edit access id is valid + * + * @param int|null $edit_access_id access id pk to check + * @return bool true/false: if the edit access is not + * in the valid list: false + */ + public function loginCheckEditAccess($edit_access_id): bool + { + if ($edit_access_id === null) { + return false; + } + if (array_key_exists($edit_access_id, $this->acl['unit'])) { + return true; + } + return false; + } + + /** + * Check if admin flag is set + * + * @return bool True if admin flag set + */ + public function loginIsAdmin(): bool + { + if (!empty($this->acl['admin'])) { + return true; + } + return false; + } + + /** + * check if min accesss string (eg, read, mod, etc) is matchable + * EQUAL to BASE set right + * + * @param string $min_access + * @return bool + */ + public function loginCheckAccessBase(string $min_access): bool + { + return $this->loginCheckAccess('base', $min_access); + } + + /** + * check if min accesss string (eg, read, mod, etc) is matchable + * EQUAL to PAGE set right + * + * @param string $min_access + * @return bool + */ + public function loginCheckAccessPage(string $min_access): bool + { + return $this->loginCheckAccess('page', $min_access); + } + /** * checks that the given edit access id is valid for this user + * * @param int|null $edit_access_id edit access id to check * @return int|null same edit access id if ok * or the default edit access id @@ -1466,14 +1571,14 @@ EOM; !array_key_exists($edit_access_id, $_SESSION['UNIT']) ) { return $_SESSION['UNIT_DEFAULT'] ?? null; - } else { - return $edit_access_id; } + return $edit_access_id; } /** * retunrn a set entry from the UNIT session for an edit access_id * if not found return false + * * @param int $edit_access_id edit access id * @param string|int $data_key key value to search for * @return bool|string false for not found or string for found data @@ -1482,9 +1587,8 @@ EOM; { if (!isset($_SESSION['UNIT'][$edit_access_id]['data'][$data_key])) { return false; - } else { - return $_SESSION['UNIT'][$edit_access_id]['data'][$data_key]; } + return $_SESSION['UNIT'][$edit_access_id]['data'][$data_key]; } // close class } diff --git a/www/lib/CoreLibs/DB/Extended/ArrayIO.php b/www/lib/CoreLibs/DB/Extended/ArrayIO.php index f6643293..f12cc8aa 100644 --- a/www/lib/CoreLibs/DB/Extended/ArrayIO.php +++ b/www/lib/CoreLibs/DB/Extended/ArrayIO.php @@ -43,7 +43,7 @@ class ArrayIO extends \CoreLibs\DB\IO /** @var string */ public $table_name; // the table_name /** @var string */ - public $pk_name; // the primary key from this table + public $pk_name = ''; // the primary key from this table /** @var int|string|null */ public $pk_id; // the PK id