/modules/main/classes/general/user.php
PHP | 1664 lines | 1386 code | 211 blank | 67 comment | 258 complexity | a03ae5da9a25215c6c767e3c9486e935 MD5 | raw file
- <?php
- /**
- * Bitrix Framework
- * @package bitrix
- * @subpackage main
- * @copyright 2001-2020 Bitrix
- */
- use Bitrix\Main;
- use Bitrix\Main\Authentication\ApplicationPasswordTable;
- use Bitrix\Main\Authentication\Internal\UserPasswordTable;
- use Bitrix\Main\Authentication\Policy;
- use Bitrix\Main\Localization\Loc;
- use Bitrix\Main\Security\Random;
- use Bitrix\Main\Security\Password;
- IncludeModuleLangFile(__FILE__);
- /**
- * @deprecated
- */
- class CAllUser extends CDBResult
- {
- var $LAST_ERROR = "";
- var $bLoginByHash = false;
- protected $admin = null;
- /** @var Main\Session\SessionInterface */
- protected static $kernelSession;
- protected static $CURRENT_USER = false;
- protected $justAuthorized = false;
- protected static $userGroupCache = array();
- const STATUS_ONLINE = 'online';
- const STATUS_OFFLINE = 'offline';
- //in seconds
- const PHONE_CODE_OTP_INTERVAL = 30;
- const PHONE_CODE_RESEND_INTERVAL = 60;
- public const PASSWORD_SPECIAL_CHARS = ',.<>/?;:\'"[]{}\|`~!@#$%^&*()_+=-';
- /**
- * CUser constructor.
- */
- public function __construct()
- {
- static::$kernelSession = Main\Application::getInstance()->getKernelSession();
- parent::__construct();
- }
- public function GetParam($name)
- {
- if(isset(static::$kernelSession["SESS_AUTH"][$name]))
- return static::$kernelSession["SESS_AUTH"][$name];
- else
- return null;
- }
- public function SetParam($name, $value)
- {
- static::$kernelSession["SESS_AUTH"][$name] = $value;
- }
- public function GetSecurityPolicy()
- {
- if(!is_array($this->GetParam("POLICY")))
- {
- $this->SetParam("POLICY", static::getPolicy($this->GetID())->getValues());
- }
- return $this->GetParam("POLICY");
- }
- public function GetID()
- {
- if(!isset($this))
- {
- trigger_error("Static call CUser::GetID() is deprecated, will be removed soon. Use global \$USER.", E_USER_WARNING);
- global $USER;
- return $USER->GetID();
- }
- return $this->GetParam("USER_ID");
- }
- public function GetLogin()
- {
- if(!isset($this))
- {
- trigger_error("Static call CUser::GetLogin() is deprecated, will be removed soon. Use global \$USER.", E_USER_WARNING);
- global $USER;
- return $USER->GetLogin();
- }
- return $this->GetParam("LOGIN");
- }
- public function GetEmail()
- {
- if(!isset($this))
- {
- trigger_error("Static call CUser::GetEmail() is deprecated, will be removed soon. Use global \$USER.", E_USER_WARNING);
- global $USER;
- return $USER->GetEmail();
- }
- return $this->GetParam("EMAIL");
- }
- public function GetFullName()
- {
- if(!isset($this))
- {
- trigger_error("Static call CUser::GetFullName() is deprecated, will be removed soon. Use global \$USER.", E_USER_WARNING);
- global $USER;
- return $USER->GetFullName();
- }
- return $this->GetParam("NAME");
- }
- public function GetFirstName()
- {
- if(!isset($this))
- {
- trigger_error("Static call CUser::GetFirstName() is deprecated, will be removed soon. Use global \$USER.", E_USER_WARNING);
- global $USER;
- return $USER->GetFirstName();
- }
- return $this->GetParam("FIRST_NAME");
- }
- public function GetLastName()
- {
- if(!isset($this))
- {
- trigger_error("Static call CUser::GetLastName() is deprecated, will be removed soon. Use global \$USER.", E_USER_WARNING);
- global $USER;
- return $USER->GetLastName();
- }
- return $this->GetParam("LAST_NAME");
- }
- public function GetSecondName()
- {
- if(!isset($this))
- {
- trigger_error("Static call CUser::GetSecondName() is deprecated, will be removed soon. Use global \$USER.", E_USER_WARNING);
- global $USER;
- return $USER->GetSecondName();
- }
- return $this->GetParam("SECOND_NAME");
- }
- public function GetFormattedName($bUseBreaks = true, $bHTMLSpec = true)
- {
- return static::FormatName(CSite::GetNameFormat($bUseBreaks),
- array(
- "TITLE" => $this->GetParam("TITLE"),
- "NAME" => $this->GetFirstName(),
- "SECOND_NAME" => $this->GetSecondName(),
- "LAST_NAME" => $this->GetLastName(),
- "LOGIN" => $this->GetLogin(),
- ),
- true,
- $bHTMLSpec
- );
- }
- public static function err_mess()
- {
- return "<br>Class: CUser<br>File: ".__FILE__;
- }
- public function Add($arFields)
- {
- /** @global CUserTypeManager $USER_FIELD_MANAGER */
- global $DB, $USER_FIELD_MANAGER, $CACHE_MANAGER;
- $ID = 0;
- if(!$this->CheckFields($arFields))
- {
- $Result = false;
- $arFields["RESULT_MESSAGE"] = &$this->LAST_ERROR;
- }
- else
- {
- unset($arFields["ID"]);
- unset($arFields["STORED_HASH"]);
- $arFields['ACTIVE'] = (is_set($arFields, 'ACTIVE') && $arFields['ACTIVE'] != 'Y'? 'N' : 'Y');
- $arFields['BLOCKED'] = (is_set($arFields, 'BLOCKED') && $arFields['BLOCKED'] == 'Y'? 'Y' : 'N');
- $arFields['PASSWORD_EXPIRED'] = (is_set($arFields, 'PASSWORD_EXPIRED') && $arFields['PASSWORD_EXPIRED'] == 'Y'? 'Y' : 'N');
- if($arFields["PERSONAL_GENDER"]=="NOT_REF" || ($arFields["PERSONAL_GENDER"]!="M" && $arFields["PERSONAL_GENDER"]!="F"))
- $arFields["PERSONAL_GENDER"] = "";
- $originalPassword = $arFields["PASSWORD"];
- $arFields["PASSWORD"] = Password::hash($arFields["PASSWORD"]);
- $checkword = ($arFields["CHECKWORD"] == ''? md5(uniqid().CMain::GetServerUniqID()) : $arFields["CHECKWORD"]);
- $arFields["CHECKWORD"] = Password::hash($checkword);
- $arFields["~CHECKWORD_TIME"] = $DB->CurrentTimeFunction();
- if(is_set($arFields, "WORK_COUNTRY"))
- $arFields["WORK_COUNTRY"] = intval($arFields["WORK_COUNTRY"]);
- if(is_set($arFields, "PERSONAL_COUNTRY"))
- $arFields["PERSONAL_COUNTRY"] = intval($arFields["PERSONAL_COUNTRY"]);
- if (
- array_key_exists("PERSONAL_PHOTO", $arFields)
- && is_array($arFields["PERSONAL_PHOTO"])
- && (
- !array_key_exists("MODULE_ID", $arFields["PERSONAL_PHOTO"])
- || $arFields["PERSONAL_PHOTO"]["MODULE_ID"] == ''
- )
- )
- $arFields["PERSONAL_PHOTO"]["MODULE_ID"] = "main";
- CFile::SaveForDB($arFields, "PERSONAL_PHOTO", "main");
- if (
- array_key_exists("WORK_LOGO", $arFields)
- && is_array($arFields["WORK_LOGO"])
- && (
- !array_key_exists("MODULE_ID", $arFields["WORK_LOGO"])
- || $arFields["WORK_LOGO"]["MODULE_ID"] == ''
- )
- )
- $arFields["WORK_LOGO"]["MODULE_ID"] = "main";
- CFile::SaveForDB($arFields, "WORK_LOGO", "main");
- $arInsert = $DB->PrepareInsert("b_user", $arFields);
- if(!is_set($arFields, "DATE_REGISTER"))
- {
- $arInsert[0] .= ", DATE_REGISTER";
- $arInsert[1] .= ", ".$DB->GetNowFunction();
- }
- $strSql = "
- INSERT INTO b_user (
- ".$arInsert[0]."
- ) VALUES (
- ".$arInsert[1]."
- )
- ";
- $DB->Query($strSql);
- $ID = $DB->LastID();
- $USER_FIELD_MANAGER->Update("USER", $ID, $arFields);
- CAccess::RecalculateForUser($ID, CUserAuthProvider::ID);
- if(is_set($arFields, "GROUP_ID"))
- static::SetUserGroup($ID, $arFields["GROUP_ID"], true);
- if(isset($arFields["PHONE_NUMBER"]) && $arFields["PHONE_NUMBER"] <> '')
- {
- Main\UserPhoneAuthTable::add(array(
- "USER_ID" => $ID,
- "PHONE_NUMBER" => $arFields["PHONE_NUMBER"],
- ));
- }
- //update digest hash for http digest authorization
- if(COption::GetOptionString('main', 'use_digest_auth', 'N') == 'Y')
- {
- static::UpdateDigest($ID, $originalPassword);
- }
- //history of passwords
- UserPasswordTable::add([
- "USER_ID" => $ID,
- "PASSWORD" => $arFields["PASSWORD"],
- "DATE_CHANGE" => new Main\Type\DateTime(),
- ]);
- if(Main\Config\Option::get("main", "user_profile_history") === "Y")
- {
- Main\UserProfileHistoryTable::addHistory($ID, Main\UserProfileHistoryTable::TYPE_ADD);
- }
- $Result = $ID;
- $arFields["ID"] = &$ID;
- $arFields["CHECKWORD"] = $checkword;
- }
- $arFields["RESULT"] = &$Result;
- foreach (GetModuleEvents("main", "OnAfterUserAdd", true) as $arEvent)
- ExecuteModuleEventEx($arEvent, array(&$arFields));
- if($ID > 0 && defined("BX_COMP_MANAGED_CACHE"))
- {
- $isRealUser = !$arFields['EXTERNAL_AUTH_ID'] || !in_array($arFields['EXTERNAL_AUTH_ID'], \Bitrix\Main\UserTable::getExternalUserTypes());
- $CACHE_MANAGER->ClearByTag("USER_CARD_".intval($ID / TAGGED_user_card_size));
- $CACHE_MANAGER->ClearByTag($isRealUser? "USER_CARD": "EXTERNAL_USER_CARD");
- $CACHE_MANAGER->ClearByTag("USER_NAME_".$ID);
- $CACHE_MANAGER->ClearByTag($isRealUser? "USER_NAME": "EXTERNAL_USER_NAME");
- }
- \Bitrix\Main\UserTable::indexRecord($ID);
- return $Result;
- }
- public static function GetDropDownList($strSqlSearch="and ACTIVE='Y'", $strSqlOrder="ORDER BY ID, NAME, LAST_NAME")
- {
- global $DB;
- $err_mess = (static::err_mess())."<br>Function: GetDropDownList<br>Line: ";
- $strSql = "
- SELECT
- ID as REFERENCE_ID,
- concat('[',ID,'] (',LOGIN,') ',ifnull(NAME,''),' ',ifnull(LAST_NAME,'')) as REFERENCE
- FROM
- b_user
- WHERE
- 1=1
- $strSqlSearch
- $strSqlOrder
- ";
- $res = $DB->Query($strSql, false, $err_mess.__LINE__);
- return $res;
- }
- public static function GetList($by = '', $order = '', $arFilter = [], $arParams = [])
- {
- /** @global CUserTypeManager $USER_FIELD_MANAGER */
- global $DB, $USER_FIELD_MANAGER;
- $err_mess = (static::err_mess())."<br>Function: GetList<br>Line: ";
- if (is_array($by))
- {
- $arOrder = $by;
- }
- else
- {
- $arOrder = [$by => $order];
- }
- static $obUserFieldsSql;
- if (!isset($obUserFieldsSql))
- {
- $obUserFieldsSql = new CUserTypeSQL;
- $obUserFieldsSql->SetEntity("USER", "U.ID");
- $obUserFieldsSql->obWhere->AddFields(array(
- "F_LAST_NAME" => array(
- "TABLE_ALIAS" => "U",
- "FIELD_NAME" => "U.LAST_NAME",
- "MULTIPLE" => "N",
- "FIELD_TYPE" => "string",
- "JOIN" => false,
- ),
- ));
- }
- if (isset($arParams["SELECT"]))
- {
- $obUserFieldsSql->SetSelect($arParams["SELECT"]);
- }
- $obUserFieldsSql->SetFilter($arFilter);
- $obUserFieldsSql->SetOrder($arOrder);
- $arFields_m = array("ID", "ACTIVE", "LAST_LOGIN", "LOGIN", "EMAIL", "NAME", "LAST_NAME", "SECOND_NAME", "TIMESTAMP_X", "PERSONAL_BIRTHDAY", "IS_ONLINE", "IS_REAL_USER");
- $arFields = array(
- "DATE_REGISTER", "PERSONAL_PROFESSION", "PERSONAL_WWW", "PERSONAL_ICQ", "PERSONAL_GENDER", "PERSONAL_PHOTO", "PERSONAL_PHONE", "PERSONAL_FAX",
- "PERSONAL_MOBILE", "PERSONAL_PAGER", "PERSONAL_STREET", "PERSONAL_MAILBOX", "PERSONAL_CITY", "PERSONAL_STATE", "PERSONAL_ZIP", "PERSONAL_COUNTRY", "PERSONAL_NOTES",
- "WORK_COMPANY", "WORK_DEPARTMENT", "WORK_POSITION", "WORK_WWW", "WORK_PHONE", "WORK_FAX", "WORK_PAGER", "WORK_STREET", "WORK_MAILBOX", "WORK_CITY", "WORK_STATE",
- "WORK_ZIP", "WORK_COUNTRY", "WORK_PROFILE", "WORK_NOTES", "ADMIN_NOTES", "XML_ID", "LAST_NAME", "SECOND_NAME", "STORED_HASH", "CHECKWORD_TIME", "EXTERNAL_AUTH_ID",
- "CONFIRM_CODE", "LOGIN_ATTEMPTS", "LAST_ACTIVITY_DATE", "AUTO_TIME_ZONE", "TIME_ZONE", "TIME_ZONE_OFFSET", "PASSWORD", "CHECKWORD", "LID", "LANGUAGE_ID", "TITLE",
- );
- $arFields_all = array_merge($arFields_m, $arFields);
- $arSelectFields = array();
- $online_interval = (array_key_exists("ONLINE_INTERVAL", $arParams) && intval($arParams["ONLINE_INTERVAL"]) > 0 ? $arParams["ONLINE_INTERVAL"] : static::GetSecondsForLimitOnline());
- if (isset($arParams['FIELDS']) && is_array($arParams['FIELDS']) && count($arParams['FIELDS']) > 0 && !in_array("*", $arParams['FIELDS']))
- {
- foreach ($arParams['FIELDS'] as $field)
- {
- $field = strtoupper($field);
- if ($field == 'TIMESTAMP_X' || $field == 'DATE_REGISTER' || $field == 'LAST_LOGIN')
- $arSelectFields[$field] = $DB->DateToCharFunction("U.".$field)." ".$field.", U.".$field." ".$field."_DATE";
- elseif ($field == 'PERSONAL_BIRTHDAY')
- $arSelectFields[$field] = $DB->DateToCharFunction("U.PERSONAL_BIRTHDAY", "SHORT")." PERSONAL_BIRTHDAY, U.PERSONAL_BIRTHDAY PERSONAL_BIRTHDAY_DATE";
- elseif ($field == 'IS_ONLINE')
- $arSelectFields[$field] = "IF(U.LAST_ACTIVITY_DATE > DATE_SUB(NOW(), INTERVAL ".$online_interval." SECOND), 'Y', 'N') IS_ONLINE";
- elseif ($field == 'IS_REAL_USER')
- $arSelectFields[$field] = "IF(U.EXTERNAL_AUTH_ID IN ('".join("', '", static::GetExternalUserTypes())."'), 'N', 'Y') IS_REAL_USER";
- elseif (in_array($field, $arFields_all))
- $arSelectFields[$field] = 'U.'.$field;
- }
- }
- if (empty($arSelectFields))
- {
- $arSelectFields[] = 'U.*';
- $arSelectFields['TIMESTAMP_X'] = $DB->DateToCharFunction("U.TIMESTAMP_X")." TIMESTAMP_X";
- $arSelectFields['IS_ONLINE'] = "IF(U.LAST_ACTIVITY_DATE > DATE_SUB(NOW(), INTERVAL ".$online_interval." SECOND), 'Y', 'N') IS_ONLINE";
- $arSelectFields['DATE_REGISTER'] = $DB->DateToCharFunction("U.DATE_REGISTER")." DATE_REGISTER";
- $arSelectFields['LAST_LOGIN'] = $DB->DateToCharFunction("U.LAST_LOGIN")." LAST_LOGIN";
- $arSelectFields['PERSONAL_BIRTHDAY'] = $DB->DateToCharFunction("U.PERSONAL_BIRTHDAY", "SHORT")." PERSONAL_BIRTHDAY";
- }
- $arSqlSearch = Array();
- $strJoin = "";
- if(is_array($arFilter))
- {
- foreach ($arFilter as $key => $val)
- {
- $key = strtoupper($key);
- if(is_array($val))
- {
- if(count($val) <= 0)
- continue;
- }
- elseif
- (
- $key != "LOGIN_EQUAL_EXACT"
- && $key != "CONFIRM_CODE"
- && $key != "!CONFIRM_CODE"
- && $key != "LAST_ACTIVITY"
- && $key != "!LAST_ACTIVITY"
- && $key != "LAST_LOGIN"
- && $key != "!LAST_LOGIN"
- && $key != "EXTERNAL_AUTH_ID"
- && $key != "!EXTERNAL_AUTH_ID"
- && $key != "IS_REAL_USER"
- )
- {
- if((string)$val == '' || $val === "NOT_REF")
- continue;
- }
- $match_value_set = array_key_exists($key."_EXACT_MATCH", $arFilter);
- switch($key)
- {
- case "ID":
- $arSqlSearch[] = GetFilterQuery("U.ID",$val,"N");
- break;
- case ">ID":
- $arSqlSearch[] = "U.ID > ".intval($val);
- break;
- case "!ID":
- $arSqlSearch[] = "U.ID <> ".intval($val);
- break;
- case "ID_EQUAL_EXACT":
- $arSqlSearch[] = "U.ID='".intval($val)."'";
- break;
- case "TIMESTAMP_1":
- $arSqlSearch[] = "U.TIMESTAMP_X >= FROM_UNIXTIME('".MkDateTime(FmtDate($val,"D.M.Y"),"d.m.Y")."')";
- break;
- case "TIMESTAMP_2":
- $arSqlSearch[] = "U.TIMESTAMP_X <= FROM_UNIXTIME('".MkDateTime(FmtDate($val,"D.M.Y")." 23:59:59","d.m.Y")."')";
- break;
- case "TIMESTAMP_X_1":
- $arSqlSearch[] = "U.TIMESTAMP_X >= FROM_UNIXTIME('".MkDateTime(FmtDate($val,"DD.MM.YYYY HH:MI:SS"),"d.m.Y H:i:s")."')";
- break;
- case "TIMESTAMP_X_2":
- $arSqlSearch[] = "U.TIMESTAMP_X <= FROM_UNIXTIME('".MkDateTime(FmtDate($val,"DD.MM.YYYY HH:MI:SS"),"d.m.Y H:i:s")."')";
- break;
- case "LAST_LOGIN_1":
- $arSqlSearch[] = "U.LAST_LOGIN >= FROM_UNIXTIME('".MkDateTime(FmtDate($val,"D.M.Y"),"d.m.Y")."')";
- break;
- case "LAST_LOGIN_2":
- $arSqlSearch[] = "U.LAST_LOGIN <= FROM_UNIXTIME('".MkDateTime(FmtDate($val,"D.M.Y")." 23:59:59","d.m.Y")."')";
- break;
- case "LAST_LOGIN":
- if ($val === false)
- $arSqlSearch[] = "U.LAST_LOGIN IS NULL";
- break;
- case "!LAST_LOGIN":
- if ($val === false)
- $arSqlSearch[] = "U.LAST_LOGIN IS NOT NULL";
- break;
- case "DATE_REGISTER_1":
- $arSqlSearch[] = "U.DATE_REGISTER >= FROM_UNIXTIME('".MkDateTime(FmtDate($val,"D.M.Y"),"d.m.Y")."')";
- break;
- case "DATE_REGISTER_2":
- $arSqlSearch[] = "U.DATE_REGISTER <= FROM_UNIXTIME('".MkDateTime(FmtDate($val,"D.M.Y")." 23:59:59","d.m.Y")."')";
- break;
- case "ACTIVE":
- $arSqlSearch[] = ($val=="Y") ? "U.ACTIVE='Y'" : "U.ACTIVE='N'";
- break;
- case "LOGIN_EQUAL":
- $arSqlSearch[] = GetFilterQuery("U.LOGIN", $val, "N");
- break;
- case "LOGIN":
- $arSqlSearch[] = GetFilterQuery("U.LOGIN", $val);
- break;
- case "EXTERNAL_AUTH_ID":
- if($val <> '')
- $arSqlSearch[] = "U.EXTERNAL_AUTH_ID='".$DB->ForSQL($val, 255)."'";
- else
- $arSqlSearch[] = "(U.EXTERNAL_AUTH_ID IS NULL OR U.EXTERNAL_AUTH_ID='')";
- break;
- case "!EXTERNAL_AUTH_ID":
- if (
- is_array($val)
- && count($val) > 0
- )
- {
- $strTmp = "";
- foreach($val as $authId)
- {
- if ($authId <> '')
- {
- $strTmp .= ($strTmp <> '' ? "," : "")."'".$DB->ForSQL($authId, 255)."'";
- }
- }
- if ($strTmp <> '')
- {
- $arSqlSearch[] = "U.EXTERNAL_AUTH_ID NOT IN (".$strTmp.") OR U.EXTERNAL_AUTH_ID IS NULL";
- }
- }
- elseif (!is_array($val))
- {
- if($val <> '')
- $arSqlSearch[] = "U.EXTERNAL_AUTH_ID <> '".$DB->ForSql($val, 255)."' OR U.EXTERNAL_AUTH_ID IS NULL";
- else
- $arSqlSearch[] = "(U.EXTERNAL_AUTH_ID IS NOT NULL AND LENGTH(U.EXTERNAL_AUTH_ID) > 0)";
- }
- break;
- case "LOGIN_EQUAL_EXACT":
- $arSqlSearch[] = "U.LOGIN='".$DB->ForSql($val)."'";
- break;
- case "XML_ID":
- $arSqlSearch[] = "U.XML_ID='".$DB->ForSql($val)."'";
- break;
- case "CONFIRM_CODE":
- if($val <> '')
- $arSqlSearch[] = "U.CONFIRM_CODE='".$DB->ForSql($val)."'";
- else
- $arSqlSearch[] = "(U.CONFIRM_CODE IS NULL OR LENGTH(U.CONFIRM_CODE) <= 0)";
- break;
- case "!CONFIRM_CODE":
- if($val <> '')
- $arSqlSearch[] = "U.CONFIRM_CODE <> '".$DB->ForSql($val)."'";
- else
- $arSqlSearch[] = "(U.CONFIRM_CODE IS NOT NULL AND LENGTH(U.CONFIRM_CODE) > 0)";
- break;
- case "COUNTRY_ID":
- case "WORK_COUNTRY":
- $arSqlSearch[] = "U.WORK_COUNTRY=".intval($val);
- break;
- case "PERSONAL_COUNTRY":
- $arSqlSearch[] = "U.PERSONAL_COUNTRY=".intval($val);
- break;
- case "NAME":
- $arSqlSearch[] = GetFilterQuery("U.NAME, U.LAST_NAME, U.SECOND_NAME", $val);
- break;
- case "NAME_SEARCH":
- $arSqlSearch[] = GetFilterQuery("U.NAME, U.LAST_NAME, U.SECOND_NAME, U.EMAIL, U.LOGIN", $val);
- break;
- case "EMAIL":
- $arSqlSearch[] = GetFilterQuery("U.EMAIL", $val, "Y", array("@","_",".","-"));
- break;
- case "=EMAIL":
- $arSqlSearch[] = "U.EMAIL = '".$DB->ForSQL(trim($val))."'";
- break;
- case "GROUP_MULTI":
- case "GROUPS_ID":
- if(is_numeric($val) && intval($val)>0)
- $val = array($val);
- if(is_array($val) && count($val)>0)
- {
- $ar = array();
- foreach($val as $id)
- $ar[intval($id)] = intval($id);
- $strJoin .=
- " INNER JOIN (SELECT DISTINCT UG.USER_ID FROM b_user_group UG
- WHERE UG.GROUP_ID in (".implode(",", $ar).")
- and (UG.DATE_ACTIVE_FROM is null or UG.DATE_ACTIVE_FROM <= ".$DB->CurrentTimeFunction().")
- and (UG.DATE_ACTIVE_TO is null or UG.DATE_ACTIVE_TO >= ".$DB->CurrentTimeFunction().")
- ) UG ON UG.USER_ID=U.ID ";
- }
- break;
- case "PERSONAL_BIRTHDATE_1":
- $arSqlSearch[] = "U.PERSONAL_BIRTHDATE>=".$DB->CharToDateFunction($val);
- break;
- case "PERSONAL_BIRTHDATE_2":
- $arSqlSearch[] = "U.PERSONAL_BIRTHDATE<=".$DB->CharToDateFunction($val." 23:59:59");
- break;
- case "PERSONAL_BIRTHDAY_1":
- $arSqlSearch[] = "U.PERSONAL_BIRTHDAY>=".$DB->CharToDateFunction($DB->ForSql($val), "SHORT");
- break;
- case "PERSONAL_BIRTHDAY_2":
- $arSqlSearch[] = "U.PERSONAL_BIRTHDAY<=".$DB->CharToDateFunction($DB->ForSql($val), "SHORT");
- break;
- case "PERSONAL_BIRTHDAY_DATE":
- $arSqlSearch[] = "DATE_FORMAT(U.PERSONAL_BIRTHDAY, '%m-%d') = '".$DB->ForSql($val)."'";
- break;
- case "KEYWORDS":
- $arSqlSearch[] = GetFilterQuery(implode(",",$arFields), $val);
- break;
- case "CHECK_SUBORDINATE":
- if(is_array($val))
- {
- $strSubord = "0";
- foreach($val as $grp)
- $strSubord .= ",".intval($grp);
- if(intval($arFilter["CHECK_SUBORDINATE_AND_OWN"]) > 0)
- $arSqlSearch[] = "(U.ID=".intval($arFilter["CHECK_SUBORDINATE_AND_OWN"])." OR NOT EXISTS(SELECT 'x' FROM b_user_group UGS WHERE UGS.USER_ID=U.ID AND UGS.GROUP_ID NOT IN (".$strSubord.")))";
- else
- $arSqlSearch[] = "NOT EXISTS(SELECT 'x' FROM b_user_group UGS WHERE UGS.USER_ID=U.ID AND UGS.GROUP_ID NOT IN (".$strSubord."))";
- }
- break;
- case "NOT_ADMIN":
- if($val !== true)
- break;
- $arSqlSearch[] = "not exists (SELECT * FROM b_user_group UGNA WHERE UGNA.USER_ID=U.ID AND UGNA.GROUP_ID = 1)";
- break;
- case "LAST_ACTIVITY":
- if ($val === false)
- $arSqlSearch[] = "U.LAST_ACTIVITY_DATE IS NULL";
- elseif (intval($val)>0)
- $arSqlSearch[] = "U.LAST_ACTIVITY_DATE > DATE_SUB(NOW(), INTERVAL ".intval($val)." SECOND)";
- break;
- case "!LAST_ACTIVITY":
- if ($val === false)
- $arSqlSearch[] = "U.LAST_ACTIVITY_DATE IS NOT NULL";
- break;
- case "INTRANET_USERS":
- $arSqlSearch[] = "U.ACTIVE = 'Y' AND U.LAST_LOGIN IS NOT NULL AND EXISTS(SELECT 'x' FROM b_utm_user UF1, b_user_field F1 WHERE F1.ENTITY_ID = 'USER' AND F1.FIELD_NAME = 'UF_DEPARTMENT' AND UF1.FIELD_ID = F1.ID AND UF1.VALUE_ID = U.ID AND UF1.VALUE_INT IS NOT NULL AND UF1.VALUE_INT <> 0)";
- break;
- case "IS_REAL_USER":
- if($val === true || $val === 'Y')
- {
- $arSqlSearch[] = "U.EXTERNAL_AUTH_ID NOT IN ('".join("', '", static::GetExternalUserTypes())."') OR U.EXTERNAL_AUTH_ID IS NULL";
- }
- else
- {
- $arSqlSearch[] = "U.EXTERNAL_AUTH_ID IN ('".join("', '", static::GetExternalUserTypes())."')";
- }
- break;
- default:
- if(in_array($key, $arFields))
- $arSqlSearch[] = GetFilterQuery('U.'.$key, $val, ($arFilter[$key."_EXACT_MATCH"]=="Y" && $match_value_set? "N" : "Y"));
- }
- }
- }
- $arSqlOrder = array();
- foreach ($arOrder as $field => $dir)
- {
- $field = strtoupper($field);
- if(strtolower($dir) != "asc")
- {
- $dir = "desc";
- }
- if($field == "CURRENT_BIRTHDAY")
- {
- $cur_year = intval(date('Y'));
- $arSqlOrder[$field] = "IF(ISNULL(U.PERSONAL_BIRTHDAY), '9999-99-99', IF (
- DATE_FORMAT(U.PERSONAL_BIRTHDAY, '".$cur_year."-%m-%d') < DATE_FORMAT(DATE_ADD(".$DB->CurrentTimeFunction().", INTERVAL ".CTimeZone::GetOffset()." SECOND), '%Y-%m-%d'),
- DATE_FORMAT(U.PERSONAL_BIRTHDAY, '".($cur_year + 1)."-%m-%d'),
- DATE_FORMAT(U.PERSONAL_BIRTHDAY, '".$cur_year."-%m-%d')
- )) ".$dir;
- }
- elseif($field == "IS_ONLINE")
- {
- $arSelectFields[$field] = "IF(U.LAST_ACTIVITY_DATE > DATE_SUB(NOW(), INTERVAL ".$online_interval." SECOND), 'Y', 'N') IS_ONLINE";
- $arSqlOrder[$field] = "IS_ONLINE ".$dir;
- }
- elseif(in_array($field,$arFields_all))
- {
- $arSqlOrder[$field] = "U.".$field." ".$dir;
- }
- elseif($s = $obUserFieldsSql->GetOrder($field))
- {
- $arSqlOrder[$field] = strtoupper($s)." ".$dir;
- }
- elseif(preg_match('/^RATING_(\d+)$/i', $field, $matches))
- {
- $ratingId = intval($matches[1]);
- if ($ratingId > 0)
- {
- $arSqlOrder[$field] = $field."_ISNULL ASC, ".$field." ".$dir;
- $arParams['SELECT'][] = $field;
- }
- else
- {
- $field = "TIMESTAMP_X";
- $arSqlOrder[$field] = "U.".$field." ".$dir;
- }
- }
- elseif ($field == 'FULL_NAME')
- {
- $arSqlOrder[$field] = sprintf(
- "IF(U.LAST_NAME IS NULL OR U.LAST_NAME = '', 1, 0) %1\$s,
- IF(U.LAST_NAME IS NULL OR U.LAST_NAME = '', 1, U.LAST_NAME) %1\$s,
- IF(U.NAME IS NULL OR U.NAME = '', 1, 0) %1\$s,
- IF(U.NAME IS NULL OR U.NAME = '', 1, U.NAME) %1\$s,
- IF(U.SECOND_NAME IS NULL OR U.SECOND_NAME = '', 1, 0) %1\$s,
- IF(U.SECOND_NAME IS NULL OR U.SECOND_NAME = '', 1, U.SECOND_NAME) %1\$s,
- U.LOGIN %1\$s", $dir
- );
- }
- }
- $userFieldsSelect = $obUserFieldsSql->GetSelect();
- $arSqlSearch[] = $obUserFieldsSql->GetFilter();
- $strSqlSearch = GetFilterSqlSearch($arSqlSearch);
- $sSelect = ($obUserFieldsSql->GetDistinct()? "DISTINCT " : "")
- .implode(', ',$arSelectFields)."
- ".$userFieldsSelect."
- ";
- if (isset($arParams['SELECT']) && is_array($arParams['SELECT']))
- {
- $arRatingInSelect = array();
- foreach ($arParams['SELECT'] as $column)
- {
- if(preg_match('/^RATING_(\d+)$/i', $column, $matches))
- {
- $ratingId = intval($matches[1]);
- if ($ratingId > 0 && !in_array($ratingId, $arRatingInSelect))
- {
- $sSelect .= ", RR".$ratingId.".CURRENT_POSITION IS NULL as RATING_".$ratingId."_ISNULL";
- $sSelect .= ", RR".$ratingId.".CURRENT_VALUE as RATING_".$ratingId;
- $sSelect .= ", RR".$ratingId.".CURRENT_VALUE as RATING_".$ratingId."_CURRENT_VALUE";
- $sSelect .= ", RR".$ratingId.".PREVIOUS_VALUE as RATING_".$ratingId."_PREVIOUS_VALUE";
- $sSelect .= ", RR".$ratingId.".CURRENT_POSITION as RATING_".$ratingId."_CURRENT_POSITION";
- $sSelect .= ", RR".$ratingId.".PREVIOUS_POSITION as RATING_".$ratingId."_PREVIOUS_POSITION";
- $strJoin .= " LEFT JOIN b_rating_results RR".$ratingId."
- ON RR".$ratingId.".RATING_ID=".$ratingId."
- and RR".$ratingId.".ENTITY_TYPE_ID = 'USER'
- and RR".$ratingId.".ENTITY_ID = U.ID ";
- $arRatingInSelect[] = $ratingId;
- }
- }
- }
- }
- $strFrom = "
- FROM
- b_user U
- ".$obUserFieldsSql->GetJoin("U.ID")."
- ".$strJoin."
- WHERE
- ".$strSqlSearch."
- ";
- $strSqlOrder = '';
- if (!empty($arSqlOrder))
- $strSqlOrder = 'ORDER BY '.implode(', ', $arSqlOrder);
- $strSql = "SELECT ".$sSelect.$strFrom.$strSqlOrder;
- if(array_key_exists("NAV_PARAMS", $arParams) && is_array($arParams["NAV_PARAMS"]))
- {
- $nTopCount = intval($arParams['NAV_PARAMS']['nTopCount']);
- if($nTopCount > 0)
- {
- $strSql = $DB->TopSql($strSql, $nTopCount);
- $res = $DB->Query($strSql, false, $err_mess.__LINE__);
- if($userFieldsSelect <> '')
- $res->SetUserFields($USER_FIELD_MANAGER->GetUserFields("USER"));
- }
- else
- {
- $res_cnt = $DB->Query("SELECT COUNT(".($obUserFieldsSql->GetDistinct()? "DISTINCT ":"")."U.ID) as C ".$strFrom);
- $res_cnt = $res_cnt->Fetch();
- $res = new CDBResult();
- if($userFieldsSelect <> '')
- $res->SetUserFields($USER_FIELD_MANAGER->GetUserFields("USER"));
- $res->NavQuery($strSql, $res_cnt["C"], $arParams["NAV_PARAMS"]);
- }
- }
- else
- {
- $res = $DB->Query($strSql, false, $err_mess.__LINE__);
- if($userFieldsSelect <> '')
- $res->SetUserFields($USER_FIELD_MANAGER->GetUserFields("USER"));
- }
- $res->is_filtered = IsFiltered($strSqlSearch);
- return $res;
- }
- public static function IsOnLine($id, $interval = null)
- {
- global $DB;
- $id = intval($id);
- if ($id <= 0)
- {
- return false;
- }
- if (is_null($interval))
- {
- $interval = static::GetSecondsForLimitOnline();
- }
- else
- {
- $interval = intval($interval);
- if ($interval <= 0)
- {
- $interval = static::GetSecondsForLimitOnline();
- }
- }
- $dbRes = $DB->Query("SELECT 'x' FROM b_user WHERE ID = ".$id." AND LAST_ACTIVITY_DATE > DATE_SUB(NOW(), INTERVAL ".$interval." SECOND)");
- return $arRes = $dbRes->Fetch()? true: false;
- }
- public function GetUserGroupArray()
- {
- $groups = $this->GetParam("GROUPS");
- if(!is_array($groups) || empty($groups))
- {
- return [2];
- }
- //always unique and sorted, containing group ID=2
- return $groups;
- }
- public function SetUserGroupArray($arr)
- {
- $arr = array_map("intval", $arr);
- $arr = array_filter($arr);
- $arr[] = 2;
- $arr = array_values(array_unique($arr));
- sort($arr);
- $this->SetParam("GROUPS", $arr);
- }
- public function GetUserGroupString()
- {
- return $this->GetGroups();
- }
- public function GetGroups()
- {
- return implode(",", $this->GetUserGroupArray());
- }
- public function RequiredHTTPAuthBasic($Realm = "Bitrix")
- {
- header("WWW-Authenticate: Basic realm=\"{$Realm}\"");
- if(stristr(php_sapi_name(), "cgi") !== false)
- header("Status: 401 Unauthorized");
- else
- header($_SERVER["SERVER_PROTOCOL"]." 401 Unauthorized");
- return false;
- }
- public function LoginByCookies()
- {
- global $USER;
- if(COption::GetOptionString("main", "store_password", "Y") == "Y")
- {
- $bLogout = isset($_REQUEST["logout"]) && (strtolower($_REQUEST["logout"]) == "yes");
- $cookie_prefix = COption::GetOptionString('main', 'cookie_name', 'BITRIX_SM');
- $cookie_login = strval($_COOKIE[$cookie_prefix.'_UIDL']);
- if($cookie_login == '')
- {
- //compatibility reasons
- $cookie_login = strval($_COOKIE[$cookie_prefix.'_LOGIN']);
- }
- $cookie_md5pass = strval($_COOKIE[$cookie_prefix.'_UIDH']);
- if($cookie_login <> '' && $cookie_md5pass <> '' && !$bLogout)
- {
- if(static::$kernelSession["SESS_PWD_HASH_TESTED"] !== md5($cookie_login."|".$cookie_md5pass))
- {
- $USER->LoginByHash($cookie_login, $cookie_md5pass);
- static::$kernelSession["SESS_PWD_HASH_TESTED"] = md5($cookie_login."|".$cookie_md5pass);
- }
- }
- }
- }
- public function LoginByHash($login, $hash)
- {
- /** @global CMain $APPLICATION */
- global $DB, $APPLICATION;
- $result_message = true;
- $user_id = 0;
- $arParams = array(
- "LOGIN" => $login,
- "HASH" => $hash,
- );
- $APPLICATION->ResetException();
- $bOk = true;
- foreach(GetModuleEvents("main", "OnBeforeUserLoginByHash", true) as $arEvent)
- {
- if(ExecuteModuleEventEx($arEvent, array(&$arParams))===false)
- {
- if($err = $APPLICATION->GetException())
- $result_message = array("MESSAGE"=>$err->GetString()."<br>", "TYPE"=>"ERROR");
- else
- {
- $APPLICATION->ThrowException("Unknown error");
- $result_message = array("MESSAGE"=>"Unknown error"."<br>", "TYPE"=>"ERROR");
- }
- $bOk = false;
- break;
- }
- }
- if($bOk && $arParams['HASH'] <> '')
- {
- $strSql =
- "SELECT U.ID, U.ACTIVE, U.STORED_HASH, U.EXTERNAL_AUTH_ID ".
- "FROM b_user U ".
- "WHERE U.LOGIN='".$DB->ForSQL($arParams['LOGIN'], 50)."' ";
- $result = $DB->Query($strSql, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
- $bFound = false;
- $bHashFound = false;
- while(($arUser = $result->Fetch()))
- {
- $bFound = true;
- //there is no stored auth for external authorization, but domain spread auth should work
- $bExternal = ($arUser["EXTERNAL_AUTH_ID"] <> '');
- $bAllowExternalSave = COption::GetOptionString("main", "allow_external_auth_stored_hash", "N") == "Y";
- if(
- // if old method (STORED_HASH <> '') and exact match
- ($arUser["STORED_HASH"] <> '' && $arUser["STORED_HASH"] == $arParams['HASH'])
- || // or new method
- (static::CheckStoredHash($arUser["ID"], $arParams['HASH'], ($bExternal) && (!$bAllowExternalSave)))
- )
- {
- $bHashFound = true;
- if($arUser["ACTIVE"] == "Y")
- {
- $user_id = $arUser["ID"];
- $this->SetParam("SESSION_HASH", $arParams['HASH']);
- $this->bLoginByHash = true;
- $this->Authorize($arUser["ID"], (!$bExternal) || ($bAllowExternalSave));
- }
- else
- {
- $APPLICATION->ThrowException(GetMessage("LOGIN_BLOCK"));
- $result_message = array("MESSAGE"=>GetMessage("LOGIN_BLOCK")."<br>", "TYPE"=>"ERROR");
- }
- break;
- }
- else
- {
- //Delete invalid stored auth cookie
- $spread = (COption::GetOptionString("main", "auth_multisite", "N") == "Y"? (Main\Web\Cookie::SPREAD_SITES | Main\Web\Cookie::SPREAD_DOMAIN) : Main\Web\Cookie::SPREAD_DOMAIN);
- $cookie = new Main\Web\Cookie("UIDH", "", 0);
- $cookie->setSpread($spread);
- $cookie->setHttpOnly(true);
- Main\Context::getCurrent()->getResponse()->addCookie($cookie);
- }
- }
- if(!$bFound)
- {
- $APPLICATION->ThrowException(GetMessage("WRONG_LOGIN"));
- $result_message = array("MESSAGE"=>GetMessage("WRONG_LOGIN")."<br>", "TYPE"=>"ERROR");
- }
- elseif(!$bHashFound)
- {
- $APPLICATION->ThrowException(GetMessage("USER_WRONG_HASH"));
- $result_message = array("MESSAGE"=>GetMessage("USER_WRONG_HASH")."<br>", "TYPE"=>"ERROR");
- }
- }
- $arParams["USER_ID"] = $user_id;
- $arParams["RESULT_MESSAGE"] = $result_message;
- foreach (GetModuleEvents("main", "OnAfterUserLoginByHash", true) as $arEvent)
- ExecuteModuleEventEx($arEvent, array(&$arParams));
- if(($result_message !== true) && (COption::GetOptionString("main", "event_log_login_fail", "N") === "Y"))
- CEventLog::Log("SECURITY", "USER_LOGINBYHASH", "main", $login, $result_message["MESSAGE"]);
- return $arParams["RESULT_MESSAGE"];
- }
- public function LoginByHttpAuth()
- {
- $arAuth = CHTTP::ParseAuthRequest();
- foreach(GetModuleEvents("main", "onBeforeUserLoginByHttpAuth", true) as $arEvent)
- {
- $res = ExecuteModuleEventEx($arEvent, array(&$arAuth));
- if($res !== null)
- {
- return $res;
- }
- }
- if(isset($arAuth["basic"]) && $arAuth["basic"]["username"] <> '' && $arAuth["basic"]["password"] <> '')
- {
- // Authorize user, if it is http basic authorization, with no remembering
- if(!$this->IsAuthorized() || $this->GetLogin() <> $arAuth["basic"]["username"])
- {
- return $this->Login($arAuth["basic"]["username"], $arAuth["basic"]["password"], "N");
- }
- }
- elseif(isset($arAuth["digest"]) && $arAuth["digest"]["username"] <> '' && COption::GetOptionString('main', 'use_digest_auth', 'N') == 'Y')
- {
- // Authorize user by http digest authorization
- if(!$this->IsAuthorized() || $this->GetLogin() <> $arAuth["digest"]["username"])
- {
- return $this->LoginByDigest($arAuth["digest"]);
- }
- }
- return null;
- }
- public function LoginByDigest($arDigest)
- {
- //array("username"=>"", "nonce"=>"", "uri"=>"", "response"=>"")
- /** @global CMain $APPLICATION */
- global $DB, $APPLICATION;
- $APPLICATION->ResetException();
- $strSql =
- "SELECT U.ID, U.PASSWORD, UD.DIGEST_HA1, U.EXTERNAL_AUTH_ID ".
- "FROM b_user U LEFT JOIN b_user_digest UD ON UD.USER_ID=U.ID ".
- "WHERE U.LOGIN='".$DB->ForSQL($arDigest["username"])."' ";
- $res = $DB->Query($strSql);
- if($arUser = $res->Fetch())
- {
- $method = (isset($_SERVER['REDIRECT_REQUEST_METHOD']) ? $_SERVER['REDIRECT_REQUEST_METHOD'] : $_SERVER['REQUEST_METHOD']);
- $HA2 = md5($method.':'.$arDigest['uri']);
- if($arUser["EXTERNAL_AUTH_ID"] == '' && $arUser["DIGEST_HA1"] <> '')
- {
- //digest is for internal authentication only
- static::$kernelSession["BX_HTTP_DIGEST_ABSENT"] = false;
- $HA1 = $arUser["DIGEST_HA1"];
- $valid_response = md5($HA1.':'.$arDigest['nonce'].':'.$HA2);
- if($arDigest["response"] === $valid_response)
- {
- //regular user password
- return $this->Login($arDigest["username"], $arUser["PASSWORD"], "N", "N");
- }
- }
- //check for an application password, including external users
- if(($appPassword = ApplicationPasswordTable::findDigestPassword($arUser["ID"], $arDigest)) !== false)
- {
- return $this->Login($arDigest["username"], $appPassword["PASSWORD"], "N", "N");
- }
- if($arUser["DIGEST_HA1"] == '')
- {
- //this indicates that we still have no user digest hash
- static::$kernelSession["BX_HTTP_DIGEST_ABSENT"] = true;
- }
- }
- $APPLICATION->ThrowException(GetMessage("USER_AUTH_DIGEST_ERR"));
- return array("MESSAGE"=>GetMessage("USER_AUTH_DIGEST_ERR")."<br>", "TYPE"=>"ERROR");
- }
- public static function UpdateDigest($ID, $pass)
- {
- global $DB;
- $ID = intval($ID);
- $res = $DB->Query("
- SELECT U.LOGIN, UD.DIGEST_HA1
- FROM b_user U LEFT JOIN b_user_digest UD on UD.USER_ID=U.ID
- WHERE U.ID=".$ID
- );
- if($arRes = $res->Fetch())
- {
- if(defined('BX_HTTP_AUTH_REALM'))
- $realm = BX_HTTP_AUTH_REALM;
- else
- $realm = "Bitrix Site Manager";
- $digest = md5($arRes["LOGIN"].':'.$realm.':'.$pass);
- if($arRes["DIGEST_HA1"] == '')
- {
- //new digest
- $DB->Query("insert into b_user_digest (user_id, digest_ha1) values('".$ID."', '".$DB->ForSQL($digest)."')");
- }
- else
- {
- //update digest (login, password or realm were changed)
- if($arRes["DIGEST_HA1"] !== $digest)
- $DB->Query("update b_user_digest set digest_ha1='".$DB->ForSQL($digest)."' where user_id=".$ID);
- }
- }
- }
- public function LoginHitByHash($hash, $closeSession = true, $delete = false, $remember = false)
- {
- global $APPLICATION;
- $hash = trim($hash);
- if ($hash == '')
- {
- return false;
- }
- $APPLICATION->ResetException();
- $connection = Main\Application::getConnection();
- $helper = $connection->getSqlHelper();
- // todo: here should be concat(replace(UH.URL, '\\', '\\\\'), '%')
- $strSql =
- "SELECT UH.ID, UH.USER_ID, UH.HASH, UH.VALID_UNTIL "
- . "FROM b_user_hit_auth UH "
- . "INNER JOIN b_user U ON U.ID = UH.USER_ID AND U.ACTIVE = 'Y' AND U.BLOCKED <> 'Y' "
- . "WHERE UH.HASH = '" . $helper->forSql($hash, 32) . "' "
- . " AND '" . $helper->forSql($APPLICATION->GetCurPageParam("", [], true), 255) . "' LIKE " . $helper->getConcatFunction("UH.URL", "'%'");
- if (!defined("ADMIN_SECTION") || ADMIN_SECTION !== true)
- {
- $strSql .= " AND UH.SITE_ID = '" . $helper->forSql(SITE_ID) . "'";
- }
- $result = $connection->query($strSql);
- if($hashData = $result->fetch())
- {
- // case sensitive
- if ($hashData['HASH'] === $hash)
- {
- $doAuthorize = true;
- if ($hashData['VALID_UNTIL'] instanceof Main\Type\DateTime)
- {
- if ((new Main\Type\DateTime())->getTimestamp() > $hashData['VALID_UNTIL']->getTimestamp())
- {
- $doAuthorize = false;
- }
- }
- if ($doAuthorize)
- {
- setSessionExpired($closeSession);
- $this->Authorize($hashData["USER_ID"], $remember);
- if (!$delete)
- {
- $connection->query("UPDATE b_user_hit_auth SET TIMESTAMP_X = " . $helper->getCurrentDateTimeFunction() . " WHERE ID = ".$hashData["ID"]);
- }
- }
- if ($delete || !$doAuthorize)
- {
- $connection->query("DELETE FROM b_user_hit_auth WHERE ID = ".$hashData["ID"]);
- }
- return $doAuthorize;
- }
- }
- return false;
- }
- public static function AddHitAuthHash($url, $user_id = false, $site_id = false, $ttl = null)
- {
- global $USER, $DB;
- if ($url == '')
- {
- return false;
- }
- if (!$user_id)
- {
- $user_id = $USER->GetID();
- }
- if (!$site_id && (!defined("ADMIN_SECTION") || ADMIN_SECTION !== true))
- {
- $site_id = SITE_ID;
- }
- $hash = false;
- if ($user_id)
- {
- $hash = Main\Security\Random::getString(32, true);
- $arFields = array(
- 'USER_ID' => $user_id,
- 'URL' => trim($url),
- 'HASH' => $hash,
- 'SITE_ID' => trim($site_id),
- '~TIMESTAMP_X' => $DB->CurrentTimeFunction(),
- );
- if ($ttl > 0)
- {
- $arFields['~VALID_UNTIL'] = Main\Application::getConnection()->getSqlHelper()->addSecondsToDateTime((int)$ttl);
- }
- $DB->Add("b_user_hit_auth", $arFields);
- }
- return $hash;
- }
- public static function GetHitAuthHash($url_mask, $userID = false, $siteId = null)
- {
- global $USER;
- $url_mask = trim($url_mask);
- if ($url_mask == '')
- {
- return false;
- }
- if (!$userID)
- {
- $userID = $USER->GetID();
- }
- if ($userID <= 0)
- {
- return false;
- }
- $connection = Main\Application::getConnection();
- $helper = $connection->getSqlHelper();
- $strSql = "
- SELECT ID, HASH, VALID_UNTIL
- FROM b_user_hit_auth
- WHERE URL = '{$helper->forSql($url_mask, 255)}'
- AND USER_ID = " . (int)$userID
- ;
- if ($siteId !== null)
- {
- $strSql .= " AND SITE_ID = '{$helper->ForSql($siteId)}'";
- }
- $result = $connection->query($strSql);
- if($hashData = $result->fetch())
- {
- if ($hashData['VALID_UNTIL'] instanceof Main\Type\DateTime)
- {
- if ((new Main\Type\DateTime())->getTimestamp() > $hashData['VALID_UNTIL']->getTimestamp())
- {
- $connection->query("DELETE FROM b_user_hit_auth WHERE ID = " . $hashData['ID']);
- return false;
- }
- }
- return $hashData["HASH"];
- }
- return false;
- }
- public static function CleanUpHitAuthAgent()
- {
- global $DB;
- $cleanup_days = COption::GetOptionInt("main", "hit_auth_cleanup_days", 30);
- if($cleanup_days > 0)
- {
- $arDate = localtime(time());
- $date = mktime(0, 0, 0, $arDate[4]+1, $arDate[3]-$cleanup_days, 1900+$arDate[5]);
- $DB->Query("DELETE FROM b_user_hit_auth WHERE TIMESTAMP_X <= ".$DB->CharToDateFunction(ConvertTimeStamp($date, "FULL")));
- }
- return "CUser::CleanUpHitAuthAgent();";
- }
- protected function UpdateSessionData($id, $applicationId = null, $onlyActive = true)
- {
- global $DB, $APPLICATION;
- unset(static::$kernelSession["SESS_OPERATIONS"]);
- unset(static::$kernelSession["MODULE_PERMISSIONS"]);
- $APPLICATION->SetNeedCAPTHA(false);
- $strSql =
- "SELECT U.* ".
- "FROM b_user U ".
- "WHERE U.ID='".intval($id)."' ";
- if ($onlyActive)
- {
- $strSql .= " AND U.ACTIVE = 'Y' AND U.BLOCKED <> 'Y' ";
- }
- $result = $DB->Query($strSql);
- if($arUser = $result->Fetch())
- {
- $data = [
- "AUTHORIZED" => "Y",
- "USER_ID" => $arUser["ID"],
- "LOGIN" => $arUser["LOGIN"],
- "EMAIL" => $arUser["EMAIL"],
- "TITLE" => $arUser["TITLE"],
- "NAME" => $arUser["NAME"].($arUser["NAME"] == '' || $arUser["LAST_NAME"] == ''? "":" ").$arUser["LAST_NAME"],
- "FIRST_NAME" => $arUser["NAME"],
- "SECOND_NAME" => $arUser["SECOND_NAME"],
- "LAST_NAME" => $arUser["LAST_NAME"],
- "PERSONAL_PHOTO" => $arUser["PERSONAL_PHOTO"],
- "PERSONAL_GENDER" => $arUser["PERSONAL_GENDER"],
- "PERSONAL_WWW" => $arUser["PERSONAL_WWW"],
- "EXTERNAL_AUTH_ID" => $arUser["EXTERNAL_AUTH_ID"],
- "XML_ID" => $arUser["XML_ID"],
- "ADMIN" => false,
- "POLICY" => static::getPolicy($arUser["ID"])->getValues(),
- "AUTO_TIME_ZONE" => trim($arUser["AUTO_TIME_ZONE"]),
- "TIME_ZONE" => $arUser["TIME_ZONE"],
- "TIME_ZONE_OFFSET" => $arUser["TIME_ZONE_OFFSET"],
- "APPLICATION_ID" => $applicationId,
- "BX_USER_ID" => $arUser["BX_USER_ID"],
- "GROUPS" => Main\UserTable::getUserGroupIds($arUser["ID"]),
- "SESSION_HASH" => $this->GetParam("SESSION_HASH"),
- "LANGUAGE_ID" => $arUser["LANGUAGE_ID"],
- ];
- foreach ($data["GROUPS"] as $groupId)
- {
- if ($groupId == 1)
- {
- $data["ADMIN"] = true;
- break;
- }
- }
- static::$kernelSession["SESS_AUTH"] = $data;
- return $arUser;
- }
- return false;
- }
- /**
- * Performs the user authorization:
- * fills session parameters;
- * remembers auth;
- * spreads auth through sites.
- * @param int $id An user ID.
- * @param bool $bSave Save authorization in cookies.
- * @param bool $bUpdate Update last login information in DB.
- * @param string|null $applicationId An application password ID.
- * @return bool
- */
- public function Authorize($id, $bSave = false, $bUpdate = true, $applicationId = null, $onlyActive = true)
- {
- global $DB;
- $arUser = $this->UpdateSessionData($id, $applicationId, $onlyActive);
- if($arUser !== false)
- {
- $regenerateIdAfterLogin = Main\Config\Configuration::getInstance()->get('session')['regenerateIdAfterLogin'] ?? false;
- if ($regenerateIdAfterLogin === true)
- {
- Main\Application::getInstance()->getCompositeSessionManager()->regenerateId();
- }
- self::$CURRENT_USER = false;
- $this->justAuthorized = true;
- $this->SetControllerAdmin(false);
- //sometimes we don't need to update db (REST)
- if($bUpdate)
- {
- $tz = '';
- if(CTimeZone::Enabled())
- {
- if(!CTimeZone::IsAutoTimeZone(trim($arUser["AUTO_TIME_ZONE"])) || CTimeZone::GetCookieValue() !== null)
- {
- $offset = CTimeZone::GetOffset();
- $tz = ', TIME_ZONE_OFFSET = '.$offset;
- $this->SetParam("TIME_ZONE_OFFSET", $offset);
- }
- }
- $bxUid = '';
- if (!empty($_COOKIE['BX_USER_ID']) && preg_match('/^[0-9a-f]{32}$/', $_COOKIE['BX_USER_ID']))
- {
- if ($_COOKIE['BX_USER_ID'] != $arUser['BX_USER_ID'])
- {
- // save new bxuid value
- $bxUid = ", BX_USER_ID = '".$_COOKIE['BX_USER_ID']."'";
- $arUser['BX_USER_ID'] = $_COOKIE['BX_USER_ID'];
- $this->SetParam("BX_USER_ID", $_COOKIE['BX_USER_ID']);
- }
- }
- $languageId = '';
- if ($arUser['LANGUAGE_ID'] === '')
- {
- $arUser['LANGUAGE_ID'] = LANGUAGE_ID;
- $this->SetParam("LANGUAGE_ID", LANGUAGE_ID);
- $languageId = ", LANGUAGE_ID='".$DB->ForSql(LANGUAGE_ID)."'";
- }
- $DB->Query("
- UPDATE b_user SET
- STORED_HASH = NULL,
- LAST_LOGIN = ".$DB->GetNowFunction().",
- TIMESTAMP_X = TIMESTAMP_X,
- LOGIN_ATTEMPTS = 0
- ".$tz."
- ".$bxUid."
- ".$languageId."
- WHERE
- ID=".$arUser["ID"]
- );
- if ($bSave || COption::GetOptionString("main", "auth_multisite", "N") == "Y")
- {
- $response = Main\Context::getCurrent()->getResponse();
- $hash = $this->GetSessionHash();
- $secure = (COption::GetOptionString("main", "use_secure_password_cookies", "N")=="Y" && CMain::IsHTTPS());
- if($bSave)
- {
- $period = time()+60*60*24*30*12;
- $spread = Main\Web\Cookie::SPREAD_SITES | Main\Web\Cookie::SPREAD_DOMAIN;
- }
- else
- {
- $period = 0;
- $spread = Main\Web\Cookie::SPREAD_SITES;
- }
- $cookie = new Bitrix\Main\Web\Cookie("UIDH", $hash, $period);
- $cookie->setSecure($secure)
- ->setSpread($spread)
- ->setHttpOnly(true);
- $response->addCookie($cookie);
- $cookie = new Bitrix\Main\Web\Cookie("UIDL", $arUser["LOGIN"], $period);
- $cookie->setSecure($secure)
- ->setSpread($spread)
- ->setHttpOnly(true);
- $response->addCookie($cookie);
- $stored_id = static::CheckStoredHash($arUser["ID"], $hash);
- if($stored_id)
- {
- $DB->Query(
- "UPDATE b_user_stored_auth SET
- LAST_AUTH = ".$DB->CurrentTimeFunction().",
- ".($this->bLoginByHash? "" : "TEMP_HASH = '".($bSave? "N" : "Y")."', ")."
- IP_ADDR = '".sprintf("%u", ip2long($_SERVER["REMOTE_ADDR"]))."'
- WHERE ID = ".$stored_id
- );
- }
- else
- {
- $arFields = array(
- 'USER_ID' => $arUser["ID"],
- '~DATE_REG' => $DB->CurrentTimeFunction(),
- '~LAST_AUTH' => $DB->CurrentTimeFunction(),
- 'TEMP_HASH' => ($bSave? "N" : "Y"),
- '~IP_ADDR' => sprintf("%u", ip2long($_SERVER["REMOTE_ADDR"])),
- 'STORED_HASH' => $hash
- );
- $stored_id = $DB->Add("b_user_stored_auth", $arFields);
- }
- $this->SetParam("STORED_AUTH_ID", $stored_id);
- }
- if(COption::GetOptionString("main", "event_log_login_success", "N") === "Y")
- CEventLog::Log("SECURITY", "USER_AUTHORIZE", "main", $arUser["ID"], $applicationId);
- }
- $this->admin = null;
- $arParams = array(
- "user_fields" => $arUser,
- "save" => $bSave,
- "update" => $bUpdate,
- "applicationId" => $applicationId,
- );
- foreach (GetModuleEvents("main", "OnAfterUserAuthorize", true) as $arEvent)
- ExecuteModuleEventEx($arEvent, array($arParams));
- foreach (GetModuleEvents("main", "OnUserLogin", true) as $arEvent)
- ExecuteModuleEventEx($arEvent, array($this->GetID(), $arParams));
- if($bUpdate)
- {
- Main\Composite\Engine::onUserLogin();
- }
- //we need it mostrly for the $this->justAuthorized flag
- $this->CheckAuthActions();
- return true;
- }
- return false;
- }
- public function GetSessionHash()
- {
- if($this->GetParam("SESSION_HASH") == '')
- {
- $this->SetParam("SESSION_HASH", md5(uniqid("", true).CMain::GetServerUniqID()));
- }
- return $this->GetParam("SESSION_HASH");
- }
- /** @deprecated */
- public function GetPasswordHash($PASSWORD_HASH)
- {
- $add = COption::GetOptionString("main", "pwdhashadd", "");
- if($add == '')
- {
- $add = md5(uniqid(rand(), true));
- COption::SetOptionString("main", "pwdhashadd", $add);
- }
- return md5($add.$PASSWORD_HASH);
- }
- /** @deprecated */
- public function SavePasswordHash()
- {
- $hash = $this->GetSessionHash();
- $time = time()+60*60*24*30*60;
- $secure = (COption::GetOptionString("main", "use_secure_password_cookies", "N")=="Y" && CMain::IsHTTPS());
- $spread = (COption::GetOptionString("main", "auth_multisite", "N") == "Y"? (Main\Web\Cookie::SPREAD_SITES | Main\Web\Cookie::SPREAD_DOMAIN) : Main\Web\Cookie::SPREAD_DOMAIN);
- $cookie = new Main\Web\Cookie("UIDH", $hash, $time);
- $cookie->setSpread($spread)
- ->setSecure($secure)
- ->setHttpOnly(true);
- Main\Context::getCurrent()->getResponse()->addCookie($cookie);
- }
- /**
- * Authenticates the user and then authorizes him
- * @param string $login
- * @param string $password
- * @param string $remember
- * @param string $password_original
- * @return array|bool
- */
- public function Login($login, $password, $remember="N", $password_original="Y")
- {
- global $APPLICATION;
- $result_message = true;
- $user_id = 0;
- $applicationId = null;
- $applicationPassId = null;
- $arParams = array(
- "LOGIN" => &$login,
- "PASSWORD" => &$password,
- "REMEMBER" => &$remember,
- "PASSWORD_ORIGINAL" => &$password_original,
- );
- unset(static::$kernelSession["SESS_OPERATIONS"]);
- unset(static::$kernelSession["MODULE_PERMISSIONS"]);
- $APPLICATION->SetNeedCAPTHA(false);
- $bOk = true;
- $APPLICATION->ResetException();
- foreach(GetModuleEvents("main", "OnBeforeUserLogin", true) as $arEvent)
- {
- if(ExecuteModuleEventEx($arEvent, array(&$arParams))===false)
- {
- if($err = $APPLICATION->GetException())
- {
- $result_message = array("MESSAGE"=>$err->GetString()."<br>", "TYPE"=>"ERROR");
- }
- else
- {
- $APPLICATION->ThrowException("Unknown login error");
- $result_message = array("MESSAGE"=>"Unknown login error"."<br>", "TYPE"=>"ERROR");
- }
- $bOk = false;
- break;
- }
- }
- if($bOk)
- {
- //external authentication
- foreach(GetModuleEvents("main", "OnUserLoginExternal", true) as $arEvent)
- {
- $user_id = ExecuteModuleEventEx($arEvent, array(&$arParams));
- if(isset($arParams["RESULT_MESSAGE"]))
- {
- $result_message = $arParams["RESULT_MESSAGE"];
- }
- if($user_id > 0)
- {
- break;
- }
- }
- if($user_id <= 0)
- {
- //internal authentication OR application password for external user
- $user_id = static::LoginInternal($arParams, $result_message, $applicationId, $applicationPassId);
- if($user_id <= 0)
- {
- //no user found by login - try to find an external user
- foreach(GetModuleEvents("main", "OnFindExternalUser", true) as $arEvent)
- {
- if(($external_user_id = intval(ExecuteModuleEventEx($arEvent, array($arParams["LOGIN"])))) > 0)
- {
- //external user authentication
- //let's try to find application password for the external user
- if(($appPassword = ApplicationPasswordTable::findPassword($external_user_id, $arParams["PASSWORD"], ($arParams["PASSWORD_ORIGINAL"] == "Y"))) !== false)
- {
- //bingo, the user has the application password
- $user_id = $external_user_id;
- $result_message = true;
- $applicationId = $appPassword["APPLICATION_ID"];
- $applicationPassId = $appPassword["ID"];
- }
- break;
- }
- }
- }
- }
- }
- // All except Admin
- if ($user_id > 1 && $arParams["CONTROLLER_ADMIN"] !== "Y")
- {
- if(!static::CheckUsersCount($user_id))
- {
- $user_id = 0;
- $APPLICATION->ThrowException(GetMessage("LIMIT_USERS_COUNT"));
- $result_message = array(
- "