v0.3.19 - last save before major refactoring

This commit is contained in:
Your Name
2025-09-30 10:47:11 -04:00
parent eefb0e427e
commit c1a6e92b1d
4 changed files with 207 additions and 229 deletions

View File

@@ -184,7 +184,7 @@
padding: 8px;
text-align: left;
font-family: var(--font-family);
font-size: 10px;
font-size: 10px;
}
.config-table-container {
@@ -509,7 +509,7 @@
<label for="relay-pubkey-manual">Relay Pubkey (if not available via NIP-11):</label>
<input type="text" id="relay-pubkey-manual" placeholder="64-character hex pubkey"
pattern="[0-9a-fA-F]{64}" title="64-character hexadecimal public key">
<small>If the relay hasn't been configured yet, enter the relay pubkey shown during startup</small>
</div>
<div class="inline-buttons">
@@ -546,116 +546,101 @@
<!-- Testing Section -->
<div id="div_config" class="section flex-section">
<div id="config-display" class="hidden">
<div id="config-view-mode">
<div class="config-table-container">
<table class="config-table" id="config-table">
<thead>
<tr>
<th>Parameter</th>
<th>Value</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="config-table-body">
</tbody>
</table>
</div>
<div class="inline-buttons">
<button type="button" id="fetch-config-btn">REFRESH</button>
<button type="button" id="edit-config-btn">EDIT CONFIGURATION</button>
<button type="button" id="copy-config-btn">COPY CONFIGURATION</button>
</div>
<!-- Testing Section -->
<div id="div_config" class="section flex-section">
<h2>RELAY CONFIGURATION</h2>
<div id="config-display" class="hidden">
<div id="config-view-mode">
<div class="config-table-container">
<table class="config-table" id="config-table">
<thead>
<tr>
<th>Parameter</th>
<th>Value</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="config-table-body">
</tbody>
</table>
</div>
<div id="config-edit-mode" class="hidden">
<h3>Edit Configuration</h3>
<div id="config-form" class="section">
<!-- Dynamic form will be generated here -->
</div>
<div class="inline-buttons">
<button type="button" id="save-config-btn">SAVE & PUBLISH</button>
<button type="button" id="cancel-edit-btn">CANCEL</button>
</div>
</div>
</div>
</div>
<!-- Auth Rules Management - Moved after configuration -->
<div class="section flex-section" id="authRulesSection" style="display: none;">
<div class="section-header">
<h2>AUTH RULES MANAGEMENT</h2>
<div class="status" id="authRulesStatus"></div>
</div>
<div class="auth-rules-controls">
<div class="inline-buttons">
<button id="viewAuthRulesBtn" class="btn">VIEW RULES</button>
<button id="refreshAuthRulesBtn" class="btn">REFRESH</button>
<button type="button" id="edit-config-btn">EDIT CONFIGURATION</button>
<button type="button" id="copy-config-btn">COPY CONFIGURATION</button>
<button type="button" id="fetch-config-btn">REFRESH</button>
</div>
</div>
<!-- Auth Rules Table -->
<div id="authRulesTableContainer" style="display: none;">
<table class="config-table" id="authRulesTable">
<thead>
<tr>
<th>Rule Type</th>
<th>Pattern Type</th>
<th>Pattern Value</th>
<th>Action</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="authRulesTableBody">
</tbody>
</table>
</div>
<!-- Simplified Auth Rule Input Section -->
<div id="authRuleInputSections" style="display: block;">
<!-- Combined Pubkey Auth Rule Section -->
<div class="auth-rule-section">
<h3>MANAGE PUBKEY ACCESS</h3>
<p>Add pubkeys to whitelist (allow) or blacklist (deny) access</p>
<div class="input-group">
<label for="authRulePubkey">Pubkey (nsec or hex):</label>
<input type="text" id="authRulePubkey" placeholder="nsec1... or 64-character hex pubkey">
<small id="authRuleHelp">Enter nsec (will auto-convert) or 64-character hex pubkey</small>
</div>
<div id="whitelistWarning" class="warning-box" style="display: none;">
<strong>⚠️ WARNING:</strong> Adding whitelist rules changes relay behavior to whitelist-only
mode.
Only whitelisted users will be able to interact with the relay.
</div>
<div class="inline-buttons">
<button type="button" id="addWhitelistBtn" onclick="addWhitelistRule()">ADD TO
WHITELIST</button>
<button type="button" id="addBlacklistBtn" onclick="addBlacklistRule()">ADD TO
BLACKLIST</button>
</div>
<div id="authRuleStatus" class="rule-status"></div>
<div id="config-edit-mode" class="hidden">
<h3>Edit Configuration</h3>
<div id="config-form" class="section">
<!-- Dynamic form will be generated here -->
</div>
</div>
<!-- Auth Rules Status Display -->
<div id="authRulesStatusDisplay" style="display: none;">
<h3>Auth System Status</h3>
<div class="status" id="authSystemStatus">CHECKING...</div>
<div class="json-display" id="authRulesCount">
Rules: Loading...
<div class="inline-buttons">
<button type="button" id="save-config-btn">SAVE & PUBLISH</button>
<button type="button" id="cancel-edit-btn">CANCEL</button>
</div>
</div>
</div>
</div>
<!-- Auth Rules Management - Moved after configuration -->
<div class="section flex-section" id="authRulesSection" style="display: none;">
<div class="section-header">
<h2>AUTH RULES MANAGEMENT</h2>
</div>
<!-- Auth Rules Table -->
<div id="authRulesTableContainer" style="display: none;">
<table class="config-table" id="authRulesTable">
<thead>
<tr>
<th>Rule Type</th>
<th>Pattern Type</th>
<th>Pattern Value</th>
<th>Action</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="authRulesTableBody">
</tbody>
</table>
</div>
<!-- Simplified Auth Rule Input Section -->
<div id="authRuleInputSections" style="display: block;">
<!-- Combined Pubkey Auth Rule Section -->
<div class="auth-rule-section">
<h3>MANAGE PUBKEY ACCESS</h3>
<p>Add pubkeys to whitelist (allow) or blacklist (deny) access</p>
<div class="input-group">
<label for="authRulePubkey">Pubkey (nsec or hex):</label>
<input type="text" id="authRulePubkey" placeholder="nsec1... or 64-character hex pubkey">
<small id="authRuleHelp">Enter nsec (will auto-convert) or 64-character hex pubkey</small>
</div>
<div id="whitelistWarning" class="warning-box" style="display: none;">
<strong>⚠️ WARNING:</strong> Adding whitelist rules changes relay behavior to whitelist-only
mode.
Only whitelisted users will be able to interact with the relay.
</div>
<div class="inline-buttons">
<button type="button" id="addWhitelistBtn" onclick="addWhitelistRule()">ADD TO
WHITELIST</button>
<button type="button" id="addBlacklistBtn" onclick="addBlacklistRule()">ADD TO
BLACKLIST</button>
<button type="button" id="refreshAuthRulesBtn">REFRESH</button>
</div>
</div>
</div>
</div>
@@ -766,7 +751,6 @@
const persistentUserPubkey = document.getElementById('persistent-user-pubkey');
const persistentUserAbout = document.getElementById('persistent-user-about');
const persistentUserDetails = document.getElementById('persistent-user-details');
const relayUrl = document.getElementById('relay-url');
const fetchConfigBtn = document.getElementById('fetch-config-btn');
// Relay connection elements
const relayConnectionUrl = document.getElementById('relay-connection-url');
@@ -992,10 +976,7 @@
// Step 4: Update UI
updateRelayConnectionStatus('connected');
// Step 5: Update the old relay URL field for backward compatibility
if (relayUrl) {
relayUrl.value = url;
}
// Step 5: Relay URL updated
// Step 6: Automatically load configuration and auth rules
log('Relay connected successfully. Auto-loading configuration and auth rules...', 'INFO');
@@ -1308,7 +1289,7 @@
function disconnectFromRelay() {
if (relayPool) {
console.log('Cleaning up relay pool connection...');
const url = relayUrl.value.trim();
const url = relayConnectionUrl.value.trim();
if (url) {
relayPool.close([url]);
}
@@ -1392,7 +1373,7 @@
// Clean up configuration pool
if (relayPool) {
console.log('Closing configuration pool...');
const url = relayUrl.value.trim();
const url = relayConnectionUrl.value.trim();
if (url) {
relayPool.close([url]);
}
@@ -1760,7 +1741,7 @@
currentAuthRules = responseData.data;
console.log('Updated currentAuthRules with', currentAuthRules.length, 'rules');
// Always show the auth rules table when we receive data
// Always show the auth rules table when we receive data (no VIEW RULES button anymore)
console.log('Auto-showing auth rules table since we received data...');
showAuthRulesTable();
@@ -1770,7 +1751,7 @@
currentAuthRules = [];
console.log('No auth rules data received, cleared currentAuthRules');
// Show empty table
// Show empty table (no VIEW RULES button anymore)
console.log('Auto-showing auth rules table with empty data...');
showAuthRulesTable();
@@ -2275,7 +2256,7 @@
console.log(`Config update event signed with ${configObjects.length} objects`);
// Publish via SimplePool with detailed error diagnostics
const url = relayUrl.value.trim();
const url = relayConnectionUrl.value.trim();
const publishPromises = relayPool.publish([url], signedEvent);
// Use Promise.allSettled to capture per-relay outcomes instead of Promise.any
@@ -2437,9 +2418,6 @@
// DOM elements for auth rules
const authRulesSection = document.getElementById('authRulesSection');
const authRulesStatus = document.getElementById('authRulesStatus');
const viewAuthRulesBtn = document.getElementById('viewAuthRulesBtn');
const addAuthRuleBtn = document.getElementById('addAuthRuleBtn');
const refreshAuthRulesBtn = document.getElementById('refreshAuthRulesBtn');
const authRulesTableContainer = document.getElementById('authRulesTableContainer');
const authRulesTableBody = document.getElementById('authRulesTableBody');
@@ -2448,9 +2426,6 @@
const authRuleFormTitle = document.getElementById('authRuleFormTitle');
const saveAuthRuleBtn = document.getElementById('saveAuthRuleBtn');
const cancelAuthRuleBtn = document.getElementById('cancelAuthRuleBtn');
const authRulesStatusDisplay = document.getElementById('authRulesStatusDisplay');
const authSystemStatus = document.getElementById('authSystemStatus');
const authRulesCount = document.getElementById('authRulesCount');
// Show auth rules section after login
function showAuthRulesSection() {
@@ -2473,9 +2448,6 @@
if (authRuleFormContainer) {
authRuleFormContainer.style.display = 'none';
}
if (authRulesStatusDisplay) {
authRulesStatusDisplay.style.display = 'none';
}
currentAuthRules = [];
editingAuthRule = null;
@@ -2483,28 +2455,9 @@
}
}
// Update auth rules status indicator
// Update auth rules status indicator (removed - no status element)
function updateAuthRulesStatus(status) {
if (!authRulesStatus) return;
switch (status) {
case 'ready':
authRulesStatus.textContent = 'READY';
authRulesStatus.className = 'status disconnected';
break;
case 'loading':
authRulesStatus.textContent = 'LOADING';
authRulesStatus.className = 'status connected';
break;
case 'loaded':
authRulesStatus.textContent = 'LOADED';
authRulesStatus.className = 'status connected';
break;
case 'error':
authRulesStatus.textContent = 'ERROR';
authRulesStatus.className = 'status error';
break;
}
// Status element removed - no-op
}
// Load auth rules from relay using admin API
@@ -2550,7 +2503,7 @@
log('Sending auth rules query to relay...', 'INFO');
// Publish via SimplePool with detailed error diagnostics
const url = relayUrl.value.trim();
const url = relayConnectionUrl.value.trim();
const publishPromises = relayPool.publish([url], signedEvent);
// Use Promise.allSettled to capture per-relay outcomes instead of Promise.any
@@ -2636,31 +2589,21 @@
});
// Update status display
if (authRulesCount) {
const activeRules = rules.filter(r => r.enabled !== false).length;
authRulesCount.textContent = `Total Rules: ${rules.length} (${activeRules} active)`;
console.log(`Updated status display: ${rules.length} total, ${activeRules} active`);
}
console.log(`Total Rules: ${rules.length}, Active Rules: ${rules.filter(r => r.enabled !== false).length}`);
console.log('=== END DISPLAY AUTH RULES DEBUG ===');
}
// Show auth rules table
// Show auth rules table (automatically called when auth rules are loaded)
function showAuthRulesTable() {
console.log('=== SHOW AUTH RULES TABLE DEBUG ===');
console.log('authRulesTableContainer element:', authRulesTableContainer);
console.log('authRulesStatusDisplay element:', authRulesStatusDisplay);
console.log('Current display style:', authRulesTableContainer ? authRulesTableContainer.style.display : 'element not found');
if (authRulesTableContainer) {
authRulesTableContainer.style.display = 'block';
console.log('Set authRulesTableContainer display to block');
if (authRulesStatusDisplay) {
authRulesStatusDisplay.style.display = 'block';
console.log('Set authRulesStatusDisplay display to block');
}
// If we already have cached auth rules, display them immediately
if (currentAuthRules && currentAuthRules.length >= 0) {
console.log('Displaying cached auth rules:', currentAuthRules.length, 'rules');
@@ -2766,7 +2709,7 @@
log('Sending delete auth rule command to relay...', 'INFO');
// Publish via SimplePool with detailed error diagnostics
const url = relayUrl.value.trim();
const url = relayConnectionUrl.value.trim();
const publishPromises = relayPool.publish([url], signedEvent);
// Use Promise.allSettled to capture per-relay outcomes instead of Promise.any
@@ -2917,20 +2860,6 @@
};
// Auth rules event handlers
if (viewAuthRulesBtn) {
viewAuthRulesBtn.addEventListener('click', function (e) {
e.preventDefault();
showAuthRulesTable();
});
}
if (addAuthRuleBtn) {
addAuthRuleBtn.addEventListener('click', function (e) {
e.preventDefault();
showAddAuthRuleForm();
});
}
if (refreshAuthRulesBtn) {
refreshAuthRulesBtn.addEventListener('click', function (e) {
e.preventDefault();
@@ -2991,34 +2920,29 @@
// Add blacklist rule (updated to use combined input)
function addBlacklistRule() {
const input = document.getElementById('authRulePubkey');
const statusDiv = document.getElementById('authRuleStatus');
if (!input || !statusDiv) return;
if (!input) return;
const inputValue = input.value.trim();
if (!inputValue) {
statusDiv.className = 'rule-status error';
statusDiv.textContent = 'Please enter a pubkey or nsec';
log('Please enter a pubkey or nsec', 'ERROR');
return;
}
// Convert nsec to hex if needed
const hexPubkey = nsecToHex(inputValue);
if (!hexPubkey) {
statusDiv.className = 'rule-status error';
statusDiv.textContent = 'Invalid pubkey format. Please enter nsec1... or 64-character hex';
log('Invalid pubkey format. Please enter nsec1... or 64-character hex', 'ERROR');
return;
}
// Validate hex length
if (hexPubkey.length !== 64) {
statusDiv.className = 'rule-status error';
statusDiv.textContent = 'Invalid pubkey length. Must be exactly 64 characters';
log('Invalid pubkey length. Must be exactly 64 characters', 'ERROR');
return;
}
statusDiv.className = 'rule-status';
statusDiv.textContent = 'Adding to blacklist...';
log('Adding to blacklist...', 'INFO');
// Create auth rule data
const ruleData = {
@@ -3031,8 +2955,7 @@
// Add to WebSocket queue for processing
addAuthRuleViaWebSocket(ruleData)
.then(() => {
statusDiv.className = 'rule-status success';
statusDiv.textContent = `Pubkey ${hexPubkey.substring(0, 16)}... added to blacklist`;
log(`Pubkey ${hexPubkey.substring(0, 16)}... added to blacklist`, 'INFO');
input.value = '';
// Refresh auth rules display if visible
@@ -3041,38 +2964,33 @@
}
})
.catch(error => {
statusDiv.className = 'rule-status error';
statusDiv.textContent = `Failed to add rule: ${error.message}`;
log(`Failed to add rule: ${error.message}`, 'ERROR');
});
}
// Add whitelist rule (updated to use combined input)
function addWhitelistRule() {
const input = document.getElementById('authRulePubkey');
const statusDiv = document.getElementById('authRuleStatus');
const warningDiv = document.getElementById('whitelistWarning');
if (!input || !statusDiv) return;
if (!input) return;
const inputValue = input.value.trim();
if (!inputValue) {
statusDiv.className = 'rule-status error';
statusDiv.textContent = 'Please enter a pubkey or nsec';
log('Please enter a pubkey or nsec', 'ERROR');
return;
}
// Convert nsec to hex if needed
const hexPubkey = nsecToHex(inputValue);
if (!hexPubkey) {
statusDiv.className = 'rule-status error';
statusDiv.textContent = 'Invalid pubkey format. Please enter nsec1... or 64-character hex';
log('Invalid pubkey format. Please enter nsec1... or 64-character hex', 'ERROR');
return;
}
// Validate hex length
if (hexPubkey.length !== 64) {
statusDiv.className = 'rule-status error';
statusDiv.textContent = 'Invalid pubkey length. Must be exactly 64 characters';
log('Invalid pubkey length. Must be exactly 64 characters', 'ERROR');
return;
}
@@ -3081,8 +2999,7 @@
warningDiv.style.display = 'block';
}
statusDiv.className = 'rule-status';
statusDiv.textContent = 'Adding to whitelist...';
log('Adding to whitelist...', 'INFO');
// Create auth rule data
const ruleData = {
@@ -3095,8 +3012,7 @@
// Add to WebSocket queue for processing
addAuthRuleViaWebSocket(ruleData)
.then(() => {
statusDiv.className = 'rule-status success';
statusDiv.textContent = `Pubkey ${hexPubkey.substring(0, 16)}... added to whitelist`;
log(`Pubkey ${hexPubkey.substring(0, 16)}... added to whitelist`, 'INFO');
input.value = '';
// Refresh auth rules display if visible
@@ -3105,8 +3021,7 @@
}
})
.catch(error => {
statusDiv.className = 'rule-status error';
statusDiv.textContent = `Failed to add rule: ${error.message}`;
log(`Failed to add rule: ${error.message}`, 'ERROR');
});
}
@@ -3179,7 +3094,7 @@
}
// Publish via SimplePool with detailed error diagnostics
const url = relayUrl.value.trim();
const url = relayConnectionUrl.value.trim();
const publishPromises = relayPool.publish([url], signedEvent);
// Use Promise.allSettled to capture per-relay outcomes instead of Promise.any
@@ -3285,7 +3200,7 @@
logTestEvent('SENT', `Get Auth Rules event: ${JSON.stringify(signedEvent)}`, 'EVENT');
// Publish via SimplePool with detailed error diagnostics
const url = relayUrl.value.trim();
const url = relayConnectionUrl.value.trim();
const publishPromises = relayPool.publish([url], signedEvent);
// Use Promise.allSettled to capture per-relay outcomes instead of Promise.any
@@ -3359,7 +3274,7 @@
logTestEvent('SENT', `Clear Auth Rules event: ${JSON.stringify(signedEvent)}`, 'EVENT');
// Publish via SimplePool with detailed error diagnostics
const url = relayUrl.value.trim();
const url = relayConnectionUrl.value.trim();
const publishPromises = relayPool.publish([url], signedEvent);
// Use Promise.allSettled to capture per-relay outcomes instead of Promise.any
@@ -3442,7 +3357,7 @@
logTestEvent('SENT', `Add Blacklist event: ${JSON.stringify(signedEvent)}`, 'EVENT');
// Publish via SimplePool with detailed error diagnostics
const url = relayUrl.value.trim();
const url = relayConnectionUrl.value.trim();
const publishPromises = relayPool.publish([url], signedEvent);
// Use Promise.allSettled to capture per-relay outcomes instead of Promise.any