Merge branch 'master' into 'master'

Modify Role view and User View

See merge request entgra/carbon-device-mgt!392
feature/appm-store/pbac
Dharmakeerthi Lasantha 5 years ago
commit e61397539a

@ -0,0 +1,340 @@
import React from 'react';
import {Button, Form, Input, message, Modal, notification, Select, Tree} from "antd";
import {withConfigContext} from "../../context/ConfigContext";
import axios from "axios";
const {Option} = Select;
const {TreeNode} = Tree;
class AddRole extends React.Component {
constructor(props) {
super(props);
this.config = this.props.context;
this.expandKeys = [];
this.state = {
isAddRoleModalVisible: false,
isAddPermissionModalVisible: false,
roleName: '',
users: [],
nodeList: [],
expandedKeys: [],
autoExpandParent: true,
checkedKeys: [],
isNodeList: false,
}
}
openAddModal = () => {
this.setState({
isAddRoleModalVisible: true
});
};
onCancelHandler = e => {
this.setState({
isAddRoleModalVisible: false,
isAddPermissionModalVisible: false,
});
};
getCheckedPermissionsList = (data) =>{
data.forEach(item => {
if (item !== null) {
this.expandKeys.push(item.resourcePath);
this.getCheckedPermissionsList(item.nodeList);
}else{
return null;
}
});
};
onAddRole = e => {
this.props.form.validateFields((err, values) => {
if (!err) {
this.onConfirmAddRole(values);
}
console.log(values);
});
};
onExpand = expandedKeys => {
this.setState({
expandedKeys,
autoExpandParent: false,
});
};
onCheck = checkedKeys => {
this.setState({checkedKeys});
};
onConfirmAddRole = (value) => {
const roleData = {
roleName: value.roleName,
users: value.users,
};
this.setState({
roleName: value.roleName,
});
axios.post(
window.location.origin + this.config.serverConfig.invoker.uri +
this.config.serverConfig.invoker.deviceMgt +
"/roles",
roleData,
{headers: {'Content-Type': 'application-json'}}
).then(res => {
if (res.status === 201) {
this.props.fetchUsers();
this.setState({
isAddRoleModalVisible: false,
isAddPermissionModalVisible: true,
});
notification["success"]({
message: "Done",
duration: 4,
description:
"Successfully added the role.",
});
this.loadPermissionList();
}
}).catch((error) => {
if (error.hasOwnProperty("response") && error.response.status === 401) {
//todo display a popop with error
message.error('You are not logged in');
window.location.href = window.location.origin + '/entgra/login';
} else {
notification["error"]({
message: "There was a problem",
duration: 0,
description:
"Error occurred while trying to add role.",
});
}
});
};
renderTreeNodes = (data) => {
return data.map(item => {
if (item !== null) {
if (item.hasOwnProperty("nodeList")) {
return (
<TreeNode title={item.displayName} key={item.resourcePath} dataRef={item}>
{this.renderTreeNodes(item.nodeList)}
</TreeNode>
);
}
return <TreeNode key={item.resourcePath} {...item}/>;
}
else{
return <TreeNode/>;
}
});
};
onAssignPermissions = () =>{
const roleData = {
roleName : this.state.roleName,
permissions : this.state.checkedKeys
};
axios.put(
window.location.origin + this.config.serverConfig.invoker.uri +
this.config.serverConfig.invoker.deviceMgt +
"/roles/"+ this.state.roleName,
roleData,
{headers: {'Content-Type' : 'application-json'}}
).then(res => {
if (res.status === 200) {
this.props.fetchUsers();
notification["success"]({
message: "Done",
duration: 4,
description:
"Successfully Updated the Permissions.",
});
this.setState({
isAddPermissionModalVisible : false
});
}
}).catch((error) => {
if (error.hasOwnProperty("response") && error.response.status === 401) {
//todo display a popop with error
message.error('You are not logged in');
window.location.href = window.location.origin + '/entgra/login';
} else {
notification["error"]({
message: "There was a problem",
duration: 0,
description:
"Error occurred while trying to add permissions.",
});
}
});
};
loadPermissionList = () => {
let apiURL = window.location.origin + this.config.serverConfig.invoker.uri +
this.config.serverConfig.invoker.deviceMgt + "/roles/" + this.state.roleName + "/permissions";
axios.get(apiURL).then(res => {
if (res.status === 200) {
this.getCheckedPermissionsList(res.data.data.nodeList);
this.setState({
nodeList: res.data.data.nodeList,
isNodeList: true,
expandedKeys : this.expandKeys
});
}
}).catch((error) => {
if (error.hasOwnProperty("response") && error.response.status === 401) {
//todo display a popop with error
message.error('You are not logged in');
window.location.href = window.location.origin + '/entgra/login';
} else {
notification["error"]({
message: "There was a problem",
duration: 0,
description: "Error occurred while trying to load permission.",
});
}
})
};
loadUsersList = (value) => {
let apiURL = window.location.origin + this.config.serverConfig.invoker.uri +
this.config.serverConfig.invoker.deviceMgt + "/users/search/usernames?filter=" + value + "&domain=Primary";
axios.get(apiURL).then(res => {
if (res.status === 200) {
let user = JSON.parse(res.data.data);
let users = [];
for (let i = 0; i < user.length; i++) {
users.push(<Option key={user[i].username}>{user[i].username}</Option>);
}
this.setState({
users: users
});
}
}).catch((error) => {
if (error.hasOwnProperty("response") && error.response.status === 401) {
//todo display a popop with error
message.error('You are not logged in');
window.location.href = window.location.origin + '/entgra/login';
} else {
notification["error"]({
message: "There was a problem",
duration: 0,
description: "Error occurred while trying to load users.",
});
}
})
};
render() {
const {getFieldDecorator} = this.props.form;
return (
<div>
<div>
<Button type="primary" icon="plus" size={"default"} onClick={this.openAddModal}
style={{marginBottom: '10px'}}>
Add Role
</Button>
</div>
<div>
<Modal
title="ADD NEW ROLE"
width="40%"
visible={this.state.isAddRoleModalVisible}
onOk={this.onAddRole}
onCancel={this.onCancelHandler}
footer={[
<Button key="cancel" onClick={this.onCancelHandler}>
Cancel
</Button>,
<Button key="submit" type="primary" onClick={this.onAddRole}>
Add Role
</Button>,
]}>
<div style={{alignItems: "center"}}>
<p>Create new user on IoT Server.</p>
<Form
labelCol={{span: 5}}
wrapperCol={{span: 18}}>
<Form.Item label="User Store Domain" style={{display: "block"}}>
{getFieldDecorator('userStoreDomain', {
initialValue: 'PRIMARY'
})(
<Select>
<Option key="PRIMARY">PRIMARY</Option>
</Select>
)}
</Form.Item>
<Form.Item label="Role Name" style={{display: "block"}}>
{getFieldDecorator('roleName', {
rules: [
{
pattern: new RegExp("^(((?!(\\@|\\/|\\s)).){3,})*$"),
message: 'Role name should be in minimum 3 characters long and not ' +
'include any whitespaces or @ or /',
},
{
required: true,
message: 'This field is required.',
},
],
})(<Input/>)}
</Form.Item>
<Form.Item label="User List" style={{display: "block"}}>
{getFieldDecorator('users', {})(<Select
mode="multiple"
style={{width: '100%'}}
onSearch={this.loadUsersList}>
{this.state.users}
</Select>)}
</Form.Item>
</Form>
</div>
</Modal>
</div>
<div>
<Modal
title="CHANGE ROLE PERMISSION"
width="40%"
visible={this.state.isAddPermissionModalVisible}
onOk={this.onAssignPermissions}
onCancel={this.onCancelHandler}
bodyStyle={{overflowY:"scroll", maxHeight:'500px', marginLeft:'10px'}}
footer={[
<Button key="cancel" onClick={this.onCancelHandler}>
Cancel
</Button>,
<Button key="submit" type="primary" onClick={this.onAssignPermissions}>
Assign
</Button>,
]}>
<div style={{alignItems: "center"}}>
<div>
{(this.state.isNodeList) && (
<Tree
checkable
onExpand={this.onExpand}
expandedKeys={this.state.expandedKeys}
autoExpandParent={this.state.autoExpandParent}
onCheck={this.onCheck}
checkedKeys={this.state.checkedKeys}>
{this.renderTreeNodes(this.state.nodeList)}
</Tree>
)}
</div>
</div>
</Modal>
</div>
</div>
);
}
}
export default withConfigContext(Form.create({name: 'add-role'})(AddRole))

@ -0,0 +1,428 @@
import React from 'react';
import {
Button,
Divider,
Form,
Icon,
Input,
message,
Modal,
notification,
Popconfirm,
Select,
Tooltip, Tree,
Typography
} from "antd";
import axios from "axios";
import {withConfigContext} from "../../context/ConfigContext";
const { Option } = Select;
const {Text} = Typography;
const { TreeNode } = Tree;
class RoleAction extends React.Component {
constructor(props) {
super(props);
this.config = this.props.context;
this.selected = [];
this.expandKeys = [];
this.state = {
roleData: [],
nodeList : [],
isNodeList: false,
users : [],
isEditRoleModalVisible: false,
isEditPermissionModalVisible: false,
expandedKeys: [],
autoExpandParent: true,
checkedKeys: [],
};
}
openEditRoleModal = () =>{
let apiUrl = window.location.origin + this.config.serverConfig.invoker.uri +
this.config.serverConfig.invoker.deviceMgt +
"/roles/"+ this.props.data;
axios.get(apiUrl).then(res => {
if (res.status === 200) {
this.setState({
roleData : res.data.data,
isEditRoleModalVisible: true,
});
}
}).catch((error) => {
if (error.hasOwnProperty("response") && error.response.status === 401) {
//todo display a popop with error
message.error('You are not logged in');
window.location.href = window.location.origin + '/entgra/login';
} else {
notification["error"]({
message: "There was a problem",
duration: 0,
description:"Error occurred while trying to load role.",
});
}
});
};
openEditPermissionModal =()=>{
this.loadPermissionList();
this.setState({
isEditPermissionModalVisible: true,
});
};
loadPermissionList = () => {
let apiURL = window.location.origin + this.config.serverConfig.invoker.uri +
this.config.serverConfig.invoker.deviceMgt + "/roles/"+this.props.data+"/permissions";
axios.get(apiURL).then(res => {
if (res.status === 200) {
this.getCheckedPermissions(res.data.data.nodeList);
this.setState({
nodeList : res.data.data.nodeList,
isNodeList: true,
checkedKeys : this.selected,
expandedKeys : this.expandKeys
});
}
}).catch((error) => {
if (error.hasOwnProperty("response") && error.response.status === 401) {
//todo display a popop with error
message.error('You are not logged in');
window.location.href = window.location.origin + '/entgra/login';
} else {
notification["error"]({
message: "There was a problem",
duration: 0,
description:"Error occurred while trying to load permission.",
});
}
})
};
getCheckedPermissions = (data) =>{
data.forEach(item => {
if (item !== null) {
this.expandKeys.push(item.resourcePath);
if (item.isSelected) {
this.selected.push(item.resourcePath);
}
this.getCheckedPermissions(item.nodeList);
}else{
return null;
}
});
};
onExpand = expandedKeys => {
this.setState({
expandedKeys,
autoExpandParent: false,
});
};
onCheck = checkedKeys => {
this.setState({checkedKeys});
};
renderTreeNodes = (data) => {
return data.map(item => {
if (item !== null) {
if (item.hasOwnProperty("nodeList")) {
return (
<TreeNode title={item.displayName} key={item.resourcePath} dataRef={item}>
{this.renderTreeNodes(item.nodeList)}
</TreeNode>
);
}
return <TreeNode key={item.resourcePath} {...item}/>;
} else{
return <TreeNode/>;
}
});
};
onUpdateRole = e => {
this.props.form.validateFields((err, values) => {
if (!err) {
this.onConfirmUpdateRole(values);
}
console.log(values);
});
};
onCancelHandler = e =>{
this.setState({
isEditRoleModalVisible: false,
isEditPermissionModalVisible:false,
})
};
onConfirmUpdateRole = (value) =>{
const roleData = {
roleName : value.roleName,
users : value.users,
};
axios.put(
window.location.origin + this.config.serverConfig.invoker.uri +
this.config.serverConfig.invoker.deviceMgt +
"/roles/"+ this.props.data,
roleData,
{headers: {'Content-Type' : 'application-json'}}
).then(res => {
if (res.status === 200) {
this.props.fetchUsers();
this.setState({
isEditRoleModalVisible: false,
});
notification["success"]({
message: "Done",
duration: 4,
description:
"Successfully Updated the role.",
});
}
}).catch((error) => {
if (error.hasOwnProperty("response") && error.response.status === 401) {
//todo display a popop with error
message.error('You are not logged in');
window.location.href = window.location.origin + '/entgra/login';
} else {
notification["error"]({
message: "There was a problem",
duration: 0,
description:
"Error occurred while trying to add role.",
});
}
});
};
onAssignPermission = () =>{
const roleData = {
roleName : this.props.data,
permissions : this.state.checkedKeys
};
axios.put(
window.location.origin + this.config.serverConfig.invoker.uri +
this.config.serverConfig.invoker.deviceMgt +
"/roles/"+ this.props.data,
roleData,
{headers: {'Content-Type' : 'application-json'}}
).then(res => {
if (res.status === 200) {
this.props.fetchUsers();
notification["success"]({
message: "Done",
duration: 4,
description:
"Successfully Updated the Permissions.",
});
this.setState({
isEditPermissionModalVisible : false
});
}
}).catch((error) => {
if (error.hasOwnProperty("response") && error.response.status === 401) {
//todo display a popop with error
message.error('You are not logged in');
window.location.href = window.location.origin + '/entgra/login';
} else {
notification["error"]({
message: "There was a problem",
duration: 0,
description:
"Error occurred while trying to add permissions.",
});
}
});
};
loadUsersList = (value) => {
let apiURL = window.location.origin + this.config.serverConfig.invoker.uri +
this.config.serverConfig.invoker.deviceMgt + "/users/search/usernames?filter="+value+"&domain=Primary";
axios.get(apiURL).then(res => {
if (res.status === 200) {
let user = JSON.parse(res.data.data);
let users = [];
for(let i=0; i<user.length; i++){
users.push(<Option key={user[i].username}>{user[i].username}</Option>);
}
this.setState({
users : users
});
}
}).catch((error) => {
if (error.hasOwnProperty("response") && error.response.status === 401) {
//todo display a popop with error
message.error('You are not logged in');
window.location.href = window.location.origin + '/entgra/login';
} else {
notification["error"]({
message: "There was a problem",
duration: 0,
description:"Error occurred while trying to load users.",
});
}
})
};
onDeleteRole = () => {
axios.delete(
window.location.origin + this.config.serverConfig.invoker.uri +
this.config.serverConfig.invoker.deviceMgt +
"/roles/" + this.props.data,
{headers: {'Content-Type': 'application/json'}}
).then(res => {
if (res.status === 200) {
this.props.fetchUsers();
notification["success"]({
message: "Done",
duration: 4,
description:
"Successfully deleted the Role.",
});
}
}).catch((error) => {
if (error.hasOwnProperty("response") && error.response.status === 401) {
//todo display a popop with error
message.error('You are not logged in');
window.location.href = window.location.origin + '/entgra/login';
} else {
notification["error"]({
message: "There was a problem",
duration: 0,
description:
"Error occurred while trying to delete role.",
});
}
});
};
render() {
const isAdminRole = this.props.data ==="admin";
const { getFieldDecorator } = this.props.form;
return (
<div>
<div style={{display:isAdminRole ? "none" : "inline"}}>
<Tooltip placement="top" title={"Edit Role"}>
<a><Icon type="edit" onClick={this.openEditRoleModal}/></a>
</Tooltip>
<Divider type="vertical" />
<Tooltip placement="top" title={"Edit Permissions"}>
<a><Icon type="file-add" onClick={this.openEditPermissionModal}/></a>
</Tooltip>
<Divider type="vertical" />
<Tooltip placement="bottom" title={"Remove Role"}>
<Popconfirm
placement="top"
title={"Are you sure?"}
onConfirm={this.onDeleteRole}
okText="Ok"
cancelText="Cancel">
<a><Text type="danger"><Icon type="delete"/></Text></a>
</Popconfirm>
</Tooltip>
</div>
<div>
<Modal
title="EDIT ROLE"
width="40%"
visible={this.state.isEditRoleModalVisible}
onOk={this.onUpdateRole}
onCancel={this.onCancelHandler}
footer={[
<Button key="cancel" onClick={this.onCancelHandler}>
Cancel
</Button>,
<Button key="submit" type="primary" onClick={this.onUpdateRole}>
Add Role
</Button>,
]}>
<div style={{alignItems:"center"}}>
<p>Create new user on IoT Server.</p>
<Form
labelCol={{ span: 5 }}
wrapperCol={{ span: 18 }}>
<Form.Item label="User Store Domain" style={{display:"block"}}>
{getFieldDecorator('userStoreDomain', {
initialValue : 'PRIMARY'
})(
<Select>
<Option key="PRIMARY">PRIMARY</Option>
</Select>
)}
</Form.Item>
<Form.Item label="Role Name" style={{display:"block"}}>
{getFieldDecorator('roleName', {
initialValue: this.state.roleData.roleName,
rules: [
{
pattern : new RegExp("^(((?!(\\@|\\/|\\s)).){3,})*$"),
message: 'Role name should be in minimum 3 characters long and not ' +
'include any whitespaces or @ or /',
},
{
required: true,
message: 'This field is required.',
},
],
})(<Input/>)}
</Form.Item>
<Form.Item label="User List" style={{display:"block"}}>
{getFieldDecorator('users', {
initialValue: this.state.roleData.users,
})(<Select
mode="multiple"
style={{ width: '100%' }}
onSearch={this.loadUsersList}>
{this.state.users}
</Select>)}
</Form.Item>
</Form>
</div>
</Modal>
</div>
<div>
<Modal
title="CHANGE ROLE PERMISSION"
width="40%"
visible={this.state.isEditPermissionModalVisible}
onOk={this.onAssignPermission}
onCancel={this.onCancelHandler}
footer={[
<Button key="cancel" onClick={this.onCancelHandler}>
Cancel
</Button>,
<Button key="submit" type="primary" onClick={this.onAssignPermission}>
Assign
</Button>,
]}
bodyStyle={{overflowY:"scroll", maxHeight:'500px', marginLeft:'10px'}}>
<div>
{(this.state.isNodeList) &&(
<Tree
checkable
onExpand={this.onExpand}
expandedKeys={this.state.expandedKeys}
autoExpandParent={this.state.autoExpandParent}
onCheck={this.onCheck}
checkedKeys={this.state.checkedKeys}>
{this.renderTreeNodes(this.state.nodeList)}
</Tree>
)}
</div>
</Modal>
</div>
</div>
);
}
}
export default withConfigContext(Form.create({name: 'role-actions'})(RoleAction));

@ -18,24 +18,19 @@
import React from "react"; import React from "react";
import axios from "axios"; import axios from "axios";
import {Card, Col, Icon, message, notification, Row, Typography} from "antd"; import {
Button,
message,
Modal,
notification,
Table, List
} from "antd";
import TimeAgo from 'javascript-time-ago' import TimeAgo from 'javascript-time-ago'
// Load locale-specific relative date/time formatting rules. // Load locale-specific relative date/time formatting rules.
import en from 'javascript-time-ago/locale/en' import en from 'javascript-time-ago/locale/en'
import {withConfigContext} from "../../context/ConfigContext"; import {withConfigContext} from "../../context/ConfigContext";
import AddRole from "./AddRole";
const {Text} = Typography; import RoleAction from "./RoleAction";
let config = null;
let apiUrl;
const columns = [
{
title: 'User Name',
dataIndex: 'username',
width: 100,
}
];
const getTimeAgo = (time) => { const getTimeAgo = (time) => {
const timeAgo = new TimeAgo('en-US'); const timeAgo = new TimeAgo('en-US');
@ -45,23 +40,76 @@ const getTimeAgo = (time) => {
class RolesTable extends React.Component { class RolesTable extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
config = this.props.context; this.config = this.props.context;
TimeAgo.addLocale(en); TimeAgo.addLocale(en);
this.state = { this.state = {
data: [], data: [],
pagination: {}, pagination: {},
loading: false, loading: false,
selectedRows: [] selectedRows: [],
userData: [],
users : [],
isEditRoleModalVisible: false,
isUserListModalVisible :false,
}; };
} }
rowSelection = {
onChange: (selectedRowKeys, selectedRows) => {
this.setState({
selectedRows: selectedRows
})
}
};
componentDidMount() { componentDidMount() {
this.fetchUsers(); this.fetchUsers();
} }
openUserListModal = (event) => {
let apiUrl = window.location.origin + this.config.serverConfig.invoker.uri +
this.config.serverConfig.invoker.deviceMgt +
"/roles/"+ event;
//send request to the invokerss
axios.get(apiUrl).then(res => {
if (res.status === 200) {
this.setState({
userData : res.data.data.users,
isUserListModalVisible: true,
});
}
}).catch((error) => {
if (error.hasOwnProperty("response") && error.response.status === 401) {
//todo display a popop with error
message.error('You are not logged in');
window.location.href = window.location.origin + '/entgra/login';
} else {
notification["error"]({
message: "There was a problem",
duration: 0,
description:"Error occurred while trying to load users.",
});
}
});
};
handleOk = e => {
this.setState({
isUserListModalVisible: false,
});
};
handleCancel = e => {
this.setState({
isUserListModalVisible: false,
});
};
//fetch data from api //fetch data from api
fetchUsers = (params = {}) => { fetchUsers = (params = {}) => {
const config = this.props.context; // const config = this.props.context;
this.setState({loading: true}); this.setState({loading: true});
// get current page // get current page
@ -75,8 +123,8 @@ class RolesTable extends React.Component {
const encodedExtraParams = Object.keys(extraParams) const encodedExtraParams = Object.keys(extraParams)
.map(key => key + '=' + extraParams[key]).join('&'); .map(key => key + '=' + extraParams[key]).join('&');
apiUrl = window.location.origin + config.serverConfig.invoker.uri + let apiUrl = window.location.origin + this.config.serverConfig.invoker.uri +
config.serverConfig.invoker.deviceMgt + this.config.serverConfig.invoker.deviceMgt +
"/roles"; "/roles";
//send request to the invokerss //send request to the invokerss
@ -124,30 +172,77 @@ class RolesTable extends React.Component {
render() { render() {
const {data, pagination, loading, selectedRows} = this.state; const {data, pagination, loading, selectedRows} = this.state;
const { Meta } = Card; const columns = [
const itemCard = data.map((data) => {
<Col span={5} key={data}> title: 'Role Name',
<Card dataIndex: '',
size="default" key: "role",
style={{ width: 200 }} width: "60%",
bordered={true} },
actions={[ {
<Icon type="setting" key="setting" />, title: 'View',
<Icon type="edit" key="edit" />,]} dataIndex: '',
> key: 'users',
<Meta render: (id, row) =>
avatar={<Icon type="book" key="roles"/>} <Button
title={data} type="primary"
/> size={"small"}
</Card> icon="book"
</Col> onClick={()=>this.openUserListModal(row)}>Users</Button>
);
},
{
title: 'Action',
dataIndex: 'id',
key: 'action',
render: (id, row) => (
<span>
<RoleAction data={row} fetchUsers={this.fetchUsers}/>
</span>
),
},
];
return ( return (
<div style={{ background: '#ECECEC', padding: '20px' }}> <div>
<Row gutter={16}> <div style={{background: '#f0f2f5'}}>
{itemCard} <AddRole fetchUsers={this.fetchUsers}/>
</Row> </div>
<div>
<Table
columns={columns}
rowKey={record => (record)}
dataSource={data}
pagination={{
...pagination,
size: "small",
// position: "top",
showTotal: (total, range) => `showing ${range[0]}-${range[1]} of ${total} groups`
// showQuickJumper: true
}}
loading={loading}
onChange={this.handleTableChange}
rowSelection={this.rowSelection}
/>
</div>
<div>
<Modal
title="USERS"
width="900px"
visible={this.state.isUserListModalVisible}
onOk={this.handleOk}
onCancel={this.handleCancel} >
<div>
<List
size="small"
bordered
dataSource={this.state.userData}
renderItem={item => <List.Item>{item}</List.Item>}/>
</div> </div>
</Modal>
</div>
</div>
); );
} }
} }

@ -0,0 +1,423 @@
import React from 'react';
import {
Button,
Divider,
Form,
Icon,
Input,
message,
Modal,
notification,
Popconfirm,
Select,
Tooltip,
Typography } from "antd";
import axios from "axios";
import {withConfigContext} from "../../context/ConfigContext";
const { Option } = Select;
const {Text} = Typography;
class UserActions extends React.Component {
constructor(props) {
super(props);
this.config = this.props.context;
this.state = {
isEditModalVisible: false,
isResetPasswordModalVisible: false,
rolesData: [],
}
}
openEditModal = () =>{
this.setState({
isEditModalVisible: true,
});
this.fetchRoles(this.props.data.username);
};
openPasswordResetModal = () =>{
this.setState({
isResetPasswordModalVisible: true,
})
};
onCancelHandler = () =>{
this.setState({
isEditModalVisible: false,
isResetPasswordModalVisible: false,
})
};
compareToFirstPassword = (rule, value, callback) => {
if (value && value !== this.props.form.getFieldValue('password')) {
callback('New password doesn\'t match the confirmation.');
} else {
callback();
}
};
onSavePassword = () => {
this.props.form.validateFields((['password', 'confirmPassword']),(err, values) => {
if (!err) {
this.onResetPassword(values);
}
});
};
onResetPassword = (value) =>{
const password = {
newPassword : value.password,
};
axios.post(
window.location.origin + this.config.serverConfig.invoker.uri +
this.config.serverConfig.invoker.deviceMgt +
"/admin/users/"+this.props.data.username+"/credentials",
password,
{headers: {'Content-Type' : 'application-json'}}
).then(res => {
if (res.status === 200) {
this.props.fetchUsers();
this.setState({
isResetPasswordModalVisible: false,
});
notification["success"]({
message: "Done",
duration: 4,
description:
"Successfully reset the password",
});
}
}).catch((error) => {
if (error.hasOwnProperty("response") && error.response.status === 401) {
//todo display a popop with error
message.error('You are not logged in');
window.location.href = window.location.origin + '/entgra/login';
} else {
notification["error"]({
message: "There was a problem",
duration: 0,
description:
"Error occurred while trying to reset password.",
});
}
});
};
componentDidMount() {
this.getRole();
}
getRole = () => {
let apiURL = window.location.origin + this.config.serverConfig.invoker.uri +
this.config.serverConfig.invoker.deviceMgt + "/roles?user-store=PRIMARY&limit=100";
axios.get(apiURL).then(res => {
if (res.status === 200) {
const roles = [];
for(let i=0; i<res.data.data.roles.length ; i++){
roles.push(<Option key={res.data.data.roles[i]}>{res.data.data.roles[i]}</Option>);
}
this.setState({
roles : roles
})
}
}).catch((error) => {
if (error.hasOwnProperty("response") && error.response.status === 401) {
//todo display a popop with error
message.error('You are not logged in');
window.location.href = window.location.origin + '/entgra/login';
} else {
notification["error"]({
message: "There was a problem",
duration: 0,
description:"Error occurred while trying to load roles.",
});
}
})
};
onConfirmDeleteUser = () => {
axios.delete(
window.location.origin + this.config.serverConfig.invoker.uri +
this.config.serverConfig.invoker.deviceMgt +
"/users/" + this.props.data.username,
{headers: {'Content-Type': 'application/json'}}
).then(res => {
if (res.status === 200) {
this.props.fetchUsers();
notification["success"]({
message: "Done",
duration: 4,
description:
"Successfully deleted the user.",
});
}
}).catch((error) => {
if (error.hasOwnProperty("response") && error.response.status === 401) {
//todo display a popop with error
message.error('You are not logged in');
window.location.href = window.location.origin + '/entgra/login';
} else {
notification["error"]({
message: "There was a problem",
duration: 0,
description:
"Error occurred while trying to delete user.",
});
}
});
};
fetchRoles = (username) => {
let apiUrl = window.location.origin + this.config.serverConfig.invoker.uri +
this.config.serverConfig.invoker.deviceMgt +
"/users/" + username + "/roles";
axios.get(apiUrl).then(res => {
if (res.status === 200) {
this.setState({
rolesData: res.data.data.roles,
});
}
}).catch((error) => {
if (error.hasOwnProperty("response") && error.response.status === 401) {
//todo display a popop with error
message.error('You are not logged in');
window.location.href = window.location.origin + '/entgra/login';
} else {
notification["error"]({
message: "There was a problem",
duration: 0,
description:"Error occurred while trying to load roles.",
});
}
});
};
handleEditOk = e =>{
this.props.form.validateFields((['userStoreDomain', 'userName', 'firstName', 'lastName' , 'email', 'userRoles']),(err, values) => {
if (!err) {
this.onUpdateUser(values);
}
});
};
onUpdateUser = (value) =>{
const userData = {
username : value.userStoreDomain +"/"+value.userName,
firstname : value.firstName,
lastname : value.lastName,
emailAddress : value.email,
roles : value.userRoles
};
axios.put(
window.location.origin + this.config.serverConfig.invoker.uri +
this.config.serverConfig.invoker.deviceMgt +
"/users/"+ this.props.data.username,
userData,
{headers: {'Content-Type' : 'application-json'}}
).then(res => {
if (res.status === 200) {
this.props.fetchUsers();
this.setState({
isEditModalVisible: false,
});
notification["success"]({
message: "Done",
duration: 4,
description:
"Successfully updated the user.",
});
}
}).catch((error) => {
if (error.hasOwnProperty("response") && error.response.status === 401) {
//todo display a popop with error
message.error('You are not logged in');
window.location.href = window.location.origin + '/entgra/login';
} else {
notification["error"]({
message: "There was a problem",
duration: 0,
description:
"Error occurred while trying to update user.",
});
}
});
};
render() {
const isAdminUser = this.props.data.username ==="admin";
const { getFieldDecorator } = this.props.form;
return (
<div>
<div style={{display:isAdminUser ? "none" : "inline"}}>
<Tooltip placement="top" title={"Edit User"}>
<a><Icon type="edit" onClick={this.openEditModal}/></a>
</Tooltip>
<Divider type="vertical" />
<Tooltip placement="top" title={"Reset Password"}>
<a><Icon type="key" onClick={this.openPasswordResetModal}/></a>
</Tooltip>
<Divider type="vertical" />
<Tooltip placement="bottom" title={"Remove User"}>
<Popconfirm
placement="top"
title={"Are you sure?"}
onConfirm={this.onConfirmDeleteUser}
okText="Ok"
cancelText="Cancel">
<a><Text type="danger"><Icon type="delete"/></Text></a>
</Popconfirm>
</Tooltip>
</div>
<div>
<Modal
title="Reset Password"
width="40%"
visible={this.state.isResetPasswordModalVisible}
onCancel={this.onCancelHandler}
onOk={this.onSavePassword}
footer={[
<Button key="cancel" onClick={this.onCancelHandler}>
Cancel
</Button>,
<Button key="submit" type="primary" onClick={this.onSavePassword} >
Save
</Button>,
]}>
<div style={{alignItems:"center"}}>
<Form
labelCol={{ span: 6 }}
wrapperCol={{ span: 17 }}>
<Form.Item label="New Password" style={{display:"block"}}>
{getFieldDecorator(
'password',
{
rules: [
{
required: true,
message: 'This field is required',
},
],
})(<Input.Password/>)}
</Form.Item>
<Form.Item label="Retype New Password" style={{display:"block"}}>
{getFieldDecorator(
'confirmPassword',
{
rules: [
{
required: true,
message: 'This field is required',
},
{
validator: this.compareToFirstPassword,
},
],
})(<Input.Password/>)}
</Form.Item>
</Form>
</div>
</Modal>
</div>
<div>
<Modal
title="EDIT USER"
width="40%"
visible={this.state.isEditModalVisible}
onOk={this.handleEditOk}
onCancel={this.onCancelHandler}
footer={[
<Button key="cancel" onClick={this.onCancelHandler}>
Cancel
</Button>,
<Button key="submit" type="primary" onClick={this.handleEditOk}>
Update
</Button>,
]}>
<div style={{alignItems:"center"}}>
<p>Create new user on IoT Server.</p>
<Form
labelCol={{ span: 5 }}
wrapperCol={{ span: 18 }}>
<Form.Item label="User Store Domain" style={{display:"block"}}>
{getFieldDecorator('userStoreDomain', {
initialValue : 'PRIMARY'
})(
<Select disabled={true}>
<Option key="PRIMARY">PRIMARY</Option>
</Select>
)}
</Form.Item>
<Form.Item label="User Name" style={{display:"block"}}>
{getFieldDecorator('userName', {
initialValue: this.props.data.username,
rules: [
{
required: true,
message: 'This field is required. Username should be at least 3 characters long with no white spaces.',
},
],
})(<Input disabled={true}/>)}
</Form.Item>
<Form.Item label="First Name" style={{display:"block"}}>
{getFieldDecorator('firstName', {
initialValue: this.props.data.firstname,
rules: [
{
required: true,
message: 'This field is required',
},
],
})(<Input/>)}
</Form.Item>
<Form.Item label="Last Name" style={{display:"block"}}>
{getFieldDecorator('lastName', {
initialValue: this.props.data.lastname,
rules: [
{
required: true,
message: 'This field is required',
},
],
})(<Input/>)}
</Form.Item>
<Form.Item label="Email Address" style={{display:"block"}}>
{getFieldDecorator('email', {
initialValue: this.props.data.emailAddress,
rules: [
{
type: 'email',
message: 'Invalid Email Address',
},
{
required: true,
message: 'This field is required',
},
],
})(<Input/>)}
</Form.Item>
<Form.Item label="User Roles" style={{display:"block"}}>
{getFieldDecorator('userRoles', {
initialValue: this.state.rolesData,
})(<Select
mode="multiple"
style={{ width: '100%' }}>
{this.state.roles}
</Select>)}
</Form.Item>
</Form>
</div>
</Modal>
</div>
</div>
);
}
}
export default withConfigContext(Form.create({name: 'user-actions'})(UserActions));

@ -25,7 +25,8 @@ import en from 'javascript-time-ago/locale/en'
import {withConfigContext} from "../../context/ConfigContext"; import {withConfigContext} from "../../context/ConfigContext";
import UsersDevices from "./UsersDevices"; import UsersDevices from "./UsersDevices";
import AddUser from "./AddUser"; import AddUser from "./AddUser";
import UserActions from "./UserActions";
const ButtonGroup = Button.Group
const {Text} = Typography; const {Text} = Typography;
let config = null; let config = null;
@ -42,6 +43,7 @@ class UsersTable extends React.Component {
loading: false, loading: false,
selectedRows: [], selectedRows: [],
rolesModalVisible: false, rolesModalVisible: false,
devicesModalVisible: false,
rolesData: [], rolesData: [],
user:'' user:''
}; };
@ -88,6 +90,8 @@ class UsersTable extends React.Component {
data: res.data.data.users, data: res.data.data.users,
pagination, pagination,
}); });
console.log(res.data.data)
} }
}).catch((error) => { }).catch((error) => {
@ -107,7 +111,6 @@ class UsersTable extends React.Component {
}); });
}; };
//fetch data from api
fetchRoles = (username) => { fetchRoles = (username) => {
const config = this.props.context; const config = this.props.context;
@ -120,7 +123,6 @@ class UsersTable extends React.Component {
config.serverConfig.invoker.deviceMgt + config.serverConfig.invoker.deviceMgt +
"/users/" + username + "/roles"; "/users/" + username + "/roles";
//send request to the invokerss
axios.get(apiUrl).then(res => { axios.get(apiUrl).then(res => {
if (res.status === 200) { if (res.status === 200) {
this.setState({ this.setState({
@ -163,15 +165,23 @@ class UsersTable extends React.Component {
handleOk = e => { handleOk = e => {
this.setState({ this.setState({
rolesModalVisible: false, rolesModalVisible: false,
devicesModalVisible: false
}); });
}; };
handleCancel = e => { handleCancel = e => {
this.setState({ this.setState({
rolesModalVisible: false, rolesModalVisible: false,
devicesModalVisible: false
}); });
}; };
openDeviceListModal = e =>{
this.setState({
devicesModalVisible: true,
})
};
render() { render() {
const {data, pagination, loading, selectedRows} = this.state; const {data, pagination, loading, selectedRows} = this.state;
const { Panel } = Collapse; const { Panel } = Collapse;
@ -180,38 +190,52 @@ class UsersTable extends React.Component {
{ {
title: 'User Name', title: 'User Name',
dataIndex: 'username', dataIndex: 'username',
width: 150,
key: "username", key: "username",
}, },
{ {
title: 'First Name', title: 'First Name',
width: 150,
dataIndex: 'firstname', dataIndex: 'firstname',
key: 'firstname', key: 'firstname',
}, },
{ {
title: 'Last Name', title: 'Last Name',
width: 150,
dataIndex: 'lastname', dataIndex: 'lastname',
key: 'lastname', key: 'lastname',
}, },
{ {
title: 'Email', title: 'Email',
width: 100,
dataIndex: 'emailAddress', dataIndex: 'emailAddress',
key: 'emailAddress', key: 'emailAddress',
}, },
{ {
title: '', title: 'View',
dataIndex: 'username', dataIndex: 'username',
key: 'roles', key: 'roles',
render: (username) => render: (username) =>
<ButtonGroup>
<Button <Button
type="link" type="primary"
size={"default"} size={"small"}
icon="info-circle" icon="book"
onClick={() => this.fetchRoles(username)}>Info</Button> onClick={() => this.fetchRoles(username)}>Roles</Button>
} <Button
type="primary"
size={"small"}
icon="desktop"
onClick={this.openDeviceListModal}>Devices</Button>
</ButtonGroup>
},
{
title: 'Action',
dataIndex: 'id',
key: 'action',
render: (id, row) => (
<span>
<UserActions data={row} fetchUsers={this.fetchUsers}/>
</span>
),
},
]; ];
return ( return (
<div> <div>
@ -237,40 +261,31 @@ class UsersTable extends React.Component {
</div> </div>
<div> <div>
<Modal <Modal
title="ROLES"
width="900px" width="900px"
visible={this.state.rolesModalVisible} visible={this.state.rolesModalVisible}
onOk={this.handleOk} onOk={this.handleOk}
onCancel={this.handleCancel} onCancel={this.handleCancel} >
> <div>
<Tabs size="small" defaultActiveKey="1">
<TabPane
tab={
<span>
<Icon type="book"/>
Roles
</span>
}
key="1"
>
<List <List
size="small" size="small"
bordered bordered
dataSource={this.state.rolesData} dataSource={this.state.rolesData}
renderItem={item => <List.Item>{item}</List.Item>} renderItem={item => <List.Item>{item}</List.Item>}/>
/> </div>
</TabPane> </Modal>
<TabPane </div>
tab={
<span> <div>
<Icon type="appstore"/> <Modal
Enrolled Devices title="DEVICES"
</span> width="900px"
} visible={this.state.devicesModalVisible}
key="2" onOk={this.handleOk}
> onCancel={this.handleCancel}>
<div>
<UsersDevices user={this.state.user}/> <UsersDevices user={this.state.user}/>
</TabPane> </div>
</Tabs>
</Modal> </Modal>
</div> </div>
</div> </div>

Loading…
Cancel
Save