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
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Supabase Configuration
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key-here

# Stripe Configuration
STANDARD_TIER_PRICE_ID=price_placeholder # must be real Stripe price ID in prod
STANDARD_TIER_CREDITS=8000
Expand Down
10 changes: 9 additions & 1 deletion app/auth/callback/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,15 @@ export async function GET(request: Request) {
}
)
const { error } = await supabase.auth.exchangeCodeForSession(code)
if (!error) {
if (error) {
console.error('[Auth Callback] Exchange code error:', {
message: error.message,
status: error.status,
name: error.name,
code: code?.substring(0, 10) + '...'
})
return NextResponse.redirect(`${origin}/auth/auth-code-error?error=${encodeURIComponent(error.message)}`)
} else {
Comment on lines 33 to +42
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error log includes a derived code value (first 10 chars). Even partial authorization codes are sensitive and can end up in centralized logs (and potentially be replayable depending on provider/settings). This increases blast radius during incident triage.

Also, redirecting with the raw error.message in the query string can leak internal/provider details to the browser history, analytics, and referrers. Consider using a generic user-facing message (and keep details server-side), or pass a short error key/correlation id instead.

Suggestion

Consider removing the auth code from logs entirely and avoid placing error.message in the redirect URL. Example:

if (error) {
  const errorId = crypto.randomUUID();
  console.error('[Auth Callback] exchangeCodeForSession failed', {
    errorId,
    message: error.message,
    status: error.status,
    name: error.name,
  });
  return NextResponse.redirect(`${origin}/auth/auth-code-error?errorId=${errorId}`);
}

Then have the error page display a generic message and optionally show errorId for support.

Reply with "@CharlieHelps yes please" if you'd like me to add a commit with this suggestion.

try {
const { data: { user }, error: userErr } = await supabase.auth.getUser()
if (!userErr && user) {
Expand Down
4 changes: 3 additions & 1 deletion bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions components/credits/purchase-credits-popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ export function PurchaseCreditsPopup() {
}, [user]);

const handleUpgrade = (tier: string) => {
// Placeholder for upgrade logic
// In a real app, this would likely redirect to Stripe Checkout
console.log(`Upgrading to ${tier}`);
// Redirect to Stripe checkout
const stripeUrl = 'https://buy.stripe.com/3cIaEX3tRcur9EM7ss';
window.open(stripeUrl, '_blank');
setIsOpen(false);
Comment on lines 52 to +56
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handleUpgrade ignores the tier parameter and uses a hard-coded Stripe URL. That makes the UI misleading (different tiers can’t map to different checkout sessions) and hard to change across environments.

Also, window.open(..., '_blank') without noopener,noreferrer enables reverse-tabnabbing. Some browsers mitigate this, but you shouldn’t rely on it.

Suggestion
  1. Remove the unused tier arg or actually use it to pick the correct destination.
  2. Prefer a same-tab navigation (window.location.assign) or set noopener,noreferrer.
  3. Avoid hard-coding: fetch a Checkout URL from your backend (creates a Stripe Checkout Session per user) or at least use an env var.

Example (minimal safer client-side change):

const handleUpgrade = () => {
  const stripeUrl = process.env.NEXT_PUBLIC_STRIPE_CHECKOUT_URL;
  if (!stripeUrl) return;
  window.open(stripeUrl, '_blank', 'noopener,noreferrer');
  setIsOpen(false);
};

Better: call /api/stripe/checkout to create a session and redirect to the returned URL.

Reply with "@CharlieHelps yes please" if you'd like me to add a commit with this suggestion.

}

const standardTier = TIER_CONFIGS[TIERS.STANDARD];
Expand Down
2 changes: 2 additions & 0 deletions components/history.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { History as HistoryIcon } from 'lucide-react'
import { ChatHistoryClient } from './sidebar/chat-history-client' // Updated import
import { Suspense } from 'react'
import { HistorySkeleton } from './history-skelton'
import { CreditsDisplay } from './credits/credits-display'

type HistoryProps = {
location: 'sidebar' | 'header'
Expand Down Expand Up @@ -39,6 +40,7 @@ export function History({ location }: HistoryProps) {
History
</SheetTitle>
</SheetHeader>
<CreditsDisplay className="mb-4" />
<div className="my-2 h-full pb-12 md:pb-10">
<Suspense fallback={<HistorySkeleton />}>
<ChatHistoryClient />
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
"remark-gfm": "^4.0.1",
"remark-math": "^6.0.0",
"sonner": "^1.7.4",
"stripe": "^20.2.0",
"supabase": "^2.66.0",
"tailwind-merge": "^2.6.0",
"tailwindcss-animate": "^1.0.7",
Expand Down