feat: implement client-side room listing UI and server-side authentication blueprint
This commit is contained in:
parent
9ccfbd1dc0
commit
c24c4acaec
3 changed files with 72 additions and 1 deletions
|
|
@ -69,3 +69,31 @@ def validate():
|
|||
|
||||
return jsonify({"error": "Invalid credentials"}), 403
|
||||
|
||||
|
||||
@auth_bp.route("/logout", methods=["POST"])
|
||||
def logout():
|
||||
data = request.get_json()
|
||||
username = data.get("username")
|
||||
key = data.get("key")
|
||||
|
||||
if not username or not key:
|
||||
return jsonify({"error": "Missing credentials"}), 400
|
||||
|
||||
if verify_user_key(username, key):
|
||||
# Remove from active sessions
|
||||
user_sessions.pop(username, None)
|
||||
# Remove from user_ips in memory and SQLite to free up the username immediately
|
||||
user_ips.pop(username, None)
|
||||
from models.database import db_delete_user_ip
|
||||
db_delete_user_ip(username)
|
||||
|
||||
# Remove from all rooms
|
||||
from models.state import room_users
|
||||
for room in room_users:
|
||||
room_users[room].pop(username, None)
|
||||
|
||||
return jsonify({"status": "logged_out"})
|
||||
|
||||
return jsonify({"error": "Invalid credentials"}), 403
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,8 +25,51 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||
return;
|
||||
}
|
||||
|
||||
function escapeHtml(text) {
|
||||
if (!text) return text;
|
||||
return text
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """)
|
||||
.replace(/'/g, "'");
|
||||
}
|
||||
|
||||
const userInfoEl = document.getElementById('user-info');
|
||||
userInfoEl.textContent = `Logged in as: ${username}`;
|
||||
userInfoEl.style.display = 'flex';
|
||||
userInfoEl.style.alignItems = 'center';
|
||||
userInfoEl.style.justifyContent = 'flex-start';
|
||||
userInfoEl.style.gap = '15px';
|
||||
userInfoEl.style.marginBottom = '20px';
|
||||
|
||||
const logoutBtn = document.createElement('button');
|
||||
logoutBtn.textContent = 'Logout';
|
||||
logoutBtn.style.backgroundColor = '#d9534f';
|
||||
logoutBtn.style.color = 'white';
|
||||
logoutBtn.style.border = 'none';
|
||||
logoutBtn.style.padding = '6px 12px';
|
||||
logoutBtn.style.borderRadius = '4px';
|
||||
logoutBtn.style.cursor = 'pointer';
|
||||
logoutBtn.onclick = async () => {
|
||||
if (confirm("Are you sure you want to logout? This will release your username immediately.")) {
|
||||
try {
|
||||
await fetch('/logout', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ username, key: userKey })
|
||||
});
|
||||
} catch (e) {
|
||||
console.error("Logout request failed:", e);
|
||||
}
|
||||
localStorage.clear();
|
||||
window.location.href = '/';
|
||||
}
|
||||
};
|
||||
|
||||
const userSpan = document.createElement('span');
|
||||
userSpan.innerHTML = `Logged in as: <strong>${escapeHtml(username)}</strong>`;
|
||||
|
||||
userInfoEl.append(logoutBtn, userSpan);
|
||||
|
||||
document.querySelectorAll('.collapsible').forEach(heading => {
|
||||
heading.addEventListener('click', () => {
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Reference in a new issue