Xataface  2.0alpha2
Xataface Application Framework
 All Data Structures Namespaces Files Functions Variables Groups Pages
PermissionsTool.php
Go to the documentation of this file.
1 <?php
2 /*-------------------------------------------------------------------------------
3  * Xataface Web Application Framework
4  * Copyright (C) 2005-2008 Web Lite Solutions Corp (shannah@sfu.ca)
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *-------------------------------------------------------------------------------
20  */
21 
26 
31  public static function &getInstance(){
32 
33  static $instance = null;
34  if ( $instance === null ){
35  $instance = new Dataface_PermissionsTool_Instance();
36  }
37  return $instance;
38  }
39 
40  public static function setDelegate($del){
41  return self::getInstance()->setDelegate($del);
42  }
43 
48  public static function addContextMask(Dataface_RelatedRecord $contextRecord){
49  $out = self::getInstance()->addContextMask($contextRecord);
50  return $out;
51  }
52 
57  public static function removeContextMask(Dataface_RelatedRecord $contextRecord){
58  $out = self::getInstance()->removeContextMask($contextRecord);
59  return $out;
60  }
65  public static function &getContextMasks(){
66  $out =& self::getInstance()->getContextMasks();
67  return $out;
68  }
69 
74  public static function &getContextMask($id, $fieldname=null){
75  $out =& self::getInstance()->getContextMask($id, $fieldname);
76  return $out;
77  }
78 
79 
84  function getPortalRecordPermissions(Dataface_Record $record, $params=array()){
85  return self::getInstance()->getPortalRecordPermissions($record, $params);
86 
87 
88  }
89 
97  function getPortalFieldPermissions(Dataface_Record $record, $params=array()){
98  return self::getInstance()->getPortalFieldPermissions($record, $params);
99  }
100 
101 
102  public static function &getContext(){ return self::getInstance()->getContext(); }
103  public static function setContext($context){
104  return self::getInstance()->setContext($context);
105  }
106 
107  public static function clearContext(){
108  self::getInstance()->clearContext();
109  }
110 
111  public static function &PUBLIC_CONTEXT(){
112  return self::getInstance()->PUBLIC_CONTEXT();
113  }
114 
120  public static function addPermissions($conf){
121  return self::getInstance()->addPermissions($conf);
122  }
123 
124 
125 
131  public static function getPermissions(&$obj, $params=array()){
132  return self::getInstance()->getPermissions($obj, $params);
133  }
134 
135  public static function filterPermissions(&$obj, &$perms, $params=array()){
136  return self::getInstance()->filterPermissions($obj, $perms, $params);
137  }
138 
145  public static function checkPermission($permissionName, $perms, $params=array()){
146  return self::getInstance()->checkPermission($permissionName, $perms, $params);
147  }
148 
156  public static function view(&$perms, $params=array()){
157  return self::getInstance()->view($perms, $params);
158 
159  }
160 
168  public static function edit(&$perms, $params=array()){
169  return self::getInstance()->edit($perms, $params);
170 
171  }
172 
180  public static function delete(&$perms, $params=array()){
181  return self::getInstance()->delete($perms, $params);
182  }
183 
184  public static function MASK(){
185  return self::getInstance()->MASK();
186 
187  }
188 
189  public static function _zero(){
190  return self::getInstance()->_zero();
191  }
192 
193  public static function _one(){
194  return self::getInstance()->_one();
195  }
196 
200  public static function NO_ACCESS(){
201  return self::getInstance()->NO_ACCESS();
202  }
203 
209  public static function READ_ONLY(){
210  return self::getInstance()->READ_ONLY();
211  }
212 
218  public static function ALL(){
219  return self::getInstance()->ALL();
220  }
221 
227  public static function &READ_EDIT(){
228  return self::getInstance()->READ_EDIT();
229  }
230 
231 
249  public static function &getRolePermissions($roleName){
250  return self::getInstance()->getRolePermissions($roleName);
251 
252 
253  }
254 
255  public static function roleExists($roleName){
256  return self::getInstance()->roleExists($roleName);
257  }
258 
259 
263  public static function namesAsArray($permissions){
264  return self::getInstance()->namesAsArray($permissions);
265  }
266 
267 
272  public static function namesAsString($permissions){
273  return self::getInstance()->namesAsString($permissions);
274  }
275 
276  public static function cachePermissions(&$record, $params, $perms){
277  return self::getInstance()->cachePermissions($record, $params, $perms);
278 
279  }
280 
281  public static function getCachedPermissions(&$record, $params){
282  return self::getInstance()->getCachedPermissions($record, $params);
283  }
284 
285 
286 
287 
288 
289 }
290 
291 
293  function getPermissions(&$record){
295  }
296 }
297 
298 
299 
300 
302 
303 
304  var $_cache = array();
309  var $rolePermissions = array();
310 
314  var $permissions = array();
315 
316  var $context = null;
317 
318  var $contextMasks = null;
319 
320 
321  var $delegate = null;
322 
323  function __construct($conf = null){
324 
325  if ( $conf === null ){
326  import('Dataface/ConfigTool.php');
327  $configTool =& Dataface_ConfigTool::getInstance();
328  $conf = $configTool->loadConfig('permissions');
329 
330  }
331 
332  $this->addPermissions($conf);
333  //print_r($this->permissions);
334  }
335 
336 
351  function removeContextMask(Dataface_RelatedRecord $contextRecord){
352 
353  if ( isset($this->contextMasks) ){
354  $destRecords = $contextRecord->toRecords();
355  $changed = false;
356  foreach ($destRecords as $destRecord){
357  $id = $destRecord->getId();
358  if ( isset($this->contextMasks[$id]) ){
359  $changed = true;
360  unset($this->contextMasks[$destRecord->getId()]);
361  }
362  }
363  if ( $changed ){
364  $this->_cache = array();
365  }
366  }
367  }
368 
385  function addContextMask(Dataface_RelatedRecord $contextRecord){
387  if ( !isset($this->contextMasks) ) $this->contextMasks = array();
388  $parentPerms = $contextRecord->getParent()->getPermissions(array('relationship'=>$contextRecord->_relationshipName));
389  $perms = array();
390  if ( @$parentPerms['add new related record'] or @$parentPerms['add existing related record'] ){
391  $perms['new'] = 1;
392  }
393  if ( @$parentPerms['delete related record'] ){
394  $perms['delete'] = 1;
395  } else if ( isset($parentPerms['delete related record']) and !@$parentPerms['delete related record'] ){
396  $perms['delete'] = 0;
397  } if ( @$parentPerms['edit related records'] ){
398  $perms['edit'] = 1;
399  } else if ( isset($parentPerms['edit related records']) and !@$parentPerms['edit related records'] ){
400  $perms['edit'] = 0;
401  }
402  if ( @$parentPerms['view related records'] ){
403  $perms['view'] = 1;
404  } else if ( isset($parentPerms['view related records']) and !@$parentPerms['view related records'] ){
405  $perms['view'] = 0;
406  }
407  if ( @$parentPerms['find related records'] ){
408  $perms['find'] = 1;
409  } else if ( isset($parentPerms['find related records']) and !@$parentPerms['find related records'] ){
410  $perms['find'] = 0;
411  }
412  if ( @$parentPerms['link related records'] ){
413  $perms['link'] = 1;
414  } else if ( isset($parentPerms['link related records']) and !@$parentPerms['link related records'] ){
415  $perms['link'] = 0;
416  }
417 
418  $recordPerms = $perms;
419  unset($perms);
420  $domainTable = $contextRecord->_relationship->getDomainTable();
421  $destRecords = $contextRecord->toRecords();
422  $numDest = count($destRecords);
423  $destRecordIndex = array();
424  $destRecordIds = array();
425  foreach ($destRecords as $destRecord){
426  $destRecordIndex[$destRecord->table()->tablename] = $destRecord;
427  $id = $destRecord->getId();
428  $destRecordIds[$destRecord->table()->tablename] = $id;
429  $this->contextMasks[$id] = $recordPerms;
430  if ( $numDest > 1 ){
431  // This is a many-to-many relationship
432  if ( strcmp($destRecord->table()->tablename,$domainTable)===0 ){
433  // For many-to-many relationships
434  // we don't want the user to be able to edit
435  // the domain table.
436  if ( !@$parentPerms['add new related record'] ){
437  unset($this->contextMasks[$id]['new']);
438  }
439  unset($this->contextMasks[$id]['edit']);
440  unset($this->contextMasks[$id]['link']);
441 
442  } else {
443  // This is a join table
444  if ( @$parentPerms['remove related record'] ){
445  $this->contextMasks[$id]['delete'] = 1;
446 
447  } else if ( isset($parentPerms['remove related record']) and !@$parentPerms['remove related record'] ){
448  $this->contextMasks[$id]['delete'] = 0;
449  }
450  }
451  }
452  }
453  $relationship = $contextRecord->_relationship;
454  $fields = $relationship->fields(true, true);
455  $constrainedFields = array_flip($contextRecord->getConstrainedFields());
456  foreach ($fields as $field){
457  $fieldTable = $relationship->getTable($field);
458  $fieldTableName = $fieldTable->tablename;
459  $rec = $destRecordIndex[$fieldTableName];
460  $perms = null;
461  if ( strpos($field,'.') !== false ) list($junk,$fieldname) = explode('.', $field);
462  else $fieldname = $field;
463  $perms = $rec->getPermissions(array('field'=>$fieldname, 'nobubble'=>1));
464  if ( !$perms ) $perms = array();
465  $rfperms = $contextRecord->getParent()->getPermissions(array('relationship'=>$contextRecord->_relationshipName, 'field'=>$fieldname, 'nobubble'=>1));
466  //echo "RFPerms: ";print_r($rfperms);
467  if ( $rfperms ){
468  foreach ($rfperms as $k=>$v){
469  $perms[$k] = $v;
470  }
471  }
472  if ( isset($constrainedFields[$fieldTableName.'.'.$fieldname]) ){
473  $perms['edit'] = 0;
474  }
475 
476  $id = $destRecordIds[$fieldTableName];
477  $this->contextMasks[$id.'#'.$fieldname] = $perms;
478  unset($perms);
479 
480  }
481 
482 
483  $this->_cache = array(); // Clear the cache because
484  // the presence of this mask will
485  // alter the result of permissions queries
486 
487 
488 
489  }
490 
562  function &getContextMasks(){
563  if ( !isset($this->contextMasks) ){
564  $this->contextMasks = array();
566  $contextRecord = $app->getRecordContext();
567  if ( $contextRecord ){
568 
569  //$contextRecord = df_get_record_by_id($query['-portal-context']);
570  if ( is_a($contextRecord, 'Dataface_RelatedRecord') ){
571  $this->addContextMask($contextRecord);
572 
573 
574  }
575 
576  }
577  }
578  return $this->contextMasks;
579  }
580 
591  function getContextMask($id, $fieldname=null){
592  if ( $fieldname ) $id .= '#'.$fieldname;
593  $masks =& $this->getContextMasks();
594  if ( isset($masks[$id]) ) return $masks[$id];
595  else {
596  $out = array();
597  return $out;
598  }
599  }
600 
607  function getPortalRecordPermissions(Dataface_Record $record, $params=array()){
608  return $this->getContextMask($record->getId());
609 
610 
611  }
612 
619  function getPortalFieldPermissions(Dataface_Record $record, $params=array()){
620  return $this->getContextMask($record->getId(), @$params['field']);
621  }
622 
623  function setDelegate($del){
624  $this->delegate = $del;
625  }
626 
627  function &getContext(){ return $this->context; }
628  function setContext($context){
629  if ( isset($this->context) ) unset($this->context);
630  $this->context =& $context;
631  }
632 
633  function clearContext(){
634  $this->context = null;
635  }
636 
637  function &PUBLIC_CONTEXT(){
638  static $pcontext = 0;
639  if ( !is_object($pcontext) ){
641  }
642  return $pcontext;
643  }
644 
650  function addPermissions($conf){
651  $this->_cache = array();
652  foreach ( array_keys($conf) as $key ){
653  // iterate through the config options
654  if ( is_array($conf[$key]) ){
655  //$out =& $conf[$key];
656  /*
657  foreach ($out as $okey=>$oval){
658  $out[$okey] = intval(trim($oval));
659  }
660  */
661  $this->rolePermissions[$key] =& $conf[$key];//$out;
662  //unset($out);
663 
664 
665 
666  } else {
667  $this->permissions[$key] = $conf[$key];
668  }
669  }
670  }
671 
672 
673 
679  function getPermissions(&$obj, $params=array()){
680  $me =& $this;
681  if ( isset($me->context) ){
682  return $me->context->getPermissions($obj, $params);
683  }
684  if (
685  is_a($obj, 'Dataface_Table') or
686  is_a($obj, 'Dataface_Record') or
687  is_a($obj, 'Dataface_RelatedRecord') or
688  is_a($obj, 'Dataface_Relationship') ){
689  //echo "Getting permissions: "; print_r($params);
690  $perms = $obj->getPermissions($params);
691  $me->filterPermissions($obj, $perms, $params);
692  return $perms;
693  }
694  throw new Exception(
695  df_translate(
696  'scripts.Dataface.PermissionsTool.getPermissions.ERROR_PARAMETER_1',
697  'In Dataface_PermissionsTool, expected first argument to be Dataface_Table, Dataface_Record, or Dataface_Relationship, but received '.get_class($obj)."\n<br>",
698  array('class'=>get_class($obj))
699  ),E_USER_ERROR);
700  }
701 
702  function filterPermissions(&$obj, &$perms, $params=array()){
703  if ( isset($this->delegate) and method_exists($this->delegate, 'filterPermissions') ) $this->delegate->filterPermissions($obj, $perms, $params);
704  }
705 
712  function checkPermission($permissionName, $perms, $params=array()){
713  $me =& $this;
714 
715 
716  if ( is_array($perms) ){
717 
718  return (isset( $perms[$permissionName]) and $perms[$permissionName]);
719  }
720 
721  if ( PEAR::isError($perms) ){
722  throw new Exception($perms->toString(), E_USER_ERROR);
723  }
724 
725  if ( !is_object($perms) ){
726  return array();
727 
728  }
729 
730  // If we are this far, then $perms must be an object.. so we must get the object's
731  // permissions array and recall this method on it.
732  return $me->checkPermission($permissionName, $me->getPermissions($perms, $params) );
733  }
734 
742  function view(&$perms, $params=array()){
743  $me =& $this;
744  return $me->checkPermission('view', $perms, $params);
745 
746  }
747 
755  function edit(&$perms, $params=array()){
756  $me =& $this;
757  return $me->checkPermission('edit', $perms, $params);
758 
759  }
760 
768  function delete(&$perms, $params=array()){
769  $me =& $this;
770 
771  return $me->checkPermission('delete',$perms,$params);
772  }
773 
774  function MASK(){
775  $me =& $this;
776  if ( isset($me->_cache['mask'] ) ) return $me->_cache['mask'];
777  else {
778 
779  //$perms = array_flip($me->permissions);
780  //$perms = array_map(array(&$me, '_zero'), $me->permissions);
781  $perms = $me->permissions;
782  foreach (array_keys($perms) as $key){
783  $perms[$key] = 0;
784  }
785  $me->_cache['mask'] = $perms;
786  return $perms;
787  }
788 
789  }
790 
791  function _zero(){
792  return 0;
793  }
794 
795  function _one(){
796  return 1;
797  }
798 
802  function NO_ACCESS(){
803  static $no_access = 0;
804  if ( $no_access === 0 ){
805  $no_access = Dataface_PermissionsTool::MASK();
806  }
807  return $no_access;
808  }
809 
815  function READ_ONLY(){
816  $me =& $this;
817  if ( isset($me->_cache['read_only']) ) return $me->_cache['read_only'];
818 
819 
820  $read_only = /*array_merge($me->MASK(),*/ $me->getRolePermissions('READ ONLY')/*)*/;
821  $read_only = array_map('intval', $read_only);
822  $me->_cache['read_only'] = $read_only;
823 
824  return $read_only;
825  }
826 
832  function ALL(){
833  $me =& $this;
834  if ( isset($me->_cache['all']) ) return $me->_cache['all'];
835  $perms = array();
836  foreach ( array_keys($me->permissions) as $key){
837  $perms[$key] = 1;
838  }
839  $me->_cache['all'] = $perms;
840  return $perms;
841  }
842 
848  function &READ_EDIT(){
849  $me =& $this;
850  if ( isset($me->_cache['read_edit']) ) return $me->_cache['read_edit'];
851  $read_and_edit = /*array_merge($me->MASK(),*/ $me->getRolePermissions('EDIT')/*)*/;
852  $read_and_edit = array_map('intval', $read_and_edit);
853  $me->_cache['read_edit'] = $read_and_edit;
854  return $read_and_edit;
855  }
856 
857 
875  function &getRolePermissions($roleName){
876  $me =& $this;
877  if ( !isset($me->rolePermissions[$roleName]) ){
878  // it looks like the role has not been defined
879  throw new Exception(
881  'Role not found',
882  'The role "'.$roleName.'" is not a registered role.',
883  array('role'=>$roleName)
884  ), E_USER_ERROR
885  );
886  }
887 
888  return $me->rolePermissions[$roleName];
889 
890 
891  }
892 
893  function roleExists($roleName){
894  return isset($this->rolePermissions[$roleName]);
895  }
896 
897 
902  if ( !is_array($permissions) ) throw new Exception("namesAsArray expects array.");
903  $names = array();
904  foreach ( $permissions as $key=>$value){
905  if ( $value ){
906  $names[] = $key;
907  }
908  }
909 
910  return $names;
911  }
912 
913 
920  }
921 
922  function cachePermissions(&$record, $params, $perms){
923  if (!isset($record) ){
924  if ( isset($params['table']) ){
925  $record_id = $params['table'];
926  } else {
927  $record_id='__null__';
928  }
929  }
930  else $record_id = $record->getId();
931 
932  if ( count($params) > 0 ){
933  $qstr = array();
934  foreach ( $params as $key=>$value ){
935  if ( is_object($value) or is_array($value) ) return null;
936  $qstr[] = urlencode($key).'='.urlencode($value);
937  }
938  $qstr = implode('&', $qstr);
939  } else {
940  $qstr = '0';
941  }
942 
943  $this->_cache['__permissions'][$record_id][$qstr] = $perms;
944 
945  }
946 
947  function getCachedPermissions(&$record, $params){
948  if (!isset($record) ){
949  if ( isset($params['table']) ){
950  $record_id = $params['table'];
951  } else {
952  $record_id='__null__';
953  }
954  }
955  else $record_id = $record->getId();
956 
957  if ( count($params) > 0 ){
958  $qstr = array();
959  foreach ( $params as $key=>$value ){
960  if ( is_object($value) or is_array($value) ) return null;
961  $qstr[] = urlencode($key).'='.urlencode($value);
962  }
963  $qstr = implode('&', $qstr);
964  } else {
965  $qstr = '0';
966  }
967 
968  if (isset($this->_cache['__permissions'][$record_id][$qstr]) ){
969  return $this->_cache['__permissions'][$record_id][$qstr];
970  } else {
971  return null;
972  }
973  }
974 
975 
976 
977 
978 
979 }
980 
981 
982 
983