🧩 SOA – Service-Oriented Architecture Project
🏗️ Architecture Overview
This project implements a Service-Oriented Architecture (SOA) for an art gallery management system using Docker containerization and microservices architecture.
System Components
🌐 HTTPS (Port 443)
│
┌──────────────────────────▼──────────────────────────────┐
│ Apache Reverse Proxy │
│ (SSL Termination + OIDC Validation) │
│ │
│ /api/public/* ──────┐ ┌────── /api/private/* │
│ (No Auth) │ │ (OIDC Required) │
└───────────────────────┼──────┼──────────────────────────┘
│ │ |
│ │ (+ OIDC Headers) |
│ │ |
┌─────────────▼──┐ ┌─▼──────────────┐ |
│ │ │ │ |
│ Public API │ │ Private API │ |
│ (Laravel) │ │ (Flask) │ |
│ Port 5001 │ │ Port 5002 │ |
└─────────┬──────┘ └─┬──────────────┘ |
│ │ |
┌─────────▼──────────▼─────────┐ ┌───────▼──────┐
│ MySQL │ │ Keycloak │
│ (Application DB) │ │ + Postgres │
└──────────────────────────────┘ └──────────────┘
│
┌─────────────────▼─────────────────┐
│ Redis │
│ (Cache + Events) │
└───────────────────────────────────┘
Technology Stack
Component |
Technology |
Purpose |
Reverse Proxy |
Apache HTTP Server |
SSL termination, request routing |
Authentication |
Keycloak |
OIDC/OAuth2 identity provider |
Public API |
Laravel 12 (PHP) |
Public galleries and artworks API |
Private API |
Flask (Python) |
User management and private content |
Databases |
PostgreSQL + MySQL |
Data persistence |
Cache/Queue |
Redis |
Caching and event messaging |
Service Architecture
🔓 Public API Service (Laravel)
- Port: Internal 5001 (via Apache)
- Database: MySQL
- Purpose: Public access to galleries and artworks
- Features:
- RESTful API for public galleries
- Artist directory
- Public artwork browsing
- Pagination and filtering
🔒 Private API Service (Flask)
- Port: Internal 5002 (via Apache)
- Database: MySQL
- Authentication: OIDC via Apache mod_auth_openidc
- Purpose: Authenticated user operations
- Features:
- User profile management
- Gallery creation and management
- Artwork upload and editing
- Review system for galleries/artworks
- Invitation system for gallery members
🔐 Authentication Service (Keycloak)
- Port: 8080
- Database: PostgreSQL
- Purpose: Centralized identity and access management
- Features:
- OIDC/OAuth2 provider
- User registration and login
- Token-based authentication
- Single Sign-On (SSO)
Request Flow
All requests enter through Apache on port 443 (HTTPS) and are processed as follows:
- SSL Termination: Apache handles SSL/TLS encryption
- Request Routing: Based on URL path:
/api/public/*
→ Routes to Public API (Laravel on port 5001)
/api/private/*
→ Routes to Private API (Flask on port 5002)
- OIDC Authentication Check:
- Public API: No authentication required
- Private API: Apache mod_auth_openidc validates OIDC tokens with Keycloak
- Header Injection: Apache injects user info headers (OIDC_email, OIDC_user) for authenticated requests
- API Processing: Backend services handle business logic
- Data Persistence: MySQL stores application data
- Event Publishing: Redis handles inter-service communication
Security Model
- SSL/TLS: All external communication encrypted
- OIDC Authentication: Industry standard OAuth2/OIDC flow
- Token-based Authorization: JWT tokens for API access
- Network Isolation: Services communicate via internal network
- Database Security: Separate databases for auth and application data
🚀 Quick Start
-
Start the application stack:
docker compose up -d --build
-
Initialize Keycloak configuration:
./setup-keycloak.sh
-
Update your /etc/hosts
file:
127.0.0.1 api.local auth.local
🔐 Credentials
Keycloak Admin Panel
Private API User
- 👤 Username:
alexis
- 🔑 Password:
password
🗂️ Public API Endpoints Overview
All routes are prefixed with /api/public
.
Method |
Endpoint |
Description |
GET |
/artists |
List all public artists |
GET |
/galleries |
List all public galleries |
GET |
/galleries/{gallery}/artworks |
List artworks for a public gallery |
🗂️ Private API Endpoints Overview
All routes are prefixed with /api/private
and require a Bearer token.
👤 User
Method |
Endpoint |
Description |
GET |
/me |
Get current user's profile |
PUT |
/me |
Update current user's profile |
🖼️ Galleries
Method |
Endpoint |
Description |
GET |
/galleries |
List all accessible galleries |
GET |
/galleries/mine |
List galleries owned by the user |
POST |
/gallery |
Create a new gallery |
GET |
/gallery/{gallery_id} |
Get details of a specific gallery |
PUT |
/gallery/{gallery_id} |
Update a gallery (owner only) |
👥 Members
Method |
Endpoint |
Description |
GET |
/gallery/{gallery_id}/members |
List members of a gallery |
📩 Invitations
Method |
Endpoint |
Description |
POST |
/gallery/{gallery_id}/invite |
Invite user to a gallery |
PUT |
/invitations/{gallery_id}/respond |
Accept or reject invitation |
GET |
/invitations/received |
List received invitations |
🖼️ Artworks
Method |
Endpoint |
Description |
GET |
/gallery/{gallery_id}/artworks |
List artworks in a gallery |
POST |
/gallery/{gallery_id}/artwork |
Add artwork to gallery (owner only) |
GET |
/artwork/{artwork_id} |
Get details of an artwork |
PUT |
/artwork/{artwork_id} |
Update an artwork (creator only) |
GET |
/artworks/mine |
List artworks created by the user |
📝 Gallery Reviews
Method |
Endpoint |
Description |
GET |
/gallery/{gallery_id}/reviews |
List reviews for a gallery |
POST |
/gallery/{gallery_id}/review |
Submit a review for a gallery |
PUT |
/galleries/review/{review_id} |
Update a gallery review (author only) |
GET |
/galleries/reviews/given |
Reviews written by the user |
GET |
/galleries/reviews/received |
Reviews received on user’s galleries |
📝 Artwork Reviews
Method |
Endpoint |
Description |
GET |
/artwork/{artwork_id}/reviews |
List reviews for an artwork |
POST |
/artwork/{artwork_id}/review |
Submit a review for an artwork |
PUT |
/artworks/review/{review_id} |
Update an artwork review (author only) |
GET |
/artworks/reviews/given |
Reviews written by the user |
GET |
/artworks/reviews/received |
Reviews received on user’s artworks |
Public API:
Routes :
GET|HEAD api/artists
GET|HEAD api/galleries
GET|HEAD api/galleries/{gallery}/artworks