Added basic RBAC component BOD-232
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import Icon, {
|
||||
ClockCircleFilled,
|
||||
CarFilled,
|
||||
ClockCircleFilled,
|
||||
DollarCircleFilled,
|
||||
FileAddFilled,
|
||||
FileFilled,
|
||||
@@ -16,15 +16,15 @@ import { FaCalendarAlt, FaCarCrash, FaCreditCard } from "react-icons/fa";
|
||||
import { connect } from "react-redux";
|
||||
import { Link } from "react-router-dom";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectRecentItems } from "../../redux/application/application.selectors";
|
||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
||||
import { signOutStart } from "../../redux/user/user.actions";
|
||||
import {
|
||||
selectBodyshop,
|
||||
selectCurrentUser,
|
||||
} from "../../redux/user/user.selectors";
|
||||
import "./header.styles.scss";
|
||||
import GlobalSearch from "../global-search/global-search.component";
|
||||
import { selectRecentItems } from "../../redux/application/application.selectors";
|
||||
import "./header.styles.scss";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
currentUser: selectCurrentUser,
|
||||
@@ -270,11 +270,13 @@ function Header({
|
||||
<Menu.Item key="shop">
|
||||
<Link to="/manage/shop">{t("menus.header.shop_config")}</Link>
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item key="shop-templates">
|
||||
<Link to="/manage/shop/templates">
|
||||
{t("menus.header.shop_templates")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item key="shop-vendors">
|
||||
<Link to="/manage/shop/vendors">
|
||||
{t("menus.header.shop_vendors")}
|
||||
|
||||
62
client/src/components/rbac-wrapper/rbac-defaults.js
Normal file
62
client/src/components/rbac-wrapper/rbac-defaults.js
Normal file
@@ -0,0 +1,62 @@
|
||||
export default {
|
||||
"accounting:payables": 1,
|
||||
"accounting:payments": 1,
|
||||
"accounting:receivables": 1,
|
||||
|
||||
"csi:page": 6,
|
||||
"csi:export": 5,
|
||||
|
||||
"contracts:create": 2,
|
||||
"contracts:detail": 2,
|
||||
"contracts:list": 2,
|
||||
|
||||
"courtesycar:create": 2,
|
||||
"courtesycar:detail": 2,
|
||||
"courtesycar:list": 2,
|
||||
|
||||
"jobs:list-active": 1,
|
||||
"jobs:list-all": 2,
|
||||
"jobs:available-list": 2,
|
||||
"jobs:create": 1,
|
||||
"jobs:intake": 1,
|
||||
"jobs:line-edit": 3,
|
||||
"jobs:scoreboard-add": 3,
|
||||
"jobs:close": 5,
|
||||
"jobs:documents-upload": 3,
|
||||
"jobs:documents-view": 2,
|
||||
"jobs:audit-trail": 5,
|
||||
"jobs:detail": 1,
|
||||
|
||||
"invoices:enter": 2,
|
||||
"invoices:view": 2,
|
||||
"invoices:list": 2,
|
||||
|
||||
"employees:rate": 5,
|
||||
"employees:page": 5,
|
||||
|
||||
"messaging:affix": 2,
|
||||
|
||||
"owners:list": 2,
|
||||
"owners:detail": 3,
|
||||
|
||||
"payments:enter": 3,
|
||||
"payments:list": 3,
|
||||
|
||||
"production:board": 1,
|
||||
"production:list": 1,
|
||||
|
||||
"sendemail:send": 1,
|
||||
|
||||
"schedule:view": 2,
|
||||
|
||||
"scoreboard:view": 3,
|
||||
|
||||
"shiftclock:view": 2,
|
||||
|
||||
"shop:vendors": 2,
|
||||
"shop:rbac": 5,
|
||||
"shop:templates": 4,
|
||||
|
||||
"timetickets:enter": 3,
|
||||
"timetickets:list": 3,
|
||||
};
|
||||
@@ -0,0 +1,57 @@
|
||||
import PropTypes from "prop-types";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import {
|
||||
selectAuthLevel,
|
||||
selectBodyshop,
|
||||
selectCurrentUser,
|
||||
} from "../../redux/user/user.selectors";
|
||||
import AlertComponent from "../alert/alert.component";
|
||||
import rbacDefaults from "./rbac-defaults";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
currentUser: selectCurrentUser,
|
||||
authLevel: selectAuthLevel,
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
|
||||
function RbacWrapper({
|
||||
currentUser,
|
||||
authLevel,
|
||||
bodyshop,
|
||||
requiredAuthLevel,
|
||||
noauth,
|
||||
children,
|
||||
action,
|
||||
dispatch,
|
||||
...restProps
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
if (
|
||||
(requiredAuthLevel && requiredAuthLevel <= authLevel) ||
|
||||
(bodyshop.md_rbac && bodyshop.md_rbac[action] <= authLevel) ||
|
||||
(!!!bodyshop.md_rbac && rbacDefaults[action] <= authLevel)
|
||||
)
|
||||
return <div>{React.cloneElement(children, restProps)}</div>;
|
||||
|
||||
return (
|
||||
noauth || (
|
||||
<AlertComponent
|
||||
message={t("general.messages.rbacunauth")}
|
||||
type="warning"
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
RbacWrapper.propTypes = {
|
||||
currentUser: PropTypes.object.isRequired,
|
||||
authLevel: PropTypes.number.isRequired,
|
||||
noauth: PropTypes.oneOfType(PropTypes.string, PropTypes.func),
|
||||
requiredAuthLevel: PropTypes.number,
|
||||
action: PropTypes.string,
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps, null)(RbacWrapper);
|
||||
@@ -1,4 +1,7 @@
|
||||
import Icon from "@ant-design/icons";
|
||||
import { Statistic } from "antd";
|
||||
import React from "react";
|
||||
import { MdFileDownload, MdFileUpload } from "react-icons/md";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import {
|
||||
@@ -6,14 +9,6 @@ import {
|
||||
selectScheduleLoadCalculating,
|
||||
} from "../../redux/application/application.selectors";
|
||||
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
|
||||
import { Progress, Statistic } from "antd";
|
||||
import {
|
||||
MdCallReceived,
|
||||
MdCallMissedOutgoing,
|
||||
MdFileDownload,
|
||||
MdFileUpload,
|
||||
} from "react-icons/md";
|
||||
import Icon from "@ant-design/icons";
|
||||
import ScheduleBlockDay from "../schedule-block-day/schedule-block-day.component";
|
||||
|
||||
const ShopTargetHrs = 100;
|
||||
|
||||
Reference in New Issue
Block a user