#Область Обработчики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", Сообщение); Возврат Результат; КонецФункции #КонецОбласти