[WEB-2589] Chore: inbox issue permissions (#5763)
* chore: changed permission in inbox issue * chore: fixed permissions for intake * fix: refactoring * fix: lint --------- Co-authored-by: NarayanBavisetti <narayan3119@gmail.com>
This commit is contained in:
parent
992adb9794
commit
45880b3a72
6 changed files with 99 additions and 16 deletions
|
|
@ -285,7 +285,7 @@ class InboxIssueAPIEndpoint(BaseAPIView):
|
|||
)
|
||||
|
||||
# Only project admins and members can edit inbox issue attributes
|
||||
if project_member.role > 5:
|
||||
if project_member.role > 15:
|
||||
serializer = InboxIssueSerializer(
|
||||
inbox_issue, data=request.data, partial=True
|
||||
)
|
||||
|
|
|
|||
|
|
@ -323,7 +323,7 @@ class InboxIssueViewSet(BaseViewSet):
|
|||
serializer.errors, status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
|
||||
@allow_permission(allowed_roles=[ROLE.ADMIN], creator=True, model=Issue)
|
||||
def partial_update(self, request, slug, project_id, pk):
|
||||
inbox_id = Inbox.objects.filter(
|
||||
workspace__slug=slug, project_id=project_id
|
||||
|
|
@ -418,7 +418,7 @@ class InboxIssueViewSet(BaseViewSet):
|
|||
)
|
||||
|
||||
# Only project admins and members can edit inbox issue attributes
|
||||
if project_member.role > 5:
|
||||
if project_member.role > 15:
|
||||
serializer = InboxIssueSerializer(
|
||||
inbox_issue, data=request.data, partial=True
|
||||
)
|
||||
|
|
|
|||
|
|
@ -89,6 +89,12 @@ export const InboxIssueActionsHeader: FC<TInboxIssueActionsHeader> = observer((p
|
|||
const canDelete =
|
||||
allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.PROJECT, workspaceSlug, projectId) ||
|
||||
issue?.created_by === currentUser?.id;
|
||||
const isProjectAdmin = allowPermissions(
|
||||
[EUserPermissions.ADMIN],
|
||||
EUserPermissionsLevel.PROJECT,
|
||||
workspaceSlug,
|
||||
projectId
|
||||
);
|
||||
const isAcceptedOrDeclined = inboxIssue?.status ? [-1, 1, 2].includes(inboxIssue.status) : undefined;
|
||||
// days left for snooze
|
||||
const numberOfDaysLeft = findHowManyDaysLeft(inboxIssue?.snoozed_till);
|
||||
|
|
@ -199,6 +205,17 @@ export const InboxIssueActionsHeader: FC<TInboxIssueActionsHeader> = observer((p
|
|||
[handleInboxIssueNavigation]
|
||||
);
|
||||
|
||||
const handleActionWithPermission = (isAdmin: boolean, action: () => void, errorMessage: string) => {
|
||||
if (isAdmin) action();
|
||||
else {
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Permission denied",
|
||||
message: errorMessage,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!isNotificationEmbed) document.addEventListener("keydown", onKeyDown);
|
||||
return () => {
|
||||
|
|
@ -293,7 +310,13 @@ export const InboxIssueActionsHeader: FC<TInboxIssueActionsHeader> = observer((p
|
|||
size="sm"
|
||||
prependIcon={<CircleCheck className="w-3 h-3" />}
|
||||
className="text-green-500 border-0.5 border-green-500 bg-green-500/20 focus:bg-green-500/20 focus:text-green-500 hover:bg-green-500/40 bg-opacity-20"
|
||||
onClick={() => setAcceptIssueModal(true)}
|
||||
onClick={() =>
|
||||
handleActionWithPermission(
|
||||
isProjectAdmin,
|
||||
() => setAcceptIssueModal(true),
|
||||
"Only project admins can accept issues"
|
||||
)
|
||||
}
|
||||
>
|
||||
Accept
|
||||
</Button>
|
||||
|
|
@ -307,7 +330,13 @@ export const InboxIssueActionsHeader: FC<TInboxIssueActionsHeader> = observer((p
|
|||
size="sm"
|
||||
prependIcon={<CircleX className="w-3 h-3" />}
|
||||
className="text-red-500 border-0.5 border-red-500 bg-red-500/20 focus:bg-red-500/20 focus:text-red-500 hover:bg-red-500/40 bg-opacity-20"
|
||||
onClick={() => setDeclineIssueModal(true)}
|
||||
onClick={() =>
|
||||
handleActionWithPermission(
|
||||
isProjectAdmin,
|
||||
() => setDeclineIssueModal(true),
|
||||
"Only project admins can deny issues"
|
||||
)
|
||||
}
|
||||
>
|
||||
Decline
|
||||
</Button>
|
||||
|
|
@ -341,7 +370,15 @@ export const InboxIssueActionsHeader: FC<TInboxIssueActionsHeader> = observer((p
|
|||
{isAllowed && (
|
||||
<CustomMenu verticalEllipsis placement="bottom-start">
|
||||
{canMarkAsAccepted && (
|
||||
<CustomMenu.MenuItem onClick={handleIssueSnoozeAction}>
|
||||
<CustomMenu.MenuItem
|
||||
onClick={() =>
|
||||
handleActionWithPermission(
|
||||
isProjectAdmin,
|
||||
handleIssueSnoozeAction,
|
||||
"Only project admins can snooze/Un-snooze issues"
|
||||
)
|
||||
}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<Clock size={14} strokeWidth={2} />
|
||||
{inboxIssue?.snoozed_till && numberOfDaysLeft && numberOfDaysLeft > 0
|
||||
|
|
@ -351,7 +388,15 @@ export const InboxIssueActionsHeader: FC<TInboxIssueActionsHeader> = observer((p
|
|||
</CustomMenu.MenuItem>
|
||||
)}
|
||||
{canMarkAsDuplicate && (
|
||||
<CustomMenu.MenuItem onClick={() => setSelectDuplicateIssue(true)}>
|
||||
<CustomMenu.MenuItem
|
||||
onClick={() =>
|
||||
handleActionWithPermission(
|
||||
isProjectAdmin,
|
||||
() => setSelectDuplicateIssue(true),
|
||||
"Only project admins can mark issues as duplicate"
|
||||
)
|
||||
}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<FileStack size={14} strokeWidth={2} />
|
||||
Mark as duplicate
|
||||
|
|
@ -401,6 +446,8 @@ export const InboxIssueActionsHeader: FC<TInboxIssueActionsHeader> = observer((p
|
|||
setIsMobileSidebar={setIsMobileSidebar}
|
||||
isNotificationEmbed={isNotificationEmbed}
|
||||
embedRemoveCurrentNotification={embedRemoveCurrentNotification}
|
||||
isProjectAdmin={isProjectAdmin}
|
||||
handleActionWithPermission={handleActionWithPermission}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ type Props = {
|
|||
setIsMobileSidebar: (value: boolean) => void;
|
||||
isNotificationEmbed: boolean;
|
||||
embedRemoveCurrentNotification?: () => void;
|
||||
isProjectAdmin: boolean;
|
||||
handleActionWithPermission: (isAdmin: boolean, action: () => void, errorMessage: string) => void;
|
||||
};
|
||||
|
||||
export const InboxIssueActionsMobileHeader: React.FC<Props> = observer((props) => {
|
||||
|
|
@ -70,6 +72,8 @@ export const InboxIssueActionsMobileHeader: React.FC<Props> = observer((props) =
|
|||
setIsMobileSidebar,
|
||||
isNotificationEmbed,
|
||||
embedRemoveCurrentNotification,
|
||||
isProjectAdmin,
|
||||
handleActionWithPermission,
|
||||
} = props;
|
||||
const router = useAppRouter();
|
||||
const issue = inboxIssue?.issue;
|
||||
|
|
@ -139,7 +143,15 @@ export const InboxIssueActionsMobileHeader: React.FC<Props> = observer((props) =
|
|||
</CustomMenu.MenuItem>
|
||||
)}
|
||||
{canMarkAsAccepted && !isAcceptedOrDeclined && (
|
||||
<CustomMenu.MenuItem onClick={handleIssueSnoozeAction}>
|
||||
<CustomMenu.MenuItem
|
||||
onClick={() =>
|
||||
handleActionWithPermission(
|
||||
isProjectAdmin,
|
||||
handleIssueSnoozeAction,
|
||||
"Only project admins can snooze/Un-snooze issues"
|
||||
)
|
||||
}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<Clock size={14} strokeWidth={2} />
|
||||
{inboxIssue?.snoozed_till && numberOfDaysLeft && numberOfDaysLeft > 0 ? "Un-snooze" : "Snooze"}
|
||||
|
|
@ -147,7 +159,15 @@ export const InboxIssueActionsMobileHeader: React.FC<Props> = observer((props) =
|
|||
</CustomMenu.MenuItem>
|
||||
)}
|
||||
{canMarkAsDuplicate && !isAcceptedOrDeclined && (
|
||||
<CustomMenu.MenuItem onClick={() => setSelectDuplicateIssue(true)}>
|
||||
<CustomMenu.MenuItem
|
||||
onClick={() =>
|
||||
handleActionWithPermission(
|
||||
isProjectAdmin,
|
||||
() => setSelectDuplicateIssue(true),
|
||||
"Only project admins can mark issues as duplicate"
|
||||
)
|
||||
}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<FileStack size={14} strokeWidth={2} />
|
||||
Mark as duplicate
|
||||
|
|
@ -155,7 +175,15 @@ export const InboxIssueActionsMobileHeader: React.FC<Props> = observer((props) =
|
|||
</CustomMenu.MenuItem>
|
||||
)}
|
||||
{canMarkAsAccepted && (
|
||||
<CustomMenu.MenuItem onClick={() => setAcceptIssueModal(true)}>
|
||||
<CustomMenu.MenuItem
|
||||
onClick={() =>
|
||||
handleActionWithPermission(
|
||||
isProjectAdmin,
|
||||
() => setAcceptIssueModal(true),
|
||||
"Only project admins can accept issues"
|
||||
)
|
||||
}
|
||||
>
|
||||
<div className="flex items-center gap-2 text-green-500">
|
||||
<CircleCheck size={14} strokeWidth={2} />
|
||||
Accept
|
||||
|
|
@ -163,7 +191,15 @@ export const InboxIssueActionsMobileHeader: React.FC<Props> = observer((props) =
|
|||
</CustomMenu.MenuItem>
|
||||
)}
|
||||
{canMarkAsDeclined && (
|
||||
<CustomMenu.MenuItem onClick={() => setDeclineIssueModal(true)}>
|
||||
<CustomMenu.MenuItem
|
||||
onClick={() =>
|
||||
handleActionWithPermission(
|
||||
isProjectAdmin,
|
||||
() => setDeclineIssueModal(true),
|
||||
"Only project admins can deny issues"
|
||||
)
|
||||
}
|
||||
>
|
||||
<div className="flex items-center gap-2 text-red-500">
|
||||
<CircleX size={14} strokeWidth={2} />
|
||||
Decline
|
||||
|
|
|
|||
|
|
@ -62,10 +62,10 @@ export const InboxContentRoot: FC<TInboxContentRoot> = observer((props) => {
|
|||
}
|
||||
);
|
||||
|
||||
const isEditable = allowPermissions(
|
||||
[EUserPermissions.ADMIN, EUserPermissions.MEMBER, EUserPermissions.GUEST],
|
||||
EUserPermissionsLevel.PROJECT
|
||||
);
|
||||
const isEditable =
|
||||
allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.PROJECT) ||
|
||||
inboxIssue.created_by === currentUser?.id;
|
||||
|
||||
const isGuest = projectPermissionsByWorkspaceSlugAndProjectId(workspaceSlug, projectId) === EUserPermissions.GUEST;
|
||||
const isOwner = inboxIssue?.issue.created_by === currentUser?.id;
|
||||
const readOnly = !isOwner && isGuest;
|
||||
|
|
|
|||
|
|
@ -423,7 +423,7 @@ export class ProjectInboxStore implements IProjectInboxStore {
|
|||
|
||||
if (inboxIssue && issueId) {
|
||||
runInAction(() => {
|
||||
set(this.inboxIssues, [issueId], new InboxIssueStore(workspaceSlug, projectId, inboxIssue, this.store));
|
||||
this.createOrUpdateInboxIssue([inboxIssue], workspaceSlug, projectId);
|
||||
set(this, "loader", undefined);
|
||||
});
|
||||
await Promise.all([
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue