Introducer swagger typescript api (#2704)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
This commit is contained in:
@@ -30,4 +30,6 @@ tests/
|
||||
.vscode/
|
||||
*.code-workspace
|
||||
*~
|
||||
.eslintcache
|
||||
.eslintcache
|
||||
|
||||
consoleApi.ts
|
||||
2
Makefile
2
Makefile
@@ -53,6 +53,8 @@ clean-swagger:
|
||||
swagger-console:
|
||||
@echo "Generating swagger server code from yaml"
|
||||
@swagger generate server -A console --main-package=management --server-package=restapi --exclude-main -P models.Principal -f ./swagger.yml -r NOTICE
|
||||
@echo "Generating typescript api"
|
||||
@npx swagger-typescript-api -p ./swagger.yml -o ./portal-ui/src/api -n consoleApi.ts
|
||||
|
||||
|
||||
assets:
|
||||
|
||||
5138
portal-ui/src/api/consoleApi.ts
Normal file
5138
portal-ui/src/api/consoleApi.ts
Normal file
File diff suppressed because it is too large
Load Diff
35
portal-ui/src/api/errors.ts
Normal file
35
portal-ui/src/api/errors.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { ErrorResponseHandler } from "../common/types";
|
||||
import { Error } from "./consoleApi";
|
||||
|
||||
// errorToHandler translates a swagger error to a ErrorResponseHandler which
|
||||
// is legacy, when all API calls are using the swagger API, we can remove this.
|
||||
export const errorToHandler = (e: Error): ErrorResponseHandler => {
|
||||
if (!e) {
|
||||
return {
|
||||
statusCode: 0,
|
||||
errorMessage: "",
|
||||
detailedError: "",
|
||||
};
|
||||
}
|
||||
return {
|
||||
statusCode: e.code,
|
||||
errorMessage: e.message,
|
||||
detailedError: e.detailedMessage,
|
||||
};
|
||||
};
|
||||
38
portal-ui/src/api/index.ts
Normal file
38
portal-ui/src/api/index.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { Api, HttpResponse, Error, FullRequestParams } from "./consoleApi";
|
||||
|
||||
export let api = new Api();
|
||||
const internalRequestFunc = api.request;
|
||||
api.request = async <T = any, E = any>({
|
||||
body,
|
||||
secure,
|
||||
path,
|
||||
type,
|
||||
query,
|
||||
format,
|
||||
baseUrl,
|
||||
cancelToken,
|
||||
...params
|
||||
}: FullRequestParams): Promise<HttpResponse<T, E>> => {
|
||||
const internalResp = internalRequestFunc({
|
||||
body,
|
||||
secure,
|
||||
path,
|
||||
type,
|
||||
query,
|
||||
format,
|
||||
baseUrl,
|
||||
cancelToken,
|
||||
...params,
|
||||
});
|
||||
return internalResp.then(CommonAPIValidation);
|
||||
};
|
||||
|
||||
export function CommonAPIValidation<D, E>(
|
||||
res: HttpResponse<D, E>
|
||||
): HttpResponse<D, E> {
|
||||
const err = res.error as Error;
|
||||
if (err && err.code === 403 && err.message === "invalid session") {
|
||||
document.location = "/";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -22,7 +22,6 @@ import Tabs from "@mui/material/Tabs";
|
||||
import Tab from "@mui/material/Tab";
|
||||
|
||||
import { TabPanel } from "../../../shared/tabs";
|
||||
import { Policy } from "../../Policies/types";
|
||||
import { User } from "../../Users/types";
|
||||
import { ErrorResponseHandler } from "../../../../common/types";
|
||||
import TableWrapper from "../../Common/TableWrapper/TableWrapper";
|
||||
@@ -41,6 +40,7 @@ import { encodeURLString } from "../../../../common/utils";
|
||||
import { setErrorSnackMessage } from "../../../../systemSlice";
|
||||
import { selBucketDetailsLoading } from "./bucketDetailsSlice";
|
||||
import { useAppDispatch } from "../../../../store";
|
||||
import { Policy } from "../../../../api/consoleApi";
|
||||
|
||||
function a11yProps(index: any) {
|
||||
return {
|
||||
|
||||
@@ -20,9 +20,10 @@ import { LinearProgress } from "@mui/material";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { BackLink, BucketsIcon, Button, HelpBox, InfoIcon } from "mds";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import { containerForHeader } from "../../../Common/FormComponents/common/styleLibrary";
|
||||
import {
|
||||
containerForHeader,
|
||||
modalBasic,
|
||||
} from "../../../Common/FormComponents/common/styleLibrary";
|
||||
import InputBoxWrapper from "../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
||||
import RadioGroupSelector from "../../../Common/FormComponents/RadioGroupSelector/RadioGroupSelector";
|
||||
import { k8sScalarUnitsExcluding } from "../../../../../common/utils";
|
||||
@@ -34,9 +35,6 @@ import {
|
||||
selSiteRep,
|
||||
setErrorSnackMessage,
|
||||
} from "../../../../../systemSlice";
|
||||
import { ErrorResponseHandler } from "../../../../../common/types";
|
||||
import { BucketList } from "../../types";
|
||||
import api from "../../../../../common/api";
|
||||
import PageLayout from "../../../Common/Layout/PageLayout";
|
||||
import InputUnitMenu from "../../../Common/FormComponents/InputUnitMenu/InputUnitMenu";
|
||||
import FormLayout from "../../../Common/FormLayout";
|
||||
@@ -65,52 +63,57 @@ import {
|
||||
import { hasPermission } from "../../../../../common/SecureComponent";
|
||||
import BucketNamingRules from "./BucketNamingRules";
|
||||
import PageHeaderWrapper from "../../../Common/PageHeaderWrapper/PageHeaderWrapper";
|
||||
import { api } from "../../../../../api";
|
||||
import {
|
||||
Error,
|
||||
HttpResponse,
|
||||
ListBucketsResponse,
|
||||
} from "../../../../../api/consoleApi";
|
||||
import { errorToHandler } from "../../../../../api/errors";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
buttonContainer: {
|
||||
marginTop: 24,
|
||||
display: "flex",
|
||||
justifyContent: "flex-end",
|
||||
"& button": {
|
||||
marginLeft: 8,
|
||||
},
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
buttonContainer: {
|
||||
marginTop: 24,
|
||||
display: "flex",
|
||||
justifyContent: "flex-end",
|
||||
"& button": {
|
||||
marginLeft: 8,
|
||||
},
|
||||
error: {
|
||||
color: "#b53b4b",
|
||||
border: "1px solid #b53b4b",
|
||||
padding: 8,
|
||||
borderRadius: 3,
|
||||
},
|
||||
error: {
|
||||
color: "#b53b4b",
|
||||
border: "1px solid #b53b4b",
|
||||
padding: 8,
|
||||
borderRadius: 3,
|
||||
},
|
||||
alertVersioning: {
|
||||
border: "#E2E2E2 1px solid",
|
||||
backgroundColor: "#FBFAFA",
|
||||
borderRadius: 3,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
padding: "10px",
|
||||
color: "#767676",
|
||||
"& > .min-icon ": {
|
||||
width: 20,
|
||||
height: 20,
|
||||
marginRight: 10,
|
||||
},
|
||||
alertVersioning: {
|
||||
border: "#E2E2E2 1px solid",
|
||||
backgroundColor: "#FBFAFA",
|
||||
borderRadius: 3,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
padding: "10px",
|
||||
color: "#767676",
|
||||
"& > .min-icon ": {
|
||||
width: 20,
|
||||
height: 20,
|
||||
marginRight: 10,
|
||||
},
|
||||
},
|
||||
h6title: {
|
||||
fontWeight: "bold",
|
||||
color: "#000000",
|
||||
fontSize: 20,
|
||||
},
|
||||
...containerForHeader,
|
||||
});
|
||||
},
|
||||
h6title: {
|
||||
fontWeight: "bold",
|
||||
color: "#000000",
|
||||
fontSize: 20,
|
||||
},
|
||||
...containerForHeader,
|
||||
...modalBasic,
|
||||
}));
|
||||
|
||||
interface IsetProps {
|
||||
classes: any;
|
||||
}
|
||||
|
||||
const AddBucket = ({ classes }: IsetProps) => {
|
||||
const AddBucket = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const navigate = useNavigate();
|
||||
const classes = useStyles();
|
||||
|
||||
const validBucketCharacters = new RegExp(
|
||||
`^[a-z0-9][a-z0-9\\.\\-]{1,61}[a-z0-9]$`
|
||||
@@ -195,19 +198,23 @@ const AddBucket = ({ classes }: IsetProps) => {
|
||||
dispatch(setName(""));
|
||||
dispatch(setIsDirty(false));
|
||||
const fetchRecords = () => {
|
||||
api
|
||||
.invoke("GET", `/api/v1/buckets`)
|
||||
.then((res: BucketList) => {
|
||||
var bucketList: string[] = [];
|
||||
if (res.buckets != null && res.buckets.length > 0) {
|
||||
res.buckets.forEach((bucket) => {
|
||||
bucketList.push(bucket.name);
|
||||
});
|
||||
api.buckets
|
||||
.listBuckets()
|
||||
.then((res: HttpResponse<ListBucketsResponse, Error>) => {
|
||||
if (res.data) {
|
||||
var bucketList: string[] = [];
|
||||
if (res.data.buckets != null && res.data.buckets.length > 0) {
|
||||
res.data.buckets.forEach((bucket) => {
|
||||
bucketList.push(bucket.name);
|
||||
});
|
||||
}
|
||||
setRecords(bucketList);
|
||||
} else if (res.error) {
|
||||
dispatch(setErrorSnackMessage(errorToHandler(res.error)));
|
||||
}
|
||||
setRecords(bucketList);
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
dispatch(setErrorSnackMessage(err));
|
||||
.catch((err) => {
|
||||
dispatch(setErrorSnackMessage(errorToHandler(err)));
|
||||
});
|
||||
};
|
||||
fetchRecords();
|
||||
@@ -544,4 +551,4 @@ const AddBucket = ({ classes }: IsetProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default withStyles(styles)(AddBucket);
|
||||
export default AddBucket;
|
||||
|
||||
@@ -14,14 +14,15 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { MakeBucketRequest } from "../../types";
|
||||
import { getBytes } from "../../../../../common/utils";
|
||||
import api from "../../../../../common/api";
|
||||
import { ErrorResponseHandler } from "../../../../../common/types";
|
||||
import { setErrorSnackMessage } from "../../../../../systemSlice";
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import { AppState } from "../../../../../store";
|
||||
import { resetForm } from "./addBucketsSlice";
|
||||
import { api } from "../../../../../api";
|
||||
import {
|
||||
MakeBucketRequest,
|
||||
ObjectRetentionMode,
|
||||
ObjectRetentionUnit,
|
||||
} from "../../../../../api/consoleApi";
|
||||
|
||||
export const addBucketAsync = createAsyncThunk(
|
||||
"buckets/addBucketAsync",
|
||||
@@ -62,23 +63,13 @@ export const addBucketAsync = createAsyncThunk(
|
||||
|
||||
if (retentionEnabled) {
|
||||
request.retention = {
|
||||
mode: retentionMode,
|
||||
unit: retentionUnit,
|
||||
mode: retentionMode as ObjectRetentionMode,
|
||||
unit: retentionUnit as ObjectRetentionUnit,
|
||||
validity: retentionValidity,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return api
|
||||
.invoke("POST", "/api/v1/buckets", request)
|
||||
.then((res) => {
|
||||
const newBucketName = `${bucketName}`;
|
||||
dispatch(resetForm());
|
||||
return newBucketName;
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
dispatch(setErrorSnackMessage(err));
|
||||
return rejectWithValue(err);
|
||||
});
|
||||
return api.buckets.makeBucket(request);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -18,7 +18,6 @@ import get from "lodash/get";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import { BucketsIcon, ReportedUsageIcon, TotalObjectsIcon } from "mds";
|
||||
import { Bucket } from "../types";
|
||||
import { Box, Grid, Typography } from "@mui/material";
|
||||
import {
|
||||
calculateBytes,
|
||||
@@ -34,6 +33,7 @@ import {
|
||||
import { hasPermission } from "../../../../common/SecureComponent";
|
||||
import clsx from "clsx";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import { Bucket } from "../../../../api/consoleApi";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
@@ -248,7 +248,10 @@ const BucketListItem = ({
|
||||
<Grid container className={classes.bucketInfo}>
|
||||
<Grid item xs={12} sm paddingRight={5}>
|
||||
<Typography variant="body2">
|
||||
Created: {new Date(bucket.creation_date).toString()}
|
||||
Created:{" "}
|
||||
{bucket.creation_date
|
||||
? new Date(bucket.creation_date).toString()
|
||||
: "n/a"}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm>
|
||||
|
||||
@@ -29,17 +29,14 @@ import {
|
||||
SelectAllIcon,
|
||||
SelectMultipleIcon,
|
||||
} from "mds";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import { LinearProgress } from "@mui/material";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import { Bucket, BucketList } from "../types";
|
||||
import {
|
||||
actionsTray,
|
||||
containerForHeader,
|
||||
searchField,
|
||||
} from "../../Common/FormComponents/common/styleLibrary";
|
||||
import { ErrorResponseHandler } from "../../../../common/types";
|
||||
import api from "../../../../common/api";
|
||||
|
||||
import BucketListItem from "./BucketListItem";
|
||||
import BulkReplicationModal from "./BulkReplicationModal";
|
||||
import { SecureComponent } from "../../../../common/SecureComponent";
|
||||
@@ -65,33 +62,39 @@ import TooltipWrapper from "../../Common/TooltipWrapper/TooltipWrapper";
|
||||
import AButton from "../../Common/AButton/AButton";
|
||||
import { setLoadingObjects } from "../../ObjectBrowser/objectBrowserSlice";
|
||||
import PageHeaderWrapper from "../../Common/PageHeaderWrapper/PageHeaderWrapper";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import { api } from "../../../../api";
|
||||
import {
|
||||
Bucket,
|
||||
Error,
|
||||
HttpResponse,
|
||||
ListBucketsResponse,
|
||||
} from "../../../../api/consoleApi";
|
||||
import { errorToHandler } from "../../../../api/errors";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
bucketList: {
|
||||
marginTop: 25,
|
||||
height: "calc(100vh - 211px)",
|
||||
"&.isEmbedded": {
|
||||
height: "calc(100vh - 128px)",
|
||||
},
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
bucketList: {
|
||||
marginTop: 25,
|
||||
height: "calc(100vh - 211px)",
|
||||
"&.isEmbedded": {
|
||||
height: "calc(100vh - 128px)",
|
||||
},
|
||||
searchField: {
|
||||
...searchField.searchField,
|
||||
minWidth: 380,
|
||||
"@media (max-width: 900px)": {
|
||||
minWidth: 220,
|
||||
},
|
||||
},
|
||||
searchField: {
|
||||
...searchField.searchField,
|
||||
minWidth: 380,
|
||||
"@media (max-width: 900px)": {
|
||||
minWidth: 220,
|
||||
},
|
||||
...containerForHeader,
|
||||
});
|
||||
},
|
||||
...containerForHeader,
|
||||
...actionsTray,
|
||||
}));
|
||||
|
||||
interface IListBucketsProps {
|
||||
classes: any;
|
||||
}
|
||||
|
||||
const ListBuckets = ({ classes }: IListBucketsProps) => {
|
||||
const ListBuckets = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const navigate = useNavigate();
|
||||
const classes = useStyles();
|
||||
|
||||
const [records, setRecords] = useState<Bucket[]>([]);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
@@ -110,16 +113,17 @@ const ListBuckets = ({ classes }: IListBucketsProps) => {
|
||||
if (loading) {
|
||||
const fetchRecords = () => {
|
||||
setLoading(true);
|
||||
api
|
||||
.invoke("GET", `/api/v1/buckets`)
|
||||
.then((res: BucketList) => {
|
||||
setLoading(false);
|
||||
setRecords(res.buckets || []);
|
||||
dispatch(setLoadingObjects(true));
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
setLoading(false);
|
||||
dispatch(setErrorSnackMessage(err));
|
||||
api.buckets
|
||||
.listBuckets()
|
||||
.then((res: HttpResponse<ListBucketsResponse, Error>) => {
|
||||
if (res.data) {
|
||||
setLoading(false);
|
||||
setRecords(res.data.buckets || []);
|
||||
dispatch(setLoadingObjects(true));
|
||||
} else if (res.error) {
|
||||
setLoading(false);
|
||||
dispatch(setErrorSnackMessage(errorToHandler(res.error)));
|
||||
}
|
||||
});
|
||||
};
|
||||
fetchRecords();
|
||||
@@ -483,4 +487,4 @@ const ListBuckets = ({ classes }: IListBucketsProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default withStyles(styles)(ListBuckets);
|
||||
export default ListBuckets;
|
||||
|
||||
@@ -14,21 +14,6 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
export interface RwAccess {
|
||||
write: boolean;
|
||||
read: boolean;
|
||||
}
|
||||
|
||||
export interface Bucket {
|
||||
name: string;
|
||||
creation_date: string;
|
||||
size?: number;
|
||||
objects?: number;
|
||||
rw_access?: RwAccess;
|
||||
manage?: boolean;
|
||||
details?: Details;
|
||||
}
|
||||
|
||||
export interface BucketEncryptionInfo {
|
||||
algorithm: string;
|
||||
kmsMasterKeyID: string;
|
||||
@@ -50,11 +35,6 @@ export interface BucketInfo {
|
||||
size?: number;
|
||||
}
|
||||
|
||||
export interface BucketList {
|
||||
buckets: Bucket[];
|
||||
total: number;
|
||||
}
|
||||
|
||||
export interface BucketEvent {
|
||||
id: string;
|
||||
arn: string;
|
||||
@@ -68,11 +48,6 @@ export interface BucketEventList {
|
||||
total: number;
|
||||
}
|
||||
|
||||
export interface BucketPolicy {
|
||||
name: string;
|
||||
body: string;
|
||||
}
|
||||
|
||||
export interface ArnList {
|
||||
arns: string[];
|
||||
}
|
||||
@@ -92,10 +67,6 @@ export interface BucketObjectLocking {
|
||||
object_locking_enabled: boolean;
|
||||
}
|
||||
|
||||
export interface BucketReplicationRuleDeleteMarker {
|
||||
status: string;
|
||||
}
|
||||
|
||||
export interface BucketReplicationDestination {
|
||||
bucket: string;
|
||||
}
|
||||
@@ -124,26 +95,6 @@ export interface BucketQuota {
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface QuotaRequest {
|
||||
enabled: boolean;
|
||||
quota_type: string;
|
||||
amount: number;
|
||||
}
|
||||
|
||||
export interface RetentionRequest {
|
||||
mode: string;
|
||||
unit: string;
|
||||
validity: number;
|
||||
}
|
||||
|
||||
export interface MakeBucketRequest {
|
||||
name: string;
|
||||
versioning: boolean;
|
||||
locking: boolean;
|
||||
quota?: QuotaRequest;
|
||||
retention?: RetentionRequest;
|
||||
}
|
||||
|
||||
export interface ChangePasswordRequest {
|
||||
current_secret_key: string;
|
||||
new_secret_key: string;
|
||||
@@ -154,27 +105,6 @@ export interface ChangeUserPasswordRequest {
|
||||
newSecretKey: string;
|
||||
}
|
||||
|
||||
export interface IRemoteBucket {
|
||||
name: string;
|
||||
accessKey: string;
|
||||
secretKey: string;
|
||||
sourceBucket: string;
|
||||
targetURL: string;
|
||||
targetBucket: string;
|
||||
remoteARN: string;
|
||||
status: string;
|
||||
service: string;
|
||||
}
|
||||
|
||||
export interface PermissionAction {
|
||||
id: string;
|
||||
can: boolean;
|
||||
}
|
||||
|
||||
export interface HasPermissionResponse {
|
||||
permissions: PermissionAction[];
|
||||
}
|
||||
|
||||
export interface BulkReplicationResponse {
|
||||
replicationState: BulkReplicationItem[];
|
||||
}
|
||||
|
||||
@@ -36,9 +36,14 @@ import { routesAsKbarActions } from "./kbar-actions";
|
||||
import { Box } from "@mui/material";
|
||||
import { MenuExpandedIcon } from "mds";
|
||||
import { useSelector } from "react-redux";
|
||||
import useApi from "./Common/Hooks/useApi";
|
||||
import { Bucket, BucketList } from "./Buckets/types";
|
||||
import { selFeatures } from "./consoleSlice";
|
||||
import {
|
||||
Bucket,
|
||||
Error,
|
||||
HttpResponse,
|
||||
ListBucketsResponse,
|
||||
} from "../../api/consoleApi";
|
||||
import { api } from "../../api";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
resultItem: {
|
||||
@@ -131,15 +136,18 @@ const CommandBar = () => {
|
||||
|
||||
const [buckets, setBuckets] = useState<Bucket[]>([]);
|
||||
|
||||
const [, invokeListBucketsApi] = useApi(
|
||||
(res: BucketList) => {
|
||||
setBuckets(res.buckets);
|
||||
},
|
||||
() => {}
|
||||
);
|
||||
const invokeListBucketsApi = () => {
|
||||
api.buckets
|
||||
.listBuckets()
|
||||
.then((res: HttpResponse<ListBucketsResponse, Error>) => {
|
||||
if (res.data !== undefined) {
|
||||
setBuckets(res.data.buckets || []);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const fetchBuckets = useCallback(() => {
|
||||
invokeListBucketsApi("GET", `/api/v1/buckets`);
|
||||
invokeListBucketsApi();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -22,14 +22,11 @@ import { BucketsIcon, Button, HelpBox, RefreshIcon } from "mds";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import { LinearProgress } from "@mui/material";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import { Bucket, BucketList } from "../Buckets/types";
|
||||
import {
|
||||
actionsTray,
|
||||
containerForHeader,
|
||||
searchField,
|
||||
} from "../Common/FormComponents/common/styleLibrary";
|
||||
import { ErrorResponseHandler } from "../../../common/types";
|
||||
import api from "../../../common/api";
|
||||
|
||||
import { SecureComponent } from "../../../common/SecureComponent";
|
||||
import {
|
||||
@@ -48,11 +45,19 @@ import { selFeatures } from "../consoleSlice";
|
||||
import AutoColorIcon from "../Common/Components/AutoColorIcon";
|
||||
import TooltipWrapper from "../Common/TooltipWrapper/TooltipWrapper";
|
||||
import AButton from "../Common/AButton/AButton";
|
||||
import { setLoadingObjects } from "../ObjectBrowser/objectBrowserSlice";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import TableWrapper from "../Common/TableWrapper/TableWrapper";
|
||||
import { niceBytesInt } from "../../../common/utils";
|
||||
import PageHeaderWrapper from "../Common/PageHeaderWrapper/PageHeaderWrapper";
|
||||
import {
|
||||
Bucket,
|
||||
HttpResponse,
|
||||
ListBucketsResponse,
|
||||
Error,
|
||||
} from "../../../api/consoleApi";
|
||||
import { api } from "../../../api";
|
||||
import { errorToHandler } from "../../../api/errors";
|
||||
import { setLoadingObjects } from "./objectBrowserSlice";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
@@ -91,16 +96,18 @@ const OBListBuckets = () => {
|
||||
if (loading) {
|
||||
const fetchRecords = () => {
|
||||
setLoading(true);
|
||||
api
|
||||
.invoke("GET", `/api/v1/buckets`)
|
||||
.then((res: BucketList) => {
|
||||
setLoading(false);
|
||||
setRecords(res.buckets || []);
|
||||
dispatch(setLoadingObjects(true));
|
||||
api.buckets
|
||||
.listBuckets()
|
||||
.then((res: HttpResponse<ListBucketsResponse, Error>) => {
|
||||
if (res.data) {
|
||||
setLoading(false);
|
||||
setRecords(res.data.buckets || []);
|
||||
dispatch(setLoadingObjects(true));
|
||||
}
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
.catch((err) => {
|
||||
setLoading(false);
|
||||
dispatch(setErrorSnackMessage(err));
|
||||
dispatch(setErrorSnackMessage(errorToHandler(err)));
|
||||
});
|
||||
};
|
||||
fetchRecords();
|
||||
|
||||
@@ -24,13 +24,14 @@ import AddPolicyHelpBox from "./AddPolicyHelpBox";
|
||||
import CodeMirrorWrapper from "../Common/FormComponents/CodeMirrorWrapper/CodeMirrorWrapper";
|
||||
import { IAM_PAGES } from "../../../common/SecureComponent/permissions";
|
||||
import { ErrorResponseHandler } from "../../../common/types";
|
||||
import api from "../../../../src/common/api";
|
||||
import FormLayout from "../Common/FormLayout";
|
||||
import { setErrorSnackMessage } from "../../../systemSlice";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useAppDispatch } from "../../../store";
|
||||
import { emptyPolicy } from "./utils";
|
||||
import PageHeaderWrapper from "../Common/PageHeaderWrapper/PageHeaderWrapper";
|
||||
import { api } from "../../../api";
|
||||
import { Error, HttpResponse, Policy } from "../../../api/consoleApi";
|
||||
|
||||
const AddPolicyScreen = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
@@ -46,12 +47,12 @@ const AddPolicyScreen = () => {
|
||||
return;
|
||||
}
|
||||
setAddLoading(true);
|
||||
api
|
||||
.invoke("POST", "/api/v1/policies", {
|
||||
api.policies
|
||||
.addPolicy({
|
||||
name: policyName,
|
||||
policy: policyDefinition,
|
||||
})
|
||||
.then((res) => {
|
||||
.then((res: HttpResponse<Policy, Error>) => {
|
||||
setAddLoading(false);
|
||||
navigate(`${IAM_PAGES.POLICIES}`);
|
||||
})
|
||||
|
||||
@@ -17,12 +17,10 @@
|
||||
import React, { Fragment, useEffect, useState } from "react";
|
||||
import { AddIcon, Button, HelpBox, IAMPoliciesIcon } from "mds";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import get from "lodash/get";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import { Policy, PolicyList } from "./types";
|
||||
|
||||
import {
|
||||
actionsTray,
|
||||
@@ -32,7 +30,6 @@ import {
|
||||
import { ErrorResponseHandler } from "../../../common/types";
|
||||
|
||||
import TableWrapper from "../Common/TableWrapper/TableWrapper";
|
||||
import api from "../../../common/api";
|
||||
import PageLayout from "../Common/Layout/PageLayout";
|
||||
import {
|
||||
CONSOLE_UI_RESOURCE,
|
||||
@@ -57,6 +54,13 @@ import { setErrorSnackMessage } from "../../../systemSlice";
|
||||
import { useAppDispatch } from "../../../store";
|
||||
import TooltipWrapper from "../Common/TooltipWrapper/TooltipWrapper";
|
||||
import PageHeaderWrapper from "../Common/PageHeaderWrapper/PageHeaderWrapper";
|
||||
import { api } from "../../../api";
|
||||
import {
|
||||
Error,
|
||||
HttpResponse,
|
||||
ListPoliciesResponse,
|
||||
Policy,
|
||||
} from "../../../api/consoleApi";
|
||||
|
||||
const DeletePolicy = withSuspense(React.lazy(() => import("./DeletePolicy")));
|
||||
|
||||
@@ -115,17 +119,17 @@ const ListPolicies = ({ classes }: IPoliciesProps) => {
|
||||
useEffect(() => {
|
||||
if (loading) {
|
||||
if (canDisplayPolicies) {
|
||||
api
|
||||
.invoke("GET", `/api/v1/policies`)
|
||||
.then((res: PolicyList) => {
|
||||
const policies = get(res, "policies", []);
|
||||
api.policies
|
||||
.listPolicies()
|
||||
.then((res: HttpResponse<ListPoliciesResponse, Error>) => {
|
||||
const policies = res.data.policies ?? [];
|
||||
|
||||
policies.sort((pa, pb) => {
|
||||
if (pa.name > pb.name) {
|
||||
if (pa.name! > pb.name!) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pa.name < pb.name) {
|
||||
if (pa.name! < pb.name!) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -181,7 +185,7 @@ const ListPolicies = ({ classes }: IPoliciesProps) => {
|
||||
];
|
||||
|
||||
const filteredRecords = records.filter((elementItem) =>
|
||||
elementItem.name.includes(filterPolicies)
|
||||
elementItem.name?.includes(filterPolicies)
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Fragment, useEffect, useState } from "react";
|
||||
import { IAMPolicy, IAMStatement, Policy } from "./types";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import {
|
||||
@@ -38,7 +37,6 @@ import Paper from "@mui/material/Paper";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import { LinearProgress } from "@mui/material";
|
||||
import TableWrapper from "../Common/TableWrapper/TableWrapper";
|
||||
import api from "../../../common/api";
|
||||
|
||||
import { ErrorResponseHandler } from "../../../common/types";
|
||||
import CodeMirrorWrapper from "../Common/FormComponents/CodeMirrorWrapper/CodeMirrorWrapper";
|
||||
@@ -75,6 +73,14 @@ import { selFeatures } from "../consoleSlice";
|
||||
import { useAppDispatch } from "../../../store";
|
||||
import TooltipWrapper from "../Common/TooltipWrapper/TooltipWrapper";
|
||||
import PageHeaderWrapper from "../Common/PageHeaderWrapper/PageHeaderWrapper";
|
||||
import {
|
||||
Error,
|
||||
HttpResponse,
|
||||
Policy,
|
||||
ServiceAccounts,
|
||||
} from "../../../api/consoleApi";
|
||||
import { api } from "../../../api";
|
||||
import { IAMPolicy, IAMStatement } from "./types";
|
||||
|
||||
const DeletePolicy = withSuspense(React.lazy(() => import("./DeletePolicy")));
|
||||
|
||||
@@ -180,8 +186,8 @@ const PolicyDetails = ({ classes }: IPolicyDetailsProps) => {
|
||||
}
|
||||
setAddLoading(true);
|
||||
if (canEditPolicy) {
|
||||
api
|
||||
.invoke("POST", "/api/v1/policies", {
|
||||
api.policies
|
||||
.addPolicy({
|
||||
name: policyName,
|
||||
policy: policyDefinition,
|
||||
})
|
||||
@@ -203,13 +209,10 @@ const PolicyDetails = ({ classes }: IPolicyDetailsProps) => {
|
||||
const loadUsersForPolicy = () => {
|
||||
if (loadingUsers) {
|
||||
if (displayUsers && !ldapIsEnabled) {
|
||||
api
|
||||
.invoke(
|
||||
"GET",
|
||||
`/api/v1/policies/${encodeURLString(policyName)}/users`
|
||||
)
|
||||
.then((result: any) => {
|
||||
setUserList(result);
|
||||
api.policies
|
||||
.listUsersForPolicy(encodeURLString(policyName))
|
||||
.then((result: HttpResponse<ServiceAccounts, Error>) => {
|
||||
setUserList(result.data ?? []);
|
||||
setLoadingUsers(false);
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
@@ -225,13 +228,10 @@ const PolicyDetails = ({ classes }: IPolicyDetailsProps) => {
|
||||
const loadGroupsForPolicy = () => {
|
||||
if (loadingGroups) {
|
||||
if (displayGroups && !ldapIsEnabled) {
|
||||
api
|
||||
.invoke(
|
||||
"GET",
|
||||
`/api/v1/policies/${encodeURLString(policyName)}/groups`
|
||||
)
|
||||
.then((result: any) => {
|
||||
setGroupList(result);
|
||||
api.policies
|
||||
.listGroupsForPolicy(encodeURLString(policyName))
|
||||
.then((result: HttpResponse<ServiceAccounts, Error>) => {
|
||||
setGroupList(result.data ?? []);
|
||||
setLoadingGroups(false);
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
@@ -246,17 +246,17 @@ const PolicyDetails = ({ classes }: IPolicyDetailsProps) => {
|
||||
const loadPolicyDetails = () => {
|
||||
if (loadingPolicy) {
|
||||
if (displayPolicy) {
|
||||
api
|
||||
.invoke("GET", `/api/v1/policy/${encodeURLString(policyName)}`)
|
||||
.then((result: any) => {
|
||||
if (result) {
|
||||
setPolicy(result);
|
||||
api.policy
|
||||
.policyInfo(encodeURLString(policyName))
|
||||
.then((result: HttpResponse<Policy, Error>) => {
|
||||
if (result.data) {
|
||||
setPolicy(result.data);
|
||||
setPolicyDefinition(
|
||||
result
|
||||
? JSON.stringify(JSON.parse(result.policy), null, 4)
|
||||
? JSON.stringify(JSON.parse(result.data?.policy!), null, 4)
|
||||
: ""
|
||||
);
|
||||
const pol: IAMPolicy = JSON.parse(result.policy);
|
||||
const pol: IAMPolicy = JSON.parse(result.data?.policy!);
|
||||
setPolicyStatements(pol.Statement);
|
||||
}
|
||||
setLoadingPolicy(false);
|
||||
|
||||
@@ -28,16 +28,20 @@ import {
|
||||
selectorsCommon,
|
||||
tableStyles,
|
||||
} from "../Common/FormComponents/common/styleLibrary";
|
||||
import { PolicyList } from "./types";
|
||||
|
||||
import { ErrorResponseHandler } from "../../../common/types";
|
||||
import api from "../../../common/api";
|
||||
import TableWrapper from "../Common/TableWrapper/TableWrapper";
|
||||
import SearchBox from "../Common/SearchBox";
|
||||
import { setModalErrorSnackMessage } from "../../../systemSlice";
|
||||
import { AppState, useAppDispatch } from "../../../store";
|
||||
import { setSelectedPolicies } from "../Users/AddUsersSlice";
|
||||
import { useSelector } from "react-redux";
|
||||
import { api } from "../../../api";
|
||||
import {
|
||||
HttpResponse,
|
||||
ListPoliciesResponse,
|
||||
Error,
|
||||
} from "../../../api/consoleApi";
|
||||
|
||||
interface ISelectPolicyProps {
|
||||
classes: any;
|
||||
@@ -90,10 +94,10 @@ const PolicySelectors = ({ classes, noTitle = false }: ISelectPolicyProps) => {
|
||||
const fetchPolicies = useCallback(() => {
|
||||
isLoading(true);
|
||||
|
||||
api
|
||||
.invoke("GET", `/api/v1/policies?limit=1000`)
|
||||
.then((res: PolicyList) => {
|
||||
const policies = res.policies === null ? [] : res.policies;
|
||||
api.policies
|
||||
.listPolicies()
|
||||
.then((res: HttpResponse<ListPoliciesResponse, Error>) => {
|
||||
const policies = res.data.policies ?? [];
|
||||
isLoading(false);
|
||||
setRecords(policies.sort(policySort));
|
||||
})
|
||||
|
||||
@@ -13,25 +13,23 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { useState } from "react";
|
||||
import { IAMStatement } from "./types";
|
||||
import React, { Fragment, useState } from "react";
|
||||
import { Box } from "@mui/material";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import SearchBox from "../Common/SearchBox";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import { searchField } from "../Common/FormComponents/common/styleLibrary";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import { DisabledIcon, EnabledIcon } from "mds";
|
||||
import { STATUS_COLORS } from "../Dashboard/BasicDashboard/Utils";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import { IAMStatement } from "./types";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
searchField: {
|
||||
...searchField.searchField,
|
||||
maxWidth: 380,
|
||||
},
|
||||
});
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
searchField: {
|
||||
...searchField.searchField,
|
||||
maxWidth: 380,
|
||||
},
|
||||
}));
|
||||
|
||||
const rowGridStyle = {
|
||||
display: "grid",
|
||||
@@ -57,11 +55,11 @@ const Highlight = ({ search = "", children = "" }): any => {
|
||||
|
||||
const PolicyView = ({
|
||||
policyStatements,
|
||||
classes = {},
|
||||
}: {
|
||||
policyStatements: IAMStatement[];
|
||||
classes?: any;
|
||||
}) => {
|
||||
const classes = useStyles();
|
||||
|
||||
const [filter, setFilter] = useState<string>("");
|
||||
|
||||
return (
|
||||
@@ -88,104 +86,107 @@ const PolicyView = ({
|
||||
/>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
sx={{
|
||||
"& .policy-row": {
|
||||
borderBottom: "1px solid #eaeaea",
|
||||
},
|
||||
"& .policy-row:first-child": {
|
||||
borderTop: "1px solid #eaeaea",
|
||||
},
|
||||
"& .policy-row:last-child": {
|
||||
borderBottom: "0px",
|
||||
},
|
||||
paddingTop: "15px",
|
||||
"& mark": {
|
||||
color: "#000000",
|
||||
fontWeight: 500,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{policyStatements.map((stmt, i) => {
|
||||
const effect = stmt.Effect;
|
||||
const isAllow = effect === "Allow";
|
||||
return (
|
||||
<Box
|
||||
className="policy-row"
|
||||
key={`${i}`}
|
||||
sx={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "1fr",
|
||||
gap: "15px",
|
||||
fontSize: "14px",
|
||||
padding: "10px 0 10px 0",
|
||||
"& .label": {
|
||||
fontWeight: 600,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box sx={rowGridStyle}>
|
||||
<Box className="label">Effect:</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
|
||||
alignItems: "center",
|
||||
"& .min-icon": {
|
||||
marginRight: "5px",
|
||||
fill: isAllow ? STATUS_COLORS.GREEN : STATUS_COLORS.RED,
|
||||
height: "14px",
|
||||
width: "14px",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{isAllow ? <EnabledIcon /> : <DisabledIcon />}
|
||||
{effect}
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{!policyStatements && <Fragment>Policy has no statements</Fragment>}
|
||||
{policyStatements && (
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
sx={{
|
||||
"& .policy-row": {
|
||||
borderBottom: "1px solid #eaeaea",
|
||||
},
|
||||
"& .policy-row:first-child": {
|
||||
borderTop: "1px solid #eaeaea",
|
||||
},
|
||||
"& .policy-row:last-child": {
|
||||
borderBottom: "0px",
|
||||
},
|
||||
paddingTop: "15px",
|
||||
"& mark": {
|
||||
color: "#000000",
|
||||
fontWeight: 500,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{policyStatements.map((stmt, i) => {
|
||||
const effect = stmt.Effect;
|
||||
const isAllow = effect === "Allow";
|
||||
return (
|
||||
<Box
|
||||
className="policy-row"
|
||||
key={`${i}`}
|
||||
sx={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: {
|
||||
sm: "1fr 1fr",
|
||||
xs: "1fr",
|
||||
},
|
||||
gridTemplateColumns: "1fr",
|
||||
gap: "15px",
|
||||
fontSize: "14px",
|
||||
padding: "10px 0 10px 0",
|
||||
"& .label": {
|
||||
fontWeight: 600,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box sx={rowGridStyle}>
|
||||
<Box className="label">Actions:</Box>
|
||||
<Box>
|
||||
{stmt.Action &&
|
||||
stmt.Action.map((act, actIndex) => (
|
||||
<div key={`${i}-r-${actIndex}`}>
|
||||
<Highlight search={filter}>{act}</Highlight>
|
||||
</div>
|
||||
))}
|
||||
<Box className="label">Effect:</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
|
||||
alignItems: "center",
|
||||
"& .min-icon": {
|
||||
marginRight: "5px",
|
||||
fill: isAllow ? STATUS_COLORS.GREEN : STATUS_COLORS.RED,
|
||||
height: "14px",
|
||||
width: "14px",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{isAllow ? <EnabledIcon /> : <DisabledIcon />}
|
||||
{effect}
|
||||
</Box>
|
||||
</Box>
|
||||
<Box sx={rowGridStyle}>
|
||||
<Box className="label">Resources:</Box>
|
||||
<Box>
|
||||
{stmt.Resource &&
|
||||
stmt.Resource.map((res, resIndex) => (
|
||||
<div key={`${i}-r-${resIndex}`}>
|
||||
{" "}
|
||||
<Highlight search={filter}>{res}</Highlight>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: {
|
||||
sm: "1fr 1fr",
|
||||
xs: "1fr",
|
||||
},
|
||||
gap: "15px",
|
||||
}}
|
||||
>
|
||||
<Box sx={rowGridStyle}>
|
||||
<Box className="label">Actions:</Box>
|
||||
<Box>
|
||||
{stmt.Action &&
|
||||
stmt.Action.map((act, actIndex) => (
|
||||
<div key={`${i}-r-${actIndex}`}>
|
||||
<Highlight search={filter}>{act}</Highlight>
|
||||
</div>
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
<Box sx={rowGridStyle}>
|
||||
<Box className="label">Resources:</Box>
|
||||
<Box>
|
||||
{stmt.Resource &&
|
||||
stmt.Resource.map((res, resIndex) => (
|
||||
<div key={`${i}-r-${resIndex}`}>
|
||||
{" "}
|
||||
<Highlight search={filter}>{res}</Highlight>
|
||||
</div>
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</Grid>
|
||||
);
|
||||
})}
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
export default withStyles(styles)(PolicyView);
|
||||
export default PolicyView;
|
||||
|
||||
@@ -14,30 +14,12 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
export interface Policy {
|
||||
name: string;
|
||||
policy: string;
|
||||
}
|
||||
|
||||
export interface PolicyList {
|
||||
policies: Policy[];
|
||||
total: number;
|
||||
}
|
||||
|
||||
export interface IAMStatement {
|
||||
Effect: string;
|
||||
Action: string[];
|
||||
Resource: string[];
|
||||
}
|
||||
|
||||
export const newStatement = (): IAMStatement => {
|
||||
return {
|
||||
Effect: "Deny",
|
||||
Action: [],
|
||||
Resource: [],
|
||||
};
|
||||
};
|
||||
|
||||
export interface IAMPolicy {
|
||||
Version: string;
|
||||
Statement: IAMStatement[];
|
||||
|
||||
@@ -18,7 +18,7 @@ import { Action } from "kbar/lib/types";
|
||||
import { BucketsIcon } from "mds";
|
||||
import { validRoutes } from "./valid-routes";
|
||||
import { IAM_PAGES } from "../../common/SecureComponent/permissions";
|
||||
import { Bucket } from "./Buckets/types";
|
||||
import { Bucket } from "../../api/consoleApi";
|
||||
|
||||
export const routesAsKbarActions = (
|
||||
features: string[] | null,
|
||||
|
||||
@@ -14,16 +14,13 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { Policy } from "../api/consoleApi";
|
||||
import { redirectRule } from "../screens/LoginPage/types";
|
||||
|
||||
interface userInterface {
|
||||
accessKey: string;
|
||||
}
|
||||
|
||||
interface policyInterface {
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface policyDetailsInterface {
|
||||
policy: string;
|
||||
}
|
||||
@@ -39,11 +36,11 @@ export const usersSort = (a: userInterface, b: userInterface) => {
|
||||
return 0;
|
||||
};
|
||||
|
||||
export const policySort = (a: policyInterface, b: policyInterface) => {
|
||||
if (a.name > b.name) {
|
||||
export const policySort = (a: Policy, b: Policy) => {
|
||||
if (a.name! > b.name!) {
|
||||
return 1;
|
||||
}
|
||||
if (a.name < b.name) {
|
||||
if (a.name! < b.name!) {
|
||||
return -1;
|
||||
}
|
||||
// a must be equal to b
|
||||
|
||||
Reference in New Issue
Block a user