| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| import { NextResponse } from 'next/server'; |
| import type { NextRequest } from 'next/server'; |
| import { verifySession, maybeRefreshSession, SESSION_COOKIE_NAME, SESSION_DURATION } from '@/lib/auth/session'; |
| import type { SessionData } from '@/lib/auth/session'; |
|
|
| async function nextWithRefreshedSession(session: SessionData): Promise<NextResponse> { |
| const response = NextResponse.next(); |
| const refreshed = await maybeRefreshSession(session); |
| if (refreshed) { |
| response.cookies.set(SESSION_COOKIE_NAME, refreshed, { |
| httpOnly: true, |
| secure: process.env.SECURE_COOKIES !== 'false' && process.env.NODE_ENV === 'production', |
| sameSite: 'lax', |
| maxAge: SESSION_DURATION / 1000, |
| path: '/', |
| }); |
| } |
| return response; |
| } |
|
|
| |
| const WORKSPACE_VIEWS = ['projects', 'dashboard', 'deployments', 'settings', 'skills', 'templates', 'docs']; |
|
|
| function loginRedirect(request: NextRequest): NextResponse { |
| const gatewayUrl = process.env.NEXT_PUBLIC_GATEWAY_URL; |
| if (gatewayUrl) return NextResponse.redirect(gatewayUrl + '/login'); |
| return NextResponse.redirect(new URL('/admin/login', request.url)); |
| } |
|
|
| export async function middleware(request: NextRequest) { |
| const isServerMode = process.env.NEXT_PUBLIC_SERVER_MODE === 'true'; |
| const { pathname } = request.nextUrl; |
| const isDesktop = process.env.OSW_DESKTOP === 'true'; |
|
|
| |
| if (isDesktop) { |
| |
| if (pathname.startsWith('/admin')) { |
| for (const view of WORKSPACE_VIEWS) { |
| if (pathname === `/admin/${view}` || pathname.startsWith(`/admin/${view}/`)) { |
| const workspaceId = request.cookies.get('osw_workspace')?.value; |
| if (workspaceId) { |
| const newPath = pathname.replace(`/admin/${view}`, `/w/${workspaceId}/${view}`); |
| return NextResponse.redirect(new URL(newPath + request.nextUrl.search, request.url)); |
| } |
| |
| return NextResponse.redirect(new URL('/', request.url)); |
| } |
| } |
| } |
| return NextResponse.next(); |
| } |
|
|
| |
| |
| |
| if (pathname.startsWith('/w/')) { |
| if (!isServerMode) { |
| return NextResponse.redirect(new URL('/', request.url)); |
| } |
|
|
| const token = request.cookies.get('osw_session')?.value; |
| if (!token) { |
| const response = loginRedirect(request); |
| |
| response.cookies.delete('osw_workspace'); |
| return response; |
| } |
|
|
| const session = await verifySession(token); |
| if (!session) { |
| const response = loginRedirect(request); |
| |
| response.cookies.delete('osw_session'); |
| response.cookies.delete('osw_workspace'); |
| return response; |
| } |
|
|
| return nextWithRefreshedSession(session); |
| } |
|
|
| |
| |
| |
| if (pathname.startsWith('/api/server-generate')) { |
| if (!isServerMode) { |
| return NextResponse.json({ error: 'Not available in Browser mode' }, { status: 404 }); |
| } |
|
|
| const token = request.cookies.get('osw_session')?.value; |
| if (!token) { |
| return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); |
| } |
| const session = await verifySession(token); |
| if (!session) { |
| return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); |
| } |
|
|
| return nextWithRefreshedSession(session); |
| } |
|
|
| |
| |
| |
| if (pathname.startsWith('/api/w/')) { |
| if (!isServerMode) { |
| return NextResponse.json({ error: 'Not available in Browser mode' }, { status: 404 }); |
| } |
|
|
| const token = request.cookies.get('osw_session')?.value; |
| if (!token) { |
| return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); |
| } |
| const session = await verifySession(token); |
| if (!session) { |
| return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); |
| } |
|
|
| return nextWithRefreshedSession(session); |
| } |
|
|
| |
| |
| |
| if (pathname.startsWith('/api/admin')) { |
| if (!isServerMode) { |
| return NextResponse.json({ error: 'Not available in Browser mode' }, { status: 404 }); |
| } |
| |
| const token = request.cookies.get('osw_session')?.value; |
| const apiKey = request.headers.get('x-instance-api-key'); |
| if (!token && !apiKey) { |
| return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); |
| } |
| if (token) { |
| const session = await verifySession(token); |
| if (!session) { |
| return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); |
| } |
| return nextWithRefreshedSession(session); |
| } |
| return NextResponse.next(); |
| } |
|
|
| |
| |
| |
| if (pathname.startsWith('/admin')) { |
| if (!isServerMode) { |
| return NextResponse.redirect(new URL('/', request.url)); |
| } |
|
|
| |
| const gatewayUrl = process.env.NEXT_PUBLIC_GATEWAY_URL; |
| if (gatewayUrl && (pathname === '/admin/login' || pathname === '/admin/register')) { |
| return NextResponse.redirect(gatewayUrl + '/login'); |
| } |
|
|
| |
| |
| if (pathname === '/admin/login' || pathname === '/admin/register') { |
| return NextResponse.next(); |
| } |
|
|
| const token = request.cookies.get('osw_session')?.value; |
| if (!token) return loginRedirect(request); |
|
|
| const session = await verifySession(token); |
| if (!session) return loginRedirect(request); |
|
|
| |
| if (!session.isAdmin && (pathname.startsWith('/admin/users') || pathname.startsWith('/admin/workspaces'))) { |
| |
| const workspaceId = request.cookies.get('osw_workspace')?.value; |
| if (workspaceId) { |
| return NextResponse.redirect(new URL(`/w/${workspaceId}/projects`, request.url)); |
| } |
| return loginRedirect(request); |
| } |
|
|
| |
| for (const view of WORKSPACE_VIEWS) { |
| if (pathname === `/admin/${view}` || pathname.startsWith(`/admin/${view}/`)) { |
| const workspaceId = request.cookies.get('osw_workspace')?.value; |
| if (workspaceId) { |
| const newPath = pathname.replace(`/admin/${view}`, `/w/${workspaceId}/${view}`); |
| return NextResponse.redirect(new URL(newPath + request.nextUrl.search, request.url)); |
| } |
| |
| return loginRedirect(request); |
| } |
| } |
|
|
| |
| if (pathname === '/admin' || pathname === '/admin/') { |
| const workspaceId = request.cookies.get('osw_workspace')?.value; |
| if (workspaceId) { |
| return NextResponse.redirect(new URL(`/w/${workspaceId}/projects`, request.url)); |
| } |
| return loginRedirect(request); |
| } |
|
|
| return nextWithRefreshedSession(session); |
| } |
|
|
| return NextResponse.next(); |
| } |
|
|
| export const config = { |
| matcher: [ |
| '/((?!_next/static|_next/image|favicon.ico|deployments/|health|api-docs|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)', |
| ], |
| }; |
|
|