mirror of
https://github.com/getredash/redash.git
synced 2026-05-09 21:02:27 -04:00
* Update DynamicForm export * Move UserShow to users folder * Migrate User profile header and create DynamicForm for basic data * Update UserShow to use UserProfile prop * Add API Key input * Add handler to regenerate API Key button * Handle user profile save * Add readOnly prop to DynamicForm and begin disabled user behavior * Add Change Password Modal * Remove action buttons for disabled users * Add send password reset behavior * Add minLength and password comparison to Password Modal * Resend Invitation button * Add Convert User Info * Fix UserShow test * Some code updates * Add enable/disable user button * Add UserPolicy as an idea * Remove UserPolicy * Create Edit Profile spec * Move User profile screenshot to Edit Profile Spec * Add tests for saving user and changing password errors * CC is back :) - Fix trailing spaces * Add test for succesful password update * A few improvements from code review * Remove Toggle User button when seeing your own profile * Create InputWithCopy * Fix possible errors when network is off and improve Email not sent alert * Add default response object for $http possible errors * Changes in UserEdit - removed onClick from methods name - regenerate API Key now uses InputWithCopy - Password title added * Update UserEdit render behavior and styling - Password title changed to h5 - change rendering rules for actions - Password modal is now closed when password is changed - change DynamicForm readOnly to the fields and add hideSubmitButton * Create ChangePasswordDialog and update UserEdit * Fix possible console error * Remove password match assertion from spec * Fix typo
147 lines
4.9 KiB
JavaScript
147 lines
4.9 KiB
JavaScript
import React from 'react';
|
|
import Form from 'antd/lib/form';
|
|
import Modal from 'antd/lib/modal';
|
|
import Input from 'antd/lib/input';
|
|
import { isFunction } from 'lodash';
|
|
import { User } from '@/services/user';
|
|
import { toastr } from '@/services/ng';
|
|
import { UserProfile } from '../proptypes';
|
|
import { wrap as wrapDialog, DialogPropType } from '@/components/DialogWrapper';
|
|
|
|
class ChangePasswordDialog extends React.Component {
|
|
static propTypes = {
|
|
user: UserProfile.isRequired,
|
|
dialog: DialogPropType.isRequired,
|
|
};
|
|
|
|
constructor(props) {
|
|
super(props);
|
|
this.state = {
|
|
currentPassword: { value: '', error: null, touched: false },
|
|
newPassword: { value: '', error: null, touched: false },
|
|
repeatPassword: { value: '', error: null, touched: false },
|
|
updatingPassword: false,
|
|
};
|
|
}
|
|
|
|
fieldError = (name, value) => {
|
|
if (value.length === 0) return 'This field is required.';
|
|
if (name !== 'currentPassword' && value.length < 6) return 'This field is too short.';
|
|
if (name === 'repeatPassword' && value !== this.state.newPassword.value) return 'Passwords don\'t match';
|
|
return null;
|
|
};
|
|
|
|
validateFields = (callback) => {
|
|
const { currentPassword, newPassword, repeatPassword } = this.state;
|
|
|
|
const errors = {
|
|
currentPassword: this.fieldError('currentPassword', currentPassword.value),
|
|
newPassword: this.fieldError('newPassword', newPassword.value),
|
|
repeatPassword: this.fieldError('repeatPassword', repeatPassword.value),
|
|
};
|
|
|
|
this.setState({
|
|
currentPassword: { ...currentPassword, error: errors.currentPassword },
|
|
newPassword: { ...newPassword, error: errors.newPassword },
|
|
repeatPassword: { ...repeatPassword, error: errors.repeatPassword },
|
|
});
|
|
|
|
if (isFunction(callback)) {
|
|
if (errors.currentPassword || errors.newPassword || errors.repeatPassword) {
|
|
callback(errors);
|
|
} else callback(null);
|
|
}
|
|
}
|
|
|
|
updatePassword = () => {
|
|
const { currentPassword, newPassword, updatingPassword } = this.state;
|
|
|
|
if (!updatingPassword) {
|
|
this.validateFields((err) => {
|
|
if (!err) {
|
|
const userData = {
|
|
id: this.props.user.id,
|
|
old_password: currentPassword.value,
|
|
password: newPassword.value,
|
|
};
|
|
|
|
this.setState({ updatingPassword: true });
|
|
|
|
User.save(userData, () => {
|
|
toastr.success('Saved.');
|
|
this.props.dialog.close({ success: true });
|
|
}, (error = {}) => {
|
|
toastr.error(error.data && error.data.message || 'Failed saving.');
|
|
this.setState({ updatingPassword: false });
|
|
});
|
|
} else {
|
|
this.setState(prevState => ({
|
|
currentPassword: { ...prevState.currentPassword, touched: true },
|
|
newPassword: { ...prevState.newPassword, touched: true },
|
|
repeatPassword: { ...prevState.repeatPassword, touched: true },
|
|
}));
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
handleChange = (e) => {
|
|
const { name, value } = e.target;
|
|
const { error } = this.state[name];
|
|
|
|
this.setState({ [name]: { value, error, touched: true } }, () => {
|
|
this.validateFields();
|
|
});
|
|
}
|
|
|
|
render() {
|
|
const { dialog } = this.props;
|
|
const { currentPassword, newPassword, repeatPassword, updatingPassword } = this.state;
|
|
|
|
const formItemProps = { className: 'm-b-10', required: true };
|
|
|
|
const inputProps = {
|
|
onChange: this.handleChange,
|
|
onPressEnter: this.updatePassword,
|
|
};
|
|
|
|
return (
|
|
<Modal
|
|
{...dialog.props}
|
|
okButtonProps={{ loading: updatingPassword }}
|
|
onOk={this.updatePassword}
|
|
title="Change Password"
|
|
>
|
|
<Form layout="vertical">
|
|
<Form.Item
|
|
{...formItemProps}
|
|
validateStatus={currentPassword.touched && currentPassword.error ? 'error' : null}
|
|
help={currentPassword.touched ? currentPassword.error : null}
|
|
label="Current Password"
|
|
>
|
|
<Input.Password {...inputProps} name="currentPassword" data-test="CurrentPassword" autoFocus />
|
|
</Form.Item>
|
|
<Form.Item
|
|
{...formItemProps}
|
|
validateStatus={newPassword.touched && newPassword.error ? 'error' : null}
|
|
help={newPassword.touched ? newPassword.error : null}
|
|
label="New Password"
|
|
>
|
|
<Input.Password {...inputProps} name="newPassword" data-test="NewPassword" />
|
|
</Form.Item>
|
|
<Form.Item
|
|
{...formItemProps}
|
|
validateStatus={repeatPassword.touched && repeatPassword.error ? 'error' : null}
|
|
help={repeatPassword.touched ? repeatPassword.error : null}
|
|
label="Repeat New Password"
|
|
>
|
|
<Input.Password {...inputProps} name="repeatPassword" data-test="RepeatPassword" />
|
|
</Form.Item>
|
|
</Form>
|
|
</Modal>
|
|
);
|
|
}
|
|
}
|
|
|
|
export default wrapDialog(ChangePasswordDialog);
|