Возможность запуска выполнения кода внутри Тотум путем обращения стороннего скрипта на адрес Remotes.
Настраивается через таблицу Системные таблицы — API — Remotes.
Вызов осуществляется обращением по адресу хост/Remotes/name_action
.
Обращение к модулю происходит по адресу host/Remotes/name_action
, где name_action
— name в таблице Remotes.
name_action
должен полностью совпадать в таблице remotes и в запросе. Запросhost/Remotes/name_action/
(со/
на конце предполагает, что в таблице remotesname
будет указан также со/
на конце).
Для того, чтобы код из строки в Remotes запускался на выполнение, чекбокс Включено
должен быть в true
и пользователь remotes_user
должен быть заполнен.
Можно выбрать динамического пользователя, тогда id пользователя надо передать в
GET
переменнуюttm_user
сid
пользователя в системе от которого нужно выполнить этот ремоут.
Код из code
будет выполнен от имени пользователя, указанного в remotes_user
.
Обращение может происходить по GET или POST. В code
при выполнении будут переданы переменные:
$#get — row из переменных, переданных в GET.
$#post — row из переменных, переданных в POST при использовании application/x-www-form-urlencoded
или multipart/form-data
в заголовке Content-Type
запроса HTTP.
$#input — строка или null — необработанные данные из тела запроса при передаче POST в raw-data.
$#headers — row из заголовков HTTP-запроса.
$#remoteIp — ip
входящего запроса.
$#method — доступен в PRO — содержит метод запроса.
$#path — доступен в PRO — содержит список из элементов пути пришедшего запроса.
Ответ возвращается в зависимости от настройки Возврат
:
success/error — возвращается success
, либо error
, если в процессе выполнения были ошибки. Текст ошибки не выводится.
200/500 — аналогично success/error
, только возвращается код ответа сервера в заголовках.
json — ответ скрипта переводится в JSON
. Если возникла ошибка, возвращается {"error":"Текст ошибки"}
.
строка — ответ скрипта возвращается в тело ответа без обработки.
headers + body — в ответе скрипта ожидается row с ключами headers
— отправляются в качестве HTTP-заголовков ответа и body
— выводится в тело ответа.
headers
надо передать список заголовков или row
. Если row
, то каждая строка будет форматирована как key + ':' + value
.В PRO возможна активация поля path
— в этом случае указанный name
становится приоритетным.
Если есть несколько ремоутов использующие один и тот же путь с разными окончаниями — они будут неактивны:
some_name
+ #path = true
— включение path
делает этот ремоут основным. Запрос на .../Remotes/some_name/
тоже будет обработан с пустой переменной $#path
.
some_name/action/param
— если есть ремоут с таким путем то его строка станет неактивной. Если придет запрос по такому пути выполнится ремоут в строке some_name
+ #path = true
.
Когда включен параметр path
, все уровни запроса будут переданы в переменную $#path
в виде списка с сохранением последовательности. То есть при запросе .../Remotes/some_name/action/param
переменная будет содержать список из двух значений: ["action","param"]
.
Если вам нужно скрыть при использовании Remotes, JSON-API, анонимных таблиц или форм основной хост вашей системы то используется shadow-host
.
Необходимо адресовать DNS хоста на тот-же сервер, на котором размещен Totum.
Открыть настройки nginx
по пути /etc/nginx/sites-available/totum.online.conf
и явно прописать основной домен в секциях ssl
и 80
порта в параметре server_name
: server_name _;
—› server_name YOUR_MAIN_DOMAIN;
. Сохранить и перезапустить nginx
.
Скопировать конфиг основного домена и указать в нем дополнительный домен в секциях ssl
и 80
порта.
Получить сертификат SSL
для дополнительного домена:
certbot certonly --dry-run -d YOUR_ADDITIONAL_DOMAIN.ZONE
Если --dry-run
проходит то
certbot certonly -d YOUR_DOMAIN.ZONE
Прописываем адрес сертификата в дополнительном конфиге nginx
.
Активируем конфиг:
ln -s /etc/nginx/sites-available/YOUR_ADDITIONAL_DOMAIN.conf /etc/nginx/sites-enabled/YOUR_ADDITIONAL_DOMAIN.conf
Рестартуем nginx
.
Открываем конфиг Totum и добавляем секцию shadow-host
:
nano /home/totum/totum-mit/Conf.php
/***getHiddenHosts***/
public function getHiddenHosts():array {
return array ('hidden.ttmapp.ru' => array (
'An' => true,
'Remotes' => true,
'Json' => true,
'Forms' => true,
),
);
}
/***getHiddenHostsEnd***/
Можно задать разные хосты для разных модулей.
Для shadow-host
можно задать кастомный язык
/***getHiddenHosts***/
public function getHiddenHosts():array {
return array ('hidden.ttmapp.ru' => array (
'An' => ["lang"=>"es"],
),
);
}
/***getHiddenHostsEnd***/
// В этом случае на hidden.ttmapp.ru будут работать только Анонимные таблицы на Испанском
Обращение к API осуществляется через POST по адресу http(s)://domain.ru/Json/
.
Если вызываются только секции auth
и remotes
задавать путь к таблице не нужно — обращение осуществляется по адресу http(s)://domain.ru/Json/
В случае, если требуется работать с таблицей используя секции import/export/recalculate
, таблица задается как:
/Json/{id таблицы} — для всех таблиц, кроме расчетных в цикле.
/Json/{id циклической таблицы}/{id цикла}/{id расчетной таблицы} — для расчетных таблиц в цикле.
Пути аналогичны web-интерфейсу без положения в дереве.
Для подключения к API должен быть создан пользователь с интерфейсом api
в таблице пользователей. Пользователь должен иметь необходимые права на таблицу.
Логин и пароль этого пользователя должны передаваться в секцию auth
входящего JSON.
{
"auth": {
"login": "json",
"password": "1111"
}
}
Входящий JSON передается в теле POST-запроса.
Обязательная секция auth
— содержит логин и пароль.
Доступ предоставляется пользователю с интерфейсом api
при наличии доступа к вызываемой таблице. Логика доступов в циклы cycles_access_type не действует.
Для манипуляций с полем через API у поля должна быть включена опция Показывать в API и в случае наличия ограничений в Видно ролям в API должна быть указана роль api-пользователя от которого идет подключение.
Для изменения поля через API для поля должно быть включено Редактируемое в API и в случае наличия ограничений в Редактирование в API доступно ролям должна быть указана роль от которой идет подключение.
import — cекция отвечает за внесение изменений в таблицу (возможно, при наличии у пользователя роли с редактированием этой таблицы). Ограничения которые могут быть установлены для роли в префильтре в API на изменение не действуют! Поэтому в целях безопасности внимательно устанавливайте разрешения для ролей в Редактирование в API доступно ролям. Если вы хотите добавить строчные ограничения, сделайте это через errorExeption.
footer и header — изменить значения полей хедера и футера можно через соответствующие секции передав "name": new_value
.
{
"import": {
"header": {
"h_title": "Изменение заголовка"
}
}
}
{
"import": {
"footer": {
"__clears": [
"f_field",
"f_field2"
]
}
}
}
{
"import": {
"footer": {
"__pins": [
"f_field",
"f_field2"
]
}
}
}
rows — секция для изменения строк по их id.
modify — изменение значений полей. Передается как объект с ключом id-строки и значениями: name поля, значение "2": {"row_field": new value}
и/или список полей в __pins
, __clears
для закрепления/открепления значений.
add — список добавляемых строк содержащий name полей и их значения для каждой добавляемой строки.
remove — список id удаляемых строк.
{
"rows": {
"modify": {
"2": {
"name_field": "new value",
"__pins": [
"name_field_pin"
]
},
"3": {
"name_field": "new value"
}
},
"add": [
{
"name_field": "added_value_in_row1"
},
{
"name_field": "added_value_in_row2"
}
],
"remove": []
}
}
rows-set-where — изменить/добавить/удалить строки в строчной части таблицы по условиям. В одном запросе может быть передано несколько разных изменений по разным условиям.
set — содержит данные для изменения в формате "name": new_value
, и/или name полей в __pins и __clear если это необходимо.
where — список условий:
{
"import": {
"rows-set-where": [
{
"where": [
{
"field": "id",
"value": "test",
"operator": "="
}
],
"set": {
"test": true,
"__pins": [
"some_field_name"
]
}
}
]
}
}
recalculate — принимает список условий для выборки строк для пересчета в простых таблицах. В расчетных таблицах эту секцию можно не вызывать — пересчет происходит при каждом обращении через API к таблице.
{
"recalculate": [
{
"field": "id",
"operator": "=",
"value": [
1,
2,
3
]
}
}
remotes — секция для вызова исполняемых конструкций из таблицы ttm__remotes.
auth
, в поле API user
и стоять галочка в Включено
.$#data
кода ремоута.{
"remotes": [
{"name":"remote1", "data": {"var1": 1, "var2": [1,2,3]}},
{"name":"remote2", "data": {"var1": 2, "var2": [3,2,5]}}
]
}
export — секция для управления возвращаемыми значениями. Ограничения которые могут быть установлены для роли в префильтре действуют в API на экспорт! Поле префильтра должно быть доступно в Показывать в API и должно быть разрешение в Видно ролям в API.
fields — список полей для возврата.
filters — задаваемые значения фильтров. Фильры расчитываются аналогично веб-версии. Доступна выборка по id без префильтра по id. Если в API выведен префильтр запрещающий показ контретной строки по id, то она показана не будет.
{
"export": {
"fields": [
"id",
"some_field_name"
],
"filters": {
"fl_filter": [
"value1",
"value2",
"value3"
],
"id": [
2
]
}
}
}
Пример входящего JSON:
{
"export": {
"fields": [
"id",
"some_field_name"
],
"filters": {
"id": [
1,
2,
3
]
}
},
"auth": {
"login": "json",
"password": "1111"
},
"import": {
"rows-set-where": [
{
"where": {
"field": "id",
"value": "test",
"operator": "="
},
"set": {
"test": true,
"__pins": [
"some_field_name"
]
}
}
],
"header": {
"__pins": [
"some_field_name"
],
"__clears": [
"some_field_name"
],
"test": "Тестовая строка"
},
"footer": {
"__pins": [
"f_sum"
],
"__clears": [
"f_sum2"
]
},
"rows": {
"modify": {
"2": {
"row_field": "new value",
"__pins": [
"some_field_name"
]
},
"3": {
"rowField": "new value"
}
},
"add": [],
"remove": []
}
},
"recalculate": [
{
"field": "id",
"operator": "=",
"value": [
1,
2,
3
]
}
]
}
В случае возникновения ошибки возвращается JSON вида:
{
"error": 5,
"errorDescription": "Пользователь с такими данными не найден. Возможно, ему не включен доступ к xml/json-интерфейсу"
}
Если запрос был выполнен без ошибок, то в случае обращения к таблице вернется время ее последнего изменения:
{
"updated": "2019-08-19 14:56"
}
Если была задана секция remotes:
Список возвращаемых элементов в секции соответствует списку вызванных ремоутов:
{
"remotes": [
null,
[1,2,3],
{"a":1, "b":2}
]
}
Если таблица была изменена:
{
"updated": "2019-08-20 16:01",
"changed": true
}
Если была задана секция export:
{
"export": {
"rows": [
{
"id": 1,
"test": "значение поля test 1"
},
{
"id": 52,
"test": "значение поля test 52"
}
],
"header": {
"test": "testtest"
}
},
"updated": "2019-08-20 16:01"
}
Это пример добавления данных через JSON-API:
<?php
$input=[];
$input['auth']=[
'login'=>"login-api-user", //Логин пользователя API подключенного к таблице
'password'=>"password-api-user" // Пароль этого пользователя
];
$input["import"]["add"]=[];
$numberVar = 1111;
$input["import"]["rows"]["add"][]=[
'data'=>[
"test1" => 12345,
"test2" => [1, 2, 3, 4, 5],
"test3" => "Тут текст",
"test4" => $numberVar
]
];
/*Внимание в настройках этих полей в ТОТУМ должен быть включен доступ в API и разрешено добавление в API */
$params = array('http' => array(
'method' => 'POST',
'header' => 'Content-type: application/json',
'content' => json_encode($input, JSON_UNESCAPED_UNICODE)
), "ssl" => array(
"verify_peer" => false,
"verify_peer_name" => false,
));
echo file_get_contents("https://totum.host.ru/Json/652", // число - ид таблицы, смотри в адресной строке web-интерфейса или в таблице Список таблиц
false,
stream_context_create($params));
В таком варианте срабатывают триггеры добавления и расчитываются коды.
Такая реализация модели обеспечивает запуск внутренних триггеров действий в Totum.
<?php
use totum\common\Auth;
use totum\common\Totum;
use totum\config\Conf;
require '../vendor/autoload.php';
/*Если приходит закодированные данные - сначала раскодируйте их*/
$encoded = json_encode(["v" => "Проверка"]);
$decoded = json_decode($encoded, true)["v"];
/*Подключаемся к ТОТУМ*/
$Conf = new Conf();
$Conf->setHostSchema(null, 'totum-copy'); // Требуется указать схему, если установка multi
$User = Auth::loadAuthUserByLogin($Conf, 'loginapiuser', false); //Пользователь, от которого будут проведены изменения
/* Запускаем Totum, передавая ему конфиг и юзер */
$Totum = new Totum($Conf, $User);
$Totum->transactionStart();
try {
/*Получаем таблицу изменения*/
$Table = $Totum->getTable('652'); //Получение таблицы Тотум (по id или name)
/*Вызов пересчета таблицы с добавлением строки*/
$Table->actionInsert([
"data" => ["test" => $decoded, "test2" => "Тестовая строка2"],
"price" => 120,
"special" => true
]);
$Totum->transactionCommit();
} catch (\Exception $errorException) {
echo 'Ошибка. Ничего не сохранено: '.$errorException->getMessage();
}
Класс aTable
предоставляет набор доступных действий над таблицей:
$Table->actionInsert(... params ...)
- вставка одной или нескольких строк.
$Table->actionSet(... params ...)
— изменение в параметрах либо строках.
$Table->actionDuplicate(... params ...)
— дублирование строк.
$Table->actionDelete(... params ...)
— удаление строк.
$Table->actionClear(... params ...)
— открепление ручных значений.
$Table->actionPin(... params ...)
—- закрепление ручных значений.
Вы можете найти их пременение в коде класса calculates/CalculateAction
.
Можно выполнить любой произвольный тотум-код при помощи классов из папки totum/common/calculates
пример реализации — функция moduls/Table/ReadTableActions::click()
В модуле Table
(папка totum/moduls/Table) реализованы в классах Actions -> ReadTableActions -> WriteTableActions -> AdminTableActions
с учетом прав доступа к таблице все возможные в настоящий момент действия.
При таком добавлении НЕ СРАБАТЫВАЮТ триггеры действий на добавление и расчет кодов.
Использовать только в крайнем случае для случаев, когда требуется очень большая производительность!**
<?php
use totum\config\Conf;
require '../vendor/autoload.php';
$Conf=new Conf();
$Conf->setHostSchema(null, 'totum-copy'); // Требуется указать схему, если установка multi
$PDO = $Conf->getSql()->getPDO(); // Возвращается стандартный класс php PDO
/*ТЕСТОВЫЕ ДАННЫЕ*/
$userID = 111;
$offer = 12121;
$numberVar = 1212;
$data = [
'special'=>true,
'price'=>12.23,
'promo'=>"Промокод'",
'payType'=>"test",
'refer'=>false,
];
/* Кладем в таблицу test_payments в соответствующие поля*/
$PDO->exec('INSERT INTO test_payments (created, user_id, offer, data, special, price, promo, pay_type, refer)' .
' VALUES ('
. 'jsonb_build_object($$v$$, ' . $PDO->quote(date('Y-m-d H:i')) . '),'
. 'jsonb_build_object($$v$$, ' . $PDO->quote($userID) . '),'
. 'JSONB_BUILD_OBJECT($$v$$, ' . $PDO->quote($offer ?? null) . '),'
. $PDO->quote(
json_encode(['v' => [
"test1" => 12345,
"test2" => [1, 2, 3, 4, 5],
"test3" => "Тут текст",
"test4" => $numberVar
]
],
JSON_UNESCAPED_UNICODE)
) . ','
. 'JSONB_BUILD_OBJECT($$v$$, ' . (!empty($data['special']) ? 'true' : 'false') . '),'
. 'JSONB_BUILD_OBJECT($$v$$, ' . (!empty($data['price']) ? $data['price'] : 'null') . '),'
. 'JSONB_BUILD_OBJECT($$v$$, ' . (!empty($data['promo']) ? $PDO->quote($data['promo']) : 'null') . '),'
. 'JSONB_BUILD_OBJECT($$v$$, ' . (!empty($data['payType']) ? $PDO->quote($data['payType']) : 'null') . '),'
. 'JSONB_BUILD_OBJECT($$v$$, ' . (($data['refer'] ?? null) === "true" ? 'true' : 'false') . ')'
. ') RETURNING id');