diff --git a/webui/src/App.js b/webui/src/App.js
index bf7c026..9d8d242 100755
--- a/webui/src/App.js
+++ b/webui/src/App.js
@@ -5,18 +5,12 @@ import LoginForm from "./Components/Forms/LoginForm";
import {Container} from "reactstrap";
import {BrowserRouter} from "react-router-dom";
import {Route} from "react-router";
-import {setGlobal} from "reactn";
import useAuth from "./Hooks/auth";
import IndexPage from "./Components/Pages/IndexPage";
import GroupPage from "./Components/Pages/GroupPage";
import Loading from "./Components/Loading";
import LightPage from "./Components/Pages/LightPage";
-setGlobal({
- "auth/login": false,
- "auth/checked": false,
-});
-
export default function App() {
const [hasStarted, setHasStarted] = useState(false);
const {isLoggedIn, isChecked, verify} = useAuth();
diff --git a/webui/src/Components/Group.jsx b/webui/src/Components/Group.jsx
index a080833..554b0a0 100644
--- a/webui/src/Components/Group.jsx
+++ b/webui/src/Components/Group.jsx
@@ -6,10 +6,15 @@ import Loading from "./Loading";
import {deleteGroup} from "../Helpers/groups";
import ColorModal from "./Modals/ColorModal";
import {changeColor} from "../Helpers/lights";
+import GroupPropertiesModal from "./Modals/GroupPropertiesModal";
+import useAuth from "../Hooks/auth";
-function Group({id, name}) {
+function Group({id, name, permissions}) {
+ const {user} = useAuth();
const lights = useLights({groupId: id});
- const [colorModal, setColorModal] = useState("");
+
+ const [colorModal, setColorModal] = useState(false);
+ const [propModal, setPropModal] = useState(false);
const ready = lights !== null;
const noLights = ready && lights.length === 0;
@@ -34,6 +39,14 @@ function Group({id, name}) {
pValue = lights[0].on;
}
+ function iCan(name) {
+ const perm = permissions.find(p => p.userId === user.id);
+
+ return typeof perm !== "undefined"
+ ? perm[name]
+ : false;
+ }
+
return (
{name}
@@ -42,15 +55,21 @@ function Group({id, name}) {
? {lights.map(light => )}
: }
-
-
+ {(iCan("manage") || iCan("write") || iCan("delete")) && (
+
+ {iCan("manage") && (
+
+ )}
{" "}
- {hasLights && (
+ {hasLights && iCan("write") && (
)}
{" "}
- {id > 0 && }
-
+ {iCan("delete") && (id > 0) && (
+
+ )}
+
+ )}
{colorModal && (
setColorModal(false)}
/>
)}
+ {propModal && (
+ setPropModal(false)}
+ />
+ )}
);
}
diff --git a/webui/src/Components/Modals/GroupAddModal.jsx b/webui/src/Components/Modals/GroupAddModal.jsx
index dffcd93..d2c5d26 100644
--- a/webui/src/Components/Modals/GroupAddModal.jsx
+++ b/webui/src/Components/Modals/GroupAddModal.jsx
@@ -1,5 +1,5 @@
import React, {useState} from "react";
-import {Button, Form, FormGroup, Input, Label, Modal, ModalBody, ModalFooter, ModalHeader} from "reactstrap";
+import {Button, Col, Form, FormGroup, Input, Label, Modal, ModalBody, ModalFooter, ModalHeader} from "reactstrap";
import {addGroup} from "../../Helpers/groups";
function GroupAddModal({onClose}) {
@@ -10,15 +10,17 @@ function GroupAddModal({onClose}) {
Ny gruppe
diff --git a/webui/src/Components/Modals/GroupPropertiesModal.jsx b/webui/src/Components/Modals/GroupPropertiesModal.jsx
new file mode 100644
index 0000000..eabfea6
--- /dev/null
+++ b/webui/src/Components/Modals/GroupPropertiesModal.jsx
@@ -0,0 +1,101 @@
+import React, {useState} from "react";
+import useAuth from "../../Hooks/auth";
+import {
+ Button,
+ Col,
+ Form,
+ FormGroup,
+ Input,
+ InputGroup,
+ InputGroupAddon,
+ Label,
+ Modal,
+ ModalBody,
+ ModalFooter,
+ ModalHeader,
+ Row
+} from "reactstrap";
+import PermissionsModal from "./PermissionsModal";
+
+function GroupPropertiesModal({id, nValue, permissions, onClose}) {
+ const {users} = useAuth();
+ const [name, setName] = useState(nValue);
+ const [permUserId, setPermUserId] = useState(null);
+ const [permModal, setPermModal] = useState(false);
+
+ function permissionFor(userId) {
+ const perm = permissions.find(p => p.userId === userId);
+
+ return typeof perm !== "undefined"
+ ? perm
+ : null;
+ }
+
+ return (
+
+ Endre gruppe
+
+
+
+
+
+ {" "}
+
+
+ {permModal && (
+ setPermModal(false)}
+ />
+ )}
+
+ );
+}
+
+export default GroupPropertiesModal;
diff --git a/webui/src/Components/Modals/LightPropertiesModal.jsx b/webui/src/Components/Modals/LightPropertiesModal.jsx
index 0b0700a..27594a3 100644
--- a/webui/src/Components/Modals/LightPropertiesModal.jsx
+++ b/webui/src/Components/Modals/LightPropertiesModal.jsx
@@ -1,6 +1,5 @@
import React, {useState} from "react";
-import {Button, Form, FormGroup, Input, Label, Modal, ModalBody, ModalFooter, ModalHeader} from "reactstrap";
-import {addGroup} from "../../Helpers/groups";
+import {Button, Col, Form, FormGroup, Input, Label, Modal, ModalBody, ModalFooter, ModalHeader} from "reactstrap";
import useGroups from "../../Hooks/group";
import Loading from "../Loading";
import {changeLight} from "../../Helpers/lights";
@@ -18,27 +17,31 @@ function LightPropertiesModal({id, gValue, nValue, onClose}) {
Lysegenskaper
diff --git a/webui/src/Components/Modals/PermissionsModal.jsx b/webui/src/Components/Modals/PermissionsModal.jsx
new file mode 100644
index 0000000..ffc73ee
--- /dev/null
+++ b/webui/src/Components/Modals/PermissionsModal.jsx
@@ -0,0 +1,84 @@
+import React, {useState} from "react";
+import {Button, CustomInput, FormGroup, Modal, ModalBody, ModalFooter, ModalHeader} from "reactstrap";
+import {savePermissions} from "../../Helpers/groups";
+
+function PermissionsModal({groupId, userId, permissions, onClose}) {
+ function getPermission(type) {
+ if (permissions === null || typeof permissions[type] === "undefined") {
+ return false;
+ }
+
+ return permissions[type];
+ }
+
+ const [read, setRead] = useState(getPermission("read"));
+ const [write, setWrite] = useState(getPermission("write"));
+ const [create, setCreate] = useState(getPermission("create"));
+ const [remove, setRemove] = useState(getPermission("delete"));
+ const manage = getPermission("manage");
+
+ return (
+
+ Endre gruppe
+
+
+ setRead(e.target.checked)}/>
+
+
+ setWrite(e.target.checked)}/>
+
+
+ setCreate(e.target.checked)}/>
+
+
+ setRemove(e.target.checked)}/>
+
+
+
+
+
+
+
+ {" "}
+
+
+
+ );
+}
+
+export default PermissionsModal;
diff --git a/webui/src/Helpers/groups.js b/webui/src/Helpers/groups.js
index f84ed12..088ee53 100644
--- a/webui/src/Helpers/groups.js
+++ b/webui/src/Helpers/groups.js
@@ -1,6 +1,6 @@
import {randId} from "./random";
-import {fetchDelete, fetchGet, fetchPost} from "./fetcher";
-import {notNullish, nullish} from "./null";
+import {fetchDelete, fetchGet, fetchPatch, fetchPost} from "./fetcher";
+import {nullish} from "./null";
const localData = {};
const callbacks = [];
@@ -42,6 +42,14 @@ export function deleteGroup(groupId) {
});
}
+export function savePermissions(groupId, userId, permissions) {
+ fetchPatch(`/group/${groupId}/permission/${userId}`, permissions).then(({data, error}) => {
+ if (error === null) {
+ fetchAll();
+ }
+ });
+}
+
function fetchAll() {
fetchGet("/group/").then(({data, error}) => {
if (error === null) {
diff --git a/webui/src/Hooks/auth.js b/webui/src/Hooks/auth.js
index 3f2de6a..f9b18d8 100644
--- a/webui/src/Hooks/auth.js
+++ b/webui/src/Hooks/auth.js
@@ -1,15 +1,40 @@
-import {useGlobal} from "reactn";
+import {setGlobal, useGlobal} from "reactn";
import {fetchGet, fetchPost} from "../Helpers/fetcher";
+setGlobal({
+ "auth/login": false,
+ "auth/checked": false,
+ "auth/users/me": null,
+ "auth/users/all": [],
+});
+
export default function useAuth() {
const [isLoggedIn, setIsLoggedIn] = useGlobal("auth/login");
const [isChecked, setIsChecked] = useGlobal("auth/checked");
+ const [user, setUser] = useGlobal("auth/users/me");
+ const [users, setUsers] = useGlobal("auth/users/all");
+
+ function fetchUsers() {
+ fetchGet("/user/").then(({data, error}) => {
+ if (error === null) {
+ setUsers(data);
+ }
+ });
+ }
function verify() {
setIsChecked(false);
fetchGet("/user/session").then(({data, error}) => {
- setIsLoggedIn(error === null && data.loggedIn);
+ const validSession = error === null && data.loggedIn;
+
+ setIsLoggedIn(validSession);
+
+ if (validSession) {
+ setUser(data.user);
+ fetchUsers();
+ }
+
setIsChecked(true);
})
}
@@ -26,6 +51,8 @@ export default function useAuth() {
}
setIsLoggedIn(true);
+ setIsLoggedIn(data);
+ fetchUsers();
});
}
@@ -60,5 +87,5 @@ export default function useAuth() {
})
}
- return {isLoggedIn, isChecked, verify, login, logout, register};
+ return {isLoggedIn, isChecked, user, users, verify, login, logout, register};
}