This commit is contained in:
NotII
2025-03-23 23:53:45 +00:00
parent edc220bc5d
commit 3413e3b1e8
8 changed files with 122 additions and 88 deletions

View File

@@ -11,9 +11,13 @@ export async function GET(req: NextRequest) {
// If not in headers, check cookies
if (!token) {
token = req.cookies.get('Authorization')?.value;
console.log('Auth check: Token from cookies');
console.log('Auth check: Token from cookies:', token ? `${token.substring(0, 10)}...` : 'none');
// Debug: List all cookies
const cookiesList = req.cookies.getAll();
console.log('Auth check: All cookies:', JSON.stringify(cookiesList.map(c => c.name)));
} else {
console.log('Auth check: Token from headers');
console.log('Auth check: Token from headers:', token.substring(0, 10) + '...');
}
if (!token) {

View File

@@ -0,0 +1,59 @@
import { NextRequest, NextResponse } from 'next/server';
// Force dynamic execution to ensure cookies are set at runtime
export const dynamic = 'force-dynamic';
export async function POST(req: NextRequest) {
try {
// Parse the request body to get the auth token
const body = await req.json();
const { token } = body;
if (!token) {
console.error('Set-cookie API: No token provided');
return NextResponse.json(
{ error: 'No token provided' },
{ status: 400 }
);
}
// Create a response object
const response = NextResponse.json(
{ success: true },
{ status: 200 }
);
// Set the token in an HTTP-only cookie that will be sent with requests
// The secure flag is conditionally set based on the environment
const isLocalhost = req.headers.get('host')?.includes('localhost') ||
req.headers.get('host')?.includes('127.0.0.1');
const cookieOptions = {
// HttpOnly for security - prevents JavaScript access
httpOnly: true,
// Valid for 7 days (same as the JWT)
maxAge: 7 * 24 * 60 * 60,
// Only send in requests to our domain
path: '/',
// Strict same-site policy to prevent CSRF
sameSite: 'strict' as const,
// Secure only in production environments
secure: !isLocalhost
};
// Set the cookie with the options
response.cookies.set('Authorization', token, cookieOptions);
console.log('Set-cookie API: Cookie set successfully');
return response;
} catch (error) {
console.error('Set-cookie API error:', error);
return NextResponse.json(
{
error: 'Failed to set cookie',
details: error instanceof Error ? error.message : String(error)
},
{ status: 500 }
);
}
}

View File

@@ -1,50 +0,0 @@
version: '3.8'
services:
traefik:
image: traefik:v2.5
container_name: traefik
command:
- "--api.insecure=true"
- "--log.level=DEBUG"
- "--accesslog"
- "--providers.docker=true"
- "--providers.docker.network=web"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.websecure.forwardedHeaders.trustedIPs=212.113.116.6,194.26.229.41,138.124.13.13,77.73.131.156" # Trust IPs for websecure
- "--entrypoints.web.forwardedHeaders.trustedIPs=212.113.116.6,194.26.229.41,138.124.13.13,77.73.131.156" # Trust IPs for web
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
networks:
- web
nextjs-app:
build:
context: .
dockerfile: Dockerfile
container_name: nextjs-app-container
expose:
- "3000"
labels:
- "traefik.enable=true"
- "traefik.http.routers.nextjs-app.rule=Host(`dash.embermarket.app`) || Host(`77.73.131.156`) || PathPrefix(`/`)"
- "traefik.http.services.nextjs-app.loadbalancer.server.port=3000"
- "traefik.http.routers.nextjs-app-https.rule=Host(`dash.embermarket.app`) || Host(`77.73.131.156`) || PathPrefix(`/`)"
- "traefik.http.middlewares.redirect-to-http.redirectscheme=http"
- "traefik.http.routers.nextjs-app-https.middlewares=redirect-to-http"
networks:
- web
environment:
- NODE_ENV=production
- NEXT_PUBLIC_API_URL=https://internal-api.inboxi.ng/api
restart: unless-stopped
networks:
web:
external: true

View File

@@ -27,24 +27,16 @@ export async function fetchClient<T>(
): Promise<T> {
const { method = 'GET', body, headers = {}, ...rest } = options;
// Get the base API URL from environment or fallback
const apiUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001';
// Ensure the endpoint starts with a slash
// Always use the Next.js API proxy by creating a path starting with /api/
// This ensures requests go through Next.js rewrites
const normalizedEndpoint = endpoint.startsWith('/') ? endpoint : `/${endpoint}`;
// For the specific case of internal-api.inboxi.ng - remove duplicate /api
// Construct the URL to always use the Next.js API routes
let url;
if (apiUrl.includes('internal-api.inboxi.ng')) {
// Special case for internal-api.inboxi.ng
if (normalizedEndpoint.startsWith('/api/')) {
url = `${apiUrl}${normalizedEndpoint.substring(4)}`; // Remove the /api part
} else {
url = `${apiUrl}${normalizedEndpoint}`;
}
if (normalizedEndpoint.startsWith('/api/')) {
url = normalizedEndpoint; // Already has /api/ prefix
} else {
// Normal case for other environments
url = `${apiUrl}${normalizedEndpoint}`;
url = `/api${normalizedEndpoint}`; // Add /api/ prefix
}
// Get auth token from cookies

View File

@@ -14,14 +14,16 @@ export async function clientFetch(url: string, options: RequestInit = {}): Promi
...options.headers,
};
// Ensure the url doesn't start with a slash if it's going to be appended to a URL that ends with one
const cleanUrl = url.startsWith('/') ? url.substring(1) : url;
const baseUrl = process.env.NEXT_PUBLIC_API_URL || '/api';
// Ensure there's only one slash between the base URL and endpoint
const fullUrl = baseUrl.endsWith('/')
? `${baseUrl}${cleanUrl}`
: `${baseUrl}/${cleanUrl}`;
// Always use the Next.js API proxy for consistent routing
// Format the URL to ensure it has the /api prefix
let fullUrl;
if (url.startsWith('/api/')) {
fullUrl = url; // Already has /api/ prefix
} else {
// Add /api prefix if not already present
const cleanUrl = url.startsWith('/') ? url : `/${url}`;
fullUrl = `/api${cleanUrl}`;
}
const res = await fetch(fullUrl, {
...options,

View File

@@ -91,7 +91,8 @@ export const updateProductStock = async (
authToken: string
) => {
try {
const url = `${process.env.NEXT_PUBLIC_API_URL}/stock/${productId}`;
// Use Next.js API proxy to ensure request goes through rewrites
const url = `/api/stock/${productId}`;
return await fetchData(url, {
method: "PUT",
headers: {

View File

@@ -29,10 +29,18 @@ export const apiRequest = async <T = any>(endpoint: string, method: string = "GE
options.body = JSON.stringify(body);
}
const API_URL = process.env.NEXT_PUBLIC_API_URL;
if (!API_URL) throw new Error("NEXT_PUBLIC_API_URL is not set in environment variables");
// Always use the Next.js API proxy to ensure all requests go through rewrites
// Format the endpoint to ensure it has the /api prefix
let url;
if (endpoint.startsWith('/api/')) {
url = endpoint; // Already has /api/ prefix
} else {
// Add /api prefix and ensure no duplicate slashes
const cleanEndpoint = endpoint.startsWith('/') ? endpoint : `/${endpoint}`;
url = `/api${cleanEndpoint}`;
}
const res = await fetchData(`${API_URL}${endpoint}`, options);
const res = await fetchData(url, options);
if (!res) {
const errorResponse = await res.json().catch(() => null);

View File

@@ -2,14 +2,28 @@ import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
export async function middleware(req: NextRequest) {
// Check for auth token in cookies
const token = req.cookies.get("Authorization")?.value;
if (!token) {
console.log("Middleware: No token found, redirecting to login...");
return NextResponse.redirect(new URL("/auth/login", req.url));
}
// Debug info about all cookies
const allCookies = req.cookies.getAll();
console.log("Middleware: All cookies:", allCookies.map(c => c.name).join(', '));
console.log("Middleware: Token found, validating...");
if (!token) {
// Try to get from Authorization header as fallback
const authHeader = req.headers.get('Authorization');
if (authHeader?.startsWith('Bearer ')) {
console.log("Middleware: Token found in Authorization header");
// Continue with validation using header auth
// The authCheckUrl will handle extracting the token from header
} else {
console.log("Middleware: No token found in cookies or headers, redirecting to login...");
return NextResponse.redirect(new URL("/auth/login", req.url));
}
} else {
console.log("Middleware: Token found in cookies, validating...");
}
try {
// Get the origin but handle localhost differently to avoid SSL issues
@@ -24,13 +38,17 @@ export async function middleware(req: NextRequest) {
console.log(`Using internal auth check URL: ${authCheckUrl}`);
// Clone headers to avoid modifying the original request
const headers = new Headers(req.headers);
// If token is in cookie, ensure it's also in Authorization header
if (token && !headers.has('Authorization')) {
headers.set('Authorization', `Bearer ${token}`);
}
const res = await fetch(authCheckUrl, {
method: "GET",
headers: {
"Content-Type": "application/json",
// Explicitly pass the token in headers as well
"Authorization": `Bearer ${token}`
},
headers,
credentials: 'include',
});