Skip to content

Repository files navigation

Library Management API

Go Gin PostgreSQL Docker License Quality Gate

REST API for managing users, books, borrowing, and returns in a small library system. Built with Clean Architecture, role-based access control, and database-level invariants.


What This Project Includes

  • JWT authentication with role-based access for admin, librarian, and member
  • Book CRUD with search, sorting, and pagination
  • Borrow and return flow with transaction boundary in the service layer
  • Stock and active-borrow invariants enforced in PostgreSQL
  • Unit, integration, and E2E test layers
  • GitHub Actions quality gate for lint and unit tests

Stack

  • Go 1.24
  • Gin (HTTP framework)
  • GORM (ORM)
  • PostgreSQL (with pg_trgm for search)
  • Zerolog (structured logging)
  • JWT (golang-jwt/v5)
  • Testify + SQLMock (testing)
  • golangci-lint (code quality)
  • Docker + docker-compose

Architecture

┌──────────────────────────────────────────────────┐
│                  HTTP Layer                        │
│  Router → Middleware (Auth, RBAC) → Handler        │
├──────────────────────────────────────────────────┤
│                Service Layer                       │
│  Business logic + transaction boundaries           │
├──────────────────────────────────────────────────┤
│              Repository Layer                      │
│  GORM queries + database invariants                │
├──────────────────────────────────────────────────┤
│         PostgreSQL (constraints, indexes)          │
└──────────────────────────────────────────────────┘
library-management-api/
├── cmd/api/          # Application entrypoint
├── configs/          # Configuration loader
├── docs/adr/         # Architecture Decision Records
├── internal/
│   ├── dto/          # Request/response data transfer objects
│   ├── handler/      # HTTP handlers
│   ├── middleware/   # Auth, RBAC middleware
│   ├── models/       # Domain models
│   ├── repository/   # Data access layer
│   └── service/      # Business logic
├── pkg/              # Shared packages (auth, database, errors, response)
├── tests/
│   ├── unit/         # Unit tests (handlers, services, repos)
│   ├── integration/  # DB-backed + concurrency tests
│   └── e2e/          # End-to-end API tests
├── Dockerfile
├── docker-compose.yml
└── Makefile

Quick Start

1. Prepare environment

cp .env.example .env

2. Start PostgreSQL

make docker-up

3. Run the API

make run

API base URL:

http://localhost:8080

Health endpoints:

GET /health
GET /ready

Environment Variables

Variable Default Notes
APP_PORT 8080 API port
DB_HOST localhost PostgreSQL host
DB_PORT 5432 PostgreSQL port
DB_USER postgres PostgreSQL user
DB_PASSWORD password PostgreSQL password
DB_NAME library_db PostgreSQL database
DB_SSLMODE disable PostgreSQL SSL mode
JWT_SECRET your-super-secret-jwt-key-change-in-production JWT signing secret
JWT_EXPIRY 24h Token expiry
READ_TIMEOUT 10s HTTP read timeout
WRITE_TIMEOUT 10s HTTP write timeout
IDLE_TIMEOUT 60s HTTP idle timeout
MAX_BOOKS_PER_USER 5 Borrow limit per user
BORROW_DAYS 14 Default due date offset
FINE_PER_DAY 1000 Overdue fine per day

API Endpoints

Public

Method Path Description
POST /api/v1/auth/register Register a user
POST /api/v1/auth/login Login and get JWT
GET /health Liveness check
GET /ready Readiness check with DB ping

Protected

Method Path Description
GET /api/v1/books List books
GET /api/v1/books/:id Get book detail
POST /api/v1/books Create book (admin, librarian)
PUT /api/v1/books/:id Update book (admin, librarian)
DELETE /api/v1/books/:id Delete book (admin, librarian)
POST /api/v1/borrow Borrow a book
POST /api/v1/borrow/return Return a book
GET /api/v1/borrow/my-books List current user borrows
GET /api/v1/borrow/active List active borrows (admin, librarian)
GET /api/v1/borrow/overdue List overdue borrows (admin, librarian)

Response Contract

Success shape:

{
  "success": true,
  "message": "optional message",
  "data": {},
  "meta": {}
}

Error shape:

{
  "success": false,
  "message": "book not found",
  "error": {
    "code": "not_found",
    "message": "book not found"
  }
}

List query params:

Param Description
page Positive integer, default 1
limit Positive integer, clamped per endpoint
search Optional search string
sort Optional endpoint-specific sort key

List meta:

{
  "page": 1,
  "limit": 10,
  "total": 42,
  "total_pages": 5
}

Makefile Commands

Command Description
make run Run API locally
make build Build binary
make test Run unit and integration tests
make test-unit Run unit tests
make test-integration Run integration tests
make test-e2e Run E2E tests
make lint Run golangci-lint
make vet Run go vet
make quality Run lint, vet, and unit tests
make docker-up Start PostgreSQL and pgAdmin
make docker-down Stop Docker services

Test Matrix

Layer Command Purpose
Unit go test ./tests/unit/... -v Fast feedback for handlers, services, repositories, middleware
Integration go test ./tests/integration/... -v DB-backed behavior and concurrency checks
E2E go test ./tests/e2e/... -v Happy path against a running API

E2E Preconditions

  • API server must already be running
  • Database must already be available
  • Default E2E base URL is http://localhost:8080
  • Override with E2E_BASE_URL=http://host:port if needed

CI

GitHub Actions workflow:

.github/workflows/quality-gates.yml

Required PR jobs:

  • lint
  • unit-test

Optional manual job:

  • integration-test

ADRs

Release

Notes

  • PostgreSQL-specific constraints and indexes are applied only when the dialector is PostgreSQL.
  • pg_trgm is enabled gracefully. If extension creation fails, the app continues without trigram indexes.
  • Integration concurrency test reference: tests/integration/borrow_concurrency_test.go

About

Library management REST API with Clean Architecture, RBAC, and 3-tier test strategy.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages