Wróć do projektów
Backend Development · REST API
2025 Akademia Tarnowska

eventHubAPI

Kompleksowy backend REST API do zarządzania eventami — Spring Boot 3.3, JWT, PostgreSQL, Swagger. System ról, zaproszeń, powiadomień i multimediów w jednym serwisie.

Java 21
Język
Spring Boot 3.3
Framework
PostgreSQL
Baza danych
JWT + Swagger
Auth & Docs

Backend
od zera do API

eventHubAPI to w pełni funkcjonalny serwis backendowy do zarządzania eventami, zbudowany w Spring Boot 3.3. Projekt był realizowany na Akademii Tarnowskiej jako aplikacja backendowa.

Architektura warstwowa — Controller → Service → Repository — z pełną dokumentacją Swagger UI, hierarchicznym systemem ról i bazą PostgreSQL z dobrze zaprojektowanym schematem relacyjnym.

🎪
Zarządzanie eventami
CRUD eventów z filtrami po nazwie i dacie, publiczne i prywatne eventy
🔐
JWT + role RBAC
Bearer token 24h, trzy role: ADMIN / ORGANIZER / USER z różnymi uprawnieniami
💌
System zaproszeń
Wysyłanie, akceptacja, odrzucanie i wycofywanie zaproszeń do eventów
🔔
Powiadomienia
Paginowane powiadomienia z statusami UNREAD / READ / ARCHIVED per użytkownik
📸
Upload multimediów
Galeria, logo i harmonogram eventu — pliki binarne w PostgreSQL (bytea)
📖
Swagger UI
Pełna dokumentacja OpenAPI 3.0 z autoryzacją Bearer JWT pod /swagger-ui.html

Stack technologiczny

Java 21
Najnowszy LTS — records, sealed classes, pattern matching. Cały backend w Javie.
🍃
Spring Boot 3.3
Web, Data JPA (Hibernate), Security, Validation, Actuator — pełny ekosystem Spring.
🐘
PostgreSQL
Relacyjna baza danych z Hibernate ORM. DDL strategy: validate — schemat nienaruszony.
🔑
JWT Security
JwtAuthenticationFilter, JwtTokenProvider — Bearer token 24h, Spring Security config.
📋
Swagger / OpenAPI
springdoc-openapi 2.5.0 — interaktywna dokumentacja API z możliwością testowania.
🏗️
Maven + Lombok
Maven build system, Lombok 1.18.32 eliminuje boilerplate — gettery, konstruktory, buildery.

Jak to działa

01
JWT Authentication Filter

Każde żądanie przechodzi przez JwtAuthenticationFilter. Token wyciągany z nagłówka Authorization: Bearer, walidowany i mapowany na SecurityContext.

// SecurityConfiguration
.requestMatchers("/api/auth/**")
  .permitAll()
.anyRequest()
  .authenticated()
// Filter: JwtAuthenticationFilter
//   → JwtTokenProvider.validate()
//   → SecurityContextHolder.set()
02
Role-Based Access Control

Trzy poziomy dostępu: USER, ORGANIZER, ADMIN. Każdy endpoint zabezpieczony przez @PreAuthorize lub konfigurację SecurityFilterChain.

// Tylko ORGANIZER i ADMIN
@PreAuthorize(
  "hasAnyRole('ORGANIZER','ADMIN')")
public EventDto createEvent(...) {}

// Tylko ADMIN
@PreAuthorize("hasRole('ADMIN')")
public void deleteAccount(...) {}
03
Composite Key — Participant

Encja Participant używa złożonego klucza głównego ParticipantId (userId + eventId) — jeden użytkownik może być uczestnikiem eventu tylko raz.

@Entity
@IdClass(ParticipantId.class)
public class Participant {
  @Id private Long userId;
  @Id private Long eventId;
  private ParticipantStatus status;
  private EventRole eventRole;
}
04
Media — bytea w PostgreSQL

Pliki multimedialne przechowywane bezpośrednio w bazie jako bytea. Trzy typy użycia: GALLERY, LOGO, SCHEDULE — enum MediaUsage.

@Entity
public class Media {
  @Lob
  private byte[] mediaFile;
  private MediaType mediaType;
  // IMAGE | DOCUMENT | VIDEO
  private MediaUsage usage;
  // GALLERY | LOGO | SCHEDULE
}
05
Hierarchia geograficzna

Lokalizacje zbudowane w pełnej hierarchii: Country → Region → City → PostalCode → Location → MapLocation z geolokacją jako osobna encja 1:1.

Location
  └─ PostalCode
       └─ City
            └─ Region
                 └─ Country
  └─ MapLocation (lat/lng)
  └─ street_name
  └─ street_number
06
Powiadomienia N:M

Tabela join account_notification łączy użytkowników z powiadomieniami ze statusem per para. Jeden komunikat może trafić do wielu odbiorców.

// account_notification (join table)
account_id      (FK → Account)
notification_id (FK → Notification)
status          (UNREAD|READ|ARCHIVED)

// Endpoint paginowany:
GET /api/notifications?page=0&size=20

Endpointy

🔐 Auth /api/auth
POST /login Logowanie — zwraca JWT token Public
POST /register Rejestracja nowego użytkownika Public
👤 Użytkownicy /api/account
GET /me Profil zalogowanego użytkownika User
PUT /me Update profilu User
POST /me/profile-image Upload zdjęcia profilowego User
POST /change-password Zmiana hasła User
🎪 Eventy /api/events
POST / Tworzenie eventu Organizer
GET /public Lista publicznych eventów (z filtrami) Public
GET /{id} Szczegóły eventu User
PUT /{id} Update eventu Organizer
DELETE /{id} Usunięcie eventu Organizer
GET /all Wszystkie eventy Admin
👥 Uczestnicy /api/events/{eventId}/participants
POST / Dołączenie do eventu User
GET / Lista uczestników User
GET /me Mój status uczestnictwa User
DELETE /me Opuszczenie eventu User
💌 Zaproszenia /api/invitations
POST / Wysłanie zaproszenia Organizer
GET /my Moje zaproszenia User
POST /{id}/accept Przyjęcie zaproszenia User
POST /{id}/decline Odrzucenie zaproszenia User
POST /{id}/revoke Wycofanie zaproszenia Organizer
🔔 Powiadomienia /api/notifications
GET / Pobieranie powiadomień (paginacja) User
PATCH /{id}/status Update statusu (READ / ARCHIVED) User
📸 Media /api/events/{id}/media
POST /gallery Upload zdjęcia do galerii User
POST /logo Upload logo eventu Organizer
POST /schedule Upload harmonogramu (PDF) Organizer
DELETE /api/media/{fileId} Usunięcie pliku Organizer
🛡️ Admin /api/admin
PATCH /accounts/{id}/status Zmiana statusu konta (ACTIVE/BANNED) Admin
PATCH /accounts/{id}/role Zmiana roli użytkownika Admin
DELETE /accounts/{id} Usunięcie konta Admin
DELETE /events/{id} Usunięcie dowolnego eventu Admin

Schemat encji

account
id PK
login
email
password
roles ADMIN | ORGANIZER | USER
status ACTIVE | INACTIVE | BANNED
created_at
1:1 → profile 1:N → event N:M → participant N:M → notification
event
id PK
name
description
start_date
end_date
is_public
max_participants
organizer_id FK → account
location_id FK → location
N:1 → account 1:1 → location 1:N → participant 1:N → media 1:N → invitation
participant
user_id PK, FK
event_id PK, FK
status JOINED | DECLINED | PENDING
event_role ATTENDEE | SPEAKER | ORGANIZER
joined_at
Composite PK N:1 → account N:1 → event
invitation
id PK
event_id FK → event
invited_user_id FK → account
status PENDING | ACCEPTED | DECLINED
sent_at
responded_at
N:1 → event N:1 → account
media
id PK
media_file bytea
media_type IMAGE | DOCUMENT | VIDEO
usage GALLERY | LOGO | SCHEDULE
event_id FK → event
uploader_id FK → account
uploaded_at
N:1 → event N:1 → account
location
id PK
street_name
street_number
apartment
postal_code_id FK → postal_code
1:1 → map_location N:1 → postal_code → city → region → country
notification
id PK
title
message
created_at
N:M → account (via account_notification)
account_notification join table
account_id PK, FK
notification_id PK, FK
status UNREAD | READ | ARCHIVED
N:1 → account N:1 → notification

Jak uruchomić

Wymagania
Java 21+ Maven 3.6+ PostgreSQL 12+ Git
1
Klonuj repozytorium
git clone https://github.com/DominikFa/eventHubAPI.git
cd eventHubAPI
2
Skonfiguruj bazę danych
# src/main/resources/application.properties
spring.datasource.url=jdbc:postgresql://localhost:5432/event_hub
spring.datasource.username=YOUR_USER
spring.datasource.password=YOUR_PASSWORD
3
Zbuduj i uruchom
./mvnw clean package
./mvnw spring-boot:run
4
Otwórz dokumentację Swagger
# Swagger UI:
http://localhost:8080/swagger-ui.html

# OpenAPI JSON:
http://localhost:8080/v3/api-docs

Autorzy projektu

AT
Andrii Torianyk
Backend · Security · Database · API Design
github.com/Andrii418
DF
Dominik Fa
Backend · Architecture · Spring Boot
github.com/DominikFa
Wszystkie projekty