0
0
mirror of https://github.com/PostHog/posthog.git synced 2024-11-28 09:16:49 +01:00
posthog/ee/api/dashboard_collaborator.py

118 lines
5.0 KiB
Python
Raw Normal View History

2022-02-08 17:22:09 +01:00
from typing import Any, Dict, cast
from django.db import IntegrityError
from rest_framework import exceptions, mixins, serializers, viewsets
2022-02-08 17:22:09 +01:00
from rest_framework.permissions import SAFE_METHODS, BasePermission, IsAuthenticated
from rest_framework.request import Request
2022-02-08 17:22:09 +01:00
from ee.models.dashboard_privilege import DashboardPrivilege
from posthog.api.routing import StructuredViewSetMixin
from posthog.api.shared import UserBasicSerializer
fix(query-performance): Speed up permissioning in API (#13952) * Get #team_effective_membership_level under test * Extract method into class * Refactor team_effective_membership_level to require less lookups * Test and scaffolding for dashboard methods * Move dashboard methods to user_permissions * Optimize dashboard methods * Insights priviledge logic to user_permissions * Make insight priviledge code efficient * Fix bug to improve efficiency * Refactor efficiency tests * Use UserPermissions in some dashboard-related views * Use UserPermissions in some insight-related views * Fix a typo * Remove insight, dashboard model methods * Experiment: make shared dashboards not have effective_priviledge_levels/effective_restriction_level * Remove team#get_effective_membership_level * Simplify TeamBaseSerializer * Update organization API * Update UserViewSet * update team view * Reduce some lookups * Make UserPermissions not dependant on organization being passed * cast-to-user * Test listing with basic as FE calls it * Update dashboard views * JOIN organizations table, dont rely on request.user.organization * Update snapshots * Handle shared dashboards slightly better * Simplify team API * Fix test_team.py * Update middleware tests * Update ee team tests * Fully refactor a problematic call pattern * Solve ee API errors * Solve lint fails * Reset in insights as well * Cast * Update snapshots * Update snapshots * Update snapshots * Update snapshots * Update snapshots * Update snapshots * Remove merge conflict * Update snapshots * Remove items --------- Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-30 10:44:16 +01:00
from posthog.models import Dashboard, User
2022-02-08 17:22:09 +01:00
from posthog.permissions import TeamMemberAccessPermission
fix(query-performance): Speed up permissioning in API (#13952) * Get #team_effective_membership_level under test * Extract method into class * Refactor team_effective_membership_level to require less lookups * Test and scaffolding for dashboard methods * Move dashboard methods to user_permissions * Optimize dashboard methods * Insights priviledge logic to user_permissions * Make insight priviledge code efficient * Fix bug to improve efficiency * Refactor efficiency tests * Use UserPermissions in some dashboard-related views * Use UserPermissions in some insight-related views * Fix a typo * Remove insight, dashboard model methods * Experiment: make shared dashboards not have effective_priviledge_levels/effective_restriction_level * Remove team#get_effective_membership_level * Simplify TeamBaseSerializer * Update organization API * Update UserViewSet * update team view * Reduce some lookups * Make UserPermissions not dependant on organization being passed * cast-to-user * Test listing with basic as FE calls it * Update dashboard views * JOIN organizations table, dont rely on request.user.organization * Update snapshots * Handle shared dashboards slightly better * Simplify team API * Fix test_team.py * Update middleware tests * Update ee team tests * Fully refactor a problematic call pattern * Solve ee API errors * Solve lint fails * Reset in insights as well * Cast * Update snapshots * Update snapshots * Update snapshots * Update snapshots * Update snapshots * Update snapshots * Remove merge conflict * Update snapshots * Remove items --------- Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-30 10:44:16 +01:00
from posthog.user_permissions import UserPermissions, UserPermissionsSerializerMixin
2022-02-08 17:22:09 +01:00
class CanEditDashboardCollaborator(BasePermission):
message = "You don't have edit permissions for this dashboard."
2022-02-08 17:22:09 +01:00
def has_permission(self, request: Request, view) -> bool:
2022-02-08 17:22:09 +01:00
if request.method in SAFE_METHODS:
return True
try:
dashboard: Dashboard = Dashboard.objects.get(id=view.parents_query_dict["dashboard_id"])
except Dashboard.DoesNotExist:
raise exceptions.NotFound("Dashboard not found.")
fix(query-performance): Speed up permissioning in API (#13952) * Get #team_effective_membership_level under test * Extract method into class * Refactor team_effective_membership_level to require less lookups * Test and scaffolding for dashboard methods * Move dashboard methods to user_permissions * Optimize dashboard methods * Insights priviledge logic to user_permissions * Make insight priviledge code efficient * Fix bug to improve efficiency * Refactor efficiency tests * Use UserPermissions in some dashboard-related views * Use UserPermissions in some insight-related views * Fix a typo * Remove insight, dashboard model methods * Experiment: make shared dashboards not have effective_priviledge_levels/effective_restriction_level * Remove team#get_effective_membership_level * Simplify TeamBaseSerializer * Update organization API * Update UserViewSet * update team view * Reduce some lookups * Make UserPermissions not dependant on organization being passed * cast-to-user * Test listing with basic as FE calls it * Update dashboard views * JOIN organizations table, dont rely on request.user.organization * Update snapshots * Handle shared dashboards slightly better * Simplify team API * Fix test_team.py * Update middleware tests * Update ee team tests * Fully refactor a problematic call pattern * Solve ee API errors * Solve lint fails * Reset in insights as well * Cast * Update snapshots * Update snapshots * Update snapshots * Update snapshots * Update snapshots * Update snapshots * Remove merge conflict * Update snapshots * Remove items --------- Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-30 10:44:16 +01:00
return view.user_permissions.dashboard(dashboard).can_edit
2022-02-08 17:22:09 +01:00
fix(query-performance): Speed up permissioning in API (#13952) * Get #team_effective_membership_level under test * Extract method into class * Refactor team_effective_membership_level to require less lookups * Test and scaffolding for dashboard methods * Move dashboard methods to user_permissions * Optimize dashboard methods * Insights priviledge logic to user_permissions * Make insight priviledge code efficient * Fix bug to improve efficiency * Refactor efficiency tests * Use UserPermissions in some dashboard-related views * Use UserPermissions in some insight-related views * Fix a typo * Remove insight, dashboard model methods * Experiment: make shared dashboards not have effective_priviledge_levels/effective_restriction_level * Remove team#get_effective_membership_level * Simplify TeamBaseSerializer * Update organization API * Update UserViewSet * update team view * Reduce some lookups * Make UserPermissions not dependant on organization being passed * cast-to-user * Test listing with basic as FE calls it * Update dashboard views * JOIN organizations table, dont rely on request.user.organization * Update snapshots * Handle shared dashboards slightly better * Simplify team API * Fix test_team.py * Update middleware tests * Update ee team tests * Fully refactor a problematic call pattern * Solve ee API errors * Solve lint fails * Reset in insights as well * Cast * Update snapshots * Update snapshots * Update snapshots * Update snapshots * Update snapshots * Update snapshots * Remove merge conflict * Update snapshots * Remove items --------- Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-30 10:44:16 +01:00
class DashboardCollaboratorSerializer(serializers.ModelSerializer, UserPermissionsSerializerMixin):
2022-02-08 17:22:09 +01:00
user = UserBasicSerializer(read_only=True)
dashboard_id = serializers.IntegerField(read_only=True)
user_uuid = serializers.UUIDField(required=True, write_only=True)
class Meta:
model = DashboardPrivilege
fields = [
"id",
"dashboard_id",
"user",
"level",
"added_at",
"updated_at",
"user_uuid", # write_only (see above)
]
read_only_fields = ["id", "dashboard_id", "user", "user"]
def validate(self, attrs: Dict[str, Any]) -> Dict[str, Any]:
dashboard: Dashboard = self.context["dashboard"]
fix(query-performance): Speed up permissioning in API (#13952) * Get #team_effective_membership_level under test * Extract method into class * Refactor team_effective_membership_level to require less lookups * Test and scaffolding for dashboard methods * Move dashboard methods to user_permissions * Optimize dashboard methods * Insights priviledge logic to user_permissions * Make insight priviledge code efficient * Fix bug to improve efficiency * Refactor efficiency tests * Use UserPermissions in some dashboard-related views * Use UserPermissions in some insight-related views * Fix a typo * Remove insight, dashboard model methods * Experiment: make shared dashboards not have effective_priviledge_levels/effective_restriction_level * Remove team#get_effective_membership_level * Simplify TeamBaseSerializer * Update organization API * Update UserViewSet * update team view * Reduce some lookups * Make UserPermissions not dependant on organization being passed * cast-to-user * Test listing with basic as FE calls it * Update dashboard views * JOIN organizations table, dont rely on request.user.organization * Update snapshots * Handle shared dashboards slightly better * Simplify team API * Fix test_team.py * Update middleware tests * Update ee team tests * Fully refactor a problematic call pattern * Solve ee API errors * Solve lint fails * Reset in insights as well * Cast * Update snapshots * Update snapshots * Update snapshots * Update snapshots * Update snapshots * Update snapshots * Remove merge conflict * Update snapshots * Remove items --------- Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-30 10:44:16 +01:00
dashboard_permissions = self.user_permissions.dashboard(dashboard)
if dashboard_permissions.effective_restriction_level <= Dashboard.RestrictionLevel.EVERYONE_IN_PROJECT_CAN_EDIT:
2022-02-08 17:22:09 +01:00
raise exceptions.ValidationError("Cannot add collaborators to a dashboard on the lowest restriction level.")
attrs = super().validate(attrs)
level = attrs.get("level")
if level is not None and level != Dashboard.PrivilegeLevel.CAN_EDIT:
raise serializers.ValidationError("Only edit access can be explicitly specified currently.")
return attrs
def create(self, validated_data):
dashboard: Dashboard = self.context["dashboard"]
user_uuid = validated_data.pop("user_uuid")
try:
validated_data["user"] = User.objects.filter(is_active=True).get(uuid=user_uuid)
2022-02-08 17:22:09 +01:00
except User.DoesNotExist:
raise serializers.ValidationError("User does not exist.")
fix(query-performance): Speed up permissioning in API (#13952) * Get #team_effective_membership_level under test * Extract method into class * Refactor team_effective_membership_level to require less lookups * Test and scaffolding for dashboard methods * Move dashboard methods to user_permissions * Optimize dashboard methods * Insights priviledge logic to user_permissions * Make insight priviledge code efficient * Fix bug to improve efficiency * Refactor efficiency tests * Use UserPermissions in some dashboard-related views * Use UserPermissions in some insight-related views * Fix a typo * Remove insight, dashboard model methods * Experiment: make shared dashboards not have effective_priviledge_levels/effective_restriction_level * Remove team#get_effective_membership_level * Simplify TeamBaseSerializer * Update organization API * Update UserViewSet * update team view * Reduce some lookups * Make UserPermissions not dependant on organization being passed * cast-to-user * Test listing with basic as FE calls it * Update dashboard views * JOIN organizations table, dont rely on request.user.organization * Update snapshots * Handle shared dashboards slightly better * Simplify team API * Fix test_team.py * Update middleware tests * Update ee team tests * Fully refactor a problematic call pattern * Solve ee API errors * Solve lint fails * Reset in insights as well * Cast * Update snapshots * Update snapshots * Update snapshots * Update snapshots * Update snapshots * Update snapshots * Remove merge conflict * Update snapshots * Remove items --------- Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-30 10:44:16 +01:00
modified_user_permissions = UserPermissions(
user=validated_data["user"],
team=self.context["view"].team,
)
if modified_user_permissions.current_team.effective_membership_level is None:
2022-02-08 17:22:09 +01:00
raise exceptions.ValidationError("Cannot add collaborators that have no access to the project.")
fix(query-performance): Speed up permissioning in API (#13952) * Get #team_effective_membership_level under test * Extract method into class * Refactor team_effective_membership_level to require less lookups * Test and scaffolding for dashboard methods * Move dashboard methods to user_permissions * Optimize dashboard methods * Insights priviledge logic to user_permissions * Make insight priviledge code efficient * Fix bug to improve efficiency * Refactor efficiency tests * Use UserPermissions in some dashboard-related views * Use UserPermissions in some insight-related views * Fix a typo * Remove insight, dashboard model methods * Experiment: make shared dashboards not have effective_priviledge_levels/effective_restriction_level * Remove team#get_effective_membership_level * Simplify TeamBaseSerializer * Update organization API * Update UserViewSet * update team view * Reduce some lookups * Make UserPermissions not dependant on organization being passed * cast-to-user * Test listing with basic as FE calls it * Update dashboard views * JOIN organizations table, dont rely on request.user.organization * Update snapshots * Handle shared dashboards slightly better * Simplify team API * Fix test_team.py * Update middleware tests * Update ee team tests * Fully refactor a problematic call pattern * Solve ee API errors * Solve lint fails * Reset in insights as well * Cast * Update snapshots * Update snapshots * Update snapshots * Update snapshots * Update snapshots * Update snapshots * Remove merge conflict * Update snapshots * Remove items --------- Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-30 10:44:16 +01:00
if modified_user_permissions.dashboard(dashboard).can_restrict:
2022-02-08 17:22:09 +01:00
raise exceptions.ValidationError(
"Cannot add collaborators that already have inherent access (the dashboard owner or a project admins)."
)
validated_data["dashboard_id"] = self.context["dashboard_id"]
try:
return super().create(validated_data)
except IntegrityError:
raise serializers.ValidationError("User already is a collaborator.")
class DashboardCollaboratorViewSet(
StructuredViewSetMixin,
mixins.ListModelMixin,
mixins.CreateModelMixin,
mixins.DestroyModelMixin,
viewsets.GenericViewSet,
):
permission_classes = [IsAuthenticated, TeamMemberAccessPermission, CanEditDashboardCollaborator]
2022-02-08 17:22:09 +01:00
pagination_class = None
queryset = DashboardPrivilege.objects.select_related("dashboard").filter(user__is_active=True)
2022-02-08 17:22:09 +01:00
lookup_field = "user__uuid"
serializer_class = DashboardCollaboratorSerializer
filter_rewrite_rules = {"team_id": "dashboard__team_id"}
include_in_docs = False
def get_serializer_context(self) -> Dict[str, Any]:
context = super().get_serializer_context()
try:
context["dashboard"] = Dashboard.objects.get(id=context["dashboard_id"])
except Dashboard.DoesNotExist:
raise exceptions.NotFound("Dashboard not found.")
return context
def perform_destroy(self, instance) -> None:
dashboard = cast(Dashboard, instance.dashboard)
fix(query-performance): Speed up permissioning in API (#13952) * Get #team_effective_membership_level under test * Extract method into class * Refactor team_effective_membership_level to require less lookups * Test and scaffolding for dashboard methods * Move dashboard methods to user_permissions * Optimize dashboard methods * Insights priviledge logic to user_permissions * Make insight priviledge code efficient * Fix bug to improve efficiency * Refactor efficiency tests * Use UserPermissions in some dashboard-related views * Use UserPermissions in some insight-related views * Fix a typo * Remove insight, dashboard model methods * Experiment: make shared dashboards not have effective_priviledge_levels/effective_restriction_level * Remove team#get_effective_membership_level * Simplify TeamBaseSerializer * Update organization API * Update UserViewSet * update team view * Reduce some lookups * Make UserPermissions not dependant on organization being passed * cast-to-user * Test listing with basic as FE calls it * Update dashboard views * JOIN organizations table, dont rely on request.user.organization * Update snapshots * Handle shared dashboards slightly better * Simplify team API * Fix test_team.py * Update middleware tests * Update ee team tests * Fully refactor a problematic call pattern * Solve ee API errors * Solve lint fails * Reset in insights as well * Cast * Update snapshots * Update snapshots * Update snapshots * Update snapshots * Update snapshots * Update snapshots * Remove merge conflict * Update snapshots * Remove items --------- Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-30 10:44:16 +01:00
if (
self.user_permissions.dashboard(dashboard).effective_restriction_level
<= Dashboard.RestrictionLevel.EVERYONE_IN_PROJECT_CAN_EDIT
):
2022-02-08 17:22:09 +01:00
raise exceptions.ValidationError(
"Cannot remove collaborators from a dashboard on the lowest restriction level."
)
return super().perform_destroy(instance)