Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

97 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Book Social Network

A Full-Stack Book Sharing & Social Networking Platform

Java Spring Boot Angular PostgreSQL Docker JWT License


Book Social Network (BSN) is a platform where book lovers can share, borrow, and discuss books within a community. Users can register their personal book collections, share them with others, and manage a complete borrow-return lifecycle with owner approval.

Getting Started | API Documentation | Architecture | Contributing


Table of Contents


About The Project

Book Social Network addresses a simple problem: sharing books should be easy. Instead of buying books that sit on shelves, this platform connects readers who want to share their collections.

How It Works

Register -> Verify via Email -> Login -> Share Your Books -> Others Borrow -> Return & Review
  1. A user registers and receives an activation email (via MailDev in development)
  2. After activation, they login and receive JWT tokens
  3. They can create book listings with details and cover images
  4. Other users can borrow available (shareable, non-archived) books
  5. The borrower returns the book, and the owner approves the return
  6. Borrowers can leave feedback and ratings on books they've read

Key Features

Authentication & Security

  • Secure registration with email-based account activation (6-digit OTP)
  • JWT-based authentication with Access Token (24h) and Refresh Token (7d)
  • Role-based access control (RBAC) with ADMIN and USER roles
  • Stateless session management — no server-side sessions
  • Automatic token refresh via HTTP interceptor on the frontend

Book Management (CRUD)

  • Create, read, update, and delete book listings
  • Upload book cover images (stored locally, up to 50MB)
  • Toggle shareable status (allow others to borrow)
  • Toggle archived status (hide from listings)
  • Ownership enforcement — only the owner can modify their books

Borrowing System

  • Full borrow-return lifecycle with owner approval
  • Prevents duplicate borrows and self-borrowing
  • Tracks borrow status: borrowed -> returned -> return approved
  • Separate views for borrowed books and returned books

Feedback & Ratings

  • Rate books on a 0-5 scale with comments
  • Own-feedback detection — users see their own feedback flagged
  • Paginated feedback listings per book

Admin Panel

  • View all registered users
  • Lock/Unlock user accounts
  • Enable/Disable user accounts
  • Role-based dashboard routing (ADMIN sees user management, USER sees books)

Architecture

High-Level System Overview

The system follows a 3-tier architecture with clear separation between presentation, business logic, and data access layers.

┌─────────────────────────────────────────────────────────────────────────┐
│                          PRESENTATION TIER                               │
│                                                                          │
│   ┌─────────────────────────────────────────────────────────────────┐   │
│   │                   Angular Frontend (:4200)                      │   │
│   │                                                                 │   │
│   │   ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────────┐ │   │
│   │   │  Login   │  │  Register│  │  Book    │  │  Admin Panel │ │   │
│   │   │  Page    │  │  Page    │  │  List    │  │  (USER Mgmt) │ │   │
│   │   └────┬─────┘  └────┬─────┘  └────┬─────┘  └──────┬───────┘ │   │
│   │        │              │              │                │          │   │
│   │   ┌────▼──────────────▼──────────────▼────────────────▼───────┐ │   │
│   │   │              HTTP Token Interceptor                       │ │   │
│   │   │         (Injects Bearer token to every request)           │ │   │
│   │   └──────────────────────────┬────────────────────────────────┘ │   │
│   └──────────────────────────────┼──────────────────────────────────┘   │
│                                  │                                      │
└──────────────────────────────────┼──────────────────────────────────────┘
                                   │  HTTP/REST (JSON)
                                   │  Authorization: Bearer <jwt>
┌──────────────────────────────────┼──────────────────────────────────────┐
│                          APPLICATION TIER                                │
│                                  │                                      │
│   ┌──────────────────────────────▼──────────────────────────────────┐   │
│   │              Spring Boot API (:8088/api/v1)                     │   │
│   │                                                                 │   │
│   │   ┌─────────────────────────────────────────────────────────┐   │   │
│   │   │                 SECURITY LAYER                          │   │   │
│   │   │                                                         │   │   │
│   │   │   ┌────────────┐  ┌──────────────┐  ┌───────────────┐  │   │   │
│   │   │   │ CorsFilter │─>│  JwtFilter   │─>│ Authentication│  │   │   │
│   │   │   │ (CORS)     │  │ (validate &  │  │ Provider      │  │   │   │
│   │   │   │            │  │  set auth)   │  │ (verify user) │  │   │   │
│   │   │   └────────────┘  └──────────────┘  └───────────────┘  │   │   │
│   │   └─────────────────────────────────────────────────────────┘   │   │
│   │                              │                                  │   │
│   │   ┌──────────────────────────▼──────────────────────────────┐   │   │
│   │   │               CONTROLLER LAYER                           │   │   │
│   │   │                                                          │   │   │
│   │   │   ┌───────────────┐  ┌──────────────┐  ┌─────────────┐  │   │   │
│   │   │   │ Authentication│  │     Book     │  │  Feedback   │  │   │   │
│   │   │   │  Controller   │  │  Controller  │  │  Controller │  │   │   │
│   │   │   │  /auth/*      │  │  /books/*    │  │  /feedbacks │  │   │   │
│   │   │   └───────┬───────┘  └──────┬───────┘  └──────┬──────┘  │   │   │
│   │   │           │                  │                  │          │   │   │
│   │   │   ┌───────┴──────────────────┴──────────────────┴──────┐  │   │   │
│   │   │   │             Validation (@Valid)                    │  │   │   │
│   │   │   │   Request DTO ──> Validate ──> Forward to Service  │  │   │   │
│   │   │   └────────────────────────┬───────────────────────────┘  │   │   │
│   │   └────────────────────────────┼──────────────────────────────┘   │   │
│   │                                │                                  │   │
│   │   ┌────────────────────────────▼──────────────────────────────┐   │   │
│   │   │                 SERVICE LAYER                              │   │   │
│   │   │               (Interface + Impl)                          │   │   │
│   │   │                                                           │   │   │
│   │   │   ┌──────────────┐  ┌──────────────┐  ┌──────────────┐   │   │   │
│   │   │   │  AuthService │  │  BookService │  │ EmailService │   │   │   │
│   │   │   │  Impl        │  │  Impl        │  │ Impl         │   │   │   │
│   │   │   │              │  │              │  │              │   │   │   │
│   │   │   │ • register   │  │ • CRUD       │  │ • sendEmail  │   │   │   │
│   │   │   │ • login      │  │ • borrow     │  │ • templates  │   │   │   │
│   │   │   │ • activate   │  │ • return     │  │              │   │   │   │
│   │   │   │ • refresh    │  │ • approve    │  │              │   │   │   │
│   │   │   └──────────────┘  └──────────────┘  └──────────────┘   │   │   │
│   │   │                                                           │   │   │
│   │   │   ┌──────────────┐  ┌──────────────┐  ┌──────────────┐   │   │   │
│   │   │   │UserService   │  │FeedbackSvc   │  │FileStorage   │   │   │   │
│   │   │   │ Impl         │  │ Impl         │  │ Impl         │   │   │   │
│   │   │   │              │  │              │  │              │   │   │   │
│   │   │   │ • list users │  │ • save       │  │ • save file  │   │   │   │
│   │   │   │ • lock/unlock│  │ • list       │  │ • read file  │   │   │   │
│   │   │   │ • profile    │  │              │  │              │   │   │   │
│   │   │   └──────────────┘  └──────────────┘  └──────────────┘   │   │   │
│   │   └──────────────────────────────────────────────────────────┘   │   │
│   │                              │                                   │   │
│   │   ┌──────────────────────────▼───────────────────────────────┐   │   │
│   │   │              REPOSITORY LAYER                             │   │   │
│   │   │           (Spring Data JPA + Hibernate)                   │   │   │
│   │   │                                                           │   │   │
│   │   │   ┌──────────┐ ┌──────────┐ ┌────────┐ ┌──────────────┐  │   │   │
│   │   │   │ BookRepo │ │ UserRepo │ │TokenRepo│ │FeedbackRepo │  │   │   │
│   │   │   └──────────┘ └──────────┘ └────────┘ └──────────────┘  │   │   │
│   │   │                                                           │   │   │
│   │   │   ┌──────────┐ ┌──────────┐                               │   │   │
│   │   │   │ RoleRepo │ │ HistoryRepo│                              │   │   │
│   │   │   └──────────┘ └──────────┘                               │   │   │
│   │   └──────────────────────────────────────────────────────────┘   │   │
│   └──────────────────────────────────────────────────────────────────┘   │
│                                                                          │
└──────────────────────────────────┬───────────────────────────────────────┘
                                   │
                      ┌────────────┼────────────┐
                      │            │             │
                      ▼            ▼             ▼
┌──────────────────────┐ ┌─────────────┐ ┌──────────────────┐
│   PostgreSQL (:5432) │ │  MailDev    │ │   Local File     │
│                      │ │             │ │   System         │
│  ┌────────────────┐  │ │ SMTP :1025  │ │                  │
│  │ book_social_   │  │ │ Web  :1080  │ │  book-network/   │
│  │ network        │  │ │             │ │  uploads/        │
│  │                │  │ │ Captures    │ │  users/{id}/     │
│  │ Tables:        │  │ │ all emails  │ │  {cover}.png     │
│  │ • _user        │  │ │ during dev  │ │                  │
│  │ • role         │  │ │             │ │                  │
│  │ • user_roles   │  │ └─────────────┘ └──────────────────┘
│  │ • book         │  │
│  │ • feedback     │  │
│  │ • token        │  │
│  │ • book_trans.. │  │
│  └────────────────┘  │
└──────────────────────┘

Request Lifecycle — Complete Flow

This diagram shows exactly what happens from the moment a user clicks a button to the final response.

  USER ACTION                    BACKEND PROCESSING
  ───────────                    ──────────────────

  ┌──────────┐
  │  User    │   Click "Borrow Book"
  │  Browser │─────────────────────────────────────────────────────────┐
  └──────────┘                                                        │
                                                                      ▼
                                                           ┌─────────────────┐
                                                           │  Angular HTTP   │
                                                           │  Interceptor    │
                                                           │  Adds:          │
                                                           │  Authorization: │
                                                           │  Bearer <jwt>   │
                                                           └────────┬────────┘
                                                                    │
                         ══════════════════════════════════════════════════════
                                        SPRING BOOT API
                         ══════════════════════════════════════════════════════
                                                                    │
                                                                    ▼
                                                           ┌─────────────────┐
                                                           │   CorsFilter    │
                                                           │   Validates     │
                                                           │   Origin header │
                                                           └────────┬────────┘
                                                                    │
                                                                    ▼
                                                           ┌─────────────────┐
                                                           │   JwtFilter     │
                                                           │                 │
                                                           │ 1. Extract JWT  │
                                                           │    from header  │
                                                           │ 2. Parse email  │
                                                           │ 3. Load User    │
                                                           │ 4. Check token  │
                                                           │    in DB        │
                                                           │ 5. Set Security │
                                                           │    Context      │
                                                           └────────┬────────┘
                                                                    │
                                                     ┌──────────────┴──────────────┐
                                                     │ Token valid?                 │
                                                     │                             │
                                               ┌─────▼─────┐                ┌──────▼──────┐
                                               │    YES     │                │     NO      │
                                               │ Continue   │                │  401 UNAUTH │
                                               └─────┬─────┘                └─────────────┘
                                                     │
                                                     ▼
                                            ┌─────────────────┐
                                            │ BookController  │
                                            │                 │
                                            │ @PreAuthorize   │
                                            │ hasAnyAuthority │
                                            │ (USER,ADMIN)    │
                                            └────────┬────────┘
                                                     │
                                                     ▼
                                            ┌─────────────────┐
                                            │  BookServiceImpl│
                                            │                 │
                                            │ 1. Get User     │
                                            │    from Auth    │
                                            │ 2. Find Book    │
                                            │    by ID        │
                                            │ 3. Check:       │
                                            │   • not archived│
                                            │   • shareable   │
                                            │   • not own book│
                                            │   • not borrowed│
                                            │ 4. Create       │
                                            │    Transaction  │
                                            └────────┬────────┘
                                                     │
                                                     ▼
                                            ┌─────────────────┐
                                            │ BookTransaction │
                                            │ HistoryRepository│
                                            │                 │
                                            │ INSERT INTO     │
                                            │ book_transaction│
                                            │ _history (...)  │
                                            └────────┬────────┘
                                                     │
                                                     ▼
                                            ┌─────────────────┐
                                            │  Return HTTP    │
                                            │  200 OK         │
                                            │  Body: {id: 42} │
                                            └────────┬────────┘
                                                     │
                         ══════════════════════════════════════════════════════
                                                     │
                                                     ▼
                                            ┌─────────────────┐
                                            │  Angular HTTP   │
                                            │  Interceptor    │
                                            │  Stores new JWT │
                                            │  if refreshed   │
                                            └────────┬────────┘
                                                     │
                                                     ▼
                                            ┌─────────────────┐
                                            │  UI Updates:    │
                                            │  "Book borrowed │
                                            │   successfully" │
                                            └─────────────────┘

Authentication & JWT Flow

This diagram shows the complete authentication lifecycle including registration, login, token refresh, and protected requests.

 REGISTRATION FLOW                     LOGIN FLOW
 ─────────────────                     ──────────

 POST /auth/register                   POST /auth/authenticate
        │                                     │
        ▼                                     ▼
 ┌─────────────┐                      ┌──────────────┐
 │ Create User │                      │ AuthManager  │
 │ (enabled=F) │                      │ .authenticate│
 └──────┬──────┘                      └──────┬───────┘
        │                                     │
        ▼                                     ▼
 ┌─────────────┐                      ┌──────────────┐
 │ Generate 6  │                      │ Validates    │
 │ digit OTP   │                      │ email+pass   │
 └──────┬──────┘                      └──────┬───────┘
        │                                     │
        ▼                                     ▼
 ┌─────────────┐                      ┌──────────────┐
 │ Save Token  │                      │ Revoke old   │
 │ in DB       │                      │ tokens       │
 └──────┬──────┘                      └──────┬───────┘
        │                                     │
        ▼                                     ▼
 ┌─────────────┐                      ┌──────────────┐
 │ Send Email  │                      │ Generate     │
 │ via Thymeleaf│                     │ JWT + Refresh│
 └──────┬──────┘                      └──────┬───────┘
        │                                     │
        ▼                                     ▼
 ┌─────────────┐                      ┌──────────────┐
 │ Return 202  │                      │ Save tokens  │
 │ Accepted    │                      │ in DB        │
 └─────────────┘                      └──────┬───────┘
                                             │
                                             ▼
                                      ┌──────────────┐
                                      │ Return 200   │
                                      │ {accessToken,│
                                      │ refreshToken,│
                                      │ roles}       │
                                      └──────────────┘

 TOKEN REFRESH FLOW                   PROTECTED REQUEST
 ─────────────────                   ─────────────────

 POST /auth/refresh-token            GET /books/owner
        │                                     │
        ▼                                     ▼
 ┌─────────────┐                      ┌──────────────┐
 │ Extract     │                      │ JwtFilter    │
 │ refresh JWT │                      │ Extract +    │
 │ from header │                      │ Validate JWT │
 └──────┬──────┘                      └──────┬───────┘
        │                                     │
        ▼                                     ▼
 ┌─────────────┐                      ┌──────────────┐
 │ Lookup in   │                      │ Check token  │
 │ token table │                      │ not expired  │
 │ (not expired│                      │ & not revoked│
 │ & revoked)  │                      └──────┬───────┘
 └──────┬──────┘                             │
        │                                    ▼
        ▼                             ┌──────────────┐
 ┌─────────────┐                      │ @PreAuthorize│
 │ Revoke all  │                      │ Check role   │
 │ old tokens  │                      │ (USER/ADMIN) │
 └──────┬──────┘                      └──────┬───────┘
        │                                    │
        ▼                                    ▼
 ┌─────────────┐                      ┌──────────────┐
 │ Generate new│                      │ Controller   │
 │ access +    │                      │ -> Service   │
 │ refresh JWT │                      │ -> Repository│
 └──────┬──────┘                      │ -> Database  │
        │                             └──────┬───────┘
        ▼                                    │
 ┌─────────────┐                             ▼
 │ Return new  │                      ┌──────────────┐
 │ tokens      │                      │ Return 200   │
 └─────────────┘                      │ + Response   │
                                      └──────────────┘

Layer Responsibilities

Each layer has a single responsibility and only communicates with the layer directly below it.

Layer Package Responsibility Knows About
Controller controller/ HTTP routing, request validation, response formatting Service interfaces
Service service/ + service/impl/ Business logic, transaction management, authorization rules Repository, other Services
Repository repository/ Database queries, CRUD operations, JPA specifications Entity classes
Entity entity/ Database table mappings, relationships, computed fields Only JPA annotations
DTO dto/request/ + dto/response/ Data transfer between layers, validation rules Nothing (pure data)
Security security/ JWT generation/parsing, authentication filter, user lookup Token repository, User entity
Common common/ Shared utilities, base classes, constants Nothing (pure utilities)

Key Design Decisions

Decision Rationale
Interface + Impl for Services Enables mocking in unit tests, decouples controller from implementation, allows swapping implementations
DTO separation from Entity Prevents exposing database internals, allows different shapes for API input/output
JWT in database (token table) Enables token revocation, prevents reuse of expired tokens, supports logout functionality
Stateless sessions No server-side session storage, enables horizontal scaling, each request is self-contained
Ownership enforcement in Service Business rules (who can edit what) live in service layer, not in controller or database
Layer-based package structure Standard Spring Boot convention, easy for new developers, clear separation of concerns

Tech Stack

Backend

Component Technology Version Purpose
Language Java 17+ Core runtime
Framework Spring Boot 3.3.1 Application framework
Security Spring Security 6.x Authentication & authorization
JWT jjwt 0.11.5 Token generation & validation
ORM Spring Data JPA / Hibernate 6.5.2 Database access
Database PostgreSQL 14+ Primary data store
Email Spring Mail + Thymeleaf - Activation email templates
Validation Jakarta Bean Validation - Request validation
API Docs springdoc-openapi 2.6.0 Swagger UI
Build Maven 3.9+ Dependency management
Code Gen Lombok - Boilerplate reduction

Frontend

Component Technology Version Purpose
Framework Angular 16.1.x SPA framework
CSS Bootstrap 5.3.3 UI components
Icons Font Awesome 6.6.0 Icon library
JWT @auth0/angular-jwt 5.2.0 Client-side JWT handling
OTP Input angular-code-input 2.0.0 Activation code input
API Gen ng-openapi-gen 0.51.0 OpenAPI client generation
Language TypeScript 5.1.3 Type-safe JavaScript
Build Angular CLI 16.1.4 Build tooling

Infrastructure

Component Technology Purpose
Containerization Docker Compose Service orchestration
Database PostgreSQL 14 Persistent data storage
Email Server MailDev Development email capture

Prerequisites

Before running this project, make sure you have the following installed:

Software Minimum Version Check Command Download
Java (JDK) 17+ java -version Oracle / Adoptium
Node.js 18+ node -v nodejs.org
npm 9+ npm -v Comes with Node.js
Docker 20.10+ docker -v docker.com
Docker Compose 2.0+ docker compose version Comes with Docker Desktop
Git 2.0+ git --version git-scm.com

Getting Started

1. Clone the Repository

git clone https://github.com/hendrowunga/SpringBoot-Book-Social-Networking.git
cd SpringBoot-Book-Social-Networking

2. Start Infrastructure (Docker)

docker compose up -d

This starts:

  • PostgreSQL on port 5432
  • MailDev Web UI on port 1080, SMTP on port 1025

Verify they're running:

docker compose ps

3. Configure Environment Variables

cp .env.example .env

Edit .env with your own values if needed. See Environment Variables for details.

4. Start the Backend

Option A: Using the run script (recommended)

chmod +x run.sh
./run.sh

Option B: Manual

export $(cat .env | grep -v '^#' | xargs)
cd book-network
./mvnw spring-boot:run

Option C: Using IntelliJ IDEA

  1. Import the book-network folder as a Maven project
  2. Set Environment Variables in Run Configuration (copy from .env)
  3. Run BookNetworkApiApplication.java

The API will start at http://localhost:8088/api/v1

5. Start the Frontend

cd book-network-frontend
npm install
ng serve

The frontend will start at http://localhost:4200

6. Verify Everything Works

Service URL Expected
Backend API http://localhost:8088/api/v1 Application starts
Swagger UI http://localhost:8088/api/v1/swagger-ui/index.html API docs visible
Frontend http://localhost:4200 Login page visible
MailDev http://localhost:1080 Email inbox visible
pgAdmin / DBeaver localhost:5432 Database accessible

Environment Variables

All configuration is managed through environment variables in the .env file. Never commit .env to version control.

Variable Default Value Description
DB_URL jdbc:postgresql://localhost:5432/book_social_network PostgreSQL JDBC connection URL
DB_USERNAME username PostgreSQL database username
DB_PASSWORD password PostgreSQL database password
JWT_SECRET_KEY 404E63... Secret key for signing JWT tokens (Base64 encoded)
JWT_EXPIRATION 86400000 Access token expiration in milliseconds (24 hours)
JWT_REFRESH_EXPIRATION 604800000 Refresh token expiration in milliseconds (7 days)
MAIL_HOST localhost SMTP server hostname
MAIL_PORT 1025 SMTP server port
MAIL_USERNAME endos SMTP authentication username
MAIL_PASSWORD endos SMTP authentication password
ACTIVATION_URL http://localhost:4200/activate-account Frontend activation URL sent in emails

Production Note: For production deployment, generate a new JWT_SECRET_KEY using:

openssl rand -base64 512

Default Accounts

These accounts are pre-configured for testing:

Email Password Role Status Purpose
john.owner@test.com password123 ADMIN + USER Active Admin panel + book management
jane.borrower@test.com password123 USER Active Borrow/return workflow
hendrowunga@test.com password123 USER Active General testing

Creating New Admin Users

There is no admin registration endpoint (by design). To make a user admin:

-- Connect to PostgreSQL
psql -U username -d book_social_network

-- Find the user ID
SELECT id, email FROM _user WHERE email = 'newuser@test.com';

-- Get ADMIN role ID
SELECT id FROM role WHERE name = 'ADMIN';

-- Assign ADMIN role
INSERT INTO user_roles (user_id, role_id) VALUES (<user_id>, <role_id>);

API Documentation

All endpoints are prefixed with /api/v1. Interactive documentation is available at:

Swagger UI: http://localhost:8088/api/v1/swagger-ui/index.html

Authentication

Method Endpoint Description Auth Required
POST /auth/register Register a new user (sends activation email) No
POST /auth/authenticate Login and receive JWT tokens No
GET /auth/activate-account?token={code} Activate account with 6-digit code No
POST /auth/refresh-token Get new access token using refresh token Refresh Token
Request/Response Examples

POST /auth/register

// Request
{
  "firstname": "John",
  "lastname": "Doe",
  "email": "john@example.com",
  "password": "securePassword123"
}

// Response: 202 Accepted (empty body)

POST /auth/authenticate

// Request
{
  "email": "john@example.com",
  "password": "securePassword123"
}

// Response: 200 OK
{
  "accessToken": "eyJhbGciOiJIUzM4NCJ9...",
  "refreshToken": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "roles": ["USER"]
}

POST /auth/refresh-token

# Header: Authorization: Bearer <refresh_token>

// Response: 200 OK
{
  "accessToken": "eyJhbGciOiJIUzM4NCJ9...",
  "refreshToken": "new-refresh-token-uuid",
  "roles": ["USER"]
}

Book Management

Method Endpoint Description Auth Required
POST /books Create a new book listing Yes
GET /books Get all shareable books (paginated) Yes
GET /books/{book-id} Get book details by ID Yes
GET /books/owner Get current user's books (paginated) Yes
GET /books/borrowed Get books borrowed by current user Yes
GET /books/returned Get books returned by current user Yes
PATCH /books/shareable/{book-id} Toggle shareable status Yes (Owner)
PATCH /books/archived/{book-id} Toggle archived status Yes (Owner)
POST /books/borrow/{book-id} Borrow a book Yes
PATCH /books/borrow/return/{book-id} Return a borrowed book Yes (Borrower)
PATCH /books/borrow/return/approve/{book-id} Approve book return Yes (Owner)
POST /books/cover/{book-id} Upload book cover image Yes (Owner)
Request/Response Examples

POST /books

// Request
{
  "title": "Effective Java",
  "authorName": "Joshua Bloch",
  "isbn": "978-0134685991",
  "synopsis": "A must-read for every Java programmer.",
  "shareable": true
}

// Response: 200 OK
42

GET /books?page=0&size=5

// Response: 200 OK
{
  "content": [
    {
      "id": 1,
      "title": "The Great Gatsby",
      "authorName": "F. Scott Fitzgerald",
      "isbn": "978-0743273565",
      "synopsis": "A story of the mysteriously wealthy Jay Gatsby...",
      "owner": "John Doe",
      "cover": "base64-encoded-image...",
      "rate": 4.5,
      "archived": false,
      "shareable": true
    }
  ],
  "number": 0,
  "size": 5,
  "totalElements": 12,
  "totalPages": 3,
  "first": true,
  "last": false
}

POST /books/cover/{book-id}

# Content-Type: multipart/form-data
# Body: file=<binary image data>

// Response: 202 Accepted

Feedback

Method Endpoint Description Auth Required
POST /feedbacks Submit feedback for a book Yes
GET /feedbacks/book/{book-id} Get all feedback for a book (paginated) Yes
Request/Response Examples

POST /feedbacks

// Request
{
  "note": 4.5,
  "comment": "Amazing book! Great story about the American dream.",
  "bookId": 1
}

// Response: 200 OK
1

GET /feedbacks/book/1?page=0&size=5

// Response: 200 OK
{
  "content": [
    {
      "note": 4.5,
      "comment": "Amazing book! Great story about the American dream.",
      "ownFeedback": true
    }
  ],
  "number": 0,
  "size": 5,
  "totalElements": 1,
  "totalPages": 1,
  "first": true,
  "last": true
}

User Management (Admin Only)

Method Endpoint Description Auth Required
GET /users Get all users (paginated) ADMIN
GET /users/{user-id} Get user details by ID ADMIN
PATCH /users/{user-id}/lock Toggle user lock status ADMIN
PATCH /users/{user-id}/enable Toggle user enabled status ADMIN
GET /users/profile Get own profile Any User

API Testing Workflow

  1. Register a new account via POST /auth/register
  2. Check MailDev at http://localhost:1080 for the activation email
  3. Activate via GET /auth/activate-account?token={6-digit-code}
  4. Login via POST /auth/authenticate to get JWT tokens
  5. Use the Access Token as Authorization: Bearer {accessToken} header
  6. Test protected endpoints via Swagger UI or your preferred HTTP client

Role & Permission System

Role Definitions

Role Description How to Assign
USER Default role for all registered users Automatically assigned on registration
ADMIN Platform administrator Manually assigned via database

Permission Matrix

Action USER ADMIN
Register Yes -
Login Yes Yes
Create books Yes (own) Yes (own)
Edit books Yes (own) Yes (own)
Delete/archive books Yes (own) Yes (own)
Toggle shareable Yes (own) Yes (own)
Upload book cover Yes (own) Yes (own)
Browse all books Yes Yes
Borrow books Yes Yes
Return books Yes Yes
Approve returns Yes (owner) Yes (owner)
Give feedback Yes Yes
View all users No Yes
Lock/Unlock users No Yes
Enable/Disable users No Yes

Ownership Enforcement

The system enforces strict ownership rules:

  • Users can only edit, archive, toggle shareable, and upload covers for books they own
  • Users can only approve returns for books they own
  • Users cannot borrow their own books
  • ADMIN cannot modify other users' books — admin manages users, not content

This design follows the principle: "Admin is a platform manager, not a content censor."


Project Structure

Layer-Based Architecture (Backend)

The backend follows a layer-based package structure with Interface + Impl pattern for the service layer, making the codebase clean, consistent, and easy to maintain.

book-network/src/main/java/com/endos/book/
│
├── BookNetworkApiApplication.java        # Entry point + role initialization
│
├── controller/                           # REST API Endpoints
│   ├── AuthenticationController.java     #   POST /auth/register, /auth/authenticate
│   ├── BookController.java               #   CRUD /books, borrow, return
│   ├── FeedbackController.java           #   CRUD /feedbacks
│   └── UserController.java               #   Admin user management
│
├── dto/                                  # Data Transfer Objects
│   ├── request/                          #   Incoming request models
│   │   ├── AuthenticationRequest.java
│   │   ├── RegistrationRequest.java
│   │   ├── BookRequest.java
│   │   └── FeedbackRequest.java
│   └── response/                         #   Outgoing response models
│       ├── AuthenticationResponse.java
│       ├── BookResponse.java
│       ├── BorrowedBookResponse.java
│       ├── FeedbackResponse.java
│       └── UserResponse.java
│
├── entity/                               # JPA Entity / Database Table Mappings
│   ├── BaseEntity.java                   #   Abstract base (id, createdDate, auditing)
│   ├── Book.java                         #   book table
│   ├── BookTransactionHistory.java       #   book_transaction_history table
│   ├── Feedback.java                     #   feedback table
│   ├── Role.java                         #   role table (USER, ADMIN)
│   ├── Token.java                        #   token table (JWT storage)
│   └── User.java                         #   _user table (implements UserDetails)
│
├── repository/                           # Spring Data JPA Repositories
│   ├── BookRepository.java               #   Book queries + JpaSpecificationExecutor
│   ├── BookTransactionHistoryRepository.java  # Borrow/return queries
│   ├── FeedbackRepository.java           #   Feedback queries
│   ├── RoleRepository.java               #   Role lookups
│   ├── TokenRepository.java              #   JWT token queries
│   └── UserRepository.java               #   User lookups
│
├── service/                              # Business Logic (Interface + Impl)
│   ├── AuthService.java                  #   Interface
│   ├── BookService.java                  #   Interface
│   ├── EmailService.java                 #   Interface
│   ├── FeedbackService.java              #   Interface
│   ├── FileStorageService.java           #   Interface
│   ├── UserService.java                  #   Interface
│   ├── BookMapper.java                   #   Book entity <-> DTO mapper
│   ├── FeedbackMapper.java               #   Feedback entity <-> DTO mapper
│   └── impl/                             #   Implementations
│       ├── AuthServiceImpl.java          #     Register, login, activate, refresh
│       ├── BookServiceImpl.java          #     Book CRUD, borrow/return logic
│       ├── EmailServiceImpl.java         #     Thymeleaf email sending
│       ├── FeedbackServiceImpl.java      #     Feedback CRUD
│       ├── FileStorageServiceImpl.java   #     Local file storage
│       └── UserServiceImpl.java          #     Admin user management
│
├── security/                             # JWT & Security
│   ├── SecurityConfig.java               #   CORS, filter chain, stateless sessions
│   ├── JwtFilter.java                    #   Token validation filter
│   ├── JwtService.java                   #   Token generation & parsing
│   └── UserDetailsServiceImpl.java       #   User authentication lookup
│
├── config/                               # Application Configuration
│   ├── BeansConfig.java                  #   PasswordEncoder, AuthenticationManager, CORS
│   ├── ApplicationAuditAware.java        #   JPA auditing (createdBy/modifiedBy)
│   └── OpenApiConfig.java                #   Swagger UI / OpenAPI 3 config
│
├── exception/                            # Error Handling
│   ├── GlobalExceptionHandler.java       #   @RestControllerAdvice
│   ├── BusinessErrorCodes.java           #   Custom error codes (300-306)
│   ├── ExceptionResponse.java            #   Error response DTO
│   └── OperationNotPermittedException.java  # Ownership violation exception
│
└── common/                               # Shared Utilities
    ├── PageResponse.java                 #   Generic paginated response wrapper
    ├── BookSpecification.java            #   JPA Specification for book queries
    ├── EmailTemplateName.java            #   Email template enum
    └── FileUtils.java                    #   File read utility

Package Dependency Flow

controller → service (interface) → service.impl (implementation)
                                      ↓
                                  repository → entity
                                      ↓
                                   common/dto

Frontend (Angular)

book-network-frontend/src/app/
├── app.module.ts
├── app-routing.module.ts
│
├── pages/                              # Public pages
│   ├── login/
│   ├── register/
│   └── activate-account/
│
├── modules/book/                       # Book module (lazy-loaded)
│   ├── book.module.ts
│   ├── book-routing.module.ts
│   │
│   ├── pages/
│   │   ├── main/
│   │   ├── book-list/
│   │   ├── book-details/
│   │   ├── my-books/
│   │   ├── manage-book/
│   │   ├── borrowed-book-list/
│   │   ├── return-books/
│   │   └── manage-users/               # Admin panel
│   │
│   └── components/
│       ├── menu/                       # Role-aware navbar
│       ├── book-card/
│       └── rating/
│
└── services/
    ├── token/token.service.ts          # JWT + role management
    ├── interceptor/http-token.interceptor.ts
    ├── guard/auth.guard.ts
    ├── models/                         # TypeScript interfaces
    ├── services/                       # API services
    │   ├── authentication.service.ts
    │   ├── book.service.ts
    │   ├── feedback.service.ts
    │   └── user.service.ts
    └── fn/                             # Generated API functions

Database Schema

Entity Relationship Diagram

┌──────────────┐       ┌──────────────────┐       ┌──────────────┐
│     role     │       │   user_roles     │       │    _user     │
├──────────────┤       ├──────────────────┤       ├──────────────┤
│ id (PK)      │◄──────│ role_id (FK)     │       │ id (PK)      │
│ name (UNIQUE)│       │ user_id (FK)     │──────►│ email (UNIQUE)│
│ created_date │       └──────────────────┘       │ firstname    │
│ last_mod_date│                                  │ lastname     │
└──────────────┘                                  │ password     │
                                                  │ enabled      │
                                                  │ account_locked│
                                                  │ created_date │
                                                  └──────┬───────┘
                                                         │
                        ┌────────────────────────────────┤
                        │                                │
              ┌─────────v──────────┐          ┌──────────v──────────┐
              │       book         │          │   book_transaction_  │
              ├────────────────────┤          │      history         │
              │ id (PK)            │◄─────────├─────────────────────┤
              │ title              │          │ id (PK)             │
              │ author_name        │          │ book_id (FK)        │
              │ isbn               │          │ user_id (FK)        │
              │ synopsis           │          │ returned            │
              │ owner_id (FK)      │──┐       │ return_approved     │
              │ book_cover         │  │       │ created_date        │
              │ archived           │  │       └─────────────────────┘
              │ shareable          │  │
              │ rate               │  │       ┌─────────────────────┐
              │ created_date       │  │       │     feedback        │
              └────────────────────┘  │       ├─────────────────────┤
                                      │       │ id (PK)             │
                                      └───────│ book_id (FK)        │
                                              │ user_id (FK)        │
                                              │ note (0-5)          │
                                              │ comment             │
                                              │ created_date        │
                                              └─────────────────────┘

Table Summary

Table Records Purpose
_user User accounts Stores all registered users
role USER, ADMIN Role definitions
user_roles M:N junction Maps users to their roles
token JWT tokens Stores access & refresh tokens
book Book listings All books created by users
book_transaction_history Borrow records Tracks borrow/return lifecycle
feedback Ratings & comments User feedback on books

Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'feat: add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Commit Convention

This project follows Conventional Commits:

Prefix Description
feat: New feature
fix: Bug fix
docs: Documentation changes
style: Code style changes (formatting, etc.)
refactor: Code refactoring
test: Adding or updating tests
chore: Build process or tooling changes

License

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


Built with Spring Boot + Angular + PostgreSQL

Book Social Network - Share knowledge, one book at a time.

Releases

Packages

Used by

Contributors

Languages