2namespace Bitrix\Rest\Api;
4use Bitrix\Intranet\Invitation;
5use Bitrix\Main\ObjectPropertyException;
7use Bitrix\Main\ModuleManager;
8use Bitrix\Main\UserTable;
9use Bitrix\Rest\AppTable;
10use Bitrix\Rest\NonLoggedExceptionDecorator;
11use Bitrix\Rest\RestException;
12use Bitrix\Rest\Controller\File;
13use Bitrix\Rest\Exceptions\ArgumentException;
21 private const ALLOWED_USER_NAME_FIELDS = [
33 'PERSONAL_PROFESSION',
53 private const ALLOWED_USER_BASIC_FIELDS = [
71 'PERSONAL_PROFESSION',
114 'UF_EMPLOYMENT_DATE',
120 private static $entityUser =
'USER';
121 private static $nameFieldFullPrefix =
'UF_USR_';
122 private static $userUserFieldList;
138 'LAST_ACTIVITY_DATE',
140 'PERSONAL_PROFESSION',
156 'PERSONAL_PROFESSION',
179 'UF_EMPLOYMENT_DATE',
202 $result = static::$allowedUserFields;
204 if (Loader::includeModule(
'intranet'))
212 private static function isMainScope(\
CRestServer $server)
214 return in_array(static::SCOPE_USER, $server->
getAuthScope());
217 private static function getErrorScope()
220 'error' =>
'insufficient_scope',
221 'error_description' =>
'The request requires higher privileges than provided by the access token',
225 private static function getAllowedUserFields($scopeList):
array
228 if (in_array(static::SCOPE_USER, $scopeList))
230 $result = static::getDefaultAllowedUserFields();
234 if (in_array(static::SCOPE_USER_BASIC, $scopeList))
236 $result = static::ALLOWED_USER_BASIC_FIELDS;
238 elseif (in_array(static::SCOPE_USER_BRIEF, $scopeList))
240 $result = static::ALLOWED_USER_NAME_FIELDS;
243 if (Loader::includeModule(
'intranet'))
259 unset(static::$allowedUserFields[
$key]);
264 static::$allowedUserFields[] = $field;
270 \CRestUtil::GLOBAL_SCOPE =>
array(
271 'user.admin' =>
array(__CLASS__,
'isAdmin'),
272 'user.access' =>
array(__CLASS__,
'hasAccess'),
273 'access.name' =>
array(__CLASS__,
'getAccess'),
280 'user.fields' =>
array(__CLASS__,
'getFields'),
281 'user.current' =>
array(__CLASS__,
'userCurrent'),
282 'user.get' =>
array(__CLASS__,
'userGet'),
283 'user.search' =>
array(__CLASS__,
'userGet'),
284 'user.add' =>
array(__CLASS__,
'userAdd'),
285 'user.update' =>
array(__CLASS__,
'userUpdate'),
286 'user.online' =>
array(__CLASS__,
'userOnline'),
287 'user.counters' =>
array(__CLASS__,
'userCounters'),
288 \CRestUtil::EVENTS =>
array(
289 'OnUserAdd' =>
array(
'main',
'OnUserInitialize',
array(__CLASS__,
'onUserInitialize')),
292 $result[static::SCOPE_USER_BRIEF] = [
293 'user.fields' =>
array(__CLASS__,
'getFields'),
294 'user.current' =>
array(__CLASS__,
'userCurrent'),
295 'user.get' =>
array(__CLASS__,
'userGet'),
296 'user.search' =>
array(__CLASS__,
'userGet'),
297 'user.online' =>
array(__CLASS__,
'userOnline'),
298 'user.counters' =>
array(__CLASS__,
'userCounters'),
299 \CRestUtil::EVENTS =>
array(
300 'OnUserAdd' =>
array(
'main',
'OnUserInitialize',
array(__CLASS__,
'onUserInitialize')),
303 $result[static::SCOPE_USER_BASIC] = [
304 'user.fields' =>
array(__CLASS__,
'getFields'),
305 'user.current' =>
array(__CLASS__,
'userCurrent'),
306 'user.get' =>
array(__CLASS__,
'userGet'),
307 'user.search' =>
array(__CLASS__,
'userGet'),
308 'user.online' =>
array(__CLASS__,
'userOnline'),
309 'user.counters' =>
array(__CLASS__,
'userCounters'),
310 \CRestUtil::EVENTS =>
array(
311 'OnUserAdd' =>
array(
'main',
'OnUserInitialize',
array(__CLASS__,
'onUserInitialize')),
315 'user.userfield.add' => [UserField::class,
'addRest'],
316 'user.userfield.update' => [UserField::class,
'updateRest'],
317 'user.userfield.delete' => [UserField::class,
'deleteRest'],
318 'user.userfield.list' => [UserField::class,
'getListRest'],
319 'user.userfield.file.get' => [__CLASS__,
'getFile'],
326 private static function getUserFields()
328 if (is_null(static::$userUserFieldList))
330 static::$userUserFieldList = [];
337 if (mb_strpos(
$code, static::$nameFieldFullPrefix) === 0)
339 static::$userUserFieldList[] =
$code;
344 return static::$userUserFieldList;
353 foreach(static::getDefaultAllowedUserFields() as
$key => $field)
355 if(mb_substr($field, 0, 3) ===
'UF_' && !array_key_exists($field,
$fields))
357 static::unsetDefaultAllowedUserField(
$key);
363 if (mb_strpos(
$code, static::$nameFieldFullPrefix) === 0)
365 static::setDefaultAllowedUserField(
$code);
375 $arUser =
$dbRes->Fetch();
377 if(in_array($arUser[
'EXTERNAL_AUTH_ID'], UserTable::getExternalUserTypes()))
379 throw new RestException(
'Unnecessary event call for this user type');
383 if ($arHandler[
'APP_ID'] > 0)
388 $scope = explode(
',',
$app[
'SCOPE']);
394 if($arUser[
'PERSONAL_PHOTO'] > 0)
396 $arRes[
'PERSONAL_PHOTO'] = \CRestUtil::GetFile($arUser[
"PERSONAL_PHOTO"]);
404 return \CRestUtil::isAdmin();
431 $ob = new \CAccess();
447 static::checkAllowedFields();
451 $langMessages = array_merge(
456 if (!is_null($server))
458 $allowedFields = static::getAllowedUserFields($server->getAuthScope());
466 if(mb_substr(
$key, 0, 3) !=
'UF_')
468 $lkey = isset($langMessages[
$key]) ?
$key : str_replace(
'PERSONAL_',
'USER_',
$key);
470 if(mb_substr(
$res[
$key], -1) ==
':')
488 static::checkAllowedFields();
491 $userFields =
$dbRes->fetch();
495 if($userFields[
'PERSONAL_PHOTO'] > 0)
497 $result[
'PERSONAL_PHOTO'] = \CRestUtil::GetFile($userFields[
"PERSONAL_PHOTO"]);
502 "EMAIL" =>
$result[
'EMAIL'] ??
'',
513 static::checkAllowedFields();
515 static $moduleAdminList =
false;
519 $sort =
$query[
'SORT'] ??
null;
526 "small"=>[
"width"=>150,
"height" => 150],
527 "medium"=>[
"width"=>300,
"height" => 300],
528 "large"=>[
"width"=>1000,
"height" => 1000],
531 $presetName =
$query[
"IMAGE_RESIZE"] ??
null;
532 $resize = ($presetName && $resizePresets[$presetName]
533 ? $resizePresets[$presetName]
536 if (isset(
$query[
'ADMIN_MODE']) &&
$query[
'ADMIN_MODE'])
538 if ($moduleAdminList ===
false && Loader::includeModule(
'socialnetwork'))
543 if (is_array($moduleAdminList))
545 $adminMode = (array_key_exists(
$USER->getID(), $moduleAdminList));
554 if ($server->getMethod() ==
"user.search")
561 if (isset(
$query[
'FILTER']) && is_array(
$query[
'FILTER']))
567 $query = array_change_key_case(
$query[
'FILTER'], CASE_UPPER);
570 $filter = self::prepareUserFilter(
587 'FIND' => $nameSearch,
590 else if ($server->getMethod() ==
"user.search")
596 unset(
$filter[
'WORK_POSITION']);
597 unset(
$filter[
'UF_DEPARTMENT_NAME']);
600 'NAME' => $previousFilter[
'NAME'] ??
null,
601 'LAST_NAME' => $previousFilter[
'LAST_NAME'] ??
null,
602 'SECOND_NAME' => $previousFilter[
'SECOND_NAME'] ??
null,
603 'WORK_POSITION' => $previousFilter[
'WORK_POSITION'] ??
null,
604 'UF_DEPARTMENT_NAME' => $previousFilter[
'UF_DEPARTMENT_NAME'] ??
null,
610 && Loader::includeModule(
"extranet")
613 $filteredUserIDs = \CExtranet::getMyGroupsUsersSimple(\CExtranet::getExtranetSiteID());
615 if (\CExtranet::isIntranetUser())
619 || !Loader::includeModule(
'socialnetwork')
620 || !\CSocNetUser::IsCurrentUserModuleAdmin(\CSite::getDefSite(),
false)
623 if (!empty($filteredUserIDs))
627 '!UF_DEPARTMENT' =>
false,
628 'ID' => $filteredUserIDs,
635 '!UF_DEPARTMENT' =>
false,
642 $filteredUserIDs[] =
$USER->getId();
647 if (array_key_exists(
'HAS_DEPARTAMENT',
$filter))
649 if (
$filter[
'HAS_DEPARTAMENT'] ===
'Y')
653 '!UF_DEPARTMENT' =>
false,
657 unset(
$filter[
'HAS_DEPARTAMENT']);
660 $filter[
'=IS_REAL_USER'] =
'Y';
662 $getListClassName =
'\Bitrix\Main\UserTable';
663 if (Loader::includeModule(
'intranet'))
665 $getListClassName =
'\Bitrix\Intranet\UserTable';
667 $getListMethodName =
'getList';
674 $querySort[$sort] =
$order;
677 $allowedFields = static::getAllowedUserFields($server->getAuthScope());
681 if (in_array(
'UF_*',
$select,
true))
683 $allowedAllUF = array_filter(
685 static fn($value) => $value && str_starts_with($value,
'UF_'),
692 $dbRes = $getListClassName::$getListMethodName(
694 'order' => $querySort,
699 'data_doubling' =>
false,
700 'count_total' => $nav !== -1,
707 while ($userInfo =
$dbRes->fetch())
711 if ($userInfo[
'PERSONAL_PHOTO'] > 0)
713 $files[] = $userInfo[
'PERSONAL_PHOTO'];
723 if (isset($userInfo[
'PERSONAL_PHOTO']) && $userInfo[
'PERSONAL_PHOTO'] > 0)
762 'select' =>
array(
'ID'),
765 $onlineUsers =
array();
766 while($userData =
$dbRes->fetch())
768 $onlineUsers[] = $userData[
'ID'];
782 if (!isset(
$arParams[
'SKIP_LIVEFEED_GROUP']) ||
$arParams[
'SKIP_LIVEFEED_GROUP'] !=
'Y')
792 if (!is_null($server) && !static::isMainScope($server))
794 return static::getErrorScope();
799 static::checkAllowedFields();
806 $bB24 &&
$USER->canDoOperation(
'bitrix24_invite')
807 ||
$USER->canDoOperation(
'edit_all_users')
809 && Loader::includeModule(
'intranet'))
811 $userFields = array_change_key_case($userFields, CASE_UPPER);
816 isset($userFields[
"EXTRANET"])
817 && $userFields[
"EXTRANET"] ==
"Y"
823 $userFields[
"UF_DEPARTMENT"] =
array();
825 if (!empty($userFields[
"SONET_GROUP_ID"]))
827 $sonetGroupId = $userFields[
"SONET_GROUP_ID"];
828 if (!is_array($sonetGroupId))
830 $sonetGroupId =
array($sonetGroupId);
833 unset($userFields[
"SONET_GROUP_ID"]);
841 unset($userFields[
"EXTRANET"]);
844 self::checkTypeFields($userFields);
848 $userFields[
"EMAIL"] = trim($userFields[
"EMAIL"] ??
'');
853 if(\CIntranetInviteDialog::checkUsersCount(1))
857 && empty($inviteFields[
"UF_DEPARTMENT"])
864 $inviteFields[
'EMAIL'] = $userFields[
"EMAIL"];
865 $inviteFields[
'ACTIVE'] = ($inviteFields[
'ACTIVE'] ??
'Y');
866 $inviteFields[
'GROUP_ID'] = \CIntranetInviteDialog::getUserGroups(
$siteId, $bExtranet);
867 $inviteFields[
"CONFIRM_CODE"] =
randString(8);
869 $ID = \CIntranetInviteDialog::RegisterUser($inviteFields);
876 $obUser = new \CUser;
877 if(!$obUser->update(
$ID, $inviteFields))
879 throw new \Exception($obUser->LAST_ERROR);
882 $inviteFields[
'ID'] =
$ID;
886 'TYPE' => Invitation::TYPE_EMAIL
889 \CIntranetInviteDialog::InviteUser(
891 (isset($userFields[
"MESSAGE_TEXT"])) ?
htmlspecialcharsbx($userFields[
"MESSAGE_TEXT"]) :
GetMessage(
"BX24_INVITE_DIALOG_INVITE_MESSAGE_TEXT_1")
896 && is_array($sonetGroupId)
897 && \CModule::IncludeModule(
'socialnetwork')
900 foreach($sonetGroupId as $groupId)
902 if (!\CSocNetUserToGroup::SendRequestToJoinGroup(
$USER->GetID(),
$ID, $groupId,
"",
false))
906 throw new \Exception($e->GetString());
933 private static function checkTypeFields(
$fields): void
935 $notStringTypeField = [
'PERSONAL_PHOTO',
'WORK_LOGO'];
938 $fieldMustBeString = str_contains(
$key,
'WORK_')
939 || str_contains(
$key,
'PERSONAL_')
940 && !in_array(
$key, $notStringTypeField,
true)
943 if ($fieldMustBeString && !is_string($field))
952 if (!is_null($server) && !static::isMainScope($server))
954 return static::getErrorScope();
959 static::checkAllowedFields();
963 $bAdmin = ($bB24 &&
$USER->canDoOperation(
'bitrix24_invite'))
964 ||
$USER->canDoOperation(
'edit_all_users');
966 $userFields = array_change_key_case($userFields, CASE_UPPER);
968 if(isset($userFields[
'ID']) && $userFields[
'ID'] > 0)
970 if(
$bAdmin || (
$USER->getID() == $userFields[
'ID'] &&
$USER->CanDoOperation(
'edit_own_profile')))
977 unset($updateFields[
'ACTIVE']);
978 unset($updateFields[
'UF_DEPARTMENT']);
982 $obUser = new \CUser;
983 if(!$obUser->update($userFields[
'ID'], $updateFields))
1005 private static function prepareUserField(
$params,
$data)
1008 switch (
$params[
'USER_TYPE_ID'])
1017 if (is_array(
$data))
1019 if (
$params[
'MULTIPLE'] ===
'N')
1021 if (!empty(
$data[
'fileData']))
1026 $id = isset(
$data[
'id']) ? (int)
$data[
'id'] : 0;
1027 $remove = isset(
$data[
'remove']) && is_string(
$data[
'remove']) && mb_strtoupper(
$data[
'remove']) ===
'Y';
1028 if ($remove && $id > 0)
1045 if ($value[
'fileData'])
1047 $result[
$key] = \CRestUtil::saveFile($value[
'fileData']);
1051 $id = isset($value[
'id']) ? (int)$value[
'id'] : 0;
1052 $remove = isset($value[
'remove']) && is_string($value[
'remove']) && mb_strtoupper($value[
'remove']) ===
'Y';
1053 if ($remove && $id > 0)
1090 foreach($userData as
$key => $value)
1101 private static function prepareUserValue(
$code, $value)
1105 if (is_array($value) && !empty($value))
1107 $value = array_map(
'intval', $value);
1111 $value = (int)($value);
1116 $value = ($value && $value !==
'N')?
'Y' :
'N';
1118 case 'AUTO_TIME_ZONE':
1119 $value = $value ===
'Y'?
'Y' :
'N';
1121 case 'PERSONAL_BIRTHDAY':
1122 $value = \CRestUtil::unConvertDate($value);
1124 case 'PERSONAL_PHOTO':
1126 $value = \CRestUtil::saveFile($value);
1135 case 'UF_DEPARTMENT':
1136 if(!is_array($value) && !empty($value))
1143 case 'CONFIRM_CODE':
1175 if ($filterType !==
'' && in_array(
$code, $clearFilterType,
true))
1179 elseif ($filterType ===
'' && in_array(
$code, [
'USER_TYPE',
'ACTIVE'],
true))
1201 $userId = (int)($userData[
'ID'] ?? 0);
1205 foreach ($userData as
$key => $value)
1209 if (mb_strpos(
$key, static::$nameFieldFullPrefix) === 0)
1211 $user[
$key] = static::prepareUserField($fieldsList[
$key], $value);
1221 if (isset(
$user[
'ACTIVE']))
1222 $user[
'ACTIVE'] = (
$user[
'ACTIVE'] &&
$user[
'ACTIVE'] !=
'N') ?
'Y' :
'N';
1224 if (isset(
$user[
'PERSONAL_BIRTHDAY']))
1225 $user[
'PERSONAL_BIRTHDAY'] = \CRestUtil::unConvertDate(
$user[
'PERSONAL_BIRTHDAY']);
1227 if (!empty(
$user[
'UF_DEPARTMENT']) && !is_array(
$user[
'UF_DEPARTMENT']))
1230 if (isset(
$user[
'PERSONAL_PHOTO']))
1232 $user[
'PERSONAL_PHOTO'] = \CRestUtil::saveFile(
$user[
'PERSONAL_PHOTO']);
1234 if (!
$user[
'PERSONAL_PHOTO'])
1236 $user[
'PERSONAL_PHOTO'] =
array(
'del' =>
'Y');
1240 $user = array_diff_key(
$user, array_fill_keys(static::$holdEditFields,
'Y'));
1247 static $extranetModuleInstalled =
null;
1248 if ($extranetModuleInstalled ===
null)
1269 case 'PERSONAL_BIRTHDAY':
1270 case 'DATE_REGISTER':
1271 $res[
$key] = \CRestUtil::convertDate($userFields[
$key]);
1274 $res[
$key] = \CRestUtil::convertDateTime($userFields[
$key]);
1276 case 'EXTERNAL_AUTH_ID':
1277 $res[
'IS_NETWORK'] = $userFields[
$key] ==
'replica';
1278 $res[
'IS_EMAIL'] = $userFields[
$key] ==
'email';
1279 unset($userFields[
$key]);
1282 if (!empty($fieldsList[
$key]))
1284 if ($fieldsList[
$key][
'USER_TYPE_ID'] ===
'date')
1286 if ($fieldsList[
$key][
'MULTIPLE'] ===
'Y' && is_array($userFields[
$key]))
1288 foreach ($userFields[
$key] as
$k => $value)
1295 $res[
$key] = \CRestUtil::convertDate($userFields[
$key]);
1298 elseif ($fieldsList[
$key][
'USER_TYPE_ID'] ===
'datetime')
1300 if ($fieldsList[
$key][
'MULTIPLE'] ===
'Y' && is_array($userFields[
$key]))
1302 foreach ($userFields[
$key] as
$k => $value)
1309 $res[
$key] = \CRestUtil::convertDateTime($userFields[
$key]);
1312 elseif ($fieldsList[
$key][
'USER_TYPE_ID'] ===
'file')
1314 if ($fieldsList[
$key][
'MULTIPLE'] ===
'Y' && is_array($userFields[
$key]))
1316 foreach ($userFields[
$key] as
$k => $value)
1319 'id' => $userFields[
$key][
$k],
1320 'showUrl' => $urlManager->create(
1323 'entity' => static::$entityUser,
1324 'id' => $userFields[
'ID'],
1326 'value' => $userFields[
$key],
1330 'id' => $userFields[
'ID'],
1332 'value' => $userFields[
$key][
$k],
1340 'id' => $userFields[
$key],
1341 'showUrl' => $urlManager->create(
1344 'entity' => static::$entityUser,
1345 'id' => $userFields[
'ID'],
1347 'value' => $userFields[
$key],
1351 'id' => $userFields[
'ID'],
1353 'value' => $userFields[
$key],
1374 return $file->getAction(static::$entityUser,
$query[
'id'],
$query[
'field'],
$query[
'value'], $server);
1379 return \CSite::getDefSite();
if(!is_object($USER)||! $USER->IsAuthorized()) $userId
static isModuleInstalled($moduleName)
static getUserSearchFilter(array $fields)
const SCOPE_USER_USERFIELD
static onRestServiceBuildDescription()
static getUserData($userFields, $allowedFields=null)
static $allowedUserFields
static userCurrent($query, $n, \CRestServer $server)
static checkAllowedFields()
static userCounters($arParams)
static userGet($query, $nav=0, \CRestServer $server=null)
static prepareSaveData($userData, $allowedUserFields=null)
static setDefaultAllowedUserField($field)
static getDefaultAllowedUserFields()
static userAdd($userFields, $nav=0, \CRestServer $server=null)
static unsetDefaultAllowedUserField($key)
static hasAccess($params)
static getFields($query=[], $nav=0, \CRestServer $server=null)
static userUpdate($userFields, $nav=0, \CRestServer $server=null)
static getFile($query, $n, \CRestServer $server)
static onUserInitialize($arParams, $arHandler)
static prepareUserData($userData, $allowedUserFields=null)
static getAccess($params)
static getByClientId($clientId)
static getModuleAdminList($siteIdList)
setSecurityState($state=null)
static setNavData($result, $dbRes)
static getNavData($start, $bORM=false)
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
while($group=$gr->Fetch()) $bAdmin
global $USER_FIELD_MANAGER
if(!is_null($config))($config as $configItem)(! $configItem->isVisible()) $code
IsModuleInstalled($module_id)
htmlspecialcharsbx($string, $flags=ENT_COMPAT, $doubleEncode=true)
IncludeModuleLangFile($filepath, $lang=false, $bReturnArray=false)
GetMessage($name, $aReplace=null)
check_email($email, $strict=false, $domainCheck=false)
randString($pass_len=10, $pass_chars=false)
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
if(empty($signedUserToken)) $key
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']