Files
site/apps/api/app/db/seed.py
T
влад 12c983c0fc Шхуна не тонет: security, infra и доки на русском.
Безопасность довёл до ума — Cursor-генерацию переписал руками.
IDOR закрыл, CSRF задушил, refresh rotation теперь как надо.
HSTS на staging, ENABLE_DOCS=false, install.env recovery протестил.

Backend:
- jwt_denylist + auth_epoch: мгновенный revoke access JWT (logout/block/reset)
- auth/admin/users: bump epoch, logout с Bearer, forgot_password skip для blocked
- install_secrets: путь всегда apps/api/data/secrets/ (bootstrap из корня не ломает Docker)
- seed: SEED_DEMO_USERS=false на prod/staging
- тесты: jwt revoke, integration, coverage gate 90%

Frontend:
- logout шлёт Bearer, обработка TOKEN_REVOKED
- guards TypeScript fix
- E2E: blocked user → 401 сразу после block

Infra:
- staging/prod compose, TLS nginx, deploy-скрипты
- k6 §17.2, backup/health/smoke scripts

Docs:
- docs/ на русском: project, security, deploy, release (старые md слили)
- README короткий + план ТЗ + стандартные логины dev

Код готов к плаванию. Капитан может идти писать фронт.
2026-07-15 00:06:13 +03:00

100 lines
3.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from __future__ import annotations
from datetime import UTC, datetime
from app.core.config import settings
from app.core.security import hash_password
from app.modules.content.repository import create_page, get_page_by_slug
from app.modules.users.repository import create_user, get_user_by_email
def _ensure_user(email: str, password: str, role: str, is_superuser: bool, status: str):
from app.modules.users import repository
user = get_user_by_email(email)
if user:
changed = False
if user.role != role:
user.role = role
changed = True
if user.is_superuser != is_superuser:
user.is_superuser = is_superuser
changed = True
if user.status != status:
user.status = status
changed = True
if user.email_verified_at is None and status == "active":
user.email_verified_at = datetime.now(UTC)
changed = True
if changed:
repository.update_user(user)
return user
user = create_user(
email=email,
password_hash=hash_password(password),
role=role,
is_superuser=is_superuser,
status=status,
)
user.email_verified_at = datetime.now(UTC)
repository.update_user(user)
return user
def run_seed(include_demo_pages: bool = True) -> None:
admin = _ensure_user(
email="admin@compton.example",
password=settings.admin_initial_password,
role="admin",
is_superuser=True,
status="active",
)
if settings.seed_demo_users and settings.app_env.lower() != "production":
_ensure_user(
email="user@compton.example",
password=settings.demo_user_password,
role="user",
is_superuser=False,
status="active",
)
_ensure_user(
email="ops@compton.example",
password=settings.demo_ops_password,
role="admin",
is_superuser=False,
status="active",
)
if not include_demo_pages:
return
demo_pages = [
{
"slug": "about",
"title": "О бренде",
"body": "<p>Compton — платформа Organic Tech.</p>",
},
{
"slug": "privacy",
"title": "Политика конфиденциальности",
"body": "<p>Мы обрабатываем персональные данные согласно политике.</p>",
},
{
"slug": "terms",
"title": "Условия использования",
"body": "<p>Используя сервис, вы принимаете условия.</p>",
},
]
for page in demo_pages:
if get_page_by_slug(page["slug"], include_draft=True):
continue
create_page(
slug=page["slug"],
title=page["title"],
body=page["body"],
status="published",
author_id=admin.id,
)