Skip to content

Commit

Permalink
Changed IDP login support in console (#2695)
Browse files Browse the repository at this point in the history
- 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 <[email protected]>
  • Loading branch information
bexsoft authored Mar 7, 2023
1 parent 1953a98 commit 1fc9a40
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 279 deletions.
3 changes: 3 additions & 0 deletions models/redirect_rule.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

177 changes: 9 additions & 168 deletions portal-ui/src/screens/LoginPage/LoginPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,38 +16,18 @@

import React, { Fragment, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import {
InputAdornment,
LinearProgress,
MenuItem,
Select,
} from "@mui/material";
import {
Button,
Loader,
LockIcon,
LoginWrapper,
LogoutIcon,
RefreshIcon,
} from "mds";
import { Button, Loader, LoginWrapper, RefreshIcon } from "mds";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import makeStyles from "@mui/styles/makeStyles";
import Grid from "@mui/material/Grid";
import { loginStrategyType, redirectRule } from "./types";
import MainError from "../Console/Common/MainError/MainError";
import { spacingUtils } from "../Console/Common/FormComponents/common/styleLibrary";
import clsx from "clsx";
import { AppState, useAppDispatch } from "../../store";
import { useSelector } from "react-redux";
import {
doLoginAsync,
getFetchConfigurationAsync,
getVersionAsync,
} from "./loginThunks";
import { resetForm, setJwt } from "./loginSlice";
import { getFetchConfigurationAsync, getVersionAsync } from "./loginThunks";
import { resetForm } from "./loginSlice";
import StrategyForm from "./StrategyForm";
import { LoginField } from "./LoginField";
import { redirectRules } from "../../utils/sortFunctions";
import { getLogoVar } from "../../config";

Expand Down Expand Up @@ -250,19 +230,12 @@ const useStyles = makeStyles((theme: Theme) =>
})
);

export interface LoginStrategyRoutes {
[key: string]: string;
}

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 = () => {
let targetPath = "/";
if (
Expand All @@ -280,13 +253,9 @@ const Login = () => {
const navigate = useNavigate();
const classes = useStyles();

const jwt = useSelector((state: AppState) => state.login.jwt);
const loginStrategy = useSelector(
(state: AppState) => state.login.loginStrategy
);
const loginSending = useSelector(
(state: AppState) => state.login.loginSending
);
const loadingFetchConfiguration = useSelector(
(state: AppState) => state.login.loadingFetchConfiguration
);
Expand All @@ -295,25 +264,15 @@ const Login = () => {
);
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 isOperator =
loginStrategy.loginStrategy === loginStrategyType.serviceAccount ||
loginStrategy.loginStrategy === loginStrategyType.redirectServiceAccount;

useEffect(() => {
if (navigateTo !== "") {
dispatch(resetForm());
navigate(navigateTo);
}
}, [navigateTo, dispatch, navigate]);

const formSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
dispatch(doLoginAsync());
};

useEffect(() => {
if (loadingFetchConfiguration) {
dispatch(getFetchConfigurationAsync());
Expand All @@ -329,12 +288,8 @@ const Login = () => {
let loginComponent;

switch (loginStrategy.loginStrategy) {
case loginStrategyType.form: {
loginComponent = <StrategyForm />;
break;
}
case loginStrategyType.redirect:
case loginStrategyType.redirectServiceAccount: {
case loginStrategyType.form: {
let redirectItems: redirectRule[] = [];

if (
Expand All @@ -344,111 +299,7 @@ const Login = () => {
redirectItems = [...loginStrategy.redirectRules].sort(redirectRules);
}

if (
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>
);
loginComponent = <StrategyForm redirectRules={redirectItems} />;
break;
}
default:
Expand Down Expand Up @@ -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";
if (isK8S) {
docsURL =
Expand All @@ -503,7 +344,7 @@ const Login = () => {
<Fragment>
<MainError />
<LoginWrapper
logoProps={{ applicationName: modeLogo, subVariant: logoVar }}
logoProps={{ applicationName: "console", subVariant: getLogoVar() }}
form={loginComponent}
formFooter={
<Fragment>
Expand Down
Loading

0 comments on commit 1fc9a40

Please sign in to comment.