Compare commits

...
3 Commits
6 changed files with 119 additions and 26 deletions
+13
View File
@@ -1486,3 +1486,16 @@ body.dark-mode .admin-verification-content {
font-size: 12px;
}
/* ================================
IP BANS TABLE - compact rows
================================ */
#ip-bans-table td, #ip-bans-table th {
padding: 4px 8px;
line-height: 1.3;
font-size: 13px;
}
#ip-bans-table button {
padding: 2px 8px;
font-size: 12px;
}
+15
View File
@@ -435,6 +435,21 @@ WEB OF TRUST
<div id="add-ban-status" class="status-message"></div>
</div>
<!-- Whitelist Management -->
<div class="input-group">
<h3>IP Whitelist (Never Banned)</h3>
<p style="font-size:13px;opacity:0.8;">IPs in this list are never idle-banned. Comma-separated.</p>
<div class="form-group">
<label for="whitelist-ip-input">Add IP to Whitelist:</label>
<input type="text" id="whitelist-ip-input" placeholder="103.81.231.220">
</div>
<div class="inline-buttons">
<button type="button" id="add-whitelist-btn">ADD TO WHITELIST</button>
</div>
<div id="whitelist-status" class="status-message"></div>
<div id="whitelist-current" style="margin-top:8px;font-size:13px;"></div>
</div>
<!-- Filter Controls -->
<div class="input-group">
<div class="inline-buttons">
+86 -21
View File
@@ -5568,6 +5568,12 @@ function handleSqlQueryResponse(response) {
console.log('=== HANDLING SQL QUERY RESPONSE ===');
console.log('Response:', response);
// Route IP bans queries to the IP bans handler
if (response.query && response.query.includes('ip_bans')) {
handleIpBansResponse(response);
return;
}
// Always display SQL query results when received
displaySqlQueryResults(response);
@@ -6196,6 +6202,7 @@ function initializeRelayEvents() {
// ================================
let ipBansFilter = 'all'; // 'all', 'banned', 'expired'
let ipBansCachedResults = null; // Cache last fetched results for client-side filtering
// Load IP bans from database
async function loadIpBans() {
@@ -6222,7 +6229,9 @@ async function executeSqlQueryRaw(query, queryId) {
function handleIpBansResponse(responseData) {
// Convert rows+columns format to array of objects
let results = [];
if (responseData.rows && responseData.columns) {
if (responseData._cachedResults) {
results = responseData._cachedResults;
} else if (responseData.rows && responseData.columns) {
const cols = responseData.columns;
results = responseData.rows.map(row => {
const obj = {};
@@ -6267,6 +6276,9 @@ function handleIpBansResponse(responseData) {
document.getElementById('ip-bans-active').textContent = currentlyBanned;
document.getElementById('ip-bans-issued').textContent = totalBans;
// Cache results for client-side filtering
ipBansCachedResults = results;
// Get whitelist for display
const whitelistStr = (currentConfig && currentConfig.idle_ban_whitelist) || '';
const whitelistedIPs = new Set(whitelistStr.split(',').map(s => s.trim()).filter(s => s.length > 0));
@@ -6355,7 +6367,7 @@ async function deleteIpBan(ip) {
setTimeout(() => loadIpBans(), 500);
}
// Set filter and reload
// Set filter and re-render from cache (no re-fetch needed)
function setIpBansFilter(filter) {
ipBansFilter = filter;
@@ -6364,8 +6376,12 @@ function setIpBansFilter(filter) {
document.getElementById('ip-ban-filter-banned').classList.toggle('active', filter === 'banned');
document.getElementById('ip-ban-filter-expired').classList.toggle('active', filter === 'expired');
// Reload with new filter
loadIpBans();
// Re-render from cache if available, otherwise fetch
if (ipBansCachedResults !== null) {
handleIpBansResponse({ rows: null, columns: null, _cachedResults: ipBansCachedResults });
} else {
loadIpBans();
}
}
// Escape HTML to prevent XSS
@@ -6376,6 +6392,63 @@ function escapeHtml(text) {
return div.innerHTML;
}
// Add IP to whitelist
async function addToWhitelist() {
const input = document.getElementById('whitelist-ip-input');
const status = document.getElementById('whitelist-status');
const ip = input.value.trim();
if (!ip) { status.innerHTML = '<span style="color:red">Enter an IP address</span>'; return; }
// Get current whitelist from config
const current = (currentConfig && currentConfig.idle_ban_whitelist) || '';
const ips = current.split(',').map(s => s.trim()).filter(s => s.length > 0);
if (ips.includes(ip)) { status.innerHTML = '<span style="color:orange">Already whitelisted</span>'; return; }
ips.push(ip);
const newValue = ips.join(', ');
try {
await sendAdminCommand(['config_set', 'idle_ban_whitelist', newValue]);
status.innerHTML = `<span style="color:green">✅ ${ip} added to whitelist</span>`;
input.value = '';
updateWhitelistDisplay(newValue);
// Update local config cache
if (currentConfig) currentConfig.idle_ban_whitelist = newValue;
} catch (e) {
status.innerHTML = `<span style="color:red">Failed: ${e.message}</span>`;
}
}
// Update whitelist display
function updateWhitelistDisplay(whitelistStr) {
const div = document.getElementById('whitelist-current');
if (!div) return;
const ips = (whitelistStr || '').split(',').map(s => s.trim()).filter(s => s.length > 0);
if (ips.length === 0) {
div.innerHTML = '<em>No IPs whitelisted</em>';
} else {
div.innerHTML = 'Current whitelist: ' + ips.map(ip =>
`<span style="background:var(--accent-color,#ff0000);color:white;padding:1px 6px;border-radius:3px;margin:2px;display:inline-block">
${escapeHtml(ip)}
<button onclick="removeFromWhitelist('${escapeHtml(ip)}')" style="background:none;border:none;color:white;cursor:pointer;padding:0 0 0 4px;font-size:11px">✕</button>
</span>`
).join('');
}
}
// Remove IP from whitelist
async function removeFromWhitelist(ip) {
const current = (currentConfig && currentConfig.idle_ban_whitelist) || '';
const ips = current.split(',').map(s => s.trim()).filter(s => s.length > 0 && s !== ip);
const newValue = ips.join(', ');
try {
await sendAdminCommand(['config_set', 'idle_ban_whitelist', newValue]);
updateWhitelistDisplay(newValue);
if (currentConfig) currentConfig.idle_ban_whitelist = newValue;
} catch (e) {
log('Failed to remove from whitelist: ' + e.message, 'ERROR');
}
}
// Initialize IP Bans event listeners
function initIpBansEventListeners() {
const addBanBtn = document.getElementById('add-ban-btn');
@@ -6383,13 +6456,14 @@ function initIpBansEventListeners() {
const filterAllBtn = document.getElementById('ip-ban-filter-all');
const filterBannedBtn = document.getElementById('ip-ban-filter-banned');
const filterExpiredBtn = document.getElementById('ip-ban-filter-expired');
const addWhitelistBtn = document.getElementById('add-whitelist-btn');
if (addBanBtn) {
addBanBtn.addEventListener('click', banIp);
}
if (refreshBtn) {
refreshBtn.addEventListener('click', loadIpBans);
refreshBtn.addEventListener('click', () => { ipBansCachedResults = null; loadIpBans(); });
}
if (filterAllBtn) {
@@ -6404,24 +6478,15 @@ function initIpBansEventListeners() {
filterExpiredBtn.addEventListener('click', () => setIpBansFilter('expired'));
}
if (addWhitelistBtn) {
addWhitelistBtn.addEventListener('click', addToWhitelist);
}
// Show current whitelist on page load
updateWhitelistDisplay(currentConfig && currentConfig.idle_ban_whitelist);
console.log('IP Bans event listeners initialized');
}
// Handle SQL query responses for IP bans
const originalHandleSqlQueryResponse = handleSqlQueryResponse;
handleSqlQueryResponse = function(response) {
console.log('=== HANDLING SQL QUERY RESPONSE ===');
console.log('Response:', response);
// Check if this is an IP bans query
if (response.query_id && (response.query_id.startsWith('ip_ban') || response.query_id === 'ip_bans_load')) {
handleIpBansResponse(response);
return;
}
// Call original handler for other queries
return originalHandleSqlQueryResponse(response);
};
// Initialize when DOM is ready
document.addEventListener('DOMContentLoaded', initIpBansEventListeners);
+1 -1
View File
@@ -1 +1 @@
2375515
2380224
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -13,8 +13,8 @@
// Using CRELAY_ prefix to avoid conflicts with nostr_core_lib VERSION macros
#define CRELAY_VERSION_MAJOR 1
#define CRELAY_VERSION_MINOR 2
#define CRELAY_VERSION_PATCH 40
#define CRELAY_VERSION "v1.2.40"
#define CRELAY_VERSION_PATCH 43
#define CRELAY_VERSION "v1.2.43"
// Relay metadata (authoritative source for NIP-11 information)
#define RELAY_NAME "C-Relay"