* feature(auth): replace clerk.com with custom auth * minor fixes * remove notification preferences * decrease live events interval fix(api): cookies.. # Conflicts: # .gitignore # apps/api/src/index.ts # apps/dashboard/src/app/providers.tsx # packages/trpc/src/trpc.ts
88 lines
2.4 KiB
TypeScript
88 lines
2.4 KiB
TypeScript
import { COOKIE_MAX_AGE, COOKIE_OPTIONS } from '@openpanel/auth/constants';
|
|
import { type NextRequest, NextResponse } from 'next/server';
|
|
|
|
function createRouteMatcher(patterns: string[]) {
|
|
// Convert route patterns to regex patterns
|
|
const regexPatterns = patterns.map((pattern) => {
|
|
// Replace route parameters (:id) with regex capture groups
|
|
const regexPattern = pattern
|
|
.replace(/\//g, '\\/') // Escape forward slashes
|
|
.replace(/:\w+/g, '([^/]+)') // Convert :param to capture groups
|
|
.replace(/\(\.\*\)\?/g, '(?:.*)?'); // Handle optional wildcards
|
|
|
|
return new RegExp(`^${regexPattern}$`);
|
|
});
|
|
|
|
// Return a matcher function
|
|
return (req: { url: string }) => {
|
|
const pathname = new URL(req.url).pathname;
|
|
return regexPatterns.some((regex) => regex.test(pathname));
|
|
};
|
|
}
|
|
|
|
// This example protects all routes including api/trpc routes
|
|
// Please edit this to allow other routes to be public as needed.
|
|
const isPublicRoute = createRouteMatcher([
|
|
'/share/overview/:id',
|
|
'/login(.*)?',
|
|
'/reset-password(.*)?',
|
|
'/register(.*)?',
|
|
'/sso-callback(.*)?',
|
|
'/onboarding',
|
|
]);
|
|
|
|
export default (request: NextRequest) => {
|
|
if (request.method === 'GET') {
|
|
const response = NextResponse.next();
|
|
const token = request.cookies.get('session')?.value ?? null;
|
|
|
|
if (!isPublicRoute(request) && token === null) {
|
|
return NextResponse.redirect(new URL('/login', request.url));
|
|
}
|
|
|
|
if (token !== null) {
|
|
// Only extend cookie expiration on GET requests since we can be sure
|
|
// a new session wasn't set when handling the request.
|
|
response.cookies.set('session', token, {
|
|
maxAge: COOKIE_MAX_AGE,
|
|
...COOKIE_OPTIONS,
|
|
});
|
|
}
|
|
return response;
|
|
}
|
|
|
|
const originHeader = request.headers.get('Origin');
|
|
// NOTE: You may need to use `X-Forwarded-Host` instead
|
|
const hostHeader = request.headers.get('Host');
|
|
if (originHeader === null || hostHeader === null) {
|
|
return new NextResponse(null, {
|
|
status: 403,
|
|
});
|
|
}
|
|
let origin: URL;
|
|
try {
|
|
origin = new URL(originHeader);
|
|
} catch {
|
|
return new NextResponse(null, {
|
|
status: 403,
|
|
});
|
|
}
|
|
if (origin.host !== hostHeader) {
|
|
return new NextResponse(null, {
|
|
status: 403,
|
|
});
|
|
}
|
|
|
|
return NextResponse.next();
|
|
};
|
|
|
|
export const config = {
|
|
matcher: [
|
|
'/((?!.+\\.[\\w]+$|_next).*)',
|
|
'/',
|
|
'/(api)(.*)',
|
|
'/(api|trpc)(.*)',
|
|
'/api/trpc(.*)',
|
|
],
|
|
};
|