Skip to content

Commit

Permalink
feat: admin action to delete all segments for project (#2646)
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewelwell committed Aug 15, 2023
1 parent 7c92525 commit 4df1b80
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 0 deletions.
15 changes: 15 additions & 0 deletions api/projects/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from __future__ import unicode_literals

from django.contrib import admin
from django.db.models import QuerySet
from django.http import HttpRequest

from environments.models import Environment
from features.models import Feature
Expand Down Expand Up @@ -47,6 +49,7 @@ class TagInline(admin.StackedInline):

@admin.register(Project)
class ProjectAdmin(admin.ModelAdmin):
actions = ["delete_all_segments"]
date_hierarchy = "created_date"
inlines = [EnvironmentInline, FeatureInline, SegmentInline, TagInline]
list_display = (
Expand All @@ -67,3 +70,15 @@ class ProjectAdmin(admin.ModelAdmin):
"max_features_allowed",
"max_segment_overrides_allowed",
)

@admin.action(
description="Delete all segments for project",
permissions=["delete_all_segments"],
)
def delete_all_segments(self, request: HttpRequest, queryset: QuerySet):
Segment.objects.filter(project__in=queryset).delete()

def has_delete_all_segments_permission(
self, request: HttpRequest, obj: Project = None
) -> bool:
return request.user.is_superuser
80 changes: 80 additions & 0 deletions api/tests/unit/projects/test_unit_projects_admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import typing
from unittest.mock import MagicMock

import pytest
from django.contrib.admin import AdminSite

from environments.models import Environment
from features.models import Feature, FeatureSegment, FeatureState
from projects.admin import ProjectAdmin
from projects.models import Project
from segments.models import EQUAL, Condition, Segment, SegmentRule

if typing.TYPE_CHECKING:
from django.contrib.auth.models import AbstractUser

from organisations.models import Organisation


def test_project_admin_delete_all_segments(organisation: "Organisation"):
# Given
project_1 = Project.objects.create(name="project_1", organisation=organisation)
project_2 = Project.objects.create(name="project_2", organisation=organisation)

for project in (project_1, project_2):
segment = Segment.objects.create(name="segment", project=project)
parent_rule = SegmentRule.objects.create(
segment=segment, type=SegmentRule.ALL_RULE
)
child_rule = SegmentRule.objects.create(
rule=parent_rule, type=SegmentRule.ANY_RULE
)
Condition.objects.create(
rule=child_rule, property="foo", operator=EQUAL, value="bar"
)

environment = Environment.objects.create(name="test", project=project)
feature = Feature.objects.create(name="test", project=project)

feature_segment = FeatureSegment.objects.create(
feature=feature, environment=environment, segment=segment
)
FeatureState.objects.create(
feature=feature, environment=environment, feature_segment=feature_segment
)

project_admin = ProjectAdmin(Project, AdminSite())

# When
project_admin.delete_all_segments(
request=MagicMock(), queryset=Project.objects.filter(id=project_1.id)
)

# Then
assert not project_1.segments.exists()
assert not FeatureState.objects.filter(
feature=feature, environment__project=project_1, feature_segment__isnull=False
).exists()

assert project_2.segments.exists()
assert FeatureState.objects.filter(
feature=feature, environment__project=project_2, feature_segment__isnull=False
).exists()


@pytest.mark.parametrize(
"is_superuser, expected_result", ((True, True), (False, False))
)
def test_project_admin_has_delete_all_segments_permission(
is_superuser: bool, expected_result: bool, django_user_model: type["AbstractUser"]
):
# Given
request = MagicMock(user=django_user_model(is_superuser=is_superuser))

# Then
assert (
ProjectAdmin(Project, AdminSite()).has_delete_all_segments_permission(
request=request
)
is expected_result
)

3 comments on commit 4df1b80

@vercel
Copy link

@vercel vercel bot commented on 4df1b80 Aug 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 4df1b80 Aug 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 4df1b80 Aug 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

docs – ./docs

docs-git-main-flagsmith.vercel.app
docs.bullet-train.io
docs.flagsmith.com
docs-flagsmith.vercel.app

Please sign in to comment.