- Blazor NET.81 + TelegramBot2: подойдёт как стартовый кейс web решения с поддержкой Telegram бота.
- Связь между службами через RabbitMQ3 в режиме
запрос-ответ
: при отправке сообщения в очередь, отправитель дожидается ответ (в границах таймаута) и возвращает результат вызывающему. При использовании вызова такой команды удалённого сервиса проходит так, как если бы это был обычныйawait
запрос к базе данных или rest/api. - ServiceDesk/HelpDesk подсистема оказания консультаций и обратной связи. Пользовательский доступ возможен прямо из Telegram (WebApp) без ввода логина/пароля и вообще регистрации. Управление документами: изменение статусов заявок, журналирование/протоколирование событий и другая универсальная функциональность.
- Подсистема электронной коммерции: на базе СЭД функционирует простой учёт заказов.
- WEB-Конструктор схем данных (формы, документы).
- Интерфейс rest API (swagger) для внешних информационных систем (план обмена для commerce).
- ui пакеты: MudBlazor 7 и два WYSIWYG: CKEditor и TinyMCE. Важно: CKEditor не поддерживает вставку картинок, а TinyMCE имеет такую поддержу (в т.ч. локальное хранение файлов в MongoDB)
Зависимости решения между проектами (в формате Mermaid):
---
title: Структура (зависимости) проектов в решении
---
classDiagram
note for DbPostgreLib "Если используется другая СУБД, тогда
указатели от [ServerLib] [Telegram.Bot.Polling], [HelpdeskService] и [RemoteCallLib]
должны ссылаться на соответсвующую библиотеку: [DbPostgreLib] или [DbMySQLLib]"
SharedLib <|-- CodegeneratorLib
SharedLib <|-- IdentityLib
SharedLib <|-- DbLayerLib
SharedLib : Общие модели
IdentityLib <|-- ServerLib
DbPostgreLib <|-- ServerLib
RemoteCallLib <|-- ServerLib
RemoteCallLib <|-- CommerceService
RemoteCallLib <|-- ApiRestService
CodegeneratorLib <|-- BlazorLib
HtmlGenerator <|-- CodegeneratorLib
DbLayerLib <|-- DbPostgreLib
DbLayerLib <|-- DbSqliteLib
DbLayerLib <|-- DbMySQLLib
DbPostgreLib <|-- RemoteCallLib
BlankBlazorApp_Client <|-- BlankBlazorApp
BlazorWebLib <|-- BlankBlazorApp
ServerLib <|-- BlankBlazorApp
RemoteCallLib <|-- Telegram_Bot_Polling
DbPostgreLib <|-- Telegram_Bot_Polling
RemoteCallLib <|-- StorageService
RemoteCallLib <|-- ConstructorService
RemoteCallLib <|-- HelpdeskService
DbPostgreLib <|-- HelpdeskService
BlazorLib <|-- BlazorWebLib
BlazorLib <|-- BlankBlazorApp_Client
class CodegeneratorLib{
Генератор исходников для Web конструктора
}
class IdentityLib{
Контекст пакета Identity (авторизация)
}
class DbLayerLib{
Абстракция над Мульти-СУБД
}
class ServerLib{
Backend для BlankBlazorApp
}
class BlazorLib{
Blazor UI Компоненты
}
class DbSqliteLib{
Sqlite
}
class DbPostgreLib{
PostgreSQL
}
class DbMySQLLib{
MySQL
}
class RemoteCallLib{
Трансмиссия
}
class StorageService{
@Микросервис
}
class ConstructorService{
@Микросервис
}
class HtmlGenerator{
Внешний репозиторий
}
class BlankBlazorApp{
@Микросервис
}
class BlankBlazorApp_Client["BlankBlazorApp.Client"]{
CSR Blazor WebAssembly
}
class Telegram_Bot_Polling["Telegram.Bot.Polling"]{
@Микросервис
}
class BlazorWebLib{
SSR Blazor Server
}
class HelpdeskService{
@Микросервис
}
class CommerceService{
@Микросервис
}
class ApiRestService{
@Микросервис
}
Пример того как может быть настроено в VS:
- Сохраняет все входящие сообщения и позволяет в последствии работать с чатами другим сервисам.
- В оригинальном исполнении
Worker Service
2. - Ответы на входящие Telegram сообщения обрабатывает реализация интерфейса
ITelegramDialogService
4. Пользователям можно индивидуально устанавливать имя автоответчика5. Это касается как простых текстовыхMessage
, так иCallbackQuery
. - Для обеспечения работы HelpDesk предусмотрен командный режим работы бота. В этом режиме простые текстовые сообщения в бота не обрабатываются автоответчиком (равно как и отправка файлов, документов и т.п.). Сообщения сохраняются, но ответ не формируется если это не команда или CallbackQuery. Команды в TelegramBot начинаются с косой черты (/). Таким образом в командном режиме бот будет пытаться выполнить/обработать входящее сообщение только если текст сообщения является командой: начинается с косой черты (/) либо в случае если это CallbackQuery, а в остальных случаях клиент будет в свободной форме вести чат с ботом, а операторы HelpDesk должны будут ему отвечать от имени бота через WEB интерфейс или воспользовавшись режимом 'экспресс-ответа'.
- Blazor вэб сервер.
- Рендеринг:
InteractiveServerRenderMode(prerender: false)
- Авторизация типовая
Microsoft.AspNetCore.Identity
(documents). - В Frontend добавлен базовый функционал для работы с Пользователями, Ролями, Claims и Telegram1.
- Служба равно как и другие службы использует RabbitMQ для обслуживания входящих команд, на которые она зарегистрировала свои обработчики3. Кроме того, Web служба обрабатывает запросы для Identity. У Identity свой автономный контекст БД.
- Система документооборота со своим собственным контекстом:
HelpdeskContext
. - Смена статуса документу. Исполнитель. SLA. Базовый набор работы с документами.
- Готовый инструмент обработки обращений в формате HelpDesk\ServiceDesk.
- используется сервисом
CommerceService
для 'ведения заказа'.
- Общее пространство хранения параметров со своим контекстом:
StorageContext
. Позволяет разным службам обращаться к параметрам друг друга. Например в Web интерфейсе HelpDesk можно изменить режим работы TelegramBot (бот читает этот параметр при каждом входящем сообщении). - Тэги. Общая система тегов для прикладных объектов.
- Обслуживает функционал хранения файлов: MongoDB.Driver.GridFS
- Справочник номенклатуры и офферов с настраиваемыми правилами ценообразования. Клиенты ведут свой перечень юридических лиц с разбивкой по филиалам, для которых можно формировать заказы. Документы после создания сразу попадают в основную СЭД, где с ними можно работать: менять статус, вести диалог с клиентом и т.д.
- Упрощённая авторизация: использование постоянного токена в заголовке запроса (ключ доступа). Служба выступает в роли посредника между внутренним контуром и внешними потребителями. Например для обмена с 1С.
- Решение для создания форм и документов. В режиме WEB редактора можно создать документ любой сложности (поля, формы, табы, таблицы) и использовать эти схемы для создания сессий (уникальные ссылки) которые можно передавать пользователям. По таким ссылкам/сессиям пользователь увидит созданный документ что бы заполнить его данными.
все службы должны быть настроены, запущены вместе и соединены общим RabbitMQ и Redis. В противном случае в MQ очередях будут копиться запросы без ответов и функционал местами будет недоступен если ответственная служба не будет обрабатывать запросы.
Файлы, встречающиеся в системе могут быть в одном из двух состояний:
- Telegram cloud: если в Telegram сообщениях фигурируют вложения (файлы), ссылки на скачивание из TG сохраняются в базе данных (но не сами данные). При попытке пользователем скачать такой файл происходит online скачивание данных с серверов TG. Эти данные не сохраняются ни где в системе, а доступны только режиме онлайн из TG.
- МетаФайлы (локальное хранилище)6: файлы хранятся
MongoDB.Driver.GridFS
. О каждом таком файле в базе данных дополнительно существуют метаданные. Эти файлы не связаны с прикладными объектами системы на логическом уровне СУБД, но по их мета-данным можно определить что это за файл и к чему он относится. В метаданных два обязательных параметраApplicationName
иPropertyName
и три не обязательных:PrefixPropertyName
,OwnerPrimaryKey
,Referrer
. Кроме того: этим файлам можно назначать произвольные Теги и установить ограничения доступа к файлу6..
Nlog пишет одновременно: в текстовый файл и в базу данных (PostgreSQL
). Строка подключения к БД находится в конфигах 'nlog.config' - отредактируйте под свои параметры. Строка подключения по умолчанию (для всех сервисов): Server=localhost;Port=5432;User Id=nlog;Password=nlog;Database=nlogs;
Пример скрипта 'PostgreSQL' для создания базы данных логов:
CREATE TABLE public.logs
(
"Id" integer GENERATED ALWAYS AS IDENTITY NOT NULL,
"Application" character(256),
"Timestamp" timestamp without time zone NOT NULL,
"Level" character(128) NOT NULL,
"Message" varchar,
"Logger" character(256),
"Callsite" character(256),
"Exception" varchar,
CONSTRAINT logs_pk PRIMARY KEY ("Id")
);
ALTER TABLE IF EXISTS public.logs
OWNER to nlog;
- Перед запуском: в Blazor1 потребуются конфиги Email (отправка писем SMTP. в. т.ч. для Identity), а для TelegramBot потребуется токен. MQ и Redis настройки потребуются всем сервисам (единый контекст для всех сервисов). База данных может быть как SQLite, так и PostgreSQL/MySQL (у каждого сервиса своя БД). MongoDB потребуется для
StorageService
. - Помимо стандартных настроек appsettings.json потребуется отдельная папка где будут храниться приватные данные: логины и пароли к внешним системам. В всех службах поиск/загрузка секретов происходит одинаково:
// Secrets
string secretPath = Path.Combine("..", "secrets");
for (int i = 0; i < 5 && !Directory.Exists(secretPath); i++)
secretPath = Path.Combine("..", secretPath);
if (Directory.Exists(secretPath))
foreach (string secret in Directory.GetFiles(secretPath, $"*.json"))
configHost.AddJsonFile(Path.GetFullPath(secret), optional: true, reloadOnChange: true);
else
logger.Warn("Секреты не найдены");
Приложение ищет папку с именем secret
на уровне выше текущей директории приложения, а если не находит нужной папки, то пытается искать её ещё выше и выше в иерархии папок пути относительно исполняемого файла пока не найдёт её. На этапе разработки эти файлы могут лежать например тут: C:\Users\ ИмяПользователя \source\repos\secrets или выше в иерархии папок.
В папке секретов secrets
предполагается наличие следующих настроек (одним *.json файлом или разными это не важно. загрузятся все *.json файлы из папки секретов):
- RabbitMQ подключение потребуется для всех четырёх служб (Telegram.Bot.Polling и BlazorWebApp):
{
"RabbitMQConfig": {
"UserName": "ваш_логин_от_rabbitmq",
"Password": "ваш_пароль_от_rabbitmq",
"VirtualHost": "/"
}
}
- Email (SMTP) потребуется только для службы BlazorWebApp (В том числе для отправки уведомлений подсистемой авторизации
Microsoft.AspNetCore.Identity
):
{
"SmtpConfig": {
"Email": "ваш-email@домен",
"Login": "логин-для-smtp",
"Password": "ваш-пароль-для-smtp",
"Host": "smtp-адрес-хоста",
"Port": 465
}
}
Если отправка Email происходит иначе чем обычный SMTP, тогда следует реализовать IMailProviderService
под условия и предусмотреть соответствующие настройки.
- MongoDB:
{
"MongoDB": {
"Sheme": "mongodb",
"Host": "localhost",
"Port": 27017,
"Login": "",
"Password": ""
}
}
Используется для хранения файлов (вложения в документы и т.п.)
- Токен TelegramBot нужен только для соответствующей службы
Telegram.Bot.Polling
:
{
"BotConfiguration": {
"BotToken": "ваш-токен-для-бота"
}
}
Создать бота и получить свой токен можно у @BotFather
У службы BlazorWebApp
можно настроить Email адреса клиентов таким образом, что бы закрепить за ними любые произвольные роли. Это полезно, для первого старта приложения: администратор прописывает свой Email под которым он будет авторизовываться с необходимой ему ролью admin
, тогда при каждом входе будут проверяться наличие требуемой роли у пользователя. Если необходимых ролей не окажется в системе, то они будут автоматически созданы. Клиент обязательно получит роли, которые ему были прописаны в конфигурации. Пример настроек:
{
"UserManage": {
"UpdatesUsersRoles": [
{
"EmailUser": "ваш_email@сайт.ru",
"SetRoles": [ "admin" ]
},
{
"EmailUser": "другой_email@домен.com",
"SetRoles": [ "manager" ]
}
]
}
}
прописать можно любые роли любым клиентам. после этого им нужно залогиниться - нужные роли обязательно окажутся у клиента. после того как требуемые роли назначены - эти настройки рекомендуется удалить. наличие таких конфигов делает невозможными попытки лишить пользователей этих ролей в связи с тем что они будут проверяться и выдаваться при каждом входе клиента.
Windows/Android утилита для удалённого взаимодействия с сервисами. Работает через штатный rest/api:
- Синхронизация (односторонняя) папок локальной (win/android) с удалённой (на сайте). Сверка файлов производится по имени, размеру и md5:hash файла. На сервер будут доставлены только новые или изменённые файлы, а недостающие будут удалены: локальная папка устройства будет спроецирована/клонирована в папку на сайте.
- Удалённый вызов команд (shell/cmd)
Footnotes
-
Стандартная ASP служба Blazor WebApp. За основу взята эта работа. ↩ ↩2 ↩3
-
WorkerService служба Telegram.Bot.Polling сделана на основе Telegram.Bot.Examples.Polling. ↩ ↩2
-
Подробнее про реализацию MQ транспорта можно узнать тут. ↩ ↩2
-
Свой обработчик ответа на входящее сообщение Telegram реализуется через интерфейс и регистрации его в Program.cs службы TelegramBot. ↩
-
Имя обработчика ответов храниться в контексте пользователя. Подробнее тут ↩
-
МетаФайлы поддерживают контроль доступа. По умолчанию файлы доступны публично по ссылке, но можно установить ограничения на чтение. Правила доступа позволяют разрешать доступ персонально пользователям или по ассоциации с документом. В случае доступа по ассоциации с документом проверяется упоминание пользователя в документе (должен быть среди подписчиков или являться автором|исполнителем). Кроме того можно создать токен доступа (guid) для файла, по которому можно получить доступ вне всяких ограничений передав его get/query параметром в строке URL. ↩ ↩2