readme updated
This commit is contained in:
parent
15e56fea50
commit
254479d475
106
README.md
106
README.md
@ -1,5 +1,111 @@
|
|||||||
# 🧩 SOA – Service-Oriented Architecture Project
|
# 🧩 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 | // NOT IMPLEMENTED YET
|
||||||
|
|
||||||
|
### 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:
|
||||||
|
|
||||||
|
1. **SSL Termination**: Apache handles SSL/TLS encryption
|
||||||
|
2. **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)
|
||||||
|
3. **OIDC Authentication Check**:
|
||||||
|
- **Public API**: No authentication required
|
||||||
|
- **Private API**: Apache mod_auth_openidc validates OIDC tokens with Keycloak
|
||||||
|
4. **Header Injection**: Apache injects user info headers (OIDC_email, OIDC_user) for authenticated requests
|
||||||
|
5. **API Processing**: Backend services handle business logic
|
||||||
|
6. **Data Persistence**: MySQL stores application data
|
||||||
|
7. **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
|
## 🚀 Quick Start
|
||||||
|
|
||||||
1. **Start the application stack:**
|
1. **Start the application stack:**
|
||||||
|
@ -50,6 +50,7 @@ Listen 443
|
|||||||
ServerName api.local
|
ServerName api.local
|
||||||
ErrorLog ${APACHE_LOG_DIR}/api_error.log
|
ErrorLog ${APACHE_LOG_DIR}/api_error.log
|
||||||
CustomLog ${APACHE_LOG_DIR}/api_access.log combined
|
CustomLog ${APACHE_LOG_DIR}/api_access.log combined
|
||||||
|
|
||||||
SSLEngine on
|
SSLEngine on
|
||||||
SSLCertificateFile /usr/local/apache2/conf/server.crt
|
SSLCertificateFile /usr/local/apache2/conf/server.crt
|
||||||
SSLCertificateKeyFile /usr/local/apache2/conf/server.key
|
SSLCertificateKeyFile /usr/local/apache2/conf/server.key
|
||||||
@ -67,18 +68,36 @@ Listen 443
|
|||||||
OIDCScope "openid email profile"
|
OIDCScope "openid email profile"
|
||||||
OIDCSessionInactivityTimeout 86400
|
OIDCSessionInactivityTimeout 86400
|
||||||
OIDCSSLValidateServer Off
|
OIDCSSLValidateServer Off
|
||||||
|
|
||||||
|
# Configure OAuth2 Bearer token validation
|
||||||
|
OIDCOAuth2IntrospectionEndpoint https://auth.local/realms/master/protocol/openid-connect/token/introspect
|
||||||
|
OIDCOAuth2IntrospectionEndpointAuth client_secret_basic
|
||||||
|
OIDCOAuth2IntrospectionClientID soa
|
||||||
|
OIDCOAuth2IntrospectionClientSecret mysecret
|
||||||
|
|
||||||
# Proxy public API (no auth)
|
# Proxy public API (no auth)
|
||||||
ProxyPass /api/public http://public_api:5001/
|
ProxyPass /api/public http://public_api:5001/
|
||||||
ProxyPassReverse /api/public http://public_api:5001/
|
ProxyPassReverse /api/public http://public_api:5001/
|
||||||
|
|
||||||
# Proxy private API (OIDC protected)
|
# Proxy private API (supports both OIDC and Bearer tokens)
|
||||||
ProxyPass /api/private http://private_api:5002/api/private
|
ProxyPass /api/private http://private_api:5002/api/private
|
||||||
ProxyPassReverse /api/private http://private_api:5002/api/private
|
ProxyPassReverse /api/private http://private_api:5002/api/private
|
||||||
|
|
||||||
<Location /api/private>
|
<Location /api/private>
|
||||||
AuthType openid-connect
|
# Accept both OIDC sessions and OAuth2 Bearer tokens
|
||||||
|
AuthType auth-openidc
|
||||||
Require valid-user
|
Require valid-user
|
||||||
|
|
||||||
|
# Allow both authentication methods
|
||||||
|
OIDCUnAuthAction auth
|
||||||
|
OIDCUnAutzAction 401
|
||||||
|
|
||||||
|
# Pass user info as headers for both auth types
|
||||||
RequestHeader set X-User-Email "%{HTTP_OIDC_EMAIL}i"
|
RequestHeader set X-User-Email "%{HTTP_OIDC_EMAIL}i"
|
||||||
RequestHeader set X-User-Name "%{HTTP_OIDC_PREFERRED_USERNAME}i"
|
RequestHeader set X-User-Name "%{HTTP_OIDC_PREFERRED_USERNAME}i"
|
||||||
|
|
||||||
|
# Also pass OAuth2 token info
|
||||||
|
RequestHeader set X-OAuth2-Email "%{HTTP_OAUTH2_EMAIL}i"
|
||||||
|
RequestHeader set X-OAuth2-Username "%{HTTP_OAUTH2_PREFERRED_USERNAME}i"
|
||||||
</Location>
|
</Location>
|
||||||
</VirtualHost>
|
</VirtualHost>
|
@ -1,4 +1,6 @@
|
|||||||
vars {
|
vars {
|
||||||
gallery_id: 6
|
gallery_id: 6
|
||||||
URL: http://localhost:8000
|
URL: http://localhost:8000
|
||||||
|
baseUrl: http://api.local/api/private
|
||||||
|
authUrl: http://auth.local:8080
|
||||||
}
|
}
|
||||||
|
14
bruno/SOA/private/artwork-reviews/artwork-reviews.bru
Normal file
14
bruno/SOA/private/artwork-reviews/artwork-reviews.bru
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
meta {
|
||||||
|
name: Get Artwork Reviews
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/artwork/1/reviews
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
23
bruno/SOA/private/artwork-reviews/create-artwork-review.bru
Normal file
23
bruno/SOA/private/artwork-reviews/create-artwork-review.bru
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
meta {
|
||||||
|
name: Create Artwork Review
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
url: {{baseUrl}}/artwork/1/review
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
Content-Type: application/json
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"grade": 5,
|
||||||
|
"description": "Absolutely stunning artwork! The colors and technique are magnificent.",
|
||||||
|
"parent_ar_id": null
|
||||||
|
}
|
||||||
|
}
|
14
bruno/SOA/private/artwork-reviews/given-artwork-reviews.bru
Normal file
14
bruno/SOA/private/artwork-reviews/given-artwork-reviews.bru
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
meta {
|
||||||
|
name: Get Given Artwork Reviews
|
||||||
|
type: http
|
||||||
|
seq: 4
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/artworks/reviews/given
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
meta {
|
||||||
|
name: Get Received Artwork Reviews
|
||||||
|
type: http
|
||||||
|
seq: 5
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/artworks/reviews/received
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
22
bruno/SOA/private/artwork-reviews/update-artwork-review.bru
Normal file
22
bruno/SOA/private/artwork-reviews/update-artwork-review.bru
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
meta {
|
||||||
|
name: Update Artwork Review
|
||||||
|
type: http
|
||||||
|
seq: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
put {
|
||||||
|
url: {{baseUrl}}/artworks/review/1
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
Content-Type: application/json
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"grade": 4,
|
||||||
|
"description": "Updated: Very beautiful artwork! Great technique and composition."
|
||||||
|
}
|
||||||
|
}
|
29
bruno/SOA/private/artworks/create-artwork.bru
Normal file
29
bruno/SOA/private/artworks/create-artwork.bru
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
meta {
|
||||||
|
name: Create Artwork
|
||||||
|
type: http
|
||||||
|
seq: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
url: {{baseUrl}}/gallery/1/artwork
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
Content-Type: application/json
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"title": "Sunset Over Mountains",
|
||||||
|
"description": "A beautiful landscape painting capturing the golden hour",
|
||||||
|
"image_url": "https://example.com/artwork1.jpg",
|
||||||
|
"medium": "Oil on Canvas",
|
||||||
|
"dimensions": "24x36 inches",
|
||||||
|
"creation_year": 2024,
|
||||||
|
"price": 1500.00,
|
||||||
|
"is_visible": true,
|
||||||
|
"is_for_sale": true
|
||||||
|
}
|
||||||
|
}
|
14
bruno/SOA/private/artworks/gallery-artworks.bru
Normal file
14
bruno/SOA/private/artworks/gallery-artworks.bru
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
meta {
|
||||||
|
name: Get Gallery Artworks
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/gallery/1/artworks
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
14
bruno/SOA/private/artworks/get-artwork.bru
Normal file
14
bruno/SOA/private/artworks/get-artwork.bru
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
meta {
|
||||||
|
name: Get Artwork Details
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/artwork/1
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
14
bruno/SOA/private/artworks/my-artworks.bru
Normal file
14
bruno/SOA/private/artworks/my-artworks.bru
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
meta {
|
||||||
|
name: Get My Artworks
|
||||||
|
type: http
|
||||||
|
seq: 5
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/artworks/mine
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
24
bruno/SOA/private/artworks/update-artwork.bru
Normal file
24
bruno/SOA/private/artworks/update-artwork.bru
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
meta {
|
||||||
|
name: Update Artwork
|
||||||
|
type: http
|
||||||
|
seq: 4
|
||||||
|
}
|
||||||
|
|
||||||
|
put {
|
||||||
|
url: {{baseUrl}}/artwork/1
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
Content-Type: application/json
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"title": "Updated Sunset Over Mountains",
|
||||||
|
"description": "An updated beautiful landscape painting",
|
||||||
|
"price": 1800.00,
|
||||||
|
"is_for_sale": false
|
||||||
|
}
|
||||||
|
}
|
14
bruno/SOA/private/auth/debug-headers.bru
Normal file
14
bruno/SOA/private/auth/debug-headers.bru
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
meta {
|
||||||
|
name: Debug Headers
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/debug-headers
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
13
bruno/SOA/private/auth/redirect.bru
Normal file
13
bruno/SOA/private/auth/redirect.bru
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
meta {
|
||||||
|
name: OIDC Redirect
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/redirect
|
||||||
|
}
|
||||||
|
|
||||||
|
params:query {
|
||||||
|
code: authorization_code_here
|
||||||
|
}
|
17
bruno/SOA/private/environments/Token User.bru
Normal file
17
bruno/SOA/private/environments/Token User.bru
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
meta {
|
||||||
|
name: Token User
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
url: {{authUrl}}/realms/master/protocol/openid-connect/token
|
||||||
|
body: formUrlEncoded
|
||||||
|
auth: inherit
|
||||||
|
}
|
||||||
|
|
||||||
|
body:form-urlencoded {
|
||||||
|
grant_type: client_credentials
|
||||||
|
client_id: soa
|
||||||
|
client_secret: mysecret
|
||||||
|
}
|
11
bruno/SOA/private/environments/Token.bru
Normal file
11
bruno/SOA/private/environments/Token.bru
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
meta {
|
||||||
|
name: Token
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: /realms/master/protocol/openid-connect/token
|
||||||
|
body: none
|
||||||
|
auth: inherit
|
||||||
|
}
|
5
bruno/SOA/private/environments/local.bru
Normal file
5
bruno/SOA/private/environments/local.bru
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
vars {
|
||||||
|
baseUrl: https://api.local/api/private
|
||||||
|
email: alexis@example.com
|
||||||
|
username: alexis
|
||||||
|
}
|
24
bruno/SOA/private/galleries/create-gallery.bru
Normal file
24
bruno/SOA/private/galleries/create-gallery.bru
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
meta {
|
||||||
|
name: Create Gallery
|
||||||
|
type: http
|
||||||
|
seq: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
url: {{baseUrl}}/gallery
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
Content-Type: application/json
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"title": "Modern Art Collection",
|
||||||
|
"description": "A curated collection of contemporary artworks",
|
||||||
|
"is_public": true,
|
||||||
|
"publication_date": "2025-06-28T10:00:00Z"
|
||||||
|
}
|
||||||
|
}
|
14
bruno/SOA/private/galleries/gallery-members.bru
Normal file
14
bruno/SOA/private/galleries/gallery-members.bru
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
meta {
|
||||||
|
name: Get Gallery Members
|
||||||
|
type: http
|
||||||
|
seq: 6
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/gallery/1/members
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
14
bruno/SOA/private/galleries/get-gallery.bru
Normal file
14
bruno/SOA/private/galleries/get-gallery.bru
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
meta {
|
||||||
|
name: Get Gallery Details
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/gallery/1
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
14
bruno/SOA/private/galleries/list-galleries.bru
Normal file
14
bruno/SOA/private/galleries/list-galleries.bru
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
meta {
|
||||||
|
name: List All Galleries
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/galleries
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
14
bruno/SOA/private/galleries/my-galleries.bru
Normal file
14
bruno/SOA/private/galleries/my-galleries.bru
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
meta {
|
||||||
|
name: Get My Galleries
|
||||||
|
type: http
|
||||||
|
seq: 5
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/galleries/mine
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
23
bruno/SOA/private/galleries/update-gallery.bru
Normal file
23
bruno/SOA/private/galleries/update-gallery.bru
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
meta {
|
||||||
|
name: Update Gallery
|
||||||
|
type: http
|
||||||
|
seq: 4
|
||||||
|
}
|
||||||
|
|
||||||
|
put {
|
||||||
|
url: {{baseUrl}}/gallery/1
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
Content-Type: application/json
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"title": "Updated Modern Art Collection",
|
||||||
|
"description": "An updated curated collection of contemporary artworks",
|
||||||
|
"is_public": false
|
||||||
|
}
|
||||||
|
}
|
23
bruno/SOA/private/gallery-reviews/create-gallery-review.bru
Normal file
23
bruno/SOA/private/gallery-reviews/create-gallery-review.bru
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
meta {
|
||||||
|
name: Create Gallery Review
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
url: {{baseUrl}}/gallery/1/review
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
Content-Type: application/json
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"grade": 5,
|
||||||
|
"description": "Excellent gallery with amazing artwork collection!",
|
||||||
|
"parent_gr_id": null
|
||||||
|
}
|
||||||
|
}
|
14
bruno/SOA/private/gallery-reviews/gallery-reviews.bru
Normal file
14
bruno/SOA/private/gallery-reviews/gallery-reviews.bru
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
meta {
|
||||||
|
name: Get Gallery Reviews
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/gallery/1/reviews
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
14
bruno/SOA/private/gallery-reviews/given-gallery-reviews.bru
Normal file
14
bruno/SOA/private/gallery-reviews/given-gallery-reviews.bru
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
meta {
|
||||||
|
name: Get Given Gallery Reviews
|
||||||
|
type: http
|
||||||
|
seq: 4
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/galleries/reviews/given
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
meta {
|
||||||
|
name: Get Received Gallery Reviews
|
||||||
|
type: http
|
||||||
|
seq: 5
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/galleries/reviews/received
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
22
bruno/SOA/private/gallery-reviews/update-gallery-review.bru
Normal file
22
bruno/SOA/private/gallery-reviews/update-gallery-review.bru
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
meta {
|
||||||
|
name: Update Gallery Review
|
||||||
|
type: http
|
||||||
|
seq: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
put {
|
||||||
|
url: {{baseUrl}}/galleries/review/1
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
Content-Type: application/json
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"grade": 4,
|
||||||
|
"description": "Updated: Very good gallery with great artwork collection!"
|
||||||
|
}
|
||||||
|
}
|
22
bruno/SOA/private/invitations/invite-user.bru
Normal file
22
bruno/SOA/private/invitations/invite-user.bru
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
meta {
|
||||||
|
name: Invite User to Gallery
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
url: {{baseUrl}}/gallery/1/invite
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
Content-Type: application/json
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"user_id": 2,
|
||||||
|
"role": "viewer"
|
||||||
|
}
|
||||||
|
}
|
14
bruno/SOA/private/invitations/received-invitations.bru
Normal file
14
bruno/SOA/private/invitations/received-invitations.bru
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
meta {
|
||||||
|
name: Get Received Invitations
|
||||||
|
type: http
|
||||||
|
seq: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/invitations/received
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
21
bruno/SOA/private/invitations/respond-invitation.bru
Normal file
21
bruno/SOA/private/invitations/respond-invitation.bru
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
meta {
|
||||||
|
name: Respond to Invitation
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
put {
|
||||||
|
url: {{baseUrl}}/invitations/1/respond
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
Content-Type: application/json
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"status": "accepted"
|
||||||
|
}
|
||||||
|
}
|
14
bruno/SOA/private/user/get-me.bru
Normal file
14
bruno/SOA/private/user/get-me.bru
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
meta {
|
||||||
|
name: Get My Profile
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/me
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
25
bruno/SOA/private/user/update-me.bru
Normal file
25
bruno/SOA/private/user/update-me.bru
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
meta {
|
||||||
|
name: Update My Profile
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
put {
|
||||||
|
url: {{baseUrl}}/me
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
Content-Type: application/json
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"alias": "Alexis Updated",
|
||||||
|
"first_name": "Alexis",
|
||||||
|
"last_name": "Doe",
|
||||||
|
"bio": "Art enthusiast and gallery curator",
|
||||||
|
"profile_picture_url": "https://example.com/avatar.jpg"
|
||||||
|
}
|
||||||
|
}
|
765
bruno/bruno.sh
Executable file
765
bruno/bruno.sh
Executable file
@ -0,0 +1,765 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Bruno API Collection Generator for Private API
|
||||||
|
# Creates a complete Bruno collection structure for testing the private API endpoints
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
COLLECTION_NAME="private"
|
||||||
|
BASE_URL="https://api.local/api/private"
|
||||||
|
DEFAULT_EMAIL="alexis@example.com"
|
||||||
|
DEFAULT_USERNAME="alexis"
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
echo_info() {
|
||||||
|
echo -e "${BLUE}ℹ️ $1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
echo_success() {
|
||||||
|
echo -e "${GREEN}✅ $1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
echo_warning() {
|
||||||
|
echo -e "${YELLOW}⚠️ $1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
echo_error() {
|
||||||
|
echo -e "${RED}❌ $1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to create directory structure
|
||||||
|
create_directories() {
|
||||||
|
local base_dir="$1"
|
||||||
|
|
||||||
|
echo_info "Creating directory structure..."
|
||||||
|
|
||||||
|
mkdir -p "${base_dir}"/{environments,auth,user,invitations,galleries,artworks,gallery-reviews,artwork-reviews}
|
||||||
|
|
||||||
|
echo_success "Directory structure created"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to create a file with content
|
||||||
|
create_file() {
|
||||||
|
local filepath="$1"
|
||||||
|
local content="$2"
|
||||||
|
|
||||||
|
echo "$content" > "$filepath"
|
||||||
|
echo_success "Created: $filepath"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Generate collection files
|
||||||
|
generate_files() {
|
||||||
|
local base_dir="$1"
|
||||||
|
|
||||||
|
echo_info "Generating Bruno collection files..."
|
||||||
|
|
||||||
|
# Main collection file
|
||||||
|
cat > "${base_dir}/bruno.json" << EOF
|
||||||
|
{
|
||||||
|
"version": "1",
|
||||||
|
"name": "Private API",
|
||||||
|
"type": "collection"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/bruno.json"
|
||||||
|
|
||||||
|
# Environment file
|
||||||
|
cat > "${base_dir}/environments/local.bru" << EOF
|
||||||
|
vars {
|
||||||
|
baseUrl: ${BASE_URL}
|
||||||
|
email: ${DEFAULT_EMAIL}
|
||||||
|
username: ${DEFAULT_USERNAME}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/environments/local.bru"
|
||||||
|
|
||||||
|
# Auth files
|
||||||
|
cat > "${base_dir}/auth/debug-headers.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Debug Headers
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/debug-headers
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/auth/debug-headers.bru"
|
||||||
|
|
||||||
|
cat > "${base_dir}/auth/redirect.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: OIDC Redirect
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/redirect
|
||||||
|
}
|
||||||
|
|
||||||
|
params:query {
|
||||||
|
code: authorization_code_here
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/auth/redirect.bru"
|
||||||
|
|
||||||
|
# User files
|
||||||
|
cat > "${base_dir}/user/get-me.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Get My Profile
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/me
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/user/get-me.bru"
|
||||||
|
|
||||||
|
cat > "${base_dir}/user/update-me.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Update My Profile
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
put {
|
||||||
|
url: {{baseUrl}}/me
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
Content-Type: application/json
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"alias": "Alexis Updated",
|
||||||
|
"first_name": "Alexis",
|
||||||
|
"last_name": "Doe",
|
||||||
|
"bio": "Art enthusiast and gallery curator",
|
||||||
|
"profile_picture_url": "https://example.com/avatar.jpg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/user/update-me.bru"
|
||||||
|
|
||||||
|
# Invitation files
|
||||||
|
cat > "${base_dir}/invitations/invite-user.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Invite User to Gallery
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
url: {{baseUrl}}/gallery/1/invite
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
Content-Type: application/json
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"user_id": 2,
|
||||||
|
"role": "viewer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/invitations/invite-user.bru"
|
||||||
|
|
||||||
|
cat > "${base_dir}/invitations/respond-invitation.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Respond to Invitation
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
put {
|
||||||
|
url: {{baseUrl}}/invitations/1/respond
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
Content-Type: application/json
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"status": "accepted"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/invitations/respond-invitation.bru"
|
||||||
|
|
||||||
|
cat > "${base_dir}/invitations/received-invitations.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Get Received Invitations
|
||||||
|
type: http
|
||||||
|
seq: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/invitations/received
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/invitations/received-invitations.bru"
|
||||||
|
|
||||||
|
# Gallery files
|
||||||
|
cat > "${base_dir}/galleries/list-galleries.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: List All Galleries
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/galleries
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/galleries/list-galleries.bru"
|
||||||
|
|
||||||
|
cat > "${base_dir}/galleries/get-gallery.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Get Gallery Details
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/gallery/1
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/galleries/get-gallery.bru"
|
||||||
|
|
||||||
|
cat > "${base_dir}/galleries/create-gallery.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Create Gallery
|
||||||
|
type: http
|
||||||
|
seq: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
url: {{baseUrl}}/gallery
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
Content-Type: application/json
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"title": "Modern Art Collection",
|
||||||
|
"description": "A curated collection of contemporary artworks",
|
||||||
|
"is_public": true,
|
||||||
|
"publication_date": "2025-06-28T10:00:00Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/galleries/create-gallery.bru"
|
||||||
|
|
||||||
|
cat > "${base_dir}/galleries/update-gallery.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Update Gallery
|
||||||
|
type: http
|
||||||
|
seq: 4
|
||||||
|
}
|
||||||
|
|
||||||
|
put {
|
||||||
|
url: {{baseUrl}}/gallery/1
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
Content-Type: application/json
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"title": "Updated Modern Art Collection",
|
||||||
|
"description": "An updated curated collection of contemporary artworks",
|
||||||
|
"is_public": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/galleries/update-gallery.bru"
|
||||||
|
|
||||||
|
cat > "${base_dir}/galleries/my-galleries.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Get My Galleries
|
||||||
|
type: http
|
||||||
|
seq: 5
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/galleries/mine
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/galleries/my-galleries.bru"
|
||||||
|
|
||||||
|
cat > "${base_dir}/galleries/gallery-members.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Get Gallery Members
|
||||||
|
type: http
|
||||||
|
seq: 6
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/gallery/1/members
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/galleries/gallery-members.bru"
|
||||||
|
|
||||||
|
# Artwork files
|
||||||
|
cat > "${base_dir}/artworks/gallery-artworks.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Get Gallery Artworks
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/gallery/1/artworks
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/artworks/gallery-artworks.bru"
|
||||||
|
|
||||||
|
cat > "${base_dir}/artworks/get-artwork.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Get Artwork Details
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/artwork/1
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/artworks/get-artwork.bru"
|
||||||
|
|
||||||
|
cat > "${base_dir}/artworks/create-artwork.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Create Artwork
|
||||||
|
type: http
|
||||||
|
seq: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
url: {{baseUrl}}/gallery/1/artwork
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
Content-Type: application/json
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"title": "Sunset Over Mountains",
|
||||||
|
"description": "A beautiful landscape painting capturing the golden hour",
|
||||||
|
"image_url": "https://example.com/artwork1.jpg",
|
||||||
|
"medium": "Oil on Canvas",
|
||||||
|
"dimensions": "24x36 inches",
|
||||||
|
"creation_year": 2024,
|
||||||
|
"price": 1500.00,
|
||||||
|
"is_visible": true,
|
||||||
|
"is_for_sale": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/artworks/create-artwork.bru"
|
||||||
|
|
||||||
|
cat > "${base_dir}/artworks/update-artwork.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Update Artwork
|
||||||
|
type: http
|
||||||
|
seq: 4
|
||||||
|
}
|
||||||
|
|
||||||
|
put {
|
||||||
|
url: {{baseUrl}}/artwork/1
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
Content-Type: application/json
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"title": "Updated Sunset Over Mountains",
|
||||||
|
"description": "An updated beautiful landscape painting",
|
||||||
|
"price": 1800.00,
|
||||||
|
"is_for_sale": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/artworks/update-artwork.bru"
|
||||||
|
|
||||||
|
cat > "${base_dir}/artworks/my-artworks.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Get My Artworks
|
||||||
|
type: http
|
||||||
|
seq: 5
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/artworks/mine
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/artworks/my-artworks.bru"
|
||||||
|
|
||||||
|
# Gallery review files
|
||||||
|
cat > "${base_dir}/gallery-reviews/gallery-reviews.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Get Gallery Reviews
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/gallery/1/reviews
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/gallery-reviews/gallery-reviews.bru"
|
||||||
|
|
||||||
|
cat > "${base_dir}/gallery-reviews/create-gallery-review.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Create Gallery Review
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
url: {{baseUrl}}/gallery/1/review
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
Content-Type: application/json
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"grade": 5,
|
||||||
|
"description": "Excellent gallery with amazing artwork collection!",
|
||||||
|
"parent_gr_id": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/gallery-reviews/create-gallery-review.bru"
|
||||||
|
|
||||||
|
cat > "${base_dir}/gallery-reviews/update-gallery-review.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Update Gallery Review
|
||||||
|
type: http
|
||||||
|
seq: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
put {
|
||||||
|
url: {{baseUrl}}/galleries/review/1
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
Content-Type: application/json
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"grade": 4,
|
||||||
|
"description": "Updated: Very good gallery with great artwork collection!"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/gallery-reviews/update-gallery-review.bru"
|
||||||
|
|
||||||
|
cat > "${base_dir}/gallery-reviews/given-gallery-reviews.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Get Given Gallery Reviews
|
||||||
|
type: http
|
||||||
|
seq: 4
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/galleries/reviews/given
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/gallery-reviews/given-gallery-reviews.bru"
|
||||||
|
|
||||||
|
cat > "${base_dir}/gallery-reviews/received-gallery-reviews.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Get Received Gallery Reviews
|
||||||
|
type: http
|
||||||
|
seq: 5
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/galleries/reviews/received
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/gallery-reviews/received-gallery-reviews.bru"
|
||||||
|
|
||||||
|
# Artwork review files
|
||||||
|
cat > "${base_dir}/artwork-reviews/artwork-reviews.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Get Artwork Reviews
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/artwork/1/reviews
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/artwork-reviews/artwork-reviews.bru"
|
||||||
|
|
||||||
|
cat > "${base_dir}/artwork-reviews/create-artwork-review.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Create Artwork Review
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
url: {{baseUrl}}/artwork/1/review
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
Content-Type: application/json
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"grade": 5,
|
||||||
|
"description": "Absolutely stunning artwork! The colors and technique are magnificent.",
|
||||||
|
"parent_ar_id": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/artwork-reviews/create-artwork-review.bru"
|
||||||
|
|
||||||
|
cat > "${base_dir}/artwork-reviews/update-artwork-review.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Update Artwork Review
|
||||||
|
type: http
|
||||||
|
seq: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
put {
|
||||||
|
url: {{baseUrl}}/artworks/review/1
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
Content-Type: application/json
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"grade": 4,
|
||||||
|
"description": "Updated: Very beautiful artwork! Great technique and composition."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/artwork-reviews/update-artwork-review.bru"
|
||||||
|
|
||||||
|
cat > "${base_dir}/artwork-reviews/given-artwork-reviews.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Get Given Artwork Reviews
|
||||||
|
type: http
|
||||||
|
seq: 4
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/artworks/reviews/given
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/artwork-reviews/given-artwork-reviews.bru"
|
||||||
|
|
||||||
|
cat > "${base_dir}/artwork-reviews/received-artwork-reviews.bru" << 'EOF'
|
||||||
|
meta {
|
||||||
|
name: Get Received Artwork Reviews
|
||||||
|
type: http
|
||||||
|
seq: 5
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/artworks/reviews/received
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
OIDC_email: {{email}}
|
||||||
|
OIDC_user: {{username}}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo_success "Created: ${base_dir}/artwork-reviews/received-artwork-reviews.bru"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main function
|
||||||
|
main() {
|
||||||
|
echo_info "🚀 Generating Bruno API Collection for Private API..."
|
||||||
|
echo_info "📁 Collection name: ${COLLECTION_NAME}"
|
||||||
|
echo_info "🌐 Base URL: ${BASE_URL}"
|
||||||
|
echo_info "👤 Default user: ${DEFAULT_USERNAME} (${DEFAULT_EMAIL})"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Get current directory or use provided path
|
||||||
|
local target_dir="${1:-$(pwd)}"
|
||||||
|
local base_dir="${target_dir}/${COLLECTION_NAME}"
|
||||||
|
|
||||||
|
echo_info "📍 Creating collection in: ${base_dir}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Create directory structure
|
||||||
|
create_directories "$base_dir"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Generate all files
|
||||||
|
generate_files "$base_dir"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo_success "Bruno collection generated successfully!"
|
||||||
|
echo ""
|
||||||
|
echo_info "📋 Next steps:"
|
||||||
|
echo " 1. Open Bruno and import the collection"
|
||||||
|
echo " 2. Select the 'local' environment"
|
||||||
|
echo " 3. Update variables in environments/local.bru if needed"
|
||||||
|
echo " 4. Start testing with auth/debug-headers.bru"
|
||||||
|
echo ""
|
||||||
|
echo_info "🔧 To customize:"
|
||||||
|
echo " - Edit environments/local.bru to change baseUrl, email, username"
|
||||||
|
echo " - Update gallery/artwork IDs in individual requests"
|
||||||
|
echo " - Modify request bodies to match your test data"
|
||||||
|
echo ""
|
||||||
|
echo_warning "💡 Don't forget to update the OIDC headers if your user changes!"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Help function
|
||||||
|
show_help() {
|
||||||
|
echo "Bruno API Collection Generator"
|
||||||
|
echo ""
|
||||||
|
echo "Usage: $0 [target_directory]"
|
||||||
|
echo ""
|
||||||
|
echo "Arguments:"
|
||||||
|
echo " target_directory Directory where to create the collection (default: current directory)"
|
||||||
|
echo ""
|
||||||
|
echo "Examples:"
|
||||||
|
echo " $0 # Create in current directory"
|
||||||
|
echo " $0 ~/bruno # Create in ~/bruno directory"
|
||||||
|
echo " $0 /path/to/bruno # Create in specific path"
|
||||||
|
echo ""
|
||||||
|
echo "Configuration (edit script to change):"
|
||||||
|
echo " Collection name: ${COLLECTION_NAME}"
|
||||||
|
echo " Base URL: ${BASE_URL}"
|
||||||
|
echo " Default email: ${DEFAULT_EMAIL}"
|
||||||
|
echo " Default username: ${DEFAULT_USERNAME}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check for help flag
|
||||||
|
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
|
||||||
|
show_help
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run main function
|
||||||
|
main "$@"}
|
@ -36,7 +36,7 @@ services:
|
|||||||
|
|
||||||
public_api:
|
public_api:
|
||||||
build:
|
build:
|
||||||
context: ./laravel
|
context: ./public
|
||||||
depends_on:
|
depends_on:
|
||||||
- keycloak
|
- keycloak
|
||||||
- mysql
|
- mysql
|
||||||
@ -104,3 +104,4 @@ volumes:
|
|||||||
postgres_data:
|
postgres_data:
|
||||||
mysql_data:
|
mysql_data:
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Variables
|
# Variables
|
||||||
KC_HOST="http://localhost:8080"
|
KC_HOST="http://localhost:8080"
|
||||||
REALM="master"
|
REALM="master"
|
||||||
@ -7,6 +6,7 @@ CLIENT_ID="soa"
|
|||||||
CLIENT_SECRET="mysecret"
|
CLIENT_SECRET="mysecret"
|
||||||
USERNAME="alexis"
|
USERNAME="alexis"
|
||||||
PASSWORD="password"
|
PASSWORD="password"
|
||||||
|
PERSONAL_TOKEN="personaltoken"
|
||||||
|
|
||||||
# Fonction d'attente
|
# Fonction d'attente
|
||||||
wait_for_keycloak() {
|
wait_for_keycloak() {
|
||||||
@ -28,9 +28,16 @@ get_admin_token() {
|
|||||||
jq -r .access_token
|
jq -r .access_token
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Générer une date d'expiration (1 an à partir de maintenant)
|
||||||
|
generate_expiry_date() {
|
||||||
|
date -d "+1 year" --iso-8601=seconds
|
||||||
|
}
|
||||||
|
|
||||||
# Créer un realm, client et utilisateur
|
# Créer un realm, client et utilisateur
|
||||||
setup_keycloak() {
|
setup_keycloak() {
|
||||||
TOKEN=$(get_admin_token)
|
TOKEN=$(get_admin_token)
|
||||||
|
CURRENT_DATE=$(date --iso-8601=seconds)
|
||||||
|
EXPIRY_DATE=$(generate_expiry_date)
|
||||||
|
|
||||||
echo "🛠️ Création du realm $REALM..."
|
echo "🛠️ Création du realm $REALM..."
|
||||||
curl -s -X POST "$KC_HOST/admin/realms" \
|
curl -s -X POST "$KC_HOST/admin/realms" \
|
||||||
@ -48,28 +55,52 @@ setup_keycloak() {
|
|||||||
\"publicClient\": false,
|
\"publicClient\": false,
|
||||||
\"secret\": \"$CLIENT_SECRET\",
|
\"secret\": \"$CLIENT_SECRET\",
|
||||||
\"redirectUris\": [\"*\"],
|
\"redirectUris\": [\"*\"],
|
||||||
\"standardFlowEnabled\": true
|
\"standardFlowEnabled\": true,
|
||||||
|
\"serviceAccountsEnabled\": true,
|
||||||
|
\"authorizationServicesEnabled\": false
|
||||||
}" > /dev/null
|
}" > /dev/null
|
||||||
|
|
||||||
echo "👤 Création de l'utilisateur $USERNAME..."
|
echo "👤 Création de l'utilisateur $USERNAME avec token personnel..."
|
||||||
curl -s -X POST "$KC_HOST/admin/realms/$REALM/users" \
|
curl -s -X POST "$KC_HOST/admin/realms/$REALM/users" \
|
||||||
-H "Authorization: Bearer $TOKEN" \
|
-H "Authorization: Bearer $TOKEN" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d "{
|
-d "{
|
||||||
\"username\": \"$USERNAME\",
|
\"username\": \"$USERNAME\",
|
||||||
\"enabled\": true,
|
\"enabled\": true,
|
||||||
|
\"emailVerified\": true,
|
||||||
|
\"attributes\": {
|
||||||
|
\"api_token\": [\"$PERSONAL_TOKEN\"],
|
||||||
|
\"token_created\": [\"$CURRENT_DATE\"],
|
||||||
|
\"token_expires\": [\"$EXPIRY_DATE\"],
|
||||||
|
\"created_by\": [\"setup_script\"],
|
||||||
|
\"department\": [\"IT\"],
|
||||||
|
\"access_level\": [\"developer\"]
|
||||||
|
},
|
||||||
\"credentials\": [{
|
\"credentials\": [{
|
||||||
\"type\": \"password\",
|
\"type\": \"password\",
|
||||||
\"value\": \"$PASSWORD\",
|
\"value\": \"$PASSWORD\",
|
||||||
\"temporary\": false
|
\"temporary\": false
|
||||||
}]
|
}]
|
||||||
}" > /dev/null
|
}"
|
||||||
|
|
||||||
echo "✅ Configuration terminée !"
|
echo "✅ Configuration terminée !"
|
||||||
echo "🔐 Utilisateur: $USERNAME / $PASSWORD"
|
echo "🔐 Utilisateur: $USERNAME / $PASSWORD"
|
||||||
echo "🪪 Client secret: $CLIENT_SECRET"
|
echo "🪪 Client secret: $CLIENT_SECRET"
|
||||||
|
echo "🎫 Personal Access Token: $PERSONAL_TOKEN"
|
||||||
|
echo "📅 Token créé le: $CURRENT_DATE"
|
||||||
|
echo "⏰ Token expire le: $EXPIRY_DATE"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction pour tester le token
|
||||||
|
test_personal_token() {
|
||||||
|
|
||||||
|
echo "Pour accéder à une ressource protégée:"
|
||||||
|
echo "curl -X GET http://localhost:3000/api/protected"
|
||||||
|
echo " -H \"Authorization: Bearer $PERSONAL_TOKEN\""
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Lancer le setup
|
# Lancer le setup
|
||||||
wait_for_keycloak
|
wait_for_keycloak
|
||||||
setup_keycloak
|
setup_keycloak
|
||||||
|
test_personal_token
|
||||||
|
@ -1,73 +0,0 @@
|
|||||||
# ---------- Stage 1: Build with Composer ----------
|
|
||||||
FROM php:8.2-cli-alpine AS build
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Install Composer and build dependencies
|
|
||||||
RUN apk add --no-cache \
|
|
||||||
libzip-dev zip unzip curl git oniguruma-dev libxml2-dev
|
|
||||||
|
|
||||||
# Install PHP extensions for Laravel
|
|
||||||
RUN docker-php-ext-install zip mbstring xml
|
|
||||||
|
|
||||||
# Install Composer
|
|
||||||
RUN curl -sS https://getcomposer.org/installer | php && \
|
|
||||||
mv composer.phar /usr/local/bin/composer
|
|
||||||
|
|
||||||
# Copy project files and install dependencies
|
|
||||||
COPY . .
|
|
||||||
RUN composer install --no-dev --optimize-autoloader --no-interaction
|
|
||||||
|
|
||||||
|
|
||||||
# ---------- Stage 2: Production Image ----------
|
|
||||||
FROM php:8.2-fpm-alpine
|
|
||||||
|
|
||||||
# Set working directory
|
|
||||||
WORKDIR /var/www
|
|
||||||
|
|
||||||
# Install system and PHP dependencies
|
|
||||||
RUN apk add --no-cache \
|
|
||||||
nginx \
|
|
||||||
supervisor \
|
|
||||||
bash \
|
|
||||||
mysql-client \
|
|
||||||
libpng-dev \
|
|
||||||
libjpeg-turbo-dev \
|
|
||||||
freetype-dev \
|
|
||||||
libxml2-dev \
|
|
||||||
oniguruma-dev \
|
|
||||||
libzip-dev \
|
|
||||||
curl \
|
|
||||||
git \
|
|
||||||
openssh \
|
|
||||||
php-pear \
|
|
||||||
gcc g++ make autoconf libtool linux-headers
|
|
||||||
|
|
||||||
# Install PHP extensions
|
|
||||||
RUN docker-php-ext-configure gd --with-freetype --with-jpeg && \
|
|
||||||
docker-php-ext-install pdo pdo_mysql mbstring gd xml zip && \
|
|
||||||
pecl install redis && \
|
|
||||||
docker-php-ext-enable redis
|
|
||||||
|
|
||||||
|
|
||||||
# Clean up build tools
|
|
||||||
RUN apk del gcc g++ make autoconf libtool
|
|
||||||
|
|
||||||
# Install Ansible
|
|
||||||
RUN apk add --no-cache ansible
|
|
||||||
# Copy built app from previous stage
|
|
||||||
COPY --from=build /app /var/www
|
|
||||||
|
|
||||||
# Set proper permissions for Laravel
|
|
||||||
RUN chown -R www-data:www-data /var/www/storage /var/www/bootstrap/cache /var/www/database && \
|
|
||||||
chmod -R 755 /var/www/storage /var/www/bootstrap/cache /var/www/database
|
|
||||||
|
|
||||||
# Copy config files
|
|
||||||
COPY nginx.conf /etc/nginx/nginx.conf
|
|
||||||
COPY supervisord.conf /etc/supervisord.conf
|
|
||||||
|
|
||||||
# Expose HTTP port
|
|
||||||
EXPOSE 80
|
|
||||||
|
|
||||||
# Start services
|
|
||||||
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]
|
|
0
laravel/.gitignore → public/.gitignore
vendored
0
laravel/.gitignore → public/.gitignore
vendored
@ -1,9 +1,73 @@
|
|||||||
FROM python:3.11-slim
|
# ---------- Stage 1: Build with Composer ----------
|
||||||
|
FROM php:8.2-cli-alpine AS build
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install Composer and build dependencies
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
libzip-dev zip unzip curl git oniguruma-dev libxml2-dev
|
||||||
|
|
||||||
|
# Install PHP extensions for Laravel
|
||||||
|
RUN docker-php-ext-install zip mbstring xml
|
||||||
|
|
||||||
|
# Install Composer
|
||||||
|
RUN curl -sS https://getcomposer.org/installer | php && \
|
||||||
|
mv composer.phar /usr/local/bin/composer
|
||||||
|
|
||||||
|
# Copy project files and install dependencies
|
||||||
COPY . .
|
COPY . .
|
||||||
|
RUN composer install --no-dev --optimize-autoloader --no-interaction
|
||||||
|
|
||||||
RUN pip install redis flask flask_sqlalchemy pyjwt requests pymysql cryptography
|
|
||||||
|
|
||||||
CMD ["python", "app.py"]
|
# ---------- Stage 2: Production Image ----------
|
||||||
|
FROM php:8.2-fpm-alpine
|
||||||
|
|
||||||
|
# Set working directory
|
||||||
|
WORKDIR /var/www
|
||||||
|
|
||||||
|
# Install system and PHP dependencies
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
nginx \
|
||||||
|
supervisor \
|
||||||
|
bash \
|
||||||
|
mysql-client \
|
||||||
|
libpng-dev \
|
||||||
|
libjpeg-turbo-dev \
|
||||||
|
freetype-dev \
|
||||||
|
libxml2-dev \
|
||||||
|
oniguruma-dev \
|
||||||
|
libzip-dev \
|
||||||
|
curl \
|
||||||
|
git \
|
||||||
|
openssh \
|
||||||
|
php-pear \
|
||||||
|
gcc g++ make autoconf libtool linux-headers
|
||||||
|
|
||||||
|
# Install PHP extensions
|
||||||
|
RUN docker-php-ext-configure gd --with-freetype --with-jpeg && \
|
||||||
|
docker-php-ext-install pdo pdo_mysql mbstring gd xml zip && \
|
||||||
|
pecl install redis && \
|
||||||
|
docker-php-ext-enable redis
|
||||||
|
|
||||||
|
|
||||||
|
# Clean up build tools
|
||||||
|
RUN apk del gcc g++ make autoconf libtool
|
||||||
|
|
||||||
|
# Install Ansible
|
||||||
|
RUN apk add --no-cache ansible
|
||||||
|
# Copy built app from previous stage
|
||||||
|
COPY --from=build /app /var/www
|
||||||
|
|
||||||
|
# Set proper permissions for Laravel
|
||||||
|
RUN chown -R www-data:www-data /var/www/storage /var/www/bootstrap/cache /var/www/database && \
|
||||||
|
chmod -R 755 /var/www/storage /var/www/bootstrap/cache /var/www/database
|
||||||
|
|
||||||
|
# Copy config files
|
||||||
|
COPY nginx.conf /etc/nginx/nginx.conf
|
||||||
|
COPY supervisord.conf /etc/supervisord.conf
|
||||||
|
|
||||||
|
# Expose HTTP port
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
# Start services
|
||||||
|
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user