From 523106c008a50042d5fe08114c538eea5feb0131 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Mon, 23 Jan 2017 11:16:24 +0100 Subject: [PATCH] * Addressbook/Mail: allow to use groups as (readonly) distribution lists --- addressbook/inc/class.addressbook_ui.inc.php | 4 +- api/src/Contacts/Ads.php | 16 ++++++++ api/src/Contacts/Ldap.php | 26 ++++++++++++ api/src/Contacts/Sql.php | 34 +++++++++++++++- api/src/Contacts/Storage.php | 42 +++++++++++++------- 5 files changed, 104 insertions(+), 18 deletions(-) diff --git a/addressbook/inc/class.addressbook_ui.inc.php b/addressbook/inc/class.addressbook_ui.inc.php index edab2bb28e..e25c6537de 100644 --- a/addressbook/inc/class.addressbook_ui.inc.php +++ b/addressbook/inc/class.addressbook_ui.inc.php @@ -1504,8 +1504,8 @@ window.egw_LAB.wait(function() { { $query['col_filter']['account_id'] = null; } - // enable/disable distribution lists depending on backend - $query['no_filter2'] = !$this->lists_available($query['filter']); + // all backends allow now at least to use groups as distribution lists + $query['no_filter2'] = false; if (isset($this->org_views[(string) $query['org_view']]) && !$query['col_filter']['parent_id']) // we have an org view { diff --git a/api/src/Contacts/Ads.php b/api/src/Contacts/Ads.php index 435abd50fe..b3cc8a771c 100644 --- a/api/src/Contacts/Ads.php +++ b/api/src/Contacts/Ads.php @@ -223,4 +223,20 @@ class Ads extends Ldap parent::sanitize_update($ldapContact); } + + /** + * Return a LDAP filter by group membership + * + * @param int $gid gidNumber (< 0 as used in EGroupware!) + * @return string filter or '' if $gid not < 0 + */ + function membershipFilter($gid) + { + $filter = ''; + if ($gid < 0 && ($dn = $GLOBALS['egw']->accounts->id2name($gid, 'account_dn'))) + { + $filter .= '(memberOf='.$dn.')'; + } + return $filter; + } } diff --git a/api/src/Contacts/Ldap.php b/api/src/Contacts/Ldap.php index 09e1769c99..a399fa1358 100644 --- a/api/src/Contacts/Ldap.php +++ b/api/src/Contacts/Ldap.php @@ -973,6 +973,10 @@ class Ldap $filters .= $this->ids_filter($value); break; + case 'list': + $filter .= $this->membershipFilter($value); + break; + default: $matches = null; if (!is_int($key)) @@ -1009,6 +1013,28 @@ class Ldap return $filters; } + /** + * Return a LDAP filter by group membership + * + * @param int $gid gidNumber (< 0 as used in EGroupware!) + * @return string filter or '' if $gid not < 0 + */ + function membershipFilter($gid) + { + $filter = ''; + if ($gid < 0) + { + $filter .= '(|'; + // unfortunately we have no group-membership attribute in LDAP, like in AD + foreach($GLOBALS['egw']->accounts->members($gid, true) as $account_id) + { + $filter .= '(uidNumber='.(int)$account_id.')'; + } + $filter .= ')'; + } + return $filter; + } + /** * Perform the actual ldap-search, retrieve and convert all entries * diff --git a/api/src/Contacts/Sql.php b/api/src/Contacts/Sql.php index 098072df47..c09837a76c 100644 --- a/api/src/Contacts/Sql.php +++ b/api/src/Contacts/Sql.php @@ -346,8 +346,16 @@ class Sql extends Api\Storage } if (isset($filter['list'])) { - $join .= " JOIN $this->ab2list_table ON $this->table_name.contact_id=$this->ab2list_table.contact_id AND ". - $this->db->expression($this->ab2list_table, array('list_id' => $filter['list'])); + if ($filter['list'] < 0) + { + $join .= " JOIN egw_acl ON $this->table_name.account_id=acl_account AND acl_appname='phpgw_group' AND ". + $this->db->expression('egw_acl', array('acl_location' => $filter['list'])); + } + else + { + $join .= " JOIN $this->ab2list_table ON $this->table_name.contact_id=$this->ab2list_table.contact_id AND ". + $this->db->expression($this->ab2list_table, array('list_id' => $filter['list'])); + } unset($filter['list']); } // add join to show only active accounts (only if accounts are shown and in sql and we not already join the accounts table, eg. used by admin) @@ -551,6 +559,28 @@ class Sql extends Api\Storage $lists[$row['list_id']]['members'][] = $row[$member_attr]; } } + /* groups as list are implemented currently in Contacts\Storage::get_lists() for all backends + if ($uid_column == 'list_owner' && in_array(0, (array)$uids) && (!$limit_in_ab || in_array(0, (array)$limit_in_ab))) + { + foreach($GLOBALS['egw']->accounts->search(array( + 'type' => 'groups' + )) as $account_id => $group) + { + $list = array( + 'list_id' => $account_id, + 'list_name' => Api\Accounts::format_username($group['account_lid'], '', '', $account_id), + 'list_owner' => 0, + 'list_uid' => 'group'.$account_id, + 'list_carddav_name' => 'group'.$account_id.'.vcf', + 'list_etag' => md5(json_encode($GLOBALS['egw']->accounts->members($account_id, true))) + ); + if ($member_attr) + { + $list['members'] = array(); // ToDo + } + $lists[(string)$account_id] = $list; + } + }*/ //error_log(__METHOD__.'('.array2string($uids).", '$uid_column', '$member_attr') returning ".array2string($lists)); return $lists; } diff --git a/api/src/Contacts/Storage.php b/api/src/Contacts/Storage.php index 30a590cafd..f83eeeb73c 100755 --- a/api/src/Contacts/Storage.php +++ b/api/src/Contacts/Storage.php @@ -1012,26 +1012,40 @@ class Storage */ function get_lists($required=Api\Acl::READ,$extra_labels=null) { - if (!method_exists($this->somain,'get_lists')) return false; - - $uids = array(); - foreach($this->grants as $uid => $rights) - { - if (($rights & $required) == $required) - { - $uids[] = $uid; - } - } $lists = is_array($extra_labels) ? $extra_labels : array(); - foreach($this->somain->get_lists($uids) as $list_id => $data) + if (method_exists($this->somain,'get_lists')) { - $lists[$list_id] = $data['list_name']; - if ($data['list_owner'] != $this->user) + $uids = array(); + foreach($this->grants as $uid => $rights) { - $lists[$list_id] .= ' ('.Api\Accounts::username($data['list_owner']).')'; + // only requests groups / list in accounts addressbook for read + if (!$uid && $required != Api\Acl::READ) continue; + + if (($rights & $required) == $required) + { + $uids[] = $uid; + } + } + + foreach($this->somain->get_lists($uids) as $list_id => $data) + { + $lists[$list_id] = $data['list_name']; + if ($data['list_owner'] != $this->user) + { + $lists[$list_id] .= ' ('.Api\Accounts::username($data['list_owner']).')'; + } } } + + // add groups for all backends + foreach($GLOBALS['egw']->accounts->search(array( + 'type' => 'groups' + )) as $account_id => $group) + { + $lists[(string)$account_id] = Api\Accounts::format_username($group['account_lid'], '', '', $account_id); + } + return $lists; }