diff --git a/apiserver/plane/api/permissions/project.py b/apiserver/plane/api/permissions/project.py index 019496cda..44659a671 100644 --- a/apiserver/plane/api/permissions/project.py +++ b/apiserver/plane/api/permissions/project.py @@ -13,16 +13,24 @@ class ProjectBasePermission(BasePermission): ## Safe Methods -> Handle the filtering logic in queryset if request.method in SAFE_METHODS: - return True + return WorkspaceMember.objects.filter( + workspace__slug=view.workspace_slug, member=request.user + ).exists() + ## Only workspace owners or admins can create the projects if request.method == "POST": return WorkspaceMember.objects.filter( - workspace=view.workspace, member=request.user, role__in=[15, 20] + workspace__slug=view.workspace_slug, + member=request.user, + role__in=[15, 20], ).exists() ## Only Project Admins can update project attributes return ProjectMember.objects.filter( - workspace=view.workspace, member=request.user, role=20 + workspace__slug=view.workspace_slug, + member=request.user, + role=20, + project_id=view.project_id, ).exists() @@ -34,16 +42,23 @@ class ProjectMemberPermission(BasePermission): ## Safe Methods -> Handle the filtering logic in queryset if request.method in SAFE_METHODS: - return True + return ProjectMember.objects.filter( + workspace=view.workspace, member=request.user + ).exists() ## Only workspace owners or admins can create the projects if request.method == "POST": return WorkspaceMember.objects.filter( - workspace=view.workspace, member=request.user, role__in=[15, 20] + workspace__slug=view.workspace_slug, + member=request.user, + role__in=[15, 20], ).exists() ## Only Project Admins can update project attributes return ProjectMember.objects.filter( - workspace=view.workspace, member=request.user, role__in=[15, 20] + workspace__slug=view.workspace_slug, + member=request.user, + role__in=[15, 20], + project_id=view.project_id, ).exists() @@ -52,12 +67,19 @@ class ProjectEntityPermission(BasePermission): if request.user.is_anonymous: return False - + ## Safe Methods -> Handle the filtering logic in queryset if request.method in SAFE_METHODS: - return True - ## Only workspace owners or admins can create the projects + return ProjectMember.objects.filter( + workspace=view.workspace, + member=request.user, + project_id=view.project_id, + ).exists() + ## Only project members or admins can create and edit the project attributes return ProjectMember.objects.filter( - workspace=view.workspace, member=request.user, role__in=[15, 20] + workspace__slug=view.workspace_slug, + member=request.user, + role__in=[15, 20], + project_id=view.project_id, ).exists() diff --git a/apiserver/plane/api/urls.py b/apiserver/plane/api/urls.py index 872f5953f..050ce9c95 100644 --- a/apiserver/plane/api/urls.py +++ b/apiserver/plane/api/urls.py @@ -4,73 +4,94 @@ from django.urls import path # Create your urls here. from plane.api.views import ( + # Authentication + SignUpEndpoint, SignInEndpoint, SignOutEndpoint, MagicSignInEndpoint, MagicSignInGenerateEndpoint, + OauthEndpoint, + ## End Authentication + # Auth Extended ForgotPasswordEndpoint, - PeopleEndpoint, - UserEndpoint, VerifyEmailEndpoint, ResetPasswordEndpoint, RequestEmailVerificationEndpoint, - OauthEndpoint, ChangePasswordEndpoint, -) - -from plane.api.views import ( - UserWorkspaceInvitationsEndpoint, + ## End Auth Extender + # User + UserEndpoint, + UpdateUserOnBoardedEndpoint, + ## End User + # Workspaces WorkSpaceViewSet, + UserWorkspaceInvitationsEndpoint, UserWorkSpacesEndpoint, InviteWorkspaceEndpoint, JoinWorkspaceEndpoint, WorkSpaceMemberViewSet, WorkspaceInvitationsViewset, UserWorkspaceInvitationsEndpoint, + WorkspaceMemberUserEndpoint, + WorkspaceMemberUserViewsEndpoint, + WorkSpaceAvailabilityCheckEndpoint, + TeamMemberViewSet, + AddTeamToProjectEndpoint, + UserLastProjectWithWorkspaceEndpoint, + UserWorkspaceInvitationEndpoint, + ## End Workspaces + # File Assets + FileAssetEndpoint, + ## End File Assets + # Projects ProjectViewSet, InviteProjectEndpoint, ProjectMemberViewSet, ProjectMemberInvitationsViewset, - StateViewSet, - ShortCutViewSet, - ViewViewSet, - CycleViewSet, - FileAssetEndpoint, + ProjectMemberUserEndpoint, + AddMemberToProjectEndpoint, + ProjectJoinEndpoint, + UserProjectInvitationsViewset, + ProjectIdentifierEndpoint, + ## End Projects + # Issues IssueViewSet, WorkSpaceIssuesEndpoint, IssueActivityEndpoint, IssueCommentViewSet, - TeamMemberViewSet, - TimeLineIssueViewSet, - CycleIssueViewSet, - IssuePropertyViewSet, - UpdateUserOnBoardedEndpoint, - UserWorkspaceInvitationEndpoint, - UserProjectInvitationsViewset, - ProjectIdentifierEndpoint, - LabelViewSet, - AddMemberToProjectEndpoint, - ProjectJoinEndpoint, + UserWorkSpaceIssues, BulkDeleteIssuesEndpoint, ProjectUserViewsEndpoint, + TimeLineIssueViewSet, + IssuePropertyViewSet, + LabelViewSet, + ## End Issues + # States + StateViewSet, + ## End States + # Shortcuts + ShortCutViewSet, + ## End Shortcuts + # Views + ViewViewSet, + ## End Views + # Cycles + CycleViewSet, + CycleIssueViewSet, + ## End Cycles + # Modules ModuleViewSet, ModuleIssueViewSet, - UserLastProjectWithWorkspaceEndpoint, - UserWorkSpaceIssues, - ProjectMemberUserEndpoint, - WorkspaceMemberUserEndpoint, - WorkspaceMemberUserViewsEndpoint, - WorkSpaceAvailabilityCheckEndpoint, + ## End Modules ) -from plane.api.views.project import AddTeamToProjectEndpoint - urlpatterns = [ # Social Auth path("social-auth/", OauthEndpoint.as_view(), name="oauth"), # Auth path("sign-in/", SignInEndpoint.as_view(), name="sign-in"), + path("sign-up/", SignUpEndpoint.as_view(), name="sign-up"), path("sign-out/", SignOutEndpoint.as_view(), name="sign-out"), # Magic Sign In/Up path( @@ -95,8 +116,6 @@ urlpatterns = [ ForgotPasswordEndpoint.as_view(), name="forgot-password", ), - # List Users - path("users/", PeopleEndpoint.as_view()), # User Profile path( "users/me/", @@ -654,9 +673,4 @@ urlpatterns = [ name="project-module-issues", ), ## End Modules - # path( - # "issues//all/", - # IssueViewSet.as_view({"get": "list_issue_history_comments"}), - # name="Issue history and comments", - # ), ] diff --git a/apiserver/plane/api/views/__init__.py b/apiserver/plane/api/views/__init__.py index 3a0193f8a..1cadd95e6 100644 --- a/apiserver/plane/api/views/__init__.py +++ b/apiserver/plane/api/views/__init__.py @@ -13,7 +13,6 @@ from .project import ( ProjectMemberUserEndpoint, ) from .people import ( - PeopleEndpoint, UserEndpoint, UpdateUserOnBoardedEndpoint, ) @@ -64,6 +63,7 @@ from .auth_extended import ( from .authentication import ( + SignUpEndpoint, SignInEndpoint, SignOutEndpoint, MagicSignInEndpoint, diff --git a/apiserver/plane/api/views/asset.py b/apiserver/plane/api/views/asset.py index 902ae7009..657383553 100644 --- a/apiserver/plane/api/views/asset.py +++ b/apiserver/plane/api/views/asset.py @@ -6,7 +6,7 @@ from sentry_sdk import capture_exception # Module imports from .base import BaseAPIView -from plane.db.models import FileAsset, Workspace +from plane.db.models import FileAsset from plane.api.serializers import FileAssetSerializer @@ -18,8 +18,8 @@ class FileAssetEndpoint(BaseAPIView): A viewset for viewing and editing task instances. """ - def get(self, request): - files = FileAsset.objects.all() + def get(self, request, slug): + files = FileAsset.objects.filter(workspace__slug=slug) serializer = FileAssetSerializer(files, context={"request": request}, many=True) return Response(serializer.data) diff --git a/apiserver/plane/api/views/issue.py b/apiserver/plane/api/views/issue.py index 78f050af8..73ee40a83 100644 --- a/apiserver/plane/api/views/issue.py +++ b/apiserver/plane/api/views/issue.py @@ -4,7 +4,6 @@ from itertools import groupby, chain # Django imports from django.db.models import Prefetch -from django.db.models import Count, Sum from django.core.serializers.json import DjangoJSONEncoder # Third Party imports diff --git a/apiserver/plane/api/views/people.py b/apiserver/plane/api/views/people.py index b45176d1d..154888812 100644 --- a/apiserver/plane/api/views/people.py +++ b/apiserver/plane/api/views/people.py @@ -7,48 +7,11 @@ from sentry_sdk import capture_exception # Module imports from plane.api.serializers import ( UserSerializer, - WorkSpaceSerializer, ) from plane.api.views.base import BaseViewSet, BaseAPIView from plane.db.models import User, Workspace - -class PeopleEndpoint(BaseAPIView): - - filterset_fields = ("date_joined",) - - search_fields = ( - "^first_name", - "^last_name", - "^email", - "^username", - ) - - def get(self, request): - try: - users = User.objects.all().order_by("-date_joined") - if ( - request.GET.get("search", None) is not None - and len(request.GET.get("search")) < 3 - ): - return Response( - {"message": "Search term must be at least 3 characters long"}, - status=status.HTTP_400_BAD_REQUEST, - ) - return self.paginate( - request=request, - queryset=self.filter_queryset(users), - on_results=lambda data: UserSerializer(data, many=True).data, - ) - except Exception as e: - capture_exception(e) - return Response( - {"message": "Something went wrong please try again later"}, - status=status.HTTP_400_BAD_REQUEST, - ) - - class UserEndpoint(BaseViewSet): serializer_class = UserSerializer model = User