Implement password change for employee profile
This commit is contained in:
@@ -147,6 +147,10 @@ class EmployeesActionManager extends SubActionManager
|
||||
return new IceResponse(IceResponse::ERROR, "Error occurred while changing password");
|
||||
}
|
||||
|
||||
if (!PasswordManager::verifyPassword($req->current, $user->password)) {
|
||||
return new IceResponse(IceResponse::ERROR, "Current password is incorrect");
|
||||
}
|
||||
|
||||
$passwordStrengthResponse = PasswordManager::isQualifiedPassword($req->pwd);
|
||||
if ($passwordStrengthResponse->getStatus() === IceResponse::ERROR) {
|
||||
return $passwordStrengthResponse;
|
||||
@@ -158,6 +162,6 @@ class EmployeesActionManager extends SubActionManager
|
||||
return new IceResponse(IceResponse::ERROR, $user->ErrorMsg());
|
||||
}
|
||||
|
||||
return new IceResponse(IceResponse::SUCCESS, $user);
|
||||
return new IceResponse(IceResponse::SUCCESS, []);
|
||||
}
|
||||
}
|
||||
|
||||
26
web/api/CustomAction.js
Normal file
26
web/api/CustomAction.js
Normal file
@@ -0,0 +1,26 @@
|
||||
const axios = require('axios');
|
||||
|
||||
class CustomAction {
|
||||
constructor(adapter) {
|
||||
this.adapter = adapter;
|
||||
}
|
||||
|
||||
execute(subAction, module, request, isPost) {
|
||||
if (!isPost) {
|
||||
return axios.get(
|
||||
this.adapter.moduleRelativeURL,
|
||||
{
|
||||
params: {
|
||||
t: this.adapter.table, a: 'ca', sa: subAction, mod: module, req: request,
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return axios.post(this.moduleRelativeURL, {
|
||||
t: this.adapter.table, a: 'ca', sa: subAction, mod: module, req: request,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default CustomAction;
|
||||
232
web/components/UpdatePasswordModal.js
Normal file
232
web/components/UpdatePasswordModal.js
Normal file
@@ -0,0 +1,232 @@
|
||||
import React, {Component} from 'react';
|
||||
import {
|
||||
Form,
|
||||
Modal,
|
||||
Input,
|
||||
Button,
|
||||
message,
|
||||
} from 'antd';
|
||||
import CustomAction from '../api/CustomAction';
|
||||
|
||||
class UpdatePasswordModal extends React.Component {
|
||||
|
||||
state = {
|
||||
loading: false,
|
||||
passwordHasError: false,
|
||||
passwordState: { hasFeedback: false, validateStatus:'', help:'Password must include at least one number, one lowercase letter, one uppercase letter and a symbol' },
|
||||
confirmationHasError: false,
|
||||
confirmationState: { hasFeedback: false, validateStatus:'', help:'' },
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.formRef = React.createRef();
|
||||
this.customAction = new CustomAction(this.props.adapter);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
message.config({
|
||||
top: 40,
|
||||
});
|
||||
}
|
||||
|
||||
clearConfirmFeedback = () => {
|
||||
this.setState({confirmationHasError: false});
|
||||
this.setState({
|
||||
confirmationState: {
|
||||
hasFeedback : false,
|
||||
validateStatus:'',
|
||||
help:'',
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
updatePasswordState(value) {
|
||||
const passwordValidationResult = this.validatePassword(value);
|
||||
if (passwordValidationResult !== null) {
|
||||
this.setState({passwordHasError: true});
|
||||
this.setState({
|
||||
passwordState: {
|
||||
hasFeedback : true,
|
||||
validateStatus:'error',
|
||||
help:passwordValidationResult,
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
} else {
|
||||
this.setState({passwordHasError: false});
|
||||
this.setState({
|
||||
passwordState: {
|
||||
hasFeedback : true,
|
||||
validateStatus:'success',
|
||||
help:'',
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
updateConfirmPasswordState(values) {
|
||||
if (values.confirm !== values.new) {
|
||||
this.setState({confirmationHasError: true});
|
||||
this.setState({
|
||||
confirmationState: {
|
||||
hasFeedback : true,
|
||||
validateStatus:'error',
|
||||
help:'Passwords don\'t match',
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
} else {
|
||||
this.setState({confirmationHasError: false});
|
||||
this.setState({
|
||||
confirmationState: {
|
||||
hasFeedback : false,
|
||||
validateStatus:'',
|
||||
help:'',
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
handleOk = () => {
|
||||
const from = this.formRef.current;
|
||||
from
|
||||
.validateFields()
|
||||
.then((values) => {
|
||||
if (this.updatePasswordState(values.new) && this.updateConfirmPasswordState(values)) {
|
||||
this.updatePassword(values.current, values.new)
|
||||
.then((response) => {
|
||||
const data = response.data;
|
||||
console.log(data);
|
||||
if (data.status === 'SUCCESS') {
|
||||
this.handleCancel();
|
||||
message.success(this.props.adapter.gt('Password updated'));
|
||||
} else {
|
||||
message.error(
|
||||
`${this.props.adapter.gt('Error updating password')}: ${this.props.adapter.gt(data.data)}`
|
||||
);
|
||||
}
|
||||
}).catch((error) => {
|
||||
message.error(
|
||||
`${this.props.adapter.gt('Error updating password')}`
|
||||
);
|
||||
console.log(error.message);
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((info) => {
|
||||
this.setState({ loading: false });
|
||||
});
|
||||
}
|
||||
|
||||
handleCancel = () => {
|
||||
if (this.formRef.current) {
|
||||
this.formRef.current.resetFields();
|
||||
}
|
||||
this.props.closeModal();
|
||||
}
|
||||
|
||||
updatePassword = (oldPassword, newPassword) => {
|
||||
const req = { current: oldPassword ? oldPassword : '', pwd: newPassword };
|
||||
const reqJson = JSON.stringify(req);
|
||||
|
||||
const callBackData = [];
|
||||
callBackData.callBackData = [];
|
||||
callBackData.callBackSuccess = 'changePasswordSuccessCallBack';
|
||||
callBackData.callBackFail = 'changePasswordFailCallBack';
|
||||
|
||||
return this.customAction.execute('changePassword', 'modules=employees', reqJson);
|
||||
|
||||
}
|
||||
|
||||
validatePassword = (password) => {
|
||||
if (password.length < 8) {
|
||||
return this.props.adapter.gt('Password too short');
|
||||
}
|
||||
|
||||
if (password.length > 20) {
|
||||
return this.props.adapter.gt('Password too long');
|
||||
}
|
||||
|
||||
const numberTester = /.*[0-9]+.*$/;
|
||||
if (!password.match(numberTester)) {
|
||||
return this.props.adapter.gt('Password must include at least one number');
|
||||
}
|
||||
|
||||
const lowerTester = /.*[a-z]+.*$/;
|
||||
if (!password.match(lowerTester)) {
|
||||
return this.props.adapter.gt('Password must include at least one lowercase letter');
|
||||
}
|
||||
|
||||
const upperTester = /.*[A-Z]+.*$/;
|
||||
if (!password.match(upperTester)) {
|
||||
return this.props.adapter.gt('Password must include at least one uppercase letter');
|
||||
}
|
||||
|
||||
const symbolTester = /.*[\W]+.*$/;
|
||||
if (!password.match(symbolTester)) {
|
||||
return this.props.adapter.gt('Password must include at least one symbol');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
render() {
|
||||
const layout = {
|
||||
labelCol: { span: 8 },
|
||||
wrapperCol: { span: 16 },
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
visible={this.props.visible}
|
||||
title="Update Password"
|
||||
onOk={this.handleOk}
|
||||
onCancel={this.handleCancel}
|
||||
footer={[
|
||||
<Button key="back" onClick={this.handleCancel}>
|
||||
{this.props.adapter.gt('Cancel')}
|
||||
</Button>,
|
||||
<Button key="submit" type="primary" loading={this.state.loading} onClick={this.handleOk}>
|
||||
{this.props.adapter.gt('Update')}
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<Form {...layout} ref={this.formRef}>
|
||||
<Form.Item label="Current Password" key="current" name="current" >
|
||||
<Input.Password placeholder="current password"/>
|
||||
</Form.Item>
|
||||
{ this.state.passwordHasError &&
|
||||
<Form.Item label="New Password" key="new" name="new" {...this.state.passwordState}>
|
||||
<Input.Password placeholder="new password" onChange={(event) => this.updatePasswordState(event.target.value)}/>
|
||||
</Form.Item>
|
||||
}
|
||||
{ !this.state.passwordHasError &&
|
||||
<Form.Item label="New Password" key="new" name="new" {...this.state.passwordState}>
|
||||
<Input.Password placeholder="new password" onChange={(event) => this.updatePasswordState(event.target.value)}/>
|
||||
</Form.Item>
|
||||
}
|
||||
{ this.state.confirmationHasError &&
|
||||
<Form.Item label="Confirm Password" key="confirm" name="confirm" {...this.state.confirmationState}>
|
||||
<Input.Password placeholder="confirm password" onChange={(event) => this.clearConfirmFeedback()}/>
|
||||
</Form.Item>
|
||||
}
|
||||
{ !this.state.confirmationHasError &&
|
||||
<Form.Item label="Confirm Password" key="confirm" name="confirm" >
|
||||
<Input.Password placeholder="confirm password" onChange={(event) => this.clearConfirmFeedback()}/>
|
||||
</Form.Item>
|
||||
}
|
||||
|
||||
</Form>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default UpdatePasswordModal;
|
||||
@@ -1,37 +1,32 @@
|
||||
import React, {Component} from 'react';
|
||||
import React from 'react';
|
||||
import {
|
||||
Col,
|
||||
Card,
|
||||
Badge,
|
||||
Avatar,
|
||||
Input,
|
||||
Row,
|
||||
Descriptions,
|
||||
Typography,
|
||||
Table,
|
||||
Space,
|
||||
Button,
|
||||
Tag,
|
||||
message,
|
||||
Tabs,
|
||||
Spin,
|
||||
Skeleton
|
||||
} from 'antd';
|
||||
import {
|
||||
FilterOutlined,
|
||||
EditOutlined,
|
||||
PhoneTwoTone,
|
||||
MailTwoTone,
|
||||
SyncOutlined,
|
||||
LockOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import TagList from "../../../../components/TagList";
|
||||
const { Search } = Input;
|
||||
import UpdatePasswordModal from "../../../../components/UpdatePasswordModal";
|
||||
const { Title, Text } = Typography;
|
||||
const { TabPane } = Tabs;
|
||||
|
||||
class EmployeeProfile extends React.Component {
|
||||
state = {
|
||||
loading: true,
|
||||
showPasswordResetModal: false,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
@@ -42,6 +37,10 @@ class EmployeeProfile extends React.Component {
|
||||
this.setState({ loading: value });
|
||||
}
|
||||
|
||||
setShowPasswordUpdate(value) {
|
||||
this.setState({ showPasswordResetModal: value });
|
||||
}
|
||||
|
||||
updateProfileImage() {
|
||||
showUploadDialog(
|
||||
`profile_image_${this.props.element.id}_${(new Date()).getTime()}`,
|
||||
@@ -71,6 +70,33 @@ class EmployeeProfile extends React.Component {
|
||||
</>);
|
||||
}
|
||||
|
||||
getEditButtonJsxWithPassword() {
|
||||
return (<>
|
||||
{this.state.loading &&
|
||||
<Tag icon={<SyncOutlined spin/>} color="processing">
|
||||
{this.props.adapter.gt('Edit')}
|
||||
</Tag>
|
||||
}
|
||||
{!this.state.loading &&
|
||||
<Tag icon={<EditOutlined/>} color="processing"
|
||||
onClick={() => modJs.edit(this.props.element.id)}>
|
||||
{this.props.adapter.gt('Edit')}
|
||||
</Tag>
|
||||
}
|
||||
<Tag icon={<LockOutlined/>} color="volcano" onClick={() => this.setShowPasswordUpdate(true)}>
|
||||
{this.props.adapter.gt('Update Password')}
|
||||
</Tag>
|
||||
</>);
|
||||
}
|
||||
|
||||
getUpdatePasswordButtonJsx() {
|
||||
return (<>
|
||||
<Tag icon={<SyncOutlined spin/>} color="processing">
|
||||
{this.props.adapter.gt('Update Password')}
|
||||
</Tag>
|
||||
</>);
|
||||
}
|
||||
|
||||
getTabViewEmployeeFilterButtonJsx(tab) {
|
||||
return (
|
||||
<Tag icon={<EditOutlined/>} color="processing"
|
||||
@@ -86,10 +112,15 @@ class EmployeeProfile extends React.Component {
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<UpdatePasswordModal
|
||||
visible={this.state.showPasswordResetModal}
|
||||
closeModal={() => {this.setState({ showPasswordResetModal: false })}}
|
||||
adapter={this.props.adapter}
|
||||
/>
|
||||
<Row direction="vertical" style={{width: '100%', padding: '10px'}} gutter={24}>
|
||||
<Col span={24}>
|
||||
<Card title={this.props.adapter.gt('Employee Profile')}
|
||||
extra={this.getEditButtonJsx()}
|
||||
extra={this.getEditButtonJsxWithPassword()}
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
<Space size={'large'}>
|
||||
|
||||
Reference in New Issue
Block a user