mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-21 23:43:17 +01:00
* Admin: allow to mark users as hidden, to show them only to admins e.g. to hide functional users from regular users
This commit is contained in:
parent
d31915df05
commit
e72c2e492a
@ -69,6 +69,7 @@ class admin_account
|
||||
$acl = new Acl($content['account_id']);
|
||||
$acl->read_repository();
|
||||
$account['anonymous'] = $acl->check('anonymous', 1, 'phpgwapi');
|
||||
$account['hidden'] = $acl->check('hidden', 1, 'phpgwapi');
|
||||
$account['changepassword'] = !$acl->check('nopasswordchange', 1, 'preferences');
|
||||
$auth = new Api\Auth();
|
||||
if (($account['account_lastpwd_change'] = $auth->getLastPwdChange($account['account_lid'])) === false)
|
||||
@ -116,7 +117,7 @@ class admin_account
|
||||
// save old values to only trigger save, if one of the following values change (contact data get saved anyway)
|
||||
$preserve = empty($content['id']) ? array() :
|
||||
array('old_account' => array_intersect_key($account, array_flip(array(
|
||||
'account_lid', 'account_status', 'account_groups', 'anonymous', 'changepassword',
|
||||
'account_lid', 'account_status', 'account_groups', 'anonymous', 'hidden', 'changepassword',
|
||||
'mustchangepassword', 'account_primary_group', 'homedirectory', 'loginshell',
|
||||
'account_expires', 'account_firstname', 'account_lastname', 'account_email'))),
|
||||
'deny_edit' => $deny_edit);
|
||||
@ -185,7 +186,7 @@ class admin_account
|
||||
'account_groups',
|
||||
// copy following fields to account
|
||||
'account_lid',
|
||||
'changepassword', 'anonymous', 'mustchangepassword',
|
||||
'changepassword', 'anonymous', 'hidden', 'mustchangepassword',
|
||||
'account_passwd', 'account_passwd_2',
|
||||
'account_primary_group',
|
||||
'account_expires', 'account_status',
|
||||
@ -215,6 +216,7 @@ class admin_account
|
||||
|
||||
case 'changepassword': // boolean values: admin_cmd_edit_user understands '' as NOT set
|
||||
case 'anonymous':
|
||||
case 'hidden':
|
||||
case 'mustchangepassword':
|
||||
$account[$a_name] = (boolean)$content[$c_name];
|
||||
break;
|
||||
|
@ -107,6 +107,7 @@ class admin_cmd_edit_user extends admin_cmd_change_pw
|
||||
// automatic set anonymous flag for username "anonymous", to not allow to create anonymous user without it
|
||||
$data['anonymous'] = ($data['account_lid'] ?: admin_cmd::$accounts->id2name($this->account)) === 'anonymous' ?
|
||||
true : admin_cmd::parse_boolean($data['anonymous'],$this->account ? null : false);
|
||||
$data['hidden'] = admin_cmd::parse_boolean($data['hidden'],null);
|
||||
|
||||
if ($data['mustchangepassword'] && $data['changepassword'])
|
||||
{
|
||||
@ -187,6 +188,18 @@ class admin_cmd_edit_user extends admin_cmd_change_pw
|
||||
admin_cmd::$acl->delete_repository('phpgwapi','anonymous',$data['account_id']);
|
||||
}
|
||||
}
|
||||
if (isset($data['hidden']))
|
||||
{
|
||||
admin_cmd::_instanciate_acl();
|
||||
if ($data['hidden'])
|
||||
{
|
||||
admin_cmd::$acl->add_repository('phpgwapi','hidden',$data['account_id'],1);
|
||||
}
|
||||
else
|
||||
{
|
||||
admin_cmd::$acl->delete_repository('phpgwapi','hidden',$data['account_id']);
|
||||
}
|
||||
}
|
||||
if (!is_null($data['changepassword']))
|
||||
{
|
||||
if (!$data['changepassword'])
|
||||
|
@ -122,6 +122,7 @@ anonymous user admin de Anonymer Benutzer
|
||||
anonymous user (not shown in list sessions) admin de Anonymer Benutzer (wird bei 'Sitzungen anzeigen' nicht angezeigt).
|
||||
anonymous user does not exist! admin de Anonymer Benutzer existiert NICHT!
|
||||
anonymous user has no run-rights for the application! admin de Anonymer Benutzer hat KEINE Ausführungsrechte für die Anwendung!
|
||||
anonymous user. not shown in list sessions. admin de Anonymer Benutzer. Wird nicht in der Liste der Sitzungen angezeigt.
|
||||
any application admin de Jede Anwendung
|
||||
any group admin de Jede Gruppe
|
||||
any user admin de Jeder Benutzer
|
||||
@ -958,6 +959,7 @@ user csv import admin de CSV-Import von Benutzern
|
||||
user data common de Benutzerdaten
|
||||
user for smtp-authentication (leave it empty if no auth required) admin de Benutzer für SMTP-Authentifizierung (leer lassen falls keine Authentifizierung nötig).
|
||||
user groups admin de Benutzergruppen
|
||||
user hidden vom non-admins. admin de Benutzer verborgen von nicht Administratoren.
|
||||
user-agent admin de Browser
|
||||
userdata admin de Benutzerkonto
|
||||
userid@domain eg. u1234@domain admin de UserId@domain z.B. u1234@domain
|
||||
|
@ -122,6 +122,7 @@ anonymous user admin en Anonymous user
|
||||
anonymous user (not shown in list sessions) admin en Anonymous user. Not shown in sessions list.
|
||||
anonymous user does not exist! admin en Anonymous user does NOT exist!
|
||||
anonymous user has no run-rights for the application! admin en Anonymous user has NO run-rights for the application!
|
||||
anonymous user. not shown in list sessions. admin en Anonymous user. Not shown in list sessions.
|
||||
any application admin en Any application
|
||||
any group admin en Any group
|
||||
any user admin en Any user
|
||||
@ -958,6 +959,7 @@ user csv import admin en User CSV import
|
||||
user data common en User data
|
||||
user for smtp-authentication (leave it empty if no auth required) admin en User for SMTP authentication. Leave it empty if no authentication is required.
|
||||
user groups admin en User groups
|
||||
user hidden vom non-admins. admin en User hidden vom non-admins.
|
||||
user-agent admin en User-Agent
|
||||
userdata admin en User data
|
||||
userid@domain eg. u1234@domain admin en UserId@domain eg. u1234@domain
|
||||
|
@ -39,7 +39,10 @@
|
||||
</et2-vbox>
|
||||
<et2-description></et2-description>
|
||||
<et2-description></et2-description>
|
||||
<et2-checkbox id="anonymous" label="Anonymous user. Not shown in list sessions."></et2-checkbox>
|
||||
<et2-vbox>
|
||||
<et2-checkbox id="anonymous" label="Anonymous user. Not shown in list sessions."></et2-checkbox>
|
||||
<et2-checkbox id="hidden" label="User hidden vom non-admins."></et2-checkbox>
|
||||
</et2-vbox>
|
||||
<et2-description></et2-description>
|
||||
</row>
|
||||
<row disabled="!@ldap_extra_attributes">
|
||||
|
@ -199,6 +199,32 @@ class Accounts
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement hidden account-filter via explicit account_id's and "hidden" ACL location
|
||||
*
|
||||
* @param bool|null $hidden false: do NOT return hidden users, true: return only hidden user, null: return all users
|
||||
* @param array|null $account_ids account_id filter, if set
|
||||
* @return array|int[] array of account_id's optionally with extra "!" for $hidden === false
|
||||
*/
|
||||
public static function hidden2account_id(bool $hidden=null, array $account_ids=null)
|
||||
{
|
||||
$hidden_account_ids = array_keys($GLOBALS['egw']->acl->get_all_rights('hidden', 'phpgwapi') ?: []);
|
||||
if (empty($account_ids))
|
||||
{
|
||||
$account_ids = $hidden_account_ids;
|
||||
if ($hidden === false) $account_ids[] = '!';
|
||||
}
|
||||
elseif ($hidden === true)
|
||||
{
|
||||
$account_ids = array_intersect($account_ids, $hidden_account_ids);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new \InvalidArgumentException(__METHOD__."(): Can NOT have hidden=false AND an account_id filter!");
|
||||
}
|
||||
return $account_ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches / lists accounts: users and/or groups
|
||||
*
|
||||
@ -225,6 +251,7 @@ 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['active']=true boolean - true: return only acctive accounts, false: return expired or deactivated too
|
||||
* @param $param['hidden']=false boolean false: do NOT return hidden users, true: return only hidden user, null: return all users
|
||||
* @param $param['account_id'] int[] return only given account_id's
|
||||
* @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
|
||||
@ -234,6 +261,8 @@ class Accounts
|
||||
//error_log(__METHOD__.'('.array2string($param).') '.function_backtrace());
|
||||
if (!isset($param['active'])) $param['active'] = true; // default is true = only return active accounts
|
||||
if (!empty($param['offset']) && !isset($param['start'])) $param['start'] = 0;
|
||||
// show hidden users by default only to admin
|
||||
if (!array_key_exists('hidden', $param)) $param['hidden'] = !empty($GLOBALS['egw_info']['user']['apps']['admin']) ? null : false;
|
||||
|
||||
// Check for lang(Group) in search - if there, we search all groups
|
||||
$group_index = array_search(strtolower(lang('Group')), array_map('strtolower', $query = explode(' ',$param['query'] ?? '')));
|
||||
@ -259,6 +288,13 @@ class Accounts
|
||||
$account_search = &self::$cache['account_search'];
|
||||
$serial = self::cacheKey($param, $serial_unlimited);
|
||||
|
||||
// implement $param['hidden'] via $param['account_id']
|
||||
if (isset($param['hidden']) && !in_array($param['type'],['groups', 'owngroups']))
|
||||
{
|
||||
$param['account_id'] = self::hidden2account_id($param['hidden'], $param['account_id']);
|
||||
}
|
||||
unset($param['hidden']);
|
||||
|
||||
// cache list of all groups on instance level (not session)
|
||||
if ($serial_unlimited === self::cacheKey(['type'=>'groups','active'=>true]))
|
||||
{
|
||||
@ -312,7 +348,7 @@ class Accounts
|
||||
}
|
||||
$param['type'] = $param['type'] == 'groupmembers+memberships' ? 'both' : 'accounts';
|
||||
}
|
||||
// call ourself recursive to get (evtl. cached) full search
|
||||
// call ourselves recursive to get (evtl. cached) full search
|
||||
$full_search = $this->search($param);
|
||||
|
||||
// filter search now on accounts with run-rights for app or a group
|
||||
|
@ -1062,7 +1062,15 @@ class Ads
|
||||
}
|
||||
if (!empty($param['account_id']))
|
||||
{
|
||||
if (($not_account_ids = array_search('!', $param['account_id'])) !== false)
|
||||
{
|
||||
unset($param['account_id'][$not_account_ids]);
|
||||
}
|
||||
$account_ids_filter = '(|(objectsid='.implode(')(objectsid=', array_map([$this, 'get_sid'], (array)$param['account_id'])).'))';
|
||||
if ($not_account_ids !== false)
|
||||
{
|
||||
$account_ids_filter = '(!'.$account_ids_filter.')';
|
||||
}
|
||||
$filter = $filter ? "(&$filter$account_ids_filter)" : $account_ids_filter;
|
||||
}
|
||||
if (!empty($param['modified']))
|
||||
|
@ -842,7 +842,17 @@ class Ldap
|
||||
// only return given account_id's
|
||||
if (!empty($param['account_id']))
|
||||
{
|
||||
// do we need a negated account_id filter
|
||||
if (($not_account_ids = array_search('!', $param['account_id'])) !== false)
|
||||
{
|
||||
$filter .= '(!';
|
||||
unset($param['account_id'][$not_account_ids]);
|
||||
}
|
||||
$filter .= '(|(uidNumber=' . implode(')(uidNumber=', (array)$param['account_id']) . '))';
|
||||
if ($not_account_ids !== false)
|
||||
{
|
||||
$filter .= ')';
|
||||
}
|
||||
}
|
||||
if (!empty($param['modified']))
|
||||
{
|
||||
|
@ -510,7 +510,11 @@ class Sql
|
||||
$this->total = 0;
|
||||
return array();
|
||||
}
|
||||
$filter[] = $this->db->expression($this->table, $this->table.'.', array(
|
||||
if (($not_account_id = array_search('!', $filter['account_id'])) !== false)
|
||||
{
|
||||
unset($filter['account_id'][$not_account_id]);
|
||||
}
|
||||
$filter[] = ($not_account_id !== false ? ' NOT ' : '').$this->db->expression($this->table, $this->table.'.', array(
|
||||
'account_id' => $filter['account_id'],
|
||||
));
|
||||
unset($filter['account_id']);
|
||||
|
@ -185,7 +185,7 @@ class Ads extends Ldap
|
||||
/**
|
||||
* Return LDAP filter for (multiple) account ids
|
||||
*
|
||||
* @param int|int[]|null $ids
|
||||
* @param int|int[]|null $ids use "!" to negate the whole filter
|
||||
* @return string
|
||||
*/
|
||||
protected function account_ids_filter($ids)
|
||||
@ -197,12 +197,20 @@ class Ads extends Ldap
|
||||
}
|
||||
elseif ($ids)
|
||||
{
|
||||
if (($not_account_ids = array_search('!', $ids)) !== false)
|
||||
{
|
||||
unset($ids[$not_account_ids]);
|
||||
}
|
||||
if (is_array($ids)) $filter = '(|';
|
||||
foreach((array)$ids as $account_id)
|
||||
{
|
||||
$filter .= '(objectsid='.$this->accounts_ads->get_sid($account_id).')';
|
||||
}
|
||||
if (is_array($ids)) $filter .= ')';
|
||||
if ($not_account_ids !== false)
|
||||
{
|
||||
$filter = '(!'.$filter.')';
|
||||
}
|
||||
}
|
||||
return $filter;
|
||||
}
|
||||
|
@ -470,10 +470,11 @@ class Ldap
|
||||
* Return LDAP filter for (multiple) contact ids
|
||||
*
|
||||
* @param array|string $ids
|
||||
* @param bool $not=false true: negate the filter
|
||||
* @throws Api\Exception\AssertionFailed if $contact_id is no valid GUID (for ADS!)
|
||||
* @return string
|
||||
*/
|
||||
protected function ids_filter($ids)
|
||||
protected function ids_filter($ids, bool $not=false)
|
||||
{
|
||||
if (!is_array($ids) || count($ids) == 1)
|
||||
{
|
||||
@ -484,13 +485,13 @@ class Ldap
|
||||
{
|
||||
$filter[] = $this->id_filter($id);
|
||||
}
|
||||
return '(|'.implode('', $filter).')';
|
||||
return ($not ? '(!' : '').'(|'.implode('', $filter).')'.($not ? ')' : '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return LDAP filter for (multiple) account ids
|
||||
*
|
||||
* @param int|int[]|null $ids
|
||||
* @param int|int[]|null $ids use "!" to negate the whole filter
|
||||
* @return string
|
||||
*/
|
||||
protected function account_ids_filter($ids)
|
||||
@ -502,10 +503,14 @@ class Ldap
|
||||
}
|
||||
elseif ($ids)
|
||||
{
|
||||
if (($not_account_ids = array_search('!', $ids)) !== false)
|
||||
{
|
||||
unset($ids[$not_account_ids]);
|
||||
}
|
||||
$filter = $this->ids_filter(array_map(static function($account_id)
|
||||
{
|
||||
return $GLOBALS['egw']->accounts->id2name($account_id, 'person_id');
|
||||
}, (array)$ids));
|
||||
}, (array)$ids), $not_account_ids !== false);
|
||||
}
|
||||
return $filter;
|
||||
}
|
||||
|
@ -716,6 +716,13 @@ class Sql extends Api\Storage
|
||||
$this->sanitize_order_by = false;
|
||||
}
|
||||
|
||||
// implement negated account_id filter
|
||||
if (!empty($filter['account_id']) && ($not_account_ids = array_search('!', $filter['account_id'])) !== false)
|
||||
{
|
||||
$filter[] = $this->db->expression($this->table_name, ' NOT ', $this->table_name.'.', ['account_id' => $filter['account_id']]);
|
||||
unset($filter['account_id']);
|
||||
}
|
||||
|
||||
$rows =& parent::search($criteria,$only_keys,$order_by,$extra_cols,$wildcard,$empty,$op,$start,$filter,$join,$need_full_no_count);
|
||||
|
||||
if ($start === false) $this->total = is_array($rows) ? count($rows) : 0; // so_sql sets total only for $start !== false!
|
||||
|
@ -659,6 +659,11 @@ class Storage
|
||||
{
|
||||
//error_log(__METHOD__.'('.array2string($criteria,true).','.array2string($only_keys).",'$order_by','$extra_cols','$wildcard','$empty','$op',".array2string($start).','.array2string($filter,true).",'$join')");
|
||||
|
||||
// add hidden user filter for non-admins
|
||||
if (empty($GLOBALS['egw_info']['user']['apps']['admin']) && empty($filter['owner']))
|
||||
{
|
||||
$filter['account_id'] = Api\Accounts::hidden2account_id(false, $filter['account_id']);
|
||||
}
|
||||
// Handle 'None' country option
|
||||
if(is_array($filter) && isset($filter['adr_one_countrycode']) && $filter['adr_one_countrycode'] === '-custom-')
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user