Skip to content

Latest commit

 

History

History
179 lines (140 loc) · 4.84 KB

File metadata and controls

179 lines (140 loc) · 4.84 KB

TaskFlow (Java Backend)

1. Overview

TaskFlow is a task management backend where users can register/login, create projects, and manage project tasks with assignment, status tracking, and priorities.

Tech stack:

  • Java 21
  • Spring Boot (Web, Validation, JPA)
  • PostgreSQL 16
  • JWT (jjwt)
  • bcrypt password hashing (cost 12)
  • Bucket4j (rate limiting)
  • Docker + Docker Compose
  • SQL migrations via migrate (with both up/down files)

2. Architecture Decisions

  • Layering: Controllers -> Services -> Repositories to keep business logic out of HTTP handlers.
  • Auth design: JWT auth via an interceptor on all non-auth routes. Claims include user_id and email with 24-hour expiry.
  • Data model decision: Added tasks.created_by to support the required delete authorization rule ("project owner or task creator only").
  • Schema management: SQL-first migrations in backend/migrations, no ORM auto-migrate. spring.jpa.hibernate.ddl-auto=validate ensures schema drift is caught.
  • Tradeoffs: Used in-memory per-IP rate limiting for /auth/login (simple and effective for single API instance). A distributed limiter (Redis) would be better for horizontal scale.
  • Intentionally left out: No frontend app in this repository because this implementation targets backend scope.

3. Running Locally

From a machine with Docker and Docker Compose installed:

git clone https://github.com/your-name/taskflow-your-name
cd taskflow-your-name
cp .env.example .env
docker compose up --build

API will be available at:

  • http://localhost:8080

Health check:

  • GET http://localhost:8080/actuator/health

4. Running Migrations

Migrations are automatically executed by the migrate container during docker compose up.

Manual migration commands (optional):

# Run all up migrations
docker compose run --rm migrate \
  -path /migrations \
  -database "postgres://$POSTGRES_USER:$POSTGRES_PASSWORD@postgres:5432/$POSTGRES_DB?sslmode=disable" \
  up

# Roll back one migration
docker compose run --rm migrate \
  -path /migrations \
  -database "postgres://$POSTGRES_USER:$POSTGRES_PASSWORD@postgres:5432/$POSTGRES_DB?sslmode=disable" \
  down 1

5. Test Credentials

Seeded credentials:

  • Email: test@example.com
  • Password: password123

6. API Reference

Base URL: http://localhost:8080

Auth

  • POST /auth/register

    • body:
      { "name": "Jane Doe", "email": "jane@example.com", "password": "secret123" }
    • response: 201 with { token, user }
  • POST /auth/login

    • body:
      { "email": "jane@example.com", "password": "secret123" }
    • response: 200 with { token, user }
    • rate limited: 429 after 5 requests/IP within 1 minute

Projects (Bearer token required)

  • GET /projects?page=1&limit=20

    • response: 200 with { projects, pagination }
  • POST /projects

    • body:
      { "name": "New Project", "description": "Optional description" }
    • response: 201 with project
  • GET /projects/:id

    • response: 200 with project + tasks
  • PATCH /projects/:id

    • body:
      { "name": "Updated Name", "description": "Updated description" }
    • response: 200 with updated project
  • DELETE /projects/:id

    • response: 204
  • GET /projects/:id/stats (bonus)

    • response: 200 with task counts by status and assignee

Tasks (Bearer token required)

  • GET /projects/:id/tasks?status=todo&assignee=<uuid>&page=1&limit=20

    • response: 200 with { tasks, pagination }
  • POST /projects/:id/tasks

    • body:
      {
        "title": "Design homepage",
        "description": "Optional",
        "priority": "high",
        "assigneeId": "00000000-0000-0000-0000-000000000001",
        "dueDate": "2026-04-20"
      }
    • response: 201 with created task (status defaults to todo)
  • PATCH /tasks/:id

    • body (all optional):
      {
        "title": "Updated title",
        "status": "done",
        "priority": "low",
        "assigneeId": "00000000-0000-0000-0000-000000000001",
        "dueDate": "2026-04-25"
      }
    • response: 200 with updated task
  • DELETE /tasks/:id

    • response: 204
    • authorization: project owner or task creator

Error Responses

  • Validation (400)
    { "error": "validation failed", "fields": { "email": "is required" } }
  • Unauthenticated (401)
    { "error": "unauthorized" }
  • Forbidden (403)
    { "error": "forbidden" }
  • Not found (404)
    { "error": "not found" }

7. What I'd Do With More Time

  • Add integration tests with Testcontainers for auth/task flow.
  • Introduce Redis-backed rate limiting for multi-instance deployments.
  • Add request tracing/correlation IDs and richer audit logging.
  • Add OpenAPI/Swagger docs and a Postman collection.
  • Implement role-based access controls and project membership model.