mirror of
https://github.com/OpenMaxIO/openmaxio-object-browser
synced 2026-07-01 07:41:18 -07:00
Changed IDP login support in console (#2695)
- Allowed to use External IDP + Built-in IDP at the same time - Added IDP type to IDP listing - Added IDP name when no display name is configured - Changed STS login link into new menu - Cleanup of Operator login strategies Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
This commit is contained in:
@@ -39,6 +39,9 @@ type RedirectRule struct {
|
|||||||
|
|
||||||
// redirect
|
// redirect
|
||||||
Redirect string `json:"redirect,omitempty"`
|
Redirect string `json:"redirect,omitempty"`
|
||||||
|
|
||||||
|
// service type
|
||||||
|
ServiceType string `json:"serviceType,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate validates this redirect rule
|
// Validate validates this redirect rule
|
||||||
|
|||||||
@@ -16,38 +16,18 @@
|
|||||||
|
|
||||||
import React, { Fragment, useEffect } from "react";
|
import React, { Fragment, useEffect } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import {
|
import { Button, Loader, LoginWrapper, RefreshIcon } from "mds";
|
||||||
InputAdornment,
|
|
||||||
LinearProgress,
|
|
||||||
MenuItem,
|
|
||||||
Select,
|
|
||||||
} from "@mui/material";
|
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
Loader,
|
|
||||||
LockIcon,
|
|
||||||
LoginWrapper,
|
|
||||||
LogoutIcon,
|
|
||||||
RefreshIcon,
|
|
||||||
} from "mds";
|
|
||||||
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 makeStyles from "@mui/styles/makeStyles";
|
import makeStyles from "@mui/styles/makeStyles";
|
||||||
import Grid from "@mui/material/Grid";
|
|
||||||
import { loginStrategyType, redirectRule } from "./types";
|
import { loginStrategyType, redirectRule } from "./types";
|
||||||
import MainError from "../Console/Common/MainError/MainError";
|
import MainError from "../Console/Common/MainError/MainError";
|
||||||
import { spacingUtils } from "../Console/Common/FormComponents/common/styleLibrary";
|
import { spacingUtils } from "../Console/Common/FormComponents/common/styleLibrary";
|
||||||
import clsx from "clsx";
|
|
||||||
import { AppState, useAppDispatch } from "../../store";
|
import { AppState, useAppDispatch } from "../../store";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import {
|
import { getFetchConfigurationAsync, getVersionAsync } from "./loginThunks";
|
||||||
doLoginAsync,
|
import { resetForm } from "./loginSlice";
|
||||||
getFetchConfigurationAsync,
|
|
||||||
getVersionAsync,
|
|
||||||
} from "./loginThunks";
|
|
||||||
import { resetForm, setJwt } from "./loginSlice";
|
|
||||||
import StrategyForm from "./StrategyForm";
|
import StrategyForm from "./StrategyForm";
|
||||||
import { LoginField } from "./LoginField";
|
|
||||||
import { redirectRules } from "../../utils/sortFunctions";
|
import { redirectRules } from "../../utils/sortFunctions";
|
||||||
import { getLogoVar } from "../../config";
|
import { getLogoVar } from "../../config";
|
||||||
|
|
||||||
@@ -250,19 +230,12 @@ const useStyles = makeStyles((theme: Theme) =>
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
export interface LoginStrategyRoutes {
|
|
||||||
[key: string]: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LoginStrategyPayload {
|
export interface LoginStrategyPayload {
|
||||||
[key: string]: any;
|
accessKey: string;
|
||||||
|
secretKey: string;
|
||||||
|
sts?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const loginStrategyEndpoints: LoginStrategyRoutes = {
|
|
||||||
form: "/api/v1/login",
|
|
||||||
"service-account": "/api/v1/login/operator",
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getTargetPath = () => {
|
export const getTargetPath = () => {
|
||||||
let targetPath = "/";
|
let targetPath = "/";
|
||||||
if (
|
if (
|
||||||
@@ -280,13 +253,9 @@ const Login = () => {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
const jwt = useSelector((state: AppState) => state.login.jwt);
|
|
||||||
const loginStrategy = useSelector(
|
const loginStrategy = useSelector(
|
||||||
(state: AppState) => state.login.loginStrategy
|
(state: AppState) => state.login.loginStrategy
|
||||||
);
|
);
|
||||||
const loginSending = useSelector(
|
|
||||||
(state: AppState) => state.login.loginSending
|
|
||||||
);
|
|
||||||
const loadingFetchConfiguration = useSelector(
|
const loadingFetchConfiguration = useSelector(
|
||||||
(state: AppState) => state.login.loadingFetchConfiguration
|
(state: AppState) => state.login.loadingFetchConfiguration
|
||||||
);
|
);
|
||||||
@@ -295,13 +264,8 @@ const Login = () => {
|
|||||||
);
|
);
|
||||||
const navigateTo = useSelector((state: AppState) => state.login.navigateTo);
|
const navigateTo = useSelector((state: AppState) => state.login.navigateTo);
|
||||||
|
|
||||||
const isDirectPV = useSelector((state: AppState) => state.login.isDirectPV);
|
|
||||||
const isK8S = useSelector((state: AppState) => state.login.isK8S);
|
const isK8S = useSelector((state: AppState) => state.login.isK8S);
|
||||||
|
|
||||||
const isOperator =
|
|
||||||
loginStrategy.loginStrategy === loginStrategyType.serviceAccount ||
|
|
||||||
loginStrategy.loginStrategy === loginStrategyType.redirectServiceAccount;
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (navigateTo !== "") {
|
if (navigateTo !== "") {
|
||||||
dispatch(resetForm());
|
dispatch(resetForm());
|
||||||
@@ -309,11 +273,6 @@ const Login = () => {
|
|||||||
}
|
}
|
||||||
}, [navigateTo, dispatch, navigate]);
|
}, [navigateTo, dispatch, navigate]);
|
||||||
|
|
||||||
const formSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
|
||||||
e.preventDefault();
|
|
||||||
dispatch(doLoginAsync());
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (loadingFetchConfiguration) {
|
if (loadingFetchConfiguration) {
|
||||||
dispatch(getFetchConfigurationAsync());
|
dispatch(getFetchConfigurationAsync());
|
||||||
@@ -329,12 +288,8 @@ const Login = () => {
|
|||||||
let loginComponent;
|
let loginComponent;
|
||||||
|
|
||||||
switch (loginStrategy.loginStrategy) {
|
switch (loginStrategy.loginStrategy) {
|
||||||
case loginStrategyType.form: {
|
|
||||||
loginComponent = <StrategyForm />;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case loginStrategyType.redirect:
|
case loginStrategyType.redirect:
|
||||||
case loginStrategyType.redirectServiceAccount: {
|
case loginStrategyType.form: {
|
||||||
let redirectItems: redirectRule[] = [];
|
let redirectItems: redirectRule[] = [];
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -344,111 +299,7 @@ const Login = () => {
|
|||||||
redirectItems = [...loginStrategy.redirectRules].sort(redirectRules);
|
redirectItems = [...loginStrategy.redirectRules].sort(redirectRules);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
loginComponent = <StrategyForm redirectRules={redirectItems} />;
|
||||||
loginStrategy.redirectRules &&
|
|
||||||
loginStrategy.redirectRules.length > 1
|
|
||||||
) {
|
|
||||||
loginComponent = (
|
|
||||||
<Fragment>
|
|
||||||
<div className={classes.loginSsoText}>Login with SSO:</div>
|
|
||||||
<Select
|
|
||||||
id="ssoLogin"
|
|
||||||
name="ssoLogin"
|
|
||||||
data-test-id="sso-login"
|
|
||||||
onChange={(e) => {
|
|
||||||
if (e.target.value) {
|
|
||||||
window.location.href = e.target.value as string;
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
displayEmpty
|
|
||||||
className={classes.ssoSelect}
|
|
||||||
renderValue={() => "Select Provider"}
|
|
||||||
>
|
|
||||||
{redirectItems.map((r, idx) => (
|
|
||||||
<MenuItem
|
|
||||||
value={r.redirect}
|
|
||||||
key={`sso-login-option-${idx}`}
|
|
||||||
className={classes.ssoMenuItem}
|
|
||||||
divider={true}
|
|
||||||
>
|
|
||||||
<LogoutIcon className={classes.ssoLoginIcon} />
|
|
||||||
{r.displayName}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
</Fragment>
|
|
||||||
);
|
|
||||||
} else if (redirectItems.length === 1) {
|
|
||||||
loginComponent = (
|
|
||||||
<div className={clsx(classes.submit, classes.ssoSubmit)}>
|
|
||||||
<Button
|
|
||||||
key={`login-button`}
|
|
||||||
variant="callAction"
|
|
||||||
id="sso-login"
|
|
||||||
label={
|
|
||||||
redirectItems[0].displayName === ""
|
|
||||||
? "Login with SSO"
|
|
||||||
: redirectItems[0].displayName
|
|
||||||
}
|
|
||||||
onClick={() => (window.location.href = redirectItems[0].redirect)}
|
|
||||||
fullWidth
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
loginComponent = (
|
|
||||||
<div className={classes.loginStrategyMessage}>
|
|
||||||
Cannot retrieve redirect from login strategy
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case loginStrategyType.serviceAccount: {
|
|
||||||
loginComponent = (
|
|
||||||
<Fragment>
|
|
||||||
<form className={classes.form} noValidate onSubmit={formSubmit}>
|
|
||||||
<Grid container spacing={2}>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<LoginField
|
|
||||||
required
|
|
||||||
className={classes.inputField}
|
|
||||||
fullWidth
|
|
||||||
id="jwt"
|
|
||||||
value={jwt}
|
|
||||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
||||||
dispatch(setJwt(e.target.value))
|
|
||||||
}
|
|
||||||
name="jwt"
|
|
||||||
autoComplete="off"
|
|
||||||
disabled={loginSending}
|
|
||||||
placeholder={"Enter JWT"}
|
|
||||||
variant={"outlined"}
|
|
||||||
InputProps={{
|
|
||||||
startAdornment: (
|
|
||||||
<InputAdornment position="start">
|
|
||||||
<LockIcon />
|
|
||||||
</InputAdornment>
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12} className={classes.submitContainer}>
|
|
||||||
<Button
|
|
||||||
variant="callAction"
|
|
||||||
id="do-login"
|
|
||||||
disabled={jwt === "" || loginSending}
|
|
||||||
label={"Login"}
|
|
||||||
fullWidth
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12} className={classes.linearPredef}>
|
|
||||||
{loginSending && <LinearProgress />}
|
|
||||||
</Grid>
|
|
||||||
</form>
|
|
||||||
</Fragment>
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -483,16 +334,6 @@ const Login = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let modeLogo: "console" | "directpv" | "operator" | "kes" | "subnet" =
|
|
||||||
"console";
|
|
||||||
const logoVar = getLogoVar();
|
|
||||||
|
|
||||||
if (isDirectPV) {
|
|
||||||
modeLogo = "directpv";
|
|
||||||
} else if (isOperator) {
|
|
||||||
modeLogo = "operator";
|
|
||||||
}
|
|
||||||
|
|
||||||
let docsURL = "https://min.io/docs/minio/linux/index.html?ref=con";
|
let docsURL = "https://min.io/docs/minio/linux/index.html?ref=con";
|
||||||
if (isK8S) {
|
if (isK8S) {
|
||||||
docsURL =
|
docsURL =
|
||||||
@@ -503,7 +344,7 @@ const Login = () => {
|
|||||||
<Fragment>
|
<Fragment>
|
||||||
<MainError />
|
<MainError />
|
||||||
<LoginWrapper
|
<LoginWrapper
|
||||||
logoProps={{ applicationName: modeLogo, subVariant: logoVar }}
|
logoProps={{ applicationName: "console", subVariant: getLogoVar() }}
|
||||||
form={loginComponent}
|
form={loginComponent}
|
||||||
formFooter={
|
formFooter={
|
||||||
<Fragment>
|
<Fragment>
|
||||||
|
|||||||
@@ -15,18 +15,31 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import Grid from "@mui/material/Grid";
|
import Grid from "@mui/material/Grid";
|
||||||
import React, { Fragment } from "react";
|
import React from "react";
|
||||||
import { Button, LockFilledIcon, PasswordKeyIcon, UserFilledIcon } from "mds";
|
import {
|
||||||
|
Button,
|
||||||
|
LockFilledIcon,
|
||||||
|
LogoutIcon,
|
||||||
|
PasswordKeyIcon,
|
||||||
|
UserFilledIcon,
|
||||||
|
} from "mds";
|
||||||
import { setAccessKey, setSecretKey, setSTS, setUseSTS } from "./loginSlice";
|
import { setAccessKey, setSecretKey, setSTS, setUseSTS } from "./loginSlice";
|
||||||
import { Box, InputAdornment, LinearProgress } from "@mui/material";
|
import {
|
||||||
|
InputAdornment,
|
||||||
|
LinearProgress,
|
||||||
|
MenuItem,
|
||||||
|
Select,
|
||||||
|
SelectChangeEvent,
|
||||||
|
} from "@mui/material";
|
||||||
import { AppState, useAppDispatch } from "../../store";
|
import { AppState, useAppDispatch } from "../../store";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { LoginField } from "./LoginField";
|
import { LoginField } from "./LoginField";
|
||||||
import makeStyles from "@mui/styles/makeStyles";
|
import makeStyles from "@mui/styles/makeStyles";
|
||||||
import { Theme, useTheme } from "@mui/material/styles";
|
import { Theme } from "@mui/material/styles";
|
||||||
import createStyles from "@mui/styles/createStyles";
|
import createStyles from "@mui/styles/createStyles";
|
||||||
import { spacingUtils } from "../Console/Common/FormComponents/common/styleLibrary";
|
import { spacingUtils } from "../Console/Common/FormComponents/common/styleLibrary";
|
||||||
import { doLoginAsync } from "./loginThunks";
|
import { doLoginAsync } from "./loginThunks";
|
||||||
|
import { IStrategyForm } from "./types";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) =>
|
const useStyles = makeStyles((theme: Theme) =>
|
||||||
createStyles({
|
createStyles({
|
||||||
@@ -59,10 +72,9 @@ const useStyles = makeStyles((theme: Theme) =>
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const StrategyForm = () => {
|
const StrategyForm = ({ redirectRules }: IStrategyForm) => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const theme = useTheme();
|
|
||||||
|
|
||||||
const accessKey = useSelector((state: AppState) => state.login.accessKey);
|
const accessKey = useSelector((state: AppState) => state.login.accessKey);
|
||||||
const secretKey = useSelector((state: AppState) => state.login.secretKey);
|
const secretKey = useSelector((state: AppState) => state.login.secretKey);
|
||||||
@@ -78,6 +90,42 @@ const StrategyForm = () => {
|
|||||||
dispatch(doLoginAsync());
|
dispatch(doLoginAsync());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let ssoOptions: React.ReactNode = null;
|
||||||
|
|
||||||
|
if (redirectRules.length > 0) {
|
||||||
|
ssoOptions = redirectRules.map((r, idx) => (
|
||||||
|
<MenuItem
|
||||||
|
value={r.redirect}
|
||||||
|
key={`sso-login-option-${idx}`}
|
||||||
|
className={classes.ssoMenuItem}
|
||||||
|
divider={true}
|
||||||
|
>
|
||||||
|
<LogoutIcon
|
||||||
|
className={classes.ssoLoginIcon}
|
||||||
|
style={{ width: 16, height: 16, marginRight: 8 }}
|
||||||
|
/>
|
||||||
|
{r.displayName}
|
||||||
|
{r.serviceType ? ` - ${r.serviceType}` : ""}
|
||||||
|
</MenuItem>
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
const extraActionSelector = (e: SelectChangeEvent) => {
|
||||||
|
const value = e.target.value;
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
console.log(value);
|
||||||
|
if (value.includes("use-sts")) {
|
||||||
|
console.log("si");
|
||||||
|
dispatch(setUseSTS(!useSTS));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.location.href = e.target.value as string;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<form className={classes.form} noValidate onSubmit={formSubmit}>
|
<form className={classes.form} noValidate onSubmit={formSubmit}>
|
||||||
@@ -184,42 +232,32 @@ const StrategyForm = () => {
|
|||||||
<Grid item xs={12} className={classes.linearPredef}>
|
<Grid item xs={12} className={classes.linearPredef}>
|
||||||
{loginSending && <LinearProgress />}
|
{loginSending && <LinearProgress />}
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} className={classes.linearPredef}>
|
<Grid
|
||||||
<Box
|
item
|
||||||
style={{
|
xs={12}
|
||||||
textAlign: "center",
|
className={classes.linearPredef}
|
||||||
marginTop: 20,
|
sx={{ marginTop: "16px" }}
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
id="alternativeMethods"
|
||||||
|
name="alternativeMethods"
|
||||||
|
onChange={extraActionSelector}
|
||||||
|
displayEmpty
|
||||||
|
className={classes.ssoSelect}
|
||||||
|
renderValue={() => "Other Authentication Methods"}
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span
|
<MenuItem
|
||||||
onClick={() => {
|
value={useSTS ? "use-sts-cred" : "use-sts"}
|
||||||
dispatch(setUseSTS(!useSTS));
|
className={classes.ssoMenuItem}
|
||||||
}}
|
divider={redirectRules.length > 0}
|
||||||
style={{
|
|
||||||
color: theme.colors.link,
|
|
||||||
font: "normal normal normal 14px Inter",
|
|
||||||
textDecoration: "underline",
|
|
||||||
cursor: "pointer",
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{!useSTS && <Fragment>Use STS</Fragment>}
|
{useSTS ? "Use Credentials" : "Use STS"}
|
||||||
{useSTS && <Fragment>Use Credentials</Fragment>}
|
</MenuItem>
|
||||||
</span>
|
{ssoOptions}
|
||||||
<span
|
</Select>
|
||||||
onClick={() => {
|
|
||||||
dispatch(setUseSTS(!useSTS));
|
|
||||||
}}
|
|
||||||
style={{
|
|
||||||
color: theme.colors.link,
|
|
||||||
font: "normal normal normal 12px/15px Inter",
|
|
||||||
textDecoration: "none",
|
|
||||||
fontWeight: "bold",
|
|
||||||
paddingLeft: 4,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
➔
|
|
||||||
</span>
|
|
||||||
</Box>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</form>
|
</form>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ export interface LoginState {
|
|||||||
sts: string;
|
sts: string;
|
||||||
useSTS: boolean;
|
useSTS: boolean;
|
||||||
|
|
||||||
jwt: string;
|
|
||||||
|
|
||||||
loginStrategy: ILoginDetails;
|
loginStrategy: ILoginDetails;
|
||||||
|
|
||||||
loginSending: boolean;
|
loginSending: boolean;
|
||||||
@@ -48,7 +46,6 @@ const initialState: LoginState = {
|
|||||||
secretKey: "",
|
secretKey: "",
|
||||||
sts: "",
|
sts: "",
|
||||||
useSTS: false,
|
useSTS: false,
|
||||||
jwt: "",
|
|
||||||
loginStrategy: {
|
loginStrategy: {
|
||||||
loginStrategy: loginStrategyType.unknown,
|
loginStrategy: loginStrategyType.unknown,
|
||||||
redirectRules: [],
|
redirectRules: [],
|
||||||
@@ -79,9 +76,6 @@ export const loginSlice = createSlice({
|
|||||||
setSTS: (state, action: PayloadAction<string>) => {
|
setSTS: (state, action: PayloadAction<string>) => {
|
||||||
state.sts = action.payload;
|
state.sts = action.payload;
|
||||||
},
|
},
|
||||||
setJwt: (state, action: PayloadAction<string>) => {
|
|
||||||
state.jwt = action.payload;
|
|
||||||
},
|
|
||||||
setNavigateTo: (state, action: PayloadAction<string>) => {
|
setNavigateTo: (state, action: PayloadAction<string>) => {
|
||||||
state.navigateTo = action.payload;
|
state.navigateTo = action.payload;
|
||||||
},
|
},
|
||||||
@@ -133,7 +127,6 @@ export const {
|
|||||||
setSecretKey,
|
setSecretKey,
|
||||||
setUseSTS,
|
setUseSTS,
|
||||||
setSTS,
|
setSTS,
|
||||||
setJwt,
|
|
||||||
setNavigateTo,
|
setNavigateTo,
|
||||||
resetForm,
|
resetForm,
|
||||||
} = loginSlice.actions;
|
} = loginSlice.actions;
|
||||||
|
|||||||
@@ -18,75 +18,41 @@ import { createAsyncThunk } from "@reduxjs/toolkit";
|
|||||||
import { AppState } from "../../store";
|
import { AppState } from "../../store";
|
||||||
import api from "../../common/api";
|
import api from "../../common/api";
|
||||||
import { ErrorResponseHandler } from "../../common/types";
|
import { ErrorResponseHandler } from "../../common/types";
|
||||||
import {
|
import { setErrorSnackMessage, userLogged } from "../../systemSlice";
|
||||||
setErrorSnackMessage,
|
import { ILoginDetails } from "./types";
|
||||||
showMarketplace,
|
|
||||||
userLogged,
|
|
||||||
} from "../../systemSlice";
|
|
||||||
import { ILoginDetails, loginStrategyType } from "./types";
|
|
||||||
import { setNavigateTo } from "./loginSlice";
|
import { setNavigateTo } from "./loginSlice";
|
||||||
import {
|
import { getTargetPath, LoginStrategyPayload } from "./LoginPage";
|
||||||
getTargetPath,
|
|
||||||
loginStrategyEndpoints,
|
|
||||||
LoginStrategyPayload,
|
|
||||||
} from "./LoginPage";
|
|
||||||
|
|
||||||
export const doLoginAsync = createAsyncThunk(
|
export const doLoginAsync = createAsyncThunk(
|
||||||
"login/doLoginAsync",
|
"login/doLoginAsync",
|
||||||
async (_, { getState, rejectWithValue, dispatch }) => {
|
async (_, { getState, rejectWithValue, dispatch }) => {
|
||||||
const state = getState() as AppState;
|
const state = getState() as AppState;
|
||||||
const loginStrategy = state.login.loginStrategy;
|
|
||||||
const accessKey = state.login.accessKey;
|
const accessKey = state.login.accessKey;
|
||||||
const secretKey = state.login.secretKey;
|
const secretKey = state.login.secretKey;
|
||||||
const jwt = state.login.jwt;
|
|
||||||
const sts = state.login.sts;
|
const sts = state.login.sts;
|
||||||
const useSTS = state.login.useSTS;
|
const useSTS = state.login.useSTS;
|
||||||
|
|
||||||
const isOperator =
|
|
||||||
loginStrategy.loginStrategy === loginStrategyType.serviceAccount ||
|
|
||||||
loginStrategy.loginStrategy === loginStrategyType.redirectServiceAccount;
|
|
||||||
|
|
||||||
let loginStrategyPayload: LoginStrategyPayload = {
|
let loginStrategyPayload: LoginStrategyPayload = {
|
||||||
form: { accessKey, secretKey },
|
accessKey,
|
||||||
"service-account": { jwt },
|
secretKey,
|
||||||
};
|
};
|
||||||
if (useSTS) {
|
if (useSTS) {
|
||||||
loginStrategyPayload = {
|
loginStrategyPayload = {
|
||||||
form: { accessKey, secretKey, sts },
|
accessKey,
|
||||||
|
secretKey,
|
||||||
|
sts,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("PAYLOAD:", loginStrategyPayload);
|
||||||
|
|
||||||
return api
|
return api
|
||||||
.invoke(
|
.invoke("POST", "/api/v1/login", loginStrategyPayload)
|
||||||
"POST",
|
|
||||||
loginStrategyEndpoints[loginStrategy.loginStrategy] || "/api/v1/login",
|
|
||||||
loginStrategyPayload[loginStrategy.loginStrategy]
|
|
||||||
)
|
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
// We set the state in redux
|
// We set the state in redux
|
||||||
dispatch(userLogged(true));
|
dispatch(userLogged(true));
|
||||||
if (loginStrategy.loginStrategy === loginStrategyType.form) {
|
|
||||||
localStorage.setItem("userLoggedIn", accessKey);
|
localStorage.setItem("userLoggedIn", accessKey);
|
||||||
}
|
|
||||||
// if it's in operator mode, check the Marketplace integration
|
|
||||||
if (isOperator) {
|
|
||||||
api
|
|
||||||
.invoke("GET", "/api/v1/mp-integration/")
|
|
||||||
.then((res: any) => {
|
|
||||||
dispatch(setNavigateTo(getTargetPath())); // Email already set, continue with normal flow
|
|
||||||
})
|
|
||||||
.catch((err: ErrorResponseHandler) => {
|
|
||||||
if (err.statusCode === 404) {
|
|
||||||
dispatch(showMarketplace(true));
|
|
||||||
dispatch(setNavigateTo("/marketplace"));
|
|
||||||
} else {
|
|
||||||
// Unexpected error, continue with normal flow
|
|
||||||
dispatch(setNavigateTo(getTargetPath()));
|
dispatch(setNavigateTo(getTargetPath()));
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
dispatch(setNavigateTo(getTargetPath()));
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
dispatch(setErrorSnackMessage(err));
|
dispatch(setErrorSnackMessage(err));
|
||||||
@@ -124,23 +90,7 @@ export const getVersionAsync = createAsyncThunk(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
.catch((err: ErrorResponseHandler) => {
|
.catch((err: ErrorResponseHandler) => {
|
||||||
// try the operator version
|
return err.errorMessage;
|
||||||
api
|
|
||||||
.invoke("GET", "/api/v1/check-operator-version")
|
|
||||||
.then(
|
|
||||||
({
|
|
||||||
current_version,
|
|
||||||
latest_version,
|
|
||||||
}: {
|
|
||||||
current_version: string;
|
|
||||||
latest_version: string;
|
|
||||||
}) => {
|
|
||||||
return latest_version;
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.catch((err: ErrorResponseHandler) => {
|
|
||||||
return err;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -24,6 +24,11 @@ export interface ILoginDetails {
|
|||||||
export interface redirectRule {
|
export interface redirectRule {
|
||||||
redirect: string;
|
redirect: string;
|
||||||
displayName: string;
|
displayName: string;
|
||||||
|
serviceType?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IStrategyForm {
|
||||||
|
redirectRules: redirectRule[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum loginStrategyType {
|
export enum loginStrategyType {
|
||||||
|
|||||||
@@ -7592,6 +7592,9 @@ func init() {
|
|||||||
},
|
},
|
||||||
"redirect": {
|
"redirect": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"serviceType": {
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -16573,6 +16576,9 @@ func init() {
|
|||||||
},
|
},
|
||||||
"redirect": {
|
"redirect": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"serviceType": {
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/go-openapi/runtime"
|
"github.com/go-openapi/runtime"
|
||||||
"github.com/go-openapi/runtime/middleware"
|
"github.com/go-openapi/runtime/middleware"
|
||||||
@@ -186,15 +188,25 @@ func getLoginDetailsResponse(params authApi.LoginDetailParams, openIDProviders o
|
|||||||
Client: oauth2Client,
|
Client: oauth2Client,
|
||||||
}
|
}
|
||||||
|
|
||||||
displayName := "Login with SSO"
|
displayName := fmt.Sprintf("Login with SSO (%s)", name)
|
||||||
|
serviceType := ""
|
||||||
|
|
||||||
if provider.DisplayName != "" {
|
if provider.DisplayName != "" {
|
||||||
displayName = provider.DisplayName
|
displayName = provider.DisplayName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if provider.RoleArn != "" {
|
||||||
|
splitRoleArn := strings.Split(provider.RoleArn, ":")
|
||||||
|
|
||||||
|
if len(splitRoleArn) > 2 {
|
||||||
|
serviceType = splitRoleArn[2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
redirectRule := models.RedirectRule{
|
redirectRule := models.RedirectRule{
|
||||||
Redirect: identityProvider.GenerateLoginURL(),
|
Redirect: identityProvider.GenerateLoginURL(),
|
||||||
DisplayName: displayName,
|
DisplayName: displayName,
|
||||||
|
ServiceType: serviceType,
|
||||||
}
|
}
|
||||||
|
|
||||||
redirectRules = append(redirectRules, &redirectRule)
|
redirectRules = append(redirectRules, &redirectRule)
|
||||||
|
|||||||
@@ -5891,6 +5891,8 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
displayName:
|
displayName:
|
||||||
type: string
|
type: string
|
||||||
|
serviceType:
|
||||||
|
type: string
|
||||||
|
|
||||||
idpServerConfiguration:
|
idpServerConfiguration:
|
||||||
type: object
|
type: object
|
||||||
|
|||||||
Reference in New Issue
Block a user