changepassword.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. /*
  2. * Password Management Servlets (PWM)
  3. * http://code.google.com/p/pwm/
  4. *
  5. * Copyright (c) 2006-2009 Novell, Inc.
  6. * Copyright (c) 2009-2015 The PWM Project
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. */
  22. //
  23. // PWM Change Password JavaScript.
  24. //
  25. "use strict";
  26. var COLOR_BAR_TOP = 0x8ced3f;
  27. var COLOR_BAR_BOTTOM = 0xcc0e3e;
  28. var PWM_CHANGEPW = PWM_CHANGEPW || {};
  29. // takes password values in the password fields, sends an http request to the servlet
  30. // and then parses (and displays) the response from the servlet.
  31. PWM_CHANGEPW.validatePasswords = function(userDN)
  32. {
  33. PWM_MAIN.getObject("password_button").disabled = true;
  34. if (PWM_MAIN.getObject("password1").value.length <= 0 && PWM_MAIN.getObject("password2").value.length <= 0) {
  35. PWM_CHANGEPW.updateDisplay(null);
  36. return;
  37. }
  38. if (PWM_GLOBAL['previousP1'] != PWM_MAIN.getObject("password1").value) { // if p1 is changing, then clear out p2.
  39. PWM_MAIN.getObject("password2").value = "";
  40. PWM_GLOBAL['previousP1'] = PWM_MAIN.getObject("password1").value;
  41. }
  42. var validationProps = new Array();
  43. validationProps['messageWorking'] = PWM_MAIN.showString('Display_CheckingPassword');
  44. validationProps['serviceURL'] = PWM_GLOBAL['url-restservice'] + "/checkpassword";
  45. validationProps['readDataFunction'] = function(){
  46. var returnObj = {};
  47. returnObj['password1'] = PWM_MAIN.getObject("password1").value;
  48. returnObj['password2'] = PWM_MAIN.getObject("password2").value;
  49. if (userDN) returnObj['username'] = userDN;
  50. return returnObj;
  51. };
  52. validationProps['processResultsFunction'] = function(data){
  53. if (data) {
  54. PWM_CHANGEPW.updateDisplay(data['data']);
  55. } else {
  56. PWM_CHANGEPW.updateDisplay(null);
  57. }
  58. };
  59. PWM_MAIN.pwmFormValidator(validationProps);
  60. };
  61. PWM_CHANGEPW.updateDisplay = function(resultInfo) {
  62. if (resultInfo == null) {
  63. var passwordButton = PWM_MAIN.getObject("password_button");
  64. if (passwordButton != null) {
  65. passwordButton.disabled = false;
  66. }
  67. PWM_MAIN.showSuccess(PWM_MAIN.showString('Display_PasswordPrompt'));
  68. PWM_CHANGEPW.markStrength(0);
  69. PWM_CHANGEPW.markConfirmationCheck(null);
  70. return;
  71. }
  72. var message = resultInfo["message"];
  73. if (resultInfo["version"] != "2") {
  74. PWM_MAIN.showError("[ unexpected version string from server ]");
  75. return;
  76. }
  77. if (resultInfo["passed"] == true) {
  78. //PWM_MAIN.getObject('password2').disabled = false;
  79. if (resultInfo["match"] == "MATCH") {
  80. PWM_MAIN.getObject("password_button").disabled = false;
  81. PWM_MAIN.showSuccess(message);
  82. } else {
  83. PWM_MAIN.getObject("password_button").disabled = true;
  84. PWM_MAIN.showInfo(message);
  85. }
  86. } else {
  87. //PWM_MAIN.getObject('password2').disabled = true;
  88. PWM_MAIN.getObject("password_button").disabled = true;
  89. PWM_MAIN.showError(message);
  90. }
  91. try {
  92. PWM_CHANGEPW.markConfirmationCheck(resultInfo["match"]);
  93. } catch (e) {
  94. console.log('error updating confirmation check icons: ' + e)
  95. }
  96. try {
  97. PWM_CHANGEPW.markStrength(resultInfo["strength"]);
  98. } catch (e) {
  99. console.log('error updating strength icon: ' + e)
  100. }
  101. };
  102. PWM_CHANGEPW.markConfirmationCheck = function(matchStatus) {
  103. if (PWM_MAIN.getObject("confirmCheckMark") && PWM_MAIN.getObject("confirmCrossMark")) {
  104. if (matchStatus == "MATCH") {
  105. PWM_MAIN.getObject("confirmCheckMark").style.visibility = 'visible';
  106. PWM_MAIN.getObject("confirmCrossMark").style.visibility = 'hidden';
  107. PWM_MAIN.getObject("confirmCheckMark").width = '15';
  108. PWM_MAIN.getObject("confirmCrossMark").width = '0';
  109. } else if (matchStatus == "NO_MATCH") {
  110. PWM_MAIN.getObject("confirmCheckMark").style.visibility = 'hidden';
  111. PWM_MAIN.getObject("confirmCrossMark").style.visibility = 'visible';
  112. PWM_MAIN.getObject("confirmCheckMark").width = '0';
  113. PWM_MAIN.getObject("confirmCrossMark").width = '15';
  114. } else {
  115. PWM_MAIN.getObject("confirmCheckMark").style.visibility = 'hidden';
  116. PWM_MAIN.getObject("confirmCrossMark").style.visibility = 'hidden';
  117. PWM_MAIN.getObject("confirmCheckMark").width = '0';
  118. PWM_MAIN.getObject("confirmCrossMark").width = '0';
  119. }
  120. }
  121. };
  122. PWM_CHANGEPW.markStrength = function(strength) { //strength meter
  123. if (PWM_MAIN.getObject("strengthBox") == null) {
  124. return;
  125. }
  126. if (PWM_MAIN.getObject("password1").value.length > 0) {
  127. PWM_MAIN.getObject("strengthBox").style.visibility = 'visible';
  128. } else {
  129. PWM_MAIN.getObject("strengthBox").style.visibility = 'hidden';
  130. }
  131. var strengthLabel = "";
  132. var barColor = "";
  133. if (strength > 70) {
  134. strengthLabel = PWM_MAIN.showString('Display_PasswordStrengthHigh');
  135. } else if (strength > 45) {
  136. strengthLabel = PWM_MAIN.showString('Display_PasswordStrengthMedium');
  137. } else {
  138. strengthLabel = PWM_MAIN.showString('Display_PasswordStrengthLow');
  139. }
  140. var colorFade = function(h1, h2, p) { return ((h1>>16)+((h2>>16)-(h1>>16))*p)<<16|(h1>>8&0xFF)+((h2>>8&0xFF)-(h1>>8&0xFF))*p<<8|(h1&0xFF)+((h2&0xFF)-(h1&0xFF))*p; }
  141. var gradColor = colorFade(COLOR_BAR_BOTTOM, COLOR_BAR_TOP, strength / 100).toString(16) + '';
  142. var barObject = PWM_MAIN.getObject("strengthBar");
  143. if (barObject != null) {
  144. barObject.style.width = strength + '%';
  145. barObject.style.backgroundColor = '#' + gradColor;
  146. }
  147. var labelObject = PWM_MAIN.getObject("strengthLabel");
  148. if (labelObject != null) {
  149. labelObject.innerHTML = strengthLabel == null ? "" : strengthLabel;
  150. }
  151. };
  152. PWM_CHANGEPW.copyToPasswordFields = function(text) { // used to copy auto-generated passwords to password field
  153. if (text.length > 255) {
  154. text = text.substring(0,255);
  155. }
  156. text = PWM_MAIN.trimString(text);
  157. PWM_MAIN.closeWaitDialog();
  158. PWM_MAIN.getObject("password1").value = text;
  159. PWM_CHANGEPW.validatePasswords();
  160. PWM_MAIN.getObject("password2").focus();
  161. ShowHidePasswordHandler.show('password1');
  162. };
  163. PWM_CHANGEPW.showPasswordGuide=function() {
  164. PWM_MAIN.showDialog({
  165. showClose:true,
  166. title: PWM_MAIN.showString('Title_PasswordGuide'),
  167. text: '<div id="passwordGuideTextContent">' + PWM_GLOBAL['passwordGuideText'] + '</div>'
  168. });
  169. /*
  170. PWM_MAIN.clearDijitWidget('dialogPopup');
  171. require(["dojo","dijit/Dialog"],function(dojo, Dialog){
  172. var theDialog = new Dialog({
  173. title: PWM_MAIN.showString('Title_PasswordGuide'),
  174. style: "border: 2px solid #D4D4D4; min-width: 300px",
  175. content: '<div id="passwordGuideTextContent">' + PWM_GLOBAL['passwordGuideText'] + '</div>',
  176. closable: true,
  177. draggable: true,
  178. id: "dialogPopup"
  179. });
  180. theDialog.show();
  181. dojo.connect(theDialog, "hide", function(){
  182. dojo.destroy(PWM_MAIN.getObject("passwordGuideTextContent"));
  183. });
  184. });
  185. */
  186. };
  187. PWM_CHANGEPW.handleChangePasswordSubmit=function() {
  188. PWM_MAIN.showInfo(PWM_MAIN.showString('Display_PleaseWait'));
  189. PWM_VAR['dirtyPageLeaveFlag'] = false;
  190. };
  191. PWM_CHANGEPW.doRandomGeneration=function(randomConfig) {
  192. randomConfig = randomConfig === undefined ? {} : randomConfig;
  193. var finishAction = 'finishAction' in randomConfig ? randomConfig['finishAction'] : function(password) {
  194. PWM_CHANGEPW.copyToPasswordFields(password)
  195. };
  196. var eventHandlers = [];
  197. var dialogBody = "";
  198. if (randomConfig['dialog'] != null && randomConfig['dialog'].length > 0) {
  199. dialogBody += randomConfig['dialog'];
  200. } else {
  201. dialogBody += PWM_MAIN.showString('Display_PasswordGeneration');
  202. }
  203. dialogBody += "<br/><br/>";
  204. dialogBody += '<table style="border: 0">';
  205. for (var i = 0; i < 20; i++) {
  206. dialogBody += '<tr style="border: 0">';
  207. for (var j = 0; j < 2; j++) {
  208. i = i + j;
  209. (function(index) {
  210. var elementID = "randomGen" + index;
  211. dialogBody += '<td style="border: 0; padding-bottom: 5px;" width="20%"><a style="text-decoration:none; color: black" href="#" id="' + elementID + '">&nbsp;</a></td>';
  212. eventHandlers.push(function(){
  213. PWM_MAIN.addEventHandler(elementID,'click',function(){
  214. var value = PWM_MAIN.getObject(elementID).innerHTML;
  215. finishAction(value);
  216. });
  217. });
  218. })(i);
  219. }
  220. dialogBody += '</tr>';
  221. }
  222. dialogBody += "</table><br/><br/>";
  223. dialogBody += '<table style="border: 0">';
  224. dialogBody += '<tr style="border: 0"><td style="border: 0"><button class="btn" id="moreRandomsButton" disabled="true"><span class="btn-icon fa fa-refresh"></span>' + PWM_MAIN.showString('Button_More') + '</button></td>';
  225. dialogBody += '<td style="border: 0; text-align:right;"><button class="btn" id="cancelRandomsButton"><span class="btn-icon fa fa-times"></span>' + PWM_MAIN.showString('Button_Cancel') + '</button></td></tr>';
  226. dialogBody += "</table>";
  227. randomConfig['dialogBody'] = dialogBody;
  228. eventHandlers.push(function(){
  229. PWM_MAIN.addEventHandler('cancelRandomsButton','click',function(){
  230. PWM_MAIN.closeWaitDialog('dialogPopup');
  231. });
  232. PWM_MAIN.addEventHandler('moreRandomsButton','click',function(){
  233. PWM_CHANGEPW.beginFetchRandoms(randomConfig);
  234. });
  235. });
  236. var titleString = randomConfig['title'] == null ? PWM_MAIN.showString('Title_RandomPasswords') : randomConfig['title'];
  237. PWM_MAIN.showDialog({
  238. title:titleString,
  239. dialogClass:'narrow',
  240. text:dialogBody,
  241. showOk:false,
  242. showClose:true,
  243. loadFunction:function(){
  244. PWM_CHANGEPW.beginFetchRandoms(randomConfig);
  245. for (var i = 0; i < eventHandlers.length; i++) {
  246. eventHandlers[i]();
  247. }
  248. }
  249. });
  250. };
  251. PWM_CHANGEPW.beginFetchRandoms=function(randomConfig) {
  252. PWM_MAIN.getObject('moreRandomsButton').disabled = true;
  253. var fetchList = new Array();
  254. for (var counter = 0; counter < 20; counter++) {
  255. fetchList[counter] = 'randomGen' + counter;
  256. var name ='randomGen' + counter;
  257. var element = PWM_MAIN.getObject(name);
  258. if (element != null) {
  259. element.firstChild.nodeValue = '\u00A0';
  260. }
  261. }
  262. fetchList.sort(function() {return 0.5 - Math.random()});
  263. fetchList.sort(function() {return 0.5 - Math.random()});
  264. randomConfig['fetchList'] = fetchList;
  265. PWM_CHANGEPW.fetchRandoms(randomConfig);
  266. };
  267. PWM_CHANGEPW.fetchRandoms=function(randomConfig) {
  268. if (randomConfig['fetchList'].length < 1) {
  269. var moreButton = PWM_MAIN.getObject('moreRandomsButton');
  270. if (moreButton != null) {
  271. moreButton.disabled = false;
  272. moreButton.focus();
  273. }
  274. return;
  275. }
  276. if (randomConfig['fetchList'].length > 0) {
  277. var successFunction = function(resultInfo) {
  278. var password = resultInfo['data']["password"];
  279. var elementID = randomConfig['fetchList'].pop();
  280. var element = PWM_MAIN.getObject(elementID);
  281. if (element != null) {
  282. element.firstChild.nodeValue = password;
  283. }
  284. PWM_CHANGEPW.fetchRandoms(randomConfig);
  285. };
  286. var url = PWM_GLOBAL['url-restservice'] + "/randompassword";
  287. var content = randomConfig['dataInput'] == null ? { } : randomConfig['dataInput'];
  288. PWM_MAIN.ajaxRequest(url,successFunction,{content:content});
  289. }
  290. };
  291. PWM_CHANGEPW.startupChangePasswordPage=function() {
  292. //PWM_MAIN.getObject('password2').disabled = true;
  293. PWM_CHANGEPW.markStrength(0);
  294. // add handlers for main form
  295. require(["dojo/on"], function(on){
  296. var changePasswordForm = PWM_MAIN.getObject('changePasswordForm');
  297. on(changePasswordForm,"keyup, change",function(){
  298. PWM_CHANGEPW.validatePasswords(null);
  299. });
  300. on(changePasswordForm,"submit",function(event){
  301. PWM_CHANGEPW.handleChangePasswordSubmit();
  302. PWM_MAIN.handleFormSubmit(changePasswordForm, event);
  303. return false;
  304. });
  305. on(changePasswordForm,"reset",function(){
  306. PWM_CHANGEPW.validatePasswords(null);
  307. PWM_CHANGEPW.setInputFocus();
  308. return false;
  309. });
  310. });
  311. // show the auto generate password panel
  312. var autoGenPasswordElement = PWM_MAIN.getObject("autogenerate-icon");
  313. if (autoGenPasswordElement != null) {
  314. autoGenPasswordElement.style.visibility = 'visible';
  315. PWM_MAIN.addEventHandler(autoGenPasswordElement,'click',function(){
  316. PWM_CHANGEPW.doRandomGeneration();
  317. });
  318. PWM_MAIN.showTooltip({
  319. id: "autogenerate-icon",
  320. text: PWM_MAIN.showString('Display_AutoGeneratedPassword')
  321. });
  322. }
  323. // add a handler so if the user leaves the page except by submitting the form, then a warning/confirm is shown
  324. var pageLeaveFunction = function() {
  325. if (PWM_VAR['dirtyPageLeaveFlag']) {
  326. var message = PWM_MAIN.showString('Display_LeaveDirtyPasswordPage');
  327. console.log('changepassword-beforeunload handler invoked');
  328. if (message.trim().length > 0) {
  329. return message;
  330. }
  331. } else {
  332. console.log('changepassword-beforeunload handler skipped');
  333. }
  334. };
  335. window.onbeforeunload=pageLeaveFunction;
  336. PWM_VAR['dirtyPageLeaveFlag'] = true;
  337. var messageElement = PWM_MAIN.getObject("message");
  338. if (messageElement.firstChild.nodeValue.length < 2) {
  339. setTimeout(function(){
  340. PWM_MAIN.showInfo(PWM_MAIN.showString('Display_PasswordPrompt'));
  341. },100);
  342. }
  343. PWM_MAIN.showTooltip({
  344. id: "strengthBox",
  345. text: PWM_MAIN.showString('Tooltip_PasswordStrength'),
  346. width: 350
  347. });
  348. if (PWM_GLOBAL['passwordGuideText'] && PWM_GLOBAL['passwordGuideText'].length > 0) {
  349. var iconElement = PWM_MAIN.getObject('password-guide-icon');
  350. if (iconElement) {
  351. try {iconElement.style.visibility = 'visible';} catch (e) { /* noop */ }
  352. PWM_MAIN.addEventHandler('password-guide-icon','click',function(){
  353. PWM_CHANGEPW.showPasswordGuide();
  354. });
  355. PWM_MAIN.showTooltip({
  356. id: ["password-guide-icon"],
  357. text: PWM_MAIN.showString('Display_ShowPasswordGuide')
  358. });
  359. }
  360. }
  361. setTimeout(function(){
  362. PWM_CHANGEPW.setInputFocus();
  363. },10);
  364. };
  365. PWM_CHANGEPW.setInputFocus=function() {
  366. var currentPassword = PWM_MAIN.getObject('currentPassword');
  367. if (currentPassword != null) {
  368. setTimeout(function() { currentPassword.focus(); },10);
  369. } else {
  370. var password1 = PWM_MAIN.getObject('password1');
  371. setTimeout(function() { password1.focus(); },10);
  372. }
  373. };
  374. PWM_CHANGEPW.refreshCreateStatus=function(refreshInterval) {
  375. require(["dojo","dijit/registry"],function(dojo,registry){
  376. var displayStringsUrl = "ChangePassword?processAction=checkProgress";
  377. var completedUrl = "ChangePassword?processAction=complete&pwmFormID=" + PWM_GLOBAL['pwmFormID'];
  378. var loadFunction = function(data) {
  379. var supportsProgress = (document.createElement('progress').max !== undefined);
  380. if (supportsProgress) {
  381. console.log('beginning html5 progress refresh');
  382. var html5passwordProgressBar = PWM_MAIN.getObject('html5ProgressBar');
  383. dojo.setAttr(html5passwordProgressBar, "value", data['data']['percentComplete']);
  384. } else {
  385. console.log('beginning dojo progress refresh');
  386. var progressBar = registry.byId('passwordProgressBar');
  387. progressBar.set("value",data['data']['percentComplete']);
  388. }
  389. try {
  390. var tableBody = '';
  391. if (data['data']['messages']) {
  392. for (var msgItem in data['data']['messages']) {
  393. (function(message){
  394. if (message['show']) {
  395. tableBody += '<tr><td>' + message['label'] + '</td><td>'
  396. tableBody += message['complete'] ? "Completed" : "In Progress"
  397. tableBody += '</td></tr>'
  398. }
  399. }(data['data']['messages'][msgItem]));
  400. }
  401. }
  402. if (PWM_MAIN.getObject('progressMessageTable')) {
  403. PWM_MAIN.getObject('progressMessageTable').innerHTML = tableBody;
  404. }
  405. if (PWM_MAIN.getObject('estimatedRemainingSeconds')) {
  406. PWM_MAIN.getObject('estimatedRemainingSeconds').innerHTML = data['data']['estimatedRemainingSeconds'];
  407. }
  408. if (PWM_MAIN.getObject('elapsedSeconds')) {
  409. PWM_MAIN.getObject('elapsedSeconds').innerHTML = data['data']['elapsedSeconds'];
  410. }
  411. } catch (e) {
  412. console.log('unable to update progressMessageTable, error: ' + e);
  413. }
  414. if (data['data']['complete'] == true) {
  415. PWM_MAIN.goto(completedUrl,{delay:1000})
  416. } else {
  417. setTimeout(function(){
  418. PWM_CHANGEPW.refreshCreateStatus(refreshInterval);
  419. },refreshInterval);
  420. }
  421. };
  422. var errorFunction = function(error) {
  423. console.log('unable to read password change status: ' + error);
  424. setTimeout(function(){
  425. PWM_CHANGEPW.refreshCreateStatus(refreshInterval);
  426. },refreshInterval);
  427. };
  428. PWM_MAIN.ajaxRequest(displayStringsUrl, loadFunction, {errorFunction:errorFunction});
  429. });
  430. };