# Nashel Backend Бэкенд для маркетплейса услуг "Nashel" — платформа для поиска мастеров и исполнителей. ## 🏗️ Архитектура Проект построен на архитектуре **Clean Architecture** с модульным подходом: ``` nashel-backend/ ├── src/ │ ├── BuildingBlocks/ # Общие блоки для всех модулей │ │ ├── Application/ # Общие абстракции и поведения │ │ ├── Domain/ # Базовые доменные сущности │ │ └── Infrastructure/ # Общая инфраструктура │ ├── Modules/ # Модули бизнес-логики │ │ ├── Identity/ # Модуль авторизации и профилей │ │ └── Order/ # Модуль заказов │ └── Host/ # Точка входа приложения └── tests/ # Тесты ``` ### Модульность Каждый модуль (Identity, Order) является автономным и содержит: - **Domain** — бизнес-логика, сущности, репозитории - **Application** — Use Cases, команды, запросы, валидация - **Infrastructure** — реализация репозиториев, EF Core - **Presentation** — API endpoints ## 🚀 Технологический стек - **.NET 10** — фреймворк - **ASP.NET Core** — веб-фреймворк - **Entity Framework Core** — ORM - **PostgreSQL** — база данных - **MediatR** — паттерн CQRS/Mediator - **FluentValidation** — валидация - **JWT** — аутентификация - **Docker** — контейнеризация - **Swagger/OpenAPI** — документация API ## 📦 Установка и запуск ### Требования - .NET 10 SDK - Docker и Docker Compose - PostgreSQL ### Запуск через Docker Compose ```bash # Клонирование репозитория git clone cd nashel-backend # Запуск всех сервисов docker-compose up -d # Просмотр логов docker-compose logs -f app # Остановка сервисов docker-compose down ``` ### Локальный запуск ```bash # Восстановление зависимостей dotnet restore # Настройка переменных окружения cp src/Host/appsettings.json src/Host/appsettings.Development.json # Отредактируйте ConnectionStrings__DefaultConnection # Применение миграций dotnet ef database update --project src/Host --startup-project src/Host # Запуск dotnet run --project src/Host ``` ## 🔧 Переменные окружения | Переменная | Описание | Пример | |------------|----------|--------| | `ASPNETCORE_ENVIRONMENT` | Окружение | `Development`, `Production` | | `ConnectionStrings__DefaultConnection` | Строка подключения к БД | `Host=db;Port=5432;Database=nashel;Username=postgres;Password=postgres` | | `JWT__Secret` | Секретный ключ JWT | `your-super-secret-key` | | `JWT__Issuer` | Издатель токена | `nashel-api` | | `JWT__Audience` | Аудитория токена | `nashel-client` | | `JWT__ExpirationMinutes` | Время жизни токена (мин) | `60` | ## 📚 API Документация Swagger доступен по адресу: `http://localhost:5000/swagger` ### Основные эндпоинты #### Аутентификация ```http POST /api/auth/register Content-Type: application/json { "phone": "+79001234567", "firstName": "Иван", "lastName": "Иванов", "password": "password123", "confirmPassword": "password123", "isCompany": false, "companyName": "ООО 'Ромашка'", "inn": "1234567890" } ``` ```http POST /api/auth/login Content-Type: application/json { "phone": "+79001234567", "password": "password123" } ``` #### Профиль пользователя ```http GET /api/profile Authorization: Bearer {access_token} PUT /api/profile Authorization: Bearer {access_token} Content-Type: application/json { "firstName": "Иван", "lastName": "Иванов", "patronymic": "Иванович", "companyName": "ООО 'Ромашка'", "inn": "1234567890" } POST /api/profile/change-phone Authorization: Bearer {access_token} Content-Type: application/json { "newPhone": "+79009876543" } POST /api/profile/become-performer Authorization: Bearer {access_token} POST /api/profile/avatar Authorization: Bearer {access_token} Content-Type: multipart/form-data avatar: PUT /api/profile/competencies Authorization: Bearer {access_token} Content-Type: application/json { "Competencies": ["сантехника", "электрика"] } ``` #### Компетенции ```http GET /api/competencies/search?q=сантех Authorization: Bearer {access_token} ``` ## 🎯 Реализованный функционал ### Модуль Identity #### Аутентификация и авторизация - ✅ Регистрация пользователей (частные лица и компании) - ✅ Вход в систему (JWT токены) - ✅ Обновление токенов - ✅ Выход из системы - ✅ Ролевая модель (Client, Master, Candidate, Company, Admin) #### Профиль пользователя - ✅ Получение профиля - ✅ Редактирование профиля - ✅ Изменение номера телефона - ✅ Загрузка аватара с кропом - ✅ Управление компетенциями - ✅ Стать исполнителем #### Компетенции - ✅ Поиск компетенций по подстроке - ✅ Общий пул компетенций для всех исполнителей - ✅ Автоматическое создание новых компетенций #### Компании - ✅ Регистрация компаний с ИНН - ✅ Управление данными компании - ✅ Отдельная логика для компаний ### Модуль Order (в разработке) - ⏳ Создание заказов - ⏳ Поиск заказов на карте - ⏳ SLA таймер для отклика на заказы ## 🗄️ База данных ### Схема ``` accounts (аккаунты пользователей) ├── id (PK) ├── phone (уникальный) ├── password_hash ├── roles (массив ролей) └── profile_id (FK) user_profiles (профили пользователей) ├── id (PK) ├── account_id (FK) ├── first_name ├── last_name ├── patronymic ├── company_name ├── inn (для компаний) ├── avatar_url └── competency_profiles (связь с компетенциями) competencies (компетенции/навыки) ├── id (PK) ├── name (уникальное, в нижнем регистре) competency_profiles (связь профилей и компетенций) ├── id (PK) ├── profile_id (FK) ├── competency_id (FK) ``` ### Миграции ```bash # Создание новой миграции dotnet ef migrations add AddNewFeature --project src/Infrastructure --startup-project src/Host # Применение миграций dotnet ef database update --project src/Infrastructure --startup-project src/Host # Откат последней миграции dotnet ef database update --project src/Infrastructure --startup-project src/Host ``` ## 🔐 Безопасность - Хеширование паролей (BCrypt) - JWT токены с refresh token - Валидация входных данных (FluentValidation) - CORS политика - Rate limiting (в планах) ## 🧪 Тестирование ```bash # Запуск всех тестов dotnet test # Запуск тестов с покрытием dotnet test --collect:"XPlat Code Coverage" # Запуск конкретного теста dotnet test --filter "FullyQualifiedName~TestName" ``` ## 📝 Конвенции кода ### CQRS Pattern Используем MediatR для реализации CQRS: ```csharp // Команда (Command) public record UpdateProfileCommand(...) : IRequest; // Обработчик команды (Handler) public class UpdateProfileCommandHandler : IRequestHandler { public async Task Handle(UpdateProfileCommand request, CancellationToken cancellationToken) { // Логика } } ``` ### Валидация Используем FluentValidation: ```csharp public class UpdateProfileCommandValidator : AbstractValidator { public UpdateProfileCommandValidator() { RuleFor(x => x.FirstName).NotEmpty().MinimumLength(2); RuleFor(x => x.LastName).NotEmpty().MinimumLength(2); } } ``` ## 🚨 Обработка ошибок - Глобальный exception handler - Стандартные HTTP статусы (400, 401, 403, 404, 500) - Подробные сообщения об ошибках в Development режиме - Обобщенные сообщения в Production режиме ## 📦 Статические файлы Загруженные аватары хранятся в `wwwroot/uploads/` и доступны по URL: ``` http://localhost:5000/uploads/{filename} ``` ## 🔄 CI/CD - GitHub Actions для автоматического тестирования - Docker Hub для хранения образов - Автоматический деплой (в планах) ## 📞 Контакты - **Проект:** Nashel - **Версия:** 1.0.0 - **Лицензия:** MIT ## 🤝 Вклад в проект 1. Fork репозитория 2. Создайте ветку для фичи (`git checkout -b feature/AmazingFeature`) 3. Закоммитьте изменения (`git commit -m 'Add some AmazingFeature'`) 4. Запушьте в ветку (`git push origin feature/AmazingFeature`) 5. Откройте Pull Request