From 245dcfb8155637ae6ba65a274193aaa77df24901 Mon Sep 17 00:00:00 2001 From: EDRipper Date: Fri, 12 Dec 2025 14:31:49 -0500 Subject: [PATCH] super evil commit --- backend/Gemfile | 1 + backend/Gemfile.lock | 4 +++ backend/config.ru | 11 ++++++ docker-compose.yml | 6 +++- src/lib/components/Navbar.svelte | 2 +- src/routes/+page.svelte | 2 +- src/routes/api/[...path]/+server.ts | 42 ++++++++++++++++++++++ src/routes/auth/[...path]/+server.ts | 52 ++++++++++++++++++++++++++++ 8 files changed, 117 insertions(+), 3 deletions(-) create mode 100644 src/routes/api/[...path]/+server.ts create mode 100644 src/routes/auth/[...path]/+server.ts diff --git a/backend/Gemfile b/backend/Gemfile index 40b8c5e..1c86c7a 100644 --- a/backend/Gemfile +++ b/backend/Gemfile @@ -17,6 +17,7 @@ gem 'rackup' gem 'puma', '~> 7.1' gem 'rack', '~> 3.2' +gem 'rack-cors' gem 'omniauth' gem 'omniauth_openid_connect' diff --git a/backend/Gemfile.lock b/backend/Gemfile.lock index fc33ae1..ce15d3d 100644 --- a/backend/Gemfile.lock +++ b/backend/Gemfile.lock @@ -140,6 +140,9 @@ GEM puma (7.1.0) nio4r (~> 2.0) rack (3.2.4) + rack-cors (3.0.0) + logger + rack (>= 3.0.14) rack-oauth2 (2.3.0) activesupport attr_required @@ -188,6 +191,7 @@ DEPENDENCIES omniauth_openid_connect puma (~> 7.1) rack (~> 3.2) + rack-cors rack-session rackup zeitwerk (~> 2.6) diff --git a/backend/config.ru b/backend/config.ru index 3878ebd..d0c1241 100644 --- a/backend/config.ru +++ b/backend/config.ru @@ -6,9 +6,20 @@ Dotenv.load require_relative 'boot' require 'grape' require 'rack/session' +require 'rack/cors' require 'omniauth' require 'omniauth_openid_connect' +use Rack::Cors do + allow do + origins ENV.fetch('FRONTEND_URL', 'http://localhost:5173') + resource '*', + headers: :any, + methods: [:get, :post, :put, :patch, :delete, :options, :head], + credentials: true + end +end + use Rack::Session::Cookie, key: 'stickers.session', secret: ENV.fetch('SESSION_SECRET'), diff --git a/docker-compose.yml b/docker-compose.yml index 393146e..0d1b3c7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,12 +9,16 @@ services: - OIDC_CLIENT_ID - OIDC_CLIENT_SECRET - OIDC_REDIRECT_URI + - FRONTEND_URL=https://kks08kkcg88ckkcocwooc4ck.a.selfhosted.hackclub.com + - AIRTABLE_BASE_ID + - AIRTABLE_PAT frontend: build: . ports: - "3000:3000" environment: - - ORIGIN=https://stickers.hackclub.com + - ORIGIN=https://kks08kkcg88ckkcocwooc4ck.a.selfhosted.hackclub.com + - BACKEND_URL=http://backend:9292 depends_on: - backend diff --git a/src/lib/components/Navbar.svelte b/src/lib/components/Navbar.svelte index 20898f2..221d1ec 100644 --- a/src/lib/components/Navbar.svelte +++ b/src/lib/components/Navbar.svelte @@ -41,7 +41,7 @@ |Trade (soon) --> Made with <3 by Nora and Euan diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index e487728..5fffa7a 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -4,7 +4,7 @@ import Logo from '$lib/assets/images/hackClubLogo.png'; function handleLogin() { - window.location.href = 'http://localhost:9292/auth/login'; + window.location.href = '/auth/login'; } diff --git a/src/routes/api/[...path]/+server.ts b/src/routes/api/[...path]/+server.ts new file mode 100644 index 0000000..41f4587 --- /dev/null +++ b/src/routes/api/[...path]/+server.ts @@ -0,0 +1,42 @@ +import { env } from '$env/dynamic/private'; + +const backend = env.BACKEND_URL || 'http://localhost:9292'; + +async function proxy({ request, params, cookies }: { request: Request; params: { path: string }; cookies: any }) { + const path = params.path || ''; + const url = new URL(request.url); + const targetUrl = `${backend}/${path}${url.search}`; + + const headers = new Headers(request.headers); + headers.delete('host'); + + const cookie = cookies.get('stickers.session'); + if (cookie) { + headers.set('cookie', `stickers.session=${cookie}`); + } + + const res = await fetch(targetUrl, { + method: request.method, + headers, + body: request.method !== 'GET' && request.method !== 'HEAD' ? await request.text() : undefined + }); + + const responseHeaders = new Headers(res.headers); + responseHeaders.delete('transfer-encoding'); + + const setCookie = res.headers.get('set-cookie'); + if (setCookie) { + responseHeaders.set('set-cookie', setCookie); + } + + return new Response(res.body, { + status: res.status, + headers: responseHeaders + }); +} + +export const GET = proxy; +export const POST = proxy; +export const PUT = proxy; +export const PATCH = proxy; +export const DELETE = proxy; diff --git a/src/routes/auth/[...path]/+server.ts b/src/routes/auth/[...path]/+server.ts new file mode 100644 index 0000000..7ab7a4c --- /dev/null +++ b/src/routes/auth/[...path]/+server.ts @@ -0,0 +1,52 @@ +import { env } from '$env/dynamic/private'; +import { redirect } from '@sveltejs/kit'; + +const backend = env.BACKEND_URL || 'http://localhost:9292'; + +async function proxy({ request, params, cookies }: { request: Request; params: { path: string }; cookies: any }) { + const path = params.path || ''; + const url = new URL(request.url); + const targetUrl = `${backend}/auth/${path}${url.search}`; + + const headers = new Headers(request.headers); + headers.delete('host'); + + const cookie = cookies.get('stickers.session'); + if (cookie) { + headers.set('cookie', `stickers.session=${cookie}`); + } + + const res = await fetch(targetUrl, { + method: request.method, + headers, + body: request.method !== 'GET' && request.method !== 'HEAD' ? await request.text() : undefined, + redirect: 'manual' + }); + + const setCookie = res.headers.get('set-cookie'); + if (setCookie) { + const match = setCookie.match(/stickers\.session=([^;]+)/); + if (match) { + cookies.set('stickers.session', match[1], { path: '/', httpOnly: true, sameSite: 'lax', maxAge: 86400 * 7 }); + } + } + + if (res.status >= 300 && res.status < 400) { + const location = res.headers.get('location'); + if (location) { + throw redirect(res.status as 301 | 302 | 303 | 307 | 308, location); + } + } + + const responseHeaders = new Headers(res.headers); + responseHeaders.delete('transfer-encoding'); + responseHeaders.delete('set-cookie'); + + return new Response(res.body, { + status: res.status, + headers: responseHeaders + }); +} + +export const GET = proxy; +export const POST = proxy;