mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-17 05:41:25 +02:00
Use raw mode on custom or broken sieve file (#3387)
* Use raw mode on custom or broken sieve file * Fixed display of sieve filters when none are active * Updated test
This commit is contained in:
@@ -5,6 +5,10 @@ auth_debug = yes
|
||||
auth_verbose = yes
|
||||
auth_debug_passwords = yes
|
||||
|
||||
# Disabling SSL (dev)
|
||||
ssl=no
|
||||
disable_plaintext_auth=no
|
||||
|
||||
passdb {
|
||||
driver = oauth2
|
||||
mechanisms = xoauth2 oauthbearer
|
||||
|
||||
@@ -36,8 +36,10 @@ _axios.interceptors.response.use(
|
||||
return Promise.reject(error)
|
||||
}
|
||||
if (error.response.status !== 401 || router.currentRoute.name === 'Login') {
|
||||
const busStore = useBusStore()
|
||||
busStore.displayNotification({ msg: error.response.data, type: 'error' })
|
||||
if (error.response.status !== 518) {
|
||||
const busStore = useBusStore()
|
||||
busStore.displayNotification({ msg: error.response.data, type: 'error' })
|
||||
}
|
||||
return Promise.reject(error)
|
||||
}
|
||||
const refreshToken = Cookies.get('refreshToken')
|
||||
|
||||
@@ -200,6 +200,9 @@ function getFilterSetName(filterSet) {
|
||||
if (filterSet.active) {
|
||||
result += ' (' + $gettext('active') + ')'
|
||||
}
|
||||
else {
|
||||
result += ' (' + $gettext('inactive') + ')'
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -216,7 +219,12 @@ function closeFilterForm() {
|
||||
|
||||
function fetchFilterSets() {
|
||||
accountApi.getFilterSets().then(resp => {
|
||||
filterSets.value = resp.data
|
||||
if (resp.data.length > 0 && resp.data[0].active && resp.data[0].name === null) {
|
||||
// No filter is active
|
||||
filterSets.value = resp.data.slice(1)
|
||||
} else {
|
||||
filterSets.value = resp.data
|
||||
}
|
||||
if (!currentFilterSet.value && route.params.filterset) {
|
||||
for (const filterSet of filterSets.value) {
|
||||
if (filterSet.name === route.params.filterset) {
|
||||
@@ -233,6 +241,12 @@ function fetchFilters(filterSetName) {
|
||||
accountApi.getFilters(filterSetName).then(resp => {
|
||||
filters.value = resp.data
|
||||
loadingFilters.value = false
|
||||
}).catch(error => {
|
||||
if (error.response.status === 518) { // Server is a teapot (sieve file contains custom code or is broken)
|
||||
// Let the user see with rawmode
|
||||
rawMode.value = true
|
||||
busStore.displayNotification({ msg: $gettext('Failed to display template. Using raw mode'), type: 'warning' })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from django.db.utils import ProgrammingError
|
||||
from django.db.utils import ProgrammingError, OperationalError
|
||||
from django.core.checks import register, Info, Warning
|
||||
from django.conf import settings
|
||||
from django.utils.translation import gettext as _
|
||||
@@ -53,7 +53,7 @@ def check_password_hasher(app_configs, **kwargs):
|
||||
msgs = []
|
||||
try:
|
||||
hasher = check_for_deprecated_password_schemes()
|
||||
except ProgrammingError:
|
||||
except (ProgrammingError, OperationalError):
|
||||
# This is probably a fresh install...
|
||||
return []
|
||||
if hasher:
|
||||
|
||||
@@ -137,6 +137,9 @@ class FilterSetViewSetTestCase(ModoAPITestCase):
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertEqual(len(resp.json()), 5)
|
||||
url = reverse("v2:filterset-get-filters", args=["complex_script"])
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(resp.status_code, 518)
|
||||
|
||||
def test_add_filter(self):
|
||||
self.authenticate()
|
||||
|
||||
@@ -15,7 +15,7 @@ from rest_framework.decorators import action
|
||||
|
||||
from modoboa.lib.viewsets import HasMailbox
|
||||
from modoboa.sievefilters import constants
|
||||
from modoboa.sievefilters.lib import SieveClient, SieveClientError
|
||||
from modoboa.sievefilters.lib import SieveClient, SieveClientError, SieveActionTemplateNotFound
|
||||
from modoboa.sievefilters.rfc6266 import build_header
|
||||
from modoboa.sievefilters.api.v2 import serializers
|
||||
|
||||
@@ -154,7 +154,10 @@ class FilterSetViewSet(viewsets.ViewSet):
|
||||
fset = sclient.getscript(pk, format="fset")
|
||||
except SieveClientError:
|
||||
return response.Response(status=404)
|
||||
serializer = serializers.FilterSerializer.from_filters(fset.filters)
|
||||
try:
|
||||
serializer = serializers.FilterSerializer.from_filters(fset.filters)
|
||||
except SieveActionTemplateNotFound:
|
||||
return HttpResponse(status=518)
|
||||
return response.Response(serializer.data)
|
||||
|
||||
@extend_schema(
|
||||
|
||||
@@ -19,6 +19,10 @@ class SieveClientError(ModoboaException):
|
||||
http_code = 400
|
||||
|
||||
|
||||
class SieveActionTemplateNotFound(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class SieveClient:
|
||||
"""Sieve client."""
|
||||
|
||||
@@ -93,4 +97,4 @@ def find_action_template(action: str):
|
||||
for tpl in constants.ACTION_TEMPLATES:
|
||||
if tpl["name"] == action:
|
||||
return tpl
|
||||
raise RuntimeError(f"action {action} not defined")
|
||||
raise SieveActionTemplateNotFound(f"action {action} not defined")
|
||||
|
||||
@@ -39,6 +39,15 @@ if anyof (header :contains "Subject" "toto", not header :contains "To" "peé") {
|
||||
}
|
||||
"""
|
||||
|
||||
SAMPLE_COMPLEX_SCRIPT = """require ["imap4flags"];
|
||||
|
||||
# Filter: Test42
|
||||
if anyof (header :contains "From" "TOBESEEN") {
|
||||
setflag "\\seen";
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
|
||||
class ManagesieveClientMock:
|
||||
"""Fake managesieve client."""
|
||||
@@ -50,6 +59,7 @@ class ManagesieveClientMock:
|
||||
"main_script": SAMPLE_SIEVE_SCRIPT,
|
||||
"second_script": SAMPLE_SIEVE_SCRIPT,
|
||||
"third_script": SAMPLE_SIEVE_SCRIPT2,
|
||||
"complex_script": SAMPLE_COMPLEX_SCRIPT,
|
||||
}
|
||||
|
||||
def connect(self, username, password, **kwargs):
|
||||
|
||||
Reference in New Issue
Block a user