Skip to content

Commit

Permalink
Merge pull request #18927 from jeclrsg/hpcc-30048-no-change-password-…
Browse files Browse the repository at this point in the history
…when-disallowed

HPCC-30048 ECL Watch disable password change when unsupported
  • Loading branch information
GordonSmith authored Aug 2, 2024
2 parents 8a2f326 + 8cc4668 commit 10fe469
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 99 deletions.
173 changes: 90 additions & 83 deletions esp/src/eclwatch/CurrentUserDetailsWidget.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,89 +26,96 @@ define([

],
function (declare, lang, nlsHPCCMod, dom, domForm, arrayUtil,
registry,
_Widget, WsAccount,
template) {

var nlsHPCC = nlsHPCCMod.default;
return declare("CurrentUserDetailsWidget", [_Widget], {
templateString: template,
baseClass: "CurrentUserDetailsWidget",
i18n: nlsHPCC,

user: null,

getTitle: function () {
return this.i18n.UserDetails;
},

postCreate: function (args) {
this.inherited(arguments);
this.userForm = registry.byId(this.id + "UserForm");
},

resize: function (args) {
this.inherited(arguments);
this.widget.BorderContainer.resize();
},

// Hitched actions ---
_onSave: function (event) {
var context = this;
var dialog = this.params.Widget;

if (this.userForm.validate()) {
var formInfo = domForm.toObject(this.id + "UserForm");
WsAccount.UpdateUser({
showOkMsg: true,
request: {
username: this.user,
oldpass: formInfo.oldPassword,
newpass1: formInfo.newPassword,
newpass2: formInfo.newPassword
}
}).then(function (response) {
if (lang.exists("UpdateUserResponse", response)) {
arrayUtil.forEach(context.userForm.getDescendants(), function (item, idx) {
item.set("value", "");
});
}
});
dialog.hide();
}
},

// Implementation ---
init: function (params) {
if (this.inherited(arguments))
return;

this.user = params.Username;
this.refresh();
},

refresh: function () {
if (this.user) {
this.updateInput("User", null, this.user);
this.updateInput("Username", null, this.user);

registry,
_Widget, WsAccount,
template) {

var nlsHPCC = nlsHPCCMod.default;
return declare("CurrentUserDetailsWidget", [_Widget], {
templateString: template,
baseClass: "CurrentUserDetailsWidget",
i18n: nlsHPCC,

user: null,
canUpdatePassword: false,

getTitle: function () {
return this.i18n.UserDetails;
},

postCreate: function (args) {
this.inherited(arguments);
this.userForm = registry.byId(this.id + "UserForm");
},

resize: function (args) {
this.inherited(arguments);
this.widget.BorderContainer.resize();
},

// Hitched actions ---
_onSave: function (event) {
var context = this;
WsAccount.MyAccount({
}).then(function (response) {
if (lang.exists("MyAccountResponse.firstName", response)) {
context.updateInput("FirstName", null, response.MyAccountResponse.firstName);
}
if (lang.exists("MyAccountResponse.employeeID", response)) {
context.updateInput("EmployeeID", null, response.MyAccountResponse.employeeID);
}
if (lang.exists("MyAccountResponse.lastName", response)) {
context.updateInput("LastName", null, response.MyAccountResponse.lastName);
}
if (lang.exists("MyAccountResponse.passwordExpiration", response)) {
context.updateInput("PasswordExpiration", null, response.MyAccountResponse.passwordExpiration);
}
});
var dialog = this.params.Widget;

if (this.canUpdatePassword && this.userForm.validate()) {
var formInfo = domForm.toObject(this.id + "UserForm");
WsAccount.UpdateUser({
showOkMsg: true,
request: {
username: this.user,
oldpass: formInfo.oldPassword,
newpass1: formInfo.newPassword,
newpass2: formInfo.newPassword
}
}).then(function (response) {
if (lang.exists("UpdateUserResponse", response)) {
arrayUtil.forEach(context.userForm.getDescendants(), function (item, idx) {
item.set("value", "");
});
}
});
dialog.hide();
}
},

// Implementation ---
init: function (params) {
if (this.inherited(arguments))
return;

this.user = params.Username;
this.refresh();
},

refresh: function () {
if (this.user) {
this.updateInput("User", null, this.user);
this.updateInput("Username", null, this.user);

var context = this;
WsAccount.MyAccount({
}).then(function (response) {
if (lang.exists("MyAccountResponse.firstName", response)) {
context.updateInput("FirstName", null, response.MyAccountResponse.firstName);
}
if (lang.exists("MyAccountResponse.employeeID", response)) {
context.updateInput("EmployeeID", null, response.MyAccountResponse.employeeID);
}
if (lang.exists("MyAccountResponse.lastName", response)) {
context.updateInput("LastName", null, response.MyAccountResponse.lastName);
}
if (lang.exists("MyAccountResponse.passwordExpiration", response)) {
context.updateInput("PasswordExpiration", null, response.MyAccountResponse.passwordExpiration);
}
if (!response?.MyAccountResponse?.CanUpdatePassword) {
context.setDisabled("dijit_form_ValidationTextBox_0", true);
context.setDisabled("dojox_form__NewPWBox_0", true);
context.setDisabled("dojox_form__VerifyPWBox_0", true);
}
context.canUpdatePassword = response?.MyAccountResponse?.CanUpdatePassword;
});
}
}
}
});
});
});
8 changes: 4 additions & 4 deletions esp/src/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion esp/src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"@hpcc-js/chart": "2.83.4",
"@hpcc-js/codemirror": "2.62.1",
"@hpcc-js/common": "2.71.18",
"@hpcc-js/comms": "2.94.0",
"@hpcc-js/comms": "2.94.1",
"@hpcc-js/dataflow": "8.1.7",
"@hpcc-js/eclwatch": "2.74.8",
"@hpcc-js/graph": "2.85.16",
Expand Down
24 changes: 16 additions & 8 deletions esp/src/src-react/components/MyAccount.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import * as React from "react";
import { DefaultButton, Dialog, DialogFooter, DialogType, MessageBar, MessageBarType, PrimaryButton } from "@fluentui/react";
import { useConst } from "@fluentui/react-hooks";
import { AccountService, WsAccount } from "@hpcc-js/comms";
import { scopedLogger } from "@hpcc-js/util";
import { PasswordStatus } from "../hooks/user";
import nlsHPCC from "src/nlsHPCC";
import { TableGroup } from "./forms/Groups";
import { useConst } from "@fluentui/react-hooks";

const logger = scopedLogger("src-react/components/MyAccount.tsx");

Expand Down Expand Up @@ -36,8 +37,14 @@ export const MyAccount: React.FunctionComponent<MyAccountProps> = ({
};
}, [currentUser]);

const resetForm = React.useCallback(() => {
setOldPassword("");
setNewPassword1("");
setNewPassword2("");
}, []);

const saveUser = React.useCallback(() => {
if (oldPassword !== "" && newPassword1 !== "") {
if (currentUser?.CanUpdatePassword && oldPassword !== "" && newPassword1 !== "") {
service.UpdateUser({
username: currentUser.username,
oldpass: oldPassword,
Expand All @@ -51,13 +58,14 @@ export const MyAccount: React.FunctionComponent<MyAccountProps> = ({
} else {
setShowError(false);
setErrorMessage("");
resetForm();
onClose();
}
})
.catch(err => logger.error(err))
;
}
}, [currentUser, newPassword1, newPassword2, oldPassword, onClose, service]);
}, [currentUser, newPassword1, newPassword2, oldPassword, onClose, resetForm, service]);

return <Dialog hidden={!show} onDismiss={onClose} dialogContentProps={dialogContentProps} minWidth="640px">
{showError &&
Expand All @@ -70,10 +78,10 @@ export const MyAccount: React.FunctionComponent<MyAccountProps> = ({
"employeeID": { label: nlsHPCC.EmployeeID, type: "string", value: currentUser?.employeeID, readonly: true },
"firstname": { label: nlsHPCC.FirstName, type: "string", value: currentUser?.firstName, readonly: true },
"lastname": { label: nlsHPCC.LastName, type: "string", value: currentUser?.lastName, readonly: true },
"oldPassword": { label: nlsHPCC.OldPassword, type: "password", value: oldPassword },
"newPassword1": { label: nlsHPCC.NewPassword, type: "password", value: newPassword1 },
"newPassword2": { label: nlsHPCC.ConfirmPassword, type: "password", value: newPassword2, errorMessage: passwordMismatch },
"PasswordExpiration": { label: nlsHPCC.PasswordExpiration, type: "string", value: currentUser?.passwordExpiration, readonly: true },
"oldPassword": { label: nlsHPCC.OldPassword, type: "password", value: oldPassword, disabled: () => !currentUser?.CanUpdatePassword },
"newPassword1": { label: nlsHPCC.NewPassword, type: "password", value: newPassword1, disabled: () => !currentUser?.CanUpdatePassword },
"newPassword2": { label: nlsHPCC.ConfirmPassword, type: "password", value: newPassword2, errorMessage: passwordMismatch, disabled: () => !currentUser?.CanUpdatePassword },
"PasswordExpiration": { label: nlsHPCC.PasswordExpiration, type: "string", value: currentUser?.passwordDaysRemaining === PasswordStatus.NeverExpires ? nlsHPCC.PasswordNeverExpires : currentUser?.passwordExpiration, readonly: true },
}} onChange={(id, value) => {
switch (id) {
case "oldPassword":
Expand All @@ -96,7 +104,7 @@ export const MyAccount: React.FunctionComponent<MyAccountProps> = ({
}} />
<DialogFooter>
<PrimaryButton onClick={saveUser} text={nlsHPCC.Save} />
<DefaultButton onClick={onClose} text={nlsHPCC.Cancel} />
<DefaultButton onClick={() => { resetForm(); onClose(); }} text={nlsHPCC.Cancel} />
</DialogFooter>
</Dialog>;
};
6 changes: 3 additions & 3 deletions esp/src/src-react/components/Title.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { replaceUrl } from "../util/history";
import { useECLWatchLogger } from "../hooks/logging";
import { useBuildInfo, useModernMode, useCheckFeatures } from "../hooks/platform";
import { useGlobalStore } from "../hooks/store";
import { useMyAccount, useUserSession } from "../hooks/user";
import { PasswordStatus, useMyAccount, useUserSession } from "../hooks/user";

import { TitlebarConfig } from "./forms/TitlebarConfig";
import { switchTechPreview } from "./controls/ComingSoon";
Expand Down Expand Up @@ -246,10 +246,10 @@ export const DevTitle: React.FunctionComponent<DevTitleProps> = ({
// cookie expires option expects whole number of days, use a decimal < 1 for hours
cookie("PasswordExpiredCheck", "true", { expires: 0.5, path: "/" });
switch (currentUser.passwordDaysRemaining) {
case -1: // password has expired
case PasswordStatus.Expired:
setPasswordExpiredConfirm(true);
break;
case -2: // password never expires
case PasswordStatus.NeverExpires:
case null:
break;
default:
Expand Down
1 change: 1 addition & 0 deletions esp/src/src-react/components/forms/Fields.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -863,6 +863,7 @@ export function createInputs(fields: Fields, onChange?: (id: string, newValue: a
onChange={(evt, newValue) => onChange(fieldID, newValue)}
borderless={field.readonly && !field.multiline}
readOnly={field.readonly}
disabled={field.disabled(field) ? true : false}
required={field.required}
multiline={field.multiline}
errorMessage={field.errorMessage ?? ""}
Expand Down
6 changes: 6 additions & 0 deletions esp/src/src-react/hooks/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ const defaults = {

const userSession = { ...defaults };

export enum PasswordStatus {
NeverExpires = -2,
Expired = -1,
Unexpired = 0,
}

export interface UserSession {
ESPSessionTimeout: number;
ESPAuthenticated: boolean;
Expand Down
1 change: 1 addition & 0 deletions esp/src/src/nls/hpcc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,7 @@ export = {
PasswordExpired: "Your password has expired. Please change now.",
PasswordExpirePrefix: "Your password will expire in ",
PasswordExpirePostfix: " day(s). Do you want to change it now?",
PasswordNeverExpires: "Password never expires",
Path: "Path",
PathAndNameOnly: "Path and name only?",
PathMask: "Path Mask",
Expand Down

0 comments on commit 10fe469

Please sign in to comment.