Implement basic auth on portal

This commit is contained in:
Dominic Ferrando
2026-06-30 00:24:48 -04:00
parent 9778c05bf0
commit 235c072421
12 changed files with 101 additions and 27 deletions
+1 -1
View File
@@ -18,5 +18,5 @@ export const env = {
WEBFLOW_AUTH: requireEnv("WEBFLOW_AUTH"),
WEBFLOW_WEBHOOK_SECRET: requireEnv("WEBFLOW_WEBHOOK_SECRET"),
NODE_ENV: optionEnv("NODE_ENV", "development"),
LOG_LEVEL: optionEnv("LOG_LEVEL", "info")
LOG_LEVEL: optionEnv("LOG_LEVEL", "info"),
};
+5 -2
View File
@@ -9,7 +9,7 @@ import {
PlayerSchema,
} from "@blade-and-brawn/domain"
import { cors } from "@elysiajs/cors";
import { Elysia, NotFoundError, status } from "elysia";
import { Elysia, NotFoundError, status, t } from "elysia";
import {
PrintfulClient,
PrintfulError,
@@ -133,6 +133,9 @@ export const app = new Elysia()
// TODO: protect with api key/token
.group("/products", (app) =>
app
.onBeforeHandle(({ }) => {
// authenticate cookie
})
.group("/sync", (app) =>
app
// Sync status
@@ -163,7 +166,7 @@ export const app = new Elysia()
return { printfulProduct, webflowProduct };
}, {
params: z.object({ printfulProductId: z.coerce.number() })
}),
})
)
// WEBHOOKS
+3 -3
View File
@@ -25,8 +25,8 @@
"@blade-and-brawn/commerce": "workspace:*",
"@blade-and-brawn/domain": "workspace:*",
"@elysia/eden": "^1.4.10",
"@tailwindcss/vite": "^4.3.1",
"daisyui": "^5.5.23",
"tailwindcss": "^4.3.1"
"@tailwindcss/vite": "^4.3.2",
"daisyui": "^5.6.6",
"tailwindcss": "^4.3.2"
}
}
+15
View File
@@ -0,0 +1,15 @@
import { env } from '$env/dynamic/private';
import { redirect, type Handle } from '@sveltejs/kit';
import { createHmac } from 'node:crypto';
export const handle: Handle = async ({ event, resolve }) => {
const cookieHash = event.cookies.get("session");
const computedHash = createHmac("sha256", env.PORTAL_SECRET)
.update("authenticated")
.digest("hex");
if (event.url.pathname !== "/login" && cookieHash !== computedHash)
redirect(307, "/login");
const response = await resolve(event);
return response;
};
@@ -1,7 +1,7 @@
<script lang="ts">
import { page } from "$app/state";
import favicon from "$lib/assets/favicon.svg";
import "./app.css";
import "../app.css";
const links = [
{ name: "Calculator", path: "/calculator" },
@@ -0,0 +1,21 @@
import { fail, redirect } from "@sveltejs/kit";
import type { Actions } from "./$types";
import { env } from "$env/dynamic/private";
import { createHmac } from "node:crypto";
export const actions: Actions = {
default: async ({ request, cookies }) => {
const data = await request.formData();
const password = data.get("password");
if (password !== env.PORTAL_PASSWORD)
return fail(401, { error: "Invalid password" });
const hash = createHmac("sha256", env.PORTAL_SECRET)
.update("authenticated")
.digest("hex");
cookies.set("session", hash, { path: "/", maxAge: 60 * 60 * 24 * 7 });
redirect(303, "/");
},
};
+35
View File
@@ -0,0 +1,35 @@
<script lang="ts">
import "../app.css";
import type { PageProps } from "./$types";
let { form }: PageProps = $props();
</script>
<div class="min-h-screen flex items-center justify-center bg-base-200">
<div class="card bg-base-100 w-full max-w-sm shadow-xl">
<div class="card-body gap-4">
{#if form?.error}
<div role="alert" class="alert alert-error">
<span>{form.error}</span>
</div>
{/if}
<form method="POST" class="flex flex-col gap-4">
<label class="floating-label">
<input
type="password"
name="password"
placeholder="Password"
class="input input-bordered w-full"
required
/>
<span>Password</span>
</label>
<button type="submit" class="btn btn-primary w-full">
Sign in
</button>
</form>
</div>
</div>
</div>