mirror of
https://github.com/taogaetz/chefbible.git
synced 2025-12-06 11:47:24 -05:00
Add access PIN authentication and manage access cookies
- Introduced ACCESS_PIN in env.example for site access control. - Updated Locals interface to include hasAccess boolean for access management. - Implemented access check in hooks.server.ts to redirect users without access to the /access page. - Cleared access cookie on logout to ensure proper session management.
This commit is contained in:
parent
ec24b39d1a
commit
fe3f532a25
4
cookies.txt
Normal file
4
cookies.txt
Normal file
@ -0,0 +1,4 @@
|
||||
# Netscape HTTP Cookie File
|
||||
# https://curl.se/docs/http-cookies.html
|
||||
# This file was generated by libcurl! Edit at your own risk.
|
||||
|
||||
@ -8,5 +8,8 @@ ORIGIN=https://your-domain.com
|
||||
# Authentication token (required - generate a secure random token)
|
||||
MAGIC_LINK_TOKEN=your-secure-token-here
|
||||
|
||||
# Access PIN code (required - set a PIN for site access)
|
||||
ACCESS_PIN=1234
|
||||
|
||||
# Cloudinary URL for photo uploads (optional)
|
||||
CLOUDINARY_URL=cloudinary://api_key:api_secret@cloud_name
|
||||
|
||||
1
src/app.d.ts
vendored
1
src/app.d.ts
vendored
@ -8,6 +8,7 @@ declare global {
|
||||
// interface Platform {}
|
||||
interface Locals {
|
||||
authenticated: boolean;
|
||||
hasAccess: boolean;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,24 @@
|
||||
import type { Handle } from '@sveltejs/kit';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import { dev } from '$app/environment';
|
||||
|
||||
export const handle: Handle = async ({ event, resolve }) => {
|
||||
// Check if user has access (PIN code authentication)
|
||||
const accessCookie = event.cookies.get('access_granted');
|
||||
const hasAccess = !!accessCookie;
|
||||
|
||||
// If user doesn't have access and is not on the access page, redirect to /access
|
||||
if (!hasAccess && event.url.pathname !== '/access') {
|
||||
throw redirect(302, '/access');
|
||||
}
|
||||
|
||||
// Check if user is authenticated using the chef token cookie
|
||||
const chefToken = event.cookies.get('chef_token');
|
||||
const authenticated = !!chefToken;
|
||||
|
||||
// Add authentication status to locals for use in load functions
|
||||
event.locals.authenticated = authenticated;
|
||||
event.locals.hasAccess = hasAccess;
|
||||
|
||||
// Continue with the request
|
||||
const response = await resolve(event);
|
||||
|
||||
38
src/routes/access/+page.server.ts
Normal file
38
src/routes/access/+page.server.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import type { PageServerLoad, Actions } from './$types';
|
||||
import { fail, redirect } from '@sveltejs/kit';
|
||||
import { dev } from '$app/environment';
|
||||
|
||||
export const load: PageServerLoad = async ({ locals }) => {
|
||||
// If user already has access, redirect to home
|
||||
if (locals.hasAccess) {
|
||||
throw redirect(302, '/');
|
||||
}
|
||||
|
||||
return {};
|
||||
};
|
||||
|
||||
export const actions: Actions = {
|
||||
default: async ({ request, cookies }) => {
|
||||
const data = await request.formData();
|
||||
const pin = data.get('pin') as string;
|
||||
|
||||
if (!pin) {
|
||||
return fail(400, { error: 'PIN is required' });
|
||||
}
|
||||
|
||||
if (pin !== process.env.ACCESS_PIN) {
|
||||
return fail(400, { error: 'Invalid PIN' });
|
||||
}
|
||||
|
||||
// Set access cookie
|
||||
cookies.set('access_granted', 'true', {
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
secure: !dev,
|
||||
maxAge: 60 * 60 * 24 * 30 // 30 days
|
||||
});
|
||||
|
||||
throw redirect(302, '/');
|
||||
}
|
||||
};
|
||||
47
src/routes/access/+page.svelte
Normal file
47
src/routes/access/+page.svelte
Normal file
@ -0,0 +1,47 @@
|
||||
<script lang="ts">
|
||||
import { enhance } from '$app/forms';
|
||||
import type { ActionData } from './$types';
|
||||
|
||||
let { form, data }: { form: ActionData; data: any } = $props();
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Access Bible</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="flex min-h-screen items-center justify-center bg-base-200">
|
||||
<div class="card w-full max-w-md bg-base-100 shadow-xl">
|
||||
<div class="card-body">
|
||||
<div class="mb-6 text-center">
|
||||
<h1 class="text-2xl font-bold text-base-content">Access</h1>
|
||||
<p class="mt-2 text-base-content/70">Enter your access code to continue</p>
|
||||
</div>
|
||||
|
||||
<form method="POST" use:enhance>
|
||||
<div class="form-control">
|
||||
<label class="label" for="pin">
|
||||
<span class="label-text">Access Code</span>
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
id="pin"
|
||||
name="pin"
|
||||
class="input-bordered input w-full"
|
||||
placeholder="Enter access code"
|
||||
required
|
||||
autocomplete="off"
|
||||
/>
|
||||
{#if form?.error}
|
||||
<div class="label">
|
||||
<span class="label-text-alt text-error">{form.error}</span>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="form-control mt-6">
|
||||
<button type="submit" class="btn btn-primary"> Access Site </button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -20,6 +20,15 @@ export const POST: RequestHandler = async ({ cookies }) => {
|
||||
maxAge: 0 // Expire immediately
|
||||
});
|
||||
|
||||
// Clear the access cookie
|
||||
cookies.set('access_granted', '', {
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
secure: !dev,
|
||||
maxAge: 0 // Expire immediately
|
||||
});
|
||||
|
||||
// Redirect to home page
|
||||
throw redirect(302, '/');
|
||||
};
|
||||
@ -42,6 +51,15 @@ export const GET: RequestHandler = async ({ cookies }) => {
|
||||
maxAge: 0 // Expire immediately
|
||||
});
|
||||
|
||||
// Clear the access cookie
|
||||
cookies.set('access_granted', '', {
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
secure: !dev,
|
||||
maxAge: 0 // Expire immediately
|
||||
});
|
||||
|
||||
// Redirect to home page
|
||||
throw redirect(302, '/');
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user