source: trunk/phpgwapi/inc/class.acl.inc.php @ 2

Revision 2, 18.5 KB checked in by niltonneto, 17 years ago (diff)

Removida todas as tags usadas pelo CVS ($Id, $Source).
Primeira versão no CVS externo.

  • Property svn:eol-style set to native
  • Property svn:executable set to *
Line 
1<?php
2  /**************************************************************************\
3  * eGroupWare API - Access Control List                                     *
4  * This file written by Dan Kuykendall <seek3r@phpgroupware.org>            *
5  * Security scheme based on ACL design                                      *
6  * Copyright (C) 2000, 2001 Dan Kuykendall                                  *
7  * -------------------------------------------------------------------------*
8  * This library is part of the eGroupWare API                               *
9  * http://www.egroupware.org/api                                            *
10  * ------------------------------------------------------------------------ *
11  * This library is free software; you can redistribute it and/or modify it  *
12  * under the terms of the GNU Lesser General Public License as published by *
13  * the Free Software Foundation; either version 2.1 of the License,         *
14  * or any later version.                                                    *
15  * This library is distributed in the hope that it will be useful, but      *
16  * WITHOUT ANY WARRANTY; without even the implied warranty of               *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                     *
18  * See the GNU Lesser General Public License for more details.              *
19  * You should have received a copy of the GNU Lesser General Public License *
20  * along with this library; if not, write to the Free Software Foundation,  *
21  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA            *
22  \**************************************************************************/
23
24
25        /*!
26                @class acl
27                @abstract Access Control List Security System
28                @discussion This class provides an ACL security scheme.
29                This can manage rights to 'run' applications, and limit certain features within an application.
30                It is also used for granting a user "membership" to a group, or making a user have the security equivilance of another user.
31                It is also used for granting a user or group rights to various records, such as todo or calendar items of another user.
32                @syntax CreateObject('phpgwapi.acl',int account_id);
33                @example $acl = CreateObject('phpgwapi.acl',5);  // 5 is the user id
34                @example $acl = CreateObject('phpgwapi.acl',10);  // 10 is the user id
35                @author Seek3r
36                @copyright LGPL
37                @package phpgwapi
38                @access public
39        */
40        class acl
41        {
42                /*! @var $account_id */
43                var $account_id;
44                /*! @var $account_type */
45                var $account_type;
46                /*! @var $data  */
47                var $data = Array();
48                /*! @var $db */
49                var $db;
50                var $table_name = 'phpgw_acl';
51
52                /*!
53                @function acl
54                @abstract ACL constructor for setting account id
55                @discussion Author: Seek3r <br>
56                Sets the ID for $acl->account_id. Can be used to change a current instances id as well. <br>
57                Some functions are specific to this account, and others are generic. <br>
58                @syntax int acl(int account_id) <br>
59                @example1 acl->acl(5); // 5 is the user id  <br>
60                @param account_id int-the user id
61                */
62                function acl($account_id = '')
63                {
64                        $this->db = clone($GLOBALS['phpgw']->db);
65                        $this->db->set_app('phpgwapi');
66
67                        if ((int)$this->account_id != (int)$account_id)
68                        {
69                                $this->account_id = get_account_id((int)$account_id,@$GLOBALS['phpgw_info']['user']['account_id']);
70                        }
71                }
72
73                function DONTlist_methods($_type='xmlrpc')
74                {
75                        /*
76                          This handles introspection or discovery by the logged in client,
77                          in which case the input might be an array.  The server always calls
78                          this function to fill the server dispatch map using a string.
79                        */
80
81                        if (is_array($_type))
82                        {
83                                $_type = $_type['type'] ? $_type['type'] : $_type[0];
84                        }
85
86                        switch($_type)
87                        {
88                                case 'xmlrpc':
89                                $xml_functions = array(
90                                                'read_repository' => array(
91                                                        'function'  => 'read_repository',
92                                                        'signature' => array(array(xmlrpcStruct)),
93                                                        'docstring' => lang('FIXME!')
94                                                ),
95                                                'get_rights' => array(
96                                                        'function'  => 'get_rights',
97                                                        'signature' => array(array(xmlrpcStruct,xmlrpcStruct)),
98                                                        'docstring' => lang('FIXME!')
99
100                                                ),
101                                                'list_methods' => array(
102                                                        'function'  => 'list_methods',
103                                                        'signature' => array(array(xmlrpcStruct,xmlrpcString)),
104                                                        'docstring' => lang('Read this list of methods.')
105                                                )
106                                        );
107                                        return $xml_functions;
108                                        break;
109                                case 'soap':
110                                        return $this->soap_functions;
111                                        break;
112                                default:
113                                        return array();
114                                        break;
115                        }
116                }
117
118                /**************************************************************************\
119                * These are the standard $this->account_id specific functions              *
120                \**************************************************************************/
121
122                /*!
123                @function read_repository
124                @abstract Read acl records from reposity
125                @discussion Author: Seek3r <br>
126                Reads ACL records for $acl->account_id and returns array along with storing it in $acl->data.  <br>
127                Syntax: array read_repository() <br>
128                Example1: acl->read_repository(); <br>
129                Should only be called within this class
130                */
131                function read_repository()
132                {
133                        // For some reason, calling this via XML-RPC doesn't call the constructor.
134                        // Here is yet another work around(tm) (jengo)
135                        if (!$this->account_id)
136                        {
137                                $this->acl();
138                        }
139                        $acl_acc_list = array_values((array)$this->get_location_list_for_id('phpgw_group', 1, $this->account_id));
140                        array_unshift($acl_acc_list,$this->account_id,0);
141                        $this->db->select($this->table_name,'*',array('acl_account' => $acl_acc_list ),__LINE__,__FILE__);
142                       
143                        $this->data = Array();
144                        while($this->db->next_record())
145                        {
146                                $this->data[] = array(
147                                        'appname'  => $this->db->f('acl_appname'),
148                                        'location' => $this->db->f('acl_location'),
149                                        'account'  => $this->db->f('acl_account'),
150                                        'rights'   => $this->db->f('acl_rights')
151                                );
152                        }
153                        return $this->data;
154                }
155
156                /*!
157                @function read
158                @abstract Read acl records from $acl->data
159                @discussion Author: Seek3r <br>
160                Returns ACL records from $acl->data. <br>
161                Syntax: array read() <br>
162                Example1: acl->read(); <br>
163                */
164                function read()
165                {
166                        if (!count($this->data))
167                        {
168                                $this->read_repository();
169                        }
170                        return $this->data;
171                }
172
173                /*!
174                @function add
175                @abstract Adds ACL record to $acl->data
176                @discussion Adds ACL record to $acl->data. <br>
177                Syntax: array add() <br>
178                Example1: acl->add();
179                @param $appname default False derives value from $phpgw_info['flags']['currentapp']
180                @param $location location
181                @param $rights rights
182                */
183                function add($appname,$location,$rights)
184                {
185                        if (!$appname) $appname = $GLOBALS['phpgw_info']['flags']['currentapp'];
186
187                        $this->data[] = array(
188                                'appname'  => $appname,
189                                'location' => $location,
190                                'account'  => (int) $this->account_id,
191                                'rights'   => (int) $rights
192                        );
193
194                        return $this->data;
195                }
196
197                /*!
198                @function delete
199                @abstract Delete ACL record
200                @discussion
201                Syntax <br>
202                Example: <br>
203                @param $appname optional defaults to $phpgw_info['flags']['currentapp']
204                @param $location app location
205                */
206                function delete($appname, $location)
207                {
208                        if (!$appname) $appname = $GLOBALS['phpgw_info']['flags']['currentapp'];
209
210                        foreach($this->data as $idx => $value)
211                        {
212                                if ($this->data[$idx]['appname'] == $appname && $this->data[$idx]['location'] == $location && $this->data[$idx]['account'] == $this->account_id)
213                                {
214                                        unset($this->data[$idx]);
215                                }
216                        }
217                        return $this->data;
218                }
219
220                /*!
221                @function save_repostiory
222                @abstract save repository
223                @discussion save the repository <br>
224                Syntax: save_repository() <br>
225                example: acl->save_repository()
226                */
227               
228                function save_repository()
229                {
230                        $this->db->delete($this->table_name,array(
231                                'acl_account' => $this->account_id,
232                        ),__LINE__,__FILE__);
233
234                        foreach($this->data as $value)
235                        {
236                                if ($value['account'] == $this->account_id)
237                                {
238                                        $this->db->insert($this->table_name,array(
239                                                'acl_appname'  => $value['appname'],
240                                                'acl_location' => $value['location'],
241                                                'acl_account'  => $this->account_id,
242                                                'acl_rights'   => $value['rights'],
243                                        ),false,__LINE__,__FILE__);
244                                }
245                        }
246                        return $this->data;
247                }
248
249                /**************************************************************************\
250                * These are the non-standard $this->account_id specific functions          *
251                \**************************************************************************/
252
253                /*!
254                @function get_rights
255                @abstract get rights from the repository not specific to this->account_id (?)
256                @discussion
257                @param $location app location to get rights from
258                @param $appname optional defaults to $phpgw_info['flags']['currentapp'];
259                */
260                function get_rights($location,$appname = False)
261                {
262                        // For XML-RPC, change this once its working correctly for passing parameters (jengo)
263                        if (is_array($location))
264                        {
265                                $appname  = $location['appname'];
266                                $location = $location['location'];
267                        }
268
269                        if (!count($this->data))
270                        {
271                                $this->read_repository();
272                        }
273                        if (!$appname) $appname = $GLOBALS['phpgw_info']['flags']['currentapp'];
274
275                        if (!count($this->data) && $GLOBALS['phpgw_info']['server']['acl_default'] != 'deny')
276                        {
277                                return True;
278                        }
279                        $rights = 0;
280                        foreach($this->data as $idx => $value)
281                        {
282                                if ($value['appname'] == $appname)
283                                {
284                                        if ($value['location'] == $location || $value['location'] == 'everywhere')
285                                        {
286                                                if ($value['rights'] == 0)
287                                                {
288                                                        return False;
289                                                }
290                                                $rights |= $value['rights'];
291                                        }
292                                }
293                        }
294                        return $rights;
295                }
296                /*!
297                @function check
298                @abstract check required rights (not specific to this->account_id?)
299                @param $location app location
300                @param $required required right to check against
301                @param $appname optional defaults to currentapp
302                */
303                function check($location, $required, $appname = False)
304                {
305                        $rights = $this->get_rights($location,$appname);
306
307                        return !!($rights & $required);
308                }
309                /*!
310                @function get_specific_rights
311                @abstract get specific rights for this->account_id for an app location
312                @param $location app location
313                @param $appname optional defaults to currentapp
314                @result $rights ?
315                */
316                function get_specific_rights($location, $appname = False)
317                {
318                        if (!$appname) $appname = $GLOBALS['phpgw_info']['flags']['currentapp'];
319
320                        if (!count($this->data) && $GLOBALS['phpgw_info']['server']['acl_default'] != 'deny')
321                        {
322                                return True;
323                        }
324                        $rights = 0;
325
326                        foreach($this->data as $idx => $value)
327                        {
328                                if ($value['appname'] == $appname &&
329                                        ($value['location'] == $location ||     $value['location'] == 'everywhere') &&
330                                        $value['account'] == $this->account_id)
331                                {
332                                        if ($value['rights'] == 0)
333                                        {
334                                                return False;
335                                        }
336                                        $rights |= $value['rights'];
337                                }
338                        }
339                        return $rights;
340                }
341                /*!
342                @function check_specific
343                @abstract check specific
344                @param $location app location
345                @param $required required rights
346                @param $appname optional defaults to currentapp
347                @result boolean
348                */
349                function check_specific($location, $required, $appname = False)
350                {
351                        $rights = $this->get_specific_rights($location,$appname);
352
353                        return !!($rights & $required);
354                }
355
356                /**************************************************************************\
357                * These are the generic functions. Not specific to $this->account_id       *
358                \**************************************************************************/
359
360                /**
361                 * add repository information / rights for app/location/account_id
362                 *
363                 * @param $app appname
364                 * @param $location location
365                 * @param $account_id account id
366                 * @param $rights rights
367                 */
368                function add_repository($app, $location, $account_id, $rights)
369                {
370                        //echo "<p>acl::add_repository('$app','$location',$account_id,$rights);</p>\n";
371                        $this->db->insert($this->table_name,array(
372                                'acl_rights' => $rights,
373                        ),array(
374                                'acl_appname' => $app,
375                                'acl_location' => $location,
376                                'acl_account'  => $account_id,
377                        ),__LINE__,__FILE__);
378
379                        return True;
380                }
381
382                /**
383                 * delete repository information / rights for app/location[/account_id]
384                 * @param string $app appname
385                 * @param string $location location
386                 * @param int/boolean $account_id account id, default 0=$this->account_id, or false to delete all entries for $app/$location
387                 * @return int number of rows deleted
388                 */
389                function delete_repository($app, $location, $accountid='')
390                {
391                        static $cache_accountid;
392
393                        $where = array(
394                                'acl_appname'  => $app,
395                                'acl_location' => $location,
396                        );
397                        if ($accountid !== false)
398                        {
399                                if(isset($cache_accountid[$accountid]) && $cache_accountid[$accountid])
400                                {
401                                        $where['acl_account'] = $cache_accountid[$accountid];
402                                }
403                                else
404                                {
405                                        $where['acl_account'] = $cache_accountid[$accountid] = get_account_id($accountid,$this->account_id);
406                                }
407                        }
408                        if ($app == '%' || $app == '%%') unset($where['acl_appname']);
409
410                        $this->db->delete($this->table_name,$where,__LINE__,__FILE__);
411
412                        return $this->db->affected_rows();
413                }
414
415                /*!
416                @function get_app_list_for_id
417                @abstract get application list for an account id
418                @param $location location
419                @param $required ?
420                @param $account_id account id defaults to $phpgw_info['user']['account_id'];
421                */
422                function get_app_list_for_id($location, $required, $accountid = '')
423                {
424                        static $cache_accountid;
425
426                        if($cache_accountid[$accountid])
427                        {
428                                $account_id = $cache_accountid[$accountid];
429                        }
430                        else
431                        {
432                                $account_id = get_account_id($accountid,$this->account_id);
433                                $cache_accountid[$accountid] = $account_id;
434                        }
435                        $this->db->select($this->table_name,array('acl_appname','acl_rights'),array(
436                                'acl_location' => $location,
437                                'acl_account'  => $account_id,
438                        ),__LINE__,__FILE__);
439
440                        $rights = 0;
441                        $apps = false;
442                        while ($this->db->next_record())
443                        {
444                                if ($this->db->f('acl_rights') == 0)
445                                {
446                                        return False;
447                                }
448                                $rights |= $this->db->f('acl_rights');
449                                if (!!($rights & $required))
450                                {
451                                        $apps[] = $this->db->f('acl_appname');
452                                }
453                        }
454                        return $apps;
455                }
456
457                /*!
458                @function get_location_list_for_id
459                @abstract get location list for id
460                @discussion ?
461                @param $app app
462                @param $required required
463                @param $account_id optional defaults to $phpgw_info['user']['account_id'];
464                */
465                function get_location_list_for_id($app, $required, $accountid = '')
466                {
467                        static $cache_accountid;
468
469                        if($cache_accountid[$accountid])
470                        {
471                                $accountid = $cache_accountid[$accountid];
472                        }
473                        else
474                        {
475                                $accountid = $cache_accountid[$accountid] = get_account_id($accountid,$this->account_id);
476                        }
477                        $this->db->select($this->table_name,'acl_location,acl_rights',array(
478                                'acl_appname' => $app,
479                                'acl_account' => $accountid,
480                        ),__LINE__,__FILE__);
481
482                        $locations = false;
483                        while ($this->db->next_record())
484                        {
485                                if ($this->db->f('acl_rights') & $required)
486                                {
487                                        $locations[] = $this->db->f('acl_location');
488                                }
489                        }
490                        return $locations;
491                }
492                /*!
493                @function get_ids_for_location
494                @abstract get ids for location
495                @param $location location
496                @param $required required
497                @param $app app optional defaults to $phpgw_info['flags']['currentapp'];
498                */
499                function get_ids_for_location($location, $required, $app = False)
500                {
501                        if (!$app) $app = $GLOBALS['phpgw_info']['flags']['currentapp'];
502
503                        $this->db->select($this->table_name,array('acl_account','acl_rights'),array(
504                                'acl_appname'  => $app,
505                                'acl_location' => $location,
506                        ),__LINE__,__FILE__);
507
508                        $accounts = false;
509                        while ($this->db->next_record())
510                        {
511                                if (!!($this->db->f('acl_rights') & $required))
512                                {
513                                        $accounts[] = (int) $this->db->f('acl_account');
514                                }
515                        }
516                        return $accounts;
517                }
518
519                /*!
520                @function get_user_applications
521                @abstract get a list of applications a user has rights to
522                @param $account_id optional defaults to $phpgw_info['user']['account_id'];
523                @result $apps array containing list of apps
524                */
525                function get_user_applications($accountid = '')
526                {
527                        static $cache_accountid;
528
529                        if($cache_accountid[$accountid])
530                        {
531                                $account_id = $cache_accountid[$accountid];
532                        }
533                        else
534                        {
535                                $account_id = get_account_id($accountid,$this->account_id);
536                                $cache_accountid[$accountid] = $account_id;
537                        }
538                        $memberships = array($account_id);
539                        foreach((array)$GLOBALS['phpgw']->accounts->membership($account_id) as $group)
540                        {
541                                $memberships[] = $group['account_id'];
542                        }
543                        $db2 = clone($this->db);
544                        $db2->select($this->table_name,array('acl_appname','acl_rights'),array(
545                                'acl_location' => 'run',
546                                'acl_account'  => $memberships,
547                        ),__LINE__,__FILE__);
548
549                        $apps = false;
550                        while ($db2->next_record())
551                        {
552                                $app = $db2->f('acl_appname');
553                                if(!isset($apps[$app]))
554                                {
555                                        $apps[$app] = 0;
556                                }
557                                $apps[$app] |= (int) $db2->f('acl_rights');
558                        }
559                        return $apps;
560                }
561                /*!
562                @function get_grants
563                @abstract ?
564                @param $app optional defaults to $phpgw_info['flags']['currentapp'];
565                */
566                function get_grants($app='')
567                {
568                        if (!$app) $app = $GLOBALS['phpgw_info']['flags']['currentapp'];
569
570                        $memberships = array($this->account_id);
571                        foreach((array)$GLOBALS['phpgw']->accounts->membership($this->account_id) as $group)
572                        {
573                                $memberships[] = $group['account_id'];
574                        }
575                        $db2 = clone($this->db);
576                        $db2->select($this->table_name,array('acl_account','acl_rights'),array(
577                                'acl_appname'  => $app,
578                                'acl_location' => $memberships,
579                        ),__LINE__,__FILE__);
580                       
581                        $grants = $accounts = Array();
582                        while ($db2->next_record())
583                        {
584                                $grantor = $db2->f('acl_account');
585                                $rights = $db2->f('acl_rights');
586
587                                if(!isset($accounts[$grantor]))
588                                // cache the group-members for performance
589                                {
590                                        // if $grantor is a group, get its members
591                                        $members = $this->get_ids_for_location($grantor,1,'phpgw_group');
592                                        if(!$members)
593                                        {
594                                                $accounts[$grantor] = Array($grantor);
595                                                $is_group[$grantor] = False;
596                                        }
597                                        else
598                                        {
599                                                $accounts[$grantor] = $members;
600                                                $is_group[$grantor] = True;
601                                        }
602                                }
603                                if(@$is_group[$grantor])
604                                {
605                                        // Don't allow to override private!
606                                        $rights &= (~ PHPGW_ACL_PRIVATE);
607                                        if(!isset($grants[$grantor]))
608                                        {
609                                                $grants[$grantor] = 0;
610                                        }
611                                        $grants[$grantor] |= $rights;
612                                        if(!!($rights & PHPGW_ACL_READ))
613                                        {
614                                                $grants[$grantor] |= PHPGW_ACL_READ;
615                                        }
616                                }
617                                foreach($accounts[$grantor] as $grantors)
618                                {
619                                        if(!isset($grants[$grantors]))
620                                        {
621                                                $grants[$grantors] = 0;
622                                        }
623                                        $grants[$grantors] |= $rights;
624                                }
625                        }
626                        $grants[$GLOBALS['phpgw_info']['user']['account_id']] = ~0;
627
628                        return $grants;
629                }
630               
631                /**
632                 * Deletes all ACL entries for an account (user or group)
633                 *
634                 * @param int $account_id acount-id
635                 */
636                function delete_account($account_id)
637                {
638                        if ((int) $account_id)
639                        {
640                                $this->db->delete($this->table_name,array(
641                                        'acl_account' => $account_id
642                                ),__LINE__,__FILE__);
643                                // delete all memberships in account_id (if it is a group)
644                                $this->db->delete($this->table_name,array(
645                                        'acl_appname' => 'phpgw_group',
646                                        'acl_location' => $account_id,
647                                ),__LINE__,__FILE__);
648                        }
649                }
650        } //end of acl class
Note: See TracBrowser for help on using the repository browser.