Categorygithub.com/F0rzend/grpc_user_auth
module
0.1.0
Repository: https://github.com/f0rzend/grpc_user_auth.git
Documentation: pkg.go.dev

# README

gRPC Basic Auth

Необходимо написать веб сервис который занимается хранением профилей пользователей и их авторизацией.

Профиль имеет набор полей:

  1. id (uuid, unique)
  2. email
  3. username (unique)
  4. password
  5. admin (bool)

Сервис должен иметь набор ручек (gRPC): Создание пользователя, Выдача списка пользователей Выдача юзера по id Изменение и удаление профиля

Сервис использует basic access authentication (https://en.wikipedia.org/wiki/Basic_access_authentication)

Просматривать профили могут все зарегистрированные пользователи. Админ может создавать, изменять и удалять профили.

Для хранения данных профилей необходимо реализовать примитивную in memory базу данных, не используя сторонние решения.

Зависимости для разработки

  • golangci-lint -- Для поддержки кода в хорошем состоянии
  • protoc + proto-gen-go & protoc-gen-go-grpc -- Для компиляции proto файлов
  • pre-commit -- Для исключения возможности создавать коммиты с "грязным" кодом
  • docker(with compose) -- Для разворачивания окружения
  • make -- Для упрощения работы с окружением

Запуск

Перед запуском проекта нужно прописать необходимые переменные окружения. Docker compose использует .env файл, пример которого находится в .env.example.

После создания .env файла, можно запустить проект с помощью команды make run, что запустит проект через docker compose.

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

В проекте реализованы unit тесты для Repository и сквозные end-to-end тесты для всего приложения.

Unit тесты

Запуск unit тестов осуществляется командой make test-unit.

End-to-end тесты

Для end-to-end тестов приложение запускается в изолированном docker контейнере, с использованием testcontainers. Сами же тесты вызываются из хостовой системы.

End-to-end тесты не читают .env файл, поэтому необходимо прописать переменные окружения вручную.

Запуск end-to-end тестов осуществляется командой make test-e2e.

Архитектура приложения

Директория proto содержит описание gRPC сервиса и сгенерированный код.

Директория internal содержит основной код приложения.

В директории tests содержатся end-to-end тесты.

В приложении используется чистая архитектура, с разделением на слои:

  • transport -- слой представления: обслуживание gRPC запросов
  • use_cases -- слой бизнес-логики
  • infrastructure -- источник данных: обращения к базе данных

Альтернативная структура

Причиной выбрать подобную структуру директорий послужил факт того, что данное приложение является примитивным CRUD интерфейсом для лишь одной сущности. В приложении с несколькими агрегатами и сложной бизнес-логикой архитектура могла бы выглядеть так:

internal/
├── main.go
├── common/
│   ├── context_logger.go
│   ├── disabled_logger.go
│   └── flagged_error.go
└── user/
    ├── models.go
    ├── usecases.go
    ├── handlers.go
    ├── repository.go
    └── repository_test.go

Решения и примечания

  • Для обработки доменных ошибок в пакете internal/common был реализован простой механизм обработки ошибок, описанный Nate Finch здесь Error Flags

  • Так как проект является примитивным CRUD интерфейсом и не содержит сложной бизнес-логики, было принято решение отказаться от слоя бизнес-логики и использовать обычную анемичную модель для представления данных в приложении.

  • API приложения следует CQS принципу, поэтому команды апи, такие, как создание и изменение пользователя, возвращают пустой объект.

  • Для хранения данных был выбран sync.Map, так как он является потокобезопасным

  • Так как sync.Map не предоставляет возможности получить количество записей, Repository.GetAll создаёт пустой срез и на каждой итерации расширяет его при необходимости (append). Это негативно сказывается на производительности. Можно было бы считать количество записей в отдельной переменной, но на данном этапе в этом нет необходимости.

  • Так как для создания пользователя необходимо авторизоваться, как администратор, было принято решение создавать первого администратора при старте приложения, используя значения из переменных окружения.

  • Для хранения паролей пользователей используется bcrypt.

# Packages

No description provided by the author
No description provided by the author