171 lines
12 KiB
Markdown
171 lines
12 KiB
Markdown
|
|
# Отчёт: интеграция внешнего приложения — данные сотрудников (Merakomis)
|
|||
|
|
|
|||
|
|
**Дата:** 13.05.2026
|
|||
|
|
**Кодовая база:** `d:\MeraProject` (PHP CMS, тема `themes\merakomis`).
|
|||
|
|
|
|||
|
|
## 1. Краткий вывод
|
|||
|
|
|
|||
|
|
- Данные сотрудников хранятся в модуле **`themes\merakomis\Emp`** (таблица `tMerakomisEmp`, контроллер CMS `themes.merakomis.emp`).
|
|||
|
|
- **Публичного REST API с API-ключом для выгрузки сотрудников в коде нет.** Доступ к спискам и карточкам строится на **сессии через cookie** после входа (`login`), по тем же правилам, что и веб-интерфейс.
|
|||
|
|
- Для вызова из браузера с другого домена хост должен попадать в **белый список CORS** в `module/engine.php` (для продуктивного домена Merakomis указан `merakomis.in`).
|
|||
|
|
|
|||
|
|
## 2. Как устроен HTTP API движка
|
|||
|
|
|
|||
|
|
### 2.1. Маршрутизация
|
|||
|
|
|
|||
|
|
В корневом `.htaccess`:
|
|||
|
|
|
|||
|
|
```55:55:d:\MeraProject\.htaccess
|
|||
|
|
RewriteRule ^api/([^/]+)?/?([^/]+)?/$ index.php?api=1&module=$1&action=$2&%{QUERY_STRING} [L]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Пример: **`https://<хост>/api/themes.merakomis.emp/login/`** → `api=1`, `module=themes.merakomis.emp`, `action=login`.
|
|||
|
|
|
|||
|
|
Альтернатива — query-string: `index.php?api=1&module=themes.merakomis.emp&action=login`.
|
|||
|
|
|
|||
|
|
### 2.2. Вызов контроллера
|
|||
|
|
|
|||
|
|
В `module/engine.php` при `api=1` создаётся класс:
|
|||
|
|
|
|||
|
|
- Имя класса: `controller\<module с точками как NS>\Api`
|
|||
|
|
- Для сотрудников: **`controller\themes\merakomis\emp\Api`** (файл `themes\merakomis\emp\controller.php`).
|
|||
|
|
|
|||
|
|
Вызывается метод с именем из параметра **`action`**.
|
|||
|
|
|
|||
|
|
### 2.3. Тело запроса (JSON)
|
|||
|
|
|
|||
|
|
При `Content-Type: application/json` тело подставляется в `$_POST`:
|
|||
|
|
|
|||
|
|
```104:107:d:\MeraProject\module\core\core\model.php
|
|||
|
|
if(substr($_SERVER["CONTENT_TYPE"],0,16) == 'application/json') {
|
|||
|
|
$_POST = json_decode(file_get_contents('php://input'),true);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Имеет смысл отправлять JSON с клиента, как это делает фронтенд CMS.
|
|||
|
|
|
|||
|
|
### 2.4. CORS
|
|||
|
|
|
|||
|
|
Для ряда хостов, включая `merakomis.in`, при `api=1` выставляются заголовки `Access-Control-Allow-Origin: *` и др. — см. `module/engine.php` (список `HTTP_HOST`).
|
|||
|
|
|
|||
|
|
## 3. Модель «сотрудник» (поля БД / сущности)
|
|||
|
|
|
|||
|
|
Основные константы полей в `themes\merakomis\emp\model.php` (фрагмент):
|
|||
|
|
|
|||
|
|
- Идентификация и доступ: `id`, `name`, `login`, `email`, `pass`, `type`, `active`, `accept`, `archive`, `portal`, `account`, …
|
|||
|
|
- Контакты и профиль: `phone`, `skype`, `discrod` (поле Discord в коде), `city`, `image`, `birthdate`, `date_hire`, …
|
|||
|
|
- Орг. данные: `org`, `org_type`, `staffing`, `status`, `is_freelancer`, …
|
|||
|
|
- Прочее: `salary`, `tg_acc` (Telegram), группы `group`, и т.д.
|
|||
|
|
|
|||
|
|
Форматирование записи для API/карточек — методы **`Emp::format()`** и **`Emp::getPublicData($emp_id)`** (учёт прав через `themes\merakomis\emp\Rules`).
|
|||
|
|
|
|||
|
|
## 4. Аутентификация для внешнего клиента
|
|||
|
|
|
|||
|
|
### 4.1. Cookie после `login`
|
|||
|
|
|
|||
|
|
После успешного входа выставляются cookie (имена в модели):
|
|||
|
|
|
|||
|
|
- **`fg_emp_id`** — id сотрудника
|
|||
|
|
- **`fg_emp_h`** — **не хэш пароля**, а значение поля пароля из БД (сервер сравнивает cookie с текущим значением в записи — см. `if_auth`).
|
|||
|
|
|
|||
|
|
```482:493:d:\MeraProject\themes\merakomis\emp\model.php
|
|||
|
|
static function if_auth(){
|
|||
|
|
if($uid = intval($_COOKIE[ self::$cookieIDKey ]) and $hash = $_COOKIE[ self::$cookieHashKey ]) {
|
|||
|
|
$acc = self::getByID($uid);
|
|||
|
|
$res = ( strcmp($acc[self::$PASSWORD],$hash)==0
|
|||
|
|
&& boolval($acc[self::$ACTIVE])
|
|||
|
|
&& !boolval($acc[self::$ARCHIVE])
|
|||
|
|
&& !boolval($acc[self::$REMOVED])
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Внешнее приложение (**сервер-сервер** или **мобильное**) должно **сохранять и передавать эти cookie** на последующие запросы к `/api/...`.
|
|||
|
|
|
|||
|
|
### 4.2. Двухфакторная цепочка через Telegram
|
|||
|
|
|
|||
|
|
Если у учётной записи включена схема «Telegram», `login` может вернуть **`e: 3`** и **`key`**: тогда ожидается повторный запрос с полями `key`, `code` (код из Telegram). Это нужно заложить в сценарий интеграции.
|
|||
|
|
|
|||
|
|
## 5. Методы `controller\themes\merakomis\emp\Api` (по коду)
|
|||
|
|
|
|||
|
|
Модуль: **`themes.merakomis.emp`**. Базовый URL:
|
|||
|
|
`https://<хост>/api/themes.merakomis.emp/<action>/`
|
|||
|
|
|
|||
|
|
| action | Назначение | Авторизация |
|
|||
|
|
|--------|------------|-------------|
|
|||
|
|
| `login` | Вход (`login`, `pass`; при Telegram — доп. `key`, `code`) | Нет |
|
|||
|
|
| `reg` | Регистрация | Нет |
|
|||
|
|
| `remind` | Восстановление пароля | Нет |
|
|||
|
|
| `new_pass` | Установка пароля по ссылке восстановления | Нет |
|
|||
|
|
| `exit` | Выход (сброс сессии) | Ожидается cookie |
|
|||
|
|
| `getTableData` | Таблица сотрудников (разные «режимы» через `data` в теле запроса) | **Требуется** (`Emp::$IS_AUTH`) |
|
|||
|
|
| `getForm` | Данные формы редактирования (как в CMS) | Требуется |
|
|||
|
|
| `getData` | Карточка по `id` (POST) | Требуется |
|
|||
|
|
| `getMyData` | Текущий авторизованный сотрудник (`Emp::format`) | Требуется |
|
|||
|
|
| `getMyForm` | Публичная карточка / форма (`Emp::getPublicData`) | Требуется |
|
|||
|
|
| `updateMe` | Обновление своих контактов (`phone`, `skype`, `discord`) | Требуется |
|
|||
|
|
| `updatePassword` | Смена пароля | Требуется |
|
|||
|
|
| `getBirthday` | Именинники на сегодня (для авторизованных) | Требуется |
|
|||
|
|
| `isSummaryAnalysis` | Флаг доступа к сводному анализу (`Rules::isAnalysisProjectsSummary`) | Требуется |
|
|||
|
|
| `qr` / `toTelegram` / `checkTelegram` / `removeTelegram` | Интеграция с Telegram | Частично / полностью только с сессией |
|
|||
|
|
|
|||
|
|
Наследованные из `merakomisControllerTable` (при наличии вызова с фронта): `getForm`, `getTableData` фильтруют данные **только если `Emp::$IS_AUTH`**.
|
|||
|
|
|
|||
|
|
### 5.1. Режимы `getTableData` (список сотрудников)
|
|||
|
|
|
|||
|
|
Реализация в `themes\merakomis\emp\controller.php` задаёт набор колонок и фильтры в зависимости от флагов в **`post['data']`**:
|
|||
|
|
|
|||
|
|
- **`my_company`** — «Моя компания»: неархивные (`archive = 0`), контактные колонки (имя, staffing, роли, skype, discord, email, город и т.д.).
|
|||
|
|
- **`my`** — подчинённые/доступные id: если нет «superview», ограничение `Emp::getSubEmps(Emp::$AUTH_ID)`.
|
|||
|
|
- **`archive`** — архив / не архив по `data.archive`.
|
|||
|
|
- **`mini`** — компактный админ-список.
|
|||
|
|
- **`all`** — расширенные колонки, включая ФОТ и др.
|
|||
|
|
|
|||
|
|
Фактические **права на строки** определяются логикой `Emp` / `Rules` и фильтрами запроса; при интеграции нужно повторить те же запросы, что и клиент CMS, либо задать новый контракт на бэкенде (см. раздел 7).
|
|||
|
|
|
|||
|
|
## 6. Выгрузка файла (Excel) по сотруднику
|
|||
|
|
|
|||
|
|
В карточке в `Emp::format` указывается ссылка:
|
|||
|
|
|
|||
|
|
- **`/api/themes.merakomis.download/emp/?id=<id>`** — отдаёт XLSX с полями из `Emp::getPublicData` (набор колонок зависит от прав текущей сессии).
|
|||
|
|
|
|||
|
|
Класс в проекте: `controller\themes\merakomis\download\API` (`themes\merakomis\download\controller.php`, метод **`emp()`**). Требуется **`Emp::$IS_AUTH`**.
|
|||
|
|
|
|||
|
|
**Замечание по именованию:** в файле объявлен класс `API` (все буквы заглавные); при строгом автозагрузчике и регистрозависимой ФС путь `.../Api` должен совпадать с именем класса. На окружении разработки это уже работает или учтено конфигурацией сервера — при переносе интеграции стоит проверить фактический вызов этого URL в вашей среде.
|
|||
|
|
|
|||
|
|
## 7. Рекомендуемая стратегия интеграции
|
|||
|
|
|
|||
|
|
### Вариант A — использовать текущий API «как веб-клиент» (быстрый старт)
|
|||
|
|
|
|||
|
|
1. Реализовать HTTP-клиент с **cookie jar**.
|
|||
|
|
2. `POST /api/themes.merakomis.emp/login/` с учётными данными сервисного пользователя (роль с нужными правами).
|
|||
|
|
3. Вызывать `getTableData` / `getData` / `getMyData` с JSON-телом, как в интерфейсе.
|
|||
|
|
4. Учесть CORS только если интеграция идёт из браузера; для **server-to-server CORS не нужен**.
|
|||
|
|
|
|||
|
|
**Минусы:** нет отдельного ограничения scope; компрометация учётной записи = полный доступ веб-пользователя; смена пароля ломает интеграцию; зависимость от внутреннего формата `getTableData`.
|
|||
|
|
|
|||
|
|
### Вариант B — отдельный интеграционный endpoint (рекомендуется для продакшена)
|
|||
|
|
|
|||
|
|
Добавить узкий контроллер, например `themes.merakomis.emp.integration.Api`:
|
|||
|
|
|
|||
|
|
- авторизация по **секрету** (заголовок или env), отдельно от cookie пользователя;
|
|||
|
|
- явные методы: «список сотрудников с полями X», «карточка по id», пагинация;
|
|||
|
|
- журналирование и ограничение по IP.
|
|||
|
|
|
|||
|
|
Этого **нет в текущем репозитории** — потребуется разработка и согласование полей (в т.ч. персональные данные, 152-ФЗ).
|
|||
|
|
|
|||
|
|
## 8. Связанные модули API (справочники и оргструктура)
|
|||
|
|
|
|||
|
|
Для полноценного отображения данных сотрудника используются справочники с собственными `Api` в `themes\merakomis\dictionary\...` (город, оргштат, департамент, статусы и т.д.) и модуль **команды** `themes.merakomis.team.member` и др. Их можно вызывать тем же шаблоном `/api/<module>/<action>/`, если есть права у той же сессии.
|
|||
|
|
|
|||
|
|
## 9. Итоговая таблица «что есть сейчас»
|
|||
|
|
|
|||
|
|
| Возможность | Есть? |
|
|||
|
|
|------------|-------|
|
|||
|
|
| Открытый API-ключ только для чтения сотрудников | Нет |
|
|||
|
|
| JSON API под cookie-сессией сотрудника/админа | Да (`themes.merakomis.emp`) |
|
|||
|
|
| CORS для стороннего фронта | Да, для перечисленных в `engine.php` хостов |
|
|||
|
|
| Экспорт карточки в XLSX | Да (`themes.merakomis.download/emp`) |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
*Документ составлен по статическому анализу кода; для точного контракта полей тела запросов к `getTableData` при необходимости следует снять примеры запросов с рабочего фронтенда (DevTools → Network).*
|