Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
543076eaac | ||
|
|
cbf1ddeb4c | ||
|
|
3746adcc13 | ||
|
|
854b984850 | ||
|
|
62fa0e2043 | ||
|
|
4f5b1b0aa7 | ||
|
|
0e362c2106 |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"files": {
|
||||
"main.css": "./static/css/main.57e739f5.css",
|
||||
"main.js": "./static/js/main.078385cd.js",
|
||||
"main.js": "./static/js/main.46564223.js",
|
||||
"static/js/1260.a025e586.chunk.js": "./static/js/1260.a025e586.chunk.js",
|
||||
"static/js/6914.8835970e.chunk.js": "./static/js/6914.8835970e.chunk.js",
|
||||
"static/js/9121.4999947f.chunk.js": "./static/js/9121.4999947f.chunk.js",
|
||||
@@ -35,7 +35,7 @@
|
||||
"static/js/191.b50b4104.chunk.js": "./static/js/191.b50b4104.chunk.js",
|
||||
"static/js/1329.98d80e22.chunk.js": "./static/js/1329.98d80e22.chunk.js",
|
||||
"static/js/7614.527036f5.chunk.js": "./static/js/7614.527036f5.chunk.js",
|
||||
"static/js/5351.41f5c7df.chunk.js": "./static/js/5351.41f5c7df.chunk.js",
|
||||
"static/js/1690.4e6b342c.chunk.js": "./static/js/1690.4e6b342c.chunk.js",
|
||||
"static/js/6491.83aa26f7.chunk.js": "./static/js/6491.83aa26f7.chunk.js",
|
||||
"static/js/4902.f064f175.chunk.js": "./static/js/4902.f064f175.chunk.js",
|
||||
"static/js/1432.6e142c2c.chunk.js": "./static/js/1432.6e142c2c.chunk.js",
|
||||
@@ -44,7 +44,7 @@
|
||||
"static/js/6577.4b3c8b41.chunk.js": "./static/js/6577.4b3c8b41.chunk.js",
|
||||
"static/js/3875.5db2c08f.chunk.js": "./static/js/3875.5db2c08f.chunk.js",
|
||||
"static/js/3115.da3a98f3.chunk.js": "./static/js/3115.da3a98f3.chunk.js",
|
||||
"static/js/5522.72ab8875.chunk.js": "./static/js/5522.72ab8875.chunk.js",
|
||||
"static/js/5522.9c77c391.chunk.js": "./static/js/5522.9c77c391.chunk.js",
|
||||
"static/js/977.4c29a863.chunk.js": "./static/js/977.4c29a863.chunk.js",
|
||||
"static/js/6686.ede27280.chunk.js": "./static/js/6686.ede27280.chunk.js",
|
||||
"static/js/9059.155bb503.chunk.js": "./static/js/9059.155bb503.chunk.js",
|
||||
@@ -52,7 +52,7 @@
|
||||
"static/js/6247.af0fb000.chunk.js": "./static/js/6247.af0fb000.chunk.js",
|
||||
"static/js/4414.ff5f95b9.chunk.js": "./static/js/4414.ff5f95b9.chunk.js",
|
||||
"static/js/8833.4ba5da15.chunk.js": "./static/js/8833.4ba5da15.chunk.js",
|
||||
"static/js/1516.147495bb.chunk.js": "./static/js/1516.147495bb.chunk.js",
|
||||
"static/js/1516.d1e7e873.chunk.js": "./static/js/1516.d1e7e873.chunk.js",
|
||||
"static/js/483.b039dcc0.chunk.js": "./static/js/483.b039dcc0.chunk.js",
|
||||
"static/js/4114.9ce1a962.chunk.js": "./static/js/4114.9ce1a962.chunk.js",
|
||||
"static/js/6895.143165e2.chunk.js": "./static/js/6895.143165e2.chunk.js",
|
||||
@@ -140,7 +140,7 @@
|
||||
"static/media/Inter-Regular.woff2": "./static/media/Inter-Regular.c8ba52b05a9ef10f4758.woff2",
|
||||
"index.html": "./index.html",
|
||||
"main.57e739f5.css.map": "./static/css/main.57e739f5.css.map",
|
||||
"main.078385cd.js.map": "./static/js/main.078385cd.js.map",
|
||||
"main.46564223.js.map": "./static/js/main.46564223.js.map",
|
||||
"1260.a025e586.chunk.js.map": "./static/js/1260.a025e586.chunk.js.map",
|
||||
"6914.8835970e.chunk.js.map": "./static/js/6914.8835970e.chunk.js.map",
|
||||
"9121.4999947f.chunk.js.map": "./static/js/9121.4999947f.chunk.js.map",
|
||||
@@ -174,7 +174,7 @@
|
||||
"191.b50b4104.chunk.js.map": "./static/js/191.b50b4104.chunk.js.map",
|
||||
"1329.98d80e22.chunk.js.map": "./static/js/1329.98d80e22.chunk.js.map",
|
||||
"7614.527036f5.chunk.js.map": "./static/js/7614.527036f5.chunk.js.map",
|
||||
"5351.41f5c7df.chunk.js.map": "./static/js/5351.41f5c7df.chunk.js.map",
|
||||
"1690.4e6b342c.chunk.js.map": "./static/js/1690.4e6b342c.chunk.js.map",
|
||||
"6491.83aa26f7.chunk.js.map": "./static/js/6491.83aa26f7.chunk.js.map",
|
||||
"4902.f064f175.chunk.js.map": "./static/js/4902.f064f175.chunk.js.map",
|
||||
"1432.6e142c2c.chunk.js.map": "./static/js/1432.6e142c2c.chunk.js.map",
|
||||
@@ -183,7 +183,7 @@
|
||||
"6577.4b3c8b41.chunk.js.map": "./static/js/6577.4b3c8b41.chunk.js.map",
|
||||
"3875.5db2c08f.chunk.js.map": "./static/js/3875.5db2c08f.chunk.js.map",
|
||||
"3115.da3a98f3.chunk.js.map": "./static/js/3115.da3a98f3.chunk.js.map",
|
||||
"5522.72ab8875.chunk.js.map": "./static/js/5522.72ab8875.chunk.js.map",
|
||||
"5522.9c77c391.chunk.js.map": "./static/js/5522.9c77c391.chunk.js.map",
|
||||
"977.4c29a863.chunk.js.map": "./static/js/977.4c29a863.chunk.js.map",
|
||||
"6686.ede27280.chunk.js.map": "./static/js/6686.ede27280.chunk.js.map",
|
||||
"9059.155bb503.chunk.js.map": "./static/js/9059.155bb503.chunk.js.map",
|
||||
@@ -191,7 +191,7 @@
|
||||
"6247.af0fb000.chunk.js.map": "./static/js/6247.af0fb000.chunk.js.map",
|
||||
"4414.ff5f95b9.chunk.js.map": "./static/js/4414.ff5f95b9.chunk.js.map",
|
||||
"8833.4ba5da15.chunk.js.map": "./static/js/8833.4ba5da15.chunk.js.map",
|
||||
"1516.147495bb.chunk.js.map": "./static/js/1516.147495bb.chunk.js.map",
|
||||
"1516.d1e7e873.chunk.js.map": "./static/js/1516.d1e7e873.chunk.js.map",
|
||||
"483.b039dcc0.chunk.js.map": "./static/js/483.b039dcc0.chunk.js.map",
|
||||
"4114.9ce1a962.chunk.js.map": "./static/js/4114.9ce1a962.chunk.js.map",
|
||||
"6895.143165e2.chunk.js.map": "./static/js/6895.143165e2.chunk.js.map",
|
||||
@@ -260,6 +260,6 @@
|
||||
},
|
||||
"entrypoints": [
|
||||
"static/css/main.57e739f5.css",
|
||||
"static/js/main.078385cd.js"
|
||||
"static/js/main.46564223.js"
|
||||
]
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><base href="/"/><meta content="width=device-width,initial-scale=1" name="viewport"/><meta content="#081C42" media="(prefers-color-scheme: light)" name="theme-color"/><meta content="#081C42" media="(prefers-color-scheme: dark)" name="theme-color"/><meta content="MinIO Console" name="description"/><meta name="minio-license" content="apgl"/><link href="./styles/root-styles.css" rel="stylesheet"/><link href="./apple-icon-180x180.png" rel="apple-touch-icon" sizes="180x180"/><link href="./favicon-32x32.png" rel="icon" sizes="32x32" type="image/png"/><link href="./favicon-96x96.png" rel="icon" sizes="96x96" type="image/png"/><link href="./favicon-16x16.png" rel="icon" sizes="16x16" type="image/png"/><link href="./manifest.json" rel="manifest"/><link color="#3a4e54" href="./safari-pinned-tab.svg" rel="mask-icon"/><title>MinIO Console</title><script defer="defer" src="./static/js/main.078385cd.js"></script><link href="./static/css/main.57e739f5.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"><div id="preload"><img src="./images/background.svg"/> <img src="./images/background-wave-orig2.svg"/></div><div id="loader-block"><img src="./Loader.svg"/></div></div></body></html>
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><base href="/"/><meta content="width=device-width,initial-scale=1" name="viewport"/><meta content="#081C42" media="(prefers-color-scheme: light)" name="theme-color"/><meta content="#081C42" media="(prefers-color-scheme: dark)" name="theme-color"/><meta content="MinIO Console" name="description"/><meta name="minio-license" content="apgl"/><link href="./styles/root-styles.css" rel="stylesheet"/><link href="./apple-icon-180x180.png" rel="apple-touch-icon" sizes="180x180"/><link href="./favicon-32x32.png" rel="icon" sizes="32x32" type="image/png"/><link href="./favicon-96x96.png" rel="icon" sizes="96x96" type="image/png"/><link href="./favicon-16x16.png" rel="icon" sizes="16x16" type="image/png"/><link href="./manifest.json" rel="manifest"/><link color="#3a4e54" href="./safari-pinned-tab.svg" rel="mask-icon"/><title>MinIO Console</title><script defer="defer" src="./static/js/main.46564223.js"></script><link href="./static/css/main.57e739f5.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"><div id="preload"><img src="./images/background.svg"/> <img src="./images/background-wave-orig2.svg"/></div><div id="loader-block"><img src="./Loader.svg"/></div></div></body></html>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/1516.d1e7e873.chunk.js
Normal file
2
portal-ui/build/static/js/1516.d1e7e873.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/1516.d1e7e873.chunk.js.map
Normal file
1
portal-ui/build/static/js/1516.d1e7e873.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/1690.4e6b342c.chunk.js
Normal file
2
portal-ui/build/static/js/1690.4e6b342c.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/1690.4e6b342c.chunk.js.map
Normal file
1
portal-ui/build/static/js/1690.4e6b342c.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/5522.9c77c391.chunk.js.map
Normal file
1
portal-ui/build/static/js/5522.9c77c391.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
3
portal-ui/build/static/js/main.46564223.js
Normal file
3
portal-ui/build/static/js/main.46564223.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/main.46564223.js.map
Normal file
1
portal-ui/build/static/js/main.46564223.js.map
Normal file
File diff suppressed because one or more lines are too long
@@ -18,7 +18,7 @@
|
||||
"local-storage-fallback": "^4.1.1",
|
||||
"lodash": "^4.17.21",
|
||||
"luxon": "^3.3.0",
|
||||
"mds": "https://github.com/minio/mds.git#v0.3.2",
|
||||
"mds": "https://github.com/minio/mds.git#v0.3.3",
|
||||
"minio": "^7.0.32",
|
||||
"react": "^18.1.0",
|
||||
"react-component-export-image": "^1.0.6",
|
||||
|
||||
@@ -26,6 +26,7 @@ import { containerForHeader } from "../../Common/FormComponents/common/styleLibr
|
||||
import ListObjects from "../ListBuckets/Objects/ListObjects/ListObjects";
|
||||
import { IAM_SCOPES } from "../../../../common/SecureComponent/permissions";
|
||||
import {
|
||||
errorInConnection,
|
||||
newMessage,
|
||||
resetMessages,
|
||||
setIsOpeningOD,
|
||||
@@ -70,7 +71,8 @@ let wsInFlight: boolean = false;
|
||||
|
||||
const initWSConnection = (
|
||||
openCallback?: () => void,
|
||||
onMessageCallback?: (message: IMessageEvent) => void
|
||||
onMessageCallback?: (message: IMessageEvent) => void,
|
||||
connErrorCallback?: (message: string) => void
|
||||
) => {
|
||||
if (wsInFlight) {
|
||||
return;
|
||||
@@ -104,10 +106,17 @@ const initWSConnection = (
|
||||
|
||||
const reconnectFn = () => {
|
||||
if (errorCounter <= 5) {
|
||||
initWSConnection(() => {}, onMessageCallback);
|
||||
initWSConnection(() => {}, onMessageCallback, connErrorCallback);
|
||||
errorCounter += 1;
|
||||
} else {
|
||||
console.error("Websocket not available.");
|
||||
console.error(
|
||||
"Websocket not available. Please review that your environment settings are enabled to allow websocket connections and that requests are made from the same origin."
|
||||
);
|
||||
if (connErrorCallback) {
|
||||
connErrorCallback(
|
||||
"Couldn't establish WebSocket connection. Please review your configuration and try again."
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -245,6 +254,7 @@ const BrowserHandler = () => {
|
||||
try {
|
||||
const newRequestID = currentRequestID + 1;
|
||||
dispatch(resetMessages());
|
||||
dispatch(errorInConnection(false));
|
||||
|
||||
const request: WebsocketRequest = {
|
||||
bucket_name: bucketName,
|
||||
@@ -266,7 +276,18 @@ const BrowserHandler = () => {
|
||||
const dupRequest = () => {
|
||||
initWSRequest(path, date);
|
||||
};
|
||||
initWSConnection(dupRequest, onMessageCallBack);
|
||||
|
||||
const fatalWSError = (message: string) => {
|
||||
dispatch(
|
||||
setErrorSnackMessage({
|
||||
errorMessage: message,
|
||||
detailedError: message,
|
||||
})
|
||||
);
|
||||
dispatch(errorInConnection(true));
|
||||
};
|
||||
|
||||
initWSConnection(dupRequest, onMessageCallBack, fatalWSError);
|
||||
}
|
||||
},
|
||||
[bucketName, rewindEnabled, showDeleted, dispatch, onMessageCallBack]
|
||||
|
||||
@@ -117,9 +117,13 @@ const ListObjectsTable = ({ internalPaths }: IListObjectTable) => {
|
||||
const selectedObjects = useSelector(
|
||||
(state: AppState) => state.objectBrowser.selectedObjects
|
||||
);
|
||||
const connectionError = useSelector(
|
||||
(state: AppState) => state.objectBrowser.connectionError
|
||||
);
|
||||
const anonymousMode = useSelector(
|
||||
(state: AppState) => state.system.anonymousMode
|
||||
);
|
||||
|
||||
const displayListObjects = hasPermission(bucketName, [
|
||||
IAM_SCOPES.S3_LIST_BUCKET,
|
||||
IAM_SCOPES.S3_ALL_LIST_BUCKET,
|
||||
@@ -228,6 +232,21 @@ const ListObjectsTable = ({ internalPaths }: IListObjectTable) => {
|
||||
return elements;
|
||||
};
|
||||
|
||||
let errorMessage =
|
||||
!displayListObjects && !anonymousMode
|
||||
? permissionTooltipHelper(
|
||||
[IAM_SCOPES.S3_LIST_BUCKET, IAM_SCOPES.S3_ALL_LIST_BUCKET],
|
||||
"view Objects in this bucket"
|
||||
)
|
||||
: `This location is empty${
|
||||
!rewindEnabled ? ", please try uploading a new file" : ""
|
||||
}`;
|
||||
|
||||
if (connectionError) {
|
||||
errorMessage =
|
||||
"Objects List unavailable. Please review your WebSockets configuration and try again";
|
||||
}
|
||||
|
||||
return (
|
||||
<TableWrapper
|
||||
itemActions={tableActions}
|
||||
@@ -241,16 +260,7 @@ const ListObjectsTable = ({ internalPaths }: IListObjectTable) => {
|
||||
} ${detailsOpen ? "actionsPanelOpen" : ""}`}
|
||||
selectedItems={selectedObjects}
|
||||
onSelect={!anonymousMode ? selectListObjects : undefined}
|
||||
customEmptyMessage={
|
||||
!displayListObjects && !anonymousMode
|
||||
? permissionTooltipHelper(
|
||||
[IAM_SCOPES.S3_LIST_BUCKET, IAM_SCOPES.S3_ALL_LIST_BUCKET],
|
||||
"view Objects in this bucket"
|
||||
)
|
||||
: `This location is empty${
|
||||
!rewindEnabled ? ", please try uploading a new file" : ""
|
||||
}`
|
||||
}
|
||||
customEmptyMessage={errorMessage}
|
||||
sortConfig={{
|
||||
currentSort: currentSortField,
|
||||
currentDirection: sortDirection,
|
||||
|
||||
@@ -27,13 +27,15 @@ import {
|
||||
InputBox,
|
||||
Loader,
|
||||
RemoveIcon,
|
||||
SearchIcon,
|
||||
SectionTitle,
|
||||
UptimeIcon,
|
||||
TimeIcon,
|
||||
} from "mds";
|
||||
import PolicySelectors from "../../Policies/PolicySelectors";
|
||||
import { useSelector } from "react-redux";
|
||||
import { LDAPEntitiesResponse } from "./types";
|
||||
import { DateTime } from "luxon";
|
||||
import LDAPResultsBlock from "./LDAPResultsBlock";
|
||||
|
||||
const LDAPEntitiesQuery = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
@@ -107,90 +109,128 @@ const LDAPEntitiesQuery = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ marginTop: 15, paddingTop: 0 }} withBorders>
|
||||
<Box sx={{ marginTop: 15, paddingTop: 0 }}>
|
||||
<Grid container sx={{ marginTop: 5 }}>
|
||||
<Grid item sm={12} md={6} lg={5} sx={{ padding: 10, paddingTop: 0 }}>
|
||||
<SectionTitle separator>Query Filters</SectionTitle>
|
||||
<SectionTitle>Query Filters</SectionTitle>
|
||||
|
||||
<Box sx={{ padding: "0 10px" }}>
|
||||
<h4>Users</h4>
|
||||
<Box
|
||||
sx={{
|
||||
overflowY: "auto",
|
||||
minHeight: 220,
|
||||
maxHeight: 250,
|
||||
"& > div > div": {
|
||||
width: "100%",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{users.map((userDat, index) => {
|
||||
return (
|
||||
<InputBox
|
||||
id={`search-user-${index}`}
|
||||
key={`search-user-${index}`}
|
||||
value={userDat}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const usersElements = [...users];
|
||||
usersElements[index] = e.target.value;
|
||||
setUsers(usersElements);
|
||||
}}
|
||||
overlayIcon={
|
||||
users.length === index + 1 ? <AddIcon /> : <RemoveIcon />
|
||||
}
|
||||
overlayAction={() => {
|
||||
alterUsersList(users.length === index + 1, index);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
<Box
|
||||
sx={{
|
||||
padding: "0 10px",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: 40,
|
||||
}}
|
||||
>
|
||||
<Box sx={{ padding: "10px 26px" }} withBorders>
|
||||
<Box sx={{ display: "flex" }}>
|
||||
<h4 style={{ margin: 0, marginBottom: 10, fontSize: 14 }}>
|
||||
Users
|
||||
</h4>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
overflowY: "auto",
|
||||
minHeight: 50,
|
||||
maxHeight: 250,
|
||||
"& > div > div": {
|
||||
width: "100%",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{users.map((userDat, index) => {
|
||||
return (
|
||||
<InputBox
|
||||
id={`search-user-${index}`}
|
||||
key={`search-user-${index}`}
|
||||
value={userDat}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const usersElements = [...users];
|
||||
usersElements[index] = e.target.value;
|
||||
setUsers(usersElements);
|
||||
}}
|
||||
overlayIcon={
|
||||
users.length === index + 1 ? (
|
||||
<AddIcon />
|
||||
) : (
|
||||
<RemoveIcon />
|
||||
)
|
||||
}
|
||||
overlayAction={() => {
|
||||
alterUsersList(users.length === index + 1, index);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<h4>Groups</h4>
|
||||
<Box
|
||||
sx={{
|
||||
overflowY: "auto",
|
||||
minHeight: 220,
|
||||
maxHeight: 250,
|
||||
"& > div > div": {
|
||||
width: "100%",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{groups.map((groupDat, index) => {
|
||||
return (
|
||||
<InputBox
|
||||
id={`search-group-${index}`}
|
||||
key={`search-group-${index}`}
|
||||
value={groupDat}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const groupsElements = [...groups];
|
||||
groupsElements[index] = e.target.value;
|
||||
setGroups(groupsElements);
|
||||
}}
|
||||
overlayIcon={
|
||||
groups.length === index + 1 ? <AddIcon /> : <RemoveIcon />
|
||||
}
|
||||
overlayAction={() => {
|
||||
alterGroupsList(groups.length === index + 1, index);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
<Box sx={{ padding: "10px 26px" }} withBorders>
|
||||
<h4 style={{ margin: 0, marginBottom: 10, fontSize: 14 }}>
|
||||
Groups
|
||||
</h4>
|
||||
<Box
|
||||
sx={{
|
||||
overflowY: "auto",
|
||||
minHeight: 50,
|
||||
maxHeight: "calc(100vh - 340px)",
|
||||
"& > div > div": {
|
||||
width: "100%",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{groups.map((groupDat, index) => {
|
||||
return (
|
||||
<InputBox
|
||||
id={`search-group-${index}`}
|
||||
key={`search-group-${index}`}
|
||||
value={groupDat}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const groupsElements = [...groups];
|
||||
groupsElements[index] = e.target.value;
|
||||
setGroups(groupsElements);
|
||||
}}
|
||||
overlayIcon={
|
||||
groups.length === index + 1 ? (
|
||||
<AddIcon />
|
||||
) : (
|
||||
<RemoveIcon />
|
||||
)
|
||||
}
|
||||
overlayAction={() => {
|
||||
alterGroupsList(groups.length === index + 1, index);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<h4>Policies</h4>
|
||||
<Box
|
||||
sx={{
|
||||
minHeight: 220,
|
||||
maxHeight: "calc(100vh - 740px)",
|
||||
}}
|
||||
>
|
||||
<PolicySelectors selectedPolicy={selectedPolicies} noTitle />
|
||||
<Box sx={{ padding: "10px 26px" }} withBorders>
|
||||
<h4 style={{ margin: 0, marginBottom: 10, fontSize: 14 }}>
|
||||
Policies
|
||||
</h4>
|
||||
<Box
|
||||
sx={{
|
||||
minHeight: 265,
|
||||
maxHeight: "calc(100vh - 740px)",
|
||||
}}
|
||||
>
|
||||
<PolicySelectors selectedPolicy={selectedPolicies} noTitle />
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid item sm={12} md={6} lg={7} sx={{ padding: 10, paddingTop: 0 }}>
|
||||
<Grid
|
||||
item
|
||||
sm={12}
|
||||
md={6}
|
||||
lg={7}
|
||||
sx={{
|
||||
padding: 10,
|
||||
paddingTop: 0,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
}}
|
||||
>
|
||||
{loading ? (
|
||||
<Box sx={{ textAlign: "center" }}>
|
||||
<Loader />
|
||||
@@ -198,8 +238,6 @@ const LDAPEntitiesQuery = () => {
|
||||
) : (
|
||||
<Fragment>
|
||||
<SectionTitle
|
||||
separator
|
||||
sx={{ marginBottom: 15 }}
|
||||
actions={
|
||||
<Box
|
||||
sx={{
|
||||
@@ -211,8 +249,13 @@ const LDAPEntitiesQuery = () => {
|
||||
>
|
||||
{results?.timestamp ? (
|
||||
<Fragment>
|
||||
<UptimeIcon
|
||||
style={{ width: 18, height: 18, marginRight: 5 }}
|
||||
<TimeIcon
|
||||
style={{
|
||||
width: 14,
|
||||
height: 14,
|
||||
marginRight: 5,
|
||||
fill: "#BEBFBF",
|
||||
}}
|
||||
/>
|
||||
{DateTime.fromISO(results.timestamp).toFormat(
|
||||
"D HH:mm:ss"
|
||||
@@ -224,114 +267,30 @@ const LDAPEntitiesQuery = () => {
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
Results
|
||||
Query Results
|
||||
</SectionTitle>
|
||||
{results ? (
|
||||
<Box>
|
||||
<Box
|
||||
sx={{
|
||||
backgroundColor: "#FBFAFA",
|
||||
padding: "8px 22px",
|
||||
flexGrow: 1,
|
||||
overflowY: "auto",
|
||||
}}
|
||||
>
|
||||
{!results.groups && !results.users && !results.policies && (
|
||||
<Box sx={{ textAlign: "center" }}>
|
||||
<h4>No Results Available</h4>
|
||||
</Box>
|
||||
)}
|
||||
{!!results.groups && (
|
||||
<Box className={"resultElement"}>
|
||||
<SectionTitle separator sx={{ fontSize: 12 }}>
|
||||
Group Mappings
|
||||
</SectionTitle>
|
||||
<Box sx={{ padding: "0 15px" }}>
|
||||
{results.groups.map((groupData, index) => {
|
||||
return (
|
||||
<Fragment key={`policy-res-${index}`}>
|
||||
<h4>{groupData.group}</h4>
|
||||
{groupData.policies && (
|
||||
<Fragment>
|
||||
Policies:
|
||||
<ul>
|
||||
{groupData.policies.map(
|
||||
(policy, index2) => (
|
||||
<li key={`policy-group-${index2}`}>
|
||||
{policy}
|
||||
</li>
|
||||
)
|
||||
)}
|
||||
</ul>
|
||||
</Fragment>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
</Box>
|
||||
<LDAPResultsBlock results={results} entityName={"Group"} />
|
||||
)}
|
||||
{!!results.users && (
|
||||
<Box className={"resultElement"}>
|
||||
<SectionTitle separator sx={{ fontSize: 12 }}>
|
||||
User Mappings
|
||||
</SectionTitle>
|
||||
<Box sx={{ padding: "0 15px" }}>
|
||||
{results.users.map((groupData, index) => {
|
||||
return (
|
||||
<Fragment key={`users-res-${index}`}>
|
||||
<h4>{groupData.user}</h4>
|
||||
{groupData.policies && (
|
||||
<Fragment>
|
||||
Policies:
|
||||
<ul>
|
||||
{groupData.policies.map(
|
||||
(policy, index2) => (
|
||||
<li key={`policy-users-${index2}`}>
|
||||
{policy}
|
||||
</li>
|
||||
)
|
||||
)}
|
||||
</ul>
|
||||
</Fragment>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
</Box>
|
||||
<LDAPResultsBlock results={results} entityName={"User"} />
|
||||
)}
|
||||
{!!results.policies && (
|
||||
<Box className={"resultElement"}>
|
||||
<SectionTitle separator sx={{ fontSize: 12 }}>
|
||||
Policy Mappings
|
||||
</SectionTitle>
|
||||
<Box sx={{ padding: "0 15px" }}>
|
||||
{results.policies.map((groupData, index) => {
|
||||
return (
|
||||
<Fragment key={`policy-map-${index}`}>
|
||||
<h4>{groupData.policy}</h4>
|
||||
{groupData.groups && (
|
||||
<Fragment>
|
||||
Groups:
|
||||
<ul>
|
||||
{groupData.groups.map((group, index2) => (
|
||||
<li key={`policy-map-group-${index}`}>
|
||||
{group}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</Fragment>
|
||||
)}
|
||||
{groupData.users && (
|
||||
<Fragment>
|
||||
Users:
|
||||
<ul>
|
||||
{groupData.users.map((user, index3) => (
|
||||
<li key={`policy-map-user-${index}`}>
|
||||
{user}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</Fragment>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
</Box>
|
||||
<LDAPResultsBlock results={results} entityName={"Policy"} />
|
||||
)}
|
||||
</Box>
|
||||
) : (
|
||||
@@ -342,12 +301,22 @@ const LDAPEntitiesQuery = () => {
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container>
|
||||
<Grid item xs={12} sx={{ display: "flex", justifyContent: "flex-end" }}>
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
sx={{
|
||||
display: "flex",
|
||||
justifyContent: "flex-start",
|
||||
marginTop: 45,
|
||||
padding: "0 20px",
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
id={"search-entity"}
|
||||
type={"button"}
|
||||
variant={"callAction"}
|
||||
onClick={searchEntities}
|
||||
icon={<SearchIcon />}
|
||||
>
|
||||
Search
|
||||
</Button>
|
||||
|
||||
165
portal-ui/src/screens/Console/IDP/LDAP/LDAPResultsBlock.tsx
Normal file
165
portal-ui/src/screens/Console/IDP/LDAP/LDAPResultsBlock.tsx
Normal file
@@ -0,0 +1,165 @@
|
||||
// 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 React, { Fragment } from "react";
|
||||
import { Box, CollapseCaret, GroupsMenuIcon, SectionTitle } from "mds";
|
||||
import { LDAPEntitiesResponse } from "./types";
|
||||
|
||||
interface IResultBlock {
|
||||
entityName: "Group" | "User" | "Policy";
|
||||
results: LDAPEntitiesResponse;
|
||||
}
|
||||
|
||||
interface IEntityResultName {
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface IEntityResultItem {
|
||||
blockName: "Policies" | "Groups" | "Users";
|
||||
results: string[];
|
||||
}
|
||||
|
||||
const EntityResultTitle = ({ name }: IEntityResultName) => {
|
||||
return (
|
||||
<h4>
|
||||
<CollapseCaret style={{ transform: "rotateZ(90deg)" }} />
|
||||
{name}
|
||||
</h4>
|
||||
);
|
||||
};
|
||||
|
||||
const EntityResultItems = ({ blockName, results }: IEntityResultItem) => {
|
||||
return (
|
||||
<Fragment>
|
||||
<strong>{blockName}:</strong>
|
||||
<ul>
|
||||
{results.map((res, index) => (
|
||||
<li key={`policy-${blockName}-${index}`}>{res}</li>
|
||||
))}
|
||||
</ul>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const LDAPResultsBlock = ({ entityName, results }: IResultBlock) => {
|
||||
let entityLength = 0;
|
||||
|
||||
switch (entityName) {
|
||||
case "Group":
|
||||
entityLength = results.groups?.length || 0;
|
||||
break;
|
||||
case "Policy":
|
||||
entityLength = results.policies?.length || 0;
|
||||
break;
|
||||
case "User":
|
||||
entityLength = results.users?.length || 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
<Box
|
||||
className={"resultElement"}
|
||||
sx={{
|
||||
marginTop: 50,
|
||||
"&:first-of-type": {
|
||||
marginTop: 0,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<SectionTitle
|
||||
separator
|
||||
sx={{ fontSize: 12 }}
|
||||
icon={<GroupsMenuIcon style={{ width: 17, height: 17 }} />}
|
||||
actions={
|
||||
<Box sx={{ fontSize: 14 }}>
|
||||
<strong>{entityLength}</strong> Entit
|
||||
{entityLength === 1 ? "y" : "ies"} Found
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
{entityName} Mappings
|
||||
</SectionTitle>
|
||||
<Box
|
||||
className={"resultsList"}
|
||||
sx={{
|
||||
h4: {
|
||||
borderBottom: "#e2e2e2 1px solid",
|
||||
padding: "12px 0",
|
||||
margin: 0,
|
||||
marginBottom: 15,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
"& svg": {
|
||||
marginRight: 10,
|
||||
fill: "#3C77A7",
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
{entityName === "Group" &&
|
||||
results.groups?.map((groupData, index) => {
|
||||
return (
|
||||
<Fragment key={`policy-res-${index}`}>
|
||||
<EntityResultTitle name={groupData.group} />
|
||||
{groupData.policies && (
|
||||
<EntityResultItems
|
||||
blockName={"Policies"}
|
||||
results={groupData.policies}
|
||||
/>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
{entityName === "User" &&
|
||||
results.users?.map((groupData, index) => {
|
||||
return (
|
||||
<Fragment key={`users-res-${index}`}>
|
||||
<EntityResultTitle name={groupData.user} />
|
||||
{groupData.policies && (
|
||||
<EntityResultItems
|
||||
blockName={"Policies"}
|
||||
results={groupData.policies}
|
||||
/>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
{entityName === "Policy" &&
|
||||
results.policies?.map((groupData, index) => {
|
||||
return (
|
||||
<Fragment key={`policy-map-${index}`}>
|
||||
<EntityResultTitle name={groupData.policy} />
|
||||
{groupData.groups && (
|
||||
<EntityResultItems
|
||||
blockName={"Groups"}
|
||||
results={groupData.groups}
|
||||
/>
|
||||
)}
|
||||
{groupData.users && (
|
||||
<EntityResultItems
|
||||
blockName={"Users"}
|
||||
results={groupData.users}
|
||||
/>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default LDAPResultsBlock;
|
||||
@@ -36,6 +36,7 @@ const initialState: ObjectBrowserState = {
|
||||
objectDetailsOpen: false,
|
||||
loadingVersions: true,
|
||||
loadingObjectInfo: true,
|
||||
connectionError: false,
|
||||
rewind: {
|
||||
...defaultRewind,
|
||||
},
|
||||
@@ -365,6 +366,14 @@ export const objectBrowserSlice = createSlice({
|
||||
setAnonymousAccessOpen: (state, action: PayloadAction<boolean>) => {
|
||||
state.anonymousAccessOpen = action.payload;
|
||||
},
|
||||
errorInConnection: (state, action: PayloadAction<boolean>) => {
|
||||
state.connectionError = action.payload;
|
||||
if (action.payload) {
|
||||
state.loadingObjects = false;
|
||||
state.loadingObjectInfo = false;
|
||||
state.objectDetailsOpen = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
export const {
|
||||
@@ -412,6 +421,7 @@ export const {
|
||||
setSelectedBucket,
|
||||
setLongFileOpen,
|
||||
setAnonymousAccessOpen,
|
||||
errorInConnection,
|
||||
} = objectBrowserSlice.actions;
|
||||
|
||||
export default objectBrowserSlice.reducer;
|
||||
|
||||
@@ -96,6 +96,7 @@ export interface ObjectBrowserState {
|
||||
retentionConfig: IRetentionConfig | null;
|
||||
longFileOpen: boolean;
|
||||
anonymousAccessOpen: boolean;
|
||||
connectionError: boolean;
|
||||
}
|
||||
|
||||
export interface ObjectManager {
|
||||
|
||||
@@ -24,7 +24,10 @@ import RegisterHelpBox from "./RegisterHelpBox";
|
||||
import { SubnetLoginRequest, SubnetLoginResponse } from "../License/types";
|
||||
import api from "../../../common/api";
|
||||
import { useAppDispatch } from "../../../store";
|
||||
import { setErrorSnackMessage } from "../../../systemSlice";
|
||||
import {
|
||||
setErrorSnackMessage,
|
||||
setServerNeedsRestart,
|
||||
} from "../../../systemSlice";
|
||||
import { ErrorResponseHandler } from "../../../common/types";
|
||||
import { spacingUtils } from "../Common/FormComponents/common/styleLibrary";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
@@ -66,6 +69,7 @@ const ApiKeyRegister = ({ classes, registerEndpoint }: IApiKeyRegister) => {
|
||||
.then((resp: SubnetLoginResponse) => {
|
||||
setLoading(false);
|
||||
if (resp && resp.registered) {
|
||||
dispatch(setServerNeedsRestart(true));
|
||||
navigate(IAM_PAGES.LICENSE);
|
||||
}
|
||||
})
|
||||
|
||||
@@ -26,7 +26,10 @@ import { useSelector } from "react-redux";
|
||||
import CommentBoxWrapper from "../Common/FormComponents/CommentBoxWrapper/CommentBoxWrapper";
|
||||
import useApi from "../Common/Hooks/useApi";
|
||||
import { fetchLicenseInfo } from "./registerThunks";
|
||||
import { setErrorSnackMessage } from "../../../systemSlice";
|
||||
import {
|
||||
setErrorSnackMessage,
|
||||
setServerNeedsRestart,
|
||||
} from "../../../systemSlice";
|
||||
|
||||
const OfflineRegistration = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
@@ -47,6 +50,7 @@ const OfflineRegistration = () => {
|
||||
const [isSaving, invokeApplyLicenseApi] = useApi(
|
||||
() => {
|
||||
dispatch(fetchLicenseInfo());
|
||||
dispatch(setServerNeedsRestart(true));
|
||||
},
|
||||
(err) => {
|
||||
dispatch(setErrorSnackMessage(err));
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2022 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public APIKey as published by
|
||||
// the Free Software Foundation, either version 3 of the APIKey, 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 APIKey for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public APIKey
|
||||
// along with this program. If not, see <http://www.gnu.org/APIKeys/>.
|
||||
|
||||
import React, { Fragment, useCallback, useEffect, useState } from "react";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import {
|
||||
actionsTray,
|
||||
containerForHeader,
|
||||
searchField,
|
||||
spacingUtils,
|
||||
} from "../Common/FormComponents/common/styleLibrary";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import { Box } from "@mui/material";
|
||||
import PageLayout from "../Common/Layout/PageLayout";
|
||||
import api from "../../../common/api";
|
||||
|
||||
import { ErrorResponseHandler } from "../../../common/types";
|
||||
|
||||
import Tabs from "@mui/material/Tabs";
|
||||
import Tab from "@mui/material/Tab";
|
||||
import { TabPanel } from "../../shared/tabs";
|
||||
import { ClusterRegistered } from "./utils";
|
||||
import ApiKeyRegister from "./ApiKeyRegister";
|
||||
import PageHeaderWrapper from "../Common/PageHeaderWrapper/PageHeaderWrapper";
|
||||
|
||||
interface IRegister {
|
||||
classes: any;
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
...actionsTray,
|
||||
...searchField,
|
||||
...spacingUtils,
|
||||
...containerForHeader,
|
||||
});
|
||||
|
||||
const RegisterOperator = ({ classes }: IRegister) => {
|
||||
const [apiKeyRegistered, setAPIKeyRegistered] = useState<boolean>(false);
|
||||
const [curTab, setCurTab] = useState<number>(0);
|
||||
|
||||
const fetchAPIKeyInfo = useCallback(() => {
|
||||
api
|
||||
.invoke("GET", `/api/v1/subnet/apikey/info`)
|
||||
.then((res: any) => {
|
||||
setAPIKeyRegistered(true);
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
setAPIKeyRegistered(false);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
fetchAPIKeyInfo();
|
||||
}, [fetchAPIKeyInfo]);
|
||||
|
||||
const apiKeyRegistration = (
|
||||
<Fragment>
|
||||
<Box
|
||||
sx={{
|
||||
border: "1px solid #eaeaea",
|
||||
borderRadius: "2px",
|
||||
display: "flex",
|
||||
flexFlow: "column",
|
||||
padding: "43px",
|
||||
}}
|
||||
>
|
||||
{apiKeyRegistered ? (
|
||||
<ClusterRegistered email={"Operator"} />
|
||||
) : (
|
||||
<ApiKeyRegister registerEndpoint={"/api/v1/subnet/apikey/register"} />
|
||||
)}
|
||||
</Box>
|
||||
</Fragment>
|
||||
);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<PageHeaderWrapper
|
||||
label="Register to MinIO Subscription Network"
|
||||
actions={<React.Fragment />}
|
||||
/>
|
||||
|
||||
<PageLayout>
|
||||
<Tabs
|
||||
value={curTab}
|
||||
onChange={(e: React.ChangeEvent<{}>, newValue: number) => {
|
||||
setCurTab(newValue);
|
||||
}}
|
||||
indicatorColor="primary"
|
||||
textColor="primary"
|
||||
aria-label="cluster-tabs"
|
||||
variant="scrollable"
|
||||
scrollButtons="auto"
|
||||
>
|
||||
<Tab
|
||||
label="API Key"
|
||||
id="simple-tab-0"
|
||||
aria-controls="simple-tabpanel-1"
|
||||
/>
|
||||
</Tabs>
|
||||
<TabPanel index={0} value={curTab}>
|
||||
{apiKeyRegistration}
|
||||
</TabPanel>
|
||||
</PageLayout>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default withStyles(styles)(RegisterOperator);
|
||||
@@ -35,7 +35,10 @@ import {
|
||||
SubnetRegisterRequest,
|
||||
} from "../License/types";
|
||||
import { ErrorResponseHandler } from "../../../common/types";
|
||||
import { setErrorSnackMessage } from "../../../systemSlice";
|
||||
import {
|
||||
setErrorSnackMessage,
|
||||
setServerNeedsRestart,
|
||||
} from "../../../systemSlice";
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import { AppState } from "../../../store";
|
||||
import { hasPermission } from "../../../common/SecureComponent";
|
||||
@@ -104,6 +107,7 @@ export const callRegister = createAsyncThunk(
|
||||
.invoke("POST", "/api/v1/subnet/register", request)
|
||||
.then(() => {
|
||||
dispatch(setLoading(false));
|
||||
dispatch(setServerNeedsRestart(true));
|
||||
dispatch(resetRegisterForm());
|
||||
dispatch(fetchLicenseInfo());
|
||||
})
|
||||
|
||||
@@ -377,22 +377,21 @@ const Login = () => {
|
||||
</a>
|
||||
</Fragment>
|
||||
}
|
||||
promoHeader={<Fragment>Multi-Cloud Object Store</Fragment>}
|
||||
promoHeader={
|
||||
<span style={{ fontSize: 28 }}>High-Performance Object Store</span>
|
||||
}
|
||||
promoInfo={
|
||||
<Fragment>
|
||||
MinIO's high-performance, Kubernetes-native object store is licensed
|
||||
under GNU AGPL v3 and is available on every cloud - public, private
|
||||
and edge. For more information on the terms of the license or to
|
||||
learn more about commercial licensing options visit the{" "}
|
||||
<a
|
||||
href={"https://min.io/pricing?ref=con"}
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
pricing page
|
||||
<span style={{ fontSize: 14, lineHeight: 1 }}>
|
||||
MinIO is a cloud-native object store built to run on any
|
||||
infrastructure - public, private or edge clouds. Primary use cases
|
||||
include data lakes, databases, AI/ML, SaaS applications and fast
|
||||
backup & recovery. MinIO is dual licensed under GNU AGPL v3 and
|
||||
commercial license. To learn more, visit{" "}
|
||||
<a href={"https://min.io/?ref=con"} target="_blank" rel="noopener">
|
||||
www.min.io
|
||||
</a>
|
||||
.
|
||||
</Fragment>
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
</Fragment>
|
||||
|
||||
@@ -4877,10 +4877,10 @@ destroy@1.2.0:
|
||||
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
|
||||
integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
|
||||
|
||||
detect-gpu@^5.0.16:
|
||||
version "5.0.16"
|
||||
resolved "https://registry.yarnpkg.com/detect-gpu/-/detect-gpu-5.0.16.tgz#a42054724f4a75d667add68ad1073c80d29ef733"
|
||||
integrity sha512-6+o6Sy+FzgQJG7Ray0fN7B4kRGGPuyaM5FHXJ4N3sLcQhsUO9+NEw9emM7vxN7DroZGG16ZydCX6kpgDmNXyKQ==
|
||||
detect-gpu@^5.0.17:
|
||||
version "5.0.17"
|
||||
resolved "https://registry.yarnpkg.com/detect-gpu/-/detect-gpu-5.0.17.tgz#fe4bbf8fc630aa68e1e770f4e63240212bdfbd38"
|
||||
integrity sha512-eAnZDpYeDASfzFYmGULBEiK0P4q1naMxDzOtMkQEBcFdesu1LjnsOraZHQ7+BGgCTOcKWvI1rxjh5FvICst0xw==
|
||||
dependencies:
|
||||
webgl-constants "^1.1.1"
|
||||
|
||||
@@ -8316,12 +8316,12 @@ mdn-data@2.0.4:
|
||||
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b"
|
||||
integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==
|
||||
|
||||
"mds@https://github.com/minio/mds.git#v0.3.2":
|
||||
version "0.3.2"
|
||||
resolved "https://github.com/minio/mds.git#85654388adaec4d2624b61bee439c7d9cd5801f7"
|
||||
"mds@https://github.com/minio/mds.git#v0.3.3":
|
||||
version "0.3.3"
|
||||
resolved "https://github.com/minio/mds.git#309b13379f64ec66a0e1f2670e7e8611b84e3215"
|
||||
dependencies:
|
||||
"@types/styled-components" "^5.1.25"
|
||||
detect-gpu "^5.0.16"
|
||||
detect-gpu "^5.0.17"
|
||||
react-virtualized "^9.22.3"
|
||||
styled-components "^5.3.9"
|
||||
|
||||
|
||||
@@ -329,6 +329,25 @@ func (s consoleSTSAssumeRole) IsExpired() bool {
|
||||
return s.stsAssumeRole.IsExpired()
|
||||
}
|
||||
|
||||
func stsCredentials(minioURL, accessKey, secretKey, location string) (*credentials.Credentials, error) {
|
||||
if accessKey == "" || secretKey == "" {
|
||||
return nil, errors.New("credentials endpoint, access and secret key are mandatory for AssumeRoleSTS")
|
||||
}
|
||||
opts := credentials.STSAssumeRoleOptions{
|
||||
AccessKey: accessKey,
|
||||
SecretKey: secretKey,
|
||||
Location: location,
|
||||
DurationSeconds: int(xjwt.GetConsoleSTSDuration().Seconds()),
|
||||
}
|
||||
stsAssumeRole := &credentials.STSAssumeRole{
|
||||
Client: GetConsoleHTTPClient(minioURL),
|
||||
STSEndpoint: minioURL,
|
||||
Options: opts,
|
||||
}
|
||||
consoleSTSWrapper := consoleSTSAssumeRole{stsAssumeRole: stsAssumeRole}
|
||||
return credentials.New(consoleSTSWrapper), nil
|
||||
}
|
||||
|
||||
func NewConsoleCredentials(accessKey, secretKey, location string) (*credentials.Credentials, error) {
|
||||
minioURL := getMinIOServer()
|
||||
|
||||
@@ -341,27 +360,37 @@ func NewConsoleCredentials(accessKey, secretKey, location string) (*credentials.
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// We verify if LDAP credentials are correct and no error is returned
|
||||
_, err = creds.Get()
|
||||
|
||||
if err != nil && strings.Contains(strings.ToLower(err.Error()), "not found") {
|
||||
// We try to use STS Credentials in case LDAP credentials are incorrect.
|
||||
stsCreds, errSTS := stsCredentials(minioURL, accessKey, secretKey, location)
|
||||
|
||||
// If there is an error with STS too, then we return the original LDAP error
|
||||
if errSTS != nil {
|
||||
LogError("error in STS credentials for LDAP case: %v ", errSTS)
|
||||
|
||||
// We return LDAP result
|
||||
return creds, nil
|
||||
}
|
||||
|
||||
_, err := stsCreds.Get()
|
||||
// There is an error with STS credentials, We return the result of LDAP as STS is not a priority in this case.
|
||||
if err != nil {
|
||||
return creds, nil
|
||||
}
|
||||
|
||||
return stsCreds, nil
|
||||
}
|
||||
|
||||
return creds, nil
|
||||
}
|
||||
// default authentication for Console is via STS (Security Token Service) against MinIO
|
||||
default:
|
||||
{
|
||||
if accessKey == "" || secretKey == "" {
|
||||
return nil, errors.New("credentials endpoint, access and secret key are mandatory for AssumeRoleSTS")
|
||||
}
|
||||
opts := credentials.STSAssumeRoleOptions{
|
||||
AccessKey: accessKey,
|
||||
SecretKey: secretKey,
|
||||
Location: location,
|
||||
DurationSeconds: int(xjwt.GetConsoleSTSDuration().Seconds()),
|
||||
}
|
||||
stsAssumeRole := &credentials.STSAssumeRole{
|
||||
Client: GetConsoleHTTPClient(minioURL),
|
||||
STSEndpoint: minioURL,
|
||||
Options: opts,
|
||||
}
|
||||
consoleSTSWrapper := consoleSTSAssumeRole{stsAssumeRole: stsAssumeRole}
|
||||
return credentials.New(consoleSTSWrapper), nil
|
||||
return stsCredentials(minioURL, accessKey, secretKey, location)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user