A RESTful API service for tracking workouts and managing users, built with Go and PostgreSQL. This project provides endpoints for user registration, authentication via JWT tokens, and comprehensive workout management.
- 🔐 User Authentication: JWT-based authentication system with token management
- 👤 User Management: User registration with secure password hashing
- 🏋️ Workout Tracking: Full CRUD operations for workout management
- 🗄️ Database Migrations: Automated database schema management with Goose
- 🐳 Docker Support: Easy deployment with Docker Compose
- 🔒 Security: Input validation, middleware protection, and secure password handling
POST /api/tokens- Create authentication token (login)POST /api/tokens/revoke-all- Revoke all tokens for authenticated user
POST /api/users- Register new user
GET /api/workouts- Get all workouts for authenticated userGET /api/workouts/{id}- Get specific workout by IDPOST /api/workouts- Create new workoutPUT /api/workouts/{id}- Update existing workoutDELETE /api/workouts/{id}- Delete workout
- Language: Go 1.24.6
- Database: PostgreSQL 17
- Router: Chi v5
- Authentication: JWT (golang-jwt/jwt/v4)
- Password Hashing: bcrypt
- Migrations: Goose
- Database Driver: pq (PostgreSQL driver)
go-workout-api/
├── main.go # Application entry point
├── compose.yml # Docker Compose configuration
├── go.mod # Go module definition
├── internal/
│ ├── api/ # HTTP handlers
│ │ ├── token_handler.go # Authentication endpoints
│ │ ├── user_handler.go # User registration
│ │ └── workout_handler.go # Workout CRUD operations
│ ├── app/
│ │ └── app.go # Application initialization
│ ├── middleware/
│ │ └── middleware.go # Authentication middleware
│ ├── routes/
│ │ └── routes.go # Route configuration
│ ├── store/ # Data access layer
│ │ ├── database.go # Database connection
│ │ ├── tokens.go # Token operations
│ │ ├── user_store.go # User operations
│ │ └── workout_store.go # Workout operations
│ ├── tokens/
│ │ └── tokens.go # JWT utilities
│ └── utils/
│ └── utils.go # Common utilities
└── migrations/ # Database migrations
├── fs.go # Embedded migrations
└── *.sql # Migration files
- Go 1.24.6 or later
- Docker and Docker Compose
- PostgreSQL 17 (if running without Docker)
-
Clone the repository
git clone https://github.com/martialanouman/go-workout-api.git cd go-workout-api -
Start the database with Docker Compose
docker compose up -d db
-
Install dependencies
go mod download
-
Set up environment variables
The application requires a
.envfile for database configuration. Copy the example file and configure it:cp .env.example .env
Edit the
.envfile with your database configuration:DB_HOST=localhost DB_PORT=5432 DB_USER= DB_PASSWORD= DB_NAME=
Note: These values should match your PostgreSQL setup. If using Docker Compose, the default values above will work with the provided configuration.
-
Run database migrations
go run main.go migrate
-
Start the application
go run main.go # or with custom port go run main.go -port=3000
The API will be available at http://localhost:8080 (or your specified port).
To run the entire application stack with Docker Compose:
- Set up environment variables (as described in step 4 above)
- Start all services:
docker compose up -dThis will start both the PostgreSQL database and the application. The compose file includes:
- db: PostgreSQL database on port 5432
- db_test: Test database on port 5433 (for testing purposes)
The application uses the following default configuration:
- Port: 8080 (configurable via
-portflag) - Database: PostgreSQL connection via environment variables
- Timeouts:
- Idle: 1 minute
- Read: 10 seconds
- Write: 30 seconds
id- Unique identifierusername- Unique username (50 chars max)email- Unique email addresspassword_hash- Hashed passwordbio- User biographycreated_at,updated_at- Timestamps
id- Unique identifieruser_id- Reference to users tabletitle- Workout title (100 chars max)description- Workout descriptionduration_minutes- Workout durationcalories_burned- Calories burned during workoutcreated_at,updated_at- Timestamps
- Authentication tokens with expiration and user association
curl -X POST http://localhost:8080/api/users \
-H "Content-Type: application/json" \
-d '{
"username": "johndoe",
"email": "john@example.com",
"password": "securepassword",
"bio": "Fitness enthusiast"
}'curl -X POST http://localhost:8080/api/tokens \
-H "Content-Type: application/json" \
-d '{
"email": "john@example.com",
"password": "securepassword"
}'curl -X POST http://localhost:8080/api/workouts \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{
"title": "Morning Run",
"description": "5km run in the park",
"duration_minutes": 30,
"calories_burned": 300
}'go test ./...To create a new migration:
goose -dir migrations create migration_name sqlTo apply migrations:
goose -dir migrations postgres "user=workout_user password=workout_password dbname=workout_db sslmode=disable" up- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
Martial Anouman - GitHub
Built with ❤️ and Go