Files
saqel/backend/scripts/provision_staff_account.php
T

68 lines
3.5 KiB
PHP

<?php
/**
* Provision a privileged staff account from the server terminal.
* Usage: php scripts/provision_staff_account.php [role] [phone] [full_name]
* Roles: super_admin, school_admin, directorate_admin, supervisor
*/
declare(strict_types=1);
require_once __DIR__ . '/../app/bootstrap.php';
use App\Core\Database;
use App\Core\Security;
$roles = ['super_admin', 'school_admin', 'directorate_admin', 'supervisor'];
$role = trim((string)($argv[1] ?? ''));
$phone = trim((string)($argv[2] ?? ''));
$name = trim((string)($argv[3] ?? ''));
if (!in_array($role, $roles, true)) {
fwrite(STDERR, "Role must be one of: " . implode(', ', $roles) . "\n");
exit(2);
}
$phone = preg_replace('/\D+/', '', $phone) ?: '';
if (str_starts_with($phone, '07')) $phone = '962' . substr($phone, 1);
if (str_starts_with($phone, '7') && strlen($phone) === 9) $phone = '962' . $phone;
if (strlen($phone) < 9 || strlen($phone) > 15 || $name === '') {
fwrite(STDERR, "Usage: php scripts/provision_staff_account.php ROLE PHONE FULL_NAME\n");
exit(2);
}
$schoolId = null;
$directorateId = null;
if ($role === 'school_admin') {
$schoolId = (int)trim((string)readline('School ID: '));
if ($schoolId < 1) { fwrite(STDERR, "A valid School ID is required.\n"); exit(2); }
} elseif (in_array($role, ['directorate_admin', 'supervisor'], true)) {
$directorateId = (int)trim((string)readline('Directorate ID: '));
if ($directorateId < 1) { fwrite(STDERR, "A valid Directorate ID is required.\n"); exit(2); }
}
try {
$phoneHash = Security::blindIndex($phone);
$identity = Database::selectOne('SELECT id FROM auth_identities WHERE phone_hash = ? LIMIT 1', [$phoneHash]);
if ($identity) {
$identityId = (int)$identity['id'];
Database::query("UPDATE auth_identities SET status = 'active', token_version = token_version + 1 WHERE id = ?", [$identityId]);
} else {
$uuid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff));
$identityId = Database::insert('INSERT INTO auth_identities (uuid, phone_number, phone_hash, status, token_version) VALUES (?, ?, ?, \'active\', 1)', [$uuid, Security::encrypt($phone), $phoneHash]);
}
$staff = Database::selectOne('SELECT id FROM staff_accounts WHERE identity_id = ? AND role = ? LIMIT 1', [$identityId, $role]);
if ($staff) {
Database::query('UPDATE staff_accounts SET full_name = ?, school_id = ?, directorate_id = ?, status = \'active\' WHERE id = ?', [$name, $schoolId, $directorateId, (int)$staff['id']]);
$staffId = (int)$staff['id'];
$action = 'updated';
} else {
$uuid = sprintf('%04x%04x-%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff));
$staffId = Database::insert('INSERT INTO staff_accounts (uuid, identity_id, full_name, role, school_id, directorate_id, status) VALUES (?, ?, ?, ?, ?, ?, \'active\')', [$uuid, $identityId, $name, $role, $schoolId, $directorateId]);
$action = 'created';
}
echo "Staff account {$action}: id={$staffId}, role={$role}, identity_id={$identityId}\n";
echo "The user can now sign in through OTP; no password is created.\n";
} catch (Throwable $e) {
fwrite(STDERR, "Provisioning failed: {$e->getMessage()}\n");
exit(1);
}