Skip to content

TonyS-dev/HexaTask

Repository files navigation

HexaTask

Domain-Driven Project & Task Management System


Live Demo

Live URL here:

https://hexatask.tonys-dev.com/

App Screenshot


Overview

HexaTask is a full-stack project and task management system built with Domain-Driven Design and Hexagonal Architecture. It features robust authentication, ownership-based authorization, audit logging, and comprehensive observability. Designed for clean code, scalability, and developer experience, HexaTask enables seamless management of projects and tasks with modern UI and API.

Architecture Flow

graph TD
  A[User] -->|Interacts| B[Angular Frontend]
  B -->|API Calls| C[Spring Boot Backend]
  C -->|DB Access| D[(PostgreSQL Database)]
  C -->|Metrics| E[Prometheus]
  E --> F[Grafana]
  B -->|Static Files| G[Nginx]
  G -->|Proxy| C
  C -->|Swagger| H[Swagger UI]
  subgraph DevOps
    I[Docker Compose]
    I --> B
    I --> C
    I --> D
    I --> E
    I --> F
    I --> G
  end
Loading

Tech Stack

Frontend

  • Angular 17 (Signals API, Material UI)
  • TypeScript 5.4
  • RxJS 7.8
  • Tailwind CSS 3.4
  • Nginx (for static serving & API proxy)

Backend

  • Java 17
  • Spring Boot 3.4.1
  • Spring Security (JWT dual token)
  • Hibernate Envers (audit logging)
  • Spring Data JPA
  • Flyway (DB migrations)
  • Micrometer (metrics)

Database & Infrastructure

  • PostgreSQL 15
  • Docker & Docker Compose
  • Prometheus (metrics)
  • Grafana (visualization)

Testing & Quality

  • JUnit 5, Mockito (backend)
  • Jasmine, Karma (frontend)
  • Swagger/OpenAPI (API docs)

DevOps & Deployment

  • Gradle (backend build)
  • Node.js & npm (frontend build)
  • Docker Compose (multi-service orchestration)

Project Structure

hexatask/
β”œβ”€β”€ backend/
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ main/
β”‚   β”‚   β”‚   β”œβ”€β”€ java/com/hexatask/hexatask/   # domain, application, infrastructure
β”‚   β”‚   β”‚   └── resources/                   # application.yml, db/migration
β”‚   β”œβ”€β”€ src/test/                            # unit & integration tests
β”‚   β”œβ”€β”€ Dockerfile
β”‚   └── build.gradle
β”œβ”€β”€ frontend/
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ app/                             # core, features, shared
β”‚   β”‚   └── main.ts
β”‚   β”œβ”€β”€ package.json
β”‚   β”œβ”€β”€ angular.json
β”‚   └── Dockerfile
β”œβ”€β”€ scripts/
β”‚   β”œβ”€β”€ setup.sh
β”‚   β”œβ”€β”€ run.sh
β”‚   └── dev/
β”‚       β”œβ”€β”€ start.sh
β”‚       β”œβ”€β”€ stop.sh
β”‚       └── logs.sh
β”œβ”€β”€ docker-compose.yml
β”œβ”€β”€ .env (example created by scripts/setup.sh)
└── README.md

Getting Started

Prerequisites

  • Java 17+
  • Node.js >= 16
  • npm (or yarn)
  • Docker & Docker Compose
  • PostgreSQL 15 (if running backend outside Docker)

Installation

  1. Clone the repository

    git clone https://github.com/TonyS-dev/hexatask.git
    cd hexatask
  2. Setup environment

    chmod +x scripts/setup.sh scripts/run.sh
    ./scripts/setup.sh
    # Edit .env with your values
    nano .env
  3. Run the application

    ./scripts/run.sh
    • Or use Docker Compose directly:
      docker compose up --build

Environment Variables

Create a .env file in the root directory with:

DB_NAME=hexatask
DB_USER=youruser
DB_PASSWORD=yourpassword
DB_PORT=5432
JWT_SECRET=your_jwt_secret
JWT_EXPIRATION=900
VITE_API_BASE_URL=http://localhost:8080/api

Features

  • Domain-Driven Design (Hexagonal Architecture)
  • JWT Dual Token Authentication (Access + Refresh)
  • Ownership-based Authorization
  • Soft Delete with Audit Trail
  • Comprehensive Unit Tests
  • Swagger/OpenAPI Documentation
  • Docker & Docker Compose Support
  • Paginated project listing with filtering
  • Real-time metrics (Prometheus/Grafana)
  • Responsive Angular UI

Usage

Example: Running locally

cd backend
./gradlew bootRun
# In another terminal
cd frontend
npm install
npm start

API Documentation


Testing

Backend:

cd backend
./gradlew test

Frontend:

cd frontend
npm test

Deployment

  • Production build (frontend):
    cd frontend
    npm run build
  • Build backend JAR:
    cd backend
    ./gradlew build
  • Deploy with Docker Compose:
    docker compose up --build

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Submit a pull request with clear description

License

MIT License (see LICENSE file or opensource.org/licenses/MIT)


Author / Contact

Antonio Santiago (TonyS-dev)


Let me know if you want to add screenshots, more API details, or further customization.

βœ… Prerequisites

  • Java 17+ (Gradle wrapper will download matching distribution)
  • Node.js >= 16 (for Angular frontend)
  • npm (or yarn) for package management
  • Docker & Docker Compose (for containerized setup)
  • PostgreSQL 15 (if running backend without Docker)

πŸš€ Quick Start (Recommended)

Linux/macOS

chmod +x scripts/setup.sh scripts/run.sh
./scripts/setup.sh  # First time only - sets up Docker and environment
./scripts/run.sh    # Starts all services

Windows (PowerShell)

Set-ExecutionPolicy RemoteSigned -Scope CurrentUser  # First time only
.\scripts\setup.ps1  # Sets up Docker and environment
.\scripts\run.ps1    # Starts all services

Services will start at:

See scripts/README.md for detailed documentation.

βš™οΈ Manual Installation & Run

A) Full-stack (recommended, Docker)

docker compose up --build

Access the application:

B) Run frontend + backend locally (no Docker)

Start backend:

cd backend
./gradlew bootRun

Start frontend (in another terminal):

cd frontend
npm install
npm start

Frontend will be available at http://localhost:4200

Test Credentials

User 1 (Owner of sample projects):
- Email: juan@mail.com
- Password: password123

User 2 (Different user):
- Email: anto@mail.com
- Password: password123

πŸ“¦ Scripts & Useful Commands

Backend (inside backend/):

./gradlew bootRun              # Run the Spring Boot app
./gradlew build                # Build jar
./gradlew test                 # Run unit tests
./gradlew clean build -x test  # Build without tests

Frontend (inside frontend/):

npm install                    # Install dependencies
npm start                      # Start Angular dev server
npm run build                  # Build production bundle
npm run lint                   # Run ESLint

Docker Compose (repo root):

docker compose up --build      # Start all services
docker compose down            # Stop all services
docker compose logs -f         # View logs

πŸ”‘ Authentication & Authorization

Dual Token Strategy

The backend exposes /api/auth/login and /api/auth/register endpoints with a secure dual-token approach:

  • Access Token (JWT, 15 minutes) β€” Used for API requests
  • Refresh Token (JWT, 30 minutes) β€” Persisted in DB, enables token rotation
  • On token refresh, old tokens are immediately deleted for enhanced security
  • Frontend stores both tokens in localStorage and sends access token in Authorization: Bearer header

Ownership-based Authorization

Every write operation validates that the authenticated user owns the resource:

// Example: Only project owner can activate
if (!project.getOwnerId().equals(currentUserId)) {
    throw new UnauthorizedException("403 Forbidden");
}

Applied to all critical operations:

  • βœ… GetProject β€” owner verification
  • βœ… ActivateProject β€” owner verification + business rules
  • βœ… CreateTask β€” project owner verification
  • βœ… UpdateTaskStatus β€” project owner verification
  • βœ… ListProjects β€” filtered by owner (no data exposure)

πŸ“š API Documentation (Swagger/OpenAPI)

Comprehensive API documentation using Swagger/OpenAPI 3.0.

Access Swagger UI:

πŸ”— http://localhost:8080/swagger-ui.html

API Groups:

  • Authentication API (/api/auth)

    • User registration
    • User login (returns dual tokens)
    • Token refresh
  • Projects API (/api/projects)

    • List user's projects (paginated & filtered)
    • Create new project
    • Get project details
    • Activate project
  • Tasks API (/api/projects/{projectId}/tasks)

    • Create task
    • Complete task
    • List tasks

Authentication in Swagger UI:

  1. Login via /api/auth/login
  2. Copy the JWT token from the response
  3. Click "Authorize" button at the top
  4. Enter: Bearer {your-token}
  5. Click "Authorize" and close

Alternative API Docs:

πŸ” Monitoring & Observability

Actuator Endpoints:

curl http://localhost:8080/actuator/health
curl http://localhost:8080/actuator/metrics
curl http://localhost:8080/actuator/prometheus

Prometheus & Grafana:

Metrics available:

  • HTTP server metrics: http.server.requests
  • JVM metrics: jvm.memory.*, jvm.gc.*, process.cpu.*
  • Data source metrics (HikariCP): hikaricp.*
  • Cache metrics: cache.*

In production, lock down actuator endpoints with proper authentication and only expose minimum required endpoints.

πŸ—οΈ Architecture

Hexagonal Design (Clean Architecture)

Strict separation of concerns across 4 layers:

domain/              β†’ Pure business logic (no Spring, no JPA)
  β”œβ”€ model/          β†’ Entities (User, Project, Task)
  β”œβ”€ ports/          β†’ Interfaces (UseCases IN, Dependencies OUT)
  └─ events/         β†’ Domain events (ProjectActivated, TaskCompleted)

application/         β†’ Business logic orchestration
  β”œβ”€ usecase/        β†’ Implementation of ports
  └─ dto/            β†’ Data Transfer Objects

infrastructure/      β†’ Framework & external integration
  β”œβ”€ web/            β†’ Controllers, REST endpoints
  β”œβ”€ adapters/       β†’ Repository implementations, Security, Audit
  β”œβ”€ entities/       β†’ JPA entities (separate from domain)
  β”œβ”€ mappers/        β†’ Domain ↔ Entity conversions
  └─ config/         β†’ Spring configuration

presentation/        β†’ Frontend (Angular)

Key Design Patterns

  • Ports & Adapters: Domain is independent of frameworks
  • Dependency Injection: All dependencies injected via constructors
  • Strategy Pattern: Configurable notification system
  • Mapper Pattern: Strict separation between Domain and JPA entities
  • Soft Delete: Logical deletion with deleted flag
  • Event Publishing: Domain events for decoupled cross-cutting concerns

Security Headers

  • JWT validated on every request via JwtAuthenticationFilter
  • Credentials stored securely with BCrypt password encoder
  • Refresh tokens persisted in DB for revocation capability

πŸ—„οΈ Database

Migrations

Flyway manages all schema changes automatically:

  • V1__create_tables.sql β€” Initial schema (User, Project, Task)
  • V2__create_audit_tables.sql β€” Audit logging tables
  • V3__add_task_status.sql β€” Add task status column
  • V5__insert_test_data.sql β€” Test credentials and sample data

Features:

  • Soft delete pattern (records marked as deleted, never removed)
  • Optimistic locking via version field
  • Foreign keys with CASCADE DELETE (logical)
  • Indexes on frequently queried columns (owner_id, created_at)

Seed Data

Test credentials and sample projects are inserted via Flyway migrations. Data is idempotent via ON CONFLICT clauses.

πŸ§ͺ Testing

Unit Tests (JUnit 5 + Mockito):

cd backend
./gradlew test

Test Coverage (5 critical tests):

  • βœ… ActivateProject_WithTasks_ShouldSucceed β€” Happy path
  • βœ… ActivateProject_WithoutTasks_ShouldFail β€” Business rule validation
  • βœ… ActivateProject_ByNonOwner_ShouldFail β€” Ownership validation
  • βœ… CompleteTask_AlreadyCompleted_ShouldFail β€” State validation
  • βœ… CompleteTask_TaskNotFound_ShouldFail β€” Resource not found

All mocks injected, no Spring context loaded (true unit tests).

πŸ› οΈ Technical Decisions

1. Ownership Validation (Security)

Why: Users should only access their own resources.

How: CurrentUserPort extracts authenticated user ID from JWT, then each use case validates:

UUID currentUserId = currentUserPort.getCurrentUserId();
if (!resource.getOwnerId().equals(currentUserId)) {
    throw new UnauthorizedException("403 Forbidden");
}

Result: 403 Forbidden if user tries to access/modify another user's resource.

2. Dual Token Strategy (Security)

Why: Access tokens are short-lived to minimize risk if stolen, refresh tokens enable persistent sessions.

How:

  • Access Token: 15 minutes (in-memory JWT)
  • Refresh Token: 30 minutes (persisted in DB)
  • On refresh: old token deleted, new pair generated (rotation)

Result: Better security than single long-lived token, better UX than forcing re-login every 15 min.

3. Hexagonal Architecture (Maintainability)

Why: Clean separation enables easy testing and refactoring.

How:

  • Domain layer has NO Spring dependencies
  • Application layer contains use cases
  • Infrastructure adapts to frameworks (Spring, JPA, REST)
  • Tests mock all output ports

Result: Business logic isolated from framework changes, highly testable.

4. Soft Delete Pattern (Data Integrity)

Why: Audit trail and compliance require keeping deleted data.

How: Entities have deleted: boolean flag, queries filter WHERE deleted = false automatically.

Result: No permanent data loss, full audit history maintained.

5. Mapper Pattern (Clean Architecture)

Why: Keep domain entities independent of JPA annotations.

How:

  • Domain entities (User, Project, Task) are POJOs
  • JPA entities (UserEntity, ProjectEntity, TaskEntity) have @Entity annotations
  • Mappers convert between layers

Result: Domain code has zero framework knowledge, easy to port to different ORM.

6. Event Publishing (Decoupling)

Why: Audit and notifications shouldn't be tightly coupled to business logic.

How:

  • Use cases publish domain events (ProjectActivatedEvent, TaskCompletedEvent)
  • Infrastructure listeners subscribe to events
  • Listeners are implementations of output ports

Result: Use cases focused on business logic, cross-cutting concerns handled by adapters.

πŸ“‚ Project Structure

hexatask/
β”œβ”€β”€ backend/
β”‚   β”œβ”€β”€ src/main/java/com/hexatask/hexatask/
β”‚   β”‚   β”œβ”€β”€ domain/              # Pure business logic (no Spring)
β”‚   β”‚   β”‚   β”œβ”€β”€ model/           # Domain entities
β”‚   β”‚   β”‚   β”œβ”€β”€ ports/           # Interfaces (in/out)
β”‚   β”‚   β”‚   └── events/          # Domain events
β”‚   β”‚   β”œβ”€β”€ application/         # Use cases & orchestration
β”‚   β”‚   β”œβ”€β”€ infrastructure/      # Adapters & frameworks
β”‚   β”‚   β”‚   β”œβ”€β”€ web/             # Controllers
β”‚   β”‚   β”‚   β”œβ”€β”€ adapters/        # Repository, Security, Audit
β”‚   β”‚   β”‚   β”œβ”€β”€ entities/        # JPA entities
β”‚   β”‚   β”‚   β”œβ”€β”€ mappers/         # Domain ↔ Entity mapping
β”‚   β”‚   β”‚   └── config/          # Spring config
β”‚   β”‚   └── HexataskApplication.java
β”‚   β”œβ”€β”€ src/test/java/           # Unit tests (JUnit 5 + Mockito)
β”‚   β”œβ”€β”€ src/main/resources/
β”‚   β”‚   β”œβ”€β”€ application.yml      # Configuration
β”‚   β”‚   └── db/migration/        # Flyway migrations
β”‚   β”œβ”€β”€ Dockerfile
β”‚   β”œβ”€β”€ build.gradle
β”‚   └── gradlew
β”œβ”€β”€ frontend/
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ app/
β”‚   β”‚   β”‚   β”œβ”€β”€ core/            # Services, guards, interceptors
β”‚   β”‚   β”‚   β”œβ”€β”€ features/        # Feature modules (auth, projects, tasks)
β”‚   β”‚   β”‚   └── shared/          # Shared components
β”‚   β”‚   └── main.ts
β”‚   β”œβ”€β”€ Dockerfile
β”‚   β”œβ”€β”€ angular.json
β”‚   β”œβ”€β”€ package.json
β”‚   └── tsconfig.json
β”œβ”€β”€ docker-compose.yml
β”œβ”€β”€ scripts/                     # Dev helper scripts
└── README.md                    # <- You are here

🧩 Frontend Notes

  • Axios is configured centrally with an interceptor to add Authorization: Bearer <token> to outgoing requests
  • Server-state is handled via RxJS observables and Angular's reactive patterns
  • Core services manage API calls, authentication, and route guards
  • Feature modules encapsulate domain-specific logic (auth, projects, tasks)
  • Angular Material provides UI components with TailwindCSS customization

βœ… Troubleshooting

Frontend not loading?

rm -rf node_modules dist .angular/cache
npm install
npm start

Backend compilation error?

./gradlew clean build -x test

Database migration failed?

# Ensure PostgreSQL is running
docker ps
# Check logs for migration errors
docker compose logs postgres

Swagger UI not loading?

πŸ“¦ Deployment

  • Frontend production build: cd frontend && npm run build
  • Backend containerized via backend/Dockerfile
  • Both deployable with Docker / Kubernetes
  • Use provided docker-compose.yml for orchestration

🀝 Contributing

Contributions are welcome. Suggested workflow:

  1. Fork the repo
  2. Create a feature branch
  3. Add tests where appropriate
  4. Open a PR describing the change

Please follow existing code style and run linting before opening pull requests.

πŸ“ License

This project is licensed under the MIT License. See the LICENSE file for details.

πŸ‘€ Author / Contact

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors