id = null; $this->authId = null; $this->csrfSalt = null; $this->login = null; } public function makeCSRFSalt(string $salted_password): void { $this->csrfSalt = salt_password(strrev($salted_password)); } }; function is_admin(): bool { global $AdminSession; if ($AdminSession->id === null) _admin_check(); return $AdminSession->id != 0; } function admin_exists(string $login): bool { $db = DB(); return (int)$db->result($db->query("SELECT COUNT(*) FROM admins WHERE login=? LIMIT 1", $login)) > 0; } function admin_add(string $login, string $password): int { $db = DB(); $db->insert('admins', [ 'login' => $login, 'password' => salt_password($password), 'activity_ts' => 0 ]); return $db->insertId(); } function admin_delete(string $login): bool { $db = DB(); $id = admin_get_id_by_login($login); if (!$db->query("DELETE FROM admins WHERE login=?", $login)) return false; if (!$db->query("DELETE FROM admin_auth WHERE admin_id=?", $id)) return false; return true; } /** * @param int[] $ids * @return string[] */ function admin_get_logins_by_id(array $ids): array { $db = DB(); $logins = []; $q = $db->query("SELECT id, login FROM admins WHERE id IN (".implode(',', $ids).")"); while ($row = $db->fetch($q)) { $logins[(int)$row['id']] = $row['login']; } return $logins; } function admin_get_id_by_login(string $login): ?int { $db = DB(); $q = $db->query("SELECT id FROM admins WHERE login=?", $login); return $db->numRows($q) > 0 ? (int)$db->result($q) : null; } function admin_set_password(string $login, string $password): bool { $db = DB(); $db->query("UPDATE admins SET password=? WHERE login=?", salt_password($password), $login); return $db->affectedRows() > 0; } function admin_auth(string $login, string $password): bool { global $AdminSession; $db = DB(); $salted_password = salt_password($password); $q = $db->query("SELECT id, active FROM admins WHERE login=? AND password=?", $login, $salted_password); if (!$db->numRows($q)) return false; $row = $db->fetch($q); $id = (int)$row['id']; $active = (bool)$row['active']; if (!$active) return false; $time = time(); do { $token = strgen(32); } while ($db->numRows($db->query("SELECT id FROM admin_auth WHERE token=? LIMIT 1", $token)) > 0); $db->insert('admin_auth', [ 'admin_id' => $id, 'token' => $token, 'ts' => $time ]); $auth_id = $db->insertId(); $db->insert('admin_log', [ 'admin_id' => $id, 'ts' => $time, 'ip' => ip2ulong($_SERVER['REMOTE_ADDR']), 'ua' => $_SERVER['HTTP_USER_AGENT'] ?? '', ]); $db->query("UPDATE admins SET activity_ts=? WHERE id=?", $time, $id); $AdminSession->id = $id; $AdminSession->login = $login; $AdminSession->makeCSRFSalt($salted_password); $AdminSession->authId = $auth_id; _admin_set_cookie($token); return true; } function admin_logout() { if (!is_admin()) return; global $AdminSession; $db = DB(); $db->query("DELETE FROM admin_auth WHERE id=?", $AdminSession->authId); $AdminSession->mrProper(); _admin_unset_cookie(); } function admin_log(\AdminActions\BaseAction $action) { \AdminActions\Util\Logger::record($action); } function _admin_check(): void { if (!isset($_COOKIE[ADMIN_COOKIE_NAME])) return; $cookie = (string)$_COOKIE[ADMIN_COOKIE_NAME]; $db = DB(); $time = time(); $q = $db->query("SELECT admin_auth.id AS auth_id, admin_auth.admin_id AS id, admins.activity_ts AS activity_ts, admins.password AS salted_password, admins.login AS login FROM admin_auth LEFT JOIN admins ON admin_auth.admin_id=admins.id WHERE admin_auth.token=? LIMIT 1", $cookie); if (!$db->numRows($q)) return; $info = $db->fetch($q); global $AdminSession; $AdminSession->id = (int)$info['id']; $AdminSession->login = $info['login']; $AdminSession->authId = (int)$info['auth_id']; $AdminSession->makeCSRFSalt($info['salted_password']); if ($time - $info['activity_ts'] > 15) $db->query("UPDATE admins SET activity_ts=? WHERE id=?", $time, $AdminSession->id); } function _admin_set_cookie(string $token): void { global $config; setcookie(ADMIN_COOKIE_NAME, $token, time() + ADMIN_SESSION_TIMEOUT, '/', $config['cookie_host']); } function _admin_unset_cookie(): void { global $config; setcookie(ADMIN_COOKIE_NAME, '', 1, '/', $config['cookie_host']); }