feat: status includes is_admin, gear icon in header for admins
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -98,7 +98,7 @@ async def setup_post(body: dict):
|
|||||||
|
|
||||||
@router.get("/status")
|
@router.get("/status")
|
||||||
async def get_status(user: dict = Depends(current_user)):
|
async def get_status(user: dict = Depends(current_user)):
|
||||||
return {"status": state.status, "username": user["username"]}
|
return {"status": state.status, "username": user["username"], "is_admin": user.get("is_admin", False)}
|
||||||
|
|
||||||
|
|
||||||
@router.post("/toggle")
|
@router.post("/toggle")
|
||||||
|
|||||||
@@ -181,6 +181,14 @@ async function loadTranscripts() {
|
|||||||
if (data.username) {
|
if (data.username) {
|
||||||
userChip.textContent = data.username;
|
userChip.textContent = data.username;
|
||||||
}
|
}
|
||||||
|
if (data.is_admin) {
|
||||||
|
const gearLink = document.createElement('a');
|
||||||
|
gearLink.href = '/settings';
|
||||||
|
gearLink.className = 'back-btn';
|
||||||
|
gearLink.title = 'Einstellungen';
|
||||||
|
gearLink.textContent = '\u2699';
|
||||||
|
document.querySelector('.header-right').prepend(gearLink);
|
||||||
|
}
|
||||||
connectWs();
|
connectWs();
|
||||||
loadTranscripts();
|
loadTranscripts();
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -68,6 +68,13 @@
|
|||||||
transition: border-color 0.15s, color 0.15s;
|
transition: border-color 0.15s, color 0.15s;
|
||||||
}
|
}
|
||||||
.logout-btn:hover { border-color: var(--red); color: var(--red); }
|
.logout-btn:hover { border-color: var(--red); color: var(--red); }
|
||||||
|
.back-btn {
|
||||||
|
font-size: .75rem; padding: 4px 10px; border-radius: 20px;
|
||||||
|
background: none; border: 1px solid var(--border); color: var(--muted);
|
||||||
|
cursor: pointer; font-family: inherit; text-decoration: none;
|
||||||
|
transition: border-color .15s, color .15s;
|
||||||
|
}
|
||||||
|
.back-btn:hover { border-color: var(--red); color: var(--red); }
|
||||||
main {
|
main {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -146,6 +146,20 @@ def test_audio_combined_forbidden_for_non_admin():
|
|||||||
app.dependency_overrides.pop(current_user, None)
|
app.dependency_overrides.pop(current_user, None)
|
||||||
|
|
||||||
|
|
||||||
|
def test_status_includes_is_admin():
|
||||||
|
from main import app
|
||||||
|
from api.router import current_user
|
||||||
|
app.dependency_overrides[current_user] = lambda: {"username": "u", "output_dir": "/tmp", "is_admin": True}
|
||||||
|
try:
|
||||||
|
from fastapi.testclient import TestClient
|
||||||
|
client = TestClient(app)
|
||||||
|
r = client.get("/status", headers={"Authorization": "Bearer fake"})
|
||||||
|
assert r.status_code == 200
|
||||||
|
assert r.json()["is_admin"] is True
|
||||||
|
finally:
|
||||||
|
app.dependency_overrides.pop(current_user, None)
|
||||||
|
|
||||||
|
|
||||||
def test_put_config_deep_merges(tmp_path, monkeypatch):
|
def test_put_config_deep_merges(tmp_path, monkeypatch):
|
||||||
import config as cfg_mod
|
import config as cfg_mod
|
||||||
monkeypatch.setattr(cfg_mod, "CONFIG_PATH", str(tmp_path / "config.toml"))
|
monkeypatch.setattr(cfg_mod, "CONFIG_PATH", str(tmp_path / "config.toml"))
|
||||||
|
|||||||
Reference in New Issue
Block a user