* Setup: when migrating accounts from SQL to LDAP or back, also migrate addressbook data

This commit is contained in:
Ralf Becker 2012-11-19 08:23:09 +00:00
parent 26de26873b
commit ec2ce0f943
4 changed files with 109 additions and 59 deletions

View File

@ -203,18 +203,43 @@ class addressbook_ldap
var $all_attributes = array();
/**
* constructor of the class
* LDAP configuration
*
* @var array values for keys "ldap_contact_context", "ldap_host", "ldap_context"
*/
function __construct()
private $ldap_config;
/**
* constructor of the class
*
* @param array $ldap_config=null default use from $GLOBALS['egw_info']['server']
* @param resource $ds=null ldap connection to use
*/
function __construct(array $ldap_config=null, $ds=null)
{
//$this->db_data_cols = $this->stock_contact_fields + $this->non_contact_fields;
$this->accountName = $GLOBALS['egw_info']['user']['account_lid'];
$this->personalContactsDN = 'ou=personal,ou=contacts,'. $GLOBALS['egw_info']['server']['ldap_contact_context'];
$this->sharedContactsDN = 'ou=shared,ou=contacts,'. $GLOBALS['egw_info']['server']['ldap_contact_context'];
if ($ldap_config)
{
$this->ldap_config = $ldap_config;
}
else
{
$this->ldap_config =& $GLOBALS['egw_info']['server'];
}
$this->personalContactsDN = 'ou=personal,ou=contacts,'. $this->ldap_config['ldap_contact_context'];
$this->sharedContactsDN = 'ou=shared,ou=contacts,'. $this->ldap_config['ldap_contact_context'];
$this->connect();
$this->ldapServerInfo = $GLOBALS['egw']->ldap->getLDAPServerInfo($GLOBALS['egw_info']['server']['ldap_contact_host']);
if ($ds)
{
$this->ds = $ds;
}
else
{
$this->connect();
}
$this->ldapServerInfo = $GLOBALS['egw']->ldap->getLDAPServerInfo($this->ldap_config['ldap_contact_host']);
foreach($this->schema2egw as $schema => $attributes)
{
@ -241,14 +266,14 @@ class addressbook_ldap
// if ldap is NOT the contact repository, we only do accounts and need to use the account-data
if (substr($GLOBALS['egw_info']['server']['contact_repository'],-4) != 'ldap') // not (ldap or sql-ldap)
{
$GLOBALS['egw_info']['server']['ldap_contact_host'] = $GLOBALS['egw_info']['server']['ldap_host'];
$GLOBALS['egw_info']['server']['ldap_contact_context'] = $GLOBALS['egw_info']['server']['ldap_context'];
$this->ldap_config['ldap_contact_host'] = $this->ldap_config['ldap_host'];
$this->ldap_config['ldap_contact_context'] = $this->ldap_config['ldap_context'];
$this->ds = $GLOBALS['egw']->ldap->ldapConnect();
}
else
{
$this->ds = $GLOBALS['egw']->ldap->ldapConnect(
$GLOBALS['egw_info']['server']['ldap_contact_host'],
$this->ldap_config['ldap_contact_host'],
$GLOBALS['egw_info']['user']['account_dn'],
$GLOBALS['egw_info']['user']['passwd']
);
@ -298,7 +323,7 @@ class addressbook_ldap
(isset ($contact_id['id']) ? $contact_id['id'] : $contact_id['uid']));
$filter = "(|(entryUUID=$contact_id)(uid=$contact_id))";
}
$rows = $this->_searchLDAP($GLOBALS['egw_info']['server']['ldap_contact_context'],
$rows = $this->_searchLDAP($this->ldap_config['ldap_contact_context'],
$filter, $this->all_attributes, ADDRESSBOOK_ALL);
return $rows ? $rows[0] : false;
@ -339,7 +364,7 @@ class addressbook_ldap
$data['account_id'] == $GLOBALS['egw_info']['user']['account_id']))
{
// account
$baseDN = $GLOBALS['egw_info']['server']['ldap_context'];
$baseDN = $this->ldap_config['ldap_context'];
$cn = false;
// we need an admin connection
$this->ds = $GLOBALS['egw']->ldap->ldapConnect();
@ -366,7 +391,7 @@ class addressbook_ldap
$attributes = array('dn','cn','objectClass','uid','mail');
$contactUID = $this->data[$this->contacts_id];
if(!empty($contactUID) &&
($result = ldap_search($this->ds, $GLOBALS['egw_info']['server']['ldap_contact_context'],
($result = ldap_search($this->ds, $this->ldap_config['ldap_contact_context'],
'(|(entryUUID='.ldap::quote($contactUID).')(uid='.ldap::quote($contactUID).'))', $attributes)) &&
($oldContactInfo = ldap_get_entries($this->ds, $result)) && $oldContactInfo['count'])
{
@ -547,7 +572,7 @@ class addressbook_ldap
foreach($keys as $entry)
{
$entry = ldap::quote(is_array($entry) ? $entry['id'] : $entry);
if($result = ldap_search($this->ds, $GLOBALS['egw_info']['server']['ldap_contact_context'],
if($result = ldap_search($this->ds, $this->ldap_config['ldap_contact_context'],
"(|(entryUUID=$entry)(uid=$entry))", $attributes))
{
$contactInfo = ldap_get_entries($this->ds, $result);
@ -625,12 +650,12 @@ class addressbook_ldap
}
elseif (!isset($filter['owner']))
{
$searchDN = $GLOBALS['egw_info']['server']['ldap_contact_context'];
$searchDN = $this->ldap_config['ldap_contact_context'];
$addressbookType = ADDRESSBOOK_ALL;
}
else
{
$searchDN = $GLOBALS['egw_info']['server']['ldap_context'];
$searchDN = $this->ldap_config['ldap_context'];
$addressbookType = ADDRESSBOOK_ACCOUNTS;
}
@ -955,7 +980,7 @@ class addressbook_ldap
/**
* check if $baseDN exists. If not create it
*
* @param string $baseDN cn=xxx,ou=yyy,ou=contacts,$GLOBALS['egw_info']['server']['ldap_contact_context']
* @param string $baseDN cn=xxx,ou=yyy,ou=contacts,$this->ldap_config['ldap_contact_context']
* @return boolean/string false on success or string with error-message
*/
function _check_create_dn($baseDN)
@ -975,8 +1000,8 @@ class addressbook_ldap
list(,$ou) = explode(',',$baseDN);
foreach(array(
'ou=contacts,'.$GLOBALS['egw_info']['server']['ldap_contact_context'],
$ou.',ou=contacts,'.$GLOBALS['egw_info']['server']['ldap_contact_context'],
'ou=contacts,'.$this->ldap_config['ldap_contact_context'],
$ou.',ou=contacts,'.$this->ldap_config['ldap_contact_context'],
$baseDN,
) as $dn)
{

View File

@ -868,58 +868,72 @@ class addressbook_so
}
/**
* Migrates an SQL contact storage to LDAP or SQL-LDAP
* Migrates an SQL contact storage to LDAP, SQL-LDAP or back to SQL
*
* @param string $type "contacts" (default), "contacts+accounts" or "contacts+accounts-back" (sql-ldap!)
* @param string|array $type comma-separated list or array of:
* - "contacts" contacts to ldap
* - "accounts" accounts to ldap
* - "accounts-back" accounts back to sql (for sql-ldap!)
* - "sql" contacts and accounts to sql
*/
function migrate2ldap($type)
{
//error_log(__METHOD__."(".array2string($type).")");
$sql_contacts = new addressbook_sql();
$ldap_contacts = new addressbook_ldap();
// we need an admin connection
$ds = $GLOBALS['egw']->ldap->ldapConnect();
$ldap_contacts = new addressbook_ldap(null, $ds);
if (!is_array($type)) $type = explode(',', $type);
$start = $n = 0;
$num = 100;
while ($type != 'sql' && ($contacts = $sql_contacts->search(false,false,'n_family,n_given','','',false,'AND',
array($start,$num),$type != 'contacts,accounts' ? array('contact_owner != 0') : false)))
{
// very worse hack, until Ralf finds a better solution
// when migrating data, we need to bind as global ldap admin account
// and not as currently logged in user
$ldap_contacts->ds = $GLOBALS['egw']->ldap->ldapConnect();
foreach($contacts as $contact)
{
if ($contact['account_id']) $contact['id'] = $GLOBALS['egw']->accounts->id2name($contact['account_id']);
$ldap_contacts->data = $contact;
$n++;
if (!($err = $ldap_contacts->save()))
{
echo '<p style="margin: 0px;">'.$n.': '.$contact['n_fn'].
($contact['org_name'] ? ' ('.$contact['org_name'].')' : '')." --> LDAP</p>\n";
}
else
{
echo '<p style="margin: 0px; color: red;">'.$n.': '.$contact['n_fn'].
($contact['org_name'] ? ' ('.$contact['org_name'].')' : '').': '.$err."</p>\n";
}
}
$start += $num;
}
if ($type == 'contacts,accounts-back' || $type == 'sql') // migrate the accounts to sql
// direction SQL --> LDAP, either only accounts, or only contacts or both
if (($do = array_intersect($type, array('contacts', 'accounts'))))
{
// very worse hack, until Ralf finds a better solution
// when migrating data, we need to bind as global ldap admin account
// and not as currently logged in user
$ldap_contacts->ds = $GLOBALS['egw']->ldap->ldapConnect();
foreach($ldap_contacts->search(false,false,'n_family,n_given','','',false,'AND',
false,$type == 'sql'?null:array('owner' => 0)) as $contact)
$filter = count($do) == 2 ? null :
array($do[0] == 'contacts' ? 'contact_owner != 0' : 'contact_owner = 0');
while (($contacts = $sql_contacts->search(false,false,'n_family,n_given','','',false,'AND',
array($start,$num),$filter)))
{
foreach($contacts as $contact)
{
if ($contact['account_id']) $contact['id'] = $GLOBALS['egw']->accounts->id2name($contact['account_id']);
$ldap_contacts->data = $contact;
$n++;
if (!($err = $ldap_contacts->save()))
{
echo '<p style="margin: 0px;">'.$n.': '.$contact['n_fn'].
($contact['org_name'] ? ' ('.$contact['org_name'].')' : '')." --> LDAP</p>\n";
}
else
{
echo '<p style="margin: 0px; color: red;">'.$n.': '.$contact['n_fn'].
($contact['org_name'] ? ' ('.$contact['org_name'].')' : '').': '.$err."</p>\n";
}
}
$start += $num;
}
}
// direction LDAP --> SQL: either "sql" (contacts and accounts) or "accounts-back" (only accounts)
if (($do = array_intersect(array('accounts-back','sql'), $type)))
{
//error_log(__METHOD__."(".array2string($type).") do=".array2string($type));
$filter = in_array('sql', $do) ? null : array('owner' => 0);
foreach($ldap_contacts->search(false,false,'n_family,n_given','','',false,'AND',
false, $filter) as $contact)
{
//error_log(__METHOD__."(".array2string($type).") do=".array2string($type)." migrating ".array2string($contact));
if ($contact['jpegphoto']) // photo is NOT read by LDAP backend on search, need to do an extra read
{
$contact = $ldap_contacts->read($contact['id']);
}
unset($contact['id']); // ldap uid/account_lid
if ($type != 'sql' && $contact['account_id'] && ($old = $sql_contacts->read(array('account_id' => $contact['account_id']))))
if ($contact['account_id'] && ($old = $sql_contacts->read(array('account_id' => $contact['account_id']))))
{
$contact['id'] = $old['id'];
}

View File

@ -990,10 +990,9 @@ class setup
if (!$config)
{
// load the configuration from the database
$this->db->select($this->config_table,'config_name,config_value',
"config_name LIKE 'ldap%' OR config_name LIKE 'account_%' OR config_name LIKE '%encryption%' OR config_name='auth_type'",__LINE__,__FILE__);
while(($row = $this->db->row(true)))
foreach($this->db->select($this->config_table,'config_name,config_value',
"config_name LIKE 'ldap%' OR config_name LIKE 'account_%' OR config_name LIKE '%encryption%' OR config_name='auth_type'",
__LINE__,__FILE__) as $row)
{
$GLOBALS['egw_info']['server'][$row['config_name']] = $config[$row['config_name']] = $row['config_value'];
}

View File

@ -257,6 +257,18 @@ class setup_cmd_ldap extends setup_cmd
$accounts_obj->set_members($account['members'],$account_id);
}
}
// migrate addressbook data
$GLOBALS['egw_info']['user']['apps']['admin'] = true; // otherwise migration will not run in setup!
$addressbook = new addressbook_so();
foreach($this->as_array() as $name => $value)
{
if (substr($name, 5) == 'ldap_')
{
$GLOBALS['egw_info']['server'][$name] = $value;
}
}
$addressbook->migrate2ldap($to_ldap ? 'accounts' : 'accounts-back');
$this->restore_db();
return lang('%1 users and %2 groups created, %3 errors',$accounts_created,$groups_created,$errors).
@ -397,7 +409,7 @@ class setup_cmd_ldap extends setup_cmd
$this->test_ldap = new ldap();
$error_rep = error_reporting();
//error_reporting($error_rep & ~E_WARNING); // switch warnings of, in case they are on
error_reporting($error_rep & ~E_WARNING); // switch warnings of, in case they are on
ob_start();
$ds = $this->test_ldap->ldapConnect($this->ldap_host,$dn,$pw);
ob_end_clean();