Skip to content

yourfavouritedeveloper/CloudNest

Repository files navigation

CloudNest

CloudNest is a cloud-native file storage and user management backend built with Spring Boot, designed to demonstrate enterprise-grade backend engineering. It features a complete authentication system backed by JWT tokens — including secure token issuance, expiration handling, refresh token rotation, and logout — protected by a custom Spring Security filter chain. Users can upload, retrieve, and delete documents stored in MinIO (AWS S3-compatible), with pre-signed URLs providing temporary, authenticated access to private files.

The system uses PostgreSQL as its primary database with Liquibase handling schema migrations, ensuring version-controlled, reproducible database states across environments. Infrastructure is fully Dockerized, enabling seamless local development and straightforward cloud deployment. Role-based access control separates public, user-level, and admin-level endpoints, with a global exception handler ensuring consistent, meaningful error responses throughout the API.


Tech Stack

Technology Purpose
Java 21 Language
Spring Boot 4.x Framework
Spring Security + JWT Authentication & Authorization
PostgreSQL Database
Liquibase Database migrations
MinIO (S3-compatible) File storage
Docker Containerization
Lombok Boilerplate reduction

Project Structure

src/
├── config/          # Security, JWT, S3, App configuration
├── controller/      # REST controllers
├── dao/             # JPA entities
├── dto/             # Request/Response DTOs
├── exception/       # Custom exceptions & global handler
├── repository/      # Spring Data JPA repositories
└── service/         # Business logic

Prerequisites

  • Java 21+
  • Docker & Docker Compose
  • PostgreSQL (or use Docker)

Setup & Running

1. Clone the repository

git clone https://github.com/your-username/cloudnest.git
cd cloudnest

2. Start MinIO with Docker

docker-compose up -d

This starts MinIO at:

  • API: http://localhost:9000
  • Dashboard: http://localhost:9001

Login to the dashboard with your S3_ACCESS_KEY and S3_SECRET_KEY to manage buckets. The bucket is auto-created on app startup.

3. Run the application

./gradlew bootRun

The API will be available at http://localhost:8080.


Docker Compose

services:
  postgresql:
    image: postgres:16
    container_name: CloudNest_db
    restart: always
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data

  minio:
    image: quay.io/minio/minio
    container_name: minio
    ports:
      - "9000:9000"
      - "9001:9001"
    environment:
      MINIO_ROOT_USER: ${S3_ACCESS_KEY}
      MINIO_ROOT_PASSWORD: ${S3_SECRET_KEY}
    volumes:
      - minio_data:/data
    command: server /data --console-address ":9001"

volumes:
  postgres_data:
  minio_data:

Authentication

CloudNest uses JWT Bearer Token authentication.

Flow

POST /api/public/users        → Register
PUT  /api/public/users/login  → Login → returns accessToken + refreshToken
PUT  /api/users/refresh-token → Refresh tokens (Authorization: Bearer <refreshToken>)
PUT  /api/users/logout        → Logout (Authorization: Bearer <refreshToken>)

Using the token

Add the Authorization header to all protected requests:

Authorization: Bearer <accessToken>

API Endpoints

Auth (Public)

Method Endpoint Description
POST /api/public/users Register a new user
PUT /api/public/users/login Login and get tokens

Users

Method Endpoint Description Auth
GET /api/users/{id} Get user by ID
PUT /api/users/{id} Update user
DELETE /api/users/{id} Delete user
PUT /api/users/logout Logout
PUT /api/users/refresh-token Refresh access token

Drivers (Document Upload)

Method Endpoint Description Auth
POST /api/drivers/upload/{userId} Upload a driver document
GET /api/drivers/user/{userId} Get all documents for a user
GET /api/drivers/{id} Get document by ID
GET /api/drivers/{id}/url Get file download URL
DELETE /api/drivers/{id} Delete document

Admin

Method Endpoint Description Auth
GET /api/admin/users Get all users ✅ ADMIN
GET /api/admin/drivers Get all driver documents ✅ ADMIN

File Upload Example

curl -X POST http://localhost:8080/api/drivers/upload/{userId} \
  -H "Authorization: Bearer <token>" \
  -F "file=@/path/to/document.pdf"

Response:

{
  "id": "uuid",
  "userId": "uuid",
  "fileName": "document.pdf",
  "fileType": null,
  "createdAt": "2026-03-29T00:00:00",
  "updatedAt": "2026-03-29T00:00:00"
}

To access the file, call GET /api/drivers/{id}/url and open the returned URL in your browser.


Database

CloudNest uses Liquibase for schema management. Migrations run automatically on startup.

Tables:

  • users — user accounts
  • refresh_tokens — active refresh tokens
  • drivers — driver document metadata

Roles

Role Access
USER Standard endpoints
ADMIN All endpoints including /api/admin/**

Default role on registration is USER.


Environment Notes

  • JWT tokens expire in 24 hours (access) and 7 days (refresh)
  • Files are stored in MinIO under the cloudnest-bucket bucket
  • MinIO bucket is set to public for direct file access via http://localhost:9000/cloudnest-bucket/<file-key>

About

Built a cloud-native file storage backend using Spring Boot, integrating object storage (AWS S3/MinIO) for scalable file management. Implemented JWT-based authentication, secure file access via pre-signed URLs, and Dockerized the application for cloud deployment.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages