Added validation for users to not delete their own account (#633)
Also Implemented an option to show / hide actions in table wrapper Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
This commit is contained in:
@@ -1,25 +1,25 @@
|
||||
{
|
||||
"files": {
|
||||
"main.css": "/static/css/main.a19f3d53.chunk.css",
|
||||
"main.js": "/static/js/main.0e3d4f4a.chunk.js",
|
||||
"main.js.map": "/static/js/main.0e3d4f4a.chunk.js.map",
|
||||
"main.js": "/static/js/main.35167004.chunk.js",
|
||||
"main.js.map": "/static/js/main.35167004.chunk.js.map",
|
||||
"runtime-main.js": "/static/js/runtime-main.f48e99e5.js",
|
||||
"runtime-main.js.map": "/static/js/runtime-main.f48e99e5.js.map",
|
||||
"static/css/2.76b14b73.chunk.css": "/static/css/2.76b14b73.chunk.css",
|
||||
"static/js/2.fa5f1dc1.chunk.js": "/static/js/2.fa5f1dc1.chunk.js",
|
||||
"static/js/2.fa5f1dc1.chunk.js.map": "/static/js/2.fa5f1dc1.chunk.js.map",
|
||||
"static/js/2.9510b4a1.chunk.js": "/static/js/2.9510b4a1.chunk.js",
|
||||
"static/js/2.9510b4a1.chunk.js.map": "/static/js/2.9510b4a1.chunk.js.map",
|
||||
"index.html": "/index.html",
|
||||
"static/css/2.76b14b73.chunk.css.map": "/static/css/2.76b14b73.chunk.css.map",
|
||||
"static/css/main.a19f3d53.chunk.css.map": "/static/css/main.a19f3d53.chunk.css.map",
|
||||
"static/js/2.fa5f1dc1.chunk.js.LICENSE.txt": "/static/js/2.fa5f1dc1.chunk.js.LICENSE.txt",
|
||||
"static/js/2.9510b4a1.chunk.js.LICENSE.txt": "/static/js/2.9510b4a1.chunk.js.LICENSE.txt",
|
||||
"static/media/minio_console_logo.0837460e.svg": "/static/media/minio_console_logo.0837460e.svg",
|
||||
"static/media/minio_operator_logo.1312b7c9.svg": "/static/media/minio_operator_logo.1312b7c9.svg"
|
||||
},
|
||||
"entrypoints": [
|
||||
"static/js/runtime-main.f48e99e5.js",
|
||||
"static/css/2.76b14b73.chunk.css",
|
||||
"static/js/2.fa5f1dc1.chunk.js",
|
||||
"static/js/2.9510b4a1.chunk.js",
|
||||
"static/css/main.a19f3d53.chunk.css",
|
||||
"static/js/main.0e3d4f4a.chunk.js"
|
||||
"static/js/main.35167004.chunk.js"
|
||||
]
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="MinIO Console"/><link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;500;700;900&display=swap" rel="stylesheet"/><link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png"/><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"/><link rel="icon" type="image/png" sizes="96x96" href="/favicon-96x96.png"/><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"/><link rel="manifest" href="/manifest.json"/><link rel="mask-icon" href="/safari-pinned-tab.svg" color="#3a4e54"/><title>MinIO Console</title><link href="/static/css/2.76b14b73.chunk.css" rel="stylesheet"><link href="/static/css/main.a19f3d53.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,l,i=r[0],a=r[1],p=r[2],c=0,s=[];c<i.length;c++)l=i[c],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(f&&f(r);s.length;)s.shift()();return u.push.apply(u,p||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++){var a=t[i];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=l(l.s=t[0]))}return e}var n={},o={1:0},u=[];function l(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,l),t.l=!0,t.exports}l.m=e,l.c=n,l.d=function(e,r,t){l.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,r){if(1&r&&(e=l(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(l.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)l.d(t,n,function(r){return e[r]}.bind(null,n));return t},l.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(r,"a",r),r},l.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},l.p="/";var i=this["webpackJsonpportal-ui"]=this["webpackJsonpportal-ui"]||[],a=i.push.bind(i);i.push=r,i=i.slice();for(var p=0;p<i.length;p++)r(i[p]);var f=a;t()}([])</script><script src="/static/js/2.fa5f1dc1.chunk.js"></script><script src="/static/js/main.0e3d4f4a.chunk.js"></script></body></html>
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="MinIO Console"/><link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;500;700;900&display=swap" rel="stylesheet"/><link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png"/><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"/><link rel="icon" type="image/png" sizes="96x96" href="/favicon-96x96.png"/><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"/><link rel="manifest" href="/manifest.json"/><link rel="mask-icon" href="/safari-pinned-tab.svg" color="#3a4e54"/><title>MinIO Console</title><link href="/static/css/2.76b14b73.chunk.css" rel="stylesheet"><link href="/static/css/main.a19f3d53.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,l,i=r[0],a=r[1],p=r[2],c=0,s=[];c<i.length;c++)l=i[c],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(f&&f(r);s.length;)s.shift()();return u.push.apply(u,p||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++){var a=t[i];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=l(l.s=t[0]))}return e}var n={},o={1:0},u=[];function l(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,l),t.l=!0,t.exports}l.m=e,l.c=n,l.d=function(e,r,t){l.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,r){if(1&r&&(e=l(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(l.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)l.d(t,n,function(r){return e[r]}.bind(null,n));return t},l.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(r,"a",r),r},l.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},l.p="/";var i=this["webpackJsonpportal-ui"]=this["webpackJsonpportal-ui"]||[],a=i.push.bind(i);i.push=r,i=i.slice();for(var p=0;p<i.length;p++)r(i[p]);var f=a;t()}([])</script><script src="/static/js/2.9510b4a1.chunk.js"></script><script src="/static/js/main.35167004.chunk.js"></script></body></html>
|
||||
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
2
portal-ui/build/static/js/main.35167004.chunk.js
Normal file
2
portal-ui/build/static/js/main.35167004.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/main.35167004.chunk.js.map
Normal file
1
portal-ui/build/static/js/main.35167004.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
@@ -27,6 +27,7 @@ import {
|
||||
} from "@material-ui/core";
|
||||
import { Table, Column, AutoSizer, InfiniteLoader } from "react-virtualized";
|
||||
import { createStyles, withStyles } from "@material-ui/core/styles";
|
||||
import CircularProgress from "@material-ui/core/CircularProgress";
|
||||
import ViewColumnIcon from "@material-ui/icons/ViewColumn";
|
||||
import ArrowDropDownIcon from "@material-ui/icons/ArrowDropDown";
|
||||
import ArrowDropUpIcon from "@material-ui/icons/ArrowDropUp";
|
||||
@@ -45,6 +46,8 @@ interface ItemActions {
|
||||
onClick?(valueToSend: any): any;
|
||||
to?: string;
|
||||
sendOnlyId?: boolean;
|
||||
hideButtonFunction?: (itemValue: any) => boolean;
|
||||
showLoaderFunction?: (itemValue: any) => boolean;
|
||||
}
|
||||
|
||||
interface IColumns {
|
||||
@@ -267,6 +270,19 @@ const styles = () =>
|
||||
".text-right": {
|
||||
textAlign: "right",
|
||||
},
|
||||
".progress-enabled": {
|
||||
paddingTop: 3,
|
||||
display: "inline-block",
|
||||
margin: "0 10px",
|
||||
position: "relative",
|
||||
width: 18,
|
||||
height: 18,
|
||||
},
|
||||
".progress-enabled > .MuiCircularProgress-root": {
|
||||
position: "absolute",
|
||||
left: 0,
|
||||
top: 3,
|
||||
},
|
||||
},
|
||||
...checkboxIcons,
|
||||
...radioIcons,
|
||||
@@ -413,6 +429,30 @@ const elementActions = (
|
||||
return null;
|
||||
}
|
||||
|
||||
const vlSend =
|
||||
typeof valueToSend === "string" ? valueToSend : valueToSend[idField];
|
||||
|
||||
if (action.hideButtonFunction) {
|
||||
if (action.hideButtonFunction(vlSend)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (action.showLoaderFunction) {
|
||||
if (action.showLoaderFunction(vlSend)) {
|
||||
return (
|
||||
<div className={"progress-enabled"}>
|
||||
<CircularProgress
|
||||
color="primary"
|
||||
size={18}
|
||||
variant="indeterminate"
|
||||
key={`actions-loader-${action.type}-${index.toString()}`}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<TableActionButton
|
||||
type={action.type}
|
||||
|
||||
@@ -174,6 +174,8 @@ const Menu = ({ userLoggedIn, classes, pages, operatorMode }: IMenuProps) => {
|
||||
const deleteSession = () => {
|
||||
clearSession();
|
||||
userLoggedIn(false);
|
||||
localStorage.setItem("userLoggedIn", "");
|
||||
|
||||
history.push("/login");
|
||||
};
|
||||
api
|
||||
|
||||
@@ -168,10 +168,16 @@ const Users = ({ classes, setErrorSnackMessage }: IUsersProps) => {
|
||||
setSelectedUser(selectionElement);
|
||||
};
|
||||
|
||||
const userLoggedIn = atob(localStorage.getItem("userLoggedIn") || "");
|
||||
|
||||
const tableActions = [
|
||||
{ type: "view", onClick: viewAction },
|
||||
{ type: "description", onClick: setPolicyAction },
|
||||
{ type: "delete", onClick: deleteAction },
|
||||
{
|
||||
type: "delete",
|
||||
onClick: deleteAction,
|
||||
hideButtonFunction: (topValue: any) => topValue === userLoggedIn,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
|
||||
@@ -242,6 +242,10 @@ const Login = ({ classes, userLoggedIn }: ILoginProps) => {
|
||||
.then(() => {
|
||||
// We set the state in redux
|
||||
userLoggedIn(true);
|
||||
if (loginStrategy.loginStrategy === loginStrategyType.form) {
|
||||
localStorage.setItem("userLoggedIn", btoa(accessKey));
|
||||
}
|
||||
|
||||
history.push("/");
|
||||
})
|
||||
.catch((err) => {
|
||||
|
||||
@@ -197,6 +197,10 @@ func getRemoveUserResponse(session *models.Principal, params admin_api.RemoveUse
|
||||
return prepareError(err)
|
||||
}
|
||||
|
||||
if session.AccountAccessKey == params.Name {
|
||||
return prepareError(errAvoidSelfAccountDelete)
|
||||
}
|
||||
|
||||
// create a minioClient interface implementation
|
||||
// defining the client to be used
|
||||
adminClient := adminClient{client: mAdmin}
|
||||
|
||||
@@ -34,6 +34,7 @@ var (
|
||||
errChangePassword = errors.New("unable to update password, please check your current password")
|
||||
errInvalidLicense = errors.New("invalid license key")
|
||||
errLicenseNotFound = errors.New("license not found")
|
||||
errAvoidSelfAccountDelete = errors.New("logged in user cannot be deleted by itself")
|
||||
)
|
||||
|
||||
// prepareError receives an error object and parse it against k8sErrors, returns the right error code paired with a generic error message
|
||||
@@ -105,6 +106,10 @@ func prepareError(err ...error) *models.Error {
|
||||
errorCode = 404
|
||||
errorMessage = errInvalidLicense.Error()
|
||||
}
|
||||
if errors.Is(err[0], errAvoidSelfAccountDelete) {
|
||||
errorCode = 403
|
||||
errorMessage = errAvoidSelfAccountDelete.Error()
|
||||
}
|
||||
if madmin.ToErrorResponse(err[0]).Code == "InvalidAccessKeyId" {
|
||||
errorCode = 401
|
||||
errorMessage = errorGenericInvalidSession.Error()
|
||||
|
||||
Reference in New Issue
Block a user