Skip to content

Commit

Permalink
MDL-80599 enrol_guest: Support password update in csv course upload
Browse files Browse the repository at this point in the history
  • Loading branch information
ilyatregubov committed May 9, 2024
1 parent b14e29b commit a694e6d
Show file tree
Hide file tree
Showing 4 changed files with 225 additions and 0 deletions.
104 changes: 104 additions & 0 deletions admin/tool/uploadcourse/tests/behat/guest.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
@tool @tool_uploadcourse @_file_upload
Feature: An admin can create courses with guest enrolments using a CSV file
In order to create courses using a CSV file with guest enrolment
As an admin
I need to be able to upload a CSV file and navigate through the import process

Background:
Given the following "categories" exist:
| name | category | idnumber |
| Cat 0 | 0 | CAT0 |
| Cat 1 | CAT0 | CAT1 |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | CAT1 |
And I log in as "admin"
And I navigate to "Courses > Upload courses" in site administration
And I set the field "Upload mode" to "Create new courses, or update existing ones"
And I set the field "Update mode" to "Update with CSV data only"

@javascript
Scenario: Validation of password for uploaded courses with guest enrolments
# usepasswordpolicy is not set.
Given I upload "admin/tool/uploadcourse/tests/fixtures/enrolment_guest.csv" file to "File" filemanager
And I click on "Preview" "button"
And I click on "Upload courses" "button"
And I should see "Courses created: 2"
And I should see "Courses updated: 1"
And I should see "Courses errors: 0"
And I am on the "Course 1" "enrolment methods" page
And I click on "Edit" "link" in the "Guest access" "table_row"
And the field "Password" matches value "test"
And I press "Cancel"
And I click on "Delete" "link" in the "Guest access" "table_row"
And I press "Continue"
And I am on the "Course 2" "enrolment methods" page
And I click on "Edit" "link" in the "Guest access" "table_row"
And the field "Password" matches value ""
And I press "Cancel"
And I click on "Delete" "link" in the "Guest access" "table_row"
And I press "Continue"
And I am on the "Course 3" "enrolment methods" page
And I click on "Edit" "link" in the "Guest access" "table_row"
And the field "Password" matches value "Test123@"
And I press "Cancel"
And I click on "Delete" "link" in the "Guest access" "table_row"
And I press "Continue"

# Policy is used, but password not required so it will not be generated if omitted.
And the following config values are set as admin:
| config | value | plugin |
| usepasswordpolicy | 1 | enrol_guest |
And I navigate to "Courses > Upload courses" in site administration
And I set the field "Upload mode" to "Create new courses, or update existing ones"
And I set the field "Update mode" to "Update with CSV data only"
And I upload "admin/tool/uploadcourse/tests/fixtures/enrolment_guest.csv" file to "File" filemanager
And I click on "Preview" "button"
And I should see "Passwords must be at least 8 characters long."
And I should see "Passwords must have at least 1 digit(s)."
And I should see "Passwords must have at least 1 upper case letter(s)."
And I should see "The password must have at least 1 special character(s) such as *, -, or #."
And I click on "Upload courses" "button"
And I should see "Courses created: 0"
And I should see "Courses updated: 2"
And I should see "Courses errors: 1"
And I am on the "Course 1" "enrolment methods" page
And "Guest access" "table_row" should not exist
And I am on the "Course 2" "enrolment methods" page
And I click on "Edit" "link" in the "Guest access" "table_row"
And the field "Password" matches value ""
And I press "Cancel"
And I click on "Delete" "link" in the "Guest access" "table_row"
And I press "Continue"
And I am on the "Course 3" "enrolment methods" page
And I click on "Edit" "link" in the "Guest access" "table_row"
And the field "Password" matches value "Test123@"
And I press "Cancel"
And I click on "Delete" "link" in the "Guest access" "table_row"
And I press "Continue"

# Policy is used and password not required so it will be generated if omitted.
And the following config values are set as admin:
| config | value | plugin |
| requirepassword | 1 | enrol_guest |
And I navigate to "Courses > Upload courses" in site administration
And I set the field "Upload mode" to "Create new courses, or update existing ones"
And I set the field "Update mode" to "Update with CSV data only"
And I upload "admin/tool/uploadcourse/tests/fixtures/enrolment_guest.csv" file to "File" filemanager
And I click on "Preview" "button"
And I should see "Passwords must be at least 8 characters long."
And I should see "Passwords must have at least 1 digit(s)."
And I should see "Passwords must have at least 1 upper case letter(s)."
And I should see "The password must have at least 1 special character(s) such as *, -, or #."
And I click on "Upload courses" "button"
And I should see "Courses created: 0"
And I should see "Courses updated: 2"
And I should see "Courses errors: 1"
And I am on the "Course 1" "enrolment methods" page
And "Guest access" "table_row" should not exist
And I am on the "Course 2" "enrolment methods" page
And I click on "Edit" "link" in the "Guest access" "table_row"
And the field "Password" does not match value ""
And I am on the "Course 3" "enrolment methods" page
And I click on "Edit" "link" in the "Guest access" "table_row"
And the field "Password" matches value "Test123@"
4 changes: 4 additions & 0 deletions admin/tool/uploadcourse/tests/fixtures/enrolment_guest.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
shortname,fullname,category_idnumber,enrolment_1,enrolment_1_role,enrolment_1_password
C1,Course 1,CAT1,guest,student,test
C2,Course 2,CAT1,guest,student,
C3,Course 3,CAT1,guest,student,Test123@
43 changes: 43 additions & 0 deletions enrol/guest/lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,49 @@ public function find_instance(array $enrolmentdata, int $courseid): ?stdClass {
public function fill_enrol_custom_fields(array $enrolmentdata, int $courseid): array {
return $enrolmentdata + ['password' => ''];
}

/**
* Updates enrol plugin instance with provided data.
* @param int $courseid Course ID.
* @param array $enrolmentdata enrolment data.
* @param stdClass $instance Instance to update.
*
* @return stdClass updated instance
*/
public function update_enrol_plugin_data(int $courseid, array $enrolmentdata, stdClass $instance): stdClass {
if (!empty($enrolmentdata['password'])) {
$instance->password = $enrolmentdata['password'];
}
return parent::update_enrol_plugin_data($courseid, $enrolmentdata, $instance);
}

/**
* Check if data is valid for a given enrolment plugin
*
* @param array $enrolmentdata enrolment data to validate.
* @param int|null $courseid Course ID.
* @return array Errors
*/
public function validate_enrol_plugin_data(array $enrolmentdata, ?int $courseid = null): array {
global $CFG;

// If password is omitted or empty in csv it will be generated automatically if it is a required policy.

$errors = parent::validate_enrol_plugin_data($enrolmentdata, $courseid);

$policy = $this->get_config('usepasswordpolicy');
if (!empty($enrolmentdata['password']) && $policy) {
$errmsg = '';
$errarray = [];
if (!check_password_policy($enrolmentdata['password'], $errmsg, null, $errarray)) {
foreach ($errarray as $err) {
$passwordconfig = str_replace('error', '', $err);
$errors[$err] = new lang_string($err, 'auth', $CFG->$passwordconfig);
}
}
}
return $errors;
}
}

/**
Expand Down
74 changes: 74 additions & 0 deletions enrol/guest/tests/lib_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,80 @@

class lib_test extends \advanced_testcase {

/**
* Test the behaviour of validate_enrol_plugin_data().
*
* @covers ::validate_enrol_plugin_data
*/
public function test_validate_enrol_plugin_data(): void {
global $CFG;

$this->resetAfterTest();

$guestplugin = enrol_get_plugin('guest');

$guestplugin->set_config('usepasswordpolicy', false);
$enrolmentdata = [];
$errors = $guestplugin->validate_enrol_plugin_data($enrolmentdata);
$this->assertEmpty($errors);

// Now enable some controls, and check that the policy responds with policy text.
$guestplugin->set_config('usepasswordpolicy', true);
$CFG->minpasswordlength = 8;
$CFG->minpassworddigits = 1;
$CFG->minpasswordlower = 1;
$CFG->minpasswordupper = 1;
$CFG->minpasswordnonalphanum = 1;
$CFG->maxconsecutiveidentchars = 1;
$errors = $guestplugin->validate_enrol_plugin_data($enrolmentdata);
// If password is omitted it will be autocreated so nothing to validate.
$this->assertEmpty($errors);

$enrolmentdata = ['password' => 'test'];
$errors = $guestplugin->validate_enrol_plugin_data($enrolmentdata);
$this->assertArrayHasKey('errorminpasswordlength', $errors);
$this->assertArrayHasKey('errorminpassworddigits', $errors);
$this->assertArrayHasKey('errorminpasswordlength', $errors);
$this->assertArrayHasKey('errorminpasswordupper', $errors);
$this->assertArrayHasKey('errorminpasswordlength', $errors);
$this->assertArrayHasKey('errorminpasswordnonalphanum', $errors);
$this->assertArrayNotHasKey('errorminpasswordlower', $errors);
$this->assertArrayNotHasKey('errormaxconsecutiveidentchars', $errors);

$enrolmentdata = ['password' => 'Testingtest123@'];
$errors = $guestplugin->validate_enrol_plugin_data($enrolmentdata);
$this->assertEmpty($errors);
}

/**
* Test the behaviour of update_enrol_plugin_data().
*
* @covers ::update_enrol_plugin_data
*/
public function test_update_enrol_plugin_data(): void {
global $DB;
$this->resetAfterTest();
$manualplugin = enrol_get_plugin('guest');

$admin = get_admin();
$this->setUser($admin);

$enrolmentdata = [];

$cat = $this->getDataGenerator()->create_category();
$course = $this->getDataGenerator()->create_course(['category' => $cat->id, 'shortname' => 'ANON']);
$instance = $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'guest'], '*', MUST_EXIST);

$expectedinstance = $instance;
$modifiedinstance = $manualplugin->update_enrol_plugin_data($course->id, $enrolmentdata, $instance);
$this->assertEquals($expectedinstance, $modifiedinstance);

$enrolmentdata['password'] = 'test';
$expectedinstance->password = 'test';
$modifiedinstance = $manualplugin->update_enrol_plugin_data($course->id, $enrolmentdata, $instance);
$this->assertEquals($expectedinstance, $modifiedinstance);
}

/**
* Test the behaviour of find_instance().
*
Expand Down

0 comments on commit a694e6d

Please sign in to comment.