♻️(models) rename document/template access rights
The "member" access right does not make sense for documents and templates. What we really need are "editor" and "reader" access rights.
This commit is contained in:
committed by
Samuel Paccoud
parent
51325df7d9
commit
926fe37e85
@@ -91,7 +91,7 @@ class DocumentAdmin(admin.ModelAdmin):
|
|||||||
"""Document admin interface declaration."""
|
"""Document admin interface declaration."""
|
||||||
|
|
||||||
inlines = (DocumentAccessInline,)
|
inlines = (DocumentAccessInline,)
|
||||||
|
|
||||||
|
|
||||||
@admin.register(models.Invitation)
|
@admin.register(models.Invitation)
|
||||||
class InvitationAdmin(admin.ModelAdmin):
|
class InvitationAdmin(admin.ModelAdmin):
|
||||||
@@ -119,4 +119,3 @@ class InvitationAdmin(admin.ModelAdmin):
|
|||||||
def save_model(self, request, obj, form, change):
|
def save_model(self, request, obj, form, change):
|
||||||
obj.issuer = request.user
|
obj.issuer = request.user
|
||||||
obj.save()
|
obj.save()
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
"""API endpoints"""
|
"""API endpoints"""
|
||||||
import json
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
from django.contrib.postgres.aggregates import ArrayAgg
|
from django.contrib.postgres.aggregates import ArrayAgg
|
||||||
@@ -368,15 +367,15 @@ class DocumentAccessViewSet(
|
|||||||
|
|
||||||
POST /api/v1.0/documents/<resource_id>/accesses/ with expected data:
|
POST /api/v1.0/documents/<resource_id>/accesses/ with expected data:
|
||||||
- user: str
|
- user: str
|
||||||
- role: str [owner|admin|member]
|
- role: str [administrator|editor|reader]
|
||||||
Return newly created document access
|
Return newly created document access
|
||||||
|
|
||||||
PUT /api/v1.0/documents/<resource_id>/accesses/<document_access_id>/ with expected data:
|
PUT /api/v1.0/documents/<resource_id>/accesses/<document_access_id>/ with expected data:
|
||||||
- role: str [owner|admin|member]
|
- role: str [owner|admin|editor|reader]
|
||||||
Return updated document access
|
Return updated document access
|
||||||
|
|
||||||
PATCH /api/v1.0/documents/<resource_id>/accesses/<document_access_id>/ with expected data:
|
PATCH /api/v1.0/documents/<resource_id>/accesses/<document_access_id>/ with expected data:
|
||||||
- role: str [owner|admin|member]
|
- role: str [owner|admin|editor|reader]
|
||||||
Return partially updated document access
|
Return partially updated document access
|
||||||
|
|
||||||
DELETE /api/v1.0/documents/<resource_id>/accesses/<document_access_id>/
|
DELETE /api/v1.0/documents/<resource_id>/accesses/<document_access_id>/
|
||||||
@@ -458,15 +457,15 @@ class TemplateAccessViewSet(
|
|||||||
|
|
||||||
POST /api/v1.0/templates/<template_id>/accesses/ with expected data:
|
POST /api/v1.0/templates/<template_id>/accesses/ with expected data:
|
||||||
- user: str
|
- user: str
|
||||||
- role: str [owner|admin|member]
|
- role: str [administrator|editor|reader]
|
||||||
Return newly created template access
|
Return newly created template access
|
||||||
|
|
||||||
PUT /api/v1.0/templates/<template_id>/accesses/<template_access_id>/ with expected data:
|
PUT /api/v1.0/templates/<template_id>/accesses/<template_access_id>/ with expected data:
|
||||||
- role: str [owner|admin|member]
|
- role: str [owner|admin|editor|reader]
|
||||||
Return updated template access
|
Return updated template access
|
||||||
|
|
||||||
PATCH /api/v1.0/templates/<template_id>/accesses/<template_access_id>/ with expected data:
|
PATCH /api/v1.0/templates/<template_id>/accesses/<template_access_id>/ with expected data:
|
||||||
- role: str [owner|admin|member]
|
- role: str [owner|admin|editor|reader]
|
||||||
Return partially updated template access
|
Return partially updated template access
|
||||||
|
|
||||||
DELETE /api/v1.0/templates/<template_id>/accesses/<template_access_id>/
|
DELETE /api/v1.0/templates/<template_id>/accesses/<template_access_id>/
|
||||||
@@ -496,7 +495,7 @@ class InvitationViewset(
|
|||||||
|
|
||||||
POST /api/v1.0/documents/<document_id>/invitations/ with expected data:
|
POST /api/v1.0/documents/<document_id>/invitations/ with expected data:
|
||||||
- email: str
|
- email: str
|
||||||
- role: str [owner|admin|member]
|
- role: str [administrator|editor|reader]
|
||||||
Return newly created invitation (issuer and document are automatically set)
|
Return newly created invitation (issuer and document are automatically set)
|
||||||
|
|
||||||
PUT / PATCH : Not permitted. Instead of updating your invitation,
|
PUT / PATCH : Not permitted. Instead of updating your invitation,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Generated by Django 5.0.3 on 2024-04-19 11:38
|
# Generated by Django 5.0.3 on 2024-05-28 20:29
|
||||||
|
|
||||||
import django.contrib.auth.models
|
import django.contrib.auth.models
|
||||||
import django.core.validators
|
import django.core.validators
|
||||||
@@ -89,7 +89,7 @@ class Migration(migrations.Migration):
|
|||||||
('created_at', models.DateTimeField(auto_now_add=True, help_text='date and time at which a record was created', verbose_name='created on')),
|
('created_at', models.DateTimeField(auto_now_add=True, help_text='date and time at which a record was created', verbose_name='created on')),
|
||||||
('updated_at', models.DateTimeField(auto_now=True, help_text='date and time at which a record was last updated', verbose_name='updated on')),
|
('updated_at', models.DateTimeField(auto_now=True, help_text='date and time at which a record was last updated', verbose_name='updated on')),
|
||||||
('team', models.CharField(blank=True, max_length=100)),
|
('team', models.CharField(blank=True, max_length=100)),
|
||||||
('role', models.CharField(choices=[('member', 'Member'), ('administrator', 'Administrator'), ('owner', 'Owner')], default='member', max_length=20)),
|
('role', models.CharField(choices=[('reader', 'Reader'), ('editor', 'Editor'), ('administrator', 'Administrator'), ('owner', 'Owner')], default='reader', max_length=20)),
|
||||||
('document', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='accesses', to='core.document')),
|
('document', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='accesses', to='core.document')),
|
||||||
('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||||
],
|
],
|
||||||
@@ -100,6 +100,23 @@ class Migration(migrations.Migration):
|
|||||||
'ordering': ('-created_at',),
|
'ordering': ('-created_at',),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Invitation',
|
||||||
|
fields=[
|
||||||
|
('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='primary key for the record as UUID', primary_key=True, serialize=False, verbose_name='id')),
|
||||||
|
('created_at', models.DateTimeField(auto_now_add=True, help_text='date and time at which a record was created', verbose_name='created on')),
|
||||||
|
('updated_at', models.DateTimeField(auto_now=True, help_text='date and time at which a record was last updated', verbose_name='updated on')),
|
||||||
|
('email', models.EmailField(max_length=254, verbose_name='email address')),
|
||||||
|
('role', models.CharField(choices=[('reader', 'Reader'), ('editor', 'Editor'), ('administrator', 'Administrator'), ('owner', 'Owner')], default='reader', max_length=20)),
|
||||||
|
('document', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='invitations', to='core.document')),
|
||||||
|
('issuer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='invitations', to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'Document invitation',
|
||||||
|
'verbose_name_plural': 'Document invitations',
|
||||||
|
'db_table': 'impress_invitation',
|
||||||
|
},
|
||||||
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='TemplateAccess',
|
name='TemplateAccess',
|
||||||
fields=[
|
fields=[
|
||||||
@@ -107,7 +124,7 @@ class Migration(migrations.Migration):
|
|||||||
('created_at', models.DateTimeField(auto_now_add=True, help_text='date and time at which a record was created', verbose_name='created on')),
|
('created_at', models.DateTimeField(auto_now_add=True, help_text='date and time at which a record was created', verbose_name='created on')),
|
||||||
('updated_at', models.DateTimeField(auto_now=True, help_text='date and time at which a record was last updated', verbose_name='updated on')),
|
('updated_at', models.DateTimeField(auto_now=True, help_text='date and time at which a record was last updated', verbose_name='updated on')),
|
||||||
('team', models.CharField(blank=True, max_length=100)),
|
('team', models.CharField(blank=True, max_length=100)),
|
||||||
('role', models.CharField(choices=[('member', 'Member'), ('administrator', 'Administrator'), ('owner', 'Owner')], default='member', max_length=20)),
|
('role', models.CharField(choices=[('reader', 'Reader'), ('editor', 'Editor'), ('administrator', 'Administrator'), ('owner', 'Owner')], default='reader', max_length=20)),
|
||||||
('template', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='accesses', to='core.template')),
|
('template', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='accesses', to='core.template')),
|
||||||
('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||||
],
|
],
|
||||||
@@ -130,6 +147,10 @@ class Migration(migrations.Migration):
|
|||||||
model_name='documentaccess',
|
model_name='documentaccess',
|
||||||
constraint=models.CheckConstraint(check=models.Q(models.Q(('team', ''), ('user__isnull', False)), models.Q(('team__gt', ''), ('user__isnull', True)), _connector='OR'), name='check_document_access_either_user_or_team', violation_error_message='Either user or team must be set, not both.'),
|
constraint=models.CheckConstraint(check=models.Q(models.Q(('team', ''), ('user__isnull', False)), models.Q(('team__gt', ''), ('user__isnull', True)), _connector='OR'), name='check_document_access_either_user_or_team', violation_error_message='Either user or team must be set, not both.'),
|
||||||
),
|
),
|
||||||
|
migrations.AddConstraint(
|
||||||
|
model_name='invitation',
|
||||||
|
constraint=models.UniqueConstraint(fields=('email', 'document'), name='email_and_document_unique_together'),
|
||||||
|
),
|
||||||
migrations.AddConstraint(
|
migrations.AddConstraint(
|
||||||
model_name='templateaccess',
|
model_name='templateaccess',
|
||||||
constraint=models.UniqueConstraint(condition=models.Q(('user__isnull', False)), fields=('user', 'template'), name='unique_template_user', violation_error_message='This user is already in this template.'),
|
constraint=models.UniqueConstraint(condition=models.Q(('user__isnull', False)), fields=('user', 'template'), name='unique_template_user', violation_error_message='This user is already in this template.'),
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
# Generated by Django 5.0.3 on 2024-05-12 19:02
|
|
||||||
|
|
||||||
import django.db.models.deletion
|
|
||||||
import uuid
|
|
||||||
from django.conf import settings
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('core', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='user',
|
|
||||||
name='language',
|
|
||||||
field=models.CharField(choices="(('en-us', 'English'), ('fr-fr', 'French'))", default='en-us', help_text='The language in which the user wants to see the interface.', max_length=10, verbose_name='language'),
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Invitation',
|
|
||||||
fields=[
|
|
||||||
('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='primary key for the record as UUID', primary_key=True, serialize=False, verbose_name='id')),
|
|
||||||
('created_at', models.DateTimeField(auto_now_add=True, help_text='date and time at which a record was created', verbose_name='created on')),
|
|
||||||
('updated_at', models.DateTimeField(auto_now=True, help_text='date and time at which a record was last updated', verbose_name='updated on')),
|
|
||||||
('email', models.EmailField(max_length=254, verbose_name='email address')),
|
|
||||||
('role', models.CharField(choices=[('member', 'Member'), ('administrator', 'Administrator'), ('owner', 'Owner')], default='member', max_length=20)),
|
|
||||||
('document', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='invitations', to='core.document')),
|
|
||||||
('issuer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='invitations', to=settings.AUTH_USER_MODEL)),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'verbose_name': 'Document invitation',
|
|
||||||
'verbose_name_plural': 'Document invitations',
|
|
||||||
'db_table': 'impress_invitation',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.AddConstraint(
|
|
||||||
model_name='invitation',
|
|
||||||
constraint=models.UniqueConstraint(fields=('email', 'document'), name='email_and_document_unique_together'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
Declare and configure the models for the impress core application
|
Declare and configure the models for the impress core application
|
||||||
"""
|
"""
|
||||||
import hashlib
|
import hashlib
|
||||||
import json
|
|
||||||
import smtplib
|
import smtplib
|
||||||
import textwrap
|
import textwrap
|
||||||
import uuid
|
import uuid
|
||||||
@@ -55,8 +54,9 @@ def get_resource_roles(resource, user):
|
|||||||
class RoleChoices(models.TextChoices):
|
class RoleChoices(models.TextChoices):
|
||||||
"""Defines the possible roles a user can have in a template."""
|
"""Defines the possible roles a user can have in a template."""
|
||||||
|
|
||||||
MEMBER = "member", _("Member")
|
READER = "reader", _("Reader") # Can read
|
||||||
ADMIN = "administrator", _("Administrator")
|
EDITOR = "editor", _("Editor") # Can read and edit
|
||||||
|
ADMIN = "administrator", _("Administrator") # Can read, edit, delete and share
|
||||||
OWNER = "owner", _("Owner")
|
OWNER = "owner", _("Owner")
|
||||||
|
|
||||||
|
|
||||||
@@ -233,7 +233,7 @@ class BaseAccess(BaseModel):
|
|||||||
)
|
)
|
||||||
team = models.CharField(max_length=100, blank=True)
|
team = models.CharField(max_length=100, blank=True)
|
||||||
role = models.CharField(
|
role = models.CharField(
|
||||||
max_length=20, choices=RoleChoices.choices, default=RoleChoices.MEMBER
|
max_length=20, choices=RoleChoices.choices, default=RoleChoices.READER
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@@ -265,14 +265,20 @@ class BaseAccess(BaseModel):
|
|||||||
RoleChoices.OWNER in roles
|
RoleChoices.OWNER in roles
|
||||||
and resource.accesses.filter(role=RoleChoices.OWNER).count() > 1
|
and resource.accesses.filter(role=RoleChoices.OWNER).count() > 1
|
||||||
)
|
)
|
||||||
set_role_to = [RoleChoices.ADMIN, RoleChoices.MEMBER] if can_delete else []
|
set_role_to = (
|
||||||
|
[RoleChoices.ADMIN, RoleChoices.EDITOR, RoleChoices.READER]
|
||||||
|
if can_delete
|
||||||
|
else []
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
can_delete = is_owner_or_admin
|
can_delete = is_owner_or_admin
|
||||||
set_role_to = []
|
set_role_to = []
|
||||||
if RoleChoices.OWNER in roles:
|
if RoleChoices.OWNER in roles:
|
||||||
set_role_to.append(RoleChoices.OWNER)
|
set_role_to.append(RoleChoices.OWNER)
|
||||||
if is_owner_or_admin:
|
if is_owner_or_admin:
|
||||||
set_role_to.extend([RoleChoices.ADMIN, RoleChoices.MEMBER])
|
set_role_to.extend(
|
||||||
|
[RoleChoices.ADMIN, RoleChoices.EDITOR, RoleChoices.READER]
|
||||||
|
)
|
||||||
|
|
||||||
# Remove the current role as we don't want to propose it as an option
|
# Remove the current role as we don't want to propose it as an option
|
||||||
try:
|
try:
|
||||||
@@ -325,7 +331,7 @@ class Document(BaseModel):
|
|||||||
except (FileNotFoundError, ClientError):
|
except (FileNotFoundError, ClientError):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
self._content = response["Body"].read().decode('utf-8')
|
self._content = response["Body"].read().decode("utf-8")
|
||||||
return self._content
|
return self._content
|
||||||
|
|
||||||
@content.setter
|
@content.setter
|
||||||
@@ -333,7 +339,7 @@ class Document(BaseModel):
|
|||||||
"""Cache the content, don't write to object storage yet"""
|
"""Cache the content, don't write to object storage yet"""
|
||||||
if not isinstance(content, str):
|
if not isinstance(content, str):
|
||||||
raise ValueError("content should be a string.")
|
raise ValueError("content should be a string.")
|
||||||
|
|
||||||
self._content = content
|
self._content = content
|
||||||
|
|
||||||
def get_content_response(self, version_id=""):
|
def get_content_response(self, version_id=""):
|
||||||
@@ -447,6 +453,7 @@ class Document(BaseModel):
|
|||||||
is_owner_or_admin = bool(
|
is_owner_or_admin = bool(
|
||||||
set(roles).intersection({RoleChoices.OWNER, RoleChoices.ADMIN})
|
set(roles).intersection({RoleChoices.OWNER, RoleChoices.ADMIN})
|
||||||
)
|
)
|
||||||
|
is_editor = bool(RoleChoices.EDITOR in roles)
|
||||||
can_get = self.is_public or bool(roles)
|
can_get = self.is_public or bool(roles)
|
||||||
can_get_versions = bool(roles)
|
can_get_versions = bool(roles)
|
||||||
|
|
||||||
@@ -456,8 +463,8 @@ class Document(BaseModel):
|
|||||||
"versions_list": can_get_versions,
|
"versions_list": can_get_versions,
|
||||||
"versions_retrieve": can_get_versions,
|
"versions_retrieve": can_get_versions,
|
||||||
"manage_accesses": is_owner_or_admin,
|
"manage_accesses": is_owner_or_admin,
|
||||||
"update": is_owner_or_admin,
|
"update": is_owner_or_admin or is_editor,
|
||||||
"partial_update": is_owner_or_admin,
|
"partial_update": is_owner_or_admin or is_editor,
|
||||||
"retrieve": can_get,
|
"retrieve": can_get,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,14 +544,15 @@ class Template(BaseModel):
|
|||||||
is_owner_or_admin = bool(
|
is_owner_or_admin = bool(
|
||||||
set(roles).intersection({RoleChoices.OWNER, RoleChoices.ADMIN})
|
set(roles).intersection({RoleChoices.OWNER, RoleChoices.ADMIN})
|
||||||
)
|
)
|
||||||
|
is_editor = bool(RoleChoices.EDITOR in roles)
|
||||||
can_get = self.is_public or bool(roles)
|
can_get = self.is_public or bool(roles)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"destroy": RoleChoices.OWNER in roles,
|
"destroy": RoleChoices.OWNER in roles,
|
||||||
"generate_document": can_get,
|
"generate_document": can_get,
|
||||||
"manage_accesses": is_owner_or_admin,
|
"manage_accesses": is_owner_or_admin,
|
||||||
"update": is_owner_or_admin,
|
"update": is_owner_or_admin or is_editor,
|
||||||
"partial_update": is_owner_or_admin,
|
"partial_update": is_owner_or_admin or is_editor,
|
||||||
"retrieve": can_get,
|
"retrieve": can_get,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -631,7 +639,7 @@ class Invitation(BaseModel):
|
|||||||
related_name="invitations",
|
related_name="invitations",
|
||||||
)
|
)
|
||||||
role = models.CharField(
|
role = models.CharField(
|
||||||
max_length=20, choices=RoleChoices.choices, default=RoleChoices.MEMBER
|
max_length=20, choices=RoleChoices.choices, default=RoleChoices.READER
|
||||||
)
|
)
|
||||||
issuer = models.ForeignKey(
|
issuer = models.ForeignKey(
|
||||||
User,
|
User,
|
||||||
|
|||||||
@@ -45,14 +45,12 @@ def test_api_documents_delete_authenticated_unrelated():
|
|||||||
assert models.Document.objects.count() == 1
|
assert models.Document.objects.count() == 1
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("role", ["member", "administrator"])
|
@pytest.mark.parametrize("role", ["reader", "editor", "administrator"])
|
||||||
@pytest.mark.parametrize("via", VIA)
|
@pytest.mark.parametrize("via", VIA)
|
||||||
def test_api_documents_delete_authenticated_member_or_administrator(
|
def test_api_documents_delete_authenticated_not_owner(via, role, mock_user_get_teams):
|
||||||
via, role, mock_user_get_teams
|
|
||||||
):
|
|
||||||
"""
|
"""
|
||||||
Authenticated users should not be allowed to delete a document for which they are
|
Authenticated users should not be allowed to delete a document for which they are
|
||||||
only a member or administrator.
|
only a reader, editor or administrator.
|
||||||
"""
|
"""
|
||||||
user = factories.UserFactory()
|
user = factories.UserFactory()
|
||||||
|
|
||||||
|
|||||||
@@ -161,7 +161,10 @@ def test_api_documents_retrieve_authenticated_related_team_none(mock_user_get_te
|
|||||||
document = factories.DocumentFactory(is_public=False)
|
document = factories.DocumentFactory(is_public=False)
|
||||||
|
|
||||||
factories.TeamDocumentAccessFactory(
|
factories.TeamDocumentAccessFactory(
|
||||||
document=document, team="members", role="member"
|
document=document, team="readers", role="reader"
|
||||||
|
)
|
||||||
|
factories.TeamDocumentAccessFactory(
|
||||||
|
document=document, team="editors", role="editor"
|
||||||
)
|
)
|
||||||
factories.TeamDocumentAccessFactory(
|
factories.TeamDocumentAccessFactory(
|
||||||
document=document, team="administrators", role="administrator"
|
document=document, team="administrators", role="administrator"
|
||||||
@@ -178,8 +181,10 @@ def test_api_documents_retrieve_authenticated_related_team_none(mock_user_get_te
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"teams",
|
"teams",
|
||||||
[
|
[
|
||||||
["members"],
|
["readers"],
|
||||||
["unknown", "members"],
|
["unknown", "readers"],
|
||||||
|
["editors"],
|
||||||
|
["unknown", "editors"],
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_api_documents_retrieve_authenticated_related_team_members(
|
def test_api_documents_retrieve_authenticated_related_team_members(
|
||||||
@@ -198,8 +203,11 @@ def test_api_documents_retrieve_authenticated_related_team_members(
|
|||||||
|
|
||||||
document = factories.DocumentFactory(is_public=False)
|
document = factories.DocumentFactory(is_public=False)
|
||||||
|
|
||||||
access_member = factories.TeamDocumentAccessFactory(
|
access_reader = factories.TeamDocumentAccessFactory(
|
||||||
document=document, team="members", role="member"
|
document=document, team="readers", role="reader"
|
||||||
|
)
|
||||||
|
access_editor = factories.TeamDocumentAccessFactory(
|
||||||
|
document=document, team="editors", role="editor"
|
||||||
)
|
)
|
||||||
access_administrator = factories.TeamDocumentAccessFactory(
|
access_administrator = factories.TeamDocumentAccessFactory(
|
||||||
document=document, team="administrators", role="administrator"
|
document=document, team="administrators", role="administrator"
|
||||||
@@ -222,10 +230,17 @@ def test_api_documents_retrieve_authenticated_related_team_members(
|
|||||||
assert sorted(content.pop("accesses"), key=lambda x: x["id"]) == sorted(
|
assert sorted(content.pop("accesses"), key=lambda x: x["id"]) == sorted(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"id": str(access_member.id),
|
"id": str(access_reader.id),
|
||||||
"user": None,
|
"user": None,
|
||||||
"team": "members",
|
"team": "readers",
|
||||||
"role": access_member.role,
|
"role": access_reader.role,
|
||||||
|
"abilities": expected_abilities,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": str(access_editor.id),
|
||||||
|
"user": None,
|
||||||
|
"team": "editors",
|
||||||
|
"role": access_editor.role,
|
||||||
"abilities": expected_abilities,
|
"abilities": expected_abilities,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -265,7 +280,7 @@ def test_api_documents_retrieve_authenticated_related_team_members(
|
|||||||
"teams",
|
"teams",
|
||||||
[
|
[
|
||||||
["administrators"],
|
["administrators"],
|
||||||
["members", "administrators"],
|
["editors", "administrators"],
|
||||||
["unknown", "administrators"],
|
["unknown", "administrators"],
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@@ -285,8 +300,11 @@ def test_api_documents_retrieve_authenticated_related_team_administrators(
|
|||||||
|
|
||||||
document = factories.DocumentFactory(is_public=False)
|
document = factories.DocumentFactory(is_public=False)
|
||||||
|
|
||||||
access_member = factories.TeamDocumentAccessFactory(
|
access_reader = factories.TeamDocumentAccessFactory(
|
||||||
document=document, team="members", role="member"
|
document=document, team="readers", role="reader"
|
||||||
|
)
|
||||||
|
access_editor = factories.TeamDocumentAccessFactory(
|
||||||
|
document=document, team="editors", role="editor"
|
||||||
)
|
)
|
||||||
access_administrator = factories.TeamDocumentAccessFactory(
|
access_administrator = factories.TeamDocumentAccessFactory(
|
||||||
document=document, team="administrators", role="administrator"
|
document=document, team="administrators", role="administrator"
|
||||||
@@ -305,14 +323,26 @@ def test_api_documents_retrieve_authenticated_related_team_administrators(
|
|||||||
assert sorted(content.pop("accesses"), key=lambda x: x["id"]) == sorted(
|
assert sorted(content.pop("accesses"), key=lambda x: x["id"]) == sorted(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"id": str(access_member.id),
|
"id": str(access_reader.id),
|
||||||
"user": None,
|
"user": None,
|
||||||
"team": "members",
|
"team": "readers",
|
||||||
"role": "member",
|
"role": "reader",
|
||||||
"abilities": {
|
"abilities": {
|
||||||
"destroy": True,
|
"destroy": True,
|
||||||
"retrieve": True,
|
"retrieve": True,
|
||||||
"set_role_to": ["administrator"],
|
"set_role_to": ["administrator", "editor"],
|
||||||
|
"update": True,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": str(access_editor.id),
|
||||||
|
"user": None,
|
||||||
|
"team": "editors",
|
||||||
|
"role": "editor",
|
||||||
|
"abilities": {
|
||||||
|
"destroy": True,
|
||||||
|
"retrieve": True,
|
||||||
|
"set_role_to": ["administrator", "reader"],
|
||||||
"update": True,
|
"update": True,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -324,7 +354,7 @@ def test_api_documents_retrieve_authenticated_related_team_administrators(
|
|||||||
"abilities": {
|
"abilities": {
|
||||||
"destroy": True,
|
"destroy": True,
|
||||||
"retrieve": True,
|
"retrieve": True,
|
||||||
"set_role_to": ["member"],
|
"set_role_to": ["editor", "reader"],
|
||||||
"update": True,
|
"update": True,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -384,8 +414,11 @@ def test_api_documents_retrieve_authenticated_related_team_owners(
|
|||||||
|
|
||||||
document = factories.DocumentFactory(is_public=False)
|
document = factories.DocumentFactory(is_public=False)
|
||||||
|
|
||||||
access_member = factories.TeamDocumentAccessFactory(
|
access_reader = factories.TeamDocumentAccessFactory(
|
||||||
document=document, team="members", role="member"
|
document=document, team="readers", role="reader"
|
||||||
|
)
|
||||||
|
access_editor = factories.TeamDocumentAccessFactory(
|
||||||
|
document=document, team="editors", role="editor"
|
||||||
)
|
)
|
||||||
access_administrator = factories.TeamDocumentAccessFactory(
|
access_administrator = factories.TeamDocumentAccessFactory(
|
||||||
document=document, team="administrators", role="administrator"
|
document=document, team="administrators", role="administrator"
|
||||||
@@ -404,14 +437,26 @@ def test_api_documents_retrieve_authenticated_related_team_owners(
|
|||||||
assert sorted(content.pop("accesses"), key=lambda x: x["id"]) == sorted(
|
assert sorted(content.pop("accesses"), key=lambda x: x["id"]) == sorted(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"id": str(access_member.id),
|
"id": str(access_reader.id),
|
||||||
"user": None,
|
"user": None,
|
||||||
"team": "members",
|
"team": "readers",
|
||||||
"role": "member",
|
"role": "reader",
|
||||||
"abilities": {
|
"abilities": {
|
||||||
"destroy": True,
|
"destroy": True,
|
||||||
"retrieve": True,
|
"retrieve": True,
|
||||||
"set_role_to": ["owner", "administrator"],
|
"set_role_to": ["owner", "administrator", "editor"],
|
||||||
|
"update": True,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": str(access_editor.id),
|
||||||
|
"user": None,
|
||||||
|
"team": "editors",
|
||||||
|
"role": "editor",
|
||||||
|
"abilities": {
|
||||||
|
"destroy": True,
|
||||||
|
"retrieve": True,
|
||||||
|
"set_role_to": ["owner", "administrator", "reader"],
|
||||||
"update": True,
|
"update": True,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -423,7 +468,7 @@ def test_api_documents_retrieve_authenticated_related_team_owners(
|
|||||||
"abilities": {
|
"abilities": {
|
||||||
"destroy": True,
|
"destroy": True,
|
||||||
"retrieve": True,
|
"retrieve": True,
|
||||||
"set_role_to": ["owner", "member"],
|
"set_role_to": ["owner", "editor", "reader"],
|
||||||
"update": True,
|
"update": True,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -436,7 +481,7 @@ def test_api_documents_retrieve_authenticated_related_team_owners(
|
|||||||
# editable only if there is another owner role than the user's team...
|
# editable only if there is another owner role than the user's team...
|
||||||
"destroy": other_access.role == "owner",
|
"destroy": other_access.role == "owner",
|
||||||
"retrieve": True,
|
"retrieve": True,
|
||||||
"set_role_to": ["administrator", "member"]
|
"set_role_to": ["administrator", "editor", "reader"]
|
||||||
if other_access.role == "owner"
|
if other_access.role == "owner"
|
||||||
else [],
|
else [],
|
||||||
"update": other_access.role == "owner",
|
"update": other_access.role == "owner",
|
||||||
|
|||||||
@@ -66,9 +66,9 @@ def test_api_documents_update_authenticated_unrelated():
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("via", VIA)
|
@pytest.mark.parametrize("via", VIA)
|
||||||
def test_api_documents_update_authenticated_members(via, mock_user_get_teams):
|
def test_api_documents_update_authenticated_reader(via, mock_user_get_teams):
|
||||||
"""
|
"""
|
||||||
Users who are members of a document but not administrators should
|
Users who are editors or reader of a document but not administrators should
|
||||||
not be allowed to update it.
|
not be allowed to update it.
|
||||||
"""
|
"""
|
||||||
user = factories.UserFactory()
|
user = factories.UserFactory()
|
||||||
@@ -78,11 +78,11 @@ def test_api_documents_update_authenticated_members(via, mock_user_get_teams):
|
|||||||
|
|
||||||
document = factories.DocumentFactory()
|
document = factories.DocumentFactory()
|
||||||
if via == USER:
|
if via == USER:
|
||||||
factories.UserDocumentAccessFactory(document=document, user=user, role="member")
|
factories.UserDocumentAccessFactory(document=document, user=user, role="reader")
|
||||||
elif via == TEAM:
|
elif via == TEAM:
|
||||||
mock_user_get_teams.return_value = ["lasuite", "unknown"]
|
mock_user_get_teams.return_value = ["lasuite", "unknown"]
|
||||||
factories.TeamDocumentAccessFactory(
|
factories.TeamDocumentAccessFactory(
|
||||||
document=document, team="lasuite", role="member"
|
document=document, team="lasuite", role="reader"
|
||||||
)
|
)
|
||||||
|
|
||||||
old_document_values = serializers.DocumentSerializer(instance=document).data
|
old_document_values = serializers.DocumentSerializer(instance=document).data
|
||||||
@@ -106,12 +106,12 @@ def test_api_documents_update_authenticated_members(via, mock_user_get_teams):
|
|||||||
assert document_values == old_document_values
|
assert document_values == old_document_values
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("role", ["administrator", "owner"])
|
@pytest.mark.parametrize("role", ["editor", "administrator", "owner"])
|
||||||
@pytest.mark.parametrize("via", VIA)
|
@pytest.mark.parametrize("via", VIA)
|
||||||
def test_api_documents_update_authenticated_administrator_or_owner(
|
def test_api_documents_update_authenticated_editor_administrator_or_owner(
|
||||||
via, role, mock_user_get_teams
|
via, role, mock_user_get_teams
|
||||||
):
|
):
|
||||||
"""Administrator or owner of a document should be allowed to update it."""
|
"""A user who is editor, administrator or owner of a document should be allowed to update it."""
|
||||||
user = factories.UserFactory()
|
user = factories.UserFactory()
|
||||||
|
|
||||||
client = APIClient()
|
client = APIClient()
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ def test_api_templates_delete_authenticated_unrelated():
|
|||||||
assert models.Template.objects.count() == 1
|
assert models.Template.objects.count() == 1
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("role", ["member", "administrator"])
|
@pytest.mark.parametrize("role", ["reader", "editor", "administrator"])
|
||||||
@pytest.mark.parametrize("via", VIA)
|
@pytest.mark.parametrize("via", VIA)
|
||||||
def test_api_templates_delete_authenticated_member_or_administrator(
|
def test_api_templates_delete_authenticated_member_or_administrator(
|
||||||
via, role, mock_user_get_teams
|
via, role, mock_user_get_teams
|
||||||
|
|||||||
@@ -160,7 +160,10 @@ def test_api_templates_retrieve_authenticated_related_team_none(mock_user_get_te
|
|||||||
template = factories.TemplateFactory(is_public=False)
|
template = factories.TemplateFactory(is_public=False)
|
||||||
|
|
||||||
factories.TeamTemplateAccessFactory(
|
factories.TeamTemplateAccessFactory(
|
||||||
template=template, team="members", role="member"
|
template=template, team="readers", role="reader"
|
||||||
|
)
|
||||||
|
factories.TeamTemplateAccessFactory(
|
||||||
|
template=template, team="editors", role="editor"
|
||||||
)
|
)
|
||||||
factories.TeamTemplateAccessFactory(
|
factories.TeamTemplateAccessFactory(
|
||||||
template=template, team="administrators", role="administrator"
|
template=template, team="administrators", role="administrator"
|
||||||
@@ -177,11 +180,13 @@ def test_api_templates_retrieve_authenticated_related_team_none(mock_user_get_te
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"teams",
|
"teams",
|
||||||
[
|
[
|
||||||
["members"],
|
["readers"],
|
||||||
["unknown", "members"],
|
["unknown", "readers"],
|
||||||
|
["editors"],
|
||||||
|
["unknown", "editors"],
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_api_templates_retrieve_authenticated_related_team_members(
|
def test_api_templates_retrieve_authenticated_related_team_readers_or_editors(
|
||||||
teams, mock_user_get_teams
|
teams, mock_user_get_teams
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
@@ -197,8 +202,11 @@ def test_api_templates_retrieve_authenticated_related_team_members(
|
|||||||
|
|
||||||
template = factories.TemplateFactory(is_public=False)
|
template = factories.TemplateFactory(is_public=False)
|
||||||
|
|
||||||
access_member = factories.TeamTemplateAccessFactory(
|
access_reader = factories.TeamTemplateAccessFactory(
|
||||||
template=template, team="members", role="member"
|
template=template, team="readers", role="reader"
|
||||||
|
)
|
||||||
|
access_editor = factories.TeamTemplateAccessFactory(
|
||||||
|
template=template, team="editors", role="editor"
|
||||||
)
|
)
|
||||||
access_administrator = factories.TeamTemplateAccessFactory(
|
access_administrator = factories.TeamTemplateAccessFactory(
|
||||||
template=template, team="administrators", role="administrator"
|
template=template, team="administrators", role="administrator"
|
||||||
@@ -221,10 +229,17 @@ def test_api_templates_retrieve_authenticated_related_team_members(
|
|||||||
assert sorted(content.pop("accesses"), key=lambda x: x["id"]) == sorted(
|
assert sorted(content.pop("accesses"), key=lambda x: x["id"]) == sorted(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"id": str(access_member.id),
|
"id": str(access_reader.id),
|
||||||
"user": None,
|
"user": None,
|
||||||
"team": "members",
|
"team": "readers",
|
||||||
"role": access_member.role,
|
"role": access_reader.role,
|
||||||
|
"abilities": expected_abilities,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": str(access_editor.id),
|
||||||
|
"user": None,
|
||||||
|
"team": "editors",
|
||||||
|
"role": access_editor.role,
|
||||||
"abilities": expected_abilities,
|
"abilities": expected_abilities,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -285,8 +300,11 @@ def test_api_templates_retrieve_authenticated_related_team_administrators(
|
|||||||
|
|
||||||
template = factories.TemplateFactory(is_public=False)
|
template = factories.TemplateFactory(is_public=False)
|
||||||
|
|
||||||
access_member = factories.TeamTemplateAccessFactory(
|
access_reader = factories.TeamTemplateAccessFactory(
|
||||||
template=template, team="members", role="member"
|
template=template, team="readers", role="reader"
|
||||||
|
)
|
||||||
|
access_editor = factories.TeamTemplateAccessFactory(
|
||||||
|
template=template, team="editors", role="editor"
|
||||||
)
|
)
|
||||||
access_administrator = factories.TeamTemplateAccessFactory(
|
access_administrator = factories.TeamTemplateAccessFactory(
|
||||||
template=template, team="administrators", role="administrator"
|
template=template, team="administrators", role="administrator"
|
||||||
@@ -304,14 +322,26 @@ def test_api_templates_retrieve_authenticated_related_team_administrators(
|
|||||||
assert sorted(content.pop("accesses"), key=lambda x: x["id"]) == sorted(
|
assert sorted(content.pop("accesses"), key=lambda x: x["id"]) == sorted(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"id": str(access_member.id),
|
"id": str(access_reader.id),
|
||||||
"user": None,
|
"user": None,
|
||||||
"team": "members",
|
"team": "readers",
|
||||||
"role": "member",
|
"role": "reader",
|
||||||
"abilities": {
|
"abilities": {
|
||||||
"destroy": True,
|
"destroy": True,
|
||||||
"retrieve": True,
|
"retrieve": True,
|
||||||
"set_role_to": ["administrator"],
|
"set_role_to": ["administrator", "editor"],
|
||||||
|
"update": True,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": str(access_editor.id),
|
||||||
|
"user": None,
|
||||||
|
"team": "editors",
|
||||||
|
"role": "editor",
|
||||||
|
"abilities": {
|
||||||
|
"destroy": True,
|
||||||
|
"retrieve": True,
|
||||||
|
"set_role_to": ["administrator", "reader"],
|
||||||
"update": True,
|
"update": True,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -323,7 +353,7 @@ def test_api_templates_retrieve_authenticated_related_team_administrators(
|
|||||||
"abilities": {
|
"abilities": {
|
||||||
"destroy": True,
|
"destroy": True,
|
||||||
"retrieve": True,
|
"retrieve": True,
|
||||||
"set_role_to": ["member"],
|
"set_role_to": ["editor", "reader"],
|
||||||
"update": True,
|
"update": True,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -384,8 +414,11 @@ def test_api_templates_retrieve_authenticated_related_team_owners(
|
|||||||
|
|
||||||
template = factories.TemplateFactory(is_public=False)
|
template = factories.TemplateFactory(is_public=False)
|
||||||
|
|
||||||
access_member = factories.TeamTemplateAccessFactory(
|
access_reader = factories.TeamTemplateAccessFactory(
|
||||||
template=template, team="members", role="member"
|
template=template, team="readers", role="reader"
|
||||||
|
)
|
||||||
|
access_editor = factories.TeamTemplateAccessFactory(
|
||||||
|
template=template, team="editors", role="editor"
|
||||||
)
|
)
|
||||||
access_administrator = factories.TeamTemplateAccessFactory(
|
access_administrator = factories.TeamTemplateAccessFactory(
|
||||||
template=template, team="administrators", role="administrator"
|
template=template, team="administrators", role="administrator"
|
||||||
@@ -403,14 +436,26 @@ def test_api_templates_retrieve_authenticated_related_team_owners(
|
|||||||
assert sorted(content.pop("accesses"), key=lambda x: x["id"]) == sorted(
|
assert sorted(content.pop("accesses"), key=lambda x: x["id"]) == sorted(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"id": str(access_member.id),
|
"id": str(access_reader.id),
|
||||||
"user": None,
|
"user": None,
|
||||||
"team": "members",
|
"team": "readers",
|
||||||
"role": "member",
|
"role": "reader",
|
||||||
"abilities": {
|
"abilities": {
|
||||||
"destroy": True,
|
"destroy": True,
|
||||||
"retrieve": True,
|
"retrieve": True,
|
||||||
"set_role_to": ["owner", "administrator"],
|
"set_role_to": ["owner", "administrator", "editor"],
|
||||||
|
"update": True,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": str(access_editor.id),
|
||||||
|
"user": None,
|
||||||
|
"team": "editors",
|
||||||
|
"role": "editor",
|
||||||
|
"abilities": {
|
||||||
|
"destroy": True,
|
||||||
|
"retrieve": True,
|
||||||
|
"set_role_to": ["owner", "administrator", "reader"],
|
||||||
"update": True,
|
"update": True,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -422,7 +467,7 @@ def test_api_templates_retrieve_authenticated_related_team_owners(
|
|||||||
"abilities": {
|
"abilities": {
|
||||||
"destroy": True,
|
"destroy": True,
|
||||||
"retrieve": True,
|
"retrieve": True,
|
||||||
"set_role_to": ["owner", "member"],
|
"set_role_to": ["owner", "editor", "reader"],
|
||||||
"update": True,
|
"update": True,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -435,7 +480,7 @@ def test_api_templates_retrieve_authenticated_related_team_owners(
|
|||||||
# editable only if there is another owner role than the user's team...
|
# editable only if there is another owner role than the user's team...
|
||||||
"destroy": other_access.role == "owner",
|
"destroy": other_access.role == "owner",
|
||||||
"retrieve": True,
|
"retrieve": True,
|
||||||
"set_role_to": ["administrator", "member"]
|
"set_role_to": ["administrator", "editor", "reader"]
|
||||||
if other_access.role == "owner"
|
if other_access.role == "owner"
|
||||||
else [],
|
else [],
|
||||||
"update": other_access.role == "owner",
|
"update": other_access.role == "owner",
|
||||||
|
|||||||
@@ -66,10 +66,9 @@ def test_api_templates_update_authenticated_unrelated():
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("via", VIA)
|
@pytest.mark.parametrize("via", VIA)
|
||||||
def test_api_templates_update_authenticated_members(via, mock_user_get_teams):
|
def test_api_templates_update_authenticated_readers(via, mock_user_get_teams):
|
||||||
"""
|
"""
|
||||||
Users who are members of a template but not administrators should
|
Users who are readers of a template should not be allowed to update it.
|
||||||
not be allowed to update it.
|
|
||||||
"""
|
"""
|
||||||
user = factories.UserFactory()
|
user = factories.UserFactory()
|
||||||
|
|
||||||
@@ -78,11 +77,11 @@ def test_api_templates_update_authenticated_members(via, mock_user_get_teams):
|
|||||||
|
|
||||||
template = factories.TemplateFactory()
|
template = factories.TemplateFactory()
|
||||||
if via == USER:
|
if via == USER:
|
||||||
factories.UserTemplateAccessFactory(template=template, user=user, role="member")
|
factories.UserTemplateAccessFactory(template=template, user=user, role="reader")
|
||||||
elif via == TEAM:
|
elif via == TEAM:
|
||||||
mock_user_get_teams.return_value = ["lasuite", "unknown"]
|
mock_user_get_teams.return_value = ["lasuite", "unknown"]
|
||||||
factories.TeamTemplateAccessFactory(
|
factories.TeamTemplateAccessFactory(
|
||||||
template=template, team="lasuite", role="member"
|
template=template, team="lasuite", role="reader"
|
||||||
)
|
)
|
||||||
|
|
||||||
old_template_values = serializers.TemplateSerializer(instance=template).data
|
old_template_values = serializers.TemplateSerializer(instance=template).data
|
||||||
@@ -106,9 +105,9 @@ def test_api_templates_update_authenticated_members(via, mock_user_get_teams):
|
|||||||
assert template_values == old_template_values
|
assert template_values == old_template_values
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("role", ["administrator", "owner"])
|
@pytest.mark.parametrize("role", ["editor", "administrator", "owner"])
|
||||||
@pytest.mark.parametrize("via", VIA)
|
@pytest.mark.parametrize("via", VIA)
|
||||||
def test_api_templates_update_authenticated_administrator_or_owner(
|
def test_api_templates_update_authenticated_editor_or_administrator_or_owner(
|
||||||
via, role, mock_user_get_teams
|
via, role, mock_user_get_teams
|
||||||
):
|
):
|
||||||
"""Administrator or owner of a template should be allowed to update it."""
|
"""Administrator or owner of a template should be allowed to update it."""
|
||||||
|
|||||||
@@ -254,9 +254,12 @@ def test_api_document_accesses_create_authenticated_unrelated():
|
|||||||
assert not models.DocumentAccess.objects.filter(user=other_user).exists()
|
assert not models.DocumentAccess.objects.filter(user=other_user).exists()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("role", ["reader", "editor"])
|
||||||
@pytest.mark.parametrize("via", VIA)
|
@pytest.mark.parametrize("via", VIA)
|
||||||
def test_api_document_accesses_create_authenticated_member(via, mock_user_get_teams):
|
def test_api_document_accesses_create_authenticated_reader_or_editor(
|
||||||
"""Members of a document should not be allowed to create document accesses."""
|
via, role, mock_user_get_teams
|
||||||
|
):
|
||||||
|
"""Readers or editors of a document should not be allowed to create document accesses."""
|
||||||
user = factories.UserFactory()
|
user = factories.UserFactory()
|
||||||
|
|
||||||
client = APIClient()
|
client = APIClient()
|
||||||
@@ -264,21 +267,21 @@ def test_api_document_accesses_create_authenticated_member(via, mock_user_get_te
|
|||||||
|
|
||||||
document = factories.DocumentFactory()
|
document = factories.DocumentFactory()
|
||||||
if via == USER:
|
if via == USER:
|
||||||
factories.UserDocumentAccessFactory(document=document, user=user, role="member")
|
factories.UserDocumentAccessFactory(document=document, user=user, role=role)
|
||||||
elif via == TEAM:
|
elif via == TEAM:
|
||||||
mock_user_get_teams.return_value = ["lasuite", "unknown"]
|
mock_user_get_teams.return_value = ["lasuite", "unknown"]
|
||||||
factories.TeamDocumentAccessFactory(
|
factories.TeamDocumentAccessFactory(
|
||||||
document=document, team="lasuite", role="member"
|
document=document, team="lasuite", role=role
|
||||||
)
|
)
|
||||||
|
|
||||||
other_user = factories.UserFactory()
|
other_user = factories.UserFactory()
|
||||||
|
|
||||||
for role in [role[0] for role in models.RoleChoices.choices]:
|
for new_role in [role[0] for role in models.RoleChoices.choices]:
|
||||||
response = client.post(
|
response = client.post(
|
||||||
f"/api/v1.0/documents/{document.id!s}/accesses/",
|
f"/api/v1.0/documents/{document.id!s}/accesses/",
|
||||||
{
|
{
|
||||||
"user": str(other_user.id),
|
"user": str(other_user.id),
|
||||||
"role": role,
|
"role": new_role,
|
||||||
},
|
},
|
||||||
format="json",
|
format="json",
|
||||||
)
|
)
|
||||||
@@ -456,9 +459,12 @@ def test_api_document_accesses_update_authenticated_unrelated():
|
|||||||
assert updated_values == old_values
|
assert updated_values == old_values
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("role", ["reader", "editor"])
|
||||||
@pytest.mark.parametrize("via", VIA)
|
@pytest.mark.parametrize("via", VIA)
|
||||||
def test_api_document_accesses_update_authenticated_member(via, mock_user_get_teams):
|
def test_api_document_accesses_update_authenticated_reader_or_editor(
|
||||||
"""Members of a document should not be allowed to update its accesses."""
|
via, role, mock_user_get_teams
|
||||||
|
):
|
||||||
|
"""Readers or editors of a document should not be allowed to update its accesses."""
|
||||||
user = factories.UserFactory()
|
user = factories.UserFactory()
|
||||||
|
|
||||||
client = APIClient()
|
client = APIClient()
|
||||||
@@ -466,11 +472,11 @@ def test_api_document_accesses_update_authenticated_member(via, mock_user_get_te
|
|||||||
|
|
||||||
document = factories.DocumentFactory()
|
document = factories.DocumentFactory()
|
||||||
if via == USER:
|
if via == USER:
|
||||||
factories.UserDocumentAccessFactory(document=document, user=user, role="member")
|
factories.UserDocumentAccessFactory(document=document, user=user, role=role)
|
||||||
elif via == TEAM:
|
elif via == TEAM:
|
||||||
mock_user_get_teams.return_value = ["lasuite", "unknown"]
|
mock_user_get_teams.return_value = ["lasuite", "unknown"]
|
||||||
factories.TeamDocumentAccessFactory(
|
factories.TeamDocumentAccessFactory(
|
||||||
document=document, team="lasuite", role="member"
|
document=document, team="lasuite", role=role
|
||||||
)
|
)
|
||||||
|
|
||||||
access = factories.UserDocumentAccessFactory(document=document)
|
access = factories.UserDocumentAccessFactory(document=document)
|
||||||
@@ -521,14 +527,14 @@ def test_api_document_accesses_update_administrator_except_owner(
|
|||||||
|
|
||||||
access = factories.UserDocumentAccessFactory(
|
access = factories.UserDocumentAccessFactory(
|
||||||
document=document,
|
document=document,
|
||||||
role=random.choice(["administrator", "member"]),
|
role=random.choice(["administrator", "editor", "reader"]),
|
||||||
)
|
)
|
||||||
old_values = serializers.DocumentAccessSerializer(instance=access).data
|
old_values = serializers.DocumentAccessSerializer(instance=access).data
|
||||||
|
|
||||||
new_values = {
|
new_values = {
|
||||||
"id": uuid4(),
|
"id": uuid4(),
|
||||||
"user_id": factories.UserFactory().id,
|
"user_id": factories.UserFactory().id,
|
||||||
"role": random.choice(["administrator", "member"]),
|
"role": random.choice(["administrator", "editor", "reader"]),
|
||||||
}
|
}
|
||||||
|
|
||||||
for field, value in new_values.items():
|
for field, value in new_values.items():
|
||||||
@@ -629,7 +635,7 @@ def test_api_document_accesses_update_administrator_to_owner(via, mock_user_get_
|
|||||||
access = factories.UserDocumentAccessFactory(
|
access = factories.UserDocumentAccessFactory(
|
||||||
document=document,
|
document=document,
|
||||||
user=other_user,
|
user=other_user,
|
||||||
role=random.choice(["administrator", "member"]),
|
role=random.choice(["administrator", "editor", "reader"]),
|
||||||
)
|
)
|
||||||
old_values = serializers.DocumentAccessSerializer(instance=access).data
|
old_values = serializers.DocumentAccessSerializer(instance=access).data
|
||||||
|
|
||||||
@@ -736,7 +742,7 @@ def test_api_document_accesses_update_owner_self(via, mock_user_get_teams):
|
|||||||
)
|
)
|
||||||
|
|
||||||
old_values = serializers.DocumentAccessSerializer(instance=access).data
|
old_values = serializers.DocumentAccessSerializer(instance=access).data
|
||||||
new_role = random.choice(["administrator", "member"])
|
new_role = random.choice(["administrator", "editor", "reader"])
|
||||||
|
|
||||||
response = client.put(
|
response = client.put(
|
||||||
f"/api/v1.0/documents/{document.id!s}/accesses/{access.id!s}/",
|
f"/api/v1.0/documents/{document.id!s}/accesses/{access.id!s}/",
|
||||||
@@ -797,11 +803,12 @@ def test_api_document_accesses_delete_authenticated():
|
|||||||
assert models.DocumentAccess.objects.count() == 1
|
assert models.DocumentAccess.objects.count() == 1
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("role", ["reader", "editor"])
|
||||||
@pytest.mark.parametrize("via", VIA)
|
@pytest.mark.parametrize("via", VIA)
|
||||||
def test_api_document_accesses_delete_member(via, mock_user_get_teams):
|
def test_api_document_accesses_delete_reader_or_editor(via, role, mock_user_get_teams):
|
||||||
"""
|
"""
|
||||||
Authenticated users should not be allowed to delete a document access for a
|
Authenticated users should not be allowed to delete a document access for a
|
||||||
document in which they are a simple member.
|
document in which they are a simple reader or editor.
|
||||||
"""
|
"""
|
||||||
user = factories.UserFactory()
|
user = factories.UserFactory()
|
||||||
|
|
||||||
@@ -810,11 +817,11 @@ def test_api_document_accesses_delete_member(via, mock_user_get_teams):
|
|||||||
|
|
||||||
document = factories.DocumentFactory()
|
document = factories.DocumentFactory()
|
||||||
if via == USER:
|
if via == USER:
|
||||||
factories.UserDocumentAccessFactory(document=document, user=user, role="member")
|
factories.UserDocumentAccessFactory(document=document, user=user, role=role)
|
||||||
elif via == TEAM:
|
elif via == TEAM:
|
||||||
mock_user_get_teams.return_value = ["lasuite", "unknown"]
|
mock_user_get_teams.return_value = ["lasuite", "unknown"]
|
||||||
factories.TeamDocumentAccessFactory(
|
factories.TeamDocumentAccessFactory(
|
||||||
document=document, team="lasuite", role="member"
|
document=document, team="lasuite", role=role
|
||||||
)
|
)
|
||||||
|
|
||||||
access = factories.UserDocumentAccessFactory(document=document)
|
access = factories.UserDocumentAccessFactory(document=document)
|
||||||
@@ -855,7 +862,7 @@ def test_api_document_accesses_delete_administrators_except_owners(
|
|||||||
)
|
)
|
||||||
|
|
||||||
access = factories.UserDocumentAccessFactory(
|
access = factories.UserDocumentAccessFactory(
|
||||||
document=document, role=random.choice(["member", "administrator"])
|
document=document, role=random.choice(["reader", "editor", "administrator"])
|
||||||
)
|
)
|
||||||
|
|
||||||
assert models.DocumentAccess.objects.count() == 2
|
assert models.DocumentAccess.objects.count() == 2
|
||||||
|
|||||||
@@ -57,13 +57,20 @@ def test_api_document_invitations__create__authenticated_outsider():
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"inviting,invited,is_allowed",
|
"inviting,invited,is_allowed",
|
||||||
(
|
(
|
||||||
["member", "member", False],
|
["reader", "reader", False],
|
||||||
["member", "administrator", False],
|
["reader", "editor", False],
|
||||||
["member", "owner", False],
|
["reader", "administrator", False],
|
||||||
["administrator", "member", True],
|
["reader", "owner", False],
|
||||||
|
["editor", "reader", False],
|
||||||
|
["editor", "editor", False],
|
||||||
|
["editor", "administrator", False],
|
||||||
|
["editor", "owner", False],
|
||||||
|
["administrator", "reader", True],
|
||||||
|
["administrator", "editor", True],
|
||||||
["administrator", "administrator", True],
|
["administrator", "administrator", True],
|
||||||
["administrator", "owner", False],
|
["administrator", "owner", False],
|
||||||
["owner", "member", True],
|
["owner", "reader", True],
|
||||||
|
["owner", "editor", True],
|
||||||
["owner", "administrator", True],
|
["owner", "administrator", True],
|
||||||
["owner", "owner", True],
|
["owner", "owner", True],
|
||||||
),
|
),
|
||||||
@@ -146,7 +153,7 @@ def test_api_document_invitations__create__cannot_duplicate_invitation():
|
|||||||
# Create a new invitation to the same document with the exact same email address
|
# Create a new invitation to the same document with the exact same email address
|
||||||
invitation_values = {
|
invitation_values = {
|
||||||
"email": existing_invitation.email,
|
"email": existing_invitation.email,
|
||||||
"role": random.choice(["administrator", "member"]),
|
"role": random.choice(["administrator", "editor", "reader"]),
|
||||||
}
|
}
|
||||||
|
|
||||||
client = APIClient()
|
client = APIClient()
|
||||||
@@ -222,12 +229,12 @@ def test_api_document_invitations__list__authenticated(
|
|||||||
document=document, role="administrator", issuer=user
|
document=document, role="administrator", issuer=user
|
||||||
)
|
)
|
||||||
other_invitations = factories.InvitationFactory.create_batch(
|
other_invitations = factories.InvitationFactory.create_batch(
|
||||||
2, document=document, role="member", issuer=other_user
|
2, document=document, role="reader", issuer=other_user
|
||||||
)
|
)
|
||||||
|
|
||||||
# invitations from other documents should not be listed
|
# invitations from other documents should not be listed
|
||||||
other_document = factories.DocumentFactory()
|
other_document = factories.DocumentFactory()
|
||||||
factories.InvitationFactory.create_batch(2, document=other_document, role="member")
|
factories.InvitationFactory.create_batch(2, document=other_document, role="reader")
|
||||||
|
|
||||||
client = APIClient()
|
client = APIClient()
|
||||||
client.force_login(user)
|
client.force_login(user)
|
||||||
@@ -275,7 +282,7 @@ def test_api_document_invitations__list__expired_invitations_still_listed(settin
|
|||||||
settings.INVITATION_VALIDITY_DURATION = 1 # second
|
settings.INVITATION_VALIDITY_DURATION = 1 # second
|
||||||
expired_invitation = factories.InvitationFactory(
|
expired_invitation = factories.InvitationFactory(
|
||||||
document=document,
|
document=document,
|
||||||
role="member",
|
role="reader",
|
||||||
issuer=user,
|
issuer=user,
|
||||||
)
|
)
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
@@ -467,17 +474,20 @@ def test_api_document_invitations__delete__privileged_members(
|
|||||||
assert response.status_code == status.HTTP_204_NO_CONTENT
|
assert response.status_code == status.HTTP_204_NO_CONTENT
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("role", ["reader", "editor"])
|
||||||
@pytest.mark.parametrize("via", VIA)
|
@pytest.mark.parametrize("via", VIA)
|
||||||
def test_api_document_invitations__delete__members(via, mock_user_get_teams):
|
def test_api_document_invitations_delete_readers_or_editors(
|
||||||
"""Member should not be able to cancel invitation."""
|
via, role, mock_user_get_teams
|
||||||
|
):
|
||||||
|
"""Readers or editors should not be able to cancel invitation."""
|
||||||
user = factories.UserFactory()
|
user = factories.UserFactory()
|
||||||
document = factories.DocumentFactory()
|
document = factories.DocumentFactory()
|
||||||
if via == USER:
|
if via == USER:
|
||||||
factories.UserDocumentAccessFactory(document=document, user=user, role="member")
|
factories.UserDocumentAccessFactory(document=document, user=user, role=role)
|
||||||
elif via == TEAM:
|
elif via == TEAM:
|
||||||
mock_user_get_teams.return_value = ["lasuite", "unknown"]
|
mock_user_get_teams.return_value = ["lasuite", "unknown"]
|
||||||
factories.TeamDocumentAccessFactory(
|
factories.TeamDocumentAccessFactory(
|
||||||
document=document, team="lasuite", role="member"
|
document=document, team="lasuite", role=role
|
||||||
)
|
)
|
||||||
|
|
||||||
invitation = factories.InvitationFactory(document=document)
|
invitation = factories.InvitationFactory(document=document)
|
||||||
|
|||||||
@@ -437,11 +437,12 @@ def test_api_document_versions_delete_authenticated_private():
|
|||||||
assert response.json() == {"detail": "Not found."}
|
assert response.json() == {"detail": "Not found."}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("role", ["reader", "editor"])
|
||||||
@pytest.mark.parametrize("via", VIA)
|
@pytest.mark.parametrize("via", VIA)
|
||||||
def test_api_document_versions_delete_member(via, mock_user_get_teams):
|
def test_api_document_versions_delete_reader_or_editor(via, role, mock_user_get_teams):
|
||||||
"""
|
"""
|
||||||
Authenticated users should not be allowed to delete a document version for a
|
Authenticated users should not be allowed to delete a document version for a
|
||||||
document in which they are a simple member.
|
document in which they are a simple reader or editor.
|
||||||
"""
|
"""
|
||||||
user = factories.UserFactory()
|
user = factories.UserFactory()
|
||||||
|
|
||||||
@@ -450,11 +451,11 @@ def test_api_document_versions_delete_member(via, mock_user_get_teams):
|
|||||||
|
|
||||||
document = factories.DocumentFactory()
|
document = factories.DocumentFactory()
|
||||||
if via == USER:
|
if via == USER:
|
||||||
factories.UserDocumentAccessFactory(document=document, user=user, role="member")
|
factories.UserDocumentAccessFactory(document=document, user=user, role=role)
|
||||||
elif via == TEAM:
|
elif via == TEAM:
|
||||||
mock_user_get_teams.return_value = ["lasuite", "unknown"]
|
mock_user_get_teams.return_value = ["lasuite", "unknown"]
|
||||||
factories.TeamDocumentAccessFactory(
|
factories.TeamDocumentAccessFactory(
|
||||||
document=document, team="lasuite", role="member"
|
document=document, team="lasuite", role=role
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create a new version should make it available to the user
|
# Create a new version should make it available to the user
|
||||||
|
|||||||
@@ -254,9 +254,12 @@ def test_api_template_accesses_create_authenticated_unrelated():
|
|||||||
assert not models.TemplateAccess.objects.filter(user=other_user).exists()
|
assert not models.TemplateAccess.objects.filter(user=other_user).exists()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("role", ["reader", "editor"])
|
||||||
@pytest.mark.parametrize("via", VIA)
|
@pytest.mark.parametrize("via", VIA)
|
||||||
def test_api_template_accesses_create_authenticated_member(via, mock_user_get_teams):
|
def test_api_template_accesses_create_authenticated_editor_or_reader(
|
||||||
"""Members of a template should not be allowed to create template accesses."""
|
via, role, mock_user_get_teams
|
||||||
|
):
|
||||||
|
"""Editors or readers of a template should not be allowed to create template accesses."""
|
||||||
user = factories.UserFactory()
|
user = factories.UserFactory()
|
||||||
|
|
||||||
client = APIClient()
|
client = APIClient()
|
||||||
@@ -264,21 +267,21 @@ def test_api_template_accesses_create_authenticated_member(via, mock_user_get_te
|
|||||||
|
|
||||||
template = factories.TemplateFactory()
|
template = factories.TemplateFactory()
|
||||||
if via == USER:
|
if via == USER:
|
||||||
factories.UserTemplateAccessFactory(template=template, user=user, role="member")
|
factories.UserTemplateAccessFactory(template=template, user=user, role=role)
|
||||||
elif via == TEAM:
|
elif via == TEAM:
|
||||||
mock_user_get_teams.return_value = ["lasuite", "unknown"]
|
mock_user_get_teams.return_value = ["lasuite", "unknown"]
|
||||||
factories.TeamTemplateAccessFactory(
|
factories.TeamTemplateAccessFactory(
|
||||||
template=template, team="lasuite", role="member"
|
template=template, team="lasuite", role=role
|
||||||
)
|
)
|
||||||
|
|
||||||
other_user = factories.UserFactory()
|
other_user = factories.UserFactory()
|
||||||
|
|
||||||
for role in [role[0] for role in models.RoleChoices.choices]:
|
for new_role in [role[0] for role in models.RoleChoices.choices]:
|
||||||
response = client.post(
|
response = client.post(
|
||||||
f"/api/v1.0/templates/{template.id!s}/accesses/",
|
f"/api/v1.0/templates/{template.id!s}/accesses/",
|
||||||
{
|
{
|
||||||
"user": str(other_user.id),
|
"user": str(other_user.id),
|
||||||
"role": role,
|
"role": new_role,
|
||||||
},
|
},
|
||||||
format="json",
|
format="json",
|
||||||
)
|
)
|
||||||
@@ -456,9 +459,12 @@ def test_api_template_accesses_update_authenticated_unrelated():
|
|||||||
assert updated_values == old_values
|
assert updated_values == old_values
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("role", ["reader", "editor"])
|
||||||
@pytest.mark.parametrize("via", VIA)
|
@pytest.mark.parametrize("via", VIA)
|
||||||
def test_api_template_accesses_update_authenticated_member(via, mock_user_get_teams):
|
def test_api_template_accesses_update_authenticated_editor_or_reader(
|
||||||
"""Members of a template should not be allowed to update its accesses."""
|
via, role, mock_user_get_teams
|
||||||
|
):
|
||||||
|
"""Editors or readers of a template should not be allowed to update its accesses."""
|
||||||
user = factories.UserFactory()
|
user = factories.UserFactory()
|
||||||
|
|
||||||
client = APIClient()
|
client = APIClient()
|
||||||
@@ -466,11 +472,11 @@ def test_api_template_accesses_update_authenticated_member(via, mock_user_get_te
|
|||||||
|
|
||||||
template = factories.TemplateFactory()
|
template = factories.TemplateFactory()
|
||||||
if via == USER:
|
if via == USER:
|
||||||
factories.UserTemplateAccessFactory(template=template, user=user, role="member")
|
factories.UserTemplateAccessFactory(template=template, user=user, role=role)
|
||||||
elif via == TEAM:
|
elif via == TEAM:
|
||||||
mock_user_get_teams.return_value = ["lasuite", "unknown"]
|
mock_user_get_teams.return_value = ["lasuite", "unknown"]
|
||||||
factories.TeamTemplateAccessFactory(
|
factories.TeamTemplateAccessFactory(
|
||||||
template=template, team="lasuite", role="member"
|
template=template, team="lasuite", role=role
|
||||||
)
|
)
|
||||||
|
|
||||||
access = factories.UserTemplateAccessFactory(template=template)
|
access = factories.UserTemplateAccessFactory(template=template)
|
||||||
@@ -521,14 +527,14 @@ def test_api_template_accesses_update_administrator_except_owner(
|
|||||||
|
|
||||||
access = factories.UserTemplateAccessFactory(
|
access = factories.UserTemplateAccessFactory(
|
||||||
template=template,
|
template=template,
|
||||||
role=random.choice(["administrator", "member"]),
|
role=random.choice(["administrator", "editor", "reader"]),
|
||||||
)
|
)
|
||||||
old_values = serializers.TemplateAccessSerializer(instance=access).data
|
old_values = serializers.TemplateAccessSerializer(instance=access).data
|
||||||
|
|
||||||
new_values = {
|
new_values = {
|
||||||
"id": uuid4(),
|
"id": uuid4(),
|
||||||
"user_id": factories.UserFactory().id,
|
"user_id": factories.UserFactory().id,
|
||||||
"role": random.choice(["administrator", "member"]),
|
"role": random.choice(["administrator", "editor", "reader"]),
|
||||||
}
|
}
|
||||||
|
|
||||||
for field, value in new_values.items():
|
for field, value in new_values.items():
|
||||||
@@ -629,7 +635,7 @@ def test_api_template_accesses_update_administrator_to_owner(via, mock_user_get_
|
|||||||
access = factories.UserTemplateAccessFactory(
|
access = factories.UserTemplateAccessFactory(
|
||||||
template=template,
|
template=template,
|
||||||
user=other_user,
|
user=other_user,
|
||||||
role=random.choice(["administrator", "member"]),
|
role=random.choice(["administrator", "editor", "reader"]),
|
||||||
)
|
)
|
||||||
old_values = serializers.TemplateAccessSerializer(instance=access).data
|
old_values = serializers.TemplateAccessSerializer(instance=access).data
|
||||||
|
|
||||||
@@ -736,7 +742,7 @@ def test_api_template_accesses_update_owner_self(via, mock_user_get_teams):
|
|||||||
)
|
)
|
||||||
|
|
||||||
old_values = serializers.TemplateAccessSerializer(instance=access).data
|
old_values = serializers.TemplateAccessSerializer(instance=access).data
|
||||||
new_role = random.choice(["administrator", "member"])
|
new_role = random.choice(["administrator", "editor", "reader"])
|
||||||
|
|
||||||
response = client.put(
|
response = client.put(
|
||||||
f"/api/v1.0/templates/{template.id!s}/accesses/{access.id!s}/",
|
f"/api/v1.0/templates/{template.id!s}/accesses/{access.id!s}/",
|
||||||
@@ -797,11 +803,12 @@ def test_api_template_accesses_delete_authenticated():
|
|||||||
assert models.TemplateAccess.objects.count() == 1
|
assert models.TemplateAccess.objects.count() == 1
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("role", ["reader", "editor"])
|
||||||
@pytest.mark.parametrize("via", VIA)
|
@pytest.mark.parametrize("via", VIA)
|
||||||
def test_api_template_accesses_delete_member(via, mock_user_get_teams):
|
def test_api_template_accesses_delete_editor_or_reader(via, role, mock_user_get_teams):
|
||||||
"""
|
"""
|
||||||
Authenticated users should not be allowed to delete a template access for a
|
Authenticated users should not be allowed to delete a template access for a
|
||||||
template in which they are a simple member.
|
template in which they are a simple editor or reader.
|
||||||
"""
|
"""
|
||||||
user = factories.UserFactory()
|
user = factories.UserFactory()
|
||||||
|
|
||||||
@@ -810,11 +817,11 @@ def test_api_template_accesses_delete_member(via, mock_user_get_teams):
|
|||||||
|
|
||||||
template = factories.TemplateFactory()
|
template = factories.TemplateFactory()
|
||||||
if via == USER:
|
if via == USER:
|
||||||
factories.UserTemplateAccessFactory(template=template, user=user, role="member")
|
factories.UserTemplateAccessFactory(template=template, user=user, role=role)
|
||||||
elif via == TEAM:
|
elif via == TEAM:
|
||||||
mock_user_get_teams.return_value = ["lasuite", "unknown"]
|
mock_user_get_teams.return_value = ["lasuite", "unknown"]
|
||||||
factories.TeamTemplateAccessFactory(
|
factories.TeamTemplateAccessFactory(
|
||||||
template=template, team="lasuite", role="member"
|
template=template, team="lasuite", role=role
|
||||||
)
|
)
|
||||||
|
|
||||||
access = factories.UserTemplateAccessFactory(template=template)
|
access = factories.UserTemplateAccessFactory(template=template)
|
||||||
@@ -855,7 +862,7 @@ def test_api_template_accesses_delete_administrators_except_owners(
|
|||||||
)
|
)
|
||||||
|
|
||||||
access = factories.UserTemplateAccessFactory(
|
access = factories.UserTemplateAccessFactory(
|
||||||
template=template, role=random.choice(["member", "administrator"])
|
template=template, role=random.choice(["reader", "editor", "administrator"])
|
||||||
)
|
)
|
||||||
|
|
||||||
assert models.TemplateAccess.objects.count() == 2
|
assert models.TemplateAccess.objects.count() == 2
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ def test_models_document_accesses_str():
|
|||||||
"""
|
"""
|
||||||
user = factories.UserFactory(email="david.bowman@example.com")
|
user = factories.UserFactory(email="david.bowman@example.com")
|
||||||
access = factories.UserDocumentAccessFactory(
|
access = factories.UserDocumentAccessFactory(
|
||||||
role="member",
|
role="reader",
|
||||||
user=user,
|
user=user,
|
||||||
document__title="admins",
|
document__title="admins",
|
||||||
)
|
)
|
||||||
assert str(access) == "david.bowman@example.com is member in document admins"
|
assert str(access) == "david.bowman@example.com is reader in document admins"
|
||||||
|
|
||||||
|
|
||||||
def test_models_document_accesses_unique_user():
|
def test_models_document_accesses_unique_user():
|
||||||
@@ -119,7 +119,7 @@ def test_models_document_access_get_abilities_for_owner_of_self_allowed():
|
|||||||
"destroy": True,
|
"destroy": True,
|
||||||
"retrieve": True,
|
"retrieve": True,
|
||||||
"update": True,
|
"update": True,
|
||||||
"set_role_to": ["administrator", "member"],
|
"set_role_to": ["administrator", "editor", "reader"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -149,7 +149,7 @@ def test_models_document_access_get_abilities_for_owner_of_owner():
|
|||||||
"destroy": True,
|
"destroy": True,
|
||||||
"retrieve": True,
|
"retrieve": True,
|
||||||
"update": True,
|
"update": True,
|
||||||
"set_role_to": ["administrator", "member"],
|
"set_role_to": ["administrator", "editor", "reader"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -165,13 +165,13 @@ def test_models_document_access_get_abilities_for_owner_of_administrator():
|
|||||||
"destroy": True,
|
"destroy": True,
|
||||||
"retrieve": True,
|
"retrieve": True,
|
||||||
"update": True,
|
"update": True,
|
||||||
"set_role_to": ["owner", "member"],
|
"set_role_to": ["owner", "editor", "reader"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def test_models_document_access_get_abilities_for_owner_of_member():
|
def test_models_document_access_get_abilities_for_owner_of_editor():
|
||||||
"""Check abilities of member access for the owner of a document."""
|
"""Check abilities of editor access for the owner of a document."""
|
||||||
access = factories.UserDocumentAccessFactory(role="member")
|
access = factories.UserDocumentAccessFactory(role="editor")
|
||||||
factories.UserDocumentAccessFactory(document=access.document) # another one
|
factories.UserDocumentAccessFactory(document=access.document) # another one
|
||||||
user = factories.UserDocumentAccessFactory(
|
user = factories.UserDocumentAccessFactory(
|
||||||
document=access.document, role="owner"
|
document=access.document, role="owner"
|
||||||
@@ -181,7 +181,23 @@ def test_models_document_access_get_abilities_for_owner_of_member():
|
|||||||
"destroy": True,
|
"destroy": True,
|
||||||
"retrieve": True,
|
"retrieve": True,
|
||||||
"update": True,
|
"update": True,
|
||||||
"set_role_to": ["owner", "administrator"],
|
"set_role_to": ["owner", "administrator", "reader"],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_models_document_access_get_abilities_for_owner_of_reader():
|
||||||
|
"""Check abilities of reader access for the owner of a document."""
|
||||||
|
access = factories.UserDocumentAccessFactory(role="reader")
|
||||||
|
factories.UserDocumentAccessFactory(document=access.document) # another one
|
||||||
|
user = factories.UserDocumentAccessFactory(
|
||||||
|
document=access.document, role="owner"
|
||||||
|
).user
|
||||||
|
abilities = access.get_abilities(user)
|
||||||
|
assert abilities == {
|
||||||
|
"destroy": True,
|
||||||
|
"retrieve": True,
|
||||||
|
"update": True,
|
||||||
|
"set_role_to": ["owner", "administrator", "editor"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -216,13 +232,13 @@ def test_models_document_access_get_abilities_for_administrator_of_administrator
|
|||||||
"destroy": True,
|
"destroy": True,
|
||||||
"retrieve": True,
|
"retrieve": True,
|
||||||
"update": True,
|
"update": True,
|
||||||
"set_role_to": ["member"],
|
"set_role_to": ["editor", "reader"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def test_models_document_access_get_abilities_for_administrator_of_member():
|
def test_models_document_access_get_abilities_for_administrator_of_editor():
|
||||||
"""Check abilities of member access for the administrator of a document."""
|
"""Check abilities of editor access for the administrator of a document."""
|
||||||
access = factories.UserDocumentAccessFactory(role="member")
|
access = factories.UserDocumentAccessFactory(role="editor")
|
||||||
factories.UserDocumentAccessFactory(document=access.document) # another one
|
factories.UserDocumentAccessFactory(document=access.document) # another one
|
||||||
user = factories.UserDocumentAccessFactory(
|
user = factories.UserDocumentAccessFactory(
|
||||||
document=access.document, role="administrator"
|
document=access.document, role="administrator"
|
||||||
@@ -232,19 +248,35 @@ def test_models_document_access_get_abilities_for_administrator_of_member():
|
|||||||
"destroy": True,
|
"destroy": True,
|
||||||
"retrieve": True,
|
"retrieve": True,
|
||||||
"update": True,
|
"update": True,
|
||||||
"set_role_to": ["administrator"],
|
"set_role_to": ["administrator", "reader"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# - for member
|
def test_models_document_access_get_abilities_for_administrator_of_reader():
|
||||||
|
"""Check abilities of reader access for the administrator of a document."""
|
||||||
|
access = factories.UserDocumentAccessFactory(role="reader")
|
||||||
|
factories.UserDocumentAccessFactory(document=access.document) # another one
|
||||||
|
user = factories.UserDocumentAccessFactory(
|
||||||
|
document=access.document, role="administrator"
|
||||||
|
).user
|
||||||
|
abilities = access.get_abilities(user)
|
||||||
|
assert abilities == {
|
||||||
|
"destroy": True,
|
||||||
|
"retrieve": True,
|
||||||
|
"update": True,
|
||||||
|
"set_role_to": ["administrator", "editor"],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def test_models_document_access_get_abilities_for_member_of_owner():
|
# - for editor
|
||||||
"""Check abilities of owner access for the member of a document."""
|
|
||||||
|
|
||||||
|
def test_models_document_access_get_abilities_for_editor_of_owner():
|
||||||
|
"""Check abilities of owner access for the editor of a document."""
|
||||||
access = factories.UserDocumentAccessFactory(role="owner")
|
access = factories.UserDocumentAccessFactory(role="owner")
|
||||||
factories.UserDocumentAccessFactory(document=access.document) # another one
|
factories.UserDocumentAccessFactory(document=access.document) # another one
|
||||||
user = factories.UserDocumentAccessFactory(
|
user = factories.UserDocumentAccessFactory(
|
||||||
document=access.document, role="member"
|
document=access.document, role="editor"
|
||||||
).user
|
).user
|
||||||
abilities = access.get_abilities(user)
|
abilities = access.get_abilities(user)
|
||||||
assert abilities == {
|
assert abilities == {
|
||||||
@@ -255,12 +287,12 @@ def test_models_document_access_get_abilities_for_member_of_owner():
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def test_models_document_access_get_abilities_for_member_of_administrator():
|
def test_models_document_access_get_abilities_for_editor_of_administrator():
|
||||||
"""Check abilities of administrator access for the member of a document."""
|
"""Check abilities of administrator access for the editor of a document."""
|
||||||
access = factories.UserDocumentAccessFactory(role="administrator")
|
access = factories.UserDocumentAccessFactory(role="administrator")
|
||||||
factories.UserDocumentAccessFactory(document=access.document) # another one
|
factories.UserDocumentAccessFactory(document=access.document) # another one
|
||||||
user = factories.UserDocumentAccessFactory(
|
user = factories.UserDocumentAccessFactory(
|
||||||
document=access.document, role="member"
|
document=access.document, role="editor"
|
||||||
).user
|
).user
|
||||||
abilities = access.get_abilities(user)
|
abilities = access.get_abilities(user)
|
||||||
assert abilities == {
|
assert abilities == {
|
||||||
@@ -271,14 +303,70 @@ def test_models_document_access_get_abilities_for_member_of_administrator():
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def test_models_document_access_get_abilities_for_member_of_member_user(
|
def test_models_document_access_get_abilities_for_editor_of_editor_user(
|
||||||
django_assert_num_queries
|
django_assert_num_queries
|
||||||
):
|
):
|
||||||
"""Check abilities of member access for the member of a document."""
|
"""Check abilities of editor access for the editor of a document."""
|
||||||
access = factories.UserDocumentAccessFactory(role="member")
|
access = factories.UserDocumentAccessFactory(role="editor")
|
||||||
factories.UserDocumentAccessFactory(document=access.document) # another one
|
factories.UserDocumentAccessFactory(document=access.document) # another one
|
||||||
user = factories.UserDocumentAccessFactory(
|
user = factories.UserDocumentAccessFactory(
|
||||||
document=access.document, role="member"
|
document=access.document, role="editor"
|
||||||
|
).user
|
||||||
|
|
||||||
|
with django_assert_num_queries(1):
|
||||||
|
abilities = access.get_abilities(user)
|
||||||
|
|
||||||
|
assert abilities == {
|
||||||
|
"destroy": False,
|
||||||
|
"retrieve": True,
|
||||||
|
"update": False,
|
||||||
|
"set_role_to": [],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# - for reader
|
||||||
|
|
||||||
|
|
||||||
|
def test_models_document_access_get_abilities_for_reader_of_owner():
|
||||||
|
"""Check abilities of owner access for the reader of a document."""
|
||||||
|
access = factories.UserDocumentAccessFactory(role="owner")
|
||||||
|
factories.UserDocumentAccessFactory(document=access.document) # another one
|
||||||
|
user = factories.UserDocumentAccessFactory(
|
||||||
|
document=access.document, role="reader"
|
||||||
|
).user
|
||||||
|
abilities = access.get_abilities(user)
|
||||||
|
assert abilities == {
|
||||||
|
"destroy": False,
|
||||||
|
"retrieve": True,
|
||||||
|
"update": False,
|
||||||
|
"set_role_to": [],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_models_document_access_get_abilities_for_reader_of_administrator():
|
||||||
|
"""Check abilities of administrator access for the reader of a document."""
|
||||||
|
access = factories.UserDocumentAccessFactory(role="administrator")
|
||||||
|
factories.UserDocumentAccessFactory(document=access.document) # another one
|
||||||
|
user = factories.UserDocumentAccessFactory(
|
||||||
|
document=access.document, role="reader"
|
||||||
|
).user
|
||||||
|
abilities = access.get_abilities(user)
|
||||||
|
assert abilities == {
|
||||||
|
"destroy": False,
|
||||||
|
"retrieve": True,
|
||||||
|
"update": False,
|
||||||
|
"set_role_to": [],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_models_document_access_get_abilities_for_reader_of_reader_user(
|
||||||
|
django_assert_num_queries
|
||||||
|
):
|
||||||
|
"""Check abilities of reader access for the reader of a document."""
|
||||||
|
access = factories.UserDocumentAccessFactory(role="reader")
|
||||||
|
factories.UserDocumentAccessFactory(document=access.document) # another one
|
||||||
|
user = factories.UserDocumentAccessFactory(
|
||||||
|
document=access.document, role="reader"
|
||||||
).user
|
).user
|
||||||
|
|
||||||
with django_assert_num_queries(1):
|
with django_assert_num_queries(1):
|
||||||
@@ -294,11 +382,11 @@ def test_models_document_access_get_abilities_for_member_of_member_user(
|
|||||||
|
|
||||||
def test_models_document_access_get_abilities_preset_role(django_assert_num_queries):
|
def test_models_document_access_get_abilities_preset_role(django_assert_num_queries):
|
||||||
"""No query is done if the role is preset, e.g., with a query annotation."""
|
"""No query is done if the role is preset, e.g., with a query annotation."""
|
||||||
access = factories.UserDocumentAccessFactory(role="member")
|
access = factories.UserDocumentAccessFactory(role="reader")
|
||||||
user = factories.UserDocumentAccessFactory(
|
user = factories.UserDocumentAccessFactory(
|
||||||
document=access.document, role="member"
|
document=access.document, role="reader"
|
||||||
).user
|
).user
|
||||||
access.user_roles = ["member"]
|
access.user_roles = ["reader"]
|
||||||
|
|
||||||
with django_assert_num_queries(0):
|
with django_assert_num_queries(0):
|
||||||
abilities = access.get_abilities(user)
|
abilities = access.get_abilities(user)
|
||||||
|
|||||||
@@ -147,9 +147,28 @@ def test_models_documents_get_abilities_administrator():
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def test_models_documents_get_abilities_member_user(django_assert_num_queries):
|
def test_models_documents_get_abilities_editor_user(django_assert_num_queries):
|
||||||
"""Check abilities returned for the member of a document."""
|
"""Check abilities returned for the editor of a document."""
|
||||||
access = factories.UserDocumentAccessFactory(role="member")
|
access = factories.UserDocumentAccessFactory(role="editor")
|
||||||
|
|
||||||
|
with django_assert_num_queries(1):
|
||||||
|
abilities = access.document.get_abilities(access.user)
|
||||||
|
|
||||||
|
assert abilities == {
|
||||||
|
"destroy": False,
|
||||||
|
"retrieve": True,
|
||||||
|
"update": True,
|
||||||
|
"manage_accesses": False,
|
||||||
|
"partial_update": True,
|
||||||
|
"versions_destroy": False,
|
||||||
|
"versions_list": True,
|
||||||
|
"versions_retrieve": True,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_models_documents_get_abilities_reader_user(django_assert_num_queries):
|
||||||
|
"""Check abilities returned for the reader of a document."""
|
||||||
|
access = factories.UserDocumentAccessFactory(role="reader")
|
||||||
|
|
||||||
with django_assert_num_queries(1):
|
with django_assert_num_queries(1):
|
||||||
abilities = access.document.get_abilities(access.user)
|
abilities = access.document.get_abilities(access.user)
|
||||||
@@ -168,8 +187,8 @@ def test_models_documents_get_abilities_member_user(django_assert_num_queries):
|
|||||||
|
|
||||||
def test_models_documents_get_abilities_preset_role(django_assert_num_queries):
|
def test_models_documents_get_abilities_preset_role(django_assert_num_queries):
|
||||||
"""No query is done if the role is preset e.g. with query annotation."""
|
"""No query is done if the role is preset e.g. with query annotation."""
|
||||||
access = factories.UserDocumentAccessFactory(role="member")
|
access = factories.UserDocumentAccessFactory(role="reader")
|
||||||
access.document.user_roles = ["member"]
|
access.document.user_roles = ["reader"]
|
||||||
|
|
||||||
with django_assert_num_queries(0):
|
with django_assert_num_queries(0):
|
||||||
abilities = access.document.get_abilities(access.user)
|
abilities = access.document.get_abilities(access.user)
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ def test_models_invitation__new_user__user_creation_constant_num_queries(
|
|||||||
|
|
||||||
def test_models_document_invitations_email():
|
def test_models_document_invitations_email():
|
||||||
"""Check email invitation during invitation creation."""
|
"""Check email invitation during invitation creation."""
|
||||||
member_access = factories.UserDocumentAccessFactory(role="member")
|
member_access = factories.UserDocumentAccessFactory(role="reader")
|
||||||
document = member_access.document
|
document = member_access.document
|
||||||
|
|
||||||
# pylint: disable-next=no-member
|
# pylint: disable-next=no-member
|
||||||
@@ -201,7 +201,7 @@ def test_models_document_invitations_email():
|
|||||||
def test_models_document_invitations_email_failed(mock_logger, _mock_send_mail):
|
def test_models_document_invitations_email_failed(mock_logger, _mock_send_mail):
|
||||||
"""Check invitation behavior when an SMTP error occurs during invitation creation."""
|
"""Check invitation behavior when an SMTP error occurs during invitation creation."""
|
||||||
|
|
||||||
member_access = factories.UserDocumentAccessFactory(role="member")
|
member_access = factories.UserDocumentAccessFactory(role="reader")
|
||||||
document = member_access.document
|
document = member_access.document
|
||||||
|
|
||||||
# pylint: disable-next=no-member
|
# pylint: disable-next=no-member
|
||||||
@@ -288,17 +288,42 @@ def test_models_document_invitations_get_abilities_privileged_member(
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("via", VIA)
|
@pytest.mark.parametrize("via", VIA)
|
||||||
def test_models_document_invitations_get_abilities_member(via, mock_user_get_teams):
|
def test_models_document_invitations_get_abilities_reader(via, mock_user_get_teams):
|
||||||
"""Check abilities for a document member with 'member' role."""
|
"""Check abilities for a document reader with 'reader' role."""
|
||||||
|
|
||||||
user = factories.UserFactory()
|
user = factories.UserFactory()
|
||||||
document = factories.DocumentFactory()
|
document = factories.DocumentFactory()
|
||||||
if via == USER:
|
if via == USER:
|
||||||
factories.UserDocumentAccessFactory(document=document, user=user, role="member")
|
factories.UserDocumentAccessFactory(document=document, user=user, role="reader")
|
||||||
elif via == TEAM:
|
elif via == TEAM:
|
||||||
mock_user_get_teams.return_value = ["lasuite", "unknown"]
|
mock_user_get_teams.return_value = ["lasuite", "unknown"]
|
||||||
factories.TeamDocumentAccessFactory(
|
factories.TeamDocumentAccessFactory(
|
||||||
document=document, team="lasuite", role="member"
|
document=document, team="lasuite", role="reader"
|
||||||
|
)
|
||||||
|
|
||||||
|
invitation = factories.InvitationFactory(document=document)
|
||||||
|
abilities = invitation.get_abilities(user)
|
||||||
|
|
||||||
|
assert abilities == {
|
||||||
|
"destroy": False,
|
||||||
|
"retrieve": True,
|
||||||
|
"partial_update": False,
|
||||||
|
"update": False,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("via", VIA)
|
||||||
|
def test_models_document_invitations_get_abilities_editor(via, mock_user_get_teams):
|
||||||
|
"""Check abilities for a document editor with 'editor' role."""
|
||||||
|
|
||||||
|
user = factories.UserFactory()
|
||||||
|
document = factories.DocumentFactory()
|
||||||
|
if via == USER:
|
||||||
|
factories.UserDocumentAccessFactory(document=document, user=user, role="editor")
|
||||||
|
elif via == TEAM:
|
||||||
|
mock_user_get_teams.return_value = ["lasuite", "unknown"]
|
||||||
|
factories.TeamDocumentAccessFactory(
|
||||||
|
document=document, team="lasuite", role="editor"
|
||||||
)
|
)
|
||||||
|
|
||||||
invitation = factories.InvitationFactory(document=document)
|
invitation = factories.InvitationFactory(document=document)
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ def test_models_template_accesses_str():
|
|||||||
"""
|
"""
|
||||||
user = factories.UserFactory(email="david.bowman@example.com")
|
user = factories.UserFactory(email="david.bowman@example.com")
|
||||||
access = factories.UserTemplateAccessFactory(
|
access = factories.UserTemplateAccessFactory(
|
||||||
role="member",
|
role="reader",
|
||||||
user=user,
|
user=user,
|
||||||
template__title="admins",
|
template__title="admins",
|
||||||
)
|
)
|
||||||
assert str(access) == "david.bowman@example.com is member in template admins"
|
assert str(access) == "david.bowman@example.com is reader in template admins"
|
||||||
|
|
||||||
|
|
||||||
def test_models_template_accesses_unique_user():
|
def test_models_template_accesses_unique_user():
|
||||||
@@ -119,7 +119,7 @@ def test_models_template_access_get_abilities_for_owner_of_self_allowed():
|
|||||||
"destroy": True,
|
"destroy": True,
|
||||||
"retrieve": True,
|
"retrieve": True,
|
||||||
"update": True,
|
"update": True,
|
||||||
"set_role_to": ["administrator", "member"],
|
"set_role_to": ["administrator", "editor", "reader"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -149,7 +149,7 @@ def test_models_template_access_get_abilities_for_owner_of_owner():
|
|||||||
"destroy": True,
|
"destroy": True,
|
||||||
"retrieve": True,
|
"retrieve": True,
|
||||||
"update": True,
|
"update": True,
|
||||||
"set_role_to": ["administrator", "member"],
|
"set_role_to": ["administrator", "editor", "reader"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -165,13 +165,13 @@ def test_models_template_access_get_abilities_for_owner_of_administrator():
|
|||||||
"destroy": True,
|
"destroy": True,
|
||||||
"retrieve": True,
|
"retrieve": True,
|
||||||
"update": True,
|
"update": True,
|
||||||
"set_role_to": ["owner", "member"],
|
"set_role_to": ["owner", "editor", "reader"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def test_models_template_access_get_abilities_for_owner_of_member():
|
def test_models_template_access_get_abilities_for_owner_of_editor():
|
||||||
"""Check abilities of member access for the owner of a template."""
|
"""Check abilities of editor access for the owner of a template."""
|
||||||
access = factories.UserTemplateAccessFactory(role="member")
|
access = factories.UserTemplateAccessFactory(role="editor")
|
||||||
factories.UserTemplateAccessFactory(template=access.template) # another one
|
factories.UserTemplateAccessFactory(template=access.template) # another one
|
||||||
user = factories.UserTemplateAccessFactory(
|
user = factories.UserTemplateAccessFactory(
|
||||||
template=access.template, role="owner"
|
template=access.template, role="owner"
|
||||||
@@ -181,7 +181,23 @@ def test_models_template_access_get_abilities_for_owner_of_member():
|
|||||||
"destroy": True,
|
"destroy": True,
|
||||||
"retrieve": True,
|
"retrieve": True,
|
||||||
"update": True,
|
"update": True,
|
||||||
"set_role_to": ["owner", "administrator"],
|
"set_role_to": ["owner", "administrator", "reader"],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_models_template_access_get_abilities_for_owner_of_reader():
|
||||||
|
"""Check abilities of reader access for the owner of a template."""
|
||||||
|
access = factories.UserTemplateAccessFactory(role="reader")
|
||||||
|
factories.UserTemplateAccessFactory(template=access.template) # another one
|
||||||
|
user = factories.UserTemplateAccessFactory(
|
||||||
|
template=access.template, role="owner"
|
||||||
|
).user
|
||||||
|
abilities = access.get_abilities(user)
|
||||||
|
assert abilities == {
|
||||||
|
"destroy": True,
|
||||||
|
"retrieve": True,
|
||||||
|
"update": True,
|
||||||
|
"set_role_to": ["owner", "administrator", "editor"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -216,13 +232,13 @@ def test_models_template_access_get_abilities_for_administrator_of_administrator
|
|||||||
"destroy": True,
|
"destroy": True,
|
||||||
"retrieve": True,
|
"retrieve": True,
|
||||||
"update": True,
|
"update": True,
|
||||||
"set_role_to": ["member"],
|
"set_role_to": ["editor", "reader"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def test_models_template_access_get_abilities_for_administrator_of_member():
|
def test_models_template_access_get_abilities_for_administrator_of_editor():
|
||||||
"""Check abilities of member access for the administrator of a template."""
|
"""Check abilities of editor access for the administrator of a template."""
|
||||||
access = factories.UserTemplateAccessFactory(role="member")
|
access = factories.UserTemplateAccessFactory(role="editor")
|
||||||
factories.UserTemplateAccessFactory(template=access.template) # another one
|
factories.UserTemplateAccessFactory(template=access.template) # another one
|
||||||
user = factories.UserTemplateAccessFactory(
|
user = factories.UserTemplateAccessFactory(
|
||||||
template=access.template, role="administrator"
|
template=access.template, role="administrator"
|
||||||
@@ -232,19 +248,35 @@ def test_models_template_access_get_abilities_for_administrator_of_member():
|
|||||||
"destroy": True,
|
"destroy": True,
|
||||||
"retrieve": True,
|
"retrieve": True,
|
||||||
"update": True,
|
"update": True,
|
||||||
"set_role_to": ["administrator"],
|
"set_role_to": ["administrator", "reader"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# - for member
|
def test_models_template_access_get_abilities_for_administrator_of_reader():
|
||||||
|
"""Check abilities of reader access for the administrator of a template."""
|
||||||
|
access = factories.UserTemplateAccessFactory(role="reader")
|
||||||
|
factories.UserTemplateAccessFactory(template=access.template) # another one
|
||||||
|
user = factories.UserTemplateAccessFactory(
|
||||||
|
template=access.template, role="administrator"
|
||||||
|
).user
|
||||||
|
abilities = access.get_abilities(user)
|
||||||
|
assert abilities == {
|
||||||
|
"destroy": True,
|
||||||
|
"retrieve": True,
|
||||||
|
"update": True,
|
||||||
|
"set_role_to": ["administrator", "editor"],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def test_models_template_access_get_abilities_for_member_of_owner():
|
# - For editor
|
||||||
"""Check abilities of owner access for the member of a template."""
|
|
||||||
|
|
||||||
|
def test_models_template_access_get_abilities_for_editor_of_owner():
|
||||||
|
"""Check abilities of owner access for the editor of a template."""
|
||||||
access = factories.UserTemplateAccessFactory(role="owner")
|
access = factories.UserTemplateAccessFactory(role="owner")
|
||||||
factories.UserTemplateAccessFactory(template=access.template) # another one
|
factories.UserTemplateAccessFactory(template=access.template) # another one
|
||||||
user = factories.UserTemplateAccessFactory(
|
user = factories.UserTemplateAccessFactory(
|
||||||
template=access.template, role="member"
|
template=access.template, role="editor"
|
||||||
).user
|
).user
|
||||||
abilities = access.get_abilities(user)
|
abilities = access.get_abilities(user)
|
||||||
assert abilities == {
|
assert abilities == {
|
||||||
@@ -255,12 +287,12 @@ def test_models_template_access_get_abilities_for_member_of_owner():
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def test_models_template_access_get_abilities_for_member_of_administrator():
|
def test_models_template_access_get_abilities_for_editor_of_administrator():
|
||||||
"""Check abilities of administrator access for the member of a template."""
|
"""Check abilities of administrator access for the editor of a template."""
|
||||||
access = factories.UserTemplateAccessFactory(role="administrator")
|
access = factories.UserTemplateAccessFactory(role="administrator")
|
||||||
factories.UserTemplateAccessFactory(template=access.template) # another one
|
factories.UserTemplateAccessFactory(template=access.template) # another one
|
||||||
user = factories.UserTemplateAccessFactory(
|
user = factories.UserTemplateAccessFactory(
|
||||||
template=access.template, role="member"
|
template=access.template, role="editor"
|
||||||
).user
|
).user
|
||||||
abilities = access.get_abilities(user)
|
abilities = access.get_abilities(user)
|
||||||
assert abilities == {
|
assert abilities == {
|
||||||
@@ -271,14 +303,70 @@ def test_models_template_access_get_abilities_for_member_of_administrator():
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def test_models_template_access_get_abilities_for_member_of_member_user(
|
def test_models_template_access_get_abilities_for_editor_of_editor_user(
|
||||||
django_assert_num_queries
|
django_assert_num_queries
|
||||||
):
|
):
|
||||||
"""Check abilities of member access for the member of a template."""
|
"""Check abilities of editor access for the editor of a template."""
|
||||||
access = factories.UserTemplateAccessFactory(role="member")
|
access = factories.UserTemplateAccessFactory(role="editor")
|
||||||
factories.UserTemplateAccessFactory(template=access.template) # another one
|
factories.UserTemplateAccessFactory(template=access.template) # another one
|
||||||
user = factories.UserTemplateAccessFactory(
|
user = factories.UserTemplateAccessFactory(
|
||||||
template=access.template, role="member"
|
template=access.template, role="editor"
|
||||||
|
).user
|
||||||
|
|
||||||
|
with django_assert_num_queries(1):
|
||||||
|
abilities = access.get_abilities(user)
|
||||||
|
|
||||||
|
assert abilities == {
|
||||||
|
"destroy": False,
|
||||||
|
"retrieve": True,
|
||||||
|
"update": False,
|
||||||
|
"set_role_to": [],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# - For reader
|
||||||
|
|
||||||
|
|
||||||
|
def test_models_template_access_get_abilities_for_reader_of_owner():
|
||||||
|
"""Check abilities of owner access for the reader of a template."""
|
||||||
|
access = factories.UserTemplateAccessFactory(role="owner")
|
||||||
|
factories.UserTemplateAccessFactory(template=access.template) # another one
|
||||||
|
user = factories.UserTemplateAccessFactory(
|
||||||
|
template=access.template, role="reader"
|
||||||
|
).user
|
||||||
|
abilities = access.get_abilities(user)
|
||||||
|
assert abilities == {
|
||||||
|
"destroy": False,
|
||||||
|
"retrieve": True,
|
||||||
|
"update": False,
|
||||||
|
"set_role_to": [],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_models_template_access_get_abilities_for_reader_of_administrator():
|
||||||
|
"""Check abilities of administrator access for the reader of a template."""
|
||||||
|
access = factories.UserTemplateAccessFactory(role="administrator")
|
||||||
|
factories.UserTemplateAccessFactory(template=access.template) # another one
|
||||||
|
user = factories.UserTemplateAccessFactory(
|
||||||
|
template=access.template, role="reader"
|
||||||
|
).user
|
||||||
|
abilities = access.get_abilities(user)
|
||||||
|
assert abilities == {
|
||||||
|
"destroy": False,
|
||||||
|
"retrieve": True,
|
||||||
|
"update": False,
|
||||||
|
"set_role_to": [],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_models_template_access_get_abilities_for_reader_of_reader_user(
|
||||||
|
django_assert_num_queries
|
||||||
|
):
|
||||||
|
"""Check abilities of reader access for the reader of a template."""
|
||||||
|
access = factories.UserTemplateAccessFactory(role="reader")
|
||||||
|
factories.UserTemplateAccessFactory(template=access.template) # another one
|
||||||
|
user = factories.UserTemplateAccessFactory(
|
||||||
|
template=access.template, role="reader"
|
||||||
).user
|
).user
|
||||||
|
|
||||||
with django_assert_num_queries(1):
|
with django_assert_num_queries(1):
|
||||||
@@ -294,11 +382,11 @@ def test_models_template_access_get_abilities_for_member_of_member_user(
|
|||||||
|
|
||||||
def test_models_template_access_get_abilities_preset_role(django_assert_num_queries):
|
def test_models_template_access_get_abilities_preset_role(django_assert_num_queries):
|
||||||
"""No query is done if the role is preset, e.g., with a query annotation."""
|
"""No query is done if the role is preset, e.g., with a query annotation."""
|
||||||
access = factories.UserTemplateAccessFactory(role="member")
|
access = factories.UserTemplateAccessFactory(role="reader")
|
||||||
user = factories.UserTemplateAccessFactory(
|
user = factories.UserTemplateAccessFactory(
|
||||||
template=access.template, role="member"
|
template=access.template, role="reader"
|
||||||
).user
|
).user
|
||||||
access.user_roles = ["member"]
|
access.user_roles = ["reader"]
|
||||||
|
|
||||||
with django_assert_num_queries(0):
|
with django_assert_num_queries(0):
|
||||||
abilities = access.get_abilities(user)
|
abilities = access.get_abilities(user)
|
||||||
|
|||||||
@@ -134,9 +134,26 @@ def test_models_templates_get_abilities_administrator():
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def test_models_templates_get_abilities_member_user(django_assert_num_queries):
|
def test_models_templates_get_abilities_editor_user(django_assert_num_queries):
|
||||||
"""Check abilities returned for the member of a template."""
|
"""Check abilities returned for the editor of a template."""
|
||||||
access = factories.UserTemplateAccessFactory(role="member")
|
access = factories.UserTemplateAccessFactory(role="editor")
|
||||||
|
|
||||||
|
with django_assert_num_queries(1):
|
||||||
|
abilities = access.template.get_abilities(access.user)
|
||||||
|
|
||||||
|
assert abilities == {
|
||||||
|
"destroy": False,
|
||||||
|
"retrieve": True,
|
||||||
|
"update": True,
|
||||||
|
"manage_accesses": False,
|
||||||
|
"partial_update": True,
|
||||||
|
"generate_document": True,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_models_templates_get_abilities_reader_user(django_assert_num_queries):
|
||||||
|
"""Check abilities returned for the reader of a template."""
|
||||||
|
access = factories.UserTemplateAccessFactory(role="reader")
|
||||||
|
|
||||||
with django_assert_num_queries(1):
|
with django_assert_num_queries(1):
|
||||||
abilities = access.template.get_abilities(access.user)
|
abilities = access.template.get_abilities(access.user)
|
||||||
@@ -153,8 +170,8 @@ def test_models_templates_get_abilities_member_user(django_assert_num_queries):
|
|||||||
|
|
||||||
def test_models_templates_get_abilities_preset_role(django_assert_num_queries):
|
def test_models_templates_get_abilities_preset_role(django_assert_num_queries):
|
||||||
"""No query is done if the role is preset e.g. with query annotation."""
|
"""No query is done if the role is preset e.g. with query annotation."""
|
||||||
access = factories.UserTemplateAccessFactory(role="member")
|
access = factories.UserTemplateAccessFactory(role="reader")
|
||||||
access.template.user_roles = ["member"]
|
access.template.user_roles = ["reader"]
|
||||||
|
|
||||||
with django_assert_num_queries(0):
|
with django_assert_num_queries(0):
|
||||||
abilities = access.template.get_abilities(access.user)
|
abilities = access.template.get_abilities(access.user)
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ export interface Access {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export enum Role {
|
export enum Role {
|
||||||
MEMBER = 'member',
|
READER = 'reader',
|
||||||
|
EDITOR = 'editor',
|
||||||
ADMIN = 'administrator',
|
ADMIN = 'administrator',
|
||||||
OWNER = 'owner',
|
OWNER = 'owner',
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
export enum Role {
|
export enum Role {
|
||||||
MEMBER = 'member',
|
READER = 'reader',
|
||||||
|
EDITOR = 'editor',
|
||||||
ADMIN = 'administrator',
|
ADMIN = 'administrator',
|
||||||
OWNER = 'owner',
|
OWNER = 'owner',
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user