1<?php 2 3namespace Drupal\user; 4 5use Drupal\Core\Access\AccessResult; 6use Drupal\Core\Access\AccessResultNeutral; 7use Drupal\Core\Access\AccessResultReasonInterface; 8use Drupal\Core\Entity\EntityInterface; 9use Drupal\Core\Entity\EntityAccessControlHandler; 10use Drupal\Core\Field\FieldDefinitionInterface; 11use Drupal\Core\Field\FieldItemListInterface; 12use Drupal\Core\Session\AccountInterface; 13 14/** 15 * Defines the access control handler for the user entity type. 16 * 17 * @see \Drupal\user\Entity\User 18 */ 19class UserAccessControlHandler extends EntityAccessControlHandler { 20 21 /** 22 * Allow access to user label. 23 * 24 * @var bool 25 */ 26 protected $viewLabelOperation = TRUE; 27 28 /** 29 * {@inheritdoc} 30 */ 31 protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) { 32 /** @var \Drupal\user\UserInterface $entity*/ 33 34 // We don't treat the user label as privileged information, so this check 35 // has to be the first one in order to allow labels for all users to be 36 // viewed, including the special anonymous user. 37 if ($operation === 'view label') { 38 return AccessResult::allowed(); 39 } 40 41 // The anonymous user's profile can neither be viewed, updated nor deleted. 42 if ($entity->isAnonymous()) { 43 return AccessResult::forbidden(); 44 } 45 46 // Administrators can view/update/delete all user profiles. 47 if ($account->hasPermission('administer users')) { 48 return AccessResult::allowed()->cachePerPermissions(); 49 } 50 51 switch ($operation) { 52 case 'view': 53 // Only allow view access if the account is active. 54 if ($account->hasPermission('access user profiles') && $entity->isActive()) { 55 return AccessResult::allowed()->cachePerPermissions()->addCacheableDependency($entity); 56 } 57 // Users can view own profiles at all times. 58 elseif ($account->id() == $entity->id()) { 59 return AccessResult::allowed()->cachePerUser(); 60 } 61 else { 62 return AccessResultNeutral::neutral("The 'access user profiles' permission is required and the user must be active.")->cachePerPermissions()->addCacheableDependency($entity); 63 } 64 break; 65 66 case 'update': 67 // Users can always edit their own account. 68 $access_result = AccessResult::allowedIf($account->id() == $entity->id())->cachePerUser(); 69 if (!$access_result->isAllowed() && $access_result instanceof AccessResultReasonInterface) { 70 $access_result->setReason("Users can only update their own account, unless they have the 'administer users' permission."); 71 } 72 return $access_result; 73 74 case 'delete': 75 // Users with 'cancel account' permission can cancel their own account. 76 return AccessResult::allowedIfHasPermission($account, 'cancel account') 77 ->andIf(AccessResult::allowedIf($account->id() == $entity->id())->cachePerUser()); 78 } 79 80 // No opinion. 81 return AccessResult::neutral(); 82 } 83 84 /** 85 * {@inheritdoc} 86 */ 87 protected function checkFieldAccess($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) { 88 // Fields that are not implicitly allowed to administrative users. 89 $explicit_check_fields = [ 90 'pass', 91 ]; 92 93 // Administrative users are allowed to edit and view all fields. 94 if (!in_array($field_definition->getName(), $explicit_check_fields) && $account->hasPermission('administer users')) { 95 return AccessResult::allowed()->cachePerPermissions(); 96 } 97 98 // Flag to indicate if this user entity is the own user account. 99 $is_own_account = $items ? $items->getEntity()->id() == $account->id() : FALSE; 100 switch ($field_definition->getName()) { 101 case 'name': 102 // Allow view access to anyone with access to the entity. 103 // The username field is editable during the registration process. 104 if ($operation == 'view' || ($items && $items->getEntity()->isAnonymous())) { 105 return AccessResult::allowed()->cachePerPermissions(); 106 } 107 // Allow edit access for the own user name if the permission is 108 // satisfied. 109 if ($is_own_account && $account->hasPermission('change own username')) { 110 return AccessResult::allowed()->cachePerPermissions()->cachePerUser(); 111 } 112 else { 113 return AccessResult::neutral(); 114 } 115 116 case 'mail': 117 // Only check for the 'view user email addresses' permission and a view 118 // operation. Use case fall-through for all other cases. 119 if ($operation == 'view' && $account->hasPermission('view user email addresses')) { 120 return AccessResult::allowed()->cachePerPermissions(); 121 } 122 case 'preferred_langcode': 123 case 'preferred_admin_langcode': 124 case 'timezone': 125 // Allow view access to own mail address and other personalization 126 // settings. 127 if ($operation == 'view') { 128 return AccessResult::allowedIf($is_own_account)->cachePerUser(); 129 } 130 // Anyone that can edit the user can also edit this field. 131 return AccessResult::allowed()->cachePerPermissions(); 132 133 case 'pass': 134 // Allow editing the password, but not viewing it. 135 return ($operation == 'edit') ? AccessResult::allowed() : AccessResult::forbidden(); 136 137 case 'created': 138 // Allow viewing the created date, but not editing it. 139 return ($operation == 'view') ? AccessResult::allowed() : AccessResult::neutral(); 140 141 case 'roles': 142 case 'status': 143 case 'access': 144 case 'login': 145 case 'init': 146 return AccessResult::neutral(); 147 } 148 149 return parent::checkFieldAccess($operation, $field_definition, $account, $items); 150 } 151 152} 153