View source
<?php
namespace Drupal\session_limit;
class SessionLimitBaseTestCase extends DrupalWebTestCase {
protected $curlHandles = array();
protected $loggedInUsers = array();
public function sessionLimitMakeRoles($user = NULL) {
$roles = array();
$roles[] = (object) array(
'name' => 'role1',
);
$roles[] = (object) array(
'name' => 'role2',
);
$roles[] = (object) array(
'name' => 'role3',
);
user_role_save($roles[0]);
user_role_save($roles[1]);
user_role_save($roles[2]);
if (!empty($user)) {
$user->roles[$roles[0]->rid] = $roles[0]->name;
$user->roles[$roles[1]->rid] = $roles[1]->name;
$user->roles[$roles[2]->rid] = $roles[2]->name;
$user
->save();
}
return $roles;
}
public function assertSessionLogout($session_limit, stdClass $user = NULL) {
\Drupal::configFactory()
->getEditable('session_limit.settings')
->set('session_limit_behaviour', 1)
->save();
\Drupal::configFactory()
->getEditable('session_limit.settings')
->set('session_limit_logged_out_message', 'Reached limit @number.')
->save();
$user = empty($user) ? $this
->drupalCreateUser(array(
'access content',
)) : $user;
$sessions = array();
for ($session_number = 1; $session_number <= $session_limit; $session_number++) {
$this
->drupalLogin($user);
$this
->drupalGet('user');
$this
->assertText(t('Log out'), t('User is logged in under session @no.', array(
'@no' => $session_number,
)));
$this
->assertText($user->name, t('User is logged in under session @no.', array(
'@no' => $session_number,
)));
$sessions[$session_number] = $this
->stashSession();
sleep(1);
}
foreach ($sessions as $session_number => $session_id) {
$this
->restoreSession($session_id);
$this
->drupalGet('user');
$this
->assertText(t('Log out'), t('User is logged in under session @no.', array(
'@no' => $session_number,
)));
$this
->assertText($user->name, t('User is logged in under session @no.', array(
'@no' => $session_number,
)));
}
$extra_session_number = $session_limit + 1;
$this
->stashSession();
$this
->drupalLogin($user);
$this
->drupalGet('user');
$this
->assertText(t('Log out'), t('User is logged in under session @no.', array(
'@no' => $extra_session_number,
)));
$this
->assertText($user->name, t('User is logged in under session @no.', array(
'@no' => $extra_session_number,
)));
$sessions[$extra_session_number] = $this
->stashSession();
$this
->restoreSession($sessions[1]);
$this
->drupalGet('node');
$this
->assertNoText(t('Log out'), t('User 1 is not logged in under session 1.'));
$this
->assertText(t('Reached limit @number.', array(
'@number' => $session_limit,
)), t('User was shown session limit message.'));
foreach ($sessions as $session_number => $session_id) {
if ($session_number == 1) {
continue;
}
$this
->restoreSession($session_id);
$this
->drupalGet('user');
$this
->assertText(t('Log out'), t('User is logged in under session @no.', array(
'@no' => $session_number,
)));
$this
->assertText($user->name, t('User is logged in under session @no.', array(
'@no' => $session_number,
)));
}
}
public function assertSessionPrevent($session_limit) {
\Drupal::configFactory()
->getEditable('session_limit.settings')
->set('session_limit_behaviour', 2)
->save();
\Drupal::configFactory()
->getEditable('session_limit.settings')
->set('session_limit_max', $session_limit)
->save();
$user = $this
->drupalCreateUser(array(
'access content',
));
$sessions = array();
for ($session_number = 1; $session_number <= $session_limit; $session_number++) {
$this
->drupalLogin($user);
$this
->drupalGet('user');
$this
->assertText(t('Log out'), t('User is logged in under session @no.', array(
'@no' => $session_number,
)));
$this
->assertText($user->name, t('User is logged in under session @no.', array(
'@no' => $session_number,
)));
$sessions[$session_number] = $this
->stashSession();
}
foreach ($sessions as $session_number => $session_id) {
$this
->restoreSession($session_id);
$this
->drupalGet('user');
$this
->assertText(t('Log out'), t('User is logged in under session @no.', array(
'@no' => $session_number,
)));
$this
->assertText($user->name, t('User is logged in under session @no.', array(
'@no' => $session_number,
)));
}
$this
->stashSession();
$this
->drupalLoginExpectFail($user);
$this
->assertText(t('The maximum number of simultaneous sessions (@session_limit) for your account has been reached. You did not log off from a previous session or someone else is logged on to your account. This may indicate that your account has been compromised or that account sharing is limited on this site. Please contact the site administrator if you suspect your account has been compromised.', array(
'@session_limit' => $session_limit,
)), t('User sees the session limit login prevention message.'));
$extra_session_number = $session_limit + 1;
$sessions[$extra_session_number] = $this
->stashSession();
$this
->restoreSession($sessions[1]);
$this
->drupalLogout($user);
$this
->drupalGet('node');
$this
->assertNoText(t('Log out'), t('User has logged out of session 1.'));
$this
->restoreSession($sessions[$extra_session_number]);
$this
->drupalLogin($user);
$this
->drupalGet('node');
$this
->assertText(t('Log out'), t('User has logged into the extra session now they have logged out of session 1.'));
}
public function stashSession() {
if (empty($this->cookieFile)) {
return;
}
$session_id = $this->cookieFile;
$this->curlHandles[$session_id] = $this->curlHandle;
$this->loggedInUsers[$session_id] = $this->loggedInUser;
unset($this->curlHandle);
$this->loggedInUser = FALSE;
do {
$this->cookieFile = $this->public_files_directory . '/' . $this
->randomName() . '.jar';
} while (isset($this->curlHandles[$this->cookieFile]));
return $session_id;
}
public function restoreSession($session_id) {
$old_session_id = NULL;
if (isset($this->curlHandle)) {
$old_session_id = $this
->stashSession();
}
$this->curlHandle = $this->curlHandles[$session_id];
$this->cookieFile = $session_id;
$this->loggedInUser = $this->loggedInUsers[$session_id];
return $old_session_id;
}
public function closeAllSessions() {
foreach ($this->curlHandles as $cookie_file => $curl_handle) {
if (isset($curl_handle)) {
curl_close($curl_handle);
}
}
db_truncate('sessions')
->execute();
$this->curlHandles = array();
$this->loggedInUsers = array();
$this->loggedInUser = FALSE;
$this->cookieFile = $this->public_files_directory . '/' . $this
->randomName() . '.jar';
unset($this->curlHandle);
}
protected function drupalLoginExpectFail(stdClass $account) {
if ($this->loggedInUser) {
$this
->drupalLogout();
}
$edit = array(
'name' => $account->name,
'pass' => $account->pass_raw,
);
$this
->drupalPost('user', $edit, t('Log in'));
$pass = $this
->assertNoLink(t('Log out'), 0, t('User %name did not log in.', array(
'%name' => $account->name,
)), t('User login'));
if (!$pass) {
$this->loggedInUser = $account;
}
}
}