Merge branch 'wip-73317-m311' into MOODLE_311_STABLE

This commit is contained in:
Lai Wei 2021-10-20 15:31:02 +01:00
Родитель eb37d755f6 612c48010f
Коммит 3efed81792
8 изменённых файлов: 327 добавлений и 41 удалений

Просмотреть файл

@ -116,7 +116,7 @@ class auth_plugin_oidc extends \auth_plugin_base {
if (!empty($noredirect)) {
$oidc = 0;
}
if (!$this->config->forceredirect) {
if (!isset($this->config->forceredirect) || !$this->config->forceredirect) {
return false; // Never redirect if we haven't enabled the forceredirect setting
}
// Never redirect on POST.

Просмотреть файл

@ -33,15 +33,19 @@ defined('MOODLE_INTERNAL') || die();
* @package auth_oidc\adminsetting
*/
class auth_oidc_admin_setting_label extends admin_setting {
private $label;
/**
* auth_oidc_admin_setting_static constructor.
*
* @param $name
* @param $label
* @param $visiblename
* @param $description
*/
public function __construct($name, $visiblename, $description) {
public function __construct($name, $label, $visiblename, $description) {
parent::__construct($name, $visiblename, $description, '');
$this->label = $label;
}
/**
@ -73,6 +77,6 @@ class auth_oidc_admin_setting_label extends admin_setting {
* @return string
*/
public function output_html($data, $query = '') {
return format_admin_setting($this, get_string('cfg_tools', 'auth_oidc'), $this->visiblename, $this->description, false);
return format_admin_setting($this, $this->label, $this->visiblename, $this->description, false);
}
}

Просмотреть файл

@ -40,45 +40,14 @@ class base {
'opname' => get_string('pluginname', 'auth_oidc')
];
$storedconfig = (array)get_config('auth_oidc');
$forcedconfig = [
'field_updatelocal_idnumber' => 'oncreate',
'field_lock_idnumber' => 'unlocked',
'field_updatelocal_lang' => 'oncreate',
'field_lock_lang' => 'unlocked',
'field_updatelocal_firstname' => 'oncreate',
'field_lock_firstname' => 'unlocked',
'field_updatelocal_lastname' => 'oncreate',
'field_lock_lastname' => 'unlocked',
'field_updatelocal_email' => 'oncreate',
'field_lock_email' => 'unlocked',
];
// If local_o365 plugin is installed, use its settings for the core fields.
if (auth_oidc_is_local_365_installed()) {
$fieldmaps = get_config('local_o365', 'fieldmap');
if ($fieldmaps === false) {
$fieldmaps = \local_o365\adminsetting\usersyncfieldmap::defaultmap();
} else {
$fieldmaps = @unserialize($fieldmaps);
if (!is_array($fieldmaps)) {
$fieldmaps = \local_o365\adminsetting\usersyncfieldmap::defaultmap();
}
}
foreach ($fieldmaps as $fieldmap) {
$fieldmap = explode('/', $fieldmap);
if (count($fieldmap) !== 3) {
continue;
}
list($remotefield, $localfield, $behavior) = $fieldmap;
if (in_array($behavior, ['onlogin', 'always'])) {
$forcedconfig['field_updatelocal_' . $localfield] = 'onlogin';
$forcedconfig['field_lock_' . $localfield] = 'unlocked';
}
foreach ($storedconfig as $configname => $configvalue) {
if (strpos($configname, 'field_updatelocal_') === 0 && $configvalue == 'always') {
$storedconfig[$configname] = 'onlogin';
}
}
$this->config = (object)array_merge($default, $storedconfig, $forcedconfig);
$this->config = (object)array_merge($default, $storedconfig);
}
/**

Просмотреть файл

@ -263,5 +263,50 @@ function xmldb_auth_oidc_upgrade($oldversion) {
upgrade_plugin_savepoint(true, 2020110903, 'auth', 'oidc');
}
if ($oldversion < 2021051701) {
// Migrate field mapping settings from local_o365.
$existingfieldmappingsettings = get_config('local_o365', 'fieldmap');
if ($existingfieldmappingsettings !== false) {
$userfields = auth_oidc_get_all_user_fields();
$existingfieldmappingsettings = @unserialize($existingfieldmappingsettings);
if (is_array($existingfieldmappingsettings)) {
foreach ($existingfieldmappingsettings as $existingfieldmappingsetting) {
$fieldmap = explode('/', $existingfieldmappingsetting);
if (count($fieldmap) !== 3) {
// Invalid settings, ignore.
continue;
}
list($remotefield, $localfield, $behaviour) = $fieldmap;
if ($remotefield == 'facsimileTelephoneNumber') {
$remotefield = 'faxNumber';
}
set_config('field_map_' . $localfield, $remotefield, 'auth_oidc');
set_config('field_lock_' . $localfield, 'unlocked', 'auth_oidc');
set_config('field_updatelocal_' . $localfield, $behaviour, 'auth_oidc');
if (($key = array_search($localfield, $userfields)) !== false) {
unset($userfields[$key]);
}
}
foreach ($userfields as $userfield) {
set_config('field_map_' . $userfield, '', 'auth_oidc');
set_config('field_lock_' . $userfield, 'unlocked', 'auth_oidc');
set_config('field_updatelocal_' . $userfield, 'always', 'auth_oidc');
}
}
unset_config('fieldmap', 'local_o365');
}
// Oidc savepoint reached.
upgrade_plugin_savepoint(true, 2021051701, 'auth', 'oidc');
}
return $result;
}

Просмотреть файл

@ -94,6 +94,11 @@ $string['cfg_logoutendpoint_desc'] = 'The URI of the logout endpoint from your i
$string['cfg_tools'] = 'Tools';
$string['cfg_cleanupoidctokens_key'] = 'Cleanup OpenID Connect Tokens';
$string['cfg_cleanupoidctokens_desc'] = 'If your users are experiencing problems logging in using their Microsoft 365 account, trying cleaning up OpenID Connect tokens. This removes stray and incomplete tokens that can cause errors. WARNING: This may interrupt logins in-process, so it\'s best to do this during downtime.';
$string['cfg_field_mapping_desc'] = 'User profile data can be mapped from Open ID Connect identity providers (IdP) to Moodle.<br/>
<ul>
<li>Basic profile data is available from ID tokens from all IdP.</li>
<li>If Azure AD is used as the IdP, additional profile data can be made available by installing and configuring the <a href="https://moodle.org/plugins/local_o365">Microsoft 365 integration plugin (local_o365)</a>.</li>
</ul>';
$string['event_debug'] = 'Debug message';
@ -181,6 +186,7 @@ $string['ucp_disconnect_details'] = 'This will disconnect your Moodle account fr
$string['ucp_title'] = '{$a} Management';
$string['ucp_o365accountconnected'] = 'This Microsoft 365 account is already connected with another Moodle account.';
// Clean up OIDC tokens.
$string['cleanup_oidc_tokens'] = 'Cleanup OpenID Connect tokens';
$string['unmatched'] = 'Unmatched';
$string['delete_token'] = 'Delete token';
@ -198,3 +204,39 @@ $string['token_deleted'] = 'Token was deleted successfully';
$string['no_token_to_cleanup'] = 'There are no OIDC token to cleanup.';
$string['errorusermatched'] = 'The Microsoft 365 account "{$a->aadupn}" is already matched with Moodle user "{$a->username}". To complete the connection, please log in as that Moodle user first and follow the instructions in the Microsoft block.';
// User mapping options.
$string['update_oncreate_and_onlogin'] = 'On creation and every login';
$string['update_oncreate_and_onlogin_and_usersync'] = 'On creation, every login, and every user sync task run';
$string['update_onlogin_and_usersync'] = 'On every login and every user sync task run';
// Remote fields.
$string['settings_fieldmap_feild_not_mapped'] = '(not mapped)';
$string['settings_fieldmap_field_city'] = 'City';
$string['settings_fieldmap_field_companyName'] = 'Company Name';
$string['settings_fieldmap_field_objectId'] = 'Object ID';
$string['settings_fieldmap_field_country'] = 'Country';
$string['settings_fieldmap_field_department'] = 'Department';
$string['settings_fieldmap_field_displayName'] = 'Display Name';
$string['settings_fieldmap_field_surname'] = 'Surname';
$string['settings_fieldmap_field_faxNumber'] = 'Fax Number';
$string['settings_fieldmap_field_telephoneNumber'] = 'Telephone Number';
$string['settings_fieldmap_field_givenName'] = 'Given Name';
$string['settings_fieldmap_field_jobTitle'] = 'Job Title';
$string['settings_fieldmap_field_mail'] = 'Email';
$string['settings_fieldmap_field_mobile'] = 'Mobile';
$string['settings_fieldmap_field_postalCode'] = 'Postal Code';
$string['settings_fieldmap_field_preferredLanguage'] = 'Language';
$string['settings_fieldmap_field_state'] = 'State';
$string['settings_fieldmap_field_streetAddress'] = 'Street Address';
$string['settings_fieldmap_field_userPrincipalName'] = 'Username (UPN)';
$string['settings_fieldmap_field_employeeId'] = 'Employee ID';
$string['settings_fieldmap_field_businessPhones'] = 'Office phone';
$string['settings_fieldmap_field_mobilePhone'] = 'Mobile phone';
$string['settings_fieldmap_field_officeLocation'] = 'Office';
$string['settings_fieldmap_field_preferredName'] = 'Preferred Name';
$string['settings_fieldmap_field_manager'] = 'Manager';
$string['settings_fieldmap_field_teams'] = 'Teams';
$string['settings_fieldmap_field_groups'] = 'Groups';
$string['settings_fieldmap_field_roles'] = 'Roles';
$string['settings_fieldmap_field_extensionattribute'] = 'Extension attribute {$a}';

221
lib.php
Просмотреть файл

@ -204,3 +204,224 @@ function auth_oidc_delete_token(int $tokenid) {
$DB->delete_records('auth_oidc_token', ['id' => $tokenid]);
}
/**
* Return the list of remote field options in field mapping.
*
* @return array
*/
function auth_oidc_get_remote_fields() {
if (auth_oidc_is_local_365_installed()) {
$remotefields = [
'' => get_string('settings_fieldmap_feild_not_mapped', 'auth_oidc'),
'objectId' => get_string('settings_fieldmap_field_objectId', 'auth_oidc'),
'userPrincipalName' => get_string('settings_fieldmap_field_userPrincipalName', 'auth_oidc'),
'displayName' => get_string('settings_fieldmap_field_displayName', 'auth_oidc'),
'givenName' => get_string('settings_fieldmap_field_givenName', 'auth_oidc'),
'surname' => get_string('settings_fieldmap_field_surname', 'auth_oidc'),
'mail' => get_string('settings_fieldmap_field_mail', 'auth_oidc'),
'streetAddress' => get_string('settings_fieldmap_field_streetAddress', 'auth_oidc'),
'city' => get_string('settings_fieldmap_field_city', 'auth_oidc'),
'postalCode' => get_string('settings_fieldmap_field_postalCode', 'auth_oidc'),
'state' => get_string('settings_fieldmap_field_state', 'auth_oidc'),
'country' => get_string('settings_fieldmap_field_country', 'auth_oidc'),
'jobTitle' => get_string('settings_fieldmap_field_jobTitle', 'auth_oidc'),
'department' => get_string('settings_fieldmap_field_department', 'auth_oidc'),
'companyName' => get_string('settings_fieldmap_field_companyName', 'auth_oidc'),
'preferredLanguage' => get_string('settings_fieldmap_field_preferredLanguage', 'auth_oidc'),
'employeeId' => get_string('settings_fieldmap_field_employeeId', 'auth_oidc'),
'businessPhones' => get_string('settings_fieldmap_field_businessPhones', 'auth_oidc'),
'faxNumber' => get_string('settings_fieldmap_field_faxNumber', 'auth_oidc'),
'mobilePhone' => get_string('settings_fieldmap_field_mobilePhone', 'auth_oidc'),
'officeLocation' => get_string('settings_fieldmap_field_officeLocation', 'auth_oidc'),
'preferredName' => get_string('settings_fieldmap_field_preferredName', 'auth_oidc'),
'manager' => get_string('settings_fieldmap_field_manager', 'auth_oidc'),
'teams' => get_string('settings_fieldmap_field_teams', 'auth_oidc'),
'groups' => get_string('settings_fieldmap_field_groups', 'auth_oidc'),
'roles' => get_string('settings_fieldmap_field_roles', 'auth_oidc'),
];
$order = 0;
while ($order++ < 15) {
$remotefields['extensionAttribute' . $order] = get_string('settings_fieldmap_field_extensionattribute', 'auth_oidc',
$order);
}
} else {
$remotefields = [
'' => '',
'objectId' => get_string('settings_fieldmap_field_objectId', 'auth_oidc'),
'userPrincipalName' => get_string('settings_fieldmap_field_userPrincipalName', 'auth_oidc'),
'givenName' => get_string('settings_fieldmap_field_givenName', 'auth_oidc'),
'surname' => get_string('settings_fieldmap_field_surname', 'auth_oidc'),
'mail' => get_string('settings_fieldmap_field_mail', 'auth_oidc'),
];
}
return $remotefields;
}
/**
* Return the current field mapping settings in an array.
*
* @return array
*/
function auth_oidc_get_field_mappings() {
$fieldmappings = [];
$userfields = auth_oidc_get_all_user_fields();
$authoidcconfig = get_config('auth_oidc');
foreach ($userfields as $userfield) {
$fieldmapsettingname = 'field_map_' . $userfield;
if (property_exists($authoidcconfig, $fieldmapsettingname) && $authoidcconfig->$fieldmapsettingname) {
$fieldsetting = [];
$fieldsetting['field_map'] = $authoidcconfig->$fieldmapsettingname;
$fieldlocksettingname = 'field_lock_' . $userfield;
if (property_exists($authoidcconfig, $fieldlocksettingname)) {
$fieldsetting['field_lock'] = $authoidcconfig->$fieldlocksettingname;
} else {
$fieldsetting['field_lock'] = 'unlocked';
}
$fieldupdatelocksettignname = 'field_updatelocal_' . $userfield;
if (property_exists($authoidcconfig, $fieldupdatelocksettignname)) {
$fieldsetting['update_local'] = $authoidcconfig->$fieldupdatelocksettignname;
} else {
$fieldsetting['update_local'] = 'always';
}
$fieldmappings[$userfield] = $fieldsetting;
}
}
return $fieldmappings;
}
/**
* Helper function used to print mapping and locking for auth_oidc plugin on admin pages.
*
* @param stdclass $settings Moodle admin settings instance
* @param string $auth authentication plugin shortname
* @param array $userfields user profile fields
* @param string $helptext help text to be displayed at top of form
* @param boolean $mapremotefields Map fields or lock only.
* @param boolean $updateremotefields Allow remote updates
* @param array $customfields list of custom profile fields
*/
function auth_oidc_display_auth_lock_options($settings, $auth, $userfields, $helptext, $mapremotefields, $updateremotefields,
$customfields = array()) {
global $DB;
// Introductory explanation and help text.
if ($mapremotefields) {
$settings->add(new admin_setting_heading($auth.'/data_mapping', new lang_string('auth_data_mapping', 'auth'), $helptext));
} else {
$settings->add(new admin_setting_heading($auth.'/auth_fieldlocks', new lang_string('auth_fieldlocks', 'auth'), $helptext));
}
// Generate the list of options.
$lockoptions = [
'unlocked' => get_string('unlocked', 'auth'),
'unlockedifempty' => get_string('unlockedifempty', 'auth'),
'locked' => get_string('locked', 'auth'),
];
if (auth_oidc_is_local_365_installed()) {
$alwaystext = get_string('update_oncreate_and_onlogin_and_usersync', 'auth_oidc');
$onlogintext = get_string('update_onlogin_and_usersync', 'auth_oidc');
} else {
$alwaystext = get_string('update_oncreate_and_onlogin', 'auth_oidc');
$onlogintext = get_string('update_onlogin', 'auth');
}
$updatelocaloptions = [
'always' => $alwaystext,
'oncreate' => get_string('update_oncreate', 'auth'),
'onlogin' => $onlogintext,
];
$updateextoptions = [
'0' => get_string('update_never', 'auth'),
'1' => get_string('update_onupdate', 'auth'),
];
// Generate the list of profile fields to allow updates / lock.
if (!empty($customfields)) {
$userfields = array_merge($userfields, $customfields);
$customfieldname = $DB->get_records('user_info_field', null, '', 'shortname, name');
}
$remotefields = auth_oidc_get_remote_fields();
foreach ($userfields as $field) {
// Define the fieldname we display to the user.
// this includes special handling for some profile fields.
$fieldname = $field;
$fieldnametoolong = false;
if ($fieldname === 'lang') {
$fieldname = get_string('language');
} else if (!empty($customfields) && in_array($field, $customfields)) {
// If custom field then pick name from database.
$fieldshortname = str_replace('profile_field_', '', $fieldname);
$fieldname = $customfieldname[$fieldshortname]->name;
if (core_text::strlen($fieldshortname) > 67) {
// If custom profile field name is longer than 67 characters we will not be able to store the setting
// such as 'field_updateremote_profile_field_NOTSOSHORTSHORTNAME' in the database because the character
// limit for the setting name is 100.
$fieldnametoolong = true;
}
} else if ($fieldname == 'url') {
$fieldname = get_string('webpage');
} else {
$fieldname = get_string($fieldname);
}
// Generate the list of fields / mappings.
if ($fieldnametoolong) {
// Display a message that the field can not be mapped because it's too long.
$url = new moodle_url('/user/profile/index.php');
$a = (object)['fieldname' => s($fieldname), 'shortname' => s($field), 'charlimit' => 67, 'link' => $url->out()];
$settings->add(new admin_setting_heading($auth.'/field_not_mapped_'.sha1($field), '',
get_string('cannotmapfield', 'auth', $a)));
} else if ($mapremotefields) {
// We are mapping to a remote field here.
// Mapping.
$settings->add(new admin_setting_configselect("auth_oidc/field_map_{$field}",
get_string('auth_fieldmapping', 'auth', $fieldname), '', null, $remotefields));
// Update local.
$settings->add(new admin_setting_configselect("auth_{$auth}/field_updatelocal_{$field}",
get_string('auth_updatelocalfield', 'auth', $fieldname), '', 'always', $updatelocaloptions));
// Update remote.
if ($updateremotefields) {
$settings->add(new admin_setting_configselect("auth_{$auth}/field_updateremote_{$field}",
get_string('auth_updateremotefield', 'auth', $fieldname), '', 0, $updateextoptions));
}
// Lock fields.
$settings->add(new admin_setting_configselect("auth_{$auth}/field_lock_{$field}",
get_string('auth_fieldlockfield', 'auth', $fieldname), '', 'unlocked', $lockoptions));
} else {
// Lock fields Only.
$settings->add(new admin_setting_configselect("auth_{$auth}/field_lock_{$field}",
get_string('auth_fieldlockfield', 'auth', $fieldname), '', 'unlocked', $lockoptions));
}
}
}
/**
* Return all user profile field names in an array.
*
* @return array|string[]|null
*/
function auth_oidc_get_all_user_fields() {
$authplugin = get_auth_plugin('oidc');
$userfields = $authplugin->userfields;
$userfields = array_merge($userfields, $authplugin->get_custom_user_profile_fields());
return $userfields;
}

Просмотреть файл

@ -203,5 +203,10 @@ $settings->add($setting);
// Tools to clean up tokens.
$cleanupoidctokensurl = new moodle_url('/auth/oidc/cleanupoidctokens.php');
$cleanupoidctokenslink = html_writer::link($cleanupoidctokensurl, get_string('cfg_cleanupoidctokens_key', 'auth_oidc'));
$settings->add(new auth_oidc_admin_setting_label('auth_oidc/cleaniodctokens', $cleanupoidctokenslink,
get_string('cfg_cleanupoidctokens_desc', 'auth_oidc')));
$settings->add(new auth_oidc_admin_setting_label('auth_oidc/cleaniodctokens', get_string('cfg_tools', 'auth_oidc'),
$cleanupoidctokenslink, get_string('cfg_cleanupoidctokens_desc', 'auth_oidc')));
// Display locking / mapping of profile fields.
$authplugin = get_auth_plugin('oidc');
auth_oidc_display_auth_lock_options($settings, $authplugin->authtype, $authplugin->userfields,
get_string('cfg_field_mapping_desc', 'auth_oidc'), true, false, $authplugin->get_custom_user_profile_fields());

Просмотреть файл

@ -23,7 +23,7 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2021051700;
$plugin->version = 2021051701;
$plugin->requires = 2021051700;
$plugin->release = '3.11.0';
$plugin->component = 'auth_oidc';