+
+
+ Message history
+
+
+
+
+
+
diff --git a/frontend/yarn.lock b/frontend/yarn.lock
index 436be592b..389527d91 100644
--- a/frontend/yarn.lock
+++ b/frontend/yarn.lock
@@ -2,7 +2,7 @@
# yarn lockfile v1
-"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.14.5":
+"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.14.5":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb"
integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==
@@ -35,7 +35,7 @@
semver "^6.3.0"
source-map "^0.5.0"
-"@babel/generator@^7.11.5", "@babel/generator@^7.14.5":
+"@babel/generator@^7.14.5":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.14.5.tgz#848d7b9f031caca9d0cd0af01b063f226f52d785"
integrity sha512-y3rlP+/G25OIX3mYKKIOlQRcqj7YgrvHxOLbVmyLJ9bPmi5ttvUmpydVjcFjZphOktWuA7ovbx91ECloWTfjIA==
@@ -110,7 +110,7 @@
dependencies:
"@babel/types" "^7.14.5"
-"@babel/helper-function-name@^7.10.4", "@babel/helper-function-name@^7.14.5":
+"@babel/helper-function-name@^7.14.5":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz#89e2c474972f15d8e233b52ee8c480e2cfcd50c4"
integrity sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==
@@ -206,14 +206,14 @@
dependencies:
"@babel/types" "^7.14.5"
-"@babel/helper-split-export-declaration@^7.11.0", "@babel/helper-split-export-declaration@^7.14.5":
+"@babel/helper-split-export-declaration@^7.14.5":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz#22b23a54ef51c2b7605d851930c1976dd0bc693a"
integrity sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA==
dependencies:
"@babel/types" "^7.14.5"
-"@babel/helper-validator-identifier@^7.10.4", "@babel/helper-validator-identifier@^7.14.5":
+"@babel/helper-validator-identifier@^7.14.5":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz#d0f0e277c512e0c938277faa85a3968c9a44c0e8"
integrity sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==
@@ -251,16 +251,11 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
-"@babel/parser@^7.11.5", "@babel/parser@^7.12.0", "@babel/parser@^7.13.9", "@babel/parser@^7.14.5", "@babel/parser@^7.14.6", "@babel/parser@^7.14.7", "@babel/parser@^7.6.0", "@babel/parser@^7.9.6":
+"@babel/parser@^7.12.0", "@babel/parser@^7.13.9", "@babel/parser@^7.14.5", "@babel/parser@^7.14.6", "@babel/parser@^7.14.7", "@babel/parser@^7.6.0", "@babel/parser@^7.7.0", "@babel/parser@^7.9.6":
version "7.14.7"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.7.tgz#6099720c8839ca865a2637e6c85852ead0bdb595"
integrity sha512-X67Z5y+VBJuHB/RjwECp8kSl5uYi0BvRbNeWqkaJCVh+LiTPl19WBUfG627psSgp9rSf6ojuXghQM3ha6qHHdA==
-"@babel/parser@^7.7.0":
- version "7.11.5"
- resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.5.tgz#c7ff6303df71080ec7a4f5b8c003c58f1cf51037"
- integrity sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==
-
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.14.5":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.14.5.tgz#4b467302e1548ed3b1be43beae2cc9cf45e0bb7e"
@@ -893,7 +888,7 @@
"@babel/parser" "^7.14.5"
"@babel/types" "^7.14.5"
-"@babel/traverse@^7.0.0", "@babel/traverse@^7.13.0", "@babel/traverse@^7.14.5":
+"@babel/traverse@^7.0.0", "@babel/traverse@^7.13.0", "@babel/traverse@^7.14.5", "@babel/traverse@^7.7.0":
version "7.14.7"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.14.7.tgz#64007c9774cfdc3abd23b0780bc18a3ce3631753"
integrity sha512-9vDr5NzHu27wgwejuKL7kIOm4bwEtaPQ4Z6cpCmjSuaRqpH/7xc4qcGEscwMqlkwgcXl6MvqoAjZkQ24uSdIZQ==
@@ -908,22 +903,7 @@
debug "^4.1.0"
globals "^11.1.0"
-"@babel/traverse@^7.7.0":
- version "7.11.5"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.5.tgz#be777b93b518eb6d76ee2e1ea1d143daa11e61c3"
- integrity sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==
- dependencies:
- "@babel/code-frame" "^7.10.4"
- "@babel/generator" "^7.11.5"
- "@babel/helper-function-name" "^7.10.4"
- "@babel/helper-split-export-declaration" "^7.11.0"
- "@babel/parser" "^7.11.5"
- "@babel/types" "^7.11.5"
- debug "^4.1.0"
- globals "^11.1.0"
- lodash "^4.17.19"
-
-"@babel/types@^7.0.0", "@babel/types@^7.11.5", "@babel/types@^7.12.0", "@babel/types@^7.13.0", "@babel/types@^7.14.5", "@babel/types@^7.4.4", "@babel/types@^7.6.1", "@babel/types@^7.9.6":
+"@babel/types@^7.0.0", "@babel/types@^7.12.0", "@babel/types@^7.13.0", "@babel/types@^7.14.5", "@babel/types@^7.4.4", "@babel/types@^7.6.1", "@babel/types@^7.7.0", "@babel/types@^7.9.6":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.14.5.tgz#3bb997ba829a2104cedb20689c4a5b8121d383ff"
integrity sha512-M/NzBpEL95I5Hh4dwhin5JlE7EzO5PHMAuzjxss3tiOBD46KfQvVedN/3jEPZvdRvtsK2222XfdHogNIttFgcg==
@@ -931,15 +911,6 @@
"@babel/helper-validator-identifier" "^7.14.5"
to-fast-properties "^2.0.0"
-"@babel/types@^7.7.0":
- version "7.11.5"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d"
- integrity sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==
- dependencies:
- "@babel/helper-validator-identifier" "^7.10.4"
- lodash "^4.17.19"
- to-fast-properties "^2.0.0"
-
"@hapi/address@2.x.x":
version "2.1.4"
resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.4.tgz#5d67ed43f3fd41a69d4b9ff7b56e7c0d1d0a81e5"
@@ -8244,7 +8215,7 @@ resolve-url@^0.2.1:
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
-resolve@^1.1.6, resolve@^1.10.0, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.15.1, resolve@^1.20.0:
+resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.15.1, resolve@^1.20.0:
version "1.20.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
@@ -8252,7 +8223,7 @@ resolve@^1.1.6, resolve@^1.10.0, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.15
is-core-module "^2.2.0"
path-parse "^1.0.6"
-resolve@^1.10.1, resolve@^1.12.0:
+resolve@^1.10.1:
version "1.17.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444"
integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==
@@ -8381,10 +8352,10 @@ sass-loader@^8.0.2:
schema-utils "^2.6.1"
semver "^6.3.0"
-sass@^1.26.5:
- version "1.35.1"
- resolved "https://registry.yarnpkg.com/sass/-/sass-1.35.1.tgz#90ecf774dfe68f07b6193077e3b42fb154b9e1cd"
- integrity sha512-oCisuQJstxMcacOPmxLNiLlj4cUyN2+8xJnG7VanRoh2GOLr9RqkvI4AxA4a6LHVg/rsu+PmxXeGhrdSF9jCiQ==
+sass@~1.32.12:
+ version "1.32.13"
+ resolved "https://registry.yarnpkg.com/sass/-/sass-1.32.13.tgz#8d29c849e625a415bce71609c7cf95e15f74ed00"
+ integrity sha512-dEgI9nShraqP7cXQH+lEXVf73WOPCse0QlFzSD8k+1TcOxCMwVXfQlr0jtoluZysQOyJGnfr21dLvYKDJq8HkA==
dependencies:
chokidar ">=3.0.0 <4.0.0"
@@ -9692,10 +9663,10 @@ vue-cli-plugin-axios@~0.0.4:
resolved "https://registry.yarnpkg.com/vue-cli-plugin-axios/-/vue-cli-plugin-axios-0.0.4.tgz#29d4eb48275c7fe15b92e1fd5d95fbe2a966436f"
integrity sha512-p2b/fvPJuPBnvU8027PAAuU5DiOzUn2lku8XLG/f6c8FU0N+/MXWZAlOuHhqd9e7+KIZitwe/c8qlmv7TglbTg==
-vue-cli-plugin-vuetify@~2.0.7:
- version "2.0.9"
- resolved "https://registry.yarnpkg.com/vue-cli-plugin-vuetify/-/vue-cli-plugin-vuetify-2.0.9.tgz#982991aec28e79d1f0c2eb8f6e3d62e042087ee8"
- integrity sha512-J4fzpz27OmCCAA3CI56ulYsUrZ859dQAh58Z9XZilY03kd/M+svLlPkK45cBIrGGfjSqQ40oyWezA3NiPBEG8g==
+vue-cli-plugin-vuetify@~2.4.1:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/vue-cli-plugin-vuetify/-/vue-cli-plugin-vuetify-2.4.1.tgz#a31a9ddb274c8e512aeca7dc2f29d828a18df0af"
+ integrity sha512-ZfhvQ13X41atsCSKdSGiHnSJlhAccv4QIFOZmd8kyq6NktpeeWlvQz/dEKBf6u1AWKmKdwiCDuxS2VNT9fxhOA==
dependencies:
null-loader "^3.0.0"
semver "^7.1.2"
diff --git a/modoboa/core/api/v2/urls.py b/modoboa/core/api/v2/urls.py
index da72ddfed..fbe9c09e2 100644
--- a/modoboa/core/api/v2/urls.py
+++ b/modoboa/core/api/v2/urls.py
@@ -13,7 +13,7 @@ from . import viewsets
router = routers.SimpleRouter()
router.register(r"account", viewsets.AccountViewSet, basename="account")
-router.register(r"logs", viewsets.LogViewSet)
+router.register(r"logs/audit-trail", viewsets.LogViewSet)
urlpatterns = router.urls
urlpatterns += [
diff --git a/modoboa/core/api/v2/viewsets.py b/modoboa/core/api/v2/viewsets.py
index a2060415a..1c56f5672 100644
--- a/modoboa/core/api/v2/viewsets.py
+++ b/modoboa/core/api/v2/viewsets.py
@@ -1,12 +1,13 @@
"""Core API v2 viewsets."""
from drf_spectacular.utils import extend_schema
-from rest_framework import filters, pagination, permissions, response, viewsets
+from rest_framework import filters, permissions, response, viewsets
from rest_framework.decorators import action
from rest_framework_simplejwt.tokens import RefreshToken
from modoboa.admin.api.v1 import serializers as admin_v1_serializers
from modoboa.core.api.v1 import viewsets as core_v1_viewsets
+from modoboa.lib import pagination
from ... import constants
from ... import models
@@ -38,17 +39,13 @@ class AccountViewSet(core_v1_viewsets.AccountViewSet):
})
-class CustomPageNumberPagination(pagination.PageNumberPagination):
- page_size_query_param = "page_size"
-
-
class LogViewSet(viewsets.ReadOnlyModelViewSet):
"""Log viewset."""
filter_backends = [filters.OrderingFilter, filters.SearchFilter]
ordering = ["-date_created"]
ordering_fields = "__all__"
- pagination_class = CustomPageNumberPagination
+ pagination_class = pagination.CustomPageNumberPagination
permission_classes = (
permissions.IsAuthenticated,
permissions.DjangoModelPermissions,
diff --git a/modoboa/lib/pagination.py b/modoboa/lib/pagination.py
new file mode 100644
index 000000000..b5283358d
--- /dev/null
+++ b/modoboa/lib/pagination.py
@@ -0,0 +1,7 @@
+"""Pagination utilities."""
+
+from rest_framework import pagination
+
+
+class CustomPageNumberPagination(pagination.PageNumberPagination):
+ page_size_query_param = "page_size"
diff --git a/modoboa/maillog/api/v2/serializers.py b/modoboa/maillog/api/v2/serializers.py
index d6ea07c18..f6c204d76 100644
--- a/modoboa/maillog/api/v2/serializers.py
+++ b/modoboa/maillog/api/v2/serializers.py
@@ -4,6 +4,8 @@ from django.utils.translation import ugettext as _
from rest_framework import serializers
+from ... import models
+
PERIODS = [
("day", "Day"),
@@ -62,3 +64,14 @@ class StatisticsSerializer(serializers.Serializer):
"""Serializer to return statistics."""
graphs = GraphSerializer(many=True)
+
+
+class MaillogSerializer(serializers.ModelSerializer):
+ """Serializer for Maillog model."""
+
+ class Meta:
+ fields = (
+ "id", "queue_id", "date", "sender", "rcpt", "original_rcpt",
+ "size", "status"
+ )
+ model = models.Maillog
diff --git a/modoboa/maillog/api/v2/tests.py b/modoboa/maillog/api/v2/tests.py
index 273c6d726..767716a3a 100644
--- a/modoboa/maillog/api/v2/tests.py
+++ b/modoboa/maillog/api/v2/tests.py
@@ -23,3 +23,11 @@ class StatisticsViewSetTestCase(ModoAPITestCase):
"?gset=mailtraffic&period=custom&start=2021-05-01&end=2021-05-02"
)
self.assertEqual(resp.status_code, 200)
+
+
+class MaillogViewSetTestCase(ModoAPITestCase):
+
+ def test_list(self):
+ url = reverse("v2:maillog-list")
+ resp = self.client.get(url)
+ self.assertEqual(resp.status_code, 200)
diff --git a/modoboa/maillog/api/v2/urls.py b/modoboa/maillog/api/v2/urls.py
index a8f43763f..3fd2217c2 100644
--- a/modoboa/maillog/api/v2/urls.py
+++ b/modoboa/maillog/api/v2/urls.py
@@ -7,5 +7,7 @@ from . import viewsets
router = routers.SimpleRouter()
router.register(
r"statistics", viewsets.StatisticsViewSet, basename="statistics")
+router.register(
+ r"logs/messages", viewsets.MaillogViewSet, basename="maillog")
urlpatterns = router.urls
diff --git a/modoboa/maillog/api/v2/viewsets.py b/modoboa/maillog/api/v2/viewsets.py
index 7e1a8f423..b5bb1be8f 100644
--- a/modoboa/maillog/api/v2/viewsets.py
+++ b/modoboa/maillog/api/v2/viewsets.py
@@ -2,9 +2,15 @@
import time
-from drf_spectacular.utils import extend_schema
-from rest_framework import permissions, response, viewsets
+from django.db.models import Q
+from drf_spectacular.utils import extend_schema
+from rest_framework import filters, permissions, response, viewsets
+
+from modoboa.admin import models as admin_models
+from modoboa.lib import pagination
+
+from ... import models
from ... import signals
from . import serializers
@@ -43,3 +49,22 @@ class StatisticsViewSet(viewsets.ViewSet):
fname, start, end, serializer.validated_data.get("graphic")
)
return response.Response({"graphs": graphs})
+
+
+class MaillogViewSet(viewsets.ReadOnlyModelViewSet):
+ """Simple viewset to access message log."""
+
+ filter_backends = [filters.OrderingFilter, filters.SearchFilter]
+ ordering = ["-date"]
+ ordering_fields = "__all__"
+ pagination_class = pagination.CustomPageNumberPagination
+ permissions = (permissions.IsAuthenticated, )
+ search_fields = ["queue_id", "sender", "rcpt", "original_rcpt", "status"]
+ serializer_class = serializers.MaillogSerializer
+
+ def get_queryset(self):
+ """Filter queryset based on current user."""
+ domains = admin_models.Domain.objects.get_for_admin(self.request.user)
+ return models.Maillog.objects.filter(
+ Q(from_domain__in=domains) | Q(to_domain__in=domains)
+ )