removing all it's acl-rights if an account gets deleted, admin only removed the run-rights, but not the grants or other rights

This commit is contained in:
Ralf Becker 2004-08-07 12:45:39 +00:00
parent 9ba1c6b641
commit 7f79ff3d66
2 changed files with 1486 additions and 0 deletions

View File

@ -0,0 +1,700 @@
<?php
/**************************************************************************\
* eGroupWare API - Accounts manager shared functions *
* Written by Joseph Engo <jengo@phpgroupware.org> *
* and Bettina Gille [ceb@phpgroupware.org] *
* shared functions for other account repository managers *
* Copyright (C) 2000 - 2002 Joseph Engo *
* Copyright (C) 2003 Joseph Engo, Bettina Gille *
* -------------------------------------------------------------------------*
* This library is part of the eGroupWare API *
* http://www.egroupware.org *
* ------------------------------------------------------------------------ *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 2.1 of the License, *
* or any later version. *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* You should have received a copy of the GNU Lesser General Public License *
* along with this library; if not, write to the Free Software Foundation, *
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
\**************************************************************************/
/* $Id$ */
if (empty($GLOBALS['phpgw_info']['server']['account_repository']))
{
if (!empty($GLOBALS['phpgw_info']['server']['auth_type']))
{
$GLOBALS['phpgw_info']['server']['account_repository'] = $GLOBALS['phpgw_info']['server']['auth_type'];
}
else
{
$GLOBALS['phpgw_info']['server']['account_repository'] = 'sql';
}
}
include_once(PHPGW_API_INC . '/class.accounts_' . $GLOBALS['phpgw_info']['server']['account_repository'] . '.inc.php');
/*
Dont know where to put this (seek3r)
This is where it belongs (jengo)
This is where it ended up (milosch)
Moved again at least temporarily since sql and ldap use it.
*/
$GLOBALS['phpgw_info']['server']['global_denied_users'] = array(
'root' => True, 'bin' => True, 'daemon' => True,
'adm' => True, 'lp' => True, 'sync' => True,
'shutdown' => True, 'halt' => True, 'ldap' => True,
'mail' => True, 'news' => True, 'uucp' => True,
'operator' => True, 'games' => True, 'gopher' => True,
'nobody' => True, 'xfs' => True, 'pgsql' => True,
'mysql' => True, 'postgres' => True, 'oracle' => True,
'ftp' => True, 'gdm' => True, 'named' => True,
'alias' => True, 'web' => True, 'sweep' => True,
'cvs' => True, 'qmaild' => True, 'qmaill' => True,
'qmaillog' => True, 'qmailp' => True, 'qmailq' => True,
'qmailr' => True, 'qmails' => True, 'rpc' => True,
'rpcuser' => True, 'amanda' => True, 'apache' => True,
'pvm' => True, 'squid' => True, 'ident' => True,
'nscd' => True, 'mailnull' => True, 'cyrus' => True,
'backup' => True
);
$GLOBALS['phpgw_info']['server']['global_denied_groups'] = array(
'root' => True, 'bin' => True, 'daemon' => True,
'sys' => True, 'adm' => True, 'tty' => True,
'disk' => True, 'lp' => True, 'mem' => True,
'kmem' => True, 'wheel' => True, 'mail' => True,
'uucp' => True, 'man' => True, 'games' => True,
'dip' => True, 'ftp' => True, 'nobody' => True,
'floppy' => True, 'xfs' => True, 'console' => True,
'utmp' => True, 'pppusers' => True, 'popusers' => True,
'slipusers' => True, 'slocate' => True, 'mysql' => True,
'dnstools' => True, 'web' => True, 'named' => True,
'dba' => True, 'oinstall' => True, 'oracle' => True,
'gdm' => True, 'sweep' => True, 'cvs' => True,
'postgres' => True, 'qmail' => True, 'nofiles' => True,
'ldap' => True, 'backup' => True
);
/*!
@class_start accounts
@abstract Class for handling user and group accounts
*/
class accounts extends accounts_
{
var $memberships = array();
var $members = array();
var $xmlrpc_methods = array();
// enables the session-cache
var $use_session_cache = True;
/**************************************************************************\
* Standard constructor for setting $this->account_id *
* This constructor sets the account id, if string is sent, converts to id *
* I might move this to the accounts_shared if it stays around *
\**************************************************************************/
function accounts($account_id = '', $account_type='')
{
// enable the caching in the session onyl for ldap
$this->use_session_cache = $GLOBALS['phpgw_info']['server']['account_repository'] == 'ldap';
$this->db = $GLOBALS['phpgw']->db;
if($account_id != '')
{
$this->account_id = get_account_id($account_id);
}
if($account_type != '')
{
$this->account_type = $account_type;
}
$this->query_types = array(
'all' => 'all fields',
'firstname' => 'firstname',
'lastname' => 'lastname',
'lid' => 'LoginID',
'email' => 'email',
'start' => 'start with',
'exact' => 'exact',
);
$this->accounts_(); // call constructor of extended class
$this->xmlrpc_methods[] = array(
'name' => 'get_list',
'description' => 'Returns a list of accounts and/or groups'
);
$this->xmlrpc_methods[] = array(
'name' => 'name2id',
'description' => 'Cross reference account_lid with account_id'
);
$this->xmlrpc_methods[] = array(
'name' => 'id2name',
'description' => 'Cross reference account_id with account_lid'
);
}
/**
* Sets up the account-data cache
*
* The cache is shared between all instances of the account-class and it can be save in the session,
* if use_session_cache is set to True
*/
function setup_cache()
{
if ($this->use_session_cache && // are we supposed to use a session-cache
!@$GLOBALS['phpgw_info']['accounts']['session_cache_setup'] && // is it already setup
// is the account-class ready (startup !)
is_object($GLOBALS['phpgw']->session) && $GLOBALS['phpgw']->session->account_id)
{
// setting up the session-cache
$GLOBALS['phpgw_info']['accounts']['cache'] = $GLOBALS['phpgw']->session->appsession('accounts_cache','phpgwapi');
$GLOBALS['phpgw_info']['accounts']['session_cache_setup'] = True;
//echo "accounts::setup_cache() cache=<pre>".print_r($GLOBALS['phpgw_info']['accounts']['cache'],True)."</pre>\n";
}
if (!isset($this->cache))
{
$this->cache = &$GLOBALS['phpgw_info']['accounts']['cache'];
}
}
/**
* Saves the account-data cache in the session
*
* Gets called from common::phpgw_final()
*/
function save_session_cache()
{
if ($this->use_session_cache && // are we supposed to use a session-cache
$GLOBALS['phpgw_info']['accounts']['session_cache_setup'] && // is it already setup
// is the account-class ready (startup !)
is_object($GLOBALS['phpgw']->session))
{
$GLOBALS['phpgw']->session->appsession('accounts_cache','phpgwapi',$GLOBALS['phpgw_info']['accounts']['cache']);
}
}
/**
* Searches / lists accounts: users and/or groups
*
* @param $param['type'] string/int 'accounts', 'groups', 'owngroups' (groups the user is a member of), 'both'
* or integer group-id for a list of members of that group
* @param $param['start'] int first account to return (returns offset or max_matches entries) or all if not set
* @param $param['sort'] string column to sort after, default account_lid if unset
* @param $param['order'] string 'ASC' or 'DESC', default 'DESC' if not set
* @param $param['query'] string to search for, no search if unset or empty
* @param $param['query_type'] string:
* 'all' - query all fields for containing $param[query]
* 'start' - query all fields starting with $param[query]
* 'exact' - query all fields for exact $param[query]
* 'lid','firstname','lastname','email' - query only the given field for containing $param[query]
* @param $param['app'] string with an app-name, to limit result on accounts with run-right for that app
* @param $param['offset'] int - number of matches to return if start given, default use the value in the prefs
* @return array with uid / data pairs, data is an array with account_id, account_lid, account_firstname,
* account_lastname, person_id (id of the linked addressbook entry), account_status, account_expires, account_primary_group
*/
function search($param)
{
//echo "<p>accounts::search(".print_r($param,True).")</p>\n";
$this->setup_cache();
$account_search = &$this->cache['account_search'];
$serial = serialize($param);
if (isset($account_search[$serial]))
{
$this->total = $account_search[$serial]['total'];
}
elseif (function_exists('accounts_::search')) // implements its on search function ==> use it
{
$account_search[$serial]['data'] = accounts_::search($param);
$account_search[$serial]['total'] = $this->total;
}
else
{
$serial2 = $serial;
if (is_numeric($param['type']) || $param['app'] || $param['type'] == 'owngroups') // do we need to limit the search on a group or app?
{
$app = $param['app'];
unset($param['app']);
if (is_numeric($param['type']))
{
$group = (int) $param['type'];
$param['type'] = 'accounts';
}
elseif ($param['type'] == 'owngroups')
{
$group = -1;
$param['type'] = 'groups';
}
$start = $param['start'];
unset($param['start']);
$serial2 = serialize($param);
}
if (!isset($account_search[$serial2])) // check if we already did this general search
{
$account_search[$serial2]['data'] = array();
$accounts = accounts_::get_list($param['type'],$param['start'],$param['sort'],$param['order'],$param['query'],$param['offset'],$param['query_type']);
if (!$accounts) $accounts = array();
foreach($accounts as $data)
{
$account_search[$serial2]['data'][$data['account_id']] = $data;
}
$account_search[$serial2]['total'] = $this->total;
}
else
{
$this->total = $account_search[$serial2]['total'];
}
//echo "accounts_::get_list($param[type],$param[start],$param[sort],$param[order],$param[query],$param[offset],$param[query_type]) returned<pre>".print_r($account_search[$serial2],True)."</pre>\n";
if ($app || $group) // limit the search on accounts with run-rights for app or a group
{
$valid = array();
if ($app)
{
$valid = $this->split_accounts($app,$param['type'] == 'both' ? 'merge' : $param['type']);
}
if ($group)
{
$members = $group > 0 ? $GLOBALS['phpgw']->acl->get_ids_for_location($group, 1, 'phpgw_group') :
$GLOBALS['phpgw']->acl->get_location_list_for_id('phpgw_group', 1,$GLOBALS['phpgw_info']['user']['account_id']);
if (!$members) $members = array();
$valid = !$app ? $members : array_intersect($valid,$members); // use the intersection
}
//echo "<p>limiting result to app='app' and/or group=$group valid-ids=".print_r($valid,true)."</p>\n";
$offset = $param['offset'] ? $param['offset'] : $GLOBALS['phpgw_info']['user']['preferences']['common']['maxmatchs'];
$stop = $start + $offset;
$n = 0;
$account_search[$serial]['data'] = array();
foreach ($account_search[$serial2]['data'] as $id => $data)
{
if (!in_array($id,$valid))
{
$this->total--;
continue;
}
// now we have a valid entry
if (!is_int($start) || $start <= $n && $n < $stop)
{
$account_search[$serial]['data'][$id] = $data;
}
$n++;
}
$account_search[$serial]['total'] = $this->total;
}
}
//echo "<p>accounts::search('$serial')=<pre>".print_r($account_search[$serial]['data'],True).")</pre>\n";
return $account_search[$serial]['data'];
}
function get_list($_type='both',$start = '',$sort = '', $order = '', $query = '', $offset = '',$query_type='')
{
//echo "<p>accounts::get_list(".print_r($_type,True).",start='$start',sort='$sort',order='$order',query='$query',offset='$offset')</p>\n";
$this->setup_cache();
$account_list = &$this->cache['account_list'];
// For XML-RPC
if (is_array($_type))
{
$p = $_type;
$_type = $p['type'];
$start = $p['start'];
$order = $p['order'];
$query = $p['query'];
$offset = $p['offset'];
$query_type = $p['query_type'];
}
else
{
$p = array(
'type' => $_type,
'start' => $start,
'order' => $order,
'query' => $query,
'offset' => $offset,
'query_type' => $query_type ,
);
}
$serial = serialize($p);
if (isset($account_list[$serial]))
{
$this->total = $account_list[$serial]['total'];
}
else
{
$account_list[$serial]['data'] = accounts_::get_list($_type,$start,$sort,$order,$query,$offset,$query_type);
$account_list[$serial]['total'] = $this->total;
}
return $account_list[$serial]['data'];
}
function is_expired()
{
if ($this->data['expires'] != -1 && $this->data['expires'] < time())
{
return True;
}
else
{
return False;
}
}
/**
* Invalidate the cache (or parts of it) after change in $account_id
*
* Atm simplest approach - delete it all ;-)
*/
function cache_invalidate($account_id)
{
//echo "<p>accounts::cache_invalidate($account_id)</p>\n";
$GLOBALS['phpgw_info']['accounts']['cache'] = array();
}
function save_repository()
{
$this->cache_invalidate($this->account_id);
accounts_::save_repository();
}
function delete($accountid)
{
$this->cache_invalidate($accountid);
accounts_::delete($accountid);
// delete all acl_entries belonging to that user or group
$GLOBALS['phpgw']->acl->delete($accountid);
}
function create($account_info,$default_prefs=True)
{
$account_id = accounts_::create($account_info,$default_prefs);
$this->cache_invalidate($account_id);
return $account_id;
}
function read_repository()
{
$this->setup_cache();
$account_data = &$this->cache['account_data'];
if (isset($account_data[$this->account_id]))
{
return $this->data = $account_data[$this->account_id];
}
return $account_data[$this->account_id] = accounts_::read_repository();
}
function read()
{
if (count($this->data) == 0)
{
$this->read_repository();
}
reset($this->data);
return $this->data;
}
function update_data($data)
{
reset($data);
$this->data = Array();
$this->data = $data;
reset($this->data);
return $this->data;
}
function membership($accountid = '')
{
$this->setup_cache();
$membership_list = &$this->cache['membership_list'];
$account_id = get_account_id($accountid);
if (isset($membership_list[$account_id]))
{
return $membership_list[$account_id];
}
$security_equals = Array();
$security_equals = $GLOBALS['phpgw']->acl->get_location_list_for_id('phpgw_group', 1, $account_id);
if ($security_equals == False)
{
return $membership_list[$account_id] = False;
}
$this->memberships = Array();
for ($idx=0; $idx<count($security_equals); $idx++)
{
$groups = (int)$security_equals[$idx];
$this->memberships[] = Array('account_id' => $groups, 'account_name' => $this->id2name($groups));
}
return $membership_list[$account_id] = $this->memberships;
}
function member($accountid = '')
{
$account_id = get_account_id($accountid);
$security_equals = Array();
$acl = CreateObject('phpgwapi.acl');
$security_equals = $acl->get_ids_for_location($account_id, 1, 'phpgw_group');
unset($acl);
if ($security_equals == False)
{
return False;
}
for ($idx=0; $idx<count($security_equals); $idx++)
{
$name = $this->id2name((int)$security_equals[$idx]);
$this->members[] = Array('account_id' => (int)$security_equals[$idx], 'account_name' => $name);
}
return $this->members;
}
/*!
@function get_nextid
@abstract Using the common functions next_id and last_id, find the next available account_id
@param $account_type (optional, default to 'u')
*/
// NOTE: to my knowledge this is not used any more RalfBecker 2004/06/15
function get_nextid($account_type='u')
{
$min = $GLOBALS['phpgw_info']['server']['account_min_id'] ? $GLOBALS['phpgw_info']['server']['account_min_id'] : 0;
$max = $GLOBALS['phpgw_info']['server']['account_max_id'] ? $GLOBALS['phpgw_info']['server']['account_max_id'] : 0;
if ($account_type == 'g')
{
$type = 'groups';
}
else
{
$type = 'accounts';
}
$nextid = (int)$GLOBALS['phpgw']->common->last_id($type,$min,$max);
/* Loop until we find a free id */
$free = 0;
while (!$free)
{
$account_lid = '';
//echo '<br>calling search for id: '.$nextid;
if ($this->exists($nextid))
{
$nextid = (int)$GLOBALS['phpgw']->common->next_id($type,$min,$max);
}
else
{
$account_lid = $this->id2name($nextid);
/* echo '<br>calling search for lid: '.$account_lid . '(from account_id=' . $nextid . ')'; */
if ($this->exists($account_lid))
{
$nextid = (int)$GLOBALS['phpgw']->common->next_id($type,$min,$max);
}
else
{
$free = True;
}
}
}
if ($GLOBALS['phpgw_info']['server']['account_max_id'] &&
($nextid > $GLOBALS['phpgw_info']['server']['account_max_id']))
{
return False;
}
/* echo '<br>using'.$nextid;exit; */
return $nextid;
}
/**
* splits users and groups from a array of id's or the accounts with run-rights for a given app-name
*
* @param $app_users array of user-id's or app-name (if you use app-name the result gets cached!)
* @param $use string what should be returned only an array with id's of either 'accounts' or 'groups'.
* Or an array with arrays for 'both' under the keys 'groups' and 'accounts' or 'merge' for accounts
* and groups merged into one array
* @return see $use
*/
function split_accounts($app_users,$use='both')
{
if (!is_array($app_users))
{
$this->setup_cache();
$cache = &$this->cache['account_split'][$app_user];
if (is_array($cache))
{
return $cache;
}
$app_users = $GLOBALS['phpgw']->acl->get_ids_for_location('run',1,$app_users);
}
$accounts = array(
'accounts' => array(),
'groups' => array(),
);
foreach($app_users as $id)
{
$type = $GLOBALS['phpgw']->accounts->get_type($id);
if($type == 'g')
{
$accounts['groups'][$id] = $id;
foreach($GLOBALS['phpgw']->acl->get_ids_for_location($id,1,'phpgw_group') as $id)
{
$accounts['accounts'][$id] = $id;
}
}
else
{
$accounts['accounts'][$id] = $id;
}
}
// not sure why they need to be sorted, but we need to remove the keys anyway
sort($accounts['groups']);
sort($accounts['accounts']);
if (isset($cache))
{
$cache = $accounts;
}
//echo "<p>accounts::split_accounts(".print_r($app_users,True).",'$use') = <pre>".print_r($accounts,True)."</pre>\n";
switch($use)
{
case 'both':
return $accounts;
case 'groups':
return $accounts['groups'];
case 'accounts':
return $accounts['accounts'];
case 'merge':
return array_merge($accounts['accounts'],$accounts['groups']);
}
return False;
}
/**
* phpgw compatibility function, better use split_accounts
*/
function return_members($accounts)
{
$arr = $this->split_accounts($accounts);
return array(
'users' => $arr['accounts'],
'groups' => $arr['groups'],
);
}
function name2id($name,$which='account_lid')
{
$this->setup_cache();
$name_list = &$this->cache['name_list'];
if(@isset($name_list[$which][$name]) && $name_list[$which][$name])
{
return $name_list[$which][$name];
}
/* Don't bother searching for empty account_lid */
if(empty($name))
{
return False;
}
return $name_list[$which][$name] = accounts_::name2id($name,$which);
}
function id2name($account_id,$which='account_lid')
{
$this->setup_cache();
$id_list = &$this->cache['id_list'];
if (! $account_id)
{
return False;
}
if($id_list[$account_id][$which])
{
return $id_list[$account_id][$which];
}
return $id_list[$account_id][$which] = accounts_::id2name($account_id,$which);
}
function get_type($accountid)
{
$this->setup_cache();
$account_type = &$this->cache['account_type'];
$account_id = get_account_id($accountid);
if (isset($this->account_type) && $account_id == $this->account_id)
{
return $this->account_type;
}
if(@isset($account_type[$account_id]) && @$account_type[$account_id])
{
return $account_type[$account_id];
}
elseif($account_id == '')
{
return False;
}
return $account_type[$account_id] = accounts_::get_type($account_id);
}
function get_account_name($accountid,&$lid,&$fname,&$lname)
{
$this->setup_cache();
$account_name = &$this->cache['account_name'];
$account_id = get_account_id($accountid);
if(isset($account_name[$account_id]))
{
$lid = $account_name[$account_id]['lid'];
$fname = $account_name[$account_id]['fname'];
$lname = $account_name[$account_id]['lname'];
return $account_name[$account_id] !== False;
}
$Ok = accounts_::get_account_name($accountid,$lid,$fname,$lname);
$account_name[$account_id] = array(
'lid' => $lid,
'fname' => $fname,
'lname' => $lname,
);
return $Ok;
}
function get_account_data($account_id)
{
$this->account_id = $account_id;
$this->read_repository();
$data[$this->data['account_id']]['lid'] = $this->data['account_lid'];
$data[$this->data['account_id']]['firstname'] = $this->data['firstname'];
$data[$this->data['account_id']]['lastname'] = $this->data['lastname'];
$data[$this->data['account_id']]['fullname'] = $this->data['fullname'];
$data[$this->data['account_id']]['type'] = $this->data['account_type'];
return $data;
}
}

View File

@ -0,0 +1,786 @@
<?php
/**************************************************************************\
* eGroupWare API - Access Control List *
* This file written by Dan Kuykendall <seek3r@phpgroupware.org> *
* Security scheme based on ACL design *
* Copyright (C) 2000, 2001 Dan Kuykendall *
* -------------------------------------------------------------------------*
* This library is part of the eGroupWare API *
* http://www.egroupware.org/api *
* ------------------------------------------------------------------------ *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 2.1 of the License, *
* or any later version. *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* You should have received a copy of the GNU Lesser General Public License *
* along with this library; if not, write to the Free Software Foundation, *
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
\**************************************************************************/
/* $Id$ */
/*!
@class acl
@abstract Access Control List Security System
@discussion This class provides an ACL security scheme.
This can manage rights to 'run' applications, and limit certain features within an application.
It is also used for granting a user "membership" to a group, or making a user have the security equivilance of another user.
It is also used for granting a user or group rights to various records, such as todo or calendar items of another user.
@syntax CreateObject('phpgwapi.acl',int account_id);
@example $acl = CreateObject('phpgwapi.acl',5); // 5 is the user id
@example $acl = CreateObject('phpgwapi.acl',10); // 10 is the user id
@author Seek3r
@copyright LGPL
@package phpgwapi
@access public
*/
class acl
{
/*! @var $account_id */
var $account_id;
/*! @var $account_type */
var $account_type;
/*! @var $data */
var $data = Array();
/*! @var $db */
var $db;
/*!
@function acl
@abstract ACL constructor for setting account id
@discussion Author: Seek3r <br>
Sets the ID for $acl->account_id. Can be used to change a current instances id as well. <br>
Some functions are specific to this account, and others are generic. <br>
@syntax int acl(int account_id) <br>
@example1 acl->acl(5); // 5 is the user id <br>
@param account_id int-the user id
*/
function acl($account_id = '')
{
copyobj($GLOBALS['phpgw']->db,$this->db);
if ((int)$this->account_id != (int)$account_id)
{
$this->account_id = get_account_id((int)$account_id,@$GLOBALS['phpgw_info']['user']['account_id']);
}
}
function DONTlist_methods($_type='xmlrpc')
{
/*
This handles introspection or discovery by the logged in client,
in which case the input might be an array. The server always calls
this function to fill the server dispatch map using a string.
*/
if (is_array($_type))
{
$_type = $_type['type'] ? $_type['type'] : $_type[0];
}
switch($_type)
{
case 'xmlrpc':
$xml_functions = array(
'read_repository' => array(
'function' => 'read_repository',
'signature' => array(array(xmlrpcStruct)),
'docstring' => lang('FIXME!')
),
'get_rights' => array(
'function' => 'get_rights',
'signature' => array(array(xmlrpcStruct,xmlrpcStruct)),
'docstring' => lang('FIXME!')
),
'list_methods' => array(
'function' => 'list_methods',
'signature' => array(array(xmlrpcStruct,xmlrpcString)),
'docstring' => lang('Read this list of methods.')
)
);
return $xml_functions;
break;
case 'soap':
return $this->soap_functions;
break;
default:
return array();
break;
}
}
/**************************************************************************\
* These are the standard $this->account_id specific functions *
\**************************************************************************/
/*!
@function read_repository
@abstract Read acl records from reposity
@discussion Author: Seek3r <br>
Reads ACL records for $acl->account_id and returns array along with storing it in $acl->data. <br>
Syntax: array read_repository() <br>
Example1: acl->read_repository(); <br>
Should only be called within this class
*/
function read_repository()
{
// For some reason, calling this via XML-RPC doesn't call the constructor.
// Here is yet another work around(tm) (jengo)
if (! $this->account_id)
{
$this->acl();
}
$sql = 'select * from phpgw_acl where (acl_account in ('.$this->account_id.', 0';
$groups = $this->get_location_list_for_id('phpgw_group', 1, $this->account_id);
while($groups && list($key,$value) = each($groups))
{
if($value != '')
$sql .= ','.$value;
}
$sql .= '))';
$this->db->query($sql ,__LINE__,__FILE__);
$count = $this->db->num_rows();
$this->data = Array();
for ($idx = 0; $idx < $count; ++$idx)
{
//reset ($this->data);
//while(list($idx,$value) = each($this->data)){
$this->db->next_record();
$this->data[] = array(
'appname' => $this->db->f('acl_appname'),
'location' => $this->db->f('acl_location'),
'account' => $this->db->f('acl_account'),
'rights' => $this->db->f('acl_rights')
);
}
reset ($this->data);
return $this->data;
}
/*!
@function read
@abstract Read acl records from $acl->data
@discussion Author: Seek3r <br>
Returns ACL records from $acl->data. <br>
Syntax: array read() <br>
Example1: acl->read(); <br>
*/
function read()
{
if (count($this->data) == 0)
{
$this->read_repository();
}
reset ($this->data);
return $this->data;
}
/*!
@function add
@abstract Adds ACL record to $acl->data
@discussion Adds ACL record to $acl->data. <br>
Syntax: array add() <br>
Example1: acl->add();
@param $appname default False derives value from $phpgw_info['flags']['currentapp']
@param $location location
@param $rights rights
*/
function add($appname = False, $location, $rights)
{
if ($appname == False)
{
settype($appname,'string');
$appname = $GLOBALS['phpgw_info']['flags']['currentapp'];
}
$this->data[] = array('appname' => $appname, 'location' => $location, 'account' => $this->account_id, 'rights' => $rights);
reset($this->data);
return $this->data;
}
/*!
@function delete
@abstract Delete ACL record
@discussion
Syntax <br>
Example: <br>
@param $appname optional defaults to $phpgw_info['flags']['currentapp']
@param $location app location
*/
function delete($appname = False, $location)
{
if ($appname == False)
{
settype($appname,'string');
$appname = $GLOBALS['phpgw_info']['flags']['currentapp'];
}
$count = count($this->data);
reset ($this->data);
while(list($idx,$value) = each($this->data))
{
if ($this->data[$idx]['appname'] == $appname && $this->data[$idx]['location'] == $location && $this->data[$idx]['account'] == $this->account_id)
{
$this->data[$idx] = Array();
}
}
reset($this->data);
return $this->data;
}
/*!
@function save_repostiory
@abstract save repository
@discussion save the repository <br>
Syntax: save_repository() <br>
example: acl->save_repository()
*/
function save_repository()
{
reset($this->data);
$sql = 'delete from phpgw_acl where acl_account = '. (int)$this->account_id;
$this->db->query($sql ,__LINE__,__FILE__);
$count = count($this->data);
reset ($this->data);
while(list($idx,$value) = each($this->data))
{
if ($this->data[$idx]['account'] == $this->account_id)
{
$sql = 'insert into phpgw_acl (acl_appname, acl_location, acl_account, acl_rights)';
$sql .= " values('".$this->data[$idx]['appname']."', '"
. $this->data[$idx]['location']."', ".$this->account_id.', '.$this->data[$idx]['rights'].')';
$this->db->query($sql ,__LINE__,__FILE__);
}
}
reset($this->data);
return $this->data;
}
/**************************************************************************\
* These are the non-standard $this->account_id specific functions *
\**************************************************************************/
/*!
@function get_rights
@abstract get rights from the repository not specific to this->account_id (?)
@discussion
@param $location app location to get rights from
@param $appname optional defaults to $phpgw_info['flags']['currentapp'];
*/
function get_rights($location,$appname = False)
{
// For XML-RPC, change this once its working correctly for passing parameters (jengo)
if (is_array($location))
{
$a = $location;
$location = $a['location'];
$appname = $a['appname'];
}
if (count($this->data) == 0)
{
$this->read_repository();
}
reset ($this->data);
if ($appname == False)
{
settype($appname,'string');
$appname = $GLOBALS['phpgw_info']['flags']['currentapp'];
}
$count = count($this->data);
if ($count == 0 && $GLOBALS['phpgw_info']['server']['acl_default'] != 'deny')
{
return True;
}
$rights = 0;
//for ($idx = 0; $idx < $count; ++$idx){
reset ($this->data);
while(list($idx,$value) = each($this->data))
{
if ($this->data[$idx]['appname'] == $appname)
{
if ($this->data[$idx]['location'] == $location || $this->data[$idx]['location'] == 'everywhere')
{
if ($this->data[$idx]['rights'] == 0)
{
return False;
}
$rights |= $this->data[$idx]['rights'];
}
}
}
return $rights;
}
/*!
@function check
@abstract check required rights (not specific to this->account_id?)
@param $location app location
@param $required required right to check against
@param $appname optional defaults to currentapp
*/
function check($location, $required, $appname = False)
{
$rights = $this->get_rights($location,$appname);
return !!($rights & $required);
}
/*!
@function get_specific_rights
@abstract get specific rights for this->account_id for an app location
@param $location app location
@param $appname optional defaults to currentapp
@result $rights ?
*/
function get_specific_rights($location, $appname = False)
{
if ($appname == False)
{
settype($appname,'string');
$appname = $GLOBALS['phpgw_info']['flags']['currentapp'];
}
$count = count($this->data);
if ($count == 0 && $GLOBALS['phpgw_info']['server']['acl_default'] != 'deny')
{
return True;
}
$rights = 0;
reset ($this->data);
while(list($idx,$value) = each($this->data))
{
if ($this->data[$idx]['appname'] == $appname &&
($this->data[$idx]['location'] == $location ||
$this->data[$idx]['location'] == 'everywhere') &&
$this->data[$idx]['account'] == $this->account_id)
{
if ($this->data[$idx]['rights'] == 0)
{
return False;
}
$rights |= $this->data[$idx]['rights'];
}
}
return $rights;
}
/*!
@function check_specific
@abstract check specific
@param $location app location
@param $required required rights
@param $appname optional defaults to currentapp
@result boolean
*/
function check_specific($location, $required, $appname = False)
{
$rights = $this->get_specific_rights($location,$appname);
return !!($rights & $required);
}
/*!
@function get_location_list
@abstract ?
@param $app appname
@param $required ?
*/
function get_location_list($app, $required)
{
// User piece
$sql = "select acl_location, acl_rights from phpgw_acl where acl_appname = '$app' ";
$sql .= " and (acl_account in ('".$this->account_id."', 0"; // group 0 covers all users
$equalto = $GLOBALS['phpgw']->accounts->security_equals($this->account_id);
if (is_array($equalto) && count($equalto) > 0)
{
for ($idx = 0; $idx < count($equalto); ++$idx)
{
$sql .= ','.$equalto[$idx][0];
}
}
$sql .= ')))';
$this->db->query($sql ,__LINE__,__FILE__);
$rights = 0;
if ($this->db->num_rows() == 0 )
{
return False;
}
while ($this->db->next_record())
{
if ($this->db->f('acl_rights') == 0)
{
return False;
}
$rights |= $this->db->f('acl_rights');
if (!!($rights & $required) == True)
{
$locations[] = $this->db->f('acl_location');
}
else
{
return False;
}
}
return $locations;
}
/*
This is kinda how the function SHOULD work, so that it doesnt need to do its own sql query.
It should use the values in the $this->data
function get_location_list($app, $required)
{
if ($appname == False)
{
$appname = $GLOBALS['phpgw_info']['flags']['currentapp'];
}
$count = count($this->data);
if ($count == 0 && $GLOBALS['phpgw_info']['server']['acl_default'] != 'deny'){ return True; }
$rights = 0;
reset ($this->data);
while(list($idx,$value) = each($this->data))
{
if ($this->data[$idx]['appname'] == $appname && $this->data[$idx]['rights'] != 0)
{
$location_rights[$this->data[$idx]['location']] |= $this->data[$idx]['rights'];
}
}
reset($location_rights);
for ($idx = 0; $idx < count($location_rights); ++$idx)
{
if (!!($location_rights[$idx] & $required) == True)
{
$location_rights[] = $this->data[$idx]['location'];
}
}
return $locations;
}
*/
/**************************************************************************\
* These are the generic functions. Not specific to $this->account_id *
\**************************************************************************/
/*!
@function add_repository
@abstract add repository information for an app
@param $app appname
@param $location location
@param $account_id account id
@param $rights rights
*/
function add_repository($app, $location, $account_id, $rights)
{
$this->delete_repository($app, $location, $account_id);
$sql = 'insert into phpgw_acl (acl_appname, acl_location, acl_account, acl_rights)';
$sql .= " values ('" . $app . "','" . $location . "','" . $account_id . "','" . $rights . "')";
$this->db->query($sql ,__LINE__,__FILE__);
return True;
}
/*!
@function delete_repository
@abstract delete repository information for an app
@param $app appname
@param $location location
@param $account_id account id
*/
function delete_repository($app, $location, $accountid = '')
{
static $cache_accountid;
if(isset($cache_accountid[$accountid]) && $cache_accountid[$accountid])
{
$account_id = $cache_accountid[$accountid];
}
else
{
$account_id = get_account_id($accountid,$this->account_id);
$cache_accountid[$accountid] = $account_id;
}
$sql = "delete from phpgw_acl where acl_appname like '".$app."'"
. " and acl_location like '".$location."' and "
. " acl_account = ".$account_id;
$this->db->query($sql ,__LINE__,__FILE__);
return $this->db->num_rows();
}
/*!
@function get_app_list_for_id
@abstract get application list for an account id
@param $location location
@param $required ?
@param $account_id account id defaults to $phpgw_info['user']['account_id'];
*/
function get_app_list_for_id($location, $required, $accountid = '')
{
static $cache_accountid;
if($cache_accountid[$accountid])
{
$account_id = $cache_accountid[$accountid];
}
else
{
$account_id = get_account_id($accountid,$this->account_id);
$cache_accountid[$accountid] = $account_id;
}
$sql = 'SELECT acl_appname, acl_rights from phpgw_acl ';
$sql .= "where acl_location = '" . $this->db->db_addslashes($location) . "' ";
$sql .= 'AND acl_account = ' . (int)$account_id;
$this->db->query($sql ,__LINE__,__FILE__);
$rights = 0;
if ($this->db->num_rows() == 0 )
{
return False;
}
while ($this->db->next_record())
{
if ($this->db->f('acl_rights') == 0)
{
return False;
}
$rights |= $this->db->f('acl_rights');
if (!!($rights & $required) == True)
{
$apps[] = $this->db->f('acl_appname');
}
}
return $apps;
}
/*!
@function get_location_list_for_id
@abstract get location list for id
@discussion ?
@param $app app
@param $required required
@param $account_id optional defaults to $phpgw_info['user']['account_id'];
*/
function get_location_list_for_id($app, $required, $accountid = '')
{
static $cache_accountid;
if($cache_accountid[$accountid])
{
$account_id = $cache_accountid[$accountid];
}
else
{
$account_id = get_account_id($accountid,$this->account_id);
$cache_accountid[$accountid] = $account_id;
}
$sql = 'SELECT acl_location, acl_rights ';
$sql .= "FROM phpgw_acl where acl_appname = '" . $this->db->db_addslashes($app) . "' ";
$sql .= 'AND acl_account =' . (int)$account_id;
$this->db->query($sql ,__LINE__,__FILE__);
$rights = 0;
if ($this->db->num_rows() == 0 )
{
return False;
}
while ($this->db->next_record())
{
if ($this->db->f('acl_rights'))
{
$rights |= $this->db->f('acl_rights');
if (!!($rights & $required) == True)
{
$locations[] = $this->db->f('acl_location');
}
}
}
return $locations;
}
/*!
@function get_ids_for_location
@abstract get ids for location
@param $location location
@param $required required
@param $app app optional defaults to $phpgw_info['flags']['currentapp'];
*/
function get_ids_for_location($location, $required, $app = False)
{
if ($app == False)
{
$app = $GLOBALS['phpgw_info']['flags']['currentapp'];
}
$sql = "select acl_account, acl_rights from phpgw_acl where acl_appname = '$app' and ";
$sql .= "acl_location = '".$location."'";
$this->db->query($sql ,__LINE__,__FILE__);
$rights = 0;
if ($this->db->num_rows() == 0 )
{
return False;
}
while ($this->db->next_record())
{
$rights = 0;
$rights |= $this->db->f('acl_rights');
if (!!($rights & $required) == True)
{
$accounts[] = (int)$this->db->f('acl_account');
}
}
@reset($accounts);
return $accounts;
}
/*!
@function get_user_applications
@abstract get a list of applications a user has rights to
@param $account_id optional defaults to $phpgw_info['user']['account_id'];
@result $apps array containing list of apps
*/
function get_user_applications($accountid = '')
{
static $cache_accountid;
if($cache_accountid[$accountid])
{
$account_id = $cache_accountid[$accountid];
}
else
{
$account_id = get_account_id($accountid,$this->account_id);
$cache_accountid[$accountid] = $account_id;
}
$db2 = $this->db;
$memberships = $GLOBALS['phpgw']->accounts->membership($account_id);
$sql = "select acl_appname, acl_rights from phpgw_acl where acl_location = 'run' and "
. 'acl_account in ';
$security = '('.$account_id;
while($groups = @each($memberships))
{
$group = each($groups);
$security .= ','.$group[1]['account_id'];
}
$security .= ')';
$db2->query($sql . $security ,__LINE__,__FILE__);
if ($db2->num_rows() == 0)
{
return False;
}
while ($db2->next_record())
{
if(isset($apps[$db2->f('acl_appname')]))
{
$rights = $apps[$db2->f('acl_appname')];
}
else
{
$rights = 0;
$apps[$db2->f('acl_appname')] = 0;
}
$rights |= $db2->f('acl_rights');
$apps[$db2->f('acl_appname')] |= $rights;
}
return $apps;
}
/*!
@function get_grants
@abstract ?
@param $app optional defaults to $phpgw_info['flags']['currentapp'];
*/
function get_grants($app='')
{
$db2 = $this->db;
if ($app=='')
{
$app = $GLOBALS['phpgw_info']['flags']['currentapp'];
}
$sql = "select acl_account, acl_rights from phpgw_acl where acl_appname = '$app' and "
. "acl_location in ";
$security = "('". $this->account_id ."'";
$myaccounts = CreateObject('phpgwapi.accounts');
$my_memberships = $myaccounts->membership($this->account_id);
unset($myaccounts);
@reset($my_memberships);
while($my_memberships && list($key,$group) = each($my_memberships))
{
$security .= ",'" . $group['account_id'] . "'";
}
$security .= ')';
$db2->query($sql . $security ,__LINE__,__FILE__);
$rights = 0;
$accounts = Array();
if ($db2->num_rows() == 0)
{
$grants[$GLOBALS['phpgw_info']['user']['account_id']] = ~0;
return $grants;
}
while ($db2->next_record())
{
$grantor = $db2->f('acl_account');
$rights = $db2->f('acl_rights');
if(!isset($accounts[$grantor]))
// cache the group-members for performance
{
// if $grantor is a group, get its members
$members = $this->get_ids_for_location($grantor,1,'phpgw_group');
if(!$members)
{
$accounts[$grantor] = Array($grantor);
$is_group[$grantor] = False;
}
else
{
$accounts[$grantor] = $members;
$is_group[$grantor] = True;
}
}
if(@$is_group[$grantor])
{
// Don't allow to override private!
$rights &= (~ PHPGW_ACL_PRIVATE);
if(!isset($grants[$grantor]))
{
$grants[$grantor] = 0;
}
$grants[$grantor] |= $rights;
if(!!($rights & PHPGW_ACL_READ))
{
$grants[$grantor] |= PHPGW_ACL_READ;
}
}
while(list($nul,$grantors) = each($accounts[$grantor]))
{
if(!isset($grants[$grantors]))
{
$grants[$grantors] = 0;
}
$grants[$grantors] |= $rights;
}
reset($accounts[$grantor]);
}
$grants[$GLOBALS['phpgw_info']['user']['account_id']] = ~0;
return $grants;
}
/**
* Deletes all ACL entries for an account (user or group)
*
* @param int $account_id acount-id
*/
function delete_account($account_id)
{
if ((int) $account_id)
{
$this->db->query('DELETE FROM phpgw_acl WHERE acl_account='.(int)$account_id,__LINE__,__FILE__);
}
}
} //end of acl class
?>