Skip to content

Commit

Permalink
Merge pull request #9 from nyx-ei/feature/gestion-des-permissions
Browse files Browse the repository at this point in the history
Feature/gestion des permissions
  • Loading branch information
karimalik authored Aug 16, 2024
2 parents 9220f89 + 90b2b48 commit 865ef2e
Show file tree
Hide file tree
Showing 13 changed files with 564 additions and 360 deletions.
37 changes: 37 additions & 0 deletions auth/nyxei/admin_ui.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

/**
* User interface for mappings
*
* @package auth_nyxei
* @copyright 2024 Nyx-EI {@link https://nyx-ei.tech}
* @author NYX-EI <help@nyx-ei.tech>
*/

require_once('../../config.php');

require_login();
admin_externalpage_setup('auth_nyxei_settings');

if (!has_capability('moodle/site:config', context_system::instance())) {
print_error('nopermissions', 'error', '', 'access this page');
}

if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['ad_group_role_mappings'])) {
$mappings = trim($_POST['ad_group_role_mappings']);
set_config('ad_group_role_mappings', $mappings, 'auth_nyxei');
echo '<div class="alert alert-success">Mappings saved successfully!</div>';
}

echo $OUTPUT->header();
echo '<h2>' . get_string('ad_group_role_mappings', 'auth_nyxei') . '</h2>';

$current_mappings = get_config('auth_nyxei', 'ad_group_role_mappings');
echo '<form method="post">';
echo '<textarea name="ad_group_role_mappings" rows="10" cols="50">' . s($current_mappings) . '</textarea>';
echo '<br><br>';
echo '<input type="submit" value="' . get_string('savechanges') . '" class="btn btn-primary">';
echo '</form>';

// Affiche le pied de page
echo $OUTPUT->footer();
154 changes: 113 additions & 41 deletions auth/nyxei/auth.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
<?php

//TODO: Synchronisation des utilisateurs AD et Moodle
//TODO: Gestion des permissions d'utilisateur via AD


/**
* Active directory Authentification plugin
Expand All @@ -16,21 +13,34 @@
*/

defined('MOODLE_INTERNAL') || die();
global $CFG;

// use core\context_system;

require_once($CFG->libdir .'/setuplib.php');
require_once($CFG->libdir . '/moodlelib.php');
// require_once($CFG->libdir . '/lib/contextlib.php');

class auth_plugin_nyxei extends auth_plugin_base
{

class auth_plugin_nyxei extends auth_plugin_base {
const LDAP_PROTOCOL_VERSION = 3;
const LDAP_PORT = 636;
const LDAP_REFERRALS = 0;
const LOGIN_ATTEMPTS = 3;

public function __construct() {
public function __construct()
{
$this->authtype = 'nyxei';
$this->config = get_config('auth_nyxei');
}

public function user_login($username, $password) {
public function user_login($username, $password)
{
// global $DB;

$ldap_host = $this->config->host;
$ldap_port = 636;
$ldap_port = self::LDAP_PORT;

$ldap_connection = ldap_connect("ldaps://{$ldap_host}", $ldap_port);

Expand All @@ -40,17 +50,17 @@ public function user_login($username, $password) {
return false;
}

ldap_set_option($ldap_connection, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldap_connection, LDAP_OPT_REFERRALS, 0);
ldap_set_option($ldap_connection, LDAP_OPT_PROTOCOL_VERSION, self::LDAP_PROTOCOL_VERSION);
ldap_set_option($ldap_connection, LDAP_OPT_REFERRALS, self::LDAP_REFERRALS);

$ldap_bind = @ldap_bind($ldap_connection, $username, $password);

if ($ldap_bind) {
ldap_unbind($ldap_connection);
$this->close_ldap_connection($ldap_connection);
return true;
}else {
} else {
$this->failed_login_log($username, 'Invalid Credentials');
ldap_unbind($ldap_connection);
$this->close_ldap_connection($ldap_connection);
return false;
}
}
Expand Down Expand Up @@ -78,17 +88,17 @@ public function process_config($config)
}

if (empty($config->login_attempts)) {
$config->login_attempts = 3; // default value

$config->login_attempts = self::LOGIN_ATTEMPTS; // default value
}

if (empty($config->bind_user)) {

$config->bind_user = '';
}

if (empty($config->bind_password)) {

$config->bind_password = '';
}

Expand All @@ -100,7 +110,7 @@ public function process_config($config)
return true;
}

//save attempts login
//save attempts login
private function failed_login_log($username, $error)
{
global $DB;
Expand All @@ -123,7 +133,7 @@ private function check_failed_attempts($username)
$attempt_count = count($attempts);

if ($attempt_count >= $this->config->login_attempts) {

$this->send_admin_notification($username, $attempt_count);
}
}
Expand All @@ -139,49 +149,50 @@ private function send_admin_notification($username, $attempt_count)
email_to_user($admin, $admin, $subject, $message);
}

public function sync_users() {
public function sync_users()
{
global $DB, $CFG;

$ldap_host = $this->config->host;
$ldap_port = 636;
$ldap_port = self::LDAP_PORT;
$bind_user = $this->config->bind_user;
$bind_password = $this->config->bind_password;

$ldap_connection = ldap_connect("ldaps://{$ldap_host}", $ldap_port);

if (!$ldap_connection) {
error_log('Could not connect to LDAP server.');
return false;
}
ldap_set_option($ldap_connection, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldap_connection, LDAP_OPT_REFERRALS, 0);

ldap_set_option($ldap_connection, LDAP_OPT_PROTOCOL_VERSION, self::LDAP_PROTOCOL_VERSION);
ldap_set_option($ldap_connection, LDAP_OPT_REFERRALS, self::LDAP_REFERRALS);

$ldap_bind = ldap_bind($ldap_connection, $bind_user, $bind_password);

if (!$ldap_bind) {
$error = ldap_error($ldap_connection);
ldap_unbind($ldap_connection);
$this->close_ldap_connection($ldap_connection);
error_log("Could not bind to LDAP server: $error.");
return false;
}

$search = ldap_search($ldap_connection, "dc=nyx-ei,dc=tech", "(objectClass=*)");
$entries = ldap_get_entries($ldap_connection, $search);

if ($entries === false) {
$error = ldap_error($ldap_connection);
ldap_unbind($ldap_connection);
$this->close_ldap_connection($ldap_connection);
error_log("LDAP search failed: $error.");
return false;
}

$ad_usernames = [];
foreach ($entries as $entry) {
if (!empty($entry['samaccountname'][0])) {
$username = $entry['samaccountname'][0];
$ad_usernames[] = $username;

if (!$DB->record_exists('user', ['username' => $username])) {
$user = new stdClass();
$user->username = $username;
Expand All @@ -191,28 +202,89 @@ public function sync_users() {
$user->auth = 'auth_nyxei';
$user->confirmed = 1;
$user->mnethostid = $CFG->mnet_localhost_id;

$DB->insert_record('user', $user);
}

if (isset($entry['useraccountcontrol'][0]) && ($entry['useraccountcontrol'][0] & 2)) {
$user = $DB->get_record('user', ['username' => $username]);
$user->suspended = 1;
$DB->update_record('user', $user);
}
}
}

$users = $DB->get_records('user', ['auth' => 'auth_nyxei']);
foreach ($users as $user) {
if (!in_array($user->username, $ad_usernames)) {
$user->suspended = 1;
$DB->update_record('user', $user);
}
}

ldap_unbind($ldap_connection);

$this->close_ldap_connection($ldap_connection);
return true;
}

public function sync_ad_groups_to_roles()
{
global $DB;


$mappings = explode("\n", $this->config->ad_group_role_mappings);
$mappings = array_filter(array_map('trim', $mappings));


$ldap_connection = ldap_connect($this->config->host);
ldap_set_option($ldap_connection, LDAP_OPT_PROTOCOL_VERSION, self::LDAP_PROTOCOL_VERSION);
ldap_set_option($ldap_connection, LDAP_OPT_REFERRALS, self::LDAP_REFERRALS);
ldap_start_tls($ldap_connection);

if (!ldap_bind($ldap_connection, $this->config->bind_user, $this->config->bind_password)) {
throw new \moodle_exception('ldapbinderror', 'auth_nyxei');
}

foreach ($mappings as $mapping) {
list($ad_group, $moodle_role) = explode(':', $mapping);

$search = ldap_search($ldap_connection, "dc=nyx-ei,dc=tech", "(memberOf=cn=$ad_group,dc=nyx-ei,dc=tech)");
$entries = ldap_get_entries($ldap_connection, $search);

if ($entries['count'] > 0) {

$roleid = $DB->get_field('role', 'id', ['shortname' => $moodle_role]);

if ($roleid) {
foreach ($entries as $entry) {
if (isset($entry['samaccountname'][0])) {
$username = $entry['samaccountname'][0];
$user = $DB->get_record('user', ['username' => $username]);

if ($user) {

role_assign($roleid, $user->id, context_system::instance());
}
}
}
} else {
error_log("Le rôle Moodle '$moodle_role' n'existe pas.");
}
}
}

$this->close_ldap_connection($ldap_connection);
return true;
}

}


/**
* Closes the LDAP connection.
*
* @param $ldap_connection
* @return void
*/
private function close_ldap_connection($ldap_connection)
{
ldap_unbind($ldap_connection);
}
}
32 changes: 32 additions & 0 deletions auth/nyxei/classes/task/sync_ad_groups.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/**
* A scheduled task for AD groups roles sync.
*
* @package auth_nyxei
* @author NYX-EI <help@nyx-ei.tech>
* @copyright 2024 Nyx-EI <help@nyx-ei.tech>
*/

namespace auth_nyxei\task;

global $CFG;

defined('MOODLE_INTERNAL') || die();


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

class sync_ad_groups extends \core\task\scheduled_task {

public function get_name()
{
return get_string('sync_ad_groups', 'auth_nyxei');
}

public function execute() {
$auth = get_auth_plugin('nyxei');
$auth->sync_ad_groups_to_roles();
}
}

4 changes: 3 additions & 1 deletion auth/nyxei/classes/task/sync_users.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
* @copyright 2024 Nyx-EI <help@nyx-ei.tech>
*/

namespace auth_nyxei\task;
namespace nyxei\task;

global $CFG;

defined('MOODLE_INTERNAL') || die();

Expand Down
8 changes: 4 additions & 4 deletions auth/nyxei/db/install.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" enconding="utf-8"?>
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="auth/nyxei/db" VERSION="2024071800" COMMENT="XMLDB file for auth_nyxei">
<TABLE>
<TABLES>
<TABLE NAME="auth_nyxei_failed_logins" COMMENT="Table to store failed login">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
Expand All @@ -12,5 +12,5 @@
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
</KEYS>
</TABLE>
</TABLE>
</XMLDB>
</TABLES>
</XMLDB>
13 changes: 11 additions & 2 deletions auth/nyxei/db/tasks.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,18 @@
'blocking' => 0,
'minute' => '*/30',
'hour' => '*',
'dayofmonth' => '*',
'day' => '*',
'month' => '*',
'dayofweek' => '*',
),

array(
'classname' => 'auth_nyxei\task\sync_ad_groups',
'blocking' => 0,
'minute' => '*/30',
'hour' => '*/6',
'day' => '*',
'month' => '*',
'wday' => '*'
'dayofweek' => '*',
)
);
Loading

0 comments on commit 865ef2e

Please sign in to comment.