Skip to content
Open
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
9 changes: 7 additions & 2 deletions app/routes/app._index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,14 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
where: { shop: session.shop },
});

// If no settings or incomplete onboarding, redirect to onboarding
// If no settings or incomplete onboarding, redirect to onboarding with shop parameter
if (!settings || !settings.companyName || !settings.companyGSTIN) {
return redirect("/app/onboarding");
const url = new URL(request.url);
const searchParams = new URLSearchParams(url.search);
searchParams.set('shop', session.shop);

console.log("Redirecting to onboarding with shop parameter:", session.shop);
return redirect(`/app/onboarding?${searchParams.toString()}`);
}

// Get dashboard statistics
Expand Down
110 changes: 94 additions & 16 deletions app/routes/app.onboarding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,104 @@ import { validateGSTIN } from "../utils/gst.server";
import { INDIAN_STATES, validateGSTINFormat } from "../utils/gst.client";

export const loader = async ({ request }: LoaderFunctionArgs) => {
const { session } = await authenticate.admin(request);
console.log("Onboarding loader - URL:", request.url);

try {
const { session } = await authenticate.admin(request);
console.log("Onboarding loader - Authenticated shop:", session.shop);

// Check if onboarding is already completed
const settings = await prisma.appSettings.findUnique({
where: { shop: session.shop },
});
// Check if onboarding is already completed
const settings = await prisma.appSettings.findUnique({
where: { shop: session.shop },
});

if (settings && settings.companyName && settings.companyGSTIN) {
// Onboarding already completed, redirect to dashboard
return redirect("/app");
}
if (settings && settings.companyName && settings.companyGSTIN) {
// Onboarding already completed, redirect to dashboard
console.log("Onboarding already completed, redirecting to /app");
return redirect("/app");
}

const url = new URL(request.url);
const step = parseInt(url.searchParams.get("step") || "1");
const url = new URL(request.url);
const step = parseInt(url.searchParams.get("step") || "1");

return json({
shop: session.shop,
currentStep: Math.max(1, Math.min(4, step)),
settings: settings || null,
});
return json({
shop: session.shop,
currentStep: Math.max(1, Math.min(4, step)),
settings: settings || null,
});
} catch (error) {
console.log("Authentication failed in onboarding, attempting to preserve shop parameter");
console.log("Error details:", error);

// Extract shop parameter from the request URL
const url = new URL(request.url);
const shop = url.searchParams.get("shop");

console.log("Onboarding - URL params:", Object.fromEntries(url.searchParams));

if (shop) {
console.log("Found shop in URL params, redirecting to auth/login with shop:", shop);
return redirect(`/auth/login?shop=${encodeURIComponent(shop)}`);
}

// Try to extract shop from referer
const referer = request.headers.get("referer");
console.log("Onboarding - Referer:", referer);

if (referer) {
try {
const refererUrl = new URL(referer);
const shopFromReferer = refererUrl.searchParams.get("shop");

if (shopFromReferer) {
console.log("Found shop in referer params, redirecting to auth/login with shop:", shopFromReferer);
return redirect(`/auth/login?shop=${encodeURIComponent(shopFromReferer)}`);
}

// Try to extract from host parameter in referer
const hostParam = refererUrl.searchParams.get("host");
if (hostParam) {
try {
const decodedHost = atob(hostParam);
console.log("Decoded host:", decodedHost);
const hostMatch = decodedHost.match(/admin\.shopify\.com\/store\/([^\/]+)/);
if (hostMatch && hostMatch[1]) {
const shopFromHost = hostMatch[1];
console.log("Found shop in host parameter, redirecting to auth/login with shop:", shopFromHost);
return redirect(`/auth/login?shop=${encodeURIComponent(shopFromHost)}.myshopify.com`);
}
} catch (decodeError) {
console.log("Error decoding host parameter:", decodeError);
}
}

// Try to extract from referer domain
const shopFromDomain = referer.match(/https?:\/\/([^.]+)\.myshopify\.com/)?.[1];
if (shopFromDomain) {
console.log("Found shop in referer domain, redirecting:", shopFromDomain);
return redirect(`/auth/login?shop=${encodeURIComponent(shopFromDomain)}.myshopify.com`);
}

} catch (refererError) {
console.log("Error parsing referer URL:", refererError);
}
}

// Check for shop in cookies as fallback
const cookies = request.headers.get("cookie");
if (cookies) {
const shopCookie = cookies.match(/shop=([^;]+)/);
if (shopCookie && shopCookie[1]) {
const shopFromCookie = decodeURIComponent(shopCookie[1]);
console.log("Found shop in cookie, redirecting:", shopFromCookie);
return redirect(`/auth/login?shop=${encodeURIComponent(shopFromCookie)}`);
}
}

console.log("Could not determine shop from any source, re-throwing error");
// If we can't determine the shop, re-throw the original error
throw error;
}
};

export const action = async ({ request }: ActionFunctionArgs) => {
Expand Down
71 changes: 67 additions & 4 deletions app/routes/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,74 @@ import {
import { authenticate } from "../shopify.server";

export const loader = async ({ request }: LoaderFunctionArgs) => {
await authenticate.admin(request);
try {
await authenticate.admin(request);

return json({
apiKey: process.env.SHOPIFY_API_KEY || "",
});
return json({
apiKey: process.env.SHOPIFY_API_KEY || "",
});
} catch (error) {
console.log("Authentication failed in app route, preserving shop parameter");

// Extract shop parameter from the request URL
const url = new URL(request.url);
const shop = url.searchParams.get("shop");

if (shop) {
console.log("Redirecting to auth/login with shop:", shop);
throw new Response(null, {
status: 302,
headers: {
Location: `/auth/login?shop=${encodeURIComponent(shop)}`,
},
});
}

// Try to extract shop from referer
const referer = request.headers.get("referer");
if (referer) {
try {
const refererUrl = new URL(referer);
const shopFromReferer = refererUrl.searchParams.get("shop");

if (shopFromReferer) {
console.log("Redirecting to auth/login with shop from referer:", shopFromReferer);
throw new Response(null, {
status: 302,
headers: {
Location: `/auth/login?shop=${encodeURIComponent(shopFromReferer)}`,
},
});
}

// Try to extract from host parameter
const hostParam = refererUrl.searchParams.get("host");
if (hostParam) {
try {
const decodedHost = atob(hostParam);
const hostMatch = decodedHost.match(/admin\.shopify\.com\/store\/([^\/]+)/);
if (hostMatch && hostMatch[1]) {
const shopFromHost = hostMatch[1];
console.log("Redirecting to auth/login with shop from host:", shopFromHost);
throw new Response(null, {
status: 302,
headers: {
Location: `/auth/login?shop=${encodeURIComponent(shopFromHost)}.myshopify.com`,
},
});
}
} catch (decodeError) {
console.log("Error decoding host parameter:", decodeError);
}
}
} catch (refererError) {
console.log("Error parsing referer URL:", refererError);
}
}

// If we can't determine the shop, re-throw the original error
throw error;
}
};

export default function App() {
Expand Down
82 changes: 82 additions & 0 deletions app/routes/auth.login.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { LoaderFunctionArgs } from "@remix-run/node";
import { redirect } from "@remix-run/node";
import { login } from "../shopify.server";

export const loader = async ({ request }: LoaderFunctionArgs) => {
Expand All @@ -7,6 +8,87 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
console.log("Auth login - URL:", url.toString());
console.log("Auth login - All params:", Object.fromEntries(url.searchParams));

// Check if shop parameter is missing
const shop = url.searchParams.get("shop");
if (!shop) {
console.log("No shop parameter found, attempting to extract from referer");

// Try to extract shop from referer or other sources
const referer = request.headers.get("referer");
console.log("No shop parameter, referer:", referer);

if (referer) {
try {
// Try to extract shop from referer URL parameters
const refererUrl = new URL(referer);
const shopFromReferer = refererUrl.searchParams.get("shop");

if (shopFromReferer) {
console.log("Found shop in referer params, redirecting with shop:", shopFromReferer);
return redirect(`/auth/login?shop=${encodeURIComponent(shopFromReferer)}`);
}

// Try to extract from referer domain (for myshopify.com domains)
const shopFromDomain = referer.match(/https?:\/\/([^.]+)\.myshopify\.com/)?.[1];
if (shopFromDomain) {
console.log("Found shop in referer domain, redirecting:", shopFromDomain);
return redirect(`/auth/login?shop=${encodeURIComponent(shopFromDomain)}.myshopify.com`);
}

// Try to extract from embedded app context (admin.shopify.com)
const adminMatch = referer.match(/admin\.shopify\.com\/store\/([^\/\?]+)/);
if (adminMatch && adminMatch[1]) {
const shopFromAdmin = adminMatch[1];
console.log("Found shop in admin URL, redirecting:", shopFromAdmin);
return redirect(`/auth/login?shop=${encodeURIComponent(shopFromAdmin)}.myshopify.com`);
}

// Try to extract from host parameter in referer
const hostParam = refererUrl.searchParams.get("host");
if (hostParam) {
try {
const decodedHost = atob(hostParam);
const hostMatch = decodedHost.match(/admin\.shopify\.com\/store\/([^\/]+)/);
if (hostMatch && hostMatch[1]) {
const shopFromHost = hostMatch[1];
console.log("Found shop in host parameter, redirecting:", shopFromHost);
return redirect(`/auth/login?shop=${encodeURIComponent(shopFromHost)}.myshopify.com`);
}
} catch (error) {
console.log("Error decoding host parameter:", error);
}
}
} catch (error) {
console.log("Error parsing referer URL:", error);
}
}

// Check for shop in cookies as fallback
const cookies = request.headers.get("cookie");
if (cookies) {
const shopCookie = cookies.match(/shop=([^;]+)/);
if (shopCookie && shopCookie[1]) {
const shopFromCookie = decodeURIComponent(shopCookie[1]);
console.log("Found shop in cookie, redirecting:", shopFromCookie);
return redirect(`/auth/login?shop=${encodeURIComponent(shopFromCookie)}`);
}
}

// If we still can't find the shop, return a helpful error
console.log("Could not determine shop from any source");
throw new Response(
"Shop parameter is required for authentication. Please access this app through your Shopify admin panel.",
{
status: 400,
statusText: "Bad Request",
headers: {
"Content-Type": "text/plain"
}
}
);
}

console.log("Shop parameter found:", shop);
// The login function will handle shop parameter extraction and validation
throw await login(request);
};
37 changes: 37 additions & 0 deletions deploy-auth-fix.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/bin/bash

# Deploy authentication fix to server
echo "πŸš€ Deploying authentication fix to server..."

# Server details
SERVER="root@194.164.149.183"
APP_DIR="/var/www/invoiceo"

# Copy fixed files to server
echo "πŸ“ Copying fixed files to server..."
sshpass -p 'Kalilinux@2812' scp -o StrictHostKeyChecking=no app/routes/auth.login.tsx $SERVER:$APP_DIR/app/routes/auth.login.tsx
sshpass -p 'Kalilinux@2812' scp -o StrictHostKeyChecking=no app/routes/app.onboarding.tsx $SERVER:$APP_DIR/app/routes/app.onboarding.tsx
sshpass -p 'Kalilinux@2812' scp -o StrictHostKeyChecking=no app/routes/app.tsx $SERVER:$APP_DIR/app/routes/app.tsx

# Deploy on server
echo "πŸ”§ Building and restarting app on server..."
sshpass -p 'Kalilinux@2812' ssh -o StrictHostKeyChecking=no $SERVER << 'EOF'
cd /var/www/invoiceo
echo "Stopping app..."
pm2 stop gst-invoice-manager

echo "Building app..."
npm run build

echo "Starting app..."
pm2 start gst-invoice-manager

echo "Checking app status..."
pm2 status gst-invoice-manager

echo "Showing recent logs..."
pm2 logs gst-invoice-manager --lines 10
EOF

echo "βœ… Deployment complete!"
echo "πŸ”— Test your app at: https://invoiceo.indigenservices.com"