Skip to content

Ichandra2 - #587

Merged
ichandrasharma merged 4 commits into
mainfrom
ichandra2
Aug 21, 2026
Merged

Ichandra2#587
ichandrasharma merged 4 commits into
mainfrom
ichandra2

Conversation

@ichandrasharma

Copy link
Copy Markdown
Collaborator

Description

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Test improvement

Testing

  • Backend tests pass (pytest)
  • Frontend type-checks (tsc --noEmit)
  • Manually tested the user flow

Checklist

  • Code follows the project style (match surrounding patterns)
  • Self-reviewed the diff
  • Comments added for complex logic
  • No new warnings introduced

@greptile-apps

greptile-apps Bot commented Aug 21, 2026

Copy link
Copy Markdown

Greptile Summary

The PR adds an authenticated Shopify connection page and backend OAuth flow, including a browser GET callback, signed shop-bound state, tenant ownership enforcement, connection status, and environment-derived redirects.

  • Mounts the Shopify REST router independently of webhook imports.
  • Adds frontend proxying and Shopify integration UI.
  • Adds expiry and shop binding to OAuth state and prevents cross-workspace store reassignment.

Confidence Score: 4/5

The PR is not yet safe to merge because the configured production flow still sends Shopify callbacks to a loopback address.

The callback resolver accepts PYTHON_BACKEND_URL, while the production Fly configuration sets that variable to http://localhost:8000; authorization therefore directs the merchant's browser to its own machine instead of the deployed backend.

Files Needing Attention: backend/integrations/shopify_routes.py and fly.toml

Important Files Changed

Filename Overview
backend/integrations/shopify_routes.py Implements the Shopify OAuth and connection flow, but its public callback resolver still accepts the production deployment's loopback-only backend URL.
backend/main_api_app.py Mounts the Shopify REST router independently so unrelated webhook import failures do not suppress these routes.
frontend-nextjs/next.config.js Proxies Shopify API requests from the frontend server to the local backend process.
frontend-nextjs/pages/integrations/index.tsx Adds Shopify to the integrations catalog.
frontend-nextjs/pages/integrations/shopify.tsx Adds the authenticated Shopify connection and status interface.

Sequence Diagram

sequenceDiagram
    participant User as Merchant Browser
    participant UI as ATOM Frontend
    participant API as ATOM Backend
    participant Shopify
    User->>UI: Connect shop
    UI->>API: GET /api/shopify/auth/url
    API-->>UI: Shopify authorize URL + signed state
    UI->>Shopify: Navigate to authorize URL
    Shopify-->>User: Authorization approval
    Shopify->>API: GET /api/shopify/auth/callback
    API->>Shopify: Exchange authorization code
    Shopify-->>API: Access token
    API->>API: Enforce workspace ownership and persist store
    API-->>UI: Redirect with connection result
Loading

Reviews (3): Last reviewed commit: "fix(shopify): one-time state + fail-clos..." | Re-trigger Greptile

Comment thread backend/integrations/shopify_routes.py Outdated
Comment thread backend/integrations/shopify_routes.py Outdated
Comment thread backend/integrations/shopify_routes.py Outdated
- GET callback route for Shopify browser redirect (was POST-only -> 405)
- callback URI derived from deployment config (ATOM_PUBLIC_URL etc.), not hardcoded localhost
- signed OAuth state binds user+workspace; tampered state rejected
- callback never reassigns a store owned by a different workspace (cross-tenant protection verified)
- require SHOPIFY_API_KEY/SHOPIFY_API_SECRET
Comment thread backend/integrations/shopify_routes.py Outdated
Comment thread backend/integrations/shopify_routes.py Outdated
- OAuth state now binds user+workspace+shop with a random nonce and 10min expiry; blocks cross-shop replay of a previously issued state
- state parsed on '|' separators so shop domains with dots don't break verification
- _redirect_base_url fails closed (no loopback) unless SHOPIFY_DEV_LOOPBACK=1; public URL resolved from ATOM_PUBLIC_URL/ATOM_BASE_URL/PYTHON_BACKEND_URL/NEXT_PUBLIC_API_URL
@ichandrasharma
ichandrasharma merged commit eec65cb into main Aug 21, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant