diff --git a/portal-ui/src/MainRouter.tsx b/portal-ui/src/MainRouter.tsx index 40ffb40a7..2cd37dd72 100644 --- a/portal-ui/src/MainRouter.tsx +++ b/portal-ui/src/MainRouter.tsx @@ -21,7 +21,7 @@ import LoadingComponent from "./common/LoadingComponent"; import AppConsole from "./screens/Console/ConsoleKBar"; import { baseUrl } from "./history"; -const Login = React.lazy(() => import("./screens/LoginPage/LoginPage")); +const Login = React.lazy(() => import("./screens/LoginPage/Login")); const Logout = React.lazy(() => import("./screens/LogoutPage/LogoutPage")); const LoginCallback = React.lazy( () => import("./screens/LoginPage/LoginCallback") diff --git a/portal-ui/src/screens/LoginPage/LoginPage.tsx b/portal-ui/src/screens/LoginPage/Login.tsx similarity index 96% rename from portal-ui/src/screens/LoginPage/LoginPage.tsx rename to portal-ui/src/screens/LoginPage/Login.tsx index 215413de5..6333c7363 100644 --- a/portal-ui/src/screens/LoginPage/LoginPage.tsx +++ b/portal-ui/src/screens/LoginPage/Login.tsx @@ -17,21 +17,16 @@ import React, { Fragment, useEffect } from "react"; import { useNavigate } from "react-router-dom"; import { Box, Button, Loader, LoginWrapper, RefreshIcon } from "mds"; -import { loginStrategyType, redirectRule } from "./types"; +import { loginStrategyType } from "./login.types"; import MainError from "../Console/Common/MainError/MainError"; import { AppState, useAppDispatch } from "../../store"; import { useSelector } from "react-redux"; import { getFetchConfigurationAsync, getVersionAsync } from "./loginThunks"; import { resetForm } from "./loginSlice"; import StrategyForm from "./StrategyForm"; -import { redirectRules } from "../../utils/sortFunctions"; import { getLogoVar } from "../../config"; - -export interface LoginStrategyPayload { - accessKey: string; - secretKey: string; - sts?: string; -} +import { RedirectRule } from "api/consoleApi"; +import { redirectRules } from "./login.utils"; export const getTargetPath = () => { let targetPath = "/"; @@ -90,7 +85,7 @@ const Login = () => { switch (loginStrategy.loginStrategy) { case loginStrategyType.redirect: case loginStrategyType.form: { - let redirectItems: redirectRule[] = []; + let redirectItems: RedirectRule[] = []; if ( loginStrategy.redirectRules && diff --git a/portal-ui/src/screens/LoginPage/StrategyForm.tsx b/portal-ui/src/screens/LoginPage/StrategyForm.tsx index f37fbbe98..bf3c8f0bd 100644 --- a/portal-ui/src/screens/LoginPage/StrategyForm.tsx +++ b/portal-ui/src/screens/LoginPage/StrategyForm.tsx @@ -38,9 +38,9 @@ import { LinearProgress } from "@mui/material"; import { AppState, useAppDispatch } from "../../store"; import { useSelector } from "react-redux"; import { doLoginAsync } from "./loginThunks"; -import { IStrategyForm } from "./types"; +import { RedirectRule } from "api/consoleApi"; -const StrategyForm = ({ redirectRules }: IStrategyForm) => { +const StrategyForm = ({ redirectRules }: { redirectRules: RedirectRule[] }) => { const dispatch = useAppDispatch(); const [ssoOptionsOpen, ssoOptionsSetOpen] = useState(false); @@ -137,7 +137,7 @@ const StrategyForm = ({ redirectRules }: IStrategyForm) => { setAnchorEl(e.currentTarget); return; } - submitSSOInitRequest(redirectRules[0].redirect); + submitSSOInitRequest(`${redirectRules[0].redirect}`); }} /> {redirectRules.length > 1 && ( diff --git a/portal-ui/src/screens/LoginPage/types.ts b/portal-ui/src/screens/LoginPage/login.types.ts similarity index 74% rename from portal-ui/src/screens/LoginPage/types.ts rename to portal-ui/src/screens/LoginPage/login.types.ts index 03c42a51f..9786ccdfa 100644 --- a/portal-ui/src/screens/LoginPage/types.ts +++ b/portal-ui/src/screens/LoginPage/login.types.ts @@ -14,23 +14,6 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -export interface ILoginDetails { - loginStrategy: loginStrategyType; - redirectRules: redirectRule[]; - isK8S?: boolean; - animatedLogin?: boolean; -} - -export interface redirectRule { - redirect: string; - displayName: string; - serviceType?: string; -} - -export interface IStrategyForm { - redirectRules: redirectRule[]; -} - export enum loginStrategyType { unknown = "unknown", form = "form", diff --git a/portal-ui/src/screens/LoginPage/login.utils.ts b/portal-ui/src/screens/LoginPage/login.utils.ts new file mode 100644 index 000000000..90019c1ff --- /dev/null +++ b/portal-ui/src/screens/LoginPage/login.utils.ts @@ -0,0 +1,29 @@ +// This file is part of MinIO Console Server +// Copyright (c) 2023 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +import { RedirectRule } from "api/consoleApi"; + +export const redirectRules = (a: RedirectRule, b: RedirectRule) => { + if (a.displayName && b.displayName) { + if (a.displayName > b.displayName) { + return 1; + } + if (a.displayName < b.displayName) { + return -1; + } + } + return 0; +}; diff --git a/portal-ui/src/screens/LoginPage/loginSlice.ts b/portal-ui/src/screens/LoginPage/loginSlice.ts index 6fae78278..ba6a9cb42 100644 --- a/portal-ui/src/screens/LoginPage/loginSlice.ts +++ b/portal-ui/src/screens/LoginPage/loginSlice.ts @@ -15,7 +15,7 @@ // along with this program. If not, see . import { createSlice, PayloadAction } from "@reduxjs/toolkit"; -import { ILoginDetails, loginStrategyType } from "./types"; +import { LoginDetails } from "api/consoleApi"; import { doLoginAsync, getFetchConfigurationAsync, @@ -28,7 +28,7 @@ export interface LoginState { sts: string; useSTS: boolean; backgroundAnimation: boolean; - loginStrategy: ILoginDetails; + loginStrategy: LoginDetails; loginSending: boolean; loadingFetchConfiguration: boolean; latestMinIOVersion: string; @@ -44,7 +44,7 @@ const initialState: LoginState = { sts: "", useSTS: false, loginStrategy: { - loginStrategy: loginStrategyType.unknown, + loginStrategy: undefined, redirectRules: [], }, loginSending: false, diff --git a/portal-ui/src/screens/LoginPage/loginThunks.ts b/portal-ui/src/screens/LoginPage/loginThunks.ts index 9210c8c5d..2696c39b2 100644 --- a/portal-ui/src/screens/LoginPage/loginThunks.ts +++ b/portal-ui/src/screens/LoginPage/loginThunks.ts @@ -16,12 +16,18 @@ import { createAsyncThunk } from "@reduxjs/toolkit"; import { AppState } from "../../store"; -import api from "../../common/api"; -import { ErrorResponseHandler } from "../../common/types"; import { setErrorSnackMessage, userLogged } from "../../systemSlice"; -import { ILoginDetails } from "./types"; import { setNavigateTo } from "./loginSlice"; -import { getTargetPath, LoginStrategyPayload } from "./LoginPage"; +import { getTargetPath } from "./Login"; +import { api } from "api"; +import { + CheckVersionResponse, + Error, + HttpResponse, + LoginDetails, + LoginRequest, +} from "api/consoleApi"; +import { errorToHandler } from "api/errors"; export const doLoginAsync = createAsyncThunk( "login/doLoginAsync", @@ -32,41 +38,47 @@ export const doLoginAsync = createAsyncThunk( const sts = state.login.sts; const useSTS = state.login.useSTS; - let loginStrategyPayload: LoginStrategyPayload = { + let payload: LoginRequest = { accessKey, secretKey, }; if (useSTS) { - loginStrategyPayload = { + payload = { accessKey, secretKey, sts, }; } - return api - .invoke("POST", "/api/v1/login", loginStrategyPayload) - .then((res) => { + return api.login + .login(payload) + .then((res: HttpResponse) => { // We set the state in redux dispatch(userLogged(true)); localStorage.setItem("userLoggedIn", accessKey); dispatch(setNavigateTo(getTargetPath())); }) - .catch((err) => { - dispatch(setErrorSnackMessage(err)); + .catch(async (res: HttpResponse) => { + const err = (await res.json()) as Error; + dispatch(setErrorSnackMessage(errorToHandler(err))); + return rejectWithValue(false); }); } ); export const getFetchConfigurationAsync = createAsyncThunk( "login/getFetchConfigurationAsync", - async (_, { getState, rejectWithValue, dispatch }) => { - return api - .invoke("GET", "/api/v1/login") - .then((loginDetails: ILoginDetails) => { - return loginDetails; + async (_, { dispatch, rejectWithValue }) => { + return api.login + .loginDetail() + .then((res: HttpResponse) => { + if (res.data) { + return res.data; + } }) - .catch((err: ErrorResponseHandler) => { - dispatch(setErrorSnackMessage(err)); + .catch(async (res: HttpResponse) => { + const err = (await res.json()) as Error; + dispatch(setErrorSnackMessage(errorToHandler(err))); + return rejectWithValue(false); }); } ); @@ -74,21 +86,17 @@ export const getFetchConfigurationAsync = createAsyncThunk( export const getVersionAsync = createAsyncThunk( "login/getVersionAsync", async (_, { getState, rejectWithValue, dispatch }) => { - return api - .invoke("GET", "/api/v1/check-version") - .then( - ({ - current_version, - latest_version, - }: { - current_version: string; - latest_version: string; - }) => { - return latest_version; + return api.checkVersion + .checkMinIoVersion() + .then((res: HttpResponse) => { + if (res.data !== undefined) { + return res.data.latest_version; } - ) - .catch((err: ErrorResponseHandler) => { - return err.errorMessage; + }) + .catch(async (res: HttpResponse) => { + const err = (await res.json()) as Error; + dispatch(setErrorSnackMessage(errorToHandler(err))); + return rejectWithValue(false); }); } ); diff --git a/portal-ui/src/utils/sortFunctions.ts b/portal-ui/src/utils/sortFunctions.ts index 55183472b..c8017fc76 100644 --- a/portal-ui/src/utils/sortFunctions.ts +++ b/portal-ui/src/utils/sortFunctions.ts @@ -14,8 +14,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -import { Policy } from "../api/consoleApi"; -import { redirectRule } from "../screens/LoginPage/types"; +import { Policy } from "api/consoleApi"; interface userInterface { accessKey: string; @@ -71,13 +70,3 @@ export const policyDetailsSort = ( // a must be equal to b return 0; }; - -export const redirectRules = (a: redirectRule, b: redirectRule) => { - if (a.displayName > b.displayName) { - return 1; - } - if (a.displayName < b.displayName) { - return -1; - } - return 0; -}; diff --git a/portal-ui/tsconfig.json b/portal-ui/tsconfig.json index 2a07c76ee..6e97e31ce 100644 --- a/portal-ui/tsconfig.json +++ b/portal-ui/tsconfig.json @@ -15,7 +15,9 @@ "noEmit": true, "jsx": "react-jsx", "downlevelIteration": true, - "noFallthroughCasesInSwitch": true + "noFallthroughCasesInSwitch": true, + "baseUrl": "./src", + "rootDir": "./src" }, "include": ["src"] }