Фамильный вики-движок Bonsai: итоги 2019 года

    В начале прошлого года я рассказывал про проект Bonsai — движок для создания семейного вики и фотоальбома с открытым исходным кодом. С тех пор проект планомерно развивался. За год сделано несколько фич, благодаря которым движок теперь значительно проще попробовать в у себя и приятнее использовать в дальнейшем.



    Под катом — подробности, планы на будущее и немного bounty.

    Docker-образ


    Установка первой версии Bonsai была весьма утомительным процессом из-за большого количества зависимостей: для работы необходимы рантайм .NET Core, PostgreSQL, Elasticsearch (а значит Java Runtime и плагин для поддержки русской морфологии), для сборки — еще .NET Core SDK, еще NodeJS для сборки фронта… Даже на фоне глобального усложнения современной веб-разработки это была задача только для сильных духом и многие изначально заинтересованные пользователи бросали ее на полпути.

    Хватит это терпеть!

    Теперь Bonsai поднимается в три элементарных действия за минуту:

    1. Скачать docker-compose.yml.
    2. Вписать вместо @@YOUR_EMAIL@@ и @@YOUR_IP@@ нужные значения.
    3. Выполнить docker-compose up -d

    Авторизация по паролю


    В первой версии использовался только один тип авторизации — через социальные сети. Для этого было много причин:

    • Авторизация происходит в один клик
    • Из коробки дается 2FA, восстановление пароля и прочие проверки безопасности
    • Просто поддерживать в коде Bonsai
    • Можно получить часть данных из профиля при регистрации

    К сожалению, это вызывало и ряд проблем:

    • Дополнительный сложный шаг при первоначальной установке
    • Нельзя дать доступ человеку, у которого нет соцсетей (например, пожилому родственнику)
    • Для некоторых данных (пол, возраст) соцсети требуют ручной проверки вашего приложения

    Поэтому был добавлен второй тип авторизации — по логину и паролю, который включен по умолчанию.

    Теперь шаг создания авторизационного приложения в соцсети можно пропустить. После старта Bonsai предложит зарегистрировать учетную запись администратора, где нужно будет ввести желаемый пароль — и все заработает.


    Создать новую учетную запись с паролем можно в админке:


    При использовании парольной авторизации следует помнить несколько вещей:

    • Пользователь не может восстановить собственный пароль — это может сделать только администратор. Если администратор только один, авторизуется по паролю и этот пароль забыл — придется воспользоваться скриптом для сброса, который необходимо выполнить напрямую в БД.
    • После 10 неудачных попыток подряд аккаунт также блокируется. Для разблокировки необходимо сменить пароль. Помимо ваших собственных действий блокировку могут вызвать вредоносные боты-краулеры, автоматически перебирающие пароли.
    • У одной учетной записи может быть только один тип авторизации за все время. Сначала сделать учетку с паролем, а потом добавить к ней дополнительный логин через соцсети или вообще заменить его штатными средствами нельзя — только через ручные манипуляции с БД.

    Рендеринг фамильных деревьев на стороне сервера


    Автоматическое построение фамильных деревьев — одна из самых главных возможностей Bonsai, но и самая хитрая.


    Как я рассказывал в предыдущей статье, автоматически расположить блоки оптимальным образом — очень сложная задача. Люди пишут про это научные работы, вкладывают тысячи человекочасов и продают готовые компоненты за безумные деньги. К счастью, удалось найти бесплатную библиотеку ELK.js, которая дает вполне приличные результаты.

    Проблема с ELK.js была в том, что для клиентской библиотеки она очень долго работает. Можно регулировать результат через свойство thoroughness — чем больше значение, тем лучше график, но тем дольше он генерируется. Чтобы отрендерить понятное дерево на 50 человек, приходилось ждать около 30-40 секунд на каждое открытие страницы с деревом!

    Теперь рендеринг происходит не на клиенте при каждом открытии, а на сервере при каждом изменении. Первое время после обновления контента придется подождать как раньше, зато потом страницы открываются мгновенно.

    С технической точки зрения перенос вычислений с клиента на сервер вызвал несколько трудностей. Чем запускать JS-код внутри .NET Core? Первой мыслью было использовать замечательную библиотеку Javascript Engine Switcher, которую написал Taritsyn. Увы, для моей задачи она не подошла: ни один из существующих движков не смог переварить код ELK.js. Вместо этого был использован встроенный механизм NodeServices, в котором все сразу заработало, как часы.

    Да, теперь Bonsai требует два рантайма, но благодаря докеру это не так страшно. Да, NodeServices собираются отправить на пенсию в одной из следующих версий ASP.NET Core, но сообщество собирается его поддерживать. А куда деваться? Современная веб-разработка полностью состоит из подобных компромиссов. Главное, чтобы это давало результат.

    Загрузка документов


    Теперь помимо фото и видео Bonsai поддерживает загрузку PDF-файлов. Это может быть удобно для документов — в частности, свидетельств о рождении, браке или смерти.

    Первоначально предполагалось делать для документов маленькие превью-картинки. Увы, эта идея разбилась о суровые скалы действительности: ни одна из существующих библиотек не подошла по тому или иному критерию. Были рассмотрены:

    • iText7 — несовместимость лицензии с MIT
    • PDF.js — огромное количество зависимостей, контейнер раздувался вдвое
    • Обертки для GhostScript — также проблемы с лицензией, плюс практически все заброшены и не поддерживают .NET Core

    Если я что-то упустил и святой грааль конвертации PDF в изображение все-таки существует — пожалуйста, напишите в комментариях!

    Новости на главной


    На главной странице под календарем теперь показываются последние измененные страницы и загруженные медиа-файлы:



    Обязательный дисклеймер


    Проект является некоммерческим и предоставляется «как есть». В нем есть баги. Один раз по банальному недосмотру в master проскочил код, который чуть не очистил базу. Поэтому если вы цените данные, которые вы заводите в Bonsai, то периодически, и особенно при каждом обновлении:

    Делайте бэкапы.
    ДЕЛАЙТЕ БЭКАПЫ!
    Д Е Л А Й Т Е   Б Э К А П Ы ! ! !

    Что дальше?


    Впереди еще много интересных задач, которые бы хотелось сделать за следующий год:

    • Ранжирование страниц: единая автоматическая метрика, позволяющая сортировать страницы по заполненности их данных. Позволит легко ответить вопросы «какие страницы можно показать в качестве эталона» и, наоборот, «над какими еще нужно поработать».
    • Редизайн главной страницы админки: изменения будут показываться в виде, похожем на «ленту новостей» в соцсетях.
    • Технические задачи: переход на .NET Core 3, всевозможный рефакторинг

    Также есть задачи, которые хотелось бы сделать, но у меня не хватает на них времени и компетенций. Надеюсь на помощь сообщества — если не забесплатно, то хотя бы за символическое вознаграждение. Если уверены в своих силах и хотите поучаствовать — пожалуйста, пишите мне в телеграм, обсудим.

    • Компонент календаря: используется стандартный, но он немного кривоват и не поддерживает неточные значения (2019.??.??): нужно написать полноценный.
    • Улучшение поиска: поиск в ElasticSearch иногда дает странные результаты. Скорее всего, я просто не умею пользоваться эластиком — нужно переписать адские конфиги со знанием дела.
    • Распознавание лиц: хорошо бы автоматически распознавать лица на загружаемых фото и привязывать их к страницам. Решений на .NET Core, одновременно открытых и дающих вменяемые результаты, пока не нашел.

    Репозиторий проекта доступен по адресу:

    https://github.com/impworks/bonsai.

    Если вы используете Bonsai — пожалуйста, расскажите об этом в комментариях. Буду рад критике и предложениям.

    Комментарии 31

      0
      Да, NodeServices собираются отправить на пенсию в одной из следующих версий ASP.NET Core, но сообщество собирается его поддерживать.

      Рекомендую посмотреть проект Jering.Javascript.NodeJS.
        +1
        Спасибо, кажется это оно и есть
        +2
        Возможно я не так понимаю нишу, которую закрывает программа, но генеалогическое древо это такая штука, которую делают внутри семьи. Первая ваша статья была примерно об этом же: вы хотели оцифровать домашнюю историю.

        Если всё запускается вот прямо локально и для себя, то некоторые блоки выглядят странно: например логин по e-mail и социальным сетям, вообще сам факт двухэтажной авторизации, когда по факту хватит пароля/токена для прав редактирования с открытым доступом на просмотр. От кого внутри семьи шифроваться? Я не эксперт докера, сам его плохо знаю, может там иначе нельзя, но настраивать айпи-адресацию проекта это тоже немножко… не знаю. Почему все считают, что крайне не модно использовать localhost, например?

        Если писать систему, которая должна заменить собой чемодан, который открывается раз в несколько лет чтобы поностальгировать, возможно, стоит на это и оглядываться? Portable версия с автозагрузкой, которая откроется на любом ПК даже вашими детьми через 20 лет выглядит лучше и надёжнее, чем куча технологий, превращающих продукт в сервис для ежедневного использования. Когда рядом не будет ни документации как настраивать, ни записанных паролей на бумажке, которые забылись за много лет… Я к тому, что не получится ли ситуация, что чемодан фотографий переживёт это решение и будет оставаться более надёжным и отказоустойчивым решением?

        Прошу прощения за сумбур.
          0

          Я так понимаю всмысл в том, чтобы была возможность дать доступ родственникам из других городов например

            0
            Бывает так, что родственники живут в других городах и странах — но все же хочется дать им возможность читать и дописывать историю собственных под-ветвей. Тогда Bonsai размещается на полноценном сервере и смотрит в интернет со всеми вытекающими.

            В то же время никто не мешает поднять docker-контейнер локально, использовать элементарную авторизацию по паролю и заполнять базу в одиночку.

            Десктопных приложений такого рода уже несколько — Gramps, Древо жизни и тому подобные. Я рассматривал их в предыдущей статье и подробно расписал, почему они для меня не подошли и какую нишу занимает Bonsai относительно них.
          0
          никто не мешает поднять docker-контейнер локально
          Я к этому вёл. Возможно плохо получилось. Докер, это тоже пример «технологии сделанной гиками для гиков». Смотрите. Есть рядовой неайтишник, который хочет поностальгировать. Кейс с чемоданом: Открыл, смотришь. Кейс с приложением: Достал. Прочитал документацию (если есть в природе), если это делается в семье разработчика — позвал его, если нет — позвал сына маминой подруги, который умеет в компьютеры, боль страдание, методы проб и ошибок. Окей. С грехом пополам запустили. Всё?

          Не всё. Хотим добавить немного от себя. Кейс с чемоданом: докинул фоток, закрыл чемодан. Кейс с докером: вообще, если я правильно понимаю докер: это контейнер, хранимый в публичном репозитории, в котором находится ПО, которое работает с данными, которые находятся… где? В контейнере? Да нет, не может быть, тогда мы отдаём свои данные всем. В другом контейнере? Вот, начинается. В базе данных за пределами контейнера? Ух, ох, сталкиваемся с необходимыми навыками администрировать базы данных. Гики справятся. И то не все. Остальные за бортом.

          То есть, как онлайн сервис с регистрацией и предоставлением услуг — всё здорово. Как домашнее решение — много вопросов возникает на практике.
            0
            В контейнере? Да нет, не может быть, тогда мы отдаём свои данные всем.

            Кому же «всем», если контейнер создается в вашем окружении? Хорошая практика требует сохранять данные БД вне контейнера, оставляя в нем только сам демон СУБД (уже настроенный и боеготовый).

            сталкиваемся с необходимыми навыками администрировать базы данных

            Зачем админить то, что работает как надо из коробки?
              +1
              Я правда докер изучаю около недели, может я банальных штук не понимаю. Контейнер создаётся в окружении пользователя — хорошо и правильно. Но данное приложение нельзя рассматривать, как установленное лишь один раз, иначе при переустановке, насколько я понимаю, данные сбросятся на дефолтные в репозитарии.
              Хорошая практика требует сохранять данные БД вне контейнера
              Я руками и ногами за практику. Но если нужно держать демон в контейнере, а базу вне его, как локальный семейный инстанс, то нужно обладать навыками администрирования баз данных, чтобы всё работало, не так ли? По вашей ссылке путь ведёт на постгрес установленный на линуксе. То есть, чтобы абстрактному обывателю удобно в два клика развернуть свой «чемодан воспоминаний», ему мало контейнера, ему надо установить линукс, настроить на нём базу данных, проплясать с бубном подключая базу к контейнеру и даже спрятав контейнер до следующего раза продолжать нежно протирать базу тряпочкой (как минимум регулярные бекапы и их проверка) чтобы чего-то не случилось.
              Зачем админить то, что работает как надо из коробки?
              Потому что у базы данных нет красивой обёртки с одним тумблером ВКЛ\ВЫКЛ. В идеале вообще этот тумблер должен быть не в базе, а в приложении. Банальное юзабилити, же.

              Это никак не противоречит тому, к чему я вёл: это прикольная игрушка для IT-гика, а не семейное решение.

              Если делать конечное решение со всеми этими сложностями, тогда стоит научить его самостоятельно разворачиваться и самостоятельно делать себе хорошо с минимальным вмешательством пользователя. То есть приложение\бинарник\демон который на вход получает команды: ВКЛ, ВЫКЛ, Бекап, Восстановить бепап, Сбросить пароль. Чтобы программу запустил, флешку воткнул, молодцом.

              p.s. Я ни в коем случае не пытаюсь сказать, что проект — говно, или что-то в этом духе. Мои аргументы направлены в сторону кажущихся мне важными вопросов юзабилити, чтобы решение было именно семейным, а не узкопрофильным.
                0
                при переустановке, насколько я понимаю, данные сбросятся на дефолтные в репозитарии.

                В ссылках, что я привел на docker-compose: создается именованный volume, который подключается в то место контейнера, где постгресс умолчательно хранит файлы баз данных. Этот volume может отображаться на любой удобный path в хост-системе (в смысле вне контейнера), благодаря чему даже запустившийся с нуля контейнер с postgres-демоном узнает, что у него уже создан ряд БД с данными (с прошлого раза), доступ к которым он с радостью предоставит клиенту.

                Подробнее можно почитать на докерхабе постгресса в разделе «Where to store data».

                Потому что у базы данных нет красивой обёртки с одним тумблером ВКЛ\ВЫКЛ.

                Эту роль выполняет контейнер, а конфигурация заводится через docker-compose. Намного роще скомандовать docker-compose up, чем вручную ставить себе СУБД-сервер, настраивать сначала его, потом приложение, чтобы они подружились.
                Не кнопка «сделай мне хорошо», разумеется, но инструкция с шагами уже будет достаточно короткой.
                  0
                  Зайду с другой стороны. Ваша бабушка сможет сделать это самостоятельно, если захочет посмотреть старые фото? Установить докер, развернуть контейнеры, подключить базы. Пусть это и дело пары команд в консоли. Но камон, это консоль, которую боятся и обходят десятой дорогой не варящиеся в нашей сфере люди.
                  Удобство и юзабилити — не пустые слова.
                    0
                    Контейнеры разворачивает не бабушка, а ее айтишник-сын, внук, племянник, сын маминой подруги. Для этого ему даже не нужно быть экспертом — с вызовом одной команды в консоли справится даже джун. А дальше бабушки-дедушки будут заходить с планшетов и смотреть фотки.
                      0
                      Для бабушки экспорт в PDF есть. Крайне маловероятно, что она внезапно вспомнит пару-тройку неучтенных предков. А вот молодые и активные ребятки с навыками продвинутых юзеров ютуба, действительно способные «растить дерево», вполне в силах пройти инструкцию из нескольких пунктов.
                        0
                        Ну окей, вот и ответ. Это не семейный проект, а проект для молодых и активных гиков. Теперь все вопросы снимаются, так как больше не имеют смысла.

                        вполне в силах пройти инструкцию из нескольких пунктов
                        Просто интересно, можно эти пункты под Windows услышать, например? Говорят, докер в нём нетривиален, контейнеризация поддерживается в Pro, Edu и Ent, вот это вот всё…
                          +1
                          По вашей логике, семейный отдых — это тур, купленный бабушкой? Проект семейный, потому что им может пользоваться вся семья (после того, как один из членов семьи его установит).
                            –1
                            По моей логике «семейный», это когда любой человек может запустить и начать пользоваться. А то что вы предлагаете — когда запустить может только специалист, который, по вашей логике обязан присутствовать в любой семье которая захочет приобщиться к прекрасному — не очень на это похоже. По такому принципу обычно взаимодействуют в Энтерпрайзе, когда ищут Интегратора для запуска стороннего решения.
                              +1
                              «Семейный» — это когда для семьи. Когда «каждый может запустить» — это «социальный» или «общедоступный».

                              Да, Bonsai в первую очередь ориентирован на гиков. У них тоже бывают семьи :) Уровень специалиста для запуска не нужен — достаточно базового знакомства с IT, чтобы разобраться за вечер. Я искренне предполагаю, что во многих семьях такой человек хоть один, да есть.

                              Я единственный разработчик, а проект сугубо некоммерческий, поэтому вылизывание UX установки не является приоритетом. Если вам в первую очередь важно развертывание в один клик на Windows Home — увы, могу только посоветовать посмотреть в сторону платных аналогов, у них такое обычно есть.
                            0
                            Это не семейный проект, а проект для молодых и активных гиков.

                            По-вашему только автомеханики могут пользоваться автомобилями?

                            можно эти пункты под Windows услышать.

                            Скачать архив с кодом по ссылке, распаковать его, скачать и установить Docker Desktop, скомандовать docker-compose up в директории с кодом, подождать, пока строчки перестанут бежать?

                            контейнеризация поддерживается в Pro, Edu и Ent, вот это вот всё…

                            Встроенная виртуализация Hyper-V недоступна в Home, но есть же VirtualBox, который идёт из коробки.
                              0
                              О какой встроенной виртуализации речь? Это требования к самому Докеру.
                              image
                                0
                                ОК, тогда Docker Toolbox
                                  0

                                  Можно виртуалбокс, в нем Линукс, а нем докер — зато бесплатно и нет ограничений на версию шиндовса

                                0
                                Все сервисы могут работать под Windows так что ничего не мешает запускать их в windows based containers.
                    0
                    Есть три типа подобных приложений:

                    1. Десктопные: полная приватность, легко установить, но нет доступа через веб
                    2. SAAS (а-ля соцсеть): доступ через веб, легко начать пользоваться, но нет приватности и стоит денег
                    3. Selfhosted: полностью бесплатно, полная приватность, но требует некоторых навыков в поддержке

                    Bonsai находится в третьей категории и не является серебряной пулей. Возможно, под ваши приоритеты больше подойдет какое-либо приложение из первых двух.
                      0
                      Вы забываете про четвёртый пункт, являющийся смесью первого и третьего: десктопный для браузера. Который запускает окружение как десктопное приложение, но отдаёт данные через веб в локалхост. При необходимости попасть извне — пробрасывается порт через роутер. Раньше народ так LAMP сервера клепал: кнопочку нажал, всё развернулось, появились папочки для взаимодействия; другую нажал, всё корректно схлопнулось. Работает через браузер, потому что его цель такая.

                      Этот пункт обычно забывают когда обсуждают коммерческий продакшн, где он выглядит как велосипед на костылях, но если это не самоцель…
                        0
                        Тогда это третья категория — работает на вашем сервере и требует некоторых (по возможности минимальных) усилий на развертывание. Кнопочке «запустить» эквивалентна команда docker-compose, шареные папки и проброс портов при желании тоже делаются довольно легко.
                    0
                    PdfiumViewer умеет конвертировать PDF в картинки, правда, не уверен, заведется ли он под .NET Core
                      0

                      Здорово. Очень странно, что пропустил статью.
                      Вопрос такой — мне очень движок gigatrees понравился. Мне кажется,, то для генеалогии будущее за генераторами статических сайтов. Ну, реально — нет админки — нет уязвимостей и контент весь можно кэшировать и отдавать хоть с дешевейшего бакета с3. Остаётся открытый вопрос с поиском (эффективным) инфы, но уверен, что можно что-то придумать.

                        0
                        А как обновлять данные? этот способ хорош для финальной публикации, но мне никуда ничего публиковать не надо. А если делать весь доступ через статику то надо будет сразу ci сервер держать который будет деплоить новую версию после каждого изменения чего либа. И еще не очень понятко а про какие уезвимости идет речь если у нас и так вся информация доступна?
                          0

                          Обновлять — ну, Вы сами и ответили. Держать CI свой необязательно — можно в том же гитлабе бесплатным на 2000 минут в месяц пользоваться. Минус в первую очередь только в том, что нет бд и, как следствие, реализация некоторых функций становится более сложной — вроде вышеупомянутого текстового поиска по сайту
                          Касательно уязвимостей тоже все просто. Есть админка — значит есть окно ввода логина/пароля. Уже потенциальная точка для sql injection. Так же не все пользователи следуют правильной парольной стратегии и используют один и тот же пароль везде. Стоит одному сайту сохранить пароль в открытом виде в бд или недостаточно хорошо зашифровать — и мы приплыли. Куча вопросов с правами доступа (всякая ролевая модель). И прочее, прочее, прочее.
                          Да, я говорю в общем, а не про конкретное решение.
                          Ещё немаловажный вопрос, что если у нас классическое приложение из фронта+Бека+бд, то у нас возникают требования к хостингу, где его размещать. Или к квалификации того, кто это будет разворачивать и поддерживать.

                        0
                        Да, но чем не устраивает традиционный вики-движок плюс отдельно любой древо-билдер?
                          0
                          С большинством вики движоков само по себе разобраться не очень то просто, а уж допилить до фамильного со внешней интеграцией люцена + генератора деревьев, вообще очень спорная идея.

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

                        Самое читаемое