Account Suspended
Account Suspended
This Account has been suspended.
Contact your hosting provider for more information.
 All Data Structures Functions Variables Pages
Group.php
1 <?php
2  /*********************************************************************************
3  * Zurmo is a customer relationship management program developed by
4  * Zurmo, Inc. Copyright (C) 2017 Zurmo Inc.
5  *
6  * Zurmo is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU Affero General Public License version 3 as published by the
8  * Free Software Foundation with the addition of the following permission added
9  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
10  * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
11  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
12  *
13  * Zurmo is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Affero General Public License along with
19  * this program; if not, see http://www.gnu.org/licenses or write to the Free
20  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  * 02110-1301 USA.
22  *
23  * You can contact Zurmo, Inc. with a mailing address at 27 North Wacker Drive
24  * Suite 370 Chicago, IL 60606. or at email address contact@zurmo.com.
25  *
26  * The interactive user interfaces in original and modified versions
27  * of this program must display Appropriate Legal Notices, as required under
28  * Section 5 of the GNU Affero General Public License version 3.
29  *
30  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
31  * these Appropriate Legal Notices must retain the display of the Zurmo
32  * logo and Zurmo copyright notice. If the display of the logo is not reasonably
33  * feasible for technical reasons, the Appropriate Legal Notices must display the words
34  * "Copyright Zurmo Inc. 2017. All rights reserved".
35  ********************************************************************************/
36 
37  class Group extends Permitable
38  {
39  const EVERYONE_GROUP_NAME = 'Everyone';
40  const SUPER_ADMINISTRATORS_GROUP_NAME = 'Super Administrators';
41 
42  // Everyone and SuperAdministrators are not subtypes
43  // because it introduces too much complication with the
44  // RedBeanModel mapping, and the subtypes would have no
45  // data. This is simply a way to identify the special
46  // groups without string comparisons. It is far from
47  // ideal, but having spent some time on a subclassed
48  // version it is perhaps better. For further thought.
49  protected $isEveryone = false;
50  protected $isSuperAdministrators = false;
51 
57  public static function getByName($name)
58  {
59  assert('is_string($name)');
60  assert('$name != ""');
61  $bean = ZurmoRedBean::findOne('_group', "name = :name ", array(':name' => $name));
62  assert('$bean === false || $bean instanceof RedBean_OODBBean');
63  if ($bean === false)
64  {
65  if ($name != self::EVERYONE_GROUP_NAME &&
66  $name != self::SUPER_ADMINISTRATORS_GROUP_NAME)
67  {
68  throw new NotFoundException();
69  }
70  $group = new Group();
71  $group->unrestrictedSet('name', $name);
72  }
73  else
74  {
75  $group = self::makeModel($bean);
76  }
77  $group->setSpecialGroup();
78  return $group;
79  }
80 
81  public static function getById($id, $modelClassName = null)
82  {
83  $group = parent::getById($id, $modelClassName);
84  $group->setSpecialGroup();
85  return $group;
86  }
87 
88  public static function isUserASuperAdministrator(User $user)
89  {
90  if ($user->id < 0)
91  {
92  throw new NotSupportedException();
93  }
94  $superGroup = Group::getByName(Group::SUPER_ADMINISTRATORS_GROUP_NAME);
95  if ($user->groups->contains($superGroup))
96  {
97  return true;
98  }
99  else
100  {
101  return false;
102  }
103  }
104 
109  protected function constructDerived($bean, $setDefaults)
110  {
111  assert('$bean === null || $bean instanceof RedBean_OODBBean');
112  assert('is_bool($setDefaults)');
113  parent::constructDerived($bean, $setDefaults);
114  $this->setSpecialGroup();
115  }
116 
117  protected function setSpecialGroup()
118  {
119  $this->isEveryone = $this->name == self::EVERYONE_GROUP_NAME;
120  $this->isSuperAdministrators = $this->name == self::SUPER_ADMINISTRATORS_GROUP_NAME;
121  }
122 
123  public function canGivePermissions()
124  {
125  return !$this->isSuperAdministrators;
126  }
127 
128  public function canModifyMemberships()
129  {
130  if (!static::isUserASuperAdministrator(Yii::app()->user->userModel) && $this->isSuperAdministrators)
131  {
132  return false;
133  }
134  return !$this->isEveryone;
135  }
136 
137  public function canModifyName()
138  {
139  return !($this->isEveryone ||
140  $this->isSuperAdministrators);
141  }
142 
143  public function canModifyRights()
144  {
145  return !$this->isSuperAdministrators;
146  }
147 
148  public function canModifyPolicies()
149  {
150  return true;
151  }
152 
153  public function isDeletable()
154  {
155  return !($this->isEveryone ||
156  $this->isSuperAdministrators);
157  }
158 
159  public function contains(Permitable $permitable)
160  {
161  if ($this->isEveryone ||
162  parent::contains($permitable))
163  {
164  return true;
165  }
166  else
167  {
168  if ($permitable instanceof User)
169  {
170  foreach ($this->users as $user)
171  {
172  if ($user->isSame($permitable))
173  {
174  return true;
175  }
176  }
177  }
178  foreach ($this->groups as $group)
179  {
180  if ($group->contains($permitable))
181  {
182  return true;
183  }
184  }
185  }
186  return false;
187  }
188 
189  public function __toString()
190  {
191  assert('$this->name === null || is_string($this->name)');
192  if ($this->name === null)
193  {
194  return Zurmo::t('Core', '(Unnamed)');
195  }
196  if ($this->name == self::EVERYONE_GROUP_NAME)
197  {
199  }
200  elseif ($this->name == self::SUPER_ADMINISTRATORS_GROUP_NAME)
201  {
202  return Zurmo::t('ZurmoModule', 'Super Administrators');
203  }
204  return $this->name;
205  }
206 
207  public static function mangleTableName()
208  {
209  return true;
210  }
211 
212  protected static function translatedAttributeLabels($language)
213  {
214  return array_merge(parent::translatedAttributeLabels($language), array(
215  'group' => Zurmo::t('ZurmoModule', 'Parent Group', array(), null, $language),
216  'groups' => Zurmo::t('ZurmoModule', 'Groups', array(), null, $language),
217  'name' => Zurmo::t('Core', 'Name', array(), null, $language),
218  'users' => Zurmo::t('UsersModule', 'Users', array(), null, $language)
219  ));
220  }
221 
222  public function __get($attributeName)
223  {
224  if ($this->isEveryone)
225  {
226  if ($attributeName == 'group')
227  {
228  return null;
229  }
230  if ($attributeName == 'groups')
231  {
232  return array();
233  }
234  }
235  if ($this->isSuperAdministrators)
236  {
237  if ($attributeName == 'rights')
238  {
239  throw new NotSupportedException();
240  }
241  }
242  return parent::__get($attributeName);
243  }
244 
245  public function __set($attributeName, $value)
246  {
247  if (in_array($value, array(self::EVERYONE_GROUP_NAME,
248  self::SUPER_ADMINISTRATORS_GROUP_NAME)) ||
249  $this->isEveryone &&
250  in_array($attributeName, array('name', 'group', 'users', 'groups')) ||
251  $this->isSuperAdministrators &&
252  in_array($attributeName, array('name', 'rights')))
253  {
254  throw new NotSupportedException();
255  }
256  parent::__set($attributeName, $value);
257  }
258 
259  public function getEffectiveRight($moduleName, $rightName)
260  {
261  return $this->getActualRight($moduleName, $rightName) == Right::ALLOW ? Right::ALLOW : Right::DENY;
262  }
263 
269  public function getActualRight($moduleName, $rightName)
270  {
271  assert('is_string($moduleName)');
272  assert('is_string($rightName)');
273  assert('$moduleName != ""');
274  assert('$rightName != ""');
275  if ($this->isSuperAdministrators)
276  {
277  return Right::ALLOW;
278  }
279  if (!SECURITY_OPTIMIZED)
280  {
281  return parent::getActualRight($moduleName, $rightName);
282  }
283  else
284  {
285  // Optimizations work on the database,
286  // anything not saved will not work.
287  assert('$this->id > 0');
288  return intval(ZurmoDatabaseCompatibilityUtil::
289  callFunction("get_group_actual_right({$this->id}, '$moduleName', '$rightName')"));
290  }
291  }
292 
293  public function getPropagatedActualAllowRight($moduleName, $rightName)
294  {
295  return Right::NONE;
296  }
297 
303  public function getInheritedActualRight($moduleName, $rightName)
304  {
305  assert('is_string($moduleName)');
306  assert('is_string($rightName)');
307  assert('$moduleName != ""');
308  assert('$rightName != ""');
309  if ($this->isEveryone)
310  {
311  return Right::NONE;
312  }
313  if (!SECURITY_OPTIMIZED)
314  {
315  return parent::getInheritedActualRight($moduleName, $rightName);
316  }
317  else
318  {
319  // Optimizations work on the database,
320  // anything not saved will not work.
321  assert('$this->id > 0');
322  return intval(ZurmoDatabaseCompatibilityUtil::
323  callFunction("get_group_inherited_actual_right({$this->id}, '$moduleName', '$rightName')"));
324  }
325  }
326 
333  protected function getInheritedActualRightIgnoringEveryone($moduleName, $rightName)
334  {
335  assert('is_string($moduleName)');
336  assert('is_string($rightName)');
337  assert('$moduleName != ""');
338  assert('$rightName != ""');
339  if (!SECURITY_OPTIMIZED)
340  {
341  // The slow way will remain here as documentation
342  // for what the optimized way is doing.
343  $combinedRight = Right::NONE;
344  if ($this->group != null && $this->group->id > 0)
345  {
346  $combinedRight = $this->group->getExplicitActualRight ($moduleName, $rightName) |
347  $this->group->getInheritedActualRightIgnoringEveryone($moduleName, $rightName);
348  }
349  if (($combinedRight & Right::DENY) == Right::DENY)
350  {
351  return Right::DENY;
352  }
353  assert('in_array($combinedRight, array(Right::NONE, Right::ALLOW))');
354  return $combinedRight;
355  }
356  else
357  {
358  // It should never get here because the optimized version
359  // of getInheritedActualRight will call
360  // get_group_inherited_actual_right_ignoring_everyone.
361  throw new NotSupportedException();
362  }
363  }
364 
370  public function getInheritedActualPolicy($moduleName, $policyName)
371  {
372  assert('is_string($moduleName)');
373  assert('is_string($policyName)');
374  assert('$moduleName != ""');
375  assert('$policyName != ""');
376  if ($this->isEveryone)
377  {
378  return null;
379  }
380  return parent::getInheritedActualPolicy($moduleName, $policyName);
381  }
382 
388  public function getInheritedActualPolicyIgnoringEveryone($moduleName, $policyName)
389  {
390  assert('is_string($moduleName)');
391  assert('is_string($policyName)');
392  assert('$moduleName != ""');
393  assert('$policyName != ""');
394  if ($this->group != null && $this->group->id > 0 && !$this->isSame($this->group)) // Prevent cycles in database autobuild.
395  {
396  $value = $this->group->getExplicitActualPolicy($moduleName, $policyName);
397  if ($value !== null)
398  {
399  return $value;
400  }
401  $value = $this->group->getInheritedActualPolicyIgnoringEveryone($moduleName, $policyName);
402  if ($value !== null)
403  {
404  return $value;
405  }
406  }
407  return null;
408  }
409 
410  public static function getDefaultMetadata()
411  {
412  $metadata = parent::getDefaultMetadata();
413  $metadata[__CLASS__] = array(
414  'members' => array(
415  'name',
416  ),
417  'relations' => array(
418  'group' => array(static::HAS_MANY_BELONGS_TO, 'Group'),
419  'groups' => array(static::HAS_MANY, 'Group'),
420  'users' => array(static::MANY_MANY, 'User'),
421  ),
422  'rules' => array(
423  array('name', 'required'),
424  array('name', 'unique'),
425  array('name', 'type', 'type' => 'string'),
426  array('name', 'length', 'min' => 2, 'max' => 64),
427  ),
428  'defaultSortAttribute' => 'name'
429  );
430  return $metadata;
431  }
432 
433  public static function isTypeDeletable()
434  {
435  return true;
436  }
437 
442  public function isNameNotAReservedName($name)
443  {
444  $name = strtolower($name);
445 
446  $group1 = Group::getByName(Group::EVERYONE_GROUP_NAME);
447  $group2 = Group::getByName(Group::SUPER_ADMINISTRATORS_GROUP_NAME);
448  if (($name == strtolower(Group::EVERYONE_GROUP_NAME) && $this->id != $group1->id) ||
449  ($name == strtolower(Group::SUPER_ADMINISTRATORS_GROUP_NAME) && $this->id != $group2->id)
450  )
451  {
452  $this->addError('name', Zurmo::t('ZurmoModule', 'This name is reserved. Please pick a different name.'));
453  return false;
454  }
455  return true;
456  }
457 
458  public static function getModuleClassName()
459  {
460  return 'GroupsModule';
461  }
462 
463  protected function forgetPermissionsRightsAndPoliciesCache()
464  {
465  PermissionsCache::forgetAll();
466  Permission::resetCaches();
467  RightsCache::forgetAll();
468  PoliciesCache::forgetAll();
469  }
470 
471  protected function afterSave()
472  {
473  if (((isset($this->originalAttributeValues['group'])) || $this->isNewModel) &&
474  $this->group != null && $this->group->id > 0)
475  {
478  }
479  if (isset($this->originalAttributeValues['group']) && $this->originalAttributeValues['group'][1] > 0)
480  {
481  $this->forgetPermissionsRightsAndPoliciesCache();
482  }
483  parent::afterSave();
484  }
485 
486  protected function beforeSave()
487  {
488  if (parent::beforeSave())
489  {
490  if (isset($this->originalAttributeValues['group']) && $this->originalAttributeValues['group'][1] > 0)
491  {
492  //copy to new object, so we can populate the old parent group as the related group.
493  //otherwise it gets passed by reference. We need the old $this->group information to properly
494  //utilize the groupBeingRemovedFromGroup method.
495  $group = unserialize(serialize($this));
496  $group->group = Group::getById($this->originalAttributeValues['group'][1]);
498  assert('$this->originalAttributeValues["group"][1] != $this->group->id');
499  }
500  return true;
501  }
502  else
503  {
504  return false;
505  }
506  }
507 
508  protected function beforeDelete()
509  {
510  if (!parent::beforeDelete())
511  {
512  return false;
513  }
515  return true;
516  }
517 
518  protected function afterDelete()
519  {
520  $this->forgetPermissionsRightsAndPoliciesCache();
522  AllPermissionsOptimizationCache::forgetAll();
523  }
524 
530  {
531  $searchAttributeData['clauses'] = array(
532  1 => array(
533  'attributeName' => 'isSystemUser',
534  'operatorType' => 'equals',
535  'value' => 0,
536  ),
537  2 => array(
538  'attributeName' => 'isSystemUser',
539  'operatorType' => 'isNull',
540  'value' => null,
541  )
542  );
543  if ($this->name == Group::EVERYONE_GROUP_NAME)
544  {
545  $searchAttributeData['structure'] = '1 or 2';
546  }
547  else
548  {
549  $searchAttributeData['clauses'][3] = array(
550  'attributeName' => 'groups',
551  'relatedAttributeName' => 'id',
552  'operatorType' => 'equals',
553  'value' => $this->id,
554  );
555  $searchAttributeData['structure'] = '(1 or 2) and 3';
556  }
557  $joinTablesAdapter = new RedBeanModelJoinTablesQueryAdapter('User');
558  $where = RedBeanModelDataProvider::makeWhere('User', $searchAttributeData, $joinTablesAdapter);
559 
560  return User::getCount($joinTablesAdapter, $where);
561  }
562 
563  public function getUsersExceptSystemUsers()
564  {
565  $searchAttributeData['clauses'] = array(
566  1 => array(
567  'attributeName' => 'isSystemUser',
568  'operatorType' => 'equals',
569  'value' => 0,
570  ),
571  2 => array(
572  'attributeName' => 'isSystemUser',
573  'operatorType' => 'isNull',
574  'value' => null,
575  )
576  );
577  if ($this->name == Group::EVERYONE_GROUP_NAME)
578  {
579  $searchAttributeData['structure'] = '1 or 2';
580  }
581  else
582  {
583  $searchAttributeData['clauses'][3] = array(
584  'attributeName' => 'groups',
585  'relatedAttributeName' => 'id',
586  'operatorType' => 'equals',
587  'value' => $this->id,
588  );
589  $searchAttributeData['structure'] = '(1 or 2) and 3';
590  }
591  $joinTablesAdapter = new RedBeanModelJoinTablesQueryAdapter('User');
592  $where = RedBeanModelDataProvider::makeWhere('User', $searchAttributeData, $joinTablesAdapter);
593  return User::getSubset($joinTablesAdapter, null, null, $where);
594  }
595  }
596 ?>
static resolveEveryoneDisplayLabel()
getInheritedActualPolicyIgnoringEveryone($moduleName, $policyName)
Definition: Group.php:388
Definition: User.php:37
getActualRight($moduleName, $rightName)
Definition: Group.php:269
static makeWhere($modelClassName, array $metadata, &$joinTablesAdapter)
getInheritedActualRightIgnoringEveryone($moduleName, $rightName)
Definition: Group.php:333
static getSubset(RedBeanModelJoinTablesQueryAdapter $joinTablesAdapter=null, $offset=null, $count=null, $where=null, $orderBy=null, $modelClassName=null, $selectDistinct=false)
isNameNotAReservedName($name)
Definition: Group.php:442
getUserCountExceptSystemUsers()
Definition: Group.php:529
Definition: Group.php:37
static getByName($name)
Definition: Group.php:57
static getCount(RedBeanModelJoinTablesQueryAdapter $joinTablesAdapter=null, $where=null, $modelClassName=null, $selectDistinct=false)
getInheritedActualPolicy($moduleName, $policyName)
Definition: Group.php:370
addError($attributeName, $errorMessage)
getInheritedActualRight($moduleName, $rightName)
Definition: Group.php:303
constructDerived($bean, $setDefaults)
Definition: Group.php:109
Generated on Wed Oct 28 2020 07:10:36
Account Suspended
Account Suspended
This Account has been suspended.
Contact your hosting provider for more information.