REST API для управления списками задач: регистрация и аутентификация пользователей по JWT, CRUD над списками (TodoList) и задачами внутри них (TodoItem). Учебный pet-проект, написанный для практики backend-разработки на Go.
- Go — основной язык
- Gin — HTTP-фреймворк / роутинг
- PostgreSQL — база данных
- sqlx — работа с БД
- golang-migrate — миграции схемы
- Viper — конфигурация (
configs/config.yml) - godotenv — секреты из
.env - JWT (
dgrijalva/jwt-go) — аутентификация - bcrypt — хеширование паролей
- logrus — логирование
- Docker / docker-compose — запуск
Приложение разбито на три слоя с однонаправленным потоком зависимостей:
handler → service → repository → PostgreSQL
(HTTP) (логика) (SQL)
- handler — парсинг запроса, вызов сервиса, формирование ответа
- service — бизнес-логика и валидация (например, проверка, что список принадлежит пользователю)
- repository — SQL-запросы к Postgres
Маршрут запроса проходит сверху вниз, ответ — обратно. JWT проверяется middleware до попадания в защищённые хендлеры.
.
├── cmd/main.go # точка входа, graceful shutdown
├── configs/config.yml # несекретная конфигурация
├── schema/ # SQL-миграции (up / down)
├── pkg/handler/ # HTTP-слой
├── pkg/handler/service/ # бизнес-логика
├── pkg/handler/service/repository/ # работа с БД
├── server.go # обёртка http.Server
├── todo.go / user.go # доменные структуры
├── Dockerfile
├── docker-compose.yml
└── .env # секреты (не коммитится)
Несекретные параметры — в configs/config.yml:
port: "8000"
db:
host: "localhost" # для docker-compose поменяйте на "db"
port: "5436"
username: "postgres"
dbname: "postgres"
sslmode: "disable"Секреты — в .env (скопируйте из .env.example):
DB_PASSWORD=qwerty
SIGNING_KEY=change_me_to_a_long_random_secret
Поднимает Postgres, накатывает миграции и запускает приложение одной командой.
cp .env.example .env # и впишите свои значения
docker-compose up --buildВнутри Docker приложение обращается к БД по имени сервиса
db. Убедитесь, что вconfig.ymlдля этого режимаhost: "db".
API будет доступен на http://localhost:8000.
- Поднимите Postgres в Docker:
docker run --name todo-db -e POSTGRES_PASSWORD=qwerty -p 5436:5432 -d postgres:15-alpine- Накатите миграции (нужен установленный
migrate):
migrate -path ./schema -database 'postgres://postgres:qwerty@localhost:5436/postgres?sslmode=disable' up- Запустите приложение (
host: "localhost"в конфиге):
go run cmd/main.go| Метод | Путь | Описание | Auth |
|---|---|---|---|
| POST | /auth/sign-up |
Регистрация пользователя | — |
| POST | /auth/sign-in |
Логин, возвращает JWT-токен | — |
| Метод | Путь | Описание |
|---|---|---|
| POST | /api/lists/ |
Создать список |
| GET | /api/lists/ |
Все списки пользователя |
| GET | /api/lists/:id |
Список по id |
| PUT | /api/lists/:id |
Обновить список |
| DELETE | /api/lists/:id |
Удалить список |
| Метод | Путь | Описание |
|---|---|---|
| POST | /api/lists/:id/items/ |
Создать задачу |
| GET | /api/lists/:id/items/ |
Все задачи списка |
| GET | /api/lists/:id/items/:item_id |
Задача по id |
| PUT | /api/lists/:id/items/:item_id |
Обновить задачу |
| DELETE | /api/lists/:id/items/:item_id |
Удалить задачу |
Регистрация:
curl -X POST http://localhost:8000/auth/sign-up \
-H "Content-Type: application/json" \
-d '{"name":"Brem","username":"bremcm","password":"qwerty"}'Логин (возвращает токен):
curl -X POST http://localhost:8000/auth/sign-in \
-H "Content-Type: application/json" \
-d '{"username":"bremcm","password":"qwerty"}'Создание списка (подставьте токен из логина):
curl -X POST http://localhost:8000/api/lists/ \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"title":"My list","description":"Things to do"}'Пять таблиц: users, todo_lists, todo_items и две связующие — users_lists
(пользователь ↔ список) и lists_items (список ↔ задача). Связи — many-to-many через
внешние ключи с ON DELETE CASCADE.