0
0
mirror of https://github.com/PostHog/posthog.git synced 2024-11-25 11:17:50 +01:00
posthog/ee/api/ee_property_definition.py
Michael Matloka bfa3b801d2
feat(activity-log): Log if activity was completed by PostHog staff using impersonation (#19657)
* Move "impersonated_session" to a context processor

* Add field `was_impersonated` to `ActivityLog`

* Fix `cannot_be_both_system_and_staff` constraint

* Fix `log_insight_activity`

* Update activityLogMocks.ts

* Update plugin.py

* Update test_migrations_are_safe.py

* Fix log_activity helpers

* Update query snapshots

* Update UI snapshots for `chromium` (2)

* Remove constraint

* Fix `ExportedAssetSerializer`

* Update query snapshots

* Update UI snapshots for `chromium` (1)

* Add integrity check

* Fail activity logging loudly in tests

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-01-11 13:33:10 +01:00

93 lines
3.6 KiB
Python

from rest_framework import serializers
from django.utils import timezone
from ee.models.property_definition import EnterprisePropertyDefinition
from posthog.api.shared import UserBasicSerializer
from posthog.api.tagged_item import TaggedItemSerializerMixin
from posthog.models import PropertyDefinition
from posthog.models.activity_logging.activity_log import (
dict_changes_between,
log_activity,
Detail,
)
from loginas.utils import is_impersonated_session
class EnterprisePropertyDefinitionSerializer(TaggedItemSerializerMixin, serializers.ModelSerializer):
updated_by = UserBasicSerializer(read_only=True)
verified_by = UserBasicSerializer(read_only=True)
class Meta:
model = EnterprisePropertyDefinition
fields = (
"id",
"name",
"description",
"tags",
"is_numerical",
"updated_at",
"updated_by",
"is_seen_on_filtered_events",
"property_type",
"verified",
"verified_at",
"verified_by",
)
read_only_fields = [
"id",
"name",
"is_numerical",
"is_seen_on_filtered_events",
"verified_at",
"verified_by",
]
def update(self, property_definition: EnterprisePropertyDefinition, validated_data):
validated_data["updated_by"] = self.context["request"].user
if "property_type" in validated_data:
if validated_data["property_type"] == "Numeric":
validated_data["is_numerical"] = True
else:
validated_data["is_numerical"] = False
if "verified" in validated_data:
if validated_data["verified"] and not property_definition.verified:
# Verify property only if previously unverified
validated_data["verified_by"] = self.context["request"].user
validated_data["verified_at"] = timezone.now()
validated_data["verified"] = True
elif not validated_data["verified"]:
# Unverifying property nullifies verified properties
validated_data["verified_by"] = None
validated_data["verified_at"] = None
validated_data["verified"] = False
else:
# Attempting to re-verify an already verified property, invalid action. Ignore attribute.
validated_data.pop("verified")
before_state = {
k: property_definition.__dict__[k] for k in validated_data.keys() if k in property_definition.__dict__
}
# KLUDGE: if we get a None value for tags, and we're not adding any
# then we get an activity log that we went from null to the empty array ¯\_(ツ)_/¯
if "tags" not in before_state or before_state["tags"] is None:
before_state["tags"] = []
changes = dict_changes_between("PropertyDefinition", before_state, validated_data, True)
log_activity(
organization_id=None,
team_id=self.context["team_id"],
user=self.context["request"].user,
was_impersonated=is_impersonated_session(self.context["request"]),
item_id=str(property_definition.id),
scope="PropertyDefinition",
activity="changed",
detail=Detail(
name=str(property_definition.name),
type=PropertyDefinition.Type(property_definition.type).label,
changes=changes,
),
)
return super().update(property_definition, validated_data)