135 lines
3.7 KiB
Plaintext
135 lines
3.7 KiB
Plaintext
---
|
|
import BaseLayout from '../layouts/BaseLayout.astro';
|
|
import { loadSiteData } from '../lib/site-data.ts';
|
|
|
|
const { siteContext } = loadSiteData();
|
|
|
|
const secret = import.meta.env.EDITOR_SESSION_SECRET || process.env.EDITOR_SESSION_SECRET || 'dev-secret';
|
|
const sessionCookie = Astro.cookies.get('editor_session')?.value;
|
|
let isAuthed = sessionCookie === secret;
|
|
|
|
if (!isAuthed && Astro.request.method === 'POST') {
|
|
const formData = await Astro.request.formData();
|
|
const password = formData.get('password') as string;
|
|
const editSecret = import.meta.env.API_EDIT_SECRET || process.env.API_EDIT_SECRET || '';
|
|
|
|
if (password === editSecret) {
|
|
Astro.cookies.set('editor_session', secret, {
|
|
httpOnly: true,
|
|
sameSite: 'strict',
|
|
maxAge: 8 * 60 * 60,
|
|
path: '/',
|
|
});
|
|
isAuthed = true;
|
|
}
|
|
}
|
|
|
|
const orchestratorUrl = import.meta.env.PUBLIC_ORCHESTRATOR_URL || process.env.PUBLIC_ORCHESTRATOR_URL || 'http://localhost:3001';
|
|
const apiSecret = import.meta.env.API_EDIT_SECRET || process.env.API_EDIT_SECRET || '';
|
|
---
|
|
<BaseLayout title={`Editor — ${siteContext.businessName}`} primaryColor={siteContext.primaryColor}>
|
|
<Fragment slot="logo">{siteContext.businessName}</Fragment>
|
|
<Fragment slot="tagline">Content Editor</Fragment>
|
|
|
|
{!isAuthed ? (
|
|
<section class="login-section">
|
|
<div class="container">
|
|
<div class="login-box">
|
|
<h2>Editor Login</h2>
|
|
<p>Enter the site edit password to continue.</p>
|
|
<form method="POST">
|
|
<input type="password" name="password" placeholder="Password" required />
|
|
<button type="submit">Log In</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
) : (
|
|
<section class="editor-section">
|
|
<div class="container">
|
|
<div id="editor-root"
|
|
data-orchestrator-url={orchestratorUrl}
|
|
data-api-secret={apiSecret}
|
|
></div>
|
|
</div>
|
|
</section>
|
|
)}
|
|
|
|
<Fragment slot="footer">
|
|
© {new Date().getFullYear()} {siteContext.businessName} · Editor
|
|
</Fragment>
|
|
</BaseLayout>
|
|
|
|
<style>
|
|
.login-section {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
min-height: 50vh;
|
|
}
|
|
.login-box {
|
|
max-width: 360px;
|
|
padding: 2rem;
|
|
background: white;
|
|
border: 1px solid var(--color-border);
|
|
border-radius: 8px;
|
|
text-align: center;
|
|
}
|
|
.login-box h2 {
|
|
font-family: var(--font-display);
|
|
font-size: 1.4rem;
|
|
color: var(--color-primary-dark);
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
.login-box p {
|
|
font-size: 0.9rem;
|
|
color: var(--color-text-muted);
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
.login-box input {
|
|
display: block;
|
|
width: 100%;
|
|
padding: 0.6rem 0.8rem;
|
|
border: 1px solid var(--color-border);
|
|
border-radius: 4px;
|
|
font-size: 0.95rem;
|
|
margin-bottom: 1rem;
|
|
font-family: var(--font-body);
|
|
}
|
|
.login-box button {
|
|
width: 100%;
|
|
padding: 0.65rem;
|
|
background: var(--color-primary);
|
|
color: white;
|
|
border: none;
|
|
border-radius: 4px;
|
|
font-size: 0.95rem;
|
|
cursor: pointer;
|
|
font-family: var(--font-body);
|
|
font-weight: 500;
|
|
}
|
|
.login-box button:hover {
|
|
background: var(--color-primary-dark);
|
|
}
|
|
.editor-section {
|
|
padding: 2rem 0;
|
|
}
|
|
</style>
|
|
|
|
{isAuthed && (
|
|
<script>
|
|
import { createElement } from 'react';
|
|
import { createRoot } from 'react-dom/client';
|
|
import { VisualEditorIsland } from '../components/editor/VisualEditorIsland';
|
|
|
|
const el = document.getElementById('editor-root');
|
|
if (el) {
|
|
const root = createRoot(el);
|
|
root.render(createElement(VisualEditorIsland, {
|
|
orchestratorUrl: el.dataset.orchestratorUrl || '',
|
|
apiSecret: el.dataset.apiSecret || '',
|
|
}));
|
|
}
|
|
</script>
|
|
)}
|