bun installCreate a .env file in the root directory with the following variables:
# Database
DATABASE_URL=postgresql://user:password@localhost:5432/security_week
# JWT
JWT_SECRET=your-secret-key-here
JWT_EXPIRY=24h
# Server
PORT=3000
NODE_ENV=development
# Shopify API
SHOPIFY_SHOP_NAME=your-shop-name
SHOPIFY_ACCESS_TOKEN=your-shopify-access-token
SHOPIFY_WEBHOOK_SECRET=your-shopify-webhook-secret- Start the PostgreSQL database:
docker-compose up -d- Push the schema to the database:
bun db:push- Seed the database with initial roles:
bun run src/db/seed.tsbun run devThen open http://localhost:3000
bun db:push- Push schema changes to database (⚠️ see note below)bun db:generate- Generate migration files from schema changesbun db:migrate- Apply pending migrationsbun dev:db- Open Drizzle Studio for database management
Due to a bug in drizzle-kit 0.31.5, running bun db:push multiple times may fail with:
error: column "id" is in a primary key
This happens because drizzle-kit creates explicit NOT NULL constraints and then tries to remove them on subsequent runs.
Workaround: Use the migration workflow instead:
# 1. Generate migration after schema changes
bun db:generate
# 2. Apply the migration
bun db:migrateAlternatively, if you encounter this issue, the database is likely already in sync with your schema and no action is needed.
POST /products
- Creates a product in Shopify and saves it to the database
- Requires authentication and
canPostProductspermission (ADMIN role only) - Request body:
{ "name": "Product Name", "price": 29.99 } - Response:
{ "id": "01HQXYZ123", "shopifyId": "7891234567890", "message": "Product created successfully" }
GET /products
- Returns all products with creator information
- Requires authentication
- Response:
[ { "id": "01HQXYZ123", "shopifyId": "7891234567890", "salesCount": 0, "createdAt": "2024-10-24T10:00:00.000Z", "creator": { "id": "01HQUSER123", "name": "John Doe", "email": "john@example.com" } } ]
GET /my-products
- Returns products created by the authenticated user
- Requires authentication
- Response:
[ { "id": "01HQXYZ123", "shopifyId": "7891234567890", "salesCount": 0, "createdAt": "2024-10-24T10:00:00.000Z" } ]
POST /webhooks/shopify-sales
- Webhook endpoint for Shopify order creation events
- Automatically increments
salesCountfor products when orders are placed - Secured with HMAC SHA-256 signature verification
- Handles multiple products and quantities in a single order
- No authentication required (secured by HMAC signature)
- Expected headers:
X-Shopify-Hmac-SHA256: HMAC signature from Shopify
- Request body: Shopify order webhook payload (JSON)
- Response:
{ "success": true, "message": "Webhook processed successfully. Updated 2 product(s).", "processedProducts": 2 }
For detailed webhook setup instructions, see WEBHOOK_SETUP.md.
To generate a test HMAC signature for webhook testing:
bun test:webhookThis will output an example payload and the corresponding HMAC signature you can use with cURL.
The application uses role-based permissions:
ADMIN- Full access including creating products (canPostProducts: true)USER- Read-only access to products (canPostProducts: false)BAN- No access to any resources