How to get a cohort being syncronised with a ldap server ?

How to get a cohort being syncronised with a ldap server ?

by Philip Siwinski -
Number of replies: 43

How to get a cohort being syncronised with a ldap server ?

I wish to see cohorts being created automatically or manually with automatical addition of members based on a ldap field (or Moodle user profile field).

Some users would share the same "class" (ldap or profile) field for example so they would need to be in the same cohort in Moodle.

I have no idea of how cohorts can be connected to external systems. Any ideas ?

Average of ratings: -
In reply to Philip Siwinski

Re: How to get a cohort being syncronised with a ldap server ?

by Patrick Pollet -

A solution has just been posted to Moodle's tracker to nightly sync cohorts with LDAP groups defined on an external server.

See http://tracker.moodle.org/browse/MDL-25011

Code still requires testing ...

Enjoy

 

Average of ratings:Useful (1)
In reply to Patrick Pollet

Re: How to get a cohort being syncronised with a ldap server ?

by Philip Siwinski -

Thanks, would it work when the cohort ID is specified in a ldap attribute ?

I don't know how to use this piece of code but I will try to understand.

I currently get this ldap attribute copied to the Moodle user profile, could I synchronise without connecting to the external server ?

In reply to Philip Siwinski

Re: How to get a cohort being syncronised with a ldap server ?

by Patrick Pollet -

>Thanks, would it work when the cohort ID is specified in a ldap attribute ?

No this piece of code just scan your LDAP server for LDAP groups having by default class = 'groupOfUniqueNames'  and create Moodle's cohorts having the same name and idnumber  . If in your place LDAP groups are differents, you will have to add in config.php the following :

 

$CFG->ldap_group_class='xxxx'; // xxxx= posixgroup or groupOfNames or whatever

 

then for each LDAP user member of that group, it will add it to the cohort. Of course user must exists in Moodle, so this script must be run after synching Moodle accounts with your LDAP server.

 

>I don't know how to use this piece of code but I will try to understand.

 

Copy it in auth/ldap/cli directory or auth/cas/cli if you use CAS authentification, and test it on the command line. (php sync_cohorts.php)

When OK add it to your server's crontab. See comments at the beginning of the script to see how to do it.

In reply to Patrick Pollet

Re: How to get a cohort being syncronised with a ldap server ?

by Philip Siwinski -

Thanks, I think all my users are in a ldap group called "people".

For each user, their is a field which specifies a group id. Do you think I could adapt your script to my needs or look into a simpler solution as I just need to keep cohorts' members sync with a field value which is already in the Moodle database ?

In reply to Philip Siwinski

Re: How to get a cohort being syncronised with a ldap server ?

by Patrick Pollet -

No my solution will not work in your case. I create/sync  as many cohorts as LDAP groups present on the LDAP server. So in your case your will get a huge cohort named 'people' with everybody in it ...

 

However you can reuse a big chunk of my code for your purpose.

1) in function ldap_get_group_list () remove all code and just return an array of the DIFFERENT values existing in your Moodle database for your 'extra field'

(a SQL statement from mdl_user_info_data  table (since you said you where using a profile field) with a DISTINCT clause should do the job)

2) remove functions ldap_get_group_members_rfc and ldap_get_group_members_ad

3) in function ldap_get_group_members($group)  return an array of Moodle's usernames having the $group value in your profile field . This array must be indiced  by Moodle's userids, something like

array( '3'=>'jdoe', '4=>'bobama','6'=>'gbush', ....)

and that should work ...

 

For testing just comment out the 'critical lines'  :

cohort_remove_member($cohortid, $userid);

cohort_add_member($cohortid, $userid);

so your will get only a notice about what could have been done without any database access.

 

Cheers.

 

Edit : If you give me more details by private message about your extra field name ( column name, in what table ...) I can send you a 'quite working' script wink

In reply to Patrick Pollet

Re: How to get a cohort being syncronised with a ldap server ?

by Rob Morgan -

Hi there Patrick. You have said that it can be put in the auth/ldap/cli directory. I have done this because I don't have CAS authentication. The script won't run however because it says the CAS plugin is not enabled.

Do I need to enable this plugin as well as the ldap authentication plugin?

In reply to Rob Morgan

Re: How to get a cohort being syncronised with a ldap server ?

by Patrick Pollet -

Hi Rob,

 

Well I guess that if you want to user on a 'pure ldap' environnement whitout CAS you indeed have to put the script in auth/ldap/cli directory but you must edit it a bit near line 70 from

$this->authtype = 'cas';   
 $this->roleauth = 'auth_cas';
 $this->errorlogtag = '[AUTH CAS] ';

to

$this->authtype = 'ldap';
        $this->roleauth = 'auth_ldap'; 
       $this->errorlogtag = '[AUTH LDAP] ';

and near line 388


if (!is_enabled_auth('cas')) {  
  error_log('[AUTH CAS] ' . get_string('pluginnotenabled', 'auth_ldap')); 
   die;
}

to


if (!is_enabled_auth('ldap')) {  
    error_log('[AUTH LDAP] ' . get_string('pluginnotenabled', 'auth_ldap'));
    die;
}

Cheers.

In reply to Patrick Pollet

Re: How to get a cohort being syncronised with a ldap server ?

by Di Zhao -

Hi Patrick,

I'm newbie on this.Just follow your instruction to run this script.

But I got an error "4 PHP Fatal error:  Call to undefined method auth_plugin_cohort::ldap_get_group_members_ad() in /var/www/html/moodle/auth/ldap/cli/sync_cohorts.php on line 350"

Could you tell me what's the reason for this ? Appreciate so much!

In reply to Di Zhao

Re: How to get a cohort being syncronised with a ldap server ?

by Patrick Pollet -

@di,

oups there is a mistake in my code at line 230 that should read

 function ldap_get_group_members_ad($group) {

and not

 function get_group_members_ad($group) {

Sorry  blush

In reply to Patrick Pollet

Re: How to get a cohort being syncronised with a ldap server ?

by Di Zhao -

Thanks Patrick !

Actually I modified ur script as you taught ,and put

$CFG->ldap_group_attribute = 'cn';
$CFG->ldap_group_class = 'group';

into my config.php

Then run the script ,it shows error again

Connecting to LDAP server...
traitement du groupe Sept 2008 Cohorts
creation cohorte 0
PHP Notice:  Undefined property: stdClass::$debug_ldap_groupes in /var/www/html/moodle/auth/ldap/cli/sync_cohorts.php on line 235

Notice: Undefined property: stdClass::$debug_ldap_groupes in /var/www/html/moodle/auth/ldap/cli/sync_cohorts.php on line 235
Default exception handler: Coding error detected, it must be fixed by a programm             er: PHP catchable fatal error Debug: Object of class stdClass could not be conve             rted to string
* line 359 of /lib/setuplib.php: coding_exception thrown
* line 243 of /auth/ldap/cli/sync_cohorts.php: call to default_error_handler()
* line 350 of /auth/ldap/cli/sync_cohorts.php: call to auth_plugin_cohort->ldap_             get_group_members_ad()
* line 414 of /auth/ldap/cli/sync_cohorts.php: call to auth_plugin_cohort->ldap_             get_group_members()

!!! Coding error detected, it must be fixed by a programmer: PHP catchable fatal  error !!!

Could u tell me what's wrong with my script ?

Thanks so much again!

Attach the script I'm using ~

In reply to Di Zhao

Re: How to get a cohort being syncronised with a ldap server ?

by Patrick Pollet -

Hello,

 

 Again these is an error in code retrieving groups from Active Directory

in line 243 a '{' is missing !

 $queryg = "(&(cn=" . trim($group) . ")(objectClass=$this->config->group_class}))";

change to

 $queryg = "(&(cn=" . trim($group) . ")(objectClass={$this->config->group_class}))";

 

This piece of code has not been tested here since we do not have AD ... Sorry. 

In reply to Patrick Pollet

Re: How to get a cohort being synchronised with a ldap server ?

by Patrick Pollet -

Hello, 

    Moodle 2.1 has changed the processing of cohort component field in table mdl_cohort (that was ignored in Moodle 2.0) . So to still be able to edit the cohorts created by this script you must clear the field in the database table under phpmyadmin with the following SQL 

update mdl_cohort set component='' where component='ldap_sync' 

For this script to still be usable in Moodle 2.1 (2.1.3+ (Build: 20111205) ) you must make the following changes :

add  $CFG->debug_ldap_groupes=false;   to remove some php notices if enabled 

near line 387 to have 

$CFG->debug = DEBUG_NORMAL;
$CFG->debug_ldap_groupes=false; // line to add 

Comment out the line 408

//$cohort->component='sync_ldap'; 

You may also add at line 409 the following line to fill the new cohort's decription field :

 $cohort->description='cohort synchronized with our  LDAP';

Cheers.

Average of ratings:Useful (1)
In reply to Patrick Pollet

Re: How to get a cohort being synchronised with a ldap server ?

by Sven Rautol -

Hello,

 does this script work in Moodle 2.2?

I copied it to /moodle/auth/ldap/cli/sync_cohorts.php, changed owner and group to www-data (Debian working here).

 Furthermore I add the following lines to moodle/config.php:

$CFG->ldap_group_attribute = 'cn';
$CFG->ldap_group_class = 'posixgroup';

 (openldap working here)

 

Finally, I mad the changes, which you described in the post above (23. february 2011, 14:48) to run the script with ldap without cas.

 Then I typed in den Command-Line: php sync_cohorts.php

Then the message appears: "connect to ldap-Server" and nothing happens any more.

Can you help me, please?

Cheers Sven

PS: sync_users is working fine 

 

 

In reply to Sven Rautol

Re: How to get a cohort being synchronised with a ldap server ?

by stephane ngov -

Hello, I try get a user cohorte, but when i execute the scipt, in a moodle ther is a new chorte but the cohorte is empty.

i add this script , i try echo variable

 


define('CLI_SCRIPT', true);

 



require ('config.php');
require_once ($CFG->dirroot . '/group/lib.php');
require_once ($CFG->dirroot . '/cohort/lib.php');

require_once ($CFG->dirroot . '/auth/ldap/auth.php');

$CFG->debug_ldap_groupes=false;
/**
 * CAS authentication plugin.
 * extended to fetch LDAP groups and to be cohort aware
 */
class auth_plugin_cohort extends auth_plugin_ldap {

    /**
    * Constructor.
    */
    
    function auth_plugin_cohort() {
        global $CFG;
        $this->authtype = 'cas';
        $this->roleauth = 'auth_cas';
        $this->errorlogtag = '[AUTH CAS] ';
        $this->init_plugin($this->authtype);
        //TODO must be in some setting screen Currently in config.php
        $this->config->group_attribute = !empty($CFG->ldap_group_attribute)?$CFG->ldap_group_attribute:'cn';
        $this->config->group_class = !empty($CFG->ldap_group_class )?$CFG->ldap_group_class :'group';

        // print_r($this->config);
    }

    /**
     * return all groups declared in LDAP
     * @return string[]
     */

    function ldap_get_grouplist($filter = "*") {
        /// returns all groups from ldap servers

        global $CFG, $DB;

        print_string('connectingldap', 'auth_ldap');
        $ldapconnection = $this->ldap_connect();

        $fresult = array ();

        if ($filter == "*") {
            $filter = "(&(" . $this->config->group_attribute . "=*)(objectclass=" . $this->config->group_class . "))";
        }

        $contexts = explode(';', $this->config->contexts);
        if (!empty ($this->config->create_context)) {
            array_push($contexts, $this->config->create_context);
        }
        var_dump($contexts);
        foreach ($contexts as $context) {
            $context = trim($context);
            if (empty ($context)) {
                continue;
            }

            if ($this->config->search_sub) {
                //use ldap_search to find first group from subtree
                $ldap_result = ldap_search($ldapconnection, $context, $filter, array (
                    $this->config->group_attribute
                ));
            } else {
                //search only in this context
                $ldap_result = ldap_list($ldapconnection, $context, $filter, array (
                    $this->config->group_attribute
                ));
            }

            $groups = ldap_get_entries($ldapconnection, $ldap_result);

            //add found groups to list
            for ($i = 0; $i < count($groups) - 1; $i++) {
                array_push($fresult, ($groups[$i][$this->config->group_attribute][0]));
            }
        }
        $this->ldap_close();
        echo "**********RESULTA group liste <br/>";
        var_dump($fresult);
        return $fresult;
    }

    /**
     * serach for group members on a openLDAP directory
     * return string[] array of usernames
     */

    function ldap_get_group_members_rfc($group) {
        global $CFG;

        $ret = array ();
        $ldapconnection = $this->ldap_connect();

        $textlib = textlib_get_instance();
        $group = $textlib->convert($group, 'utf-8', $this->config->ldapencoding);

        if ($CFG->debug_ldap_groupes)
            print_object("connexion ldap: ", $ldapconnection);
        if (!$ldapconnection)
            return $ret;

        $queryg = "(&(cn=" . trim($group) . ")(objectClass={$this->config->group_class}))";
        if ($CFG->debug_ldap_groupes)
            print_object("queryg: ", $queryg);

        $contexts = explode(';', $this->config->contexts);
        if (!empty ($this->config->create_context)) {
            array_push($contexts, $this->config->create_context);
        }

        foreach ($contexts as $context) {
            $context = trim($context);
            if (empty ($context)) {
                continue;
            }

            $resultg = ldap_search($ldapconnection, $context, $queryg);

            if (!empty ($resultg) AND ldap_count_entries($ldapconnection, $resultg)) {
                $groupe = ldap_get_entries($ldapconnection, $resultg);
                if ($CFG->debug_ldap_groupes)
                    print_object("groupe: ", $groupe);

                //todo tester existence du groupe !!!
                for ($g = 0; $g < (sizeof($groupe[0][$this->config->memberattribute]) - 1); $g++) {

                    $membre = trim($groupe[0][$this->config->memberattribute][$g]);
                    if ($membre != "") { //*3
                        if ($CFG->debug_ldap_groupes)
                            print_object("membre : ", $membre);

                        // la cle count contient le nombre de membres
                        // 3 cas : 1 - membre est de la forme  cn=xxxxxx, ou =zzzz ....
                        //         2 - membre est de la forme uid=login,ou=people,dc=insa_lyon,dc=fr
                        //         3 - membre est simplement un login
                        // récupération de la chaîne membre
                        // vérification du format
                        $membre_tmp1 = explode(",", $membre);
                        if (count($membre_tmp1) > 1) {
                            // normalement le premier élément est soir cn=..., soit uid=...
                            if ($CFG->debug_ldap_groupes)
                                print_object("membre_tpl1: ", $membre_tmp1);
                            //essaie de virer la suite
                            $membre_tmp2 = explode("=", trim($membre_tmp1[0]));
                            if ($CFG->debug_ldap_groupes)
                                print_object("membre_tpl2: ", $membre_tmp2);
                            //pas le peine d'aller dans le ldap si c'est bon
                            if ($membre_tmp2[0] == $this->config->user_attribute) //celui de la config
                                $ret[] = $membre_tmp2[1];
                            else {
                                //intervenir ici !!!
                                if ($CFG->debug_ldap_groupes)
                                    print_object("attribut trouvé different de ", $this->config->user_attribute);
                                // rev 1012 Lyon1 (AD)
                                if ($this->config->memberattribute_isdn) {
                                    // allez chercher son "login" (uid)
                                    if ($cpt = $this->get_account_bydn($membre_tmp2[0], $membre_tmp2[1]))
                                        $ret[] = $cpt->username;
                                }
                            }

                        } else
                            $ret[] = $membre;
                    }
                }
            }
        }
        if ($CFG->debug_ldap_groupes)
            print_object("retour get_g_m ", $ret);
        $this->ldap_close();
        return $ret;
    }

    /**
     * specific serach for active Directory  problems if more than 999 members
     * recherche paginée voir http://forums.sun.com/thread.jspa?threadID=578347
     */

    function ldap_get_group_members_ad($group) {
        global $CFG;

        $ret = array ();
        $ldapconnection = $this->ldap_connect();
        if ($CFG->debug_ldap_groupes)
            print_object("connexion ldap: ", $ldapconnection);
        if (!$ldapconnection)
            return $ret;

        $textlib = textlib_get_instance();
        $group = $textlib->convert($group, 'utf-8', $this->config->ldapencoding);

        $queryg = "(&(cn=" . trim($group) . ")(objectClass={$this->config->group_class}))";
    echo "*****QUERYG<br/>";
    var_dump($members);
        if ($CFG->debug_ldap_groupes)
            print_object("queryg: ", $queryg);

        $size = 999;
        

        $contexts = explode(';', $this->config->contexts);
        if (!empty ($this->config->create_context)) {
            array_push($contexts, $this->config->create_context);
        }

            echo "*****CONTEXTS<br/>";
    var_dump($contexts);
        foreach ($contexts as $context) {
            $context = trim($context);
            if (empty ($context)) {
                continue;
            }
            $start = 0;
            $end = $size;
            $fini = false;

            while (!$fini) {
                //recherche paginée par paquet de 1000
                $attribut = $this->config->memberattribute . ";range=" . $start . '-' . $end;
                    echo "*****ATTRIBUT<br/>";
    var_dump($attribut);
                $resultg = ldap_search($ldapconnection, $context, $queryg, array (
                    $attribut
                ));

                if (!empty ($resultg) AND ldap_count_entries($ldapconnection, $resultg)) {
                    $groupe = ldap_get_entries($ldapconnection, $resultg);
                    if ($CFG->debug_ldap_groupes)
                        print_object("groupe: ", $groupe);

                    // a la derniere passe, AD renvoie member;Range=numero-* !!!
                    if (empty ($groupe[0][$attribut])) {
                        $attribut = $this->config->memberattribute . ";range=" . $start . '-*';
                        $fini = true;
                    }

                    for ($g = 0; $g < (sizeof($groupe[0][$attribut]) - 1); $g++) {

                        $membre = trim($groupe[0][$attribut][$g]);
                        if ($membre != "") { //*3
                            if ($CFG->debug_ldap_groupes)
                                print_object("membre : ", $membre);

                            $membre_tmp1 = explode(",", $membre);
                            if (count($membre_tmp1) > 1) {
                                // normalement le premier élément est soir cn=..., soit uid=...

                                if ($CFG->debug_ldap_groupes)
                                    print_object("membre_tpl1: ", $membre_tmp1);
                                //essaie de virer la suite
                                $membre_tmp2 = explode("=", trim($membre_tmp1[0]));
                                if ($CFG->debug_ldap_groupes)
                                    print_object("membre_tpl2: ", $membre_tmp2);
                                //pas le peine d'aller dans le ldap si c'est bon
                                if ($membre_tmp2[0] == $this->config->user_attribute) //celui de la config
                                    $ret[] = $membre_tmp2[1];
                                else {
                                    //intervenir ici !!!
                                    if ($CFG->debug_ldap_groupes)
                                        print_object("attribut trouvé different de ", $this->config->user_attribute);
                                    // rev 1012 Lyon1 (AD)
                                    if ($this->config->memberattribute_isdn) {
                                        // allez chercher son "login" (uid)
                                        if ($cpt = $this->get_account_bydn($membre_tmp2[0], $membre_tmp2[1]))
                                            $ret[] = $cpt->username;
                                    }
                                }

                            } else
                                $ret[] = $membre;

                        }
                    }
                } else
                    $fini = true;
                $start = $start + $size;
                $end = $end + $size;
            }
        }
        if ($CFG->debug_ldap_groupes)
            print_object("retour get_g_m ", $ret);
        $this->ldap_close();
        return $ret;
    }

    /**
     * not yet implemented
     * should return a Moodle account from its LDAP dn
     * @param string $dnid
     * @param string $dn
     */
    function get_account_bydn($dnid,$dn) {
        return false;
    }

    /**
     * rev 1012 traitement de l'execption avec active directory pour des groupes >1000 membres
     * voir http://forums.sun.com/thread.jspa?threadID=578347
     *
     * @return string[] an array of username indexed by Moodle's userid
     */
    function ldap_get_group_members($groupe) {
        global $DB;
        if ($this->config->user_type == "ad")
            $members = $this->ldap_get_group_members_ad($groupe);
        else
            $members = $this->ldap_get_group_members_rfc($groupe);
        $ret = array ();
    echo "*****MEMBERS<br/>";
    var_dump($members);
        foreach ($members as $member) {
            $params = array (
                'username' => $member
            );
            if ($user = $DB->get_record('user', $params, 'id,username'))
                $ret[$user->id] = $user->username;
        }
        return $ret;
    }

    function get_cohort_members($cohortid) {
        global $DB;
        $sql = " SELECT u.id,u.username
                          FROM {user} u
                         JOIN {cohort_members} cm ON (cm.userid = u.id AND cm.cohortid = :cohortid)
                        WHERE u.deleted=0";
        $params['cohortid'] = $cohortid;
        return $DB->get_records_sql($sql, $params);
    }

    function cohort_is_member($cohortid, $userid) {
        global $DB;
   echo "*****USER ID<br/>";
    var_dump($userid);        $params = array (
            'cohortid' => $cohortid,
            'userid' => $userid
        );
        return $DB->record_exists('cohort_members', $params);
    }

}

// Ensure errors are well explained
$CFG->debug = DEBUG_NORMAL;

if (!is_enabled_auth('cas')) {
    error_log('[AUTH CAS] ' . get_string('pluginnotenabled', 'auth_ldap'));
    die;
}

$plugin = new auth_plugin_cohort();

$ldap_groups = $plugin->ldap_get_grouplist();
    echo "*****LDAP_GET_GROUPLIST<br/>";
    var_dump($ldap_groups);
//print_r($ldap_groups);

foreach ($ldap_groups as $group=>$groupname) {
    print "traitement du groupe " . $groupname . "\n";
    $params = array (
        'idnumber' => $groupname
    );
    if (!$cohort = $DB->get_record('cohort', $params, '*')) {
        $cohort = new StdClass();
        $cohort->name = $cohort->idnumber = $groupname;
        $cohort->contextid = get_system_context()->id;
        //$cohort->component='sync_ldap';
        $cohort->description='cohorte synchronisée avec notre LDAP';
        $cohortid = cohort_add_cohort($cohort);
        print "creation cohorte " . $group . "\n";

    } else
        $cohortid = $cohort->id;
    echo "*****USER NAME<br/>";
    var_dump($cohort);
    //    print ($cohortid." ");
    $ldap_members = $plugin->ldap_get_group_members($groupname);
    $cohort_members = $plugin->get_cohort_members($cohortid);
    var_dump($ldap_members);

    foreach ($cohort_members as $userid => $user) {
        if (!isset ($ldap_members[$userid])) {
            cohort_remove_member($cohortid, $userid);
            print "desinscription de " .
            $user->username .
            " de la cohorte " .
            $groupname .
            "\n";
        }
    }
    echo "*****USER NAME<br/>";
    var_dump($username);

    foreach ($ldap_members as $userid => $username) {
        if (!$plugin->cohort_is_member($cohortid, $userid)) {
            cohort_add_member($cohortid, $userid);
            print "inscription de " . $username . " à la cohorte " . $groupname . "\n";
        }
    }
    //break;

}

?>


in the consol is display:

-bash-4.1$ php sync_cohorts.php
Connection au serveur LDAP...array(1) {
  [0]=>
  string(23) "ou=People,dc=test,dc=lan"
}
**********RESULTA group liste <br/>array(1) {
  [0]=>
  string(19) "Moodle_cohorte_test"
}
*****LDAP_GET_GROUPLIST<br/>array(1) {
  [0]=>
  string(19) "Moodle_cohorte_test"
}
traitement du groupe Moodle_cohorte_test
*****USER NAME<br/>object(stdClass)#362 (9) {
  ["id"]=>
  string(1) "8"
  ["contextid"]=>
  string(1) "1"
  ["name"]=>
  string(19) "Moodle_cohorte_test"
  ["idnumber"]=>
  string(19) "Moodle_cohorte_test"
  ["description"]=>
  string(37) "cohorte synchronisée avec notre LDAP"
  ["descriptionformat"]=>
  string(1) "1"
  ["component"]=>
  string(0) ""
  ["timecreated"]=>
  string(10) "1342529699"
  ["timemodified"]=>
  string(10) "1342529699"
}
*****QUERYG<br/>NULL
*****CONTEXTS<br/>array(1) {
  [0]=>
  string(23) "ou=People,dc=test,dc=lan"
}
*****ATTRIBUT<br/>string(20) "memberof;range=0-999"
*****MEMBERS<br/>array(0) {
}
array(0) {
}
*****USER NAME<br/>NULL
-bash-4.1$

how i must create the user in my LDAP, In the group Moodle_cohortes_test in my LDAP the are not empty.

why the script can't get the user in Moodle_cohortes_test ?

 

thanks for reply me

Attachment empty.png
In reply to stephane ngov

Re: How to get a cohort being synchronised with a ldap server ?

by Patrick Pollet -

Hello,

    A new version have just been posted in the tracker http://tracker.moodle.org/browse/MDL-25011 that address this problem of cohorts not populated when LDAP user's DN do not contains the Moodle username , such as dn='cn=user fullname,ou=wwww,dc=xxx...'  which is quite common with Active Directory

Enjoy

In reply to Patrick Pollet

Re: How to get a cohort being synchronised with a ldap server ?

by Jörg Tuttas -

Dear Patrick Pollet,

just have a problem in Moodle 2.9.1. to get the sync_cohots script to work, i just run into the following error and have no idea to fix it. Did you have and idea? The error message is in german an means some problem with the (text) coding.


Would be nice to hear from you. best regards


Default exception handler: Fehler in der Kodierung gefunden, den nur ein Programmierer korrigieren kann: textlib_get_instance() can not be used any more, please use core_text::functioname() instead. Debug:

Error code: codingerror

* line 1490 of /lib/deprecatedlib.php: coding_exception thrown

* line 347 of /auth/ldap/cli/sync_cohorts.php: call to textlib_get_instance()

* line 540 of /auth/ldap/cli/sync_cohorts.php: call to auth_plugin_cohort->ldap_get_group_members_ad()

* line 653 of /auth/ldap/cli/sync_cohorts.php: call to auth_plugin_cohort->ldap_get_group_members()


!!! Fehler in der Kodierung gefunden, den nur ein Programmierer korrigieren kann: textlib_get_instance() can not be used any more, please use core_text::functioname() instead. !!!

In reply to Jörg Tuttas

Re: How to get a cohort being synchronised with a ldap server ?

by Christine Legemble -

Hi Jörg ,

I have the same problem with my Moodle 2.9.1 (the plugin worked well before with older versions of Moodle).  

Have you find a solution ?

Best regards.

Christine

In reply to Christine Legemble

Re: How to get a cohort being synchronised with a ldap server ?

by Séverin Terrier -
Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Testers Picture of Translators

Hi,

Sadly, Patrick Pollet died in january sad

But it seems someone found a solution for Moodle 2.9, exposed in a french discussion. Have also a look at this bug (with solution).

Séverin

In reply to Séverin Terrier

Re: How to get a cohort being synchronised with a ldap server ?

by Robert Holt -

Hi, 

Very sorry to hear

we have upgraded to 3.0+ , i have been trying to get this plugin to work as i can't find any alternative and it is perfect for our needs.

i have got it installed but when i run it, it gets as far as collecting the groups and the users within the groups from LDAP but then throws an error: membre : xxx not found. 

I have poured over the settings and code but am stumped, don't suppose anyone knows what i'm doing wrong or know of any solution. 


Many Thanks

Rob


In reply to Jörg Tuttas

Re: How to get a cohort being synchronised with a ldap server ?

by Charles Fulton -
Picture of Core developers Picture of Plugin developers Picture of Testers

Hello everyone,

I've updated the plugin to support Moodle 3.1 and the new scheduled task infrastructure. The plugin is now available on the plugins repository: https://moodle.org/plugins/local_ldap. It still supports both OpenLDAP and Active Directory but I've no way to test the latter.

Best,

Charles

In reply to Charles Fulton

Re: How to get a cohort being synchronised with a ldap server ?

by Matjaž Mozetič -

Hi Charles.


Thank you for your effort to make this plugin work on newer versions of Moodle. Unfortunately for me is not working on Active Directory. I'm pretty sure I configured everything correctly. I also tried to run the script in command line and received just this info:

Execute scheduled task: Synchronize cohorts from LDAP groups (local_ldap\task\group_sync_task)

... used 0 dbqueries

... used 0.099068880081177 seconds

Scheduled task complete: Synchronize cohorts from LDAP groups (local_ldap\task\group_sync_task)

Can anyone else please test this plugin to confirm if it is working/not working on Active Directory?


Regards,

Matjaž

In reply to Matjaž Mozetič

Odp: Re: How to get a cohort being synchronised with a ldap server ?

by Paweł Gaw -

Hello, I have the same problem. What did You set that it works? Do You have any screenshots of settings? 

In reply to Charles Fulton

Re: How to get a cohort being synchronised with a ldap server ?

by Matjaž Mozetič -

Hi.


Actually it seems it is working!! I just configured wrong some things.

Charles thank you for bringing back this plugin!


Regards,

Matjaž

In reply to Matjaž Mozetič

Re: How to get a cohort being synchronised with a ldap server ?

by Reed Glasener -

Thats great we still have not been able to get the group cohort sync to work what did you configure on the Group Class for Windows AD?




We have a windows 2008r2 and are able snyc users to moodle and wanted to sync cohorts
The AD group is CN=Engineering,OU=Training,OU=Domain Groups,DC=example,DC=com

We tried the following changes on the plugin the Group attribute as cn even tried department and tried Group Class as both group and groupOfNames 

Also used combinations of the following for the chort but still no sync.
Cohort 
Name Engineering
Chort ID CN=Engineering,OU=Training,OU=Domain Groups,DC=example,DC=com

Cohort 
Name Engineering
Chort ID Engineering

Cohort 
Name Engineering
Chort ID CN=Engineering

In reply to Reed Glasener

Re: How to get a cohort being synchronised with a ldap server ?

by Reed Glasener -

We got it going the plugin Linux permissions when installed did not allow execute on the PHP files.


Below is or settings for Windows AD to sync groups to cohorts.


We used in the plugin field names.

cn

group

sAMAccountName



Also on the LDAP authentications originally it was search two user OUs  we also added the OU where the groups are stored



Attachment Cohort-group-sync.PNG
In reply to Reed Glasener

Re: How to get a cohort being synchronised with a ldap server ?

by santosh dharamsale -

Hi All,


I Moodle 3.3 Bitnami and fresh configuration and when I am trying to sync cohorts I am getting the following message and no cohorts are getting sync in Moodle, we have production rollout not sure how to address if anyone has fix please let me know and I tried all the steps mentioned.


C:\Bitnami\moodle\php>php C:\Bitnami\moodle\apps\moodle\htdocs\admin\tool\task\c
li\schedule_task.php --execute=\local_ldap\task\group_sync_task
Execute scheduled task: Synchronize cohorts from LDAP groups (local_ldap\task\gr
oup_sync_task)
... used 1063 dbqueries
... used 27.389446020126 seconds
Scheduled task complete: Synchronize cohorts from LDAP groups (local_ldap\task\g
roup_sync_task)

In reply to Charles Fulton

Re: How to get a cohort being synchronised with a ldap server ?

by Guybrush Threepwood -

Hi,

The cohort sync with our AD groups is not working for me.

Using latest moodle version 3.4.2+

Users sync is working well however.

Here are the config I used:

  • group_attribute: cn
  • group_class: group
  • real_user_attribure: sAMAccountName (also tried empty)
  • process_nested_groups: disabled (also tried enabled)
  • cohort_synching_ldap_groups_autocreate_cohorts: enabled.


When I launche the scheduled task, I have many warnings:

PHP Notice:  Undefined index: memberof;range=0-* in [...]\root\local\ldap\locallib.php on line 312

PHP Warning:  count(): Parameter must be an array or an object that implements Countable in [...]\root\local\ldap\locallib.php on line 312


The cohorts are not even created.


I tried to create a cohort with "Cohort ID" as same as the group name, it's not populated.


The test script root\local\ldap\tests\sync_test.php don't give any output...


Is there a way to have a verbal output like the previons version using "\root\local\ldap\cli\sync_cohorts.php"?


Any help will be appreciated!


In reply to Guybrush Threepwood

Re: How to get a cohort being synchronised with a ldap server ?

by Emma Richardson -
Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Plugin developers

real_user_attribute should be empty.

Are your groups within the ou that your ldap server is accessing?

In reply to Emma Richardson

Re: How to get a cohort being synchronised with a ldap server ?

by Guybrush Threepwood -

Hello,

I have the same behavior when real_user_attribute is empty.

Yes, the groups are in the sub OUs from the contexts defined in LDAP server settings.

In reply to Guybrush Threepwood

Re: How to get a cohort being synchronised with a ldap server ?

by Emma Richardson -
Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Plugin developers

Can you try one more time with attribute empty and process nested groups enabled?

I know when I am testing it is easy to bounce through settings and never quite try the right combination...

In reply to Emma Richardson

Re: How to get a cohort being synchronised with a ldap server ?

by Guybrush Threepwood -

Same behaviour (warning, no cohort created or pupulated) with the settings as below:


Attachment moodle.png
In reply to Guybrush Threepwood

Re: How to get a cohort being synchronised with a ldap server ?

by Emma Richardson -
Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Plugin developers

Any error message when you run it?  Does your bind user have the appropriate permissions on the groups/ou's containing groups?

In reply to Guybrush Threepwood

Re: How to get a cohort being synchronised with a ldap server ?

by Guybrush Threepwood -

Hi,

with the new version of the plugin as of today (2018050400), the output is slighty different:

Execute scheduled task: Synchronize cohorts from LDAP groups (local_ldap\task\group_sync_task)
... started 12:56:49. Current memory use 6.2Mo.
... used 1358 dbqueries
... used 48.352494955063 seconds
Scheduled task complete: Synchronize cohorts from LDAP groups (local_ldap\task\group_sync_task)

But the result is still the same: no cohort is created (or even synchronized for existing correlating one).


If I run the script using --showsql parameter, I can see that it is enumerating the different AD Groups:

SELECT * FROM mdl_cohort WHERE idnumber = ?
[array (
  0 => 'GGM_S2M_ET_Classes_2HMI',
)]
--------------------------------
Query took: 0.0034809112548828 seconds.


What is going wrong?

In reply to Guybrush Threepwood

Re: How to get a cohort being synchronised with a ldap server ?

by Emma Richardson -
Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Plugin developers

So you have never got it working?

Did you check the bind user permissions as suggested before?

In reply to Emma Richardson

Re: How to get a cohort being synchronised with a ldap server ?

by Guybrush Threepwood -

No, it never worked.

The bind user has the good permissions, as LDAP users synchronization and authentication is working.

Furthermore, the cohort script output is showing the groups... but not creating cohorts as requested.

In reply to Emma Richardson

Re: How to get a cohort being synchronised with a ldap server ?

by Guybrush Threepwood -

I tried to synchronize a cohort with a group using LDAP Attribute instead of Groupe membership and it worked. The existing cohort has been correctly populated. However using an attribute is not a good option for me...

In reply to Guybrush Threepwood

Re: How to get a cohort being synchronised with a ldap server ?

by Marlise Nauer -

Hi, i have the same problem like Guybrush

What can we check more, thanks for ideaswink

Best regards

Marlise

In reply to Guybrush Threepwood

Re: How to get a cohort being synchronised with a ldap server ?

by Visvanath Ratnaweera -
Picture of Particularly helpful Moodlers Picture of Translators
Guybrush Threepwood wrote:
> I tried to synchronize a cohort with a group using LDAP Attribute instead of Groupe membership and it worked. The existing cohort has been correctly populated. However using an attribute is not a good option for me...

I can confirm. There is a bug. See https://moodle.org/mod/forum/discuss.php?d=378935.

Moodle 3.5.3+ (Build: 20181116)
LDAP syncing scripts: v3.4.1 (2018090700)
In reply to Guybrush Threepwood

Re: How to get a cohort being synchronised with a ldap server ?

by Charles Fulton -
Picture of Core developers Picture of Plugin developers Picture of Testers

I've identified and fixed a couple bugs in the Active Directory code related to pagination. I can't say for sure that these changes will resolve the issues folks are seeing, but they might. The code is available here: https://github.com/LafColITS/moodle-local_ldap/releases/tag/v3.4.1-rc.1. I'd love to hear from folks on Active Directory before I publish a formal release.

Thanks,

Charles

In reply to Charles Fulton

Re: How to get a cohort being synchronised with a ldap server ?

by Guybrush Threepwood -

Hello Charles,

I tried the new version of the plugin (2018090700), but the cohort are not synchronised.

I can see that the task iterates the groups well:

--------------------------------
SELECT * FROM mdl_cohort WHERE idnumber = ?
[array (
  0 => 'GGM_S2L_EAM_Utilisateurs_Eleves_1COIB',
)]
--------------------------------
Query took: 0.00063800811767578 seconds.
--------------------------------

but the cohort isn't created.

In the case of an existing cohort, the group members are not added to the cohort:

--------------------------------
SELECT * FROM mdl_cohort WHERE idnumber = ?
[array (
  0 => 'GGM_S2L_EAM_Utilisateurs_Eleves_2COIA',
)]
--------------------------------
Query took: 0.00070786476135254 seconds.
--------------------------------
--------------------------------
 SELECT u.id,u.username
                          FROM mdl_user u
                         JOIN mdl_cohort_members cm ON (cm.userid = u.id AND cm.cohortid = ?)
                        WHERE u.deleted=0
[array (
  0 => '40',
)]
--------------------------------
Query took: 0.00065398216247559 seconds.
--------------------------------

Best regards

In reply to Charles Fulton

Re: How to get a cohort being synchronised with a ldap server ?

by Guybrush Threepwood -

Hi!


Reading Visvanath Ratnaweera's deep dive (https://moodle.org/mod/forum/discuss.php?d=378935), it helped me to point what was wrong in my configuration: in my Moodle auth_ldap configuration, memberattribute was empty. I set it to "member" and now cohorts are created in populated correctly.

Now I want to have the "displayName" attribute of the groupe to be used instead of the name (CN).

The plugin dot now allow to change this unfortunately.

Looking into the code, it looks like the name of the group is specified on line 163 in localib.php:

array_push($fresult, ($groups[$i][$this->config->group_attribute][0]));


How to replace "groupe_attribute", that is CN, with the "displayName" attribute?

In reply to Guybrush Threepwood

Re: How to get a cohort being synchronised with a ldap server ?

by Guybrush Threepwood -

I managed the change in code to use the DisplayName (if set) of a group instead of the CN.

In locallib.php.

In function ldap_get_grouplist

line 148:

$ldapresult = ldap_search($ldapconnection, $context, $filter, array ($this->config->group_attribute));

becomes

$ldapresult = ldap_search($ldapconnection, $context, $filter, array ($this->config->group_attribute, "displayName"));


line 151:

$ldapresult = ldap_list($ldapconnection, $context, $filter, array ($this->config->group_attribute));

becomes

$ldapresult = ldap_list($ldapconnection, $context, $filter, array ($this->config->group_attribute, "displayName"));


line 162:

array_push($fresult, ($groups[$i][$this->config->group_attribute][0]));

becomes

array_push($fresult, ($groups[$i]));


in function sync_cohorts_by_group

replace line 639:

foreach ($ldapgroups as $groupname) {

with

foreach ($ldapgroups as $ldapgroup) {
   $groupname = $ldapgroup[$this->config->group_attribute][0];
   if($ldapgroup["displayname"][0]===NULL){
    $displayName = $groupname;
   }
   else{
    $displayName = $ldapgroup["displayname"][0];
   }

could be improved with the use of a variable for the displayname of the cohort...

Average of ratings:Useful (1)