added session revocation and settings menu for security measures
This commit is contained in:
@ -230,6 +230,9 @@ function updateRoleGroupTable(roleKey, myUsername) {
|
||||
role: btn.dataset.role || '',
|
||||
}));
|
||||
});
|
||||
tbody.querySelectorAll('.revoke-sessions-btn').forEach(btn => {
|
||||
btn.addEventListener('click', () => revokeUserSessions(btn.dataset.id, btn.dataset.name));
|
||||
});
|
||||
tbody.querySelectorAll('.coach-supervisor-select').forEach(sel => {
|
||||
sel.addEventListener('change', () => reassignCoachSupervisor(sel));
|
||||
});
|
||||
@ -276,6 +279,10 @@ function userRowHTML(u, myUsername) {
|
||||
(callerRole === 'admin' && (u.role === 'supervisor' || u.role === 'coach')) ||
|
||||
(callerRole === 'supervisor' && u.role === 'coach')
|
||||
);
|
||||
const canRevokeSessions = !isSelf && (
|
||||
callerRole === 'admin' ||
|
||||
(callerRole === 'supervisor' && u.role === 'coach')
|
||||
);
|
||||
|
||||
const actions = [];
|
||||
if (canResetPassword) {
|
||||
@ -283,6 +290,11 @@ function userRowHTML(u, myUsername) {
|
||||
`<button type="button" class="btn btn-sm reset-password-btn" data-id="${u.userID}" data-name="${esc(u.username)}" data-role="${esc(u.role)}">Reset password</button>`
|
||||
);
|
||||
}
|
||||
if (canRevokeSessions) {
|
||||
actions.push(
|
||||
`<button type="button" class="btn btn-sm revoke-sessions-btn" data-id="${u.userID}" data-name="${esc(u.username)}">Sign out everywhere</button>`
|
||||
);
|
||||
}
|
||||
if (canDelete) {
|
||||
actions.push(
|
||||
`<button type="button" class="btn btn-sm btn-danger delete-user-btn" data-id="${u.userID}" data-name="${esc(u.username)}">Delete</button>`
|
||||
@ -330,6 +342,23 @@ async function reassignCoachSupervisor(selectEl) {
|
||||
}
|
||||
}
|
||||
|
||||
async function revokeUserSessions(userID, username) {
|
||||
if (!confirm(
|
||||
`Sign out "${username}" on all devices?\n\n`
|
||||
+ 'They must log in again on the website and mobile app.'
|
||||
)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const data = await apiPut('users.php', { action: 'revokeSessions', userID });
|
||||
if (!data.success) throw new Error(data.error || 'Failed');
|
||||
const n = data.revokedSessions ?? 0;
|
||||
showToast(`Signed out "${username}" (${n} session${n === 1 ? '' : 's'} revoked)`, 'success');
|
||||
} catch (e) {
|
||||
showToast(e.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteUser(userID, username) {
|
||||
if (!confirm(`Delete user "${username}"? This cannot be undone.`)) return;
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user