Сборка бэк
This commit is contained in:
105
backend/src/Docs/profiles_module_documentation.md
Normal file
105
backend/src/Docs/profiles_module_documentation.md
Normal file
@@ -0,0 +1,105 @@
|
||||
# Документация модуля Profiles (Профили пользователей)
|
||||
|
||||
## Введение
|
||||
|
||||
Модуль `Knot.Modules.Profiles` отвечает за управление публичными данными пользователей, их аватарами и настройками отображения в мессенджере Knot Messager.
|
||||
|
||||
### Разделение ответственности (Auth vs Profiles)
|
||||
В соответствии с принципами **DDD (Domain-Driven Design)** и **Чистой Архитектуры**, модуль Profiles отделен от модуля Auth:
|
||||
* **Auth (Postgres):** Занимается идентификацией (логин, пароль, токены, email).
|
||||
* **Profiles (MongoDB + S3):** Занимается представлением пользователя (имя, био, аватар, настройки видимости).
|
||||
|
||||
Это разделение позволяет изменять структуру профиля (добавлять новые социальные ссылки, поля "О себе") без выполнения миграций в основной реляционной БД.
|
||||
|
||||
---
|
||||
|
||||
## Архитектура хранения данных (Гибридный подход)
|
||||
|
||||
Модуль использует **гибридную схему хранения**, оптимизированную для производительности и гибкости:
|
||||
|
||||
1. **Metadata (MongoDB):** Документ `ProfileDocument` содержит все текстовые данные профиля. Использование NoSQL позволяет легко расширять схему данных.
|
||||
2. **Media (S3/MinIO):** Файлы аватаров хранятся во внешнем объектном хранилище. В MongoDB хранится только `AvatarUrl` (ссылка на файл).
|
||||
3. **Identity Link (UserId):** Поле `Id` в MongoDB-документе совпадает с `UserId` из PostgreSQL. Это единственный ключ для связи модулей.
|
||||
|
||||
---
|
||||
|
||||
## Доменная модель
|
||||
|
||||
### ProfileDocument (Aggregate Root)
|
||||
Основная сущность в модуле. Находится в слое `Domain`.
|
||||
* **Username:** Уникальный хендл пользователя.
|
||||
* **DisplayName:** Публичное имя (может меняться).
|
||||
* **Bio:** Короткая биографическая справка.
|
||||
* **AvatarUrl:** Путь к файлу в формате `/api/files/{fileId}`.
|
||||
* **HideStoryViews:** Флаг приватности (скрывать просмотр сторис от других).
|
||||
|
||||
### Доменные события
|
||||
Модуль генерирует и слушает события для обеспечения согласованности:
|
||||
* `UserRegisteredDomainEvent`: Слушается модулем Profiles (от Auth). При получении создается начальный документ профиля в MongoDB.
|
||||
* `ProfileAvatarChangedDomainEvent`: Генерируется при смене аватара (для потенциальной очистки кэша).
|
||||
|
||||
---
|
||||
|
||||
## Ключевые возможности
|
||||
|
||||
### 1. Управление аватарами
|
||||
Модуль предоставляет эндпоинты для загрузки и удаления аватаров:
|
||||
* **Автоматическое кадрирование:** При вызове `/avatar/crop` используется библиотека `ImageSharp` для вырезания области изображения и ресайза до `400x400` пикселей в формате JPEG.
|
||||
* **Авто-очистка:** При загрузке нового аватара модуль автоматически удаляет старый файл из S3, предотвращая появление "файлов-сирот".
|
||||
|
||||
### 2. Поиск пользователей
|
||||
Реализован через `ProfileRepository` с использованием регулярных выражений MongoDB (case-insensitive) по полям `Username` и `DisplayName`.
|
||||
|
||||
### 3. Настройки приватности
|
||||
Пользователь может управлять отображением своей активности (например, `HideStoryViews`), что сохраняется непосредственно в документе профиля.
|
||||
|
||||
---
|
||||
|
||||
## Структура проекта
|
||||
|
||||
```text
|
||||
Knot.Modules.Profiles/
|
||||
├── Application/
|
||||
│ ├── Abstractions/ # Интерфейсы IProfileRepository, IAvatarStorageService
|
||||
│ ├── Profiles/ # Case-обработчики (Handlers)
|
||||
│ │ ├── Avatar/ # Загрузка, обрезка, удаление аватара
|
||||
│ │ ├── GetUser/ # Получение данных профиля
|
||||
│ │ ├── Search/ # Поиск по базе профилей
|
||||
│ │ └── UpdateProfile/ # Обновление текстовых данных
|
||||
│ └── Integration/ # Обработчики событий от других модулей
|
||||
├── Domain/
|
||||
│ ├── ProfileDocument.cs # Корень агрегата (Mongo Document)
|
||||
│ └── Events/ # Доменные события
|
||||
├── Infrastructure/
|
||||
│ └── Database/ # Реализация репозиториев для MongoDB и S3
|
||||
├── Presentation/
|
||||
│ └── Endpoints/ # Carter-модули (API эндпоинты)
|
||||
└── DependencyInjection.cs # Регистрация сервисов и MongoDB клиента
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Технические детали реализации
|
||||
|
||||
### Интеграция с S3 (MinIO)
|
||||
В модуле реализован адаптер `AvatarStorageService`, который инкапсулирует работу с `IFileStorageService`. Он отвечает за:
|
||||
1. Генерацию уникальных ключей файлов.
|
||||
2. Шифрование контента (через Shared Infrastructure).
|
||||
3. Очистку путей (преобразование URL в ID файла для удаления).
|
||||
|
||||
### Настройка MongoDB
|
||||
Репозиторий `ProfileRepository` использует типизированную коллекцию `IMongoCollection<ProfileDocument>`. Первичный ключ `Id` мапится как строка (BsonType.String) для совместимости с `Guid` из .NET.
|
||||
|
||||
---
|
||||
|
||||
## API Эндпоинты (Примеры)
|
||||
|
||||
| Метод | Путь | Описание |
|
||||
| :--- | :--- | :--- |
|
||||
| `GET` | `/api/profiles/{id}` | Получить данные профиля пользователя. |
|
||||
| `GET` | `/api/profiles/search?q=text` | Найти пользователей по имени или никнейму. |
|
||||
| `PUT` | `/api/profiles/profile` | Обновить DisplayName, Bio, Birthday. |
|
||||
| `POST` | `/api/profiles/avatar` | Простая загрузка аватара (FormFile). |
|
||||
| `POST` | `/api/profiles/avatar/crop` | Загрузка с указанием координат обрезки (x, y, w, h). |
|
||||
| `DELETE` | `/api/profiles/avatar` | Удаление текущего аватара и файла из S3. |
|
||||
| `PUT` | `/api/profiles/settings` | Обновить настройки приватности профиля. |
|
||||
129
backend/src/Docs/settings_module_documentation.md
Normal file
129
backend/src/Docs/settings_module_documentation.md
Normal file
@@ -0,0 +1,129 @@
|
||||
# Документация модуля Settings (Настройки)
|
||||
|
||||
## Введение
|
||||
|
||||
Модуль `Knot.Modules.Settings` является централизованным компонентом для управления глобальными конфигурациями и параметрами системы в архитектуре модульного монолита (Modular Monolith) Knot Messager. Он обеспечивает единый источник истины (Single Source of Truth) для настроек всех других модулей (WebRTC, Federation, Messages, Chats, Admin и др.).
|
||||
|
||||
## Основные принципы (DDD и Clean Architecture)
|
||||
|
||||
- **Независимость и Инкапсуляция:** Модуль выступает как самостоятельная единица и не зависит от реализаций других модулей. Другие модули ссылаются на `Settings` только через абстракции или контракты.
|
||||
- **Единственный Источник Истины:** Любое изменение системной конфигурации (включение/отключение фич, лимиты, домены) происходит через этот модуль.
|
||||
- **Событийная Модель (Domain Events):** При изменении настроек инфраструктура Settings генерирует доменное событие `SystemSettingsUpdatedDomainEvent`, позволяя другим модулям (например, `Federation` для отправки новых Capabilities) реагировать на изменения асинхронно, не создавая жестких связей.
|
||||
|
||||
## Структура модуля
|
||||
|
||||
Модуль спроектирован по принципам Чистой Архитектуры и разделен на слои:
|
||||
|
||||
```text
|
||||
Knot.Modules.Settings/
|
||||
├── Application/ # Слой Приложения (Application Layer)
|
||||
│ ├── Settings/
|
||||
│ │ ├── Abstractions/ # Определение интерфейсов доступа к каждому разделу настроек
|
||||
│ │ │ ├── ISettingsService.cs
|
||||
│ │ │ ├── IMessagesSettings.cs
|
||||
│ │ │ ├── IWebRtcSettings.cs
|
||||
│ │ │ └── ...
|
||||
│ │ ├── DTOs/ # Структуры данных конфигураций
|
||||
│ │ ├── SystemSettingsDto.cs
|
||||
│ │ ├── PublicConfigDto.cs
|
||||
│ │ ├── KlipyConfig.cs
|
||||
│ │ └── ...
|
||||
├── Domain/ # Доменный Слой (Domain Layer)
|
||||
│ ├── Events/
|
||||
│ │ └── SystemSettingsUpdatedDomainEvent.cs # Событие об изменении настроек
|
||||
├── Infrastructure/ # Слой Инфраструктуры (Infrastructure Layer)
|
||||
│ ├── Configuration/
|
||||
│ │ └── SettingsService.cs # Реализация логики кэширования и обновления
|
||||
├── DependencyInjection.cs # Регистрация модуля в DI (AddSettingsModule)
|
||||
```
|
||||
|
||||
## Как это работает?
|
||||
|
||||
### 1. Интерфейсы сегрегации (Interface Segregation Principle - ISP)
|
||||
|
||||
Чтобы модули не зависели от огромного объекта настройки всей системы `SystemSettingsDto`, в слое `Application/Settings/Abstractions/ISettingsService.cs` мы разделили конфигурации на интерфейсы по специализациям:
|
||||
|
||||
- `ISystemSettings` — Системные и общие параметры.
|
||||
- `IWebRtcSettings` — Настройки аудио/видео вызовов (WebRTC, TURN).
|
||||
- `IMessagesSettings` — Настройки сообщений (файлы, ограничения).
|
||||
- `IFederationSettings` — Настройки ActivityPub/Федерации.
|
||||
- `IKlipySettings` — Настройки интеграции внешней библиотеки гифок (Klipy).
|
||||
|
||||
### 2. Доступ к настройкам из других модулей
|
||||
|
||||
Если, например, модулю бесед (Conversations) требуется проверить, включены ли интеграции Klipy, он инжектит специфичный интерфейс `IKlipySettings`, не получая доступа к настройкам админки или WebRTC:
|
||||
|
||||
```csharp
|
||||
public class CreateStoryCommandHandler
|
||||
{
|
||||
private readonly IKlipySettings _klipySettings;
|
||||
|
||||
public CreateStoryCommandHandler(IKlipySettings klipySettings)
|
||||
{
|
||||
_klipySettings = klipySettings;
|
||||
}
|
||||
|
||||
public async Task Handle(...)
|
||||
{
|
||||
if (!_klipySettings.Current.Enabled) {
|
||||
// Отбросить логику
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Хранение и шифрование данных
|
||||
|
||||
Реализация `SettingsService` хранит данные централизованно (в таблице `SystemSettings` БД через `SystemDbContext` в `Knot.Shared.Infrastructure`) в формате JSON.
|
||||
Для безопасности вся JSON-строка **зашифрована** с использованием `IEncryptionService`.
|
||||
|
||||
Особенности хранения:
|
||||
- **Кэширование**: `SettingsService` зарегистрирован как `Singleton`. При запуске сервера конфигурация загружается один раз из базы данных (или кеша/файла) и сохраняется в памяти.
|
||||
- **Обновление**: Метод `UpdateSettingsAsync` сохраняет новый стейт в БД и обновляет объект в памяти (`_current`), предотвращая лишние запросы к базе данных при обычной работе мессенджера.
|
||||
|
||||
## Жизненный цикл обновления настроек (Управление)
|
||||
|
||||
Администратор изменяет настройки через UI (или API), после чего происходит следующий процесс:
|
||||
|
||||
1. Вызывается эндпоинт в модуле **Admin**: `PUT /api/admin/settings`.
|
||||
2. Команда `UpdateSettingsCommand` валидирует входные данные.
|
||||
3. Команда обращается к `ISettingsService.UpdateSettingsAsync(newSettings)`.
|
||||
4. `SettingsService` шифрует новые настройки, обновляет запись в БД, и заменяет кэш в оперативной памяти.
|
||||
5. После успешного сохранения, диспетчер MediatR (в `Admin` модуле) публикует `SystemSettingsUpdatedDomainEvent`.
|
||||
6. Событие отлавливается через `INotificationHandler<SystemSettingsUpdatedDomainEvent>` независимыми слушателями, например:
|
||||
- Модулем `Federation` для рассылки всем "соседним" инстансам новых возможностей `Capabilities`.
|
||||
|
||||
## Регистрация модуля
|
||||
|
||||
При старте приложения в `Host/Program.cs` модуль инициализируется:
|
||||
|
||||
```csharp
|
||||
// Регистрация сервисов модуля настроек
|
||||
builder.Services.AddSettingsModule(builder.Configuration);
|
||||
|
||||
// Дополнительно можно вызывать Initialize(...) чтобы загрузить кэш из БД при старте
|
||||
```
|
||||
|
||||
Под капотом `DependencyInjection.cs`:
|
||||
```csharp
|
||||
public static IServiceCollection AddSettingsModule(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.AddSingleton<SettingsService>();
|
||||
|
||||
// Привязываем конкретные абстракции к одному Singleton инстансу
|
||||
services.AddSingleton<ISettingsService>(sp => sp.GetRequiredService<SettingsService>());
|
||||
services.AddSingleton<IMessagesSettings>(sp => sp.GetRequiredService<SettingsService>());
|
||||
// ... и остальные
|
||||
}
|
||||
```
|
||||
|
||||
## Публичная конфигурация клиента (PublicConfig)
|
||||
|
||||
Для клиентской части (Frontend) предусмотрен специальный DTO объект `PublicConfigDto`.
|
||||
Это subset (урезанная часть) от `SystemSettingsDto`, которая не содержит чувствительной информации о сервере и ключах:
|
||||
|
||||
- Доступные лимиты медиа файлов.
|
||||
- Включены ли аудио/видео звонки.
|
||||
- Включена ли федерация для поиска глобальных пользователей.
|
||||
|
||||
Таким образом, клиент может запросить `GET /api/app/config`, а бэкенд отдаст безопасный набор доступных разрешений через маппинг `SettingsService.Current`.
|
||||
Reference in New Issue
Block a user