Login: Show additional information when prompting to change password (#69537)

* add some information to the password change screen

* update threshold cause pa11y is stupid

* override the loginlayout title if changing password

* remove top padding from inner box
pull/69633/head
Ashley Harrison 2 years ago committed by GitHub
parent c1d3a2d81e
commit 48e328c1dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .pa11yci-pr.conf.js
  2. 8
      public/app/core/components/ForgottenPassword/ChangePassword.tsx
  3. 2
      public/app/core/components/ForgottenPassword/ChangePasswordPage.tsx
  4. 11
      public/app/core/components/Login/LoginCtrl.tsx
  5. 15
      public/app/core/components/Login/LoginLayout.tsx
  6. 92
      public/app/core/components/Login/LoginPage.tsx

@ -74,7 +74,7 @@ var config = {
"click element button[aria-label='Login button']",
"wait for element [aria-label='Skip change password button'] to be visible",
],
threshold: 14,
threshold: 15,
rootElement: '.main-view',
},
{

@ -1,13 +1,14 @@
import React, { SyntheticEvent } from 'react';
import { selectors } from '@grafana/e2e-selectors';
import { Tooltip, Form, Field, VerticalGroup, Button } from '@grafana/ui';
import { Tooltip, Form, Field, VerticalGroup, Button, Alert } from '@grafana/ui';
import { submitButton } from '../Login/LoginForm';
import { PasswordField } from '../PasswordField/PasswordField';
interface Props {
onSubmit: (pw: string) => void;
onSkip?: (event?: SyntheticEvent) => void;
showDefaultPasswordWarning?: boolean;
}
interface PasswordDTO {
@ -15,7 +16,7 @@ interface PasswordDTO {
confirmNew: string;
}
export const ChangePassword = ({ onSubmit, onSkip }: Props) => {
export const ChangePassword = ({ onSubmit, onSkip, showDefaultPasswordWarning }: Props) => {
const submit = (passwords: PasswordDTO) => {
onSubmit(passwords.newPassword);
};
@ -23,6 +24,9 @@ export const ChangePassword = ({ onSubmit, onSkip }: Props) => {
<Form onSubmit={submit}>
{({ errors, register, getValues }) => (
<>
{showDefaultPasswordWarning && (
<Alert severity="info" title="Continuing to use the default password exposes you to security risks." />
)}
<Field label="New password" invalid={!!errors.newPassword} error={errors?.newPassword?.message}>
<PasswordField
id="new-password"

@ -11,7 +11,7 @@ export interface Props extends GrafanaRouteComponentProps<{}, { code: string }>
export const ChangePasswordPage = (props: Props) => {
return (
<LoginLayout>
<LoginLayout isChangingPassword>
<InnerBox>
<LoginCtrl resetCode={props.queryParams.code}>
{({ changePassword }) => <ChangePassword onSubmit={changePassword} />}

@ -31,12 +31,14 @@ interface Props {
isOauthEnabled: boolean;
loginHint: string;
passwordHint: string;
showDefaultPasswordWarning: boolean;
}) => JSX.Element;
}
interface State {
isLoggingIn: boolean;
isChangingPassword: boolean;
showDefaultPasswordWarning: boolean;
}
export class LoginCtrl extends PureComponent<Props, State> {
@ -47,6 +49,7 @@ export class LoginCtrl extends PureComponent<Props, State> {
this.state = {
isLoggingIn: false,
isChangingPassword: false,
showDefaultPasswordWarning: false,
};
if (config.loginError) {
@ -96,7 +99,7 @@ export class LoginCtrl extends PureComponent<Props, State> {
this.toGrafana();
return;
} else {
this.changeView();
this.changeView(formModel.password === 'admin');
}
})
.catch(() => {
@ -106,9 +109,10 @@ export class LoginCtrl extends PureComponent<Props, State> {
});
};
changeView = () => {
changeView = (showDefaultPasswordWarning: boolean) => {
this.setState({
isChangingPassword: true,
showDefaultPasswordWarning,
});
};
@ -127,7 +131,7 @@ export class LoginCtrl extends PureComponent<Props, State> {
render() {
const { children } = this.props;
const { isLoggingIn, isChangingPassword } = this.state;
const { isLoggingIn, isChangingPassword, showDefaultPasswordWarning } = this.state;
const { login, toGrafana, changePassword } = this;
const { loginHint, passwordHint, disableLoginForm, disableUserSignUp } = config;
@ -144,6 +148,7 @@ export class LoginCtrl extends PureComponent<Props, State> {
changePassword,
skipPasswordChange: toGrafana,
isChangingPassword,
showDefaultPasswordWarning,
})}
</>
);

@ -19,9 +19,10 @@ export const InnerBox = ({ children, enterAnimation = true }: React.PropsWithChi
export interface LoginLayoutProps {
/** Custom branding settings that can be used e.g. for previewing the Login page changes */
branding?: BrandingSettings;
isChangingPassword?: boolean;
}
export const LoginLayout = ({ children, branding }: React.PropsWithChildren<LoginLayoutProps>) => {
export const LoginLayout = ({ children, branding, isChangingPassword }: React.PropsWithChildren<LoginLayoutProps>) => {
const loginStyles = useStyles2(getLoginStyles);
const [startAnim, setStartAnim] = useState(false);
const subTitle = branding?.loginSubtitle ?? Branding.GetLoginSubTitle();
@ -39,8 +40,14 @@ export const LoginLayout = ({ children, branding }: React.PropsWithChildren<Logi
<div className={loginStyles.loginLogoWrapper}>
<Branding.LoginLogo className={loginStyles.loginLogo} logo={loginLogo} />
<div className={loginStyles.titleWrapper}>
<h1 className={loginStyles.mainTitle}>{loginTitle}</h1>
{subTitle && <h3 className={loginStyles.subTitle}>{subTitle}</h3>}
{isChangingPassword ? (
<h1 className={loginStyles.mainTitle}>Update your password</h1>
) : (
<>
<h1 className={loginStyles.mainTitle}>{loginTitle}</h1>
{subTitle && <h3 className={loginStyles.subTitle}>{subTitle}</h3>}
</>
)}
</div>
</div>
<div className={loginStyles.loginOuterBox}>{children}</div>
@ -144,7 +151,7 @@ export const getLoginStyles = (theme: GrafanaTheme2) => {
justify-content: center;
`,
loginInnerBox: css`
padding: ${theme.spacing(2)};
padding: ${theme.spacing(0, 2, 2, 2)};
display: flex;
flex-direction: column;

@ -23,52 +23,50 @@ const forgottenPasswordStyles = css`
export const LoginPage = () => {
document.title = Branding.AppTitle;
return (
<LoginLayout>
<LoginCtrl>
{({
loginHint,
passwordHint,
disableLoginForm,
disableUserSignUp,
login,
isLoggingIn,
changePassword,
skipPasswordChange,
isChangingPassword,
}) => (
<>
{!isChangingPassword && (
<InnerBox>
{!disableLoginForm && (
<LoginForm
onSubmit={login}
loginHint={loginHint}
passwordHint={passwordHint}
isLoggingIn={isLoggingIn}
>
<HorizontalGroup justify="flex-end">
<LinkButton
className={forgottenPasswordStyles}
fill="text"
href={`${config.appSubUrl}/user/password/send-reset-email`}
>
Forgot your password?
</LinkButton>
</HorizontalGroup>
</LoginForm>
)}
<LoginServiceButtons />
{!disableUserSignUp && <UserSignup />}
</InnerBox>
)}
{isChangingPassword && (
<InnerBox>
<ChangePassword onSubmit={changePassword} onSkip={() => skipPasswordChange()} />
</InnerBox>
)}
</>
)}
</LoginCtrl>
</LoginLayout>
<LoginCtrl>
{({
loginHint,
passwordHint,
disableLoginForm,
disableUserSignUp,
login,
isLoggingIn,
changePassword,
skipPasswordChange,
isChangingPassword,
showDefaultPasswordWarning,
}) => (
<LoginLayout isChangingPassword={isChangingPassword}>
{!isChangingPassword && (
<InnerBox>
{!disableLoginForm && (
<LoginForm onSubmit={login} loginHint={loginHint} passwordHint={passwordHint} isLoggingIn={isLoggingIn}>
<HorizontalGroup justify="flex-end">
<LinkButton
className={forgottenPasswordStyles}
fill="text"
href={`${config.appSubUrl}/user/password/send-reset-email`}
>
Forgot your password?
</LinkButton>
</HorizontalGroup>
</LoginForm>
)}
<LoginServiceButtons />
{!disableUserSignUp && <UserSignup />}
</InnerBox>
)}
{isChangingPassword && (
<InnerBox>
<ChangePassword
showDefaultPasswordWarning={showDefaultPasswordWarning}
onSubmit={changePassword}
onSkip={() => skipPasswordChange()}
/>
</InnerBox>
)}
</LoginLayout>
)}
</LoginCtrl>
);
};

Loading…
Cancel
Save