UI updates and remove CSP for plugins

This commit is contained in:
KingKDot
2026-05-15 11:52:26 -05:00
parent da3bec8de1
commit 12972d6e8b
7 changed files with 86 additions and 63 deletions
+1
View File
@@ -68,6 +68,7 @@ plugins/build-toxi.bat
Overlord-Server/plugins/* Overlord-Server/plugins/*
plugins/toxi/* plugins/toxi/*
plugins/toxi copy/* plugins/toxi copy/*
plugins/extension/*
*.zip *.zip
@@ -124,7 +124,7 @@ if (typeof anime !== "undefined") {
form?.addEventListener("submit", async (e) => { form?.addEventListener("submit", async (e) => {
e.preventDefault(); e.preventDefault();
errEl.textContent = ""; errEl.textContent = "";
successEl.style.display = "none"; successEl.textContent = "";
if (newPass.value !== confirmPass.value) { if (newPass.value !== confirmPass.value) {
errEl.textContent = "New passwords do not match"; errEl.textContent = "New passwords do not match";
@@ -164,19 +164,14 @@ form?.addEventListener("submit", async (e) => {
sessionStorage.removeItem("temp_user"); sessionStorage.removeItem("temp_user");
successEl.textContent = "Password changed successfully! Redirecting..."; successEl.textContent = "Password changed successfully! Redirecting...";
successEl.style.opacity = "0";
successEl.style.display = "block";
if (typeof anime !== "undefined") { if (typeof anime !== "undefined") {
anime({ anime({
targets: successEl, targets: successEl,
opacity: [0, 1],
translateY: [-5, 0], translateY: [-5, 0],
duration: 400, duration: 400,
easing: "easeOutQuad", easing: "easeOutQuad",
}); });
} else {
successEl.style.opacity = "1";
} }
setTimeout(() => { setTimeout(() => {
+57 -4
View File
@@ -1478,21 +1478,74 @@ article.card[data-bookmarked="true"] {
.error { .error {
color: #ff9b9b; color: #ff9b9b;
min-height: 18px;
margin-top: 12px; margin-top: 12px;
font-size: 13px; font-size: 13px;
text-align: center; text-align: center;
padding: 8px; padding: 0;
border-radius: 8px; border-radius: 8px;
background: rgba(255, 99, 99, 0.1); background: transparent;
border: 1px solid rgba(255, 99, 99, 0.2); border: 1px solid transparent;
opacity: 0; opacity: 0;
transition:
opacity 220ms ease,
padding 220ms ease,
background-color 220ms ease,
border-color 220ms ease;
} }
.error:not(:empty) { .error:not(:empty) {
opacity: 1; opacity: 1;
padding: 8px 10px;
background: rgba(255, 99, 99, 0.1);
border-color: rgba(255, 99, 99, 0.22);
} }
.success {
color: #6ee7b7;
margin-top: 12px;
font-size: 13px;
text-align: center;
padding: 0;
border-radius: 8px;
background: transparent;
border: 1px solid transparent;
opacity: 0;
transition:
opacity 220ms ease,
padding 220ms ease,
background-color 220ms ease,
border-color 220ms ease;
}
.success:not(:empty) {
opacity: 1;
padding: 8px 10px;
background: rgba(16, 185, 129, 0.12);
border-color: rgba(16, 185, 129, 0.28);
}
.login-footer {
margin-top: 18px;
padding-top: 16px;
border-top: 1px solid rgba(255, 255, 255, 0.06);
text-align: center;
font-size: 13px;
color: var(--color-text-muted);
}
.login-footer a {
color: #c4b8ff;
text-decoration: none;
border-bottom: 1px solid rgba(196, 184, 255, 0.25);
transition: color 180ms ease, border-color 180ms ease;
}
.login-footer a:hover {
color: #e6dffe;
border-bottom-color: rgba(230, 223, 254, 0.7);
}
.console-body { .console-body {
background: background:
radial-gradient(120% 120% at 20% 20%, #102040 0%, transparent 45%), radial-gradient(120% 120% at 20% 20%, #102040 0%, transparent 45%),
+16 -31
View File
@@ -23,28 +23,23 @@
</div> </div>
<div class="login-card"> <div class="login-card">
<div class="login-crown-wrapper"> <div class="login-crown-wrapper">
<i <i class="fa-solid fa-shield-halved login-crown"></i>
class="fa-solid fa-shield-halved login-crown"
style="color: #f59e0b"
></i>
</div> </div>
<div class="brand login-brand" style="color: #f59e0b"> <div class="brand login-brand">Secure your account</div>
Password Change Required <h2 class="login-title">Set a new password</h2>
</div>
<h2 class="login-title">Change Default Password</h2>
<p class="muted login-subtitle"> <p class="muted login-subtitle">
For security reasons, you must change the default password before Choose a fresh password to replace the default before you continue.
continuing.
</p> </p>
<form id="change-password-form"> <form id="change-password-form">
<div class="form-group"> <div class="form-group">
<label class="label">Current Password</label> <label class="label">Current password</label>
<div class="input-row input-animated"> <div class="input-row input-animated">
<i class="fa-solid fa-lock"></i <i class="fa-solid fa-lock"></i
><input ><input
id="current-pass" id="current-pass"
name="current-pass" name="current-pass"
type="password" type="password"
autocomplete="current-password"
required required
placeholder="Enter current password" placeholder="Enter current password"
/> />
@@ -52,52 +47,42 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="label">New Password</label> <label class="label">New password</label>
<div class="input-row input-animated"> <div class="input-row input-animated">
<i class="fa-solid fa-key"></i <i class="fa-solid fa-key"></i
><input ><input
id="new-pass" id="new-pass"
name="new-pass" name="new-pass"
type="password" type="password"
autocomplete="new-password"
required required
placeholder="Enter new password (min 6 characters)" minlength="6"
placeholder="At least 6 characters"
/> />
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="label">Confirm New Password</label> <label class="label">Confirm new password</label>
<div class="input-row input-animated"> <div class="input-row input-animated">
<i class="fa-solid fa-key"></i <i class="fa-solid fa-key"></i
><input ><input
id="confirm-pass" id="confirm-pass"
name="confirm-pass" name="confirm-pass"
type="password" type="password"
autocomplete="new-password"
required required
placeholder="Confirm new password" placeholder="Re-enter new password"
/> />
</div> </div>
</div> </div>
<button type="submit" class="button primary full login-btn"> <button type="submit" class="button primary full login-btn">
<span class="btn-text">Change Password</span> <span class="btn-text">Update password</span>
<i class="fa-solid fa-check btn-icon"></i> <i class="fa-solid fa-arrow-right btn-icon"></i>
</button> </button>
<div id="error" class="error" aria-live="polite"></div> <div id="error" class="error" aria-live="polite"></div>
<div <div id="success" class="success" aria-live="polite"></div>
id="success"
class="success"
style="
color: #10b981;
margin-top: 12px;
text-align: center;
padding: 8px;
border-radius: 8px;
background: rgba(16, 185, 129, 0.1);
border: 1px solid rgba(16, 185, 129, 0.2);
"
aria-live="polite"
></div>
</form> </form>
</div> </div>
<script type="module" src="/assets/change-password.js"></script> <script type="module" src="/assets/change-password.js"></script>
+5 -8
View File
@@ -26,10 +26,8 @@
<i class="fa-solid fa-crown login-crown"></i> <i class="fa-solid fa-crown login-crown"></i>
</div> </div>
<div class="brand login-brand">Overlord</div> <div class="brand login-brand">Overlord</div>
<h2 class="login-title">Sign in</h2> <h2 class="login-title">Welcome back</h2>
<p class="muted login-subtitle"> <p class="muted login-subtitle">Sign in to your control plane</p>
Access your Overlord
</p>
<form id="login-form"> <form id="login-form">
<div class="form-group"> <div class="form-group">
<label class="label">Username</label> <label class="label">Username</label>
@@ -65,10 +63,9 @@
</button> </button>
<div id="error" class="error" aria-live="polite"></div> <div id="error" class="error" aria-live="polite"></div>
</form> </form>
<div id="register-link" style="text-align: center; margin-top: 1rem; display: none"> <div id="register-link" class="login-footer" style="display: none">
<a href="/register.html" class="muted" style="font-size: 0.85rem; text-decoration: underline" Don't have an account?
>Don't have an account? Register</a <a href="/register.html">Create one</a>
>
</div> </div>
</div> </div>
<script src="/assets/login.js"></script> <script src="/assets/login.js"></script>
-8
View File
@@ -7,14 +7,6 @@ export function secureHeaders(contentType?: string) {
}; };
} }
export function securePluginHeaders() {
return {
...SECURITY_HEADERS,
"X-Frame-Options": "SAMEORIGIN",
"Content-Security-Policy": "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self' wss: ws:; object-src 'none'; base-uri 'self'; frame-ancestors 'self'",
};
}
const MIME_TYPES: Record<string, string> = { const MIME_TYPES: Record<string, string> = {
".html": "text/html; charset=utf-8", ".html": "text/html; charset=utf-8",
".css": "text/css; charset=utf-8", ".css": "text/css; charset=utf-8",
@@ -1065,9 +1065,9 @@ export async function handlePluginRoutes(
return new Response(null, { status: 304 }); return new Response(null, { status: 304 });
} }
return new Response(injected, { const frameHeaders = { ...deps.secureHeaders("text/html; charset=utf-8"), "Cache-Control": "no-cache", ETag: etag };
headers: { ...deps.secureHeaders("text/html; charset=utf-8"), "Cache-Control": "no-cache", ETag: etag }, delete (frameHeaders as any)["Content-Security-Policy"];
}); return new Response(injected, { headers: frameHeaders });
} }
const pluginPageMatch = url.pathname.match(/^\/plugins\/([^/]+)$/); const pluginPageMatch = url.pathname.match(/^\/plugins\/([^/]+)$/);
@@ -1166,9 +1166,9 @@ export async function handlePluginRoutes(
</body> </body>
</html>`; </html>`;
return new Response(html, { const pageHeaders = { ...deps.secureHeaders("text/html; charset=utf-8"), "Cache-Control": "no-cache", ETag: etag };
headers: { ...deps.secureHeaders("text/html; charset=utf-8"), "Cache-Control": "no-cache", ETag: etag }, delete (pageHeaders as any)["Content-Security-Policy"];
}); return new Response(html, { headers: pageHeaders });
} }
const pluginAssetMatch = url.pathname.match(/^\/plugins\/([^/]+)\/assets\/(.+)$/); const pluginAssetMatch = url.pathname.match(/^\/plugins\/([^/]+)\/assets\/(.+)$/);