Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 28 additions & 7 deletions apiserver/plane/app/views/inbox/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ def list(self, request, slug, project_id):
inbox_id = Inbox.objects.get(
workspace__slug=slug, project_id=project_id
)
project = Project.objects.get(pk=project_id)
filters = issue_filters(request.GET, "GET", "issue__")
inbox_issue = (
InboxIssue.objects.filter(
Expand Down Expand Up @@ -199,13 +200,16 @@ def list(self, request, slug, project_id):
if inbox_status:
inbox_issue = inbox_issue.filter(status__in=inbox_status)

if ProjectMember.objects.filter(
workspace__slug=slug,
project_id=project_id,
member=request.user,
role=5,
is_active=True,
).exists():
if (
ProjectMember.objects.filter(
workspace__slug=slug,
project_id=project_id,
member=request.user,
role=5,
is_active=True,
).exists()
and not project.guest_view_all_features
):
inbox_issue = inbox_issue.filter(created_by=request.user)
return self.paginate(
request=request,
Expand Down Expand Up @@ -517,6 +521,7 @@ def partial_update(self, request, slug, project_id, pk):
allowed_roles=[
ROLE.ADMIN,
ROLE.MEMBER,
ROLE.GUEST,
],
creator=True,
model=Issue,
Expand All @@ -525,6 +530,7 @@ def retrieve(self, request, slug, project_id, pk):
inbox_id = Inbox.objects.get(
workspace__slug=slug, project_id=project_id
)
project = Project.objects.get(pk=project_id)
inbox_issue = (
InboxIssue.objects.select_related("issue")
.prefetch_related(
Expand All @@ -551,6 +557,21 @@ def retrieve(self, request, slug, project_id, pk):
)
.get(inbox_id=inbox_id.id, issue_id=pk, project_id=project_id)
)
if (
ProjectMember.objects.filter(
workspace__slug=slug,
project_id=project_id,
member=request.user,
role=5,
is_active=True,
).exists()
and not project.guest_view_all_features
and not inbox_issue.created_by == request.user
):
return Response(
{"error": "You are not allowed to view this issue"},
status=status.HTTP_400_BAD_REQUEST,
)
issue = InboxIssueDetailSerializer(inbox_issue).data
return Response(
issue,
Expand Down
40 changes: 17 additions & 23 deletions apiserver/plane/app/views/project/invite.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from .base import BaseViewSet, BaseAPIView
from plane.app.serializers import ProjectMemberInviteSerializer

from plane.app.permissions import ProjectBasePermission
from plane.app.permissions import allow_permission, ROLE

from plane.db.models import (
ProjectMember,
Expand All @@ -35,10 +35,6 @@ class ProjectInvitationsViewset(BaseViewSet):

search_fields = []

permission_classes = [
ProjectBasePermission,
]

def get_queryset(self):
return self.filter_queryset(
super()
Expand All @@ -49,6 +45,7 @@ def get_queryset(self):
.select_related("workspace", "workspace__owner")
)

@allow_permission([ROLE.ADMIN])
def create(self, request, slug, project_id):
emails = request.data.get("emails", [])

Expand All @@ -59,24 +56,21 @@ def create(self, request, slug, project_id):
status=status.HTTP_400_BAD_REQUEST,
)

requesting_user = ProjectMember.objects.get(
workspace__slug=slug,
project_id=project_id,
member_id=request.user.id,
)

# Check if any invited user has an higher role
if len(
[
email
for email in emails
if int(email.get("role", 5)) > requesting_user.role
]
):
return Response(
{"error": "You cannot invite a user with higher role"},
status=status.HTTP_400_BAD_REQUEST,
)
for email in emails:
workspace_role = WorkspaceMember.objects.filter(
workspace__slug=slug,
member__email=email.get("email"),
is_active=True,
).role

if workspace_role in [5, 20] and workspace_role != email.get(
"role", 5
):
return Response(
{
"error": "You cannot invite a user with different role than workspace role"
},
)

workspace = Workspace.objects.get(slug=slug)

Expand Down
15 changes: 11 additions & 4 deletions web/core/components/inbox/content/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import useSWR from "swr";
import { ContentWrapper } from "@plane/ui";
import { InboxIssueActionsHeader, InboxIssueMainContent } from "@/components/inbox";
// hooks
import { useProjectInbox, useUserPermissions } from "@/hooks/store";
import { useProjectInbox, useUser, useUserPermissions } from "@/hooks/store";
import { useAppRouter } from "@/hooks/use-app-router";
import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/user-permissions";

Expand Down Expand Up @@ -34,9 +34,10 @@ export const InboxContentRoot: FC<TInboxContentRoot> = observer((props) => {
// states
const [isSubmitting, setIsSubmitting] = useState<"submitting" | "submitted" | "saved">("saved");
// hooks
const { data: currentUser } = useUser();
const { currentTab, fetchInboxIssueById, getIssueInboxByIssueId, getIsIssueAvailable } = useProjectInbox();
const inboxIssue = getIssueInboxByIssueId(inboxIssueId);
const { allowPermissions } = useUserPermissions();
const { allowPermissions, projectPermissionsByWorkspaceSlugAndProjectId } = useUserPermissions();

// derived values
const isIssueAvailable = getIsIssueAvailable(inboxIssueId?.toString() || "");
Expand All @@ -61,7 +62,13 @@ export const InboxContentRoot: FC<TInboxContentRoot> = observer((props) => {
}
);

const isEditable = allowPermissions([EUserPermissions.ADMIN, EUserPermissions.MEMBER], EUserPermissionsLevel.PROJECT);
const isEditable = allowPermissions(
[EUserPermissions.ADMIN, EUserPermissions.MEMBER, EUserPermissions.GUEST],
EUserPermissionsLevel.PROJECT
);
const isGuest = projectPermissionsByWorkspaceSlugAndProjectId(workspaceSlug, projectId) === EUserPermissions.GUEST;
const isOwner = inboxIssue.issue.created_by === currentUser?.id;
const readOnly = !isOwner && isGuest;

if (!inboxIssue) return <></>;

Expand All @@ -87,7 +94,7 @@ export const InboxContentRoot: FC<TInboxContentRoot> = observer((props) => {
workspaceSlug={workspaceSlug}
projectId={projectId}
inboxIssue={inboxIssue}
isEditable={isEditable && !isIssueDisabled}
isEditable={isEditable && !isIssueDisabled && !readOnly}
isSubmitting={isSubmitting}
setIsSubmitting={setIsSubmitting}
/>
Expand Down
4 changes: 2 additions & 2 deletions web/core/components/project/send-project-invitation-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,10 @@ export const SendProjectInvitationModal: React.FC<Props> = observer((props) => {
const currentMemberWorkspaceRole = getWorkspaceMemberDetails(value)?.role;
if (!value || !currentMemberWorkspaceRole) return ROLE;

const isGuest = [EUserPermissions.GUEST].includes(currentMemberWorkspaceRole);
const isGuestOROwner = [EUserPermissions.ADMIN, EUserPermissions.GUEST].includes(currentMemberWorkspaceRole);

return Object.fromEntries(
Object.entries(ROLE).filter(([key]) => !isGuest || [5].includes(parseInt(key)))
Object.entries(ROLE).filter(([key]) => !isGuestOROwner || [currentMemberWorkspaceRole].includes(parseInt(key)))
);
};

Expand Down