Модуль аутентификации для продукта Orbitto в рамках Advanced Engineer Challenge:
- Регистрация пользователя
- Авторизация и выдача JWT-токенов (access + refresh)
- Восстановление пароля по e‑mail (reset‑token)
Сервис работает по gRPC и использует PostgreSQL в Docker Compose.
- Язык: Go
- Простая сборка в один бинарник, удобно для gRPC и микросервисов.
- Хорошая экосистема для сетевых сервисов, миграций, PostgreSQL, JWT.
- gRPC (+ protobuf) – строгая схема контракта, типобезопасность, удобная генерация кода.
- PostgreSQL – стабильная, привычная реляционная БД, хорошо подходит для хранения пользователей.
- golang-migrate – простой и надёжный инструмент для миграций через код/CLI.
- Docker Compose – минимальный, но воспроизводимый стенд для локального запуска (IaC).
Альтернативы, которые рассматривал:
- REST вместо gRPC – проще дебажить через браузер, но в задании явно просят gRPC/GraphQL, поэтому выбрал gRPC.
Требования:
- Docker
- Docker Compose
Команды из корня проекта:
docker compose build
docker compose upЧто при этом поднимается:
db– контейнер с PostgreSQL15-alpineauth-service– gRPC-сервис аутентификации на порту5555
При старте сервис:
- Подключается к PostgreSQL.
- Прогоняет миграции из
./migrations. - Запускает gRPC‑сервер на
:5555.
Ожидаемые строки:
Running database migrations...Migrations applied successfully or already up to dategRPC Server listening on :5555
Требования:
- Go
1.22+ - Локальный PostgreSQL
-
Настроить БД (по умолчанию):
- host:
localhost - port:
5432 - user:
postgres - password:
postgres - database:
postgres
- host:
-
Создать
.env(есть пример.env.example) или экспортировать переменные в shell: -
Запустить сервис:
go run ./cmd/auth-service/main.goПрото‑контракт: api/proto/identity.proto
Сервис:
identity.IdentityService
Методы:
Register(RegisterRequest) returns (RegisterResponse)Login(LoginRequest) returns (LoginResponse)ForgotPassword(ForgotPasswordRequest) returns (ForgotPasswordResponse)ResetPassword(ResetPasswordRequest) returns (ResetPasswordResponse)
Register
{
"email": "test@example.com",
"password": "StrongP@ssword123!",
"display_name": "Test User"
}Login
{
"email": "test@example.com",
"password": "StrongP@ssword123!"
}ForgotPassword
{
"email": "test@example.com"
}Токен сброса попадает в лог сервиса в виде ссылки:
[EMAIL STUB] To: test@example.com | Reset Link: http://localhost:5555/reset?token=...
ResetPassword
{
"token": "СКОПИРОВАННЫЙ_ТОКЕН_ТУТА",
"new_password": "NewStrongP@ss123!"
}Запуск тестов:
go test ./...Что покрыто:
internal/domain/user_test.go- Проверка сложности пароля (
ValidatePassword). - Проверка статуса пользователя (
IsPro).
- Проверка сложности пароля (
internal/app/auth_service_test.go- Фейковый in‑memory
UserRepositoryдля unit‑тестов. - Проверка, что
Loginна несуществующий e‑mail возвращаетErrInvalidCredentials. - Проверка, что
Registerне даёт зарегистрировать пользователя с существующим e‑mail.
- Фейковый in‑memory