Merge branch 'application-mgt-new' of gitlab.com:entgra/carbon-device-mgt into application-mgt-new

feature/appm-store/pbac
lasanthaDLPDS 5 years ago
commit 67f442f1c4

@ -1,6 +1,6 @@
{ {
"theme": { "theme": {
"logo" : "https://localhost:9443/entgra/public/images/logo.svg", "logo" : "https://entgra.io/assets/images/svg/logo.svg",
"primaryColor": "rgb(24, 144, 255)" "primaryColor": "rgb(24, 144, 255)"
}, },
"serverConfig": { "serverConfig": {

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 48 KiB

@ -67,11 +67,8 @@ class App extends React.Component {
axios.get( axios.get(
window.location.origin + "/entgra/public/conf/config.json", window.location.origin + "/entgra/public/conf/config.json",
).then(res => { ).then(res => {
console.log(res); const config = res.data;
this.setState({ this.checkUserLoggedIn(config);
loading: false,
config: res.data
})
}).catch((error) => { }).catch((error) => {
this.setState({ this.setState({
loading: false, loading: false,
@ -80,6 +77,44 @@ class App extends React.Component {
}); });
} }
checkUserLoggedIn = (config) => {
axios.post(
window.location.origin + "/entgra-ui-request-handler/user",
"platform=entgra"
).then(res => {
config.user = res.data.data;
const pageURL = window.location.pathname;
const lastURLSegment = pageURL.substr(pageURL.lastIndexOf('/') + 1);
if (lastURLSegment === "login") {
window.location.href = window.location.origin + `/entgra/`;
} else {
this.setState({
loading: false,
config: config
});
}
}).catch((error) => {
if (error.hasOwnProperty("response") && error.response.status === 401) {
const redirectUrl = encodeURI(window.location.href);
const pageURL = window.location.pathname;
const lastURLSegment = pageURL.substr(pageURL.lastIndexOf('/') + 1);
if (lastURLSegment !== "login") {
window.location.href = window.location.origin + `/entgra/login?redirect=${redirectUrl}`;
} else {
this.setState({
loading: false,
config: config
})
}
} else {
this.setState({
loading: false,
error: true
})
}
});
};
render() { render() {
const {loading, error} = this.state; const {loading, error} = this.state;

@ -0,0 +1,135 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import React from "react";
import axios from "axios";
import {Tag, message, notification, Table, Typography, Tooltip, Icon, Divider, Card, Col, Row, Select} from "antd";
import TimeAgo from 'javascript-time-ago'
// Load locale-specific relative date/time formatting rules.
import en from 'javascript-time-ago/locale/en'
import {withConfigContext} from "../../context/ConfigContext";
const {Text} = Typography;
let config = null;
let apiUrl;
class DeviceTypesTable extends React.Component {
constructor(props) {
super(props);
config = this.props.context;
TimeAgo.addLocale(en);
this.state = {
data: [],
pagination: {},
loading: false,
selectedRows: []
};
}
componentDidMount() {
this.fetchUsers();
}
//fetch data from api
fetchUsers = (params = {}) => {
const config = this.props.context;
this.setState({loading: true});
// get current page
const currentPage = (params.hasOwnProperty("page")) ? params.page : 1;
const extraParams = {
offset: 10 * (currentPage - 1), //calculate the offset
limit: 10,
};
const encodedExtraParams = Object.keys(extraParams)
.map(key => key + '=' + extraParams[key]).join('&');
apiUrl = window.location.origin + config.serverConfig.invoker.uri +
config.serverConfig.invoker.deviceMgt +
"/device-types";
//send request to the invokerss
axios.get(apiUrl).then(res => {
if (res.status === 200) {
const pagination = {...this.state.pagination};
this.setState({
loading: false,
data: JSON.parse(res.data.data),
pagination,
});
}
console.log(JSON.parse(res.data.data))
}).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 device types.",
});
}
this.setState({loading: false});
});
};
handleTableChange = (pagination, filters, sorter) => {
const pager = {...this.state.pagination};
pager.current = pagination.current;
this.setState({
pagination: pager,
});
this.fetch({
results: pagination.pageSize,
page: pagination.current,
sortField: sorter.field,
sortOrder: sorter.order,
...filters,
});
};
render() {
const {data, pagination, loading, selectedRows} = this.state;
const itemCard = data.map((data) =>
<Col span={8} key={data.id}>
<Card hoverable title="Device Type" bordered={true}>
{data.name}
</Card>
</Col>
);
return (
<div style={{ background: '#ECECEC', padding: '30px' }}>
<Row gutter={16}>
{itemCard}
</Row>
</div>
);
}
}
export default withConfigContext(DeviceTypesTable);

@ -176,7 +176,7 @@ class DeviceTable extends React.Component {
this.setState({ this.setState({
loading: false, loading: false,
data: res.data.data.devices, data: res.data.data.devices,
pagination, pagination
}); });
} }
@ -253,7 +253,7 @@ class DeviceTable extends React.Component {
message: "Done", message: "Done",
duration: 4, duration: 4,
description: description:
"Successfully disenrolled the device.", "Successfully dis-enrolled the device.",
}); });
} }
}).catch((error) => { }).catch((error) => {
@ -266,7 +266,7 @@ class DeviceTable extends React.Component {
message: "There was a problem", message: "There was a problem",
duration: 0, duration: 0,
description: description:
"Error occurred while trying to disenroll devices.", "Error occurred while trying to dis-enroll devices.",
}); });
} }

@ -112,18 +112,7 @@ const columns = [
return <Tooltip title={new Date(dateOfLastUpdate).toString()}>{timeAgoString}</Tooltip>; return <Tooltip title={new Date(dateOfLastUpdate).toString()}>{timeAgoString}</Tooltip>;
} }
// todo add filtering options // todo add filtering options
}, }
{
title: 'Action',
key: 'action',
render: () => (
<span>
<a><Icon type="edit" /></a>
<Divider type="vertical" />
<a><Text type="danger"><Icon type="delete" /></Text></a>
</span>
),
},
]; ];
const getTimeAgo = (time) => { const getTimeAgo = (time) => {

@ -0,0 +1,174 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import React from "react";
import axios from "axios";
import {Tag, message, notification, Table, Typography, Tooltip, Icon, Divider} from "antd";
import TimeAgo from 'javascript-time-ago'
// Load locale-specific relative date/time formatting rules.
import en from 'javascript-time-ago/locale/en'
import {withConfigContext} from "../../context/ConfigContext";
const {Text} = Typography;
let config = null;
let apiUrl;
const columns = [
{
title: 'Group Name',
dataIndex: 'name',
width: 100,
},
{
title: 'Owner',
dataIndex: 'owner',
key: 'owner',
// render: enrolmentInfo => enrolmentInfo.owner
// todo add filtering options
},
{
title: 'Description',
dataIndex: 'description',
key: 'description',
// render: enrolmentInfo => enrolmentInfo.ownership
// todo add filtering options
}
];
const getTimeAgo = (time) => {
const timeAgo = new TimeAgo('en-US');
return timeAgo.format(time);
};
class GroupsTable extends React.Component {
constructor(props) {
super(props);
config = this.props.context;
TimeAgo.addLocale(en);
this.state = {
data: [],
pagination: {},
loading: false,
selectedRows: []
};
}
rowSelection = {
onChange: (selectedRowKeys, selectedRows) => {
this.setState({
selectedRows: selectedRows
})
}
};
componentDidMount() {
this.fetchGroups();
}
//fetch data from api
fetchGroups = (params = {}) => {
const config = this.props.context;
this.setState({loading: true});
// get current page
const currentPage = (params.hasOwnProperty("page")) ? params.page : 1;
const extraParams = {
offset: 10 * (currentPage - 1), //calculate the offset
limit: 10,
};
const encodedExtraParams = Object.keys(extraParams)
.map(key => key + '=' + extraParams[key]).join('&');
apiUrl = window.location.origin + config.serverConfig.invoker.uri +
config.serverConfig.invoker.deviceMgt +
"/admin/groups?" + encodedExtraParams;
//send request to the invokerss
axios.get(apiUrl).then(res => {
if (res.status === 200) {
const pagination = {...this.state.pagination};
this.setState({
loading: false,
data: res.data.data.deviceGroups,
pagination,
});
}
}).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 device groups.",
});
}
this.setState({loading: false});
});
};
handleTableChange = (pagination, filters, sorter) => {
const pager = {...this.state.pagination};
pager.current = pagination.current;
this.setState({
pagination: pager,
});
this.fetch({
results: pagination.pageSize,
page: pagination.current,
sortField: sorter.field,
sortOrder: sorter.order,
...filters,
});
};
render() {
const {data, pagination, loading, selectedRows} = this.state;
return (
<div>
<Table
columns={columns}
rowKey={record => (record.id)}
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}
scroll={{x: 1000}}
/>
</div>
);
}
}
export default withConfigContext(GroupsTable);

@ -0,0 +1,147 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import React from "react";
import axios from "axios";
import {Tag, message, notification, Table, Typography, Tooltip, Icon, Divider, Card, Col, Row, Select} from "antd";
import TimeAgo from 'javascript-time-ago'
// Load locale-specific relative date/time formatting rules.
import en from 'javascript-time-ago/locale/en'
import {withConfigContext} from "../../context/ConfigContext";
const {Text} = Typography;
let config = null;
let apiUrl;
const columns = [
{
title: 'User Name',
dataIndex: 'username',
width: 100,
}
];
const getTimeAgo = (time) => {
const timeAgo = new TimeAgo('en-US');
return timeAgo.format(time);
};
class RolesTable extends React.Component {
constructor(props) {
super(props);
config = this.props.context;
TimeAgo.addLocale(en);
this.state = {
data: [],
pagination: {},
loading: false,
selectedRows: []
};
}
componentDidMount() {
this.fetchUsers();
}
//fetch data from api
fetchUsers = (params = {}) => {
const config = this.props.context;
this.setState({loading: true});
// get current page
const currentPage = (params.hasOwnProperty("page")) ? params.page : 1;
const extraParams = {
offset: 10 * (currentPage - 1), //calculate the offset
limit: 10,
};
const encodedExtraParams = Object.keys(extraParams)
.map(key => key + '=' + extraParams[key]).join('&');
apiUrl = window.location.origin + config.serverConfig.invoker.uri +
config.serverConfig.invoker.deviceMgt +
"/roles";
//send request to the invokerss
axios.get(apiUrl).then(res => {
if (res.status === 200) {
const pagination = {...this.state.pagination};
this.setState({
loading: false,
data: res.data.data.roles,
pagination,
});
}
}).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.",
});
}
this.setState({loading: false});
});
};
handleTableChange = (pagination, filters, sorter) => {
const pager = {...this.state.pagination};
pager.current = pagination.current;
this.setState({
pagination: pager,
});
this.fetch({
results: pagination.pageSize,
page: pagination.current,
sortField: sorter.field,
sortOrder: sorter.order,
...filters,
});
};
render() {
const {data, pagination, loading, selectedRows} = this.state;
const itemCard = data.map((data) =>
<Col span={8} key={data}>
<Card hoverable title="Role" bordered={true}>
{data}
</Card>
</Col>
);
return (
<div style={{ background: '#ECECEC', padding: '30px' }}>
<Row gutter={16}>
{itemCard}
</Row>
</div>
);
}
}
export default withConfigContext(RolesTable);

@ -0,0 +1,134 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import React from "react";
import axios from "axios";
import {Tag, message, notification, Table, Typography, Tooltip, Icon, Divider, Card, Col, Row, Select} from "antd";
import TimeAgo from 'javascript-time-ago'
// Load locale-specific relative date/time formatting rules.
import en from 'javascript-time-ago/locale/en'
import {withConfigContext} from "../../context/ConfigContext";
const {Text} = Typography;
let config = null;
let apiUrl;
class UsersTable extends React.Component {
constructor(props) {
super(props);
config = this.props.context;
TimeAgo.addLocale(en);
this.state = {
data: [],
pagination: {},
loading: false,
selectedRows: []
};
}
componentDidMount() {
this.fetchUsers();
}
//fetch data from api
fetchUsers = (params = {}) => {
const config = this.props.context;
this.setState({loading: true});
// get current page
const currentPage = (params.hasOwnProperty("page")) ? params.page : 1;
const extraParams = {
offset: 10 * (currentPage - 1), //calculate the offset
limit: 10,
};
const encodedExtraParams = Object.keys(extraParams)
.map(key => key + '=' + extraParams[key]).join('&');
apiUrl = window.location.origin + config.serverConfig.invoker.uri +
config.serverConfig.invoker.deviceMgt +
"/users";
//send request to the invokerss
axios.get(apiUrl).then(res => {
if (res.status === 200) {
const pagination = {...this.state.pagination};
this.setState({
loading: false,
data: res.data.data.users,
pagination,
});
}
}).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.",
});
}
this.setState({loading: false});
});
};
handleTableChange = (pagination, filters, sorter) => {
const pager = {...this.state.pagination};
pager.current = pagination.current;
this.setState({
pagination: pager,
});
this.fetch({
results: pagination.pageSize,
page: pagination.current,
sortField: sorter.field,
sortOrder: sorter.order,
...filters,
});
};
render() {
const {data, pagination, loading, selectedRows} = this.state;
const itemCard = data.map((data) =>
<Col span={8} key={data.username}>
<Card hoverable title="User Name" bordered={true}>
{data.username}
</Card>
</Col>
);
return (
<div style={{ background: '#ECECEC', padding: '30px' }}>
<Row gutter={16}>
{itemCard}
</Row>
</div>
);
}
}
export default withConfigContext(UsersTable);

@ -26,6 +26,11 @@ import './index.css';
import Devices from "./pages/Dashboard/Devices/Devices"; import Devices from "./pages/Dashboard/Devices/Devices";
import Reports from "./pages/Dashboard/Reports/Reports"; import Reports from "./pages/Dashboard/Reports/Reports";
import Geo from "./pages/Dashboard/Geo/Geo"; import Geo from "./pages/Dashboard/Geo/Geo";
import Groups from "./pages/Dashboard/Groups/Groups";
import Users from "./pages/Dashboard/Users/Users";
import Policies from "./pages/Dashboard/Policies/Policies";
import Roles from "./pages/Dashboard/Roles/Roles";
import DeviceTypes from "./pages/Dashboard/DeviceTypes/DeviceTypes";
const routes = [ const routes = [
{ {
@ -52,6 +57,31 @@ const routes = [
path: '/entgra/reports', path: '/entgra/reports',
component: Reports, component: Reports,
exact: true exact: true
},
{
path: '/entgra/groups',
component: Groups,
exact: true
},
{
path: '/entgra/users',
component: Users,
exact: true
},
{
path: '/entgra/policies',
component: Policies,
exact: true
},
{
path: '/entgra/roles',
component: Roles,
exact: true
},
{
path: '/entgra/devicetypes',
component: DeviceTypes,
exact: true
} }
] ]
} }

@ -54,8 +54,11 @@
} }
.layout .logo-image img { .layout .logo-image img {
height: 32px; height: 55px;
margin: 16px; margin-top: 5px;
margin-left: 16px;
margin-right: 16px;
margin-bottom: 5px;
} }
@media only screen and (min-width: 760px) { @media only screen and (min-width: 760px) {

@ -42,9 +42,11 @@ class Dashboard extends React.Component {
mobileWidth mobileWidth
}; };
this.logo = this.props.context.theme.logo; this.logo = this.props.context.theme.logo;
this.config = this.props.context;
} }
toggle = () => { toggle = () => {
console.log(this.config)
this.setState({ this.setState({
isNavBarCollapsed: !this.state.isNavBarCollapsed, isNavBarCollapsed: !this.state.isNavBarCollapsed,
}); });
@ -63,8 +65,7 @@ class Dashboard extends React.Component {
> >
<div className="logo-image"> <div className="logo-image">
<Link to="/entgra/devices"><img alt="logo" src={this.logo}/> <Link to="/entgra/devices"><img alt="logo" src={this.logo}/></Link>
<span className="brand">Entgra</span></Link>
</div> </div>
<Menu theme="dark" mode="inline" defaultSelectedKeys={['devices']}> <Menu theme="dark" mode="inline" defaultSelectedKeys={['devices']}>
<Menu.Item key="devices"> <Menu.Item key="devices">
@ -85,6 +86,36 @@ class Dashboard extends React.Component {
<span>Reports</span> <span>Reports</span>
</Link> </Link>
</Menu.Item> </Menu.Item>
<Menu.Item key="groups">
<Link to="/entgra/groups">
<Icon type="deployment-unit"/>
<span>Groups</span>
</Link>
</Menu.Item>
<Menu.Item key="users">
<Link to="/entgra/users">
<Icon type="user"/>
<span>Users</span>
</Link>
</Menu.Item>
<Menu.Item key="policies">
<Link to="/entgra/policies">
<Icon type="audit"/>
<span>Policies</span>
</Link>
</Menu.Item>
<Menu.Item key="roles">
<Link to="/entgra/roles">
<Icon type="book"/>
<span>Roles</span>
</Link>
</Menu.Item>
<Menu.Item key="devicetypes">
<Link to="/entgra/devicetypes">
<Icon type="desktop"/>
<span>Device Types</span>
</Link>
</Menu.Item>
</Menu> </Menu>
</Sider> </Sider>
@ -109,9 +140,8 @@ class Dashboard extends React.Component {
title={ title={
<span className="submenu-title-wrapper"> <span className="submenu-title-wrapper">
<Icon type="user"/> <Icon type="user"/>
</span> {this.config.user}
} </span> }>
>
<Logout/> <Logout/>
</SubMenu> </SubMenu>

@ -0,0 +1,65 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import React from "react";
import {
PageHeader,
Typography,
Breadcrumb,
Icon
} from "antd";
import {Link} from "react-router-dom";
import DeviceTypesTable from "../../../components/DeviceTypes/DeviceTypesTable";
const {Paragraph} = Typography;
class DeviceTypes extends React.Component {
routes;
constructor(props) {
super(props);
this.routes = props.routes;
}
render() {
return (
<div>
<PageHeader style={{paddingTop: 0}}>
<Breadcrumb style={{paddingBottom: 16}}>
<Breadcrumb.Item>
<Link to="/entgra"><Icon type="home"/> Home</Link>
</Breadcrumb.Item>
<Breadcrumb.Item>Device Types</Breadcrumb.Item>
</Breadcrumb>
<div className="wrap">
<h3>Device Types</h3>
<Paragraph>All device types for device management.</Paragraph>
</div>
<div style={{backgroundColor:"#ffffff", borderRadius: 5}}>
<DeviceTypesTable/>
</div>
</PageHeader>
<div style={{background: '#f0f2f5', padding: 24, minHeight: 720}}>
</div>
</div>
);
}
}
export default DeviceTypes;

@ -49,8 +49,7 @@ class Devices extends React.Component {
</Breadcrumb> </Breadcrumb>
<div className="wrap"> <div className="wrap">
<h3>Devices</h3> <h3>Devices</h3>
<Paragraph>Lorem ipsum dolor sit amet, est similique constituto at, quot inermis id mel, an <Paragraph>All enrolled devices</Paragraph>
illud incorrupte nam.</Paragraph>
</div> </div>
<div style={{backgroundColor:"#ffffff", borderRadius: 5}}> <div style={{backgroundColor:"#ffffff", borderRadius: 5}}>
<DeviceTable/> <DeviceTable/>

@ -0,0 +1,62 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import React from "react";
import {
PageHeader,
Typography,
Breadcrumb,
Icon
} from "antd";
import {Link} from "react-router-dom";
import GroupsTable from "../../../components/Groups/GroupsTable";
const {Paragraph} = Typography;
class Groups extends React.Component {
routes;
constructor(props) {
super(props);
this.routes = props.routes;
}
render() {
return (
<div>
<PageHeader style={{paddingTop: 0}}>
<Breadcrumb style={{paddingBottom: 16}}>
<Breadcrumb.Item>
<Link to="/entgra"><Icon type="home"/> Home</Link>
</Breadcrumb.Item>
<Breadcrumb.Item>Groups</Breadcrumb.Item>
</Breadcrumb>
<div className="wrap">
<h3>Groups</h3>
<Paragraph>All device groups.</Paragraph>
</div>
<div style={{backgroundColor:"#ffffff", borderRadius: 5}}>
<GroupsTable/>
</div>
</PageHeader>
</div>
);
}
}
export default Groups;

@ -0,0 +1,61 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import React from "react";
import {
PageHeader,
Typography,
Breadcrumb,
Icon
} from "antd";
import {Link} from "react-router-dom";
const {Paragraph} = Typography;
class Policies extends React.Component {
routes;
constructor(props) {
super(props);
this.routes = props.routes;
}
render() {
return (
<div>
<PageHeader style={{paddingTop: 0}}>
<Breadcrumb style={{paddingBottom: 16}}>
<Breadcrumb.Item>
<Link to="/entgra"><Icon type="home"/> Home</Link>
</Breadcrumb.Item>
<Breadcrumb.Item>Policies</Breadcrumb.Item>
</Breadcrumb>
<div className="wrap">
<h3>Policies</h3>
<Paragraph>All policies for device management</Paragraph>
</div>
<div style={{backgroundColor:"#ffffff", borderRadius: 5}}>
</div>
</PageHeader>
</div>
);
}
}
export default Policies;

@ -0,0 +1,65 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import React from "react";
import {
PageHeader,
Typography,
Breadcrumb,
Icon
} from "antd";
import {Link} from "react-router-dom";
import RolesTable from "../../../components/Roles/RolesTable";
const {Paragraph} = Typography;
class Roles extends React.Component {
routes;
constructor(props) {
super(props);
this.routes = props.routes;
}
render() {
return (
<div>
<PageHeader style={{paddingTop: 0}}>
<Breadcrumb style={{paddingBottom: 16}}>
<Breadcrumb.Item>
<Link to="/entgra"><Icon type="home"/> Home</Link>
</Breadcrumb.Item>
<Breadcrumb.Item>Roles</Breadcrumb.Item>
</Breadcrumb>
<div className="wrap">
<h3>Roles</h3>
<Paragraph>All user roles</Paragraph>
</div>
<div style={{backgroundColor:"#ffffff", borderRadius: 5}}>
<RolesTable/>
</div>
</PageHeader>
<div style={{background: '#f0f2f5', padding: 24, minHeight: 720}}>
</div>
</div>
);
}
}
export default Roles;

@ -0,0 +1,65 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import React from "react";
import {
PageHeader,
Typography,
Breadcrumb,
Icon
} from "antd";
import {Link} from "react-router-dom";
import UsersTable from "../../../components/Users/UsersTable";
const {Paragraph} = Typography;
class Users extends React.Component {
routes;
constructor(props) {
super(props);
this.routes = props.routes;
}
render() {
return (
<div>
<PageHeader style={{paddingTop: 0}}>
<Breadcrumb style={{paddingBottom: 16}}>
<Breadcrumb.Item>
<Link to="/entgra"><Icon type="home"/> Home</Link>
</Breadcrumb.Item>
<Breadcrumb.Item>Users</Breadcrumb.Item>
</Breadcrumb>
<div className="wrap">
<h3>Users</h3>
<Paragraph>All users for device management.</Paragraph>
</div>
<div style={{backgroundColor:"#ffffff", borderRadius: 5}}>
<UsersTable/>
</div>
</PageHeader>
<div style={{background: '#f0f2f5', padding: 24, minHeight: 720}}>
</div>
</div>
);
}
}
export default Users;

@ -142,7 +142,13 @@ public interface GroupManagementAdminService {
value = "Provide how many device details you require from the starting pagination index/offset.", value = "Provide how many device details you require from the starting pagination index/offset.",
defaultValue = "5") defaultValue = "5")
@QueryParam("limit") @QueryParam("limit")
int limit); int limit,
@ApiParam(
name = "status",
value = "status of group to be retrieve.")
@QueryParam("status")
String status);
@Path("/count") @Path("/count")
@GET @GET
@ -190,6 +196,10 @@ public interface GroupManagementAdminService {
message = "Internal Server Error. \n Server error occurred while fetching the group count.", message = "Internal Server Error. \n Server error occurred while fetching the group count.",
response = ErrorResponse.class) response = ErrorResponse.class)
}) })
Response getGroupCount(); Response getGroupCount(@ApiParam(
name = "status",
value = "status of groups of which count should be retrieved")
@QueryParam("status")
String status);
} }

@ -29,6 +29,7 @@ import org.wso2.carbon.device.mgt.common.exceptions.DeviceNotFoundException;
import org.wso2.carbon.device.mgt.common.GroupPaginationRequest; import org.wso2.carbon.device.mgt.common.GroupPaginationRequest;
import org.wso2.carbon.device.mgt.common.PaginationResult; import org.wso2.carbon.device.mgt.common.PaginationResult;
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup;
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroupConstants;
import org.wso2.carbon.device.mgt.common.group.mgt.GroupAlreadyExistException; import org.wso2.carbon.device.mgt.common.group.mgt.GroupAlreadyExistException;
import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException; import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException;
import org.wso2.carbon.device.mgt.common.group.mgt.RoleDoesNotExistException; import org.wso2.carbon.device.mgt.common.group.mgt.RoleDoesNotExistException;
@ -100,6 +101,7 @@ public class GroupManagementServiceImpl implements GroupManagementService {
return Response.status(Response.Status.BAD_REQUEST).build(); return Response.status(Response.Status.BAD_REQUEST).build();
} }
group.setOwner(owner); group.setOwner(owner);
group.setStatus(DeviceGroupConstants.GroupStatus.ACTIVE);
try { try {
DeviceMgtAPIUtils.getGroupManagementProviderService().createGroup(group, DEFAULT_ADMIN_ROLE, DEFAULT_ADMIN_PERMISSIONS); DeviceMgtAPIUtils.getGroupManagementProviderService().createGroup(group, DEFAULT_ADMIN_ROLE, DEFAULT_ADMIN_PERMISSIONS);
return Response.status(Response.Status.CREATED).build(); return Response.status(Response.Status.CREATED).build();

@ -20,6 +20,7 @@ package org.wso2.carbon.device.mgt.jaxrs.service.impl.admin;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.solr.common.StringUtils;
import org.wso2.carbon.device.mgt.common.GroupPaginationRequest; import org.wso2.carbon.device.mgt.common.GroupPaginationRequest;
import org.wso2.carbon.device.mgt.common.PaginationResult; import org.wso2.carbon.device.mgt.common.PaginationResult;
import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException; import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException;
@ -36,7 +37,7 @@ public class GroupManagementAdminServiceImpl implements GroupManagementAdminServ
private static final Log log = LogFactory.getLog(GroupManagementAdminServiceImpl.class); private static final Log log = LogFactory.getLog(GroupManagementAdminServiceImpl.class);
@Override @Override
public Response getGroups(String name, String owner, int offset, int limit) { public Response getGroups(String name, String owner, int offset, int limit, String status) {
try { try {
RequestValidationUtil.validatePaginationParameters(offset, limit); RequestValidationUtil.validatePaginationParameters(offset, limit);
GroupPaginationRequest request = new GroupPaginationRequest(offset, limit); GroupPaginationRequest request = new GroupPaginationRequest(offset, limit);
@ -46,6 +47,9 @@ public class GroupManagementAdminServiceImpl implements GroupManagementAdminServ
if (owner != null) { if (owner != null) {
request.setOwner(owner.toUpperCase()); request.setOwner(owner.toUpperCase());
} }
if (status != null && !status.isEmpty()) {
request.setStatus(status.toUpperCase());
}
PaginationResult deviceGroupsResult = DeviceMgtAPIUtils.getGroupManagementProviderService() PaginationResult deviceGroupsResult = DeviceMgtAPIUtils.getGroupManagementProviderService()
.getGroups(request); .getGroups(request);
DeviceGroupList deviceGroupList = new DeviceGroupList(); DeviceGroupList deviceGroupList = new DeviceGroupList();
@ -65,9 +69,14 @@ public class GroupManagementAdminServiceImpl implements GroupManagementAdminServ
} }
@Override @Override
public Response getGroupCount() { public Response getGroupCount(String status) {
try { try {
int count = DeviceMgtAPIUtils.getGroupManagementProviderService().getGroupCount(); int count;
if (status == null || status.isEmpty()) {
count = DeviceMgtAPIUtils.getGroupManagementProviderService().getGroupCount();
} else {
count = DeviceMgtAPIUtils.getGroupManagementProviderService().getGroupCountByStatus(status);
}
return Response.status(Response.Status.OK).entity(count).build(); return Response.status(Response.Status.OK).entity(count).build();
} catch (GroupManagementException e) { } catch (GroupManagementException e) {
String msg = "ErrorResponse occurred while retrieving group count."; String msg = "ErrorResponse occurred while retrieving group count.";

@ -27,12 +27,21 @@ public class GroupPaginationRequest {
private int rowCount; private int rowCount;
private String owner; private String owner;
private String groupName; private String groupName;
private String status;
public GroupPaginationRequest(int start, int rowCount) { public GroupPaginationRequest(int start, int rowCount) {
this.startIndex = start; this.startIndex = start;
this.rowCount = rowCount; this.rowCount = rowCount;
} }
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public int getStartIndex() { public int getStartIndex() {
return startIndex; return startIndex;
} }

@ -44,6 +44,17 @@ public class DeviceGroup implements Serializable {
private String owner; private String owner;
@ApiModelProperty(name = "status", value = "The status of group that needs updating/retrieval.")
private String status;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
private Map<String,String> groupProperties; private Map<String,String> groupProperties;
public DeviceGroup() {} public DeviceGroup() {}

@ -65,6 +65,11 @@ public class DeviceGroupConstants {
public static final String DEFAULT_VIEW_EVENTS = "view-events"; public static final String DEFAULT_VIEW_EVENTS = "view-events";
} }
public static class GroupStatus {
public static final String ACTIVE = "ACTIVE";
public static final String INACTIVE = "INACTIVE";
}
public static class Permissions { public static class Permissions {
public static final String[] DEFAULT_ADMIN_PERMISSIONS = public static final String[] DEFAULT_ADMIN_PERMISSIONS =
{"/permission/device-mgt/groups", "/permission/device-mgt/user/groups"}; {"/permission/device-mgt/groups", "/permission/device-mgt/user/groups"};

@ -158,7 +158,7 @@ public interface GroupDAO {
* @return List of all Device Groups in tenant. * @return List of all Device Groups in tenant.
* @throws GroupManagementDAOException * @throws GroupManagementDAOException
*/ */
int getGroupCount(int tenantId) throws GroupManagementDAOException; int getGroupCount(int tenantId, String status) throws GroupManagementDAOException;
/** /**
* Get paginated count of Device Groups in tenant. * Get paginated count of Device Groups in tenant.

@ -18,6 +18,7 @@
package org.wso2.carbon.device.mgt.core.dao.impl; package org.wso2.carbon.device.mgt.core.dao.impl;
import org.apache.solr.common.StringUtils;
import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.GroupPaginationRequest; import org.wso2.carbon.device.mgt.common.GroupPaginationRequest;
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup;
@ -46,14 +47,25 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO {
PreparedStatement stmt = null; PreparedStatement stmt = null;
ResultSet rs; ResultSet rs;
int groupId = -1; int groupId = -1;
boolean hasStatus = false;
try { try {
Connection conn = GroupManagementDAOFactory.getConnection(); Connection conn = GroupManagementDAOFactory.getConnection();
String sql = "INSERT INTO DM_GROUP(DESCRIPTION, GROUP_NAME, OWNER, TENANT_ID) VALUES (?, ?, ?, ?)"; String sql;
if(deviceGroup.getStatus() == null || deviceGroup.getStatus().isEmpty()){
sql = "INSERT INTO DM_GROUP(DESCRIPTION, GROUP_NAME, OWNER, TENANT_ID) VALUES (?, ?, ?, ?)";
} else {
sql = "INSERT INTO DM_GROUP(DESCRIPTION, GROUP_NAME, OWNER, TENANT_ID, STATUS) VALUES (?, ?, ?, ?, ?)";
hasStatus = true;
}
stmt = conn.prepareStatement(sql, new String[]{"ID"}); stmt = conn.prepareStatement(sql, new String[]{"ID"});
stmt.setString(1, deviceGroup.getDescription()); stmt.setString(1, deviceGroup.getDescription());
stmt.setString(2, deviceGroup.getName()); stmt.setString(2, deviceGroup.getName());
stmt.setString(3, deviceGroup.getOwner()); stmt.setString(3, deviceGroup.getOwner());
stmt.setInt(4, tenantId); stmt.setInt(4, tenantId);
if(hasStatus) {
stmt.setString(5, deviceGroup.getStatus());
}
stmt.executeUpdate(); stmt.executeUpdate();
rs = stmt.getGeneratedKeys(); rs = stmt.getGeneratedKeys();
if (rs.next()) { if (rs.next()) {
@ -128,16 +140,26 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO {
public void updateGroup(DeviceGroup deviceGroup, int groupId, int tenantId) public void updateGroup(DeviceGroup deviceGroup, int groupId, int tenantId)
throws GroupManagementDAOException { throws GroupManagementDAOException {
PreparedStatement stmt = null; PreparedStatement stmt = null;
boolean hasStatus = false;
try { try {
Connection conn = GroupManagementDAOFactory.getConnection(); Connection conn = GroupManagementDAOFactory.getConnection();
String sql = String sql =
"UPDATE DM_GROUP SET DESCRIPTION = ?, GROUP_NAME = ?, OWNER = ? WHERE ID = ? AND TENANT_ID = ?"; "UPDATE DM_GROUP SET DESCRIPTION = ?, GROUP_NAME = ?, OWNER = ? WHERE ID = ? AND TENANT_ID = ?";
if(deviceGroup.getStatus() != null && !deviceGroup.getStatus().isEmpty()){
sql = "UPDATE DM_GROUP SET DESCRIPTION = ?, GROUP_NAME = ?, OWNER = ?, STATUS = ? WHERE ID = ? AND TENANT_ID = ?";
hasStatus = true;
}
stmt = conn.prepareStatement(sql); stmt = conn.prepareStatement(sql);
stmt.setString(1, deviceGroup.getDescription()); int paramIndex = 1;
stmt.setString(2, deviceGroup.getName()); stmt.setString(paramIndex++, deviceGroup.getDescription());
stmt.setString(3, deviceGroup.getOwner()); stmt.setString(paramIndex++, deviceGroup.getName());
stmt.setInt(4, groupId); stmt.setString(paramIndex++, deviceGroup.getOwner());
stmt.setInt(5, tenantId); if(hasStatus) {
stmt.setString(paramIndex++, deviceGroup.getStatus());
}
stmt.setInt(paramIndex++, groupId);
stmt.setInt(paramIndex++, tenantId);
stmt.executeUpdate(); stmt.executeUpdate();
} catch (SQLException e) { } catch (SQLException e) {
throw new GroupManagementDAOException("Error occurred while updating deviceGroup '" + throw new GroupManagementDAOException("Error occurred while updating deviceGroup '" +
@ -213,8 +235,8 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO {
Map<String,String> properties = new HashMap<String, String>(); Map<String,String> properties = new HashMap<String, String>();
try { try {
Connection conn = GroupManagementDAOFactory.getConnection(); Connection conn = GroupManagementDAOFactory.getConnection();
stmt = conn.prepareStatement( String sql = "SELECT PROPERTY_NAME, PROPERTY_VALUE FROM GROUP_PROPERTIES WHERE GROUP_ID = ? AND TENANT_ID = ?";
"SELECT PROPERTY_NAME, PROPERTY_VALUE FROM GROUP_PROPERTIES WHERE GROUP_ID = ? AND TENANT_ID = ?"); stmt = conn.prepareStatement(sql);
stmt.setInt(1, groupId); stmt.setInt(1, groupId);
stmt.setInt(2, tenantId); stmt.setInt(2, tenantId);
resultSet = stmt.executeQuery(); resultSet = stmt.executeQuery();
@ -304,14 +326,22 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO {
} }
@Override @Override
public int getGroupCount(int tenantId) throws GroupManagementDAOException { public int getGroupCount(int tenantId, String status) throws GroupManagementDAOException {
PreparedStatement stmt = null; PreparedStatement stmt = null;
ResultSet resultSet = null; ResultSet resultSet = null;
boolean statusAvailable = false;
try { try {
Connection conn = GroupManagementDAOFactory.getConnection(); Connection conn = GroupManagementDAOFactory.getConnection();
String sql = "SELECT COUNT(ID) AS GROUP_COUNT FROM DM_GROUP WHERE TENANT_ID = ?"; String sql = "SELECT COUNT(ID) AS GROUP_COUNT FROM DM_GROUP WHERE TENANT_ID = ?";
if(!StringUtils.isEmpty(status)){
sql += " AND STATUS = ?";
statusAvailable = true;
}
stmt = conn.prepareStatement(sql); stmt = conn.prepareStatement(sql);
stmt.setInt(1, tenantId); stmt.setInt(1, tenantId);
if(statusAvailable){
stmt.setString(2, status);
}
resultSet = stmt.executeQuery(); resultSet = stmt.executeQuery();
if (resultSet.next()) { if (resultSet.next()) {
return resultSet.getInt("GROUP_COUNT"); return resultSet.getInt("GROUP_COUNT");
@ -335,6 +365,7 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO {
boolean hasGroupName = false; boolean hasGroupName = false;
String owner = request.getOwner(); String owner = request.getOwner();
boolean hasOwner = false; boolean hasOwner = false;
boolean hasStatus = false;
try { try {
Connection conn = GroupManagementDAOFactory.getConnection(); Connection conn = GroupManagementDAOFactory.getConnection();
@ -347,6 +378,10 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO {
sql += " AND OWNER LIKE ?"; sql += " AND OWNER LIKE ?";
hasOwner = true; hasOwner = true;
} }
if(!StringUtils.isEmpty(request.getStatus())){
sql += " AND STATUS = ?";
hasStatus = true;
}
int paramIndex = 1; int paramIndex = 1;
stmt = conn.prepareStatement(sql); stmt = conn.prepareStatement(sql);
@ -357,6 +392,9 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO {
if (hasOwner) { if (hasOwner) {
stmt.setString(paramIndex, owner + "%"); stmt.setString(paramIndex, owner + "%");
} }
if (hasStatus) {
stmt.setString(paramIndex, request.getStatus());
}
resultSet = stmt.executeQuery(); resultSet = stmt.executeQuery();
if (resultSet.next()) { if (resultSet.next()) {
return resultSet.getInt("GROUP_COUNT"); return resultSet.getInt("GROUP_COUNT");

@ -48,7 +48,9 @@ public class GenericGroupDAOImpl extends AbstractGroupDAOImpl {
String groupName = request.getGroupName(); String groupName = request.getGroupName();
boolean hasGroupName = false; boolean hasGroupName = false;
String owner = request.getOwner(); String owner = request.getOwner();
String status = request.getStatus();
boolean hasOwner = false; boolean hasOwner = false;
boolean hasStatus = false;
boolean hasLimit = request.getRowCount() != 0; boolean hasLimit = request.getRowCount() != 0;
try { try {
@ -62,6 +64,10 @@ public class GenericGroupDAOImpl extends AbstractGroupDAOImpl {
sql += " AND UPPER(OWNER) LIKE ?"; sql += " AND UPPER(OWNER) LIKE ?";
hasOwner = true; hasOwner = true;
} }
if (status != null && !status.isEmpty()) {
sql += " AND STATUS = ?";
hasStatus = true;
}
if (hasLimit) { if (hasLimit) {
sql += " LIMIT ?, ?"; sql += " LIMIT ?, ?";
} }
@ -75,6 +81,9 @@ public class GenericGroupDAOImpl extends AbstractGroupDAOImpl {
if (hasOwner) { if (hasOwner) {
stmt.setString(paramIndex++, owner + "%"); stmt.setString(paramIndex++, owner + "%");
} }
if (hasStatus) {
stmt.setString(paramIndex++, status.toUpperCase());
}
if (hasLimit) { if (hasLimit) {
stmt.setInt(paramIndex++, request.getStartIndex()); stmt.setInt(paramIndex++, request.getStartIndex());
stmt.setInt(paramIndex, request.getRowCount()); stmt.setInt(paramIndex, request.getRowCount());

@ -49,7 +49,9 @@ public class OracleGroupDAOImpl extends AbstractGroupDAOImpl {
String groupName = request.getGroupName(); String groupName = request.getGroupName();
boolean hasGroupName = false; boolean hasGroupName = false;
String owner = request.getOwner(); String owner = request.getOwner();
String status = request.getStatus();
boolean hasOwner = false; boolean hasOwner = false;
boolean hasStatus = false;
boolean hasLimit = request.getRowCount() != 0; boolean hasLimit = request.getRowCount() != 0;
try { try {
@ -63,6 +65,10 @@ public class OracleGroupDAOImpl extends AbstractGroupDAOImpl {
sql += " AND OWNER LIKE ?"; sql += " AND OWNER LIKE ?";
hasOwner = true; hasOwner = true;
} }
if (status != null && !status.isEmpty()) {
sql += " AND STATUS = ?";
hasStatus = true;
}
if (hasLimit) { if (hasLimit) {
sql += " OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; sql += " OFFSET ? ROWS FETCH NEXT ? ROWS ONLY";
} }
@ -76,6 +82,9 @@ public class OracleGroupDAOImpl extends AbstractGroupDAOImpl {
if (hasOwner) { if (hasOwner) {
stmt.setString(paramIndex++, owner + "%"); stmt.setString(paramIndex++, owner + "%");
} }
if (hasStatus) {
stmt.setString(paramIndex++, status.toUpperCase());
}
if (hasLimit) { if (hasLimit) {
stmt.setInt(paramIndex++, request.getStartIndex()); stmt.setInt(paramIndex++, request.getStartIndex());
stmt.setInt(paramIndex, request.getRowCount()); stmt.setInt(paramIndex, request.getRowCount());

@ -18,6 +18,7 @@
package org.wso2.carbon.device.mgt.core.dao.impl.group; package org.wso2.carbon.device.mgt.core.dao.impl.group;
import org.apache.solr.common.StringUtils;
import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.GroupPaginationRequest; import org.wso2.carbon.device.mgt.common.GroupPaginationRequest;
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup;
@ -44,15 +45,26 @@ public class PostgreSQLGroupDAOImpl extends AbstractGroupDAOImpl {
PreparedStatement stmt = null; PreparedStatement stmt = null;
ResultSet rs; ResultSet rs;
int groupId = -1; int groupId = -1;
boolean hasStatus = false;
try { try {
Connection conn = GroupManagementDAOFactory.getConnection(); Connection conn = GroupManagementDAOFactory.getConnection();
String sql = "INSERT INTO DM_GROUP(DESCRIPTION, GROUP_NAME, OWNER, TENANT_ID) " + String sql;
"VALUES (?, ?, ?, ?) RETURNING ID"; if(StringUtils.isEmpty(deviceGroup.getStatus())) {
sql = "INSERT INTO DM_GROUP(DESCRIPTION, GROUP_NAME, OWNER, TENANT_ID) " +
"VALUES (?, ?, ?, ?) RETURNING ID";
} else {
sql = "INSERT INTO DM_GROUP(DESCRIPTION, GROUP_NAME, OWNER, TENANT_ID, STATUS) " +
"VALUES (?, ?, ?, ?, ?) RETURNING ID";
hasStatus = true;
}
stmt = conn.prepareStatement(sql); stmt = conn.prepareStatement(sql);
stmt.setString(1, deviceGroup.getDescription()); stmt.setString(1, deviceGroup.getDescription());
stmt.setString(2, deviceGroup.getName()); stmt.setString(2, deviceGroup.getName());
stmt.setString(3, deviceGroup.getOwner()); stmt.setString(3, deviceGroup.getOwner());
stmt.setInt(4, tenantId); stmt.setInt(4, tenantId);
if(hasStatus) {
stmt.setString(5, deviceGroup.getStatus());
}
stmt.execute(); stmt.execute();
rs = stmt.getGeneratedKeys(); rs = stmt.getGeneratedKeys();
if (rs.next()) { if (rs.next()) {
@ -77,7 +89,9 @@ public class PostgreSQLGroupDAOImpl extends AbstractGroupDAOImpl {
String groupName = request.getGroupName(); String groupName = request.getGroupName();
boolean hasGroupName = false; boolean hasGroupName = false;
String owner = request.getOwner(); String owner = request.getOwner();
String status = request.getStatus();
boolean hasOwner = false; boolean hasOwner = false;
boolean hasStatus = false;
boolean hasLimit = request.getRowCount() != 0; boolean hasLimit = request.getRowCount() != 0;
try { try {
@ -91,6 +105,10 @@ public class PostgreSQLGroupDAOImpl extends AbstractGroupDAOImpl {
sql += " AND OWNER LIKE ?"; sql += " AND OWNER LIKE ?";
hasOwner = true; hasOwner = true;
} }
if (status != null && !status.isEmpty()) {
sql += " AND STATUS = ?";
hasStatus = true;
}
if (hasLimit) { if (hasLimit) {
sql += " LIMIT ? OFFSET ?"; sql += " LIMIT ? OFFSET ?";
} }
@ -104,6 +122,9 @@ public class PostgreSQLGroupDAOImpl extends AbstractGroupDAOImpl {
if (hasOwner) { if (hasOwner) {
stmt.setString(paramIndex++, owner + "%"); stmt.setString(paramIndex++, owner + "%");
} }
if (hasStatus) {
stmt.setString(paramIndex++, status.toUpperCase());
}
if (hasLimit) { if (hasLimit) {
stmt.setInt(paramIndex++, request.getRowCount()); stmt.setInt(paramIndex++, request.getRowCount());
stmt.setInt(paramIndex, request.getStartIndex()); stmt.setInt(paramIndex, request.getStartIndex());

@ -50,6 +50,8 @@ public class SQLServerGroupDAOImpl extends AbstractGroupDAOImpl {
boolean hasGroupName = false; boolean hasGroupName = false;
String owner = request.getOwner(); String owner = request.getOwner();
boolean hasOwner = false; boolean hasOwner = false;
String status = request.getStatus();
boolean hasStatus = false;
boolean hasLimit = request.getRowCount() != 0; boolean hasLimit = request.getRowCount() != 0;
try { try {
@ -63,6 +65,10 @@ public class SQLServerGroupDAOImpl extends AbstractGroupDAOImpl {
sql += " AND OWNER LIKE ?"; sql += " AND OWNER LIKE ?";
hasOwner = true; hasOwner = true;
} }
if (status != null && !status.isEmpty()) {
sql += " AND STATUS = ?";
hasStatus = true;
}
if (hasLimit) { if (hasLimit) {
sql += " ORDER BY ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; sql += " ORDER BY ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY";
} }
@ -76,6 +82,9 @@ public class SQLServerGroupDAOImpl extends AbstractGroupDAOImpl {
if (hasOwner) { if (hasOwner) {
stmt.setString(paramIndex++, owner + "%"); stmt.setString(paramIndex++, owner + "%");
} }
if (hasStatus) {
stmt.setString(paramIndex++, status.toUpperCase());
}
if (hasLimit) { if (hasLimit) {
stmt.setInt(paramIndex++, request.getStartIndex()); stmt.setInt(paramIndex++, request.getStartIndex());
stmt.setInt(paramIndex, request.getRowCount()); stmt.setInt(paramIndex, request.getRowCount());

@ -2794,6 +2794,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
defaultGroup = new DeviceGroup(groupName); defaultGroup = new DeviceGroup(groupName);
// Setting system level user (wso2.system.user) as the owner // Setting system level user (wso2.system.user) as the owner
defaultGroup.setOwner(CarbonConstants.REGISTRY_SYSTEM_USERNAME); defaultGroup.setOwner(CarbonConstants.REGISTRY_SYSTEM_USERNAME);
defaultGroup.setStatus(DeviceGroupConstants.GroupStatus.ACTIVE);
defaultGroup.setDescription("Default system group for devices with " + groupName + " ownership."); defaultGroup.setDescription("Default system group for devices with " + groupName + " ownership.");
try { try {
service.createGroup(defaultGroup, DeviceGroupConstants.Roles.DEFAULT_ADMIN_ROLE, service.createGroup(defaultGroup, DeviceGroupConstants.Roles.DEFAULT_ADMIN_ROLE,

@ -127,6 +127,14 @@ public interface GroupManagementProviderService {
*/ */
int getGroupCount() throws GroupManagementException; int getGroupCount() throws GroupManagementException;
/**
* Get all device group count in tenant by group status
*
* @return group count
* @throws GroupManagementException
*/
int getGroupCountByStatus(String status) throws GroupManagementException;
/** /**
* Get device group count of user * Get device group count of user
* *

@ -472,7 +472,7 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid
try { try {
int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
GroupManagementDAOFactory.openConnection(); GroupManagementDAOFactory.openConnection();
return groupDAO.getGroupCount(tenantId); return groupDAO.getGroupCount(tenantId, null);
} catch (GroupManagementDAOException | SQLException e) { } catch (GroupManagementDAOException | SQLException e) {
String msg = "Error occurred while retrieving all groups in tenant"; String msg = "Error occurred while retrieving all groups in tenant";
log.error(msg, e); log.error(msg, e);
@ -485,6 +485,29 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid
GroupManagementDAOFactory.closeConnection(); GroupManagementDAOFactory.closeConnection();
} }
} }
@Override
public int getGroupCountByStatus(String status) throws GroupManagementException {
if (log.isDebugEnabled()) {
log.debug("Get groups count by Status");
}
int tenantId = -1;
try {
tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
GroupManagementDAOFactory.openConnection();
return groupDAO.getGroupCount(tenantId, status);
} catch (GroupManagementDAOException | SQLException e) {
String msg = "Error occurred while retrieving all groups in tenant " + tenantId
+" by status : " + status;
log.error(msg, e);
throw new GroupManagementException(msg, e);
} catch (Exception e) {
String msg = "Error occurred";
log.error(msg, e);
throw new GroupManagementException(msg, e);
} finally {
GroupManagementDAOFactory.closeConnection();
}
}
private int getGroupCount(GroupPaginationRequest request) throws GroupManagementException { private int getGroupCount(GroupPaginationRequest request) throws GroupManagementException {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
@ -882,6 +905,7 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid
DeviceGroup defaultGroup = this.getGroup(groupName); DeviceGroup defaultGroup = this.getGroup(groupName);
if (defaultGroup == null) { if (defaultGroup == null) {
defaultGroup = new DeviceGroup(groupName); defaultGroup = new DeviceGroup(groupName);
defaultGroup.setStatus(DeviceGroupConstants.GroupStatus.ACTIVE);
// Setting system level user (wso2.system.user) as the owner // Setting system level user (wso2.system.user) as the owner
defaultGroup.setOwner(CarbonConstants.REGISTRY_SYSTEM_USERNAME); defaultGroup.setOwner(CarbonConstants.REGISTRY_SYSTEM_USERNAME);
defaultGroup.setDescription("Default system group for devices with " + groupName + " ownership."); defaultGroup.setDescription("Default system group for devices with " + groupName + " ownership.");

@ -11,6 +11,7 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_TYPE (
CREATE TABLE IF NOT EXISTS DM_GROUP ( CREATE TABLE IF NOT EXISTS DM_GROUP (
ID INTEGER AUTO_INCREMENT NOT NULL, ID INTEGER AUTO_INCREMENT NOT NULL,
GROUP_NAME VARCHAR(100) DEFAULT NULL, GROUP_NAME VARCHAR(100) DEFAULT NULL,
STATUS VARCHAR(50) DEFAULT NULL,
DESCRIPTION TEXT DEFAULT NULL, DESCRIPTION TEXT DEFAULT NULL,
OWNER VARCHAR(45) DEFAULT NULL, OWNER VARCHAR(45) DEFAULT NULL,
TENANT_ID INTEGER DEFAULT 0, TENANT_ID INTEGER DEFAULT 0,

@ -14,6 +14,7 @@ CREATE TABLE IF NOT EXISTS DM_GROUP (
ID INTEGER AUTO_INCREMENT NOT NULL, ID INTEGER AUTO_INCREMENT NOT NULL,
GROUP_NAME VARCHAR(100) DEFAULT NULL, GROUP_NAME VARCHAR(100) DEFAULT NULL,
DESCRIPTION TEXT DEFAULT NULL, DESCRIPTION TEXT DEFAULT NULL,
STATUS VARCHAR(50) DEFAULT NULL,
DATE_OF_CREATE BIGINT DEFAULT NULL, DATE_OF_CREATE BIGINT DEFAULT NULL,
DATE_OF_LAST_UPDATE BIGINT DEFAULT NULL, DATE_OF_LAST_UPDATE BIGINT DEFAULT NULL,
OWNER VARCHAR(45) DEFAULT NULL, OWNER VARCHAR(45) DEFAULT NULL,

@ -20,6 +20,7 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_CERTIFICATE (
CREATE TABLE IF NOT EXISTS DM_GROUP ( CREATE TABLE IF NOT EXISTS DM_GROUP (
ID INTEGER AUTO_INCREMENT NOT NULL, ID INTEGER AUTO_INCREMENT NOT NULL,
GROUP_NAME VARCHAR(100) DEFAULT NULL, GROUP_NAME VARCHAR(100) DEFAULT NULL,
STATUS VARCHAR(50) DEFAULT NULL,
DESCRIPTION TEXT DEFAULT NULL, DESCRIPTION TEXT DEFAULT NULL,
OWNER VARCHAR(255) DEFAULT NULL, OWNER VARCHAR(255) DEFAULT NULL,
TENANT_ID INTEGER DEFAULT 0, TENANT_ID INTEGER DEFAULT 0,

@ -29,6 +29,7 @@ IF NOT EXISTS(SELECT *
CREATE TABLE DM_GROUP ( CREATE TABLE DM_GROUP (
ID INTEGER IDENTITY (1, 1) NOT NULL, ID INTEGER IDENTITY (1, 1) NOT NULL,
GROUP_NAME VARCHAR(100) DEFAULT NULL, GROUP_NAME VARCHAR(100) DEFAULT NULL,
STATUS VARCHAR(50) DEFAULT NULL,
DESCRIPTION VARCHAR(MAX) DEFAULT NULL, DESCRIPTION VARCHAR(MAX) DEFAULT NULL,
OWNER VARCHAR(255) DEFAULT NULL, OWNER VARCHAR(255) DEFAULT NULL,
TENANT_ID INTEGER DEFAULT 0, TENANT_ID INTEGER DEFAULT 0,

@ -24,6 +24,7 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_CERTIFICATE (
CREATE TABLE IF NOT EXISTS DM_GROUP ( CREATE TABLE IF NOT EXISTS DM_GROUP (
ID INTEGER AUTO_INCREMENT NOT NULL, ID INTEGER AUTO_INCREMENT NOT NULL,
GROUP_NAME VARCHAR(100) DEFAULT NULL, GROUP_NAME VARCHAR(100) DEFAULT NULL,
STATUS VARCHAR(50) DEFAULT NULL,
DESCRIPTION TEXT DEFAULT NULL, DESCRIPTION TEXT DEFAULT NULL,
OWNER VARCHAR(255) DEFAULT NULL, OWNER VARCHAR(255) DEFAULT NULL,
TENANT_ID INTEGER DEFAULT 0, TENANT_ID INTEGER DEFAULT 0,

@ -48,6 +48,7 @@ CREATE TABLE DM_GROUP (
ID NUMBER(10) NOT NULL, ID NUMBER(10) NOT NULL,
DESCRIPTION CLOB DEFAULT NULL, DESCRIPTION CLOB DEFAULT NULL,
GROUP_NAME VARCHAR2(100) DEFAULT NULL, GROUP_NAME VARCHAR2(100) DEFAULT NULL,
STATUS VARCHAR2(50) DEFAULT NULL,
OWNER VARCHAR2(255) DEFAULT NULL, OWNER VARCHAR2(255) DEFAULT NULL,
TENANT_ID NUMBER(10) DEFAULT 0, TENANT_ID NUMBER(10) DEFAULT 0,
CONSTRAINT PK_DM_GROUP PRIMARY KEY (ID) CONSTRAINT PK_DM_GROUP PRIMARY KEY (ID)

@ -19,6 +19,7 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_CERTIFICATE (
CREATE TABLE IF NOT EXISTS DM_GROUP ( CREATE TABLE IF NOT EXISTS DM_GROUP (
ID BIGSERIAL NOT NULL PRIMARY KEY, ID BIGSERIAL NOT NULL PRIMARY KEY,
GROUP_NAME VARCHAR(100) DEFAULT NULL, GROUP_NAME VARCHAR(100) DEFAULT NULL,
STATUS VARCHAR(50) DEFAULT NULL,
DESCRIPTION TEXT DEFAULT NULL, DESCRIPTION TEXT DEFAULT NULL,
OWNER VARCHAR(255) DEFAULT NULL, OWNER VARCHAR(255) DEFAULT NULL,
TENANT_ID INTEGER DEFAULT 0 TENANT_ID INTEGER DEFAULT 0

Loading…
Cancel
Save