diff --git a/apps/api-service/_tests/.env b/apps/api-service/_tests/.env new file mode 100644 index 0000000..c8e7069 --- /dev/null +++ b/apps/api-service/_tests/.env @@ -0,0 +1,9 @@ +# REST Client Environment Variables +# This file is read by VSCode REST Client extension + +# Base URL +baseUrl=http://localhost:3000 + +# API Keys (update these with your actual keys) +masterKey=bnt_f056994b6ccc024d7d0dd9d37103997ba4e47ef52aa62478356ee4eda8aa73db +apiKey=bnt_71e7e16732ac5e21f597edc56e99e8c3696e713552ec9d1f44dfeffb2ef7c495 diff --git a/apps/api-service/_tests/api.rest b/apps/api-service/_tests/api.rest new file mode 100644 index 0000000..065a008 --- /dev/null +++ b/apps/api-service/_tests/api.rest @@ -0,0 +1,252 @@ +### Banatie API Tests +### VSCode REST Client Extension format +### https://marketplace.visualstudio.com/items?itemName=humao.rest-client + +### +### Setup: +### 1. Update apiKey in _tests/.env file +### 2. Run "Get API Info" to extract org/project from response +### 3. Other requests will use those values automatically + +############################################################################### +# PUBLIC ENDPOINTS (No Authentication) +############################################################################### + +### 1. Health Check +GET {{$dotenv baseUrl}}/health +Content-Type: application/json + +### 2. API Info (No Auth) +GET {{$dotenv baseUrl}}/api/info +Content-Type: application/json + +### 3. Get API Info (Extract org/project) +# @name getApiInfo +GET {{$dotenv baseUrl}}/api/info +Content-Type: application/json +X-API-Key: {{$dotenv apiKey}} + +############################################################################### +# ADMIN ENDPOINTS (Master Key Required) +############################################################################### + +### 4. List All API Keys +GET {{$dotenv baseUrl}}/api/admin/keys +Content-Type: application/json +X-API-Key: {{$dotenv masterKey}} + +### 5. Create New Organization + Project + Project API Key +# Update the slugs and names below, then execute +# After execution, copy the returned apiKey to _tests/.env +POST {{$dotenv baseUrl}}/api/admin/keys +Content-Type: application/json +X-API-Key: {{$dotenv masterKey}} + +{ + "type": "project", + "organizationSlug": "acme-corp", + "organizationName": "Acme Corporation", + "projectSlug": "mobile-app", + "projectName": "Mobile App Project", + "name": "Mobile App API Key", + "expiresInDays": 90 +} + +### 6. Create Another Master Key (admin use) +POST {{$dotenv baseUrl}}/api/admin/keys +Content-Type: application/json +X-API-Key: {{$dotenv masterKey}} + +{ + "type": "master", + "name": "Secondary Master Key" +} + +### 7. Revoke an API Key +# Replace with actual ID from "List All API Keys" response +# DELETE {{$dotenv baseUrl}}/api/admin/keys/ +# Content-Type: application/json +# X-API-Key: {{$dotenv masterKey}} + +############################################################################### +# PROTECTED ENDPOINTS (Project Key Required) +# These use org/project from the API Info response +############################################################################### + +### 8. Generate Image - Simple Sunset +# @name generateSunset +POST {{$dotenv baseUrl}}/api/text-to-image +Content-Type: application/json +X-API-Key: {{$dotenv apiKey}} + +{ + "prompt": "A beautiful sunset over mountains with orange and purple sky, dramatic clouds, peaceful atmosphere", + "filename": "sunset_{{$timestamp}}" +} + +### 9. Generate Image - Cyberpunk City +# @name generateCyberpunk +POST {{$dotenv baseUrl}}/api/text-to-image +Content-Type: application/json +X-API-Key: {{$dotenv apiKey}} + +{ + "prompt": "A futuristic cyberpunk cityscape at night with neon lights, flying cars, holographic advertisements, rain-slicked streets, highly detailed, cinematic lighting", + "filename": "cyberpunk_{{$timestamp}}", + "aspectRatio": "16:9" +} + +### 10. Generate Image - Portrait +# @name generatePortrait +POST {{$dotenv baseUrl}}/api/text-to-image +Content-Type: application/json +X-API-Key: {{$dotenv apiKey}} + +{ + "prompt": "Professional portrait of a business person, confident expression, modern office background, natural lighting, high quality photography", + "filename": "portrait_{{$timestamp}}", + "aspectRatio": "9:16" +} + +### 11. Generate Image - Abstract Art +POST {{$dotenv baseUrl}}/api/text-to-image +Content-Type: application/json +X-API-Key: {{$dotenv apiKey}} + +{ + "prompt": "Abstract digital art with vibrant colors, flowing shapes, geometric patterns, modern artistic style", + "filename": "abstract_{{$timestamp}}", + "aspectRatio": "1:1" +} + +### 12. List Generated Images +# @name listImages +GET {{$dotenv baseUrl}}/api/images +Content-Type: application/json +X-API-Key: {{$dotenv apiKey}} + +### 13. List Images with Filters (limit 5, generated only) +GET {{$dotenv baseUrl}}/api/images?limit=5&category=generated +Content-Type: application/json +X-API-Key: {{$dotenv apiKey}} + +### 14. Upload Image File +# NOTE: Update the file path to an actual image on your system +# For example: < /projects/my-projects/banatie-service/results/some_image.png +POST {{$dotenv baseUrl}}/api/upload +X-API-Key: {{$dotenv apiKey}} +Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW + +------WebKitFormBoundary7MA4YWxkTrZu0gW +Content-Disposition: form-data; name="file"; filename="uploaded-test.png" +Content-Type: image/png + +< /projects/my-projects/banatie-service/results/banatie-party.png +------WebKitFormBoundary7MA4YWxkTrZu0gW-- + +############################################################################### +# ERROR CASES (Testing Validation) +############################################################################### + +### 15. Text-to-Image WITHOUT API Key (Should return 401) +POST {{$dotenv baseUrl}}/api/text-to-image +Content-Type: application/json + +{ + "prompt": "This should fail without API key" +} + +### 16. Text-to-Image with INVALID API Key (Should return 401) +POST {{$dotenv baseUrl}}/api/text-to-image +Content-Type: application/json +X-API-Key: invalid_key_12345 + +{ + "prompt": "This should fail with invalid key" +} + +### 17. Text-to-Image WITHOUT Prompt (Should return 400) +POST {{$dotenv baseUrl}}/api/text-to-image +Content-Type: application/json +X-API-Key: {{$dotenv apiKey}} + +{ + "filename": "no_prompt_test" +} + +### 18. Text-to-Image with Empty Prompt (Should return 400) +POST {{$dotenv baseUrl}}/api/text-to-image +Content-Type: application/json +X-API-Key: {{$dotenv apiKey}} + +{ + "prompt": "", + "filename": "empty_prompt" +} + +### 19. Admin Endpoint with Project Key (Should return 403) +GET {{$dotenv baseUrl}}/api/admin/keys +Content-Type: application/json +X-API-Key: {{$dotenv apiKey}} + +### 20. Create Master Key with Project Key (Should return 403) +POST {{$dotenv baseUrl}}/api/admin/keys +Content-Type: application/json +X-API-Key: {{$dotenv apiKey}} + +{ + "type": "master", + "name": "This should fail - wrong key type" +} + +############################################################################### +# RATE LIMITING & HEADERS +############################################################################### + +### 21. Check Rate Limit Headers +GET {{$dotenv baseUrl}}/api/info +Content-Type: application/json +X-API-Key: {{$dotenv apiKey}} + +############################################################################### +# USAGE NOTES +############################################################################### + +# Workflow: +# ========= +# 1. Update apiKey in _tests/.env with your project key +# 2. Run request #3 "Get API Info" - this validates the key and shows org/project +# 3. Run requests #8-11 to generate images +# 4. Run request #12 to list all generated images +# 5. Run request #14 to upload an image (update file path first) +# 6. Run requests #15-20 to test error handling + +# Admin Workflow: +# =============== +# 1. masterKey in _tests/.env is already set +# 2. Run request #4 to list all existing keys +# 3. Run request #5 to create new org/project/key +# 4. Copy the returned apiKey from response +# 5. Update apiKey in _tests/.env +# 6. Continue with testing workflow above + +# Expected Results: +# ================= +# - Request #3: Returns keyInfo with organizationSlug, projectSlug +# - Requests #8-11: Return image URLs and metadata +# - Request #12: Returns array of generated images +# - Request #14: Returns upload confirmation +# - Requests #15-20: Return appropriate error codes (401, 400, 403) + +# Useful Commands: +# ================ +# View MinIO Console: http://localhost:9001 +# Database access: psql -h localhost -p 5460 -U banatie_user -d banatie_db +# View logs: tail -f apps/api-service/api-dev.log + +# Dynamic Variables: +# ================== +# {{$timestamp}} - Current Unix timestamp +# {{$randomInt}} - Random integer +# {{$guid}} - Random GUID +# Responses can be referenced: {{requestName.response.body.$.field}} diff --git a/apps/api-service/docker-compose.yml b/apps/api-service/docker-compose.yml index 2a7020c..57f59cc 100644 --- a/apps/api-service/docker-compose.yml +++ b/apps/api-service/docker-compose.yml @@ -24,7 +24,7 @@ services: timeout: 10s retries: 3 start_period: 40s - restart: unless-stopped + restart: "no" # MinIO Object Storage - SNMD Mode minio: @@ -54,7 +54,7 @@ services: timeout: 10s retries: 3 start_period: 40s - restart: unless-stopped + restart: "no" # MinIO Storage Initialization storage-init: