def about():
return {
"app": {
- "version": settings.APP_VERSION
+ "version": settings.APP_VERSION,
},
"baseimg": {
- "name": settings.BASEIMG_NAME,
- "version": settings.BASEIMG_VERSION
+ "name": settings.BASEIMG_NAME,
+ "version": settings.BASEIMG_VERSION,
},
"domain": settings.DOMAIN,
"admin_hash_loaded": settings.ADMIN_PASSWORD_HASH is not None,
# Create Router
router = APIRouter()
-# IP -> lista timestamp tentativi
+# IP -> lista timestamp tentativi
login_attempts = {}
def check_rate_limit(ip: str):
pwd = data.get("password")
if verify_login(user, pwd):
- # reset tentativi su IP
+ # reset tentativi su IP
login_attempts.pop(ip, None)
apply_session(response, username=user)
data-bs-toggle="modal" data-bs-target="#addHostModal">
<i class="bi bi-plus-lg"></i><span class="label"> Add Host</span>
</button>
- <button class="btn btn-primary" title="Reload DNS (BIND)" aria-label="Reload DNS"
+ <button class="btn btn-primary" title="Reload DNS (BIND)" aria-label="Reload DNS"
data-action="reloadDns">
<i class="bi bi-arrow-repeat"></i><span class="label"> Reload DNS</span>
</button>
- <button class="btn btn-primary" title="Reload DHCP (Kea)" aria-label="Reload DHCP"
+ <button class="btn btn-primary" title="Reload DHCP (Kea)" aria-label="Reload DHCP"
data-action="reloadDhcp">
<i class="bi bi-arrow-repeat"></i><span class="label"> Reload DHCP</span>
</button>
data-host-id="${id}">
<i class="bi bi-pencil-fill icon icon-action" aria-hidden="true"></i>
</span>
- <span class="action-icon"
+ <span class="action-icon"
role="button" tabindex="0"
title="Delete host" aria-label="Delete host"
aria-label="Delete host"
async function editHost(id) {
// Clear form first
clearAddHostForm();
-
+
try {
const res = await fetch(`/api/hosts/${id}`);
if (!res.ok) throw new Error(`Fetch failed for host ${id}: ${res.status}`);
if (!isValidMAC(hostData.mac)) {
showToast("Invalid MAC format", false);
return false;
- }
+ }
try {
if (editingHostId !== null) {
headers: { "Content-Type": "application/json" },
body: JSON.stringify(hostData)
});
- if (res.ok) {
+ if (res.ok) {
showToast("Host updated successfully");
} else {
throw new Error(`Update failed: ${res.status}`);
async delete(e, el) { handleDeleteHost(e, el); },
// edit is handled by bootstrap modal show event
- edit(e, el) {
+ edit(e, el) {
// no-op o log
},
document.addEventListener("keydown", (e) => {
// Ignore if focus is in a typing field
const tag = (e.target.tagName || "").toLowerCase();
- const isTypingField =
+ const isTypingField =
tag === "input" || tag === "textarea" || tag === "select" || e.target.isContentEditable;
if (e.key === "Escape" && !isTypingField) {
// check Add or Edit mode
const idAttr = lastTriggerEl?.getAttribute?.('data-host-id');
const id = idAttr ? Number(idAttr) : null;
-
- if (Number.isFinite(id)) {
+
+ if (Number.isFinite(id)) {
// Edit Mode
console.log("Modal in EDIT mode for host ID:", id);
try {
document.addEventListener('click', async (e) => {
const el = e.target.closest('[data-action]');
if (!el) return;
-
+
const action = el.dataset.action;
const handler = actionHandlers[action];
if (!handler) return;
const isEnter = e.key === 'Enter';
const isSpace = e.key === ' ' || e.key === 'Spacebar';
if (!isEnter && !isSpace) return;
-
+
const el = e.target.closest('[data-action]');
if (!el) return;
// Trigger click event
- el.click();
+ el.click();
});
}
});