Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
9fcdf12
Исправление отображения списка в режиме для чтения
n2ref Oct 7, 2025
c7d6bb1
Исправление поля для импорта в edit классе
n2ref Oct 8, 2025
45059fc
Исправление фатала
Oct 12, 2025
ccfe649
Исправление sql ошибки при входе через ldap
n2ref Oct 14, 2025
b8a97f8
Merge remote-tracking branch 'origin/2.9.1' into 2.9.1
n2ref Oct 14, 2025
e1d40e0
Merge remote-tracking branch 'easterism/2.9.2' into 2.9.2
n2ref Oct 15, 2025
9eda6d8
listTable deprecated
Oct 27, 2025
fee6b3b
Исправление варнинга
n2ref Nov 14, 2025
64e2ade
Улучшение checkbox2
n2ref Nov 14, 2025
5829278
Добавлено описание доступных для загрузки форматов файлов
n2ref Nov 18, 2025
8850315
api работает с двумя подходами
Nov 22, 2025
e603c4e
Исправление ошибок при отображении схемы api
Nov 23, 2025
2381ce6
Исправление создания лишних серверов при наличии папки
Nov 23, 2025
a93ed9b
Добавлено описание ошибки при отсутствии методы api
n2ref Dec 12, 2025
1f82473
Добавлена возможсность кастомно обрабатывать сортировку в таблицах
Dec 18, 2025
0eccbbd
Исправление переноса меню на новую строку
n2ref Dec 22, 2025
2d751c3
Merge remote-tracking branch 'easterism/2.9.2' into 2.9.2
n2ref Dec 23, 2025
36410a7
Добавлен метод getFilesNormalize
Dec 23, 2025
c845ed2
Merge remote-tracking branch 'origin/2.9.2' into 2.9.2
Dec 23, 2025
d4b1adf
Merge remote-tracking branch 'easterism/2.9.2' into 2.9.2
n2ref Jan 22, 2026
82c517f
Исправление генерации документации апи
n2ref Jan 22, 2026
53a3b97
Добавлено ограничение в api модулей по доступу
n2ref Jan 22, 2026
ed40284
В регулярках путей для api по умолчанию только цифры
n2ref Jan 23, 2026
eeef2fc
Merge remote-tracking branch 'easterism/2.9.2' into 2.9.2
n2ref Jan 29, 2026
71ffcc5
Исправление получения схемы api
n2ref Jan 29, 2026
e414019
Версия
Feb 3, 2026
db068f7
Возможность указывать лимит на одновременную загрузку
n2ref Feb 5, 2026
766a98d
Merge remote-tracking branch 'origin/2.9.2' into 2.9.2
BeHuK Feb 17, 2026
c9534fe
Добавлен метод setOverflow
n2ref Feb 17, 2026
5481579
Merge remote-tracking branch 'origin/2.9.2'
n2ref Feb 17, 2026
64b80b4
Merge remote-tracking branch 'easterism/2.9.2'
n2ref Feb 20, 2026
2450208
Merge remote-tracking branch 'easterism/2.9.2' into 2.9.2
n2ref Mar 25, 2026
084c6fb
Добавлен метод для получения справочника по id
n2ref Mar 25, 2026
fbc31b0
Исправление некорректного определения типа переменной в IDE
n2ref Mar 26, 2026
661a702
мердж с веткой Паши
n2ref Mar 26, 2026
bf3e003
Исправление некорректного определения типа переменной в IDE
n2ref Mar 26, 2026
708727f
Паша добавил метод deleteRow. я его перенес сюда
n2ref Mar 27, 2026
0e245d7
Исправления ошибок
n2ref Mar 27, 2026
b12dde4
Merge remote-tracking branch 'origin/2.9.2' into 2.9.2
n2ref Mar 27, 2026
b90218c
исправление фатала
n2ref Mar 30, 2026
a3d7fd8
Merge remote-tracking branch 'origin/2.9.2' into 2.9.2
BeHuK Apr 9, 2026
4460b98
Merge remote-tracking branch 'ihor/2.9.2' into 2.9.2
BeHuK Apr 9, 2026
224b701
employees#114 проверка на устаревание пароля.
BeHuK Apr 10, 2026
9fb12a9
фильтр диапазона дат 23:59:59 по умолчанию
BeHuK Apr 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions cli.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@
<?php
namespace Core2;

require_once 'inc/classes/Error.php';
require_once 'inc/classes/Cli.php';
require_once 'inc/classes/Registry.php';
require_once 'inc/classes/Config.php';
require_once 'inc/classes/I18n.php';

try {
if (PHP_SAPI !== 'cli') {
throw new \Exception("Allowed for CLI only.");
Expand All @@ -17,6 +11,11 @@
throw new \Exception("Composer autoload is missing.");
}
require_once($autoload);
require_once 'inc/classes/Error.php';
require_once 'inc/classes/Cli.php';
require_once 'inc/classes/Registry.php';
require_once 'inc/classes/Config.php';
require_once 'inc/classes/I18n.php';

$_SERVER['SERVER_NAME'] = '_';
$options = getopt('c:m:a:p:s:h', array(
Expand Down
2 changes: 1 addition & 1 deletion conf.ini
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

[production]
; ## Текущая версия ядра
version = 2.9.1
version = 2.9.2

; ## Используется в модуле webservice
; ## Время в секундах на которое выписывается вебтокен пользователя
Expand Down
70 changes: 67 additions & 3 deletions inc/CoreController.php
Original file line number Diff line number Diff line change
Expand Up @@ -392,10 +392,23 @@ public function action_seq(): string {

if ($rows) {
$rows_seq = array_values($rows);
$records = [];

foreach ($_POST['data'] as $k => $row_id) {
$where = $this->db->quoteInto("{$id_name} = ?", $row_id);
$this->db->update($table_name, ['seq' => $rows_seq[$k]], $where);
foreach ($_POST['data'] as $k => $row_id) {
$records[$row_id] = $rows_seq[$k];
}


$is_custom = $records
? $this->customSequence($resource, $records)
: false;


if ( ! $is_custom) {
foreach ($records as $row_id => $sequence) {
$where = $this->db->quoteInto("{$id_name} = ?", $row_id);
$this->db->update($table_name, ['seq' => $sequence], $where);
}
}
}

Expand Down Expand Up @@ -1106,4 +1119,55 @@ public function action_workhorse() {
echo Alert::danger($e->getMessage());
}
}


/**
* Проверка модуля на реализацию собственного удаления
* @param string $resource
* @param array $records
* @return bool
* @throws Exception
*/
private function customSequence(string $resource, array $records): bool {

$mod = explode('xxx', $resource);
$mod = explode("_", $mod[0]);
$controller_name = "Mod" . ucfirst(strtolower($mod[0])) . "Controller";

$this->requireController($mod[0], $controller_name);
$controller = new $controller_name();

return $controller instanceof Sequence
? $controller->sequence($resource, $records)
: false;
}


/**
* @param string $module_name
* @param string $mod_controller
* @return void
* @throws Exception
*/
private function requireController(string $module_name, string $mod_controller): void {

$location = $this->getModuleLocation($module_name); //определяем местоположение модуля
$controller_path = $location . "/" . $mod_controller . ".php";

if ( ! file_exists($controller_path)) {
throw new Exception(sprintf($this->translate->tr("Модуль не найден: %s"), $mod_controller), 400);
}

$autoload = $location . "/vendor/autoload.php";

if (file_exists($autoload)) { //подключаем автозагрузку если есть
require_once $autoload;
}

require_once $controller_path; // подлючаем контроллер

if ( ! class_exists($mod_controller)) {
throw new RuntimeException(sprintf($this->translate->tr("Модуль сломан: %s"), $location));
}
}
}
16 changes: 16 additions & 0 deletions inc/Interfaces/Sequence.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php


/**
*
*/
interface Sequence {

/**
* @param string $resource_name
* @param array $records
* Если возвращено true, то будет считаться, что вы самостоятельно сортировали объекты
* Если возвращено false будет считаться, что нужно применить стандартную процедуру сортировки
*/
public function sequence(string $resource_name, array $records): bool;
}
2 changes: 2 additions & 0 deletions inc/Traits/Import.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ public function getFieldImport(array $options, array $data): string {

if ($options['rows_select'] == 'checked') {
$tpl->row->checked_row->assign('[ROW_NUMBER]', $num);
} else {
$tpl->row->start_row->assign('[ROW_NUMBER]', $num);
}

$col = 0;
Expand Down
4 changes: 3 additions & 1 deletion inc/classes/Error.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@ public static function catchException(\Exception $exception): void {
self::Exception('Нет такой страницы', 404);

} elseif ($message == 'expired') {
setcookie($cnf->session->name, false);
if ($cnf && $cnf?->session?->name) {
setcookie($cnf->session->name, false);
}
header("{$_SERVER['SERVER_PROTOCOL']} 403 Forbidden");
die();
}
Expand Down
98 changes: 67 additions & 31 deletions inc/classes/Init.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,77 +93,78 @@

$section = !empty($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'production';

$conf = new Core2\Config($config_origin);
$config = $conf->getData()->merge($conf->readIni($conf_file, $section));
$conf = new Core2\Config($config_origin);
$system_config = $conf->getData()->merge($conf->readIni($conf_file, $section));



$conf_d = __DIR__ . "/../../conf.ext.ini";
if (file_exists($conf_d)) {
$config->merge($conf->readIni($conf_d, $section));
$system_config->merge($conf->readIni($conf_d, $section));
}

if (empty($_SERVER['HTTPS'])) {
if (isset($config->system) && ! empty($config->system->https)) {
if (isset($system_config->system) && ! empty($system_config->system->https)) {
header('Location: https://' . $_SERVER['SERVER_NAME']);
exit(); // TODO нужно убрать
}
}
$tz = $config->system->timezone;
$tz = $system_config->system->timezone;
if (!empty($tz)) {
date_default_timezone_set($tz);
}
if (!$config) throw new Exception("Unable to load configuration.");
if (!$system_config) throw new Exception("Unable to load configuration.");
}
catch (Exception $e) {
Error::Exception($e->getMessage());
}

// отладка приложения
if ($config->debug->on) {
if ($system_config->debug->on) {
error_reporting(E_ALL);
ini_set('display_errors', 1);
} else {
ini_set('display_errors', 0);
}

//проверяем настройки для базы данных
if ($config->database) {
if (empty($config->database->adapter)) {
if ($system_config->database) {
if (empty($system_config->database->adapter)) {
Error::Exception('Database adapter is empty!');
}
if (empty($config->database->params->dbname)) {
if (empty($system_config->database->params->dbname)) {
Error::Exception('Database name is empty!');
}
}

//конфиг стал только для чтения
$config->setReadOnly();
$system_config->setReadOnly();


if (isset($config->include_path) && $config->include_path) {
set_include_path(get_include_path() . PATH_SEPARATOR . $config->include_path);
if (isset($system_config->include_path) && $system_config->include_path) {
set_include_path(get_include_path() . PATH_SEPARATOR . $system_config->include_path);
}

//подключаем мультиязычность
require_once 'I18n.php';
$translate = new I18n($config);
$translate = new I18n($system_config);

//сохраняем конфиг
Registry::set('config', $config);
Registry::set('config', $system_config);

//обрабатываем конфиг ядра
$core_conf_file = __DIR__ . "/../../conf.ini";
if (file_exists($core_conf_file)) {
$config = new Core2\Config();
Registry::set('core_config', $config->readIni($core_conf_file, 'production'));
$core_config = new Core2\Config();
Registry::set('core_config', $core_config->readIni($core_conf_file, 'production'));
}

require_once 'Acl.php';
require_once 'Common.php';
require_once 'SSE.php';


/**
* Class Init
* @property Core2\Model\Modules $dataModules
*/
class Init extends Acl {
Expand All @@ -173,9 +174,6 @@ class Init extends Acl {
*/
private $auth;

protected $is_rest = array();
protected $is_soap = array();


/**
* Общая проверка аутентификации
Expand Down Expand Up @@ -250,13 +248,6 @@ public function checkAuth() {

$auth = new SessionContainer('Auth');
if (!empty($auth->ID) && is_int($auth->ID)) {
if (!empty($_POST['login']) && !empty($_POST['password'])) {
//попытка повторного входа
return [
'status' => 'success',
'return_url' => DOC_PATH,
];
}
if (!$auth->getManager()->isValid()) {
$this->closeSession('Y');
}
Expand Down Expand Up @@ -327,24 +318,28 @@ public function dispatch() {

if (isset($route['module'])) {
if (isset($route['api']) && $route['api'] === 'openapi') {

if ($route['action'] == 'core2.json') {
define("SERVER", (!empty($_SERVER['HTTPS']) ? 'https://' : 'http://') . $_SERVER['SERVER_NAME'] . DOC_PATH);
define("SERVER", ( ! empty($_SERVER['HTTPS']) ? 'https://' : 'http://') . $_SERVER['SERVER_NAME'] . DOC_PATH);
//генерация свагера для общего API
require_once "OpenApi.php";
header("Cache-Control: no-cache");
$schema = new \Core2\OpenApi();
$html = $schema->render();
$html = $schema->render();
return $html;
}

if ($route['action'] == 'sections') {
require_once "OpenApiSpec.php";
header('Content-Type: application/json');
$schema = new \Core2\OpenApiSpec();
$this->setupAcl();

if ( ! empty($route['params'])) {
$section = key($route['params']);
return json_encode($schema->getSectionSchema($section));
}

return json_encode([ 'sections' => $schema->getSections() ]);
}
}
Expand All @@ -359,6 +354,11 @@ public function dispatch() {
$sse = new Core2\SSE();
$sse->run();
return '';
} elseif ($route['module'] === 'change_pass') {
require_once 'Login.php';
$login = new Login();
$this->setupSkin();
return $login->dispatch($route);
}
}

Expand All @@ -370,6 +370,9 @@ public function dispatch() {
$this->logActivity($logExclude);
//TODO CHECK DIRECT REQUESTS except iframes

//Проверка устаревания пароля
$this->checkExpired();

require_once 'Zend_Session_Namespace.php'; //DEPRECATED
require_once 'core2/inc/Interfaces/Delete.php';
require_once 'core2/inc/Interfaces/File.php';
Expand Down Expand Up @@ -548,6 +551,39 @@ public function dispatch() {
}


/**
* Проверка на устаревание пароля пользователя
* @return void
* @throws Exception
*/
private function checkExpired()
{

if ($this->config->registry->pass_expired == 'Y') {
if ( ! empty($this->auth->check_expired)) {
return;
}

if ( ! empty($this->config->registry->pass_expired_exception_user_id)) {
$exception_ids = explode(',', $this->config->registry->pass_expired_exception_user_id);
if (in_array($this->auth->ID, $exception_ids)) {
$this->auth->check_expired = 1;
return;
}
}

$data_user = $this->dataUsers->getUserById($this->auth->ID);

if (
(new DateTime($data_user['date_expired'])) < (new DateTime())) {
header('Location: /change_pass');
exit;
}
$this->auth->check_expired = 1;
}
}



/**
* проверка модуля на доступность
Expand Down Expand Up @@ -751,7 +787,7 @@ private function checkToken() {
//http basic auth allowed
[$login, $password] = explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));
$user = $this->dataUsers->getUserByLogin($login);
if ($user && \Core2\Tool::password_verify_secure($password, (string)$user['u_pass'])) {
if ($user && $user['u_pass'] === Tool::pass_salt(md5($password))) {
$auth = new \StdClass();

$auth->LIVEID = 0;
Expand Down
2 changes: 1 addition & 1 deletion inc/classes/LdapAuth.php
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ public function getLdapInfo(string $login): void {
]);

if ( ! $isset_email) {
$where = $this->db->quoteInto('id = ?', $user_id);
$where = $this->db->quoteInto('u_id = ?', $user_id);
$this->db->update('core_users', [
'email' => $data['mail'][0],
], $where);
Expand Down
Loading