From 14d9b8002909dacbb377294249850859e7651313 Mon Sep 17 00:00:00 2001 From: Misha Bragin Date: Tue, 15 Aug 2023 22:36:21 +0200 Subject: [PATCH] Limit UI view for the "user" role (#259) --- src/components/Navbar.tsx | 1 + src/components/UserEdit.tsx | 5 +- src/index.css | 4 + src/store/peer/sagas.ts | 343 ++++++++++++++++++++++-------------- src/views/Peers.tsx | 155 ++++++++-------- 5 files changed, 296 insertions(+), 212 deletions(-) diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 36ee0ba2..d96bf7bd 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -53,6 +53,7 @@ const Navbar = () => { "/acls", "/routes", "/dns", + "/users", "/activity", "/settings", ]; diff --git a/src/components/UserEdit.tsx b/src/components/UserEdit.tsx index a1fc0dd0..f17f4bb5 100644 --- a/src/components/UserEdit.tsx +++ b/src/components/UserEdit.tsx @@ -166,6 +166,7 @@ const UserEdit = (props: any) => { dispatch(userActions.setUser(null as unknown as User)); dispatch(personalAccessTokenActions.resetPersonalAccessTokens(null)); dispatch(userActions.setUserTabOpen(key)); + dispatch(userActions.setEditUserPopupVisible(false)); }; const selectValidator = (_: RuleObject, value: string[]) => { @@ -331,7 +332,7 @@ const UserEdit = (props: any) => { // menu: { items: menuItems }, }, { - title: user.name, + title: user?.name, }, ]} /> @@ -386,7 +387,7 @@ const UserEdit = (props: any) => { style={{ marginRight: "70px", fontWeight: "500" }} > ): Generator { +import { actions as groupActions } from "../group"; +import userService from "../user/service"; +export function* getPeers( + action: ReturnType +): Generator { try { + yield put( + actions.setDeletePeer({ + loading: false, + success: false, + failure: false, + error: null, + data: null, + } as DeleteResponse) + ); - yield put(actions.setDeletePeer({ - loading: false, - success: false, - failure: false, - error: null, - data: null - } as DeleteResponse)) - + const users: any = yield call(userService.getUsers, action.payload); + let currentUser = users.body.find((user: any) => user.is_current); const effect = yield call(service.getPeers, action.payload); const response = effect as ApiResponse; - yield put(actions.getPeers.success(response.body)); + let peersBody: any; + if (currentUser.role === "user") { + peersBody = response.body.filter((pe) => { + return pe.user_id === currentUser.id; + }); + } else { + peersBody = response.body; + } + yield put(actions.getPeers.success(peersBody)); } catch (err) { yield put(actions.getPeers.failure(err as ApiError)); } } -export function* setDeletePeer(action: ReturnType): Generator { - yield put(actions.setDeletePeer(action.payload)) +export function* setDeletePeer( + action: ReturnType +): Generator { + yield put(actions.setDeletePeer(action.payload)); } -export function* deletePeer(action: ReturnType): Generator { +export function* deletePeer( + action: ReturnType +): Generator { try { - yield call(actions.setDeletePeer,{ + yield call(actions.setDeletePeer, { loading: true, success: false, failure: false, error: null, - data: null - } as DeleteResponse) + data: null, + } as DeleteResponse); const effect = yield call(service.deletedPeer, action.payload); const response = effect as ApiResponse; - yield put(actions.deletedPeer.success({ - loading: false, - success: true, - failure: false, - error: null, - data: response.body - } as DeleteResponse)); + yield put( + actions.deletedPeer.success({ + loading: false, + success: true, + failure: false, + error: null, + data: response.body, + } as DeleteResponse) + ); - const peers = (yield select(state => state.peer.data)) as Peer[] - yield put(actions.getPeers.success(peers.filter((p:Peer) => p.id !== action.payload.payload))) + const peers = (yield select((state) => state.peer.data)) as Peer[]; + yield put( + actions.getPeers.success( + peers.filter((p: Peer) => p.id !== action.payload.payload) + ) + ); } catch (err) { - yield put(actions.deletedPeer.failure({ - loading: false, - success: false, - failure: false, - error: err as ApiError, - data: null - } as DeleteResponse)); + yield put( + actions.deletedPeer.failure({ + loading: false, + success: false, + failure: false, + error: err as ApiError, + data: null, + } as DeleteResponse) + ); } } -export function* saveGroups(action: ReturnType): Generator { +export function* saveGroups( + action: ReturnType +): Generator { try { - yield put(actions.setSavedGroups({ - loading: true, - success: false, - failure: false, - error: null, - data: null - })) + yield put( + actions.setSavedGroups({ + loading: true, + success: false, + failure: false, + error: null, + data: null, + }) + ); - const currentGroups = [...(yield select(state => state.group.data)) as Group[]] + const currentGroups = [ + ...((yield select((state) => state.group.data)) as Group[]), + ]; - const peerGroupsToSave = action.payload.payload + const peerGroupsToSave = action.payload.payload; - let groupsToSave = [] as Group[] - let groupsNoId = [] as Group[] + let groupsToSave = [] as Group[]; + let groupsNoId = [] as Group[]; groupsToSave = groupsToSave.concat( - currentGroups - .filter(g => peerGroupsToSave.groupsToRemove.includes(g.id || '')) - .map(g => ({ - id: g.id, - name: g.name, - peers: (g.peers as GroupPeer[]).filter(p => p.id !== peerGroupsToSave.ID).map(p => p.id) as string[] - })) - ) + currentGroups + .filter((g) => peerGroupsToSave.groupsToRemove.includes(g.id || "")) + .map((g) => ({ + id: g.id, + name: g.name, + peers: (g.peers as GroupPeer[]) + .filter((p) => p.id !== peerGroupsToSave.ID) + .map((p) => p.id) as string[], + })) + ); groupsToSave = groupsToSave.concat( - currentGroups - .filter(g => peerGroupsToSave.groupsToAdd.includes(g.id || '')) - .map(g => ({ - id: g.id, - name: g.name, - Peers: g.peers ? [...(g.peers as GroupPeer[]).map((p:GroupPeer) => p.id), peerGroupsToSave.ID] : [peerGroupsToSave.ID] - })) - ) - - groupsNoId = peerGroupsToSave.groupsNoId.map(g => ({ + currentGroups + .filter((g) => peerGroupsToSave.groupsToAdd.includes(g.id || "")) + .map((g) => ({ + id: g.id, + name: g.name, + Peers: g.peers + ? [ + ...(g.peers as GroupPeer[]).map((p: GroupPeer) => p.id), + peerGroupsToSave.ID, + ] + : [peerGroupsToSave.ID], + })) + ); + + groupsNoId = peerGroupsToSave.groupsNoId.map((g) => ({ name: g, - peers: [peerGroupsToSave.ID] - })) + peers: [peerGroupsToSave.ID], + })); if (!groupsNoId.length && !groupsToSave.length) { - return + return; } - const responsesGroup = yield all(groupsToSave.map(g => call(serviceGroup.editGroup, { - getAccessTokenSilently: action.payload.getAccessTokenSilently, - payload: g - }) - )) - - const responsesGroupNoId = yield all(groupsNoId.map(g => call(serviceGroup.createGroup, { - getAccessTokenSilently: action.payload.getAccessTokenSilently, - payload: g - }) - )) - - yield put(actions.saveGroups.success({ - loading: false, - success: true, - failure: false, - error: null, - data: [...(responsesGroup as ApiResponse[]).map(r => r.body), ...(responsesGroupNoId as ApiResponse[]).map(r => r.body)] - } as CreateResponse)) + const responsesGroup = yield all( + groupsToSave.map((g) => + call(serviceGroup.editGroup, { + getAccessTokenSilently: action.payload.getAccessTokenSilently, + payload: g, + }) + ) + ); + + const responsesGroupNoId = yield all( + groupsNoId.map((g) => + call(serviceGroup.createGroup, { + getAccessTokenSilently: action.payload.getAccessTokenSilently, + payload: g, + }) + ) + ); - yield put(groupActions.getGroups.request({ getAccessTokenSilently: action.payload.getAccessTokenSilently, payload: null })); - yield put(actions.getPeers.request({ getAccessTokenSilently: action.payload.getAccessTokenSilently, payload: null })); + yield put( + actions.saveGroups.success({ + loading: false, + success: true, + failure: false, + error: null, + data: [ + ...(responsesGroup as ApiResponse[]).map((r) => r.body), + ...(responsesGroupNoId as ApiResponse[]).map((r) => r.body), + ], + } as CreateResponse) + ); + yield put( + groupActions.getGroups.request({ + getAccessTokenSilently: action.payload.getAccessTokenSilently, + payload: null, + }) + ); + yield put( + actions.getPeers.request({ + getAccessTokenSilently: action.payload.getAccessTokenSilently, + payload: null, + }) + ); } catch (err) { - console.log(err) - yield put(actions.saveGroups.failure({ - loading: false, - success: false, - failure: true, - error: err as ApiError, - data: null - } as ChangeResponse)); + console.log(err); + yield put( + actions.saveGroups.failure({ + loading: false, + success: false, + failure: true, + error: err as ApiError, + data: null, + } as ChangeResponse) + ); } } -export function* updatePeer(action: ReturnType): Generator { +export function* updatePeer( + action: ReturnType +): Generator { try { - yield put(actions.setUpdatedPeer({ - loading: true, - success: false, - failure: false, - error: null, - data: null - })) + yield put( + actions.setUpdatedPeer({ + loading: true, + success: false, + failure: false, + error: null, + data: null, + }) + ); - const peer = action.payload.payload - const peerId = peer.id + const peer = action.payload.payload; + const peerId = peer.id; const payloadToSave = { getAccessTokenSilently: action.payload.getAccessTokenSilently, - payload: peer - } + payload: peer, + }; - const effect = yield call(service.updatePeer, payloadToSave) + const effect = yield call(service.updatePeer, payloadToSave); const response = effect as ApiResponse; - yield put(actions.updatePeer.success({ - loading: false, - success: true, - failure: false, - error: null, - data: response.body - } as ChangeResponse)); - - const peers = (yield select(state => state.peer.data)) as Peer[] - yield put(actions.getPeers.success(peers.filter((p:Peer) => p.id !== peerId).concat(response.body))) + yield put( + actions.updatePeer.success({ + loading: false, + success: true, + failure: false, + error: null, + data: response.body, + } as ChangeResponse) + ); + const peers = (yield select((state) => state.peer.data)) as Peer[]; + yield put( + actions.getPeers.success( + peers.filter((p: Peer) => p.id !== peerId).concat(response.body) + ) + ); } catch (err) { - console.log(err) - yield put(actions.updatePeer.failure({ - loading: false, - success: false, - failure: true, - error: err as ApiError, - data: null - } as ChangeResponse)); + console.log(err); + yield put( + actions.updatePeer.failure({ + loading: false, + success: false, + failure: true, + error: err as ApiError, + data: null, + } as ChangeResponse) + ); } } @@ -201,7 +271,6 @@ export default function* sagas(): Generator { takeLatest(actions.getPeers.request, getPeers), takeLatest(actions.deletedPeer.request, deletePeer), takeLatest(actions.saveGroups.request, saveGroups), - takeLatest(actions.updatePeer.request, updatePeer) + takeLatest(actions.updatePeer.request, updatePeer), ]); } - diff --git a/src/views/Peers.tsx b/src/views/Peers.tsx index a8046c49..8bdbf17c 100644 --- a/src/views/Peers.tsx +++ b/src/views/Peers.tsx @@ -434,6 +434,7 @@ export const Peers = () => { }; const setUpdateGroupsVisible = (peerToAction: Peer, status: boolean) => { + if (!isAdmin) return; if (status) { dispatch(peerActions.setPeer({ ...peerToAction })); dispatch(peerActions.setUpdateGroupsVisible(true)); @@ -502,10 +503,7 @@ export const Peers = () => { open={groupPopupVisible === peerToAction.key} title={null} > - @@ -592,6 +590,7 @@ export const Peers = () => { type="text" style={{ height: "auto", whiteSpace: "normal", textAlign: "left" }} onClick={() => setUpdateGroupsVisible(peer, true)} + className={!isAdmin ? "nohover" : ""} > @@ -607,6 +606,7 @@ export const Peers = () => {