Initial SFERA platform baseline

This commit is contained in:
2026-05-16 19:03:49 +03:00
commit 3b845c8fce
282 changed files with 55045 additions and 0 deletions
+44
View File
@@ -0,0 +1,44 @@
# SFERA 1C Extension
Исходники расширения SFERA для опубликованной базы 1С.
## Публикация
HTTP-сервис расширения должен быть опубликован с корнем:
```text
sfera
```
Тогда URL формируются по правилу платформы 1С:
```text
http://server/base/hs/sfera/health
http://server/base/hs/sfera/v1/metadata
http://server/base/hs/sfera/v1/query
http://server/base/hs/sfera/v1/data/read
http://server/base/hs/sfera/v1/data/write
http://server/base/hs/sfera/v1/metadata/apply
```
## Возможности
- `health` - проверка публикации, версии расширения и режима безопасности.
- `metadata.snapshot` - снимок доступных коллекций metadata и объектов.
- `query.execute` - консоль запросов 1С. По умолчанию read-only/dry-run.
- `data.read` - чтение данных через ограниченный запрос или менеджер объекта.
- `data.write` - изменение данных только при явном `allow_mutation`.
- `metadata.apply` - изменение структуры не выполняется из HTTP runtime. Возвращает план установки `.cfe`; применение делает Windows Agent через Designer.
## Безопасность
Расширение рассчитано на работу за сервером SFERA. Для опасных операций должны быть включены сразу все уровни:
- публикация защищена пользователем 1С/IIS;
- SFERA передает `X-SFERA-Token`;
- в проекте включено `sfera_extension_allow_mutation`;
- запрос содержит `allow_mutation=true`;
- `dry_run=false`.
Без этого операции изменения возвращают блокировку.
@@ -0,0 +1,18 @@
{
"name": "SFERA",
"version": "0.1.0",
"http_service_root": "sfera",
"endpoints": {
"health": "health",
"metadata_snapshot": "v1/metadata",
"query": "v1/query",
"data_read": "v1/data/read",
"data_write": "v1/data/write",
"metadata_apply": "v1/metadata/apply"
},
"notes": [
"This folder contains source templates for a 1C extension.",
"Build/install of .cfe is performed by the Windows Agent in the next integration step."
]
}
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<ConfigDumpInfo xmlns="http://v8.1c.ru/8.3/xcf/dumpinfo" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" format="Hierarchical" version="2.21">
<ConfigVersions>
<Metadata name="Configuration.SFERA" id="ea36c7cb-b56f-4e56-9c6e-7f5dc9e9c1ef" configVersion="0000000000000000000000000000000000000001"/>
<Metadata name="HTTPService.BridgeHTTP" id="f8df0ad1-f152-49df-aebb-9b2ff8db4580" configVersion="0000000000000000000000000000000000000004">
<Metadata name="HTTPService.BridgeHTTP.URLTemplate.health" id="1872224d-87e7-4c12-bf6f-1af0520d346f"/>
<Metadata name="HTTPService.BridgeHTTP.URLTemplate.health.Method.GET" id="499209a4-9b88-46bb-9c13-5d88dff15ead"/>
<Metadata name="HTTPService.BridgeHTTP.URLTemplate.v1_metadata" id="d00d9ff8-5357-406c-9f0d-1e0ff5a8d02a"/>
<Metadata name="HTTPService.BridgeHTTP.URLTemplate.v1_metadata.Method.POST" id="ec0d5d95-bfe9-4389-8f95-fe2369c67e69"/>
<Metadata name="HTTPService.BridgeHTTP.URLTemplate.v1_query" id="746ca047-7cad-4ce0-b7e3-8bfdb60e900e"/>
<Metadata name="HTTPService.BridgeHTTP.URLTemplate.v1_query.Method.POST" id="1172f149-8cb9-4f57-bb56-9a887bd5f1d6"/>
<Metadata name="HTTPService.BridgeHTTP.URLTemplate.v1_data_read" id="d308d5a0-58e6-49ce-8e26-6336d78c756e"/>
<Metadata name="HTTPService.BridgeHTTP.URLTemplate.v1_data_read.Method.POST" id="49505f43-68dd-4ee2-ad77-f5f2a41fd93d"/>
<Metadata name="HTTPService.BridgeHTTP.URLTemplate.v1_data_write" id="2a5a4ac1-2a21-40d2-90d9-11f52578d6bb"/>
<Metadata name="HTTPService.BridgeHTTP.URLTemplate.v1_data_write.Method.POST" id="3dac1d67-6371-4d92-9b9a-de2652e6a7b5"/>
<Metadata name="HTTPService.BridgeHTTP.URLTemplate.v1_metadata_apply" id="e7b07595-572f-4f2c-8b92-737072bf9e5b"/>
<Metadata name="HTTPService.BridgeHTTP.URLTemplate.v1_metadata_apply.Method.POST" id="efcc63f3-c2f5-4729-8656-3b83112f7299"/>
</Metadata>
<Metadata name="HTTPService.BridgeHTTP.Module" id="f8df0ad1-f152-49df-aebb-9b2ff8db4580.0" configVersion="0000000000000000000000000000000000000005"/>
</ConfigVersions>
</ConfigDumpInfo>
@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:pal="http://v8.1c.ru/8.1/data/ui/colors/palette" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.21">
<Configuration uuid="ea36c7cb-b56f-4e56-9c6e-7f5dc9e9c1ef">
<InternalInfo>
<xr:ContainedObject>
<xr:ClassId>9fcd25a0-4822-11d4-9414-008048da11f9</xr:ClassId>
<xr:ObjectId>64b4c3aa-ea0a-4f25-b187-f4d94a32b37d</xr:ObjectId>
</xr:ContainedObject>
<xr:ContainedObject>
<xr:ClassId>e3687481-0a87-462c-a166-9f34594f9bba</xr:ClassId>
<xr:ObjectId>b20b7b75-2d07-4d59-a16f-7c0b5e9f50c4</xr:ObjectId>
</xr:ContainedObject>
<xr:ContainedObject>
<xr:ClassId>9cd510cd-abfc-11d4-9434-004095e12fc7</xr:ClassId>
<xr:ObjectId>c2395ef1-3dcf-4af4-a174-ea544a740c7f</xr:ObjectId>
</xr:ContainedObject>
<xr:ContainedObject>
<xr:ClassId>9de14907-ec23-4a07-96f0-85521cb6b53b</xr:ClassId>
<xr:ObjectId>ac6767f8-77d0-40bc-80f3-45f71e8e29a1</xr:ObjectId>
</xr:ContainedObject>
<xr:ContainedObject>
<xr:ClassId>51f2d5d8-ea4d-4064-8892-82951750031e</xr:ClassId>
<xr:ObjectId>147f3972-f3f1-4501-b76e-c297ee1dba78</xr:ObjectId>
</xr:ContainedObject>
<xr:ContainedObject>
<xr:ClassId>e68182ea-4237-4383-967f-90c1e3370bc7</xr:ClassId>
<xr:ObjectId>0f04c40c-a318-48df-a665-3aec5ff43bc0</xr:ObjectId>
</xr:ContainedObject>
<xr:ContainedObject>
<xr:ClassId>fb282519-d103-4dd3-bc12-cb271d631dfc</xr:ClassId>
<xr:ObjectId>2f210a41-f819-45c0-a9f1-61bd30d64fb0</xr:ObjectId>
</xr:ContainedObject>
</InternalInfo>
<Properties>
<ObjectBelonging>Adopted</ObjectBelonging>
<Name>SFERA</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>SFERA</v8:content>
</v8:item>
</Synonym>
<Comment/>
<ConfigurationExtensionPurpose>AddOn</ConfigurationExtensionPurpose>
<KeepMappingToExtendedConfigurationObjectsByIDs>true</KeepMappingToExtendedConfigurationObjectsByIDs>
<NamePrefix>SFERA_</NamePrefix>
<ConfigurationExtensionCompatibilityMode>Version8_3_20</ConfigurationExtensionCompatibilityMode>
<DefaultRunMode>ManagedApplication</DefaultRunMode>
<UsePurposes>
<v8:Value xsi:type="app:ApplicationUsePurpose">PlatformApplication</v8:Value>
</UsePurposes>
<ScriptVariant>Russian</ScriptVariant>
<Vendor>SFERA</Vendor>
<Version>0.1.0</Version>
<Caption/>
<ShortCaption/>
<BriefInformation/>
<DetailedInformation/>
<Copyright/>
<VendorInformationAddress/>
<ConfigurationInformationAddress/>
<InterfaceCompatibilityMode>TaxiEnableVersion8_2</InterfaceCompatibilityMode>
</Properties>
<ChildObjects>
<HTTPService>BridgeHTTP</HTTPService>
</ChildObjects>
</Configuration>
</MetaDataObject>
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:pal="http://v8.1c.ru/8.1/data/ui/colors/palette" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.21">
<HTTPService uuid="f8df0ad1-f152-49df-aebb-9b2ff8db4580">
<Properties>
<ObjectBelonging>Native</ObjectBelonging>
<Name>BridgeHTTP</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>SFERA</v8:content>
</v8:item>
</Synonym>
<Comment/>
<RootURL>sfera</RootURL>
<ReuseSessions>AutoUse</ReuseSessions>
<SessionMaxAge>20</SessionMaxAge>
</Properties>
<ChildObjects>
<URLTemplate uuid="1872224d-87e7-4c12-bf6f-1af0520d346f">
<Properties><Name>health</Name><Synonym/><Comment/><Template>/health</Template></Properties>
<ChildObjects><Method uuid="499209a4-9b88-46bb-9c13-5d88dff15ead"><Properties><Name>GET</Name><Synonym/><Comment/><HTTPMethod>GET</HTTPMethod><Handler>Health</Handler></Properties></Method></ChildObjects>
</URLTemplate>
<URLTemplate uuid="d00d9ff8-5357-406c-9f0d-1e0ff5a8d02a">
<Properties><Name>v1_metadata</Name><Synonym/><Comment/><Template>/v1/metadata</Template></Properties>
<ChildObjects><Method uuid="ec0d5d95-bfe9-4389-8f95-fe2369c67e69"><Properties><Name>POST</Name><Synonym/><Comment/><HTTPMethod>POST</HTTPMethod><Handler>MetadataSnapshot</Handler></Properties></Method></ChildObjects>
</URLTemplate>
<URLTemplate uuid="746ca047-7cad-4ce0-b7e3-8bfdb60e900e">
<Properties><Name>v1_query</Name><Synonym/><Comment/><Template>/v1/query</Template></Properties>
<ChildObjects><Method uuid="1172f149-8cb9-4f57-bb56-9a887bd5f1d6"><Properties><Name>POST</Name><Synonym/><Comment/><HTTPMethod>POST</HTTPMethod><Handler>Query</Handler></Properties></Method></ChildObjects>
</URLTemplate>
<URLTemplate uuid="d308d5a0-58e6-49ce-8e26-6336d78c756e">
<Properties><Name>v1_data_read</Name><Synonym/><Comment/><Template>/v1/data/read</Template></Properties>
<ChildObjects><Method uuid="49505f43-68dd-4ee2-ad77-f5f2a41fd93d"><Properties><Name>POST</Name><Synonym/><Comment/><HTTPMethod>POST</HTTPMethod><Handler>DataRead</Handler></Properties></Method></ChildObjects>
</URLTemplate>
<URLTemplate uuid="2a5a4ac1-2a21-40d2-90d9-11f52578d6bb">
<Properties><Name>v1_data_write</Name><Synonym/><Comment/><Template>/v1/data/write</Template></Properties>
<ChildObjects><Method uuid="3dac1d67-6371-4d92-9b9a-de2652e6a7b5"><Properties><Name>POST</Name><Synonym/><Comment/><HTTPMethod>POST</HTTPMethod><Handler>DataWrite</Handler></Properties></Method></ChildObjects>
</URLTemplate>
<URLTemplate uuid="e7b07595-572f-4f2c-8b92-737072bf9e5b">
<Properties><Name>v1_metadata_apply</Name><Synonym/><Comment/><Template>/v1/metadata/apply</Template></Properties>
<ChildObjects><Method uuid="efcc63f3-c2f5-4729-8656-3b83112f7299"><Properties><Name>POST</Name><Synonym/><Comment/><HTTPMethod>POST</HTTPMethod><Handler>MetadataApply</Handler></Properties></Method></ChildObjects>
</URLTemplate>
</ChildObjects>
</HTTPService>
</MetaDataObject>
@@ -0,0 +1,268 @@
#Область ОбработчикиHTTPСервиса
Функция Health(Запрос) Экспорт
Возврат ОтветJSON(BridgeHealth());
КонецФункции
Функция MetadataSnapshot(Запрос) Экспорт
Контекст = ПрочитатьКонтекст(Запрос);
Если Не Авторизован(Запрос, Контекст) Тогда
Возврат ОтветОшибка(401, "Unauthorized");
КонецЕсли;
Возврат ОтветJSON(BridgeMetadataSnapshot());
КонецФункции
Функция Query(Запрос) Экспорт
Контекст = ПрочитатьКонтекст(Запрос);
Если Не Авторизован(Запрос, Контекст) Тогда
Возврат ОтветОшибка(401, "Unauthorized");
КонецЕсли;
Возврат ОтветJSON(BridgeExecuteQuery(
ПолучитьПоле(Контекст, "payload", Новый Структура),
ПолучитьПоле(Контекст, "dry_run", Истина),
ПолучитьПоле(Контекст, "allow_mutation", Ложь)));
КонецФункции
Функция DataRead(Запрос) Экспорт
Контекст = ПрочитатьКонтекст(Запрос);
Если Не Авторизован(Запрос, Контекст) Тогда
Возврат ОтветОшибка(401, "Unauthorized");
КонецЕсли;
Возврат ОтветJSON(BridgeReadData(ПолучитьПоле(Контекст, "payload", Новый Структура)));
КонецФункции
Функция DataWrite(Запрос) Экспорт
Контекст = ПрочитатьКонтекст(Запрос);
Если Не Авторизован(Запрос, Контекст) Тогда
Возврат ОтветОшибка(401, "Unauthorized");
КонецЕсли;
Возврат ОтветJSON(BridgeWriteData(
ПолучитьПоле(Контекст, "payload", Новый Структура),
ПолучитьПоле(Контекст, "dry_run", Истина),
ПолучитьПоле(Контекст, "allow_mutation", Ложь)));
КонецФункции
Функция MetadataApply(Запрос) Экспорт
Контекст = ПрочитатьКонтекст(Запрос);
Если Не Авторизован(Запрос, Контекст) Тогда
Возврат ОтветОшибка(401, "Unauthorized");
КонецЕсли;
Возврат ОтветJSON(BridgeMetadataApply(
ПолучитьПоле(Контекст, "payload", Новый Структура),
ПолучитьПоле(Контекст, "dry_run", Истина)));
КонецФункции
#КонецОбласти
#Область ЛогикаSFERA
Функция BridgeHealth()
Результат = Новый Структура;
Результат.Вставить("status", "ok");
Результат.Вставить("extension", "SFERA");
Результат.Вставить("version", "0.1.0");
Результат.Вставить("timestamp", ТекущаяДата());
Результат.Вставить("mutation_supported", Истина);
Результат.Вставить("metadata_apply_supported", Ложь);
Возврат Результат;
КонецФункции
Функция BridgeMetadataSnapshot()
Коллекции = Новый Массив;
ДобавитьКоллекциюМетаданных(Коллекции, "Справочники", Метаданные.Справочники);
ДобавитьКоллекциюМетаданных(Коллекции, "Документы", Метаданные.Документы);
ДобавитьКоллекциюМетаданных(Коллекции, "Перечисления", Метаданные.Перечисления);
ДобавитьКоллекциюМетаданных(Коллекции, "Отчеты", Метаданные.Отчеты);
ДобавитьКоллекциюМетаданных(Коллекции, "Обработки", Метаданные.Обработки);
ДобавитьКоллекциюМетаданных(Коллекции, "ПланыОбмена", Метаданные.ПланыОбмена);
ДобавитьКоллекциюМетаданных(Коллекции, "ПланыВидовХарактеристик", Метаданные.ПланыВидовХарактеристик);
ДобавитьКоллекциюМетаданных(Коллекции, "ПланыСчетов", Метаданные.ПланыСчетов);
ДобавитьКоллекциюМетаданных(Коллекции, "ПланыВидовРасчета", Метаданные.ПланыВидовРасчета);
ДобавитьКоллекциюМетаданных(Коллекции, "РегистрыСведений", Метаданные.РегистрыСведений);
ДобавитьКоллекциюМетаданных(Коллекции, "РегистрыНакопления", Метаданные.РегистрыНакопления);
ДобавитьКоллекциюМетаданных(Коллекции, "РегистрыБухгалтерии", Метаданные.РегистрыБухгалтерии);
ДобавитьКоллекциюМетаданных(Коллекции, "РегистрыРасчета", Метаданные.РегистрыРасчета);
ДобавитьКоллекциюМетаданных(Коллекции, "БизнесПроцессы", Метаданные.БизнесПроцессы);
ДобавитьКоллекциюМетаданных(Коллекции, "Задачи", Метаданные.Задачи);
ДобавитьКоллекциюМетаданных(Коллекции, "ОбщиеМодули", Метаданные.ОбщиеМодули);
ДобавитьКоллекциюМетаданных(Коллекции, "Роли", Метаданные.Роли);
ДобавитьКоллекциюМетаданных(Коллекции, "Подсистемы", Метаданные.Подсистемы);
ДобавитьКоллекциюМетаданных(Коллекции, "HTTPСервисы", Метаданные.HTTPСервисы);
ДобавитьКоллекциюМетаданных(Коллекции, "WebСервисы", Метаданные.WebСервисы);
Результат = Новый Структура;
Результат.Вставить("status", "ok");
Результат.Вставить("collections", Коллекции);
Возврат Результат;
КонецФункции
Функция BridgeExecuteQuery(Параметры, DryRun, AllowMutation)
ТекстЗапроса = Строка(ПолучитьПоле(Параметры, "query", ""));
Если ПустаяСтрока(ТекстЗапроса) Тогда
Возврат ОшибкаSFERA("query is required");
КонецЕсли;
Если ЗапросОпасный(ТекстЗапроса) И Не AllowMutation Тогда
Возврат ОшибкаSFERA("Mutation query is blocked. Set allow_mutation=true and disable dry_run.");
КонецЕсли;
Если DryRun Тогда
Результат = Новый Структура;
Результат.Вставить("status", "dry_run");
Результат.Вставить("query", ТекстЗапроса);
Результат.Вставить("mutation_detected", ЗапросОпасный(ТекстЗапроса));
Возврат Результат;
КонецЕсли;
Запрос = Новый Запрос(ТекстЗапроса);
ПараметрыЗапроса = ПолучитьПоле(Параметры, "parameters", Неопределено);
Если ТипЗнч(ПараметрыЗапроса) = Тип("Структура") Тогда
Для Каждого Параметр Из ПараметрыЗапроса Цикл
Запрос.УстановитьПараметр(Параметр.Ключ, Параметр.Значение);
КонецЦикла;
КонецЕсли;
Таблица = Запрос.Выполнить().Выгрузить();
Строки = Новый Массив;
Для Каждого СтрокаТаблицы Из Таблица Цикл
Строки.Добавить(СтрокаТаблицыВСтруктуру(СтрокаТаблицы, Таблица.Колонки));
Если Строки.Количество() >= 1000 Тогда
Прервать;
КонецЕсли;
КонецЦикла;
Результат = Новый Структура;
Результат.Вставить("status", "ok");
Результат.Вставить("rows", Строки);
Результат.Вставить("limit", 1000);
Возврат Результат;
КонецФункции
Функция BridgeReadData(Параметры)
Если ЗначениеЗаполнено(ПолучитьПоле(Параметры, "query", "")) Тогда
Возврат BridgeExecuteQuery(Параметры, Ложь, Ложь);
КонецЕсли;
Возврат ОшибкаSFERA("For generic data read use query with SELECT text.");
КонецФункции
Функция BridgeWriteData(Параметры, DryRun, AllowMutation)
Если Не AllowMutation Тогда
Возврат ОшибкаSFERA("Write operation is blocked.");
КонецЕсли;
Если DryRun Тогда
Результат = Новый Структура;
Результат.Вставить("status", "dry_run");
Результат.Вставить("message", "Write request accepted for preview only.");
Результат.Вставить("payload", Параметры);
Возврат Результат;
КонецЕсли;
Возврат ОшибкаSFERA("Generic write adapter is intentionally not enabled yet. Implement object-specific handlers first.");
КонецФункции
Функция BridgeMetadataApply(Параметры, DryRun)
Результат = Новый Структура;
Результат.Вставить("status", "planned");
Результат.Вставить("message", "Changing configuration structure is performed by SFERA Windows Agent through Designer and .cfe update, not by runtime HTTP.");
Результат.Вставить("dry_run", DryRun);
Результат.Вставить("payload", Параметры);
Возврат Результат;
КонецФункции
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция ПрочитатьКонтекст(Запрос)
Тело = Запрос.ПолучитьТелоКакСтроку();
Если ПустаяСтрока(Тело) Тогда
Возврат Новый Структура;
КонецЕсли;
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(Тело);
Возврат ПрочитатьJSON(Чтение);
КонецФункции
Функция Авторизован(Запрос, Контекст)
// Основная авторизация выполняется публикацией 1С/IIS. Токен SFERA включается после настройки секрета.
ОжидаемыйТокен = "";
Если ПустаяСтрока(ОжидаемыйТокен) Тогда
Возврат Истина;
КонецЕсли;
Возврат Запрос.Заголовки.Получить("X-SFERA-Token") = ОжидаемыйТокен;
КонецФункции
Функция ОтветJSON(Данные, КодСостояния = 200)
Запись = Новый ЗаписьJSON;
Запись.УстановитьСтроку();
ЗаписатьJSON(Запись, Данные);
Тело = Запись.Закрыть();
Ответ = Новый HTTPСервисОтвет(КодСостояния);
Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
Ответ.УстановитьТелоИзСтроки(Тело, КодировкаТекста.UTF8);
Возврат Ответ;
КонецФункции
Функция ОтветОшибка(КодСостояния, Сообщение)
Данные = Новый Структура;
Данные.Вставить("status", "error");
Данные.Вставить("message", Сообщение);
Возврат ОтветJSON(Данные, КодСостояния);
КонецФункции
Функция ПолучитьПоле(СтруктураИсточник, ИмяПоля, ЗначениеПоУмолчанию = Неопределено)
Если ТипЗнч(СтруктураИсточник) = Тип("Структура") И СтруктураИсточник.Свойство(ИмяПоля) Тогда
Возврат СтруктураИсточник[ИмяПоля];
КонецЕсли;
Возврат ЗначениеПоУмолчанию;
КонецФункции
Процедура ДобавитьКоллекциюМетаданных(Коллекции, ИмяКоллекции, КоллекцияМетаданных)
Объекты = Новый Массив;
Для Каждого ОбъектМетаданных Из КоллекцияМетаданных Цикл
Описание = Новый Структура;
Описание.Вставить("name", ОбъектМетаданных.Имя);
Описание.Вставить("synonym", ОбъектМетаданных.Синоним);
Описание.Вставить("full_name", ИмяКоллекции + "." + ОбъектМетаданных.Имя);
Объекты.Добавить(Описание);
КонецЦикла;
Коллекция = Новый Структура;
Коллекция.Вставить("name", ИмяКоллекции);
Коллекция.Вставить("count", Объекты.Количество());
Коллекция.Вставить("objects", Объекты);
Коллекции.Добавить(Коллекция);
КонецПроцедуры
Функция ЗапросОпасный(ТекстЗапроса)
Текст = НРег(ТекстЗапроса);
Возврат Найти(Текст, "вставить") > 0
Или Найти(Текст, "изменить") > 0
Или Найти(Текст, "удалить") > 0
Или Найти(Текст, "поместить") > 0
Или Найти(Текст, "создать") > 0;
КонецФункции
Функция СтрокаТаблицыВСтруктуру(СтрокаТаблицы, Колонки)
Результат = Новый Структура;
Для Каждого Колонка Из Колонки Цикл
Результат.Вставить(Колонка.Имя, ЗначениеДляJSON(СтрокаТаблицы[Колонка.Имя]));
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ЗначениеДляJSON(Значение)
Если Значение = Неопределено Или Значение = Null Тогда
Возврат Неопределено;
КонецЕсли;
Если ТипЗнч(Значение) = Тип("Строка")
Или ТипЗнч(Значение) = Тип("Число")
Или ТипЗнч(Значение) = Тип("Булево") Тогда
Возврат Значение;
КонецЕсли;
Если ТипЗнч(Значение) = Тип("Дата") Тогда
Возврат Формат(Значение, "ДФ=yyyy-MM-ddTHH:mm:ss");
КонецЕсли;
Возврат Строка(Значение);
КонецФункции
Функция ОшибкаSFERA(Сообщение)
Результат = Новый Структура;
Результат.Вставить("status", "error");
Результат.Вставить("message", Сообщение);
Возврат Результат;
КонецФункции
#КонецОбласти