diff --git a/Core/API/Parameter/ArrayType.class.php b/Core/API/Parameter/ArrayType.class.php
index 133ca4f..d55b154 100644
--- a/Core/API/Parameter/ArrayType.class.php
+++ b/Core/API/Parameter/ArrayType.class.php
@@ -24,7 +24,7 @@ class ArrayType extends Parameter {
}
public function parseParam($value): bool {
- if(!is_array($value)) {
+ if (!is_array($value)) {
if (!$this->canBeOne) {
return false;
} else {
diff --git a/Core/API/Request.class.php b/Core/API/Request.class.php
index a4ba499..2f1b0a6 100644
--- a/Core/API/Request.class.php
+++ b/Core/API/Request.class.php
@@ -93,7 +93,7 @@ abstract class Request {
foreach ($structure as $name => $param) {
$value = $values[$name] ?? NULL;
- $isEmpty = (is_string($value) && strlen($value) === 0) || (is_array($value) && empty($value));
+ $isEmpty = is_string($value) && strlen($value) === 0;
if (!$param->optional && (is_null($value) || $isEmpty)) {
return $this->createError("Missing parameter: $name");
}
diff --git a/react/admin-panel/src/views/access-control-list.js b/react/admin-panel/src/views/access-control-list.js
index 4205004..bf20f64 100644
--- a/react/admin-panel/src/views/access-control-list.js
+++ b/react/admin-panel/src/views/access-control-list.js
@@ -1,9 +1,23 @@
import {useCallback, useContext, useEffect, useState} from "react";
import {LocaleContext} from "shared/locale";
import {Link, useNavigate} from "react-router-dom";
-import {Button, Checkbox, TextField, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow} from "@material-ui/core";
-import {Add, Refresh} from "@material-ui/icons";
+import {
+ Button,
+ Checkbox,
+ TextField,
+ Paper,
+ Table,
+ TableBody,
+ TableCell,
+ TableContainer,
+ TableHead,
+ TableRow,
+ IconButton
+} from "@material-ui/core";
+import {Add, Delete, Edit, Refresh} from "@material-ui/icons";
import {USER_GROUP_ADMIN} from "shared/constants";
+import Dialog from "shared/elements/dialog";
+import {TableFooter} from "@mui/material";
export default function AccessControlList(props) {
@@ -20,6 +34,9 @@ export default function AccessControlList(props) {
// filters
const [query, setQuery] = useState("");
+ // view
+ const [dialogData, setDialogData] = useState({open: false});
+
const onFetchACL = useCallback((force = false) => {
if (force || fetchACL) {
setFetchACL(false);
@@ -84,8 +101,33 @@ export default function AccessControlList(props) {
}
}, [acl]);
+ const onDeletePermission = useCallback(method => {
+ props.api.deletePermission(method).then(data => {
+ if (data.success) {
+ let newACL = acl.filter(acl => acl.method.toLowerCase() !== method.toLowerCase());
+ setACL(newACL);
+ } else {
+ props.showDialog("Error deleting permission: " + data.msg);
+ }
+ })
+ }, [acl]);
+
+ const onUpdatePermission = useCallback((inputData, groups) => {
+ props.api.updatePermission(inputData.method, groups, inputData.description).then(data => {
+ if (data.success) {
+ let newACL = acl.filter(acl => acl.method.toLowerCase() !== inputData.method.toLowerCase());
+ newACL.push({method: inputData.method, groups: groups, description: inputData.description});
+ newACL = newACL.sort((a, b) => a.method.localeCompare(b.method))
+ setACL(newACL);
+ } else {
+ props.showDialog("Error updating permission: " + data.msg);
+ }
+ })
+ }, [acl]);
+
const isRestricted = (method) => {
- return ["permissions/update", "permissions/delete"].includes(method.toLowerCase());
+ return ["permissions/update", "permissions/delete"].includes(method.toLowerCase()) &&
+ !props.api.hasGroup(USER_GROUP_ADMIN);
}
const PermissionList = () => {
@@ -104,13 +146,44 @@ export default function AccessControlList(props) {
rows.push(
- {permission.description}
+
+ {permission.description}
+