Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,18 @@ TWILIO_ACCOUNT_SID=AC_your_account_sid
TWILIO_AUTH_TOKEN=your_auth_token
TWILIO_FROM_NUMBER=+1234567890

# ============================================================
# GCS IMAGE STORAGE (product-service)
# ============================================================
# Google Cloud Storage bucket for product images.
# Leave empty to disable image upload (service still starts without it).
GCS_BUCKET_NAME=auron-product-images

# Raw JSON content of the service account key file.
# To prepare: cat gcs-credentials.json
# Leave empty to use Application Default Credentials (GOOGLE_APPLICATION_CREDENTIALS).
GCS_CREDENTIALS_JSON=

# ============================================================
# FRONTEND
# ============================================================
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,8 @@ coverage/
tmp/
temp/
*.tmp

# ============================================================
# GCP SERVICE ACCOUNT KEYS
# ============================================================
auron-ecommerce-gcp-*.json
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ services:
- DATABASE_URL=postgres://auron:auron_pass@products-db:5432/products_db?sslmode=disable
- REDIS_URL=redis://redis:6379/0
- KAFKA_BROKERS=kafka:29092
- GCS_BUCKET_NAME=${GCS_BUCKET_NAME}
- GCS_CREDENTIALS_JSON=${GCS_CREDENTIALS_JSON}
depends_on:
products-db:
condition: service_healthy
Expand Down
112 changes: 100 additions & 12 deletions docs/API_CURL_TESTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,8 @@ CATEGORY_ID=$(curl -s -X POST $BASE/categories \

### Create — admin only, save ID

> `image_url` removed from request body — upload images separately after creation.

```bash
PRODUCT_ID=$(curl -s -X POST $BASE/products \
-H "Authorization: Bearer $ADMIN_TOKEN" \
Expand All @@ -288,23 +290,112 @@ PRODUCT_ID=$(curl -s -X POST $BASE/products \
\"price\": 15999000,
\"is_active\": true
}" | jq -r '.data.id')
echo "Product ID: $PRODUCT_ID"
```

**Response:**
```json
{
"data": { "id": "<uuid>", "name": "iPhone 15 Pro", "price": 15999000, "is_active": true, ... },
"success": true
"success": true,
"data": { "id": "<uuid>", "name": "iPhone 15 Pro", "price": 15999000, "image_url": "", "images": [], "is_active": true, ... }
}
```

---

### Upload image — admin only, save first image ID

```bash
IMAGE_ID=$(curl -s -X POST "$BASE/products/$PRODUCT_ID/images" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-F "image=@/path/to/iphone.jpg" | jq -r '.data.id')
echo "Image ID: $IMAGE_ID"
```

**Response:**
```json
{
"success": true,
"data": {
"id": "<uuid>",
"product_id": "<uuid>",
"url": "https://storage.googleapis.com/auron-product-images/products/<uuid>.jpg",
"position": 0,
"created_at": "2026-01-01T00:00:00Z"
}
}
```

---

### Upload second image

```bash
IMAGE_ID_2=$(curl -s -X POST "$BASE/products/$PRODUCT_ID/images" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-F "image=@/path/to/iphone-back.jpg" | jq -r '.data.id')
echo "Image 2 ID: $IMAGE_ID_2"
```

---

### Get product — confirm images array and image_url

```bash
curl -s "$BASE/products/$PRODUCT_ID" | jq '.data | {image_url, images}'
```

**Response:**
```json
{
"image_url": "https://storage.googleapis.com/auron-product-images/products/<uuid>.jpg",
"images": [
{ "id": "<uuid-1>", "url": "https://...", "position": 0, "created_at": "..." },
{ "id": "<uuid-2>", "url": "https://...", "position": 1, "created_at": "..." }
]
}
```

---

### Reorder images — make second image primary

```bash
curl -s -X PUT "$BASE/products/$PRODUCT_ID/images/reorder" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"image_ids\":[\"$IMAGE_ID_2\",\"$IMAGE_ID\"]}" | jq '.data[] | {id,position}'
```

**Response:**
```json
[
{ "id": "<uuid-2>", "position": 0 },
{ "id": "<uuid-1>", "position": 1 }
]
```

---

### Delete image — admin only

```bash
curl -s -X DELETE "$BASE/products/$PRODUCT_ID/images/$IMAGE_ID" \
-H "Authorization: Bearer $ADMIN_TOKEN" | jq
```

**Response:**
```json
{ "success": true, "message": "image deleted" }
```

---

### List — public, with filters

```bash
# All products
curl -s "$BASE/products" | jq '.data[0] | {id,name,price}'
curl -s "$BASE/products" | jq '.data[0] | {id, name, price, image_url, images_count: (.images | length)}'

# Full-text search
curl -s "$BASE/products?q=iphone" | jq '{total: .meta.total, first: .data[0].name}'
Expand All @@ -316,9 +407,9 @@ curl -s "$BASE/products?category_id=$CATEGORY_ID&sort=price_asc&page=1&limit=5"
**Response (list):**
```json
{
"data": [{ "id": "<uuid>", "name": "iPhone 15 Pro", "price": 15999000, "is_active": true, ... }],
"meta": { "page": 1, "limit": 20, "total": 1 },
"success": true
"success": true,
"data": [{ "id": "<uuid>", "name": "iPhone 15 Pro", "price": 15999000, "image_url": "https://...", "images": [...], ... }],
"meta": { "page": 1, "limit": 20, "total": 1 }
}
```

Expand All @@ -327,15 +418,12 @@ curl -s "$BASE/products?category_id=$CATEGORY_ID&sort=price_asc&page=1&limit=5"
### Get by ID — public

```bash
curl -s "$BASE/products/$PRODUCT_ID" | jq '.data | {id,name,price}'
curl -s "$BASE/products/$PRODUCT_ID" | jq '.data | {id, name, price, image_url}'
```

**Response:**
```json
{
"data": { "id": "<uuid>", "name": "iPhone 15 Pro", "price": 15999000, ... },
"success": true
}
{ "id": "<uuid>", "name": "iPhone 15 Pro", "price": 15999000, "image_url": "https://..." }
```

---
Expand All @@ -356,7 +444,7 @@ curl -s -X PUT "$BASE/products/$PRODUCT_ID" \

---

### Delete — admin only
### Delete — admin only (also deletes all GCS images)

```bash
curl -s -X DELETE "$BASE/products/$PRODUCT_ID" -H "Authorization: Bearer $ADMIN_TOKEN" | jq
Expand Down
Loading
Loading