Security update for permissions_by_term
[yaffs-website] / web / modules / contrib / permissions_by_term / src / Service / AccessCheck.php
1 <?php
2
3 namespace Drupal\permissions_by_term\Service;
4
5 use Drupal\Core\Access\AccessResult;
6 use Drupal\Core\Database\Connection;
7 use Drupal\user\Entity\User;
8 use Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher;
9 use Drupal\permissions_by_term\Event\PermissionsByTermDeniedEvent;
10
11 /**
12  * AccessCheckService class.
13  */
14 class AccessCheck {
15
16   /**
17    * The database connection.
18    *
19    * @var \Drupal\Core\Database\Connection
20    */
21   protected $database;
22
23   /**
24    * @var ContainerAwareEventDispatcher
25    */
26   private $eventDispatcher;
27
28   /**
29    * Constructs AccessCheck object.
30    *
31    * @param Connection $database
32    *   The database connection.
33    */
34   public function __construct(Connection $database, ContainerAwareEventDispatcher $eventDispatcher) {
35     $this->database  = $database;
36     $this->eventDispatcher = $eventDispatcher;
37   }
38
39   /**
40    * @return bool
41    */
42   public function canUserAccessByNodeId($nid, $uid = FALSE) {
43     if (!$singleTermRestriction = \Drupal::config('permissions_by_term.settings.single_term_restriction')->get('value')) {
44       $access_allowed = TRUE;
45     } else {
46       $access_allowed = FALSE;
47     }
48
49     $terms = $this->database
50       ->query("SELECT tid FROM {taxonomy_index} WHERE nid = :nid",
51       [':nid' => $nid])->fetchAll();
52
53     foreach ($terms as $term) {
54       $access_allowed = $this->isAccessAllowedByDatabase($term->tid, $uid);
55       if (!$access_allowed) {
56         if ($singleTermRestriction) {
57           return $access_allowed;
58         }
59       }
60
61       if ($access_allowed && !$singleTermRestriction) {
62         return $access_allowed;
63       }
64
65     }
66
67     return $access_allowed;
68   }
69
70   /**
71    * @param int      $tid
72    * @param bool|int $uid
73    * @return array
74    */
75   public function isAccessAllowedByDatabase($tid, $uid = FALSE) {
76
77     if ($uid === FALSE) {
78       $user = \Drupal::currentUser();
79     } elseif (is_numeric($uid)) {
80       $user = User::load($uid);
81     }
82
83     // Admin can access everything (user id "1").
84     if ($user->id() == 1) {
85       return TRUE;
86     }
87
88     $tid = intval($tid);
89
90     if (!$this->isAnyPermissionSetForTerm($tid)) {
91       return TRUE;
92     }
93
94     /* At this point permissions are enabled, check to see if this user or one
95      * of their roles is allowed.
96      */
97     $aUserRoles = $user->getRoles();
98
99     foreach ($aUserRoles as $sUserRole) {
100
101       if ($this->isTermAllowedByUserRole($tid, $sUserRole)) {
102         return TRUE;
103       }
104
105     }
106
107     $iUid = intval($user->id());
108
109     if ($this->isTermAllowedByUserId($tid, $iUid)) {
110       return TRUE;
111     }
112
113     return FALSE;
114
115   }
116
117   /**
118    * @param int $tid
119    * @param int $iUid
120    *
121    * @return bool
122    */
123   private function isTermAllowedByUserId($tid, $iUid) {
124     $query_result = $this->database->query("SELECT uid FROM {permissions_by_term_user} WHERE tid = :tid AND uid = :uid",
125       [':tid' => $tid, ':uid' => $iUid])->fetchField();
126
127     if (!empty($query_result)) {
128       return TRUE;
129     }
130     else {
131       return FALSE;
132     }
133   }
134
135   /**
136    * @param int    $tid
137    * @param string $sUserRole
138    *
139    * @return bool
140    */
141   public function isTermAllowedByUserRole($tid, $sUserRole) {
142     $query_result = $this->database->query("SELECT rid FROM {permissions_by_term_role} WHERE tid = :tid AND rid IN (:user_roles)",
143       [':tid' => $tid, ':user_roles' => $sUserRole])->fetchField();
144
145     if (!empty($query_result)) {
146       return TRUE;
147     }
148     else {
149       return FALSE;
150     }
151
152   }
153
154   /**
155    * @param int $tid
156    *
157    * @return bool
158    */
159   public function isAnyPermissionSetForTerm($tid) {
160
161     $iUserTableResults = intval($this->database->query("SELECT COUNT(1) FROM {permissions_by_term_user} WHERE tid = :tid",
162       [':tid' => $tid])->fetchField());
163
164     $iRoleTableResults = intval($this->database->query("SELECT COUNT(1) FROM {permissions_by_term_role} WHERE tid = :tid",
165       [':tid' => $tid])->fetchField());
166
167     if ($iUserTableResults > 0 ||
168       $iRoleTableResults > 0) {
169       return TRUE;
170     }
171
172   }
173
174   /**
175    * @return AccessResult
176    */
177   public function handleNode($nodeId) {
178     if ($this->canUserAccessByNodeId($nodeId) === TRUE) {
179       return AccessResult::neutral();
180     }
181     else {
182       $accessDeniedEvent = new PermissionsByTermDeniedEvent($nodeId);
183       $this->eventDispatcher->dispatch(PermissionsByTermDeniedEvent::NAME, $accessDeniedEvent);
184
185       return AccessResult::forbidden();
186     }
187   }
188
189 }