2022-07-26 22:36:14 +02:00
|
|
|
|
import posthoganalytics
|
2022-04-20 13:33:41 +02:00
|
|
|
|
import requests
|
2020-08-14 11:23:55 +02:00
|
|
|
|
from django.conf import settings
|
|
|
|
|
from django.db.models import QuerySet
|
2022-05-18 13:23:19 +02:00
|
|
|
|
from django.shortcuts import get_object_or_404
|
|
|
|
|
from django.utils.timezone import now
|
|
|
|
|
from rest_framework import mixins, request, serializers, viewsets
|
|
|
|
|
from rest_framework.response import Response
|
2020-08-14 11:23:55 +02:00
|
|
|
|
|
2022-04-20 13:33:41 +02:00
|
|
|
|
from ee.models.license import License, LicenseError
|
2022-07-26 22:36:14 +02:00
|
|
|
|
from posthog.event_usage import groups
|
2022-05-18 13:23:19 +02:00
|
|
|
|
from posthog.models.organization import Organization
|
|
|
|
|
from posthog.models.team import Team
|
2020-08-14 11:23:55 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class LicenseSerializer(serializers.ModelSerializer):
|
|
|
|
|
class Meta:
|
|
|
|
|
model = License
|
|
|
|
|
fields = [
|
2021-04-14 17:45:39 +02:00
|
|
|
|
"id",
|
2020-08-14 11:23:55 +02:00
|
|
|
|
"key",
|
2021-04-14 17:45:39 +02:00
|
|
|
|
"plan",
|
2020-08-14 11:23:55 +02:00
|
|
|
|
"valid_until",
|
2021-04-14 17:45:39 +02:00
|
|
|
|
"max_users",
|
|
|
|
|
"created_at",
|
2020-08-14 11:23:55 +02:00
|
|
|
|
]
|
2021-04-14 17:45:39 +02:00
|
|
|
|
read_only_fields = ["plan", "valid_until", "max_users"]
|
2020-08-14 11:23:55 +02:00
|
|
|
|
|
2022-04-20 13:33:41 +02:00
|
|
|
|
def validate(self, data):
|
|
|
|
|
validation = requests.post("https://license.posthog.com/licenses/activate", data={"key": data["key"]})
|
|
|
|
|
resp = validation.json()
|
2022-07-26 22:36:14 +02:00
|
|
|
|
user = self.context["request"].user
|
2022-04-20 13:33:41 +02:00
|
|
|
|
if not validation.ok:
|
2022-07-26 22:36:14 +02:00
|
|
|
|
posthoganalytics.capture(
|
|
|
|
|
user.distinct_id,
|
|
|
|
|
"license key activation failure",
|
|
|
|
|
properties={"error": validation.content},
|
|
|
|
|
groups=groups(user.current_organization, user.current_team),
|
|
|
|
|
)
|
2022-04-20 13:33:41 +02:00
|
|
|
|
raise LicenseError(resp["code"], resp["detail"])
|
2022-07-26 22:36:14 +02:00
|
|
|
|
|
|
|
|
|
posthoganalytics.capture(
|
|
|
|
|
user.distinct_id,
|
|
|
|
|
"license key activation success",
|
|
|
|
|
properties={},
|
|
|
|
|
groups=groups(user.current_organization, user.current_team),
|
|
|
|
|
)
|
2022-04-20 13:33:41 +02:00
|
|
|
|
data["valid_until"] = resp["valid_until"]
|
|
|
|
|
data["plan"] = resp["plan"]
|
|
|
|
|
data["max_users"] = resp.get("max_users", 0)
|
|
|
|
|
return data
|
2020-08-14 11:23:55 +02:00
|
|
|
|
|
2021-04-14 17:45:39 +02:00
|
|
|
|
|
|
|
|
|
class LicenseViewSet(
|
2022-09-05 14:38:54 +02:00
|
|
|
|
mixins.ListModelMixin,
|
|
|
|
|
mixins.RetrieveModelMixin,
|
|
|
|
|
mixins.CreateModelMixin,
|
|
|
|
|
viewsets.GenericViewSet,
|
2021-04-14 17:45:39 +02:00
|
|
|
|
):
|
2020-08-14 11:23:55 +02:00
|
|
|
|
queryset = License.objects.all()
|
|
|
|
|
serializer_class = LicenseSerializer
|
|
|
|
|
|
|
|
|
|
def get_queryset(self) -> QuerySet:
|
2020-09-28 13:21:03 +02:00
|
|
|
|
if getattr(settings, "MULTI_TENANCY", False):
|
2020-08-14 11:23:55 +02:00
|
|
|
|
return License.objects.none()
|
|
|
|
|
|
|
|
|
|
return super().get_queryset()
|
2022-05-18 13:23:19 +02:00
|
|
|
|
|
|
|
|
|
def destroy(self, request: request.Request, pk=None, **kwargs) -> Response:
|
|
|
|
|
license = get_object_or_404(License, pk=pk)
|
|
|
|
|
validation = requests.post("https://license.posthog.com/licenses/deactivate", data={"key": license.key})
|
|
|
|
|
validation.raise_for_status()
|
|
|
|
|
|
|
|
|
|
has_another_valid_license = License.objects.filter(valid_until__gte=now()).exclude(pk=pk).exists()
|
|
|
|
|
if not has_another_valid_license:
|
|
|
|
|
teams = Team.objects.exclude(is_demo=True).order_by("pk")[1:]
|
|
|
|
|
for team in teams:
|
|
|
|
|
team.delete()
|
|
|
|
|
|
|
|
|
|
# delete any organization where we've deleted all teams
|
|
|
|
|
# there is no way in the interface to create multiple organizations so we won't bother informing people that this is happening
|
|
|
|
|
for organization in Organization.objects.all():
|
|
|
|
|
if organization.teams.count() == 0:
|
|
|
|
|
organization.delete()
|
|
|
|
|
|
|
|
|
|
license.delete()
|
|
|
|
|
|
|
|
|
|
return Response({"ok": True})
|