feat: share SSO session with admin panel
All checks were successful
Build & Push Docker Image to Gitea Registry / build-and-push (push) Successful in 12s

This commit is contained in:
Kroonk
2026-05-21 23:55:18 +02:00
parent 14505c2296
commit ae775c4dcf
7 changed files with 23 additions and 9 deletions

View File

@@ -241,6 +241,6 @@
</div> </div>
</div> </div>
<script src="/admin.js?v=27" defer></script> <script src="/admin.js?v=28" defer></script>
</body> </body>
</html> </html>

View File

@@ -5,6 +5,7 @@ const SCOPES = 'openid profile email';
const CONFIG_URL = '/services.json?v=1'; const CONFIG_URL = '/services.json?v=1';
const LOCAL_CONFIG_KEY = 'mischlabs.dashboard.config'; const LOCAL_CONFIG_KEY = 'mischlabs.dashboard.config';
const TOKEN_KEY = 'mischlabs.admin.tokens'; const TOKEN_KEY = 'mischlabs.admin.tokens';
const DASHBOARD_TOKEN_KEY = 'mischlabs.dashboard.tokens';
const PKCE_KEY = 'mischlabs.admin.pkce'; const PKCE_KEY = 'mischlabs.admin.pkce';
const loginButton = document.querySelector('#loginButton'); const loginButton = document.querySelector('#loginButton');
@@ -69,7 +70,7 @@ function decodeJwt(token) {
function getStoredTokens() { function getStoredTokens() {
try { try {
const raw = sessionStorage.getItem(TOKEN_KEY); const raw = sessionStorage.getItem(TOKEN_KEY) || sessionStorage.getItem(DASHBOARD_TOKEN_KEY);
return raw ? JSON.parse(raw) : null; return raw ? JSON.parse(raw) : null;
} catch { } catch {
return null; return null;
@@ -78,10 +79,12 @@ function getStoredTokens() {
function storeTokens(tokens) { function storeTokens(tokens) {
sessionStorage.setItem(TOKEN_KEY, JSON.stringify(tokens)); sessionStorage.setItem(TOKEN_KEY, JSON.stringify(tokens));
sessionStorage.setItem(DASHBOARD_TOKEN_KEY, JSON.stringify(tokens));
} }
function clearTokens() { function clearTokens() {
sessionStorage.removeItem(TOKEN_KEY); sessionStorage.removeItem(TOKEN_KEY);
sessionStorage.removeItem(DASHBOARD_TOKEN_KEY);
sessionStorage.removeItem(PKCE_KEY); sessionStorage.removeItem(PKCE_KEY);
} }
@@ -1185,6 +1188,9 @@ function closeNavDrawer() {
async function boot() { async function boot() {
await handleCallback(); await handleCallback();
tokenSet = getStoredTokens(); tokenSet = getStoredTokens();
if (isTokenValid(tokenSet)) {
storeTokens(tokenSet);
}
if (!isTokenValid(tokenSet)) { if (!isTokenValid(tokenSet)) {
loginPanel.hidden = false; loginPanel.hidden = false;

6
app.js
View File

@@ -33,6 +33,7 @@ const favoritesSections = document.querySelector('#favoritesSections');
const loginButton = document.querySelector('#dashboardLoginButton'); const loginButton = document.querySelector('#dashboardLoginButton');
const logoutButton = document.querySelector('#dashboardLogoutButton'); const logoutButton = document.querySelector('#dashboardLogoutButton');
const favoritesLink = document.querySelector('#favoritesLink'); const favoritesLink = document.querySelector('#favoritesLink');
const adminPanelLink = document.querySelector('#adminPanelLink');
const userBadge = document.querySelector('#dashboardUserBadge'); const userBadge = document.querySelector('#dashboardUserBadge');
function normalize(value) { function normalize(value) {
@@ -492,9 +493,14 @@ searchInput.addEventListener('input', updateVisibility);
function updateAuthNav() { function updateAuthNav() {
const authenticated = MischLabsAuth.isAuthenticated(); const authenticated = MischLabsAuth.isAuthenticated();
const claims = MischLabsAuth.claims();
const username = String(claims?.preferred_username || '').toLowerCase();
const email = String(claims?.email || '').toLowerCase();
const isAdmin = authenticated && (username === 'mrdiderot' || email === 'mail.misch@pm.me');
if (loginButton) loginButton.hidden = authenticated; if (loginButton) loginButton.hidden = authenticated;
if (logoutButton) logoutButton.hidden = !authenticated; if (logoutButton) logoutButton.hidden = !authenticated;
if (favoritesLink) favoritesLink.hidden = !authenticated; if (favoritesLink) favoritesLink.hidden = !authenticated;
if (adminPanelLink) adminPanelLink.hidden = !isAdmin;
if (userBadge) { if (userBadge) {
userBadge.hidden = !authenticated; userBadge.hidden = !authenticated;
userBadge.textContent = authenticated ? MischLabsAuth.displayName() : ''; userBadge.textContent = authenticated ? MischLabsAuth.displayName() : '';

View File

@@ -195,6 +195,7 @@ const MischLabsAuth = (() => {
handleCallback, handleCallback,
isAuthenticated, isAuthenticated,
login, login,
logout logout,
tokens
}; };
})(); })();

View File

@@ -67,7 +67,7 @@
</section> </section>
</main> </main>
<script src="/auth.js?v=1" defer></script> <script src="/auth.js?v=2" defer></script>
<script src="/favorites.js?v=1" defer></script> <script src="/favorites.js?v=1" defer></script>
</body> </body>
</html> </html>

View File

@@ -45,6 +45,7 @@
<nav class="dashboard-actions" aria-label="Dashboard Aktionen"> <nav class="dashboard-actions" aria-label="Dashboard Aktionen">
<span class="user-badge" id="dashboardUserBadge" hidden></span> <span class="user-badge" id="dashboardUserBadge" hidden></span>
<a class="ghost-button mini" id="adminPanelLink" href="/admin.html" hidden>Admin Panel</a>
<a class="ghost-button mini" id="favoritesLink" href="/favorites.html" hidden>Favoriten</a> <a class="ghost-button mini" id="favoritesLink" href="/favorites.html" hidden>Favoriten</a>
<button class="ghost-button mini" id="dashboardLoginButton" type="button">SSO Login</button> <button class="ghost-button mini" id="dashboardLoginButton" type="button">SSO Login</button>
<button class="ghost-button mini" id="dashboardLogoutButton" type="button" hidden>Abmelden</button> <button class="ghost-button mini" id="dashboardLogoutButton" type="button" hidden>Abmelden</button>
@@ -133,7 +134,7 @@
</svg> </svg>
</div> </div>
<script src="/auth.js?v=1" defer></script> <script src="/auth.js?v=2" defer></script>
<script src="/app.js?v=34" defer></script> <script src="/app.js?v=35" defer></script>
</body> </body>
</html> </html>

6
sw.js
View File

@@ -1,12 +1,12 @@
const CACHE_NAME = 'mischlabs-pwa-v18'; const CACHE_NAME = 'mischlabs-pwa-v19';
const APP_SHELL = [ const APP_SHELL = [
'/', '/',
'/index.html', '/index.html',
'/favorites.html', '/favorites.html',
'/offline.html', '/offline.html',
'/style.css?v=29', '/style.css?v=29',
'/auth.js?v=1', '/auth.js?v=2',
'/app.js?v=34', '/app.js?v=35',
'/favorites.js?v=1', '/favorites.js?v=1',
'/services.json?v=1', '/services.json?v=1',
'/manifest.webmanifest?v=4', '/manifest.webmanifest?v=4',