Commit 4d85fa44 authored by alexpott's avatar alexpott

Issue #1825332 by Berdir, ParisLiakos, andypost, dawehner, jrglasgow,...

Issue #1825332 by Berdir, ParisLiakos, andypost, dawehner, jrglasgow, aspilicious: Introduce an AccountInterface to represent the current user.
parent da83b1ab
......@@ -21,8 +21,7 @@
use Drupal\Core\Language\Language;
use Drupal\Core\Lock\DatabaseLockBackend;
use Drupal\Core\Lock\LockBackendInterface;
use Drupal\user\Plugin\Core\Entity\User;
use Drupal\Core\Entity\EntityBCDecorator;
use Drupal\Core\Session\UserSession;
/**
* @file
......@@ -1733,15 +1732,16 @@ function drupal_set_title($title = NULL, $output = CHECK_PLAIN) {
/**
* Generates a default anonymous $user object.
*
* @return object
* The user object.
* @return \Drupal\Core\Session\AccountInterface
* The user session object.
*/
function drupal_anonymous_user() {
return (object) array(
$values = array(
'uid' => 0,
'hostname' => Drupal::request()->getClientIP(),
'roles' => array(DRUPAL_ANONYMOUS_RID),
);
return new UserSession($values);
}
/**
......
......@@ -548,14 +548,14 @@ function hook_entity_field_info_alter(&$info, $entity_type) {
* \Drupal\Core\TypedData\AccessibleInterface::access() for possible values.
* @param \Drupal\Core\Entity\Field\Type\Field $field
* The entity field object on which the operation is to be performed.
* @param \Drupal\user\UserInterface $account
* @param \Drupal\Core\Session\AccountInterface $account
* The user account to check.
*
* @return bool|NULL
* TRUE if access should be allowed, FALSE if access should be denied and NULL
* if the implementation has no opinion.
*/
function hook_entity_field_access($operation, $field, $account) {
function hook_entity_field_access($operation, $field, \Drupal\Core\Session\AccountInterface $account) {
if ($field->getName() == 'field_of_interest' && $operation == 'update') {
return user_access('update field of interest', $account);
}
......
......@@ -18,6 +18,8 @@
use Drupal\Component\Utility\Crypt;
use Drupal\Core\Session\UserSession;
/**
* Session handler assigned by session_set_save_handler().
*
......@@ -91,22 +93,27 @@ function _drupal_session_read($sid) {
// a HTTPS session or we are about to log in so we check the sessions table
// for an anonymous session with the non-HTTPS-only cookie.
if (Drupal::request()->isSecure()) {
$user = db_query("SELECT u.*, s.* FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.ssid = :ssid", array(':ssid' => $sid))->fetchObject();
if (!$user) {
$values = db_query("SELECT u.*, s.* FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.ssid = :ssid", array(':ssid' => $sid))->fetchAssoc();
if (!$values) {
if (isset($_COOKIE[$insecure_session_name])) {
$user = db_query("SELECT u.*, s.* FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.sid = :sid AND s.uid = 0", array(
$values = db_query("SELECT u.*, s.* FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.sid = :sid AND s.uid = 0", array(
':sid' => $_COOKIE[$insecure_session_name]))
->fetchObject();
->fetchAssoc();
}
}
}
else {
$user = db_query("SELECT u.*, s.* FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.sid = :sid", array(':sid' => $sid))->fetchObject();
$values = db_query("SELECT u.*, s.* FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.sid = :sid", array(':sid' => $sid))->fetchAssoc();
}
if ($values) {
$user = new UserSession($values);
}
// We found the client's session record and they are an authenticated,
// active user.
if ($user && $user->uid > 0 && $user->status == 1) {
if ($values && $values['uid'] > 0 && $values['status'] == 1) {
$user = new UserSession($values);
// Add roles element to $user.
$rids = db_query("SELECT ur.rid FROM {users_roles} ur WHERE ur.uid = :uid", array(':uid' => $user->uid))->fetchCol();
$user->roles = array_merge(array(DRUPAL_AUTHENTICATED_RID), $rids);
......
......@@ -12,6 +12,7 @@
use Drupal\Core\TypedData\TypedDataInterface;
use Drupal\user\UserInterface;
use IteratorAggregate;
use Drupal\Core\Session\AccountInterface;
/**
* Defines a base entity class.
......@@ -258,7 +259,7 @@ public function getIterator() {
/**
* Implements \Drupal\Core\TypedData\AccessibleInterface::access().
*/
public function access($operation = 'view', UserInterface $account = NULL) {
public function access($operation = 'view', AccountInterface $account = NULL) {
return \Drupal::entityManager()
->getAccessController($this->entityType)
->access($this, $operation, Language::LANGCODE_DEFAULT, $account);
......
......@@ -8,7 +8,7 @@
namespace Drupal\Core\Entity;
use Drupal\Core\Language\Language;
use Drupal\user\UserInterface;
use Drupal\Core\Session\AccountInterface;
/**
* Defines a default implementation for entity access controllers.
......@@ -25,11 +25,9 @@ class EntityAccessController implements EntityAccessControllerInterface {
/**
* {@inheritdoc}
*/
public function access(EntityInterface $entity, $operation, $langcode = Language::LANGUAGE_DEFAULT, UserInterface $account = NULL) {
// @todo Remove this once we can rely on $account.
public function access(EntityInterface $entity, $operation, $langcode = Language::LANGUAGE_DEFAULT, AccountInterface $account = NULL) {
if (!$account) {
$account = user_load($GLOBALS['user']->uid);
$account = $GLOBALS['user'];
}
if (($access = $this->getCache($entity, $operation, $langcode, $account)) !== NULL) {
......@@ -73,14 +71,14 @@ public function access(EntityInterface $entity, $operation, $langcode = Language
* 'delete'.
* @param string $langcode
* The language code for which to check access.
* @param \Drupal\user\UserInterface $account
* @param \Drupal\Core\Session\AccountInterface; $account
* The user for which to check access.
*
* @return bool|null
* TRUE if access was granted, FALSE if access was denied and NULL if access
* could not be determined.
*/
protected function checkAccess(EntityInterface $entity, $operation, $langcode, UserInterface $account) {
protected function checkAccess(EntityInterface $entity, $operation, $langcode, AccountInterface $account) {
return NULL;
}
......@@ -94,7 +92,7 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, U
* 'delete'.
* @param string $langcode
* The language code for which to check access.
* @param \Drupal\user\UserInterface $account
* @param \Drupal\Core\Session\AccountInterface $account
* The user for which to check access.
*
* @return bool|null
......@@ -102,7 +100,7 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, U
* is no record for the given user, operation, langcode and entity in the
* cache.
*/
protected function getCache(EntityInterface $entity, $operation, $langcode, UserInterface $account) {
protected function getCache(EntityInterface $entity, $operation, $langcode, AccountInterface $account) {
$uid = $account ? $account->id() : 0;
$uuid = $entity->uuid();
......@@ -122,13 +120,13 @@ protected function getCache(EntityInterface $entity, $operation, $langcode, User
* 'delete'.
* @param string $langcode
* The language code for which to check access.
* @param \Drupal\user\UserInterface $account
* @param \Drupal\Core\Session\AccountInterface $account
* The user for which to check access.
*
* @return bool
* TRUE if access was granted, FALSE otherwise.
*/
protected function setCache($access, EntityInterface $entity, $operation, $langcode, UserInterface $account) {
protected function setCache($access, EntityInterface $entity, $operation, $langcode, AccountInterface $account) {
$uid = $account ? $account->id() : 0;
$uuid = $entity->uuid();
......
......@@ -8,8 +8,7 @@
namespace Drupal\Core\Entity;
use Drupal\Core\Language\Language;
// @todo Don't depend on module level code.
use Drupal\user\UserInterface;
use Drupal\Core\Session\AccountInterface;
/**
* Defines a common interface for entity access controller classes.
......@@ -27,14 +26,14 @@ interface EntityAccessControllerInterface {
* @param string $langcode
* (optional) The language code for which to check access. Defaults to
* Language::LANGCODE_DEFAULT.
* @param \Drupal\user\UserInterface $account
* (optional) The user for which to check access, or NULL to check access
* for the current user. Defaults to NULL.
* @param \Drupal\Core\Session\AccountInterface $account
* (optional) The user session for which to check access, or NULL to check
* access for the current user. Defaults to NULL.
*
* @return bool
* TRUE if access was granted, FALSE otherwise.
*/
public function access(EntityInterface $entity, $operation, $langcode = Language::LANGUAGE_DEFAULT, UserInterface $account = NULL);
public function access(EntityInterface $entity, $operation, $langcode = Language::LANGCODE_DEFAULT, AccountInterface $account = NULL);
/**
* Clears all cached access checks.
......
......@@ -11,7 +11,7 @@
use IteratorAggregate;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\TypedData\TypedDataInterface;
use Drupal\user\UserInterface;
use Drupal\Core\Session\AccountInterface;
/**
* Provides backwards compatible (BC) access to entity fields.
......@@ -214,7 +214,7 @@ function __clone() {
/**
* Forwards the call to the decorated entity.
*/
public function access($operation = 'view', UserInterface $account = NULL) {
public function access($operation = 'view', AccountInterface $account = NULL) {
return $this->decorated->access($operation, $account);
}
......
......@@ -7,10 +7,10 @@
namespace Drupal\Core\Entity\Field\Type;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\TypedData\AccessibleInterface;
use Drupal\Core\TypedData\ComplexDataInterface;
use Drupal\Core\TypedData\TypedData;
use Drupal\user\UserInterface;
use ArrayIterator;
use Drupal\Core\TypedData\TypedDataInterface;
use IteratorAggregate;
......@@ -211,7 +211,7 @@ public function onChange($property_name) {
/**
* Implements \Drupal\Core\TypedData\AccessibleInterface::access().
*/
public function access($operation = 'view', UserInterface $account = NULL) {
public function access($operation = 'view', AccountInterface $account = NULL) {
// Determine the language code of this translation by cutting of the
// leading "@" from the property name to get the langcode.
// @todo Add a way to set and get the langcode so that's more obvious what
......
......@@ -8,7 +8,7 @@
namespace Drupal\Core\Entity\Field\Type;
use Drupal\Core\Entity\Field\FieldInterface;
use Drupal\user\UserInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\TypedData\TypedDataInterface;
use Drupal\Core\TypedData\ItemList;
......@@ -145,7 +145,7 @@ public function __unset($property_name) {
/**
* Implements \Drupal\Core\TypedData\AccessibleInterface::access().
*/
public function access($operation = 'view', UserInterface $account = NULL) {
public function access($operation = 'view', AccountInterface $account = NULL) {
global $user;
if (!isset($account) && $user->uid) {
$account = user_load($user->uid);
......@@ -190,7 +190,7 @@ public function access($operation = 'view', UserInterface $account = NULL) {
* @return bool
* TRUE if access to this field is allowed per default, FALSE otherwise.
*/
public function defaultAccess($operation = 'view', UserInterface $account = NULL) {
public function defaultAccess($operation = 'view', AccountInterface $account = NULL) {
// Grant access per default.
return TRUE;
}
......
<?php
/**
* @file
* Contains \Drupal\Core\Session\AccountInterface.
*/
namespace Drupal\Core\Session;
/**
* Defines an account interface which represents the current user.
*
* Defines an object that has a user id, roles and can have session data. The
* interface is implemented both by the global session and the user entity.
*/
interface AccountInterface {
/**
* Returns the user ID or 0 for anonymous.
*
* @return int
* The user ID.
*/
public function id();
/**
* Returns a list of roles.
*
* @return array
* List of role IDs.
*/
public function getRoles();
/**
* Returns the session ID.
*
* @return string|NULL
* The session ID or NULL if this user does not have an active session.
*/
public function getSessionId();
/**
* Returns the secure session ID.
*
* @return string|NULL
* The session ID or NULL if this user does not have an active secure session.
*/
public function getSecureSessionId();
/**
* Returns the session data.
*
* @return array
* Array with the session data that belongs to this object.
*/
public function getSessionData();
}
<?php
/**
* @file
* Contains \Drupal\Core\Session\UserSession.
*/
namespace Drupal\Core\Session;
/**
* An implementation of the user account interface for the global user.
*
* @todo: Change all properties to protected.
*/
class UserSession implements AccountInterface {
/**
* User ID.
*
* @var int
*/
public $uid;
/**
* Session hostname.
*
* @todo: This does not seem to be used, remove?
*
* @var string
*/
public $hostname;
/**
* List of the roles this user has.
*
* @var array
*/
public $roles;
/**
* Session ID.
*
* @var string.
*/
public $sid;
/**
* Secure session ID.
*
* @var string.
*/
public $ssid;
/**
* Session data.
*
* @var array.
*/
public $session;
/**
* The Unix timestamp when this session last requested a page.
*
* @var string.
*/
public $timestamp;
/**
* Constructs a new user session.
*
* @param array $values
* Array of initial values for the user sesion.
*/
public function __construct(array $values = array()) {
foreach ($values as $key => $value) {
$this->$key = $value;
}
}
/**
* {@inheritdoc}
*/
public function id() {
return $this->uid;
}
/**
* {@inheritdoc}
*/
public function getRoles() {
return $this->roles;
}
/**
* {@inheritdoc}
*/
public function getSecureSessionId() {
return $this->ssid;
}
/**
* {@inheritdoc}
*/
public function getSessionData() {
return $this->session;
}
/**
* {@inheritdoc}
*/
public function getSessionId() {
return $this->sid;
}
}
......@@ -7,7 +7,7 @@
namespace Drupal\Core\TypedData;
use Drupal\user\UserInterface;
use Drupal\Core\Session\AccountInterface;
/**
* Interface for checking access.
......@@ -24,7 +24,7 @@ interface AccessibleInterface {
* - update
* - delete
* Defaults to 'view'.
* @param \Drupal\user\UserInterface $account
* @param Drupal\Core\Session\AccountInterface $account
* (optional) The user for which to check access, or NULL to check access
* for the current user. Defaults to NULL.
*
......@@ -34,6 +34,6 @@ interface AccessibleInterface {
*
* @todo Don't depend on module level code.
*/
public function access($operation = 'view', UserInterface $account = NULL);
public function access($operation = 'view', AccountInterface $account = NULL);
}
......@@ -8,8 +8,8 @@
namespace Drupal\custom_block;
use Drupal\Core\Entity\EntityInterface;
use Drupal\user\UserInterface;
use Drupal\Core\Entity\EntityAccessController;
use Drupal\Core\Session\AccountInterface;
/**
* Defines the access controller for the custom block entity type.
......@@ -19,7 +19,7 @@ class CustomBlockAccessController extends EntityAccessController {
/**
* {@inheritdoc}
*/
protected function checkAccess(EntityInterface $entity, $operation, $langcode, UserInterface $account) {
protected function checkAccess(EntityInterface $entity, $operation, $langcode, AccountInterface $account) {
if ($operation === 'view') {
return TRUE;
}
......
......@@ -9,7 +9,7 @@
use Drupal\Core\Entity\EntityAccessController;
use Drupal\Core\Entity\EntityInterface;
use Drupal\user\UserInterface;
use Drupal\Core\Session\AccountInterface;
/**
* Provides a Block access controller.
......@@ -19,7 +19,7 @@ class BlockAccessController extends EntityAccessController {
/**
* {@inheritdoc}
*/
protected function checkAccess(EntityInterface $entity, $operation, $langcode, UserInterface $account) {
protected function checkAccess(EntityInterface $entity, $operation, $langcode, AccountInterface $account) {
// Currently, only view access is implemented.
if ($operation != 'view') {
return FALSE;
......
......@@ -9,7 +9,7 @@
use Drupal\Core\Entity\EntityAccessController;
use Drupal\Core\Entity\EntityInterface;
use Drupal\user\UserInterface;
use Drupal\Core\Session\AccountInterface;
/**
* Access controller for the comment entity.
......@@ -21,7 +21,7 @@ class CommentAccessController extends EntityAccessController {
/**
* {@inheritdoc}
*/
protected function checkAccess(EntityInterface $entity, $operation, $langcode, UserInterface $account) {
protected function checkAccess(EntityInterface $entity, $operation, $langcode, AccountInterface $account) {
switch ($operation) {
case 'view':
return user_access('access comments', $account);
......
......@@ -9,8 +9,7 @@
use Drupal\Core\Entity\EntityAccessController;
use Drupal\Core\Entity\EntityInterface;
use Drupal\user\UserInterface;
use Drupal\Core\Session\AccountInterface;
/**
* Defines an access controller for the contact category entity.
*
......@@ -21,7 +20,7 @@ class CategoryAccessController extends EntityAccessController {
/**
* {@inheritdoc}
*/
public function checkAccess(EntityInterface $entity, $operation, $langcode, UserInterface $account) {
public function checkAccess(EntityInterface $entity, $operation, $langcode, AccountInterface $account) {
if ($operation == 'delete' || $operation == 'update') {
// Do not allow delete 'personal' category used for personal contact form.
return user_access('administer contact forms', $account) && $entity->id() !== 'personal';
......
......@@ -8,10 +8,10 @@
namespace Drupal\node;
use Drupal\Core\Language\Language;
use Drupal\user\UserInterface;
use Drupal\Core\Entity\EntityAccessController;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityNG;
use Drupal\Core\Session\AccountInterface;
/**
* Defines the access controller for the node entity type.
......@@ -21,7 +21,7 @@ class NodeAccessController extends EntityAccessController {
/**
* {@inheritdoc}
*/
public function access(EntityInterface $entity, $operation, $langcode = Language::LANGUAGE_DEFAULT, UserInterface $account = NULL) {
public function access(EntityInterface $entity, $operation, $langcode = Language::LANGCODE_DEFAULT, AccountInterface $account = NULL) {
if (user_access('bypass node access', $account)) {
return TRUE;
}
......@@ -34,7 +34,7 @@ public function access(EntityInterface $entity, $operation, $langcode = Language
/**
* {@inheritdoc}
*/
protected function checkAccess(EntityInterface $node, $operation, $langcode, UserInterface $account) {
protected function checkAccess(EntityInterface $node, $operation, $langcode, AccountInterface $account) {
// Fetch information from the node object if possible.
$status = isset($node->status) ? $node->status : NULL;
$uid = isset($node->uid) ? $node->uid : NULL;
......@@ -75,7 +75,7 @@ protected function checkAccess(EntityInterface $node, $operation, $langcode, Use
* 'delete'.
* @param string $langcode
* The language code for which to check access.
* @param \Drupal\user\UserInterface $account
* @param \Drupal\Core\Session\AccountInterface $account
* The user for which to check access.
*
* @return bool|null
......@@ -83,7 +83,7 @@ protected function checkAccess(EntityInterface $node, $operation, $langcode, Use
* module implements hook_node_grants(), the node does not (yet) have an id
* or none of the implementing modules explicitly granted or denied access.
*/
protected function accessGrants(EntityInterface $node, $operation, $langcode, UserInterface $account) {
protected function accessGrants(EntityInterface $node, $operation, $langcode, AccountInterface $account) {
// If no module implements the hook or the node does not have an id there is
// no point in querying the database for access grants.
if (!module_implements('node_grants') || !$node->id()) {
......
......@@ -7,6 +7,7 @@
namespace Drupal\node\Tests;
use Drupal\Core\Session\AccountInterface;
use Drupal\simpletest\WebTestBase;
/**
......@@ -41,13 +42,13 @@ function setUp() {
* operation should be granted.
* @param \Drupal\node\Plugin\Core\Entity\Node $node
* The node object to check.
* @param \Drupal\user\UserInterface $account
* @param \Drupal\Core\Session\AccountInterface $account
* The user account for which to check access.
* @param string|null $langcode
* (optional) The language code indicating which translation of the node
* to check. If NULL, the untranslated (fallback) access is checked.
*/
function assertNodeAccess(array $ops, $node, $account, $langcode = NULL) {
function assertNodeAccess(array $ops, $node, AccountInterface $account, $langcode = NULL) {
foreach ($ops as $op => $result) {
$msg = format_string(
'node_access() returns @result with operation %op, language code %langcode.',
......
......@@ -8,7 +8,7 @@
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Drupal\block\Plugin\Core\Entity\Block;
use Drupal\user\UserInterface;
use Drupal\Core\Session\AccountInterface;
/**
* Implements hook_help().
......@@ -394,7 +394,7 @@ function template_preprocess_overlay_disable_message(&$variables) {
/**
* Implements hook_block_access().
*/
function overlay_block_access(Block $block, $operation, UserInterface $account, $langcode) {
function overlay_block_access(Block $block, $operation, AccountInterface $account, $langcode) {
// If we are limiting rendering to a subset of page regions, hide all blocks
// which appear in regions not on that list. Note that overlay_page_alter()
// does a more comprehensive job of preventing unwanted regions from being
......
......@@ -9,7 +9,7 @@
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityAccessController;
use Drupal\user\UserInterface;
use Drupal\Core\Session\AccountInterface;
/**
* Defines the access controller for the shortcut entity type.
......@@ -19,7 +19,7 @@ class ShortcutAccessController extends EntityAccessController {
/**
* {@inheritdoc}
*/
protected function checkAccess(EntityInterface $entity, $operation, $langcode, UserInterface $account) {
protected function checkAccess(EntityInterface $entity, $operation, $langcode, AccountInterface $account) {
switch ($operation) {
case 'edit':
if (user_access('administer shortcuts', $account)) {
......@@ -38,4 +38,5 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, U
break;
}
}
}
......@@ -8,8 +8,8 @@
namespace Drupal\system\Tests\Entity;
use Drupal\Core\Language\Language;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\TypedData\AccessibleInterface;
use Drupal\user\UserInterface;
use Drupal\Core\Entity\EntityAccessController;
/**
......@@ -45,7 +45,7 @@ function setUp() {
/**
* Asserts entity access correctly grants or denies access.
*/
function assertEntityAccess($ops, AccessibleInterface $object, UserInterface $account = NULL) {
function assertEntityAccess($ops, AccessibleInterface $object, AccountInterface $account = NULL) {
foreach ($ops as $op => $result) {
$message = format_string("Entity access returns @result with operation '@op'.", array(
'@result' => !isset($result) ? 'null' : ($result ? 'true' : 'false'),
......
......@@ -10,7 +10,7 @@
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityAccessController;
use Drupal\Core\Language\Language;
use Drupal\user\UserInterface;
use Drupal\Core\Session\AccountInterface;
/**
* Defines the access controller for the test entity type.
......@@ -20,7 +20,7 @@ class EntityTestAccessController extends EntityAccessController {
/**
* {@inheritdoc}
*/
protected function checkAccess(EntityInterface $entity, $operation, $langcode, UserInterface $account) {
protected function checkAccess(EntityInterface $entity, $operation, $langcode, AccountInterface $account) {
if ($operation === 'view') {
if ($langcode != Language::LANGCODE_DEFAULT) {
return user_access('view test entity translations', $account);
......
......@@ -9,7 +9,7 @@
use Drupal\Core\Entity\EntityAccessController;
use Drupal\Core\Entity\EntityInterface;
use Drupal\user\UserInterface;
use Drupal\Core\Session\AccountInterface;
/**
* Defines an access controller for the taxonomy term entity.
......@@ -21,7 +21,7 @@ class TermAccessController extends EntityAccessController {
/**