name TEXT NOT NULL UNIQUE,
target TEXT NOT NULL,
note TEXT,
- ssl_enabled INTEGER NOT NULL DEFAULT 0
+ ssl_enabled INTEGER NOT NULL DEFAULT 0,
+ external_mode INTEGER NOT NULL DEFAULT 0,
+ last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
""")
cur.execute("CREATE INDEX idx_aliases_name ON aliases(name);")
logger.info("ALIASES DB: Database initialized successfully for %s", settings.DOMAIN)
- logger.info("ALIASES DB: Public IP: %s", settings.PUBLIC_IP)
+ logger.info("ALIASES DB: Public IP: %s", settings.EXTERNAL_NAME)
ipv6 TEXT,
mac TEXT,
note TEXT,
- ssl_enabled INTEGER NOT NULL DEFAULT 0
+ ssl_enabled INTEGER NOT NULL DEFAULT 0,
+ external_mode INTEGER NOT NULL DEFAULT 0,
+ last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
""")
cur.execute("CREATE INDEX idx_hosts_name ON hosts(name);")
<th data-type="string" data-sortable="true">Alias <span class="sort-arrow" aria-hidden="true"></span></th>
<th data-type="string" data-sortable="true">Target <span class="sort-arrow" aria-hidden="true"></span></th>
<th data-type="string" data-sortable="true">Note <span class="sort-arrow" aria-hidden="true"></span></th>
- <th data-type="string" data-sortable="true">SSL <span class="sort-arrow" aria-hidden="true"></span></th>
+ <th data-type="string" data-sortable="true">Options <span class="sort-arrow" aria-hidden="true"></span></th>
<th data-type="string" data-sortable="false">Actions <span class="sort-arrow" aria-hidden="true"></span></th>
</tr>
</thead>
.icon-static {
--icon-color-hover: var(--icon-color);
+ margin-right: 6px;
}
.icon-action {
cursor: pointer;
}
+.icon-placeholder {
+ opacity: 0;
+ pointer-events: none;
+}
+
/* ================================
Table
================================ */
<th data-type="ipv6" data-sortable="true">IPv6 <span class="sort-arrow" aria-hidden="true"></span></th>
<th data-type="mac" data-sortable="true">MAC <span class="sort-arrow" aria-hidden="true"></span></th>
<th data-type="string" data-sortable="true">Note <span class="sort-arrow" aria-hidden="true"></span></th>
- <th data-type="string" data-sortable="true">SSL <span class="sort-arrow" aria-hidden="true"></span></th>
+ <th data-type="string" data-sortable="true">Options <span class="sort-arrow" aria-hidden="true"></span></th>
<th data-type="string" data-sortable="false">Actions <span class="sort-arrow" aria-hidden="true"></span></th>
</tr>
</thead>
tr.appendChild(td);
}
- // SSL (icon)
+ // Options (icons)
{
const td = document.createElement("td");
+ td.style.textAlign = "center";
+ td.style.verticalAlign = "middle";
+
+ //
+ // SSL icon
+ //
const sslEnabled = !!h.ssl_enabled;
td.setAttribute("data-value", sslEnabled ? "true" : "false");
td.setAttribute("aria-label", sslEnabled ? "SSL attivo" : "SSL non attivo");
- td.style.textAlign = "center";
- td.style.verticalAlign = "middle";
+ const icon = document.createElement("i");
if (sslEnabled) {
- const icon = document.createElement("i");
icon.className = "bi bi-shield-lock-fill icon icon-static";
icon.setAttribute("aria-hidden", "true");
+ icon.setAttribute("title", "SSL certificate enabled");
+ } else {
+ icon.className = "bi bi-shield-lock-fill icon icon-static icon-placeholder";
+ icon.setAttribute("aria-hidden", "true");
+ }
+ td.appendChild(icon);
+
+ //
+ // external_mode icon
+ //
+ const ext = (h.external_mode ?? "").toString();
+ let aria = "";
+ let iconClass = "";
+ switch (ext) {
+ case "0":
+ // Only local (CNAME record internally resolved)
+ aria = "Only local (CNAME record internally resolved)";
+ iconClass = "bi bi-hdd-network";
+ break;
+
+ case "1":
+ // Local and external (CNAME record internally resolved, CNAME externally)
+ aria = "Internal and external are identical";
+ iconClass = "bi bi-globe2";
+ break;
+
+ case "2":
+ // CNAME -> DDNS / external_name
+ aria = "External is a CNAME to external_name";
+ iconClass = "bi bi-link-45deg";
+ break;
+ }
+ if (iconClass) {
+ const icon = document.createElement("i");
+ icon.className = iconClass + " icon icon-static";
+ icon.setAttribute("aria-hidden", "true");
+ icon.setAttribute("title", aria);
td.appendChild(icon);
}
+
tr.appendChild(td);
}
- // Actions
- {
- const td = document.createElement("td");
- td.className = "actions";
- td.style.textAlign = "center";
- td.style.verticalAlign = "middle";
-
- const id = Number(h.id);
-
- // Usa elementi reali invece di innerHTML con entity
- const editSpan = document.createElement("span");
- editSpan.className = "action-icon";
- editSpan.setAttribute("role", "button");
- editSpan.tabIndex = 0;
- editSpan.title = "Edit alias";
- editSpan.setAttribute("aria-label", "Edit alias");
- editSpan.setAttribute("data-bs-toggle", "modal");
- editSpan.setAttribute("data-bs-target", "#addAliasModal");
- editSpan.setAttribute("data-action", "edit");
- editSpan.setAttribute("data-alias-id", String(id));
+ // Actions
{
- const i = document.createElement("i");
- i.className = "bi bi-pencil-fill icon icon-action";
- i.setAttribute("aria-hidden", "true");
- editSpan.appendChild(i);
- }
+ const td = document.createElement("td");
+ td.className = "actions";
+ td.style.textAlign = "center";
+ td.style.verticalAlign = "middle";
- const delSpan = document.createElement("span");
- delSpan.className = "action-icon";
- delSpan.setAttribute("role", "button");
- delSpan.tabIndex = 0;
- delSpan.title = "Delete alias";
- delSpan.setAttribute("aria-label", "Delete alias");
- delSpan.setAttribute("data-action", "delete");
- delSpan.setAttribute("data-alias-id", String(id));
- {
- const i = document.createElement("i");
- i.className = "bi bi-trash-fill icon icon-action";
- i.setAttribute("aria-hidden", "true");
- delSpan.appendChild(i);
- }
+ const id = Number(h.id);
+
+ // Usa elementi reali invece di innerHTML con entity
+ const editSpan = document.createElement("span");
+ editSpan.className = "action-icon";
+ editSpan.setAttribute("role", "button");
+ editSpan.tabIndex = 0;
+ editSpan.title = "Edit alias";
+ editSpan.setAttribute("aria-label", "Edit alias");
+ editSpan.setAttribute("data-bs-toggle", "modal");
+ editSpan.setAttribute("data-bs-target", "#addAliasModal");
+ editSpan.setAttribute("data-action", "edit");
+ editSpan.setAttribute("data-alias-id", String(id));
+ {
+ const i = document.createElement("i");
+ i.className = "bi bi-pencil-fill icon icon-action";
+ i.setAttribute("aria-hidden", "true");
+ editSpan.appendChild(i);
+ }
- td.appendChild(editSpan);
- td.appendChild(delSpan);
- tr.appendChild(td);
- }
+ const delSpan = document.createElement("span");
+ delSpan.className = "action-icon";
+ delSpan.setAttribute("role", "button");
+ delSpan.tabIndex = 0;
+ delSpan.title = "Delete alias";
+ delSpan.setAttribute("aria-label", "Delete alias");
+ delSpan.setAttribute("data-action", "delete");
+ delSpan.setAttribute("data-alias-id", String(id));
+ {
+ const i = document.createElement("i");
+ i.className = "bi bi-trash-fill icon icon-action";
+ i.setAttribute("aria-hidden", "true");
+ delSpan.appendChild(i);
+ }
+
+ td.appendChild(editSpan);
+ td.appendChild(delSpan);
+ tr.appendChild(td);
+ }
- frag.appendChild(tr);
+ frag.appendChild(tr);
});
// publish all rows
tr.appendChild(td);
}
- // SSL (icon)
+ // Options (icons)
{
const td = document.createElement("td");
+ td.style.textAlign = "center";
+ td.style.verticalAlign = "middle";
+
+ //
+ // SSL icon
+ //
const sslEnabled = !!h.ssl_enabled;
td.setAttribute("data-value", sslEnabled ? "true" : "false");
td.setAttribute("aria-label", sslEnabled ? "SSL attivo" : "SSL non attivo");
- td.style.textAlign = "center";
- td.style.verticalAlign = "middle";
+ const icon = document.createElement("i");
if (sslEnabled) {
- const icon = document.createElement("i");
icon.className = "bi bi-shield-lock-fill icon icon-static";
icon.setAttribute("aria-hidden", "true");
+ icon.setAttribute("title", "SSL certificate enabled");
+ } else {
+ icon.className = "bi bi-shield-lock-fill icon icon-static icon-placeholder";
+ icon.setAttribute("aria-hidden", "true");
+ }
+ td.appendChild(icon);
+
+ //
+ // external_mode icon
+ //
+ const ext = (h.external_mode ?? "").toString();
+ let aria = "";
+ let iconClass = "";
+ switch (ext) {
+ case "0":
+ // Only local (A record internally resolved)
+ aria = "Only local (A record internally resolved)";
+ iconClass = "bi bi-hdd-network";
+ break;
+
+ case "1":
+ // Local and external (A record internally resolved, A externally)
+ aria = "Internal and external are identical";
+ iconClass = "bi bi-globe2";
+ break;
+
+ case "2":
+ // CNAME -> DDNS / external_name
+ aria = "External is a CNAME to external_name";
+ iconClass = "bi bi-link-45deg";
+ break;
+ }
+ if (iconClass) {
+ const icon = document.createElement("i");
+ icon.className = iconClass + " icon icon-static";
+ icon.setAttribute("aria-hidden", "true");
+ icon.setAttribute("title", aria);
td.appendChild(icon);
}
+
tr.appendChild(td);
}
- // Actions
- {
- const td = document.createElement("td");
- td.className = "actions";
- td.style.textAlign = "center";
- td.style.verticalAlign = "middle";
-
- const id = Number(h.id);
-
- // Usa elementi reali invece di innerHTML con entity
- const editSpan = document.createElement("span");
- editSpan.className = "action-icon";
- editSpan.setAttribute("role", "button");
- editSpan.tabIndex = 0;
- editSpan.title = "Edit host";
- editSpan.setAttribute("aria-label", "Edit host");
- editSpan.setAttribute("data-bs-toggle", "modal");
- editSpan.setAttribute("data-bs-target", "#addHostModal");
- editSpan.setAttribute("data-action", "edit");
- editSpan.setAttribute("data-host-id", String(id));
+ // Actions
{
- const i = document.createElement("i");
- i.className = "bi bi-pencil-fill icon icon-action";
- i.setAttribute("aria-hidden", "true");
- editSpan.appendChild(i);
- }
+ const td = document.createElement("td");
+ td.className = "actions";
+ td.style.textAlign = "center";
+ td.style.verticalAlign = "middle";
- const delSpan = document.createElement("span");
- delSpan.className = "action-icon";
- delSpan.setAttribute("role", "button");
- delSpan.tabIndex = 0;
- delSpan.title = "Delete host";
- delSpan.setAttribute("aria-label", "Delete host");
- delSpan.setAttribute("data-action", "delete");
- delSpan.setAttribute("data-host-id", String(id));
- {
- const i = document.createElement("i");
- i.className = "bi bi-trash-fill icon icon-action";
- i.setAttribute("aria-hidden", "true");
- delSpan.appendChild(i);
- }
+ const id = Number(h.id);
+
+ // Usa elementi reali invece di innerHTML con entity
+ const editSpan = document.createElement("span");
+ editSpan.className = "action-icon";
+ editSpan.setAttribute("role", "button");
+ editSpan.tabIndex = 0;
+ editSpan.title = "Edit host";
+ editSpan.setAttribute("aria-label", "Edit host");
+ editSpan.setAttribute("data-bs-toggle", "modal");
+ editSpan.setAttribute("data-bs-target", "#addHostModal");
+ editSpan.setAttribute("data-action", "edit");
+ editSpan.setAttribute("data-host-id", String(id));
+ {
+ const i = document.createElement("i");
+ i.className = "bi bi-pencil-fill icon icon-action";
+ i.setAttribute("aria-hidden", "true");
+ editSpan.appendChild(i);
+ }
- td.appendChild(editSpan);
- td.appendChild(delSpan);
- tr.appendChild(td);
- }
+ const delSpan = document.createElement("span");
+ delSpan.className = "action-icon";
+ delSpan.setAttribute("role", "button");
+ delSpan.tabIndex = 0;
+ delSpan.title = "Delete host";
+ delSpan.setAttribute("aria-label", "Delete host");
+ delSpan.setAttribute("data-action", "delete");
+ delSpan.setAttribute("data-host-id", String(id));
+ {
+ const i = document.createElement("i");
+ i.className = "bi bi-trash-fill icon icon-action";
+ i.setAttribute("aria-hidden", "true");
+ delSpan.appendChild(i);
+ }
+
+ td.appendChild(editSpan);
+ td.appendChild(delSpan);
+ tr.appendChild(td);
+ }
- frag.appendChild(tr);
+ frag.appendChild(tr);
});
// publish all rows