diff --git a/portal-ui/src/ProtectedRoutes.tsx b/portal-ui/src/ProtectedRoutes.tsx index 3b500c514..bbb4b66c2 100644 --- a/portal-ui/src/ProtectedRoutes.tsx +++ b/portal-ui/src/ProtectedRoutes.tsx @@ -16,8 +16,6 @@ import React, { useEffect, useState } from "react"; import { Navigate, useLocation } from "react-router-dom"; -import api from "./common/api"; -import { ISessionResponse } from "./screens/Console/types"; import useApi from "./screens/Console/Common/Hooks/useApi"; import { ErrorResponseHandler } from "./common/types"; import { ReplicationSite } from "./screens/Console/Configurations/SiteReplication/SiteReplication"; @@ -34,6 +32,7 @@ import { AppState, useAppDispatch } from "./store"; import { saveSessionResponse } from "./screens/Console/consoleSlice"; import { getOverrideColorVariants } from "./utils/stylesUtils"; import LoadingComponent from "./common/LoadingComponent"; +import { api } from "api"; interface ProtectedRouteProps { Component: any; @@ -58,17 +57,17 @@ const ProtectedRoute = ({ Component }: ProtectedRouteProps) => { const screen = pathnameParts.length > 2 ? pathnameParts[1] : ""; useEffect(() => { - api - .invoke("GET", `/api/v1/session`) - .then((res: ISessionResponse) => { - dispatch(saveSessionResponse(res)); + api.session + .sessionCheck() + .then((res) => { + dispatch(saveSessionResponse(res.data)); dispatch(userLogged(true)); setSessionLoading(false); - dispatch(globalSetDistributedSetup(res?.distributedMode || false)); + dispatch(globalSetDistributedSetup(res.data?.distributedMode || false)); - if (res.customStyles && res.customStyles !== "") { + if (res.data.customStyles && res.data.customStyles !== "") { const overrideColorVariants = getOverrideColorVariants( - res.customStyles + res.data.customStyles ); if (overrideColorVariants !== false) { @@ -86,16 +85,13 @@ const ProtectedRoute = ({ Component }: ProtectedRouteProps) => { return; } // before marking the session as done, let's check if the bucket is publicly accessible - api - .invoke( - "GET", - `/api/v1/buckets/${bucket}/objects?limit=1`, - undefined, - { - "X-Anonymous": "1", - } + api.buckets + .listObjects( + bucket, + { limit: 1 }, + { headers: { "X-Anonymous": "1" } } ) - .then((value) => { + .then(() => { dispatch(setAnonymousMode()); setSessionLoading(false); }) diff --git a/portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/utils.ts b/portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/utils.ts index 6121f44ea..9a31a7447 100644 --- a/portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/utils.ts +++ b/portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/utils.ts @@ -15,11 +15,11 @@ // along with this program. If not, see . import { BucketObjectItem } from "./ListObjects/types"; -import { IAllowResources } from "../../../types"; import { encodeURLString } from "../../../../../common/utils"; import { removeTrace } from "../../../ObjectBrowser/transferManager"; import streamSaver from "streamsaver"; import store from "../../../../../store"; +import { PermissionResource } from "api/consoleApi"; export const download = ( bucketName: string, @@ -278,7 +278,7 @@ export const sortListObjects = (fieldSort: string) => { export const permissionItems = ( bucketName: string, currentPath: string, - permissionsArray: IAllowResources[] + permissionsArray: PermissionResource[] ): BucketObjectItem[] | null => { if (permissionsArray.length === 0) { return null; @@ -287,8 +287,8 @@ export const permissionItems = ( // We get permissions applied to the current bucket const filteredPermissionsForBucket = permissionsArray.filter( (permissionItem) => - permissionItem.resource.endsWith(`:${bucketName}`) || - permissionItem.resource.includes(`:${bucketName}/`) + permissionItem.resource?.endsWith(`:${bucketName}`) || + permissionItem.resource?.includes(`:${bucketName}/`) ); // No permissions for this bucket. we can throw the error message at this point @@ -305,8 +305,8 @@ export const permissionItems = ( // We review paths in resource address // We split ARN & get the last item to check the URL - const splitARN = permissionElement.resource.split(":"); - const urlARN = splitARN.pop() || ""; + const splitARN = permissionElement.resource?.split(":"); + const urlARN = splitARN?.pop() || ""; // We split the paths of the URL & compare against current location to see if there are more items to include. In case current level is a wildcard or is the last one, we omit this validation @@ -347,7 +347,7 @@ export const permissionItems = ( permissionElement.conditionOperator === "StringEquals" || permissionElement.conditionOperator === "StringLike" ) { - permissionElement.prefixes.forEach((prefixItem) => { + permissionElement.prefixes?.forEach((prefixItem) => { // Prefix Item is not empty? if (prefixItem !== "") { const splitItems = prefixItem.split("/"); diff --git a/portal-ui/src/screens/Console/Common/ModalWrapper/ConfirmDialog.tsx b/portal-ui/src/screens/Console/Common/ModalWrapper/ConfirmDialog.tsx index 5ab82bd91..9fd16229d 100644 --- a/portal-ui/src/screens/Console/Common/ModalWrapper/ConfirmDialog.tsx +++ b/portal-ui/src/screens/Console/Common/ModalWrapper/ConfirmDialog.tsx @@ -20,7 +20,15 @@ import { Theme } from "@mui/material/styles"; import createStyles from "@mui/styles/createStyles"; import withStyles from "@mui/styles/withStyles"; import { deleteDialogStyles } from "../FormComponents/common/styleLibrary"; -import { ButtonProps } from "../../types"; +interface ButtonProps { + label?: string; + variant?: "regular" | "callAction" | "secondary"; + icon?: React.ReactNode; + iconLocation?: "start" | "end"; + fullWidth?: boolean; + disabled?: boolean; + onClick?: React.MouseEventHandler; +} const styles = (theme: Theme) => createStyles({ diff --git a/portal-ui/src/screens/Console/consoleSlice.ts b/portal-ui/src/screens/Console/consoleSlice.ts index af08275bb..3225399ff 100644 --- a/portal-ui/src/screens/Console/consoleSlice.ts +++ b/portal-ui/src/screens/Console/consoleSlice.ts @@ -15,22 +15,22 @@ // along with this program. If not, see . import { createSlice, PayloadAction } from "@reduxjs/toolkit"; -import { ISessionResponse } from "./types"; import { AppState } from "../../store"; +import { SessionResponse } from "api/consoleApi"; export interface ConsoleState { - session: ISessionResponse; + session: SessionResponse; } const initialState: ConsoleState = { session: { - status: "", + status: undefined, features: [], distributedMode: false, permissions: {}, - allowResources: null, - customStyles: null, - envConstants: null, + allowResources: undefined, + customStyles: undefined, + envConstants: undefined, serverEndPoint: "", }, }; @@ -39,7 +39,7 @@ export const consoleSlice = createSlice({ name: "console", initialState, reducers: { - saveSessionResponse: (state, action: PayloadAction) => { + saveSessionResponse: (state, action: PayloadAction) => { state.session = action.payload; }, resetSession: (state) => { diff --git a/portal-ui/src/screens/Console/kbar-actions.tsx b/portal-ui/src/screens/Console/kbar-actions.tsx index c2b82a0cb..aec5ed139 100644 --- a/portal-ui/src/screens/Console/kbar-actions.tsx +++ b/portal-ui/src/screens/Console/kbar-actions.tsx @@ -21,7 +21,7 @@ import { IAM_PAGES } from "../../common/SecureComponent/permissions"; import { Bucket } from "../../api/consoleApi"; export const routesAsKbarActions = ( - features: string[] | null, + features: string[] | undefined, buckets: Bucket[], navigate: (url: string) => void ) => { diff --git a/portal-ui/src/screens/Console/types.ts b/portal-ui/src/screens/Console/types.ts deleted file mode 100644 index b46a57006..000000000 --- a/portal-ui/src/screens/Console/types.ts +++ /dev/null @@ -1,53 +0,0 @@ -// This file is part of MinIO Console Server -// Copyright (c) 2021 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 React from "react"; - -export interface ISessionPermissions { - [key: string]: string[]; -} - -export interface IAllowResources { - conditionOperator: string; - prefixes: string[]; - resource: string; -} - -export interface IEnvironmentContants { - maxConcurrentDownloads: number; - maxConcurrentUploads: number; -} - -export interface ISessionResponse { - status: string; - features: string[]; - distributedMode: boolean; - permissions: ISessionPermissions; - allowResources: IAllowResources[] | null; - customStyles?: string | null; - envConstants?: IEnvironmentContants | null; - serverEndPoint?: string | undefined; -} - -export interface ButtonProps { - label?: string; - variant?: "regular" | "callAction" | "secondary"; - icon?: React.ReactNode; - iconLocation?: "start" | "end"; - fullWidth?: boolean; - disabled?: boolean; - onClick?: React.MouseEventHandler; -}