Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions baseapp-profiles/baseapp_profiles/graphql/mutations.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
from graphql.error import GraphQLError
from rest_framework import serializers

from .object_types import ProfileRoleTypesEnum

Profile = swapper.load_model("baseapp_profiles", "Profile")
app_label = Profile._meta.app_label
ProfileUserRole = swapper.load_model("baseapp_profiles", "ProfileUserRole")
Expand Down Expand Up @@ -120,6 +122,40 @@ def perform_mutate(cls, serializer, info):
)


class RoleUpdate(RelayMutation):
profile_user_role = graphene.Field(get_object_type_for_model(ProfileUserRole))

class Input:
profile_id = graphene.ID(required=True)
user_id = graphene.ID(required=True)
role_type = graphene.Field(ProfileRoleTypesEnum)

@classmethod
@login_required
def mutate_and_get_payload(cls, root, info, **input):
user_id = input.get("user_id")
profile_id = input.get("profile_id")
role_type = input.get("role_type")
user_pk = get_pk_from_relay_id(user_id)
profile_pk = get_pk_from_relay_id(profile_id)

try:
obj = ProfileUserRole.objects.get(user_id=user_pk, profile_id=profile_pk)
except ProfileUserRole.DoesNotExist:
raise GraphQLError(_("Role not found"))

if not info.context.user.has_perm("baseapp_profiles.change_profileuserrole", obj.profile):
raise GraphQLError(
str(_("You don't have permission to perform this action")),
extensions={"code": "permission_required"},
)

obj.role = role_type
obj.save()

return RoleUpdate(profile_user_role=obj)


class ProfileUpdate(SerializerMutation):
profile = graphene.Field(get_object_type_for_model(Profile))

Expand Down Expand Up @@ -210,3 +246,4 @@ class ProfilesMutations(object):
profile_create = ProfileCreate.Field()
profile_update = ProfileUpdate.Field()
profile_delete = ProfileDelete.Field()
profile_role_update = RoleUpdate.Field()
10 changes: 10 additions & 0 deletions baseapp-profiles/baseapp_profiles/permissions.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import swapper
from django.contrib.auth.backends import BaseBackend

ProfileUserRole = swapper.load_model("baseapp_profiles", "ProfileUserRole")
Profile = swapper.load_model("baseapp_profiles", "Profile")


Expand Down Expand Up @@ -45,3 +46,12 @@ def has_perm(self, user_obj, perm, obj=None):
or user_obj.is_superuser
or obj.members.filter(user_id=user_obj.id).exists()
)

if perm == "baseapp_profiles.change_profileuserrole" and obj:
if isinstance(obj, Profile):
return (
obj.owner_id == user_obj.id
or obj.members.filter(
user_id=user_obj.id, role=ProfileUserRole.ProfileRoles.ADMIN
).exists()
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
from baseapp_pages.tests.factories import URLPathFactory
from django.contrib.contenttypes.models import ContentType

from ..models import ProfileUserRole
from .factories import ProfileFactory, ProfileUserRoleFactory

pytestmark = pytest.mark.django_db

Profile = swapper.load_model("baseapp_profiles", "Profile")
ProfileUserRole = swapper.load_model("baseapp_profiles", "ProfileUserRole")

GET_PROFILE_BY_PATH = """
query Profile($id: ID!) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import pytest
import swapper
from baseapp_core.tests.factories import UserFactory
from baseapp_pages.tests.factories import URLPathFactory
from django.contrib.auth.models import Permission
from django.test.client import MULTIPART_CONTENT

from .factories import ProfileFactory
from .factories import ProfileFactory, ProfileUserRoleFactory

pytestmark = pytest.mark.django_db

Profile = swapper.load_model("baseapp_profiles", "Profile")
ProfileUserRole = swapper.load_model("baseapp_profiles", "ProfileUserRole")

PROFILE_UPDATE_GRAPHQL = """
mutation ProfileUpdateMutation($input: ProfileUpdateInput!) {
Expand All @@ -32,6 +34,22 @@
}
"""

PROFILE_ROLE_UPDATE_GRAPHQL = """
mutation ProfileRoleUpdateMutation($input: RoleUpdateInput!) {
profileRoleUpdate(input: $input) {
profileUserRole {
id
role
status
}
errors {
field
messages
}
}
}
"""


def test_anon_cant_update_profile(graphql_client):
profile = ProfileFactory()
Expand Down Expand Up @@ -199,3 +217,81 @@ def test_user_with_permission_can_update_profile(django_user_client, graphql_use
assert content["data"]["profileUpdate"]["profile"]["biography"] == new_biography
profile.refresh_from_db()
assert profile.biography == new_biography


def test_user_profile_owner_can_update_role(django_user_client, graphql_user_client):

perm = Permission.objects.get(
content_type__app_label="baseapp_profiles", codename="change_profileuserrole"
)

user = django_user_client.user
user_2 = UserFactory()

user.user_permissions.add(perm)
profile = ProfileFactory(owner=user)
ProfileUserRoleFactory(profile=profile, user=user_2, role=ProfileUserRole.ProfileRoles.MANAGER)

response = graphql_user_client(
PROFILE_ROLE_UPDATE_GRAPHQL,
variables={
"input": {"userId": user_2.relay_id, "profileId": profile.relay_id, "roleType": "ADMIN"}
},
)
content = response.json()

assert content["data"]["profileRoleUpdate"]["profileUserRole"]["role"] == "ADMIN"
profile.refresh_from_db()


def test_user_with_permission_can_update_role(django_user_client, graphql_user_client):

perm = Permission.objects.get(
content_type__app_label="baseapp_profiles", codename="change_profileuserrole"
)

user = django_user_client.user
user.user_permissions.add(perm)
user_2 = UserFactory()
user_3 = UserFactory()

profile = ProfileFactory(owner=user_2)
ProfileUserRoleFactory(profile=profile, user=user, role=ProfileUserRole.ProfileRoles.ADMIN)
ProfileUserRoleFactory(profile=profile, user=user_3, role=ProfileUserRole.ProfileRoles.MANAGER)

response = graphql_user_client(
PROFILE_ROLE_UPDATE_GRAPHQL,
variables={
"input": {"userId": user_3.relay_id, "profileId": profile.relay_id, "roleType": "ADMIN"}
},
)
content = response.json()

assert content["data"]["profileRoleUpdate"]["profileUserRole"]["role"] == "ADMIN"
profile.refresh_from_db()


def test_user_without_permission_cant_update_role(django_user_client, graphql_user_client):

perm = Permission.objects.get(
content_type__app_label="baseapp_profiles", codename="change_profileuserrole"
)

user = django_user_client.user
user.user_permissions.add(perm)
user_2 = UserFactory()
user_3 = UserFactory()

profile = ProfileFactory(owner=user_2)
ProfileUserRoleFactory(profile=profile, user=user, role=ProfileUserRole.ProfileRoles.MANAGER)
ProfileUserRoleFactory(profile=profile, user=user_3, role=ProfileUserRole.ProfileRoles.MANAGER)

response = graphql_user_client(
PROFILE_ROLE_UPDATE_GRAPHQL,
variables={
"input": {"userId": user_3.relay_id, "profileId": profile.relay_id, "roleType": "ADMIN"}
},
)
content = response.json()
assert content["errors"][0]["message"] == "You don't have permission to perform this action"
profile.refresh_from_db()
2 changes: 1 addition & 1 deletion baseapp-profiles/setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = baseapp_profiles
version = 0.3.5
version = 0.3.6
description = BaseApp Profiles
long_description = file: README.md
long_description_content_type = text/markdown
Expand Down
Loading