UNPKG

@paroicms/server

Version:
170 lines (157 loc) 5.16 kB
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 `<!DOCTYPE html> <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