Account Suspended
Account Suspended
This Account has been suspended.
Contact your hosting provider for more information.
 All Data Structures Functions Variables Pages
OwnedSecurableItem.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 
41  {
45  private $treatCurrentUserAsOwnerForPermissions = false;
46 
50  private $onAfterOwnerChangeEventRaised = false;
51 
58  {
59  assert('is_bool($value)');
60  $this->treatCurrentUserAsOwnerForPermissions = $value;
61  }
62 
68  protected function constructDerived($bean, $setDefaults)
69  {
70  assert('$bean === null || $bean instanceof RedBean_OODBBean');
71  assert('is_bool($setDefaults)');
72  parent::constructDerived($bean, $setDefaults);
73  // Even though setting the owner is not technically
74  // a default in the sense of a Yii default rule,
75  // if true the owner is not set because blank models
76  // are used for searching mass updating.
77  if ($bean === null && $setDefaults)
78  {
79  $currentUser = Yii::app()->user->userModel;
80  if (!$currentUser instanceof User)
81  {
83  }
84  AuditUtil::saveOriginalAttributeValue($this, 'owner', $currentUser);
85  $this->unrestrictedSet('owner', $currentUser);
86  }
87  }
88 
100  public function isReallyModified($relationType, $isOwned)
101  {
102  assert('is_int($relationType)');
103  assert('is_bool($isOwned)');
104  if ($relationType == self::HAS_ONE || $relationType == self::HAS_MANY_BELONGS_TO)
105  {
106  $modifiedSignalAttribute = static::getModifiedSignalAttribute();
107  if ($modifiedSignalAttribute != null &&
108  !$isOwned && $this->id < 0 && $this->isModified() && $this->$modifiedSignalAttribute == null)
109  {
110  return false;
111  }
112  }
113  return $this->isModified();
114  }
115 
120  protected static function getModifiedSignalAttribute()
121  {
122  return 'name';
123  }
124 
125  public function getEffectivePermissions($permitable = null)
126  {
127  assert('$permitable === null || $permitable instanceof Permitable');
128  if ($permitable === null)
129  {
130  $permitable = Yii::app()->user->userModel;
131  if (!$permitable instanceof User)
132  {
133  throw new NoCurrentUserSecurityException();
134  }
135  }
136  if (Permission::ALL == $this->resolveEffectivePermissionsForOwnerAndCreatedByUser($permitable))
137  {
138  return Permission::ALL;
139  }
140  else
141  {
142  return parent::getEffectivePermissions($permitable);
143  }
144  }
145 
146  protected function resolveEffectivePermissionsForOwnerAndCreatedByUser($permitable)
147  {
148  $owner = $this->unrestrictedGet('owner');
149  $createdByUser = $this->unrestrictedGet('createdByUser');
150  # If an owned securable item doesn't yet have an owner
151  # then whoever is creating it has full access to it. If they
152  # save it with the owner being someone else they are giving
153  # it away and potentially lose access to it.
154  if ($owner->id < 0 ||
155  $owner->isSame($permitable))
156  {
157  return Permission::ALL;
158  }
159  //If the record has not been created yet, then the created user should have full access
160  //Or if the record has not been created yet and doesn't have a createdByUser than any user can
161  //have full access
162  elseif ((($this->id < 0) &&
163  (($createdByUser->id > 0 &&
164  $createdByUser->isSame($permitable)) || $createdByUser->id < 0)) ||
165  $this->treatCurrentUserAsOwnerForPermissions)
166  {
167  return Permission::ALL;
168  }
169  return null;
170  }
171 
172  public function getActualPermissions($permitable = null)
173  {
174  assert('$permitable === null || $permitable instanceof Permitable');
175  if ($permitable === null)
176  {
177  $permitable = Yii::app()->user->userModel;
178  if (!$permitable instanceof User)
179  {
180  throw new NoCurrentUserSecurityException();
181  }
182  }
183  $owner = $this->unrestrictedGet('owner');
184  # If an owned securable item doesn't yet have an owner
185  # then whoever is creating it has full access to it. If they
186  # save it with the owner being someone else they are giving
187  # it away and potentially lose access to it.
188  if ($owner->id < 0 ||
189  $owner->isSame($permitable))
190  {
191  return array(Permission::ALL, Permission::NONE);
192  }
193  else
194  {
195  return parent::getActualPermissions($permitable);
196  }
197  }
198 
204  public function setOwnerUnrestricted(User $user)
205  {
206  parent::unrestrictedSet('owner', $user);
207  }
208 
209  public function __set($attributeName, $value)
210  {
211  if ($attributeName == 'owner')
212  {
213  $this->isSetting = true;
214  if ($value === null || !$this->owner->isSame($value))
215  {
216  $this->isSetting = false;
217  $this->onBeforeOwnerChange(new CEvent($this, array('newOwner' => $value)));
218  $this->ownerChange($value);
219  $this->onAfterOwnerChange(new CEvent($this));
220  }
221  else
222  {
223  $this->isSetting = false;
224  }
225  }
226  else
227  {
228  parent::__set($attributeName, $value);
229  }
230  }
231 
232  public function onBeforeOwnerChange(CEvent $event)
233  {
234  $this->raiseEvent('onBeforeOwnerChange', $event);
235  }
236 
237  protected function ownerChange($newOwnerValue)
238  {
239  $this->checkPermissionsHasAnyOf(Permission::CHANGE_OWNER);
240  $this->isSetting = true;
241  try
242  {
243  if (!$this->isSaving)
244  {
245  AuditUtil::saveOriginalAttributeValue($this, 'owner', $newOwnerValue);
246  }
247  parent::__set('owner', $newOwnerValue);
248  $this->isSetting = false;
249  }
250  catch (Exception $e)
251  {
252  $this->isSetting = false;
253  throw $e;
254  }
255  }
256 
257  public function onAfterOwnerChange(CEvent $event)
258  {
259  $this->raiseEvent('onAfterOwnerChange', $event);
260  $this->onAfterOwnerChangeEventRaised = true;
261  }
262 
263  public function onAfterOwnerChangeAfterSave(CEvent $event)
264  {
265  $this->raiseEvent('onAfterOwnerChangeAfterSave', $event);
266  }
267 
268  protected function afterSave()
269  {
270  if ($this->hasReadPermissionsOptimization())
271  {
272  if ($this->isNewModel)
273  {
275  }
276  elseif (isset($this->originalAttributeValues['owner']) &&
277  $this->originalAttributeValues['owner'][1] > 0)
278  {
280  User::getById($this->originalAttributeValues['owner'][1]));
281  }
282  }
283  if ($this->onAfterOwnerChangeEventRaised)
284  {
285  $this->onAfterOwnerChangeAfterSave(new CEvent($this));
286  $this->onAfterOwnerChangeEventRaised = false;
287  }
288  parent::afterSave();
289  }
290 
291  protected function beforeDelete()
292  {
293  if (!parent::beforeDelete())
294  {
295  return false;
296  }
297  if ($this->hasReadPermissionsOptimization())
298  {
300  }
301  return true;
302  }
303 
304  public static function getDefaultMetadata()
305  {
306  $metadata = parent::getDefaultMetadata();
307  $metadata[__CLASS__] = array(
308  'relations' => array(
309  'owner' => array(static::HAS_ONE, 'User', static::NOT_OWNED,
310  static::LINK_TYPE_SPECIFIC, 'owner'),
311  ),
312  'rules' => array(
313  array('owner', 'required'),
314  ),
315  'elements' => array(
316  'owner' => 'User',
317  ),
318  'indexes' => array(
319  'owner__user_id' => array(
320  'members' => array('owner__user_id'),
321  'unique' => false),
322  'securableitem_id' => array(
323  'members' => array('securableitem_id'),
324  'unique' => false),
325  ),
326  );
327  return $metadata;
328  }
329 
344  public static function makeSubsetOrCountSqlQuery($tableName,
345  RedBeanModelJoinTablesQueryAdapter $joinTablesAdapter = null,
346  $offset = null, $count = null,
347  $where = null, $orderBy = null,
348  $selectCount = false, $selectDistinct = false,
349  array $quotedExtraSelectColumnNameAndAliases = array())
350  {
351  assert('is_string($tableName) && $tableName != ""');
352  assert('$offset === null || is_integer($offset) && $offset >= 0');
353  assert('$count === null || is_integer($count) && $count >= 1');
354  assert('$where === null || is_string ($where) && $where != ""');
355  assert('$orderBy === null || is_string ($orderBy) && $orderBy != ""');
356  assert('is_bool($selectCount)');
357  assert('is_bool($selectDistinct)');
358  $user = Yii::app()->user->userModel;
359  if (!$user instanceof User)
360  {
361  throw new NoCurrentUserSecurityException();
362  }
363  if ($joinTablesAdapter == null)
364  {
365  $joinTablesAdapter = new RedBeanModelJoinTablesQueryAdapter(get_called_class());
366  }
367  static::resolveReadPermissionsOptimizationToSqlQuery($user, $joinTablesAdapter, $where, $selectDistinct);
368  return parent::makeSubsetOrCountSqlQuery($tableName, $joinTablesAdapter, $offset, $count,
369  $where, $orderBy, $selectCount, $selectDistinct,
370  $quotedExtraSelectColumnNameAndAliases);
371  }
372 
381  RedBeanModelJoinTablesQueryAdapter $joinTablesAdapter,
382  & $where,
383  & $selectDistinct)
384  {
385  assert('$where == null || is_string($where)');
386  assert('is_bool($selectDistinct)');
387  $modelClassName = get_called_class();
388  $moduleClassName = $modelClassName::getModuleClassName();
389  //Currently only adds munge if the module is securable and this model supports it.
390  if (static::hasReadPermissionsOptimization() && $moduleClassName != null &&
391  is_subclass_of($moduleClassName, 'SecurableModule'))
392  {
394 
395  if (($permission == Permission::NONE || $permission == Permission::DENY) &&
396  !static::bypassReadPermissionsOptimizationToSqlQueryBasedOnWhere($where))
397  {
399  $modelAttributeToDataProviderAdapter = new OwnedSecurableItemIdToDataProviderAdapter(
400  $modelClassName, null);
401  $builder = new ModelJoinBuilder($modelAttributeToDataProviderAdapter, $joinTablesAdapter);
402  $ownedTableAliasName = $builder->resolveJoins();
403  $ownerColumnName = static::getForeignKeyName('OwnedSecurableItem', 'owner');
405  if ($where != null)
406  {
407  $where = '(' . $where . ') and ';
408  }
409  if (count($mungeIds) > 0 && $permission == Permission::NONE)
410  {
411  $extraOnQueryPart = " and {$quote}munge_id{$quote} in ('" . join("', '", $mungeIds) . "')";
412  $mungeTableName = ReadPermissionsOptimizationUtil::getMungeTableName($modelClassName);
413  $mungeTableAliasName = $joinTablesAdapter->addLeftTableAndGetAliasName(
414  $mungeTableName,
415  'securableitem_id',
416  $ownedTableAliasName,
417  'securableitem_id',
418  $extraOnQueryPart);
419 
420  $where .= "($quote$ownedTableAliasName$quote.$quote$ownerColumnName$quote = $user->id OR "; // Not Coding Standard
421  $where .= "$quote$mungeTableName$quote.{$quote}munge_id{$quote} IS NOT NULL)"; // Not Coding Standard
422  $selectDistinct = true; //must use distinct since adding munge table query.
423  }
424  elseif ($permission == Permission::DENY)
425  {
426  $where .= "$quote$ownedTableAliasName$quote.$quote$ownerColumnName$quote = $user->id"; // Not Coding Standard
427  }
428  else
429  {
430  throw new NotSupportedException();
431  }
432  }
433  }
434  }
435 
436  protected static function bypassReadPermissionsOptimizationToSqlQueryBasedOnWhere($where)
437  {
438  return false;
439  }
440 
441  public static function isTypeDeletable()
442  {
443  return false;
444  }
445 
446  protected static function translatedAttributeLabels($language)
447  {
448  return array_merge(parent::translatedAttributeLabels($language),
449  array(
450  'owner' => Zurmo::t('ZurmoModule', 'Owner', array(), null, $language),
451  )
452  );
453  }
454 
461  {
462  return false;
463  }
464 
469  public static function supportsQueueing()
470  {
471  return false;
472  }
473 
474  public function checkPermissionsHasAnyOf($requiredPermissions, User $user = null)
475  {
476  assert('is_int($requiredPermissions)');
477  assert('in_array($requiredPermissions,
478  array(Permission::READ, Permission::WRITE, Permission::DELETE,
479  Permission::CHANGE_PERMISSIONS, Permission::CHANGE_OWNER))');
480  if ($user == null)
481  {
482  $user = Yii::app()->user->userModel;
483  }
484  if (Permission::ALL == $this->resolveEffectivePermissionsForOwnerAndCreatedByUser($user))
485  {
486  return;
487  }
488  elseif ($this->isDeleting)
489  {
490  //Avoid potential problems with accessing information already removed from munge.
491  //Potentially there could be some gap with doing this, but it improves performance on complex
492  //role/group setups.
493  return;
494  }
495  else
496  {
497  if (SECURITY_OPTIMIZED)
498  {
499  $modelClassName = get_called_class();
500  $moduleClassName = $modelClassName::getModuleClassName();
501  if (static::hasReadPermissionsOptimization() &&
502  $moduleClassName != null &&
503  is_subclass_of($moduleClassName, 'SecurableModule') &&
504  AllPermissionsOptimizationUtil::checkPermissionsHasAnyOf($requiredPermissions, $this, $user))
505  {
506  return;
507  }
508  }
509  parent::checkPermissionsHasAnyOf($requiredPermissions, $user);
510  }
511  }
512  }
513 ?>
static ownedSecurableItemOwnerChanged(OwnedSecurableItem $ownedSecurableItem, User $oldUser=null)
setTreatCurrentUserAsOwnerForPermissions($value)
Definition: User.php:37
static resolveReadPermissionsOptimizationToSqlQuery(User $user, RedBeanModelJoinTablesQueryAdapter $joinTablesAdapter, &$where, &$selectDistinct)
static securableItemBeingDeleted(SecurableItem $securableItem)
static saveOriginalAttributeValue($auditableModel, $attributeName, $value)
Definition: AuditUtil.php:66
static makeSubsetOrCountSqlQuery($tableName, RedBeanModelJoinTablesQueryAdapter $joinTablesAdapter=null, $offset=null, $count=null, $where=null, $orderBy=null, $selectCount=false, $selectDistinct=false, array $quotedExtraSelectColumnNameAndAliases=array())
static hasReadPermissionsOptimization()
setOwnerUnrestricted(User $user)
constructDerived($bean, $setDefaults)
isReallyModified($relationType, $isOwned)
static hasReadPermissionsSubscriptionOptimization()
unrestrictedSet($attributeName, $value)
addLeftTableAndGetAliasName($tableName, $onTableJoinIdName, $onTableAliasName=null, $tableJoinIdName= 'id', $extraOnQueryPart=null)
static getById($id, $modelClassName=null)
static getActualPermissionDataForReadByModuleNameForUser($moduleClassName, User $user=null)
static checkPermissionsHasAnyOf($requiredPermissions, OwnedSecurableItem $ownedSecurableItem, User $user)
static ownedSecurableItemCreated(OwnedSecurableItem $ownedSecurableItem)
Generated on Sat Aug 15 2020 07:10:35
Account Suspended
Account Suspended
This Account has been suspended.
Contact your hosting provider for more information.