Skip to content

Commit

Permalink
MDL-62253 core_auth: Implement privacy API
Browse files Browse the repository at this point in the history
  • Loading branch information
FMCorz committed May 1, 2018
1 parent af099b4 commit 1582d54
Show file tree
Hide file tree
Showing 3 changed files with 214 additions and 0 deletions.
103 changes: 103 additions & 0 deletions auth/classes/privacy/provider.php
@@ -0,0 +1,103 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

/**
* Data provider.
*
* @package core_auth
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

namespace core_auth\privacy;
defined('MOODLE_INTERNAL') || die();

use context;
use core_privacy\local\metadata\collection;
use core_privacy\local\request\transform;
use core_privacy\local\request\writer;

/**
* Data provider class.
*
* @package core_auth
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements
\core_privacy\local\metadata\provider,
\core_privacy\local\request\user_preference_provider {

/**
* Returns metadata.
*
* @param collection $collection The initialised collection to add items to.
* @return collection A listing of user data stored through this system.
*/
public static function get_metadata(collection $collection) : collection {

$collection->add_user_preference('auth_forcepasswordchange', 'privacy:metadata:userpref:forcepasswordchange');
$collection->add_user_preference('create_password', 'privacy:metadata:userpref:createpassword');
$collection->add_user_preference('login_failed_count', 'privacy:metadata:userpref:loginfailedcount');
$collection->add_user_preference('login_failed_count_since_success',
'privacy:metadata:userpref:loginfailedcountsincesuccess');
$collection->add_user_preference('login_failed_last', 'privacy:metadata:userpref:loginfailedlast');
$collection->add_user_preference('login_lockout', 'privacy:metadata:userpref:loginlockout');
$collection->add_user_preference('login_lockout_ignored', 'privacy:metadata:userpref:loginlockoutignored');
$collection->add_user_preference('login_lockout_secret', 'privacy:metadata:userpref:loginlockoutsecret');

return $collection;
}

/**
* Export all user preferences for the plugin.
*
* @param int $userid The userid of the user whose data is to be exported.
*/
public static function export_user_preferences(int $userid) {

$yesno = function($v) {
return transform::yesno($v);
};
$datetime = function($v) {
return $v ? transform::datetime($v) : null;
};

$prefs = [
['auth_forcepasswordchange', 'forcepasswordchange', $yesno],
['create_password', 'createpassword', $yesno],
['login_failed_count', 'loginfailedcount', null],
['login_failed_count_since_success', 'loginfailedcountsincesuccess', null],
['login_failed_last', 'loginfailedlast', $datetime],
['login_lockout', 'loginlockout', $datetime],
['login_lockout_ignored', 'loginlockoutignored', $yesno],
['login_lockout_secret', 'loginlockoutsecret', null],
];

foreach ($prefs as $prefdata) {
list($prefname, $langkey, $transformer) = $prefdata;
$value = get_user_preferences($prefname, null, $userid);
if ($value === null) {
continue;
}
writer::export_user_preference('core_auth', $prefname, $transformer ? $transformer($value) : $value,
get_string("privacy:metadata:userpref:{$langkey}", 'core_auth'));
}
}

}
103 changes: 103 additions & 0 deletions auth/tests/privacy_test.php
@@ -0,0 +1,103 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

/**
* Data provider tests.
*
* @package core_auth
* @category test
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

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

use core_privacy\tests\provider_testcase;
use core_privacy\local\request\transform;
use core_privacy\local\request\writer;
use core_auth\privacy\provider;

/**
* Data provider testcase class.
*
* @package core_auth
* @category test
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class core_auth_privacy_testcase extends provider_testcase {

public function setUp() {
$this->resetAfterTest();
}

public function test_export_user_preferences() {
$dg = $this->getDataGenerator();
$u1 = $dg->create_user();
$u2 = $dg->create_user();
$sysctx = context_system::instance();
$now = time();

// Check nothing is there.
writer::reset();
provider::export_user_preferences($u1->id);
$prefs = writer::with_context($sysctx)->get_user_preferences('core_auth');
$this->assertEmpty((array) $prefs);

// Set some preferences.
set_user_preference('auth_forcepasswordchange', 1, $u1);
set_user_preference('create_password', 1, $u1);
set_user_preference('login_failed_count', 18, $u1);
set_user_preference('login_failed_count_since_success', 7, $u1);
set_user_preference('login_failed_last', $now - DAYSECS, $u1);
set_user_preference('login_lockout', $now - HOURSECS, $u1);
set_user_preference('login_lockout_ignored', 0, $u1);
set_user_preference('login_lockout_secret', 'Hello world!', $u1);

set_user_preference('auth_forcepasswordchange', 0, $u2);
set_user_preference('create_password', 0, $u2);
set_user_preference('login_lockout_ignored', 1, $u2);

// Check user 1.
writer::reset();
provider::export_user_preferences($u1->id);
$prefs = writer::with_context($sysctx)->get_user_preferences('core_auth');
$this->assertEquals(transform::yesno(true), $prefs->auth_forcepasswordchange->value);
$this->assertEquals(transform::yesno(true), $prefs->create_password->value);
$this->assertEquals(18, $prefs->login_failed_count->value);
$this->assertEquals(7, $prefs->login_failed_count_since_success->value);
$this->assertEquals(transform::datetime($now - DAYSECS), $prefs->login_failed_last->value);
$this->assertEquals(transform::datetime($now - HOURSECS), $prefs->login_lockout->value);
$this->assertEquals(transform::yesno(false), $prefs->login_lockout_ignored->value);
$this->assertEquals('Hello world!', $prefs->login_lockout_secret->value);

// Check user 2.
writer::reset();
provider::export_user_preferences($u2->id);
$prefs = writer::with_context($sysctx)->get_user_preferences('core_auth');
$this->assertEquals(transform::yesno(false), $prefs->auth_forcepasswordchange->value);
$this->assertEquals(transform::yesno(false), $prefs->create_password->value);
$this->assertObjectNotHasAttribute('login_failed_count', $prefs);
$this->assertObjectNotHasAttribute('login_failed_count_since_success', $prefs);
$this->assertObjectNotHasAttribute('login_failed_last', $prefs);
$this->assertObjectNotHasAttribute('login_lockout', $prefs);
$this->assertEquals(transform::yesno(true), $prefs->login_lockout_ignored->value);
$this->assertObjectNotHasAttribute('login_lockout_secret', $prefs);
}
}
8 changes: 8 additions & 0 deletions lang/en/auth.php
Expand Up @@ -138,6 +138,14 @@
$string['plaintext'] = 'Plain text';
$string['pluginnotenabled'] = 'Authentication plugin \'{$a}\' is not enabled.';
$string['pluginnotinstalled'] = 'Authentication plugin \'{$a}\' is not installed.';
$string['privacy:metadata:userpref:createpassword'] = 'Indicates that a password should be generated for the user';
$string['privacy:metadata:userpref:forcepasswordchange'] = 'Indicates whether the user should change their password upon logging in';
$string['privacy:metadata:userpref:loginfailedcount'] = 'The number of times the user failed to log in';
$string['privacy:metadata:userpref:loginfailedcountsincesuccess'] = 'The number of times the user failed to login since their last successful login';
$string['privacy:metadata:userpref:loginfailedlast'] = 'The date at which the last failed login attempt was recorded';
$string['privacy:metadata:userpref:loginlockout'] = 'Indicates whether the user\'s account is locked due to failed login attempts, and the date at which the account entered the lockout state';
$string['privacy:metadata:userpref:loginlockoutignored'] = 'Indicates that a user\'s account should never be subject to lockouts';
$string['privacy:metadata:userpref:loginlockoutsecret'] = 'When locked, the secret the user must use for unlocking their account';
$string['potentialidps'] = 'Log in using your account on:';
$string['recaptcha'] = 'reCAPTCHA';
$string['recaptcha_help'] = 'The CAPTCHA is for preventing abuse from automated programs. Follow the instructions to verify you are a person. This could be a box to check, characters presented in an image you must enter or a set of images to select from.
Expand Down

0 comments on commit 1582d54

Please sign in to comment.