Skip to content

Handle malformed affiliate payout JSON#170

Closed
morganschp wants to merge 2 commits into
profullstack:masterfrom
morganschp:fix-affiliate-conversion-pay-invalid-json
Closed

Handle malformed affiliate payout JSON#170
morganschp wants to merge 2 commits into
profullstack:masterfrom
morganschp:fix-affiliate-conversion-pay-invalid-json

Conversation

@morganschp
Copy link
Copy Markdown
Contributor

Fixes #169.

Summary

  • parse affiliate conversion payout request bodies with the existing safe parser
  • keep malformed JSON on the existing 400 validation path
  • add a regression test proving malformed JSON does not query conversions or call payout logic

Validation

  • ./node_modules/.bin/vitest run 'src/app/api/affiliates/offers/[id]/conversions/pay/route.test.ts'\n- npm run type-check\n- git diff --check

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 23, 2026

Greptile Summary

This PR fixes a crash when the POST /api/affiliates/offers/[id]/conversions/pay endpoint receives malformed JSON by switching from request.json() (which throws on bad input) to the existing safeParseBody helper (which returns null). It also strengthens the conversion_id guard from a simple falsy check to a full typeof … !== "string" check, and adds a regression test suite covering both malformed JSON and non-string IDs.

  • route.ts: Replaces request.json() with safeParseBody, tightens the guard to typeof conversion_id !== \"string\" || !conversion_id.trim(), and adds .trim() to the SELECT .eq(\"id\", …) call.
  • route.test.ts (new): Adds two Vitest cases verifying that malformed JSON and object-typed conversion_id values both return 400 without touching affiliate_conversions, wallet lookups, or the internal transfer.

Confidence Score: 4/5

Safe to merge for the malformed-JSON fix itself; the trim mismatch between the SELECT and UPDATE on conversion_id (flagged in a prior review) is still unresolved and could leave a conversion charged but never marked paid.

The SELECT now uses conversion_id.trim() but the UPDATE at line 105 still uses the raw conversion_id. If a caller sends a conversion ID with leading/trailing whitespace the select finds the row, internalTransfer fires, but the update matches zero rows — the affiliate gets paid and the conversion record stays in an unpaid state.

src/app/api/affiliates/offers/[id]/conversions/pay/route.ts — the UPDATE query on line 105 needs the same .trim() applied to the SELECT on line 50.

Important Files Changed

Filename Overview
src/app/api/affiliates/offers/[id]/conversions/pay/route.ts Switches to safeParseBody and adds a string type guard; the SELECT query gains .trim() but the UPDATE at line 105 still uses the un-trimmed value — a whitespace mismatch flagged in a prior review that remains unaddressed.
src/app/api/affiliates/offers/[id]/conversions/pay/route.test.ts New regression test file; correctly mocks auth, Supabase, and Lightning helpers and verifies both malformed-JSON and non-string conversion_id inputs return 400 before touching downstream resources.

Sequence Diagram

sequenceDiagram
    participant Client
    participant Route as POST /conversions/pay
    participant DB as Supabase
    participant SafeParse as safeParseBody
    participant LN as Lightning

    Client->>Route: POST with body
    Route->>DB: Check affiliate_offers ownership
    DB-->>Route: offer or null
    alt not owner
        Route-->>Client: 403
    end
    Route->>SafeParse: parse request body
    SafeParse-->>Route: typed object or null
    alt malformed JSON or non-string conversion_id
        Route-->>Client: 400 conversion_id is required
    end
    Route->>DB: SELECT affiliate_conversions .eq(id.trim())
    DB-->>Route: conversion record
    alt not found or invalid status
        Route-->>Client: 404 or 400
    end
    Route->>DB: getUserLnWallet (seller and affiliate)
    Route->>LN: internalTransfer sats
    Route->>DB: UPDATE affiliate_conversions .eq(id)
    Route->>DB: INSERT wallet_transactions
    Route-->>Client: 200 ok
Loading

Reviews (4): Last reviewed commit: "Validate conversion payout id type" | Re-trigger Greptile

@ralyodio ralyodio closed this May 23, 2026
@ralyodio ralyodio reopened this May 23, 2026
Comment thread src/app/api/affiliates/offers/[id]/conversions/pay/route.ts Outdated
@ralyodio ralyodio closed this May 23, 2026
@ralyodio ralyodio reopened this May 23, 2026
@ralyodio ralyodio closed this May 23, 2026
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.

bug: affiliate conversion payout API returns 500 on malformed JSON

2 participants