REST API платформы SsuBench: заказчики публикуют задания, исполнители оставляют отклики, заказчик выбирает исполнителя и подтверждает выполнение. После подтверждения баллы атомарно списываются у заказчика и начисляются исполнителю.
- .NET SDK 10
- Docker и Docker Compose
- PostgreSQL запускается через Docker
ASPNETCORE_URLS=http://+:8080
ConnectionStrings__Postgres=Host=localhost;Port=5432;Database=ssubench;Username=ssubench;Password=ssubench
Jwt__Issuer=SsuBench
Jwt__Secret=change-this-secret-to-a-long-random-value
Admin__RegistrationSecret=change-this-admin-registration-secretdocker compose up -d postgres
psql "postgresql://ssubench:ssubench@127.0.0.1:5432/ssubench" -f SsuBench/migrations/001_init.sql
dotnet restore
dotnet run --project SsuBenchЕсли на macOS psql попадает в локальный PostgreSQL вместо контейнера, примените миграцию внутри контейнера:
docker compose exec -T postgres psql -U ssubench -d ssubench -f /docker-entrypoint-initdb.d/001_init.sqlПолный запуск в Docker:
docker compose up --buildПри первом запуске Docker скачивает образы .NET/Postgres и NuGet-пакеты, поэтому dotnet restore внутри сборки может занять несколько минут. Повторные сборки используют Docker BuildKit cache для NuGet. Миграция 001_init.sql применяется контейнером Postgres автоматически при первом создании volume.
Если приложение запущено через dotnet run, API доступно на адресе из вывода ASP.NET. При Docker Compose API доступно на http://localhost:8080.
dotnet testcurl -s -X POST http://localhost:8080/auth/register \
-H "Content-Type: application/json" \
-d '{"email":"customer@example.com","password":"Password123!","role":"customer"}'CUSTOMER_TOKEN="..."
EXECUTOR_TOKEN="..."
curl -s -X POST http://localhost:8080/tasks \
-H "Authorization: Bearer $CUSTOMER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"title":"Build landing page","description":"Create adaptive HTML/CSS page","price":100}'
curl -s -X POST http://localhost:8080/tasks/1/bids \
-H "Authorization: Bearer $EXECUTOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"message":"I can do it today"}'
curl -s -X POST http://localhost:8080/tasks/1/bids/1/accept \
-H "Authorization: Bearer $CUSTOMER_TOKEN"
curl -s -X POST http://localhost:8080/tasks/1/complete \
-H "Authorization: Bearer $EXECUTOR_TOKEN"
curl -s -X POST http://localhost:8080/tasks/1/confirm \
-H "Authorization: Bearer $CUSTOMER_TOKEN"Администратор регистрируется ролью admin только при передаче adminSecret, совпадающего с Admin__RegistrationSecret, и может блокировать пользователей:
curl -s -X POST http://localhost:8080/auth/register \
-H "Content-Type: application/json" \
-d '{"email":"admin@example.com","password":"Password123!","role":"admin","adminSecret":"change-this-admin-registration-secret"}'
curl -s -X POST http://localhost:8080/admin/users/2/block \
-H "Authorization: Bearer $ADMIN_TOKEN"Статический контракт находится в SsuBench/openapi.yaml. Swagger UI доступен на /docs, JSON Swagger-контракт — на /swagger/v1/swagger.json, встроенный OpenAPI endpoint — на /openapi/v1.json.