10 KiB
Профиль и аватар пользователя
Эндпоинты управления профилем, загрузкой аватаров и поиска пользователей.
Быстрый старт
# 1. Получить профиль
curl http://localhost:8000/api/v1/users/me \
-H "Authorization: Bearer $TOKEN"
# 2. Обновить ФИО и команду
curl -X PATCH http://localhost:8000/api/v1/users/me \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name_user":"Новое имя","team_id":"uuid-team"}'
# 3. Загрузить аватар
curl -X POST http://localhost:8000/api/v1/users/me/avatar \
-H "Authorization: Bearer $TOKEN" \
-F "file=@/path/to/photo.jpg"
# 4. Удалить аватар
curl -X DELETE http://localhost:8000/api/v1/users/me/avatar \
-H "Authorization: Bearer $TOKEN"
# 5. Сменить пароль
curl -X POST http://localhost:8000/api/v1/users/me/password \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"current_password":"oldPassword123","new_password":"newSecurePassword456"}'
# 6. Поиск пользователей (для пикера участников)
curl 'http://localhost:8000/api/v1/users?q=john' \
-H "Authorization: Bearer $TOKEN"
# 7. Получить справочник команд
curl http://localhost:8000/api/v1/teams \
-H "Authorization: Bearer $TOKEN"
Эндпоинты
GET /api/v1/users/me
Получить профиль текущего аутентифицированного пользователя.
Требует auth: JWT Bearer token
Response (200 OK):
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"name_user": "Иван Петров",
"team_id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
"team_name": "Backend",
"avatar_path": "avatars/550e8400-e29b-41d4-a716-446655440000.jpg",
"avatar_url": "/media/avatars/550e8400-e29b-41d4-a716-446655440000.jpg",
"created_at": "2026-07-16T12:00:00Z"
}
Поля:
email— адрес электронной почты (read-only)name_user— отображаемое имя (редактируемое)team_id— UUID команды (опционально, редактируемое)team_name— имя команды (null если не привязан)avatar_path— путь к файлу аватара (null если нет)avatar_url— готовый URL для отображения; при отсутствии аватара фронтенд показывает заглушку с инициалами
PATCH /api/v1/users/me
Изменить ФИО и/или команду текущего пользователя; email — read-only.
Требует auth: JWT Bearer token
Request body: (все поля опциональны)
{
"name_user": "Новое имя",
"team_id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
}
Поля:
name_user(str, 1..255) — новое ФИОteam_id(UUID или null) — переназначить команду; явноеnullснимает привязку; отсутствие поля команду не трогает
Response (200 OK): обновленный профиль (как GET /me)
Коды ошибок:
404— team_not_found (если передан несуществующийteam_id)422— Unprocessable Entity (валидация: name_user пуст и т.д.)
POST /api/v1/users/me/avatar
Загрузить аватар текущего пользователя.
Требует auth: JWT Bearer token
Request body: multipart/form-data
file— файл изображения (обязателен)
Требования:
- Формат: JPEG, PNG или WebP (проверяется по magic bytes, не по расширению)
- Максимальный размер: 2 МБ
- Старый аватар автоматически удаляется при загрузке нового
Response (200 OK): обновленный профиль (как GET /me, с новым avatar_url)
Коды ошибок:
413— avatar_too_large (файл больше 2 МБ)415— avatar_invalid_type (не JPEG/PNG/WebP; проверяется по magic bytes)422— Unprocessable Entity (невалидный multipart и т.д.)
Примеры:
# JPEG
curl -X POST http://localhost:8000/api/v1/users/me/avatar \
-H "Authorization: Bearer $TOKEN" \
-F "file=@photo.jpg"
# PNG
curl -X POST http://localhost:8000/api/v1/users/me/avatar \
-H "Authorization: Bearer $TOKEN" \
-F "file=@photo.png"
# WebP
curl -X POST http://localhost:8000/api/v1/users/me/avatar \
-H "Authorization: Bearer $TOKEN" \
-F "file=@photo.webp"
DELETE /api/v1/users/me/avatar
Удалить аватар текущего пользователя.
Требует auth: JWT Bearer token
Response (204 No Content) — без тела
Примечание: После удаления avatar_path становится null, фронтенд отображает заглушку с инициалами.
POST /api/v1/users/me/password
Сменить пароль текущего пользователя.
Требует auth: JWT Bearer token
Request body:
{
"current_password": "oldPassword123",
"new_password": "newSecurePassword456"
}
Поля:
current_password(str) — текущий пароль (обязательно, для верификации)new_password(str, ≥8) — новый пароль (политика как при регистрации: минимум 8 символов)
Response (204 No Content) — без тела
Коды ошибок:
400— invalid_current_password (текущий пароль не совпадает)422— Unprocessable Entity (новый пароль короче 8 символов)
Примечание: Refresh-сессии сознательно не отзываются (см. ADR-005 docs/architecture/adr/005-password-reset-deferred.md) — пользователь останется залогинен на других устройствах. Массовый отзыв всех сессий появится вместе со сбросом пароля по email (v0.1.0).
GET /api/v1/users
Поиск пользователей для пикера участников конференции.
Требует auth: JWT Bearer token
Query параметры:
q(str, опционально) — текст для поиска (по имени и email)
Поведение:
- Без
q— возвращает полный список (с ограничением ~20 результатов) - С
q— полнотекстовый поиск (также ~20 результатов) - Поиск регистронезависим
Response (200 OK):
[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "ivan@example.com",
"name_user": "Иван Петров",
"avatar_url": "/media/avatars/550e8400-e29b-41d4-a716-446655440000.jpg"
},
{
"id": "6ba7b811-9dad-11d1-80b4-00c04fd430c8",
"email": "maria@example.com",
"name_user": "Мария Сидорова",
"avatar_url": null
}
]
Примеры:
# Полный список
curl http://localhost:8000/api/v1/users \
-H "Authorization: Bearer $TOKEN"
# Поиск по имени
curl 'http://localhost:8000/api/v1/users?q=ivan' \
-H "Authorization: Bearer $TOKEN"
# Поиск по email
curl 'http://localhost:8000/api/v1/users?q=example.com' \
-H "Authorization: Bearer $TOKEN"
Аватары
Хранение
Аватары хранятся в каталоге MEDIA_ROOT/avatars/:
MEDIA_ROOT/
└── avatars/
├── 550e8400-e29b-41d4-a716-446655440000.jpg
├── 6ba7b811-9dad-11d1-80b4-00c04fd430c8.png
└── ...
Адресация:
- Backend сохраняет:
user.avatar_path = "avatars/{user_id}.{ext}" - Frontend отображает:
avatar_url = "/media/avatars/{user_id}.{ext}" - Nginx раздаёт напрямую (location
/media/→ aliasMEDIA_ROOT)
Валидация
Magic bytes (не расширение):
- JPEG:
FF D8 FF - PNG:
89 50 4E 47 - WebP:
52 49 46 46 ... 57 45 42 50
Размер: max 2 МБ (413 Payload Too Large)
Заглушка (дефолт)
Если avatar_path = null:
- Фронтенд отображает цветную заглушку с инициалами (2 буквы ФИО)
- Цвет выбирается детерминированно по хэшу
user_id(всегда одинаковый для пользователя)
Типы данных
UserProfileOut
{
"id": "uuid",
"email": "string",
"name_user": "string",
"team_id": "uuid or null",
"team_name": "string or null",
"avatar_path": "string or null",
"avatar_url": "string or null",
"created_at": "datetime"
}
UserListItemOut
{
"id": "uuid",
"email": "string",
"name_user": "string",
"avatar_url": "string or null"
}
Примечания
- Email read-only: адрес электронной почты менять нельзя (требует переверификации, которая не реализована в v0.0.1)
- Таймзона: все
created_atсохраняются в UTC (ISO 8601) - Команда опциональна: пользователь может работать без привязки к команде (
team_id= null) - Безопасность: пароли никогда не передаются в API; для смены пароля используйте
POST /api/v1/users/me/password. Сброс пароля по email появится в v0.1.0 (см. ADR-005)
Ссылки
- Справочник команд — GET /api/v1/teams
- Администраторский API — GET/PATCH /api/v1/admin/users/{id}, POST /api/v1/admin/users/{id}/avatar
- Аутентификация — регистрация, логин
- Конференции — параметр
participantsпри создании/редактировании