diff --git a/common.php b/common.php
index daa69cd..9b8a9ef 100644
--- a/common.php
+++ b/common.php
@@ -286,9 +286,15 @@ function qdb_is_web_client_request(): bool {
return strtolower(trim($h)) === 'web';
}
-/** Reject coach sign-in from the website; coaches use the mobile app only. */
+/** Website or coordinator mobile app — not the counselor field app. */
+function qdb_is_management_client_request(): bool {
+ $h = strtolower(trim($_SERVER['HTTP_X_QDB_CLIENT'] ?? ''));
+ return in_array($h, ['web', 'coordinator'], true);
+}
+
+/** Reject coach sign-in from management clients; coaches use the field app only. */
function qdb_reject_coach_web_login(string $role): void {
- if ($role === 'coach' && qdb_is_web_client_request()) {
+ if ($role === 'coach' && qdb_is_management_client_request()) {
json_error(
'FORBIDDEN',
'Counselor accounts can only sign in through the mobile app.',
diff --git a/website/js/pages/users.js b/website/js/pages/users.js
index fd84b65..9f8a537 100644
--- a/website/js/pages/users.js
+++ b/website/js/pages/users.js
@@ -246,7 +246,7 @@ function userRowHTML(u, myUsername) {
: '—';
const pwBadge = u.mustChangePassword == 1
? 'Temporary'
- : 'Permanent';
+ : '';
const canDelete = !isSelf && (
callerRole === 'admin' ||
@@ -408,25 +408,9 @@ function showCreateForm() {
}
-
+
+ They must choose their own password on first sign-in.
+
@@ -476,7 +460,7 @@ async function submitCreateUser() {
const username = document.getElementById('cu_username').value.trim();
const password = document.getElementById('cu_password').value;
const role = isSupervisor ? 'coach' : (document.getElementById('cu_role').value || 'coach');
- const mustChange = document.querySelector('input[name="cu_pw_mode"]:checked')?.value === 'temporary' ? 1 : 0;
+ const mustChange = 1;
let location = '';
let supervisorID = '';
diff --git a/website/js/password-modal.js b/website/js/password-modal.js
index 33d05af..8fb35a3 100644
--- a/website/js/password-modal.js
+++ b/website/js/password-modal.js
@@ -39,25 +39,9 @@ function ensurePasswordModal() {
Password
-
+
+ They sign in with the password below, then must choose their own password before they can continue.
+
@@ -115,13 +99,9 @@ function openPasswordModal(options) {
? 'You will stay signed in after saving. Use this password on your next login.'
: signInHintForRole(role);
- modal.querySelector('#passwordModalModeFieldset').style.display = isSelf ? 'none' : '';
+ modal.querySelector('#passwordModalTempHint').style.display = isSelf ? 'none' : '';
modal.querySelector('#passwordModalOldGroup').style.display = isSelf ? '' : 'none';
- if (!isSelf) {
- modal.querySelector('input[name="pw_mode"][value="temporary"]').checked = true;
- }
-
modal.querySelector('#pw_old_password').value = '';
modal.querySelector('#pw_new_password').value = '';
modal.querySelector('#pw_new_password_confirm').value = '';
@@ -201,27 +181,23 @@ async function submitPasswordModal() {
return;
}
- const mode = modal.querySelector('input[name="pw_mode"]:checked')?.value || 'temporary';
- const temporary = mode === 'temporary';
const { userID, username } = modalContext;
const data = await apiPatch('users.php', {
userID,
password: newPassword,
- mustChangePassword: temporary ? 1 : 0,
+ mustChangePassword: 1,
});
if (!data.success) throw new Error(data.error || 'Failed to reset password');
closePasswordModal();
showToast(
- temporary
- ? `Temporary password set for "${username}" — they must change it on next sign-in`
- : `Permanent password set for "${username}"`,
+ `Temporary password set for "${username}" — they must change it on next sign-in`,
'success'
);
document.dispatchEvent(new CustomEvent('qdb:password-reset', {
- detail: { userID, mustChangePassword: data.mustChangePassword ?? (temporary ? 1 : 0) },
+ detail: { userID, mustChangePassword: data.mustChangePassword ?? 1 },
}));
} catch (e) {
showModalError(errEl, e.message);