mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-17 05:41:25 +02:00
Merge pull request #3760 from modoboa/fix/permission_on_internal_aliases
Do not set permissions on internal aliases.
This commit is contained in:
@@ -647,6 +647,11 @@ class AliasAPITestCase(ModoAPITestCase):
|
||||
response = response.json()
|
||||
self.assertEqual(len(response), 3)
|
||||
|
||||
response = self.client.get(f"{url}?domain=test2.com")
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = response.json()
|
||||
self.assertEqual(len(response), 0)
|
||||
|
||||
def test_get_alias(self):
|
||||
"""Retrieve an alias."""
|
||||
al = models.Alias.objects.get(address="alias@test.com")
|
||||
|
||||
@@ -192,6 +192,18 @@ class AccountViewSet(
|
||||
return Response(body)
|
||||
|
||||
|
||||
class AliasFilter(dj_filters.FilterSet):
|
||||
|
||||
domain = dj_filters.ModelChoiceFilter(
|
||||
queryset=lambda request: models.Domain.objects.get_for_admin(request.user),
|
||||
to_field_name="name",
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = models.Alias
|
||||
fields = ["domain"]
|
||||
|
||||
|
||||
class AliasViewSet(
|
||||
GetThrottleViewsetMixin, lib_viewsets.RevisionModelMixin, viewsets.ModelViewSet
|
||||
):
|
||||
@@ -200,6 +212,10 @@ class AliasViewSet(
|
||||
Create a new alias instance.
|
||||
"""
|
||||
|
||||
filter_backends = [
|
||||
dj_filters.DjangoFilterBackend,
|
||||
]
|
||||
filterset_class = AliasFilter
|
||||
permission_classes = [
|
||||
IsAuthenticated,
|
||||
DjangoModelPermissions,
|
||||
@@ -209,14 +225,12 @@ class AliasViewSet(
|
||||
def get_queryset(self):
|
||||
"""Filter queryset based on current user."""
|
||||
user = self.request.user
|
||||
if user is None or user.is_anonymous:
|
||||
return models.Alias.objects.none()
|
||||
ids = user.objectaccess_set.filter(
|
||||
content_type=ContentType.objects.get_for_model(models.Alias)
|
||||
).values_list("object_id", flat=True)
|
||||
queryset = models.Alias.objects.filter(pk__in=ids)
|
||||
domain = self.request.query_params.get("domain")
|
||||
if domain:
|
||||
queryset = queryset.filter(domain__name=domain)
|
||||
return queryset
|
||||
return models.Alias.objects.filter(pk__in=ids, internal=False)
|
||||
|
||||
|
||||
class SenderAddressFilterSet(dj_filters.FilterSet):
|
||||
|
||||
@@ -521,7 +521,8 @@ class WritableAccountSerializer(v1_serializers.WritableAccountSerializer):
|
||||
if not param_tools.get_global_parameter("enable_admin_limits", app="limits"):
|
||||
return
|
||||
del self.fields["domains"]
|
||||
if self.context["request"].user.role in ["Resellers", "SuperAdmins"]:
|
||||
user = self.context["request"].user
|
||||
if not user.is_anonymous and user.role in ["Resellers", "SuperAdmins"]:
|
||||
self.fields["resources"] = WritableResourceSerializer(
|
||||
many=True, required=False
|
||||
)
|
||||
|
||||
@@ -74,7 +74,9 @@ class DomainViewSet(
|
||||
|
||||
def get_queryset(self):
|
||||
"""Filter queryset based on current user."""
|
||||
return models.Domain.objects.get_for_admin(self.request.user)
|
||||
if self.request.user and not self.request.user.is_anonymous:
|
||||
return models.Domain.objects.get_for_admin(self.request.user)
|
||||
return models.Domain.objects.none()
|
||||
|
||||
def get_serializer_class(self, *args, **kwargs):
|
||||
if self.action == "delete":
|
||||
@@ -198,6 +200,8 @@ class AccountViewSet(v1_viewsets.AccountViewSet):
|
||||
def get_queryset(self):
|
||||
"""Filter queryset based on current user."""
|
||||
user = self.request.user
|
||||
if not user or user.is_anonymous:
|
||||
return core_models.User.objects.none()
|
||||
ids = user.objectaccess_set.filter(
|
||||
content_type=ContentType.objects.get_for_model(user)
|
||||
).values_list("object_id", flat=True)
|
||||
@@ -271,14 +275,27 @@ class IdentityViewSet(GetThrottleViewsetMixin, viewsets.ViewSet):
|
||||
return response.Response({"status": status, "message": msg})
|
||||
|
||||
|
||||
class AliasFilter(dj_filters.FilterSet):
|
||||
|
||||
domain = dj_filters.ModelChoiceFilter(
|
||||
queryset=lambda request: models.Domain.objects.get_for_admin(request.user),
|
||||
to_field_name="name",
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = models.Alias
|
||||
fields = ["domain"]
|
||||
|
||||
|
||||
class AliasViewSet(v1_viewsets.AliasViewSet):
|
||||
"""Viewset for Alias."""
|
||||
|
||||
filter_backends = (
|
||||
filter_backends = [
|
||||
dj_filters.DjangoFilterBackend,
|
||||
filters.OrderingFilter,
|
||||
filters.SearchFilter,
|
||||
dj_filters.DjangoFilterBackend,
|
||||
)
|
||||
]
|
||||
filterset_class = AliasFilter
|
||||
pagination_class = pagination.CustomPageNumberPagination
|
||||
search_fields = ["address"]
|
||||
serializer_class = serializers.AliasSerializer
|
||||
@@ -391,6 +408,8 @@ class AlarmViewSet(
|
||||
serializer_class = serializers.AlarmSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
if self.request.user.is_anonymous:
|
||||
return models.Alarm.objects.none()
|
||||
return (
|
||||
models.Alarm.objects.select_related("domain")
|
||||
.filter(domain__in=models.Domain.objects.get_for_admin(self.request.user))
|
||||
|
||||
@@ -236,11 +236,6 @@ def import_account_mailbox(sender, user, account, row, **kwargs):
|
||||
sender="import", context=domain, object_type="mailboxes"
|
||||
)
|
||||
account.save()
|
||||
qset = models.Mailbox.objects.filter(address=mailbox, domain=domain)
|
||||
if qset.exists():
|
||||
raise exceptions.Conflict(
|
||||
_("Mailbox {} already exists").format(account.email)
|
||||
)
|
||||
if len(row) == 1:
|
||||
quota = None
|
||||
else:
|
||||
@@ -274,16 +269,16 @@ def grant_access_to_all_objects(sender, account, role, **kwargs):
|
||||
"""Grant all permissions if new role is SuperAdmin."""
|
||||
if role != "SuperAdmins":
|
||||
return
|
||||
perm_models = [
|
||||
core_models.User,
|
||||
models.Domain,
|
||||
models.DomainAlias,
|
||||
models.Mailbox,
|
||||
models.Alias,
|
||||
querysets = [
|
||||
core_models.User.objects.all(),
|
||||
models.Domain.objects.all(),
|
||||
models.DomainAlias.objects.all(),
|
||||
models.Mailbox.objects.all(),
|
||||
models.Alias.objects.filter(internal=False),
|
||||
]
|
||||
for model in perm_models:
|
||||
for queryset in querysets:
|
||||
permissions.grant_access_to_objects(
|
||||
account, model.objects.all(), ContentType.objects.get_for_model(model)
|
||||
account, queryset, ContentType.objects.get_for_model(queryset.model)
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ def sometimes_objects_have_no_owner(**options):
|
||||
User.objects.all(),
|
||||
models.Domain.objects.all(),
|
||||
models.DomainAlias.objects.all(),
|
||||
models.Alias.objects.filter(domain__isnull=False),
|
||||
models.Alias.objects.filter(internal=False, domain__isnull=False),
|
||||
models.Mailbox.objects.filter(domain__isnull=False),
|
||||
)
|
||||
for qs in owned_models:
|
||||
|
||||
@@ -257,7 +257,7 @@ class Domain(mixins.MessageLimitMixin, AdminObject):
|
||||
continue
|
||||
grant_access_to_object(account, mb)
|
||||
grant_access_to_object(account, mb.user)
|
||||
for al in self.alias_set.all():
|
||||
for al in self.alias_set.filter(internal=False):
|
||||
grant_access_to_object(account, al)
|
||||
|
||||
def remove_admin(self, account):
|
||||
|
||||
@@ -20,7 +20,7 @@ class RepairTestCase(ModoTestCase):
|
||||
"""Check that command works fine."""
|
||||
ObjectAccess.objects.all().delete()
|
||||
mbox = models.Mailbox.objects.first()
|
||||
alias = models.Alias.objects.first()
|
||||
alias = models.Alias.objects.filter(internal=False).first()
|
||||
# assert mbox has no owner
|
||||
self.assertIs(get_object_owner(mbox), None)
|
||||
# fix it. run in quiet mode because we dont want output in tests
|
||||
@@ -53,7 +53,7 @@ class RepairTestCase(ModoTestCase):
|
||||
count, detail = models.Alias.objects.filter(
|
||||
address="user@test.com", internal=True
|
||||
).delete()
|
||||
self.assertEqual(count, 3)
|
||||
self.assertEqual(count, 2)
|
||||
ret = management.call_command("modo", "repair", "--quiet")
|
||||
assert ret is None
|
||||
self.assertTrue(
|
||||
|
||||
@@ -71,6 +71,7 @@ INSTALLED_APPS = (
|
||||
'corsheaders',
|
||||
'rest_framework',
|
||||
'rest_framework.authtoken',
|
||||
'django_filters',
|
||||
'drf_spectacular',
|
||||
'phonenumber_field',
|
||||
'django_otp',
|
||||
@@ -246,6 +247,9 @@ SPECTACULAR_SETTINGS = {
|
||||
'TITLE': 'Modoboa API',
|
||||
'VERSION': None,
|
||||
'SERVE_AUTHENTICATION': [],
|
||||
'DEFAULT_FILTER_INSPECTORS': [
|
||||
'drf_spectacular.contrib.django_filters.DjangoFilterBackendInspector',
|
||||
],
|
||||
}
|
||||
|
||||
# Modoboa settings
|
||||
|
||||
@@ -79,6 +79,7 @@ INSTALLED_APPS = (
|
||||
"corsheaders",
|
||||
"rest_framework",
|
||||
"rest_framework.authtoken",
|
||||
"django_filters",
|
||||
"drf_spectacular",
|
||||
"django_otp",
|
||||
"django_otp.plugins.otp_totp",
|
||||
@@ -262,6 +263,9 @@ SPECTACULAR_SETTINGS = {
|
||||
"TITLE": "Modoboa API",
|
||||
"VERSION": None,
|
||||
"SERVE_AUTHENTICATION": [],
|
||||
"DEFAULT_FILTER_INSPECTORS": [
|
||||
"drf_spectacular.contrib.django_filters.DjangoFilterBackendInspector",
|
||||
],
|
||||
}
|
||||
|
||||
# Modoboa settings
|
||||
|
||||
Reference in New Issue
Block a user