* all apps: exclude expired or deactivated accounts from all lists and selections (beside admin app to be able to activate them again)

This commit is contained in:
Ralf Becker 2013-01-25 13:21:31 +00:00
parent 8a3f81c77c
commit 2841317b08
7 changed files with 78 additions and 19 deletions

View File

@ -669,6 +669,10 @@ class addressbook_ldap
$objectFilter = '(objectclass=inetorgperson)';
break;
}
// exclude expired accounts
//$shadowExpireNow = floor((time()+date('Z'))/86400);
//$objectFilter .= "(|(!(shadowExpire=*))(shadowExpire>=$shadowExpireNow))";
// shadowExpire>= does NOT work, as shadow schema only specifies intergerMatch and not integerOrderingMatch :-(
$searchFilter = '';
if(is_array($criteria) && count($criteria) > 0)
@ -870,6 +874,7 @@ class addressbook_ldap
$_attributes[] = 'modifyTimestamp';
$_attributes[] = 'creatorsName';
$_attributes[] = 'modifiersName';
$_attributes[] = 'shadowExpire';
//echo "<p>ldap_search($this->ds, $_ldapContext, $_filter, $_attributes, 0, $this->ldapLimit)</p>\n";
if($_addressbooktype == ADDRESSBOOK_ALL)
@ -883,11 +888,19 @@ class addressbook_ldap
if(!$result) return array();
$entries = ldap_get_entries($this->ds, $result);
$this->total = $entries['count'];
$shadowExpireNow = floor((time()-date('Z'))/86400);
foreach((array)$entries as $i => $entry)
{
if (!is_int($i)) continue; // eg. count
// exclude expired or deactivated accounts
if (isset($entry['shadowexpire']) && $entry['shadowexpire'][0] <= $shadowExpireNow)
{
--$this->total;
continue;
}
$contact = array(
'id' => $entry['uid'][0] ? $entry['uid'][0] : $entry['entryuuid'][0],
'tid' => 'n', // the type id for the addressbook

View File

@ -29,10 +29,10 @@ class addressbook_sql extends so_sql_cf
*/
const ACCOUNT_ACTIVE_JOIN = ' LEFT JOIN egw_accounts ON egw_addressbook.account_id=egw_accounts.account_id';
/**
* filter to show only active account (and not already expired ones)
* filter to show only active account (and not already expired or deactived ones)
* UNIX_TIMESTAMP(NOW()) gets replaced with value of time() in the code!
*/
const ACOUNT_ACTIVE_FILTER = '(account_expires IS NULL OR account_expires = -1 OR account_expires > UNIX_TIMESTAMP(NOW()))';
const ACOUNT_ACTIVE_FILTER = "(account_expires IS NULL OR account_expires = -1 OR account_expires > UNIX_TIMESTAMP(NOW())) AND account_status='A'";
/**
* internal name of the id, gets mapped to uid

View File

@ -352,6 +352,7 @@
'sort' => $sort,
'order' => $order,
'query_type' => $_REQUEST['query_type'],
'active' => false, // false = return inactive and expired accounts too
);
if (!$GLOBALS['egw']->acl->check('account_access',2,'admin'))
{
@ -791,7 +792,7 @@
$group_info = Array(
'account_id' => (int)$_GET['account_id'],
'account_name' => $GLOBALS['egw']->accounts->id2name($_GET['account_id']),
'account_user' => $GLOBALS['egw']->accounts->members($_GET['account_id']),
'account_user' => $GLOBALS['egw']->accounts->members($_GET['account_id'], false, false),
'account_apps' => $this->bo->load_group_apps($_GET['account_id'])
);

View File

@ -234,12 +234,15 @@ class accounts
* '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
* @param $param['active']=true boolean - true: return only acctive accounts, false: return expired or deactivated too
* @return array with account_id => 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)
{
//error_log(__METHOD__.'('.array2string($param).')');
//error_log(__METHOD__.'('.array2string($param).') '.function_backtrace());
if (!isset($param['active'])) $param['active'] = true; // default is true = only return active accounts
self::setup_cache();
$account_search = &self::$cache['account_search'];
$serial = serialize($param);
@ -326,7 +329,7 @@ class accounts
else
{
$account_search[$serial]['data'] = array();
$accounts = $this->backend->get_list($param['type'],$param['start'],$param['sort'],$param['order'],$param['query'],$param['offset'],$param['query_type']);
$accounts = $this->backend->get_list($param['type'],$param['start'],$param['sort'],$param['order'],$param['query'],$param['offset'],$param['query_type'],$param['active']);
if (!$accounts) $accounts = array();
foreach($accounts as $data)
{
@ -523,7 +526,7 @@ class accounts
}
else
{
$invalidate = $this->members($id, true);
$invalidate = $this->members($id, true, false);
}
$invalidate[] = $id;
@ -555,6 +558,19 @@ class accounts
return $expires != -1 && $expires < time();
}
/**
* Test if an account is active - NOT deactivated or expired
*
* @param int|array $data account_id or array with account-data
* @return boolean false if account does not exist, is expired or decativated, true otherwise
*/
function is_active($data)
{
if (!is_array($data)) $data = $this->read($data);
return $data && !($this->is_expired($data) || $data['account_status'] != 'A');
}
/**
* convert an alphanumeric account-value (account_lid, account_email) to the account_id
*
@ -727,17 +743,20 @@ class accounts
* @param int/string $accountid='' numeric account-id or alphanum. account-lid,
* default account of the user of this session
* @param boolean $just_id=false return just an array of id's and not id => lid pairs, default false
* @param boolean $active=false true: return only active (not expired or deactived) members, false: return all accounts
* @return array with account_id ($just_id) or account_id => account_lid pairs (!$just_id)
*/
function members($account_id,$just_id=false)
function members($account_id, $just_id=false, $active=true)
{
if (!is_int($account_id) && !is_numeric($account_id))
{
$account_id = $this->name2id($account_id);
}
if ($account_id && ($data = self::cache_read($account_id)))
if ($account_id && ($data = self::cache_read($account_id, $active)))
{
return $just_id && $data['members'] ? array_keys($data['members']) : $data['members'];
$members = $active ? $data['members-active'] : $data['members'];
return $just_id && $members ? array_keys($members) : $members;
}
return null;
}
@ -751,7 +770,7 @@ class accounts
function set_members($members,$gid)
{
//echo "<p>accounts::set_members(".print_r($members,true).",$gid)</p>\n";
if (($old_members = $this->members($gid, true)) != $members)
if (($old_members = $this->members($gid, true, false)) != $members)
{
$this->backend->set_members($members, $gid);
@ -797,7 +816,7 @@ class accounts
$accounts['groups'][$id] = $id;
if ($use != 'groups')
{
foreach((array)$this->members($id,true) as $id)
foreach((array)$this->members($id, true) as $id)
{
$accounts['accounts'][$id] = $id;
}
@ -1007,10 +1026,11 @@ class accounts
* Read account incl. members/memberships from cache (or backend and cache it)
*
* @param int $account_id
* @param boolean $need_active=false true = 'members-active' required
* @return array
* @throws egw_exception_wrong_parameter if no integer was passed as $account_id
*/
static function cache_read($account_id)
static function cache_read($account_id, $need_active=false)
{
if (!is_numeric($account_id)) throw new egw_exception_wrong_parameter('Not an integer!');
@ -1040,6 +1060,18 @@ class accounts
}
//else error_log(__METHOD__."($account_id) read from instance cache ".array2string($account));
}
// if required and not already set, query active members AND cache them too
if ($need_active && $account_id < 0 && !isset($account['members-active']))
{
$instance = self::getInstance();
$account['members-active'] = array();
foreach($account['members'] as $id => $lid)
{
if ($instance->is_active($id)) $account['members-active'][$id] = $lid;
}
egw_cache::setInstance(__CLASS__, 'account-'.$account_id, $account, self::READ_CACHE_TIMEOUT);
}
//error_log(__METHOD__."($account_id, $need_active) returning ".array2string($account));
return $account;
}

View File

@ -760,11 +760,17 @@ class accounts_ldap
'account_firstname' => translation::convert($allVals['givenname'][0],'utf-8'),
'account_lastname' => translation::convert($allVals['sn'][0],'utf-8'),
'account_status' => isset($allVals['shadowexpire'][0]) && $allVals['shadowexpire'][0]*24*3600-$utc_diff < time() ? false : 'A',
'account_expires' => isset($data['shadowexpire']) && $data['shadowexpire'][0] ? $data['shadowexpire'][0]*24*3600+$utc_diff : -1, // LDAP date is in UTC
'account_email' => $allVals['mail'][0],
'account_created' => isset($allVals['createtimestamp'][0]) ? self::accounts_ldap2ts($allVals['createtimestamp'][0]) : null,
'account_modified' => isset($allVals['modifytimestamp'][0]) ? self::accounts_ldap2ts($allVals['modifytimestamp'][0]) : null,
);
$account['account_fullname'] = common::display_fullname($account['account_lid'],$account['account_firstname'],$account['account_lastname']);
if ($param['active'] && !$this->frontend->is_active($account))
{
--$totalcount;
continue;
}
$account['account_fullname'] = common::display_fullname($account['account_lid'],$account['account_firstname'],$account['account_lastname'],$allVals['uidnumber'][0]);
// return objectclass(es)
if ($param['objectclass'])
{

View File

@ -45,7 +45,8 @@ class accounts_sql
*
* @var string
*/
var $table = 'egw_accounts';
const TABLE = 'egw_accounts';
var $table = self::TABLE;
/**
* table name for the contacts
*
@ -363,9 +364,10 @@ class accounts_sql
* @param string $query=''
* @param int $offset=null
* @param string $query_type='all' 'start', 'all' (default), 'exact'
* @param boolean $active=false true: return only active accounts
* @return array
*/
function get_list($_type='both', $start = null,$sort = '', $order = '', $query = '', $offset = null, $query_type='')
function get_list($_type='both', $start = null,$sort = '', $order = '', $query = '', $offset = null, $query_type='', $active=false)
{
//echo "<p>accounts_sql($_type,$start,$sort,$order,$query,$offset,$query_type)</p>\n";
static $order2contact = array(
@ -389,13 +391,17 @@ class accounts_sql
$filter = array('owner' => 0);
break;
case 'groups':
$filter = "account_type = 'g'";
$filter = array("account_type = 'g'");
break;
default:
case 'both':
$filter = "(egw_addressbook.contact_owner=0 OR egw_addressbook.contact_owner IS NULL)";
$filter = array("(egw_addressbook.contact_owner=0 OR egw_addressbook.contact_owner IS NULL)");
break;
}
if ($active)
{
$filter[] = str_replace('UNIX_TIMESTAMP(NOW())',time(),addressbook_sql::ACOUNT_ACTIVE_FILTER);
}
$criteria = array();
$wildcard = $query_type == 'start' || $query_type == 'exact' ? '' : '%';
if ($query)

View File

@ -161,7 +161,7 @@ class uiaccountsel
{
foreach((array)$this->accounts->members($gid,true) as $member)
{
if (!in_array($member,$select)) $select[] = $member;
if (!in_array($member,$select) && $this->accounts->is_active($member)) $select[] = $member;
}
}
if ($use == 'both') // show all memberships
@ -181,6 +181,7 @@ class uiaccountsel
$select = $GLOBALS['egw']->accounts->search(array(
'type' => $use,
'app' => $app,
'active' => true, // return only active accounts
));
//error_log(__METHOD__."() account_selection='$this->account_selection', accounts->search(array('type'=>'$use', 'app' => '$app')) returns ".array2string($select));
}
@ -217,7 +218,7 @@ class uiaccountsel
{
$users[$id] = !is_array($val) ? $label :
common::display_fullname(
$val['account_lid'],$val['account_firstname'],$val['account_lastname']);
$val['account_lid'],$val['account_firstname'],$val['account_lastname'],$id);
}
else
{