Делаем админпанель для MySQL и MongoDB на Node.js

    Хотим «phpMyAdmin» (читай web GUI) для ноды


    Отсутствие универсальных веб-интерфейсов для управления распространенными СУБД, несколько усложняет освоение Node.js, а разворачивать рядом другой веб-сервер и другой язык с инфраструктурой, ой как не хочется. Открывать порты и управлять базами, подключаясь с другого сервера или со своего рабочего компьютера — это и неудобно и есть соображения безопасности. Поэтому мы решили включить такой инструмент в платформу для веб-приложений Impress, которую анонсировали, о которой я немного писал и которая доступна в открытом коде для всеобщей пользы. Задумка такая: реализовать простой и удобный унифицированный интерфейс для СУБД, которые чаще всего применяются в связке с Node.js, позаботиться о быстром развертывании (просто скопировать папку) и независимости от среды. В бета-версии уже поддерживаются MySQL, MongoDB и в скором времени очередь дойдет до PostgreSQL и Oracle.

    Возможности DBMI


    Для всех операций с БД используется скаффолдинг, т.е. построение интерфейсов, запросов и всех операций обработки данных на основе динамического получения метаданных о структуре БД или интроспекции структур СУБД. Интерфейс представлен ниже на картинке. Дерево трехуровневое, первый уровень — соединения с БД (они, естественно, пока двух типов), второй уровень — базы данных, третий уровень — коллекции (для Mongo) и таблицы (для MySQL). На узлах дерева можно вызывать контекстное меню правой кнопкой мыши.



    Функциональность же такая:
    • Отображение таблиц и коллекций. Это естественный способ редактирования для MySQL, но и для MongoDB мы применили грид, столбцы — это поля, собранные из всех записей коллекции, думаю, что такое редактирование будет удобнее, чем правка JSON, дерево или инспектор свойств.
    • Фильтры по полям. В заголовке грида есть строка для фильтра, для MongoDB она работает только по строгому совпадению, а для MySQL, кроме полного совпадения есть еще синтаксис условий фильтрации, вводить без кавычек: ">5" — больше 5 и все другие знаки сравнения как в SQL, т.е. «не равно 5» пишется как "<>5", диапазоны «5..10» — преобразовывается в BETWEEN, шаблоны с символами "*" (любая последовательность, даже пустая, преобразовывается в "%" в SQL LIKE-выражении) и "?" (обязательно любой символ, преобразовывается в "_" в SQL LIKE-выражении), например, "*str?" (такие символы привычнее для пользователей), одно значение из множества "(1,2,4,10,11)" — преобразовывается в SQL IN-выражение.
    • Вставка записей. Работает пока только для MySQL. Последняя пустая строка грида служит для вставки, если после редактирования одного поля уже можно сделать INSERT, то запись добавляется сразу, в колонке в PRIMARY KEY появляется ее ID, а дальнейшее редактирование уже через UPDATE, но если ограничения «NOT NULL» требуют заполнить более одного поля, то INSERT происходит только после того, как все нужные поля заполнены).
    • Редактирование записей в таблицах и коллекциях (работает для Mongo всегда, а для MySQL пока только при наличии не составного первичного ключа, т.е. ID записи, позже будет поддержка составных primary key, составных и не составных unique index и уже в случае, если ничего такого не найдено, то в WHERE для UPDATE оператора будем помещать все поля редактируемой записи.
    • Удаление записей из таблиц и коллекций. Для Mongo работает, для MySQL работает пока тоже по не составному PRIMARY KEY.
    • Лог SQL операторов. Естественно, будет поддерживаться только для реляционных СУБД. Возможно, потом для MongoDB будем выводить в лог JavaScript код для копирования и вставки в проекты.
    • Создание и удаление баз. Для MySQL работает, а для Mongo есть особенность, база создается только если в ней сразу создать хоть одну коллекцию, иначе при обновлении экрана база пропадет, это особенности СУБД, но возможно, я чего-то не знаю, пролежите способ, если я не прав.
    • Переименование баз. Работает как в Mongo, но не работает пока в MySQL, ибо, как Вам известно, RENAME DATABASE в MySQL был введен и потом ликвидирован, а для переименования баз нужно создать новую с новым именем, скопировать туда все таблицы, потом скопировать пользователей и права доступа, возможно, еще какие-то вещи нужно будет учесть, но пока до этого не добрались.
    • Создание коллекций и таблиц. Пока работает только в Mongo, но скоро допишем конструктор таблиц для MySQL.
    • Удаление коллекций и таблиц. Работает как в MySQL и в Mongo, но в MySQL удалению могут препятствовать связи между таблицами, (FOREIGN KEYS), в этом случае удаление не проходит и таблица опять появляется в дереве.
    • Переименование коллекций и таблиц. Работает как в MySQL и в Mongo.

    Установка и настройка


    Полная процедура настройки такая (это из-за безопасности, но в, большинстве случаев, она существенно сокращается):
    1. Создаем каталог проекта и в устанавливаем в него Impress из репозитория npm.
    $ npm install impress
    

    2. Копируем из папки /node_modules/impress/examples/copyContentToProjectFolder все содержимое в корневой каталог проекта.
    3. В файле config.js прописываем нужные нам базы данных (конекшенстринги к ним) в разделе «databases».
    4. В файле /sites/localhost/dbmi/access.js находим настройки доступа
    module.exports = {
    	guests: true, // позволять или нет заходить без автентификации
    	logged: true, // позволять или нет заходить автентифицированным пользователям
    	http:   true, // доступно или нет по http
    	https:  true, // доступно или нет по https
    	groups: [] // пользователям каких групп доступно (массив строк)
    }
    

    5. Для того, чтобы закрыть админпанель паролем, нужно создать базу пользователей при помощи команды «node setup.js». И потом запустить систему «node server.js». Зайти на 127.0.0.1 и зарегистрироваться («Create account» справа вверху). После этого, можно закрыть возможность регистрации, добавив в /sites/localhost/api/auth/register.json файл access.js и задав в нем guests = false.
    6. Если хочется ходить к базе через HTTPS, то положите в корень проекта свои server.key и server.cer файлы, а так же поправьте в config.js параметр servers.www.protocol = «https».
    7. Ну и заходить можно через 127.0.0.1/dbmi или на 127.0.0.1 и там в меню слева выбрать вреди примеров пункт «DB Management Interface».

    Планы развития DBMI


    Весь модуль DBMI занимает сейчас 70кб, половина из которых состоит из css и html, примерно четверть — серверный js, и еще четверть — клиентского. Думаю, что это не так много, чтобы разобраться в коде, если что-то хочется поправить или дописать. Небольшой размер, это еще и потому, что платформа Impress (нашего же изготовления), производить большую часть инфраструктурной работы, как маршрутизацию URLов, обработку шаблонов, огромное количество вспомогательных функций по работе с базами данных, особенно с MySQL (методы доступа к данным, методы интроспекции, методы генерации запросов и т.д.). Что планируем дописывать мы в ближайшее время:
    • Исполнение произвольных SQL запросов. В т.ч. CREATE TABLE, DROP..., ALTER… и т.д. Сохранение истории этих запросов и вызов их в редактор запросов в дальнейшем.
    • Сохранение фильтров в гридах в виде именованных узлов четвертого уровня в дереве. И написание кастомного SQL-запроса, который тоже можно будет сохранить с заданным именем, как четвертый уровень дерева и работать с его результатами тоже в том же гриде.
    • Переход по связям между таблицами: переход к «родительской» таблице или к «дочерней» (по связям один-ко-многим).
    • Генерация форм для редактирования и вставки записей, таким же способом скаффолдинга, как и гридов.
    • Отображение значений из справочников, вместо ID. И, соответственно, при редактировании использование выпадающих списков для отображения справочников.
    • Генерация таблиц из их JSON-метаописания, см. примеры в /node_modules/impress/schemas. Генерация уже работает, но она еще не связана с DBMI, на результат генерации можно посмотреть запустив:

    require('impress');
    var schemaCore = require('./schemas/impress.core.schema.js'),
    	schemaCMS = require('./schemas/impress.cms.schema.js');
    impress.init(function() {
    	console.log(db.schema.mysql.generateScript(schemaCore, true).script);
    	console.log(db.schema.mysql.generateScript(schemaCMS, true).script);
    });
    


    Движется шустро, но нужно штука такая, что всем нужно и желательно — еще шустрее. Так что, присоединяйтесь к тестированию и доработке, будем рады Вашему участию.

    UPD: Добавлена возможность исполнять введенный в редактор (на закладке «Command») SQL код и вывод результатов и ошибок исполнения в лог (на закладке «Logs»).
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 22

      +7
      Открывать порты и управлять базами, подключаясь с другого сервера или со своего рабочего компьютера — это и неудобно и есть соображения безопасности
      А открывать web-морду безопасно? И да, мне вот удобнее подключиться десктопным клиентом. Интерфейс отзывчивее и возможностей больше. Так что это субъективно.
      А так, молодцы, начинание хорошее.
        0
        Открыть веб-морду безопасно, если есть SSL-шифрование трафика и аутентифиуация, что мы и реализовали.
          +11
          так же безопасно соединиться с десктопного клиента по ssh-тоннелю
            +1
            вот вот, Valentina и Robomongo ни на что не променяю :) Хотя и для веб интерфейса есть ситуации, когда его использование оправдано.
              –1
              Вообще хочется допилить веб-интерфейс до такого состояния, что он будет доступен обычному пользователю. Для этого нужно только ввести права доступа к разным данным с настройкой этих прав админом и подстановка в WHERE условий ID пользователя из сессии, если нужно ему отфильтровать его данные. Ну и убрать панель с SQL-запросами. Это будет куда удобнее, чем пользователи, ходившие в phpMyAdmin, напуганные программистами, что они могут все уничтожить и делающие там по 2 клика в минуту трясущимися руками, вычитывая в ужасе все что есть на экране. Я такое наблюдал в нескольких проектах, и это, к сожалению, не редкость.
                +3
                Честно говоря не совсем понимаю зачем пользователям вообще знать о phpMyAdmin и что им там делать :)
                Для них-то админки и создаются.
                  –1
                  Это понятно, но случаи такие были зафиксированы, похоже, программисты этих проектов были совсем не гуманистами )
        0
        Планируется ли поддержка SQL Server?
          +1
          Не планируется, это не типичный выбор для ноды. Напиши сам, Андрюха, сделай Майкрософту приятно.
            –2
            Андрюха, ты шо, обиделся? Там делов то на 2 часа, основные SELECT, UPDATE, DELETE, ALTER и т.д. выражения же не сильно отличаются, так что, добавить поддержку любой SQL-ной СУБД не сложно. Вот добавить туда другие NoSQL базы будет посложнее (CouchDB, memcached, Redis хотелось бы реализовать).
            +1
            И остается один вопрос: зачем?
              0
              А вот зачем, из-за простоты своей реализации — это хорошая основа для разработки кастомных интерфейсов по управлению базами данных. Кастомизировать такой редактор — дело одного дня и я сам уже для нескольких проектов быстро поднял админки на его основе, убрав вывод SQL и ограничив доступ. И теперь ими пользуются люди, ничего не смыслящие в ssh и не имеющие развернутого локально софта по управлению БД. Все универсальные средствам для управления БД, что мне попадались, для этого не годятся.
                0
                Вы допускаете людей не смыслящих в ssh до управления БД?
                  0
                  Люди, для которых эта БД является рабочим инструментом автоматизации их бизнеса, вполне в состоянии наполнить справочники, вручную задать параметры объектов, сделать выборки, которых не предусматривает фронт-энд интерфейс, найти и исправить данные, которые недоступны из фронт-энда. Так же есть постановщики заданий, специалисты по моделированию предметной области, они не обязаны знать что такое ssh, и часто не знают этого.
                    0
                    Иными словами система позволяет вносить изменения в уровень БД, минуя уровень приложения, а следовательно создавать инвалидные данные или уничтожать их, если не понравилось. Здорово!
                      0
                      Для специалистов и сотрудников, имеющих квалификацию и понимание структуры базы, но не занимающихся разработкой, это великое счастье. Кроме того, контроль целостности данных может выполняться как на уровне приложения, так и на уровне БД, это уже на выбор архитектора. Да и миновать уровень приложения часто необходимо.
                        0
                        У нас очень разные взгляды в этом вопросе, я бы сказал диаметрально противоположные.
                        Я против перескакивания уровня приложения, это может нарушить счетчики, актуализацию кеша, целостность деревьев, управление состоянием объектов, валидацию данных итпитпитп
                        Я против неуправляемого приложением контроля целостности данных, т.к. это вызывает необходимость дополнительной обработки исключений на уровне приложения, а двойную работу делать как-то лень в частности и не ДРАЙно в общем.
                        Великое счастье разработчика, для меня в квалифицированных сотрудниках способных сформулировать тз достаточное для управления информационной системой в целом, а не базы данных в частности. За последние 3 года в базу непосредственно лазил ну с 10-к раз, за последние 2 года, только при сбоях. Конечно не считая случаев настройки первичных прав.
                        А сверстать формочку или отчетик клиенту при грамотно спроектированном приложении часто занимает минуты. Это однозначно быстрее и лучше, чем сотрудники каким-нибудь БДадмином и своими шаловливыми руками будут перескакивать через уровень приложения, ломая все мыслимые и немыслимые связи. Привет дебаг!
              0
              Да, сомнительная вещь как мне кажется. ssh -L 2345:localhost:5432 my-db-server и pgadmin — делов всего ничего
              +1
              По моему интересная идея, главное допилить ее до готовности :)
              Тогда можно будет судить, насколько она востребована.

              А как реализован вывод логов sql запроса в logs?
                0
                Стараемся, со времени этой публикации, уже существенно улучшили.
                Для вывода логов же, сделали так: с клиента происходит вызов AJAX API, на сервере написали обертку вокруг драйверов, которая делает запись в логи на сервере, замеряет время выполнения и логает медленные запросы, ну и возвращает сгенерированные запросы в AJAX API, которое возвращает SQL, результат и сообщения об ощибках на клиент.
                0
                Полезная публикация. Побольше бы таких.

                Only users with full accounts can post comments. Log in, please.