New: More robust LDAP synchronizing

This commit is contained in:
Laurent Destailleur 2009-08-11 23:42:21 +00:00
parent 9382e5b6ef
commit 7ef1ef93ea
19 changed files with 230 additions and 105 deletions

View File

@ -32,6 +32,7 @@ For users:
- New: Add log tab on emailing module.
- New: Minor enhancements in look themes.
- New: Add option to hide help in menu.
- New: Added a "force LDAP synchronize" on member and contact cards.
- Fix: "Now" link works when date popup is not used.
- Fix: Debug seriously the email notification module.
- Fix: Error Call to a member function trans when refusing a supplier order.
@ -44,6 +45,7 @@ For users:
new product lines.
- Fix: CC and BCC in emails was not used if using SMTPS handler.
- Fix: Last character was lost when text end with n or r.
- Fix: LDAP synchronization is now more robust.
For translators:
- Update some language files.
@ -61,6 +63,8 @@ For developers:
- Better W3C standard.
- Can add init data when enabling a module.
- Can fix some corruptions in database by calling the update page with action=repair
- Log files contains more information (PHP_SELD added and OS user used for log of
command lines scripts)
***** Changelog for 2.6 compared to 2.5 *****

View File

@ -96,12 +96,12 @@ class Adherent extends CommonObject
// var $public;
var $array_options;
var $oldcopy; // To contains a clone of this when we need to save old properties of object
/**
\brief Adherent
\param DB base de donnees
\param id id de l'adherent
* \brief Adherent
* \param DB base de donnees
*/
function Adherent($DB)
{

View File

@ -209,6 +209,8 @@ if ($_REQUEST["action"] == 'update' && ! $_POST["cancel"] && $user->rights->adhe
// Create new object
if ($result > 0)
{
$adh->oldcopy=dol_clone($adh);
// Modifie valeures
$adh->prenom = trim($_POST["prenom"]);
$adh->nom = trim($_POST["nom"]);

View File

@ -18,11 +18,11 @@
*/
/**
\file htdocs/adherents/ldap.php
\ingroup ldap
\brief Page fiche LDAP adherent
\version $Id$
*/
* \file htdocs/adherents/ldap.php
* \ingroup ldap
* \brief Page fiche LDAP adherent
* \version $Id$
*/
require("./pre.inc.php");
require_once(DOL_DOCUMENT_ROOT."/lib/member.lib.php");
@ -64,7 +64,36 @@ if (! $result)
}
/*
* Actions
*/
if ($_GET["action"] == 'dolibarr2ldap')
{
$message="";
$db->begin();
$ldap=new Ldap();
$result=$ldap->connect_bind();
$info=$adh->_load_ldap_info();
$dn=$adh->_load_ldap_dn($info);
$olddn=$dn; // We can say that old dn = dn as we force synchro
$result=$ldap->update($dn,$info,$user,$olddn);
if ($result >= 0)
{
$message.='<div class="ok">'.$langs->trans("MemberSynchronized").'</div>';
$db->commit();
}
else
{
$message.='<div class="error">'.$ldap->error.'</div>';
$db->rollback();
}
}
@ -138,7 +167,24 @@ print '</table>';
print '</div>';
print '<br>';
if ($message) { print $message; }
/*
* Barre d'actions
*/
print '<div class="tabsAction">';
if ($conf->global->LDAP_SYNCHRO_ACTIVE == 'dolibarr2ldap')
{
print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$adh->id.'&amp;action=dolibarr2ldap">'.$langs->trans("ForceSynchronize").'</a>';
}
print "</div>\n";
if ($conf->global->LDAP_SYNCHRO_ACTIVE == 'dolibarr2ldap') print "<br>\n";

View File

@ -65,6 +65,8 @@ class Contact extends CommonObject
var $user_id;
var $user_login;
var $oldcopy; // To contains a clone of this when we need to save old properties of object
/**
* \brief Constructeur de l'objet contact
@ -375,7 +377,7 @@ class Contact extends CommonObject
/*
* \brief Charge l'objet contact
* \param id id du contact
* \param user Utilisateur lie au contact pour une alerte
* \param user Utilisateur abonnes aux alertes si on veut les alertes de ce contact
* \return int -1 if KO, 0 if OK but not found, 1 if OK
*/
function fetch($id, $user=0)
@ -442,7 +444,7 @@ class Contact extends CommonObject
$this->user_id = $obj->user_id;
$this->user_login = $obj->user_login;
// Recherche le user Dolibarr li<EFBFBD> <20> ce contact
// Recherche le user Dolibarr lie a ce contact
$sql = "SELECT u.rowid ";
$sql .= " FROM ".MAIN_DB_PREFIX."user as u";
$sql .= " WHERE u.fk_socpeople = ". $this->id;

View File

@ -144,6 +144,9 @@ if ($_REQUEST["action"] == 'confirm_delete' && $_REQUEST["confirm"] == 'yes' &&
if ($_POST["action"] == 'update' && ! $_POST["cancel"] && $user->rights->societe->contact->creer)
{
$contact = new Contact($db);
$contact->fetch($_POST["contactid"]);
$contact->oldcopy=dol_clone($contact);
$contact->old_name = $_POST["old_name"];
$contact->old_firstname = $_POST["old_firstname"];

View File

@ -18,11 +18,11 @@
*/
/**
\file htdocs/contact/ldap.php
\ingroup ldap
\brief Page fiche LDAP contact
\version $Id$
*/
* \file htdocs/contact/ldap.php
* \ingroup ldap
* \brief Page fiche LDAP contact
* \version $Id$
*/
require("./pre.inc.php");
require_once(DOL_DOCUMENT_ROOT."/contact.class.php");
@ -43,11 +43,41 @@ $contact = new Contact($db);
$contact->fetch($_GET["id"], $user);
/*
* Actions
*/
if ($_GET["action"] == 'dolibarr2ldap')
{
$message="";
$db->begin();
$ldap=new Ldap();
$result=$ldap->connect_bind();
$info=$contact->_load_ldap_info();
$dn=$contact->_load_ldap_dn($info);
$olddn=$dn; // We can say that old dn = dn as we force synchro
$result=$ldap->update($dn,$info,$user,$olddn);
if ($result >= 0)
{
$message.='<div class="ok">'.$langs->trans("ContactSynchronized").'</div>';
$db->commit();
}
else
{
$message.='<div class="error">'.$ldap->error.'</div>';
$db->rollback();
}
}
/*
* View
*/
* View
*/
llxHeader();
@ -72,16 +102,16 @@ print '<td>'.$langs->trans("Firstname").'</td><td width="25%">'.$contact->firstn
// Company
if ($contact->socid > 0)
{
$objsoc = new Societe($db);
$objsoc->fetch($contact->socid);
$objsoc = new Societe($db);
$objsoc->fetch($contact->socid);
print '<tr><td width="20%">'.$langs->trans("Company").'</td><td colspan="3">'.$objsoc->getNomUrl(1).'</td></tr>';
print '<tr><td width="20%">'.$langs->trans("Company").'</td><td colspan="3">'.$objsoc->getNomUrl(1).'</td></tr>';
}
else
{
print '<tr><td width="20%">'.$langs->trans("Company").'</td><td colspan="3">';
print $langs->trans("ContactNotLinkedToCompany");
print '</td></tr>';
print '<tr><td width="20%">'.$langs->trans("Company").'</td><td colspan="3">';
print $langs->trans("ContactNotLinkedToCompany");
print '</td></tr>';
}
// Civility
@ -104,7 +134,25 @@ print '</table>';
print '</div>';
print '<br>';
if ($message) { print $message; }
/*
* Barre d'actions
*/
print '<div class="tabsAction">';
if ($conf->global->LDAP_SYNCHRO_ACTIVE == 'dolibarr2ldap')
{
print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$contact->id.'&amp;action=dolibarr2ldap">'.$langs->trans("ForceSynchronize").'</a>';
}
print "</div>\n";
if ($conf->global->LDAP_SYNCHRO_ACTIVE == 'dolibarr2ldap') print "<br>\n";
// Affichage attributs LDAP

View File

@ -135,10 +135,8 @@ class InterfaceLdapsynchro
$ldap=new Ldap();
$ldap->connect_bind();
$oldobject=$object; // TODO Get oldobject
$oldinfo=$oldobject->_load_ldap_info();
$olddn=$oldobject->_load_ldap_dn($oldinfo);
$oldinfo=$object->oldcopy->_load_ldap_info();
$olddn=$object->oldcopy->_load_ldap_dn($oldinfo);
$info=$object->_load_ldap_info();
$dn=$object->_load_ldap_dn($info);
@ -205,10 +203,8 @@ class InterfaceLdapsynchro
$ldap=new Ldap();
$ldap->connect_bind();
$oldobject=$object; // TODO Get oldobject
$oldinfo=$oldobject->_load_ldap_info();
$olddn=$oldobject->_load_ldap_dn($oldinfo);
$oldinfo=$object->oldcopy->_load_ldap_info();
$olddn=$object->oldcopy->_load_ldap_dn($oldinfo);
$info=$object->_load_ldap_info();
$dn=$object->_load_ldap_dn($info);
@ -268,10 +264,8 @@ class InterfaceLdapsynchro
$ldap=new Ldap();
$ldap->connect_bind();
$oldobject=$object; // TODO Get oldobject
$oldinfo=$oldobject->_load_ldap_info();
$olddn=$oldobject->_load_ldap_dn($oldinfo);
$oldinfo=$object->oldcopy->_load_ldap_info();
$olddn=$object->oldcopy->_load_ldap_dn($oldinfo);
$info=$object->_load_ldap_info();
$dn=$object->_load_ldap_dn($info);
@ -384,10 +378,8 @@ class InterfaceLdapsynchro
$ldap=new Ldap();
$ldap->connect_bind();
$oldobject=$object; // TODO Get oldobject
$oldinfo=$oldobject->_load_ldap_info();
$olddn=$oldobject->_load_ldap_dn($oldinfo);
$oldinfo=$object->oldcopy->_load_ldap_info();
$olddn=$object->oldcopy->_load_ldap_dn($oldinfo);
$info=$object->_load_ldap_info();
$dn=$object->_load_ldap_dn($info);

View File

@ -24,5 +24,7 @@ LDAPFieldLastSubscriptionAmount=Last subscription amount
SynchronizeDolibarr2Ldap=Synchronize user (Dolibarr -> LDAP)
UserSynchronized=User synchronized
GroupSynchronized=Group synchronized
MemberSynchronized=Member synchronized
ContactSynchronized=Contact synchronized
ForceSynchronize=Force synchronizing Dolibarr -> LDAP
ErrorFailedToReadLDAP=Failed to read LDAP database. Check LDAP module setup and database accessibility.

View File

@ -24,5 +24,7 @@ LDAPFieldLastSubscriptionAmount=Montant dernière adhésion
SynchronizeDolibarr2Ldap=Synchroniser utilisateur (Dolibarr -> LDAP)
UserSynchronized=Utilisateur synchronisé
GroupSynchronized=Groupe synchronisé
MemberSynchronized=Adhérent synchronisé
ContactSynchronized=Contact synchronizé
ForceSynchronize=Forcer synchro Dolibarr -> LDAP
ErrorFailedToReadLDAP=Echec de la lecture de l'annuaire LDAP. Vérifier la configuration du module LDAP et l'accessibilité de l'annuaire.

View File

@ -1,7 +1,7 @@
<?php
/* Copyright (C) 2000-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2003 Jean-Louis Bergamo <jlb@j1b.org>
* Copyright (C) 2004-2008 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2004-2009 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2004 Sebastien Di Cintio <sdicintio@ressource-toi.org>
* Copyright (C) 2004 Benoit Mortier <benoit.mortier@opensides.be>
* Copyright (C) 2004 Christophe Combelles <ccomb@free.fr>
@ -35,6 +35,27 @@
if (! defined('DOL_DOCUMENT_ROOT')) define('DOL_DOCUMENT_ROOT', '..');
if (! defined('ADODB_DATE_VERSION')) include_once(DOL_DOCUMENT_ROOT."/includes/adodbtime/adodb-time.inc.php");
/**
* \brief Create a clone of instance of object (new instance with same properties)
* This function works for both PHP4 and PHP5
* \param object Object to clone
* \return date Timestamp
*/
function dol_clone($object)
{
dol_syslog("Functions.lib::dol_clone Clone object");
// We create dynamically a clone function, making a =
if (version_compare(phpversion(), '5.0') < 0 && ! function_exists('clone'))
{
eval('function clone($object){return($object);}');
}
$myclone=clone($object);
return $myclone;
}
/**
* \brief Return date for now
* \param mode 'gmt' => we return GMT timestamp,

View File

@ -565,15 +565,15 @@ class Ldap
if (! $olddn || $olddn != $dn)
{
// This case is not used for the moment
// If change we make is rename the key of LDAP record, we create new one and if ok, we delete old one.
$result = $this->add($dn, $info, $user);
if ($result > 0 && $olddn && $olddn != $dn) $result = $this->delete($olddn); // If add fails, we do not try to delete old one
}
else
{
$result = $this->delete($olddn);
$result = $this->add($dn, $info, $user);
//$result = $this->modify($dn, $info, $user); // TODO Must use modify instead of delete/add when olddn is received (for the moment olddn is dn)
//$result = $this->delete($olddn);
$result = $this->add($dn, $info, $user); // If record has been deleted from LDAP, we recreate it. We ignore error if it already exists.
$result = $this->modify($dn, $info, $user); // We use add/modify instead of delete/add when olddn is received
}
if ($result <= 0)
{

View File

@ -94,7 +94,7 @@ function show_ldap_test_button($butlabel,$testlabel,$key,$dn,$objectclass)
}
else if (empty($conf->global->LDAP_SERVER_HOST))
{
print '<a class="butActionRefused" href="#" title="'.$langs->trans('SetupNotComplete').'">'.$butlabel.'</a>';
print '<a class="butActionRefused" href="#" title="'.$langs->trans('LDAPSetupNotComplete').'">'.$butlabel.'</a>';
}
else if (empty($key) || empty($dn) || empty($objectclass))
{

View File

@ -96,6 +96,7 @@ class User extends CommonObject
var $all_permissions_are_loaded; /**< \private all_permissions_are_loaded */
var $tab_loaded=array(); // Tableau pour signaler les permissions deja chargees
var $oldcopy; // To contains a clone of this when we need to save old properties of object

View File

@ -233,7 +233,7 @@ if ($_POST["action"] == 'update' && ! $_POST["cancel"] && $caneditfield)
$edituser = new User($db, $_GET["id"]);
$edituser->fetch();
//$edituser->oldpass_indatabase = $edituser->pass_indatabase;
$edituser->oldcopy=dol_clone($edituser);
$edituser->nom = $_POST["nom"];
$edituser->prenom = $_POST["prenom"];
@ -263,7 +263,7 @@ if ($_POST["action"] == 'update' && ! $_POST["cancel"] && $caneditfield)
}
}
if ($ret >= 0 && isset($_POST["password"]) && $_POST["password"] !='')
if ($ret >= 0 && ! sizeof($edituser->errors) && isset($_POST["password"]) && $_POST["password"] !='')
{
$ret=$edituser->setPassword($user,$_POST["password"]);
if ($ret < 0)
@ -272,28 +272,32 @@ if ($_POST["action"] == 'update' && ! $_POST["cancel"] && $caneditfield)
}
}
if (isset($_FILES['photo']['tmp_name']) && trim($_FILES['photo']['tmp_name']))
if ($ret >=0 && ! sizeof($edituser->errors))
{
// If photo is provided
if (! is_dir($conf->user->dir_output))
if (isset($_FILES['photo']['tmp_name']) && trim($_FILES['photo']['tmp_name']))
{
create_exdir($conf->user->dir_output);
}
if (is_dir($conf->user->dir_output))
{
$newfile=$conf->user->dir_output . "/" . $edituser->id . ".jpg";
if (! dol_move_uploaded_file($_FILES['photo']['tmp_name'],$newfile,1) > 0)
// If photo is provided
if (! is_dir($conf->user->dir_output))
{
$message .= '<div class="error">'.$langs->trans("ErrorFailedToSaveFile").'</div>';
create_exdir($conf->user->dir_output);
}
if (is_dir($conf->user->dir_output))
{
$newfile=$conf->user->dir_output . "/" . $edituser->id . ".jpg";
if (! dol_move_uploaded_file($_FILES['photo']['tmp_name'],$newfile,1) > 0)
{
$message .= '<div class="error">'.$langs->trans("ErrorFailedToSaveFile").'</div>';
}
}
}
}
if ($ret >= 0)
if ($ret >= 0 && ! sizeof($edituser->errors))
{
$message.='<div class="ok">'.$langs->trans("UserModified").'</div>';
$db->commit();
} else
}
else
{
$db->rollback();
}

View File

@ -136,7 +136,8 @@ if ($_GET["action"] == 'removeuser')
if ($_POST["action"] == 'update')
{
if($caneditperms){
if($caneditperms)
{
$message="";
$db->begin();
@ -144,35 +145,41 @@ if ($_POST["action"] == 'update')
$editgroup = new Usergroup($db, $_GET["id"]);
$editgroup->fetch($_GET["id"]);
$editgroup->oldcopy=dol_clone($editgroup);
$editgroup->nom = trim($_POST["group"]);
$editgroup->note = dol_htmlcleanlastbr($_POST["note"]);
$ret=$editgroup->update();
if ($ret >= 0) {
if ($ret >= 0 && ! sizeof($editgroup->errors))
{
$message.='<div class="ok">'.$langs->trans("GroupModified").'</div>';
$db->commit();
} else {
$message.='<div class="error">'.$editgroup->error.'</div>';
$db->rollback;
}
}else{
else
{
$message.='<div class="error">'.$editgroup->error.'</div>';
$db->rollback();
}
}
else
{
$message = '<div class="error">'.$langs->trans('ErrorForbidden').'</div>';
}
}
/*
* View
*/
llxHeader('',$langs->trans("GroupCard"));
$html = new Form($db);
/* ************************************************************************** */
/* */
/* Affichage fiche en mode cr<63>ation */
/* */
/* ************************************************************************** */
if ($action == 'create')
{
print_fiche_titre($langs->trans("NewGroup"));

View File

@ -1,6 +1,6 @@
<?php
/* Copyright (C) 2006 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2006 Regis Houssin <regis@dolibarr.fr>
/* Copyright (C) 2006-2009 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2006 Regis Houssin <regis@dolibarr.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -18,11 +18,11 @@
*/
/**
\file htdocs/user/group/ldap.php
\ingroup ldap
\brief Page fiche LDAP groupe
\version $Id$
*/
* \file htdocs/user/group/ldap.php
* \ingroup ldap
* \brief Page fiche LDAP groupe
* \version $Id$
*/
require("./pre.inc.php");
require_once(DOL_DOCUMENT_ROOT."/contact.class.php");
@ -60,14 +60,10 @@ if ($_GET["action"] == 'dolibarr2ldap')
$ldap=new Ldap();
$result=$ldap->connect_bind();
$oldobject=$fgroup; // TODO Get oldobject
$oldinfo=$oldobject->_load_ldap_info();
$olddn=$oldobject->_load_ldap_dn($oldinfo);
$info=$fgroup->_load_ldap_info();
$dn=$fgroup->_load_ldap_dn($info);
$result=$ldap->add($dn,$info,$user);
$olddn=$dn; // We can say that old dn = dn as we force synchro
$result=$ldap->update($dn,$info,$user,$olddn);
if ($result >= 0)
@ -138,6 +134,7 @@ print "</table>\n";
print '</div>';
if ($message) { print $message; }

View File

@ -61,14 +61,10 @@ if ($_GET["action"] == 'dolibarr2ldap')
$ldap=new Ldap();
$result=$ldap->connect_bind();
$oldobject=$fuser; // TODO Get oldobject
$oldinfo=$oldobject->_load_ldap_info();
$olddn=$oldobject->_load_ldap_dn($oldinfo);
$info=$fuser->_load_ldap_info();
$dn=$fuser->_load_ldap_dn($info);
$result=$ldap->add($dn,$info,$user);
$olddn=$dn; // We can say that old dn = dn as we force synchro
$result=$ldap->update($dn,$info,$user,$olddn);
if ($result >= 0)
@ -92,19 +88,11 @@ llxHeader();
$form = new Form($db);
/*
* Affichage onglets
*/
$head = user_prepare_head($fuser);
$title = $langs->trans("User");
dol_fiche_head($head, 'ldap', $title, 0, 'user');
/*
* Fiche en mode visu
*/
print '<table class="border" width="100%">';
// Ref

View File

@ -46,6 +46,8 @@ class UserGroup extends CommonObject
var $datec; // Creation date of group
var $datem; // Modification date of group
var $oldcopy; // To contains a clone of this when we need to save old properties of object
/**
* \brief Constructeur de la classe
@ -94,6 +96,8 @@ class UserGroup extends CommonObject
$this->next_prev_filter = 'entity IN (0,'.$conf->entity.')';
// Sav current LDAP Current DN
//$this->ldap_dn = $this->_load_ldap_dn($this->_load_ldap_info(),0);
}
$this->db->free($result);
return 1;
@ -488,19 +492,21 @@ class UserGroup extends CommonObject
{
global $user, $conf, $langs;
$error=0;
$sql = "UPDATE ".MAIN_DB_PREFIX."usergroup SET ";
$sql .= " nom = '".addslashes($this->nom)."',";
$sql .= " note = '".addslashes($this->note)."'";
$sql .= " WHERE rowid = ".$this->id;
$result = $this->db->query($sql);
if ($result)
dol_syslog("Usergroup::update sql=".$sql);
$resql = $this->db->query($sql);
if ($resql)
{
if ($this->db->affected_rows())
if ($this->db->affected_rows($resql))
{
if (! $notrigger)
if (!$error && ! $notrigger)
{
// Appel des triggers
include_once(DOL_DOCUMENT_ROOT . "/interfaces.class.php");