Преглед изворни кода

- PostgreSQL support has been added (experimental, not for production use).
- HTML: Migrated from mysqli to PDO for database access

Dmitriev Roman пре 4 месеци
родитељ
комит
3aa8667567
57 измењених фајлова са 6311 додато и 2003 уклоњено
  1. 2 0
      CHANGELOG.md
  2. 408 8
      README.md
  3. 0 229
      Readme.en.md
  4. 0 225
      Readme.ru.md
  5. 0 0
      docs/databases/mysql/en/create_db.sql
  6. 1 1
      docs/databases/mysql/en/data.sql
  7. 0 0
      docs/databases/mysql/nagios.sql
  8. 0 0
      docs/databases/mysql/reset_admin.sql
  9. 791 0
      docs/databases/mysql/ru/create_db.sql
  10. 0 0
      docs/databases/mysql/ru/data.sql
  11. 726 0
      docs/databases/postgres/en/create_db.sql
  12. 537 0
      docs/databases/postgres/en/data.sql
  13. 726 0
      docs/databases/postgres/ru/create_db.sql
  14. 530 0
      docs/databases/postgres/ru/data.sql
  15. 1 0
      html/cfg/config.sample.php
  16. 0 1110
      install-eye.ru.sh
  17. 406 90
      install-eye.sh
  18. 4 3
      scripts/cfg/config.sample
  19. 1 0
      scripts/check_dhcp_pool.pl
  20. 1 0
      scripts/dhcp-log.pl
  21. 1 0
      scripts/eye-statd.pl
  22. 1617 0
      scripts/eyelib/common.pm
  23. 485 337
      scripts/eyelib/database.pm
  24. 41 0
      scripts/eyelib/main.pm
  25. 1 0
      scripts/eyelib/nagios.pm
  26. 1 0
      scripts/fetch_new_arp.pl
  27. 1 0
      scripts/garbage.pl
  28. 1 0
      scripts/gen_nagios_config.pl
  29. 1 0
      scripts/hmonitor.pl
  30. 1 0
      scripts/print-dnsmasq.pl
  31. 1 0
      scripts/restart_port_snmp.pl
  32. 1 0
      scripts/run/syslog-stat.pid
  33. 1 0
      scripts/stat-sync.pl
  34. 1 0
      scripts/sync_mikrotik.pl
  35. 1 0
      scripts/sync_mikrotik_poe_monitor.pl
  36. 1 0
      scripts/syslog-stat.pl
  37. 1 0
      scripts/updates/2-8-0/after_sql.pl
  38. 1 0
      scripts/updates/2-9-1/readme.txt
  39. 1 0
      scripts/updates/db-patch-mysql-utf8.pl
  40. 1 0
      scripts/updates/upgrade.pl
  41. 1 0
      scripts/utils/backupcfg.pl
  42. 1 0
      scripts/utils/bind/print-dns-zones.pl
  43. 1 0
      scripts/utils/import/import_auth.pl
  44. 1 0
      scripts/utils/mac-oids/update-mac-vendors.pl
  45. 1 0
      scripts/utils/nf_calc
  46. 1 0
      scripts/utils/parse_flow.pl
  47. 1 0
      scripts/utils/print-ou-ip.pl
  48. 1 0
      scripts/utils/print_cacti_create.pl
  49. 1 0
      scripts/utils/print_cacti_hosts.pl
  50. 1 0
      scripts/utils/print_devices.pl
  51. 1 0
      scripts/utils/radius/print_huntgroups.pl
  52. 1 0
      scripts/utils/reaply_rules.pl
  53. 1 0
      scripts/utils/scan_ipcam.pl
  54. 1 0
      scripts/utils/set_dns_record.pl
  55. 1 0
      scripts/utils/set_port_descr.pl
  56. 1 0
      scripts/utils/win32/print-dhcpd-netsh.pl
  57. 1 0
      scripts/utils/win32/sync-dhcpd-netsh.pl

+ 2 - 0
CHANGELOG.md

@@ -1,4 +1,6 @@
 # Changelog 2.9.1 - release
+- Added PostgreSQL support (EXPERIMENTAL — DO NOT USE IN PRODUCTION!)
+- html: switched to use PDO
 - added perl-Net-SNMP module patch to support sha512 in AltLinux
 - The installer has been added 
 - Old versions of the database dump have been removed 

+ 408 - 8
README.md

@@ -2,11 +2,411 @@
 
 Обычный быдло-кодинг, разросшийся за последние 13 лет. Выкладываю сюда - может кого-то сподвигнет сделать что-то своё нормально).
 
-Предназначен для контроля доступа юзеров в интернет на оборудовании микротик или linux-сервере.
-Возможности:
-- Управляет выходом в интернет для ip-адресов. Настраивается фильтрация, объём трафика в сутки, месяц.
-- Ограничивать скорость (только на микротике, функционал на линухе был, но давно вырезан)
-- генерит конфиги для dhcp-серверов (dnsmasq, mikrotik)
-- генерит конфиг для named
-- опрашивает свичи и роутеры по snmp после чего анализирует и находит порты подключения ip-адресов
-- ну и ещё по мелочи...
+## 📋 Обзор
+
+Eye — это комплексная система сетевого мониторинга и управления, обеспечивающая:
+
+- Управление выходом в интернет для IP-адресов через маршрутизаторы MikroTik/Linux (настраивается фильтрация, лимиты трафика в сутки и за месяц).
+- Ограничение скорости доступа (реализовано на MikroTik; функциональность для Linux ранее существовала, но была удалена).
+- Генерация конфигураций для DHCP-серверов  (dnsmasq, MikroTik).
+- Генерация конфигураций для DNS-сервера (BIND).
+- Опрос коммутаторов и маршрутизаторов по SNMP с последующим анализом и определением портов подключения IP-адресов.
+- Мониторинг и управление сетевыми устройствами.
+- Анализ трафика и контроль пропускной способности.
+- Сбор и анализ Syslog-сообщений.
+- Статистика и отчёты в реальном времени.
+
+---
+
+# Eye Monitoring System — Руководство по установке
+
+### Системные требования
+
+#### Поддерживаемые дистрибутивы:
+
+* ALT Linux 11.1+
+* Debian 11+
+* Ubuntu 20.04+
+
+---
+
+## 🚀 Быстрая установка с помощью скрипта
+
+Для автоматизированной установки используйте установочный скрипт:
+
+```bash
+# Сделать скрипт исполняемым
+chmod +x install-eye.sh
+
+# Запуск установки
+sudo ./install-eye.sh
+
+# Автоматический режим (минимальное вмешательство)
+sudo ./install-eye.sh --auto
+````
+
+### Возможности скрипта
+
+* Поддержка ALT Linux, Debian и Ubuntu
+* Поддержка двух СУБД: MySQL/MariaDB или PostgreSQL (экспериментально, не для production!)
+* Многоязычный интерфейс: английский или русский
+* Автоматическая установка зависимостей
+* Настройка конфигурационных файлов
+* Инициализация базы данных
+
+---
+
+## 🔧 Ручная установка
+
+
+### Установка требуемых пакетов
+
+#### Для ALT Linux:
+
+```bash
+# Обновление репозиториев
+apt-get update
+
+# Установка пакетов Eye
+apt-get install git xxd wget fping hwdata
+
+# База данных (выберите одну)
+apt-get install mariadb-server mariadb-client    # Для MySQL
+# ИЛИ
+apt-get install postgresql postgresql-client     # Для PostgreSQL
+
+# Веб-сервер и PHP
+apt-get install apache2 php8.2 php8.2-mysqlnd php8.2-pgsql \
+php8.2-intl php8.2-mbstring php8.2-fpm-fcgi apache2-mod_fcgid
+
+# Perl-модули
+apt-get install perl perl-Net-Patricia perl-NetAddr-IP \
+perl-Config-Tiny perl-Net-DNS perl-DateTime perl-Net-Ping \
+perl-Net-Netmask perl-Text-Iconv perl-Net-SNMP perl-Net-Telnet \
+perl-DBI perl-DBD-mysql perl-DBD-Pg perl-Parallel-ForkManager \
+perl-Proc-Daemon perl-DateTime-Format-DateParse perl-Net-OpenSSH \
+perl-File-Tail perl-Crypt-Rijndael perl-Crypt-CBC perl-CryptX \
+perl-Crypt-DES perl-File-Path-Tiny perl-Expect perl-Proc-ProcessTable
+
+# Дополнительные сервисы
+apt-get install dnsmasq syslog-ng syslog-ng-journal pwgen
+```
+
+#### Для Debian / Ubuntu:
+
+```bash
+# Обновление репозиториев
+apt-get update
+
+# Установка пакетов Eye
+apt-get install git xxd bsdmainutils pwgen wget fping ieee-data
+
+# База данных (выберите одну)
+apt-get install mariadb-server mariadb-client    # Для MySQL
+# ИЛИ
+apt-get install postgresql postgresql-client     # Для PostgreSQL
+
+# Веб-сервер и PHP
+apt-get install apache2 php php-mysql php-pgsql php-bcmath \
+php-intl php-mbstring php-date php-mail php-snmp php-zip \
+php-db php-fpm libapache2-mod-fcgid
+
+# Perl-модули
+apt-get install perl libnet-patricia-perl libnetaddr-ip-perl \
+libconfig-tiny-perl libnet-dns-perl libdatetime-perl \
+libnet-netmask-perl libtext-iconv-perl libnet-snmp-perl \
+libnet-telnet-perl libdbi-perl libdbd-mysql-perl libdbd-pg-perl \
+libparallel-forkmanager-perl libproc-daemon-perl \
+libdatetime-format-dateparse-perl libnet-openssh-perl \
+libfile-tail-perl libcrypt-rijndael-perl libcrypt-cbc-perl \
+libcryptx-perl libfile-path-tiny-perl libexpect-perl libcrypt-des-perl
+
+# Дополнительные сервисы
+apt-get install dnsmasq syslog-ng
+```
+
+---
+
+### Создание пользователя и группы
+
+```bash
+# Создание группы
+groupadd --system eye
+
+# Создание пользователя
+adduser --system --disabled-password --disabled-login \
+--ingroup eye --home=/opt/Eye eye
+
+# Создание каталога
+mkdir -p /opt/Eye
+chown eye:eye /opt/Eye
+chmod 770 /opt/Eye
+
+# Опционально: добавить nagios в группу eye
+usermod -a -G eye nagios
+```
+
+---
+
+### Загрузка и установка исходного кода
+
+```bash
+# Клонирование репозитория
+git clone https://github.com/rajven/Eye
+
+# Создание структуры каталогов
+mkdir -p /opt/Eye/scripts/cfg
+mkdir -p /opt/Eye/scripts/log
+mkdir -p /opt/Eye/html/cfg
+mkdir -p /opt/Eye/html/js
+mkdir -p /opt/Eye/docs
+
+# Копирование файлов
+cp -R scripts/ /opt/Eye/
+cp -R html/ /opt/Eye/
+cp -R docs/ /opt/Eye/
+
+# Установка прав
+chown -R eye:eye /opt/Eye
+chmod -R 755 /opt/Eye/html
+chmod -R 770 /opt/Eye/scripts/log
+chmod 750 /opt/Eye/scripts
+```
+
+---
+
+### Применение патча SNMP SHA512 (опционально)
+
+```bash
+# Патч для поддержки SNMPv3 SHA512
+# Файл: /opt/Eye/docs/patches/sha512.patch
+# Для ALT Linux: /opt/Eye/docs/patches/sha512.alt.patch
+
+# Применение патча при необходимости
+cp /opt/Eye/docs/patches/USM.pm /usr/share/perl5/Net/SNMP/Security/USM.pm
+```
+
+---
+
+### Загрузка дополнительных JavaScript-библиотек
+
+```bash
+# Создание каталогов
+mkdir -p /opt/Eye/html/js/jq
+mkdir -p /opt/Eye/html/js/select2
+mkdir -p /opt/Eye/html/js/jstree
+
+# Загрузка jQuery
+wget https://code.jquery.com/jquery-3.7.0.min.js \
+-O /opt/Eye/html/js/jq/jquery.min.js
+
+# Загрузка Select2
+wget https://github.com/select2/select2/archive/4.0.12.tar.gz -O 4.0.12.tar.gz
+tar -xzf 4.0.12.tar.gz -C /opt/Eye/html/js/select2/ \
+--strip-components=2 select2-4.0.12/dist
+rm -f 4.0.12.tar.gz
+
+# Загрузка jsTree
+wget https://github.com/vakata/jstree/archive/3.3.12.tar.gz -O jstree.tar.gz
+tar -xzf jstree.tar.gz -C /opt/Eye/html/js/
+mv /opt/Eye/html/js/jstree-3.3.12/dist/* /opt/Eye/html/js/jstree
+rm -rf /opt/Eye/html/js/jstree-3.3.12
+rm -f jstree.tar.gz
+```
+
+---
+
+### Настройка базы данных
+
+#### MySQL / MariaDB:
+
+```bash
+systemctl enable mariadb
+systemctl start mariadb
+
+mysql_secure_installation
+
+mysql -u root -p < /opt/Eye/docs/databases/mysql/en/create_db.sql
+mysql -u root -p stat < /opt/Eye/docs/databases/mysql/en/data.sql
+
+mysql -u root -p <<EOF
+CREATE USER 'stat'@'localhost' IDENTIFIED BY 'your_password';
+GRANT ALL PRIVILEGES ON stat.* TO 'stat'@'localhost';
+FLUSH PRIVILEGES;
+EOF
+```
+
+#### PostgreSQL:
+
+```bash
+systemctl enable postgresql
+systemctl start postgresql
+
+sudo -u postgres psql -f /opt/Eye/docs/databases/postgres/en/create_db.sql
+sudo -u postgres psql -d stat -f /opt/Eye/docs/databases/postgres/en/data.sql
+sudo -u postgres psql -c "ALTER USER stat WITH PASSWORD 'your_password';"
+
+# В pg_hba.conf добавить строку:
+# local   stat            stat                                    md5
+```
+
+---
+
+### Конфигурационные файлы
+
+```bash
+cp /opt/Eye/html/cfg/config.sample.php /opt/Eye/html/cfg/config.php
+cp /opt/Eye/scripts/cfg/config.sample /opt/Eye/scripts/cfg/config
+
+ENCRYPTION_KEY=$(pwgen 16 1)
+ENCRYPTION_IV=$(tr -dc 0-9 </dev/urandom | head -c 16)
+
+chown -R eye:eye /opt/Eye/html/cfg /opt/Eye/scripts/cfg
+chmod 660 /opt/Eye/html/cfg/config.php /opt/Eye/scripts/cfg/config
+```
+
+---
+
+### Настройка Apache и PHP
+
+```bash
+cp /opt/Eye/docs/apache/000-default.conf /etc/apache2/sites-available/
+a2enmod setenvif proxy proxy_fcgi
+cp /opt/Eye/docs/php-fpm/eye.conf /etc/php/8.2/fpm/pool.d/
+
+cp /opt/Eye/docs/sudoers.d/www-data /etc/sudoers.d/eye
+sed -i 's/www-data/eye/g' /etc/sudoers.d/eye
+chmod 440 /etc/sudoers.d/eye
+
+systemctl restart apache2
+systemctl restart php8.2-fpm
+```
+
+---
+
+### Cron и Logrotate
+
+```bash
+cp /opt/Eye/docs/cron/stat /etc/cron.d/eye
+chmod 644 /etc/cron.d/eye
+
+cp /opt/Eye/docs/logrotate/dnsmasq /etc/logrotate.d/dnsmasq-eye
+cp /opt/Eye/docs/logrotate/scripts /etc/logrotate.d/eye-scripts
+```
+
+---
+
+### Дополнительные сервисы (опционально)
+
+#### DHCP (dnsmasq):
+
+```bash
+cp /etc/dnsmasq.conf /etc/dnsmasq.conf.backup
+cat /opt/Eye/docs/addons/dnsmasq.conf > /etc/dnsmasq.conf
+
+cp /opt/Eye/docs/systemd/dhcp-log.service /etc/systemd/system/
+cp /opt/Eye/docs/systemd/dhcp-log-truncate.service /etc/systemd/system/
+
+systemctl enable dnsmasq dhcp-log dhcp-log-truncate
+systemctl start dnsmasq
+```
+
+#### Syslog-ng:
+
+```bash
+cp /etc/syslog-ng/syslog-ng.conf /etc/syslog-ng/syslog-ng.conf.backup
+mkdir -p /etc/syslog-ng/conf.d
+cp /opt/Eye/docs/syslog-ng/eye.conf /etc/syslog-ng/conf.d/
+
+cp /opt/Eye/docs/systemd/syslog-stat.service /etc/systemd/system/
+
+systemctl enable syslog-ng syslog-stat
+systemctl restart syslog-ng
+systemctl start syslog-stat
+```
+
+#### NetFlow:
+
+```bash
+cp /opt/Eye/docs/systemd/eye-statd.service /etc/systemd/system/
+systemctl enable eye-statd
+```
+
+#### Stat-sync:
+
+```bash
+cp /opt/Eye/docs/systemd/stat-sync.service /etc/systemd/system/
+systemctl enable stat-sync.service
+```
+
+---
+
+### Импорт базы MAC-адресов
+
+```bash
+cd /opt/Eye/scripts/utils/mac-oids/
+bash download-macs.sh
+perl update-mac-vendors.pl
+```
+
+---
+
+## 🌐 Доступ к веб-интерфейсу
+
+* URL: `http://your-server-ip/`
+* Админ-панель: `http://your-server-ip/admin/`
+* Логин: `admin`
+* Пароль: `admin`
+
+---
+
+## 🔐 Рекомендации по безопасности
+
+* **НЕМЕДЛЕННО смените пароль администратора**
+* Сгенерируйте новый API-ключ
+* Ограничьте доступ с помощью firewall
+* Используйте HTTPS (без принудительного редиректа!)
+* Делайте регулярные обновления и резервные копии
+
+---
+
+## 📊 Интеграция с MikroTik
+
+### Firewall:
+
+```routeros
+/ip firewall filter
+add action=jump chain=forward comment="users set" in-interface-list=WAN jump-target=Users
+add action=jump chain=forward jump-target=Users out-interface-list=WAN
+```
+
+### Управление трафиком:
+
+```routeros
+/queue tree
+add max-limit=100M name=upload_root_ether1 parent=ether1 queue=pcq-upload-default
+add name=download_root_bridge parent=bridge queue=pcq-download-default
+```
+
+### DHCP-скрипт (RouterOS 6):
+
+```routeros
+/tool fetch mode=http keep-result=no url="http://<STAT_IP>/api.php?login=<LOGIN>&api_key=<API_KEY>&send=dhcp&mac=\$leaseActMAC&ip=\$leaseActIP&action=\$leaseBound&hostname=\$lease-hostname"
+```
+
+### NetFlow:
+
+```routeros
+# RouterOS 6
+/ip traffic-flow
+set enabled=yes
+
+# RouterOS 7
+/ip traffic-flow
+set enabled=yes interfaces=WAN
+
+/ip traffic-flow target
+add dst-address=<NETFLOW_SERVER_IP> port=2055
+```
+
+---

+ 0 - 229
Readme.en.md

@@ -1,229 +0,0 @@
-Installation
-
-1. Install the packages
-
-#common
-apt install git xxd bsdmainutils
-
-#for database server
-apt install mariadb-server
-
-#for web
-apt install apache2 libapache2-mod-fcgid \
-php php-mysql php-bcmath php-intl php-mbstring php-date php-mail php-snmp php-zip php-fpm php-db php-pgsql
-
-#for backend
-apt install perl libnet-patricia-perl libnetaddr-ip-perl libconfig-tiny-perl libnet-dns-perl libdatetime-perl \
-libnet-netmask-perl libtext-iconv-perl libnet-snmp-perl libnet-telnet-perl libdbi-perl \
-libdbd-mysql-perl libparallel-forkmanager-perl libproc-daemon-perl libdatetime-format-dateparse-perl \
-libnetwork-ipv4addr-perl libnet-openssh-perl libfile-tail-perl libcrypt-rijndael-perl \
-libcrypt-cbc-perl libcryptx-perl libdbd-pg-perl libfile-path-tiny-perl libexpect-perl libcrypt-des-perl
-
-#additional packages 
-apt install dnsmasq syslog-ng 
-apt install bind9 bind9-utils bind9-host
-
-2. Create user and group
-
-addgroup --system eye
-adduser --system  --disabled-password --disabled-login --ingroup eye --home=/opt/Eye eye
-chmod 770 /opt/Eye
-
-2.1 For nagios
-usermod -a -G eye nagios
-
-3. Download the source code and spread it in catalogs:
-
-git clone https://github.com/rajven/Eye
-mkdir -p /opt/Eye/scripts
-mkdir -p /opt/Eye/scripts/cfg
-mkdir -p /opt/Eye/scripts/log
-cd Eye/
-cp -R scripts/ /opt/Eye/
-cp -R html/ /opt/Eye/
-
-patch perl snmp for support SHA512
-
-#cp -f docs/patches/USM.pm /usr/share/perl5/Net/SNMP/Security/USM.pm
-
-4. You can download additional scripts (prettiness)
-
-mkdir -p /opt/Eye/html/js/jq
-mkdir -p /opt/Eye/html/js/select2
-
-download from https://jquery.com/download/ production jQuery to /opt/Eye/html/js/jq
-#wget https://code.jquery.com/jquery-1.12.4.min.js -O /opt/Eye/html/js/jq/jquery.min.js
-or
-#wget https://code.jquery.com/jquery-3.7.0.min.js -O /opt/Eye/html/js/jq/jquery.min.js
-
-download from https://github.com/select2/select2 release
-#wget https://github.com/select2/select2/archive/4.0.12.tar.gz
-#tar -xzf 4.0.12.tar.gz -C /opt/Eye/html/js/select2/ --strip-components=2 select2-4.0.12/dist
-#rm -f 4.0.12.tar.gz
-
-download jstree from  https://github.com/vakata/jstree/
-#wget https://github.com/vakata/jstree/zipball/3.3.12 -O js.zip
-#unzip js.zip "vakata-jstree-7a03954/dist/*" -d "/opt/Eye/html/"
-#mv /opt/Eye/html/vakata-jstree-7a03954/dist/ /opt/Eye/html/js/jstree
-#rm -d /opt/Eye/html/vakata-jstree-7a03954
-#rm -f js.zip
-
-5. Setting up mysql 
-
-systemctl enable mariadb
-systemctl start mariadb
-
-set password for root
-#mysql_secure_installation
-
-Create database
-#cat docs/mysql/create_db.sql | mysql -u root -p
-
-Import default tables
-#cat docs/mysql/latest-mysql.sql | mysql -u root -p stat
-
-Create user and database
-
-#mysql -u root -p
-
-CREATE USER 'stat'@'localhost' IDENTIFIED BY 'password';
-GRANT ALL PRIVILEGES ON stat.* TO 'stat'@'localhost';
-FLUSH PRIVILEGES;
-exit
-
-6. Edit configs for web and scripts:
-
-cp html/cfg/config.sample.php /opt/Eye/html/cfg/
-mv /opt/Eye/html/cfg/config.sample.php /opt/Eye/html/cfg/config.php
-
-edit: /opt/Eye/html/cfg/config.php
-
-cp scripts/cfg/config.sample /opt/Eye/scripts/cfg/config
-
-edit: /opt/Eye/scripts/cfg/config
-
-You need to specify the password in mysql and the database!
-
-Symmetric AES-128-CBC encryption is used to encrypt passwords to devices. It is necessary to generate a password and an initialization vector, enter in both configs:
-Password: pwgen 16
-Vector: tr -dc 0-9 </dev/urandom | head -c 16 ; echo ''
-
-7. Configuring apache and php:
-
-sed -i 's/short_open_tag = Off/short_open_tag = On/' /etc/php/7.4/apache2/php.ini
-sed -i 's/;date.time zone =/date.time zone = Europe\/Moscow/' /etc/php/7.4/apache2/php.ini
-sed -i -E 's/DocumentRoot\s+\/var\/www\/html/DocumentRoot \/opt\/Eye\/html/' /etc/apache2/sites-available/000-default.conf
-
-systemctl enable apache2
-systemctl start apache2
-
-cp docs/sudoers.d/www-data /etc/sudoers.d/www-data
-
-8. Cron and logrotate
-
-cp docs/cron/stat /etc/cron.d/stat
-cp docs/logrotate/dnsmasq /etc/logrotate.d/dnsmasq
-cp docs/logrotate/scripts/etc/logrotate.d/scripts
-
-Do not forget to uncomment the necessary scripts in the crown
-
-9. Minimal setup is ready! Log in: http://[ip]/admin/ user: admin password: admin, configure the user interface, user networks, etc.
-
-10. Change the administrator password and api key!!!
-
-######################################### DHCP server on Linux ###############################################################
-
-You can use a dhcp server both on mirkotik and on a server with Linux. Imho, dnsmasq is preferable.
-
-apt install dnsmasq -y
-
-cp docs/systemd/dhcp-log.service /etc/systemd/system
-cp docs/systemd/dhcp-log-truncate.service /etc/systemd/system
-cp /etc/dnsmasq.conf /etc/dnsmasq.conf.default
-cat docs/addons/dnsmasq.conf >/etc/dnsmasq.conf
-
-#edit /etc/dnsmasq.conf for you network
-
-systemctl enable dnsmasq dhcp-log dhcp-log-truncate --now
-
-######################################### Additional ##################################################################
-
-1. To determine the vendor of equipment by mac, you need to import a database of macs:
-
-scripts/utils/mac-oids/download-macs.sh
-scripts/utils/mac-oids/update-mac-vendors.pl
-
-2. enable stat-sync service
-
-cp docs/systemd/stat-sync.service /etc/systemd/system
-
-systemctl enable stat-sync.service
-
-######################################### Network flow #####################################################################
-
-Enable netflow at mikrotik:
-/ip traffic-flow
-#for ROS 6
-set enabled=yes
-#for ROS 7
-set enabled=yes  interfaces=WAN
-/ip traffic-flow target
-add dst-address=[IP-NETFLOW-SERVER] port=2055
-
-#cp docs/systemd/eye-statd.service /etc/systemd/system
-#systemctl enable eye-statd
-
-######################################### Remote System Log ###############################################################
-
-If you need to write logs from devices:
-
-apt install syslog-ng -y
-
-cp /etc/syslog-ng/syslog-ng.conf  /etc/syslog-ng/syslog-ng.conf.default
-cat docs/syslog-ng/syslog-ng.conf >/etc/syslog-ng/syslog-ng.conf
-
-systemctl enable syslog-ng
-systemctl start syslog-ng
-
-cp docs/systemd/syslog-stat.service /etc/systemd/system/syslog-stat.service
-
-systemctl enable syslog-stat
-systemctl start syslog-stat
-
-######################################### Mikrotik Management ##########################################################
-
-configure ssh access parameters to the router in the admin panel (login | password | port) http://[IP]/admin/customers/control-options.php
-
-we register in the router (http:// [IP]/admin/devices/), enter and disable servers, enable the use of servers, a dhcp server (not necessary if we use dnsmasq)
-
-Adding rules to the firewall:
-
-/ip firewall filter
-
-add action=jump chain=forward comment="users set" in-interface-list=WAN jump-target=Users
-add action=jump chain=forward jump-target=Users out-interface-list=WAN
-
-#the above rules should be put above these default ones:
-#add action=drop chain=forward comment="drop forward invalid" connection-state=invalid
-#add action=accept chain=forward comment=related,established connection-state=established,related
-
-#And these rules should be lower than the default ones
-add action=reject chain=forward comment="deny default wan" in-interface-list=WAN log=yes log-prefix=unk_wan: reject-with=icmp-network-unreachable 
-add action=drop chain=forward out-interface-list=WAN
-
-shaper:
-/queue tree
-add max-limit=[YOU BANDWIDTH] name=upload_root_[WAN_INTERFACE_NAME] parent=[WAN_INTERFACE_NAME] queue=pcq-upload-default
-add name=download_root_[LAN_INTERFACE_NAME] parent=[LAN_INTERFACE_NAME] queue=pcq-download-default
-
-launching /opt/Eye/scripts/sync_mikrotik.pl
-The script will create filtering and shaper rules
-
-#dhcp script sampling
-#ROS6
-/tool fetch mode=http keep-result=no url="http://<STAT_IP_OR_HOSTNAME>/api.php\?login=<LOGIN>&api_key=<API_CUSTOMER_KEY>&send=dhcp&mac=$leaseActMAC&ip=$leaseActIP&action=$leaseBound&hostname=$"lease-hostname""
-#ROS7
-/tool fetch mode=http keep-result=no url="http://<STAT_IP_OR_HOSTNAME>/api.php?login=<LOGIN>&api_key=<API_CUSTOMER_KEY>&send=dhcp&mac=$leaseActMAC&ip=$leaseActIP&action=$leaseBound&hostname=$"lease-hostname""
-
-
-#########################################################################################################################

+ 0 - 225
Readme.ru.md

@@ -1,225 +0,0 @@
-Установка
-
-1. Ставим пакеты
-
-#общая часть
-apt install git xxd bsdmainutils
-
-#для сервера с БД
-apt install mariadb-server
-
-#для сервера с вэбом
-apt install apache2 libapache2-mod-fcgid \
-php php-mysql php-bcmath php-intl php-mbstring php-date php-mail php-snmp php-zip php-fpm php-db php-pgsql
-
-#для ядра
-apt install perl libnet-patricia-perl libnetaddr-ip-perl libconfig-tiny-perl libnet-dns-perl libdatetime-perl \
-libnet-netmask-perl libtext-iconv-perl libnet-snmp-perl libnet-telnet-perl libdbi-perl \
-libdbd-mysql-perl libparallel-forkmanager-perl libproc-daemon-perl libdatetime-format-dateparse-perl \
-libnetwork-ipv4addr-perl libnet-openssh-perl libfile-tail-perl libcrypt-rijndael-perl \
-libcrypt-cbc-perl libcryptx-perl libdbd-pg-perl libfile-path-tiny-perl libexpect-perl libcrypt-des-perl
-
-#дополнительно
-apt install dnsmasq syslog-ng 
-apt install bind9 bind9-utils bind9-host
-
-2. Create user and group
-
-addgroup --system eye
-adduser --system  --disabled-password --disabled-login --ingroup eye --home=/opt/Eye eye
-chmod 770 /opt/Eye
-
-2.1 Если нужна работа с nagios
-usermod -a -G eye nagios
-
-3. Качаем исходники и раскидываем по каталогам:
-
-git clone https://github.com/rajven/Eye
-mkdir -p /opt/Eye/scripts
-mkdir -p /opt/Eye/scripts/cfg
-mkdir -p /opt/Eye/scripts/log
-cd Eye/
-cp -R scripts/ /opt/Eye/
-cp -R html/ /opt/Eye/
-
-patch perl snmp for support SHA512
-
-#cp -f docs/patches/USM.pm /usr/share/perl5/Net/SNMP/Security/USM.pm
-
-4. Можно скачать дополнительные скрипты (красивости)
-
-mkdir -p /opt/Eye/html/js/jq
-mkdir -p /opt/Eye/html/js/select2
-
-download from https://jquery.com/download/ production jQuery to /opt/Eye/html/js/jq
-#wget https://code.jquery.com/jquery-1.12.4.min.js -O /opt/Eye/html/js/jq/jquery.min.js
-or
-#wget https://code.jquery.com/jquery-3.7.0.min.js -O /opt/Eye/html/js/jq/jquery.min.js
-
-download from https://github.com/select2/select2 release
-#wget https://github.com/select2/select2/archive/4.0.12.tar.gz
-#tar -xzf 4.0.12.tar.gz -C /opt/Eye/html/js/select2/ --strip-components=2 select2-4.0.12/dist
-#rm -f 4.0.12.tar.gz
-
-download jstree from  https://github.com/vakata/jstree/
-#wget https://github.com/vakata/jstree/zipball/3.3.12 -O js.zip
-#unzip js.zip "vakata-jstree-7a03954/dist/*" -d "/opt/Eye/html/"
-#mv /opt/Eye/html/vakata-jstree-7a03954/dist/ /opt/Eye/html/js/jstree
-#rm -d /opt/Eye/html/vakata-jstree-7a03954
-#rm -f js.zip
-
-5. Настраиваем mysql 
-
-set password for root
-#mysql_secure_installation
-
-Создаём базу данных
-#cat docs/mysql/create_db.sql | mysql -u root -p
-
-Импортируем таблицы
-#cat docs/mysql/latest-mysql.sql | mysql -u root -p stat
-
-Create user and database
-
-#mysql -u root -p
-
-CREATE USER 'stat'@'localhost' IDENTIFIED BY 'password';
-GRANT ALL PRIVILEGES ON stat.* TO 'stat'@'localhost';
-FLUSH PRIVILEGES;
-exit
-
-6. Настраиваем конфиги для вэба и скриптов:
-
-cp html/inc/config.sample.php /opt/Eye/html/cfg/
-mv /opt/Eye/html/cfg/config.sample.php /opt/Eye/html/cfg/config.php
-
-edit: /opt/Eye/html/cfg/config.php
-
-cp scripts/cfg/config.sample /opt/Eye/scripts/cfg/config
-
-edit: /opt/Eye/scripts/cfg/config
-
-Надо указать пароль в  mysql и базу данных!
-
-Для шифрования паролей на устройства используется симметричное ишфрование AES-128-CBC. Необходимо сгенерировать пароль и вектор инициализации, внести в оба конфига:
-Пароль: pwgen 16
-Вектор: tr -dc 0-9 </dev/urandom | head -c 16 ; echo ''
-
-7. Настраиваем апач и php:
-
-sed -i 's/short_open_tag = Off/short_open_tag = On/' /etc/php/7.4/apache2/php.ini
-sed -i 's/;date.timezone =/date.timezone = Europe\/Moscow/' /etc/php/7.4/apache2/php.ini
-sed -i -E 's/DocumentRoot\s+\/var\/www\/html/DocumentRoot \/opt\/Eye\/html/' /etc/apache2/sites-available/000-default.conf
-
-systemctl enable apache2
-systemctl start apache2
-
-cp docs/sudoers.d/www-data /etc/sudoers.d/www-data
-
-8. Cron & logrotate
-
-cp docs/cron/stat /etc/cron.d/stat
-cp docs/logrotate/dnsmasq /etc/logrotate.d/dnsmasq
-cp docs/logrotate/scripts /etc/logrotate.d/scripts
-
-Не забудьте раскомментировать в кроне неоходимые скрипты
-
-9. Минимальная настройка готова! Заходим: http://[ip]/admin/ user: admin password: admin, настраиваем список устройств, используемые сети и т.д.
-
-10. Change admin password and api key!!!
-
-######################################### DHCP Server at Linux ###############################################################
-
-Можно использовать dhcp-сервер как на миркотике, так и на сервере с Linux. Имхо, dnsmasq - предпочтительнее.
-
-apt install dnsmasq -y
-
-cp docs/systemd/dhcp-log.service /etc/systemd/system
-cp docs/systemd/dhcp-log-truncate.service /etc/systemd/system
-cp /etc/dnsmasq.conf /etc/dnsmasq.conf.default
-cat docs/addons/dnsmasq.conf >/etc/dnsmasq.conf
-
-#edit /etc/dnsmasq.conf for you network
-
-systemctl enable dnsmasq dhcp-log dhcp-log-truncate --now
-
-######################################### Additional ##################################################################
-
-1. Для определения вендора оборудования по маку, необходимо импортировать базу маков:
-
-scripts/utils/mac-oids/download-macs.sh
-scripts/utils/mac-oids/update-mac-vendors.pl
-
-2. Для изменения списков доступа на маршрутизаторе сразу после внесения изменений в вэб-интерфейсе необходимо включить сервис stat-sync
-
-cp docs/systemd/stat-sync.service /etc/systemd/system
-
-systemctl enable stat-sync.service
-
-######################################### Network flow #####################################################################
-
-Включаем netflow на роутере микротик:
-#for ROS 6
-set enabled=yes
-#for ROS 7
-set enabled=yes  interfaces=WAN
-
-/ip traffic-flow target
-add dst-address=[IP-SERVER] port=2055
-
-#cp docs/systemd/eye-statd.service /etc/systemd/system
-#systemctl enable eye-statd
-
-######################################### Remote syslog ###############################################################
-
-Если нужно писать логи с устройств:
-
-apt install syslog-ng -y
-
-cp /etc/syslog-ng/syslog-ng.conf  /etc/syslog-ng/syslog-ng.conf.default
-cat docs/syslog-ng/syslog-ng.conf >/etc/syslog-ng/syslog-ng.conf
-
-systemctl enable syslog-ng
-systemctl start syslog-ng
-
-cp docs/systemd/syslog-stat.service /etc/systemd/system/syslog-stat.service
-
-systemctl enable syslog-stat
-systemctl start syslog-stat
-
-######################################### Mikrotik managment ##########################################################
-
-настраиваем параметры доступа по ssh к роутеру в админке (login|password|port)  http://[IP]/admin/customers/control-options.php
-
-указываем в роутере (http://[IP]/admin/devices/) внешние и внутренние интерфейсы, включаем использование шейперов, dhcp-сервера (не нужно, если исопльзуем dnsmasq)
-
-Добавляем правила в фаервол:
-
-/ip firewall filter
-
-add action=jump chain=forward comment="users set" in-interface-list=WAN jump-target=Users
-add action=jump chain=forward jump-target=Users out-interface-list=WAN
-
-#указанные выше правила надо поставить выше этих дефалтных:
-#add action=drop chain=forward comment="drop forward invalid" connection-state=invalid
-#add action=accept chain=forward comment=related,established connection-state=established,related
-
-#А эти правила должны быть ниже дефолтных
-add action=reject chain=forward comment="deny default wan" in-interface-list=WAN log=yes log-prefix=unk_wan: reject-with=icmp-network-unreachable 
-add action=drop chain=forward out-interface-list=WAN
-
-шейпер:
-/queue tree
-add max-limit=[YOU BANDWIDTH] name=upload_root_[WAN_INTERFACE_NAME] parent=[WAN_INTERFACE_NAME] queue=pcq-upload-default
-add name=download_root_[LAN_INTERFACE_NAME] parent=[LAN_INTERFACE_NAME] queue=pcq-download-default
-
-запускаем /opt/Eye/scripts/sync_mikrotik.pl
-Скрипт создаст правила фильтрации и шейпера
-
-#dhcp script
-#ROS6
-/tool fetch mode=http keep-result=no url="http://<STAT_IP_OR_HOSTNAME>/api.php\?login=<LOGIN>&api_key=<API_CUSTOMER_KEY>&send=dhcp&mac=$leaseActMAC&ip=$leaseActIP&action=$leaseBound&hostname=$"lease-hostname""
-#ROS7
-/tool fetch mode=http keep-result=no url="http://<STAT_IP_OR_HOSTNAME>/api.php?login=<LOGIN>&api_key=<API_CUSTOMER_KEY>&send=dhcp&mac=$leaseActMAC&ip=$leaseActIP&action=$leaseBound&hostname=$"lease-hostname""
-
-#########################################################################################################################

+ 0 - 0
docs/mysql/create_db.sql → docs/databases/mysql/en/create_db.sql


+ 1 - 1
docs/mysql/latest-mysql-en.sql → docs/databases/mysql/en/data.sql

@@ -284,7 +284,7 @@ INSERT INTO `Filter_list` VALUES (3,'http',NULL,'tcp','0/0','80',NULL,0);
 INSERT INTO `Filter_list` VALUES (4,'https',NULL,'tcp','0/0','443',NULL,0);
 INSERT INTO `Filter_list` VALUES (5,'icq',NULL,'tcp','0/0','5190',NULL,0);
 INSERT INTO `Filter_list` VALUES (6,'jabber',NULL,'tcp','0/0','5222',NULL,0);
-INSERT INTO `Filter_list` VALUES (9,'allow_all','любой трафик','all','0/0','0','0',0);
+INSERT INTO `Filter_list` VALUES (9,'allow_all','any','all','0/0','0','0',0);
 INSERT INTO `Filter_list` VALUES (10,'icmp',NULL,'icmp','0/0','0',NULL,0);
 INSERT INTO `Filter_list` VALUES (11,'ftp',NULL,'tcp','0/0','20-21',NULL,0);
 INSERT INTO `Filter_list` VALUES (15,'telnet',NULL,'tcp','0/0','23',NULL,0);

+ 0 - 0
docs/mysql/nagios.sql → docs/databases/mysql/nagios.sql


+ 0 - 0
docs/mysql/reset_admin.sql → docs/databases/mysql/reset_admin.sql


+ 791 - 0
docs/databases/mysql/ru/create_db.sql

@@ -0,0 +1,791 @@
+SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
+SET time_zone = "+00:00";
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8mb4 */;
+
+CREATE DATABASE IF NOT EXISTS `stat` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+USE `stat`;
+
+CREATE TABLE `acl` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) NOT NULL,
+  `description.english` varchar(250) NOT NULL,
+  `description.russian` varchar(250) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `ad_comp_cache` (
+  `id` int(11) NOT NULL,
+  `name` varchar(63) NOT NULL,
+  `last_found` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp()
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `auth_rules` (
+  `id` int(11) NOT NULL,
+  `user_id` int(11) DEFAULT NULL,
+  `ou_id` int(11) DEFAULT NULL,
+  `type` int(11) NOT NULL,
+  `rule` varchar(40) DEFAULT NULL,
+  `comment` varchar(250) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `building` (
+  `id` int(11) NOT NULL,
+  `name` varchar(50) NOT NULL,
+  `comment` varchar(250) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `config` (
+  `id` int(11) NOT NULL,
+  `option_id` int(11) DEFAULT NULL,
+  `value` varchar(250) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `config_options` (
+  `id` int(11) NOT NULL,
+  `option_name` varchar(50) NOT NULL,
+  `description.russian` text DEFAULT NULL,
+  `description.english` text DEFAULT NULL,
+  `draft` tinyint(1) NOT NULL DEFAULT 0,
+  `uniq` tinyint(1) NOT NULL DEFAULT 1,
+  `type` varchar(100) NOT NULL,
+  `default_value` varchar(250) DEFAULT NULL,
+  `min_value` int(11) NOT NULL DEFAULT 0,
+  `max_value` int(11) NOT NULL DEFAULT 0
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `connections` (
+  `id` bigint(20) UNSIGNED NOT NULL,
+  `device_id` bigint(20) UNSIGNED NOT NULL,
+  `port_id` bigint(20) UNSIGNED NOT NULL,
+  `auth_id` bigint(20) UNSIGNED NOT NULL,
+  `last_found` datetime NOT NULL DEFAULT current_timestamp()
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `Customers` (
+  `id` int(11) NOT NULL,
+  `Login` varchar(20) DEFAULT 'NULL',
+  `comment` varchar(100) DEFAULT NULL,
+  `password` varchar(255) DEFAULT 'NULL',
+  `api_key` varchar(255) DEFAULT NULL,
+  `rights` tinyint(1) NOT NULL DEFAULT 3
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `devices` (
+  `id` int(11) NOT NULL,
+  `device_type` int(11) NOT NULL DEFAULT 1,
+  `device_model_id` int(11) DEFAULT 89,
+  `firmware` varchar(100) DEFAULT NULL,
+  `vendor_id` int(11) NOT NULL DEFAULT 1,
+  `device_name` varchar(50) DEFAULT NULL,
+  `building_id` int(11) NOT NULL DEFAULT 1,
+  `ip` varchar(15) DEFAULT NULL,
+  `ip_int` bigint(10) UNSIGNED DEFAULT NULL,
+  `login` varchar(50) DEFAULT NULL,
+  `password` varchar(255) DEFAULT NULL,
+  `protocol` int(11) NOT NULL DEFAULT 0,
+  `control_port` int(11) NOT NULL DEFAULT 23,
+  `port_count` int(11) NOT NULL DEFAULT 0,
+  `SN` varchar(80) DEFAULT NULL,
+  `comment` varchar(255) DEFAULT NULL,
+  `snmp_version` tinyint(4) NOT NULL DEFAULT 0,
+  `snmp3_auth_proto` varchar(10) NOT NULL DEFAULT 'sha512',
+  `snmp3_priv_proto` varchar(10) NOT NULL DEFAULT 'aes128',
+  `snmp3_user_rw` varchar(20) DEFAULT NULL,
+  `snmp3_user_rw_password` varchar(20) DEFAULT NULL,
+  `snmp3_user_ro` varchar(20) DEFAULT NULL,
+  `snmp3_user_ro_password` varchar(20) DEFAULT NULL,
+  `community` varchar(50) NOT NULL DEFAULT 'public',
+  `rw_community` varchar(50) NOT NULL DEFAULT 'private',
+  `fdb_snmp_index` tinyint(1) NOT NULL DEFAULT 0,
+  `discovery` tinyint(1) NOT NULL DEFAULT 1,
+  `netflow_save` tinyint(1) NOT NULL DEFAULT 0,
+  `user_acl` tinyint(1) NOT NULL DEFAULT 0,
+  `dhcp` tinyint(1) NOT NULL DEFAULT 0,
+  `nagios` tinyint(1) NOT NULL DEFAULT 0,
+  `active` tinyint(1) NOT NULL DEFAULT 1,
+  `nagios_status` varchar(10) NOT NULL DEFAULT 'UP',
+  `queue_enabled` tinyint(1) NOT NULL DEFAULT 0,
+  `connected_user_only` tinyint(1) NOT NULL DEFAULT 1,
+  `user_id` int(11) DEFAULT NULL,
+  `deleted` tinyint(1) NOT NULL DEFAULT 0,
+  `discovery_locked` tinyint(1) NOT NULL DEFAULT 0,
+  `locked_timestamp` timestamp NULL DEFAULT current_timestamp()
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `device_filter_instances` (
+  `id` int(11) NOT NULL,
+  `instance_id` int(11) DEFAULT NULL,
+  `device_id` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `device_l3_interfaces` (
+  `id` int(11) NOT NULL,
+  `device_id` int(11) DEFAULT NULL,
+  `snmpin` int(11) DEFAULT NULL,
+  `interface_type` int(11) NOT NULL DEFAULT 0,
+  `name` varchar(100) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `device_models` (
+  `id` int(11) NOT NULL,
+  `model_name` varchar(200) DEFAULT NULL,
+  `vendor_id` int(11) DEFAULT 1,
+  `poe_in` tinyint(1) NOT NULL DEFAULT 0,
+  `poe_out` tinyint(1) NOT NULL DEFAULT 0,
+  `nagios_template` varchar(200) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `device_ports` (
+  `id` bigint(20) UNSIGNED NOT NULL,
+  `device_id` int(11) DEFAULT NULL,
+  `snmp_index` int(11) DEFAULT NULL,
+  `port` int(11) DEFAULT NULL,
+  `ifName` varchar(40) DEFAULT NULL,
+  `port_name` varchar(40) DEFAULT NULL,
+  `comment` varchar(50) DEFAULT NULL,
+  `target_port_id` int(11) NOT NULL DEFAULT 0,
+  `auth_id` bigint(20) UNSIGNED DEFAULT NULL,
+  `last_mac_count` int(11) DEFAULT 0,
+  `uplink` tinyint(1) NOT NULL DEFAULT 0,
+  `nagios` tinyint(1) NOT NULL DEFAULT 0,
+  `skip` tinyint(1) NOT NULL DEFAULT 0,
+  `vlan` int(11) NOT NULL DEFAULT 1,
+  `tagged_vlan` varchar(250) DEFAULT NULL,
+  `untagged_vlan` varchar(250) DEFAULT NULL,
+  `forbidden_vlan` varchar(250) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `device_types` (
+  `id` int(11) NOT NULL,
+  `name.russian` varchar(50) DEFAULT NULL,
+  `name.english` varchar(50) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `dhcp_log` (
+  `id` bigint(20) UNSIGNED NOT NULL,
+  `mac` varchar(17) NOT NULL,
+  `ip_int` bigint(20) UNSIGNED NOT NULL,
+  `ip` varchar(15) NOT NULL,
+  `action` varchar(10) NOT NULL,
+  `timestamp` timestamp NOT NULL DEFAULT current_timestamp(),
+  `auth_id` bigint(20) UNSIGNED NOT NULL,
+  `dhcp_hostname` varchar(250) DEFAULT NULL,
+  `circuit-id` varchar(255) DEFAULT NULL,
+  `remote-id` varchar(255) DEFAULT NULL,
+  `client-id` varchar(250) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci KEY_BLOCK_SIZE=8 ROW_FORMAT=COMPRESSED;
+
+CREATE TABLE `dhcp_queue` (
+  `id` bigint(20) UNSIGNED NOT NULL,
+  `mac` varchar(17) NOT NULL,
+  `ip` varchar(15) NOT NULL,
+  `action` varchar(10) NOT NULL,
+  `timestamp` timestamp NOT NULL DEFAULT current_timestamp(),
+  `dhcp_hostname` varchar(250) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci KEY_BLOCK_SIZE=8 ROW_FORMAT=COMPRESSED;
+
+CREATE TABLE `dns_cache` (
+  `id` bigint(20) UNSIGNED NOT NULL,
+  `dns` varchar(250) DEFAULT NULL,
+  `ip` bigint(20) UNSIGNED DEFAULT NULL,
+  `timestamp` timestamp NOT NULL DEFAULT current_timestamp()
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `dns_queue` (
+  `id` int(11) NOT NULL,
+  `auth_id` int(11) DEFAULT NULL,
+  `name_type` varchar(10) NOT NULL DEFAULT 'A',
+  `name` varchar(200) DEFAULT NULL,
+  `type` varchar(10) NOT NULL DEFAULT 'add',
+  `value` varchar(100) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `filter_instances` (
+  `id` int(11) NOT NULL,
+  `name` varchar(50) DEFAULT NULL,
+  `comment` varchar(200) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `Filter_list` (
+  `id` int(11) NOT NULL,
+  `name` varchar(50) DEFAULT NULL,
+  `comment` varchar(250) DEFAULT NULL,
+  `proto` varchar(10) DEFAULT NULL,
+  `dst` text DEFAULT NULL,
+  `dstport` varchar(20) DEFAULT NULL,
+  `srcport` varchar(20) DEFAULT NULL,
+  `type` int(10) UNSIGNED NOT NULL DEFAULT 0
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `gateway_subnets` (
+  `id` int(11) NOT NULL,
+  `device_id` int(11) DEFAULT NULL,
+  `subnet_id` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `Group_filters` (
+  `id` int(11) NOT NULL,
+  `group_id` int(11) NOT NULL DEFAULT 0,
+  `filter_id` int(11) NOT NULL DEFAULT 0,
+  `order` int(11) NOT NULL DEFAULT 0,
+  `action` tinyint(1) NOT NULL DEFAULT 0
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `Group_list` (
+  `id` int(11) NOT NULL,
+  `instance_id` int(11) NOT NULL DEFAULT 1,
+  `group_name` varchar(50) DEFAULT NULL,
+  `comment` varchar(250) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `mac_history` (
+  `id` bigint(20) UNSIGNED NOT NULL,
+  `mac` varchar(12) DEFAULT NULL,
+  `timestamp` timestamp NOT NULL DEFAULT current_timestamp(),
+  `device_id` bigint(20) UNSIGNED DEFAULT NULL,
+  `port_id` bigint(20) UNSIGNED DEFAULT NULL,
+  `ip` varchar(16) NOT NULL DEFAULT '',
+  `auth_id` bigint(20) UNSIGNED DEFAULT NULL,
+  `dhcp_hostname` varchar(250) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `mac_vendors` (
+  `id` int(11) NOT NULL,
+  `oui` varchar(20) DEFAULT NULL,
+  `companyName` varchar(255) DEFAULT NULL,
+  `companyAddress` varchar(255) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `OU` (
+  `id` int(11) NOT NULL,
+  `ou_name` varchar(40) DEFAULT NULL,
+  `comment` varchar(250) DEFAULT NULL,
+  `default_users` tinyint(1) NOT NULL DEFAULT 0,
+  `default_hotspot` tinyint(1) NOT NULL DEFAULT 0,
+  `nagios_dir` varchar(255) DEFAULT NULL,
+  `nagios_host_use` varchar(50) DEFAULT NULL,
+  `nagios_ping` tinyint(1) NOT NULL DEFAULT 1,
+  `nagios_default_service` varchar(100) DEFAULT NULL,
+  `enabled` int(11) NOT NULL DEFAULT 0,
+  `filter_group_id` int(11) NOT NULL DEFAULT 0,
+  `queue_id` int(11) NOT NULL DEFAULT 0,
+  `dynamic` tinyint(1) NOT NULL DEFAULT 0,
+  `life_duration` decimal(10,2) NOT NULL DEFAULT 24.00,
+  `parent_id` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `Queue_list` (
+  `id` int(11) NOT NULL,
+  `queue_name` varchar(20) NOT NULL,
+  `Download` int(11) NOT NULL DEFAULT 0,
+  `Upload` int(11) NOT NULL DEFAULT 0
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `remote_syslog` (
+  `id` bigint(20) UNSIGNED NOT NULL,
+  `date` timestamp NOT NULL DEFAULT current_timestamp(),
+  `device_id` bigint(20) UNSIGNED NOT NULL,
+  `ip` varchar(15) NOT NULL,
+  `message` text NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci KEY_BLOCK_SIZE=8 ROW_FORMAT=COMPRESSED;
+
+CREATE TABLE `sessions` (
+  `id` varchar(128) NOT NULL,
+  `data` text NOT NULL,
+  `last_accessed` int(11) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `subnets` (
+  `id` int(11) NOT NULL,
+  `subnet` varchar(18) DEFAULT NULL,
+  `vlan_tag` int(11) NOT NULL DEFAULT 1,
+  `ip_int_start` bigint(20) NOT NULL,
+  `ip_int_stop` bigint(20) NOT NULL,
+  `dhcp_start` bigint(20) NOT NULL DEFAULT 0,
+  `dhcp_stop` bigint(20) NOT NULL DEFAULT 0,
+  `dhcp_lease_time` int(11) NOT NULL DEFAULT 480,
+  `gateway` bigint(20) NOT NULL DEFAULT 0,
+  `office` tinyint(1) NOT NULL DEFAULT 1,
+  `hotspot` tinyint(1) NOT NULL DEFAULT 0,
+  `vpn` tinyint(1) NOT NULL DEFAULT 0,
+  `free` tinyint(1) NOT NULL DEFAULT 0,
+  `dhcp` tinyint(1) NOT NULL DEFAULT 1,
+  `static` tinyint(1) NOT NULL DEFAULT 0,
+  `dhcp_update_hostname` tinyint(1) NOT NULL DEFAULT 0,
+  `discovery` tinyint(1) NOT NULL DEFAULT 1,
+  `notify` tinyint(1) NOT NULL DEFAULT 7,
+  `comment` varchar(250) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `Traffic_detail` (
+  `id` bigint(20) UNSIGNED NOT NULL,
+  `auth_id` bigint(20) UNSIGNED DEFAULT NULL,
+  `router_id` int(11) NOT NULL DEFAULT 0,
+  `timestamp` timestamp NULL DEFAULT NULL,
+  `proto` tinyint(3) UNSIGNED DEFAULT NULL,
+  `src_ip` int(10) UNSIGNED NOT NULL,
+  `dst_ip` int(10) UNSIGNED NOT NULL,
+  `src_port` smallint(5) UNSIGNED NOT NULL,
+  `dst_port` smallint(5) UNSIGNED NOT NULL,
+  `bytes` bigint(20) NOT NULL,
+  `pkt` int(10) UNSIGNED NOT NULL DEFAULT 0
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `Unknown_mac` (
+  `id` bigint(20) UNSIGNED NOT NULL,
+  `mac` varchar(12) DEFAULT NULL,
+  `port_id` bigint(20) UNSIGNED DEFAULT NULL,
+  `device_id` int(11) DEFAULT NULL,
+  `timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp()
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `User_auth` (
+  `id` int(11) NOT NULL,
+  `user_id` bigint(20) UNSIGNED NOT NULL DEFAULT 0,
+  `ou_id` int(11) DEFAULT NULL,
+  `ip` varchar(18) NOT NULL DEFAULT '',
+  `ip_int` bigint(10) UNSIGNED NOT NULL DEFAULT 0,
+  `save_traf` tinyint(1) NOT NULL DEFAULT 0,
+  `enabled` tinyint(1) NOT NULL DEFAULT 0,
+  `dhcp` tinyint(1) NOT NULL DEFAULT 1,
+  `filter_group_id` tinyint(1) NOT NULL DEFAULT 0,
+  `dynamic` tinyint(1) NOT NULL DEFAULT 0,
+  `eof` datetime DEFAULT NULL,
+  `deleted` tinyint(4) NOT NULL DEFAULT 0,
+  `comments` varchar(250) DEFAULT NULL,
+  `dns_name` varchar(253) DEFAULT NULL,
+  `dns_ptr_only` tinyint(1) NOT NULL DEFAULT 0,
+  `WikiName` varchar(250) DEFAULT NULL,
+  `dhcp_acl` text DEFAULT NULL,
+  `queue_id` int(11) NOT NULL DEFAULT 0,
+  `mac` varchar(20) NOT NULL DEFAULT '',
+  `dhcp_action` varchar(10) NOT NULL DEFAULT '',
+  `dhcp_option_set` varchar(50) DEFAULT NULL,
+  `dhcp_time` datetime NOT NULL DEFAULT current_timestamp(),
+  `dhcp_hostname` varchar(60) DEFAULT NULL,
+  `last_found` datetime NOT NULL DEFAULT current_timestamp(),
+  `arp_found` datetime DEFAULT NULL,
+  `blocked` tinyint(1) NOT NULL DEFAULT 0,
+  `day_quota` int(11) NOT NULL DEFAULT 0,
+  `month_quota` int(11) NOT NULL DEFAULT 0,
+  `device_model_id` int(11) DEFAULT 87,
+  `firmware` varchar(100) DEFAULT NULL,
+  `timestamp` timestamp NOT NULL DEFAULT current_timestamp(),
+  `client-id` varchar(250) DEFAULT NULL,
+  `nagios` tinyint(1) NOT NULL DEFAULT 0,
+  `nagios_status` varchar(10) NOT NULL DEFAULT '',
+  `nagios_handler` varchar(50) NOT NULL DEFAULT '',
+  `link_check` tinyint(1) NOT NULL DEFAULT 0,
+  `changed` tinyint(1) NOT NULL DEFAULT 0,
+  `dhcp_changed` int(11) NOT NULL DEFAULT 0,
+  `changed_time` datetime NOT NULL DEFAULT current_timestamp(),
+  `created_by` varchar(10) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `User_auth_alias` (
+  `id` int(11) NOT NULL,
+  `auth_id` int(11) NOT NULL,
+  `alias` varchar(100) DEFAULT NULL,
+  `description` varchar(100) DEFAULT NULL,
+  `timestamp` timestamp NOT NULL DEFAULT current_timestamp()
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `User_list` (
+  `id` bigint(20) UNSIGNED NOT NULL,
+  `timestamp` timestamp NOT NULL DEFAULT current_timestamp(),
+  `login` varchar(255) DEFAULT NULL,
+  `fio` varchar(255) DEFAULT NULL,
+  `enabled` tinyint(1) NOT NULL DEFAULT 1,
+  `blocked` tinyint(1) NOT NULL DEFAULT 0,
+  `deleted` tinyint(1) NOT NULL DEFAULT 0,
+  `ou_id` int(11) NOT NULL DEFAULT 0,
+  `device_id` int(11) DEFAULT NULL,
+  `filter_group_id` int(11) NOT NULL DEFAULT 0,
+  `queue_id` int(11) NOT NULL DEFAULT 0,
+  `day_quota` int(11) NOT NULL DEFAULT 0,
+  `month_quota` int(11) NOT NULL DEFAULT 0,
+  `permanent` tinyint(1) NOT NULL DEFAULT 0
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `user_sessions` (
+  `id` int(11) NOT NULL,
+  `session_id` varchar(128) NOT NULL,
+  `user_id` int(11) NOT NULL,
+  `ip_address` varchar(45) NOT NULL,
+  `user_agent` text NOT NULL,
+  `created_at` int(11) NOT NULL,
+  `last_activity` int(11) NOT NULL,
+  `is_active` tinyint(1) DEFAULT 1
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `User_stats` (
+  `id` bigint(20) UNSIGNED NOT NULL,
+  `router_id` bigint(20) UNSIGNED DEFAULT 0,
+  `auth_id` bigint(20) UNSIGNED NOT NULL DEFAULT 0,
+  `timestamp` datetime NOT NULL DEFAULT current_timestamp(),
+  `byte_in` bigint(20) NOT NULL DEFAULT 0,
+  `byte_out` bigint(20) NOT NULL DEFAULT 0
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `User_stats_full` (
+  `id` bigint(20) UNSIGNED NOT NULL,
+  `router_id` bigint(20) UNSIGNED DEFAULT 0,
+  `auth_id` bigint(20) UNSIGNED NOT NULL DEFAULT 0,
+  `timestamp` datetime NOT NULL DEFAULT current_timestamp(),
+  `byte_in` bigint(20) NOT NULL DEFAULT 0,
+  `byte_out` bigint(20) NOT NULL DEFAULT 0,
+  `pkt_in` int(11) DEFAULT NULL,
+  `pkt_out` int(11) DEFAULT NULL,
+  `step` int(11) NOT NULL DEFAULT 600
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `variables` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) NOT NULL,
+  `value` varchar(255) DEFAULT NULL,
+  `clear_time` timestamp NOT NULL DEFAULT current_timestamp(),
+  `created` timestamp NOT NULL DEFAULT current_timestamp()
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `vendors` (
+  `id` int(11) NOT NULL,
+  `name` varchar(40) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `version` (
+  `id` int(11) NOT NULL DEFAULT 1,
+  `version` varchar(10) NOT NULL DEFAULT '2.4.14'
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `Wan_stats` (
+  `id` int(11) NOT NULL,
+  `time` datetime NOT NULL DEFAULT current_timestamp(),
+  `router_id` int(11) DEFAULT NULL,
+  `interface_id` int(11) DEFAULT NULL,
+  `in` bigint(20) UNSIGNED NOT NULL DEFAULT 0,
+  `out` bigint(20) UNSIGNED NOT NULL DEFAULT 0,
+  `forward_in` bigint(20) UNSIGNED NOT NULL DEFAULT 0,
+  `forward_out` bigint(20) UNSIGNED NOT NULL DEFAULT 0
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE `worklog` (
+  `id` bigint(20) UNSIGNED NOT NULL,
+  `timestamp` timestamp NOT NULL DEFAULT current_timestamp(),
+  `auth_id` bigint(20) UNSIGNED NOT NULL DEFAULT 0,
+  `customer` varchar(50) NOT NULL DEFAULT 'system',
+  `ip` varchar(18) NOT NULL DEFAULT '127.0.0.1',
+  `message` text NOT NULL,
+  `level` int(11) NOT NULL DEFAULT 1
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci KEY_BLOCK_SIZE=8 ROW_FORMAT=COMPRESSED;
+
+
+ALTER TABLE `acl`
+  ADD PRIMARY KEY (`id`);
+
+ALTER TABLE `ad_comp_cache`
+  ADD PRIMARY KEY (`id`),
+  ADD UNIQUE KEY `comp_name` (`name`);
+
+ALTER TABLE `auth_rules`
+  ADD PRIMARY KEY (`id`),
+  ADD UNIQUE KEY `rule` (`rule`),
+  ADD KEY `user_id` (`user_id`);
+
+ALTER TABLE `building`
+  ADD PRIMARY KEY (`id`);
+
+ALTER TABLE `config`
+  ADD PRIMARY KEY (`id`),
+  ADD KEY `option` (`option_id`);
+
+ALTER TABLE `config_options`
+  ADD PRIMARY KEY (`id`);
+
+ALTER TABLE `connections`
+  ADD PRIMARY KEY (`id`),
+  ADD KEY `auth_id` (`auth_id`),
+  ADD KEY `device_id` (`device_id`,`port_id`);
+
+ALTER TABLE `Customers`
+  ADD PRIMARY KEY (`id`);
+
+ALTER TABLE `devices`
+  ADD PRIMARY KEY (`id`),
+  ADD KEY `ip` (`ip`),
+  ADD KEY `device_type` (`device_type`);
+
+ALTER TABLE `device_filter_instances`
+  ADD PRIMARY KEY (`id`);
+
+ALTER TABLE `device_l3_interfaces`
+  ADD PRIMARY KEY (`id`);
+
+ALTER TABLE `device_models`
+  ADD PRIMARY KEY (`id`);
+
+ALTER TABLE `device_ports`
+  ADD PRIMARY KEY (`id`),
+  ADD KEY `device_id` (`device_id`),
+  ADD KEY `port` (`port`),
+  ADD KEY `target_port_id` (`target_port_id`);
+
+ALTER TABLE `device_types`
+  ADD PRIMARY KEY (`id`);
+
+ALTER TABLE `dhcp_log`
+  ADD PRIMARY KEY (`id`),
+  ADD KEY `timestamp` (`timestamp`,`action`);
+
+ALTER TABLE `dhcp_queue`
+  ADD PRIMARY KEY (`id`),
+  ADD KEY `timestamp` (`timestamp`,`action`);
+
+ALTER TABLE `dns_cache`
+  ADD PRIMARY KEY (`id`),
+  ADD KEY `dns` (`dns`,`ip`),
+  ADD KEY `timestamp` (`timestamp`);
+
+ALTER TABLE `dns_queue`
+  ADD PRIMARY KEY (`id`);
+
+ALTER TABLE `filter_instances`
+  ADD PRIMARY KEY (`id`),
+  ADD UNIQUE KEY `name` (`name`);
+
+ALTER TABLE `Filter_list`
+  ADD PRIMARY KEY (`id`),
+  ADD KEY `Name` (`name`);
+
+ALTER TABLE `gateway_subnets`
+  ADD PRIMARY KEY (`id`);
+
+ALTER TABLE `Group_filters`
+  ADD PRIMARY KEY (`id`),
+  ADD KEY `GroupId` (`group_id`,`filter_id`);
+
+ALTER TABLE `Group_list`
+  ADD PRIMARY KEY (`id`);
+
+ALTER TABLE `mac_history`
+  ADD PRIMARY KEY (`id`),
+  ADD KEY `mac` (`mac`,`timestamp`),
+  ADD KEY `ip` (`ip`,`timestamp`),
+  ADD KEY `timestamp` (`timestamp`) USING BTREE,
+  ADD KEY `mac_2` (`mac`),
+  ADD KEY `ip_2` (`ip`);
+
+ALTER TABLE `mac_vendors`
+  ADD PRIMARY KEY (`id`),
+  ADD KEY `oui` (`oui`);
+
+ALTER TABLE `OU`
+  ADD PRIMARY KEY (`id`);
+ALTER TABLE `OU` ADD FULLTEXT KEY `ou_name` (`ou_name`);
+ALTER TABLE `OU` ADD FULLTEXT KEY `ou_name_2` (`ou_name`);
+
+ALTER TABLE `Queue_list`
+  ADD PRIMARY KEY (`id`),
+  ADD UNIQUE KEY `id` (`id`);
+
+ALTER TABLE `remote_syslog`
+  ADD PRIMARY KEY (`id`),
+  ADD KEY `date` (`date`,`device_id`,`ip`);
+
+ALTER TABLE `sessions`
+  ADD PRIMARY KEY (`id`),
+  ADD KEY `last_accessed` (`last_accessed`);
+
+ALTER TABLE `subnets`
+  ADD PRIMARY KEY (`id`),
+  ADD KEY `ip_int_start` (`ip_int_start`,`ip_int_stop`),
+  ADD KEY `dhcp` (`dhcp`,`office`,`hotspot`,`static`);
+
+ALTER TABLE `Traffic_detail`
+  ADD PRIMARY KEY (`id`),
+  ADD KEY `src` (`auth_id`,`timestamp`,`router_id`,`src_ip`) USING BTREE,
+  ADD KEY `dst` (`auth_id`,`timestamp`,`router_id`,`dst_ip`) USING BTREE;
+
+ALTER TABLE `Unknown_mac`
+  ADD PRIMARY KEY (`id`),
+  ADD KEY `timestamp` (`timestamp`,`device_id`,`port_id`,`mac`);
+
+ALTER TABLE `User_auth`
+  ADD PRIMARY KEY (`id`),
+  ADD KEY `auth_index` (`id`,`user_id`,`ip_int`,`mac`,`ip`,`deleted`) USING BTREE,
+  ADD KEY `deleted` (`deleted`),
+  ADD KEY `ou_id` (`ou_id`);
+
+ALTER TABLE `User_auth_alias`
+  ADD PRIMARY KEY (`id`),
+  ADD KEY `auth_id` (`auth_id`);
+
+ALTER TABLE `User_list`
+  ADD PRIMARY KEY (`id`),
+  ADD KEY `users` (`id`,`ou_id`,`enabled`,`blocked`,`deleted`);
+
+ALTER TABLE `user_sessions`
+  ADD PRIMARY KEY (`id`),
+  ADD KEY `session_id` (`session_id`),
+  ADD KEY `user_id` (`user_id`),
+  ADD KEY `is_active` (`is_active`);
+
+ALTER TABLE `User_stats`
+  ADD PRIMARY KEY (`id`),
+  ADD KEY `timestamp` (`timestamp`,`auth_id`,`router_id`);
+
+ALTER TABLE `User_stats_full`
+  ADD PRIMARY KEY (`id`),
+  ADD KEY `timestamp` (`timestamp`,`auth_id`,`router_id`);
+
+ALTER TABLE `variables`
+  ADD PRIMARY KEY (`id`),
+  ADD UNIQUE KEY `name` (`name`),
+  ADD KEY `clear_time` (`clear_time`,`created`);
+
+ALTER TABLE `vendors`
+  ADD PRIMARY KEY (`id`);
+
+ALTER TABLE `version`
+  ADD UNIQUE KEY `id` (`id`);
+
+ALTER TABLE `Wan_stats`
+  ADD PRIMARY KEY (`id`),
+  ADD UNIQUE KEY `main` (`time`,`router_id`,`interface_id`),
+  ADD KEY `times` (`time`);
+
+ALTER TABLE `worklog`
+  ADD PRIMARY KEY (`id`),
+  ADD KEY `idx_customer` (`customer`,`level`,`timestamp`),
+  ADD KEY `idx_timestamp` (`level`,`timestamp`),
+  ADD KEY `idx_auth_id` (`auth_id`,`level`,`timestamp`);
+
+
+ALTER TABLE `acl`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `ad_comp_cache`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `auth_rules`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `building`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `config`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `config_options`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `connections`
+  MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `Customers`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `devices`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `device_filter_instances`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `device_l3_interfaces`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `device_models`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `device_ports`
+  MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `device_types`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `dhcp_log`
+  MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `dhcp_queue`
+  MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `dns_cache`
+  MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `dns_queue`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `filter_instances`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `Filter_list`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `gateway_subnets`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `Group_filters`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `Group_list`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `mac_history`
+  MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `mac_vendors`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `OU`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `Queue_list`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `remote_syslog`
+  MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `subnets`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `Traffic_detail`
+  MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `Unknown_mac`
+  MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `User_auth`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `User_auth_alias`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `User_list`
+  MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `user_sessions`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `User_stats`
+  MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `User_stats_full`
+  MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `variables`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `vendors`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `Wan_stats`
+  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `worklog`
+  MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
+
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

+ 0 - 0
docs/mysql/latest-mysql-ru.sql → docs/databases/mysql/ru/data.sql


+ 726 - 0
docs/databases/postgres/en/create_db.sql

@@ -0,0 +1,726 @@
+-- Create database with English locale
+CREATE DATABASE stat
+    WITH 
+    ENCODING = 'UTF8'
+    LC_COLLATE = 'en_US.UTF-8'
+    LC_CTYPE = 'en_US.UTF-8'
+    TEMPLATE = template0
+    CONNECTION LIMIT = -1;
+
+\c stat;
+
+-- Enable required extensions
+CREATE EXTENSION IF NOT EXISTS pg_trgm;
+CREATE EXTENSION IF NOT EXISTS btree_gin;
+CREATE EXTENSION IF NOT EXISTS ip4r;
+
+-- Access Control List
+CREATE TABLE acl (
+    id SERIAL PRIMARY KEY,
+    name VARCHAR(30) NOT NULL,
+    "description.english" VARCHAR(250) NOT NULL,
+    "description.russian" VARCHAR(250) NOT NULL
+);
+COMMENT ON TABLE acl IS 'Access Control List - roles and permissions';
+COMMENT ON COLUMN acl."description.english" IS 'Description in English';
+COMMENT ON COLUMN acl."description.russian" IS 'Description in Russian';
+
+-- Active Directory computer cache
+CREATE TABLE ad_comp_cache (
+    id SERIAL PRIMARY KEY,
+    name VARCHAR(63) NOT NULL UNIQUE,
+    last_found TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+COMMENT ON TABLE ad_comp_cache IS 'Cache of computers from Active Directory';
+COMMENT ON COLUMN ad_comp_cache.name IS 'Computer name in AD';
+COMMENT ON COLUMN ad_comp_cache.last_found IS 'Last time this computer was found';
+
+-- Authentication rules
+CREATE TABLE auth_rules (
+    id SERIAL PRIMARY KEY,
+    user_id INTEGER,
+    ou_id INTEGER,
+    type INTEGER NOT NULL,
+    rule VARCHAR(40) UNIQUE,
+    comment VARCHAR(250)
+);
+COMMENT ON TABLE auth_rules IS 'User authentication and authorization rules';
+COMMENT ON COLUMN auth_rules.type IS 'Rule type: 0=allow, 1=deny, etc.';
+COMMENT ON COLUMN auth_rules.rule IS 'Rule identifier (unique)';
+
+-- Buildings
+CREATE TABLE building (
+    id SERIAL PRIMARY KEY,
+    name VARCHAR(50) NOT NULL,
+    comment VARCHAR(250)
+);
+COMMENT ON TABLE building IS 'Physical buildings/locations';
+COMMENT ON COLUMN building.name IS 'Building name';
+
+-- System configuration
+CREATE TABLE config (
+    id SERIAL PRIMARY KEY,
+    option_id INTEGER,
+    value VARCHAR(250)
+);
+COMMENT ON TABLE config IS 'System configuration values';
+
+-- Configuration options
+CREATE TABLE config_options (
+    id SERIAL PRIMARY KEY,
+    option_name VARCHAR(50) NOT NULL,
+    "description.russian" TEXT,
+    "description.english" TEXT,
+    draft BOOLEAN NOT NULL DEFAULT FALSE,
+    uniq BOOLEAN NOT NULL DEFAULT TRUE,
+    type VARCHAR(100) NOT NULL,
+    default_value VARCHAR(250),
+    min_value INTEGER NOT NULL DEFAULT 0,
+    max_value INTEGER NOT NULL DEFAULT 0
+);
+COMMENT ON TABLE config_options IS 'Available configuration options';
+COMMENT ON COLUMN config_options.option_name IS 'Option name/key';
+COMMENT ON COLUMN config_options.draft IS 'Is option in draft state';
+COMMENT ON COLUMN config_options.uniq IS 'Is option unique (single value)';
+
+-- Network connections
+CREATE TABLE connections (
+    id BIGSERIAL PRIMARY KEY,
+    device_id BIGINT NOT NULL,
+    port_id BIGINT NOT NULL,
+    auth_id BIGINT NOT NULL,
+    last_found TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+COMMENT ON TABLE connections IS 'Current network connections (MAC-IP-device-port)';
+COMMENT ON COLUMN connections.device_id IS 'Network device ID';
+COMMENT ON COLUMN connections.port_id IS 'Device port ID';
+COMMENT ON COLUMN connections.auth_id IS 'User authorization ID';
+COMMENT ON COLUMN connections.last_found IS 'Last time this connection was active';
+
+-- System customers/users
+CREATE TABLE Customers (
+    id SERIAL PRIMARY KEY,
+    Login VARCHAR(20),
+    comment VARCHAR(100),
+    password VARCHAR(255),
+    api_key VARCHAR(255),
+    rights SMALLINT NOT NULL DEFAULT 3
+);
+COMMENT ON TABLE Customers IS 'System users/administrators';
+COMMENT ON COLUMN Customers.Login IS 'User login name';
+COMMENT ON COLUMN Customers.rights IS 'Access rights level: 0=view, 1=operator, 2=admin, 3=superadmin';
+
+-- Network devices
+CREATE TABLE devices (
+    id SERIAL PRIMARY KEY,
+    device_type INTEGER NOT NULL DEFAULT 1,
+    device_model_id INTEGER DEFAULT 89,
+    firmware VARCHAR(100),
+    vendor_id INTEGER NOT NULL DEFAULT 1,
+    device_name VARCHAR(50),
+    building_id INTEGER NOT NULL DEFAULT 1,
+    ip INET,
+    ip_int BIGINT,
+    login VARCHAR(50),
+    password VARCHAR(255),
+    protocol SMALLINT NOT NULL DEFAULT 0,
+    control_port INTEGER NOT NULL DEFAULT 23,
+    port_count INTEGER NOT NULL DEFAULT 0,
+    SN VARCHAR(80),
+    comment VARCHAR(255),
+    snmp_version SMALLINT NOT NULL DEFAULT 0,
+    snmp3_auth_proto VARCHAR(10) NOT NULL DEFAULT 'sha512',
+    snmp3_priv_proto VARCHAR(10) NOT NULL DEFAULT 'aes128',
+    snmp3_user_rw VARCHAR(20),
+    snmp3_user_rw_password VARCHAR(20),
+    snmp3_user_ro VARCHAR(20),
+    snmp3_user_ro_password VARCHAR(20),
+    community VARCHAR(50) NOT NULL DEFAULT 'public',
+    rw_community VARCHAR(50) NOT NULL DEFAULT 'private',
+    fdb_snmp_index BOOLEAN NOT NULL DEFAULT FALSE,
+    discovery BOOLEAN NOT NULL DEFAULT TRUE,
+    netflow_save BOOLEAN NOT NULL DEFAULT FALSE,
+    user_acl BOOLEAN NOT NULL DEFAULT FALSE,
+    dhcp BOOLEAN NOT NULL DEFAULT FALSE,
+    nagios BOOLEAN NOT NULL DEFAULT FALSE,
+    active BOOLEAN NOT NULL DEFAULT TRUE,
+    nagios_status VARCHAR(10) NOT NULL DEFAULT 'UP',
+    queue_enabled BOOLEAN NOT NULL DEFAULT FALSE,
+    connected_user_only BOOLEAN NOT NULL DEFAULT TRUE,
+    user_id INTEGER,
+    deleted BOOLEAN NOT NULL DEFAULT FALSE,
+    discovery_locked BOOLEAN NOT NULL DEFAULT FALSE,
+    locked_timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
+COMMENT ON TABLE devices IS 'Network devices (switches, routers, etc.)';
+COMMENT ON COLUMN devices.device_type IS 'Device type ID';
+COMMENT ON COLUMN devices.ip IS 'Device management IP address';
+COMMENT ON COLUMN devices.snmp_version IS 'SNMP version: 0=disabled, 1=v1, 2=v2c, 3=v3';
+COMMENT ON COLUMN devices.discovery IS 'Enable automatic discovery';
+COMMENT ON COLUMN devices.active IS 'Is device active and monitored';
+
+-- Device filter instances
+CREATE TABLE device_filter_instances (
+    id SERIAL PRIMARY KEY,
+    instance_id INTEGER,
+    device_id INTEGER
+);
+COMMENT ON TABLE device_filter_instances IS 'Filter instances assigned to devices';
+
+-- Device L3 interfaces
+CREATE TABLE device_l3_interfaces (
+    id SERIAL PRIMARY KEY,
+    device_id INTEGER,
+    snmpin INTEGER,
+    interface_type INTEGER NOT NULL DEFAULT 0,
+    name VARCHAR(100)
+);
+COMMENT ON TABLE device_l3_interfaces IS 'Layer 3 interfaces on devices';
+COMMENT ON COLUMN device_l3_interfaces.interface_type IS 'Interface type: 0=unknown, 1=LAN, 2=WAN, 3=DMZ';
+
+-- Device models
+CREATE TABLE device_models (
+    id SERIAL PRIMARY KEY,
+    model_name VARCHAR(200),
+    vendor_id INTEGER DEFAULT 1,
+    poe_in BOOLEAN NOT NULL DEFAULT FALSE,
+    poe_out BOOLEAN NOT NULL DEFAULT FALSE,
+    nagios_template VARCHAR(200)
+);
+COMMENT ON TABLE device_models IS 'Device models and specifications';
+COMMENT ON COLUMN device_models.poe_in IS 'Supports Power over Ethernet input';
+COMMENT ON COLUMN device_models.poe_out IS 'Provides Power over Ethernet';
+
+-- Device ports
+CREATE TABLE device_ports (
+    id BIGSERIAL PRIMARY KEY,
+    device_id INTEGER,
+    snmp_index INTEGER,
+    port INTEGER,
+    ifName VARCHAR(40),
+    port_name VARCHAR(40),
+    comment VARCHAR(50),
+    target_port_id INTEGER NOT NULL DEFAULT 0,
+    auth_id BIGINT,
+    last_mac_count INTEGER DEFAULT 0,
+    uplink BOOLEAN NOT NULL DEFAULT FALSE,
+    nagios BOOLEAN NOT NULL DEFAULT FALSE,
+    skip BOOLEAN NOT NULL DEFAULT FALSE,
+    vlan INTEGER NOT NULL DEFAULT 1,
+    tagged_vlan VARCHAR(250),
+    untagged_vlan VARCHAR(250),
+    forbidden_vlan VARCHAR(250)
+);
+COMMENT ON TABLE device_ports IS 'Network device ports/interfaces';
+COMMENT ON COLUMN device_ports.port IS 'Physical port number';
+COMMENT ON COLUMN device_ports.uplink IS 'Is this an uplink port';
+COMMENT ON COLUMN device_ports.vlan IS 'Default/native VLAN ID';
+
+-- Device types
+CREATE TABLE device_types (
+    id SERIAL PRIMARY KEY,
+    "name.russian" VARCHAR(50),
+    "name.english" VARCHAR(50)
+);
+COMMENT ON TABLE device_types IS 'Device type classification';
+COMMENT ON COLUMN device_types."name.russian" IS 'Device type name in Russian';
+COMMENT ON COLUMN device_types."name.english" IS 'Device type name in English';
+
+-- DHCP logs
+CREATE TABLE dhcp_log (
+    id BIGSERIAL PRIMARY KEY,
+    mac MACADDR NOT NULL,
+    ip_int BIGINT NOT NULL,
+    ip INET NOT NULL,
+    action VARCHAR(10) NOT NULL,
+    timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    auth_id BIGINT NOT NULL,
+    dhcp_hostname VARCHAR(250),
+    "circuit-id" VARCHAR(255),
+    "remote-id" VARCHAR(255),
+    "client-id" VARCHAR(250)
+);
+COMMENT ON TABLE dhcp_log IS 'DHCP server transaction logs';
+COMMENT ON COLUMN dhcp_log.action IS 'DHCP action: DISCOVER, REQUEST, ACK, NAK, RELEASE';
+COMMENT ON COLUMN dhcp_log."circuit-id" IS 'DHCP option 82 circuit ID';
+
+-- DHCP queue
+CREATE TABLE dhcp_queue (
+    id BIGSERIAL PRIMARY KEY,
+    mac MACADDR NOT NULL,
+    ip INET NOT NULL,
+    action VARCHAR(10) NOT NULL,
+    timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    dhcp_hostname VARCHAR(250)
+);
+COMMENT ON TABLE dhcp_queue IS 'Pending DHCP operations queue';
+
+-- DNS cache
+CREATE TABLE dns_cache (
+    id BIGSERIAL PRIMARY KEY,
+    dns VARCHAR(250),
+    ip BIGINT,
+    timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+COMMENT ON TABLE dns_cache IS 'DNS resolution cache';
+
+-- DNS queue
+CREATE TABLE dns_queue (
+    id SERIAL PRIMARY KEY,
+    auth_id INTEGER,
+    name_type VARCHAR(10) NOT NULL DEFAULT 'A',
+    name VARCHAR(200),
+    type VARCHAR(10) NOT NULL DEFAULT 'add',
+    value VARCHAR(100)
+);
+COMMENT ON TABLE dns_queue IS 'Pending DNS operations queue';
+COMMENT ON COLUMN dns_queue.name_type IS 'DNS record type: A, AAAA, PTR, CNAME';
+COMMENT ON COLUMN dns_queue.type IS 'Operation type: add, delete, update';
+
+-- Filter instances
+CREATE TABLE filter_instances (
+    id SERIAL PRIMARY KEY,
+    name VARCHAR(50) UNIQUE,
+    comment VARCHAR(200)
+);
+COMMENT ON TABLE filter_instances IS 'Filter policy instances';
+
+-- Filter rules list
+CREATE TABLE Filter_list (
+    id SERIAL PRIMARY KEY,
+    name VARCHAR(50),
+    comment VARCHAR(250),
+    proto VARCHAR(10),
+    dst TEXT,
+    dstport VARCHAR(20),
+    srcport VARCHAR(20),
+    type INTEGER NOT NULL DEFAULT 0
+);
+COMMENT ON TABLE Filter_list IS 'Firewall/filter rules';
+COMMENT ON COLUMN Filter_list.proto IS 'Protocol: tcp, udp, icmp, etc.';
+COMMENT ON COLUMN Filter_list.dst IS 'Destination IP/CIDR';
+COMMENT ON COLUMN Filter_list.type IS 'Rule type: 0=allow, 1=deny';
+
+-- Gateway subnets
+CREATE TABLE gateway_subnets (
+    id SERIAL PRIMARY KEY,
+    device_id INTEGER,
+    subnet_id INTEGER
+);
+COMMENT ON TABLE gateway_subnets IS 'Which devices serve as gateways for which subnets';
+
+-- Filter assignments to groups
+CREATE TABLE Group_filters (
+    id SERIAL PRIMARY KEY,
+    group_id INTEGER NOT NULL DEFAULT 0,
+    filter_id INTEGER NOT NULL DEFAULT 0,
+    "order" INTEGER NOT NULL DEFAULT 0,
+    action BOOLEAN NOT NULL DEFAULT FALSE
+);
+COMMENT ON TABLE Group_filters IS 'Filter rules assigned to groups';
+COMMENT ON COLUMN Group_filters."order" IS 'Rule processing order';
+COMMENT ON COLUMN Group_filters.action IS 'Action: true=allow, false=deny';
+
+-- Filter groups
+CREATE TABLE Group_list (
+    id SERIAL PRIMARY KEY,
+    instance_id INTEGER NOT NULL DEFAULT 1,
+    group_name VARCHAR(50),
+    comment VARCHAR(250)
+);
+COMMENT ON TABLE Group_list IS 'Filter policy groups';
+
+-- MAC address history
+CREATE TABLE mac_history (
+    id BIGSERIAL PRIMARY KEY,
+    mac VARCHAR(12),
+    timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    device_id BIGINT,
+    port_id BIGINT,
+    ip VARCHAR(16) NOT NULL DEFAULT '',
+    auth_id BIGINT,
+    dhcp_hostname VARCHAR(250)
+);
+COMMENT ON TABLE mac_history IS 'Historical MAC address movements';
+COMMENT ON COLUMN mac_history.mac IS 'MAC address (12 hex chars)';
+COMMENT ON COLUMN mac_history.ip IS 'IP address last used';
+
+-- MAC address vendors
+CREATE TABLE mac_vendors (
+    id SERIAL PRIMARY KEY,
+    oui VARCHAR(20),
+    companyName VARCHAR(255),
+    companyAddress VARCHAR(255)
+);
+COMMENT ON TABLE mac_vendors IS 'MAC address vendor database';
+COMMENT ON COLUMN mac_vendors.oui IS 'Organizationally Unique Identifier (first 6 chars of MAC)';
+
+-- Organizational Units
+CREATE TABLE OU (
+    id SERIAL PRIMARY KEY,
+    ou_name VARCHAR(40),
+    comment VARCHAR(250),
+    default_users BOOLEAN NOT NULL DEFAULT FALSE,
+    default_hotspot BOOLEAN NOT NULL DEFAULT FALSE,
+    nagios_dir VARCHAR(255),
+    nagios_host_use VARCHAR(50),
+    nagios_ping BOOLEAN NOT NULL DEFAULT TRUE,
+    nagios_default_service VARCHAR(100),
+    enabled INTEGER NOT NULL DEFAULT 0,
+    filter_group_id INTEGER NOT NULL DEFAULT 0,
+    queue_id INTEGER NOT NULL DEFAULT 0,
+    dynamic BOOLEAN NOT NULL DEFAULT FALSE,
+    life_duration DECIMAL(10,2) NOT NULL DEFAULT 24.00,
+    parent_id INTEGER
+);
+COMMENT ON TABLE OU IS 'Organizational Units (departments/groups)';
+COMMENT ON COLUMN OU.ou_name IS 'OU name/identifier';
+COMMENT ON COLUMN OU.life_duration IS 'Default lease duration in hours for dynamic OUs';
+
+-- Traffic shaping queues
+CREATE TABLE Queue_list (
+    id SERIAL PRIMARY KEY,
+    queue_name VARCHAR(20) NOT NULL,
+    Download INTEGER NOT NULL DEFAULT 0,
+    Upload INTEGER NOT NULL DEFAULT 0
+);
+COMMENT ON TABLE Queue_list IS 'Traffic shaping bandwidth profiles';
+COMMENT ON COLUMN Queue_list.Download IS 'Download speed limit in Kbps';
+COMMENT ON COLUMN Queue_list.Upload IS 'Upload speed limit in Kbps';
+
+-- Remote syslog messages
+CREATE TABLE remote_syslog (
+    id BIGSERIAL PRIMARY KEY,
+    date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    device_id BIGINT NOT NULL,
+    ip VARCHAR(15) NOT NULL,
+    message TEXT NOT NULL
+);
+COMMENT ON TABLE remote_syslog IS 'Syslog messages from network devices';
+
+-- PHP sessions
+CREATE TABLE sessions (
+    id VARCHAR(128) PRIMARY KEY,
+    data TEXT NOT NULL,
+    last_accessed INTEGER NOT NULL
+);
+COMMENT ON TABLE sessions IS 'PHP session storage';
+
+-- Network subnets
+CREATE TABLE subnets (
+    id SERIAL PRIMARY KEY,
+    subnet VARCHAR(18),
+    vlan_tag INTEGER NOT NULL DEFAULT 1,
+    ip_int_start BIGINT NOT NULL,
+    ip_int_stop BIGINT NOT NULL,
+    dhcp_start BIGINT NOT NULL DEFAULT 0,
+    dhcp_stop BIGINT NOT NULL DEFAULT 0,
+    dhcp_lease_time INTEGER NOT NULL DEFAULT 480,
+    gateway BIGINT NOT NULL DEFAULT 0,
+    office BOOLEAN NOT NULL DEFAULT TRUE,
+    hotspot BOOLEAN NOT NULL DEFAULT FALSE,
+    vpn BOOLEAN NOT NULL DEFAULT FALSE,
+    free BOOLEAN NOT NULL DEFAULT FALSE,
+    dhcp BOOLEAN NOT NULL DEFAULT TRUE,
+    static BOOLEAN NOT NULL DEFAULT FALSE,
+    dhcp_update_hostname BOOLEAN NOT NULL DEFAULT FALSE,
+    discovery BOOLEAN NOT NULL DEFAULT TRUE,
+    notify SMALLINT NOT NULL DEFAULT 7,
+    comment VARCHAR(250)
+);
+COMMENT ON TABLE subnets IS 'Network subnets configuration';
+COMMENT ON COLUMN subnets.subnet IS 'Network in CIDR notation';
+COMMENT ON COLUMN subnets.vlan_tag IS 'VLAN ID for this subnet';
+COMMENT ON COLUMN subnets.office IS 'Is this an office subnet';
+COMMENT ON COLUMN subnets.hotspot IS 'Is this a hotspot/public subnet';
+COMMENT ON COLUMN subnets.notify IS 'Bitmask for notifications: 1=email, 2=sms, 4=telegram';
+
+-- Detailed traffic logs
+CREATE TABLE Traffic_detail (
+    id BIGSERIAL PRIMARY KEY,
+    auth_id BIGINT,
+    router_id INTEGER NOT NULL DEFAULT 0,
+    timestamp TIMESTAMP,
+    proto SMALLINT,
+    src_ip INTEGER NOT NULL,
+    dst_ip INTEGER NOT NULL,
+    src_port INTEGER NOT NULL,
+    dst_port INTEGER NOT NULL,
+    bytes BIGINT NOT NULL,
+    pkt INTEGER NOT NULL DEFAULT 0
+);
+COMMENT ON TABLE Traffic_detail IS 'Detailed traffic flow records (NetFlow)';
+COMMENT ON COLUMN Traffic_detail.proto IS 'IP protocol number';
+COMMENT ON COLUMN Traffic_detail.src_ip IS 'Source IP as integer';
+COMMENT ON COLUMN Traffic_detail.bytes IS 'Bytes transferred in this flow';
+
+-- Unknown MAC addresses
+CREATE TABLE Unknown_mac (
+    id BIGSERIAL PRIMARY KEY,
+    mac VARCHAR(12),
+    port_id BIGINT,
+    device_id INTEGER,
+    timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+COMMENT ON TABLE Unknown_mac IS 'Recently discovered unknown MAC addresses';
+
+-- User authorization records
+CREATE TABLE User_auth (
+    id SERIAL PRIMARY KEY,
+    user_id BIGINT NOT NULL DEFAULT 0,
+    ou_id INTEGER,
+    ip VARCHAR(18) NOT NULL DEFAULT '',
+    ip_int BIGINT NOT NULL DEFAULT 0,
+    save_traf BOOLEAN NOT NULL DEFAULT FALSE,
+    enabled BOOLEAN NOT NULL DEFAULT FALSE,
+    dhcp BOOLEAN NOT NULL DEFAULT TRUE,
+    filter_group_id SMALLINT NOT NULL DEFAULT 0,
+    dynamic BOOLEAN NOT NULL DEFAULT FALSE,
+    eof TIMESTAMP,
+    deleted BOOLEAN NOT NULL DEFAULT FALSE,
+    comments VARCHAR(250),
+    dns_name VARCHAR(253),
+    dns_ptr_only BOOLEAN NOT NULL DEFAULT FALSE,
+    WikiName VARCHAR(250),
+    dhcp_acl TEXT,
+    queue_id INTEGER NOT NULL DEFAULT 0,
+    mac VARCHAR(20) NOT NULL DEFAULT '',
+    dhcp_action VARCHAR(10) NOT NULL DEFAULT '',
+    dhcp_option_set VARCHAR(50),
+    dhcp_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    dhcp_hostname VARCHAR(60),
+    last_found TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    arp_found TIMESTAMP,
+    blocked BOOLEAN NOT NULL DEFAULT FALSE,
+    day_quota INTEGER NOT NULL DEFAULT 0,
+    month_quota INTEGER NOT NULL DEFAULT 0,
+    device_model_id INTEGER DEFAULT 87,
+    firmware VARCHAR(100),
+    timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "client-id" VARCHAR(250),
+    nagios BOOLEAN NOT NULL DEFAULT FALSE,
+    nagios_status VARCHAR(10) NOT NULL DEFAULT '',
+    nagios_handler VARCHAR(50) NOT NULL DEFAULT '',
+    link_check BOOLEAN NOT NULL DEFAULT FALSE,
+    changed BOOLEAN NOT NULL DEFAULT FALSE,
+    dhcp_changed INTEGER NOT NULL DEFAULT 0,
+    changed_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    created_by VARCHAR(10)
+);
+COMMENT ON TABLE User_auth IS 'Network user/device authorization records';
+COMMENT ON COLUMN User_auth.enabled IS 'Is this authorization active';
+COMMENT ON COLUMN User_auth.dynamic IS 'Is this a dynamically created record';
+COMMENT ON COLUMN User_auth.day_quota IS 'Daily traffic quota in bytes';
+COMMENT ON COLUMN User_auth.nagios IS 'Enable Nagios monitoring for this host';
+
+-- User authorization aliases
+CREATE TABLE User_auth_alias (
+    id SERIAL PRIMARY KEY,
+    auth_id INTEGER NOT NULL,
+    alias VARCHAR(100),
+    description VARCHAR(100),
+    timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+COMMENT ON TABLE User_auth_alias IS 'Aliases/DNS names for authorization records';
+
+-- User list
+CREATE TABLE User_list (
+    id BIGSERIAL PRIMARY KEY,
+    timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    login VARCHAR(255),
+    fio VARCHAR(255),
+    enabled BOOLEAN NOT NULL DEFAULT TRUE,
+    blocked BOOLEAN NOT NULL DEFAULT FALSE,
+    deleted BOOLEAN NOT NULL DEFAULT FALSE,
+    ou_id INTEGER NOT NULL DEFAULT 0,
+    device_id INTEGER,
+    filter_group_id INTEGER NOT NULL DEFAULT 0,
+    queue_id INTEGER NOT NULL DEFAULT 0,
+    day_quota INTEGER NOT NULL DEFAULT 0,
+    month_quota INTEGER NOT NULL DEFAULT 0,
+    permanent BOOLEAN NOT NULL DEFAULT FALSE
+);
+COMMENT ON TABLE User_list IS 'User accounts in the system';
+COMMENT ON COLUMN User_list.fio IS 'Full name (ФИО)';
+COMMENT ON COLUMN User_list.permanent IS 'Is this a permanent user (not dynamic)';
+
+-- User sessions (web interface)
+CREATE TABLE user_sessions (
+    id SERIAL PRIMARY KEY,
+    session_id VARCHAR(128) NOT NULL,
+    user_id INTEGER NOT NULL,
+    ip_address VARCHAR(45) NOT NULL,
+    user_agent TEXT NOT NULL,
+    created_at INTEGER NOT NULL,
+    last_activity INTEGER NOT NULL,
+    is_active BOOLEAN DEFAULT TRUE
+);
+COMMENT ON TABLE user_sessions IS 'Web interface user sessions';
+
+-- User traffic statistics
+CREATE TABLE User_stats (
+    id BIGSERIAL PRIMARY KEY,
+    router_id BIGINT DEFAULT 0,
+    auth_id BIGINT NOT NULL DEFAULT 0,
+    timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    byte_in BIGINT NOT NULL DEFAULT 0,
+    byte_out BIGINT NOT NULL DEFAULT 0
+);
+COMMENT ON TABLE User_stats IS 'User traffic statistics (aggregated)';
+
+-- Detailed user statistics
+CREATE TABLE User_stats_full (
+    id BIGSERIAL PRIMARY KEY,
+    router_id BIGINT DEFAULT 0,
+    auth_id BIGINT NOT NULL DEFAULT 0,
+    timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    byte_in BIGINT NOT NULL DEFAULT 0,
+    byte_out BIGINT NOT NULL DEFAULT 0,
+    pkt_in INTEGER,
+    pkt_out INTEGER,
+    step INTEGER NOT NULL DEFAULT 600
+);
+COMMENT ON TABLE User_stats_full IS 'Detailed user traffic statistics';
+COMMENT ON COLUMN User_stats_full.step IS 'Statistics collection interval in seconds';
+
+-- Temporary variables
+CREATE TABLE variables (
+    id SERIAL PRIMARY KEY,
+    name VARCHAR(30) NOT NULL UNIQUE,
+    value VARCHAR(255),
+    clear_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+COMMENT ON TABLE variables IS 'Temporary system variables and locks';
+
+-- Device vendors
+CREATE TABLE vendors (
+    id SERIAL PRIMARY KEY,
+    name VARCHAR(40) NOT NULL
+);
+COMMENT ON TABLE vendors IS 'Network equipment vendors';
+
+-- System version
+CREATE TABLE version (
+    id INTEGER PRIMARY KEY DEFAULT 1,
+    version VARCHAR(10) NOT NULL DEFAULT '2.4.14'
+);
+COMMENT ON TABLE version IS 'System version information';
+
+-- WAN interface statistics
+CREATE TABLE Wan_stats (
+    id SERIAL PRIMARY KEY,
+    time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    router_id INTEGER,
+    interface_id INTEGER,
+    "in" BIGINT NOT NULL DEFAULT 0,
+    "out" BIGINT NOT NULL DEFAULT 0,
+    forward_in BIGINT NOT NULL DEFAULT 0,
+    forward_out BIGINT NOT NULL DEFAULT 0
+);
+COMMENT ON TABLE Wan_stats IS 'WAN interface traffic statistics';
+COMMENT ON COLUMN Wan_stats."in" IS 'Bytes received on WAN interface';
+COMMENT ON COLUMN Wan_stats."out" IS 'Bytes transmitted on WAN interface';
+
+-- System activity log
+CREATE TABLE worklog (
+    id BIGSERIAL PRIMARY KEY,
+    timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    auth_id BIGINT NOT NULL DEFAULT 0,
+    customer VARCHAR(50) NOT NULL DEFAULT 'system',
+    ip VARCHAR(18) NOT NULL DEFAULT '127.0.0.1',
+    message TEXT NOT NULL,
+    level INTEGER NOT NULL DEFAULT 1
+);
+COMMENT ON TABLE worklog IS 'System activity and audit log';
+COMMENT ON COLUMN worklog.level IS 'Log level: 1=info, 2=warning, 3=error, 4=debug';
+
+-- Create indexes (same as original structure)
+CREATE INDEX idx_devices_ip ON devices(ip);
+CREATE INDEX idx_devices_device_type ON devices(device_type);
+CREATE INDEX idx_devices_active ON devices(active) WHERE active = TRUE;
+
+CREATE INDEX idx_device_ports_device_id ON device_ports(device_id);
+CREATE INDEX idx_device_ports_port ON device_ports(port);
+CREATE INDEX idx_device_ports_target_port_id ON device_ports(target_port_id);
+
+CREATE INDEX idx_dhcp_log_timestamp ON dhcp_log(timestamp, action);
+CREATE INDEX idx_dhcp_queue_timestamp ON dhcp_queue(timestamp, action);
+
+CREATE INDEX idx_dns_cache_dns ON dns_cache(dns, ip);
+CREATE INDEX idx_dns_cache_timestamp ON dns_cache(timestamp);
+
+CREATE INDEX idx_mac_history_mac ON mac_history(mac, timestamp);
+CREATE INDEX idx_mac_history_ip ON mac_history(ip, timestamp);
+CREATE INDEX idx_mac_history_timestamp ON mac_history(timestamp);
+
+CREATE INDEX idx_ou_ou_name_gin ON OU USING GIN(ou_name gin_trgm_ops);
+
+CREATE INDEX idx_subnets_ip_int_start ON subnets(ip_int_start, ip_int_stop);
+CREATE INDEX idx_subnets_dhcp ON subnets(dhcp, office, hotspot, static);
+
+CREATE INDEX idx_traffic_detail_src ON Traffic_detail(auth_id, timestamp, router_id, src_ip);
+CREATE INDEX idx_traffic_detail_dst ON Traffic_detail(auth_id, timestamp, router_id, dst_ip);
+
+CREATE INDEX idx_unknown_mac_timestamp ON Unknown_mac(timestamp, device_id, port_id, mac);
+
+CREATE INDEX idx_user_auth_main ON User_auth(id, user_id, ip_int, mac, ip, deleted);
+CREATE INDEX idx_user_auth_deleted ON User_auth(deleted) WHERE deleted = FALSE;
+CREATE INDEX idx_user_auth_ou_id ON User_auth(ou_id);
+
+CREATE INDEX idx_user_list_main ON User_list(id, ou_id, enabled, blocked, deleted);
+
+CREATE INDEX idx_user_sessions_session_id ON user_sessions(session_id);
+CREATE INDEX idx_user_sessions_user_id ON user_sessions(user_id);
+CREATE INDEX idx_user_sessions_is_active ON user_sessions(is_active) WHERE is_active = TRUE;
+
+CREATE INDEX idx_user_stats_timestamp ON User_stats(timestamp, auth_id, router_id);
+CREATE INDEX idx_user_stats_full_timestamp ON User_stats_full(timestamp, auth_id, router_id);
+
+CREATE INDEX idx_wan_stats_time ON Wan_stats(time, router_id, interface_id);
+
+CREATE INDEX idx_worklog_customer ON worklog(customer, level, timestamp);
+CREATE INDEX idx_worklog_timestamp ON worklog(level, timestamp);
+CREATE INDEX idx_worklog_auth_id ON worklog(auth_id, level, timestamp);
+
+-- Functions for IP address conversion
+CREATE OR REPLACE FUNCTION inet_to_bigint(ip_address INET)
+RETURNS BIGINT AS $$
+BEGIN
+    RETURN (
+        (split_part(host(ip_address), '.', 1)::BIGINT << 24) +
+        (split_part(host(ip_address), '.', 2)::BIGINT << 16) +
+        (split_part(host(ip_address), '.', 3)::BIGINT << 8) +
+        split_part(host(ip_address), '.', 4)::BIGINT
+    );
+END;
+$$ LANGUAGE plpgsql IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION bigint_to_inet(ip_int BIGINT)
+RETURNS INET AS $$
+BEGIN
+    RETURN ((ip_int >> 24) & 255) || '.' ||
+           ((ip_int >> 16) & 255) || '.' ||
+           ((ip_int >> 8) & 255) || '.' ||
+           (ip_int & 255);
+END;
+$$ LANGUAGE plpgsql IMMUTABLE;
+
+-- Trigger to automatically update ip_int when ip changes
+CREATE OR REPLACE FUNCTION update_ip_int()
+RETURNS TRIGGER AS $$
+BEGIN
+    IF NEW.ip IS NOT NULL AND (NEW.ip_int IS NULL OR OLD.ip != NEW.ip) THEN
+        NEW.ip_int := inet_to_bigint(NEW.ip::INET);
+    END IF;
+    RETURN NEW;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE TRIGGER trigger_devices_ip_int 
+    BEFORE INSERT OR UPDATE ON devices 
+    FOR EACH ROW EXECUTE FUNCTION update_ip_int();
+
+CREATE TRIGGER trigger_user_auth_ip_int 
+    BEFORE INSERT OR UPDATE ON User_auth 
+    FOR EACH ROW EXECUTE FUNCTION update_ip_int();

+ 537 - 0
docs/databases/postgres/en/data.sql

@@ -0,0 +1,537 @@
+-- Импорт данных в PostgreSQL (сохранены оригинальные названия)
+
+-- ACL (Access Control List)
+INSERT INTO acl (id, name, "description.english", "description.russian") 
+VALUES 
+(1, 'Full access', 'Full access', 'Полный доступ'),
+(2, 'Operator', 'Editing parameters that are not related to access rights', 'Редактирование параметров, не связанных с правами доступа'),
+(3, 'View only', 'View only', 'Только просмотр')
+ON CONFLICT (id) DO UPDATE SET
+    name = EXCLUDED.name,
+    "description.english" = EXCLUDED."description.english",
+    "description.russian" = EXCLUDED."description.russian";
+
+-- Buildings
+INSERT INTO building (id, name, comment)
+VALUES (1, 'Earth', 'Somewhere')
+ON CONFLICT (id) DO UPDATE SET
+    name = EXCLUDED.name,
+    comment = EXCLUDED.comment;
+
+-- Configuration options
+INSERT INTO config_options (id, option_name, "description.russian", "description.english", draft, uniq, type, default_value, min_value, max_value)
+VALUES
+(1, 'KB', 'Еденица измерения трафика - Килобайт (0) или кибибайт (1,default)', 'Traffic measurement unit - Kilobyte (1000b) or kibibyte (1024b,default)', false, true, 'bool', '1024', 0, 1),
+(3, 'dns server', 'ip-адрес DNS-сервера', 'DNS server ip address', false, true, 'text', '127.0.0.1', 0, 0),
+(5, 'dhcp server', 'ip-адрес DHCP-сервера', 'ip address of the DHCP server', false, true, 'text', '127.0.0.1', 0, 0),
+(9, 'default snmp version', 'Версия snmp по умолчанию. В настоящиймомент поддерживаются 1 и 2. Поддержка версии 3 в разработке.', 'The default version of snmp. Currently, 1 and 2 are supported. Support for version 3 is in development.', false, true, 'int', '2', 1, 3),
+(11, 'default snmp community', 'Read snmp community по умолчанию', 'Read snmp community by default', false, true, 'text', 'public', 0, 0),
+(21, 'admin email', 'E-mail администратора', 'Administrator e-mail', false, true, 'text', 'root', 0, 0),
+(22, 'add user from netflow', 'Создавать ли новые записи для неизвестных адресов из анализа трафика netflow. Не включать, если netflow снимает данные с маршрутизатора локальной сети', 'Whether to create new records for unknown addresses from netflow traffic analysis. Do not enable if netflow get data from the local network router', false, true, 'bool', '0', 0, 1),
+(23, 'save traffic detail', 'Сохранять ли детализацию трафика из netflow по ip-адресам пользователей', 'Whether to keep the details of traffic from netflow by ip addresses of users', false, true, 'bool', '1', 0, 1),
+(26, 'history detail traffic', 'Глубина хранения детализации в сутках. Установка значения больше 3-7 дней приведёт к разрастанию базы данных и увеличит время отображения детализации в интерфейсе администратора', 'Depth of detail storage in days. Setting a value greater than 3-7 days will cause the database to grow and increase the time about to display details in the admin interface', false, true, 'int', '3', 1, 7),
+(27, 'history dhcp lease', 'Глубина хранения аренды dhcp-сервера', 'Storage depth of the dhcp server lease', false, true, 'int', '1', 0, 0),
+(28, 'router_login', 'Логин для входа на сетевые устройства по умолчанию', 'Default login for network devices', false, true, 'text', 'admin', 0, 0),
+(29, 'router_password', 'Пароль по умолчанию на сетевые устройства', 'Default password for network devices', false, true, 'text', 'admin', 0, 0),
+(30, 'router_ssh_port', 'Порт ssh по умолчанию', 'SSH default port', false, true, 'int', '22', 22, 0),
+(32, 'org name', 'Название организации', 'Organization name', false, true, 'text', 'ORG', 0, 0),
+(33, 'office domain', 'Домен организации', 'Organization domain', false, true, 'text', 'local', 0, 0),
+(34, 'debug', 'Включить отладку', 'Enable debugging', false, true, 'bool', '0', 0, 1),
+(35, 'connections history, days', 'Время хранения истории мест подключения ip-адресов', 'Storage time of the history of connection locations of ip addresses', false, true, 'int', '90', 1, 365),
+(37, 'refresh access lists', 'Расположение скрипта управления контролем доступа для роутеров Mikrotik', 'Location of the access control script for Mikrotik routers', false, true, 'text', '/opt/Eye/scripts/sync_mikrotik.pl', 0, 0),
+(38, 'regenerate dhcp cconfig', 'Расположение скрипта управления конфигурацией dhcp-серверами', 'Location of the dhcp server configuration management script', false, true, 'text', '/opt/Eye/scripts/update-dnsmasq', 0, 0),
+(39, 'regenerate dns cconfig', 'Расположение скрипта управления dns-сервером', 'Location of the dns server management script', false, true, 'text', '/opt/Eye/scripts/update-dns', 0, 0),
+(40, 'regenerate nagios cconfig', 'Расположение скрипта конфигурирования Nagios', 'Location of the Nagios configuration script', false, true, 'text', '/etc/nagios/restart_nagios', 0, 0),
+(41, 'discovery network', 'Расположение скрипта сканирования сети', 'Location of the network scan script', false, true, 'text', '/opt/Eye/scripts/fetch_new_arp.pl', 0, 0),
+(44, 'Ignore hotspot dhcp log', 'Не писать лог событий dhcp-сервера хотспота. Имеет смысл вклчючать, поскольку время аренды в хот-споте как правило маленькое и в записях хот-спота становятся незаметны логи обычных пользователей', 'Do not write the event log of the hotspot dhcp server. It makes sense to include it, since the rental time in the hotspot is usually small and the logs of ordinary users become invisible in the hotspot records', false, true, 'bool', '1', 0, 1),
+(45, 'ignore update dhcp event', 'Не писать события обновления ip-адреса dhcp-сервера.', 'Do not write events for updating the IP address of the dhcp server.', false, true, 'bool', '0', 0, 1),
+(46, 'update hostname from dhcp', 'Обновлять имя хоста в DNS при получении адреса по DHCP', 'Update the hostname in DNS when receiving the address via DHCP', false, true, 'bool', '0', 0, 1),
+(47, 'history worklog', 'Глубина хранения VERBOSE логов работы в интерфейсе администратора', 'Depth of work VERBOSE logs storage in the admin interface', false, true, 'int', '90', 0, 1095),
+(48, 'history syslog', 'Глубина хранения логов работы syslog-сервера', 'Syslog server logs storage depth', false, true, 'int', '90', 0, 1095),
+(49, 'history traffic stats', 'Глубина хранения статистики трафикаюзеров', 'User traffic statistics storage depth', false, true, 'int', '365', 0, 0),
+(50, 'urgent sync access', 'Немедленное изменение списков доступа на роутере после правки записи пользователя', 'Immediate change of access lists on the router after editing the user record', false, true, 'bool', '0', 0, 1),
+(51, 'Email_alert', 'Отправлять e-mail уведомления', 'Send e-mail notifications', false, true, 'bool', '1', 0, 1),
+(52, 'Sender email', 'E-mail адрес, с которого рассылается почта', 'E-mail address from which mail is sent', false, true, 'text', 'root', 0, 0),
+(53, 'log level', 'Каждый уровень включает в себя предыдущий:
+0- ERROR - писать только ошибки
+1 - WARNING - писать предупреждения
+2 - INFO - писать информационные сообщения
+3 - VERBOSE - писать подробную информацию о выполняемых операциях', 'Each level includes the previous one:
+0 - ERROR - write only errors
+1 - WARNING - write warnings
+2 - INFO - write informational
+3 - VERBOSE - write detailed information about the operations performed', false, true, 'int', '2', 0, 3),
+(54, 'enable_quotes', 'Включить обработку квот по трафику', 'Enable traffic quota processing', false, true, 'bool', '0', 0, 1),
+(55, 'netflow_step', 'Интервал сброса данных из коллектора netflow, минуты', 'Data reset interval from netflow collector, minutes', false, true, 'int', '1', 1, 10),
+(56, 'traffic_ipstat_history', 'Время хранения полной статистики по трафику для каждого ip-адреса в сутках. Таблица в 6 раз больше обычной часовой статистики. Врядли кому-то потребуется глубина хранения более месяца.', 'The storage time of complete traffic statistics for each ip address in days. The table is 6 times larger than the usual hourly statistic Hardly anyone will need a storage depth of more than a month.', false, true, 'int', '30', 0, 365),
+(57, 'nagios_url', 'Адрес сайта nagios', 'nagios site address', false, true, 'text', 'http://127.0.0.1/nagios', 0, 0),
+(58, 'cacti_url', 'Адрес сайта cacti', 'cacti site address', false, true, 'text', 'http://127.0.0.1/cacti', 0, 0),
+(59, 'torrus_url', 'Адрес сайта Torrus', 'Torrus website address', false, true, 'text', 'http://127.0.0.1/torrus/CollectorName/', 0, 0),
+(60, 'wiki_url', 'Адрес wiki', 'Wiki website address', false, true, 'text', 'http://127.0.0.1/wiki', 0, 0),
+(61, 'wiki_path', 'Путь к каталогу данных вики', 'Path to wiki data directory', false, true, 'text', '/var/www/foswiki/data/', 0, 0),
+(62, 'stat_url', 'Адрес этого сайта', 'Address of this site', false, true, 'text', 'http://127.0.0.1/stat', 0, 0),
+(63, 'wiki_web', 'Web for Wiki. Default - Main. http://example.local/Main/WebHome', 'Web for Wiki. Default - Main. http://example.local/Main/WebHome', false, true, 'text', 'Main', 0, 0),
+(64, 'auto_mac_rule', 'Создавать автоматическую привязку мак-адреса к юзеру. Т.е. все ip-адреса для найденного мака будут привязываться к одном и тому же юзеру.', 'Create an automatic binding of the mac address to the user. I.e. all ip addresses for the found mac will be bound to the same user.', false, true, 'bool', '0', 0, 1),
+(65, 'mikrotik_command_interface', 'Используемый способ конфигурирования (0 - cli для ROS 6, 1 - rest api для ROS 7)', 'Configuration method used (0 - cli for ROS 6, 1 - rest api for ROS 7)', true, true, 'int', '0', 0, 1),
+(66, 'mikrotik_rest_api_ssl', 'Использовать https для rest api', 'Use HTTPS for rest api', true, true, 'bool', '1', 0, 1),
+(67, 'mikrotik_rest_api_port', 'Порт вэб-интерфейса для rest api', 'Web interface port for rest API', true, true, 'int', '443', 0, 0),
+(68, 'config_mode', 'Режим конфигурирования. Скрипт опроса устройств не выполняется.', 'Configuration mode. The device polling script is not running.', false, true, 'bool', '0', 0, 1),
+(69, 'clean_empty_user', 'Автоматически удалять записи пользователей, не содержащие ip-адресов или автоматических привязок', 'Automatically delete user records that do not contain IP addresses or automatic bindings', false, true, 'bool', '0', 0, 1),
+(70, 'dns_server_type', 'Тип используемого dns-сервера: Windows, Bind. Если используется локальный dnsmasq - параметры dns-сервера указывать не надо.', 'The type of dns server used: Windows, Bind. If you are using a local dnsmasq, you do not need to specify the dns server parameters.', false, true, 'list;windows;bind', 'bind', 0, 0),
+(71, 'enable_dns_updates', 'Включить обновления DNS имен при изменении dns-имени в ip-записи', 'Enable DNS name updates when dns name changes in an ip record', false, true, 'bool', '0', 0, 1),
+(72, 'netflow_path', 'Каталог для хранения данных, полученных по netflow от маршрутизаторов', 'The directory for storing data received via netflow from routers', false, true, 'text', '/opt/Eye/netflow', 0, 0),
+(73, 'check_computer_exists', 'Проверять существование компьютера в домене перед обновлением DNS по DHCP запросу', 'Verify the existence of a computer in the domain before updating DNS by DHCP request', false, true, 'bool', '1', 0, 0)
+ON CONFLICT (id) DO UPDATE SET
+    option_name = EXCLUDED.option_name,
+    "description.russian" = EXCLUDED."description.russian",
+    "description.english" = EXCLUDED."description.english",
+    draft = EXCLUDED.draft,
+    uniq = EXCLUDED.uniq,
+    type = EXCLUDED.type,
+    default_value = EXCLUDED.default_value,
+    min_value = EXCLUDED.min_value,
+    max_value = EXCLUDED.max_value;
+
+-- System configuration values
+INSERT INTO config (id, option_id, value)
+VALUES
+(1, 1, '0'),
+(2, 11, 'public'),
+(3, 32, 'ORG'),
+(123, 19, '1'),
+(124, 35, '120'),
+(125, 9, '2'),
+(126, 41, '/opt/Eye/scripts/fetch_new_arp.pl'),
+(127, 26, '3'),
+(128, 27, '10'),
+(129, 48, '90'),
+(130, 49, '365'),
+(131, 47, '90'),
+(132, 53, '1'),
+(133, 55, '1'),
+(134, 56, '30'),
+(135, 34, '0'),
+(137, 65, '0'),
+(142, 54, ''),
+(143, 17, '1'),
+(144, 37, '/opt/Eye/scripts/sync_mikrotik.pl'),
+(145, 23, '1'),
+(148, 22, '1')
+ON CONFLICT (id) DO UPDATE SET
+    option_id = EXCLUDED.option_id,
+    value = EXCLUDED.value;
+
+-- System users/administrators
+INSERT INTO Customers (id, Login, comment, password, api_key, rights)
+VALUES (1, 'admin', 'Administrator', '$2y$11$wohV8Tuqu0Yai9Shacei5OKfMxG5bnLxB5ACcZcJJ3pYEbIH0qLGG', 'c3284d0f94606de1fd2af172aba15bf31', 1)
+ON CONFLICT (id) DO UPDATE SET
+    Login = EXCLUDED.Login,
+    comment = EXCLUDED.comment,
+    password = EXCLUDED.password,
+    api_key = EXCLUDED.api_key,
+    rights = EXCLUDED.rights;
+
+-- Device models
+INSERT INTO device_models (id, model_name, vendor_id, poe_in, poe_out, nagios_template)
+VALUES
+(1, '2011LS', 9, true, false, NULL),
+(2, '2011UAS-2HnD', 9, true, false, NULL),
+(3, 'AT-8000S', 8, false, false, NULL),
+(4, 'AT-8100S/48POE', 8, false, false, NULL),
+(5, 'AT-9000/28', 8, false, false, NULL),
+(6, 'AT-GS950/24', 8, false, false, NULL),
+(7, 'CCR1009-7G-1C-1S+', 9, false, false, NULL),
+(8, 'CCR1036-8G-2S+', 9, false, false, NULL),
+(10, 'CRS317-1G-16S+', 9, false, false, NULL),
+(11, 'CRS326-24S+2Q+', 9, false, false, NULL),
+(12, 'CRS328-24P-4S+', 9, true, false, NULL),
+(14, 'CRS328-4C-20S-4S+', 9, false, false, NULL),
+(15, 'DGS-3120-48TC', 7, false, false, NULL),
+(16, 'ES-2024', 4, false, false, NULL),
+(17, 'ES-2024A', 4, false, false, NULL),
+(18, 'ES-2108', 4, false, false, NULL),
+(19, 'ES-2108-G', 4, false, false, NULL),
+(20, 'ES-3124-4F', 4, false, false, NULL),
+(21, 'GS110TP', 10, false, true, NULL),
+(22, 'GS-4024', 4, false, false, NULL),
+(23, 'HP 1910', 15, false, false, NULL),
+(24, 'ISCOM2110A-MA', 5, false, false, NULL),
+(25, 'ISCOM2110EA-MA', 5, false, false, NULL),
+(26, 'ISCOM2126EA-MA', 5, false, false, NULL),
+(27, 'ISCOM2128EA-MA', 5, false, false, NULL),
+(28, 'Linux server', 1, false, false, ''),
+(29, 'MES2124F', 2, false, false, NULL),
+(30, 'MES2124MB', 2, false, false, NULL),
+(31, 'MES5248', 2, false, false, NULL),
+(32, 'RB2011UAS', 9, true, false, NULL),
+(33, 'RB3011UiAS', 9, true, false, NULL),
+(34, 'RB960PGS', 9, true, true, NULL),
+(35, 'RBD52G-5HacD2HnD', 9, true, false, NULL),
+(36, 'S2940-8G-v2', 6, false, false, NULL),
+(37, 'S2980G-24T', 6, false, false, NULL),
+(38, 'S3750G-24S-E', 6, false, false, NULL),
+(39, 'S5300-52P-LI-AC', 3, false, false, NULL),
+(40, 'S5320-52X-PWR-SI-AC', 3, false, false, NULL),
+(41, 'S5321-28X-SI-AC', 3, false, false, NULL),
+(42, 'S5321-52X-SI-AC', 3, false, false, NULL),
+(43, 'S6320-54C-EI-48S-AC', 3, false, false, NULL),
+(44, 'SNR-S2980G-24T', 6, false, false, NULL),
+(45, 'V1910-16G', 15, false, false, NULL),
+(46, 'V1910-24G-PoE', 15, false, false, NULL),
+(47, 'Windows server', 1, false, false, NULL),
+(48, 'WS-C2960G-24TC-L', 16, false, false, NULL),
+(49, 'WS-C3560G-24TS-S', 16, false, false, NULL),
+(50, 'x210-16GT', 8, false, false, NULL),
+(51, 'x210-24GT', 8, false, false, NULL),
+(52, 'x610-24Ts/X', 8, false, false, NULL),
+(53, 'x610-48Ts', 8, false, false, NULL),
+(54, 'XGS-4728', 4, false, false, NULL),
+(55, 'ZyWall 310', 4, false, false, NULL),
+(56, 'APC Smart-UPS_3000', 20, false, false, 'ups.cfg'),
+(57, 'APC Smart-UPS_5000', 20, false, false, 'ups.cfg'),
+(58, 'Schneider Smart-UPS_3000', 21, false, false, NULL),
+(59, 'SMG-1016M', 2, false, false, NULL),
+(60, 'EATON 9PX 1500i RT 2U', 64, false, false, NULL),
+(61, 'EATON 9PX3000i_RT_2U', 64, false, false, NULL),
+(62, 'EATON 9PX_6000i', 64, false, false, NULL),
+(63, 'EATON PW9130_3000', 64, false, false, NULL),
+(64, 'EATON PW9130_3000VA-R', 64, false, false, NULL),
+(65, 'Epson WF-5620 Series', 59, false, false, NULL),
+(66, 'Epson WF-8590 Series', 59, false, false, NULL),
+(67, 'HP Officejet-7000', 15, false, false, 'hp.cfg'),
+(68, 'OKI C610', 62, false, false, NULL),
+(69, 'OKI MB472', 62, false, false, NULL),
+(70, 'OKI MB491', 62, false, false, NULL),
+(71, 'OKI MC562', 62, false, false, NULL),
+(72, 'OKI MC573', 62, false, false, NULL),
+(73, 'OKI MC861', 62, false, false, NULL),
+(74, 'Panasonic KX-MB2000RU', 61, false, false, NULL),
+(75, 'PT-MZ10KE', 61, false, false, NULL),
+(76, 'PT-VX41', 61, false, false, NULL),
+(77, 'Rave 522AA', 33, false, false, NULL),
+(78, 'DZ570E', 61, false, false, NULL),
+(79, 'DZ6700', 61, false, false, NULL),
+(80, 'Rcq80', 61, false, false, NULL),
+(81, 'RZ12K', 61, false, false, NULL),
+(82, 'RZ660', 61, false, false, NULL),
+(83, 'RZ770', 61, false, false, NULL),
+(84, 'RZ970', 61, false, false, NULL),
+(85, 'XVR-5216', 66, false, false, NULL),
+(86, 'HWg-STE', 68, false, false, NULL),
+(87, 'Computer', 1, false, false, ''),
+(88, 'Mobile Phone', 1, false, false, NULL),
+(89, 'Switch', 1, false, false, NULL),
+(90, 'Projectiondesign F22', 34, false, false, NULL),
+(91, 'DS-I252', 36, false, false, NULL),
+(92, 'LTV-CNE-720-48', 37, false, false, NULL),
+(93, 'U-100', 38, false, false, NULL),
+(94, 'TAU-8', 2, false, false, NULL),
+(95, 'SIP-T21P E2', 39, false, false, NULL),
+(96, 'A510 IP', 40, false, false, NULL),
+(97, 'W60B', 39, false, false, NULL),
+(98, 'TAU-2M', 2, false, false, NULL),
+(99, 'PAP2T', 41, false, false, NULL),
+(100, 'VP-12', 2, false, false, NULL),
+(101, 'SIP-T23P', 39, false, false, NULL),
+(102, 'SPA-2102', 16, false, false, NULL),
+(103, 'RB760iGS', 9, true, false, NULL),
+(104, 'MES2324B', 2, false, false, NULL),
+(105, 'MES2324FB', 2, false, false, NULL),
+(106, 'MES2124P', 2, false, true, NULL),
+(107, 'MES2428P', 2, false, true, NULL),
+(108, 'Symmetra LX 16000', 20, false, false, 'symmetra.cfg'),
+(109, 'SNR-UPS-ONT20', 6, false, false, 'ups3.cfg'),
+(110, 'MES-3728', 4, false, false, NULL),
+(111, 'SNR-S5210G-24TX-UPS-R', 6, false, false, NULL),
+(112, 'SNR-S2985G-24TC', 6, false, false, NULL),
+(113, 'MES-5248', 2, false, false, NULL),
+(114, 'SNR-S5210G-24TX-POE', 6, false, true, NULL),
+(115, 'SNR-S5210G-24TX-UPS', 6, false, false, NULL),
+(116, 'SNR-S5210X-8F-UPS', 6, false, false, NULL),
+(117, 'SNR-S2982G-8T-UPS', 6, false, false, NULL)
+ON CONFLICT (id) DO UPDATE SET
+    model_name = EXCLUDED.model_name,
+    vendor_id = EXCLUDED.vendor_id,
+    poe_in = EXCLUDED.poe_in,
+    poe_out = EXCLUDED.poe_out,
+    nagios_template = EXCLUDED.nagios_template;
+
+-- Device types
+INSERT INTO device_types (id, "name.russian", "name.english")
+VALUES
+(0, 'Роутер', 'Router'),
+(1, 'Свич', 'Switch'),
+(2, 'Шлюз', 'Gateway'),
+(3, 'Сервер', 'Server'),
+(4, 'Точка доступа', 'WiFi Access Point'),
+(5, 'Сетевое устройство', 'Network device')
+ON CONFLICT (id) DO UPDATE SET
+    "name.russian" = EXCLUDED."name.russian",
+    "name.english" = EXCLUDED."name.english";
+
+-- Filter instances
+INSERT INTO filter_instances (id, name, comment)
+VALUES (1, 'default', NULL)
+ON CONFLICT (id) DO UPDATE SET
+    name = EXCLUDED.name,
+    comment = EXCLUDED.comment;
+
+-- Filter groups
+INSERT INTO Group_list (id, instance_id, group_name, comment)
+VALUES
+(0, 1, 'default', 'Forbidden all'),
+(1, 1, 'Allow all', 'Allowed all'),
+(2, 1, 'Users', 'For users')
+ON CONFLICT (id) DO UPDATE SET
+    instance_id = EXCLUDED.instance_id,
+    group_name = EXCLUDED.group_name,
+    comment = EXCLUDED.comment;
+
+-- Organizational Units
+INSERT INTO OU (id, ou_name, comment, default_users, default_hotspot, nagios_dir, nagios_host_use, nagios_ping, nagios_default_service, enabled, filter_group_id, queue_id, dynamic, life_duration, parent_id)
+VALUES
+(0, '!Any', NULL, false, false, '/etc/nagios/any', 'generic-host', true, NULL, 0, 0, 0, false, 24.00, NULL),
+(1, 'Servers', NULL, false, false, NULL, NULL, true, NULL, 1, 1, 0, false, 24.00, NULL),
+(2, 'Administrators', NULL, false, false, NULL, NULL, true, NULL, 0, 0, 0, false, 24.00, NULL),
+(3, 'Users', NULL, false, false, NULL, NULL, true, NULL, 0, 0, 0, false, 24.00, NULL),
+(4, 'VOIP', NULL, false, false, 'voip', 'voip', true, NULL, 1, 4, 5, false, 24.00, NULL),
+(5, 'IPCAM', NULL, false, false, 'videocam', 'ip-cam', true, NULL, 0, 0, 0, false, 24.00, NULL),
+(6, 'Printers', NULL, false, false, 'printers', 'printers', true, 'printer-service', 0, 0, 0, false, 24.00, NULL),
+(7, 'Switches', NULL, false, false, 'switches', 'switches', true, NULL, 0, 0, 0, false, 24.00, NULL),
+(8, 'UPS', NULL, false, false, 'ups', 'ups', true, NULL, 0, 0, 0, false, 24.00, NULL),
+(9, 'Security', NULL, false, false, 'security', 'security', true, NULL, 0, 0, 0, false, 24.00, NULL),
+(10, 'Routers', NULL, false, false, 'routers', 'routers', true, NULL, 0, 0, 0, false, 24.00, NULL),
+(11, 'WiFi AP', NULL, false, false, 'ap', 'ap', true, NULL, 0, 0, 0, false, 24.00, NULL),
+(12, 'DHCP', NULL, true, false, NULL, NULL, true, NULL, 0, 0, 0, false, 24.00, NULL),
+(13, 'Guests', NULL, false, false, NULL, NULL, true, NULL, 1, 1, 4, true, 24.00, NULL)
+ON CONFLICT (id) DO UPDATE SET
+    ou_name = EXCLUDED.ou_name,
+    comment = EXCLUDED.comment,
+    default_users = EXCLUDED.default_users,
+    default_hotspot = EXCLUDED.default_hotspot,
+    nagios_dir = EXCLUDED.nagios_dir,
+    nagios_host_use = EXCLUDED.nagios_host_use,
+    nagios_ping = EXCLUDED.nagios_ping,
+    nagios_default_service = EXCLUDED.nagios_default_service,
+    enabled = EXCLUDED.enabled,
+    filter_group_id = EXCLUDED.filter_group_id,
+    queue_id = EXCLUDED.queue_id,
+    dynamic = EXCLUDED.dynamic,
+    life_duration = EXCLUDED.life_duration,
+    parent_id = EXCLUDED.parent_id;
+
+-- Traffic shaping queues
+INSERT INTO Queue_list (id, queue_name, Download, Upload)
+VALUES
+(0, 'unlimited', 0, 0),
+(1, '2M/2M', 2048, 2048),
+(2, '10M/10M', 10240, 10240),
+(3, '100M/100M', 102400, 102400),
+(4, '50M/50M', 50000, 50000),
+(5, '20M/20M', 20480, 20480),
+(6, '200M/200M', 212400, 212400),
+(7, '1G/1G', 1024000, 1024000),
+(8, '2G/2G', 2048000, 2048000)
+ON CONFLICT (id) DO UPDATE SET
+    queue_name = EXCLUDED.queue_name,
+    Download = EXCLUDED.Download,
+    Upload = EXCLUDED.Upload;
+
+-- Network subnets
+INSERT INTO subnets (id, subnet, vlan_tag, ip_int_start, ip_int_stop, dhcp_start, dhcp_stop, dhcp_lease_time, gateway, office, hotspot, vpn, free, dhcp, static, dhcp_update_hostname, discovery, notify, comment)
+VALUES (1, '192.168.2.0/24', 2, 3232236032, 3232236287, 3232236132, 3232236182, 480, 3232236033, true, false, false, false, true, false, true, true, 7, 'LAN')
+ON CONFLICT (id) DO UPDATE SET
+    subnet = EXCLUDED.subnet,
+    vlan_tag = EXCLUDED.vlan_tag,
+    ip_int_start = EXCLUDED.ip_int_start,
+    ip_int_stop = EXCLUDED.ip_int_stop,
+    dhcp_start = EXCLUDED.dhcp_start,
+    dhcp_stop = EXCLUDED.dhcp_stop,
+    dhcp_lease_time = EXCLUDED.dhcp_lease_time,
+    gateway = EXCLUDED.gateway,
+    office = EXCLUDED.office,
+    hotspot = EXCLUDED.hotspot,
+    vpn = EXCLUDED.vpn,
+    free = EXCLUDED.free,
+    dhcp = EXCLUDED.dhcp,
+    static = EXCLUDED.static,
+    dhcp_update_hostname = EXCLUDED.dhcp_update_hostname,
+    discovery = EXCLUDED.discovery,
+    notify = EXCLUDED.notify,
+    comment = EXCLUDED.comment;
+
+-- Device vendors
+INSERT INTO vendors (id, name)
+VALUES
+(1, 'Unknown'),
+(2, 'Eltex'),
+(3, 'Huawei'),
+(4, 'Zyxel'),
+(5, 'Raisecom'),
+(6, 'SNR'),
+(7, 'Dlink'),
+(8, 'Allied Telesis'),
+(9, 'Mikrotik'),
+(10, 'NetGear'),
+(11, 'Ubiquiti'),
+(15, 'HP'),
+(16, 'Cisco'),
+(17, 'Maipu'),
+(18, 'Asus'),
+(19, 'Linux'),
+(20, 'APC'),
+(21, 'Schneider'),
+(33, 'QSC'),
+(34, 'Projectiondesign'),
+(35, 'Lenovo'),
+(36, 'HiWatch'),
+(37, 'LTV'),
+(38, 'Yeastar'),
+(39, 'Yealink'),
+(40, 'Gigaset'),
+(41, 'Linksys'),
+(42, 'Samsung'),
+(43, 'Supermicro'),
+(44, 'RDP'),
+(45, 'SANYO'),
+(46, 'Extreme'),
+(47, 'Intel'),
+(48, 'Micron'),
+(49, 'Gigabyte'),
+(50, 'Acer'),
+(51, 'Seagate'),
+(52, 'SanDisk'),
+(53, 'Toshiba'),
+(54, 'Kingston'),
+(55, 'AddPac'),
+(56, 'Devline'),
+(57, 'Canon'),
+(58, 'Brother'),
+(59, 'Epson'),
+(60, 'IP-COM'),
+(61, 'Panasonic'),
+(62, 'OKI'),
+(63, 'Apple'),
+(64, 'Eaton'),
+(65, 'Barco'),
+(66, 'Trassir'),
+(67, 'Testo'),
+(68, 'Hw-group'),
+(69, 'Tp-link')
+ON CONFLICT (id) DO UPDATE SET
+    name = EXCLUDED.name;
+
+-- Filter rules list
+INSERT INTO Filter_list (id, name, comment, proto, dst, dstport, srcport, type)
+VALUES
+(1, 'pop3', NULL, 'tcp', '0/0', '110', NULL, 0),
+(3, 'http', NULL, 'tcp', '0/0', '80', NULL, 0),
+(4, 'https', NULL, 'tcp', '0/0', '443', NULL, 0),
+(5, 'icq', NULL, 'tcp', '0/0', '5190', NULL, 0),
+(6, 'jabber', NULL, 'tcp', '0/0', '5222', NULL, 0),
+(9, 'allow_all', 'any', 'all', '0/0', '0', '0', 0),
+(10, 'icmp', NULL, 'icmp', '0/0', '0', NULL, 0),
+(11, 'ftp', NULL, 'tcp', '0/0', '20-21', NULL, 0),
+(15, 'telnet', NULL, 'tcp', '0/0', '23', NULL, 0),
+(16, 'ssh', NULL, 'tcp', '0/0', '22', NULL, 0),
+(28, 'smtp', NULL, 'tcp', '0/0', '25', NULL, 0),
+(32, 'rdp', NULL, 'tcp', '0/0', '3389', NULL, 0),
+(40, 'ntp', NULL, 'udp', '0/0', '123', NULL, 0),
+(44, 'vnc', NULL, 'tcp', '0/0', '5800-5900', NULL, 0),
+(55, 'unprivileged tcp', NULL, 'tcp', '0/0', '1024-65500', NULL, 0),
+(76, 'ipsec', NULL, 'udp', '0/0', '500', NULL, 0),
+(77, 'isakmp', NULL, 'udp', '0/0', '4500', NULL, 0),
+(79, 'pop3s', NULL, 'tcp', '0/0', '995', NULL, 0),
+(80, 'smtps', NULL, 'tcp', '0/0', '465,587', NULL, 0),
+(81, 'imap', NULL, 'tcp', '0/0', '143', NULL, 0),
+(82, 'imaps', NULL, 'tcp', '0/0', '993', NULL, 0),
+(83, 'unprivileged udp', NULL, 'udp', '0/0', '1024-65000', NULL, 0),
+(84, 'pptp', NULL, 'tcp', '0/0', '1723', NULL, 0),
+(85, 'openvpn-udp', NULL, 'udp', '0/0', '1194', NULL, 0),
+(90, 'dns_udp', NULL, 'udp', '0/0', '53', NULL, 0),
+(91, 'dns_tcp', NULL, 'tcp', '0/0', '53', NULL, 0),
+(94, 'squid', NULL, 'tcp', '0/0', '3128', NULL, 0),
+(101, 'snmp', NULL, 'udp', '0/0', '161', NULL, 0),
+(105, 'http_udp', NULL, 'udp', '0/0', '80', NULL, 0),
+(106, 'https_udp', NULL, 'udp', '0/0', '443', NULL, 0),
+(107, 'l2tp-ipsec', NULL, 'udp', '0/0', '1701,4500,500', NULL, 0),
+(108, 'gre', NULL, 'gre', '0/0', NULL, NULL, 0)
+ON CONFLICT (id) DO UPDATE SET
+    name = EXCLUDED.name,
+    comment = EXCLUDED.comment,
+    proto = EXCLUDED.proto,
+    dst = EXCLUDED.dst,
+    dstport = EXCLUDED.dstport,
+    srcport = EXCLUDED.srcport,
+    type = EXCLUDED.type;
+
+-- Filter group assignments
+INSERT INTO Group_filters (id, group_id, filter_id, "order", action)
+VALUES
+(1, 2, 90, 1, true),
+(2, 2, 91, 2, true),
+(3, 2, 11, 3, true),
+(5, 2, 3, 4, true),
+(6, 2, 105, 5, true),
+(7, 2, 4, 6, true),
+(8, 2, 106, 7, true),
+(9, 2, 10, 8, true),
+(10, 2, 81, 9, true),
+(11, 2, 82, 10, true),
+(15, 2, 40, 11, true),
+(16, 2, 1, 12, true),
+(17, 2, 79, 13, true),
+(18, 2, 80, 14, true),
+(19, 1, 9, 1, true)
+ON CONFLICT (id) DO UPDATE SET
+    group_id = EXCLUDED.group_id,
+    filter_id = EXCLUDED.filter_id,
+    "order" = EXCLUDED."order",
+    action = EXCLUDED.action;
+
+-- System version
+INSERT INTO version (id, version)
+VALUES (1, '2.9.1')
+ON CONFLICT (id) DO UPDATE SET
+    version = EXCLUDED.version;
+
+-- Обновление последовательностей после импорта данных
+SELECT setval(pg_get_serial_sequence('acl', 'id'), COALESCE((SELECT MAX(id) FROM acl), 0) + 1);
+SELECT setval(pg_get_serial_sequence('building', 'id'), COALESCE((SELECT MAX(id) FROM building), 0) + 1);
+SELECT setval(pg_get_serial_sequence('config_options', 'id'), COALESCE((SELECT MAX(id) FROM config_options), 0) + 1);
+SELECT setval(pg_get_serial_sequence('config', 'id'), COALESCE((SELECT MAX(id) FROM config), 0) + 1);
+SELECT setval(pg_get_serial_sequence('Customers', 'id'), COALESCE((SELECT MAX(id) FROM Customers), 0) + 1);
+SELECT setval(pg_get_serial_sequence('device_models', 'id'), COALESCE((SELECT MAX(id) FROM device_models), 0) + 1);
+SELECT setval(pg_get_serial_sequence('device_types', 'id'), COALESCE((SELECT MAX(id) FROM device_types), 0) + 1);
+SELECT setval(pg_get_serial_sequence('filter_instances', 'id'), COALESCE((SELECT MAX(id) FROM filter_instances), 0) + 1);
+SELECT setval(pg_get_serial_sequence('Group_list', 'id'), COALESCE((SELECT MAX(id) FROM Group_list), 0) + 1);
+SELECT setval(pg_get_serial_sequence('OU', 'id'), COALESCE((SELECT MAX(id) FROM OU), 0) + 1);
+SELECT setval(pg_get_serial_sequence('Queue_list', 'id'), COALESCE((SELECT MAX(id) FROM Queue_list), 0) + 1);
+SELECT setval(pg_get_serial_sequence('subnets', 'id'), COALESCE((SELECT MAX(id) FROM subnets), 0) + 1);
+SELECT setval(pg_get_serial_sequence('vendors', 'id'), COALESCE((SELECT MAX(id) FROM vendors), 0) + 1);
+SELECT setval(pg_get_serial_sequence('Filter_list', 'id'), COALESCE((SELECT MAX(id) FROM Filter_list), 0) + 1);
+SELECT setval(pg_get_serial_sequence('Group_filters', 'id'), COALESCE((SELECT MAX(id) FROM Group_filters), 0) + 1);
+
+-- Информация о завершении импорта
+DO $$
+BEGIN
+    RAISE NOTICE 'Импорт данных завершен успешно!';
+    RAISE NOTICE 'Всего импортировано таблиц: 16';
+    RAISE NOTICE 'Всего импортировано записей:';
+    RAISE NOTICE '  - acl: %', (SELECT COUNT(*) FROM acl);
+    RAISE NOTICE '  - building: %', (SELECT COUNT(*) FROM building);
+    RAISE NOTICE '  - config_options: %', (SELECT COUNT(*) FROM config_options);
+    RAISE NOTICE '  - config: %', (SELECT COUNT(*) FROM config);
+    RAISE NOTICE '  - Customers: %', (SELECT COUNT(*) FROM Customers);
+    RAISE NOTICE '  - device_models: %', (SELECT COUNT(*) FROM device_models);
+    RAISE NOTICE '  - device_types: %', (SELECT COUNT(*) FROM device_types);
+    RAISE NOTICE '  - filter_instances: %', (SELECT COUNT(*) FROM filter_instances);
+    RAISE NOTICE '  - Group_list: %', (SELECT COUNT(*) FROM Group_list);
+    RAISE NOTICE '  - OU: %', (SELECT COUNT(*) FROM OU);
+    RAISE NOTICE '  - Queue_list: %', (SELECT COUNT(*) FROM Queue_list);
+    RAISE NOTICE '  - subnets: %', (SELECT COUNT(*) FROM subnets);
+    RAISE NOTICE '  - vendors: %', (SELECT COUNT(*) FROM vendors);
+    RAISE NOTICE '  - Filter_list: %', (SELECT COUNT(*) FROM Filter_list);
+    RAISE NOTICE '  - Group_filters: %', (SELECT COUNT(*) FROM Group_filters);
+    RAISE NOTICE '  - version: %', (SELECT COUNT(*) FROM version);
+END $$;

+ 726 - 0
docs/databases/postgres/ru/create_db.sql

@@ -0,0 +1,726 @@
+-- Создаем базу данных с русской локалью
+CREATE DATABASE stat
+    WITH 
+    ENCODING = 'UTF8'
+    LC_COLLATE = 'ru_RU.UTF-8'
+    LC_CTYPE = 'ru_RU.UTF-8'
+    TEMPLATE = template0
+    CONNECTION LIMIT = -1;
+
+\c stat;
+
+-- Включаем необходимые расширения
+CREATE EXTENSION IF NOT EXISTS pg_trgm;
+CREATE EXTENSION IF NOT EXISTS btree_gin;
+CREATE EXTENSION IF NOT EXISTS ip4r;
+
+-- Access Control List
+CREATE TABLE acl (
+    id SERIAL PRIMARY KEY,
+    name VARCHAR(30) NOT NULL,
+    "description.english" VARCHAR(250) NOT NULL,
+    "description.russian" VARCHAR(250) NOT NULL
+);
+COMMENT ON TABLE acl IS 'Список контроля доступа - роли и разрешения';
+COMMENT ON COLUMN acl."description.english" IS 'Описание на английском языке';
+COMMENT ON COLUMN acl."description.russian" IS 'Описание на русском языке';
+
+-- Кэш компьютеров из Active Directory
+CREATE TABLE ad_comp_cache (
+    id SERIAL PRIMARY KEY,
+    name VARCHAR(63) NOT NULL UNIQUE,
+    last_found TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+COMMENT ON TABLE ad_comp_cache IS 'Кэш компьютеров из Active Directory';
+COMMENT ON COLUMN ad_comp_cache.name IS 'Имя компьютера в AD';
+COMMENT ON COLUMN ad_comp_cache.last_found IS 'Время последнего обнаружения этого компьютера';
+
+-- Правила аутентификации
+CREATE TABLE auth_rules (
+    id SERIAL PRIMARY KEY,
+    user_id INTEGER,
+    ou_id INTEGER,
+    type INTEGER NOT NULL,
+    rule VARCHAR(40) UNIQUE,
+    comment VARCHAR(250)
+);
+COMMENT ON TABLE auth_rules IS 'Правила аутентификации и авторизации пользователей';
+COMMENT ON COLUMN auth_rules.type IS 'Тип правила: 0=разрешить, 1=запретить, и т.д.';
+COMMENT ON COLUMN auth_rules.rule IS 'Идентификатор правила (уникальный)';
+
+-- Здания
+CREATE TABLE building (
+    id SERIAL PRIMARY KEY,
+    name VARCHAR(50) NOT NULL,
+    comment VARCHAR(250)
+);
+COMMENT ON TABLE building IS 'Физические здания/локации';
+COMMENT ON COLUMN building.name IS 'Название здания';
+
+-- Системная конфигурация
+CREATE TABLE config (
+    id SERIAL PRIMARY KEY,
+    option_id INTEGER,
+    value VARCHAR(250)
+);
+COMMENT ON TABLE config IS 'Значения системной конфигурации';
+
+-- Опции конфигурации
+CREATE TABLE config_options (
+    id SERIAL PRIMARY KEY,
+    option_name VARCHAR(50) NOT NULL,
+    "description.russian" TEXT,
+    "description.english" TEXT,
+    draft BOOLEAN NOT NULL DEFAULT FALSE,
+    uniq BOOLEAN NOT NULL DEFAULT TRUE,
+    type VARCHAR(100) NOT NULL,
+    default_value VARCHAR(250),
+    min_value INTEGER NOT NULL DEFAULT 0,
+    max_value INTEGER NOT NULL DEFAULT 0
+);
+COMMENT ON TABLE config_options IS 'Доступные опции конфигурации';
+COMMENT ON COLUMN config_options.option_name IS 'Имя/ключ опции';
+COMMENT ON COLUMN config_options.draft IS 'Опция в черновом состоянии';
+COMMENT ON COLUMN config_options.uniq IS 'Опция уникальна (единственное значение)';
+
+-- Сетевые соединения
+CREATE TABLE connections (
+    id BIGSERIAL PRIMARY KEY,
+    device_id BIGINT NOT NULL,
+    port_id BIGINT NOT NULL,
+    auth_id BIGINT NOT NULL,
+    last_found TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+COMMENT ON TABLE connections IS 'Текущие сетевые соединения (MAC-IP-устройство-порт)';
+COMMENT ON COLUMN connections.device_id IS 'ID сетевого устройства';
+COMMENT ON COLUMN connections.port_id IS 'ID порта устройства';
+COMMENT ON COLUMN connections.auth_id IS 'ID авторизации пользователя';
+COMMENT ON COLUMN connections.last_found IS 'Время последней активности соединения';
+
+-- Пользователи системы
+CREATE TABLE Customers (
+    id SERIAL PRIMARY KEY,
+    Login VARCHAR(20),
+    comment VARCHAR(100),
+    password VARCHAR(255),
+    api_key VARCHAR(255),
+    rights SMALLINT NOT NULL DEFAULT 3
+);
+COMMENT ON TABLE Customers IS 'Пользователи/администраторы системы';
+COMMENT ON COLUMN Customers.Login IS 'Логин пользователя';
+COMMENT ON COLUMN Customers.rights IS 'Уровень прав доступа: 0=просмотр, 1=оператор, 2=админ, 3=суперадмин';
+
+-- Сетевые устройства
+CREATE TABLE devices (
+    id SERIAL PRIMARY KEY,
+    device_type INTEGER NOT NULL DEFAULT 1,
+    device_model_id INTEGER DEFAULT 89,
+    firmware VARCHAR(100),
+    vendor_id INTEGER NOT NULL DEFAULT 1,
+    device_name VARCHAR(50),
+    building_id INTEGER NOT NULL DEFAULT 1,
+    ip INET,
+    ip_int BIGINT,
+    login VARCHAR(50),
+    password VARCHAR(255),
+    protocol SMALLINT NOT NULL DEFAULT 0,
+    control_port INTEGER NOT NULL DEFAULT 23,
+    port_count INTEGER NOT NULL DEFAULT 0,
+    SN VARCHAR(80),
+    comment VARCHAR(255),
+    snmp_version SMALLINT NOT NULL DEFAULT 0,
+    snmp3_auth_proto VARCHAR(10) NOT NULL DEFAULT 'sha512',
+    snmp3_priv_proto VARCHAR(10) NOT NULL DEFAULT 'aes128',
+    snmp3_user_rw VARCHAR(20),
+    snmp3_user_rw_password VARCHAR(20),
+    snmp3_user_ro VARCHAR(20),
+    snmp3_user_ro_password VARCHAR(20),
+    community VARCHAR(50) NOT NULL DEFAULT 'public',
+    rw_community VARCHAR(50) NOT NULL DEFAULT 'private',
+    fdb_snmp_index BOOLEAN NOT NULL DEFAULT FALSE,
+    discovery BOOLEAN NOT NULL DEFAULT TRUE,
+    netflow_save BOOLEAN NOT NULL DEFAULT FALSE,
+    user_acl BOOLEAN NOT NULL DEFAULT FALSE,
+    dhcp BOOLEAN NOT NULL DEFAULT FALSE,
+    nagios BOOLEAN NOT NULL DEFAULT FALSE,
+    active BOOLEAN NOT NULL DEFAULT TRUE,
+    nagios_status VARCHAR(10) NOT NULL DEFAULT 'UP',
+    queue_enabled BOOLEAN NOT NULL DEFAULT FALSE,
+    connected_user_only BOOLEAN NOT NULL DEFAULT TRUE,
+    user_id INTEGER,
+    deleted BOOLEAN NOT NULL DEFAULT FALSE,
+    discovery_locked BOOLEAN NOT NULL DEFAULT FALSE,
+    locked_timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
+COMMENT ON TABLE devices IS 'Сетевые устройства (коммутаторы, маршрутизаторы и т.д.)';
+COMMENT ON COLUMN devices.device_type IS 'ID типа устройства';
+COMMENT ON COLUMN devices.ip IS 'IP-адрес управления устройством';
+COMMENT ON COLUMN devices.snmp_version IS 'Версия SNMP: 0=отключено, 1=v1, 2=v2c, 3=v3';
+COMMENT ON COLUMN devices.discovery IS 'Включить автоматическое обнаружение';
+COMMENT ON COLUMN devices.active IS 'Устройство активно и мониторится';
+
+-- Экземпляры фильтров устройств
+CREATE TABLE device_filter_instances (
+    id SERIAL PRIMARY KEY,
+    instance_id INTEGER,
+    device_id INTEGER
+);
+COMMENT ON TABLE device_filter_instances IS 'Экземпляры фильтров, назначенные устройствам';
+
+-- L3 интерфейсы устройств
+CREATE TABLE device_l3_interfaces (
+    id SERIAL PRIMARY KEY,
+    device_id INTEGER,
+    snmpin INTEGER,
+    interface_type INTEGER NOT NULL DEFAULT 0,
+    name VARCHAR(100)
+);
+COMMENT ON TABLE device_l3_interfaces IS 'Интерфейсы 3 уровня на устройствах';
+COMMENT ON COLUMN device_l3_interfaces.interface_type IS 'Тип интерфейса: 0=неизвестно, 1=LAN, 2=WAN, 3=DMZ';
+
+-- Модели устройств
+CREATE TABLE device_models (
+    id SERIAL PRIMARY KEY,
+    model_name VARCHAR(200),
+    vendor_id INTEGER DEFAULT 1,
+    poe_in BOOLEAN NOT NULL DEFAULT FALSE,
+    poe_out BOOLEAN NOT NULL DEFAULT FALSE,
+    nagios_template VARCHAR(200)
+);
+COMMENT ON TABLE device_models IS 'Модели устройств и их характеристики';
+COMMENT ON COLUMN device_models.poe_in IS 'Поддерживает питание по Ethernet на входе';
+COMMENT ON COLUMN device_models.poe_out IS 'Обеспечивает питание по Ethernet';
+
+-- Порты устройств
+CREATE TABLE device_ports (
+    id BIGSERIAL PRIMARY KEY,
+    device_id INTEGER,
+    snmp_index INTEGER,
+    port INTEGER,
+    ifName VARCHAR(40),
+    port_name VARCHAR(40),
+    comment VARCHAR(50),
+    target_port_id INTEGER NOT NULL DEFAULT 0,
+    auth_id BIGINT,
+    last_mac_count INTEGER DEFAULT 0,
+    uplink BOOLEAN NOT NULL DEFAULT FALSE,
+    nagios BOOLEAN NOT NULL DEFAULT FALSE,
+    skip BOOLEAN NOT NULL DEFAULT FALSE,
+    vlan INTEGER NOT NULL DEFAULT 1,
+    tagged_vlan VARCHAR(250),
+    untagged_vlan VARCHAR(250),
+    forbidden_vlan VARCHAR(250)
+);
+COMMENT ON TABLE device_ports IS 'Порты/интерфейсы сетевых устройств';
+COMMENT ON COLUMN device_ports.port IS 'Номер физического порта';
+COMMENT ON COLUMN device_ports.uplink IS 'Это аплинк-порт';
+COMMENT ON COLUMN device_ports.vlan IS 'VLAN по умолчанию/нативный VLAN';
+
+-- Типы устройств
+CREATE TABLE device_types (
+    id SERIAL PRIMARY KEY,
+    "name.russian" VARCHAR(50),
+    "name.english" VARCHAR(50)
+);
+COMMENT ON TABLE device_types IS 'Классификация типов устройств';
+COMMENT ON COLUMN device_types."name.russian" IS 'Название типа устройства на русском';
+COMMENT ON COLUMN device_types."name.english" IS 'Название типа устройства на английском';
+
+-- Логи DHCP
+CREATE TABLE dhcp_log (
+    id BIGSERIAL PRIMARY KEY,
+    mac MACADDR NOT NULL,
+    ip_int BIGINT NOT NULL,
+    ip INET NOT NULL,
+    action VARCHAR(10) NOT NULL,
+    timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    auth_id BIGINT NOT NULL,
+    dhcp_hostname VARCHAR(250),
+    "circuit-id" VARCHAR(255),
+    "remote-id" VARCHAR(255),
+    "client-id" VARCHAR(250)
+);
+COMMENT ON TABLE dhcp_log IS 'Логи транзакций DHCP сервера';
+COMMENT ON COLUMN dhcp_log.action IS 'Действие DHCP: DISCOVER, REQUEST, ACK, NAK, RELEASE';
+COMMENT ON COLUMN dhcp_log."circuit-id" IS 'DHCP опция 82 circuit ID';
+
+-- Очередь DHCP
+CREATE TABLE dhcp_queue (
+    id BIGSERIAL PRIMARY KEY,
+    mac MACADDR NOT NULL,
+    ip INET NOT NULL,
+    action VARCHAR(10) NOT NULL,
+    timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    dhcp_hostname VARCHAR(250)
+);
+COMMENT ON TABLE dhcp_queue IS 'Очередь отложенных операций DHCP';
+
+-- DNS кэш
+CREATE TABLE dns_cache (
+    id BIGSERIAL PRIMARY KEY,
+    dns VARCHAR(250),
+    ip BIGINT,
+    timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+COMMENT ON TABLE dns_cache IS 'Кэш DNS разрешений';
+
+-- Очередь DNS
+CREATE TABLE dns_queue (
+    id SERIAL PRIMARY KEY,
+    auth_id INTEGER,
+    name_type VARCHAR(10) NOT NULL DEFAULT 'A',
+    name VARCHAR(200),
+    type VARCHAR(10) NOT NULL DEFAULT 'add',
+    value VARCHAR(100)
+);
+COMMENT ON TABLE dns_queue IS 'Очередь отложенных операций DNS';
+COMMENT ON COLUMN dns_queue.name_type IS 'Тип DNS записи: A, AAAA, PTR, CNAME';
+COMMENT ON COLUMN dns_queue.type IS 'Тип операции: add, delete, update';
+
+-- Экземпляры фильтров
+CREATE TABLE filter_instances (
+    id SERIAL PRIMARY KEY,
+    name VARCHAR(50) UNIQUE,
+    comment VARCHAR(200)
+);
+COMMENT ON TABLE filter_instances IS 'Экземпляры политик фильтрации';
+
+-- Список правил фильтрации
+CREATE TABLE Filter_list (
+    id SERIAL PRIMARY KEY,
+    name VARCHAR(50),
+    comment VARCHAR(250),
+    proto VARCHAR(10),
+    dst TEXT,
+    dstport VARCHAR(20),
+    srcport VARCHAR(20),
+    type INTEGER NOT NULL DEFAULT 0
+);
+COMMENT ON TABLE Filter_list IS 'Правила firewall/фильтрации';
+COMMENT ON COLUMN Filter_list.proto IS 'Протокол: tcp, udp, icmp и т.д.';
+COMMENT ON COLUMN Filter_list.dst IS 'IP/CIDR назначения';
+COMMENT ON COLUMN Filter_list.type IS 'Тип правила: 0=разрешить, 1=запретить';
+
+-- Шлюзы подсетей
+CREATE TABLE gateway_subnets (
+    id SERIAL PRIMARY KEY,
+    device_id INTEGER,
+    subnet_id INTEGER
+);
+COMMENT ON TABLE gateway_subnets IS 'Какие устройства являются шлюзами для каких подсетей';
+
+-- Назначения фильтров группам
+CREATE TABLE Group_filters (
+    id SERIAL PRIMARY KEY,
+    group_id INTEGER NOT NULL DEFAULT 0,
+    filter_id INTEGER NOT NULL DEFAULT 0,
+    "order" INTEGER NOT NULL DEFAULT 0,
+    action BOOLEAN NOT NULL DEFAULT FALSE
+);
+COMMENT ON TABLE Group_filters IS 'Правила фильтрации, назначенные группам';
+COMMENT ON COLUMN Group_filters."order" IS 'Порядок обработки правил';
+COMMENT ON COLUMN Group_filters.action IS 'Действие: true=разрешить, false=запретить';
+
+-- Группы фильтров
+CREATE TABLE Group_list (
+    id SERIAL PRIMARY KEY,
+    instance_id INTEGER NOT NULL DEFAULT 1,
+    group_name VARCHAR(50),
+    comment VARCHAR(250)
+);
+COMMENT ON TABLE Group_list IS 'Группы политик фильтрации';
+
+-- История MAC-адресов
+CREATE TABLE mac_history (
+    id BIGSERIAL PRIMARY KEY,
+    mac VARCHAR(12),
+    timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    device_id BIGINT,
+    port_id BIGINT,
+    ip VARCHAR(16) NOT NULL DEFAULT '',
+    auth_id BIGINT,
+    dhcp_hostname VARCHAR(250)
+);
+COMMENT ON TABLE mac_history IS 'История перемещений MAC-адресов';
+COMMENT ON COLUMN mac_history.mac IS 'MAC-адрес (12 шестнадцатеричных символов)';
+COMMENT ON COLUMN mac_history.ip IS 'Последний использованный IP-адрес';
+
+-- Производители MAC-адресов
+CREATE TABLE mac_vendors (
+    id SERIAL PRIMARY KEY,
+    oui VARCHAR(20),
+    companyName VARCHAR(255),
+    companyAddress VARCHAR(255)
+);
+COMMENT ON TABLE mac_vendors IS 'База данных производителей по MAC-адресам';
+COMMENT ON COLUMN mac_vendors.oui IS 'Organizationally Unique Identifier (первые 6 символов MAC)';
+
+-- Организационные единицы
+CREATE TABLE OU (
+    id SERIAL PRIMARY KEY,
+    ou_name VARCHAR(40),
+    comment VARCHAR(250),
+    default_users BOOLEAN NOT NULL DEFAULT FALSE,
+    default_hotspot BOOLEAN NOT NULL DEFAULT FALSE,
+    nagios_dir VARCHAR(255),
+    nagios_host_use VARCHAR(50),
+    nagios_ping BOOLEAN NOT NULL DEFAULT TRUE,
+    nagios_default_service VARCHAR(100),
+    enabled INTEGER NOT NULL DEFAULT 0,
+    filter_group_id INTEGER NOT NULL DEFAULT 0,
+    queue_id INTEGER NOT NULL DEFAULT 0,
+    dynamic BOOLEAN NOT NULL DEFAULT FALSE,
+    life_duration DECIMAL(10,2) NOT NULL DEFAULT 24.00,
+    parent_id INTEGER
+);
+COMMENT ON TABLE OU IS 'Организационные единицы (отделы/группы)';
+COMMENT ON COLUMN OU.ou_name IS 'Имя/идентификатор OU';
+COMMENT ON COLUMN OU.life_duration IS 'Время жизни по умолчанию в часах для динамических OU';
+
+-- Очереди шейпинга трафика
+CREATE TABLE Queue_list (
+    id SERIAL PRIMARY KEY,
+    queue_name VARCHAR(20) NOT NULL,
+    Download INTEGER NOT NULL DEFAULT 0,
+    Upload INTEGER NOT NULL DEFAULT 0
+);
+COMMENT ON TABLE Queue_list IS 'Профили полосы пропускания для шейпинга трафика';
+COMMENT ON COLUMN Queue_list.Download IS 'Ограничение скорости скачивания в Кбит/с';
+COMMENT ON COLUMN Queue_list.Upload IS 'Ограничение скорости отдачи в Кбит/с';
+
+-- Удаленные syslog сообщения
+CREATE TABLE remote_syslog (
+    id BIGSERIAL PRIMARY KEY,
+    date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    device_id BIGINT NOT NULL,
+    ip VARCHAR(15) NOT NULL,
+    message TEXT NOT NULL
+);
+COMMENT ON TABLE remote_syslog IS 'Syslog сообщения от сетевых устройств';
+
+-- PHP сессии
+CREATE TABLE sessions (
+    id VARCHAR(128) PRIMARY KEY,
+    data TEXT NOT NULL,
+    last_accessed INTEGER NOT NULL
+);
+COMMENT ON TABLE sessions IS 'Хранилище PHP сессий';
+
+-- Сетевые подсети
+CREATE TABLE subnets (
+    id SERIAL PRIMARY KEY,
+    subnet VARCHAR(18),
+    vlan_tag INTEGER NOT NULL DEFAULT 1,
+    ip_int_start BIGINT NOT NULL,
+    ip_int_stop BIGINT NOT NULL,
+    dhcp_start BIGINT NOT NULL DEFAULT 0,
+    dhcp_stop BIGINT NOT NULL DEFAULT 0,
+    dhcp_lease_time INTEGER NOT NULL DEFAULT 480,
+    gateway BIGINT NOT NULL DEFAULT 0,
+    office BOOLEAN NOT NULL DEFAULT TRUE,
+    hotspot BOOLEAN NOT NULL DEFAULT FALSE,
+    vpn BOOLEAN NOT NULL DEFAULT FALSE,
+    free BOOLEAN NOT NULL DEFAULT FALSE,
+    dhcp BOOLEAN NOT NULL DEFAULT TRUE,
+    static BOOLEAN NOT NULL DEFAULT FALSE,
+    dhcp_update_hostname BOOLEAN NOT NULL DEFAULT FALSE,
+    discovery BOOLEAN NOT NULL DEFAULT TRUE,
+    notify SMALLINT NOT NULL DEFAULT 7,
+    comment VARCHAR(250)
+);
+COMMENT ON TABLE subnets IS 'Конфигурация сетевых подсетей';
+COMMENT ON COLUMN subnets.subnet IS 'Сеть в нотации CIDR';
+COMMENT ON COLUMN subnets.vlan_tag IS 'ID VLAN для этой подсети';
+COMMENT ON COLUMN subnets.office IS 'Это офисная подсеть';
+COMMENT ON COLUMN subnets.hotspot IS 'Это публичная/гостевая подсеть';
+COMMENT ON COLUMN subnets.notify IS 'Битовая маска для уведомлений: 1=email, 2=sms, 4=telegram';
+
+-- Подробные логи трафика
+CREATE TABLE Traffic_detail (
+    id BIGSERIAL PRIMARY KEY,
+    auth_id BIGINT,
+    router_id INTEGER NOT NULL DEFAULT 0,
+    timestamp TIMESTAMP,
+    proto SMALLINT,
+    src_ip INTEGER NOT NULL,
+    dst_ip INTEGER NOT NULL,
+    src_port INTEGER NOT NULL,
+    dst_port INTEGER NOT NULL,
+    bytes BIGINT NOT NULL,
+    pkt INTEGER NOT NULL DEFAULT 0
+);
+COMMENT ON TABLE Traffic_detail IS 'Подробные записи потоков трафика (NetFlow)';
+COMMENT ON COLUMN Traffic_detail.proto IS 'Номер IP протокола';
+COMMENT ON COLUMN Traffic_detail.src_ip IS 'Исходный IP в виде целого числа';
+COMMENT ON COLUMN Traffic_detail.bytes IS 'Байтов переданно в этом потоке';
+
+-- Неизвестные MAC-адреса
+CREATE TABLE Unknown_mac (
+    id BIGSERIAL PRIMARY KEY,
+    mac VARCHAR(12),
+    port_id BIGINT,
+    device_id INTEGER,
+    timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+COMMENT ON TABLE Unknown_mac IS 'Недавно обнаруженные неизвестные MAC-адреса';
+
+-- Записи авторизации пользователей
+CREATE TABLE User_auth (
+    id SERIAL PRIMARY KEY,
+    user_id BIGINT NOT NULL DEFAULT 0,
+    ou_id INTEGER,
+    ip VARCHAR(18) NOT NULL DEFAULT '',
+    ip_int BIGINT NOT NULL DEFAULT 0,
+    save_traf BOOLEAN NOT NULL DEFAULT FALSE,
+    enabled BOOLEAN NOT NULL DEFAULT FALSE,
+    dhcp BOOLEAN NOT NULL DEFAULT TRUE,
+    filter_group_id SMALLINT NOT NULL DEFAULT 0,
+    dynamic BOOLEAN NOT NULL DEFAULT FALSE,
+    eof TIMESTAMP,
+    deleted BOOLEAN NOT NULL DEFAULT FALSE,
+    comments VARCHAR(250),
+    dns_name VARCHAR(253),
+    dns_ptr_only BOOLEAN NOT NULL DEFAULT FALSE,
+    WikiName VARCHAR(250),
+    dhcp_acl TEXT,
+    queue_id INTEGER NOT NULL DEFAULT 0,
+    mac VARCHAR(20) NOT NULL DEFAULT '',
+    dhcp_action VARCHAR(10) NOT NULL DEFAULT '',
+    dhcp_option_set VARCHAR(50),
+    dhcp_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    dhcp_hostname VARCHAR(60),
+    last_found TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    arp_found TIMESTAMP,
+    blocked BOOLEAN NOT NULL DEFAULT FALSE,
+    day_quota INTEGER NOT NULL DEFAULT 0,
+    month_quota INTEGER NOT NULL DEFAULT 0,
+    device_model_id INTEGER DEFAULT 87,
+    firmware VARCHAR(100),
+    timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "client-id" VARCHAR(250),
+    nagios BOOLEAN NOT NULL DEFAULT FALSE,
+    nagios_status VARCHAR(10) NOT NULL DEFAULT '',
+    nagios_handler VARCHAR(50) NOT NULL DEFAULT '',
+    link_check BOOLEAN NOT NULL DEFAULT FALSE,
+    changed BOOLEAN NOT NULL DEFAULT FALSE,
+    dhcp_changed INTEGER NOT NULL DEFAULT 0,
+    changed_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    created_by VARCHAR(10)
+);
+COMMENT ON TABLE User_auth IS 'Записи авторизации пользователей/устройств в сети';
+COMMENT ON COLUMN User_auth.enabled IS 'Эта авторизация активна';
+COMMENT ON COLUMN User_auth.dynamic IS 'Это динамически созданная запись';
+COMMENT ON COLUMN User_auth.day_quota IS 'Дневная квота трафика в байтах';
+COMMENT ON COLUMN User_auth.nagios IS 'Включить мониторинг Nagios для этого хоста';
+
+-- Алиасы авторизации пользователей
+CREATE TABLE User_auth_alias (
+    id SERIAL PRIMARY KEY,
+    auth_id INTEGER NOT NULL,
+    alias VARCHAR(100),
+    description VARCHAR(100),
+    timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+COMMENT ON TABLE User_auth_alias IS 'Алиасы/DNS имена для записей авторизации';
+
+-- Список пользователей
+CREATE TABLE User_list (
+    id BIGSERIAL PRIMARY KEY,
+    timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    login VARCHAR(255),
+    fio VARCHAR(255),
+    enabled BOOLEAN NOT NULL DEFAULT TRUE,
+    blocked BOOLEAN NOT NULL DEFAULT FALSE,
+    deleted BOOLEAN NOT NULL DEFAULT FALSE,
+    ou_id INTEGER NOT NULL DEFAULT 0,
+    device_id INTEGER,
+    filter_group_id INTEGER NOT NULL DEFAULT 0,
+    queue_id INTEGER NOT NULL DEFAULT 0,
+    day_quota INTEGER NOT NULL DEFAULT 0,
+    month_quota INTEGER NOT NULL DEFAULT 0,
+    permanent BOOLEAN NOT NULL DEFAULT FALSE
+);
+COMMENT ON TABLE User_list IS 'Учетные записи пользователей в системе';
+COMMENT ON COLUMN User_list.fio IS 'Фамилия Имя Отчество';
+COMMENT ON COLUMN User_list.permanent IS 'Это постоянный пользователь (не динамический)';
+
+-- Сессии пользователей (веб-интерфейс)
+CREATE TABLE user_sessions (
+    id SERIAL PRIMARY KEY,
+    session_id VARCHAR(128) NOT NULL,
+    user_id INTEGER NOT NULL,
+    ip_address VARCHAR(45) NOT NULL,
+    user_agent TEXT NOT NULL,
+    created_at INTEGER NOT NULL,
+    last_activity INTEGER NOT NULL,
+    is_active BOOLEAN DEFAULT TRUE
+);
+COMMENT ON TABLE user_sessions IS 'Сессии пользователей веб-интерфейса';
+
+-- Статистика трафика пользователей
+CREATE TABLE User_stats (
+    id BIGSERIAL PRIMARY KEY,
+    router_id BIGINT DEFAULT 0,
+    auth_id BIGINT NOT NULL DEFAULT 0,
+    timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    byte_in BIGINT NOT NULL DEFAULT 0,
+    byte_out BIGINT NOT NULL DEFAULT 0
+);
+COMMENT ON TABLE User_stats IS 'Статистика трафика пользователей (агрегированная)';
+
+-- Подробная статистика пользователей
+CREATE TABLE User_stats_full (
+    id BIGSERIAL PRIMARY KEY,
+    router_id BIGINT DEFAULT 0,
+    auth_id BIGINT NOT NULL DEFAULT 0,
+    timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    byte_in BIGINT NOT NULL DEFAULT 0,
+    byte_out BIGINT NOT NULL DEFAULT 0,
+    pkt_in INTEGER,
+    pkt_out INTEGER,
+    step INTEGER NOT NULL DEFAULT 600
+);
+COMMENT ON TABLE User_stats_full IS 'Подробная статистика трафика пользователей';
+COMMENT ON COLUMN User_stats_full.step IS 'Интервал сбора статистики в секундах';
+
+-- Временные переменные
+CREATE TABLE variables (
+    id SERIAL PRIMARY KEY,
+    name VARCHAR(30) NOT NULL UNIQUE,
+    value VARCHAR(255),
+    clear_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+COMMENT ON TABLE variables IS 'Временные системные переменные и блокировки';
+
+-- Производители устройств
+CREATE TABLE vendors (
+    id SERIAL PRIMARY KEY,
+    name VARCHAR(40) NOT NULL
+);
+COMMENT ON TABLE vendors IS 'Производители сетевого оборудования';
+
+-- Версия системы
+CREATE TABLE version (
+    id INTEGER PRIMARY KEY DEFAULT 1,
+    version VARCHAR(10) NOT NULL DEFAULT '2.4.14'
+);
+COMMENT ON TABLE version IS 'Информация о версии системы';
+
+-- Статистика WAN интерфейсов
+CREATE TABLE Wan_stats (
+    id SERIAL PRIMARY KEY,
+    time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    router_id INTEGER,
+    interface_id INTEGER,
+    "in" BIGINT NOT NULL DEFAULT 0,
+    "out" BIGINT NOT NULL DEFAULT 0,
+    forward_in BIGINT NOT NULL DEFAULT 0,
+    forward_out BIGINT NOT NULL DEFAULT 0
+);
+COMMENT ON TABLE Wan_stats IS 'Статистика трафика WAN интерфейсов';
+COMMENT ON COLUMN Wan_stats."in" IS 'Байтов получено на WAN интерфейсе';
+COMMENT ON COLUMN Wan_stats."out" IS 'Байтов отправлено с WAN интерфейса';
+
+-- Журнал активности системы
+CREATE TABLE worklog (
+    id BIGSERIAL PRIMARY KEY,
+    timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    auth_id BIGINT NOT NULL DEFAULT 0,
+    customer VARCHAR(50) NOT NULL DEFAULT 'system',
+    ip VARCHAR(18) NOT NULL DEFAULT '127.0.0.1',
+    message TEXT NOT NULL,
+    level INTEGER NOT NULL DEFAULT 1
+);
+COMMENT ON TABLE worklog IS 'Журнал активности и аудита системы';
+COMMENT ON COLUMN worklog.level IS 'Уровень логирования: 1=инфо, 2=предупреждение, 3=ошибка, 4=отладка';
+
+-- Индексы (такие же как в оригинальной структуре)
+CREATE INDEX idx_devices_ip ON devices(ip);
+CREATE INDEX idx_devices_device_type ON devices(device_type);
+CREATE INDEX idx_devices_active ON devices(active) WHERE active = TRUE;
+
+CREATE INDEX idx_device_ports_device_id ON device_ports(device_id);
+CREATE INDEX idx_device_ports_port ON device_ports(port);
+CREATE INDEX idx_device_ports_target_port_id ON device_ports(target_port_id);
+
+CREATE INDEX idx_dhcp_log_timestamp ON dhcp_log(timestamp, action);
+CREATE INDEX idx_dhcp_queue_timestamp ON dhcp_queue(timestamp, action);
+
+CREATE INDEX idx_dns_cache_dns ON dns_cache(dns, ip);
+CREATE INDEX idx_dns_cache_timestamp ON dns_cache(timestamp);
+
+CREATE INDEX idx_mac_history_mac ON mac_history(mac, timestamp);
+CREATE INDEX idx_mac_history_ip ON mac_history(ip, timestamp);
+CREATE INDEX idx_mac_history_timestamp ON mac_history(timestamp);
+
+CREATE INDEX idx_ou_ou_name_gin ON OU USING GIN(ou_name gin_trgm_ops);
+
+CREATE INDEX idx_subnets_ip_int_start ON subnets(ip_int_start, ip_int_stop);
+CREATE INDEX idx_subnets_dhcp ON subnets(dhcp, office, hotspot, static);
+
+CREATE INDEX idx_traffic_detail_src ON Traffic_detail(auth_id, timestamp, router_id, src_ip);
+CREATE INDEX idx_traffic_detail_dst ON Traffic_detail(auth_id, timestamp, router_id, dst_ip);
+
+CREATE INDEX idx_unknown_mac_timestamp ON Unknown_mac(timestamp, device_id, port_id, mac);
+
+CREATE INDEX idx_user_auth_main ON User_auth(id, user_id, ip_int, mac, ip, deleted);
+CREATE INDEX idx_user_auth_deleted ON User_auth(deleted) WHERE deleted = FALSE;
+CREATE INDEX idx_user_auth_ou_id ON User_auth(ou_id);
+
+CREATE INDEX idx_user_list_main ON User_list(id, ou_id, enabled, blocked, deleted);
+
+CREATE INDEX idx_user_sessions_session_id ON user_sessions(session_id);
+CREATE INDEX idx_user_sessions_user_id ON user_sessions(user_id);
+CREATE INDEX idx_user_sessions_is_active ON user_sessions(is_active) WHERE is_active = TRUE;
+
+CREATE INDEX idx_user_stats_timestamp ON User_stats(timestamp, auth_id, router_id);
+CREATE INDEX idx_user_stats_full_timestamp ON User_stats_full(timestamp, auth_id, router_id);
+
+CREATE INDEX idx_wan_stats_time ON Wan_stats(time, router_id, interface_id);
+
+CREATE INDEX idx_worklog_customer ON worklog(customer, level, timestamp);
+CREATE INDEX idx_worklog_timestamp ON worklog(level, timestamp);
+CREATE INDEX idx_worklog_auth_id ON worklog(auth_id, level, timestamp);
+
+-- Функции для конвертации IP-адресов
+CREATE OR REPLACE FUNCTION inet_to_bigint(ip_address INET)
+RETURNS BIGINT AS $$
+BEGIN
+    RETURN (
+        (split_part(host(ip_address), '.', 1)::BIGINT << 24) +
+        (split_part(host(ip_address), '.', 2)::BIGINT << 16) +
+        (split_part(host(ip_address), '.', 3)::BIGINT << 8) +
+        split_part(host(ip_address), '.', 4)::BIGINT
+    );
+END;
+$$ LANGUAGE plpgsql IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION bigint_to_inet(ip_int BIGINT)
+RETURNS INET AS $$
+BEGIN
+    RETURN ((ip_int >> 24) & 255) || '.' ||
+           ((ip_int >> 16) & 255) || '.' ||
+           ((ip_int >> 8) & 255) || '.' ||
+           (ip_int & 255);
+END;
+$$ LANGUAGE plpgsql IMMUTABLE;
+
+-- Триггер для автоматического обновления ip_int при изменении ip
+CREATE OR REPLACE FUNCTION update_ip_int()
+RETURNS TRIGGER AS $$
+BEGIN
+    IF NEW.ip IS NOT NULL AND (NEW.ip_int IS NULL OR OLD.ip != NEW.ip) THEN
+        NEW.ip_int := inet_to_bigint(NEW.ip::INET);
+    END IF;
+    RETURN NEW;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE TRIGGER trigger_devices_ip_int 
+    BEFORE INSERT OR UPDATE ON devices 
+    FOR EACH ROW EXECUTE FUNCTION update_ip_int();
+
+CREATE TRIGGER trigger_user_auth_ip_int 
+    BEFORE INSERT OR UPDATE ON User_auth 
+    FOR EACH ROW EXECUTE FUNCTION update_ip_int();

+ 530 - 0
docs/databases/postgres/ru/data.sql

@@ -0,0 +1,530 @@
+-- Импорт данных в PostgreSQL для русской локали
+
+-- ACL (Access Control List)
+INSERT INTO acl (id, name, "description.english", "description.russian") 
+VALUES 
+(1, 'Full access', 'Full access', 'Полный доступ'),
+(2, 'Operator', 'Editing parameters that are not related to access rights', 'Редактирование параметров, не связанных с правами доступа'),
+(3, 'View only', 'View only', 'Только просмотр')
+ON CONFLICT (id) DO UPDATE SET
+    name = EXCLUDED.name,
+    "description.english" = EXCLUDED."description.english",
+    "description.russian" = EXCLUDED."description.russian";
+
+-- Buildings
+INSERT INTO building (id, name, comment)
+VALUES (1, 'Earth', 'Somewhere')
+ON CONFLICT (id) DO UPDATE SET
+    name = EXCLUDED.name,
+    comment = EXCLUDED.comment;
+
+-- Configuration options
+INSERT INTO config_options (id, option_name, "description.russian", "description.english", draft, uniq, type, default_value, min_value, max_value)
+VALUES
+(1, 'KB', 'Еденица измерения трафика - Килобайт (0) или кибибайт (1,default)', 'Traffic measurement unit - Kilobyte (1000b) or kibibyte (1024b,default)', false, true, 'bool', '1024', 0, 1),
+(3, 'dns server', 'ip-адрес DNS-сервера', 'DNS server ip address', false, true, 'text', '127.0.0.1', 0, 0),
+(5, 'dhcp server', 'ip-адрес DHCP-сервера', 'ip address of the DHCP server', false, true, 'text', '127.0.0.1', 0, 0),
+(9, 'default snmp version', 'Версия snmp по умолчанию. В настоящиймомент поддерживаются 1 и 2. Поддержка версии 3 в разработке.', 'The default version of snmp. Currently, 1 and 2 are supported. Support for version 3 is in development.', false, true, 'int', '2', 1, 3),
+(11, 'default snmp community', 'Read snmp community по умолчанию','Read snmp community by default', false, true, 'text', 'public', 0, 0),
+(21, 'admin email', 'E-mail администратора', 'Administrator e-mail', false, true, 'text', 'root', 0, 0),
+(22, 'add user from netflow', 'Создавать ли новые записи для неизвестных адресов из анализа трафика netflow. Не включать, если netflow снимает данные с маршрутизатора локальной сети', 'Whether to create new records for unknown addresses from netflow traffic analysis. Do not enable if netflow get data from the local network router', false, true, 'bool', '0', 0, 1),
+(23, 'save traffic detail', 'Сохранять ли детализацию трафика из netflow по ip-адресам пользователей', 'Whether to keep the details of traffic from netflow by ip addresses of users', false, true, 'bool', '1', 0, 1),
+(26, 'history detail traffic', 'Глубина хранения детализации в сутках. Установка значения больше 3-7 дней приведёт к разрастанию базы данных и увеличит время отображения детализации в интерфейсе администратора', 'Depth of detail storage in days. Setting a value greater than 3-7 days will cause the database to grow and increase the time about to display details in the admin interface', false, true, 'int', '3', 1, 7),
+(27, 'history dhcp lease', 'Глубина хранения аренды dhcp-сервера','Storage depth of the dhcp server lease', false, true, 'int', '1', 0, 0),
+(28, 'router_login', 'Логин для входа на сетевые устройства по умолчанию', 'Default login for network devices', false, true, 'text', 'admin', 0, 0),
+(29, 'router_password', 'Пароль по умолчанию на сетевые устройства', 'Default password for network devices', false, true, 'text', 'admin', 0, 0),
+(30, 'router_ssh_port', 'Порт ssh по умолчанию', 'SSH default port', false, true, 'int', '22', 22, 0),
+(32, 'org name', 'Название организации', 'Organization name', false, true, 'text', 'ORG', 0, 0),
+(33, 'office domain', 'Домен организации', 'Organization domain', false, true, 'text', 'local', 0, 0),
+(34, 'debug', 'Включить отладку', 'Enable debugging', false, true, 'bool', '0', 0, 1),
+(35, 'connections history, days', 'Время хранения истории мест подключения ip-адресов', 'Storage time of the history of connection locations of ip addresses', false, true, 'int', '90', 1, 365),
+(37, 'refresh access lists', 'Расположение скрипта управления контролем доступа для роутеров Mikrotik', 'Location of the access control script for Mikrotik routers', false, true, 'text', '/opt/Eye/scripts/sync_mikrotik.pl', 0, 0),
+(38, 'regenerate dhcp cconfig', 'Расположение скрипта управления конфигурацией dhcp-серверами', 'Location of the dhcp server configuration management script', false, true, 'text', '/opt/Eye/scripts/update-dnsmasq', 0, 0),
+(39, 'regenerate dns cconfig', 'Расположение скрипта управления dns-сервером', 'Location of the dns server management script', false, true, 'text', '/opt/Eye/scripts/update-dns', 0, 0),
+(40, 'regenerate nagios cconfig', 'Расположение скрипта конфигурирования Nagios', 'Location of the Nagios configuration script', false, true, 'text', '/etc/nagios/restart_nagios', 0, 0),
+(41, 'discovery network', 'Расположение скрипта сканирования сети', 'Location of the network scan script', false, true, 'text', '/opt/Eye/scripts/fetch_new_arp.pl', 0, 0),
+(44, 'Ignore hotspot dhcp log', 'Не писать лог событий dhcp-сервера хотспота. Имеет смысл вклчючать, поскольку время аренды в хот-споте как правило маленькое и в записях хот-спота становятся незаметны логи обычных пользователей', 'Do not write the event log of the hotspot dhcp server. It makes sense toinclude it, since the rental time in the hotspot is usually small and the logs of ordinary users become invisible in the hotspot records', false, true, 'bool', '1', 0, 1),
+(45, 'ignore update dhcp event', 'Не писать события обновления ip-адреса dhcp-сервера. ', 'Do not write events for updating the IP address of the dhcp server. ', false, true, 'bool', '0', 0, 1),
+(46, 'update hostname from dhcp', 'Обновлять имя хоста в DNS при получении адреса по DHCP', 'Update the hostname in DNS when receiving the address via DHCP', false, true, 'bool', '0', 0, 1),
+(47, 'history worklog', 'Глубина хранения VERBOSE логов работы в интерфейсе администратора', 'Depth of work VERBOSE logs storage in the admin interface', false, true, 'int', '90', 0, 1095),
+(48, 'history syslog', 'Глубина хранения логов работы syslog-сервера', 'Syslog server logs storage depth', false, true, 'int', '90', 0, 1095),
+(49, 'history traffic stats', 'Глубина хранения статистики трафикаюзеров', 'User traffic statistics storage depth', false, true, 'int', '365', 0, 0),
+(50, 'urgent sync access', 'Немедленное изменение списков доступа на роутере после правки записи пользователя', 'Immediate change of access lists on the router after editing the user record ', false, true, 'bool', '0', 0, 1),
+(51, 'Email_alert', 'Отправлять e-mail уведомления', 'Send e-mail notifications', false, true, 'bool', '1', 0, 1),
+(52, 'Sender email', 'E-mail адрес, с которого рассылается почта','E-mail address from which mail is sent', false, true, 'text', 'root', 0, 0),
+(53, 'log level', 'Каждый уровень включает в себя предыдущий:\r\n0- ERROR - писать только ошибки\r\n1 - WARNING - писать предупреждения\r\n2 - INFO - писать информационные сообщения\r\n3 - VERBOSE - писать подробную информацию о выполняемых операциях', 'Each level includes the previous one:\r\n0 - ERROR - write only errors\r\n1 - WARNING - write warnings\r\n2 - INFO - write informational\r\n3 - VERBOSE - write detailed information about the operations performed ', false, true, 'int', '2', 0, 3),
+(54, 'enable_quotes', 'Включить обработку квот по трафику', 'Enable traffic quota processing', false, true, 'bool', '0', 0, 1),
+(55, 'netflow_step', 'Интервал сброса данных из коллектора netflow, минуты', 'Data reset interval from netflow collector, minutes', false, true, 'int', '1', 1, 10),
+(56, 'traffic_ipstat_history', 'Время хранения полной статистики по трафику для каждого ip-адреса в сутках. Таблица в 6 раз больше обычной часовой статистики. Врядли кому-то потребуется глубина хранения более месяца.', 'The storage time of complete traffic statistics for each ip address in days. The table is 6 times larger than the usual hourly statistic Hardly anyone will need a storage depth of more than a month.', false, true, 'int', '30', 0, 365),
+(57, 'nagios_url', 'Адрес сайта nagios', 'nagios site address', false, true, 'text', 'http://127.0.0.1/nagios', 0, 0),
+(58, 'cacti_url', 'Адрес сайта cacti', 'cacti site address', false, true, 'text', 'http://127.0.0.1/cacti', 0, 0),
+(59, 'torrus_url', 'Адрес сайта Torrus', 'Torrus website address', false, true, 'text', 'http://127.0.0.1/torrus/CollectorName/', 0, 0),
+(60, 'wiki_url', 'Адрес wiki', 'Wiki website address', false, true, 'text', 'http://127.0.0.1/wiki', 0, 0),
+(61, 'wiki_path', 'Путь к каталогу данных вики', 'Path to wiki data directory', false, true, 'text', '/var/www/foswiki/data/', 0, 0),
+(62, 'stat_url', 'Адрес этого сайта', 'Address of this site', false, true, 'text', 'http://127.0.0.1/stat', 0, 0),
+(63, 'wiki_web', 'Web for Wiki. Default - Main. http://example.local/Main/WebHome', 'Web for Wiki. Default - Main. http://example.local/Main/WebHome', false, true, 'text', 'Main', 0, 0),
+(64, 'auto_mac_rule', 'Создавать автоматическую привязку мак-адреса к юзеру. Т.е. все ip-адреса для найденного мака будут привязываться к одном и тому же юзеру.', 'Create an automatic binding of the mac address to the user. I.e. all ip addresses for the found mac will be bound to the same user.', false, true, 'bool', '0', 0, 1),
+(65, 'mikrotik_command_interface', 'Используемый способ конфигурирования (0 - cli для ROS 6, 1 - rest api для ROS 7)', 'Configuration method used (0 - cli for ROS 6, 1 - rest api for ROS 7)', true, true, 'int', '0', 0, 1),
+(66, 'mikrotik_rest_api_ssl', 'Использовать https для rest api', 'Use HTTPS for rest api', true, true, 'bool', '1', 0, 1),
+(67, 'mikrotik_rest_api_port', 'Порт вэб-интерфейса для rest api','Web interface port for rest API', true, true, 'int', '443', 0, 0),
+(68, 'config_mode', 'Режим конфигурирования. Скрипт опроса устройств не выполняется.', 'Configuration mode. The device polling script is not running.', false, true, 'bool', '0', 0, 1),
+(69, 'clean_empty_user', 'Автоматически удалять записи пользователей, не содержащие ip-адресов или автоматических привязок', 'Automatically delete user records that do not contain IP addresses or automatic bindings', false, true, 'bool', '0', 0, 1),
+(70, 'dns_server_type', 'Тип используемого dns-сервера: Windows, Bind. Если используется локальный dnsmasq - параметры dns-сервера указывать не надо.', 'The type of dns server used: Windows, Bind. If you are using a local dnsmasq, you do not need to specify the dns server parameters.', false, true, 'list;windows;bind', 'bind', 0, 0),
+(71, 'enable_dns_updates', 'Включить обновления DNS имен при изменении dns-имени в ip-записи', 'Enable DNS name updates when dns name changes in an ip record', false, true, 'bool', '0', 0, 1),
+(72, 'netflow_path', 'Каталог для хранения данных, полученных по netflow от маршрутизаторов', 'The directory for storing data received via netflow from routers', false, true, 'text', '/opt/Eye/netflow', 0, 0),
+(73, 'check_computer_exists', 'Проверять существование компьютера в домене перед обновлением DNS по DHCP запросу', 'Verify the existence of a computer in the domain before updating DNS by DHCP request', false, true, 'bool', '1', 0, 0)
+ON CONFLICT (id) DO UPDATE SET
+    option_name = EXCLUDED.option_name,
+    "description.russian" = EXCLUDED."description.russian",
+    "description.english" = EXCLUDED."description.english",
+    draft = EXCLUDED.draft,
+    uniq = EXCLUDED.uniq,
+    type = EXCLUDED.type,
+    default_value = EXCLUDED.default_value,
+    min_value = EXCLUDED.min_value,
+    max_value = EXCLUDED.max_value;
+
+-- System configuration values
+INSERT INTO config (id, option_id, value)
+VALUES
+(1, 1, '0'),
+(2, 11, 'public'),
+(3, 32, 'ORG'),
+(123, 19, '1'),
+(124, 35, '120'),
+(125, 9, '2'),
+(126, 41, '/opt/Eye/scripts/fetch_new_arp.pl'),
+(127, 26, '3'),
+(128, 27, '10'),
+(129, 48, '90'),
+(130, 49, '365'),
+(131, 47, '90'),
+(132, 53, '1'),
+(133, 55, '1'),
+(134, 56, '30'),
+(135, 34, '0'),
+(137, 65, '0'),
+(142, 54, ''),
+(143, 17, '1'),
+(144, 37, '/opt/Eye/scripts/sync_mikrotik.pl'),
+(145, 23, '1'),
+(148, 22, '1')
+ON CONFLICT (id) DO UPDATE SET
+    option_id = EXCLUDED.option_id,
+    value = EXCLUDED.value;
+
+-- System users/administrators
+-- В PostgreSQL нет аналога ON DUPLICATE KEY UPDATE, используем ON CONFLICT
+INSERT INTO Customers (id, Login, comment, password, api_key, rights)
+VALUES (1, 'admin', 'Administrator', '$2y$11$wohV8Tuqu0Yai9Shacei5OKfMxG5bnLxB5ACcZcJJ3pYEbIH0qLGG', 'c3284d0f94606de1fd2af172aba15bf31', 1)
+ON CONFLICT (id) DO UPDATE SET
+    Login = EXCLUDED.Login,
+    comment = EXCLUDED.comment,
+    password = EXCLUDED.password,
+    api_key = EXCLUDED.api_key,
+    rights = EXCLUDED.rights;
+
+-- Device models
+INSERT INTO device_models (id, model_name, vendor_id, poe_in, poe_out, nagios_template)
+VALUES
+(1, '2011LS', 9, true, false, NULL),
+(2, '2011UAS-2HnD', 9, true, false, NULL),
+(3, 'AT-8000S', 8, false, false, NULL),
+(4, 'AT-8100S/48POE', 8, false, false, NULL),
+(5, 'AT-9000/28', 8, false, false, NULL),
+(6, 'AT-GS950/24', 8, false, false, NULL),
+(7, 'CCR1009-7G-1C-1S+', 9, false, false, NULL),
+(8, 'CCR1036-8G-2S+', 9, false, false, NULL),
+(10, 'CRS317-1G-16S+', 9, false, false, NULL),
+(11, 'CRS326-24S+2Q+', 9, false, false, NULL),
+(12, 'CRS328-24P-4S+', 9, true, false, NULL),
+(14, 'CRS328-4C-20S-4S+', 9, false, false, NULL),
+(15, 'DGS-3120-48TC', 7, false, false, NULL),
+(16, 'ES-2024', 4, false, false, NULL),
+(17, 'ES-2024A', 4, false, false, NULL),
+(18, 'ES-2108', 4, false, false, NULL),
+(19, 'ES-2108-G', 4, false, false, NULL),
+(20, 'ES-3124-4F', 4, false, false, NULL),
+(21, 'GS110TP', 10, false, true, NULL),
+(22, 'GS-4024', 4, false, false, NULL),
+(23, 'HP 1910', 15, false, false, NULL),
+(24, 'ISCOM2110A-MA', 5, false, false, NULL),
+(25, 'ISCOM2110EA-MA', 5, false, false, NULL),
+(26, 'ISCOM2126EA-MA', 5, false, false, NULL),
+(27, 'ISCOM2128EA-MA', 5, false, false, NULL),
+(28, 'Linux server', 1, false, false, ''),
+(29, 'MES2124F', 2, false, false, NULL),
+(30, 'MES2124MB', 2, false, false, NULL),
+(31, 'MES5248', 2, false, false, NULL),
+(32, 'RB2011UAS', 9, true, false, NULL),
+(33, 'RB3011UiAS', 9, true, false, NULL),
+(34, 'RB960PGS', 9, true, true, NULL),
+(35, 'RBD52G-5HacD2HnD', 9, true, false, NULL),
+(36, 'S2940-8G-v2', 6, false, false, NULL),
+(37, 'S2980G-24T', 6, false, false, NULL),
+(38, 'S3750G-24S-E', 6, false, false, NULL),
+(39, 'S5300-52P-LI-AC', 3, false, false, NULL),
+(40, 'S5320-52X-PWR-SI-AC', 3, false, false, NULL),
+(41, 'S5321-28X-SI-AC', 3, false, false, NULL),
+(42, 'S5321-52X-SI-AC', 3, false, false, NULL),
+(43, 'S6320-54C-EI-48S-AC', 3, false, false, NULL),
+(44, 'SNR-S2980G-24T', 6, false, false, NULL),
+(45, 'V1910-16G', 15, false, false, NULL),
+(46, 'V1910-24G-PoE', 15, false, false, NULL),
+(47, 'Windows server', 1, false, false, NULL),
+(48, 'WS-C2960G-24TC-L', 16, false, false, NULL),
+(49, 'WS-C3560G-24TS-S', 16, false, false, NULL),
+(50, 'x210-16GT', 8, false, false, NULL),
+(51, 'x210-24GT', 8, false, false, NULL),
+(52, 'x610-24Ts/X', 8, false, false, NULL),
+(53, 'x610-48Ts', 8, false, false, NULL),
+(54, 'XGS-4728', 4, false, false, NULL),
+(55, 'ZyWall 310', 4, false, false, NULL),
+(56, 'APC Smart-UPS_3000', 20, false, false, 'ups.cfg'),
+(57, 'APC Smart-UPS_5000', 20, false, false, 'ups.cfg'),
+(58, 'Schneider Smart-UPS_3000', 21, false, false, NULL),
+(59, 'SMG-1016M', 2, false, false, NULL),
+(60, 'EATON 9PX 1500i RT 2U', 64, false, false, NULL),
+(61, 'EATON 9PX3000i_RT_2U', 64, false, false, NULL),
+(62, 'EATON 9PX_6000i', 64, false, false, NULL),
+(63, 'EATON PW9130_3000', 64, false, false, NULL),
+(64, 'EATON PW9130_3000VA-R', 64, false, false, NULL),
+(65, 'Epson WF-5620 Series', 59, false, false, NULL),
+(66, 'Epson WF-8590 Series', 59, false, false, NULL),
+(67, 'HP Officejet-7000', 15, false, false, 'hp.cfg'),
+(68, 'OKI C610', 62, false, false, NULL),
+(69, 'OKI MB472', 62, false, false, NULL),
+(70, 'OKI MB491', 62, false, false, NULL),
+(71, 'OKI MC562', 62, false, false, NULL),
+(72, 'OKI MC573', 62, false, false, NULL),
+(73, 'OKI MC861', 62, false, false, NULL),
+(74, 'Panasonic KX-MB2000RU', 61, false, false, NULL),
+(75, 'PT-MZ10KE', 61, false, false, NULL),
+(76, 'PT-VX41', 61, false, false, NULL),
+(77, 'Rave 522AA', 33, false, false, NULL),
+(78, 'DZ570E', 61, false, false, NULL),
+(79, 'DZ6700', 61, false, false, NULL),
+(80, 'Rcq80', 61, false, false, NULL),
+(81, 'RZ12K', 61, false, false, NULL),
+(82, 'RZ660', 61, false, false, NULL),
+(83, 'RZ770', 61, false, false, NULL),
+(84, 'RZ970', 61, false, false, NULL),
+(85, 'XVR-5216', 66, false, false, NULL),
+(86, 'HWg-STE', 68, false, false, NULL),
+(87, 'Computer', 1, false, false, ''),
+(88, 'Mobile Phone', 1, false, false, NULL),
+(89, 'Switch', 1, false, false, NULL),
+(90, 'Projectiondesign F22', 34, false, false, NULL),
+(91, 'DS-I252', 36, false, false, NULL),
+(92, 'LTV-CNE-720-48', 37, false, false, NULL),
+(93, 'U-100', 38, false, false, NULL),
+(94, 'TAU-8', 2, false, false, NULL),
+(95, 'SIP-T21P E2', 39, false, false, NULL),
+(96, 'A510 IP', 40, false, false, NULL),
+(97, 'W60B', 39, false, false, NULL),
+(98, 'TAU-2M', 2, false, false, NULL),
+(99, 'PAP2T', 41, false, false, NULL),
+(100, 'VP-12', 2, false, false, NULL),
+(101, 'SIP-T23P', 39, false, false, NULL),
+(102, 'SPA-2102', 16, false, false, NULL),
+(103, 'RB760iGS', 9, true, false, NULL),
+(104, 'MES2324B', 2, false, false, NULL),
+(105, 'MES2324FB', 2, false, false, NULL),
+(106, 'MES2124P', 2, false, true, NULL),
+(107, 'MES2428P', 2, false, true, NULL),
+(108, 'Symmetra LX 16000', 20, false, false, 'symmetra.cfg'),
+(109, 'SNR-UPS-ONT20', 6, false, false, 'ups3.cfg'),
+(110, 'MES-3728', 4, false, false, NULL),
+(111, 'SNR-S5210G-24TX-UPS-R', 6, false, false, NULL),
+(112, 'SNR-S2985G-24TC', 6, false, false, NULL),
+(113, 'MES-5248', 2, false, false, NULL),
+(114, 'SNR-S5210G-24TX-POE', 6, false, true, NULL),
+(115, 'SNR-S5210G-24TX-UPS', 6, false, false, NULL),
+(116, 'SNR-S5210X-8F-UPS', 6, false, false, NULL),
+(117, 'SNR-S2982G-8T-UPS', 6, false, false, NULL)
+ON CONFLICT (id) DO UPDATE SET
+    model_name = EXCLUDED.model_name,
+    vendor_id = EXCLUDED.vendor_id,
+    poe_in = EXCLUDED.poe_in,
+    poe_out = EXCLUDED.poe_out,
+    nagios_template = EXCLUDED.nagios_template;
+
+-- Device types
+INSERT INTO device_types (id, "name.russian", "name.english")
+VALUES
+(0, 'Роутер', 'Router'),
+(1, 'Свич', 'Switch'),
+(2, 'Шлюз', 'Gateway'),
+(3, 'Сервер', 'Server'),
+(4, 'Точка доступа', 'WiFi Access Point'),
+(5, 'Сетевое устройство', 'Network device')
+ON CONFLICT (id) DO UPDATE SET
+    "name.russian" = EXCLUDED."name.russian",
+    "name.english" = EXCLUDED."name.english";
+
+-- Filter instances
+INSERT INTO filter_instances (id, name, comment)
+VALUES (1, 'default', NULL)
+ON CONFLICT (id) DO UPDATE SET
+    name = EXCLUDED.name,
+    comment = EXCLUDED.comment;
+
+-- Filter groups (русские названия)
+INSERT INTO Group_list (id, instance_id, group_name, comment)
+VALUES
+(0, 1, 'default', 'Всё запрещено'),
+(1, 1, 'Allow all', 'Разрешено всё'),
+(2, 1, 'Users', 'Для пользователей')
+ON CONFLICT (id) DO UPDATE SET
+    instance_id = EXCLUDED.instance_id,
+    group_name = EXCLUDED.group_name,
+    comment = EXCLUDED.comment;
+
+-- Organizational Units (русские названия)
+INSERT INTO OU (id, ou_name, comment, default_users, default_hotspot, nagios_dir, nagios_host_use, nagios_ping, nagios_default_service, enabled, filter_group_id, queue_id, dynamic, life_duration, parent_id)
+VALUES
+(0, '!Всё', NULL, false, false, '/etc/nagios/any', 'generic-host', true, NULL, 0, 0, 0, false, 24.00, NULL),
+(1, 'Сервера', NULL, false, false, NULL, NULL, true, NULL, 1, 1, 0, false, 24.00, NULL),
+(2, 'Администраторы', NULL, false, false, NULL, NULL, true, NULL, 0, 0, 0, false, 24.00, NULL),
+(3, 'Пользователи', NULL, false, false, NULL, NULL, true, NULL, 0, 0, 0, false, 24.00, NULL),
+(4, 'VOIP', NULL, false, false, 'voip', 'voip', true, NULL, 1, 4, 5, false, 24.00, NULL),
+(5, 'IPCAM', NULL, false, false, 'videocam', 'ip-cam', true, NULL, 0, 0, 0, false, 24.00, NULL),
+(6, 'Принтеры', NULL, false, false, 'printers', 'printers', true, 'printer-service', 0, 0, 0, false, 24.00, NULL),
+(7, 'Свичи', NULL, false, false, 'switches', 'switches', true, NULL, 0, 0, 0, false, 24.00, NULL),
+(8, 'UPS', NULL, false, false, 'ups', 'ups', true, NULL, 0, 0, 0, false, 24.00, NULL),
+(9, 'Охрана', NULL, false, false, 'security', 'security', true, NULL, 0, 0, 0, false, 24.00, NULL),
+(10, 'Роутеры', NULL, false, false, 'routers', 'routers', true, NULL, 0, 0, 0, false, 24.00, NULL),
+(11, 'WiFi AP', NULL, false, false, 'ap', 'ap', true, NULL, 0, 0, 0, false, 24.00, NULL),
+(12, 'DHCP', NULL, true, false, NULL, NULL, true, NULL, 0, 0, 0, false, 24.00, NULL),
+(13, 'Гости', NULL, false, false, NULL, NULL, true, NULL, 1, 1, 4, true, 24.00, NULL)
+ON CONFLICT (id) DO UPDATE SET
+    ou_name = EXCLUDED.ou_name,
+    comment = EXCLUDED.comment,
+    default_users = EXCLUDED.default_users,
+    default_hotspot = EXCLUDED.default_hotspot,
+    nagios_dir = EXCLUDED.nagios_dir,
+    nagios_host_use = EXCLUDED.nagios_host_use,
+    nagios_ping = EXCLUDED.nagios_ping,
+    nagios_default_service = EXCLUDED.nagios_default_service,
+    enabled = EXCLUDED.enabled,
+    filter_group_id = EXCLUDED.filter_group_id,
+    queue_id = EXCLUDED.queue_id,
+    dynamic = EXCLUDED.dynamic,
+    life_duration = EXCLUDED.life_duration,
+    parent_id = EXCLUDED.parent_id;
+
+-- Traffic shaping queues
+INSERT INTO Queue_list (id, queue_name, Download, Upload)
+VALUES
+(0, 'unlimited', 0, 0),
+(1, '2M/2M', 2048, 2048),
+(2, '10M/10M', 10240, 10240),
+(3, '100M/100M', 102400, 102400),
+(4, '50M/50M', 50000, 50000),
+(5, '20M/20M', 20480, 20480),
+(6, '200M/200M', 212400, 212400),
+(7, '1G/1G', 1024000, 1024000),
+(8, '2G/2G', 2048000, 2048000)
+ON CONFLICT (id) DO UPDATE SET
+    queue_name = EXCLUDED.queue_name,
+    Download = EXCLUDED.Download,
+    Upload = EXCLUDED.Upload;
+
+-- Network subnets
+INSERT INTO subnets (id, subnet, vlan_tag, ip_int_start, ip_int_stop, dhcp_start, dhcp_stop, dhcp_lease_time, gateway, office, hotspot, vpn, free, dhcp, static, dhcp_update_hostname, discovery, notify, comment)
+VALUES (1, '192.168.2.0/24', 2, 3232236032, 3232236287, 3232236132, 3232236182, 480, 3232236033, true, false, false, false, true, false, true, true, 7, 'LAN')
+ON CONFLICT (id) DO UPDATE SET
+    subnet = EXCLUDED.subnet,
+    vlan_tag = EXCLUDED.vlan_tag,
+    ip_int_start = EXCLUDED.ip_int_start,
+    ip_int_stop = EXCLUDED.ip_int_stop,
+    dhcp_start = EXCLUDED.dhcp_start,
+    dhcp_stop = EXCLUDED.dhcp_stop,
+    dhcp_lease_time = EXCLUDED.dhcp_lease_time,
+    gateway = EXCLUDED.gateway,
+    office = EXCLUDED.office,
+    hotspot = EXCLUDED.hotspot,
+    vpn = EXCLUDED.vpn,
+    free = EXCLUDED.free,
+    dhcp = EXCLUDED.dhcp,
+    static = EXCLUDED.static,
+    dhcp_update_hostname = EXCLUDED.dhcp_update_hostname,
+    discovery = EXCLUDED.discovery,
+    notify = EXCLUDED.notify,
+    comment = EXCLUDED.comment;
+
+-- Device vendors
+INSERT INTO vendors (id, name)
+VALUES
+(1, 'Unknown'),
+(2, 'Eltex'),
+(3, 'Huawei'),
+(4, 'Zyxel'),
+(5, 'Raisecom'),
+(6, 'SNR'),
+(7, 'Dlink'),
+(8, 'Allied Telesis'),
+(9, 'Mikrotik'),
+(10, 'NetGear'),
+(11, 'Ubiquiti'),
+(15, 'HP'),
+(16, 'Cisco'),
+(17, 'Maipu'),
+(18, 'Asus'),
+(19, 'Linux'),
+(20, 'APC'),
+(21, 'Schneider'),
+(33, 'QSC'),
+(34, 'Projectiondesign'),
+(35, 'Lenovo'),
+(36, 'HiWatch'),
+(37, 'LTV'),
+(38, 'Yeastar'),
+(39, 'Yealink'),
+(40, 'Gigaset'),
+(41, 'Linksys'),
+(42, 'Samsung'),
+(43, 'Supermicro'),
+(44, 'RDP'),
+(45, 'SANYO'),
+(46, 'Extreme'),
+(47, 'Intel'),
+(48, 'Micron'),
+(49, 'Gigabyte'),
+(50, 'Acer'),
+(51, 'Seagate'),
+(52, 'SanDisk'),
+(53, 'Toshiba'),
+(54, 'Kingston'),
+(55, 'AddPac'),
+(56, 'Devline'),
+(57, 'Canon'),
+(58, 'Brother'),
+(59, 'Epson'),
+(60, 'IP-COM'),
+(61, 'Panasonic'),
+(62, 'OKI'),
+(63, 'Apple'),
+(64, 'Eaton'),
+(65, 'Barco'),
+(66, 'Trassir'),
+(67, 'Testo'),
+(68, 'Hw-group'),
+(69, 'Tp-link')
+ON CONFLICT (id) DO UPDATE SET
+    name = EXCLUDED.name;
+
+-- Filter rules list
+INSERT INTO Filter_list (id, name, comment, proto, dst, dstport, srcport, type)
+VALUES
+(1, 'pop3', NULL, 'tcp', '0/0', '110', NULL, 0),
+(3, 'http', NULL, 'tcp', '0/0', '80', NULL, 0),
+(4, 'https', NULL, 'tcp', '0/0', '443', NULL, 0),
+(5, 'icq', NULL, 'tcp', '0/0', '5190', NULL, 0),
+(6, 'jabber', NULL, 'tcp', '0/0', '5222', NULL, 0),
+(9, 'allow_all', 'любой трафик', 'all', '0/0', '0', '0', 0),
+(10, 'icmp', NULL, 'icmp', '0/0', '0', NULL, 0),
+(11, 'ftp', NULL, 'tcp', '0/0', '20-21', NULL, 0),
+(15, 'telnet', NULL, 'tcp', '0/0', '23', NULL, 0),
+(16, 'ssh', NULL, 'tcp', '0/0', '22', NULL, 0),
+(28, 'smtp', NULL, 'tcp', '0/0', '25', NULL, 0),
+(32, 'rdp', NULL, 'tcp', '0/0', '3389', NULL, 0),
+(40, 'ntp', NULL, 'udp', '0/0', '123', NULL, 0),
+(44, 'vnc', NULL, 'tcp', '0/0', '5800-5900', NULL, 0),
+(55, 'unprivileged tcp', NULL, 'tcp', '0/0', '1024-65500', NULL, 0),
+(76, 'ipsec', NULL, 'udp', '0/0', '500', NULL, 0),
+(77, 'isakmp', NULL, 'udp', '0/0', '4500', NULL, 0),
+(79, 'pop3s', NULL, 'tcp', '0/0', '995', NULL, 0),
+(80, 'smtps', NULL, 'tcp', '0/0', '465,587', NULL, 0),
+(81, 'imap', NULL, 'tcp', '0/0', '143', NULL, 0),
+(82, 'imaps', NULL, 'tcp', '0/0', '993', NULL, 0),
+(83, 'unprivileged udp', NULL, 'udp', '0/0', '1024-65000', NULL, 0),
+(84, 'pptp', NULL, 'tcp', '0/0', '1723', NULL, 0),
+(85, 'openvpn-udp', NULL, 'udp', '0/0', '1194', NULL, 0),
+(90, 'dns_udp', NULL, 'udp', '0/0', '53', NULL, 0),
+(91, 'dns_tcp', NULL, 'tcp', '0/0', '53', NULL, 0),
+(94, 'squid', NULL, 'tcp', '0/0', '3128', NULL, 0),
+(101, 'snmp', NULL, 'udp', '0/0', '161', NULL, 0),
+(105, 'http_udp', NULL, 'udp', '0/0', '80', NULL, 0),
+(106, 'https_udp', NULL, 'udp', '0/0', '443', NULL, 0),
+(107, 'l2tp-ipsec', NULL, 'udp', '0/0', '1701,4500,500', NULL, 0),
+(108, 'gre', NULL, 'gre', '0/0', NULL, NULL, 0)
+ON CONFLICT (id) DO UPDATE SET
+    name = EXCLUDED.name,
+    comment = EXCLUDED.comment,
+    proto = EXCLUDED.proto,
+    dst = EXCLUDED.dst,
+    dstport = EXCLUDED.dstport,
+    srcport = EXCLUDED.srcport,
+    type = EXCLUDED.type;
+
+-- Filter group assignments
+INSERT INTO Group_filters (id, group_id, filter_id, "order", action)
+VALUES
+(1, 2, 90, 1, true),
+(2, 2, 91, 2, true),
+(3, 2, 11, 3, true),
+(5, 2, 3, 4, true),
+(6, 2, 105, 5, true),
+(7, 2, 4, 6, true),
+(8, 2, 106, 7, true),
+(9, 2, 10, 8, true),
+(10, 2, 81, 9, true),
+(11, 2, 82, 10, true),
+(15, 2, 40, 11, true),
+(16, 2, 1, 12, true),
+(17, 2, 79, 13, true),
+(18, 2, 80, 14, true),
+(19, 1, 9, 1, true)
+ON CONFLICT (id) DO UPDATE SET
+    group_id = EXCLUDED.group_id,
+    filter_id = EXCLUDED.filter_id,
+    "order" = EXCLUDED."order",
+    action = EXCLUDED.action;
+
+-- System version
+INSERT INTO version (id, version)
+VALUES (1, '2.9.1')
+ON CONFLICT (id) DO UPDATE SET
+    version = EXCLUDED.version;
+
+-- Обновление последовательностей после импорта данных
+SELECT setval(pg_get_serial_sequence('acl', 'id'), COALESCE((SELECT MAX(id) FROM acl), 0) + 1);
+SELECT setval(pg_get_serial_sequence('building', 'id'), COALESCE((SELECT MAX(id) FROM building), 0) + 1);
+SELECT setval(pg_get_serial_sequence('config_options', 'id'), COALESCE((SELECT MAX(id) FROM config_options), 0) + 1);
+SELECT setval(pg_get_serial_sequence('config', 'id'), COALESCE((SELECT MAX(id) FROM config), 0) + 1);
+SELECT setval(pg_get_serial_sequence('Customers', 'id'), COALESCE((SELECT MAX(id) FROM Customers), 0) + 1);
+SELECT setval(pg_get_serial_sequence('device_models', 'id'), COALESCE((SELECT MAX(id) FROM device_models), 0) + 1);
+SELECT setval(pg_get_serial_sequence('device_types', 'id'), COALESCE((SELECT MAX(id) FROM device_types), 0) + 1);
+SELECT setval(pg_get_serial_sequence('filter_instances', 'id'), COALESCE((SELECT MAX(id) FROM filter_instances), 0) + 1);
+SELECT setval(pg_get_serial_sequence('Group_list', 'id'), COALESCE((SELECT MAX(id) FROM Group_list), 0) + 1);
+SELECT setval(pg_get_serial_sequence('OU', 'id'), COALESCE((SELECT MAX(id) FROM OU), 0) + 1);
+SELECT setval(pg_get_serial_sequence('Queue_list', 'id'), COALESCE((SELECT MAX(id) FROM Queue_list), 0) + 1);
+SELECT setval(pg_get_serial_sequence('subnets', 'id'), COALESCE((SELECT MAX(id) FROM subnets), 0) + 1);
+SELECT setval(pg_get_serial_sequence('vendors', 'id'), COALESCE((SELECT MAX(id) FROM vendors), 0) + 1);
+SELECT setval(pg_get_serial_sequence('Filter_list', 'id'), COALESCE((SELECT MAX(id) FROM Filter_list), 0) + 1);
+SELECT setval(pg_get_serial_sequence('Group_filters', 'id'), COALESCE((SELECT MAX(id) FROM Group_filters), 0) + 1);
+
+-- Информация о завершении импорта
+DO $$
+BEGIN
+    RAISE NOTICE 'Импорт данных для русской локали завершен успешно!';
+    RAISE NOTICE 'Всего импортировано таблиц: 16';
+    RAISE NOTICE 'Всего импортировано записей:';
+    RAISE NOTICE '  - acl: %', (SELECT COUNT(*) FROM acl);
+    RAISE NOTICE '  - building: %', (SELECT COUNT(*) FROM building);
+    RAISE NOTICE '  - config_options: %', (SELECT COUNT(*) FROM config_options);
+    RAISE NOTICE '  - config: %', (SELECT COUNT(*) FROM config);
+    RAISE NOTICE '  - Customers: %', (SELECT COUNT(*) FROM Customers);
+    RAISE NOTICE '  - device_models: %', (SELECT COUNT(*) FROM device_models);
+    RAISE NOTICE '  - device_types: %', (SELECT COUNT(*) FROM device_types);
+    RAISE NOTICE '  - filter_instances: %', (SELECT COUNT(*) FROM filter_instances);
+    RAISE NOTICE '  - Group_list: %', (SELECT COUNT(*) FROM Group_list);
+    RAISE NOTICE '  - OU: %', (SELECT COUNT(*) FROM OU);
+    RAISE NOTICE '  - Queue_list: %', (SELECT COUNT(*) FROM Queue_list);
+    RAISE NOTICE '  - subnets: %', (SELECT COUNT(*) FROM subnets);
+    RAISE NOTICE '  - vendors: %', (SELECT COUNT(*) FROM vendors);
+    RAISE NOTICE '  - Filter_list: %', (SELECT COUNT(*) FROM Filter_list);
+    RAISE NOTICE '  - Group_filters: %', (SELECT COUNT(*) FROM Group_filters);
+    RAISE NOTICE '  - version: %', (SELECT COUNT(*) FROM version);
+END $$;

+ 1 - 0
html/cfg/config.sample.php

@@ -8,6 +8,7 @@ define("HTML_LANG","russian");
 define("HTML_STYLE","white");
 
 define("DB_HOST","localhost");
+define("DB_TYPE","db_type");
 define("DB_NAME","stat");
 define("DB_USER","user");
 define("DB_PASS","password");

+ 0 - 1110
install-eye.ru.sh

@@ -1,1110 +0,0 @@
-#!/bin/bash
-# Eye Installation Script for ALT Linux/Debian/Ubuntu
-# Version: 2.0
-
-set -e
-
-# Цвета для вывода
-RED='\033[0;31m'
-GREEN='\033[0;32m'
-YELLOW='\033[1;33m'
-BLUE='\033[0;34m'
-NC='\033[0m' # No Color
-
-# Функции для вывода
-print_info() {
-    echo -e "${GREEN}[INFO]${NC} $1"
-}
-
-print_warn() {
-    echo -e "${YELLOW}[WARN]${NC} $1"
-}
-
-print_error() {
-    echo -e "${RED}[ERROR]${NC} $1"
-}
-
-print_step() {
-    echo -e "${BLUE}=== $1 ===${NC}"
-}
-
-# Проверка прав root
-check_root() {
-    if [[ $EUID -ne 0 ]]; then
-        print_error "Этот скрипт должен быть запущен с правами root"
-        print_error "Используйте: sudo $0"
-        exit 1
-    fi
-}
-
-# Определение дистрибутива и менеджера пакетов
-detect_distro() {
-    if [[ -f /etc/os-release ]]; then
-        . /etc/os-release
-        OS_ID=$ID
-        OS_VERSION=$VERSION_ID
-        OS_NAME=$NAME
-        
-        case $OS_ID in
-            altlinux)
-                PACKAGE_MANAGER="apt-get"
-                SERVICE_MANAGER="systemctl"
-                OS_FAMILY="alt"
-                print_info "Обнаружен ALT Linux $OS_VERSION"
-                ;;
-            debian)
-                PACKAGE_MANAGER="apt"
-                SERVICE_MANAGER="systemctl"
-                OS_FAMILY="debian"
-                print_info "Обнаружен Debian $OS_VERSION"
-                ;;
-            ubuntu)
-                PACKAGE_MANAGER="apt"
-                SERVICE_MANAGER="systemctl"
-                OS_FAMILY="debian"
-                print_info "Обнаружен Ubuntu $OS_VERSION"
-                ;;
-            *)
-                print_error "Неподдерживаемый дистрибутив: $OS_ID"
-                print_error "Поддерживаются: ALT Linux, Debian, Ubuntu"
-                exit 1
-                ;;
-        esac
-    else
-        print_error "Не удалось определить дистрибутив"
-        exit 1
-    fi
-}
-
-# Установка зависимостей для ALT Linux
-install_deps_altlinux() {
-    print_step "Установка зависимостей для ALT Linux"
-    
-    # Обновление репозиториев
-    apt-get update
-    
-    # Общие утилиты
-    apt-get install -y git xxd wget fping hwdata
-    
-    # База данных
-    apt-get install -y mariadb-server mariadb-client
-    
-    # Веб-сервер и PHP
-    apt-get install -y apache2 \
-        php8.2 php8.2-mysqlnd php8.2-intl php8.2-mbstring \
-        pear-Mail php8.2-snmp php8.2-zip \
-        php8.2-pgsql php8.2-mysqlnd php8.2-pdo_mysql php8.2-mysqlnd-mysqli
-    
-    # Perl модули
-    apt-get install -y perl perl-Net-Patricia perl-NetAddr-IP \
-        perl-Config-Tiny perl-Net-DNS perl-DateTime perl-Net-Ping \
-        perl-Net-Netmask perl-Text-Iconv perl-Net-SNMP \
-        perl-Net-Telnet perl-DBI perl-DBD-mysql perl-DBD-Pg \
-        perl-Parallel-ForkManager perl-Proc-Daemon \
-        perl-DateTime-Format-DateParse \
-        perl-Net-OpenSSH perl-File-Tail perl-Crypt-Rijndael \
-        perl-Crypt-CBC perl-CryptX perl-Crypt-DES \
-        perl-File-Path-Tiny perl-Expect \
-        perl-Proc-ProcessTable
-
-    # Дополнительные сервисы
-    apt-get install -y dnsmasq syslog-ng syslog-ng-journal
-    
-    # Установка pwgen если нет
-    if ! command -v pwgen &> /dev/null; then
-        apt-get install -y pwgen
-    fi
-    
-    control fping public
-    control ping public
-}
-
-# Установка зависимостей для Debian/Ubuntu
-install_deps_debian() {
-    print_step "Установка зависимостей для Debian/Ubuntu"
-    
-    # Обновление репозиториев
-    apt-get update
-    
-    # Общие утилиты
-    apt-get install -y git xxd bsdmainutils pwgen wget fping ieee-data
-    
-    # База данных
-    apt-get install -y mariadb-server mariadb-client
-    
-    # Веб-сервер и PHP
-    apt-get install -y apache2 libapache2-mod-fcgid \
-        php php-mysql php-bcmath php-intl php-mbstring \
-        php-date php-mail php-snmp php-zip php-fpm \
-        php-db php-pgsql
-    
-    # Perl модули
-    apt-get install -y perl libnet-patricia-perl libnetaddr-ip-perl \
-        libconfig-tiny-perl libnet-dns-perl libdatetime-perl \
-        libnet-netmask-perl libtext-iconv-perl libnet-snmp-perl \
-        libnet-telnet-perl libdbi-perl libdbd-mysql-perl \
-        libparallel-forkmanager-perl libproc-daemon-perl \
-        libdatetime-format-dateparse-perl \
-        libnet-openssh-perl libfile-tail-perl libcrypt-rijndael-perl \
-        libcrypt-cbc-perl libcryptx-perl libdbd-pg-perl \
-        libfile-path-tiny-perl libexpect-perl libcrypt-des-perl
-    
-    # Дополнительные сервисы
-    apt-get install -y dnsmasq syslog-ng
-}
-
-# Обновление системы
-update_system() {
-    print_step "Обновление системы"
-    $PACKAGE_MANAGER update -y
-}
-
-# Установка пакетов
-install_packages() {
-    print_step "Установка пакетов"
-    
-    case $OS_FAMILY in
-        alt)
-            install_deps_altlinux
-            ;;
-        debian)
-            install_deps_debian
-            ;;
-    esac
-}
-
-# Создание пользователя и группы
-create_user_group() {
-    print_step "Создание пользователя и группы"
-    
-    # Создание группы
-    if ! getent group eye >/dev/null; then
-        groupadd --system eye
-        print_info "Создана группа eye"
-    else
-        print_info "Группа eye уже существует"
-    fi
-    
-    # Создание пользователя
-    if ! id -u eye >/dev/null 2>&1; then
-        if [[ "$OS_FAMILY" == "alt" ]]; then
-            # Для ALT Linux
-            useradd --system --shell /bin/bash --home-dir /opt/Eye \
-                --gid eye --groups eye eye
-        else
-            # Для Debian/Ubuntu
-            adduser --system --disabled-password --disabled-login \
-                --ingroup eye --home=/opt/Eye eye
-        fi
-        print_info "Создан пользователь eye"
-    else
-        print_info "Пользователь eye уже существует"
-    fi
-    
-    # Создание директории
-    mkdir -p /opt/Eye
-    chown eye:eye /opt/Eye
-    chmod 770 /opt/Eye
-    
-    # Добавление nagios в группу eye (если существует)
-    if id -u nagios >/dev/null 2>&1; then
-        usermod -a -G eye nagios
-        print_info "Пользователь nagios добавлен в группу eye"
-    fi
-}
-
-# Проверка и применение патча для SNMP SHA512
-apply_snmp_patch() {
-    print_info "Проверка поддержки SNMPv3 SHA512..."
-    
-    # Пути к файлам
-    USM_PATCH_FILE="/opt/Eye/docs/patches/sha512.patch"
-    if [[ "$OS_FAMILY" == "alt" ]]; then
-        USM_PATCH_FILE="/opt/Eye/docs/patches/sha512.alt.patch"
-	fi
-
-    USM_PM_FILE=""
-    
-    # Поиск файла USM.pm в системе
-    local usm_paths=(
-        "/usr/share/perl5/Net/SNMP/Security/USM.pm"
-        "/usr/lib/perl5/vendor_perl/Net/SNMP/Security/USM.pm"
-        "/usr/local/share/perl5/Net/SNMP/Security/USM.pm"
-    )
-    
-    for path in "${usm_paths[@]}"; do
-        if [[ -f "$path" ]]; then
-            USM_PM_FILE="$path"
-            print_info "Найден USM.pm: $USM_PM_FILE"
-            break
-        fi
-    done
-    
-    if [[ -z "$USM_PM_FILE" ]]; then
-        print_warn "Файл USM.pm не найден в системе"
-        return 1
-    fi
-
-    # Проверка, уже ли применен патч
-    if grep -q "AUTH_PROTOCOL_HMACSHA512" "$USM_PM_FILE"; then
-        print_info "Патч SHA512 уже применен"
-        return 0
-    fi
-    
-    # Создание резервной копии
-    cp "$USM_PM_FILE" "${USM_PM_FILE}.backup"
-    print_info "Создана резервная копия: ${USM_PM_FILE}.backup"
-    
-    # Попытка применить patch файл
-    local patch_applied=false
-    
-    if [[ -f "$USM_PATCH_FILE" ]]; then
-        print_info "Попытка применить патч из $USM_PATCH_FILE"
-        
-        # Проверка возможности применить патч
-        if patch --dry-run -l -p1 -i "$USM_PATCH_FILE" -r /tmp/patch.rej "$USM_PM_FILE" 2>/dev/null; then
-            # Применяем патч
-            if patch -l -p1 -i "$USM_PATCH_FILE" "$USM_PM_FILE" 2>/dev/null; then
-                print_info "Патч успешно применен!"
-                patch_applied=true
-            else
-                print_warn "Не удалось применить патч (dry-run прошел, но реальное применение не удалось)"
-            fi
-        else
-            print_warn "Патч не может быть применен автоматически (несоответствие версий)"
-            
-            # Проверка отличий
-            print_info "Проверка отличий в патче..."
-            if [[ -f "/opt/Eye/docs/patches/USM.pm" ]]; then
-                diff -u "$USM_PM_FILE" "/opt/Eye/docs/patches/USM.pm" > /tmp/usm.diff 2>/dev/null || true
-                
-                if [[ -s /tmp/usm.diff ]]; then
-                    print_warn "Обнаружены отличия в файле USM.pm"
-                    echo "Отличия:"
-                    head -20 /tmp/usm.diff
-                    echo "..."
-                fi
-            fi
-        fi
-    fi
-    
-    # Если патч не применился, спрашиваем пользователя
-    if [[ "$patch_applied" == false ]]; then
-        echo ""
-        print_warn "Автоматическое применение патча не удалось"
-        print_warn "Для работы SNMPv3 с SHA512 требуется модифицировать файл USM.pm"
-        echo ""
-        
-        read -p "Требуется ли поддержка SNMPv3 с SHA512? (y/n): " -n 1 -r
-        echo
-        if [[ $REPLY =~ ^[Yy]$ ]]; then
-            # Пробуем заменить файл целиком
-            if [[ -f "/opt/Eye/docs/patches/USM.pm" ]]; then
-                print_info "Замена файла USM.pm целиком..."
-                
-                # Проверка совместимости версий
-                local original_ver=$(grep -i "version" "$USM_PM_FILE" | head -1)
-                local patch_ver=$(grep -i "version" "/opt/Eye/docs/patches/USM.pm" | head -1)
-                
-                if [[ -n "$original_ver" && -n "$patch_ver" ]]; then
-                    print_info "Версия оригинального файла: $original_ver"
-                    print_info "Версия патча: $patch_ver"
-                fi
-                
-                # Создаем дополнительную резервную копию
-                cp "$USM_PM_FILE" "${USM_PM_FILE}.backup.$(date +%Y%m%d_%H%M%S)"
-                
-                # Заменяем файл
-                cp -f "/opt/Eye/docs/patches/USM.pm" "$USM_PM_FILE"
-                
-                # Проверяем успешность замены
-                if grep -q "SHA-512" "$USM_PM_FILE"; then
-                    print_info "Файл USM.pm успешно заменен, поддержка SHA512 добавлена"
-                    
-                    # Сохраняем информацию о замене
-                    echo "Файл USM.pm был заменен для поддержки SHA512" > "${USM_PM_FILE}.replaced"
-                    echo "Оригинальный файл сохранен как: ${USM_PM_FILE}.backup" >> "${USM_PM_FILE}.replaced"
-                    echo "Дата замены: $(date)" >> "${USM_PM_FILE}.replaced"
-                    
-                    return 0
-                else
-                    print_error "Не удалось добавить поддержку SHA512 после замены файла"
-                    # Восстанавливаем из резервной копии
-                    cp "${USM_PM_FILE}.backup" "$USM_PM_FILE"
-                    return 1
-                fi
-            else
-                print_error "Файл USM.pm с патчем не найден в /opt/Eye/docs/patches/"
-                return 1
-            fi
-        else
-            print_info "Поддержка SNMPv3 SHA512 отключена"
-            return 0
-        fi
-    fi
-    
-    return 0
-}
-
-# Загрузка и копирование исходного кода
-install_source_code() {
-    print_step "Установка исходного кода Eye"
-    
-    # Создание структуры каталогов
-    print_info "Создание структуры каталогов..."
-    mkdir -p /opt/Eye/scripts/cfg
-    mkdir -p /opt/Eye/scripts/log
-    mkdir -p /opt/Eye/html/cfg
-    mkdir -p /opt/Eye/html/js
-    mkdir -p /opt/Eye/docs
-
-    chmod -R 755 /opt/Eye/html
-    chmod -R 770 /opt/Eye/scripts/log
-    chmod 750 /opt/Eye/scripts
-
-    # Копирование файлов
-    print_info "Копирование файлов..."
-    cp -R scripts/ /opt/Eye/
-    cp -R html/ /opt/Eye/
-    cp -R docs/ /opt/Eye/
-
-    # Настройка прав
-    chown -R eye:eye /opt/Eye
-
-    # применение патча для SNMP SHA512
-    apply_snmp_patch
-}
-
-# Загрузка дополнительных скриптов
-download_additional_scripts() {
-    print_step "Загрузка дополнительных скриптов"
-    
-    # Создание директорий
-    mkdir -p /opt/Eye/html/js/jq
-    mkdir -p /opt/Eye/html/js/select2
-    mkdir -p /opt/Eye/html/js/jstree
-    
-    # Загрузка jQuery
-    print_info "Загрузка jQuery..."
-    if ! wget -q https://code.jquery.com/jquery-3.7.0.min.js \
-        -O /opt/Eye/html/js/jq/jquery.min.js; then
-        print_warn "Не удалось загрузить jQuery, попытка альтернативного источника..."
-        wget -q https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js \
-            -O /opt/Eye/html/js/jq/jquery.min.js || \
-        print_error "Не удалось загрузить jQuery"
-    fi
-    
-    # Загрузка Select2
-    print_info "Загрузка Select2..."
-    if wget -q https://github.com/select2/select2/archive/4.0.12.tar.gz -O 4.0.12.tar.gz; then
-        tar -xzf 4.0.12.tar.gz -C /opt/Eye/html/js/select2/ \
-            --strip-components=2 select2-4.0.12/dist 2>/dev/null || \
-        tar -xzf 4.0.12.tar.gz -C /opt/Eye/html/js/select2/ \
-            --strip-components=1 select2-4.0.12/dist 2>/dev/null
-        rm -f 4.0.12.tar.gz
-    else
-        print_warn "Не удалось загрузить Select2"
-    fi
-    
-    # Загрузка jsTree
-    print_info "Загрузка jsTree..."
-    if wget -q https://github.com/vakata/jstree/archive/3.3.12.tar.gz -O jstree.tar.gz; then
-        tar -xzf jstree.tar.gz -C /opt/Eye/html/js/
-        mv /opt/Eye/html/js/jstree-3.3.12/dist/* /opt/Eye/html/js/jstree
-        rm -rf /opt/Eye/html/js/jstree-3.3.12
-        rm -f jstree.tar.gz
-    else
-        print_warn "Не удалось загрузить jsTree"
-    fi
-    
-    # Настройка прав
-    chown -R eye:eye /opt/Eye/html/js
-}
-
-# Настройка MySQL
-setup_mysql() {
-    print_step "Настройка MySQL"
-    
-    # Запуск и включение службы
-    $SERVICE_MANAGER enable mariadb 2>/dev/null || \
-    $SERVICE_MANAGER enable mysql 2>/dev/null || true
-    
-    $SERVICE_MANAGER start mariadb 2>/dev/null || \
-    $SERVICE_MANAGER start mysql 2>/dev/null || true
-    
-    # Проверка доступа к MySQL
-    if ! command -v mysql &> /dev/null; then
-        print_error "MySQL клиент не установлен"
-        return 1
-    fi
-    
-    MYSQL_OPT="-u root"
-    
-    # Проверяем доступ без пароля
-    if mysql -u root -e "SELECT 1;" 2>/dev/null; then
-        print_info "MySQL доступен с пустым паролем"
-        echo ""
-        print_warn "ВАЖНО: Нужно настроить пароль root для MySQL!"
-        print_warn "После установки запустите: mysql_secure_installation"
-        echo ""
-    else
-        # Запрашиваем пароль и создаем конфиг файл
-        read -p "Введите пароль пользователя root MySQL: " DB_ROOT_PASSWORD
-        echo ""
-        
-        # Создаем временный конфиг файл
-        MYSQL_CNF_FILE="/tmp/mysql_root_eye.cnf"
-        echo "[client]" > "$MYSQL_CNF_FILE"
-        echo "user=root" >> "$MYSQL_CNF_FILE"
-        echo "password=$DB_ROOT_PASSWORD" >> "$MYSQL_CNF_FILE"
-        chmod 600 "$MYSQL_CNF_FILE"
-        
-        # Проверяем подключение
-        if mysql --defaults-extra-file="$MYSQL_CNF_FILE" -e "SELECT 1;" &>/dev/null; then
-            print_info "Успешное подключение к MySQL"
-            MYSQL_OPT="--defaults-extra-file=$MYSQL_CNF_FILE"
-        else
-            print_error "Неверный пароль root MySQL"
-            rm -f "$MYSQL_CNF_FILE"
-            return 1
-        fi
-    fi
-    
-    read -p "Создать базу данных и пользователя для Eye? (y/n): " -n 1 -r
-    echo
-    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
-        print_warn "Создание БД пропущено. Создайте вручную:"
-        print_warn "  mysql -u root -p < /opt/Eye/docs/mysql/create_db.sql"
-        print_warn "  mysql -u root -p stat < /opt/Eye/docs/mysql/latest-mysql-ru.sql"
-        if [[ -f "$MYSQL_CNF_FILE" ]]; then
-            rm -f "$MYSQL_CNF_FILE"
-        fi
-        return 0
-    fi
-    
-    # Генерация пароля для пользователя stat
-    DB_PASSWORD=$(pwgen 16 1)
-    MYSQL_PASSWORD=$DB_PASSWORD
-    
-    print_info "Импорт структуры базы данных..."
-    
-    # Импорт основного SQL файла
-    mysql $MYSQL_OPT < /opt/Eye/docs/mysql/create_db.sql
-    
-    if [[ $? -ne 0 ]]; then
-        print_error "Ошибка при импорте create_db.sql"
-        if [[ -f "$MYSQL_CNF_FILE" ]]; then
-            rm -f "$MYSQL_CNF_FILE"
-        fi
-        return 1
-    fi
-    
-    print_info "Структура базы данных импортирована"
-    
-    # Импорт данных
-    print_info "Импорт начальных данных..."
-    mysql $MYSQL_OPT stat < /opt/Eye/docs/mysql/latest-mysql-ru.sql
-    
-    if [[ $? -ne 0 ]]; then
-        print_warn "Ошибка при импорте latest-mysql-ru.sql (возможно данные уже существуют)"
-    else
-        print_info "Начальные данные импортированы"
-    fi
-    
-    # Создание пользователя stat
-    print_info "Создание пользователя stat..."
-    mysql $MYSQL_OPT <<EOF
-CREATE USER IF NOT EXISTS 'stat'@'localhost' IDENTIFIED BY '$DB_PASSWORD';
-GRANT ALL PRIVILEGES ON stat.* TO 'stat'@'localhost';
-FLUSH PRIVILEGES;
-EOF
-    
-    if [[ $? -ne 0 ]]; then
-        print_error "Ошибка при создании пользователя stat"
-        if [[ -f "$MYSQL_CNF_FILE" ]]; then
-            rm -f "$MYSQL_CNF_FILE"
-        fi
-        return 1
-    fi
-    
-    print_info "Пользователь 'stat' успешно создан"
-    
-    # Сохранение информации о паролях
-    echo "Пароль пользователя MySQL 'stat': $DB_PASSWORD" > /root/eye_mysql_password.txt
-    chmod 600 /root/eye_mysql_password.txt
-    
-    print_info "Пароль пользователя 'stat': $DB_PASSWORD"
-    print_warn "Пароль сохранен в /root/eye_mysql_password.txt"
-    
-    # Очистка временного файла если он был создан
-    if [[ -f "$MYSQL_CNF_FILE" ]]; then
-        rm -f "$MYSQL_CNF_FILE"
-    fi
-    
-    return 0
-}
-
-# Настройка конфигурационных файлов
-setup_configs() {
-    print_step "Настройка конфигурационных файлов"
-    
-    # Копирование конфигурационных файлов
-    if [[ -f "/opt/Eye/html/cfg/config.sample.php" ]]; then
-        cp /opt/Eye/html/cfg/config.sample.php /opt/Eye/html/cfg/config.php
-    fi
-    
-    if [[ -f "/opt/Eye/scripts/cfg/config.sample" ]]; then
-        cp /opt/Eye/scripts/cfg/config.sample /opt/Eye/scripts/cfg/config
-    fi
-    
-    # Генерация ключей шифрования
-    print_info "Генерация ключей шифрования..."
-    if command -v pwgen &> /dev/null; then
-        ENC_PASSWORD=$(pwgen 16 1)
-    else
-        ENC_PASSWORD=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c16)
-    fi
-    
-    ENC_VECTOR=$(tr -dc 0-9 </dev/urandom | head -c 16)
-    
-    # Настройка config.php
-    if [[ -f "/opt/Eye/html/cfg/config.sample.php" ]]; then
-        cp /opt/Eye/html/cfg/config.sample.php /opt/Eye/html/cfg/config.php
-    
-        # Обновляем пароль БД
-        if [[ -n "$MYSQL_PASSWORD" ]]; then
-            sed -i "s/define(\"DB_PASS\",\"[^\"]*\");/define(\"DB_PASS\",\"$MYSQL_PASSWORD\");/" /opt/Eye/html/cfg/config.php
-            sed -i "s/define(\"DB_NAME\",\"[^\"]*\");/define(\"DB_NAME\",\"stat\");/" /opt/Eye/html/cfg/config.php
-            sed -i "s/define(\"DB_USER\",\"[^\"]*\");/define(\"DB_USER\",\"stat\");/" /opt/Eye/html/cfg/config.php
-        fi
-    
-        # Обновляем ключ шифрования
-        sed -i "s/ENCRYPTION_KEY\",\"[^\"]*\"/ENCRYPTION_KEY\",\"$ENC_PASSWORD\"/" /opt/Eye/html/cfg/config.php
-        sed -i "s/ENCRYPTION_KEY','[^']*'/ENCRYPTION_KEY','$ENC_PASSWORD'/" /opt/Eye/html/cfg/config.php
-    
-        # Обновляем вектор инициализации
-        sed -i "s/ENCRYPTION_IV\",\"[^\"]*\"/ENCRYPTION_IV\",\"$ENC_VECTOR\"/" /opt/Eye/html/cfg/config.php
-        sed -i "s/ENCRYPTION_IV','[^']*'/ENCRYPTION_IV','$ENC_VECTOR'/" /opt/Eye/html/cfg/config.php
-    
-        print_info "Конфигурационный файл config.php создан из шаблона"
-    fi
-    
-    # Настройка config для скриптов
-    if [[ -f "/opt/Eye/scripts/cfg/config.sample" ]]; then
-        cp /opt/Eye/scripts/cfg/config.sample /opt/Eye/scripts/cfg/config
-    
-        # Обновляем пароль БД
-        if [[ -n "$MYSQL_PASSWORD" ]]; then
-            sed -i "s/^DBPASS=.*/DBPASS=$MYSQL_PASSWORD/" /opt/Eye/scripts/cfg/config
-            sed -i "s/DBPASS=mysql_password/DBPASS=$MYSQL_PASSWORD/" /opt/Eye/scripts/cfg/config
-        fi
-    
-        # Обновляем имя пользователя БД
-        sed -i "s/^DBUSER=.*/DBUSER=stat/" /opt/Eye/scripts/cfg/config
-        sed -i "s/DBUSER=mysql_user/DBUSER=stat/" /opt/Eye/scripts/cfg/config
-    
-        # Обновляем имя БД
-        sed -i "s/^DBNAME=.*/DBNAME=stat/" /opt/Eye/scripts/cfg/config
-        sed -i "s/DBNAME=mysql_database/DBNAME=stat/" /opt/Eye/scripts/cfg/config
-    
-        # Обновляем ключ шифрования
-        sed -i "s/^encryption_key=.*/encryption_key=$ENC_PASSWORD/" /opt/Eye/scripts/cfg/config
-        sed -i "s/encryption_key=!!!CHANGE_ME!!!!/encryption_key=$ENC_PASSWORD/" /opt/Eye/scripts/cfg/config
-    
-        # Обновляем вектор инициализации
-        sed -i "s/^encryption_iv=.*/encryption_iv=$ENC_VECTOR/" /opt/Eye/scripts/cfg/config
-        sed -i "s/encryption_iv=0123456789012345/encryption_iv=$ENC_VECTOR/" /opt/Eye/scripts/cfg/config
-    
-        print_info "Конфигурационный файл scripts/cfg/config создан из шаблона"
-    fi
-    
-    # Настройка прав
-    chown -R eye:eye /opt/Eye/html/cfg /opt/Eye/scripts/cfg
-    chmod 660 /opt/Eye/html/cfg/config.php /opt/Eye/scripts/cfg/config
-    chmod 750 /opt/Eye/html/cfg /opt/Eye/scripts/cfg
-    
-    print_info "Ключи шифрования сгенерированы"
-    print_info "Пароль: $ENC_PASSWORD"
-    print_info "Вектор: $ENC_VECTOR"
-}
-
-# Настройка Apache и PHP
-setup_apache_php() {
-    print_step "Настройка Apache и PHP"
-    
-    # Определение версии PHP
-    PHP_VERSION=$(php -v 2>/dev/null | head -n1 | grep -oP '\d+\.\d+' || echo "8.1")
-    
-    # Настройка PHP для всех дистрибутивов
-    if [[ "$OS_FAMILY" == "alt" ]]; then
-        # ALT Linux
-        PHP_INI="/etc/php/$PHP_VERSION/apache2/php.ini"
-        APACHE_CONF_DIR="/etc/httpd2/conf"
-        APACHE_SITES_DIR="$APACHE_CONF_DIR/sites-available"
-        DEFAULT_CONF="$APACHE_SITES_DIR/000-default.conf"
-        APACHE_USER="apache2"
-    else
-        # Debian/Ubuntu
-        PHP_INI="/etc/php/$PHP_VERSION/apache2/php.ini"
-        APACHE_CONF_DIR="/etc/apache2"
-        APACHE_SITES_DIR="$APACHE_CONF_DIR/sites-available"
-        DEFAULT_CONF="$APACHE_SITES_DIR/000-default.conf"
-        APACHE_USER="www-data"
-    fi
-    
-    # Настраиваем Apache
-    if [[ -f "/opt/Eye/docs/apache/000-default.conf" ]]; then
-        print_info "Используем готовый шаблон сайта"
-
-        # Создаём директории
-        mkdir -p "$APACHE_SITES_DIR"
-
-        # Копируем дефалтный конфиг
-        cp "/opt/Eye/docs/apache/000-default.conf" "$DEFAULT_CONF"
-
-        # Включаем сайт
-        if [[ -f "$APACHE_CONF_DIR/sites-enabled/000-default.conf" ]]; then
-            rm -f "$APACHE_CONF_DIR/sites-enabled/000-default.conf"
-            ln -sf "$DEFAULT_CONF" "$APACHE_CONF_DIR/sites-enabled/000-default.conf"
-        fi
-    fi
-
-    # Настраиваем sudoers
-    if [[ -f "/opt/Eye/docs/sudoers.d/www-data" ]]; then
-        # Используем подготовленный шаблон для корректного юзера
-        sed "s/www-data/eye/g" /opt/Eye/docs/sudoers.d/www-data > /etc/sudoers.d/eye
-        chmod 440 /etc/sudoers.d/eye
-        print_info "Sudoers создан из шаблона"
-    fi
-
-    # Restart Apache
-    if [[ "$OS_FAMILY" == "alt" ]]; then
-        # ALT Linux uses httpd2
-        APACHE_SERVICE="httpd2"
-        else
-        APACHE_SERVICE="apache2"
-    fi
-
-    #    usermod -a -G eye $APACHE_USER
-
-    if [[ "$OS_FAMILY" == "debian" ]]; then
-        a2dismod php${PHP_VERSION} 2>/dev/null
-        a2dismod mpm_prefork 2>/dev/null
-
-        a2enmod mpm_event 2>/dev/null
-        a2enconf php${PHP_VERSION}-fpm  2>/dev/null
-    fi
-
-    mkdir -p /var/log/php-fpm/
-
-    a2enmod setenvif
-    a2enmod proxy
-    a2enmod proxy_fcgi
-
-    print_info "Apache настроен, sudoers user: $APACHE_USER"
-    print_info "Apache service: $APACHE_SERVICE"
-
-    print_info "Настраиваем php-fpm${PHP_VERSION}"
-
-    # Configure php-fpm
-    if [[ -f "/opt/Eye/docs/php-fpm/eye.conf" ]]; then
-        print_info "Используем подготовленный php-fpm шаблон"
-        if [[ "$OS_FAMILY" == "alt" ]]; then
-            cp "/opt/Eye/docs/php-fpm/eye.conf" /etc/fpm${PHP_VERSION}/php-fpm.d/
-            else
-            cp "/opt/Eye/docs/php-fpm/eye.conf" /etc/php/${PHP_VERSION}/fpm/pool.available/
-            ln -sf "/etc/php/${PHP_VERSION}/fpm/pool.available/eye.conf" "/etc/php/${PHP_VERSION}/fpm/pool.d/eye.conf"
-        fi
-    fi
-
-    $SERVICE_MANAGER enable "$APACHE_SERVICE"
-    $SERVICE_MANAGER restart "$APACHE_SERVICE"
-
-    $SERVICE_MANAGER enable php${PHP_VERSION}-fpm.service
-    $SERVICE_MANAGER restart php${PHP_VERSION}-fpm.service
-
-    # Check configuration
-    if [[ "$OS_FAMILY" == "alt" ]]; then
-        httpd2 -t 2>/dev/null && print_info "Конфигурация Apache (httpd2) корректна" || print_warn "Проверьте конфигурацию Apache "
-        else
-        apache2ctl -t 2>/dev/null && print_info "Конфигурация Apache (httpd2) корректна" || print_warn "Проверьте конфигурацию Apache "
-    fi
-}
-
-
-# Настройка cron и logrotate
-setup_cron_logrotate() {
-    print_step "Настройка cron и logrotate"
-    
-    # Cron
-    if [[ -f "/opt/Eye/docs/cron/stat" ]]; then
-        cp /opt/Eye/docs/cron/stat /etc/cron.d/eye
-        chmod 644 /etc/cron.d/eye
-        print_info "Cron задача добавлена: /etc/cron.d/eye"
-    fi
-    
-    # Logrotate
-    if [[ -f "/opt/Eye/docs/logrotate/dnsmasq" ]]; then
-        cp /opt/Eye/docs/logrotate/dnsmasq /etc/logrotate.d/dnsmasq-eye
-    fi
-    
-    if [[ -f "/opt/Eye/docs/logrotate/scripts" ]]; then
-        cp /opt/Eye/docs/logrotate/scripts /etc/logrotate.d/eye-scripts
-    fi
-    
-    print_info "Настройка cron и logrotate завершена"
-    print_warn "Отредактируйте /etc/cron.d/eye для включения нужных скриптов"
-}
-
-# Настройка DHCP сервера (dnsmasq)
-setup_dhcp_server() {
-    print_step "Настройка DHCP сервера"
-    
-    read -p "Настроить DHCP сервер (dnsmasq)? (y/n): " -n 1 -r
-    echo
-    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
-        return 0
-    fi
-    
-    # Резервная копия конфигурации
-    if [[ -f "/etc/dnsmasq.conf" ]]; then
-        cp /etc/dnsmasq.conf /etc/dnsmasq.conf.backup
-    fi
-    
-    # Копирование конфигурации из Eye
-    if [[ -f "/opt/Eye/docs/addons/dnsmasq.conf" ]]; then
-        cat /opt/Eye/docs/addons/dnsmasq.conf > /etc/dnsmasq.conf
-    fi
-    
-    # Копирование systemd сервисов
-    if [[ -f "/opt/Eye/docs/systemd/dhcp-log.service" ]]; then
-        cp /opt/Eye/docs/systemd/dhcp-log.service /etc/systemd/system/
-    fi
-    
-    if [[ -f "/opt/Eye/docs/systemd/dhcp-log-truncate.service" ]]; then
-        cp /opt/Eye/docs/systemd/dhcp-log-truncate.service /etc/systemd/system/
-    fi
-    
-    # Включение сервисов
-    $SERVICE_MANAGER enable dnsmasq
-    $SERVICE_MANAGER start dnsmasq
-    
-    print_info "DHCP сервер настроен"
-    print_warn "Отредактируйте /etc/dnsmasq.conf под вашу сеть"
-}
-
-# Настройка syslog-ng
-setup_syslog() {
-    print_step "Настройка syslog-ng"
-    
-    read -p "Настроить удаленный сбор логов (syslog-ng)? (y/n): " -n 1 -r
-    echo
-    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
-        return 0
-    fi
-    
-    # Создаем резервную копию основного конфига
-    if [[ -f "/etc/syslog-ng/syslog-ng.conf" ]]; then
-        cp /etc/syslog-ng/syslog-ng.conf /etc/syslog-ng/syslog-ng.conf.backup
-        print_info "Создана резервная копия /etc/syslog-ng/syslog-ng.conf"
-    fi
-    
-    # Копируем дополнительный конфиг для Eye
-    if [[ -f "/opt/Eye/docs/syslog-ng/eye.conf" ]]; then
-        mkdir -p /etc/syslog-ng/conf.d
-        cp /opt/Eye/docs/syslog-ng/eye.conf /etc/syslog-ng/conf.d/eye.conf
-        
-        # Проверяем, есть ли уже включение conf.d в основном конфиге
-        if [[ -f "/etc/syslog-ng/syslog-ng.conf" ]]; then
-            if ! grep -q "@include.*conf\.d" /etc/syslog-ng/syslog-ng.conf && \
-               ! grep -q "include.*conf\.d" /etc/syslog-ng/syslog-ng.conf; then
-                # Добавляем включение conf.d директории в конец файла
-                echo "" >> /etc/syslog-ng/syslog-ng.conf
-                echo "# Include Eye monitoring configuration" >> /etc/syslog-ng/syslog-ng.conf
-                echo "@include \"/etc/syslog-ng/conf.d/*.conf\"" >> /etc/syslog-ng/syslog-ng.conf
-                print_info "Добавлено включение conf.d директории в syslog-ng.conf"
-            fi
-        fi
-        print_info "Конфигурационный файл eye.conf скопирован в /etc/syslog-ng/conf.d/"
-    else
-        print_warn "Файл конфигурации eye.conf не найден в /opt/Eye/docs/syslog-ng/"
-    fi
-    
-# блок options
-syslogng_options='options {
-    chain_hostnames(off);
-    flush_lines(0);
-    use_dns(no);
-    use_fqdn(no);
-    dns_cache(no);
-    owner("root");
-    group("adm");
-    perm(0640);
-    stats_freq(0);
-    time_reopen(10);
-    log_fifo_size(1000);
-    create_dirs(yes);
-    keep_hostname(no);
-};'
-
-    # Проверяем наличие options в основном конфиге
-    if [[ -f "/etc/syslog-ng/syslog-ng.conf" ]]; then
-        if ! grep -q "^options\s*{" /etc/syslog-ng/syslog-ng.conf; then
-            # Добавляем блок options если его нет
-
-            if grep -q "^@version:" /etc/syslog-ng/syslog-ng.conf; then
-                # Вставляем после строки @version:
-                sed -i "/^@version:/a\\$syslogng_options" /etc/syslog-ng/syslog-ng.conf
-            else
-                # Вставляем в начало файла
-                sed -i "1i\\$syslogng_options" /etc/syslog-ng/syslog-ng.conf
-            fi
-            print_info "Добавлен блок options в syslog-ng.conf"
-        else
-            # Проверяем наличие необходимых параметров в существующем блоке options
-            local missing_params=()
-            
-            if ! grep -q "time_reopen\s*(.*)" /etc/syslog-ng/syslog-ng.conf; then
-                missing_params+=("time_reopen(10)")
-            fi
-            
-            if ! grep -q "log_fifo_size\s*(.*)" /etc/syslog-ng/syslog-ng.conf; then
-                missing_params+=("log_fifo_size(1000)")
-            fi
-            
-            if ! grep -q "chain_hostnames\s*(.*)" /etc/syslog-ng/syslog-ng.conf; then
-                missing_params+=("chain_hostnames(off)")
-            fi
-            
-            if ! grep -q "create_dirs\s*(.*)" /etc/syslog-ng/syslog-ng.conf; then
-                missing_params+=("create_dirs(yes)")
-            fi
-            
-            if ! grep -q "keep_hostname\s*(.*)" /etc/syslog-ng/syslog-ng.conf; then
-                missing_params+=("keep_hostname(no)")
-            fi
-            
-            # Добавляем недостающие параметры
-            if [[ ${#missing_params[@]} -gt 0 ]]; then
-                # Находим блок options и добавляем параметры в конец блока
-                sed -i '/^options\s*{/,/^}/ {
-                    /^}/ i\    '"$(IFS='; '; echo "${missing_params[*]}")"';
-                }' /etc/syslog-ng/syslog-ng.conf
-                print_info "Добавлены параметры в блок options: ${missing_params[*]}"
-            fi
-        fi
-    fi
-    
-    # Копирование systemd сервиса для обработки логов Eye
-    if [[ -f "/opt/Eye/docs/systemd/syslog-stat.service" ]]; then
-        cp /opt/Eye/docs/systemd/syslog-stat.service /etc/systemd/system/
-        chmod 644 /etc/systemd/system/syslog-stat.service
-        print_info "Сервис syslog-stat скопирован"
-    fi
-    
-    # Создаем директорию для логов если её нет
-    mkdir -p /opt/Eye/scripts/log
-    chown eye:eye /opt/Eye/scripts/log
-    chmod 770 /opt/Eye/scripts/log
-    
-    # Включение и запуск сервисов
-    $SERVICE_MANAGER daemon-reload
-    
-    if $SERVICE_MANAGER enable syslog-ng; then
-        print_info "Сервис syslog-ng включен в автозагрузку"
-    else
-        print_warn "Не удалось включить syslog-ng в автозагрузку"
-    fi
-    
-    if $SERVICE_MANAGER restart syslog-ng; then
-        print_info "Сервис syslog-ng перезапущен"
-    else
-        print_warn "Не удалось перезапустить syslog-ng"
-    fi
-    
-    if [[ -f "/etc/systemd/system/syslog-stat.service" ]]; then
-        if $SERVICE_MANAGER enable syslog-stat; then
-            print_info "Сервис syslog-stat включен в автозагрузку"
-        else
-            print_warn "Не удалось включить syslog-stat в автозагрузку"
-        fi
-        
-        if $SERVICE_MANAGER start syslog-stat; then
-            print_info "Сервис syslog-stat запущен"
-        else
-            print_warn "Не удалось запустить syslog-stat"
-        fi
-    fi
-    
-    # Проверка конфигурации syslog-ng
-    if command -v syslog-ng &> /dev/null; then
-        if syslog-ng --syntax-only; then
-            print_info "Конфигурация syslog-ng корректна"
-        else
-            print_error "Ошибка в конфигурации syslog-ng"
-            print_warn "Проверьте файлы: /etc/syslog-ng/syslog-ng.conf и /etc/syslog-ng/conf.d/eye.conf"
-        fi
-    fi
-    
-    print_info "Настройка syslog-ng завершена"
-    print_info "Для приема логов с устройств настройте их на отправку на IP: $(hostname -f)"
-}
-
-# Настройка дополнительных сервисов
-setup_additional_services() {
-    print_step "Настройка дополнительных сервисов"
-    
-    # Сервис stat-sync
-    if [[ -f "/opt/Eye/docs/systemd/stat-sync.service" ]]; then
-        cp /opt/Eye/docs/systemd/stat-sync.service /etc/systemd/system/
-        $SERVICE_MANAGER enable stat-sync.service
-        print_info "Сервис stat-sync включен"
-    fi
-    
-    # Сервис eye-statd (NetFlow)
-    if [[ -f "/opt/Eye/docs/systemd/eye-statd.service" ]]; then
-        cp /opt/Eye/docs/systemd/eye-statd.service /etc/systemd/system/
-        $SERVICE_MANAGER enable eye-statd.service
-        print_info "Сервис eye-statd (NetFlow) включен"
-    fi
-    
-    # Настройка DHCP
-    setup_dhcp_server
-    
-    # Настройка syslog
-    setup_syslog
-}
-
-# Импорт базы MAC-адресов
-import_mac_database() {
-    print_step "Импорт базы MAC-адресов"
-    
-    if [[ -f "/opt/Eye/scripts/utils/mac-oids/download-macs.sh" ]]; then
-        cd /opt/Eye/scripts/utils/mac-oids/
-
-        # Загрузка базы MAC
-        print_info "Загрузка базы MAC-адресов..."
-        bash download-macs.sh
-        
-        # Обновление вендоров
-        if [[ -f "update-mac-vendors.pl" ]]; then
-            print_info "Обновление информации о вендорах..."
-            perl update-mac-vendors.pl
-        fi
-        
-        cd - >/dev/null
-    else
-        print_warn "Скрипты для импорта MAC-адресов не найдены"
-    fi
-}
-
-# Финальные инструкции
-show_final_instructions() {
-    echo ""
-    echo -e "${GREEN}===========================================${NC}"
-    echo -e "${GREEN}   УСТАНОВКА ЗАВЕРШЕНА УСПЕШНО!          ${NC}"
-    echo -e "${GREEN}===========================================${NC}"
-    echo ""
-    echo "СИСТЕМНАЯ ИНФОРМАЦИЯ:"
-    echo "  Дистрибутив:      $OS_NAME"
-    echo "  Версия:           $OS_VERSION"
-    echo "  Пользователь:     eye"
-    echo "  Директория:       /opt/Eye"
-    echo ""
-    echo "ДЛЯ ЗАВЕРШЕНИЯ НАСТРОЙКИ ВЫПОЛНИТЕ:"
-    echo ""
-    echo "1. Настройте безопасность MySQL:"
-    echo "   mysql_secure_installation"
-    echo ""
-    echo "2. Проверьте и отредактируйте конфигурационные файлы:"
-    echo "   /opt/Eye/html/cfg/config.php"
-    echo "   /opt/Eye/scripts/cfg/config"
-    echo ""
-    if [[ -f "/root/eye_mysql_password.txt" ]]; then
-        echo "3. Пароль MySQL пользователя 'stat' сохранен в:"
-        echo "   /root/eye_mysql_password.txt"
-        echo ""
-    fi
-    echo "4. Настройте cron задачи:"
-    echo "   nano /etc/cron.d/eye"
-    echo "   Раскомментируйте нужные скрипты"
-    echo ""
-    echo "5. Настройте при необходимости:"
-    echo "   - DHCP: /etc/dnsmasq.conf"
-    echo "   - NetFlow: настройте на сетевых устройствах"
-    echo ""
-    echo "6. ДОСТУП К ВЕБ-ИНТЕРФЕЙСУ:"
-    echo "   URL:      http://$(hostname -f)/"
-    echo "   Админка:  http://$(hostname -f)/admin/"
-    echo "   Логин:    admin"
-    echo "   Пароль:   admin"
-    echo ""
-    echo -e "${RED}ВАЖНО:${NC}"
-    echo "   - СМЕНИТЕ пароль администратора и API ключ!"
-    echo "   - Настройте пользователей и сети в веб-интерфейсе"
-    echo ""
-    echo -e "${GREEN}===========================================${NC}"
-    echo ""
-}
-
-# Главная функция
-main() {
-    clear
-    echo -e "${GREEN}===========================================${NC}"
-    echo -e "${GREEN}   Установка Eye Monitoring System        ${NC}"
-    echo -e "${GREEN}   для ALT Linux/Debian/Ubuntu            ${NC}"
-    echo -e "${GREEN}===========================================${NC}"
-    echo ""
-    
-    # Глобальные переменные
-    MYSQL_PASSWORD=""
-    
-    # Выполнение шагов установки
-    check_root
-    detect_distro
-    update_system
-    install_packages
-    create_user_group
-    install_source_code
-    download_additional_scripts
-    setup_mysql
-    setup_configs
-    setup_apache_php
-    setup_cron_logrotate
-    setup_additional_services
-    import_mac_database
-    
-    show_final_instructions
-}
-
-# Обработка аргументов командной строки
-case "$1" in
-    --help|-h)
-        echo "Использование: $0 [опции]"
-        echo ""
-        echo "Опции:"
-        echo "  --help, -h     Показать эту справку"
-        echo "  --auto         Автоматическая установка (минимальное взаимодействие)"
-        echo ""
-        echo "Поддерживаемые дистрибутивы:"
-        echo "  - ALT Linux 11.1+"
-        echo "  - Debian 11+"
-        echo "  - Ubuntu 20.04+"
-        echo ""
-        exit 0
-        ;;
-    --auto)
-        # Режим с минимальным взаимодействием
-        print_warn "Автоматический режим. Все подтверждения будут приняты как 'yes'"
-        export DEBIAN_FRONTEND=noninteractive
-        ;;
-    *)
-        # Интерактивный режим по умолчанию
-        ;;
-esac
-
-# Запуск установки
-main "$@"
-
-# Выход с кодом успеха
-exit 0

+ 406 - 90
install-eye.en.sh → install-eye.sh

@@ -1,6 +1,6 @@
 #!/bin/bash
-# Eye Installation Script for ALT Linux/Debian/Ubuntu
-# Version: 2.0
+# Eye Installation Script for ALT Linux/Debian/Ubuntu with PostgreSQL support
+# Version: 2.1
 
 set -e
 
@@ -11,6 +11,14 @@ YELLOW='\033[1;33m'
 BLUE='\033[0;34m'
 NC='\033[0m' # No Color
 
+# Global variables
+MYSQL_PASSWORD=""
+POSTGRES_PASSWORD=""
+NA
+DB_TYPE="mysql"  # Default database type
+DB_NAME="stat"
+DB_USER="stat"
+
 # Output functions
 print_info() {
     echo -e "${GREEN}[INFO]${NC} $1"
@@ -76,6 +84,78 @@ detect_distro() {
     fi
 }
 
+select_language_with_auto() {
+    print_step "Select Installation Language"
+    
+    # Проверка автоматического режима
+    if [[ "$AUTO_MODE" == "true" ]]; then
+        EYE_LANG="english"
+        EYE_LANG_SHORT="en"
+        print_info "Auto mode: English language selected by default"
+        return 0
+    fi
+    
+    echo "Available languages:"
+    echo "1) English"
+    echo "2) Russian (default)"
+    echo ""
+
+    while true; do
+        read -p "Select language (1 or 2) [2]: " lang_choice
+        
+        # Если пустой ввод - по умолчанию английский
+        if [[ -z "$lang_choice" ]]; then
+            lang_choice="2"
+        fi
+        
+        # Обработка ввода (приводим к нижнему регистру)
+        lang_choice_lower=$(echo "$lang_choice" | tr '[:upper:]' '[:lower:]')
+        
+        case $lang_choice_lower in
+            1|english|en|eng|анг|английский)
+                EYE_LANG="english"
+                EYE_LANG_SHORT="en"
+                print_info "Selected English language"
+                break
+                ;;
+            2|russian|ru|rus|ру|русский)
+                EYE_LANG="russian"
+                EYE_LANG_SHORT="ru"
+                print_info "Selected Russian language (Русский)"
+                break
+                ;;
+            *)
+                print_error "Invalid choice: '$lang_choice'"
+                print_warn "Available options: 1 (English), 2 (Russian)"
+                print_warn "You can also type: english, en, russian, ru"
+                ;;
+        esac
+    done
+}
+
+# Ask user for database type
+select_database_type() {
+    print_step "Select Database Type"
+    
+    echo "Available database types:"
+    echo "1) MySQL/MariaDB (default)"
+    echo "2) PostgreSQL"
+    echo ""
+    
+    read -p "Select database type (1 or 2) [1]: " db_choice
+    
+    case $db_choice in
+        2|postgres|postgresql|pgsql)
+            DB_TYPE="postgresql"
+            print_info "Selected PostgreSQL"
+            ;;
+        *)
+            DB_TYPE="mysql"
+            print_info "Selected MySQL/MariaDB"
+            ;;
+    esac
+}
+
 # Install dependencies for ALT Linux
 install_deps_altlinux() {
     print_step "Installing dependencies for ALT Linux"
@@ -86,27 +166,51 @@ install_deps_altlinux() {
     # General utilities
     apt-get install -y git xxd wget fping hwdata
 
-    # Database
-    apt-get install -y mariadb-server mariadb-client
+    # Database installation based on selected type
+    if [[ "$DB_TYPE" == "postgresql" ]]; then
+        apt-get install -y postgresql postgresql-client
+    else
+        apt-get install -y mariadb-server mariadb-client
+    fi
 
     # Web server and PHP
-    apt-get install -y apache2 \
-        php8.2 php8.2-mysqlnd php8.2-intl php8.2-mbstring \
-        pear-Mail php8.2-snmp php8.2-zip \
-        php8.2-pgsql php8.2-mysqlnd php8.2-pdo_mysql php8.2-mysqlnd-mysqli \
-        php8.2-fpm-fcgi apache2-mod_fcgid
+    if [[ "$DB_TYPE" == "postgresql" ]]; then
+        apt-get install -y apache2 \
+            php8.2 php8.2-pgsql php8.2-pdo-pgsql php8.2-intl php8.2-mbstring \
+            pear-Mail php8.2-snmp php8.2-zip \
+            php8.2-fpm-fcgi apache2-mod_fcgid
+    else
+        apt-get install -y apache2 \
+            php8.2 php8.2-mysqlnd php8.2-intl php8.2-mbstring \
+            pear-Mail php8.2-snmp php8.2-zip \
+            php8.2-pgsql php8.2-mysqlnd php8.2-pdo_mysql php8.2-mysqlnd-mysqli \
+            php8.2-fpm-fcgi apache2-mod_fcgid
+    fi
 
     # Perl modules
-    apt-get install -y perl perl-Net-Patricia perl-NetAddr-IP \
-        perl-Config-Tiny perl-Net-DNS perl-DateTime perl-Net-Ping \
-        perl-Net-Netmask perl-Text-Iconv perl-Net-SNMP \
-        perl-Net-Telnet perl-DBI perl-DBD-mysql perl-DBD-Pg \
-        perl-Parallel-ForkManager perl-Proc-Daemon \
-        perl-DateTime-Format-DateParse \
-        perl-Net-OpenSSH perl-File-Tail perl-Crypt-Rijndael \
-        perl-Crypt-CBC perl-CryptX perl-Crypt-DES \
-        perl-File-Path-Tiny perl-Expect \
-        perl-Proc-ProcessTable
+    if [[ "$DB_TYPE" == "postgresql" ]]; then
+        apt-get install -y perl perl-Net-Patricia perl-NetAddr-IP \
+            perl-Config-Tiny perl-Net-DNS perl-DateTime perl-Net-Ping \
+            perl-Net-Netmask perl-Text-Iconv perl-Net-SNMP \
+            perl-Net-Telnet perl-DBI perl-DBD-Pg \
+            perl-Parallel-ForkManager perl-Proc-Daemon \
+            perl-DateTime-Format-DateParse \
+            perl-Net-OpenSSH perl-File-Tail perl-Crypt-Rijndael \
+            perl-Crypt-CBC perl-CryptX perl-Crypt-DES \
+            perl-File-Path-Tiny perl-Expect \
+            perl-Proc-ProcessTable
+    else
+        apt-get install -y perl perl-Net-Patricia perl-NetAddr-IP \
+            perl-Config-Tiny perl-Net-DNS perl-DateTime perl-Net-Ping \
+            perl-Net-Netmask perl-Text-Iconv perl-Net-SNMP \
+            perl-Net-Telnet perl-DBI perl-DBD-mysql perl-DBD-Pg \
+            perl-Parallel-ForkManager perl-Proc-Daemon \
+            perl-DateTime-Format-DateParse \
+            perl-Net-OpenSSH perl-File-Tail perl-Crypt-Rijndael \
+            perl-Crypt-CBC perl-CryptX perl-Crypt-DES \
+            perl-File-Path-Tiny perl-Expect \
+            perl-Proc-ProcessTable
+    fi
 
     # Additional services
     apt-get install -y dnsmasq syslog-ng syslog-ng-journal
@@ -130,25 +234,48 @@ install_deps_debian() {
     # General utilities
     apt-get install -y git xxd bsdmainutils pwgen wget fping ieee-data
 
-    # Database
-    apt-get install -y mariadb-server mariadb-client
+    # Database installation based on selected type
+    if [[ "$DB_TYPE" == "postgresql" ]]; then
+        apt-get install -y postgresql postgresql-client
+    else
+        apt-get install -y mariadb-server mariadb-client
+    fi
 
     # Web server and PHP
-    apt-get install -y apache2 \
-        php php-mysql php-bcmath php-intl php-mbstring \
-        php-date php-mail php-snmp php-zip \
-        php-db php-pgsql php-fpm libapache2-mod-fcgid
+    if [[ "$DB_TYPE" == "postgresql" ]]; then
+        apt-get install -y apache2 \
+            php php-pgsql php-bcmath php-intl php-mbstring \
+            php-date php-mail php-snmp php-zip \
+            php-db php-fpm libapache2-mod-fcgid
+    else
+        apt-get install -y apache2 \
+            php php-mysql php-bcmath php-intl php-mbstring \
+            php-date php-mail php-snmp php-zip \
+            php-db php-pgsql php-fpm libapache2-mod-fcgid
+    fi
 
     # Perl modules
-    apt-get install -y perl libnet-patricia-perl libnetaddr-ip-perl \
-        libconfig-tiny-perl libnet-dns-perl libdatetime-perl \
-        libnet-netmask-perl libtext-iconv-perl libnet-snmp-perl \
-        libnet-telnet-perl libdbi-perl libdbd-mysql-perl \
-        libparallel-forkmanager-perl libproc-daemon-perl \
-        libdatetime-format-dateparse-perl \
-        libnet-openssh-perl libfile-tail-perl libcrypt-rijndael-perl \
-        libcrypt-cbc-perl libcryptx-perl libdbd-pg-perl \
-        libfile-path-tiny-perl libexpect-perl libcrypt-des-perl
+    if [[ "$DB_TYPE" == "postgresql" ]]; then
+        apt-get install -y perl libnet-patricia-perl libnetaddr-ip-perl \
+            libconfig-tiny-perl libnet-dns-perl libdatetime-perl \
+            libnet-netmask-perl libtext-iconv-perl libnet-snmp-perl \
+            libnet-telnet-perl libdbi-perl \
+            libparallel-forkmanager-perl libproc-daemon-perl \
+            libdatetime-format-dateparse-perl \
+            libnet-openssh-perl libfile-tail-perl libcrypt-rijndael-perl \
+            libcrypt-cbc-perl libcryptx-perl libdbd-pg-perl \
+            libfile-path-tiny-perl libexpect-perl libcrypt-des-perl
+    else
+        apt-get install -y perl libnet-patricia-perl libnetaddr-ip-perl \
+            libconfig-tiny-perl libnet-dns-perl libdatetime-perl \
+            libnet-netmask-perl libtext-iconv-perl libnet-snmp-perl \
+            libnet-telnet-perl libdbi-perl libdbd-mysql-perl \
+            libparallel-forkmanager-perl libproc-daemon-perl \
+            libdatetime-format-dateparse-perl \
+            libnet-openssh-perl libfile-tail-perl libcrypt-rijndael-perl \
+            libcrypt-cbc-perl libcryptx-perl libdbd-pg-perl \
+            libfile-path-tiny-perl libexpect-perl libcrypt-des-perl
+    fi
 
     # Additional services
     apt-get install -y dnsmasq syslog-ng
@@ -428,10 +555,10 @@ setup_mysql() {
 
     # Start and enable service
     $SERVICE_MANAGER enable mariadb 2>/dev/null || \
-        $SERVICE_MANAGER enable mysql 2>/dev/null || true
+    $SERVICE_MANAGER enable mysql 2>/dev/null || true
 
     $SERVICE_MANAGER start mariadb 2>/dev/null || \
-        $SERVICE_MANAGER start mysql 2>/dev/null || true
+    $SERVICE_MANAGER start mysql 2>/dev/null || true
 
     # Check MySQL access
     if ! command -v mysql &> /dev/null; then
@@ -475,8 +602,8 @@ setup_mysql() {
     echo
     if [[ ! $REPLY =~ ^[Yy]$ ]]; then
         print_warn "Database creation skipped. Create manually:"
-        print_warn "  mysql -u root -p < /opt/Eye/docs/mysql/create_db.sql"
-        print_warn "  mysql -u root -p stat < /opt/Eye/docs/mysql/latest-mysql-en.sql"
+        print_warn "  mysql -u root -p < ${SQL_CREATE_FILE}"
+        print_warn "  mysql -u root -p stat < ${SQL_DATA_FILE}"
         if [[ -f "$MYSQL_CNF_FILE" ]]; then
             rm -f "$MYSQL_CNF_FILE"
         fi
@@ -490,7 +617,7 @@ setup_mysql() {
     print_info "Importing database structure..."
 
     # Import main SQL file
-    mysql $MYSQL_OPT < /opt/Eye/docs/mysql/create_db.sql
+    mysql $MYSQL_OPT < ${SQL_CREATE_FILE}
 
     if [[ $? -ne 0 ]]; then
         print_error "Error importing create_db.sql"
@@ -504,10 +631,10 @@ setup_mysql() {
 
     # Import data
     print_info "Importing initial data..."
-    mysql $MYSQL_OPT stat < /opt/Eye/docs/mysql/latest-mysql-en.sql
+    mysql $MYSQL_OPT stat < ${SQL_DATA_FILE}
 
     if [[ $? -ne 0 ]]; then
-        print_warn "Error importing latest-mysql-en.sql (data may already exist)"
+        print_warn "Error importing data.sql (data may already exist)"
     else
         print_info "Initial data imported"
     fi
@@ -545,6 +672,117 @@ EOF
     return 0
 }
 
+# Configure PostgreSQL
+setup_postgresql() {
+    print_step "Configuring PostgreSQL"
+
+    # Start and enable service
+    $SERVICE_MANAGER enable postgresql
+    $SERVICE_MANAGER start postgresql
+
+    # Check PostgreSQL access
+    if ! command -v psql &> /dev/null; then
+        print_error "PostgreSQL client not installed"
+        return 1
+    fi
+
+    # Switch to postgres user to execute commands
+    read -p "Create database and user for Eye? (y/n): " -n 1 -r
+    echo
+    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
+        print_warn "Database creation skipped. Create manually as postgres user:"
+        print_warn "  sudo -u postgres psql -f ${SQL_CREATE_FILE}"
+        print_warn "  sudo -u postgres psql -d stat -f ${SQL_DATA_FILE}"
+        return 0
+    fi
+
+    # Generate password for stat user
+    DB_PASSWORD=$(pwgen 16 1)
+    POSTGRES_PASSWORD=$DB_PASSWORD
+
+    print_info "Importing database structure..."
+
+    # Import main SQL file as postgres user
+    sudo -u postgres psql -f ${SQL_CREATE_FILE}
+
+    if [[ $? -ne 0 ]]; then
+        print_error "Error importing create_db.sql"
+        return 1
+    fi
+
+    print_info "Database structure imported"
+
+    # Set password for stat user
+    print_info "Setting password for user 'stat'..."
+    sudo -u postgres psql -c "ALTER USER stat WITH PASSWORD '$DB_PASSWORD';"
+
+    # Import data
+    print_info "Importing initial data..."
+    sudo -u postgres psql -d stat -f ${SQL_DATA_FILE}
+
+    if [[ $? -ne 0 ]]; then
+        print_warn "Error importing data.sql (data may already exist)"
+    else
+        print_info "Initial data imported"
+    fi
+
+    # Configure PostgreSQL for MD5 authentication
+    local pg_hba_file="/etc/postgresql/$(ls /etc/postgresql/ | head -1)/main/pg_hba.conf"
+    if [[ -f "$pg_hba_file" ]]; then
+        # Backup original
+        cp "$pg_hba_file" "${pg_hba_file}.backup"
+        
+        # Add local md5 authentication if not present
+        if ! grep -q "local.*stat.*md5" "$pg_hba_file"; then
+            echo "local   stat            stat                                    md5" >> "$pg_hba_file"
+            print_info "Added MD5 authentication for stat user in pg_hba.conf"
+        fi
+    fi
+
+    # Restart PostgreSQL to apply changes
+    $SERVICE_MANAGER restart postgresql
+
+    # Save password information
+    echo "PostgreSQL 'stat' user password: $DB_PASSWORD" > /root/eye_postgres_password.txt
+    chmod 600 /root/eye_postgres_password.txt
+
+    print_info "User 'stat' password: $DB_PASSWORD"
+    print_warn "Password saved in /root/eye_postgres_password.txt"
+
+    return 0
+}
+
+# Configure database based on selected type
+setup_database() {
+
+    # Выбор правильных SQL файлов для импорта данных
+    if [[ "$DB_TYPE" == "mysql" ]]; then
+        if [[ "$EYE_LANG" == "russian" && -d "/opt/Eye/docs/databases/mysql/ru" ]]; then
+            SQL_DATA_FILE="/opt/Eye/docs/databases/mysql/ru/data.sql"
+            SQL_CREATE_FILE="/opt/Eye/docs/databases/mysql/ru/create_db.sql"
+        else
+            SQL_DATA_FILE="/opt/Eye/docs/databases/mysql/en/data.sql"
+            SQL_CREATE_FILE="/opt/Eye/docs/databases/mysql/en/create_db.sql"
+        fi
+    elif [[ "$DB_TYPE" == "postgresql" ]]; then
+        if [[ "$EYE_LANG" == "russian" && -d "/opt/Eye/docs/databases/postgres/ru" ]]; then
+            SQL_DATA_FILE="/opt/Eye/docs/databases/postgres/ru/data.sql"
+            SQL_CREATE_FILE="/opt/Eye/docs/databases/postgres/ru/create_db.sql"
+        else
+            SQL_DATA_FILE="/opt/Eye/docs/databases/postgres/en/data.sql"
+            SQL_CREATE_FILE="/opt/Eye/docs/databases/postgres/en/create_db.sql"
+        fi
+    fi
+    
+    print_info "Using SQL files for $EYE_LANG language"
+
+    if [[ "$DB_TYPE" == "postgresql" ]]; then
+        setup_postgresql
+    else
+        setup_mysql
+    fi
+}
+
 # Configure configuration files
 setup_configs() {
     print_step "Configuring configuration files"
@@ -572,19 +810,29 @@ setup_configs() {
     if [[ -f "/opt/Eye/html/cfg/config.sample.php" ]]; then
         cp /opt/Eye/html/cfg/config.sample.php /opt/Eye/html/cfg/config.php
 
-        # Update database password
-        if [[ -n "$MYSQL_PASSWORD" ]]; then
-            sed -i "s/define(\"DB_PASS\",\"[^\"]*\");/define(\"DB_PASS\",\"$MYSQL_PASSWORD\");/" /opt/Eye/html/cfg/config.php
+        # Update database configuration based on type
+        if [[ "$DB_TYPE" == "postgresql" ]]; then
+            # PostgreSQL configuration
+            if [[ -n "$POSTGRES_PASSWORD" ]]; then
+                sed -i "s/define(\"DB_PASS\",\"[^\"]*\");/define(\"DB_PASS\",\"$POSTGRES_PASSWORD\");/" /opt/Eye/html/cfg/config.php
+            fi
+            sed -i "s/define(\"DB_TYPE\",\"[^\"]*\");/define(\"DB_TYPE\",\"postgresql\");/" /opt/Eye/html/cfg/config.php
+            sed -i "s/define(\"DB_HOST\",\"[^\"]*\");/define(\"DB_HOST\",\"localhost\");/" /opt/Eye/html/cfg/config.php
+            sed -i "s/define(\"DB_PORT\",\"[^\"]*\");/define(\"DB_PORT\",\"5432\");/" /opt/Eye/html/cfg/config.php
+            sed -i "s/define(\"DB_NAME\",\"[^\"]*\");/define(\"DB_NAME\",\"stat\");/" /opt/Eye/html/cfg/config.php
+            sed -i "s/define(\"DB_USER\",\"[^\"]*\");/define(\"DB_USER\",\"stat\");/" /opt/Eye/html/cfg/config.php
+        else
+            # MySQL configuration
+            if [[ -n "$MYSQL_PASSWORD" ]]; then
+                sed -i "s/define(\"DB_PASS\",\"[^\"]*\");/define(\"DB_PASS\",\"$MYSQL_PASSWORD\");/" /opt/Eye/html/cfg/config.php
+            fi
+            sed -i "s/define(\"DB_TYPE\",\"[^\"]*\");/define(\"DB_TYPE\",\"mysql\");/" /opt/Eye/html/cfg/config.php
+            sed -i "s/define(\"DB_HOST\",\"[^\"]*\");/define(\"DB_HOST\",\"localhost\");/" /opt/Eye/html/cfg/config.php
+            sed -i "s/define(\"DB_PORT\",\"[^\"]*\");/define(\"DB_PORT\",\"3306\");/" /opt/Eye/html/cfg/config.php
             sed -i "s/define(\"DB_NAME\",\"[^\"]*\");/define(\"DB_NAME\",\"stat\");/" /opt/Eye/html/cfg/config.php
             sed -i "s/define(\"DB_USER\",\"[^\"]*\");/define(\"DB_USER\",\"stat\");/" /opt/Eye/html/cfg/config.php
         fi
 
-        # Replacing the Russian locale with the English
-        sed -i "s/setlocale(LC_ALL, 'ru_RU\.UTF8');/setlocale(LC_ALL, 'en_US.UTF-8');/g" /opt/Eye/html/cfg/config.php
-
-        # Replacing HTML_LANG with English
-        sed -i "s/define(\"HTML_LANG\",\"russian\");/define(\"HTML_LANG\",\"english\");/g" /opt/Eye/html/cfg/config.php
-
         # Update encryption key
         sed -i "s/ENCRYPTION_KEY\",\"[^\"]*\"/ENCRYPTION_KEY\",\"$ENC_PASSWORD\"/" /opt/Eye/html/cfg/config.php
         sed -i "s/ENCRYPTION_KEY','[^']*'/ENCRYPTION_KEY','$ENC_PASSWORD'/" /opt/Eye/html/cfg/config.php
@@ -600,19 +848,40 @@ setup_configs() {
     if [[ -f "/opt/Eye/scripts/cfg/config.sample" ]]; then
         cp /opt/Eye/scripts/cfg/config.sample /opt/Eye/scripts/cfg/config
 
-        # Update database password
-        if [[ -n "$MYSQL_PASSWORD" ]]; then
-            sed -i "s/^DBPASS=.*/DBPASS=$MYSQL_PASSWORD/" /opt/Eye/scripts/cfg/config
-            sed -i "s/DBPASS=mysql_password/DBPASS=$MYSQL_PASSWORD/" /opt/Eye/scripts/cfg/config
+        # Update database configuration based on type
+        if [[ "$DB_TYPE" == "postgresql" ]]; then
+            # PostgreSQL configuration
+            sed -i "s/^DBTYPE=.*/DBTYPE=postgresql/" /opt/Eye/scripts/cfg/config
+            sed -i "s/DBTYPE=db_type/DBTYPE=postgresql/" /opt/Eye/scripts/cfg/config
+            
+            # Update database connection settings
+            sed -i "s/^DBHOST=.*/DBHOST=localhost/" /opt/Eye/scripts/cfg/config
+            sed -i "s/^DBPORT=.*/DBPORT=5432/" /opt/Eye/scripts/cfg/config
+            
+            if [[ -n "$POSTGRES_PASSWORD" ]]; then
+                sed -i "s/^DBPASS=.*/DBPASS=$POSTGRES_PASSWORD/" /opt/Eye/scripts/cfg/config
+                sed -i "s/DBPASS=db_password/DBPASS=$POSTGRES_PASSWORD/" /opt/Eye/scripts/cfg/config
+            fi
+        else
+            # MySQL configuration
+            sed -i "s/^DBTYPE=.*/DBTYPE=mysql/" /opt/Eye/scripts/cfg/config
+            sed -i "s/DBTYPE=db_type/DBTYPE=mysql/" /opt/Eye/scripts/cfg/config
+            
+            # Update database connection settings
+            sed -i "s/^DBHOST=.*/DBHOST=localhost/" /opt/Eye/scripts/cfg/config
+            sed -i "s/^DBPORT=.*/DBPORT=3306/" /opt/Eye/scripts/cfg/config
+            
+            if [[ -n "$MYSQL_PASSWORD" ]]; then
+                sed -i "s/^DBPASS=.*/DBPASS=$MYSQL_PASSWORD/" /opt/Eye/scripts/cfg/config
+                sed -i "s/DBPASS=db_password/DBPASS=$MYSQL_PASSWORD/" /opt/Eye/scripts/cfg/config
+            fi
         fi
 
-        # Update database username
-        sed -i "s/^DBUSER=.*/DBUSER=stat/" /opt/Eye/scripts/cfg/config
-        sed -i "s/DBUSER=mysql_user/DBUSER=stat/" /opt/Eye/scripts/cfg/config
-
-        # Update database name
+        # Common settings
         sed -i "s/^DBNAME=.*/DBNAME=stat/" /opt/Eye/scripts/cfg/config
-        sed -i "s/DBNAME=mysql_database/DBNAME=stat/" /opt/Eye/scripts/cfg/config
+        sed -i "s/DBNAME=db_database/DBNAME=stat/" /opt/Eye/scripts/cfg/config
+        sed -i "s/^DBUSER=.*/DBUSER=stat/" /opt/Eye/scripts/cfg/config
+        sed -i "s/DBUSER=db_user/DBUSER=stat/" /opt/Eye/scripts/cfg/config
 
         # Update encryption key
         sed -i "s/^encryption_key=.*/encryption_key=$ENC_PASSWORD/" /opt/Eye/scripts/cfg/config
@@ -635,6 +904,27 @@ setup_configs() {
     print_info "Vector: $ENC_VECTOR"
 }
 
+# Функция применения языковых настроек к конфигурации
+apply_language_settings() {
+    print_info "Applying language settings: $EYE_LANG"
+    
+    # Настройка config.php
+    if [[ -f "/opt/Eye/html/cfg/config.php" ]]; then
+        if [[ "$EYE_LANG" == "russian" ]]; then
+            # Установка русского языка
+            sed -i "s/define(\"HTML_LANG\",\"english\");/define(\"HTML_LANG\",\"russian\");/g" /opt/Eye/html/cfg/config.php
+            sed -i "s/setlocale(LC_ALL, 'en_US\.UTF-8');/setlocale(LC_ALL, 'ru_RU.UTF8');/g" /opt/Eye/html/cfg/config.php
+            print_info "Web interface language set to Russian"
+        else
+            # Установка английского языка (по умолчанию)
+            sed -i "s/define(\"HTML_LANG\",\"russian\");/define(\"HTML_LANG\",\"english\");/g" /opt/Eye/html/cfg/config.php
+            sed -i "s/setlocale(LC_ALL, 'ru_RU\.UTF8');/setlocale(LC_ALL, 'en_US.UTF-8');/g" /opt/Eye/html/cfg/config.php
+            print_info "Web interface language set to English"
+        fi
+    fi
+
+}
+
 # Configure Apache and PHP
 setup_apache_php() {
     print_step "Configuring Apache and PHP"
@@ -692,7 +982,7 @@ setup_apache_php() {
         APACHE_SERVICE="apache2"
     fi
 
-#    usermod -a -G eye $APACHE_USER
+    #    usermod -a -G eye $APACHE_USER
 
     if [[ "$OS_FAMILY" == "debian" ]]; then
         a2dismod php${PHP_VERSION} 2>/dev/null
@@ -700,7 +990,7 @@ setup_apache_php() {
 
         a2enmod mpm_event 2>/dev/null
         a2enconf php${PHP_VERSION}-fpm  2>/dev/null
-        fi
+    fi
 
     mkdir -p /var/log/php-fpm/
 
@@ -717,11 +1007,11 @@ setup_apache_php() {
         print_info "Using prepared php-fpm template"
         if [[ "$OS_FAMILY" == "alt" ]]; then
             cp "/opt/Eye/docs/php-fpm/eye.conf" /etc/fpm${PHP_VERSION}/php-fpm.d/
-            else
+        else
             cp "/opt/Eye/docs/php-fpm/eye.conf" /etc/php/${PHP_VERSION}/fpm/pool.available/
             ln -sf "/etc/php/${PHP_VERSION}/fpm/pool.available/eye.conf" "/etc/php/${PHP_VERSION}/fpm/pool.d/eye.conf"
-            fi
         fi
+    fi
 
     $SERVICE_MANAGER enable "$APACHE_SERVICE"
     $SERVICE_MANAGER restart "$APACHE_SERVICE"
@@ -822,7 +1112,7 @@ setup_syslog() {
         # Check if conf.d inclusion already exists in main config
         if [[ -f "/etc/syslog-ng/syslog-ng.conf" ]]; then
             if ! grep -q "@include.*conf\.d" /etc/syslog-ng/syslog-ng.conf && \
-               ! grep -q "include.*conf\.d" /etc/syslog-ng/syslog-ng.conf; then
+                ! grep -q "include.*conf\.d" /etc/syslog-ng/syslog-ng.conf; then
                 # Add conf.d directory inclusion to end of file
                 echo "" >> /etc/syslog-ng/syslog-ng.conf
                 echo "# Include Eye monitoring configuration" >> /etc/syslog-ng/syslog-ng.conf
@@ -837,20 +1127,20 @@ setup_syslog() {
 
     # options block
     syslogng_options='options {
-        chain_hostnames(off);
-        flush_lines(0);
-        use_dns(no);
-        use_fqdn(no);
-        dns_cache(no);
-        owner("root");
-        group("adm");
-        perm(0640);
-        stats_freq(0);
-        time_reopen(10);
-        log_fifo_size(1000);
-        create_dirs(yes);
-        keep_hostname(no);
-    };'
+chain_hostnames(off);
+flush_lines(0);
+use_dns(no);
+use_fqdn(no);
+dns_cache(no);
+owner("root");
+group("adm");
+perm(0640);
+stats_freq(0);
+time_reopen(10);
+log_fifo_size(1000);
+create_dirs(yes);
+keep_hostname(no);
+};'
 
     # Check for options in main config
     if [[ -f "/etc/syslog-ng/syslog-ng.conf" ]]; then
@@ -893,8 +1183,8 @@ setup_syslog() {
             if [[ ${#missing_params[@]} -gt 0 ]]; then
                 # Find options block and add parameters to end of block
                 sed -i '/^options\s*{/,/^}/ {
-                    /^}/ i\    '"$(IFS='; '; echo "${missing_params[*]}")"';
-                }' /etc/syslog-ng/syslog-ng.conf
+/^}/ i\    '"$(IFS='; '; echo "${missing_params[*]}")"';
+}' /etc/syslog-ng/syslog-ng.conf
                 print_info "Added parameters to options block: ${missing_params[*]}"
             fi
         fi
@@ -1013,23 +1303,39 @@ show_final_instructions() {
     echo "SYSTEM INFORMATION:"
     echo "  Distribution:     $OS_NAME"
     echo "  Version:          $OS_VERSION"
+    echo "  Database:         $DB_TYPE"
+    echo "  Language:         $EYE_LANG"  # <-- Добавлено
     echo "  User:             eye"
     echo "  Directory:        /opt/Eye"
     echo ""
+    echo ""
     echo "TO COMPLETE SETUP, EXECUTE:"
     echo ""
-    echo "1. Configure MySQL security:"
-    echo "   mysql_secure_installation"
+    echo "1. Configure database security:"
+    if [[ "$DB_TYPE" == "postgresql" ]]; then
+        print_info "   PostgreSQL: Edit pg_hba.conf if needed"
+        if [[ -f "/root/eye_postgres_password.txt" ]]; then
+            echo ""
+            echo "3. PostgreSQL 'stat' user password saved in:"
+            echo "   /root/eye_postgres_password.txt"
+            echo ""
+        fi
+    else
+        echo "   mysql_secure_installation"
+        if [[ -f "/root/eye_mysql_password.txt" ]]; then
+            echo ""
+            echo "3. MySQL 'stat' user password saved in:"
+            echo "   /root/eye_mysql_password.txt"
+            echo ""
+        fi
+    fi
+    
     echo ""
     echo "2. Check and edit configuration files:"
     echo "   /opt/Eye/html/cfg/config.php"
     echo "   /opt/Eye/scripts/cfg/config"
     echo ""
-    if [[ -f "/root/eye_mysql_password.txt" ]]; then
-        echo "3. MySQL 'stat' user password saved in:"
-        echo "   /root/eye_mysql_password.txt"
-        echo ""
-    fi
+    
     echo "4. Configure cron jobs:"
     echo "   nano /etc/cron.d/eye"
     echo "   Uncomment required scripts"
@@ -1061,19 +1367,29 @@ main() {
     echo -e "${GREEN}===========================================${NC}"
     echo ""
 
-    # Global variables
+
+    # Глобальные переменные
     MYSQL_PASSWORD=""
+    POSTGRES_PASSWORD=""
+    DB_TYPE="mysql"
+    EYE_LANG="english"
+    EYE_LANG_SHORT="en"
+    SQL_DATA_FILE=
+    SQL_CREATE_FILE=
 
     # Execute installation steps
     check_root
     detect_distro
+    select_language_with_auto
+    select_database_type
     update_system
     install_packages
     create_user_group
     install_source_code
     download_additional_scripts
-    setup_mysql
+    setup_database
     setup_configs
+    apply_language_settings
     setup_apache_php
     setup_cron_logrotate
     setup_additional_services

+ 4 - 3
scripts/cfg/config.sample

@@ -12,9 +12,10 @@ from_addr=admin@example.com
 
 #database - change it!!!
 DBSERVER=localhost
-DBUSER=mysql_user
-DBNAME=mysql_database
-DBPASS=mysql_password
+DBTYPE=db_type
+DBUSER=db_user
+DBNAME=db_name
+DBPASS=db_password
 
 #login for windows AD
 #domain_auth=EXAMPLE\roman%password

+ 1 - 0
scripts/check_dhcp_pool.pl

@@ -21,6 +21,7 @@ use Data::Dumper;
 use eyelib::config;
 use eyelib::main;
 use eyelib::database;
+use eyelib::common;
 use eyelib::net_utils;
 use File::Basename;
 use File::Path;

+ 1 - 0
scripts/dhcp-log.pl

@@ -19,6 +19,7 @@ use Data::Dumper;
 use eyelib::config;
 use eyelib::main;
 use eyelib::database;
+use eyelib::common;
 use eyelib::net_utils;
 use strict;
 use warnings;

+ 1 - 0
scripts/eye-statd.pl

@@ -19,6 +19,7 @@ use eyelib::config;
 use eyelib::main;
 use eyelib::net_utils;
 use eyelib::database;
+use eyelib::common;
 use eyelib::snmp;
 use Socket qw(AF_INET6 inet_ntop);
 use IO::Socket;

+ 1617 - 0
scripts/eyelib/common.pm

@@ -0,0 +1,1617 @@
+package eyelib::common;
+
+#
+# Copyright (C) Roman Dmitiriev, rnd@rajven.ru
+#
+
+use utf8;
+use open ":encoding(utf8)";
+use strict;
+use English;
+use FindBin '$Bin';
+use lib "/opt/Eye/scripts";
+use base 'Exporter';
+use vars qw(@EXPORT @ISA);
+use eyelib::config;
+use eyelib::main;
+use Net::Patricia;
+use eyelib::net_utils;
+use Data::Dumper;
+use eyelib::database;
+use DateTime;
+use POSIX qw(mktime ctime strftime);
+use File::Temp qw(tempfile);
+use DBI;
+
+our @ISA = qw(Exporter);
+
+our @EXPORT = qw(
+apply_device_lock
+create_dns_cname
+create_dns_hostname
+create_dns_ptr
+delete_device
+delete_dns_cname
+delete_dns_hostname
+delete_dns_ptr
+delete_user
+delete_user_auth
+find_mac_in_subnet
+get_default_ou
+get_device_by_ip
+get_dns_name
+get_dynamic_ou
+get_first_line
+get_ip_subnet
+get_new_user_id
+get_notify_subnet
+GetNowTime
+get_office_subnet
+get_subnets_ref
+GetTimeStrByUnixTime
+GetUnixTimeByStr
+is_ad_computer
+is_default_ou
+is_dynamic_ou
+is_hotspot
+new_auth
+new_user
+process_dhcp_request
+recalc_quotes
+record_to_txt
+resurrection_auth
+set_changed
+set_lock_discovery
+unbind_ports
+unblock_user
+unset_lock_discovery
+update_dns_record
+update_dns_record_by_dhcp
+);
+
+BEGIN
+{
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub get_first_line {
+my $msg = shift;
+if (!$msg) { return; }
+if ($msg=~ /(.*)(\n|\<br\>)/) {
+    $msg = $1 if ($1);
+    chomp($msg);
+    }
+return $msg;
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub unbind_ports {
+my $db = shift;
+my $device_id = shift;
+return if (!$db);
+return if (!$device_id);
+my @target = get_records_sql($db, "SELECT U.target_port_id,U.id FROM device_ports U WHERE U.device_id=".$device_id);
+foreach my $row (@target) {
+        do_sql($db, "UPDATE device_ports SET target_port_id=0 WHERE target_port_id=".$row->{id});
+        do_sql($db, "UPDATE device_ports SET target_port_id=0 WHERE id=".$row->{id});
+    }
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub get_dns_name {
+my $db = shift;
+my $id = shift;
+my $auth_record = get_record_sql($db,"SELECT dns_name FROM User_auth WHERE deleted=0 AND id=".$id);
+if ($auth_record and $auth_record->{'dns_name'}) { return $auth_record->{'dns_name'}; }
+return;
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub record_to_txt {
+my $db = shift;
+my $table = shift;
+my $id = shift;
+my $record = get_record_sql($db,'SELECT * FROM '.$table.' WHERE id='.$id);
+return hash_to_text($record);
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub delete_user_auth {
+my $db = shift;
+my $id = shift;
+
+my $record = get_record_sql($db,'SELECT * FROM User_auth WHERE id='.$id);
+my $auth_ident = $record->{ip};
+$auth_ident = $auth_ident . '['.$record->{dns_name} .']' if ($record->{dns_name});
+$auth_ident = $auth_ident . ' :: '.$record->{comments} if ($record->{dns_name});
+my $msg = "";
+my $txt_record = hash_to_text($record);
+#remove aliases
+my @t_User_auth_alias = get_records_sql($db,'SELECT * FROM User_auth_alias WHERE auth_id='.$id);
+if (@t_User_auth_alias and scalar @t_User_auth_alias) {
+    foreach my $row ( @t_User_auth_alias) {
+        my $alias_txt = record_to_txt($db,'User_auth_alias','id='.$row->{'id'});
+        if (delete_record($db,'User_auth_alias','id='.$row->{'id'})) {
+            $msg = "Deleting an alias: ". $alias_txt . "\n::Success!\n" . $msg;
+            } else {
+            $msg = "Deleting an alias: ". $alias_txt . "\n::Fail!\n" . $msg;
+            }
+        }
+    }
+#remove connections
+do_sql($db,'DELETE FROM connections WHERE auth_id='.$id);
+#remove user auth record
+my $changes = delete_record($db, "User_auth", "id=" . $id);
+if ($changes) {
+    $msg = "Deleting ip-record: ". $txt_record . "\n::Success!\n" . $msg;
+    } else {
+    $msg = "Deleting ip-record: ". $txt_record . "\n::Fail!\n" . $msg;
+    }
+
+$msg = "Deleting user ip record $auth_ident\n\n".$msg;
+db_log_warning($db, $msg, $id);
+my $send_alert = isNotifyDelete(get_notify_subnet($db,$record->{ip}));
+sendEmail("WARN! ".get_first_line($msg),$msg,1) if ($send_alert);
+return $changes;
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub unblock_user {
+my $db = shift;
+my $user_id = shift;
+my $user_record = get_record_sql($db,'SELECT * FROM User_list WHERE id='.$user_id);
+my $user_ident = 'id:'. $user_record->{'id'} . ' '. $user_record->{'login'};
+$user_ident = $user_ident . '[' . $user_record->{'fio'} . ']' if ($user_record->{'fio'});
+my $msg = "Amnistuyemo blocked by traffic user $user_ident \nInternet access for the user's IP address has been restored:\n";
+my @user_auth = get_records_sql($db,'SELECT * FROM User_auth WHERE deleted=0 AND user_id='.$user_id);
+my $send_alert = 0;
+if (@user_auth and scalar @user_auth) {
+    foreach my $record (@user_auth) {
+        $send_alert = ($send_alert or isNotifyUpdate(get_notify_subnet($db,$record->{ip})));
+        my $auth_ident = $record->{ip};
+        $auth_ident = $auth_ident . '['.$record->{dns_name} .']' if ($record->{dns_name});
+        $auth_ident = $auth_ident . ' :: '.$record->{comments} if ($record->{dns_name});
+        my $new;
+        $new->{'blocked'}=0;
+        $new->{'changed'}=1;
+        my $ret_id = update_record($db,'User_auth',$new,'id='.$record->{'id'});
+        if ($ret_id) {
+            $msg = $msg ."\n".$auth_ident;
+            }
+        }
+    }
+my $new;
+$new->{'blocked'}=0;
+my $ret_id = update_record($db,'User_list','id='.$user_id);
+if ($ret_id) {
+    db_log_info($db,$msg);
+    sendEmail("WARN! ".get_first_line($msg),$msg,1) if ($send_alert);
+    }
+return $ret_id;
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub delete_user {
+my $db = shift;
+my $id = shift;
+#remove user record
+my $changes = delete_record($db, "User_list", "id=" . $id);
+#if fail - exit
+if (!$changes) { return; }
+#remove auth records
+my @t_User_auth = get_records_sql($db,'SELECT * FROM User_auth WHERE user_id='.$id);
+if (@t_User_auth and scalar @t_User_auth) {
+    foreach my $row ( @t_User_auth ) { delete_user_auth($db,$row->{'id'}); }
+    }
+#remove device
+my $device = get_record_sql($db, "SELECT * FROM devices WHERE user_id=".$id);
+if ($device) { delete_device($db,$device->{'id'}); }
+#remove auth assign rules
+do_sql($db, "DELETE FROM auth_rules WHERE user_id=$id");
+return $changes;
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub delete_device {
+my $db = shift;
+my $id = shift;
+#remove user record
+my $changes = delete_record($db, "devices", "id=" . $id);
+#if fail - exit
+if (!$changes) { return; }
+unbind_ports($db, $id);
+do_sql($db, "DELETE FROM connections WHERE device_id=" . $id);
+do_sql($db, "DELETE FROM device_l3_interfaces WHERE device_id=" . $id);
+do_sql($db, "DELETE FROM device_ports WHERE device_id=" . $id);
+do_sql($db, "DELETE FROM device_filter_instances WHERE device_id=" . $id);
+do_sql($db, "DELETE FROM gateway_subnets WHERE device_id=".$id);
+return $changes;
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub is_hotspot {
+my $db = shift;
+my $ip  = shift;
+my $users = new Net::Patricia;
+#check hotspot
+my @ip_rules = get_records_sql($db,'SELECT * FROM subnets WHERE hotspot=1 AND LENGTH(subnet)>0');
+foreach my $row (@ip_rules) { $users->add_string($row->{subnet}); }
+if ($users->match_string($ip)) { return 1; }
+return 0;
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub get_office_subnet {
+my $db = shift;
+my $ip  = shift;
+my $subnets = new Net::Patricia;
+my @ip_rules = get_records_sql($db,'SELECT * FROM subnets WHERE office=1 AND LENGTH(subnet)>0');
+foreach my $row (@ip_rules) { $subnets->add_string($row->{subnet},$row); }
+return $subnets->match_string($ip);
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub get_notify_subnet {
+my $db = shift;
+my $ip  = shift;
+my $notify_flag = get_office_subnet($db,$ip);
+if ($notify_flag) { return $notify_flag->{notify}; }
+return 0;
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub get_new_user_id {
+my $db = shift;
+my $ip  = shift;
+my $mac = shift;
+my $hostname = shift;
+
+my $result;
+#check user rules
+$mac = mac_simplify($mac);
+
+$result->{ip} = $ip;
+$result->{mac} = mac_splitted($mac);
+$result->{dhcp_hostname} = $hostname;
+$result->{ou_id}=undef;
+$result->{user_id}=undef;
+
+my $hotspot_users = new Net::Patricia;
+#check hotspot
+my @hotspot_rules = get_records_sql($db,'SELECT * FROM subnets WHERE hotspot=1 AND LENGTH(subnet)>0');
+foreach my $row (@hotspot_rules) { $hotspot_users->add_string($row->{subnet},$default_hotspot_ou_id); }
+if ($hotspot_users->match_string($ip)) { $result->{ou_id}=$hotspot_users->match_string($ip); return $result; }
+
+#check ip
+if (defined $ip and $ip) {
+    my $users = new Net::Patricia;
+    #check ip rules
+    my @ip_rules = get_records_sql($db,'SELECT * FROM auth_rules WHERE type=1 and LENGTH(rule)>0 AND user_id IS NOT NULL');
+    foreach my $row (@ip_rules) { eval { $users->add_string($row->{rule},$row->{user_id}); }; }
+    if ($users->match_string($ip)) { $result->{user_id}=$users->match_string($ip); return $result; }
+    }
+
+#check mac
+if (defined $mac and $mac) {
+    my @user_rules=get_records_sql($db,'SELECT * FROM auth_rules WHERE type=2 AND LENGTH(rule)>0 AND user_id IS NOT NULL');
+    foreach my $user (@user_rules) {
+	my $rule = mac_simplify($user->{rule});
+        if ($mac=~/$rule/i) { $result->{user_id}=$user->{user_id}; return $result; }
+        }
+    }
+#check hostname
+if (defined $hostname and $hostname) {
+    my @user_rules=get_records_sql($db,'SELECT * FROM auth_rules WHERE type=3 AND LENGTH(rule)>0 AND user_id IS NOT NULL');
+    foreach my $user (@user_rules) {
+        if ($hostname=~/$user->{rule}/i) { $result->{user_id}=$user->{user_id}; return $result; }
+        }
+    }
+
+#check ou rules
+
+#check ip
+if (defined $ip and $ip) {
+    my $users = new Net::Patricia;
+    #check ip rules
+    my @ip_rules = get_records_sql($db,'SELECT * FROM auth_rules WHERE type=1 and LENGTH(rule)>0 AND ou_id IS NOT NULL');
+    foreach my $row (@ip_rules) { eval { $users->add_string($row->{rule},$row->{ou_id}); }; }
+    if ($users->match_string($ip)) { $result->{ou_id}=$users->match_string($ip); return $result; }
+    }
+
+#check mac
+if (defined $mac and $mac) {
+    my @user_rules=get_records_sql($db,'SELECT * FROM auth_rules WHERE type=2 AND LENGTH(rule)>0 AND ou_id IS NOT NULL');
+    foreach my $user (@user_rules) {
+	my $rule = mac_simplify($user->{rule});
+        if ($mac=~/$rule/i) { $result->{ou_id}=$user->{ou_id}; return $result; }
+        }
+    }
+
+#check hostname
+if (defined $hostname and $hostname) {
+    my @user_rules=get_records_sql($db,'SELECT * FROM auth_rules WHERE type=3 AND LENGTH(rule)>0 AND ou_id IS NOT NULL');
+    foreach my $user (@user_rules) {
+        if ($hostname=~/$user->{rule}/i) { $result->{ou_id}=$user->{ou_id}; return $result; }
+        }
+    }
+
+if (!$result->{ou_id}) { $result->{ou_id}=$default_user_ou_id; }
+
+return $result;
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub set_changed {
+my $db = shift;
+my $id = shift;
+return if (!$db or !$id);
+my $update_record;
+$update_record->{changed}=1;
+update_record($db,'User_auth',$update_record,"id=$id");
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub update_dns_record {
+
+my $hdb = shift;
+my $auth_id = shift;
+
+return if (!$config_ref{enable_dns_updates});
+
+# Переподключение
+if (!$hdb or !$hdb->ping) { $hdb = init_db(); }
+
+#get domain
+my $ad_zone = get_option($hdb,33);
+
+#get dns server
+my $ad_dns = get_option($hdb,3);
+
+my $enable_ad_dns_update = ($ad_zone and $ad_dns and $config_ref{enable_dns_updates});
+
+log_debug("Auth id: ".$auth_id);
+log_debug("enable_ad_dns_update: ".$enable_ad_dns_update);
+log_debug("DNS update flags - zone: ".$ad_zone.", dns: ".$ad_dns.", enable_ad_dns_update: ".$enable_ad_dns_update);
+
+my @dns_queue = get_records_sql($hdb,"SELECT * FROM dns_queue WHERE auth_id=".$auth_id." AND `value`>'' AND `value` NOT LIKE '%.'ORDER BY id ASC");
+
+if (!@dns_queue or !scalar @dns_queue) { return; }
+
+foreach my $dns_cmd (@dns_queue) {
+
+my $fqdn = '';
+my $fqdn_ip = '';
+my $fqdn_parent = '';
+my $static_exists = 0;
+my $static_ref = '';
+my $static_ok = 0;
+
+eval {
+
+if ($dns_cmd->{name_type}=~/^cname$/i) {
+    #skip update unknown domain
+    if ($dns_cmd->{name} =~/\.$/ or $dns_cmd->{value} =~/\.$/) { next; }
+
+    $fqdn=lc($dns_cmd->{name});
+    $fqdn=~s/\.$ad_zone$//i;
+#    $fqdn=~s/\.$//;
+    if ($dns_cmd->{value}) {
+        $fqdn_parent=lc($dns_cmd->{value});
+        $fqdn_parent=~s/\.$ad_zone$//i;
+#        $fqdn_parent=~s/\.$//;
+        }
+
+    $fqdn = $fqdn.".".$ad_zone;
+    $fqdn_parent = $fqdn_parent.".".$ad_zone;
+
+    #remove cname
+    if ($dns_cmd->{type} eq 'del') {
+        delete_dns_cname($fqdn_parent,$fqdn,$ad_zone,$ad_dns,$hdb);
+        }
+    #create cname
+    if ($dns_cmd->{type} eq 'add') {
+        create_dns_cname($fqdn_parent,$fqdn,$ad_zone,$ad_dns,$hdb);
+        }
+    }
+
+if ($dns_cmd->{name_type}=~/^a$/i) {
+    #skip update unknown domain
+    if ($dns_cmd->{name} =~/\.$/ or $dns_cmd->{value} =~/\.$/) { next; }
+    $fqdn=lc($dns_cmd->{name});
+    $fqdn=~s/\.$ad_zone$//i;
+#    $fqdn=~s/\.$//;
+    if (!$dns_cmd->{value}) { next; }
+    $fqdn_ip=lc($dns_cmd->{value});
+    $fqdn = $fqdn.".".$ad_zone;
+    #dns update disabled?
+    my $maybe_update_dns=( $enable_ad_dns_update and $office_networks->match_string($fqdn_ip) );
+    if (!$maybe_update_dns) {
+        db_log_info($hdb,"FOUND Auth_id: $auth_id. DNS update disabled.");
+        next;
+        }
+    #get aliases
+    my @aliases = get_records_sql($hdb,"SELECT * FROM User_auth_alias WHERE auth_id=".$auth_id);
+    #remove A & PTR
+    if ($dns_cmd->{type} eq 'del') {
+        #remove aliases
+        if (@aliases and scalar @aliases) {
+                foreach my $alias (@aliases) {
+                    delete_dns_cname($fqdn,$alias->{alias},$ad_zone,$ad_dns,$hdb) if ($alias->{alias});
+                    delete_dns_hostname($fqdn,$alias->{alias},$ad_zone,$ad_dns,$hdb) if ($alias->{alias});
+                }
+            }
+        #remove main record
+        delete_dns_hostname($fqdn,$fqdn_ip,$ad_zone,$ad_dns,$hdb);
+        delete_dns_ptr($fqdn,$fqdn_ip,$ad_zone,$ad_dns,$hdb);
+        }
+    #create A & PTR
+    if ($dns_cmd->{type} eq 'add') {
+        my @dns_record=ResolveNames($fqdn,$dns_server);
+        $static_exists = (scalar @dns_record>0);
+        if ($static_exists) {
+            $static_ref = join(' ',@dns_record);
+            foreach my $dns_a (@dns_record) {
+                if ($dns_a=~/^$fqdn_ip$/) { $static_ok = 1; }
+                }
+            db_log_debug($hdb,"Dns record for static record $fqdn: $static_ref");
+            }
+        #skip update if already exists
+        if ($static_ok) {
+            db_log_debug($hdb,"Static record for $fqdn [$static_ok] correct.");
+            next;
+            }
+        #create record
+        create_dns_hostname($fqdn,$fqdn_ip,$ad_zone,$ad_dns,$hdb);
+        create_dns_ptr($fqdn,$fqdn_ip,$ad_zone,$ad_dns,$hdb);
+        #create aliases
+        if (@aliases and scalar @aliases) {
+                foreach my $alias (@aliases) {
+                    create_dns_cname($fqdn,$alias->{alias},$ad_zone,$ad_dns,$hdb) if ($alias->{alias});
+                }
+            }
+        }
+    }
+#PTR
+if ($dns_cmd->{name_type}=~/^ptr$/i) {
+    $fqdn=lc($dns_cmd->{name});
+    $fqdn=~s/\.$ad_zone$//i;
+#    $fqdn=~s/\.$//;
+    if (!$dns_cmd->{value}) { next; }
+    $fqdn_ip=lc($dns_cmd->{value});
+    #skip update unknown domain
+    if ($fqdn =~/\.$/) { next; }
+    $fqdn = $fqdn.".".$ad_zone;
+    #dns update disabled?
+    my $maybe_update_dns=( $enable_ad_dns_update and $office_networks->match_string($fqdn_ip) );
+    if (!$maybe_update_dns) {
+        db_log_info($hdb,"FOUND Auth_id: $auth_id. DNS update disabled.");
+        next;
+        }
+    #remove A & PTR
+    if ($dns_cmd->{type} eq 'del') {
+        #remove main record
+        delete_dns_ptr($fqdn,$fqdn_ip,$ad_zone,$ad_dns,$hdb);
+        }
+    #create A & PTR
+    if ($dns_cmd->{type} eq 'add') {
+        #create record
+        create_dns_ptr($fqdn,$fqdn_ip,$ad_zone,$ad_dns,$hdb);
+        }
+    }
+
+};
+if ($@) { log_error("Error dns commands: $@"); }
+}
+
+}
+
+#---------------------------------------------------------------------------------------------------------------
+sub is_ad_computer {
+
+my $hdb = shift;
+my $computer_name = shift;
+
+if (!$computer_name or $computer_name =~/UNDEFINED/i) { return 0; }
+
+my $ad_check = get_option($hdb,73);
+if (!$ad_check) { return 1; }
+
+my $ad_zone = get_option($hdb,33);
+
+if ($computer_name =~/\./) {
+    if ($computer_name!~/\.$ad_zone$/i) { 
+        db_log_verbose($hdb,"The domain of the computer $computer_name does not match the domain of the organization $ad_zone. Skip update.");
+        return 0;
+        }
+    }
+
+if ($computer_name =~/^(.+)\./) {
+    $computer_name = $1;
+    }
+
+my $ad_computer_name = trim($computer_name).'$';
+
+my $name_in_cache = get_record_sql($hdb,"SELECT * FROM ad_comp_cache WHERE name='".$computer_name."'");
+if ($name_in_cache) { return 1; }
+
+my %name_found=do_exec_ref('/usr/bin/getent passwd '.$ad_computer_name);
+if (!$name_found{output} or $name_found{status} ne 0) {
+    db_log_verbose($hdb,"The computer ".uc($ad_computer_name)." was not found in the domain $ad_zone. Skip update.");
+    return 0;
+    }
+
+do_sql($hdb,"INSERT INTO ad_comp_cache(name) VALUES('".$computer_name."') ON DUPLICATE KEY UPDATE name='".$computer_name."';");
+return 1;
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub update_dns_record_by_dhcp {
+
+my $hdb = shift;
+my $dhcp_record = shift;
+my $auth_record = shift;
+
+return if (!$config_ref{enable_dns_updates});
+
+my $ad_zone = get_option($hdb,33);
+my $ad_dns = get_option($hdb,3);
+
+$update_hostname_from_dhcp = get_option($hdb,46) || 0;
+my $subnets_dhcp = get_subnets_ref($hdb);
+my $enable_ad_dns_update = ($ad_zone and $ad_dns and $update_hostname_from_dhcp);
+
+log_debug("Dhcp record: ".Dumper($dhcp_record));
+log_debug("Subnets: ".Dumper($subnets_dhcp->{$dhcp_record->{network}->{subnet}}));
+log_debug("enable_ad_dns_update: ".$enable_ad_dns_update);
+log_debug("DNS update flags - zone: ".$ad_zone.",dns: ".$ad_dns.", update_hostname_from_dhcp: ".$update_hostname_from_dhcp.", enable_ad_dns_update: ".$enable_ad_dns_update. ", network dns-update enabled: ".$subnets_dhcp->{$dhcp_record->{network}->{subnet}}->{dhcp_update_hostname});
+
+my $maybe_update_dns=($enable_ad_dns_update and $subnets_dhcp->{$dhcp_record->{network}->{subnet}}->{dhcp_update_hostname} and (is_ad_computer($hdb,$dhcp_record->{hostname_utf8}) and ($dhcp_record->{type}=~/add/i or $dhcp_record->{type}=~/old/i)));
+if (!$maybe_update_dns) {
+    db_log_debug($hdb,"FOUND Auth_id: $auth_record->{id}. DNS update don't needed.");
+    return 0;
+    }
+
+log_debug("DNS update enabled.");
+#update dns block
+my $fqdn_static;
+if ($auth_record->{dns_name}) {
+    $fqdn_static=lc($auth_record->{dns_name});
+    if ($fqdn_static!~/\.$ad_zone$/i) {
+            $fqdn_static=~s/\.$//;
+            $fqdn_static=lc($fqdn_static.'.'.$ad_zone);
+            }
+    }
+
+my $fqdn=lc(trim($dhcp_record->{hostname_utf8}));
+if ($fqdn!~/\.$ad_zone$/i) {
+    $fqdn=~s/\.$//;
+    $fqdn=lc($fqdn.'.'.$ad_zone);
+    }
+
+db_log_debug($hdb,"FOUND Auth_id: $auth_record->{id} dns_name: $fqdn_static dhcp_hostname: $fqdn");
+
+#check exists static dns name
+my $static_exists = 0;
+my $dynamic_exists = 0;
+my $static_ok = 0;
+my $dynamic_ok = 0;
+my $static_ref;
+my $dynamic_ref;
+
+if ($fqdn_static ne '') {
+    my @dns_record=ResolveNames($fqdn_static,$dns_server);
+    $static_exists = (scalar @dns_record>0);
+    if ($static_exists) {
+            $static_ref = join(' ',@dns_record);
+            foreach my $dns_a (@dns_record) {
+                if ($dns_a=~/^$dhcp_record->{ip}$/) { $static_ok = $dns_a; }
+                }
+            }
+    } else { $static_ok = 1; }
+
+if ($fqdn ne '') {
+    my @dns_record=ResolveNames($fqdn,$dns_server);
+    $dynamic_exists = (scalar @dns_record>0);
+    if ($dynamic_exists) {
+            $dynamic_ref = join(' ',@dns_record);
+            foreach my $dns_a (@dns_record) {
+                if ($dns_a=~/^$dhcp_record->{ip}$/) { $dynamic_ok = $dns_a; }
+                }
+            }
+    }
+
+db_log_debug($hdb,"Dns record for static record $fqdn_static: $static_ok");
+db_log_debug($hdb,"Dns record for dhcp-hostname $fqdn: $dynamic_ok");
+
+if ($fqdn_static ne '') {
+    if (!$static_ok) {
+        db_log_info($hdb,"Static record mismatch! Expected $fqdn_static => $dhcp_record->{ip}, recivied: $static_ref");
+        if (!$static_exists) {
+                db_log_info($hdb,"Static dns hostname defined but not found. Create it ($fqdn_static => $dhcp_record->{ip})!");
+                create_dns_hostname($fqdn_static,$dhcp_record->{ip},$ad_zone,$ad_dns,$hdb);
+                }
+        } else {
+	db_log_debug($hdb,"Static record for $fqdn_static [$static_ok] correct.");
+	}
+    }
+
+if ($fqdn ne '' and $dynamic_ok ne '') { db_log_debug($hdb,"Dynamic record for $fqdn [$dynamic_ok] correct. No changes required."); }
+
+if ($fqdn ne '' and !$dynamic_ok) {
+    log_error("Dynamic record mismatch! Expected: $fqdn => $dhcp_record->{ip}, recivied: $dynamic_ref. Checking the status.");
+    #check exists hostname
+    my $another_hostname_exists = 0;
+    my $hostname_filter = ' LOWER(dns_name) REGEXP("^'.lc($dhcp_record->{hostname_utf8}).'\.*$")';
+    if ($fqdn_static ne '' and $fqdn !~/$fqdn_static/) {
+	    $hostname_filter = $hostname_filter . ' or LOWER(dns_name) REGEXP("^'.lc($auth_record->{dns_name}).'\.*$")';
+	    }
+    #check exists another records with some static hostname
+    my $filter_sql = 'SELECT * FROM User_auth WHERE id<>'.$auth_record->{id}.' and deleted=0 and ('.$hostname_filter.') ORDER BY last_found DESC';
+    db_log_debug($hdb,"Search dhcp hostname by: ".$filter_sql);
+    my $name_record = get_record_sql($hdb,$filter_sql);
+    if ($name_record->{dns_name} =~/^$fqdn$/i or $name_record->{dns_name} =~/^$dhcp_record->{hostname_utf8}$/i) {
+	    $another_hostname_exists = 1;
+	    }
+    if (!$another_hostname_exists) {
+            if ($fqdn_static and $fqdn_static ne '') {
+                    if ($fqdn_static!~/$fqdn/) {
+                        db_log_info($hdb,"Hostname from dhcp request $fqdn differs from static dns hostname $fqdn_static. Ignore dynamic binding!");
+#                        delete_dns_hostname($fqdn,$dhcp_record->{ip},$ad_zone,$ad_dns,$hdb);
+#                        create_dns_hostname($fqdn,$dhcp_record->{ip},$ad_zone,$ad_dns,$hdb);
+                        }
+                    } else {
+        	    db_log_info($hdb,"Rewrite aliases if exists for $fqdn => $dhcp_record->{ip}");
+                    #get and remove aliases
+                    my @aliases = get_records_sql($hdb,"SELECT * FROM User_auth_alias WHERE auth_id=".$auth_record->{id});
+                    if (@aliases and scalar @aliases) {
+                            foreach my $alias (@aliases) {
+                                delete_dns_cname($fqdn_static,$alias->{alias},$ad_zone,$ad_dns,$hdb) if ($alias->{alias});
+                            }
+                        }
+        	    db_log_info($hdb,"Static dns hostname not defined. Create dns record by dhcp request. $fqdn => $dhcp_record->{ip}");
+        	    create_dns_hostname($fqdn,$dhcp_record->{ip},$ad_zone,$ad_dns,$hdb);
+                    if (@aliases and scalar @aliases) {
+                            foreach my $alias (@aliases) {
+                                create_dns_cname($fqdn_static,$alias->{alias},$ad_zone,$ad_dns,$hdb) if ($alias->{alias});
+                            }
+                        }
+        	    }
+	    } else {
+            db_log_error($hdb,"Found another record with some hostname id: $name_record->{id} ip: $name_record->{ip} hostname: $name_record->{dns_name}. Skip update.");
+            }
+    }
+#end update dns block
+}
+
+#------------------------------------------------------------------------------------------------------------
+
+sub apply_device_lock {
+    my $db = shift;
+    my $device_id = shift;
+    my $iteration = shift || 0;
+    $iteration++;
+    if ($iteration>2) { return 0; }
+    my $dev = get_record_sql($db,"SELECT `discovery_locked`, `locked_timestamp`, UNIX_TIMESTAMP(`locked_timestamp`) as u_locked_timestamp  FROM devices WHERE id=".$device_id);
+    if (!$dev) { return 0; }
+    if (!$dev->{'discovery_locked'}) { return set_lock_discovery($db,$device_id); }
+    #if timestamp undefined, set and return
+    if (!$dev->{'locked_timestamp'}) { return set_lock_discovery($db,$device_id); }
+    #wait for discovery
+    my $wait_time = $dev->{'locked_timestamp'} + 30 - time();
+    if ($wait_time<0) { return set_lock_discovery($db,$device_id); }
+    sleep($wait_time);
+    return apply_device_lock($db,$device_id,$iteration);
+}
+
+#------------------------------------------------------------------------------------------------------------
+
+sub set_lock_discovery {
+    my $db = shift;
+    my $device_id = shift;
+    my $new;
+    $new->{'discovery_locked'} = 1;
+    $new->{'locked_timestamp'} = GetNowTime();
+    if (update_record($db,'devices',$new,'id='.$device_id)) { return 1; } 
+    return 0;
+}
+
+#------------------------------------------------------------------------------------------------------------
+
+sub unset_lock_discovery {
+    my $db = shift;
+    my $device_id = shift;
+    my $new;
+    $new->{'discovery_locked'} = 0;
+    $new->{'locked_timestamp'} = GetNowTime();
+    if (update_record($db,'devices',$new,'id='.$device_id)) { return 1; } 
+    return 0;
+}
+
+#------------------------------------------------------------------------------------------------------------
+
+sub create_dns_cname {
+my $fqdn = shift;
+my $alias = shift;
+my $zone = shift;
+my $server = shift;
+my $db = shift;
+#skip update domain controllers
+if (!$db) {
+    log_info("DNS-UPDATE: Add => Zone $zone Server: $server CNAME: $alias for $fqdn"); 
+    } else {
+    db_log_info($db,"DNS-UPDATE: Add => Zone $zone Server: $server CNAME: $alias for $fqdn ");
+    }
+my $ad_zone = get_option($db,33);
+my $nsupdate_file = "/tmp/".$fqdn."-nsupdate";
+my @add_dns;
+if ($config_ref{dns_server_type}=~/windows/i) {
+    push(@add_dns,"gsstsig");
+    push(@add_dns,"server $server");
+    push(@add_dns,"zone $zone");
+    push(@add_dns,"update add $alias 3600 cname $fqdn.");
+    push(@add_dns,"send");
+    write_to_file($nsupdate_file,\@add_dns);
+    do_exec('/usr/bin/kinit -k -t /opt/Eye/scripts/cfg/dns_updater.keytab dns_updater@'.uc($ad_zone).' && /usr/bin/nsupdate "'.$nsupdate_file.'"');
+    }
+
+if ($config_ref{dns_server_type}=~/bind/i) {
+    push(@add_dns,"server $server");
+    push(@add_dns,"zone $zone");
+    push(@add_dns,"update add $alias 3600 cname $fqdn.");
+    push(@add_dns,"send");
+    write_to_file($nsupdate_file,\@add_dns);
+    do_exec('/usr/bin/nsupdate -k /etc/bind/rndc.key "'.$nsupdate_file.'"');
+    }
+
+if (-e "$nsupdate_file") { unlink "$nsupdate_file"; }
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub delete_dns_cname {
+my $fqdn = shift;
+my $alias = shift;
+my $zone = shift;
+my $server = shift;
+my $db = shift;
+if (!$db) {
+    log_info("DNS-UPDATE: Delete => Zone $zone Server: $server CNAME: $alias for $fqdn ");
+    } else {
+    db_log_info($db,"DNS-UPDATE: Delete => Zone $zone Server: $server CNAME: $alias for $fqdn");
+    }
+my $ad_zone = get_option($db,33);
+my $nsupdate_file = "/tmp/".$fqdn."-nsupdate";
+my @add_dns;
+if ($config_ref{dns_server_type}=~/windows/i) {
+    push(@add_dns,"gsstsig");
+    push(@add_dns,"server $server");
+    push(@add_dns,"zone $zone");
+    push(@add_dns,"update delete $alias cname ");
+    push(@add_dns,"send");
+    write_to_file($nsupdate_file,\@add_dns);
+    do_exec('/usr/bin/kinit -k -t /opt/Eye/scripts/cfg/dns_updater.keytab dns_updater@'.uc($ad_zone).' && /usr/bin/nsupdate "'.$nsupdate_file.'"');
+    }
+
+if ($config_ref{dns_server_type}=~/bind/i) {
+    push(@add_dns,"server $server");
+    push(@add_dns,"zone $zone");
+    push(@add_dns,"update delete $alias cname");
+    push(@add_dns,"send");
+    write_to_file($nsupdate_file,\@add_dns);
+    do_exec('/usr/bin/nsupdate -k /etc/bind/rndc.key "'.$nsupdate_file.'"');
+    }
+
+if (-e "$nsupdate_file") { unlink "$nsupdate_file"; }
+}
+
+#------------------------------------------------------------------------------------------------------------
+
+sub create_dns_hostname {
+my $fqdn = shift;
+my $ip = shift;
+my $zone = shift;
+my $server = shift;
+my $db = shift;
+#skip update domain controllers
+if ($fqdn=~/^dc[0-9]{1,2}\./i) { return; }
+if (!$db) {
+    log_info("DNS-UPDATE: Add => Zone $zone Server: $server A: $fqdn IP: $ip"); 
+    } else {
+    db_log_info($db,"DNS-UPDATE: Add => Zone $zone Server: $server A: $fqdn IP: $ip");
+    }
+my $ad_zone = get_option($db,33);
+my $nsupdate_file = "/tmp/".$fqdn."-nsupdate";
+my @add_dns;
+if ($config_ref{dns_server_type}=~/windows/i) {
+    push(@add_dns,"gsstsig");
+    push(@add_dns,"server $server");
+    push(@add_dns,"zone $zone");
+    push(@add_dns,"update add $fqdn 3600 A $ip");
+    push(@add_dns,"send");
+    write_to_file($nsupdate_file,\@add_dns);
+    do_exec('/usr/bin/kinit -k -t /opt/Eye/scripts/cfg/dns_updater.keytab dns_updater@'.uc($ad_zone).' && /usr/bin/nsupdate "'.$nsupdate_file.'"');
+    }
+
+if ($config_ref{dns_server_type}=~/bind/i) {
+    push(@add_dns,"server $server");
+    push(@add_dns,"zone $zone");
+    push(@add_dns,"update add $fqdn 3600 A $ip");
+    push(@add_dns,"send");
+    write_to_file($nsupdate_file,\@add_dns);
+    do_exec('/usr/bin/nsupdate -k /etc/bind/rndc.key "'.$nsupdate_file.'"');
+    }
+
+if (-e "$nsupdate_file") { unlink "$nsupdate_file"; }
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub delete_dns_hostname {
+my $fqdn = shift;
+my $ip = shift;
+my $zone = shift;
+my $server = shift;
+my $db = shift;
+#skip update domain controllers
+if ($fqdn=~/^dc[0-9]{1,2}\./i) { return; }
+if (!$db) {
+    log_info("DNS-UPDATE: Delete => Zone $zone Server: $server A: $fqdn IP: $ip"); 
+    } else {
+    db_log_info($db,"DNS-UPDATE: Delete => Zone $zone Server: $server A: $fqdn IP: $ip");
+    }
+my $ad_zone = get_option($db,33);
+my $nsupdate_file = "/tmp/".$fqdn."-nsupdate";
+my @add_dns;
+if ($config_ref{dns_server_type}=~/windows/i) {
+    push(@add_dns,"gsstsig");
+    push(@add_dns,"server $server");
+    push(@add_dns,"zone $zone");
+    push(@add_dns,"update delete $fqdn A");
+    push(@add_dns,"send");
+    write_to_file($nsupdate_file,\@add_dns);
+    do_exec('/usr/bin/kinit -k -t /opt/Eye/scripts/cfg/dns_updater.keytab dns_updater@'.uc($ad_zone).' && /usr/bin/nsupdate "'.$nsupdate_file.'"');
+    }
+
+if ($config_ref{dns_server_type}=~/bind/i) {
+    push(@add_dns,"server $server");
+    push(@add_dns,"zone $zone");
+    push(@add_dns,"update delete $fqdn A");
+    push(@add_dns,"send");
+    write_to_file($nsupdate_file,\@add_dns);
+    do_exec('/usr/bin/nsupdate -k /etc/bind/rndc.key "'.$nsupdate_file.'"');
+    }
+
+if (-e "$nsupdate_file") { unlink "$nsupdate_file"; }
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub create_dns_ptr {
+my $fqdn = shift;
+my $ip = shift;
+my $ad_zone = shift;
+my $server = shift;
+my $db = shift;
+
+my $radr;
+my $zone;
+
+#skip update domain controllers
+if ($fqdn=~/^dc[0-9]{1,2}\./i) { return; }
+if ($ip =~ /([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})(\/[0-9]{1,2}){0,1}/) {
+    return 0 if($1 > 255 || $2 > 255 || $3 > 255 || $4 > 255);
+    $radr = "$4.$3.$2.$1.in-addr.arpa";
+    $zone = "$3.$2.$1.in-addr.arpa";
+    }
+
+if (!$radr or !$zone) { return 0; }
+
+if (!$db) { return 0; }
+
+db_log_info($db,"DNS-UPDATE: Zone $zone Server: $server A: $fqdn PTR: $ip");
+
+my $nsupdate_file = "/tmp/".$radr."-nsupdate";
+
+my @add_dns;
+
+if ($config_ref{dns_server_type}=~/windows/i) {
+    push(@add_dns,"gsstsig");
+    push(@add_dns,"server $server");
+    push(@add_dns,"zone $zone");
+    push(@add_dns,"update add $radr 3600 PTR $fqdn.");
+    push(@add_dns,"send");
+    write_to_file($nsupdate_file,\@add_dns);
+    my $run_cmd = '/usr/bin/kinit -k -t /opt/Eye/scripts/cfg/dns_updater.keytab dns_updater@'.uc($ad_zone).' && /usr/bin/nsupdate "'.$nsupdate_file.'"';
+    do_exec($run_cmd);
+    }
+
+if ($config_ref{dns_server_type}=~/bind/i) {
+    push(@add_dns,"server $server");
+    push(@add_dns,"zone $zone");
+    push(@add_dns,"update add $radr 3600 PTR $fqdn.");
+    push(@add_dns,"send");
+    write_to_file($nsupdate_file,\@add_dns);
+    my $run_cmd = '/usr/bin/nsupdate -k /etc/bind/rndc.key "'.$nsupdate_file.'"';
+    do_exec($run_cmd);
+    }
+
+if (-e "$nsupdate_file") { unlink "$nsupdate_file"; }
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub delete_dns_ptr {
+my $fqdn = shift;
+my $ip = shift;
+my $ad_zone = shift;
+my $server = shift;
+my $db = shift;
+
+my $radr;
+my $zone;
+
+#skip update domain controllers
+if ($fqdn=~/^dc[0-9]{1,2}\./i) { return; }
+if ($ip =~ /([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})(\/[0-9]{1,2}){0,1}/) {
+    return 0 if($1 > 255 || $2 > 255 || $3 > 255 || $4 > 255);
+    $radr = "$4.$3.$2.$1.in-addr.arpa";
+    $zone = "$3.$2.$1.in-addr.arpa";
+    }
+if (!$radr or !$zone) { return 0; }
+
+if (!$db) { return 0 ; }
+
+db_log_info($db,"DNS-UPDATE: Delete => Zone $zone Server: $server A: $fqdn PTR: $ip");
+
+my $nsupdate_file = "/tmp/".$radr."-nsupdate";
+
+my @add_dns;
+
+if ($config_ref{dns_server_type}=~/windows/i) {
+    push(@add_dns,"gsstsig");
+    push(@add_dns,"server $server");
+    push(@add_dns,"zone $zone");
+    push(@add_dns,"update delete $radr PTR");
+    push(@add_dns,"send");
+    write_to_file($nsupdate_file,\@add_dns);
+    my $run_cmd = '/usr/bin/kinit -k -t /opt/Eye/scripts/cfg/dns_updater.keytab dns_updater@'.uc($ad_zone).' && /usr/bin/nsupdate "'.$nsupdate_file.'"';
+    do_exec($run_cmd);
+    }
+
+if ($config_ref{dns_server_type}=~/bind/i) {
+    push(@add_dns,"server $server");
+    push(@add_dns,"zone $zone");
+    push(@add_dns,"update delete $radr PTR");
+    push(@add_dns,"send");
+    write_to_file($nsupdate_file,\@add_dns);
+    my $run_cmd = '/usr/bin/nsupdate -k /etc/bind/rndc.key "'.$nsupdate_file.'"';
+    do_exec($run_cmd);
+    }
+
+if (-e "$nsupdate_file") { unlink "$nsupdate_file"; }
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub new_user {
+my $db = shift;
+my $user_info = shift;
+my $user;
+if ($user_info->{mac}) {
+    $user->{login}=mac_splitted($user_info->{mac});
+    } else {
+    $user->{login}=$user_info->{ip};
+    }
+
+if ($user_info->{dhcp_hostname}) { $user->{fio}=$user_info->{dhcp_hostname}; } 
+if (!$user->{fio}) { $user->{fio}=$user_info->{ip}; }
+
+my $login_count = get_count_records($db,"User_list","(login LIKE '".$user->{login}."(%)') OR (login='".$user->{login}."')");
+if ($login_count) { $login_count++; $user->{login} .="(".$login_count.")"; }
+
+$user->{ou_id} = $user_info->{ou_id};
+my $ou_info = get_record_sql($db,"SELECT * FROM OU WHERE id=".$user_info->{'ou_id'});
+if ($ou_info) {
+    $user->{'enabled'} = $ou_info->{'enabled'};
+    $user->{'queue_id'} = $ou_info->{'queue_id'};
+    $user->{'filter_group_id'} = $ou_info->{'filter_group_id'};
+    }
+
+my $result = insert_record($db,"User_list",$user);
+if ($result and $config_ref{auto_mac_rule} and $user_info->{mac}) {
+    my $auth_rule;
+    $auth_rule->{user_id} = $result;
+    $auth_rule->{type} = 2;
+    $auth_rule->{rule} = mac_splitted($user_info->{mac});
+    insert_record($db,"auth_rules",$auth_rule);
+    }
+return $result;
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub get_ip_subnet {
+    my $db = shift;
+    my $ip = shift;
+    if (!$ip) { return; }
+    my $ip_aton = StrToIp($ip);
+    my $user_subnet = get_record_sql($db, "SELECT * FROM `subnets` WHERE hotspot=1 or office=1 and ( ".$ip_aton." >= ip_int_start and ".$ip_aton." <= ip_int_stop)");
+    return $user_subnet;
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub find_mac_in_subnet {
+    my $db = shift;
+    my $ip = shift;
+    my $mac = shift;
+    if (!$ip or !$mac) { return; }
+    my $ip_subnet = get_ip_subnet($db, $ip);
+    if (!$ip_subnet) { return; }
+    my @t_auth = get_records_sql($db, "SELECT * FROM User_auth WHERE ip_int>=" . $ip_subnet->{'ip_int_start'} . " and ip_int<=" . $ip_subnet->{'ip_int_stop'} . " and mac='" . $mac . "' and deleted=0 ORDER BY id");
+    my $auth_count = 0;
+    my $result;
+    $result->{'count'} = 0;
+    foreach my $row (@t_auth) {
+        next if (!$row);
+        $auth_count++;
+        $result->{'count'} = $auth_count;
+        $result->{items}{$auth_count} = $row;
+        }
+    return $result;
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub resurrection_auth {
+my $db = shift;
+my $ip_record = shift;
+
+my $ip = $ip_record->{'ip'};
+my $mac = $ip_record->{'mac'};
+my $action = $ip_record->{'type'};
+my $hostname = $ip_record->{'hostname_utf8'};
+my $client_id = $ip_record->{'client-id'};
+
+if (!exists $ip_record->{ip_aton}) { $ip_record->{ip_aton}=StrToIp($ip); }
+if (!exists $ip_record->{hotspot}) { $ip_record->{hotspot}=is_hotspot($db,$ip); }
+
+my $auth_ident = "Found new ip-address: " . $ip;
+$auth_ident = $auth_ident . ' ['.$mac .']' if ($mac);
+$auth_ident = $auth_ident . ' :: '.$hostname if ($hostname);
+
+my $ip_aton=$ip_record->{ip_aton};
+
+my $timestamp=GetNowTime();
+
+my $record=get_record_sql($db,'SELECT * FROM User_auth WHERE `deleted`=0 AND `ip_int`='.$ip_aton.' AND `mac`="'.$mac.'"');
+
+my $new_record;
+$new_record->{last_found}=$timestamp;
+$new_record->{arp_found}=$timestamp;
+
+if ($client_id) { $new_record->{'client-id'} = $client_id; }
+
+#auth found?
+if ($record->{user_id}) {
+    #update timestamp and return
+    if ($action=~/^(add|old|del)$/i) {
+	    $new_record->{dhcp_action}=$action;
+	    $new_record->{created_by}='dhcp';
+	    $new_record->{dhcp_time}=$timestamp;
+	    if ($hostname) { $new_record->{dhcp_hostname} = $hostname; }
+	    }
+    update_record($db,'User_auth',$new_record,"id=$record->{id}");
+    return $record->{id};
+    }
+
+my $user_subnet=$office_networks->match_string($ip);
+if ($user_subnet->{static}) {
+    db_log_warning($db,"Unknown ip+mac found in static subnet! Abort create record for ip: $ip mac: [".$mac."]");
+    return 0;
+    }
+
+my $send_alert_update = isNotifyUpdate(get_notify_subnet($db,$ip));
+my $send_alert_create = isNotifyCreate(get_notify_subnet($db,$ip));
+#my $send_alert_delete = isNotifyDelete(get_notify_subnet($db,$ip));
+
+my $mac_exists=find_mac_in_subnet($db,$ip,$mac);
+
+my $msg = '';
+
+#search changed mac
+$record=get_record_sql($db,'SELECT * FROM User_auth WHERE `ip_int`='.$ip_aton." and deleted=0");
+if ($record->{id}) {
+    #if found record with same ip but without mac - update it
+    if (!$record->{mac}) {
+        $msg = $auth_ident. "\nUse auth record with no mac: " . hash_to_text($record);
+        db_log_verbose($db,$msg);
+        $new_record->{mac}=$mac;
+        #disable dhcp for same mac in one ip subnet
+        if ($mac_exists and $mac_exists->{'count'}) { $new_record->{dhcp}=0; }
+        if ($action=~/^(add|old|del)$/i) {
+	        $new_record->{dhcp_action}=$action;
+	        $new_record->{dhcp_time}=$timestamp;
+                $new_record->{created_by}='dhcp';
+	        if ($hostname) { $new_record->{dhcp_hostname} = $hostname; }
+                }
+        update_record($db,'User_auth',$new_record,"id=$record->{id}");
+        sendEmail("WARN! ".get_first_line($msg),$msg,1) if ($send_alert_update);
+        return $record->{id};
+        }
+    #if found record with same ip but another mac - delete old record
+    if ($record->{mac}) {
+        if (!$ip_record->{hotspot}) {
+            my $msg = "For ip: $ip mac change detected! Old mac: [".$record->{mac}."] New mac: [".$mac."]. Disable old auth_id: $record->{id}";
+            db_log_warning($db,$msg,$record->{id});
+            sendEmail("WARN! ".get_first_line($msg),$msg,1) if ($send_alert_update);
+            }
+        delete_user_auth($db,$record->{id});
+        }
+    }
+
+#default user
+my $new_user_info=get_new_user_id($db,$ip,$mac,$hostname);
+my $new_user_id;
+if ($new_user_info->{user_id}) { $new_user_id = $new_user_info->{user_id}; }
+if (!$new_user_id) { $new_user_id = new_user($db,$new_user_info); }
+
+if ($mac_exists) {
+    #deleting the user's entry if the address belongs to a dynamic group
+    foreach my $dup_record_id (keys %{$mac_exists->{items}}) {
+        my $dup_record = $mac_exists->{items}{$dup_record_id};
+        next if (!$dup_record);
+        #remove old dynamic record with some mac
+        if ($dup_record->{dynamic}) {
+            delete_user_auth($db,$dup_record->{id});
+            }
+        }
+    }
+
+#recheck
+$mac_exists=find_mac_in_subnet($db,$ip,$mac);
+
+#disable dhcp for same mac in one ip subnet
+if ($mac_exists and $mac_exists->{'count'}) { $new_record->{dhcp}=0; }
+
+#seek old auth with same ip and mac
+my $auth_exists=get_count_records($db,'User_auth',"ip_int=".$ip_aton." and mac='".$mac."'");
+
+$new_record->{ip_int}=$ip_aton;
+$new_record->{ip}=$ip;
+$new_record->{mac}=$mac;
+$new_record->{user_id}=$new_user_id;
+$new_record->{save_traf}="$save_detail";
+$new_record->{deleted}="0";
+if ($action=~/^(add|old|del)$/i) {
+    $new_record->{dhcp_action}=$action;
+    $new_record->{dhcp_time}=$timestamp;
+    $new_record->{created_by}='dhcp';
+    } else {
+    $new_record->{created_by}=$action;
+    }
+
+my $cur_auth_id= 0;
+if ($auth_exists) {
+    #found ->Resurrection old record
+    my $resurrection_id = get_id_record($db,'User_auth',"ip_int=".$ip_aton." and mac='".$mac."'");
+    $msg = $auth_ident . " Resurrection auth_id: $resurrection_id with ip: $ip and mac: $mac";
+    if (!$ip_record->{hotspot}) { db_log_warning($db,$msg); } else { db_log_info($db,$msg); }
+    if (update_record($db,'User_auth',$new_record,"id=$resurrection_id")) { $cur_auth_id = $resurrection_id; }
+    } else {
+    #not found ->create new record
+    $msg = $auth_ident ."\n";
+    $cur_auth_id = insert_record($db,'User_auth',$new_record);
+    if ($cur_auth_id) {
+        if (!$ip_record->{hotspot}) { db_log_warning($db,$msg); } else { db_log_info($db,$msg); }
+        }
+    }
+#filter and status
+$cur_auth_id=get_id_record($db,'User_auth',"ip='$ip' and mac='$mac' and deleted=0 ORDER BY last_found DESC") if (!$cur_auth_id);
+if ($cur_auth_id) {
+    my $user_record=get_record_sql($db,"SELECT * FROM User_list WHERE id=".$new_user_id);
+    if ($user_record) {
+	    my $ou_info = get_record_sql($db,'SELECT * FROM OU WHERE id='.$user_record->{ou_id});
+	    if ($ou_info and $ou_info->{'dynamic'}) {
+                    # Устанавливаем значение по умолчанию, если не задано
+                    if (!$ou_info->{'life_duration'}) { 
+                            $ou_info->{'life_duration'} = 24.0;  # Явно указываем дробное число
+                            }
+                    my $now = DateTime->now(time_zone => 'local');
+                    # Разбиваем life_duration на часы и минуты (для дробного значения)
+                    my $hours = int($ou_info->{'life_duration'});  # Целая часть (часы)
+                    my $minutes = ($ou_info->{'life_duration'} - $hours) * 60;  # Дробная часть → минуты
+                    # Создаём продолжительность с учётом дробных часов (в виде часов + минут)
+                    my $duration = DateTime::Duration->new( hours   => $hours, minutes => $minutes);
+                    my $eof = $now + $duration;
+                    $new_record->{'dynamic'} = 1;
+                    $new_record->{'eof'} = $eof->strftime('%Y-%m-%d %H:%M:%S');
+		    }
+	    $new_record->{ou_id}=$user_record->{ou_id};
+	    $new_record->{comments}=$user_record->{fio};
+	    $new_record->{filter_group_id}=$user_record->{filter_group_id};
+	    $new_record->{queue_id}=$user_record->{queue_id};
+	    $new_record->{enabled}="$user_record->{enabled}";
+            update_record($db,'User_auth',$new_record,"id=$cur_auth_id");
+	    }
+    db_log_warning($db, $msg, $cur_auth_id);
+    sendEmail("WARN! ".get_first_line($msg),$msg."\n".record_to_txt($db,'User_auth',$cur_auth_id),1) if ($send_alert_create);
+    } else { return; }
+return $cur_auth_id;
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub new_auth {
+my $db = shift;
+my $ip = shift;
+my $ip_aton=StrToIp($ip);
+my $record=get_record_sql($db,'SELECT id FROM User_auth WHERE `deleted`=0 AND `ip_int`='.$ip_aton);
+if ($record->{id}) { return $record->{id}; }
+#default user
+my $new_user_info=get_new_user_id($db,$ip,undef,undef);
+my $new_user_id;
+if ($new_user_info->{user_id}) { $new_user_id = $new_user_info->{user_id}; }
+if ($new_user_info->{ou_id}) { $new_user_id = new_user($db,$new_user_info); }
+
+if (is_dynamic_ou($db,$new_user_info->{ou_id})) {
+    db_log_debug($db,"The ip-address $ip belongs to a dynamic group - ignore it.");
+    return;
+    }
+
+my $send_alert = isNotifyCreate(get_notify_subnet($db,$ip));
+my $user_record=get_record_sql($db,"SELECT * FROM User_list WHERE id=".$new_user_id);
+my $timestamp=GetNowTime();
+my $new_record;
+$new_record->{ip_int}=$ip_aton;
+$new_record->{ip}=$ip;
+$new_record->{user_id}=$new_user_id;
+$new_record->{save_traf}="$save_detail";
+$new_record->{deleted}="0";
+$new_record->{created_by}='netflow';
+$new_record->{ou_id}=$user_record->{ou_id};
+$new_record->{filter_group_id}=$user_record->{filter_group_id};
+$new_record->{queue_id}=$user_record->{queue_id};
+$new_record->{enabled}="$user_record->{enabled}";
+if ($user_record->{fio}) { $new_record->{comments}=$user_record->{fio}; }
+
+my $cur_auth_id=insert_record($db,'User_auth',$new_record);
+if ($cur_auth_id) {
+    my $msg = "New ip created by netflow! ip: $ip";
+    db_log_warning($db,$msg,$cur_auth_id);
+    sendEmail("WARN! ".get_first_line($msg),$msg,1) if ($send_alert);
+    }
+return $cur_auth_id;
+}
+
+#--------------------------------------------------------------------------------------------------------------
+
+sub get_dynamic_ou {
+my $db = shift;
+my @dynamic=();
+my @ou_list = get_records_sql($db,"SELECT id FROM OU WHERE dynamic = 1");
+foreach my $group (@ou_list) {
+    next if (!$group);
+    push(@dynamic,$group->{id});
+    }
+return wantarray ? @dynamic : \@dynamic;
+}
+
+#--------------------------------------------------------------------------------------------------------------
+
+sub get_default_ou {
+my $db = shift;
+my @dynamic=();
+my $ou = get_record_sql($db,"SELECT id FROM OU WHERE default_users = 1");
+if (!$ou) { push(@dynamic,0); } else { push(@dynamic,$ou->{'id'}); }
+$ou = get_record_sql($db,"SELECT id FROM OU WHERE default_hotspot = 1");
+if ($ou) { push(@dynamic,$ou->{id}); }
+return wantarray ? @dynamic : \@dynamic;
+}
+
+#--------------------------------------------------------------------------------------------------------------
+
+sub is_dynamic_ou {
+my $db = shift;
+my $ou_id = shift;
+my @dynamic=get_dynamic_ou($db);
+if (in_array(\@dynamic,$ou_id)) { return 1; }
+return 0;
+}
+
+#--------------------------------------------------------------------------------------------------------------
+
+sub is_default_ou {
+my $db = shift;
+my $ou_id = shift;
+my @dynamic=get_default_ou($db);
+if (in_array(\@dynamic,$ou_id)) { return 1; }
+return 0;
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub get_subnets_ref {
+my $db = shift;
+my @list=get_records_sql($db,'SELECT * FROM subnets ORDER BY ip_int_start');
+my $list_ref;
+foreach my $net (@list) {
+next if (!$net->{subnet});
+$list_ref->{$net->{subnet}}=$net;
+}
+return $list_ref;
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub get_device_by_ip {
+my $db = shift;
+my $ip = shift;
+my $netdev=get_record_sql($db,'SELECT * FROM devices WHERE ip="'.$ip.'"');
+if ($netdev and $netdev->{id}>0) { return $netdev; }
+my $auth_rec=get_record_sql($db,'SELECT user_id FROM User_auth WHERE ip="'.$ip.'" and deleted=0');
+if ($auth_rec and $auth_rec->{user_id}>0) {
+    $netdev=get_record_sql($db,'SELECT * FROM devices WHERE user_id='.$auth_rec->{user_id});
+    return $netdev;
+    }
+return;
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub recalc_quotes {
+
+my $db = shift;
+my $calc_id = shift || $$;
+
+return if (!get_option($db,54));
+
+clean_variables($db);
+
+return if (Get_Variable($db,'RECALC'));
+
+my $timeshift = get_option($db,55);
+
+Set_Variable($db,'RECALC',$calc_id,time()+$timeshift*60);
+
+my $now = DateTime->now(time_zone=>'local');
+my $day_start = $db->quote($now->ymd("-")." 00:00:00");
+my $day_dur = DateTime::Duration->new( days => 1 );
+my $tomorrow = $now+$day_dur;
+my $day_stop = $db->quote($tomorrow->ymd("-")." 00:00:00");
+
+$now->set(day=>1);
+my $month_start=$db->quote($now->ymd("-")." 00:00:00");
+my $month_dur = DateTime::Duration->new( months => 1 );
+my $next_month = $now + $month_dur;
+$next_month->set(day=>1);
+my $month_stop = $db->quote($next_month->ymd("-")." 00:00:00");
+
+#get user limits
+my $user_auth_list_sql="SELECT A.id as auth_id, U.id, U.day_quota, U.month_quota, A.day_quota as auth_day, A.month_quota as auth_month FROM User_auth as A,User_list as U WHERE A.deleted=0 ORDER by user_id";
+my @authlist_ref = get_records_sql($db,$user_auth_list_sql);
+my %user_stats;
+my %auth_info;
+foreach my $row (@authlist_ref) {
+    $auth_info{$row->{auth_id}}{user_id}=$row->{id};
+    $auth_info{$row->{auth_id}}{day_limit}=$row->{auth_day};
+    $auth_info{$row->{auth_id}}{month_limit}=$row->{auth_month};
+    $auth_info{$row->{auth_id}}{day}=0;
+    $auth_info{$row->{auth_id}}{month}=0;
+    $user_stats{$row->{id}}{day_limit}=$row->{day_quota};
+    $user_stats{$row->{id}}{month_limit}=$row->{month_quota};
+    $user_stats{$row->{id}}{day}=0;
+    $user_stats{$row->{id}}{month}=0;
+}
+
+#recalc quotes - global
+#day
+my $day_sql="SELECT User_stats.auth_id, SUM( byte_in + byte_out ) AS traf_all FROM User_stats
+WHERE User_stats.`timestamp`>= $day_start AND User_stats.`timestamp`< $day_stop GROUP BY User_stats.auth_id";
+my @day_stats = get_records_sql($db,$day_sql);
+foreach my $row (@day_stats) {
+    my $user_id=$auth_info{$row->{auth_id}}{user_id};
+    $auth_info{$row->{auth_id}}{day}=$row->{traf_all};
+    $user_stats{$user_id}{day}+=$row->{traf_all};
+}
+
+#month
+my $month_sql="SELECT User_stats.auth_id, SUM( byte_in + byte_out ) AS traf_all FROM User_stats
+WHERE User_stats.`timestamp`>= $month_start AND User_stats.`timestamp`< $month_stop GROUP BY User_stats.auth_id";
+my @month_stats = get_records_sql($db,$month_sql);
+foreach my $row (@month_stats) {
+    my $user_id=$auth_info{$row->{auth_id}}{user_id};
+    $auth_info{$row->{auth_id}}{month}=$row->{traf_all};
+    $user_stats{$user_id}{month}+=$row->{traf_all};
+}
+
+foreach my $auth_id (keys %auth_info) {
+next if (!$auth_info{$auth_id}{day_limit});
+next if (!$auth_info{$auth_id}{month_limit});
+my $day_limit=$auth_info{$auth_id}{day_limit}*$KB*$KB;
+my $month_limit=$auth_info{$auth_id}{month_limit}*$KB*$KB;
+my $blocked_d=($auth_info{$auth_id}{day}>$day_limit);
+my $blocked_m=($auth_info{$auth_id}{month}>$month_limit);
+if ($blocked_d or $blocked_m) {
+    my $history_msg;
+    if ($blocked_d) { $history_msg=printf "Day quota limit found for auth_id: $auth_id - Current: %d Max: %d",$auth_info{$auth_id}{day},$day_limit; }
+    if ($blocked_m) { $history_msg=printf "Month quota limit found for auth_id: $auth_id - Current: %d Max: %d",$auth_info{$auth_id}{month},$month_limit; }
+    do_sql($db,"UPDATE User_auth set blocked=1, changed=1 where id=$auth_id");
+    db_log_verbose($db,$history_msg);
+    }
+}
+
+foreach my $user_id (keys %user_stats) {
+next if (!$user_stats{$user_id}{day_limit});
+next if (!$user_stats{$user_id}{month_limit});
+my $day_limit=$user_stats{$user_id}{day_limit}*$KB*$KB;
+my $month_limit=$user_stats{$user_id}{month_limit}*$KB*$KB;
+my $blocked_d=($user_stats{$user_id}{day}>$day_limit);
+my $blocked_m=($user_stats{$user_id}{month}>$month_limit);
+if ($blocked_d or $blocked_m) {
+    my $history_msg;
+    if ($blocked_d) { $history_msg=printf "Day quota limit found for user_id: $user_id - Current: %d Max: %d",$user_stats{$user_id}{day},$day_limit; }
+    if ($blocked_m) { $history_msg=printf "Month quota limit found for user_id: $user_id - Current: %d Max: %d",$user_stats{$user_id}{month},$month_limit; }
+    do_sql($db,"UPDATE User_user set blocked=1 where id=$user_id");
+    do_sql($db,"UPDATE User_auth set blocked=1, changed=1 where user_id=$user_id");
+    db_log_verbose($db,$history_msg);
+    }
+}
+Del_Variable($db,'RECALC');
+}
+
+#--------------------------------------------------------------------------------
+
+sub process_dhcp_request {
+
+my ($db, $type, $mac, $ip, $hostname, $client_id, $circuit_id, $remote_id) = @_;
+
+return if (!$type);
+return if ($type!~/(old|add|del)/i);
+
+my $client_hostname='';
+if ($hostname and ($hostname ne "undef" or $hostname !~ /UNDEFINED/i)) { $client_hostname=$hostname; }
+
+my $auth_network = $office_networks->match_string($ip);
+if (!$auth_network) {
+    log_error("Unknown network in dhcp request! IP: $ip");
+    return;
+    }
+
+if (!$circuit_id) { $circuit_id=''; }
+if (!$client_id) { $client_id = ''; }
+if (!$remote_id) { $remote_id = ''; }
+
+my $timestamp=time();
+
+my $ip_aton=StrToIp($ip);
+$mac=mac_splitted(isc_mac_simplify($mac));
+
+my $dhcp_event_time = GetNowTime($timestamp);
+
+my $dhcp_record;
+$dhcp_record->{'mac'}=$mac;
+$dhcp_record->{'ip'}=$ip;
+$dhcp_record->{'ip_aton'}=$ip_aton;
+$dhcp_record->{'hostname'}=$client_hostname;
+$dhcp_record->{'network'}=$auth_network;
+$dhcp_record->{'type'}=$type;
+$dhcp_record->{'hostname_utf8'}=$client_hostname;
+$dhcp_record->{'timestamp'} = $timestamp;
+$dhcp_record->{'last_time'} = time();
+$dhcp_record->{'circuit-id'} = $circuit_id;
+$dhcp_record->{'client-id'} = $client_id;
+$dhcp_record->{'remote-id'} = $remote_id;
+$dhcp_record->{'hotspot'}=is_hotspot($dbh,$dhcp_record->{ip});
+
+#search actual record
+my $auth_record = get_record_sql($db,'SELECT * FROM User_auth WHERE ip="'.$dhcp_record->{ip}.'" and mac="'.$mac.'" and deleted=0 ORDER BY last_found DESC');
+
+#if record not found and type del => next event
+if (!$auth_record and $type eq 'del') { return; }
+
+#if record not found - create it
+if (!$auth_record and $type=~/(add|old)/i) {
+#        db_log_warning($db,"Record for dhcp request type: ".$type." ip=".$dhcp_record->{ip}." and mac=".$mac." does not exists!");
+        my $res_id = resurrection_auth($db,$dhcp_record);
+        if (!$res_id) {  db_log_error($db,"Error creating an ip address record for ip=".$dhcp_record->{ip}." and mac=".$mac."!");  return; }
+        $auth_record = get_record_sql($db,'SELECT * FROM User_auth WHERE id='.$res_id);
+        db_log_info($db,"Check for new auth. Found id: $res_id",$res_id);
+        }
+
+my $auth_id = $auth_record->{id};
+my $auth_ou_id = $auth_record->{ou_id};
+
+$dhcp_record->{'auth_id'} = $auth_id;
+$dhcp_record->{'auth_ou_id'} = $auth_ou_id;
+
+log_debug(uc($type).">>");
+log_debug("MAC:        ".$dhcp_record->{'mac'});
+log_debug("IP:         ".$dhcp_record->{'ip'});
+log_debug("CIRCUIT-ID: ".$dhcp_record->{'circuit-id'});
+log_debug("REMOTE-ID:  ".$dhcp_record->{'remote-id'});
+log_debug("HOSTNAME:   ".$dhcp_record->{'hostname'});
+log_debug("TYPE:       ".$dhcp_record->{'type'});
+log_debug("TIME:       ".$dhcp_event_time);
+log_debug("AUTH_ID:    ".$auth_id);
+log_debug("END GET");
+
+update_dns_record_by_dhcp($db,$dhcp_record,$auth_record);
+
+if ($type=~/add/i and $dhcp_record->{hostname_utf8}) {
+                my $auth_rec;
+                $auth_rec->{dhcp_hostname} = $dhcp_record->{hostname_utf8};
+                $auth_rec->{dhcp_time}=$dhcp_event_time;
+                $auth_rec->{arp_found}=$dhcp_event_time;
+                $auth_rec->{created_by}='dhcp';
+                db_log_verbose($db,"Add lease by dhcp event for dynamic clients id: $auth_id ip: $dhcp_record->{ip}",$auth_id);
+                update_record($db,'User_auth',$auth_rec,"id=$auth_id");
+                }
+
+if ($type=~/old/i) {
+                my $auth_rec;
+                $auth_rec->{dhcp_action}=$type;
+                $auth_rec->{dhcp_time}=$dhcp_event_time;
+                $auth_rec->{created_by}='dhcp';
+                $auth_rec->{arp_found}=$dhcp_event_time;
+                db_log_verbose($db,"Update lease by dhcp event for dynamic clients id: $auth_id ip: $dhcp_record->{ip}",$auth_id);
+                update_record($db,'User_auth',$auth_rec,"id=$auth_id");
+                }
+
+if ($type=~/del/i and $auth_id) {
+                if ($auth_record->{dhcp_time} =~ /([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})/) {
+                    my $d_time = mktime($6,$5,$4,$3,$2-1,$1-1900);
+                    if (time()-$d_time>60 and (is_dynamic_ou($db,$auth_ou_id) or is_default_ou($db,$auth_ou_id))) {
+                        db_log_info($db,"Remove user ip record by dhcp release event for dynamic clients id: $auth_id ip: $dhcp_record->{ip}",$auth_id);
+                        my $auth_rec;
+                        $auth_rec->{dhcp_action}=$type;
+                        $auth_rec->{dhcp_time}=$dhcp_event_time;
+                        update_record($db,'User_auth',$auth_rec,"id=$auth_id");
+                        #remove user auth record if it belongs to the default pool or it is dynamic
+                        if (is_default_ou($db,$auth_ou_id) or (is_dynamic_ou($db,$auth_ou_id) and $auth_record->{dynamic})) {
+                                delete_user_auth($db,$auth_id);
+                                my $u_count=get_count_records($db,'User_auth','deleted=0 and user_id='.$auth_record->{'user_id'});
+                                if (!$u_count) { delete_user($db,$auth_record->{'user_id'}); }
+                                }
+                        }
+                    }
+                }
+
+if ($dhcp_record->{hotspot} and $ignore_hotspot_dhcp_log) { return $dhcp_record; }
+
+if ($ignore_update_dhcp_event and $type=~/old/i) { return $dhcp_record; }
+
+my $dhcp_log;
+if (!$auth_id) { $auth_id=0; }
+$dhcp_log->{'auth_id'} = $auth_id;
+$dhcp_log->{'ip'} = $dhcp_record->{'ip'};
+$dhcp_log->{'ip_int'} = $dhcp_record->{'ip_aton'};
+$dhcp_log->{'mac'} = $dhcp_record->{'mac'};
+$dhcp_log->{'action'} = $type;
+$dhcp_log->{'dhcp_hostname'} = $dhcp_record->{'hostname_utf8'};
+$dhcp_log->{'timestamp'} = $dhcp_event_time;
+$dhcp_log->{'circuit-id'} = $circuit_id;
+$dhcp_log->{'client-id'} = $client_id;
+$dhcp_log->{'remote-id'} = $remote_id;
+
+insert_record($db,'dhcp_log',$dhcp_log);
+
+return $dhcp_record;
+}
+
+1;
+}

Разлика између датотеке није приказан због своје велике величине
+ 485 - 337
scripts/eyelib/database.pm


+ 41 - 0
scripts/eyelib/main.pm

@@ -65,6 +65,9 @@ translit
 crypt_string
 decrypt_string
 netdev_set_auth
+GetNowTime
+GetUnixTimeByStr
+GetTimeStrByUnixTime
 );
 
 BEGIN
@@ -832,6 +835,44 @@ my $result = encode_base64($cipher_handle->encrypt($simple_string));
 return $result;
 }
 
+#---------------------------------------------------------------------------------------------------------------
+
+sub GetNowTime {
+my ($sec,$min,$hour,$day,$month,$year,$zone) = localtime(time());
+$month += 1;
+$year += 1900;
+my $now_str=sprintf "%04d-%02d-%02d %02d:%02d:%02d",$year,$month,$day,$hour,$min,$sec;
+return $now_str;
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub GetUnixTimeByStr {
+my $time_str = shift;
+$time_str =~s/\//-/g;
+$time_str = trim($time_str);
+my ($sec,$min,$hour,$day,$mon,$year) = (localtime())[0,1,2,3,4,5];
+$year+=1900;
+$mon++;
+if ($time_str =~/^([0-9]{2,4})\-([0-9]{1,2})-([0-9]{1,2})\s+/) {
+$year = $1; $mon = $2; $day = $3;
+}
+if ($time_str =~/([0-9]{1,2})\:([0-9]{1,2})\:([0-9]{1,2})$/) {
+$hour = $1; $min = $2; $sec = $3;
+}
+my $result = mktime($sec,$min,$hour,$day,$mon-1,$year-1900);
+return $result;
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub GetTimeStrByUnixTime {
+my $time = shift || time();
+my ($sec, $min, $hour, $mday, $mon, $year) = (localtime($time))[0,1,2,3,4,5];
+my $result = strftime("%Y-%m-%d %H:%M:%S",$sec, $min, $hour, $mday, $mon, $year);
+return $result;
+}
+
 #---------------------------------------------------------------------------------------------------------
 
 # Helper function for HTML escaping

+ 1 - 0
scripts/eyelib/nagios.pm

@@ -12,6 +12,7 @@ use vars qw(@EXPORT @ISA);
 use eyelib::config;
 use eyelib::main;
 use eyelib::database;
+use eyelib::common;
 use eyelib::snmp;
 use Time::Local;
 use Data::Dumper;

+ 1 - 0
scripts/fetch_new_arp.pl

@@ -23,6 +23,7 @@ use eyelib::main;
 use eyelib::net_utils;
 use eyelib::snmp;
 use eyelib::database;
+use eyelib::common;
 use NetAddr::IP;
 use Fcntl qw(:flock);
 use Parallel::ForkManager;

+ 1 - 0
scripts/garbage.pl

@@ -17,6 +17,7 @@ use DBI;
 use Date::Parse;
 use eyelib::config;
 use eyelib::database;
+use eyelib::common;
 use eyelib::net_utils;
 use eyelib::main;
 use DateTime;

+ 1 - 0
scripts/gen_nagios_config.pl

@@ -24,6 +24,7 @@ use eyelib::main;
 use eyelib::nagios;
 use eyelib::snmp;
 use eyelib::database;
+use eyelib::common;
 use Fcntl qw(:flock);
 
 open(SELF,"<",$0) or die "Cannot open $0 - $!";

+ 1 - 0
scripts/hmonitor.pl

@@ -16,6 +16,7 @@ use Time::Local;
 use FileHandle;
 use eyelib::config;
 use eyelib::database;
+use eyelib::common;
 use eyelib::main;
 use eyelib::nagios;
 use Data::Dumper;

+ 1 - 0
scripts/print-dnsmasq.pl

@@ -21,6 +21,7 @@ use Data::Dumper;
 use eyelib::config;
 use eyelib::main;
 use eyelib::database;
+use eyelib::common;
 use eyelib::net_utils;
 use File::Basename;
 use File::Path;

+ 1 - 0
scripts/restart_port_snmp.pl

@@ -14,6 +14,7 @@ use eyelib::config;
 use eyelib::main;
 use eyelib::net_utils;
 use eyelib::database;
+use eyelib::common;
 use eyelib::snmp;
 use Net::SNMP qw(:snmp);
 

+ 1 - 0
scripts/run/syslog-stat.pid

@@ -0,0 +1 @@
+61020

+ 1 - 0
scripts/stat-sync.pl

@@ -16,6 +16,7 @@ use Data::Dumper;
 use eyelib::config;
 use eyelib::main;
 use eyelib::database;
+use eyelib::common;
 use eyelib::net_utils;
 use strict;
 use warnings;

+ 1 - 0
scripts/sync_mikrotik.pl

@@ -23,6 +23,7 @@ use Net::Patricia;
 use Date::Parse;
 use eyelib::net_utils;
 use eyelib::database;
+use eyelib::common;
 use DBI;
 use Fcntl qw(:flock);
 use Parallel::ForkManager;

+ 1 - 0
scripts/sync_mikrotik_poe_monitor.pl

@@ -17,6 +17,7 @@ use Net::Patricia;
 use Date::Parse;
 use eyelib::net_utils;
 use eyelib::database;
+use eyelib::common;
 use DBI;
 use utf8;
 use Fcntl qw(:flock);

+ 1 - 0
scripts/syslog-stat.pl

@@ -18,6 +18,7 @@ use FileHandle;
 use eyelib::config;
 use eyelib::main;
 use eyelib::database;
+use eyelib::common;
 use Data::Dumper;
 use DBI;
 use Time::Local;

+ 1 - 0
scripts/updates/2-8-0/after_sql.pl

@@ -13,6 +13,7 @@ use lib "/opt/Eye/scripts";
 use eyelib::config;
 use eyelib::main;
 use eyelib::database;
+use eyelib::common;
 use strict;
 use warnings;
 use Data::Dumper;

+ 1 - 0
scripts/updates/2-9-1/readme.txt

@@ -0,0 +1 @@
+release 2.9.1

+ 1 - 0
scripts/updates/db-patch-mysql-utf8.pl

@@ -11,6 +11,7 @@ use Data::Dumper;
 use eyelib::config;
 use eyelib::main;
 use eyelib::database;
+use eyelib::common;
 use strict;
 use warnings;
 

+ 1 - 0
scripts/updates/upgrade.pl

@@ -14,6 +14,7 @@ use lib "/opt/Eye/scripts";
 use eyelib::config;
 use eyelib::main;
 use eyelib::database;
+use eyelib::common;
 use strict;
 use warnings;
 

+ 1 - 0
scripts/utils/backupcfg.pl

@@ -17,6 +17,7 @@ use Data::Dumper;
 use eyelib::config;
 use eyelib::main;
 use eyelib::database;
+use eyelib::common;
 use eyelib::net_utils;
 use eyelib::cmd;
 use Fcntl qw(:flock);

+ 1 - 0
scripts/utils/bind/print-dns-zones.pl

@@ -14,6 +14,7 @@ use Data::Dumper;
 use eyelib::config;
 use eyelib::main;
 use eyelib::database;
+use eyelib::common;
 
 setpriority(0,0,19);
 

+ 1 - 0
scripts/utils/import/import_auth.pl

@@ -16,6 +16,7 @@ use Data::Dumper;
 use eyelib::config;
 use eyelib::main;
 use eyelib::database;
+use eyelib::common;
 use eyelib::net_utils;
 use Net::Patricia;
 use strict;

+ 1 - 0
scripts/utils/mac-oids/update-mac-vendors.pl

@@ -15,6 +15,7 @@ use Data::Dumper;
 use eyelib::config;
 use eyelib::main;
 use eyelib::database;
+use eyelib::common;
 use eyelib::net_utils;
 use strict;
 use warnings;

+ 1 - 0
scripts/utils/nf_calc

@@ -14,6 +14,7 @@ use Socket;
 use eyelib::config;
 use eyelib::main;
 use eyelib::database;
+use eyelib::common;
 
 my @router_list = get_records_sql($dbh,"SELECT D.*, DM.model_name, B.name AS building_name FROM devices D
 LEFT JOIN device_models DM ON D.device_model_id = DM.id

+ 1 - 0
scripts/utils/parse_flow.pl

@@ -21,6 +21,7 @@ use eyelib::config;
 use eyelib::main;
 use eyelib::net_utils;
 use eyelib::database;
+use eyelib::common;
 use Parallel::ForkManager;
 
 if (!$ARGV[0]) { exit 110; }

+ 1 - 0
scripts/utils/print-ou-ip.pl

@@ -15,6 +15,7 @@ use eyelib::config;
 use eyelib::main;
 use eyelib::net_utils;
 use eyelib::database;
+use eyelib::common;
 
 my $OU_ID=$ARGV[0];
 my $ou_filter=" and L.ou_id=$OU_ID ";

+ 1 - 0
scripts/utils/print_cacti_create.pl

@@ -9,6 +9,7 @@ use DBI;
 use Date::Parse;
 use eyelib::config;
 use eyelib::database;
+use eyelib::common;
 use utf8;
 
 

+ 1 - 0
scripts/utils/print_cacti_hosts.pl

@@ -10,6 +10,7 @@ use DBI;
 use Date::Parse;
 use eyelib::config;
 use eyelib::database;
+use eyelib::common;
 use utf8;
 
 ##### unknown mac clean ############

+ 1 - 0
scripts/utils/print_devices.pl

@@ -17,6 +17,7 @@ use eyelib::config;
 use eyelib::main;
 use eyelib::net_utils;
 use eyelib::database;
+use eyelib::common;
 use NetAddr::IP;
 
 setpriority(0,0,19);

+ 1 - 0
scripts/utils/radius/print_huntgroups.pl

@@ -14,6 +14,7 @@ use eyelib::config;
 use eyelib::main;
 use eyelib::net_utils;
 use eyelib::database;
+use eyelib::common;
 
 my %huntgroups=(
 '2'=>'eltex',

+ 1 - 0
scripts/utils/reaply_rules.pl

@@ -21,6 +21,7 @@ use Data::Dumper;
 use eyelib::config;
 use eyelib::main;
 use eyelib::database;
+use eyelib::common;
 use eyelib::net_utils;
 use File::Basename;
 use File::Path;

+ 1 - 0
scripts/utils/scan_ipcam.pl

@@ -20,6 +20,7 @@ use Net::SNMP qw(ticks_to_time TRANSLATE_NONE);
 use eyelib::config;
 use eyelib::main;
 use eyelib::database;
+use eyelib::common;
 use Fcntl qw(:flock);
 
 open(SELF,"<",$0) or die "Cannot open $0 - $!";

+ 1 - 0
scripts/utils/set_dns_record.pl

@@ -19,6 +19,7 @@ use Data::Dumper;
 use eyelib::config;
 use eyelib::main;
 use eyelib::database;
+use eyelib::common;
 use eyelib::net_utils;
 use File::Basename;
 use File::Path;

+ 1 - 0
scripts/utils/set_port_descr.pl

@@ -20,6 +20,7 @@ use eyelib::config;
 use eyelib::main;
 use eyelib::net_utils;
 use eyelib::database;
+use eyelib::common;
 use eyelib::snmp;
 use eyelib::cmd;
 use Net::SNMP qw(:snmp);

+ 1 - 0
scripts/utils/win32/print-dhcpd-netsh.pl

@@ -14,6 +14,7 @@ use eyelib::config;
 use eyelib::main;
 use eyelib::net_utils;
 use eyelib::database;
+use eyelib::common;
 
 my $time_shift=$ARGV[0];
 

+ 1 - 0
scripts/utils/win32/sync-dhcpd-netsh.pl

@@ -14,6 +14,7 @@ use eyelib::config;
 use eyelib::main;
 use eyelib::net_utils;
 use eyelib::database;
+use eyelib::common;
 use Text::Iconv;
 
 exit;

Неке датотеке нису приказане због велике количине промена