feat: enforce user roles
enforces user admin role requirement for - creating / deleting / setting role for organization users - creating / deleting / setting role for project users - updating project name - deleting project hides action elements based on role for - admin console - team settings if team is only visible through project membership - add project tile if not team admin - project name text editor if not team / project admin - add redirect from team page if settings only visible through project membership - add redirect from admin console if not org admin role enforcement is handled on the api side through a custom GraphQL directive `hasRole`. on the client side, role information is fetched in the TopNavbar's `me` query and stored in the `UserContext`. there is a custom hook, `useCurrentUser`, that provides a user object with two functions, `isVisibile` & `isAdmin` which is used to check roles in order to render/hide relevant UI elements.
This commit is contained in:
committed by
Jordan Knott
parent
5dbdc20b36
commit
e64f6f8569
@@ -15,7 +15,6 @@ import {
|
||||
Redirect,
|
||||
} from 'react-router-dom';
|
||||
import {
|
||||
useSetProjectOwnerMutation,
|
||||
useUpdateProjectMemberRoleMutation,
|
||||
useCreateProjectMemberMutation,
|
||||
useDeleteProjectMemberMutation,
|
||||
@@ -34,10 +33,10 @@ import {
|
||||
} from 'shared/generated/graphql';
|
||||
|
||||
import produce from 'immer';
|
||||
import UserIDContext from 'App/context';
|
||||
import UserContext, { useCurrentUser } from 'App/context';
|
||||
import Input from 'shared/components/Input';
|
||||
import Member from 'shared/components/Member';
|
||||
import Board from './Board';
|
||||
import Board, { BoardLoading } from './Board';
|
||||
import Details from './Details';
|
||||
import EmptyBoard from 'shared/components/EmptyBoard';
|
||||
|
||||
@@ -140,7 +139,7 @@ const Project = () => {
|
||||
const [updateTaskName] = useUpdateTaskNameMutation();
|
||||
|
||||
const { loading, data } = useFindProjectQuery({
|
||||
variables: { projectId: projectID },
|
||||
variables: { projectID },
|
||||
});
|
||||
|
||||
const [updateProjectName] = useUpdateProjectNameMutation({
|
||||
@@ -152,7 +151,7 @@ const Project = () => {
|
||||
produce(cache, draftCache => {
|
||||
draftCache.findProject.name = newName.data.updateProjectName.name;
|
||||
}),
|
||||
{ projectId: projectID },
|
||||
{ projectID },
|
||||
);
|
||||
},
|
||||
});
|
||||
@@ -166,11 +165,10 @@ const Project = () => {
|
||||
produce(cache, draftCache => {
|
||||
draftCache.findProject.members.push({ ...response.data.createProjectMember.member });
|
||||
}),
|
||||
{ projectId: projectID },
|
||||
{ projectID },
|
||||
);
|
||||
},
|
||||
});
|
||||
const [setProjectOwner] = useSetProjectOwnerMutation();
|
||||
const [deleteProjectMember] = useDeleteProjectMemberMutation({
|
||||
update: (client, response) => {
|
||||
updateApolloCache<FindProjectQuery>(
|
||||
@@ -184,12 +182,12 @@ const Project = () => {
|
||||
m => m.id !== response.data.deleteProjectMember.member.id,
|
||||
);
|
||||
}),
|
||||
{ projectId: projectID },
|
||||
{ projectID },
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const { userID } = useContext(UserIDContext);
|
||||
const { user } = useCurrentUser();
|
||||
const location = useLocation();
|
||||
|
||||
const { showPopup, hidePopup } = usePopup();
|
||||
@@ -205,7 +203,7 @@ const Project = () => {
|
||||
return (
|
||||
<>
|
||||
<GlobalTopNavbar onSaveProjectName={projectName => {}} name="" projectID={null} />
|
||||
<Board loading />
|
||||
<BoardLoading />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -221,7 +219,6 @@ const Project = () => {
|
||||
updateProjectMemberRole({ variables: { userID, roleCode, projectID } });
|
||||
}}
|
||||
onChangeProjectOwner={uid => {
|
||||
setProjectOwner({ variables: { ownerID: uid, projectID } });
|
||||
hidePopup();
|
||||
}}
|
||||
onRemoveFromBoard={userID => {
|
||||
@@ -248,6 +245,7 @@ const Project = () => {
|
||||
currentTab={0}
|
||||
projectMembers={data.findProject.members}
|
||||
projectID={projectID}
|
||||
teamID={data.findProject.team.id}
|
||||
name={data.findProject.name}
|
||||
/>
|
||||
<Route path={`${match.path}`} exact render={() => <Redirect to={`${match.url}/board`} />} />
|
||||
|
||||
Reference in New Issue
Block a user