⟵ сюдатуда ⟶
  • Установка
  • Установка на Ubuntu
  • Обновления
  • Установка PRO
  • Бэкапы
  • Multi/no-multi
  • Консольная утилита bin/totum
  • Основы для пользователей
  • Интерфейс и компоновка
  • Таблицы и их параметры
  • Префильтр
  • Поля и их параметры
  • Синтаксис
  • Код, действия, форматирование
  • Реляционные взаимосвязи
  • Порядок расчета и единицы пересчета
  • Сравнения
  • Функции
  • Отладка
  • Автозаполнение расчетных и временных
  • Дублирование строк и циклов
  • Печать и CSV
  • API
  • REMOTES
  • Remotes
  • Модуль remotes
  • PRO Пути
  • Shadow Hosts
  • JSON
  • Подключение
  • Входящий JSON
  • Возвращаемый JSON
  • Пример вызова JSON-API на PHP
  • Собственный API-модуль
  • Модуль API на PHP
  • База данных
  • Запись напрямую в pgsql
  • Роли и пользователи
  • Нотификации
  • Действия по расписанию
  • Системные таблицы
  • Дополнительные интерфейсы
  • Структура файлов
  • Структура базы
  • [PRO] Деревья
  • [PRO] Анонимные таблицы
  • [PRO] Внешние формы
  • [PRO] Экспорт и импорт таблиц
  • [PRO] MeiliSearch
  • [PRO] Базы данных
  • [PRO] Настройка CSS
  • [PRO] Custom docs
  • [PRO] LDAP AD
  • [PRO] Версии файлов
  • [PRO] List-unsubscribe
  • [PRO] Динамические поля
  • [PRO] Only Office
  • [PRO] Auth Tokens
  • [PRO] 2FA
  • [PRO] Superlang
  • [PRO] Profiler
  • [PRO] Подключение функций
  • [SRV] Подключение
  • [SRV] Пользовательские возможности
  • [SRV] XLSX/DOCX генераторы
  • [SRV] chatGPT
  • Взаимодействие по API

    REMOTES

    Remotes

    Возможность запуска выполнения кода внутри Тотум путем обращения стороннего скрипта на адрес Remotes.

    Настраивается через таблицу Системные таблицы — API — Remotes.

    Вызов осуществляется обращением по адресу хост/Remotes/name_action.


    youtube

    Видео на YouTube: Remotes


    Модуль remotes

    Обращение к модулю происходит по адресу host/Remotes/name_action, где name_action — name в таблице Remotes.

    name_action должен полностью совпадать в таблице remotes и в запросе. Запрос host/Remotes/name_action/ (со / на конце предполагает, что в таблице remotes name будет указан также со / на конце).

    Для того, чтобы код из строки в Remotes запускался на выполнение, чекбокс Включено должен быть в true и пользователь remotes_user должен быть заполнен.

    Можно выбрать динамического пользователя, тогда id пользователя надо передать в GET переменную ttm_user с id пользователя в системе от которого нужно выполнить этот ремоут.

    Код из code будет выполнен от имени пользователя, указанного в remotes_user.

    Обращение может происходить по GET или POST. В code при выполнении будут переданы переменные:

    • $#getrow из переменных, переданных в GET.

    • $#postrow из переменных, переданных в POST при использовании application/x-www-form-urlencoded или multipart/form-data в заголовке Content-Type запроса HTTP.

    • $#inputстрока или null — необработанные данные из тела запроса при передаче POST в raw-data.

    • $#headersrow из заголовков HTTP-запроса.

    • $#remoteIpip входящего запроса.

    • $#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 Пути

    В PRO возможна активация поля path — в этом случае указанный name становится приоритетным.

    Если есть ремоуты использующие тот же путь они будут неактивны:

    • some_name #path = true — основной. Запрос на .../Remotes/some_name/ тоже будет обработан.
    • some_name/action/param — будет неактивен.

    Когда включен параметр path, все уровни запроса будут переданы в переменную $#path в виде списка с сохранением последовательности. То есть при запросе .../Remotes/some_name/action/param переменная будет содержать список из двух значений:

    • action
    • param

    Shadow Hosts

    Если вам нужно скрыть при использовании Remotes, JSON-API, анонимных таблиц или форм основной хост вашей системы то используется shadow-host.

    1. Необходимо адресовать DNS хоста на тот-же сервер, на котором размещен Totum.

    2. Открыть настройки nginx по пути /etc/nginx/sites-available/totum.online.conf и явно прописать основной домен в секциях ssl и 80 порта в параметре server_name: server_name _; —› server_name YOUR_MAIN_DOMAIN;. Сохранить и перезапустить nginx.

    3. Скопировать конфиг основного домена и указать в нем дополнительный домен в секциях ssl и 80 порта.

    4. Получить сертификат SSL для дополнительного домена:

    certbot certonly --dry-run -d YOUR_ADDITIONAL_DOMAIN.ZONE
    

    Если --dry-run проходит то

    certbot certonly -d YOUR_DOMAIN.ZONE
    
    1. Прописываем адрес сертификата в дополнительном конфиге nginx.

    2. Активируем конфиг:

    ln -s /etc/nginx/sites-available/YOUR_ADDITIONAL_DOMAIN.conf /etc/nginx/sites-enabled/YOUR_ADDITIONAL_DOMAIN.conf
    
    1. Рестартуем nginx.

    2. Открываем конфиг 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***/
    
    1. Можно задать разные хосты для разных модулей.

    2. Для 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, таблица задается как:

    Для подключения к API должен быть создан пользователь с интерфейсом api в таблице пользователей. Пользователь должен иметь необходимые права на таблицу.

    Логин и пароль этого пользователя должны передаваться в секцию auth входящего JSON.

    {
    "auth": {
        "login": "json",
        "password": "1111"
      }
    }
    

    Входящий JSON

    Входящий JSON передается в теле POST-запроса.

    Обязательная секция auth — содержит логин и пароль.

    Доступ предоставляется пользователю с интерфейсом api при наличии доступа к вызываемой таблице. Логика доступов в циклы cycles_access_type не действует.

    Для манипуляций с полем через API у поля должна быть включена опция Показывать в API и в случае наличия ограничений в Видно ролям в API должна быть указана роль api-пользователя от которого идет подключение.

    Для изменения поля через API для поля должно быть включено Редактируемое в API и в случае наличия ограничений в Редактирование в API доступно ролям должна быть указана роль от которой идет подключение.

    • import — cекция отвечает за внесение изменений в таблицу (возможно, при наличии у пользователя роли с редактированием этой таблицы). Ограничения которые могут быть установлены для роли в префильтре в API на изменение не действуют! Поэтому в целях безопасности внимательно устанавливайте разрешения для ролей в Редактирование в API доступно ролям. Если вы хотите добавить строчные ограничения, сделайте это через errorExeption.

      • footer и header — изменить значения полей хедера и футера можно через соответствующие секции передав "name": new_value.

        • __clearscбросить значения к расчетным передав name полей.

        • __pinsзапинить значения передав name полей.

      {
        "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 — список условий:

          • field — name поля, по которому будет осуществляться выборка. Поле, по которому осуществляется выборка не чувствительно к Показывать в API.
          • value — значение сравнения.
          • operatop — оператор сравнения.
        {
          "import": {
            "rows-set-where": [
              {
                "where": [
                  {
                    "field": "id",
                    "value": "test",
                    "operator": "="
                  }
                ],
                "set": {
                  "test": true,
                  "__pins": [
                    "rekvizity"
                  ]
                }
              }
            ]
          }
        }
        
    • recalculate — принимает список условий для выборки строк для пересчета в простых таблицах. В расчетных таблицах эту секцию можно не вызывать — пересчет происходит при каждом обращении через API к таблице.

      • field — name поля, по которому будет осуществляться выборка. Поле, по которому осуществляется выборка, не чувствительно к Показывать в API.
      • operator — оператор сравнения.
      • value — значение сравнения.
    {
      "recalculate": [
        {
          "field": "id",
          "operator": "=",
          "value": [
            1,
            2,
            3
          ]
        }
    }
    
    • remotes — секция для вызова исполняемых конструкций из таблицы ttm__remotes.

      • name — name из таблицы ttm__remotes. В строке ремоута должен быть выбран пользователь, который указан в секции auth, в поле API user и стоять галочка в Включено.
      • data — информация для передачи в параметр $#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",
            "rekvizity"
          ],
          "filters": {
            "fl_filter": [
              "value1",
              "value2",
              "value3"
            ],
            "id": [
              2
            ]
          }
        }
      }
      

    Пример входящего JSON:

    {
      "export": {
        "fields": [
          "id",
          "rekvizity"
        ],
        "filters": {
          "id": [
            1,
            2,
            3
          ]
        }
      },
      "auth": {
        "login": "json",
        "password": "1111"
      },
      "import": {
        "rows-set-where": [
          {
            "where": {
              "field": "id",
              "value": "test",
              "operator": "="
            },
            "set": {
              "test": true,
              "__pins": [
                "rekvizity"
              ]
            }
          }
        ],
        "header": {
          "__pins": [
            "rekvizity"
          ],
          "__clears": [
            "rekvizity"
          ],
          "test": "Тестовая строка"
        },
        "footer": {
          "__pins": [
            "f_summ"
          ],
          "__clears": [
            "f_summ2"
          ]
        },
        "rows": {
          "modify": {
            "2": {
              "row_field": "new value",
              "__pins": [
                "rekvizity"
              ]
            },
            "3": {
              "rowField": "new value"
            }
          },
          "add": [],
          "remove": []
        }
      },
      "recalculate": [
        {
          "field": "id",
          "operator": "=",
          "value": [
            1,
            2,
            3
          ]
        }
      ]
    }
    

    Возвращаемый JSON

    В случае возникновения ошибки возвращается 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

    Это пример добавления данных через 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));
    

    В таком варианте срабатывают триггеры добавления и расчитываются коды.

    Собственный API-модуль

    Модуль API на PHP

    Такая реализация модели обеспечивает запуск внутренних триггеров действий в 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 с учетом прав доступа к таблице все возможные в настоящий момент действия.

    База данных

    Запись напрямую в pgsql

    При таком добавлении НЕ СРАБАТЫВАЮТ триггеры действий на добавление и расчет кодов.

    Использовать только в крайнем случае для случаев, когда требуется очень большая производительность!**

    <?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');