Compare commits

...

2 Commits

Author SHA1 Message Date
Your Name
eefb0e427e v0.3.18 - index.html improvements 2025-09-30 07:51:23 -04:00
Your Name
c23d81b740 v0.3.17 - Embedded login button 2025-09-30 06:47:09 -04:00
3 changed files with 777 additions and 501 deletions

134
api/button.html Normal file
View File

@@ -0,0 +1,134 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Embedded NOSTR_LOGIN_LITE</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
margin: 0;
padding: 40px;
background: white;
display: flex;
justify-content: center;
align-items: center;
min-height: 90vh;
}
.container {
max-width: 400px;
width: 100%;
}
#login-button {
background: #0066cc;
color: white;
padding: 12px 24px;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 16px;
text-align: center;
transition: background 0.2s;
}
#login-button:hover {
opacity: 0.8;
}
</style>
</head>
<body>
<div class="container">
<div id="login-button">Login</div>
</div>
<script src="../lite/nostr.bundle.js"></script>
<script src="../lite/nostr-lite.js"></script>
<script>
let isAuthenticated = false;
let currentUser = null;
document.addEventListener('DOMContentLoaded', async () => {
await window.NOSTR_LOGIN_LITE.init({
methods: {
extension: true,
local: true,
readonly: true,
connect: true,
remote: true,
otp: true
},
floatingTab: {
enabled: false
}
});
// Listen for authentication events
window.addEventListener('nlMethodSelected', handleAuthEvent);
window.addEventListener('nlLogout', handleLogoutEvent);
// Check for existing authentication state
checkAuthState();
// Initialize button
updateButtonState();
});
function handleAuthEvent(event) {
const { pubkey, method } = event.detail;
console.log(`Authenticated with ${method}, pubkey: ${pubkey}`);
isAuthenticated = true;
currentUser = event.detail;
updateButtonState();
}
function handleLogoutEvent() {
console.log('Logout event received');
isAuthenticated = false;
currentUser = null;
updateButtonState();
}
function checkAuthState() {
// Check if user is already authenticated (from persistent storage)
try {
// Try to get public key - this will work if already authenticated
window.nostr.getPublicKey().then(pubkey => {
console.log('Found existing authentication, pubkey:', pubkey);
isAuthenticated = true;
currentUser = { pubkey, method: 'persistent' };
updateButtonState();
}).catch(error => {
console.log('No existing authentication found:', error.message);
// User is not authenticated, button stays in login state
});
} catch (error) {
console.log('No existing authentication found');
// User is not authenticated, button stays in login state
}
}
function updateButtonState() {
const button = document.getElementById('login-button');
if (isAuthenticated) {
button.textContent = 'Logout';
button.onclick = () => window.NOSTR_LOGIN_LITE.logout();
button.style.background = '#dc3545'; // Red for logout
} else {
button.textContent = 'Login';
button.onclick = () => window.NOSTR_LOGIN_LITE.launch('login');
button.style.background = '#0066cc'; // Blue for login
}
}
</script>
</body>
</html>

View File

@@ -169,10 +169,11 @@
} }
.config-table { .config-table {
border: var(--border-width) solid var(--primary-color); border: 1px solid var(--primary-color);
border-radius: var(--border-radius); border-radius: var(--border-radius);
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: separate;
border-spacing: 0;
margin: 10px 0; margin: 10px 0;
overflow: hidden; overflow: hidden;
} }
@@ -183,6 +184,12 @@
padding: 8px; padding: 8px;
text-align: left; text-align: left;
font-family: var(--font-family); font-family: var(--font-family);
font-size: 10px;
}
.config-table-container {
overflow-x: auto;
max-width: 100%;
} }
.config-table th { .config-table th {
@@ -243,6 +250,53 @@
background-color: var(--secondary-color); background-color: var(--secondary-color);
} }
.user-info-container {
display: flex;
align-items: flex-start;
gap: 20px;
}
.user-details {
flex: 1;
}
.login-logout-btn {
width: auto;
min-width: 120px;
padding: 12px 16px;
background: var(--secondary-color);
color: var(--primary-color);
border: var(--border-width) solid var(--primary-color);
border-radius: var(--border-radius);
font-family: var(--font-family);
font-size: 14px;
font-weight: bold;
cursor: pointer;
transition: all 0.2s ease;
margin: 0;
flex-shrink: 0;
}
.login-logout-btn:hover {
border-color: var(--accent-color);
}
.login-logout-btn:active {
background: var(--accent-color);
color: var(--secondary-color);
}
.login-logout-btn.logout-state {
background: var(--accent-color);
color: var(--secondary-color);
border-color: var(--accent-color);
}
.login-logout-btn.logout-state:hover {
background: var(--primary-color);
border-color: var(--primary-color);
}
.user-pubkey { .user-pubkey {
font-family: var(--font-family); font-family: var(--font-family);
font-size: 12px; font-size: 12px;
@@ -378,7 +432,20 @@
transition: all 0.2s ease; transition: all 0.2s ease;
} }
@media (max-width: 768px) { /* Main Sections Wrapper */
.main-sections-wrapper {
display: flex;
flex-wrap: wrap;
gap: var(--border-width);
margin-bottom: 20px;
}
.flex-section {
flex: 1;
min-width: 300px;
}
@media (max-width: 700px) {
body { body {
padding: 10px; padding: 10px;
} }
@@ -401,42 +468,47 @@
<body> <body>
<h1>C-RELAY ADMIN API</h1> <h1>C-RELAY ADMIN API</h1>
<!-- Main Sections Wrapper -->
<div class="main-sections-wrapper">
<!-- Persistent Authentication Header - Always Visible -->
<div id="persistent-auth-container" class="section flex-section">
<div class="user-info-container">
<button type="button" id="login-logout-btn" class="login-logout-btn">LOGIN</button>
<div class="user-details" id="persistent-user-details" style="display: none;">
<div><strong>Name:</strong> <span id="persistent-user-name">Loading...</span></div>
<div><strong>Public Key:</strong>
<div class="user-pubkey" id="persistent-user-pubkey">Loading...</div>
</div>
<div><strong>About:</strong> <span id="persistent-user-about">Loading...</span></div>
</div>
</div>
</div>
<!-- Login Section --> <!-- Login Section -->
<div id="login-section"> <div id="login-section" class="flex-section">
<div class="section"> <div class="section">
<h2>NOSTR AUTHENTICATION</h2> <h2>NOSTR AUTHENTICATION</h2>
<p>Please login with your Nostr identity to access the admin interface.</p> <p id="login-instructions">Please login with your Nostr identity to access the admin interface.</p>
<!-- nostr-lite login UI will be injected here --> <!-- nostr-lite login UI will be injected here -->
</div> </div>
</div> </div>
<!-- Main Interface (hidden until logged in) -->
<div id="main-interface" class="hidden">
<!-- User Info Section - At the top of main interface -->
<div class="section">
<h2>LOGGED IN USER</h2>
<div class="user-info">
<div><strong>Name:</strong> <span id="user-name">Loading...</span></div>
<div><strong>Public Key:</strong>
<div class="user-pubkey" id="user-pubkey">Loading...</div>
</div>
<div><strong>About:</strong> <span id="user-about">Loading...</span></div>
</div>
<button type="button" id="logout-btn">LOGOUT</button>
</div>
<!-- Relay Connection Section --> <!-- Relay Connection Section -->
<div id="relay-connection-section" class="flex-section">
<div class="section"> <div class="section">
<h2>RELAY CONNECTION</h2>
<div class="input-group"> <div class="input-group">
<label for="relay-connection-url">Relay URL:</label> <label for="relay-connection-url">Relay URL:</label>
<input type="text" id="relay-connection-url" value="ws://localhost:8888" placeholder="ws://localhost:8888 or wss://relay.example.com"> <input type="text" id="relay-connection-url" value="ws://localhost:8888"
placeholder="ws://localhost:8888 or wss://relay.example.com">
</div> </div>
<div class="input-group"> <div class="input-group">
<label for="relay-pubkey-manual">Relay Pubkey (if not available via NIP-11):</label> <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"> <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> <small>If the relay hasn't been configured yet, enter the relay pubkey shown during startup</small>
</div> </div>
@@ -464,20 +536,22 @@
</div> </div>
</div> </div>
</div> </div>
<!-- Testing Section - Always Visible -->
<div class="section">
<div class="status disconnected" id="relay-status">READY TO FETCH</div>
<div class="inline-buttons">
<button type="button" id="fetch-config-btn">FETCH CONFIGURATION (REQUIRES LOGIN + RELAY CONNECTION)</button> </div> <!-- End Main Sections Wrapper -->
</div>
<div class="status disconnected" id="config-status">NO CONFIGURATION LOADED</div>
<!-- Testing Section -->
<div id="div_config" class="section flex-section">
<div id="config-display" class="hidden"> <div id="config-display" class="hidden">
<div id="config-view-mode"> <div id="config-view-mode">
<div class="config-table-container">
<table class="config-table" id="config-table"> <table class="config-table" id="config-table">
<thead> <thead>
<tr> <tr>
@@ -489,8 +563,10 @@
<tbody id="config-table-body"> <tbody id="config-table-body">
</tbody> </tbody>
</table> </table>
</div>
<div class="inline-buttons"> <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="edit-config-btn">EDIT CONFIGURATION</button>
<button type="button" id="copy-config-btn">COPY CONFIGURATION</button> <button type="button" id="copy-config-btn">COPY CONFIGURATION</button>
</div> </div>
@@ -512,7 +588,7 @@
</div> </div>
<!-- Auth Rules Management - Moved after configuration --> <!-- Auth Rules Management - Moved after configuration -->
<div class="section" id="authRulesSection" style="display: none;"> <div class="section flex-section" id="authRulesSection" style="display: none;">
<div class="section-header"> <div class="section-header">
<h2>AUTH RULES MANAGEMENT</h2> <h2>AUTH RULES MANAGEMENT</h2>
<div class="status" id="authRulesStatus"></div> <div class="status" id="authRulesStatus"></div>
@@ -556,12 +632,15 @@
<small id="authRuleHelp">Enter nsec (will auto-convert) or 64-character hex pubkey</small> <small id="authRuleHelp">Enter nsec (will auto-convert) or 64-character hex pubkey</small>
</div> </div>
<div id="whitelistWarning" class="warning-box" style="display: none;"> <div id="whitelistWarning" class="warning-box" style="display: none;">
<strong>⚠️ WARNING:</strong> Adding whitelist rules changes relay behavior to whitelist-only mode. <strong>⚠️ WARNING:</strong> Adding whitelist rules changes relay behavior to whitelist-only
mode.
Only whitelisted users will be able to interact with the relay. Only whitelisted users will be able to interact with the relay.
</div> </div>
<div class="inline-buttons"> <div class="inline-buttons">
<button type="button" id="addWhitelistBtn" onclick="addWhitelistRule()">ADD TO WHITELIST</button> <button type="button" id="addWhitelistBtn" onclick="addWhitelistRule()">ADD TO
<button type="button" id="addBlacklistBtn" onclick="addBlacklistRule()">ADD TO BLACKLIST</button> WHITELIST</button>
<button type="button" id="addBlacklistBtn" onclick="addBlacklistRule()">ADD TO
BLACKLIST</button>
</div> </div>
<div id="authRuleStatus" class="rule-status"></div> <div id="authRuleStatus" class="rule-status"></div>
</div> </div>
@@ -578,6 +657,11 @@
</div> </div>
</div> </div>
<!-- TESTS Section --> <!-- TESTS Section -->
<div class="section"> <div class="section">
<h2>ADMIN API TESTS</h2> <h2>ADMIN API TESTS</h2>
@@ -588,7 +672,8 @@
<label for="test-event-log">Event Log (Sent/Received):</label> <label for="test-event-log">Event Log (Sent/Received):</label>
<div class="log-panel" id="test-event-log" style="height: 300px;"> <div class="log-panel" id="test-event-log" style="height: 300px;">
<div class="log-entry"> <div class="log-entry">
<span class="log-timestamp">SYSTEM:</span> Test interface ready. Click buttons below to test admin API functions. <span class="log-timestamp">SYSTEM:</span> Test interface ready. Click buttons below to test admin
API functions.
</div> </div>
</div> </div>
<button type="button" id="clear-test-log-btn">CLEAR TEST LOG</button> <button type="button" id="clear-test-log-btn">CLEAR TEST LOG</button>
@@ -616,8 +701,10 @@
<div class="input-group"> <div class="input-group">
<label for="test-pubkey-input">Test Pubkey (for blacklist/whitelist):</label> <label for="test-pubkey-input">Test Pubkey (for blacklist/whitelist):</label>
<div style="display: flex; gap: 10px; align-items: flex-start;"> <div style="display: flex; gap: 10px; align-items: flex-start;">
<input type="text" id="test-pubkey-input" placeholder="Enter pubkey or nsec1... for testing" style="flex: 1;"> <input type="text" id="test-pubkey-input" placeholder="Enter pubkey or nsec1... for testing"
<button type="button" id="generate-test-key-btn" style="width: auto; padding: 8px 16px; white-space: nowrap;">GENERATE KEY</button> style="flex: 1;">
<button type="button" id="generate-test-key-btn"
style="width: auto; padding: 8px 16px; white-space: nowrap;">GENERATE KEY</button>
</div> </div>
<small>This pubkey will be used for blacklist/whitelist tests</small> <small>This pubkey will be used for blacklist/whitelist tests</small>
</div> </div>
@@ -674,13 +761,12 @@
// DOM elements // DOM elements
const loginSection = document.getElementById('login-section'); const loginSection = document.getElementById('login-section');
const mainInterface = document.getElementById('main-interface'); // const mainInterface = document.getElementById('main-interface');
const userName = document.getElementById('user-name'); const persistentUserName = document.getElementById('persistent-user-name');
const userPubkeyDisplay = document.getElementById('user-pubkey'); const persistentUserPubkey = document.getElementById('persistent-user-pubkey');
const userAbout = document.getElementById('user-about'); const persistentUserAbout = document.getElementById('persistent-user-about');
const logoutBtn = document.getElementById('logout-btn'); const persistentUserDetails = document.getElementById('persistent-user-details');
const relayUrl = document.getElementById('relay-url'); const relayUrl = document.getElementById('relay-url');
const relayStatus = document.getElementById('relay-status');
const fetchConfigBtn = document.getElementById('fetch-config-btn'); const fetchConfigBtn = document.getElementById('fetch-config-btn');
// Relay connection elements // Relay connection elements
const relayConnectionUrl = document.getElementById('relay-connection-url'); const relayConnectionUrl = document.getElementById('relay-connection-url');
@@ -689,7 +775,6 @@
const connectRelayBtn = document.getElementById('connect-relay-btn'); const connectRelayBtn = document.getElementById('connect-relay-btn');
const disconnectRelayBtn = document.getElementById('disconnect-relay-btn'); const disconnectRelayBtn = document.getElementById('disconnect-relay-btn');
const testWebSocketBtn = document.getElementById('test-websocket-btn'); const testWebSocketBtn = document.getElementById('test-websocket-btn');
const configStatus = document.getElementById('config-status');
const configDisplay = document.getElementById('config-display'); const configDisplay = document.getElementById('config-display');
const configViewMode = document.getElementById('config-view-mode'); const configViewMode = document.getElementById('config-view-mode');
const configEditMode = document.getElementById('config-edit-mode'); const configEditMode = document.getElementById('config-edit-mode');
@@ -1106,6 +1191,7 @@
// Show main interface // Show main interface
showMainInterface(); showMainInterface();
loadUserProfile(); loadUserProfile();
updateLoginLogoutButton();
// Note: Configuration fetching now requires explicit relay connection // Note: Configuration fetching now requires explicit relay connection
// User must connect to relay manually after login // User must connect to relay manually after login
@@ -1131,25 +1217,25 @@
readonly: true, readonly: true,
connect: true, connect: true,
remote: true, remote: true,
otp: true otp: false
}, },
floatingTab: { floatingTab: {
enabled: true, enabled: false,
hPosition: 1, // 0.0-1.0 or '95%' from left // hPosition: 1, // 0.0-1.0 or '95%' from left
vPosition: 0, // 0.0-1.0 or '50%' from top // vPosition: 0, // 0.0-1.0 or '50%' from top
appearance: { // appearance: {
style: 'square', // 'pill', 'square', 'circle', 'minimal' // style: 'square', // 'pill', 'square', 'circle', 'minimal'
// icon: '[LOGIN]', // Now uses text-based icons like [LOGIN], [KEY], [NET] // // icon: '[LOGIN]', // Now uses text-based icons like [LOGIN], [KEY], [NET]
text: 'Login' // text: 'Login'
}, // },
behavior: { // behavior: {
hideWhenAuthenticated: false, // hideWhenAuthenticated: false,
showUserInfo: true, // showUserInfo: true,
autoSlide: true // autoSlide: true
}, // },
animation: { // animation: {
slideDirection: 'auto' // 'auto', 'left', 'right', 'up', 'down' // slideDirection: 'auto' // 'auto', 'left', 'right', 'up', 'down'
} // }
} }
}); });
@@ -1167,6 +1253,7 @@
// Listen for authentication events // Listen for authentication events
window.addEventListener('nlMethodSelected', handleAuthEvent); window.addEventListener('nlMethodSelected', handleAuthEvent);
window.addEventListener('nlLogout', handleLogoutEvent);
} catch (error) { } catch (error) {
console.log('Failed to initialize Nostr login: ' + error.message); console.log('Failed to initialize Nostr login: ' + error.message);
@@ -1185,6 +1272,7 @@
showMainInterface(); showMainInterface();
loadUserProfile(); loadUserProfile();
updateLoginLogoutButton();
// Note: Configuration fetching now requires explicit relay connection // Note: Configuration fetching now requires explicit relay connection
// User must connect to relay manually after login // User must connect to relay manually after login
@@ -1195,11 +1283,45 @@
} }
} }
// Handle logout events
function handleLogoutEvent() {
console.log('Logout event received');
userPubkey = null;
isLoggedIn = false;
currentConfig = null;
// Clean up relay connection
disconnectFromRelay();
// Reset UI
// mainInterface.classList.add('hidden');
loginSection.classList.remove('hidden');
updateConfigStatus(false);
updateLoginLogoutButton();
hideAuthRulesSection();
console.log('Logout event handled successfully');
}
// Disconnect from relay and clean up connections
function disconnectFromRelay() {
if (relayPool) {
console.log('Cleaning up relay pool connection...');
const url = relayUrl.value.trim();
if (url) {
relayPool.close([url]);
}
relayPool = null;
subscriptionId = null;
}
}
// Show main interface after login // Show main interface after login
function showMainInterface() { function showMainInterface() {
loginSection.classList.add('hidden'); loginSection.classList.add('hidden');
mainInterface.classList.remove('hidden'); // mainInterface.classList.remove('hidden');
userPubkeyDisplay.textContent = userPubkey; updateLoginLogoutButton();
} }
// Load user profile using nostr-tools pool // Load user profile using nostr-tools pool
@@ -1207,8 +1329,8 @@
if (!userPubkey) return; if (!userPubkey) return;
console.log('Loading user profile...'); console.log('Loading user profile...');
userName.textContent = 'Loading...'; persistentUserName.textContent = 'Loading...';
userAbout.textContent = 'Loading...'; persistentUserAbout.textContent = 'Loading...';
try { try {
// Create a SimplePool instance for profile loading // Create a SimplePool instance for profile loading
@@ -1223,11 +1345,16 @@
}); });
if (events.length > 0) { if (events.length > 0) {
console.log('Profile event found:', events[0]);
const profile = JSON.parse(events[0].content); const profile = JSON.parse(events[0].content);
console.log('Parsed profile:', profile);
displayProfile(profile); displayProfile(profile);
} else { } else {
userName.textContent = 'Anonymous User'; console.log('No profile events found for pubkey:', userPubkey);
userAbout.textContent = 'No profile found'; persistentUserName.textContent = 'Anonymous User';
persistentUserAbout.textContent = 'No profile found';
// Still show the pubkey since we have it
persistentUserPubkey.textContent = userPubkey;
} }
// Close the profile pool // Close the profile pool
@@ -1235,8 +1362,10 @@
} catch (error) { } catch (error) {
console.log('Profile loading failed: ' + error.message); console.log('Profile loading failed: ' + error.message);
userName.textContent = 'Error loading profile'; persistentUserName.textContent = 'Error loading profile';
userAbout.textContent = error.message; persistentUserAbout.textContent = error.message;
// Still show the pubkey since we have it
persistentUserPubkey.textContent = userPubkey;
} }
} }
@@ -1245,10 +1374,12 @@
const name = profile.name || profile.display_name || profile.displayName || 'Anonymous User'; const name = profile.name || profile.display_name || profile.displayName || 'Anonymous User';
const about = profile.about || 'No description provided'; const about = profile.about || 'No description provided';
userName.textContent = name; // Update persistent user details
userAbout.textContent = about; persistentUserName.textContent = name;
persistentUserPubkey.textContent = userPubkey;
persistentUserAbout.textContent = about;
console.log(`Profile loaded for: ${name}`); console.log(`Profile loaded for: ${name} with pubkey: ${userPubkey}`);
} }
// Logout function // Logout function
@@ -1275,12 +1406,11 @@
isLoggedIn = false; isLoggedIn = false;
currentConfig = null; currentConfig = null;
// Reset UI // Reset UI - keep persistent auth container visible
mainInterface.classList.add('hidden'); // mainInterface.classList.add('hidden');
loginSection.classList.remove('hidden'); loginSection.classList.remove('hidden');
updateConfigStatus(false); updateConfigStatus(false);
relayStatus.textContent = 'READY TO FETCH'; updateLoginLogoutButton();
relayStatus.className = 'status disconnected';
console.log('Logged out successfully'); console.log('Logged out successfully');
@@ -1291,12 +1421,8 @@
function updateConfigStatus(loaded) { function updateConfigStatus(loaded) {
if (loaded) { if (loaded) {
configStatus.textContent = 'CONFIGURATION LOADED';
configStatus.className = 'status connected';
configDisplay.classList.remove('hidden'); configDisplay.classList.remove('hidden');
} else { } else {
configStatus.textContent = 'NO CONFIGURATION LOADED';
configStatus.className = 'status disconnected';
configDisplay.classList.add('hidden'); configDisplay.classList.add('hidden');
} }
} }
@@ -1324,8 +1450,6 @@
} }
console.log(`Connecting to relay via SimplePool: ${url}`); console.log(`Connecting to relay via SimplePool: ${url}`);
relayStatus.textContent = 'CONNECTING...';
relayStatus.className = 'status connected';
// Clean up existing pool // Clean up existing pool
if (relayPool) { if (relayPool) {
@@ -1341,9 +1465,6 @@
console.log(`Generated subscription ID: ${subscriptionId}`); console.log(`Generated subscription ID: ${subscriptionId}`);
relayStatus.textContent = 'CONNECTED - SUBSCRIBING...';
relayStatus.className = 'status connected';
// Subscribe to kind 23457 events (admin response events) // Subscribe to kind 23457 events (admin response events)
const subscription = relayPool.subscribeMany([url], [{ const subscription = relayPool.subscribeMany([url], [{
since: Math.floor(Date.now() / 1000), since: Math.floor(Date.now() / 1000),
@@ -1367,9 +1488,6 @@
// Process admin response event // Process admin response event
processAdminResponse(event); processAdminResponse(event);
relayStatus.textContent = 'SUBSCRIBED - LIVE UPDATES';
relayStatus.className = 'status connected';
}, },
oneose() { oneose() {
console.log('EOSE received - End of stored events'); console.log('EOSE received - End of stored events');
@@ -1377,19 +1495,10 @@
if (!currentConfig) { if (!currentConfig) {
console.log('No configuration events were received'); console.log('No configuration events were received');
configStatus.textContent = 'NO CONFIGURATION EVENTS FOUND';
configStatus.className = 'status error';
relayStatus.textContent = 'SUBSCRIBED - NO EVENTS FOUND';
relayStatus.className = 'status error';
} else {
relayStatus.textContent = 'SUBSCRIBED - LIVE UPDATES';
relayStatus.className = 'status connected';
} }
}, },
onclose(reason) { onclose(reason) {
console.log('Subscription closed:', reason); console.log('Subscription closed:', reason);
relayStatus.textContent = 'SUBSCRIPTION CLOSED';
relayStatus.className = 'status error';
updateConfigStatus(false); updateConfigStatus(false);
} }
}); });
@@ -1404,9 +1513,6 @@
console.error('Configuration subscription failed:', error.message); console.error('Configuration subscription failed:', error.message);
console.error('Configuration subscription failed:', error); console.error('Configuration subscription failed:', error);
console.error('Error stack:', error.stack); console.error('Error stack:', error.stack);
relayStatus.textContent = 'SUBSCRIPTION FAILED';
relayStatus.className = 'status error';
return false; return false;
} }
} }
@@ -1558,8 +1664,6 @@
} else { } else {
console.log('No configuration data received'); console.log('No configuration data received');
updateConfigStatus(false); updateConfigStatus(false);
configStatus.textContent = 'NO CONFIGURATION DATA RECEIVED';
configStatus.className = 'status error';
} }
// Also log to test interface for debugging // Also log to test interface for debugging
@@ -1866,21 +1970,15 @@
} }
console.log('Config query command sent successfully - waiting for response...'); console.log('Config query command sent successfully - waiting for response...');
configStatus.textContent = 'CONFIGURATION QUERY SENT - WAITING FOR RESPONSE';
configStatus.className = 'status connected';
} else { } else {
console.log('Not logged in - only subscription established for testing'); console.log('Not logged in - only subscription established for testing');
configStatus.textContent = 'SUBSCRIPTION ESTABLISHED - LOGIN REQUIRED FOR CONFIG QUERY';
configStatus.className = 'status disconnected';
} }
return true; return true;
} catch (error) { } catch (error) {
console.error('Failed to fetch configuration:', error); console.error('Failed to fetch configuration:', error);
configStatus.textContent = 'CONFIGURATION FETCH FAILED';
configStatus.className = 'status error';
return false; return false;
} }
} }
@@ -2224,8 +2322,39 @@
// Login/Logout button functionality
function updateLoginLogoutButton() {
const loginLogoutBtn = document.getElementById('login-logout-btn');
if (!loginLogoutBtn) return;
if (isLoggedIn) {
loginLogoutBtn.textContent = 'LOGOUT';
loginLogoutBtn.className = 'login-logout-btn logout-state';
loginLogoutBtn.onclick = logout;
// Show user details when logged in
if (persistentUserDetails) {
persistentUserDetails.style.display = 'block';
}
} else {
loginLogoutBtn.textContent = 'ADMIN NOSTR LOGIN';
loginLogoutBtn.className = 'login-logout-btn';
loginLogoutBtn.onclick = () => {
if (window.NOSTR_LOGIN_LITE && window.NOSTR_LOGIN_LITE.launch) {
window.NOSTR_LOGIN_LITE.launch('login');
} else {
console.log('NOSTR_LOGIN_LITE not available');
}
};
// Hide user details when logged out
if (persistentUserDetails) {
persistentUserDetails.style.display = 'none';
}
}
}
// Event handlers // Event handlers
logoutBtn.addEventListener('click', logout); // Initialize login/logout button
updateLoginLogoutButton();
fetchConfigBtn.addEventListener('click', function (e) { fetchConfigBtn.addEventListener('click', function (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
@@ -2336,9 +2465,18 @@
function hideAuthRulesSection() { function hideAuthRulesSection() {
if (authRulesSection) { if (authRulesSection) {
authRulesSection.style.display = 'none'; authRulesSection.style.display = 'none';
// Add null checks for all elements
if (authRulesTableContainer) {
authRulesTableContainer.style.display = 'none'; authRulesTableContainer.style.display = 'none';
}
if (authRuleFormContainer) {
authRuleFormContainer.style.display = 'none'; authRuleFormContainer.style.display = 'none';
}
if (authRulesStatusDisplay) {
authRulesStatusDisplay.style.display = 'none'; authRulesStatusDisplay.style.display = 'none';
}
currentAuthRules = []; currentAuthRules = [];
editingAuthRule = null; editingAuthRule = null;
log('Auth rules section hidden', 'INFO'); log('Auth rules section hidden', 'INFO');
@@ -2767,34 +2905,34 @@
// Update existing logout and showMainInterface functions to handle auth rules // Update existing logout and showMainInterface functions to handle auth rules
const originalLogout = logout; const originalLogout = logout;
logout = async function() { logout = async function () {
hideAuthRulesSection(); hideAuthRulesSection();
await originalLogout(); await originalLogout();
}; };
const originalShowMainInterface = showMainInterface; const originalShowMainInterface = showMainInterface;
showMainInterface = function() { showMainInterface = function () {
originalShowMainInterface(); originalShowMainInterface();
showAuthRulesSection(); showAuthRulesSection();
}; };
// Auth rules event handlers // Auth rules event handlers
if (viewAuthRulesBtn) { if (viewAuthRulesBtn) {
viewAuthRulesBtn.addEventListener('click', function(e) { viewAuthRulesBtn.addEventListener('click', function (e) {
e.preventDefault(); e.preventDefault();
showAuthRulesTable(); showAuthRulesTable();
}); });
} }
if (addAuthRuleBtn) { if (addAuthRuleBtn) {
addAuthRuleBtn.addEventListener('click', function(e) { addAuthRuleBtn.addEventListener('click', function (e) {
e.preventDefault(); e.preventDefault();
showAddAuthRuleForm(); showAddAuthRuleForm();
}); });
} }
if (refreshAuthRulesBtn) { if (refreshAuthRulesBtn) {
refreshAuthRulesBtn.addEventListener('click', function(e) { refreshAuthRulesBtn.addEventListener('click', function (e) {
e.preventDefault(); e.preventDefault();
loadAuthRules(); loadAuthRules();
}); });
@@ -2805,7 +2943,7 @@
} }
if (cancelAuthRuleBtn) { if (cancelAuthRuleBtn) {
cancelAuthRuleBtn.addEventListener('click', function(e) { cancelAuthRuleBtn.addEventListener('click', function (e) {
e.preventDefault(); e.preventDefault();
hideAuthRuleForm(); hideAuthRuleForm();
}); });
@@ -3715,6 +3853,10 @@
// Initialize the app // Initialize the app
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
console.log('C-Relay Admin API interface loaded'); console.log('C-Relay Admin API interface loaded');
// Initialize login/logout button state
updateLoginLogoutButton();
setTimeout(() => { setTimeout(() => {
initializeApp(); initializeApp();
// Enhance SimplePool for testing after initialization // Enhance SimplePool for testing after initialization

View File

@@ -1 +1 @@
1182553 1371445