@paroicms/server
Version:
The ParoiCMS server
170 lines (157 loc) • 5.16 kB
JavaScript
import { ADMIN_TOKEN_COOKIE, PROTECTED_TOKEN_COOKIE, validateAdminUiToken, validateProtectedToken, } from "./protected-access-token.js";
export async function protectedSiteReqHandler(siteContext, httpContext) {
const { access: { access, password }, } = siteContext;
if (access === "public")
return false;
const adminUiToken = httpContext.req.cookies?.[ADMIN_TOKEN_COOKIE];
if (adminUiToken) {
if (await validateAdminUiToken(adminUiToken))
return false;
httpContext.res.clearCookie(ADMIN_TOKEN_COOKIE);
}
const protectedToken = httpContext.req.cookies?.[PROTECTED_TOKEN_COOKIE];
if (protectedToken && password) {
if (await validateProtectedToken(protectedToken, password))
return false;
httpContext.res.clearCookie(PROTECTED_TOKEN_COOKIE);
}
httpContext.res.status(401).send(renderPasswordForm());
return true;
}
function renderPasswordForm(errorMessage) {
return `
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Protected Access</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100dvh;
margin: 0;
background-color: #f5f5f5;
}
.container {
background-color: white;
padding: 2rem;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
width: 100%;
max-width: 360px;
}
.form-group {
margin-bottom: 1rem;
}
label {
display: block;
margin-bottom: 0.5rem;
font-weight: 500;
}
input[type="password"] {
width: 100%;
padding: 0.75rem;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 1rem;
box-sizing: border-box;
}
.checkbox-container {
display: flex;
align-items: center;
margin-top: 1rem;
}
.checkbox-container input {
margin-right: 0.5rem;
}
button {
background-color: #4a56e2;
color: white;
border: none;
padding: 0.75rem 1rem;
border-radius: 4px;
font-size: 1rem;
cursor: pointer;
width: 100%;
margin-top: 1rem;
}
button:hover {
background-color: #3a46d2;
}
.error-message {
color: #e53935;
margin-top: 1rem;
font-size: 0.875rem;
}
</style>
</head>
<body>
<div class="container">
<h2 style="text-align: center; margin-top: 0;">Protected Access</h2>
${errorMessage ? `<div class="error-message">${errorMessage}</div>` : ""}
<form id="password-form">
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" name="password" placeholder="Password" required>
</div>
<div class="checkbox-container">
<input type="checkbox" id="remember" name="remember">
<label for="remember">Remember the access on this device</label>
</div>
<button type="submit">Submit</button>
</form>
</div>
<script>
document.getElementById('password-form').addEventListener('submit', async (e) => {
e.preventDefault();
const password = document.getElementById('password').value;
const remember = document.getElementById('remember').checked;
try {
const response = await fetch('/api/v1/protected-access', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ password, remember })
});
const data = await response.json();
if (data.status === 200) {
// Access granted, reload the page
window.location.reload();
} else {
// Access denied
const errorMessage = document.createElement('div');
errorMessage.className = 'error-message';
errorMessage.textContent = 'Invalid password';
const existingError = document.querySelector('.error-message');
if (existingError) {
existingError.remove();
}
document.querySelector('.container').insertBefore(
errorMessage,
document.getElementById('password-form')
);
}
} catch (error) {
// Network or other error
const errorMessage = document.createElement('div');
errorMessage.className = 'error-message';
errorMessage.textContent = 'An error occurred: ' + error.message;
const existingError = document.querySelector('.error-message');
if (existingError) {
existingError.remove();
}
document.querySelector('.container').insertBefore(
errorMessage,
document.getElementById('password-form')
);
}
});
</script>
</body>
</html>`;
}
//# sourceMappingURL=protected-site.req-handler.js.map