UI updates and remove CSP for plugins
This commit is contained in:
@@ -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(() => {
|
||||||
|
|||||||
@@ -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%),
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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\/(.+)$/);
|
||||||
|
|||||||
Reference in New Issue
Block a user