diff --git a/backend/src/controllers/RealmController.cpp b/backend/src/controllers/RealmController.cpp index 475db56..05b7119 100644 --- a/backend/src/controllers/RealmController.cpp +++ b/backend/src/controllers/RealmController.cpp @@ -630,31 +630,35 @@ void RealmController::updateRealm(const HttpRequestPtr &req, } >> DB_ERROR_MSG(callback, "update retention", "Failed to update retention"); } else if (json->isMember("name")) { - // Update realm name - std::string newName = (*json)["name"].asString(); + // Update realm name (display name with optional uppercase) + std::string displayName = (*json)["name"].asString(); - // Validate name format - if (!validateRealmName(newName)) { - callback(jsonError("Invalid realm name. Use 3-30 lowercase letters, numbers, and hyphens only.")); + // Validate display name format + if (!validateRealmDisplayName(displayName)) { + callback(jsonError("Invalid realm name. Use 3-30 letters, numbers, and hyphens only.")); return; } - // Check if name is already taken by another realm + // Generate lowercase slug for URL + std::string newSlug = toSlug(displayName); + + // Check if slug is already taken by another realm *dbClient << "SELECT id FROM realms WHERE name = $1 AND id != $2" - << newName << id - >> [callback, dbClient, id, user, newName](const Result& nameCheck) { + << newSlug << id + >> [callback, dbClient, id, user, displayName, newSlug](const Result& nameCheck) { if (!nameCheck.empty()) { callback(jsonError("Realm name is already taken")); return; } - *dbClient << "UPDATE realms SET name = $1 WHERE id = $2 AND user_id = $3" - << newName << id << user.id - >> [callback, newName](const Result&) { + *dbClient << "UPDATE realms SET name = $1, display_name = $2 WHERE id = $3 AND user_id = $4" + << newSlug << displayName << id << user.id + >> [callback, displayName, newSlug](const Result&) { Json::Value resp; resp["success"] = true; resp["message"] = "Realm renamed successfully"; - resp["name"] = newName; + resp["name"] = newSlug; + resp["displayName"] = displayName; callback(jsonResp(resp)); } >> DB_ERROR_MSG(callback, "rename realm", "Failed to rename realm"); diff --git a/frontend/src/routes/admin/+page.svelte b/frontend/src/routes/admin/+page.svelte index bb0e5cb..75cfb98 100644 --- a/frontend/src/routes/admin/+page.svelte +++ b/frontend/src/routes/admin/+page.svelte @@ -1619,8 +1619,20 @@ async function loadUberbannedFingerprints() { try { + // Fetch JWT token for chat-service authentication + const tokenResp = await fetch('/api/user/token', { credentials: 'include' }); + if (!tokenResp.ok) { + console.error('Failed to load uberbanned fingerprints'); + return; + } + const tokenData = await tokenResp.json(); + const token = tokenData.token; + const response = await fetch('/api/chat/uberbanned', { - credentials: 'include' + credentials: 'include', + headers: { + 'Authorization': `Bearer ${token}` + } }); if (response.ok) { @@ -1639,9 +1651,22 @@ if (!confirm(`Remove uberban for fingerprint ${truncated}?\n\nThis will allow this device to access the site again.`)) return; try { + // Fetch JWT token for chat-service authentication + const tokenResp = await fetch('/api/user/token', { credentials: 'include' }); + if (!tokenResp.ok) { + error = 'Failed to authenticate'; + setTimeout(() => { error = ''; }, 3000); + return; + } + const tokenData = await tokenResp.json(); + const token = tokenData.token; + const response = await fetch('/api/chat/unuberban', { method: 'POST', - headers: { 'Content-Type': 'application/json' }, + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` + }, credentials: 'include', body: JSON.stringify({ fingerprint }) });