Backend / Database

Модели базы данных

SQLAlchemy ORM модели для SQLite и PostgreSQL. Файл: srv/app/db/models.py

Обзор таблиц

База данных содержит 4 основные таблицы. Поддерживается как SQLite (для разработки), так и PostgreSQL (для продакшна). При старте сервер автоматически выполняет миграции через init_models().

ТаблицаМодельНазначениеСтрок (ожидаемо)
usersUserАккаунты пользователейСотни
messagesMessageЗашифрованные сообщенияМиллионы
media_itemsMediaItemМетаданные медиафайловСотни тысяч
sessionsSessionАктивные JWT-сессииЕдиницы на пользователя

User — Пользователь

Основная таблица пользователей. ID начинается с 100 (системные аккаунты занимают 0-99). Пользователь с id=0 — системный аккаунт Chepuhagram для системных сообщений.

ℹ️
ID пользователей начинаются с 100 благодаря Sequence('user_id_seq', start=100). IDs 0-99 зарезервированы для системных аккаунтов.
Поле
Тип
Описание
id
Integer (PK)
Уникальный ID, начиная с 100. Первичный ключ.
first_name
String(50)
Имя пользователя. По умолчанию: "User".
last_name
String(50)?
Фамилия (необязательно).
username
String (unique)
Уникальный логин для входа и идентификации.
about
String?
Биография / описание профиля.
phone
String(20)?
Номер телефона (уникальный, необязательный).
email
String(255)?
Email адрес (уникальный, необязательный).
totp_secret
String(32)?
Секрет TOTP для 2FA. NULL если 2FA не активирована.
totp_temp_secret
String(32)?
Временный TOTP секрет до подтверждения кода.
hashed_password
String
bcrypt хеш пароля аутентификации.
public_key
String?
Base64 публичный X25519 ключ E2EE шифрования.
encrypted_private_key
String?
Зашифрованный мастер-паролем приватный X25519 ключ (Base64, AES-GCM).
fcm_token
String?
Firebase Cloud Messaging токен для push-уведомлений.
avatar_file_id
String?
UUID аватарки в таблице media_items.
show_email
Integer
Настройка приватности: показывать email. 1=да, 0=нет.
show_phone
Integer
Настройка приватности: показывать телефон. 1=да, 0=нет.
show_avatar
Integer
Настройка приватности: показывать аватарку. 1=да, 0=нет.
show_about
Integer
Настройка приватности: показывать биографию. 1=да, 0=нет.
show_username
Integer
Настройка приватности: показывать логин. Всегда 1 (нельзя скрыть).
show_last_online
Integer
Настройка приватности: показывать время последней активности. 1=да, 0=нет.
last_online
DateTime?
Время последней активности (timezone aware).
is_blocked
Integer
Заблокирован ли аккаунт администратором. 0=нет, 1=да.

Message — Сообщение

Таблица зашифрованных сообщений. Содержимое (content) всегда зашифровано на стороне клиента с помощью AES-256-GCM. Сервер не может прочитать сообщения.

🔒
Поле content содержит только зашифрованные данные в формате Base64. Сервер хранит шифртекст и не имеет доступа к открытому тексту.
Поле
Тип
Описание
id
Integer (PK)
Уникальный ID сообщения.
sender_id
Integer (FK)
ID отправителя (FK → users.id).
receiver_id
Integer (FK)
ID получателя (FK → users.id).
content
Text
Зашифрованное содержимое: Base64(nonce + mac + ciphertext).
timestamp
DateTime
Время отправки (серверное, UTC).
delivered_at
DateTime?
Время доставки (получатель подключился).
read_at
DateTime?
Время прочтения (получатель открыл чат). NULL = непрочитано.
reply_to_id
Integer? (FK)
ID цитируемого сообщения (FK → messages.id).
reply_to_text
Text?
Зашифрованный предпросмотр цитируемого сообщения.
edited_at
DateTime?
Время последнего редактирования. NULL = не редактировалось.
message_type
String
Тип: text, image, video, voice_note, video_note, file, call.
file_id
String?
UUID медиафайла в media_items (если есть вложение).
encrypted_key
String?
Зашифрованный ключ для медиафайла (AES ключ файла, шифрованный chat shared key).

Типы сообщений

message_typeОписание
textТекстовое сообщение
imageИзображение (JPEG, PNG, HEIC)
videoВидеофайл (MP4)
voice_noteГолосовое сообщение (M4A/AAC)
video_noteВидеокружок (MP4, квадрат)
fileПроизвольный файл
callСистемная запись о звонке (длительность, статус)

MediaItem — Медиафайл

Метаданные загруженных медиафайлов. Реальные файлы хранятся в Google Drive; в этой таблице только ссылки и метаданные.

Поле
Тип
Описание
id
Integer (PK)
Внутренний ID записи.
file_id
String(32) (unique)
UUID файла — используется в API URL (/media/{file_id}).
owner_id
Integer? (FK)
ID пользователя-владельца (FK → users.id).
original_filename
String(255)?
Исходное имя файла при загрузке.
content_type
String(100)?
MIME-тип: image/jpeg, video/mp4 и т.д.
storage_file_id
String(255)
ID файла в Google Drive для операций Drive API.
size_bytes
BigInteger
Размер файла в байтах. BigInteger для файлов > 2 ГБ.
created_at
DateTime
Время загрузки файла.
updated_at
DateTime
Время последнего обновления метаданных.

Session — Сессия устройства

Каждый вход с устройства создаёт запись Session. JWT токены привязаны к session_id. При завершении сессии токены аннулируются, WebSocket соединение разрывается.

Поле
Тип
Описание
id
Integer (PK)
Уникальный ID сессии, встраивается в JWT payload.
user_id
Integer (FK)
Владелец сессии (FK → users.id, CASCADE DELETE).
session_token
String?
Последний access_token сессии (для обратной совместимости).
device_name
String
Название устройства: «Samsung SM-G991B» или «iPhone Ивана».
ip_address
String
IP-адрес при создании сессии.
app_name
String?
Название приложения.
app_version
String?
Версия приложения.
platform
String?
Платформа: Android, iOS, Windows.
created_at
DateTime
Время создания сессии (вход).
last_active
DateTime
Время последнего обновления тоена.
fcm_token
String?
FCM токен конкретного устройства для push-уведомлений.
⚠️
APScheduler удаляет неактивные сессии каждые 24 часа через задачу delete_old_sessions() в app/tasks.py.