my own indieAuth provider! indiko.dunkirk.sh/docs
indieauth oauth2-server
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: prevent being deactivated as an admin

+13 -4
+7 -4
src/client/admin.ts
··· 1 1 const token = localStorage.getItem('indiko_session'); 2 2 const footer = document.getElementById('footer') as HTMLElement; 3 3 const usersList = document.getElementById('usersList') as HTMLElement; 4 + let currentUserId: number; 4 5 5 6 // Check auth and display user 6 7 async function checkAuth() { ··· 23 24 } 24 25 25 26 const data = await response.json(); 27 + currentUserId = data.id; 26 28 27 29 footer.innerHTML = `admin • signed in as <strong><a href="/u/${data.username}">${data.username}</a></strong> • <a href="/login" id="logoutLink">sign out</a> 28 30 <div class="back-link"><a href="/">← back to dashboard</a></div>`; ··· 95 97 const avatarContent = user.photo 96 98 ? `<img src="${user.photo}" alt="${user.username}" />` 97 99 : initials; 100 + const isSelf = user.id === currentUserId; 98 101 99 102 return ` 100 103 <div class="user-card ${user.status === 'suspended' ? 'user-suspended' : ''}" data-user-id="${user.id}"> 101 104 <div class="user-avatar">${avatarContent}</div> 102 105 <div class="user-info"> 103 - <div class="user-name">${user.username}</div> 106 + <div class="user-name">${user.username}${isSelf ? ' (you)' : ''}</div> 104 107 <div class="user-meta"> 105 108 <span class="user-meta-item">${user.credentialCount} passkey${user.credentialCount !== 1 ? 's' : ''}</span> 106 109 <span class="user-meta-item">joined ${createdDate}</span> ··· 112 115 <span class="user-badge badge-role">${user.role}</span> 113 116 </div> 114 117 <div class="user-actions"> 115 - ${user.status === 'suspended' 118 + ${!isSelf ? (user.status === 'suspended' 116 119 ? `<button class="btn-edit" data-action="enable" data-user-id="${user.id}">enable</button>` 117 120 : `<button class="btn-disable" data-action="disable" data-user-id="${user.id}">disable</button>` 118 - } 119 - <button class="btn-delete" data-action="delete" data-user-id="${user.id}">delete</button> 121 + ) : ''} 122 + ${!isSelf ? `<button class="btn-delete" data-action="delete" data-user-id="${user.id}">delete</button>` : ''} 120 123 </div> 121 124 </div> 122 125 `;
+6
src/routes/api.ts
··· 45 45 46 46 return Response.json({ 47 47 message: `Hello ${user.username}! You're authenticated with passkeys.`, 48 + id: user.userId, 48 49 username: user.username, 49 50 isAdmin: user.is_admin, 50 51 }); ··· 393 394 const targetUserId = Number.parseInt(userId, 10); 394 395 if (Number.isNaN(targetUserId)) { 395 396 return Response.json({ error: "Invalid user ID" }, { status: 400 }); 397 + } 398 + 399 + // Prevent disabling self 400 + if (targetUserId === user.id) { 401 + return Response.json({ error: "Cannot disable your own account" }, { status: 400 }); 396 402 } 397 403 398 404 const targetUser = db