✨(back) accept for a owner the request to access a document
Add the action accepting a request to access a document. It is possible to override the role from the request and also update an existing DocumentAccess
This commit is contained in:
@@ -665,10 +665,22 @@ class InvitationSerializer(serializers.ModelSerializer):
|
|||||||
return role
|
return role
|
||||||
|
|
||||||
|
|
||||||
|
class RoleSerializer(serializers.Serializer):
|
||||||
|
"""Serializer validating role choices."""
|
||||||
|
|
||||||
|
role = serializers.ChoiceField(
|
||||||
|
choices=models.RoleChoices.choices, required=False, allow_null=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class DocumentAskForAccessCreateSerializer(serializers.Serializer):
|
class DocumentAskForAccessCreateSerializer(serializers.Serializer):
|
||||||
"""Serializer for creating a document ask for access."""
|
"""Serializer for creating a document ask for access."""
|
||||||
|
|
||||||
role = serializers.ChoiceField(choices=models.RoleChoices.choices, required=False, default=models.RoleChoices.READER)
|
role = serializers.ChoiceField(
|
||||||
|
choices=models.RoleChoices.choices,
|
||||||
|
required=False,
|
||||||
|
default=models.RoleChoices.READER,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class DocumentAskForAccessSerializer(serializers.ModelSerializer):
|
class DocumentAskForAccessSerializer(serializers.ModelSerializer):
|
||||||
@@ -695,7 +707,8 @@ class DocumentAskForAccessSerializer(serializers.ModelSerializer):
|
|||||||
if request:
|
if request:
|
||||||
return invitation.get_abilities(request.user)
|
return invitation.get_abilities(request.user)
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
class VersionFilterSerializer(serializers.Serializer):
|
class VersionFilterSerializer(serializers.Serializer):
|
||||||
"""Validate version filters applied to the list endpoint."""
|
"""Validate version filters applied to the list endpoint."""
|
||||||
|
|
||||||
|
|||||||
@@ -1837,6 +1837,17 @@ class DocumentAskForAccessViewSet(
|
|||||||
|
|
||||||
return drf.response.Response(status=drf.status.HTTP_201_CREATED)
|
return drf.response.Response(status=drf.status.HTTP_201_CREATED)
|
||||||
|
|
||||||
|
@drf.decorators.action(detail=True, methods=["post"])
|
||||||
|
def accept(self, request, *args, **kwargs):
|
||||||
|
"""Accept a document ask for access resource."""
|
||||||
|
document_ask_for_access = self.get_object()
|
||||||
|
|
||||||
|
serializer = serializers.RoleSerializer(data=request.data)
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
|
||||||
|
document_ask_for_access.accept(role=serializer.validated_data.get("role"))
|
||||||
|
return drf.response.Response(status=drf.status.HTTP_204_NO_CONTENT)
|
||||||
|
|
||||||
|
|
||||||
class ConfigView(drf.views.APIView):
|
class ConfigView(drf.views.APIView):
|
||||||
"""API ViewSet for sharing some public settings."""
|
"""API ViewSet for sharing some public settings."""
|
||||||
|
|||||||
@@ -1205,8 +1205,22 @@ class DocumentAskForAccess(BaseModel):
|
|||||||
"update": is_admin_or_owner,
|
"update": is_admin_or_owner,
|
||||||
"partial_update": is_admin_or_owner,
|
"partial_update": is_admin_or_owner,
|
||||||
"retrieve": is_admin_or_owner,
|
"retrieve": is_admin_or_owner,
|
||||||
|
"accept": is_admin_or_owner,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def accept(self, role=None):
|
||||||
|
"""Accept a document ask for access resource."""
|
||||||
|
if role is None:
|
||||||
|
role = self.role
|
||||||
|
|
||||||
|
DocumentAccess.objects.update_or_create(
|
||||||
|
document=self.document,
|
||||||
|
user=self.user,
|
||||||
|
defaults={"role": role},
|
||||||
|
create_defaults={"role": role},
|
||||||
|
)
|
||||||
|
self.delete()
|
||||||
|
|
||||||
|
|
||||||
class Template(BaseModel):
|
class Template(BaseModel):
|
||||||
"""HTML and CSS code used for formatting the print around the MarkDown body."""
|
"""HTML and CSS code used for formatting the print around the MarkDown body."""
|
||||||
|
|||||||
@@ -190,6 +190,7 @@ def test_api_documents_ask_for_access_list_authenticated_own_request():
|
|||||||
"+00:00", "Z"
|
"+00:00", "Z"
|
||||||
),
|
),
|
||||||
"abilities": {
|
"abilities": {
|
||||||
|
"accept": False,
|
||||||
"destroy": False,
|
"destroy": False,
|
||||||
"update": False,
|
"update": False,
|
||||||
"partial_update": False,
|
"partial_update": False,
|
||||||
@@ -277,6 +278,7 @@ def test_api_documents_ask_for_access_list_owner_or_admin(role):
|
|||||||
"+00:00", "Z"
|
"+00:00", "Z"
|
||||||
),
|
),
|
||||||
"abilities": {
|
"abilities": {
|
||||||
|
"accept": True,
|
||||||
"destroy": True,
|
"destroy": True,
|
||||||
"update": True,
|
"update": True,
|
||||||
"partial_update": True,
|
"partial_update": True,
|
||||||
@@ -365,6 +367,7 @@ def test_api_documents_ask_for_access_retrieve_owner_or_admin(role):
|
|||||||
"+00:00", "Z"
|
"+00:00", "Z"
|
||||||
),
|
),
|
||||||
"abilities": {
|
"abilities": {
|
||||||
|
"accept": True,
|
||||||
"destroy": True,
|
"destroy": True,
|
||||||
"update": True,
|
"update": True,
|
||||||
"partial_update": True,
|
"partial_update": True,
|
||||||
@@ -443,3 +446,172 @@ def test_api_documents_ask_for_access_delete_owner_or_admin(role):
|
|||||||
assert not DocumentAskForAccess.objects.filter(
|
assert not DocumentAskForAccess.objects.filter(
|
||||||
id=document_ask_for_access.id
|
id=document_ask_for_access.id
|
||||||
).exists()
|
).exists()
|
||||||
|
|
||||||
|
|
||||||
|
## Accept
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_documents_ask_for_access_accept_anonymous():
|
||||||
|
"""Anonymous users should not be able to accept document ask for access."""
|
||||||
|
document = DocumentFactory()
|
||||||
|
document_ask_for_access = DocumentAskForAccessFactory(
|
||||||
|
document=document, role=RoleChoices.READER
|
||||||
|
)
|
||||||
|
|
||||||
|
client = APIClient()
|
||||||
|
response = client.post(
|
||||||
|
f"/api/v1.0/documents/{document.id}/ask-for-access/{document_ask_for_access.id}/accept/"
|
||||||
|
)
|
||||||
|
assert response.status_code == 401
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_documents_ask_for_access_accept_authenticated():
|
||||||
|
"""Authenticated users should not be able to accept document ask for access."""
|
||||||
|
document = DocumentFactory()
|
||||||
|
document_ask_for_access = DocumentAskForAccessFactory(
|
||||||
|
document=document, role=RoleChoices.READER
|
||||||
|
)
|
||||||
|
|
||||||
|
client = APIClient()
|
||||||
|
client.force_login(UserFactory())
|
||||||
|
response = client.post(
|
||||||
|
f"/api/v1.0/documents/{document.id}/ask-for-access/{document_ask_for_access.id}/accept/"
|
||||||
|
)
|
||||||
|
assert response.status_code == 404
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("role", [RoleChoices.READER, RoleChoices.EDITOR])
|
||||||
|
def test_api_documents_ask_for_access_accept_authenticated_non_owner_or_admin(role):
|
||||||
|
"""Non owner or admin users should not be able to accept document ask for access."""
|
||||||
|
user = UserFactory()
|
||||||
|
document = DocumentFactory(users=[(user, role)])
|
||||||
|
document_ask_for_access = DocumentAskForAccessFactory(
|
||||||
|
document=document, role=RoleChoices.READER
|
||||||
|
)
|
||||||
|
|
||||||
|
client = APIClient()
|
||||||
|
client.force_login(user)
|
||||||
|
|
||||||
|
response = client.post(
|
||||||
|
f"/api/v1.0/documents/{document.id}/ask-for-access/{document_ask_for_access.id}/accept/"
|
||||||
|
)
|
||||||
|
assert response.status_code == 404
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("role", [RoleChoices.OWNER, RoleChoices.ADMIN])
|
||||||
|
def test_api_documents_ask_for_access_accept_owner_or_admin(role):
|
||||||
|
"""Owner or admin users should be able to accept document ask for access."""
|
||||||
|
user = UserFactory()
|
||||||
|
document = DocumentFactory(users=[(user, role)])
|
||||||
|
document_ask_for_access = DocumentAskForAccessFactory(
|
||||||
|
document=document, role=RoleChoices.READER
|
||||||
|
)
|
||||||
|
|
||||||
|
client = APIClient()
|
||||||
|
client.force_login(user)
|
||||||
|
|
||||||
|
response = client.post(
|
||||||
|
f"/api/v1.0/documents/{document.id}/ask-for-access/{document_ask_for_access.id}/accept/"
|
||||||
|
)
|
||||||
|
assert response.status_code == 204
|
||||||
|
|
||||||
|
assert not DocumentAskForAccess.objects.filter(
|
||||||
|
id=document_ask_for_access.id
|
||||||
|
).exists()
|
||||||
|
assert DocumentAccess.objects.filter(
|
||||||
|
document=document, user=document_ask_for_access.user, role=RoleChoices.READER
|
||||||
|
).exists()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("role", [RoleChoices.OWNER, RoleChoices.ADMIN])
|
||||||
|
def test_api_documents_ask_for_access_accept_authenticated_specific_role(role):
|
||||||
|
"""
|
||||||
|
Owner or admin users should be able to accept document ask for access with a specific role.
|
||||||
|
"""
|
||||||
|
user = UserFactory()
|
||||||
|
document = DocumentFactory(users=[(user, role)])
|
||||||
|
document_ask_for_access = DocumentAskForAccessFactory(
|
||||||
|
document=document, role=RoleChoices.READER
|
||||||
|
)
|
||||||
|
|
||||||
|
client = APIClient()
|
||||||
|
client.force_login(user)
|
||||||
|
|
||||||
|
response = client.post(
|
||||||
|
f"/api/v1.0/documents/{document.id}/ask-for-access/{document_ask_for_access.id}/accept/",
|
||||||
|
data={"role": RoleChoices.EDITOR},
|
||||||
|
)
|
||||||
|
assert response.status_code == 204
|
||||||
|
|
||||||
|
assert not DocumentAskForAccess.objects.filter(
|
||||||
|
id=document_ask_for_access.id
|
||||||
|
).exists()
|
||||||
|
assert DocumentAccess.objects.filter(
|
||||||
|
document=document, user=document_ask_for_access.user, role=RoleChoices.EDITOR
|
||||||
|
).exists()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("role", [RoleChoices.OWNER, RoleChoices.ADMIN])
|
||||||
|
def test_api_documents_ask_for_access_accept_authenticated_owner_or_admin_update_access(
|
||||||
|
role,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Owner or admin users should be able to accept document ask for access and update the access.
|
||||||
|
"""
|
||||||
|
user = UserFactory()
|
||||||
|
document = DocumentFactory(users=[(user, role)])
|
||||||
|
document_access = UserDocumentAccessFactory(
|
||||||
|
document=document, role=RoleChoices.READER
|
||||||
|
)
|
||||||
|
document_ask_for_access = DocumentAskForAccessFactory(
|
||||||
|
document=document, user=document_access.user, role=RoleChoices.EDITOR
|
||||||
|
)
|
||||||
|
|
||||||
|
client = APIClient()
|
||||||
|
client.force_login(user)
|
||||||
|
|
||||||
|
response = client.post(
|
||||||
|
f"/api/v1.0/documents/{document.id}/ask-for-access/{document_ask_for_access.id}/accept/",
|
||||||
|
data={"role": RoleChoices.EDITOR},
|
||||||
|
)
|
||||||
|
assert response.status_code == 204
|
||||||
|
|
||||||
|
assert not DocumentAskForAccess.objects.filter(
|
||||||
|
id=document_ask_for_access.id
|
||||||
|
).exists()
|
||||||
|
document_access.refresh_from_db()
|
||||||
|
assert document_access.role == RoleChoices.EDITOR
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("role", [RoleChoices.OWNER, RoleChoices.ADMIN])
|
||||||
|
# pylint: disable=line-too-long
|
||||||
|
def test_api_documents_ask_for_access_accept_authenticated_owner_or_admin_update_access_with_specific_role(
|
||||||
|
role,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Owner or admin users should be able to accept document ask for access and update the access
|
||||||
|
with a specific role.
|
||||||
|
"""
|
||||||
|
user = UserFactory()
|
||||||
|
document = DocumentFactory(users=[(user, role)])
|
||||||
|
document_access = UserDocumentAccessFactory(
|
||||||
|
document=document, role=RoleChoices.READER
|
||||||
|
)
|
||||||
|
document_ask_for_access = DocumentAskForAccessFactory(
|
||||||
|
document=document, user=document_access.user, role=RoleChoices.EDITOR
|
||||||
|
)
|
||||||
|
|
||||||
|
client = APIClient()
|
||||||
|
client.force_login(user)
|
||||||
|
|
||||||
|
response = client.post(
|
||||||
|
f"/api/v1.0/documents/{document.id}/ask-for-access/{document_ask_for_access.id}/accept/",
|
||||||
|
data={"role": RoleChoices.ADMIN},
|
||||||
|
)
|
||||||
|
assert response.status_code == 204
|
||||||
|
|
||||||
|
assert not DocumentAskForAccess.objects.filter(
|
||||||
|
id=document_ask_for_access.id
|
||||||
|
).exists()
|
||||||
|
document_access.refresh_from_db()
|
||||||
|
assert document_access.role == RoleChoices.ADMIN
|
||||||
|
|||||||
Reference in New Issue
Block a user