Skip to content

Repository files navigation

Task Management API

⚠️ Disclaimer: This is a showcase / portfolio project, not a production-ready system. It may evolve toward production use in the future, but as of now it hasn't been hardened, audited, or tested for that purpose. Use it at your own risk — no responsibility is taken for bugs, security issues, or data loss resulting from its use.

RESTful task management API built with Java and Spring Boot. Backend showcase project focused on authentication, authorization, REST API design, persistence, validation, testing, and clean separation of responsibilities.

Features

  • User registration and authentication (JWT access + refresh tokens)
  • Refresh token rotation with reuse prevention
  • Refresh tokens stored as SHA-256 hashes (never in plaintext)
  • Logout with refresh token revocation
  • Role based authorization
  • Project, task, and comment management
  • Task status and priority management, task assignment
  • Pagination and sorting
  • Request validation and global exception handling
  • PostgreSQL persistence
  • Integration tests with Testcontainers
  • Docker support

Tech Stack

Java 25 · Spring Boot · Spring Security · Spring Data JPA · Hibernate · PostgreSQL · Gradle · JUnit 5 · MockMvc · Testcontainers · Docker

Architecture

Layered architecture with domain based package organization (controller → service → repository), separating entities (persistent domain objects) from DTOs (API contract).

src/main/java/dev/iamforyy/taskmanagementapi/
├── auth/       AuthController, AuthService, JwtService
├── user/       User, UserController, UserService, UserRepository
├── project/    Project, ProjectController, ProjectService, ProjectRepository
├── task/       Task, TaskController, TaskService, TaskRepository
└── comment/    Comment, CommentController, CommentService, CommentRepository

Authentication

Two-token model:

  • Access token — short lived, authenticates API requests
  • Refresh token — long lived, used to obtain a new access token; stored as a SHA-256 hash

Refresh flow (rotation): validate existing token → revoke it → issue new access + refresh tokens → store new hash → return both to the client. This prevents a consumed refresh token from being reused.

API Endpoints

Authentication

Method Endpoint Description Auth
POST /auth/register Register a new user Public
POST /auth/login Authenticate a user Public
POST /auth/refresh Refresh access and refresh tokens Public
POST /auth/logout Revoke a refresh token Public

Users

Method Endpoint Description Auth
GET /api/users/me Get the currently authenticated user Required

Projects

Method Endpoint Description Auth
GET /api/projects Get projects Required
GET /api/projects/{projectId} Get a project by ID Required
POST /api/projects Create a project Required
PATCH /api/projects/{projectId} Update a project Required
DELETE /api/projects/{projectId} Delete a project Required

Tasks

Method Endpoint Description Auth
GET /api/tasks Get tasks Required
GET /api/tasks/{taskId} Get a task by ID Required
POST /api/tasks Create a task Required
PATCH /api/tasks/{taskId} Update a task Required
PATCH /api/tasks/{taskId}/status Update task status Required
DELETE /api/tasks/{taskId} Delete a task Required

Comments

Method Endpoint Description Auth
GET /api/tasks/{taskId}/comments Get task comments Required
POST /api/tasks/{taskId}/comments Create a comment Required
PATCH /api/comments/{commentId} Update a comment Required
DELETE /api/comments/{commentId} Delete a comment Required

Example Flow

POST /auth/register
Content-Type: application/json

{ "username": "john", "email": "john@example.com", "password": "password123" }
POST /auth/login
Content-Type: application/json

{ "email": "john@example.com", "password": "password123" }

Response:

{ "accessToken": "eyJ...", "refreshToken": "..." }

Authenticated request:

GET /api/users/me
Authorization: Bearer eyJ...

Refresh (returns a new access + refresh token pair; previous refresh token is revoked):

POST /auth/refresh
Content-Type: application/json

{ "refreshToken": "..." }

Logout (revokes the refresh token):

POST /auth/logout
Content-Type: application/json

{ "refreshToken": "..." }

Pagination

Collection endpoints support pagination and sorting via Spring Data's Pageable:

GET /api/projects?page=0&size=20&sort=name,asc

Validation & Error Handling

Request DTOs use Jakarta Bean Validation. Invalid requests, auth errors, missing resources, and invalid/expired tokens are handled by a global exception handler with a consistent error shape:

{
  "status": 404,
  "code": "RESOURCE_NOT_FOUND",
  "message": "Task not found",
  "timestamp": "2026-08-25T12:00:00Z"
}

Database

User
 ├── Project
 │    └── Task
 │         └── Comment
 └── RefreshToken

PostgreSQL, mapped via JPA. Passwords are hashed with Spring Security's PasswordEncoder; refresh tokens are stored as SHA-256 hashes. No sensitive data is ever stored in plaintext.

Testing

Integration tests with JUnit 5, Spring Boot Test, MockMvc, and Testcontainers, covering auth requirements, token refresh/logout, registration, validation, response status/content, and persistence.

./gradlew test        # gradlew.bat test on Windows

Running Locally

Requirements: Java 25, Docker, PostgreSQL, Git

git clone <repository-url>
cd task-management-api

Set the required environment variables (e.g. via .env — never commit real secrets):

POSTGRES_DB=tmapdb
POSTGRES_USER=tmap
POSTGRES_PASSWORD=your_postgres_password

JWT_SECRET=your_jwt_secret
JWT_EXPIRATION=300000

Run:

./gradlew bootRun     # gradlew.bat bootRun on Windows

API available at http://localhost:8080.

Docker

./gradlew build
docker build -t task-management-api .
docker run -p 8080:8080 task-management-api

Or run the full stack (API + PostgreSQL) with Docker Compose:

docker compose up

Project Goals

This project demonstrates production-oriented backend development practices, including:

  • Authentication & authorization with Spring Security (JWT access + rotating refresh tokens, role-based authorization)
  • Persistence with Spring Data JPA + Hibernate and relational data modeling
  • Layered architecture with clear domain/DTO separation
  • Request validation and centralized error handling
  • Integration testing with Testcontainers
  • Containerization for reproducible deployment

Future Improvements

  • OpenAPI / Swagger documentation
  • Rate limiting
  • Redis caching
  • Better refresh token reuse detection
  • Email verification & password reset
  • Account management
  • Advanced task filtering
  • Project-scoped membership - restrict project visibility to the creator and users explicitly added by the project owner
  • Per-project roles/permissions (e.g. owner vs. member, beyond the current global role check)
  • Audit logging
  • CI/CD improvements & production deployment

License

MIT License.

About

A backend application for task management and user authentication.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages