87 private static $skipRemoteUpdate =
false;
94 'landing_cloud',
'rating',
116 'data_type' =>
'integer',
118 'autocomplete' =>
true,
120 'CLIENT_ID' => array(
121 'data_type' =>
'string',
123 'validation' => array(__CLASS__,
'validateClientId'),
126 'data_type' =>
'string',
128 'validation' => array(__CLASS__,
'validateCode'),
131 'data_type' =>
'boolean',
132 'values' => array(static::INACTIVE, static::ACTIVE),
134 'INSTALLED' => array(
135 'data_type' =>
'boolean',
136 'values' => array(static::NOT_INSTALLED, static::INSTALLED),
139 'data_type' =>
'string',
140 'validation' => array(__CLASS__,
'validateUrl'),
143 'data_type' =>
'string',
144 'validation' => array(__CLASS__,
'validateUrlDemo'),
146 'URL_INSTALL' => array(
147 'data_type' =>
'string',
148 'validation' => array(__CLASS__,
'validateUrlInstall'),
151 'data_type' =>
'string',
152 'validation' => array(__CLASS__,
'validateVersion'),
155 'data_type' =>
'string',
157 'validation' => array(__CLASS__,
'validateScope'),
160 'data_type' =>
'enum',
163 static::STATUS_LOCAL,
167 static::STATUS_TRIAL,
168 static::STATUS_SUBSCRIPTION,
171 'DATE_FINISH' => array(
172 'data_type' =>
'date',
174 'IS_TRIALED' => array(
175 'data_type' =>
'boolean',
176 'values' => array(static::NOT_TRIALED, static::TRIALED),
178 'SHARED_KEY' => array(
179 'data_type' =>
'string',
180 'validation' => array(__CLASS__,
'validateSharedKey'),
182 'CLIENT_SECRET' => array(
183 'data_type' =>
'string',
184 'validation' => array(__CLASS__,
'validateClientSecret'),
187 'data_type' =>
'string',
188 'validation' => array(__CLASS__,
'validateAppName'),
191 'data_type' =>
'string',
192 'validation' => array(__CLASS__,
'validateAccess'),
194 'APPLICATION_TOKEN' => array(
195 'data_type' =>
'string',
198 'data_type' =>
'boolean',
199 'values' => array(static::INACTIVE, static::ACTIVE),
201 'USER_INSTALL' => array(
202 'data_type' =>
'boolean',
203 'values' => array(static::INACTIVE, static::ACTIVE),
206 'data_type' =>
'Bitrix\Rest\AppLangTable',
207 'reference' => array(
208 '=this.ID' =>
'ref.APP_ID',
209 '=ref.LANGUAGE_ID' =>
new Main\DB\
SqlExpression(
'?s', LANGUAGE_ID),
212 'LANG_DEFAULT' => array(
213 'data_type' =>
'Bitrix\Rest\AppLangTable',
214 'reference' => array(
215 '=this.ID' =>
'ref.APP_ID',
219 'LANG_LICENSE' => array(
220 'data_type' =>
'Bitrix\Rest\AppLangTable',
221 'reference' => array(
222 '=this.ID' =>
'ref.APP_ID',
223 '=ref.LANGUAGE_ID' =>
new Main\DB\
SqlExpression(
'?s', static::getLicenseLanguage()),
226 (
new OneToMany(
'LANG_ALL', AppLangTable::class,
'APP'))
227 ->configureJoinType(
'left')
238 static::$skipRemoteUpdate = $v;
249 $result =
new Main\Entity\EventResult();
250 $data = $event->getParameters();
252 if($data[
'fields'][
'STATUS'] == static::STATUS_LOCAL && !$data[
'fields'][
'CLIENT_ID'])
254 $rnd = Main\Security\Random::getString(8);
255 $dummyClientId =
'no_client_id_'.$rnd;
256 $dummyClientSecret =
'no_client_secret_'.$rnd;
258 $result->modifyFields(array(
259 "CLIENT_ID" => $dummyClientId,
260 "CLIENT_SECRET" => $dummyClientSecret,
261 "CODE" => $dummyClientId,
277 EventController::onAddApp($event);
278 $data = $event->getParameters();
279 if(!static::$skipRemoteUpdate)
282 $data[
'fields'][
'STATUS'] === static::STATUS_LOCAL
289 'TITLE' => $data[
'fields'][
'APP_NAME'],
290 'REDIRECT_URI' => $data[
'fields'][
'URL'],
291 'SCOPE' => $data[
'fields'][
'SCOPE'],
296 ->addApplication($appFields);
301 "error" => $e->getCode(),
302 "error_description" => $e->getMessage(),
306 if(is_array($clientData))
308 if($clientData[
'result'])
310 static::$skipRemoteUpdate =
true;
312 static::clearClientCache($clientData[
'result'][
'client_id']);
314 $updateResult = static::update($data[
'id'], array(
315 'CLIENT_ID' => $clientData[
'result'][
'client_id'],
316 'CLIENT_SECRET' => $clientData[
'result'][
'client_secret'],
317 'STATUS' => static::STATUS_LOCAL,
318 'SHARED_KEY' => md5(\CRestUtil::getMemberId().$clientData[
'result'][
'client_secret']),
319 'CODE' => $clientData[
'result'][
'client_id'],
321 static::$skipRemoteUpdate =
false;
323 if($updateResult->isSuccess())
329 $clientData = array(
'error' => $updateResult->getErrorMessages());
335 $clientData = array(
'error' =>
'Unknown error');
338 static::$skipRemoteUpdate =
true;
339 static::delete($data[
'id']);
340 static::$skipRemoteUpdate =
false;
346 if($data[
'fields'][
'STATUS'] !== static::STATUS_LOCAL)
348 \Bitrix\Rest\Engine\Access::getActiveEntity(
true);
363 $data = $event->getParameters();
364 static::clearClientCache($data[
'primary'][
'ID']);
366 if(!static::$skipRemoteUpdate)
369 isset($data[
'fields'][
'STATUS'])
370 && $data[
'fields'][
'STATUS'] === static::STATUS_LOCAL
374 $app = static::getByClientId($data[
'primary'][
'ID']);
380 ->updateApplication(array(
381 "CLIENT_ID" => $app[
'CLIENT_ID'],
382 'TITLE' => $data[
'fields'][
'APP_NAME'],
383 'REDIRECT_URI' => $data[
'fields'][
'URL'],
384 'SCOPE' => $data[
'fields'][
'SCOPE'],
387 if($updateResult[
'result'])
394 $updateResult = array(
395 "error" => $e->getCode(),
396 "error_description" => $e->getMessage(),
404 if(isset($data[
'fields'][
'STATUS']) && $data[
'fields'][
'STATUS'] !== static::STATUS_LOCAL)
406 \Bitrix\Rest\Engine\Access::getActiveEntity(
true);
419 if(!static::$skipRemoteUpdate)
421 $data = $event->getParameters();
422 $app = static::getByClientId($data[
'primary'][
'ID']);
428 \CRestUtil::cleanApp($app[
"ID"],
true);
434 ->deleteApplication(array(
435 'CLIENT_ID' => $app[
'CLIENT_ID'],
453 $data = $event->getParameters();
455 static::clearClientCache($data[
'primary'][
'ID']);
461 $appInfo = static::getByClientId($appId);
464 $eventFields = array(
466 'VERSION' => $appInfo[
'VERSION'],
467 'ACTIVE' => $appInfo[
'ACTIVE'],
468 'INSTALLED' => $appInfo[
'INSTALLED'],
471 if ($appInfo[
'ACTIVE'] === self::ACTIVE && $appInfo[
'INSTALLED'] === self::INSTALLED)
473 $res = PlacementTable::getList(
476 '=APP_ID' => $appInfo[
'ID'],
485 while ($item = $res->fetch())
492 'PLACEMENT' => $item[
'PLACEMENT'],
493 'USER_ID' => $item[
'USER_ID'],
496 EventManager::getInstance()->send($event);
500 foreach(GetModuleEvents(
"rest",
"OnRestAppInstall",
true) as $eventHandler)
502 ExecuteModuleEventEx($eventHandler, array($eventFields));
515 $appInfo = static::getByClientId($appId);
518 \CRestUtil::cleanApp($appId, $clean);
520 if($appInfo[
'STATUS'] !== static::STATUS_LOCAL)
523 'CLIENT_ID' => $appInfo[
'CLIENT_ID']
536 public static function checkUninstallAvailability($appId, $clean = 0)
538 $event =
new Main\Event(
'rest',
'onBeforeApplicationUninstall', [
545 if ($event->getResults())
548 foreach ($event->getResults() as $eventResult)
550 if($eventResult->getType() === EventResult::ERROR)
552 $eventResultData = $eventResult->getParameters();
553 if ($eventResultData instanceof Main\
Error)
555 $result->add([$eventResultData]);
575 if(is_array($appList) && is_array($appList[
'result']))
577 $dbApps = static::getList(array(
579 '!=STATUS' => static::STATUS_LOCAL,
582 'ID',
'CLIENT_ID',
'STATUS',
'DATE_FINISH',
586 $localApps = array();
587 while($app = $dbApps->fetch())
589 $localApps[$app[
'CLIENT_ID']] = $app;
592 foreach($appList[
'result'] as $app)
594 if(array_key_exists($app[
'client_id'], $localApps))
596 $dateFinishLocal = $localApps[$app[
'client_id']][
'DATE_FINISH']
597 ? $localApps[$app[
'client_id']][
'DATE_FINISH']->getTimestamp()
599 $dateFinishRemote = ($app[
'date_finish'] ??
null) ? Main\
Type\Date::createFromTimestamp($app[
'date_finish'])->getTimestamp() :
'';
602 $localApps[$app[
'client_id']][
'STATUS'] !== $app[
'status']
603 || $dateFinishRemote != $dateFinishLocal
607 'STATUS' => $app[
'status'],
608 'DATE_FINISH' => $app[
'date_finish']
609 ? Main\
Type\Date::createFromTimestamp($app[
'date_finish'])
613 static::setSkipRemoteUpdate(
true);
614 $result = static::update($localApps[$app[
'client_id']][
'ID'], $appFields);
615 static::setSkipRemoteUpdate(
false);
619 && $appFields[
'STATUS'] === static::STATUS_PAID
622 static::callAppPaymentEvent($localApps[$app[
'client_id']][
'ID']);
629 'CLIENT_ID' => $app[
'client_id'],
630 'CODE' => $app[
'code'],
631 'ACTIVE' => $app[
'active'] ? static::ACTIVE : static::INACTIVE,
632 'INSTALLED' => static::NOT_INSTALLED,
633 'VERSION' => $app[
'version'],
634 'STATUS' => $app[
'status'],
635 'SCOPE' => $app[
'scope'],
638 if(!empty($app[
'date_finish']))
640 $appFields[
'DATE_FINISH'] = Main\Type\Date::createFromTimestamp($app[
'date_finish']);
643 $result = static::add($appFields);
645 if($result->isSuccess() && $appFields[
'STATUS'] === static::STATUS_PAID)
647 static::callAppPaymentEvent($result->getId());
662 foreach(GetModuleEvents(
'bitrix24',
'OnAfterAppPaid',
true) as $event)
664 ExecuteModuleEventEx($event, array($appId));
687 $appInfo = $app = static::getByClientId($app);
689 elseif (isset($app[
'CODE']))
691 $appInfo = static::getByClientId($app[
'CODE']);
696 $res[
'STATUS'] = $app[
'STATUS'];
697 $res[
'PAYMENT_NOTIFY'] =
'N';
698 $res[
'PAYMENT_EXPIRED'] =
'N';
699 $res[
'PAYMENT_ALLOW'] =
'Y';
701 if ($app[
'STATUS'] === self::STATUS_SUBSCRIPTION)
703 if (!\
Bitrix\Rest\Marketplace\Client::isSubscriptionAvailable())
705 $res[
'MESSAGE_REPLACE'] = array(
706 '#DETAIL_URL#' => $detailUrl,
708 '#CODE#' => urlencode($app[
'CODE'])
710 $res[
'PAYMENT_NOTIFY'] =
'Y';
711 $res[
'PAYMENT_EXPIRED'] =
'Y';
712 $res[
'PAYMENT_ALLOW'] =
'N';
716 $dateFinish = \Bitrix\Rest\Marketplace\Client::getSubscriptionFinalDate();
717 if (!is_null($dateFinish))
719 $res[
'DAYS_LEFT'] = floor(($dateFinish->getTimestamp() - \CTimeZone::getOffset() - time()) / 86400);
720 if($res[
'DAYS_LEFT'] < 0)
722 $res[
'MESSAGE_REPLACE'] = array(
723 '#DETAIL_URL#' => $detailUrl,
724 '#DAYS#' => $res[
'DAYS_LEFT'],
725 '#CODE#' => urlencode($app[
'CODE'])
727 $res[
'PAYMENT_NOTIFY'] =
'Y';
728 $res[
'PAYMENT_EXPIRED'] =
'Y';
729 $res[
'PAYMENT_ALLOW'] =
'N';
731 elseif ($res[
'DAYS_LEFT'] < static::PAID_NOTIFY_DAYS)
733 $res[
'MESSAGE_REPLACE'] = array(
734 '#DETAIL_URL#' => $detailUrl,
735 '#DAYS#' => $res[
'DAYS_LEFT'],
736 '#CODE#' => urlencode($app[
'CODE'])
738 $res[
'PAYMENT_NOTIFY'] =
'Y';
743 elseif($app[
'DATE_FINISH'] <>
'' && $app[
'STATUS'] != self::STATUS_FREE)
745 $res[
'DAYS_LEFT'] = floor(
746 (MakeTimeStamp($app[
'DATE_FINISH']) - \CTimeZone::getOffset() - time()) / 86400
750 $res[
'DAYS_LEFT'] < static::PAID_NOTIFY_DAYS
751 || $app[
'STATUS'] == static::STATUS_TRIAL)
753 $res[
'PAYMENT_NOTIFY'] =
'Y';
755 if($res[
'DAYS_LEFT'] < 0)
757 $res[
'PAYMENT_EXPIRED'] =
'Y';
759 if($app[
'STATUS'] == static::STATUS_TRIAL)
761 $res[
'PAYMENT_ALLOW'] =
'N';
764 $app[
'STATUS'] == static::STATUS_PAID
765 && $res[
'DAYS_LEFT'] < static::PAID_GRACE_PERIOD
768 if($app[
'IS_TRIALED'] ==
'N' && $app[
'URL_DEMO'] <>
'')
770 $res[
'STATUS'] = static::STATUS_DEMO;
774 $res[
'PAYMENT_ALLOW'] =
'N';
780 $res[
'MESSAGE_REPLACE'] = array(
781 "#DETAIL_URL#" => $detailUrl,
782 "#DAYS#" => $res[
'DAYS_LEFT'],
783 "#CODE#" => urlencode($app[
'CODE']),
786 elseif($app[
'STATUS'] == self::STATUS_DEMO)
788 $res[
'PAYMENT_NOTIFY'] =
'Y';
789 $res[
'MESSAGE_REPLACE'] = array(
790 "#DETAIL_URL#" => $detailUrl,
791 "#CODE#" => urlencode($app[
'CODE'])
796 $res[
'MESSAGE_REPLACE'] = array(
797 "#DETAIL_URL#" => $detailUrl,
798 "#CODE#" => urlencode($app[
'CODE'])
802 $res[
'MESSAGE_SUFFIX'] =
'_'.$res[
'STATUS'].
'_'.$res[
'PAYMENT_EXPIRED'].
'_'.$res[
'PAYMENT_ALLOW'];
806 if (!empty($appInfo[
'CLIENT_ID']))
808 $isHold = \Bitrix\Rest\Engine\Access\HoldEntity::is(
810 $appInfo[
'CLIENT_ID']
814 $res[
'MESSAGE_SUFFIX'] =
'_HOLD_OVERLOAD';
815 $res[
'PAYMENT_NOTIFY'] =
'Y';
832 public static function getStatusMessage($suffix, $replace =
null, $checkAdmin =
true, $language =
null)
834 if ($checkAdmin && \CRestUtil::isAdmin())
841 && array_key_exists(
'#DAYS#', $replace)
843 is_int($replace[
'#DAYS#'])
844 || preg_match(
'/^(-|)\d+$/', $replace[
'#DAYS#'])
848 $replace[
'#DAYS#'] = FormatDate(
'ddiff', time(), time() + 24 * 60 * 60 * $replace[
'#DAYS#']);
851 return Loc::getMessage(
'PAYMENT_MESSAGE' . $suffix, $replace, $language);
860 $appInfo = static::getByClientId($appId);
863 if($appInfo[
'ACCESS'] <>
'')
865 $rightsList = explode(
",", $appInfo[
"ACCESS"]);
867 $access = new \CAccess();
868 $accessNames = $access->getNames($rightsList);
871 foreach($rightsList as $right)
873 $result[$right] = array(
875 "provider" => $accessNames[$right][
"provider_id"],
876 "name" => $accessNames[$right][
"name"]
891 public static function setAccess($appId, $newRights = array())
893 $appInfo = static::getByClientId($appId);
897 if(is_array($newRights) && !empty($newRights))
899 $rightIdList = array();
900 foreach($newRights as $key => $rightsList)
902 foreach($rightsList as $rightId => $ar)
904 $rightIdList[] = $rightId;
907 $rights = implode(
",", $rightIdList);
910 static::update($appId, array(
915 if(defined(
"BX_COMP_MANAGED_CACHE"))
917 global $CACHE_MANAGER;
918 $CACHE_MANAGER->ClearByTag(
'bitrix24_left_menu');
931 if(!array_key_exists($clientId, static::$applicationCache))
933 if(strval(intval($clientId)) == $clientId)
935 $filter = array(
'=ID' => $clientId);
942 '=CODE' => $clientId,
943 '=CLIENT_ID' => $clientId,
948 $dbRes = static::getList(
953 'MENU_NAME' =>
'LANG.MENU_NAME',
954 'MENU_NAME_DEFAULT' =>
'LANG_DEFAULT.MENU_NAME',
955 'MENU_NAME_LICENSE' =>
'LANG_LICENSE.MENU_NAME',
961 foreach ($dbRes->fetchCollection() as $app)
964 'ID' => $app->getId(),
965 'MENU_NAME' => !is_null($app->getLang()) ? $app->getLang()->getMenuName() :
'',
966 'MENU_NAME_DEFAULT' => !is_null($app->getLangDefault()) ? $app->getLangDefault()->getMenuName() :
'',
967 'MENU_NAME_LICENSE' => !is_null($app->getLangLicense()) ? $app->getLangLicense()->getMenuName() :
'',
969 foreach ($app->sysGetEntity()->getScalarFields() as $field)
971 $fieldName = $field->getName();
974 $appInfo[$fieldName] = $app->get($fieldName) ?
'Y' :
'N';
978 $appInfo[$fieldName] = $app->get($fieldName);
982 if (!is_null($app->getLangAll()))
984 foreach ($app->getLangAll() as $lang)
986 $appInfo[
'LANG_ALL'][$lang->getLanguageId()] = [
987 'MENU_NAME' => $lang->getMenuName(),
991 if ($appInfo[
'MENU_NAME'] ===
'')
997 if (isset($appInfo) && is_array($appInfo))
999 static::$applicationCache[$appInfo[
'ID']] = $appInfo;
1000 static::$applicationCache[$appInfo[
'CLIENT_ID']] = $appInfo;
1001 static::$applicationCache[$appInfo[
'CODE']] = $appInfo;
1005 return static::$applicationCache[$clientId];
1010 if(array_key_exists($clientId, static::$applicationCache))
1012 $app = static::$applicationCache[$clientId];
1015 unset(static::$applicationCache[$app[
'ID']]);
1016 unset(static::$applicationCache[$app[
'CLIENT_ID']]);
1020 unset(static::$applicationCache[$clientId]);
1027 if(static::$licenseLang ===
null)
1029 if(Main\Loader::includeModule(
'bitrix24'))
1031 static::$licenseLang = \CBitrix24::getLicensePrefix();
1035 $dbSites = \CSite::getList(
'sort',
'asc', array(
'DEFAULT' =>
'Y',
'ACTIVE' =>
'Y'));
1036 $site = $dbSites->fetch();
1038 static::$licenseLang = is_array($site) && isset($site[
'LANGUAGE_ID']) ? $site[
'LANGUAGE_ID'] : LANGUAGE_ID;
1041 if(static::$licenseLang ===
null)
1043 static::$licenseLang =
'en';
1047 return static::$licenseLang;
1059 new Main\
Entity\Validator\Length(
null, 128),
1060 new Main\
Entity\Validator\Unique(),
1072 new Main\
Entity\Validator\Length(
null, 128),
1073 new Main\
Entity\Validator\Unique(),
1085 new Main\
Entity\Validator\Length(
null, 1000),
1097 new Main\
Entity\Validator\Length(
null, 1000),
1109 new Main\
Entity\Validator\Length(
null, 1000),
1110 function ($value, $primary, array $row, Main\
Entity\
Field $field)
1112 $checkResult =
true;
1120 $checkResult =
false;
1125 $checkResult =
false;
1147 new Main\
Entity\Validator\Length(
null, 4),
1159 new Main\
Entity\Validator\Length(
null, 2000),
1171 new Main\
Entity\Validator\Length(
null, 32),
1183 new Main\
Entity\Validator\Length(
null, 100),
1195 new Main\
Entity\Validator\Length(
null, 1000),
1207 new Main\
Entity\Validator\Length(
null, 2000),
1217 foreach($permissionList as $key => $perm)
1219 if(in_array($perm, static::$localAppDeniedScope))
1221 unset($permissionList[$key]);
1225 return array_values($permissionList);
1237 $type = static::getAppType($code, $version);
1238 if($type == static::TYPE_CONFIGURATION)
1240 $appList = \Bitrix\Rest\Configuration\Helper::getInstance()->getBasicAppList();
1241 if(in_array($code, $appList))
1258 $cache = Cache::createInstance();
1259 if ($cache->initCache(static::CACHE_TTL,
'appType'.md5($code.$version), static::CACHE_PATH))
1261 $result = $cache->getVars();
1263 elseif ($cache->startDataCache())
1265 $appDetailInfo = Client::getInstall($code, $version);
1266 $result = ($appDetailInfo[
'ITEMS'][
'TYPE'])?:
false;
1267 $cache->endDataCache($result);
static loadMessages($file)
static getDefaultLang($lang)
static getMessage($code, $replace=null, $language=null)
static deleteByApp($appId)
static validateClientId()
static getStatusMessage($suffix, $replace=null, $checkAdmin=true, $language=null)
static canUninstallByType($code, $version=false)
static getAppType($code, $version=false)
static getAppStatusInfo($app, $detailUrl)
static onBeforeAdd(Main\Entity\Event $event)
static clearClientCache($clientId)
static onAfterDelete(Main\Entity\Event $event)
static validateUrlInstall()
static getByClientId($clientId)
static $localAppDeniedScope
static uninstall($appId, $clean=0)
static onDelete(Main\Entity\Event $event)
static getLicenseLanguage()
static onAfterUpdate(Main\Entity\Event $event)
static cleanLocalPermissionList(array $permissionList)
static validateSharedKey()
static setAccess($appId, $newRights=array())
const STATUS_SUBSCRIPTION
static onAfterAdd(Main\Entity\Event $event)
static setSkipRemoteUpdate($v)
static updateAppStatusInfo()
static callAppPaymentEvent($appId)
static validateClientSecret()
static checkCallback($handlerUrl, $appInfo=array(), $checkInstallUrl=true)
static mergeFromLangAll($data)
const PREFIX_EVENT_ON_AFTER_ADD