feat: Global-Admin Org-Switcher fuer info@aegis-sight.de
Ermoeglicht dem Global Admin (is_global_admin Flag) zwischen Organisationen zu wechseln. Neue Endpoints: GET /api/auth/organizations, POST /api/auth/switch-org. Org-Dropdown im Header-Menue, nur fuer Global Admin sichtbar. Komplett herausnehmbar (Flag + Code-Bloecke). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Dieser Commit ist enthalten in:
@@ -5445,3 +5445,41 @@ body.tutorial-active .tutorial-cursor {
|
||||
font-size: 11px;
|
||||
color: var(--text-tertiary);
|
||||
}
|
||||
|
||||
/* --- Global Admin: Org-Switcher (herausnehmbar) --- */
|
||||
.org-switcher-section {
|
||||
padding: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.org-switcher-label {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.5px;
|
||||
color: var(--text-tertiary);
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 6px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.org-switcher-select {
|
||||
width: 100%;
|
||||
padding: 6px 8px;
|
||||
font-size: 13px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid var(--border);
|
||||
background: var(--bg-secondary);
|
||||
color: var(--text-primary);
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
transition: border-color 0.15s;
|
||||
}
|
||||
|
||||
.org-switcher-select:hover {
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
.org-switcher-select:focus {
|
||||
border-color: var(--accent);
|
||||
box-shadow: 0 0 0 2px rgba(var(--accent-rgb, 59, 130, 246), 0.15);
|
||||
}
|
||||
|
||||
@@ -52,6 +52,12 @@
|
||||
<span class="header-dropdown-label">Organisation</span>
|
||||
<span class="header-dropdown-value" id="header-org-name">-</span>
|
||||
</div>
|
||||
<!-- Global Admin: Org-Switcher (herausnehmbar) -->
|
||||
<div id="org-switcher-section" class="org-switcher-section" style="display: none;">
|
||||
<div class="credits-divider"></div>
|
||||
<label class="org-switcher-label" for="org-switcher-select">Wechseln zu:</label>
|
||||
<select id="org-switcher-select" class="org-switcher-select"></select>
|
||||
</div>
|
||||
<div class="header-dropdown-row">
|
||||
<span class="header-dropdown-label">Lizenz</span>
|
||||
<span class="header-dropdown-value" id="header-license-info">-</span>
|
||||
|
||||
@@ -243,4 +243,13 @@ const API = {
|
||||
headers: { 'Authorization': `Bearer ${token}` },
|
||||
});
|
||||
},
|
||||
|
||||
// --- Global Admin: Org-Wechsel (herausnehmbar) ---
|
||||
listOrganizations() {
|
||||
return this._request('GET', '/auth/organizations');
|
||||
},
|
||||
|
||||
switchOrg(organizationId) {
|
||||
return this._request('POST', '/auth/switch-org', { organization_id: organizationId });
|
||||
},
|
||||
};
|
||||
|
||||
@@ -515,6 +515,11 @@ const App = {
|
||||
warningEl.textContent = 'Lizenz abgelaufen – nur Lesezugriff';
|
||||
warningEl.classList.add('visible');
|
||||
}
|
||||
|
||||
// --- Global Admin: Org-Switcher (herausnehmbar) ---
|
||||
if (user.is_global_admin) {
|
||||
this._initOrgSwitcher(user.tenant_id);
|
||||
}
|
||||
} catch {
|
||||
window.location.href = '/';
|
||||
return;
|
||||
@@ -2939,6 +2944,42 @@ async handleRefresh() {
|
||||
}
|
||||
},
|
||||
|
||||
// --- Global Admin: Org-Switcher (herausnehmbar) ---
|
||||
async _initOrgSwitcher(currentTenantId) {
|
||||
const section = document.getElementById('org-switcher-section');
|
||||
const select = document.getElementById('org-switcher-select');
|
||||
if (!section || !select) return;
|
||||
|
||||
try {
|
||||
const orgs = await API.listOrganizations();
|
||||
if (!orgs || orgs.length < 2) return;
|
||||
|
||||
section.style.display = 'block';
|
||||
select.innerHTML = '';
|
||||
orgs.forEach(org => {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = org.id;
|
||||
opt.textContent = org.name + (org.is_active ? '' : ' (inaktiv)');
|
||||
if (org.id === currentTenantId) opt.selected = true;
|
||||
select.appendChild(opt);
|
||||
});
|
||||
|
||||
select.addEventListener('change', async () => {
|
||||
const orgId = parseInt(select.value, 10);
|
||||
if (orgId === currentTenantId) return;
|
||||
try {
|
||||
const result = await API.switchOrg(orgId);
|
||||
localStorage.setItem('osint_token', result.access_token);
|
||||
window.location.reload();
|
||||
} catch (err) {
|
||||
console.error('Org-Wechsel fehlgeschlagen:', err);
|
||||
}
|
||||
});
|
||||
} catch {
|
||||
// Kein Global Admin oder Fehler - Switcher bleibt versteckt
|
||||
}
|
||||
},
|
||||
|
||||
logout() {
|
||||
localStorage.removeItem('osint_token');
|
||||
localStorage.removeItem('osint_username');
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren