Files
scripts-2/README.md
T
2026-10-12 19:48:57 +03:00

9.4 KiB
Raw Blame History

Лабараторная 2

Минимальный костяк сервиса управления пользователями и OAuth-клиентами. Предоставляет REST API по пути /auth/*, GraphQL-эндпоинт по адресу /graphql и небольшое админ-SPA на чистом JS, отдаваемое по /admin.

Основные технологии:

  • Python 3.12
  • FastAPI - REST API (/auth/register, /auth/login, /auth/me)
  • Ariadne - GraphQL-сервер
  • SQLAlchemy 2.x - ORM
  • Alembic - миграции
  • SQLite - база данных
  • argon2-cffi - хеширование паролей Argon2id + стойкость через zxcvbn
  • python-jose - JWT токены

Установка

git clone https://vantablacktea.ddns.net/Agzamus/scripts-2.git
cd scripts-2

С помощью uv

Скачать uv

uv sync
uv run python run.py

Тесты:

uv run pytest -q

Альтернатива с pip

Linux:

python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Windows:

python -m venv .venv
source .venv\Scripts\activate
pip install -r requirements.txt

Настройка

Необходимо создать .env файл, например скопировав пример:

cp .env.example .env

Записать для JWT_SECRET и PASSWORD_PEPPER длинные случайные строки JWT_SECRET подписывает каждый access-токен, а PASSWORD_PEPPER добавляется к паролю перед хешированием

Переменные из .env.example:

Переменная Пример Назначение
DATABASE_URL sqlite:///./vault.db Строка подключения SQLAlchemy
JWT_SECRET replace_with_a_long_random_string Секрет для подписи/проверки JWT
JWT_ALGORITHM HS256 Алгоритм подписи JWT
ACCESS_TOKEN_TTL_MIN 60 Время жизни access-токена в минутах
PASSWORD_PEPPER replace_with_another_long_random_string Глобальный секрет, добавляемый перед хешированием
PASSWORD_MIN_LENGTH 12 Минимальная длина пароля
ENVIRONMENT development Метка окружения выполнения
APP_NAME Vault Заголовок приложения

Запуск

Примените миграции базы данных, затем запустите сервер:

uv run alembic upgrade head # создать/обновить схему базы данных
uv run python run.py        # uvicorn на 0.0.0.0:8000 с reload

Или напрямую:

uv run uvicorn app.main:app --reload

После запуска:

Заполнение демо-данными

Администратор

Может открыть админ-панель

Почта:

admin@example.com

Пароль:

Kz8#Fj2!Lm9@Qw4$xR
Пользователь
user@example.com
DemoUser-Pass#2024
OAuth-клиент

demo-client - "Demo App"

redirect_uris = ["https://example.com/callback"]

Заполнение:

Убедитесь, что схема создана (запустите один раз или при каждом изменении миграций):

uv run alembic upgrade head

Запустите скрипт заполнения:

uv run python seed.py

Запустите сервер:

uv run python run.py

Админ панель: http://localhost:8000/admin

Свои учётные данные

Переопределите значения по умолчанию через переменные окружения, например:

SEED_ADMIN_EMAIL=root@corp.io \
SEED_ADMIN_PASSWORD='S0me-very-Long-Random-Passphrase!42' \
uv run python seed.py
Переменная Значение по умолчанию
SEED_ADMIN_EMAIL admin@example.com
SEED_ADMIN_PASSWORD Kz8#Fj2!Lm9@Qw4$xR
SEED_USER_EMAIL user@example.com
SEED_USER_PASSWORD DemoUser-Pass#2024

Пароли из seed-скрипта обходят политику стойкости при регистрации

Сброс

Чтобы сбросить базу данных:

rm -f vault.db
uv run alembic upgrade head
uv run python seed.py

Структура проекта

.
├── alembic/                # окружение миграций Alembic
├── alembic.ini             # конфигурация Alembic
├── app/
│   ├── main.py             # FastAPI приложение
│   ├── config.py           # настройки из .env
│   ├── db/                 # движок, SessionLocal, get_db() и декларативная Base
│   ├── models/             # модели SQLAlchemy: User, OAuthClient, AuditEvent
│   ├── core/               # JWT, хеширование паролей, зависимости аутентификации
│   ├── auth/               # REST и схемы Pydantic
│   ├── audit/              # запись событий в базу данных
│   ├── graphql/            # схема Ariadne, резолверы, контекст и директивы
│   │   └── schema.graphql  # SDL GraphQL
│   └── static/             # Фронт
├── tests/                  # тесты Pytest
├── run.py                  # точка входа Uvicorn
├── seed.py                 # заполнение демо-данными
├── pyproject.toml          # метаданные проекта и зависимости (uv)
└── requirements.txt        # зафиксированные зависимости для установки через pip

Пример GraphQL

Передайте JWT как bearer-токен:

curl http://localhost:8000/graphql/ \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <token>' \
  -d '{"query": "{ me { email } }"}'

Тело запроса:

{ me { email } }

Пример ответа:

{
  "data": {
    "me": {
      "email": "user@example.com"
    }
  }
}

Тестирование

uv run pytest -q

Примечания

.env и *.db не коммитятся - они перечислены в .gitignore вместе с __pycache__/, .venv/ и другими локальными артефактами

Держите секреты и локальные базы данных вне системы контроля версий