Skip to content

Commit 41447e5

Browse files
gakshitasangeethailangoNarayanBavisetti
authored
[WEB-3600] fix: private project join issue (#6799)
* fix: private project join issue * chore: return network value * fix: refactor * fix: refactor * fix: type * chore: added restricition for private projects * chore: removed extra validations * chore: added value to access enum --------- Co-authored-by: sangeethailango <sangeethailango21@gmail.com> Co-authored-by: NarayanBavisetti <narayan3119@gmail.com>
1 parent cebd0b3 commit 41447e5

File tree

6 files changed

+48
-10
lines changed

6 files changed

+48
-10
lines changed

apiserver/plane/app/views/project/base.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ def list(self, request, slug):
179179
"inbox_view",
180180
"guest_view_all_features",
181181
"project_lead",
182+
"network",
182183
"created_at",
183184
"updated_at",
184185
"created_by",

apiserver/plane/app/views/project/invite.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,17 @@
1616
# Module imports
1717
from .base import BaseViewSet, BaseAPIView
1818
from plane.app.serializers import ProjectMemberInviteSerializer
19-
2019
from plane.app.permissions import allow_permission, ROLE
21-
2220
from plane.db.models import (
2321
ProjectMember,
2422
Workspace,
2523
ProjectMemberInvite,
2624
User,
2725
WorkspaceMember,
26+
Project,
2827
IssueUserProperty,
2928
)
29+
from plane.db.models.project import ProjectNetwork
3030

3131

3232
class ProjectInvitationsViewset(BaseViewSet):
@@ -128,6 +128,7 @@ def get_queryset(self):
128128
.select_related("workspace", "workspace__owner", "project")
129129
)
130130

131+
@allow_permission([ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE")
131132
def create(self, request, slug):
132133
project_ids = request.data.get("project_ids", [])
133134

@@ -136,11 +137,20 @@ def create(self, request, slug):
136137
member=request.user, workspace__slug=slug, is_active=True
137138
)
138139

139-
if workspace_member.role not in [ROLE.ADMIN.value, ROLE.MEMBER.value]:
140-
return Response(
141-
{"error": "You do not have permission to join the project"},
142-
status=status.HTTP_403_FORBIDDEN,
143-
)
140+
# Get all the projects
141+
projects = Project.objects.filter(
142+
id__in=project_ids, workspace__slug=slug
143+
).only("id", "network")
144+
# Check if user has permission to join each project
145+
for project in projects:
146+
if (
147+
project.network == ProjectNetwork.SECRET.value
148+
and workspace_member.role != ROLE.ADMIN.value
149+
):
150+
return Response(
151+
{"error": "Only workspace admins can join private project"},
152+
status=status.HTTP_403_FORBIDDEN,
153+
)
144154

145155
workspace_role = workspace_member.role
146156
workspace = workspace_member.workspace

apiserver/plane/db/models/project.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Python imports
22
import pytz
33
from uuid import uuid4
4+
from enum import Enum
45

56
# Django imports
67
from django.conf import settings
@@ -17,6 +18,15 @@
1718
ROLE_CHOICES = ((20, "Admin"), (15, "Member"), (5, "Guest"))
1819

1920

21+
class ProjectNetwork(Enum):
22+
SECRET = 0
23+
PUBLIC = 2
24+
25+
@classmethod
26+
def choices(cls):
27+
return [(0, "Secret"), (2, "Public")]
28+
29+
2030
def get_default_props():
2131
return {
2232
"filters": {

packages/types/src/enums.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ export enum EUserPermissions {
66

77
export type TUserPermissions = EUserPermissions.ADMIN | EUserPermissions.MEMBER | EUserPermissions.GUEST;
88

9+
// project network
10+
export enum EProjectNetwork {
11+
PRIVATE = 0,
12+
PUBLIC = 2,
13+
}
14+
915
// project pages
1016
export enum EPageAccess {
1117
PUBLIC = 0,

packages/types/src/project/projects.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export interface IPartialProject {
2727
inbox_view: boolean;
2828
guest_view_all_features?: boolean;
2929
project_lead?: IUserLite | string | null;
30+
network?: number;
3031
// Timestamps
3132
created_at?: Date;
3233
updated_at?: Date;
@@ -50,7 +51,6 @@ export interface IProject extends IPartialProject {
5051
anchor?: string | null;
5152
is_favorite?: boolean;
5253
members?: string[];
53-
network?: number;
5454
timezone?: string;
5555
}
5656

web/core/layouts/auth-layout/project-wrapper.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import useSWR from "swr";
77
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
88
import { useTranslation } from "@plane/i18n";
99
// components
10+
import { EProjectNetwork } from "@plane/types/src/enums";
1011
import { JoinProject } from "@/components/auth-screens";
1112
import { LogoSpinner } from "@/components/common";
1213
import { ComicBoxButton, DetailedEmptyState } from "@/components/empty-state";
@@ -70,6 +71,11 @@ export const ProjectAuthWrapper: FC<IProjectAuthWrapper> = observer((props) => {
7071
workspaceSlug.toString(),
7172
projectId?.toString()
7273
);
74+
const isWorkspaceAdmin = allowPermissions(
75+
[EUserPermissions.ADMIN],
76+
EUserPermissionsLevel.WORKSPACE,
77+
workspaceSlug.toString()
78+
);
7379

7480
// Initialize module timeline chart
7581
useEffect(() => {
@@ -168,10 +174,15 @@ export const ProjectAuthWrapper: FC<IProjectAuthWrapper> = observer((props) => {
168174
);
169175

170176
// check if the user don't have permission to access the project
171-
if (projectExists && projectId && hasPermissionToCurrentProject === false) return <JoinProject />;
177+
if (
178+
((projectExists?.network && projectExists?.network !== EProjectNetwork.PRIVATE) || isWorkspaceAdmin) &&
179+
projectId &&
180+
hasPermissionToCurrentProject === false
181+
)
182+
return <JoinProject />;
172183

173184
// check if the project info is not found.
174-
if (loader === "loaded" && !projectExists && projectId && !!hasPermissionToCurrentProject === false)
185+
if (loader === "loaded" && projectId && !!hasPermissionToCurrentProject === false)
175186
return (
176187
<div className="grid h-screen place-items-center bg-custom-background-100">
177188
<DetailedEmptyState

0 commit comments

Comments
 (0)