Skip to content

Commit

Permalink
fix: Check that feature owners are able to view the project of a feat…
Browse files Browse the repository at this point in the history
…ure (#2931)
  • Loading branch information
zachaysan committed Nov 8, 2023
1 parent ac26fc9 commit a0eefdd
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 14 deletions.
10 changes: 8 additions & 2 deletions api/features/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
)
from projects.models import Project
from projects.permissions import VIEW_PROJECT
from users.models import UserPermissionGroup
from users.models import FFAdminUser, UserPermissionGroup
from webhooks.webhooks import WebhookEventType

from .models import Feature, FeatureState
Expand Down Expand Up @@ -202,8 +202,14 @@ def remove_group_owners(self, request, *args, **kwargs):
def add_owners(self, request, *args, **kwargs):
serializer = FeatureOwnerInputSerializer(data=request.data)
serializer.is_valid(raise_exception=True)

feature = self.get_object()

for user in FFAdminUser.objects.filter(
id__in=serializer.validated_data["user_ids"]
):
if not user.has_project_permission(VIEW_PROJECT, feature.project):
raise serializers.ValidationError("Some users not found")

serializer.add_owners(feature)
return Response(self.get_serializer(instance=feature).data)

Expand Down
51 changes: 39 additions & 12 deletions api/tests/unit/features/test_unit_features_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from features.multivariate.models import MultivariateFeatureOption
from organisations.models import Organisation, OrganisationRole
from projects.models import Project, UserProjectPermission
from projects.permissions import VIEW_PROJECT
from segments.models import Segment
from users.models import FFAdminUser, UserPermissionGroup

Expand Down Expand Up @@ -529,9 +530,11 @@ def test_should_create_tags_when_feature_created(client, project, tag_one, tag_t
"client",
[lazy_fixture("admin_master_api_key_client"), lazy_fixture("admin_client")],
)
def test_add_owners_adds_owner(client, project):
def test_add_owners_fails_if_user_not_found(client, project):
# Given
feature = Feature.objects.create(name="Test Feature", project=project)

# Users have no association to the project or organisation.
user_1 = FFAdminUser.objects.create_user(email="user1@mail.com")
user_2 = FFAdminUser.objects.create_user(email="user2@mail.com")
url = reverse(
Expand All @@ -541,24 +544,48 @@ def test_add_owners_adds_owner(client, project):
data = {"user_ids": [user_1.id, user_2.id]}

# When
json_response = client.post(
url, data=json.dumps(data), content_type="application/json"
).json()
response = client.post(url, data=json.dumps(data), content_type="application/json")
# Then
assert response.status_code == status.HTTP_400_BAD_REQUEST
assert response.data == ["Some users not found"]
assert feature.owners.filter(id__in=[user_1.id, user_2.id]).count() == 0


@pytest.mark.parametrize(
"client",
[lazy_fixture("admin_master_api_key_client"), lazy_fixture("admin_client")],
)
def test_add_owners_adds_owner(staff_user, admin_user, client, project):
# Given
feature = Feature.objects.create(name="Test Feature", project=project)
UserProjectPermission.objects.create(
user=staff_user, project=project
).add_permission(VIEW_PROJECT)

url = reverse(
"api-v1:projects:project-features-add-owners",
args=[project.id, feature.id],
)
data = {"user_ids": [staff_user.id, admin_user.id]}

# When
response = client.post(url, data=json.dumps(data), content_type="application/json")

json_response = response.json()
# Then
assert len(json_response["owners"]) == 2
assert json_response["owners"][0] == {
"id": user_1.id,
"email": user_1.email,
"first_name": user_1.first_name,
"last_name": user_1.last_name,
"id": staff_user.id,
"email": staff_user.email,
"first_name": staff_user.first_name,
"last_name": staff_user.last_name,
"last_login": None,
}
assert json_response["owners"][1] == {
"id": user_2.id,
"email": user_2.email,
"first_name": user_2.first_name,
"last_name": user_2.last_name,
"id": admin_user.id,
"email": admin_user.email,
"first_name": admin_user.first_name,
"last_name": admin_user.last_name,
"last_login": None,
}

Expand Down

3 comments on commit a0eefdd

@vercel
Copy link

@vercel vercel bot commented on a0eefdd Nov 8, 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 a0eefdd Nov 8, 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 a0eefdd Nov 8, 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-flagsmith.vercel.app
docs.bullet-train.io
docs-git-main-flagsmith.vercel.app
docs.flagsmith.com

Please sign in to comment.