{"id":29053407,"url":"https://github.com/cdxy1/fastapi-merch-shop","last_synced_at":"2026-04-29T23:03:10.066Z","repository":{"id":277894814,"uuid":"930709163","full_name":"cdxy1/fastapi-merch-shop","owner":"cdxy1","description":"Merch shop FastAPI","archived":false,"fork":false,"pushed_at":"2026-04-25T16:22:27.000Z","size":305,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-04-25T16:24:24.406Z","etag":null,"topics":["fastapi","postgres","pyhton","redis","sqlalchemy"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cdxy1.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-02-11T04:35:07.000Z","updated_at":"2026-04-25T16:22:31.000Z","dependencies_parsed_at":"2025-05-14T05:15:39.749Z","dependency_job_id":"1d443331-95fc-4110-ac51-3181f1d4d54b","html_url":"https://github.com/cdxy1/fastapi-merch-shop","commit_stats":null,"previous_names":["cdxy1/avito-test-task"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/cdxy1/fastapi-merch-shop","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdxy1%2Ffastapi-merch-shop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdxy1%2Ffastapi-merch-shop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdxy1%2Ffastapi-merch-shop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdxy1%2Ffastapi-merch-shop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cdxy1","download_url":"https://codeload.github.com/cdxy1/fastapi-merch-shop/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdxy1%2Ffastapi-merch-shop/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32447312,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-29T22:27:22.272Z","status":"ssl_error","status_checked_at":"2026-04-29T22:10:49.234Z","response_time":110,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fastapi","postgres","pyhton","redis","sqlalchemy"],"created_at":"2025-06-27T01:06:06.595Z","updated_at":"2026-04-29T23:03:10.053Z","avatar_url":"https://github.com/cdxy1.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# fastapi-merch-shop\n\nREST API магазина мерча с монетной системой. Пользователи получают монеты при регистрации, могут покупать товары и переводить монеты друг другу.\n\n## Стек\n\n| Компонент | Технология |\n|-----------|------------|\n| Framework | FastAPI (async) |\n| Database | PostgreSQL + SQLAlchemy 2.0 (asyncpg) |\n| Migrations | Alembic |\n| Sessions | Redis (refresh tokens) |\n| Auth | JWT (access + refresh tokens) |\n| Package manager | uv |\n| Containerization | Docker / Docker Compose |\n| Tests | pytest-asyncio, SQLite in-memory |\n| Load testing | Locust |\n\n## Структура проекта\n\n```\nsrc/\n├── config.py           # конфигурация из env\n├── db.py               # SQLAlchemy engine, сессии\n├── main.py             # FastAPI app, lifespan, exception handlers\n├── models/\n│   ├── user.py         # UserModel\n│   ├── item.py         # ItemModel\n│   ├── transaction.py  # TransferModel\n│   └── purchase.py     # PurchaseModel\n├── repository/         # слой БД — только SQL-запросы\n│   ├── user.py\n│   ├── item.py\n│   └── transaction.py\n├── service/            # бизнес-логика\n│   ├── auth.py\n│   └── transaction.py\n├── routes/             # HTTP-слой\n│   ├── auth.py\n│   └── transaction.py\n├── schemas/            # Pydantic request/response модели\n│   ├── user.py\n│   ├── transaction.py\n│   └── response.py\n└── utils/\n    ├── security.py     # JWT, bcrypt, redis-хелперы\n    └── redis.py        # RedisClient\n\nmigrations/             # Alembic\ntests/\n├── conftest.py\n└── routes/\n    ├── test_auth.py\n    └── test_transaction.py\n```\n\n## API\n\nВсе маршруты доступны с префиксом `/api` (задан через `root_path`).\n\n### Auth\n\n| Метод | Путь | Описание | Auth |\n|-------|------|----------|------|\n| `POST` | `/register` | Регистрация | — |\n| `POST` | `/auth` | Логин, возвращает access + refresh токены | — |\n| `POST` | `/refresh` | Обновить access token по refresh | Bearer |\n| `PATCH` | `/change_password` | Сменить пароль | Bearer |\n| `DELETE` | `/logout` | Инвалидировать refresh token | Bearer |\n\n### Транзакции\n\n| Метод | Путь | Описание | Auth |\n|-------|------|----------|------|\n| `POST` | `/buy/{item}` | Купить товар за монеты | Bearer |\n| `POST` | `/sendCoin` | Перевести монеты другому пользователю | Bearer |\n| `GET` | `/info` | Баланс, инвентарь, история переводов | Bearer |\n\n**Swagger UI:** `http://localhost:8000/api/docs`\n\n### Примеры запросов\n\n```bash\n# Регистрация\ncurl -X POST http://localhost:8000/api/register \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"username\": \"artem\", \"password\": \"secret123\"}'\n\n# Логин\ncurl -X POST http://localhost:8000/api/auth \\\n  -F \"username=artem\" -F \"password=secret123\"\n\n# Купить товар\ncurl -X POST http://localhost:8000/api/buy/t-shirt \\\n  -H \"Authorization: Bearer \u003caccess_token\u003e\"\n\n# Перевести монеты\ncurl -X POST http://localhost:8000/api/sendCoin \\\n  -H \"Authorization: Bearer \u003caccess_token\u003e\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"user\": \"bob\", \"amount\": 100}'\n\n# Информация о пользователе\ncurl http://localhost:8000/api/info \\\n  -H \"Authorization: Bearer \u003caccess_token\u003e\"\n```\n\n### Пример ответа `/info`\n\n```json\n{\n  \"coins\": 870,\n  \"inventory\": [\n    {\"type\": \"t-shirt\", \"quantity\": 1}\n  ],\n  \"CoinHistory\": {\n    \"received\": [],\n    \"sent\": [\n      {\"toUser\": \"bob\", \"amount\": 50}\n    ]\n  }\n}\n```\n\n### Коды ответов\n\n| Код | Описание |\n|-----|----------|\n| `200` | Успех |\n| `201` | Создано (регистрация) |\n| `400` | Неверный запрос (недостаток монет, неверный пароль) |\n| `401` | Не авторизован |\n| `403` | Доступ запрещён |\n| `404` | Не найдено |\n| `409` | Пользователь уже существует |\n| `503` | Redis недоступен |\n\n### Товары\n\nПри запуске через `alembic upgrade head` в БД сидируются 11 товаров:\n\n| Товар | Цена |\n|-------|------|\n| t-shirt | 80 |\n| cup | 20 |\n| book | 50 |\n| pen | 10 |\n| powerbank | 200 |\n| hoody | 300 |\n| umbrella | 200 |\n| socks | 10 |\n| wallet | 50 |\n| pink-hoody | 500 |\n\nНовый пользователь получает **1000 монет** при регистрации.\n\n## Запуск\n\n### Переменные окружения\n\nСкопируйте `.env.example` и заполните:\n\n```bash\ncp .env.example .env\n```\n\n```env\nALGORITHM=HS256\nSECRET_KEY=\u003cсгенерировать: openssl rand -hex 32\u003e\nEXPIRATION_SECONDS=3600\n\nREDIS_HOST=localhost\nREDIS_PORT=6379\n\nPOSTGRES_HOST=localhost\nPOSTGRES_PORT=5432\nPOSTGRES_USER=admin\nPOSTGRES_PASSWORD=changeme\nPOSTGRES_DB=merch_db\n```\n\n### Docker Compose (рекомендуется)\n\n```bash\n# Запустить postgres, redis, приложение\njust up\n\n# Применить миграции (в первый раз)\njust upgrade\n\n# Остановить\njust down\n```\n\nИли напрямую:\n\n```bash\ndocker compose up -d --build\ndocker compose exec fastapi alembic upgrade head\n```\n\n### Локально (без Docker)\n\nНужны запущенные PostgreSQL и Redis.\n\n```bash\n# Установить зависимости\nuv sync\n\n# Применить миграции\nuv run alembic upgrade head\n\n# Запустить\nuvicorn src.main:app --reload\n```\n\nПриложение: `http://localhost:8000`\n\n## Разработка\n\n```bash\njust test      # запустить тесты\njust lint      # ruff check --fix\njust fmt       # ruff format\njust migrate   # создать новую миграцию: just migrate msg=\"описание\"\njust upgrade   # применить миграции\n```\n\n## Тесты\n\n17 тестов, SQLite in-memory — внешние сервисы не нужны:\n\n```bash\nuv run pytest -v\n```\n\nТесты покрывают:\n\n- Регистрацию и логин (успех / дубликат / неверный пароль)\n- Refresh и logout токенов\n- Смену пароля (успех / неверный старый пароль)\n- Покупку товара (успех / недостаток монет / товар не найден)\n- Перевод монет (успех / недостаток / получатель не найден)\n- Получение информации о пользователе\n\n## Деплой в Minikube\n\nPostgreSQL и Redis запускаются локально (через `docker compose` или нативно). Приложение деплоится в minikube и обращается к ним через `host.docker.internal`.\n\n### Требования\n\n```bash\nbrew install minikube kubectl\nminikube start --driver=docker\n```\n\n### Структура манифестов\n\n```\nk8s/\n├── configmap.yaml   # ALGORITHM, REDIS_HOST, POSTGRES_HOST и т.д.\n├── secrets.yaml     # SECRET_KEY, POSTGRES_PASSWORD\n├── deployment.yaml  # Deployment (5 реплик), NodePort сервис\n└── service.yaml     # NodePort :30007\n```\n\n### Сборка образа\n\nОбраз собирается внутри Docker-контекста minikube через `docker compose build` — имя образа берётся из `docker-compose.yml`:\n\n```bash\neval $(minikube docker-env)\ndocker compose build\n```\n\n### Деплой\n\n```bash\nkubectl apply -f k8s/\n```\n\nПрименить миграции:\n\n```bash\nkubectl exec deploy/merch-shop-api -- alembic upgrade head\n```\n\nУзнать адрес сервиса:\n\n```bash\nminikube service merch-shop-api-service --url\n# → http://\u003cminikube-ip\u003e:30007\n```\n\n### Обновление после изменений в коде\n\n```bash\neval $(minikube docker-env)\ndocker compose build\nkubectl rollout restart deployment/merch-shop-api\n```\n\n### Полезные команды\n\n```bash\n# логи\nkubectl logs -l app=merch-shop-api -f\n\n# статус подов\nkubectl get pods\n\n# зайти в под\nkubectl exec -it deploy/merch-shop-api -- /bin/bash\n\n# применить миграции\nkubectl exec deploy/merch-shop-api -- alembic upgrade head\n```\n\n## Лицензия\n\nMIT — см. [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcdxy1%2Ffastapi-merch-shop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcdxy1%2Ffastapi-merch-shop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcdxy1%2Ffastapi-merch-shop/lists"}