diff --git a/classes/XDUser.php b/classes/XDUser.php index 3006f8f912..02894ff405 100644 --- a/classes/XDUser.php +++ b/classes/XDUser.php @@ -7,6 +7,7 @@ use Models\Acl; use Models\Services\Acls; use User\aRole; +use DataWarehouse\Query\Exceptions\AccessDeniedException; /** * XDMoD Portal User @@ -544,9 +545,11 @@ public static function getUserByID($uid, &$targetInstance = NULL) public function setPassword($raw_password) { + if ($this->getUserType() === FEDERATED_USER_TYPE) { + throw new AccessDeniedException("Permission Denied. Only local accounts may have their passwords modified."); + } return $this->_password = $raw_password; - }//setPassword // --------------------------- diff --git a/html/gui/js/profile_editor/ProfileGeneralSettings.js b/html/gui/js/profile_editor/ProfileGeneralSettings.js index b17f792331..c0b0f85891 100644 --- a/html/gui/js/profile_editor/ProfileGeneralSettings.js +++ b/html/gui/js/profile_editor/ProfileGeneralSettings.js @@ -1,455 +1,447 @@ XDMoD.ProfileGeneralSettings = Ext.extend(Ext.form.FormPanel, { - autoHeight: true, - border: false, - frame: true, - resizable: false, - title: 'General', - cls: 'no-underline-invalid-fields-form', - - // Dictates whether closing the profile editor logs out the user automatically - perform_logout_on_close: false, - - init: function() { - - XDMoD.REST.connection.request({ - url: '/users/current', - method: 'GET', - callback: this.cbProfile - }); - - }, - - initComponent: function() { - - var self = this; - - // ------------------------------------------------ - - var fieldRequiredText = 'This field is required.'; - var reservedCharactersNotAllowedText = 'This field may not contain reserved characters. ($, ^, #, <, >, ", :, \\, /, !)'; - - var maxFirstNameLength = XDMoD.constants.maxFirstNameLength; - var user_profile_firstname = new Ext.form.TextField({ - name: 'first_name', - fieldLabel: 'First Name', - emptyText: '1 min, ' + maxFirstNameLength + ' max', - msgTarget: 'under', - - allowBlank: false, - blankText: fieldRequiredText, - maxLength: maxFirstNameLength, - maxLengthText: 'Maximum length (' + maxFirstNameLength + ' characters) exceeded.', - regex: XDMoD.regex.noReservedCharacters, - regexText: reservedCharactersNotAllowedText, - - listeners: { - blur: XDMoD.utils.trimOnBlur, - invalid: XDMoD.utils.syncWindowShadow, - valid: XDMoD.utils.syncWindowShadow - } - }); - - var maxLastNameLength = XDMoD.constants.maxLastNameLength; - var user_profile_lastname = new Ext.form.TextField({ - name: 'last_name', - fieldLabel: 'Last Name', - emptyText: '1 min, ' + maxLastNameLength + ' max', - msgTarget: 'under', - - allowBlank: false, - blankText: fieldRequiredText, - maxLength: maxLastNameLength, - maxLengthText: 'Maximum length (' + maxLastNameLength + ' characters) exceeded.', - regex: XDMoD.regex.noReservedCharacters, - regexText: reservedCharactersNotAllowedText, - - listeners: { - blur: XDMoD.utils.trimOnBlur, - invalid: XDMoD.utils.syncWindowShadow, - valid: XDMoD.utils.syncWindowShadow - } - }); - - var minEmailLength = XDMoD.constants.minEmailLength; - var maxEmailLength = XDMoD.constants.maxEmailLength; - var removeFieldHighlight = function(thisField) { - thisField.removeClass('user_profile_highlight_entry'); - }; - var user_profile_email_addr = new Ext.form.TextField({ - name: 'email_address', - fieldLabel: 'E-Mail Address', - emptyText: minEmailLength + ' min, ' + maxEmailLength + ' max', - msgTarget: 'under', - allowBlank: false, - blankText: fieldRequiredText, - minLength: minEmailLength, - minLengthText: 'Minimum length (' + minEmailLength + ' characters) not met.', - maxLength: maxEmailLength, - maxLengthText: 'Maximum length (' + maxEmailLength + ' characters) exceeded.', - validator: XDMoD.validator.email, - - listeners: { - blur: XDMoD.utils.trimOnBlur, - focus: removeFieldHighlight, - invalid: function(thisField, msg) { - removeFieldHighlight(thisField); - XDMoD.utils.syncWindowShadow(thisField); - }, - valid: XDMoD.utils.syncWindowShadow - } - }); - - var passwordFieldWidth = 120; - var minPasswordLength = XDMoD.constants.minPasswordLength; - var maxPasswordLength = XDMoD.constants.maxPasswordLength; - var user_profile_new_pass = new Ext.form.TextField({ - name: 'password', - fieldLabel: 'Password', - width: passwordFieldWidth, - inputType: 'password', - disabled: true, - cls: 'user_profile_password_field', - - allowBlank: false, - blankText: fieldRequiredText, - minLength: minPasswordLength, - minLengthText: 'Minimum length (' + minPasswordLength + ' characters) not met.', - maxLength: maxPasswordLength, - maxLengthText: 'Maximum length (' + maxPasswordLength + ' characters) exceeded.', - - listeners: { - invalid: XDMoD.utils.syncWindowShadow, - valid: XDMoD.utils.syncWindowShadow - } - }); - - var user_profile_new_pass_again = new Ext.form.TextField({ - fieldLabel: 'Password Again', - width: passwordFieldWidth, - inputType: 'password', - disabled: true, - cls: 'user_profile_password_field', - msgTarget: 'under', - submitValue: false, - - validator: function(value) { - if (user_profile_new_pass.getValue() === user_profile_new_pass_again.getValue()) { - return true; - } - - return "This password does not match the password above."; - }, - - listeners: { - invalid: XDMoD.utils.syncWindowShadow, - valid: XDMoD.utils.syncWindowShadow - } - }); - - // ------------------------------------------------ - - var active_layout_index = CCR.xdmod.ui.userIsFederated ? XDMoD.ProfileEditorConstants.FEDERATED_USER : XDMoD.ProfileEditorConstants.PASSWORD; - - - // ------------------------------------------------ - - var switchToSection = function(id) { - - rpanel = sectionBottom.getLayout(); - - if (rpanel != 'card') { - - rpanel.setActiveItem(id); - - } - - }; //switchToSection - - // ------------------------------------------------ - - this.cbProfile = function(options, success, response) { - // If success reported, attempt to extract user data. - var data; - if (success) { - data = CCR.safelyDecodeJSONResponse(response); - success = CCR.checkDecodedJSONResponseSuccess(data); - } - - if (success) { - - user_profile_firstname.setValue(data.results.first_name); - user_profile_lastname.setValue(data.results.last_name); - user_profile_email_addr.setValue(data.results.email_address); - - // ================================================ - - //active_layout_index = XDMoD.ProfileEditorConstants.PASSWORD; - if (data.results.is_federated_user && data.results.email_address.length === 0) { - XDMoD.Profile.logoutOnClose = true; - } - if (data.results.is_federated_user === true) { - if (data.results.first_time_login) { - // If the user is logging in for the first time, prompt them to validate their email address - active_layout_index = XDMoD.ProfileEditorConstants.WELCOME_EMAIL_CHANGE; - user_profile_email_addr.addClass('user_profile_highlight_entry'); + autoHeight: true, + border: false, + frame: true, + resizable: false, + title: 'General', + cls: 'no-underline-invalid-fields-form', + + // Dictates whether closing the profile editor logs out the user automatically + perform_logout_on_close: false, + + init: function () { + XDMoD.REST.connection.request({ + url: '/users/current', + method: 'GET', + callback: this.cbProfile + }); + }, + + initComponent: function () { + var self = this; + + // ------------------------------------------------ + + var fieldRequiredText = 'This field is required.'; + var reservedCharactersNotAllowedText = 'This field may not contain reserved characters. ($, ^, #, <, >, ", :, \\, /, !)'; + + var maxFirstNameLength = XDMoD.constants.maxFirstNameLength; + var user_profile_firstname = new Ext.form.TextField({ + name: 'first_name', + fieldLabel: 'First Name', + emptyText: '1 min, ' + maxFirstNameLength + ' max', + msgTarget: 'under', + + allowBlank: false, + blankText: fieldRequiredText, + maxLength: maxFirstNameLength, + maxLengthText: 'Maximum length (' + maxFirstNameLength + ' characters) exceeded.', + regex: XDMoD.regex.noReservedCharacters, + regexText: reservedCharactersNotAllowedText, + + listeners: { + blur: XDMoD.utils.trimOnBlur, + invalid: XDMoD.utils.syncWindowShadow, + valid: XDMoD.utils.syncWindowShadow + } + }); + + var maxLastNameLength = XDMoD.constants.maxLastNameLength; + var user_profile_lastname = new Ext.form.TextField({ + name: 'last_name', + fieldLabel: 'Last Name', + emptyText: '1 min, ' + maxLastNameLength + ' max', + msgTarget: 'under', + + allowBlank: false, + blankText: fieldRequiredText, + maxLength: maxLastNameLength, + maxLengthText: 'Maximum length (' + maxLastNameLength + ' characters) exceeded.', + regex: XDMoD.regex.noReservedCharacters, + regexText: reservedCharactersNotAllowedText, + + listeners: { + blur: XDMoD.utils.trimOnBlur, + invalid: XDMoD.utils.syncWindowShadow, + valid: XDMoD.utils.syncWindowShadow + } + }); + + var minEmailLength = XDMoD.constants.minEmailLength; + var maxEmailLength = XDMoD.constants.maxEmailLength; + var removeFieldHighlight = function (thisField) { + thisField.removeClass('user_profile_highlight_entry'); + }; + var user_profile_email_addr = new Ext.form.TextField({ + name: 'email_address', + fieldLabel: 'E-Mail Address', + emptyText: minEmailLength + ' min, ' + maxEmailLength + ' max', + msgTarget: 'under', + allowBlank: false, + blankText: fieldRequiredText, + minLength: minEmailLength, + minLengthText: 'Minimum length (' + minEmailLength + ' characters) not met.', + maxLength: maxEmailLength, + maxLengthText: 'Maximum length (' + maxEmailLength + ' characters) exceeded.', + validator: XDMoD.validator.email, + + listeners: { + blur: XDMoD.utils.trimOnBlur, + focus: removeFieldHighlight, + invalid: function (thisField, msg) { + removeFieldHighlight(thisField); + XDMoD.utils.syncWindowShadow(thisField); + }, + valid: XDMoD.utils.syncWindowShadow + } + }); + + var passwordFieldWidth = 120; + var minPasswordLength = XDMoD.constants.minPasswordLength; + var maxPasswordLength = XDMoD.constants.maxPasswordLength; + var user_profile_new_pass = new Ext.form.TextField({ + name: 'password', + fieldLabel: 'Password', + width: passwordFieldWidth, + inputType: 'password', + disabled: true, + cls: 'user_profile_password_field', + + allowBlank: false, + blankText: fieldRequiredText, + minLength: minPasswordLength, + minLengthText: 'Minimum length (' + minPasswordLength + ' characters) not met.', + maxLength: maxPasswordLength, + maxLengthText: 'Maximum length (' + maxPasswordLength + ' characters) exceeded.', + + listeners: { + invalid: XDMoD.utils.syncWindowShadow, + valid: XDMoD.utils.syncWindowShadow + } + }); + + var user_profile_new_pass_again = new Ext.form.TextField({ + fieldLabel: 'Password Again', + width: passwordFieldWidth, + inputType: 'password', + disabled: true, + cls: 'user_profile_password_field', + msgTarget: 'under', + submitValue: false, + + validator: function (value) { + if (user_profile_new_pass.getValue() === user_profile_new_pass_again.getValue()) { + return true; + } + + return 'This password does not match the password above.'; + }, + + listeners: { + invalid: XDMoD.utils.syncWindowShadow, + valid: XDMoD.utils.syncWindowShadow + } + }); + + // ------------------------------------------------ + + var active_layout_index = CCR.xdmod.ui.userIsFederated ? XDMoD.ProfileEditorConstants.FEDERATED_USER : XDMoD.ProfileEditorConstants.PASSWORD; + + + // ------------------------------------------------ + var sectionBottom; + + var switchToSection = function (id) { + var rpanel = sectionBottom.getLayout(); + + if (rpanel !== 'card') { + rpanel.setActiveItem(id); + } + }; // switchToSection + + // ------------------------------------------------ + + this.cbProfile = function (options, success, response) { + // If success reported, attempt to extract user data. + var data; + var decodedSuccessResponse; + if (success) { + data = CCR.safelyDecodeJSONResponse(response); + decodedSuccessResponse = CCR.checkDecodedJSONResponseSuccess(data); + } + + if (decodedSuccessResponse) { + user_profile_firstname.setValue(data.results.first_name); + user_profile_lastname.setValue(data.results.last_name); + user_profile_email_addr.setValue(data.results.email_address); + + // ================================================ + + // active_layout_index = XDMoD.ProfileEditorConstants.PASSWORD; + if (data.results.is_federated_user && data.results.email_address.length === 0) { + XDMoD.Profile.logoutOnClose = true; + } + if (data.results.is_federated_user === true) { + if (data.results.first_time_login) { + // If the user is logging in for the first time, prompt them to validate their email address + active_layout_index = XDMoD.ProfileEditorConstants.WELCOME_EMAIL_CHANGE; + user_profile_email_addr.addClass('user_profile_highlight_entry'); + } + } + + // ================================================ + // eslint-disable-next-line no-use-before-define + lblRole.on( + 'afterrender', + function () { + // eslint-disable-next-line no-undef + document.getElementById('profile_editor_most_privileged_role').innerHTML = data.results.most_privileged_role; + } + ); + + self.parentWindow.show(); + } else { + Ext.MessageBox.alert('My Profile', 'There was a problem retrieving your profile information.'); + } + }; // cbProfile + + // ------------------------------------------------ + var optPasswordUpdate; + var updateProfile = function () { + // This prevents the radio buttons in the password panel from being + // submitted. Setting submitValue to false in the buttons breaks them + // in ExtJS 3.4.0. A call to re-enable them is in the failure handler. + optPasswordUpdate.setDisabled(true); + + self.getForm().submit({ + url: XDMoD.REST.prependPathBase('/users/current'), + method: 'PATCH', + + success: function (form, action) { + XDMoD.Profile.logoutOnClose = false; + + CCR.xdmod.ui.generalMessage('My Profile', action.result.message, true); + + var f_name = user_profile_firstname.getValue(); + var l_name = user_profile_lastname.getValue(); + + document.getElementById('welcome_message').innerHTML = Ext.util.Format.htmlEncode(f_name) + ' ' + Ext.util.Format.htmlEncode(l_name); + + self.parentWindow.close(); + }, + + failure: function (form, action) { + optPasswordUpdate.setDisabled(false); + + if (action.failureType === Ext.form.Action.CLIENT_INVALID) { + CCR.xdmod.ui.userManagementMessage( + 'Please resolve any problems in the form and try updating again.', + false + ); + return; + } + + CCR.xdmod.ui.presentFailureResponse(action.response, { + title: 'My Profile', + wrapperMessage: 'There was a problem updating your information.' + }); + } + }); + }; // updateProfile + + // ------------------------------------------------ + + optPasswordUpdate = new Ext.form.RadioGroup({ + + fieldLabel: 'Update', + cls: 'user_profile_option_password_update', + columns: 2, + width: 180, + + items: [{ + boxLabel: 'Keep Existing', + name: 'group_view', + inputValue: 'keep', + checked: true + }, { + boxLabel: 'Update', + name: 'group_view', + inputValue: 'update', + checked: false + }], + + listeners: { + + change: function (thisRadioGroup, checked) { + var userKeepingPassword = thisRadioGroup.getValue().getGroupValue() === 'keep'; + user_profile_new_pass.setDisabled(userKeepingPassword); + user_profile_new_pass_again.setDisabled(userKeepingPassword); + + if (userKeepingPassword) { + user_profile_new_pass.setValue(''); + user_profile_new_pass_again.setValue(''); + } + } // change + + } // listeners + + }); // optPasswordUpdate + + // ------------------------------------------------ + + var lblRole = new Ext.form.Label({ + html: '