This repository has been archived by the owner on Mar 31, 2024. It is now read-only.
forked from elastic/kibana
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Convert account screen to React/EUI (elastic#30977)
* WIP account management redesign * style updates * start implementing change password logic * restyle * remove api key management section * improved change password validation * first round of design edits * cleanup and testing * fix import * fix translations * fix error handling on user management page * consolidate password change logic * fix tests * happy linter, happy life * finish change password test * removes unused translations * fix typo in test * fix change password functional test * Design edits (#19) - Made `fullWidth` - Added a consistent password requirement help text - Use `title` for toast - Change username/email to us `dl` - Don’t use html elements in tests * clear password form on success * copy edits * fix handling of Change Password button * use encodeURIComponent for user supplied data
- Loading branch information
Showing
24 changed files
with
948 additions
and
256 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import { canUserChangePassword, getUserDisplayName, User } from './user'; | ||
|
||
describe('#getUserDisplayName', () => { | ||
it(`uses the full name when available`, () => { | ||
expect( | ||
getUserDisplayName({ | ||
full_name: 'my full name', | ||
username: 'foo', | ||
} as User) | ||
).toEqual('my full name'); | ||
}); | ||
|
||
it(`uses the username when full name is not available`, () => { | ||
expect( | ||
getUserDisplayName({ | ||
username: 'foo', | ||
} as User) | ||
).toEqual('foo'); | ||
}); | ||
}); | ||
|
||
describe('#canUserChangePassword', () => { | ||
['reserved', 'native'].forEach(realm => { | ||
it(`returns true for users in the ${realm} realm`, () => { | ||
expect( | ||
canUserChangePassword({ | ||
username: 'foo', | ||
authentication_realm: { | ||
name: 'the realm name', | ||
type: realm, | ||
}, | ||
} as User) | ||
).toEqual(true); | ||
}); | ||
}); | ||
|
||
it(`returns true when no realm is provided`, () => { | ||
expect( | ||
canUserChangePassword({ | ||
username: 'foo', | ||
} as User) | ||
).toEqual(true); | ||
}); | ||
|
||
it(`returns false for all other realms`, () => { | ||
expect( | ||
canUserChangePassword({ | ||
username: 'foo', | ||
authentication_realm: { | ||
name: 'the realm name', | ||
type: 'does not matter', | ||
}, | ||
} as User) | ||
).toEqual(false); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
export interface User { | ||
username: string; | ||
email: string; | ||
full_name: string; | ||
roles: string[]; | ||
enabled: boolean; | ||
authentication_realm?: { | ||
name: string; | ||
type: string; | ||
}; | ||
lookup_realm?: { | ||
name: string; | ||
type: string; | ||
}; | ||
} | ||
|
||
const REALMS_ELIGIBLE_FOR_PASSWORD_CHANGE = ['reserved', 'native']; | ||
|
||
export function getUserDisplayName(user: User): string { | ||
return user.full_name || user.username; | ||
} | ||
|
||
export function canUserChangePassword(user: User): boolean { | ||
const { authentication_realm: authenticationRealm } = user; | ||
|
||
if (!authenticationRealm) { | ||
return true; | ||
} | ||
|
||
return REALMS_ELIGIBLE_FOR_PASSWORD_CHANGE.includes(authenticationRealm.type); | ||
} |
111 changes: 111 additions & 0 deletions
111
.../security/public/components/management/change_password_form/change_password_form.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
jest.mock('../../../lib/api', () => { | ||
return { | ||
UserAPIClient: { | ||
changePassword: jest.fn(), | ||
}, | ||
}; | ||
}); | ||
import { EuiFieldText } from '@elastic/eui'; | ||
import { ReactWrapper } from 'enzyme'; | ||
import React from 'react'; | ||
import { mountWithIntl } from 'test_utils/enzyme_helpers'; | ||
import { User } from '../../../../common/model/user'; | ||
import { UserAPIClient } from '../../../lib/api'; | ||
import { ChangePasswordForm } from './change_password_form'; | ||
|
||
function getCurrentPasswordField(wrapper: ReactWrapper<any>) { | ||
return wrapper.find(EuiFieldText).filter('[data-test-subj="currentPassword"]'); | ||
} | ||
|
||
function getNewPasswordField(wrapper: ReactWrapper<any>) { | ||
return wrapper.find(EuiFieldText).filter('[data-test-subj="newPassword"]'); | ||
} | ||
|
||
function getConfirmPasswordField(wrapper: ReactWrapper<any>) { | ||
return wrapper.find(EuiFieldText).filter('[data-test-subj="confirmNewPassword"]'); | ||
} | ||
|
||
describe('<ChangePasswordForm>', () => { | ||
describe('for the current user', () => { | ||
it('shows fields for current and new passwords', () => { | ||
const user: User = { | ||
username: 'user', | ||
full_name: 'john smith', | ||
email: '[email protected]', | ||
enabled: true, | ||
roles: [], | ||
}; | ||
|
||
const wrapper = mountWithIntl( | ||
<ChangePasswordForm user={user} isUserChangingOwnPassword={true} /> | ||
); | ||
|
||
expect(getCurrentPasswordField(wrapper)).toHaveLength(1); | ||
expect(getNewPasswordField(wrapper)).toHaveLength(1); | ||
expect(getConfirmPasswordField(wrapper)).toHaveLength(1); | ||
}); | ||
|
||
it('allows a password to be changed', () => { | ||
const user: User = { | ||
username: 'user', | ||
full_name: 'john smith', | ||
email: '[email protected]', | ||
enabled: true, | ||
roles: [], | ||
}; | ||
|
||
const callback = jest.fn(); | ||
|
||
const wrapper = mountWithIntl( | ||
<ChangePasswordForm | ||
user={user} | ||
isUserChangingOwnPassword={true} | ||
onChangePassword={callback} | ||
/> | ||
); | ||
|
||
const currentPassword = getCurrentPasswordField(wrapper); | ||
currentPassword.props().onChange!({ target: { value: 'myCurrentPassword' } } as any); | ||
|
||
const newPassword = getNewPasswordField(wrapper); | ||
newPassword.props().onChange!({ target: { value: 'myNewPassword' } } as any); | ||
|
||
const confirmPassword = getConfirmPasswordField(wrapper); | ||
confirmPassword.props().onChange!({ target: { value: 'myNewPassword' } } as any); | ||
|
||
wrapper.find('button[data-test-subj="changePasswordButton"]').simulate('click'); | ||
|
||
expect(UserAPIClient.changePassword).toHaveBeenCalledTimes(1); | ||
expect(UserAPIClient.changePassword).toHaveBeenCalledWith( | ||
'user', | ||
'myNewPassword', | ||
'myCurrentPassword' | ||
); | ||
}); | ||
}); | ||
|
||
describe('for another user', () => { | ||
it('shows fields for new password only', () => { | ||
const user: User = { | ||
username: 'user', | ||
full_name: 'john smith', | ||
email: '[email protected]', | ||
enabled: true, | ||
roles: [], | ||
}; | ||
|
||
const wrapper = mountWithIntl( | ||
<ChangePasswordForm user={user} isUserChangingOwnPassword={false} /> | ||
); | ||
|
||
expect(getCurrentPasswordField(wrapper)).toHaveLength(0); | ||
expect(getNewPasswordField(wrapper)).toHaveLength(1); | ||
expect(getConfirmPasswordField(wrapper)).toHaveLength(1); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.