Redirect back to original URL if user redirected to loging screen (#1187)
* Redirect back to original URL if user redirected to loging screen Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com> * Cover SSO cases Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com> Co-authored-by: Lenin Alevski <alevsk.8772@gmail.com> Co-authored-by: Alex <33497058+bexsoft@users.noreply.github.com>
This commit is contained in:
@@ -8,7 +8,7 @@ RUN yarn install
|
|||||||
|
|
||||||
COPY ./portal-ui .
|
COPY ./portal-ui .
|
||||||
|
|
||||||
RUN yarn install && make build-static
|
RUN make build-static
|
||||||
|
|
||||||
USER node
|
USER node
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ export class API {
|
|||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
// if we get unauthorized, kick out the user
|
// if we get unauthorized, kick out the user
|
||||||
if (err.status === 401) {
|
if (err.status === 401) {
|
||||||
|
if (window.location.pathname !== "/") {
|
||||||
|
localStorage.setItem("redirect-path", window.location.pathname);
|
||||||
|
}
|
||||||
clearSession();
|
clearSession();
|
||||||
// Refresh the whole page to ensure cache is clear
|
// Refresh the whole page to ensure cache is clear
|
||||||
// and we dont end on an infinite loop
|
// and we dont end on an infinite loop
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ import {
|
|||||||
serverIsLoading,
|
serverIsLoading,
|
||||||
serverNeedsRestart,
|
serverNeedsRestart,
|
||||||
setMenuOpen,
|
setMenuOpen,
|
||||||
setSnackBarMessage
|
setSnackBarMessage,
|
||||||
} from "../../actions";
|
} from "../../actions";
|
||||||
import { ISessionResponse } from "./types";
|
import { ISessionResponse } from "./types";
|
||||||
import { snackBarMessage } from "../../types";
|
import { snackBarMessage } from "../../types";
|
||||||
@@ -75,44 +75,44 @@ const styles = (theme: Theme) =>
|
|||||||
display: "flex",
|
display: "flex",
|
||||||
"& .MuiPaper-root.MuiSnackbarContent-root": {
|
"& .MuiPaper-root.MuiSnackbarContent-root": {
|
||||||
borderRadius: "0px 0px 5px 5px",
|
borderRadius: "0px 0px 5px 5px",
|
||||||
boxShadow: "none"
|
boxShadow: "none",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
toolbar: {
|
toolbar: {
|
||||||
background: theme.palette.background.default,
|
background: theme.palette.background.default,
|
||||||
color: "black",
|
color: "black",
|
||||||
paddingRight: 24 // keep right padding when drawer closed
|
paddingRight: 24, // keep right padding when drawer closed
|
||||||
},
|
},
|
||||||
toolbarIcon: {
|
toolbarIcon: {
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "flex-end",
|
justifyContent: "flex-end",
|
||||||
padding: "0 8px",
|
padding: "0 8px",
|
||||||
...theme.mixins.toolbar
|
...theme.mixins.toolbar,
|
||||||
},
|
},
|
||||||
appBar: {
|
appBar: {
|
||||||
zIndex: theme.zIndex.drawer + 1,
|
zIndex: theme.zIndex.drawer + 1,
|
||||||
transition: theme.transitions.create(["width", "margin"], {
|
transition: theme.transitions.create(["width", "margin"], {
|
||||||
easing: theme.transitions.easing.sharp,
|
easing: theme.transitions.easing.sharp,
|
||||||
duration: theme.transitions.duration.leavingScreen
|
duration: theme.transitions.duration.leavingScreen,
|
||||||
})
|
}),
|
||||||
},
|
},
|
||||||
appBarShift: {
|
appBarShift: {
|
||||||
marginLeft: drawerWidth,
|
marginLeft: drawerWidth,
|
||||||
width: `calc(100% - ${drawerWidth}px)`,
|
width: `calc(100% - ${drawerWidth}px)`,
|
||||||
transition: theme.transitions.create(["width", "margin"], {
|
transition: theme.transitions.create(["width", "margin"], {
|
||||||
easing: theme.transitions.easing.sharp,
|
easing: theme.transitions.easing.sharp,
|
||||||
duration: theme.transitions.duration.enteringScreen
|
duration: theme.transitions.duration.enteringScreen,
|
||||||
})
|
}),
|
||||||
},
|
},
|
||||||
menuButton: {
|
menuButton: {
|
||||||
marginRight: 36
|
marginRight: 36,
|
||||||
},
|
},
|
||||||
menuButtonHidden: {
|
menuButtonHidden: {
|
||||||
display: "none"
|
display: "none",
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
flexGrow: 1
|
flexGrow: 1,
|
||||||
},
|
},
|
||||||
drawerPaper: {
|
drawerPaper: {
|
||||||
position: "relative",
|
position: "relative",
|
||||||
@@ -120,44 +120,44 @@ const styles = (theme: Theme) =>
|
|||||||
width: drawerWidth,
|
width: drawerWidth,
|
||||||
transition: theme.transitions.create("width", {
|
transition: theme.transitions.create("width", {
|
||||||
easing: theme.transitions.easing.sharp,
|
easing: theme.transitions.easing.sharp,
|
||||||
duration: theme.transitions.duration.enteringScreen
|
duration: theme.transitions.duration.enteringScreen,
|
||||||
}),
|
}),
|
||||||
overflowX: "hidden",
|
overflowX: "hidden",
|
||||||
background:
|
background:
|
||||||
"transparent linear-gradient(90deg, #073052 0%, #081C42 100%) 0% 0% no-repeat padding-box",
|
"transparent linear-gradient(90deg, #073052 0%, #081C42 100%) 0% 0% no-repeat padding-box",
|
||||||
boxShadow: "0px 3px 7px #00000014"
|
boxShadow: "0px 3px 7px #00000014",
|
||||||
},
|
},
|
||||||
drawerPaperClose: {
|
drawerPaperClose: {
|
||||||
overflowX: "hidden",
|
overflowX: "hidden",
|
||||||
transition: theme.transitions.create("width", {
|
transition: theme.transitions.create("width", {
|
||||||
easing: theme.transitions.easing.sharp,
|
easing: theme.transitions.easing.sharp,
|
||||||
duration: theme.transitions.duration.leavingScreen
|
duration: theme.transitions.duration.leavingScreen,
|
||||||
}),
|
}),
|
||||||
width: theme.spacing(7),
|
width: theme.spacing(7),
|
||||||
[theme.breakpoints.up("sm")]: {
|
[theme.breakpoints.up("sm")]: {
|
||||||
width: theme.spacing(9)
|
width: theme.spacing(9),
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
height: "100vh",
|
height: "100vh",
|
||||||
overflow: "auto",
|
overflow: "auto",
|
||||||
position: "relative"
|
position: "relative",
|
||||||
},
|
},
|
||||||
container: {
|
container: {
|
||||||
paddingBottom: theme.spacing(4),
|
paddingBottom: theme.spacing(4),
|
||||||
margin: 0,
|
margin: 0,
|
||||||
width: "100%",
|
width: "100%",
|
||||||
maxWidth: "initial"
|
maxWidth: "initial",
|
||||||
},
|
},
|
||||||
paper: {
|
paper: {
|
||||||
padding: theme.spacing(2),
|
padding: theme.spacing(2),
|
||||||
display: "flex",
|
display: "flex",
|
||||||
overflow: "auto",
|
overflow: "auto",
|
||||||
flexDirection: "column"
|
flexDirection: "column",
|
||||||
},
|
},
|
||||||
fixedHeight: {
|
fixedHeight: {
|
||||||
minHeight: 240
|
minHeight: 240,
|
||||||
},
|
},
|
||||||
warningBar: {
|
warningBar: {
|
||||||
background: theme.palette.primary.main,
|
background: theme.palette.primary.main,
|
||||||
@@ -165,13 +165,13 @@ const styles = (theme: Theme) =>
|
|||||||
heigh: "60px",
|
heigh: "60px",
|
||||||
widht: "100%",
|
widht: "100%",
|
||||||
lineHeight: "60px",
|
lineHeight: "60px",
|
||||||
textAlign: "center"
|
textAlign: "center",
|
||||||
},
|
},
|
||||||
progress: {
|
progress: {
|
||||||
height: "3px",
|
height: "3px",
|
||||||
backgroundColor: "#eaeaea"
|
backgroundColor: "#eaeaea",
|
||||||
},
|
},
|
||||||
...snackBarCommon
|
...snackBarCommon,
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IConsoleProps {
|
interface IConsoleProps {
|
||||||
@@ -190,17 +190,17 @@ interface IConsoleProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Console = ({
|
const Console = ({
|
||||||
classes,
|
classes,
|
||||||
open,
|
open,
|
||||||
needsRestart,
|
needsRestart,
|
||||||
isServerLoading,
|
isServerLoading,
|
||||||
serverNeedsRestart,
|
serverNeedsRestart,
|
||||||
serverIsLoading,
|
serverIsLoading,
|
||||||
session,
|
session,
|
||||||
loadingProgress,
|
loadingProgress,
|
||||||
snackBarMessage,
|
snackBarMessage,
|
||||||
setSnackBarMessage
|
setSnackBarMessage,
|
||||||
}: IConsoleProps) => {
|
}: IConsoleProps) => {
|
||||||
const [openSnackbar, setOpenSnackbar] = useState<boolean>(false);
|
const [openSnackbar, setOpenSnackbar] = useState<boolean>(false);
|
||||||
|
|
||||||
const restartServer = () => {
|
const restartServer = () => {
|
||||||
@@ -223,185 +223,186 @@ const Console = ({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const allowedPages = session.pages.reduce(
|
const allowedPages = !session
|
||||||
(result: any, item: any, index: any) => {
|
? []
|
||||||
result[item] = true;
|
: session.pages.reduce((result: any, item: any, index: any) => {
|
||||||
return result;
|
result[item] = true;
|
||||||
},
|
return result;
|
||||||
{}
|
}, {});
|
||||||
);
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{
|
{
|
||||||
component: Dashboard,
|
component: Dashboard,
|
||||||
path: "/dashboard"
|
path: "/dashboard",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: Metrics,
|
component: Metrics,
|
||||||
path: "/metrics"
|
path: "/metrics",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: Buckets,
|
component: Buckets,
|
||||||
path: "/buckets"
|
path: "/buckets",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: Buckets,
|
component: Buckets,
|
||||||
path: "/buckets/*"
|
path: "/buckets/*",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: Watch,
|
component: Watch,
|
||||||
path: "/tools/watch"
|
path: "/tools/watch",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: Users,
|
component: Users,
|
||||||
path: "/users/:userName+"
|
path: "/users/:userName+",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: Users,
|
component: Users,
|
||||||
path: "/users"
|
path: "/users",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: Groups,
|
component: Groups,
|
||||||
path: "/groups"
|
path: "/groups",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: GroupsDetails,
|
component: GroupsDetails,
|
||||||
path: "/groups/:groupName+"
|
path: "/groups/:groupName+",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: Policies,
|
component: Policies,
|
||||||
path: "/policies/*"
|
path: "/policies/*",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: Policies,
|
component: Policies,
|
||||||
path: "/policies"
|
path: "/policies",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: Heal,
|
component: Heal,
|
||||||
path: "/tools/heal"
|
path: "/tools/heal",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: Trace,
|
component: Trace,
|
||||||
path: "/tools/trace"
|
path: "/tools/trace",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: HealthInfo,
|
component: HealthInfo,
|
||||||
path: "/tools/diagnostics"
|
path: "/tools/diagnostics",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: ErrorLogs,
|
component: ErrorLogs,
|
||||||
path: "/tools/logs"
|
path: "/tools/logs",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: LogsSearchMain,
|
component: LogsSearchMain,
|
||||||
path: "/tools/audit-logs"
|
path: "/tools/audit-logs",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: Tools,
|
component: Tools,
|
||||||
path: "/tools"
|
path: "/tools",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: ConfigurationMain,
|
component: ConfigurationMain,
|
||||||
path: "/settings"
|
path: "/settings",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: ConfigurationMain,
|
component: ConfigurationMain,
|
||||||
path: "/settings/:option"
|
path: "/settings/:option",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: AddNotificationEndpoint,
|
component: AddNotificationEndpoint,
|
||||||
path: "/notification-endpoints/add/:service"
|
path: "/notification-endpoints/add/:service",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: NotificationTypeSelector,
|
component: NotificationTypeSelector,
|
||||||
path: "/notification-endpoints/add"
|
path: "/notification-endpoints/add",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: NotificationEndpoints,
|
component: NotificationEndpoints,
|
||||||
path: "/notification-endpoints"
|
path: "/notification-endpoints",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: AddTierConfiguration,
|
component: AddTierConfiguration,
|
||||||
path: "/tiers/add/:service"
|
path: "/tiers/add/:service",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: TierTypeSelector,
|
component: TierTypeSelector,
|
||||||
path: "/tiers/add"
|
path: "/tiers/add",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: ListTiersConfiguration,
|
component: ListTiersConfiguration,
|
||||||
path: "/tiers"
|
path: "/tiers",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: Account,
|
component: Account,
|
||||||
path: "/account",
|
path: "/account",
|
||||||
props: {
|
props: {
|
||||||
changePassword: session.pages.includes("/account/change-password")
|
changePassword: (!session ? [] : session.pages).includes(
|
||||||
}
|
"/account/change-password"
|
||||||
|
),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: ListTenants,
|
component: ListTenants,
|
||||||
path: "/tenants"
|
path: "/tenants",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: AddTenant,
|
component: AddTenant,
|
||||||
path: "/tenants/add"
|
path: "/tenants/add",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: Storage,
|
component: Storage,
|
||||||
path: "/storage"
|
path: "/storage",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: Storage,
|
component: Storage,
|
||||||
path: "/storage/volumes"
|
path: "/storage/volumes",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: Storage,
|
component: Storage,
|
||||||
path: "/storage/drives"
|
path: "/storage/drives",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: TenantDetails,
|
component: TenantDetails,
|
||||||
path: "/namespaces/:tenantNamespace/tenants/:tenantName"
|
path: "/namespaces/:tenantNamespace/tenants/:tenantName",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: Hop,
|
component: Hop,
|
||||||
path: "/namespaces/:tenantNamespace/tenants/:tenantName/hop"
|
path: "/namespaces/:tenantNamespace/tenants/:tenantName/hop",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: TenantDetails,
|
component: TenantDetails,
|
||||||
path: "/namespaces/:tenantNamespace/tenants/:tenantName/pods/:podName"
|
path: "/namespaces/:tenantNamespace/tenants/:tenantName/pods/:podName",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: TenantDetails,
|
component: TenantDetails,
|
||||||
path: "/namespaces/:tenantNamespace/tenants/:tenantName/summary"
|
path: "/namespaces/:tenantNamespace/tenants/:tenantName/summary",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: TenantDetails,
|
component: TenantDetails,
|
||||||
path: "/namespaces/:tenantNamespace/tenants/:tenantName/metrics"
|
path: "/namespaces/:tenantNamespace/tenants/:tenantName/metrics",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: TenantDetails,
|
component: TenantDetails,
|
||||||
path: "/namespaces/:tenantNamespace/tenants/:tenantName/pods"
|
path: "/namespaces/:tenantNamespace/tenants/:tenantName/pods",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: TenantDetails,
|
component: TenantDetails,
|
||||||
path: "/namespaces/:tenantNamespace/tenants/:tenantName/pools"
|
path: "/namespaces/:tenantNamespace/tenants/:tenantName/pools",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: TenantDetails,
|
component: TenantDetails,
|
||||||
path: "/namespaces/:tenantNamespace/tenants/:tenantName/volumes"
|
path: "/namespaces/:tenantNamespace/tenants/:tenantName/volumes",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: TenantDetails,
|
component: TenantDetails,
|
||||||
path: "/namespaces/:tenantNamespace/tenants/:tenantName/license"
|
path: "/namespaces/:tenantNamespace/tenants/:tenantName/license",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: TenantDetails,
|
component: TenantDetails,
|
||||||
path: "/namespaces/:tenantNamespace/tenants/:tenantName/security"
|
path: "/namespaces/:tenantNamespace/tenants/:tenantName/security",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: License,
|
component: License,
|
||||||
path: "/license"
|
path: "/license",
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
const allowedRoutes = routes.filter((route: any) => allowedPages[route.path]);
|
const allowedRoutes = routes.filter((route: any) => allowedPages[route.path]);
|
||||||
|
|
||||||
@@ -432,7 +433,7 @@ const Console = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
{session.status === "ok" ? (
|
{session && session.status === "ok" ? (
|
||||||
<div className={classes.root}>
|
<div className={classes.root}>
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
{!hideMenu && <Menu pages={session.pages} />}
|
{!hideMenu && <Menu pages={session.pages} />}
|
||||||
@@ -486,7 +487,7 @@ const Console = ({
|
|||||||
snackBarMessage.type === "error"
|
snackBarMessage.type === "error"
|
||||||
? classes.errorSnackBar
|
? classes.errorSnackBar
|
||||||
: ""
|
: ""
|
||||||
}`
|
}`,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -520,14 +521,14 @@ const mapState = (state: AppState) => ({
|
|||||||
isServerLoading: state.system.serverIsLoading,
|
isServerLoading: state.system.serverIsLoading,
|
||||||
session: state.console.session,
|
session: state.console.session,
|
||||||
loadingProgress: state.system.loadingProgress,
|
loadingProgress: state.system.loadingProgress,
|
||||||
snackBarMessage: state.system.snackBar
|
snackBarMessage: state.system.snackBar,
|
||||||
});
|
});
|
||||||
|
|
||||||
const connector = connect(mapState, {
|
const connector = connect(mapState, {
|
||||||
setMenuOpen,
|
setMenuOpen,
|
||||||
serverNeedsRestart,
|
serverNeedsRestart,
|
||||||
serverIsLoading,
|
serverIsLoading,
|
||||||
setSnackBarMessage
|
setSnackBarMessage,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default withStyles(styles)(connector(Console));
|
export default withStyles(styles)(connector(Console));
|
||||||
|
|||||||
@@ -14,36 +14,34 @@ import { modalBasic } from "../Common/FormComponents/common/styleLibrary";
|
|||||||
import withStyles from "@mui/styles/withStyles";
|
import withStyles from "@mui/styles/withStyles";
|
||||||
|
|
||||||
type UserPickerModalProps = {
|
type UserPickerModalProps = {
|
||||||
classes?: any,
|
classes?: any;
|
||||||
title?: string
|
title?: string;
|
||||||
preSelectedUsers?: string[]
|
preSelectedUsers?: string[];
|
||||||
selectedGroup?: string,
|
selectedGroup?: string;
|
||||||
open: boolean,
|
open: boolean;
|
||||||
onClose: () => void,
|
onClose: () => void;
|
||||||
onSaveClick: () => void,
|
onSaveClick: () => void;
|
||||||
groupStatus?: string,
|
groupStatus?: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
const styles = (theme: Theme) =>
|
const styles = (theme: Theme) =>
|
||||||
createStyles({
|
createStyles({
|
||||||
buttonContainer: {
|
buttonContainer: {
|
||||||
textAlign: "right",
|
textAlign: "right",
|
||||||
marginTop: "1rem"
|
marginTop: "1rem",
|
||||||
},
|
},
|
||||||
...modalBasic
|
...modalBasic,
|
||||||
});
|
});
|
||||||
|
|
||||||
const AddGroupMember = ({
|
const AddGroupMember = ({
|
||||||
classes,
|
classes,
|
||||||
title = "",
|
title = "",
|
||||||
groupStatus = "enabled",
|
groupStatus = "enabled",
|
||||||
preSelectedUsers = [],
|
preSelectedUsers = [],
|
||||||
selectedGroup = "",
|
selectedGroup = "",
|
||||||
open,
|
open,
|
||||||
onClose
|
onClose,
|
||||||
}: UserPickerModalProps) => {
|
}: UserPickerModalProps) => {
|
||||||
|
|
||||||
const [selectedUsers, setSelectedUsers] = useState(preSelectedUsers);
|
const [selectedUsers, setSelectedUsers] = useState(preSelectedUsers);
|
||||||
|
|
||||||
function addMembersToGroup() {
|
function addMembersToGroup() {
|
||||||
@@ -51,8 +49,7 @@ const AddGroupMember = ({
|
|||||||
.invoke("PUT", `/api/v1/group?name=${encodeURI(selectedGroup)}`, {
|
.invoke("PUT", `/api/v1/group?name=${encodeURI(selectedGroup)}`, {
|
||||||
group: selectedGroup,
|
group: selectedGroup,
|
||||||
members: selectedUsers,
|
members: selectedUsers,
|
||||||
status: groupStatus
|
status: groupStatus,
|
||||||
|
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
onClose();
|
onClose();
|
||||||
@@ -64,16 +61,8 @@ const AddGroupMember = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ModalWrapper
|
<ModalWrapper modalOpen={open} onClose={onClose} title={title}>
|
||||||
modalOpen={open}
|
<PredefinedList label={`Selected Group`} content={selectedGroup} />
|
||||||
onClose={onClose}
|
|
||||||
title={title}
|
|
||||||
>
|
|
||||||
|
|
||||||
<PredefinedList
|
|
||||||
label={`Selected Group`}
|
|
||||||
content={selectedGroup}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
<UsersSelectors
|
<UsersSelectors
|
||||||
@@ -83,7 +72,6 @@ const AddGroupMember = ({
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<Grid item xs={12} className={classes.buttonContainer}>
|
<Grid item xs={12} className={classes.buttonContainer}>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
color="primary"
|
color="primary"
|
||||||
@@ -106,15 +94,12 @@ const AddGroupMember = ({
|
|||||||
Save
|
Save
|
||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
</ModalWrapper>
|
</ModalWrapper>
|
||||||
);
|
);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const mapDispatchToProps = {
|
const mapDispatchToProps = {
|
||||||
setModalErrorSnackMessage
|
setModalErrorSnackMessage,
|
||||||
};
|
};
|
||||||
|
|
||||||
const connector = connect(null, mapDispatchToProps);
|
const connector = connect(null, mapDispatchToProps);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import {
|
|||||||
actionsTray,
|
actionsTray,
|
||||||
containerForHeader,
|
containerForHeader,
|
||||||
linkStyles,
|
linkStyles,
|
||||||
searchField
|
searchField,
|
||||||
} from "../Common/FormComponents/common/styleLibrary";
|
} from "../Common/FormComponents/common/styleLibrary";
|
||||||
import { ErrorResponseHandler } from "../../../common/types";
|
import { ErrorResponseHandler } from "../../../common/types";
|
||||||
import api from "../../../common/api";
|
import api from "../../../common/api";
|
||||||
@@ -53,42 +53,42 @@ interface IGroupsProps {
|
|||||||
const styles = (theme: Theme) =>
|
const styles = (theme: Theme) =>
|
||||||
createStyles({
|
createStyles({
|
||||||
seeMore: {
|
seeMore: {
|
||||||
marginTop: theme.spacing(3)
|
marginTop: theme.spacing(3),
|
||||||
},
|
},
|
||||||
paper: {
|
paper: {
|
||||||
// padding: theme.spacing(2),
|
// padding: theme.spacing(2),
|
||||||
display: "flex",
|
display: "flex",
|
||||||
overflow: "auto",
|
overflow: "auto",
|
||||||
flexDirection: "column"
|
flexDirection: "column",
|
||||||
},
|
},
|
||||||
addSideBar: {
|
addSideBar: {
|
||||||
width: "320px",
|
width: "320px",
|
||||||
padding: "20px"
|
padding: "20px",
|
||||||
},
|
},
|
||||||
tableToolbar: {
|
tableToolbar: {
|
||||||
paddingLeft: theme.spacing(2),
|
paddingLeft: theme.spacing(2),
|
||||||
paddingRight: theme.spacing(0)
|
paddingRight: theme.spacing(0),
|
||||||
},
|
},
|
||||||
wrapCell: {
|
wrapCell: {
|
||||||
maxWidth: "200px",
|
maxWidth: "200px",
|
||||||
whiteSpace: "normal",
|
whiteSpace: "normal",
|
||||||
wordWrap: "break-word"
|
wordWrap: "break-word",
|
||||||
},
|
},
|
||||||
twHeight: {
|
twHeight: {
|
||||||
minHeight: 600
|
minHeight: 600,
|
||||||
},
|
},
|
||||||
minTableHeader: {
|
minTableHeader: {
|
||||||
color: "#393939",
|
color: "#393939",
|
||||||
"& tr": {
|
"& tr": {
|
||||||
"& th": {
|
"& th": {
|
||||||
fontWeight: "bold"
|
fontWeight: "bold",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
...linkStyles(theme.palette.info.main),
|
...linkStyles(theme.palette.info.main),
|
||||||
...actionsTray,
|
...actionsTray,
|
||||||
...searchField,
|
...searchField,
|
||||||
...containerForHeader(theme.spacing(4))
|
...containerForHeader(theme.spacing(4)),
|
||||||
});
|
});
|
||||||
|
|
||||||
const Groups = ({ classes, setErrorSnackMessage }: IGroupsProps) => {
|
const Groups = ({ classes, setErrorSnackMessage }: IGroupsProps) => {
|
||||||
@@ -158,7 +158,7 @@ const Groups = ({ classes, setErrorSnackMessage }: IGroupsProps) => {
|
|||||||
|
|
||||||
const tableActions = [
|
const tableActions = [
|
||||||
{ type: "view", onClick: viewAction },
|
{ type: "view", onClick: viewAction },
|
||||||
{ type: "delete", onClick: deleteAction }
|
{ type: "delete", onClick: deleteAction },
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -202,7 +202,7 @@ const Groups = ({ classes, setErrorSnackMessage }: IGroupsProps) => {
|
|||||||
<InputAdornment position="start">
|
<InputAdornment position="start">
|
||||||
<SearchIcon />
|
<SearchIcon />
|
||||||
</InputAdornment>
|
</InputAdornment>
|
||||||
)
|
),
|
||||||
}}
|
}}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setFilter(e.target.value);
|
setFilter(e.target.value);
|
||||||
@@ -313,7 +313,7 @@ const Groups = ({ classes, setErrorSnackMessage }: IGroupsProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const mapDispatchToProps = {
|
const mapDispatchToProps = {
|
||||||
setErrorSnackMessage
|
setErrorSnackMessage,
|
||||||
};
|
};
|
||||||
|
|
||||||
const connector = connect(null, mapDispatchToProps);
|
const connector = connect(null, mapDispatchToProps);
|
||||||
|
|||||||
@@ -3,8 +3,15 @@ import PageHeader from "../Common/PageHeader/PageHeader";
|
|||||||
import { Link, useParams } from "react-router-dom";
|
import { Link, useParams } from "react-router-dom";
|
||||||
import { Theme } from "@mui/material/styles";
|
import { Theme } from "@mui/material/styles";
|
||||||
import createStyles from "@mui/styles/createStyles";
|
import createStyles from "@mui/styles/createStyles";
|
||||||
import { actionsTray, containerForHeader, searchField } from "../Common/FormComponents/common/styleLibrary";
|
import {
|
||||||
import { setErrorSnackMessage, setModalErrorSnackMessage } from "../../../actions";
|
actionsTray,
|
||||||
|
containerForHeader,
|
||||||
|
searchField,
|
||||||
|
} from "../Common/FormComponents/common/styleLibrary";
|
||||||
|
import {
|
||||||
|
setErrorSnackMessage,
|
||||||
|
setModalErrorSnackMessage,
|
||||||
|
} from "../../../actions";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import withStyles from "@mui/styles/withStyles";
|
import withStyles from "@mui/styles/withStyles";
|
||||||
import { Button, Grid, IconButton, Tooltip } from "@mui/material";
|
import { Button, Grid, IconButton, Tooltip } from "@mui/material";
|
||||||
@@ -22,17 +29,16 @@ import AddGroupMember from "./AddGroupMember";
|
|||||||
import { ErrorResponseHandler } from "../../../common/types";
|
import { ErrorResponseHandler } from "../../../common/types";
|
||||||
import DeleteGroup from "./DeleteGroup";
|
import DeleteGroup from "./DeleteGroup";
|
||||||
|
|
||||||
|
|
||||||
const styles = (theme: Theme) =>
|
const styles = (theme: Theme) =>
|
||||||
createStyles({
|
createStyles({
|
||||||
breadcrumLink: {
|
breadcrumLink: {
|
||||||
textDecoration: "none",
|
textDecoration: "none",
|
||||||
color: "black"
|
color: "black",
|
||||||
},
|
},
|
||||||
...actionsTray,
|
...actionsTray,
|
||||||
...searchField,
|
...searchField,
|
||||||
actionsTray: { ...actionsTray.actionsTray },
|
actionsTray: { ...actionsTray.actionsTray },
|
||||||
...containerForHeader(theme.spacing(4))
|
...containerForHeader(theme.spacing(4)),
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IGroupDetailsProps {
|
interface IGroupDetailsProps {
|
||||||
@@ -42,24 +48,22 @@ interface IGroupDetailsProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TabItemsProps = {
|
type TabItemsProps = {
|
||||||
activeTab: number,
|
activeTab: number;
|
||||||
onTabChange: (tab: number) => void
|
onTabChange: (tab: number) => void;
|
||||||
}
|
};
|
||||||
|
|
||||||
type DetailsHeaderProps = {
|
type DetailsHeaderProps = {
|
||||||
classes: any
|
classes: any;
|
||||||
}
|
};
|
||||||
|
|
||||||
type GroupInfo = {
|
type GroupInfo = {
|
||||||
members?: any[]
|
members?: any[];
|
||||||
name?: string
|
name?: string;
|
||||||
policy?: string
|
policy?: string;
|
||||||
status?: string
|
status?: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
const TabItems = ({ activeTab, onTabChange }: TabItemsProps) => {
|
const TabItems = ({ activeTab, onTabChange }: TabItemsProps) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<List component="nav" dense={true}>
|
<List component="nav" dense={true}>
|
||||||
<ListItem
|
<ListItem
|
||||||
@@ -80,12 +84,10 @@ const TabItems = ({ activeTab, onTabChange }: TabItemsProps) => {
|
|||||||
>
|
>
|
||||||
<ListItemText primary="Policies" />
|
<ListItemText primary="Policies" />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
</List>
|
</List>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export const formatPolicy = (policy: string = ""): string[] => {
|
export const formatPolicy = (policy: string = ""): string[] => {
|
||||||
if (policy.length <= 0) return [];
|
if (policy.length <= 0) return [];
|
||||||
return policy.split(",");
|
return policy.split(",");
|
||||||
@@ -95,7 +97,6 @@ export const getPoliciesAsString = (policies: string[]): string => {
|
|||||||
return policies.join(", ");
|
return policies.join(", ");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const GroupDetailsHeader = ({ classes }: DetailsHeaderProps) => {
|
const GroupDetailsHeader = ({ classes }: DetailsHeaderProps) => {
|
||||||
return (
|
return (
|
||||||
<PageHeader
|
<PageHeader
|
||||||
@@ -111,9 +112,7 @@ const GroupDetailsHeader = ({ classes }: DetailsHeaderProps) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
|
const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
|
||||||
|
|
||||||
const [currentTab, setCurrentTab] = useState<number>(0);
|
const [currentTab, setCurrentTab] = useState<number>(0);
|
||||||
const [groupDetails, setGroupDetails] = useState<GroupInfo>({});
|
const [groupDetails, setGroupDetails] = useState<GroupInfo>({});
|
||||||
|
|
||||||
@@ -122,15 +121,9 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
|
|||||||
const [usersOpen, setUsersOpen] = useState<boolean>(false);
|
const [usersOpen, setUsersOpen] = useState<boolean>(false);
|
||||||
const [deleteOpen, setDeleteOpen] = useState<boolean>(false);
|
const [deleteOpen, setDeleteOpen] = useState<boolean>(false);
|
||||||
|
|
||||||
const {
|
const { groupName = "" } = useParams<Record<string, string>>();
|
||||||
groupName = ""
|
|
||||||
} = useParams<Record<string, string>>();
|
|
||||||
|
|
||||||
const {
|
const { members = [], policy = "", status: groupEnabled } = groupDetails;
|
||||||
members = [],
|
|
||||||
policy = "",
|
|
||||||
status: groupEnabled
|
|
||||||
} = groupDetails;
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (groupName) {
|
if (groupName) {
|
||||||
@@ -148,18 +141,18 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
|
|||||||
.invoke("GET", `/api/v1/group?name=${encodeURI(groupName)}`)
|
.invoke("GET", `/api/v1/group?name=${encodeURI(groupName)}`)
|
||||||
.then((res: any) => {
|
.then((res: any) => {
|
||||||
setGroupDetails(res);
|
setGroupDetails(res);
|
||||||
}).catch(() => {
|
})
|
||||||
setGroupDetails({});
|
.catch(() => {
|
||||||
});
|
setGroupDetails({});
|
||||||
};
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function toggleGroupStatus(nextStatus: boolean) {
|
function toggleGroupStatus(nextStatus: boolean) {
|
||||||
|
|
||||||
return api
|
return api
|
||||||
.invoke("PUT", `/api/v1/group?name=${encodeURI(groupName)}`, {
|
.invoke("PUT", `/api/v1/group?name=${encodeURI(groupName)}`, {
|
||||||
group: groupName,
|
group: groupName,
|
||||||
members: members,
|
members: members,
|
||||||
status: nextStatus ? "enabled" : "disabled"
|
status: nextStatus ? "enabled" : "disabled",
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
fetchGroupInfo();
|
fetchGroupInfo();
|
||||||
@@ -170,7 +163,6 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<GroupDetailsHeader classes={classes} />
|
<GroupDetailsHeader classes={classes} />
|
||||||
<Grid container className={classes.container}>
|
<Grid container className={classes.container}>
|
||||||
@@ -183,7 +175,9 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
|
|||||||
}
|
}
|
||||||
title={groupName}
|
title={groupName}
|
||||||
subTitle={
|
subTitle={
|
||||||
<Fragment>Status: {isGroupEnabled ? "Enabled" : "Disabled"}</Fragment>
|
<Fragment>
|
||||||
|
Status: {isGroupEnabled ? "Enabled" : "Disabled"}
|
||||||
|
</Fragment>
|
||||||
}
|
}
|
||||||
actions={
|
actions={
|
||||||
<Fragment>
|
<Fragment>
|
||||||
@@ -214,9 +208,12 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
|
|||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid item xs={2}>
|
<Grid item xs={2}>
|
||||||
<TabItems activeTab={currentTab} onTabChange={(num) => {
|
<TabItems
|
||||||
setCurrentTab(num);
|
activeTab={currentTab}
|
||||||
}} />
|
onTabChange={(num) => {
|
||||||
|
setCurrentTab(num);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={10}>
|
<Grid item xs={10}>
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
@@ -270,8 +267,8 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
|
|||||||
type: "view",
|
type: "view",
|
||||||
onClick: (policy) => {
|
onClick: (policy) => {
|
||||||
history.push(`/policies/${policy}`);
|
history.push(`/policies/${policy}`);
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]}
|
]}
|
||||||
columns={[{ label: "Policy", elementKey: "" }]}
|
columns={[{ label: "Policy", elementKey: "" }]}
|
||||||
isLoading={false}
|
isLoading={false}
|
||||||
@@ -297,12 +294,10 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
|
|||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{usersOpen ?
|
{usersOpen ? (
|
||||||
<AddGroupMember
|
<AddGroupMember
|
||||||
selectedGroup={groupName}
|
selectedGroup={groupName}
|
||||||
onSaveClick={() => {
|
onSaveClick={() => {}}
|
||||||
|
|
||||||
}}
|
|
||||||
title={memberActionText}
|
title={memberActionText}
|
||||||
groupStatus={groupEnabled}
|
groupStatus={groupEnabled}
|
||||||
classes={classes}
|
classes={classes}
|
||||||
@@ -311,7 +306,9 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
|
|||||||
onClose={() => {
|
onClose={() => {
|
||||||
setUsersOpen(false);
|
setUsersOpen(false);
|
||||||
fetchGroupInfo();
|
fetchGroupInfo();
|
||||||
}} /> : null}
|
}}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
|
||||||
{deleteOpen && (
|
{deleteOpen && (
|
||||||
<DeleteGroup
|
<DeleteGroup
|
||||||
@@ -328,14 +325,12 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
|
|||||||
{/*Modals*/}
|
{/*Modals*/}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const mapDispatchToProps = {
|
const mapDispatchToProps = {
|
||||||
setErrorSnackMessage
|
setErrorSnackMessage,
|
||||||
};
|
};
|
||||||
|
|
||||||
const connector = connect(null, mapDispatchToProps);
|
const connector = connect(null, mapDispatchToProps);
|
||||||
|
|
||||||
export default withStyles(styles)(connector(GroupsDetails));
|
export default withStyles(styles)(connector(GroupsDetails));
|
||||||
|
|||||||
@@ -40,7 +40,15 @@ const LoginCallback: FC<RouteComponentProps> = ({ location }) => {
|
|||||||
// store the jwt token
|
// store the jwt token
|
||||||
storage.setItem("token", res.sessionId);
|
storage.setItem("token", res.sessionId);
|
||||||
// We push to history the new URL.
|
// We push to history the new URL.
|
||||||
window.location.href = "/";
|
let targetPath = "/";
|
||||||
|
if (
|
||||||
|
localStorage.getItem("redirect-path") &&
|
||||||
|
localStorage.getItem("redirect-path") != ""
|
||||||
|
) {
|
||||||
|
targetPath = `${localStorage.getItem("redirect-path")}`;
|
||||||
|
localStorage.setItem("redirect-path", "");
|
||||||
|
}
|
||||||
|
window.location.href = targetPath;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((res: any) => {
|
.catch((res: any) => {
|
||||||
|
|||||||
@@ -242,7 +242,15 @@ const Login = ({
|
|||||||
if (loginStrategy.loginStrategy === loginStrategyType.form) {
|
if (loginStrategy.loginStrategy === loginStrategyType.form) {
|
||||||
localStorage.setItem("userLoggedIn", encodeFileName(accessKey));
|
localStorage.setItem("userLoggedIn", encodeFileName(accessKey));
|
||||||
}
|
}
|
||||||
history.push("/");
|
let targetPath = "/";
|
||||||
|
if (
|
||||||
|
localStorage.getItem("redirect-path") &&
|
||||||
|
localStorage.getItem("redirect-path") != ""
|
||||||
|
) {
|
||||||
|
targetPath = `${localStorage.getItem("redirect-path")}`;
|
||||||
|
localStorage.setItem("redirect-path", "");
|
||||||
|
}
|
||||||
|
history.push(targetPath);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
setLoginSending(false);
|
setLoginSending(false);
|
||||||
|
|||||||
Reference in New Issue
Block a user