From 598b2df5a02e6e5532f86c936812a7bd23030a9a Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 2 Nov 2021 13:04:40 +0100 Subject: [PATCH 01/30] update wtforms --- core/admin/requirements-prod.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt index 3406122d..506cf050 100644 --- a/core/admin/requirements-prod.txt +++ b/core/admin/requirements-prod.txt @@ -52,5 +52,5 @@ tenacity==5.0.4 validators==0.12.6 visitor==0.1.3 Werkzeug==0.15.5 -WTForms==2.2.1 -WTForms-Components==0.10.4 +WTForms==2.3.3 +WTForms-Components==0.10.5 From 80be3506daddf5d075c93e94b1521321baa369af Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 2 Nov 2021 13:32:12 +0100 Subject: [PATCH 02/30] upgrade pip. completed reqs via pip freeze --- core/admin/Dockerfile | 3 ++- core/admin/requirements-prod.txt | 27 ++++++++++++++++++++++++--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/core/admin/Dockerfile b/core/admin/Dockerfile index cdc426c6..95a46fa2 100644 --- a/core/admin/Dockerfile +++ b/core/admin/Dockerfile @@ -35,7 +35,8 @@ COPY requirements-prod.txt requirements.txt RUN set -eu \ && apk add --no-cache libressl curl postgresql-libs mariadb-connector-c \ && apk add --no-cache --virtual build-dep libressl-dev libffi-dev python3-dev build-base postgresql-dev mariadb-connector-c-dev cargo \ - && pip3 install -r requirements.txt \ + && pip install --upgrade pip \ + && pip install -r requirements.txt \ && apk del --no-cache build-dep COPY --from=assets static ./mailu/ui/static diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt index 506cf050..38717145 100644 --- a/core/admin/requirements-prod.txt +++ b/core/admin/requirements-prod.txt @@ -1,14 +1,23 @@ alembic==1.0.10 +appdirs==1.4.4 asn1crypto==0.24.0 Babel==2.6.0 bcrypt==3.1.6 blinker==1.4 +CacheControl==0.12.6 +certifi==2020.12.5 cffi==1.12.3 +chardet==4.0.0 Click==7.0 +colorama==0.4.4 +contextlib2==0.6.0 cryptography==3.4.7 decorator==4.4.0 +distlib==0.3.1 +distro==1.5.0 dnspython==1.16.0 dominate==2.3.5 +email-validator==1.1.3 Flask==1.0.2 Flask-Babel==0.12.2 Flask-Bootstrap==3.3.7.1 @@ -21,36 +30,48 @@ Flask-Script==2.0.6 Flask-SQLAlchemy==2.4.0 Flask-WTF==0.14.2 gunicorn==20.1.0 +html5lib==1.1 idna==2.8 infinity==1.4 intervals==0.8.1 itsdangerous==1.1.0 Jinja2==2.11.3 limits==1.3 +lockfile==0.12.2 Mako==1.0.9 MarkupSafe==1.1.1 -mysqlclient==1.4.2.post1 marshmallow==3.10.0 marshmallow-sqlalchemy==0.24.1 +msgpack==1.0.2 +mysqlclient==1.4.2.post1 +ordered-set==4.0.2 +packaging==20.9 passlib==1.7.4 +pep517==0.10.0 +progress==1.5 psycopg2==2.8.2 pycparser==2.19 Pygments==2.8.1 pyOpenSSL==20.0.1 +pyparsing==2.4.7 python-dateutil==2.8.0 python-editor==1.0.4 pytz==2019.1 PyYAML==5.4.1 redis==3.2.1 -#alpine3:12 provides six==1.15.0 -#six==1.12.0 +requests==2.25.1 +retrying==1.3.3 +six==1.15.0 socrate==0.1.1 SQLAlchemy==1.3.3 srslib==0.1.4 tabulate==0.8.3 tenacity==5.0.4 +toml==0.10.2 +urllib3==1.26.5 validators==0.12.6 visitor==0.1.3 +webencodings==0.5.1 Werkzeug==0.15.5 WTForms==2.3.3 WTForms-Components==0.10.5 From 8d90a74624631745ea7f4964a4f7b55a5c27ad46 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 2 Nov 2021 15:39:41 +0100 Subject: [PATCH 03/30] update werkzeug to 1.x --- core/admin/mailu/debug.py | 4 ++-- core/admin/mailu/utils.py | 4 ++-- core/admin/requirements-prod.txt | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core/admin/mailu/debug.py b/core/admin/mailu/debug.py index 7677901b..4d63f3c5 100644 --- a/core/admin/mailu/debug.py +++ b/core/admin/mailu/debug.py @@ -1,6 +1,6 @@ import flask_debugtoolbar -from werkzeug.contrib import profiler as werkzeug_profiler +from werkzeug.middleware.profiler import ProfilerMiddleware # Debugging toolbar @@ -10,7 +10,7 @@ toolbar = flask_debugtoolbar.DebugToolbarExtension() # Profiler class Profiler(object): def init_app(self, app): - app.wsgi_app = werkzeug_profiler.ProfilerMiddleware( + app.wsgi_app = ProfilerMiddleware( app.wsgi_app, restrictions=[30] ) diff --git a/core/admin/mailu/utils.py b/core/admin/mailu/utils.py index dda927b0..eddd6848 100644 --- a/core/admin/mailu/utils.py +++ b/core/admin/mailu/utils.py @@ -28,7 +28,7 @@ import redis from flask.sessions import SessionMixin, SessionInterface from itsdangerous.encoding import want_bytes from werkzeug.datastructures import CallbackDict -from werkzeug.contrib import fixers +from werkzeug.middleware.proxy_fix import ProxyFix # Login configuration login = flask_login.LoginManager() @@ -109,7 +109,7 @@ class PrefixMiddleware(object): return self.app(environ, start_response) def init_app(self, app): - self.app = fixers.ProxyFix(app.wsgi_app, x_for=1, x_proto=1) + self.app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1) app.wsgi_app = self proxy = PrefixMiddleware() diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt index 38717145..673c4445 100644 --- a/core/admin/requirements-prod.txt +++ b/core/admin/requirements-prod.txt @@ -19,7 +19,7 @@ dnspython==1.16.0 dominate==2.3.5 email-validator==1.1.3 Flask==1.0.2 -Flask-Babel==0.12.2 +Flask-Babel==1.0.0 Flask-Bootstrap==3.3.7.1 Flask-DebugToolbar==0.10.1 Flask-Limiter==1.0.1 @@ -28,7 +28,7 @@ flask-marshmallow==0.14.0 Flask-Migrate==2.4.0 Flask-Script==2.0.6 Flask-SQLAlchemy==2.4.0 -Flask-WTF==0.14.2 +Flask-WTF==0.15.1 gunicorn==20.1.0 html5lib==1.1 idna==2.8 @@ -72,6 +72,6 @@ urllib3==1.26.5 validators==0.12.6 visitor==0.1.3 webencodings==0.5.1 -Werkzeug==0.15.5 +Werkzeug==1.0.1 WTForms==2.3.3 WTForms-Components==0.10.5 From 23d0cd04660abdb4ce9f4ebfb8b3f52070fa4c25 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 2 Nov 2021 15:55:20 +0100 Subject: [PATCH 04/30] update tabluate. fix audit.py and include in container --- core/admin/Dockerfile | 1 + core/admin/audit.py | 28 +++++++++++++++------------- core/admin/requirements-prod.txt | 2 +- 3 files changed, 17 insertions(+), 14 deletions(-) mode change 100644 => 100755 core/admin/audit.py diff --git a/core/admin/Dockerfile b/core/admin/Dockerfile index 95a46fa2..8adf2ca5 100644 --- a/core/admin/Dockerfile +++ b/core/admin/Dockerfile @@ -43,6 +43,7 @@ COPY --from=assets static ./mailu/ui/static COPY mailu ./mailu COPY migrations ./migrations COPY start.py /start.py +COPY audit.py /audit.py RUN pybabel compile -d mailu/translations diff --git a/core/admin/audit.py b/core/admin/audit.py old mode 100644 new mode 100755 index db105ff4..79365286 --- a/core/admin/audit.py +++ b/core/admin/audit.py @@ -1,14 +1,17 @@ -from mailu import app +#!/usr/bin/python3 import sys import tabulate +import mailu +app = mailu.create_app() + # Known endpoints without permissions known_missing_permissions = [ - "index", - "static", "bootstrap.static", - "admin.static", "admin.login" + 'index', + 'static', 'bootstrap.static', + 'admin.static', 'admin.login' ] @@ -16,7 +19,7 @@ known_missing_permissions = [ missing_permissions = [] permissions = {} for endpoint, function in app.view_functions.items(): - audit = function.__dict__.get("_audit_permissions") + audit = function.__dict__.get('_audit_permissions') if audit: handler, args = audit if args: @@ -28,16 +31,15 @@ for endpoint, function in app.view_functions.items(): elif endpoint not in known_missing_permissions: missing_permissions.append(endpoint) - -# Fail if any endpoint is missing a permission check -if missing_permissions: - print("The following endpoints are missing permission checks:") - print(missing_permissions.join(",")) - sys.exit(1) - - # Display the permissions table print(tabulate.tabulate([ [route, *permissions[route.endpoint]] for route in app.url_map.iter_rules() if route.endpoint in permissions ])) + +# Warn if any endpoint is missing a permission check +if missing_permissions: + print() + print('The following endpoints are missing permission checks:') + print(','.join(missing_permissions)) + diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt index 673c4445..79075f96 100644 --- a/core/admin/requirements-prod.txt +++ b/core/admin/requirements-prod.txt @@ -65,7 +65,7 @@ six==1.15.0 socrate==0.1.1 SQLAlchemy==1.3.3 srslib==0.1.4 -tabulate==0.8.3 +tabulate==0.8.9 tenacity==5.0.4 toml==0.10.2 urllib3==1.26.5 From 771b2d1112d846ddde6e5f7f54f787280c9a0c04 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 2 Nov 2021 16:21:31 +0100 Subject: [PATCH 05/30] duh --- core/admin/audit.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/admin/audit.py b/core/admin/audit.py index 79365286..60583f83 100755 --- a/core/admin/audit.py +++ b/core/admin/audit.py @@ -3,6 +3,8 @@ import sys import tabulate +sys.path[0:0] = ['/app'] + import mailu app = mailu.create_app() From dcbe55f0620395532a767d1a69647154d886a943 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 2 Nov 2021 16:28:37 +0100 Subject: [PATCH 06/30] updated crypto --- core/admin/requirements-prod.txt | 13 ++++++------- core/admin/requirements.txt | 1 - 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt index 79075f96..9bd131fb 100644 --- a/core/admin/requirements-prod.txt +++ b/core/admin/requirements-prod.txt @@ -1,18 +1,17 @@ alembic==1.0.10 appdirs==1.4.4 -asn1crypto==0.24.0 Babel==2.6.0 -bcrypt==3.1.6 +bcrypt==3.2.0 blinker==1.4 CacheControl==0.12.6 certifi==2020.12.5 -cffi==1.12.3 +cffi==1.15.0 chardet==4.0.0 Click==7.0 colorama==0.4.4 contextlib2==0.6.0 -cryptography==3.4.7 -decorator==4.4.0 +cryptography==35.0.0 +decorator==5.1.0 distlib==0.3.1 distro==1.5.0 dnspython==1.16.0 @@ -50,9 +49,9 @@ passlib==1.7.4 pep517==0.10.0 progress==1.5 psycopg2==2.8.2 -pycparser==2.19 +pycparser==2.20 Pygments==2.8.1 -pyOpenSSL==20.0.1 +pyOpenSSL==21.0.0 pyparsing==2.4.7 python-dateutil==2.8.0 python-editor==1.0.4 diff --git a/core/admin/requirements.txt b/core/admin/requirements.txt index e1de3b01..6cfa8a35 100644 --- a/core/admin/requirements.txt +++ b/core/admin/requirements.txt @@ -18,7 +18,6 @@ PyYAML PyOpenSSL Pygments dnspython -bcrypt tenacity mysqlclient psycopg2 From 40cdff491192cf8135e9c7818d490a39ce0f5fe0 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 2 Nov 2021 16:49:25 +0100 Subject: [PATCH 07/30] updated dnspython --- core/admin/mailu/models.py | 3 ++- core/admin/mailu/ui/views/domains.py | 1 - core/admin/mailu/utils.py | 6 +++++- core/admin/requirements-prod.txt | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index f5fe3b5e..300d8d8c 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -19,7 +19,8 @@ import os import hmac import smtplib import idna -import dns +import dns.resolver +import dns.exception from flask import current_app as app from sqlalchemy.ext import declarative diff --git a/core/admin/mailu/ui/views/domains.py b/core/admin/mailu/ui/views/domains.py index f394ce7d..a48bb154 100644 --- a/core/admin/mailu/ui/views/domains.py +++ b/core/admin/mailu/ui/views/domains.py @@ -5,7 +5,6 @@ from flask import current_app as app import flask import flask_login import wtforms_components -import dns.resolver @ui.route('/domain', methods=['GET']) diff --git a/core/admin/mailu/utils.py b/core/admin/mailu/utils.py index eddd6848..d9cc1894 100644 --- a/core/admin/mailu/utils.py +++ b/core/admin/mailu/utils.py @@ -6,8 +6,12 @@ try: except ImportError: import pickle -import dns import dns.resolver +import dns.exception +import dns.flags +import dns.rdtypes +import dns.rdatatype +import dns.rdataclass import hmac import secrets diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt index 9bd131fb..ecb0b8ed 100644 --- a/core/admin/requirements-prod.txt +++ b/core/admin/requirements-prod.txt @@ -14,7 +14,7 @@ cryptography==35.0.0 decorator==5.1.0 distlib==0.3.1 distro==1.5.0 -dnspython==1.16.0 +dnspython==2.1.0 dominate==2.3.5 email-validator==1.1.3 Flask==1.0.2 From 3ac1b3d86ce2452a87ff1a27de94f597773fff0e Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 2 Nov 2021 17:02:54 +0100 Subject: [PATCH 08/30] update pyyaml and pygments --- core/admin/requirements-prod.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt index ecb0b8ed..159a3c3c 100644 --- a/core/admin/requirements-prod.txt +++ b/core/admin/requirements-prod.txt @@ -50,13 +50,13 @@ pep517==0.10.0 progress==1.5 psycopg2==2.8.2 pycparser==2.20 -Pygments==2.8.1 +Pygments==2.10.0 pyOpenSSL==21.0.0 pyparsing==2.4.7 python-dateutil==2.8.0 python-editor==1.0.4 pytz==2019.1 -PyYAML==5.4.1 +PyYAML==6.0 redis==3.2.1 requests==2.25.1 retrying==1.3.3 From 8ad8cde0e27b62679e924fc7b4ba64ed7c53cb67 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 2 Nov 2021 17:06:28 +0100 Subject: [PATCH 09/30] removed some obsolete requirements --- core/admin/requirements-prod.txt | 2 -- core/admin/requirements.txt | 1 - 2 files changed, 3 deletions(-) diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt index 159a3c3c..9d734d94 100644 --- a/core/admin/requirements-prod.txt +++ b/core/admin/requirements-prod.txt @@ -53,8 +53,6 @@ pycparser==2.20 Pygments==2.10.0 pyOpenSSL==21.0.0 pyparsing==2.4.7 -python-dateutil==2.8.0 -python-editor==1.0.4 pytz==2019.1 PyYAML==6.0 redis==3.2.1 diff --git a/core/admin/requirements.txt b/core/admin/requirements.txt index 6cfa8a35..65130a8c 100644 --- a/core/admin/requirements.txt +++ b/core/admin/requirements.txt @@ -20,7 +20,6 @@ Pygments dnspython tenacity mysqlclient -psycopg2 idna srslib marshmallow From d8efd3057c85a397dd7c77f81d59ae4d91475841 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 2 Nov 2021 17:52:25 +0100 Subject: [PATCH 10/30] updated idna --- core/admin/requirements-prod.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt index 9d734d94..649eac49 100644 --- a/core/admin/requirements-prod.txt +++ b/core/admin/requirements-prod.txt @@ -30,7 +30,7 @@ Flask-SQLAlchemy==2.4.0 Flask-WTF==0.15.1 gunicorn==20.1.0 html5lib==1.1 -idna==2.8 +idna==3.2 infinity==1.4 intervals==0.8.1 itsdangerous==1.1.0 From ef19869cdef45829c8b52276d58ddab4e72085ad Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 2 Nov 2021 18:06:26 +0100 Subject: [PATCH 11/30] updated redis --- core/admin/requirements-prod.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt index 649eac49..40447e79 100644 --- a/core/admin/requirements-prod.txt +++ b/core/admin/requirements-prod.txt @@ -55,7 +55,7 @@ pyOpenSSL==21.0.0 pyparsing==2.4.7 pytz==2019.1 PyYAML==6.0 -redis==3.2.1 +redis==3.5.3 requests==2.25.1 retrying==1.3.3 six==1.15.0 From 866741bcbeaae33cf819bd0bebe2517ad9317008 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 2 Nov 2021 19:22:58 +0100 Subject: [PATCH 12/30] updated WTForms-Components deps --- core/admin/requirements-prod.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt index 40447e79..d88c71ed 100644 --- a/core/admin/requirements-prod.txt +++ b/core/admin/requirements-prod.txt @@ -31,8 +31,8 @@ Flask-WTF==0.15.1 gunicorn==20.1.0 html5lib==1.1 idna==3.2 -infinity==1.4 -intervals==0.8.1 +infinity==1.5 +intervals==0.9.2 itsdangerous==1.1.0 Jinja2==2.11.3 limits==1.3 @@ -66,7 +66,7 @@ tabulate==0.8.9 tenacity==5.0.4 toml==0.10.2 urllib3==1.26.5 -validators==0.12.6 +validators==0.18.2 visitor==0.1.3 webencodings==0.5.1 Werkzeug==1.0.1 From aca1e136484d73ea9c978a97563220bf1e633280 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 2 Nov 2021 20:47:53 +0100 Subject: [PATCH 13/30] update socrate - will be removed later --- core/admin/requirements-prod.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt index d88c71ed..3883c1c6 100644 --- a/core/admin/requirements-prod.txt +++ b/core/admin/requirements-prod.txt @@ -59,7 +59,7 @@ redis==3.5.3 requests==2.25.1 retrying==1.3.3 six==1.15.0 -socrate==0.1.1 +socrate==0.2.0 SQLAlchemy==1.3.3 srslib==0.1.4 tabulate==0.8.9 From f1d7bedd1b5465ac4fd86f7c4f380b257eee9059 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 3 Nov 2021 19:54:15 +0100 Subject: [PATCH 14/30] fix display of range inputs (again) --- core/admin/assets/app.css | 5 +++++ core/admin/assets/app.js | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/core/admin/assets/app.css b/core/admin/assets/app.css index 3886b5c1..84644900 100644 --- a/core/admin/assets/app.css +++ b/core/admin/assets/app.css @@ -52,3 +52,8 @@ fieldset:disabled .form-control:disabled { .select2-container--default .select2-selection--multiple .select2-selection__choice { color: black; } + +/* range input spacing */ +.input-group-text { + margin-right: 1em; +} diff --git a/core/admin/assets/app.js b/core/admin/assets/app.js index 54602d1f..e18228eb 100644 --- a/core/admin/assets/app.js +++ b/core/admin/assets/app.js @@ -43,7 +43,9 @@ $('document').ready(function() { var infinity = $(this).data('infinity'); var step = $(this).attr('step'); $(this).on('input', function() { - value_element.text((infinity && this.value == 0) ? '∞' : (this.value/step).toFixed(2)); + var num = (infinity && this.value == 0) ? '∞' : (this.value/step).toFixed(2); + if (num.endsWith('.00')) num = num.substr(0, num.length - 3); + value_element.text(num); }).trigger('input'); } }); From abc4112242d24ee6d6e4dd976ee51cae720df228 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 3 Nov 2021 20:12:20 +0100 Subject: [PATCH 15/30] updated Werkzeug, Click and Flask-Migrate --- core/admin/requirements-prod.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt index 3883c1c6..4a209fba 100644 --- a/core/admin/requirements-prod.txt +++ b/core/admin/requirements-prod.txt @@ -7,7 +7,7 @@ CacheControl==0.12.6 certifi==2020.12.5 cffi==1.15.0 chardet==4.0.0 -Click==7.0 +click==8.0.3 colorama==0.4.4 contextlib2==0.6.0 cryptography==35.0.0 @@ -24,7 +24,7 @@ Flask-DebugToolbar==0.10.1 Flask-Limiter==1.0.1 Flask-Login==0.4.1 flask-marshmallow==0.14.0 -Flask-Migrate==2.4.0 +Flask-Migrate==3.1.0 Flask-Script==2.0.6 Flask-SQLAlchemy==2.4.0 Flask-WTF==0.15.1 @@ -69,6 +69,6 @@ urllib3==1.26.5 validators==0.18.2 visitor==0.1.3 webencodings==0.5.1 -Werkzeug==1.0.1 +Werkzeug==2.0.2 WTForms==2.3.3 WTForms-Components==0.10.5 From 26fb108a3fb435d097883901470781726757f9f4 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 3 Nov 2021 20:22:47 +0100 Subject: [PATCH 16/30] updated Flask-Login --- core/admin/mailu/utils.py | 2 +- core/admin/requirements-prod.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/admin/mailu/utils.py b/core/admin/mailu/utils.py index 972546d6..8ae028bf 100644 --- a/core/admin/mailu/utils.py +++ b/core/admin/mailu/utils.py @@ -269,7 +269,7 @@ class MailuSession(CallbackDict, SessionMixin): # set uid from dict data if self._uid is None: - self._uid = self.app.session_config.gen_uid(self.get('user_id', '')) + self._uid = self.app.session_config.gen_uid(self.get('_user_id', '')) # create new session id for new or regenerated sessions and force setting the cookie if self._sid is None: diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt index 4a209fba..bb94e4b5 100644 --- a/core/admin/requirements-prod.txt +++ b/core/admin/requirements-prod.txt @@ -22,7 +22,7 @@ Flask-Babel==1.0.0 Flask-Bootstrap==3.3.7.1 Flask-DebugToolbar==0.10.1 Flask-Limiter==1.0.1 -Flask-Login==0.4.1 +Flask-Login==0.5.0 flask-marshmallow==0.14.0 Flask-Migrate==3.1.0 Flask-Script==2.0.6 From 8b15820b014f73bf41aaffca3914ee8207082114 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 3 Nov 2021 20:35:05 +0100 Subject: [PATCH 17/30] fix sso login button spacing --- core/admin/mailu/ui/templates/macros.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/admin/mailu/ui/templates/macros.html b/core/admin/mailu/ui/templates/macros.html index 5143b697..75de4e0e 100644 --- a/core/admin/mailu/ui/templates/macros.html +++ b/core/admin/mailu/ui/templates/macros.html @@ -22,7 +22,7 @@ {%- if spacing %} {%- set width = (12 / fields|length)|int %} {%- else %} - {%- set width = 0 %} + {%- set width = 2 %} {% endif %}
From 833ccb5544816e5321a4066bb1102ed144c02384 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 3 Nov 2021 20:38:00 +0100 Subject: [PATCH 18/30] reload page using GET when selecting language --- core/admin/assets/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/admin/assets/app.js b/core/admin/assets/app.js index e18228eb..0926578d 100644 --- a/core/admin/assets/app.js +++ b/core/admin/assets/app.js @@ -18,7 +18,7 @@ $('document').ready(function() { $.post({ url: $(this).attr('href'), success: function() { - location.reload(); + window.location = window.location.href; }, }); }); From f613205fe16488fcc1b7658bfff35eb186a543fa Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 3 Nov 2021 21:30:34 +0100 Subject: [PATCH 19/30] update tenacity --- core/admin/migrations/env.py | 69 ++++++++++++++++---------------- core/admin/requirements-prod.txt | 2 +- 2 files changed, 36 insertions(+), 35 deletions(-) diff --git a/core/admin/migrations/env.py b/core/admin/migrations/env.py index 3e45bb18..65a4e471 100755 --- a/core/admin/migrations/env.py +++ b/core/admin/migrations/env.py @@ -1,10 +1,12 @@ -from __future__ import with_statement +import logging +import tenacity + from alembic import context from sqlalchemy import engine_from_config, pool from logging.config import fileConfig -import logging -import tenacity -from tenacity import retry + +from flask import current_app +from mailu import models # this is the Alembic Config object, which provides # access to the values within the .ini file in use. @@ -17,20 +19,12 @@ logger = logging.getLogger('alembic.env') # add your model's MetaData object here # for 'autogenerate' support -# from myapp import mymodel -# target_metadata = mymodel.Base.metadata -from flask import current_app -config.set_main_option('sqlalchemy.url', - current_app.config.get('SQLALCHEMY_DATABASE_URI')) -#target_metadata = current_app.extensions['migrate'].db.metadata -from mailu import models +config.set_main_option( + 'sqlalchemy.url', + current_app.config.get('SQLALCHEMY_DATABASE_URI') +) target_metadata = models.Base.metadata -# other values from the config, defined by the needs of env.py, -# can be acquired: -# my_important_option = config.get_main_option("my_important_option") -# ... etc. - def run_migrations_offline(): """Run migrations in 'offline' mode. @@ -44,7 +38,7 @@ def run_migrations_offline(): script output. """ - url = config.get_main_option("sqlalchemy.url") + url = config.get_main_option('sqlalchemy.url') context.configure(url=url) with context.begin_transaction(): @@ -69,28 +63,35 @@ def run_migrations_online(): directives[:] = [] logger.info('No changes in schema detected.') - engine = engine_from_config(config.get_section(config.config_ini_section), - prefix='sqlalchemy.', - poolclass=pool.NullPool) + engine = engine_from_config( + config.get_section(config.config_ini_section), + prefix = 'sqlalchemy.', + poolclass = pool.NullPool + ) - connection = tenacity.Retrying( - stop=tenacity.stop_after_attempt(100), - wait=tenacity.wait_random(min=2, max=5), - before=tenacity.before_log(logging.getLogger("tenacity.retry"), logging.DEBUG), - before_sleep=tenacity.before_sleep_log(logging.getLogger("tenacity.retry"), logging.INFO), - after=tenacity.after_log(logging.getLogger("tenacity.retry"), logging.DEBUG) - ).call(engine.connect) + @tenacity.retry( + stop = tenacity.stop_after_attempt(100), + wait = tenacity.wait_random(min=2, max=5), + before = tenacity.before_log(logging.getLogger('tenacity.retry'), logging.DEBUG), + before_sleep = tenacity.before_sleep_log(logging.getLogger('tenacity.retry'), logging.INFO), + after = tenacity.after_log(logging.getLogger('tenacity.retry'), logging.DEBUG) + ) + def try_connect(db): + return db.connect() - context.configure(connection=connection, - target_metadata=target_metadata, - process_revision_directives=process_revision_directives, - **current_app.extensions['migrate'].configure_args) + with try_connect(engine) as connection: + + context.configure( + connection = connection, + target_metadata = target_metadata, + process_revision_directives = process_revision_directives, + **current_app.extensions['migrate'].configure_args + ) - try: with context.begin_transaction(): context.run_migrations() - finally: - connection.close() + + connection.close() if context.is_offline_mode(): run_migrations_offline() diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt index bb94e4b5..3d08e2ff 100644 --- a/core/admin/requirements-prod.txt +++ b/core/admin/requirements-prod.txt @@ -63,7 +63,7 @@ socrate==0.2.0 SQLAlchemy==1.3.3 srslib==0.1.4 tabulate==0.8.9 -tenacity==5.0.4 +tenacity==8.0.1 toml==0.10.2 urllib3==1.26.5 validators==0.18.2 From 5238b00f0b0358700a16c52e77f35f1759cf6437 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 3 Nov 2021 21:33:39 +0100 Subject: [PATCH 20/30] update alembic --- core/admin/requirements-prod.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt index 3d08e2ff..4b629d5d 100644 --- a/core/admin/requirements-prod.txt +++ b/core/admin/requirements-prod.txt @@ -1,4 +1,4 @@ -alembic==1.0.10 +alembic==1.7.4 appdirs==1.4.4 Babel==2.6.0 bcrypt==3.2.0 From 56f65d724d1982fa0c3cb9a5444812328d283094 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 3 Nov 2021 21:52:59 +0100 Subject: [PATCH 21/30] update babel --- core/admin/mailu/__init__.py | 5 +++++ core/admin/mailu/ui/templates/domain/list.html | 4 ++-- core/admin/mailu/utils.py | 3 +-- core/admin/requirements-prod.txt | 6 +++--- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/core/admin/mailu/__init__.py b/core/admin/mailu/__init__.py index e4024e47..b49bdd67 100644 --- a/core/admin/mailu/__init__.py +++ b/core/admin/mailu/__init__.py @@ -57,6 +57,11 @@ def create_app_from_config(config): config = app.config, ) + # Jinja filter + @app.template_filter() + def format_date(value): + return utils.flask_babel.format_date(value) if value else '' + # Import views from mailu import ui, internal, sso app.register_blueprint(ui.ui, url_prefix=app.config['WEB_ADMIN']) diff --git a/core/admin/mailu/ui/templates/domain/list.html b/core/admin/mailu/ui/templates/domain/list.html index 6f6bc467..61c09151 100644 --- a/core/admin/mailu/ui/templates/domain/list.html +++ b/core/admin/mailu/ui/templates/domain/list.html @@ -46,8 +46,8 @@ {{ domain.users | count }} / {{ '∞' if domain.max_users == -1 else domain.max_users }} {{ domain.aliases | count }} / {{ '∞' if domain.max_aliases == -1 else domain.max_aliases }} {{ domain.comment or '' }} - {{ domain.created_at }} - {{ domain.updated_at or '' }} + {{ domain.created_at | format_date }} + {{ domain.updated_at | format_date }} {%- endfor %} diff --git a/core/admin/mailu/utils.py b/core/admin/mailu/utils.py index 8ae028bf..024c487f 100644 --- a/core/admin/mailu/utils.py +++ b/core/admin/mailu/utils.py @@ -18,10 +18,9 @@ import secrets import time from multiprocessing import Value - from mailu import limiter - from flask import current_app as app + import flask import flask_login import flask_migrate diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt index 4b629d5d..ccd2b83d 100644 --- a/core/admin/requirements-prod.txt +++ b/core/admin/requirements-prod.txt @@ -1,6 +1,6 @@ alembic==1.7.4 appdirs==1.4.4 -Babel==2.6.0 +Babel==2.9.1 bcrypt==3.2.0 blinker==1.4 CacheControl==0.12.6 @@ -18,7 +18,7 @@ dnspython==2.1.0 dominate==2.3.5 email-validator==1.1.3 Flask==1.0.2 -Flask-Babel==1.0.0 +Flask-Babel==2.0.0 Flask-Bootstrap==3.3.7.1 Flask-DebugToolbar==0.10.1 Flask-Limiter==1.0.1 @@ -53,7 +53,7 @@ pycparser==2.20 Pygments==2.10.0 pyOpenSSL==21.0.0 pyparsing==2.4.7 -pytz==2019.1 +pytz==2021.3 PyYAML==6.0 redis==3.5.3 requests==2.25.1 From 87884213c466472a98cbd19e988b65c9190fea62 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 3 Nov 2021 22:03:51 +0100 Subject: [PATCH 22/30] update misc helper libs --- core/admin/requirements-prod.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt index ccd2b83d..282d00c3 100644 --- a/core/admin/requirements-prod.txt +++ b/core/admin/requirements-prod.txt @@ -15,12 +15,12 @@ decorator==5.1.0 distlib==0.3.1 distro==1.5.0 dnspython==2.1.0 -dominate==2.3.5 +dominate==2.6.0 email-validator==1.1.3 Flask==1.0.2 Flask-Babel==2.0.0 Flask-Bootstrap==3.3.7.1 -Flask-DebugToolbar==0.10.1 +Flask-DebugToolbar==0.11.0 Flask-Limiter==1.0.1 Flask-Login==0.5.0 flask-marshmallow==0.14.0 @@ -33,12 +33,12 @@ html5lib==1.1 idna==3.2 infinity==1.5 intervals==0.9.2 -itsdangerous==1.1.0 -Jinja2==2.11.3 -limits==1.3 +itsdangerous==2.0.1 +Jinja2==3.0.2 +limits==1.5.1 lockfile==0.12.2 -Mako==1.0.9 -MarkupSafe==1.1.1 +Mako==1.1.5 +MarkupSafe==2.0.1 marshmallow==3.10.0 marshmallow-sqlalchemy==0.24.1 msgpack==1.0.2 From ffd99c3fa8ee6c3ad590973c4c5ebdbe0172474d Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 3 Nov 2021 22:21:26 +0100 Subject: [PATCH 23/30] updated flask ConfigManager should not replace app.config - this is causing trouble with some other flask modules (swagger). Updated ConfigManager to only modify app.config and not replace it. --- core/admin/mailu/__init__.py | 2 +- core/admin/mailu/configuration.py | 48 +++++++++---------------------- core/admin/requirements-prod.txt | 2 +- 3 files changed, 16 insertions(+), 36 deletions(-) diff --git a/core/admin/mailu/__init__.py b/core/admin/mailu/__init__.py index b49bdd67..2f1b8469 100644 --- a/core/admin/mailu/__init__.py +++ b/core/admin/mailu/__init__.py @@ -33,7 +33,7 @@ def create_app_from_config(config): app.srs_key = hmac.new(bytearray(app.secret_key, 'utf-8'), bytearray('SRS_KEY', 'utf-8'), 'sha256').digest() # Initialize list of translations - config.translations = { + app.config.translations = { str(locale): locale for locale in sorted( utils.babel.list_translations(), diff --git a/core/admin/mailu/configuration.py b/core/admin/mailu/configuration.py index 9829f798..96127ee2 100644 --- a/core/admin/mailu/configuration.py +++ b/core/admin/mailu/configuration.py @@ -88,7 +88,7 @@ DEFAULT_CONFIG = { 'POD_ADDRESS_RANGE': None } -class ConfigManager(dict): +class ConfigManager: """ Naive configuration manager that uses environment only """ @@ -103,19 +103,16 @@ class ConfigManager(dict): def get_host_address(self, name): # if MYSERVICE_ADDRESS is defined, use this - if '{}_ADDRESS'.format(name) in os.environ: - return os.environ.get('{}_ADDRESS'.format(name)) + if f'{name}_ADDRESS' in os.environ: + return os.environ.get(f'{name}_ADDRESS') # otherwise use the host name and resolve it - return system.resolve_address(self.config['HOST_{}'.format(name)]) + return system.resolve_address(self.config[f'HOST_{name}']) def resolve_hosts(self): - self.config["IMAP_ADDRESS"] = self.get_host_address("IMAP") - self.config["POP3_ADDRESS"] = self.get_host_address("POP3") - self.config["AUTHSMTP_ADDRESS"] = self.get_host_address("AUTHSMTP") - self.config["SMTP_ADDRESS"] = self.get_host_address("SMTP") - self.config["REDIS_ADDRESS"] = self.get_host_address("REDIS") - if self.config["WEBMAIL"] != "none": - self.config["WEBMAIL_ADDRESS"] = self.get_host_address("WEBMAIL") + for key in ['IMAP', 'POP3', 'AUTHSMTP', 'SMTP', 'REDIS']: + self.config[f'{key}_ADDRESS'] = self.get_host_address(key) + if self.config['WEBMAIL'] != 'none': + self.config['WEBMAIL_ADDRESS'] = self.get_host_address('WEBMAIL') def __get_env(self, key, value): key_file = key + "_FILE" @@ -134,6 +131,7 @@ class ConfigManager(dict): return value def init_app(self, app): + # get current app config self.config.update(app.config) # get environment variables self.config.update({ @@ -147,9 +145,9 @@ class ConfigManager(dict): template = self.DB_TEMPLATES[self.config['DB_FLAVOR']] self.config['SQLALCHEMY_DATABASE_URI'] = template.format(**self.config) - self.config['RATELIMIT_STORAGE_URL'] = 'redis://{0}/2'.format(self.config['REDIS_ADDRESS']) - self.config['QUOTA_STORAGE_URL'] = 'redis://{0}/1'.format(self.config['REDIS_ADDRESS']) - self.config['SESSION_STORAGE_URL'] = 'redis://{0}/3'.format(self.config['REDIS_ADDRESS']) + self.config['RATELIMIT_STORAGE_URL'] = f'redis://{self.config["REDIS_ADDRESS"]}/2' + self.config['QUOTA_STORAGE_URL'] = f'redis://{self.config["REDIS_ADDRESS"]}/1' + self.config['SESSION_STORAGE_URL'] = f'redis://{self.config["REDIS_ADDRESS"]}/3' self.config['SESSION_COOKIE_SAMESITE'] = 'Strict' self.config['SESSION_COOKIE_HTTPONLY'] = True self.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=int(self.config['SESSION_LIFETIME'])) @@ -157,25 +155,7 @@ class ConfigManager(dict): self.config['AUTH_RATELIMIT_EXEMPTION'] = set(ipaddress.ip_network(cidr, False) for cidr in (cidr.strip() for cidr in self.config['AUTH_RATELIMIT_EXEMPTION'].split(',')) if cidr) self.config['HOSTNAMES'] = ','.join(hostnames) self.config['HOSTNAME'] = hostnames[0] - # update the app config itself - app.config = self - def setdefault(self, key, value): - if key not in self.config: - self.config[key] = value - return self.config[key] + # update the app config + app.config.update(self.config) - def get(self, *args): - return self.config.get(*args) - - def keys(self): - return self.config.keys() - - def __getitem__(self, key): - return self.config.get(key) - - def __setitem__(self, key, value): - self.config[key] = value - - def __contains__(self, key): - return key in self.config diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt index 282d00c3..ce7d4017 100644 --- a/core/admin/requirements-prod.txt +++ b/core/admin/requirements-prod.txt @@ -17,7 +17,7 @@ distro==1.5.0 dnspython==2.1.0 dominate==2.6.0 email-validator==1.1.3 -Flask==1.0.2 +Flask==2.0.2 Flask-Babel==2.0.0 Flask-Bootstrap==3.3.7.1 Flask-DebugToolbar==0.11.0 From 85d86d415624f2d3c335a1922527f92886d9fd3f Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 3 Nov 2021 22:55:26 +0100 Subject: [PATCH 24/30] some more libs updated --- core/admin/requirements-prod.txt | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt index ce7d4017..331239ba 100644 --- a/core/admin/requirements-prod.txt +++ b/core/admin/requirements-prod.txt @@ -3,17 +3,17 @@ appdirs==1.4.4 Babel==2.9.1 bcrypt==3.2.0 blinker==1.4 -CacheControl==0.12.6 -certifi==2020.12.5 +CacheControl==0.12.9 +certifi==2021.10.8 cffi==1.15.0 chardet==4.0.0 click==8.0.3 colorama==0.4.4 -contextlib2==0.6.0 +contextlib2==21.6.0 cryptography==35.0.0 decorator==5.1.0 -distlib==0.3.1 -distro==1.5.0 +# distlib==0.3.1 +# distro==1.5.0 dnspython==2.1.0 dominate==2.6.0 email-validator==1.1.3 @@ -21,7 +21,7 @@ Flask==2.0.2 Flask-Babel==2.0.0 Flask-Bootstrap==3.3.7.1 Flask-DebugToolbar==0.11.0 -Flask-Limiter==1.0.1 +Flask-Limiter==1.4 Flask-Login==0.5.0 flask-marshmallow==0.14.0 Flask-Migrate==3.1.0 @@ -30,7 +30,7 @@ Flask-SQLAlchemy==2.4.0 Flask-WTF==0.15.1 gunicorn==20.1.0 html5lib==1.1 -idna==3.2 +idna==3.3 infinity==1.5 intervals==0.9.2 itsdangerous==2.0.1 @@ -44,28 +44,28 @@ marshmallow-sqlalchemy==0.24.1 msgpack==1.0.2 mysqlclient==1.4.2.post1 ordered-set==4.0.2 -packaging==20.9 +# packaging==20.9 passlib==1.7.4 -pep517==0.10.0 -progress==1.5 +# pep517==0.10.0 +progress==1.6 psycopg2==2.8.2 pycparser==2.20 Pygments==2.10.0 pyOpenSSL==21.0.0 -pyparsing==2.4.7 +pyparsing==3.0.4 pytz==2021.3 PyYAML==6.0 redis==3.5.3 -requests==2.25.1 +requests==2.26.0 retrying==1.3.3 -six==1.15.0 +# six==1.15.0 socrate==0.2.0 SQLAlchemy==1.3.3 srslib==0.1.4 tabulate==0.8.9 tenacity==8.0.1 toml==0.10.2 -urllib3==1.26.5 +urllib3==1.26.7 validators==0.18.2 visitor==0.1.3 webencodings==0.5.1 From 4669374b9ec951c081777fe4284edc69cb4be0a2 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 3 Nov 2021 22:55:41 +0100 Subject: [PATCH 25/30] use python wheels --- core/admin/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/admin/Dockerfile b/core/admin/Dockerfile index 5c1227e5..cf911d82 100644 --- a/core/admin/Dockerfile +++ b/core/admin/Dockerfile @@ -25,7 +25,7 @@ COPY --from=balenalib/rpi-alpine:3.14 /usr/bin/qemu-arm-static /usr/bin/qemu-arm # python3 shared with most images RUN set -eu \ - && apk add --no-cache python3 py3-pip git bash \ + && apk add --no-cache python3 py3-pip py3-wheel git bash \ && pip3 install --upgrade pip RUN mkdir -p /app From 73ab4327c29b3e5f65e5c26b5f86418612daa972 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 3 Nov 2021 22:57:07 +0100 Subject: [PATCH 26/30] updated database libraries (sqlalchemy etc.) this is working fine, but introduces a sqlalchemy warning when using config-import: /app/mailu/schemas.py:822: SAWarning: Identity map already had an identity for (...), replacing it with newly flushed object. Are there load operations occurring inside of an event handler within the flush? --- core/admin/mailu/models.py | 16 ++++++++-------- core/admin/mailu/schemas.py | 5 +++++ core/admin/requirements-prod.txt | 13 +++++++------ 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index 300d8d8c..697e4df7 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -39,6 +39,8 @@ class IdnaDomain(db.TypeDecorator): """ impl = db.String(80) + cache_ok = True + python_type = str def process_bind_param(self, value, dialect): """ encode unicode domain name to punycode """ @@ -48,13 +50,13 @@ class IdnaDomain(db.TypeDecorator): """ decode punycode domain name to unicode """ return idna.decode(value) - python_type = str - class IdnaEmail(db.TypeDecorator): """ Stores a Unicode string in it's IDNA representation (ASCII only) """ impl = db.String(255) + cache_ok = True + python_type = str def process_bind_param(self, value, dialect): """ encode unicode domain part of email address to punycode """ @@ -70,13 +72,13 @@ class IdnaEmail(db.TypeDecorator): localpart, domain_name = value.rsplit('@', 1) return f'{localpart}@{idna.decode(domain_name)}' - python_type = str - class CommaSeparatedList(db.TypeDecorator): """ Stores a list as a comma-separated string, compatible with Postfix. """ impl = db.String + cache_ok = True + python_type = list def process_bind_param(self, value, dialect): """ join list of items to comma separated string """ @@ -91,13 +93,13 @@ class CommaSeparatedList(db.TypeDecorator): """ split comma separated string to list """ return list(filter(bool, (item.strip() for item in value.split(',')))) if value else [] - python_type = list - class JSONEncoded(db.TypeDecorator): """ Represents an immutable structure as a json-encoded string. """ impl = db.String + cache_ok = True + python_type = str def process_bind_param(self, value, dialect): """ encode data as json """ @@ -107,8 +109,6 @@ class JSONEncoded(db.TypeDecorator): """ decode json to data """ return json.loads(value) if value else None - python_type = str - class Base(db.Model): """ Base class for all models """ diff --git a/core/admin/mailu/schemas.py b/core/admin/mailu/schemas.py index 191d01ac..00cbf464 100644 --- a/core/admin/mailu/schemas.py +++ b/core/admin/mailu/schemas.py @@ -145,6 +145,11 @@ class Logger: if history.has_changes() and history.deleted: before = history.deleted[-1] after = getattr(target, attr.key) + # we don't have ordered lists + if isinstance(before, list): + before = set(before) + if isinstance(after, list): + after = set(after) # TODO: this can be removed when comment is not nullable in model if attr.key == 'comment' and not before and not after: pass diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt index 331239ba..d6c7aca3 100644 --- a/core/admin/requirements-prod.txt +++ b/core/admin/requirements-prod.txt @@ -26,8 +26,9 @@ Flask-Login==0.5.0 flask-marshmallow==0.14.0 Flask-Migrate==3.1.0 Flask-Script==2.0.6 -Flask-SQLAlchemy==2.4.0 +Flask-SQLAlchemy==2.5.1 Flask-WTF==0.15.1 +greenlet==1.1.2 gunicorn==20.1.0 html5lib==1.1 idna==3.3 @@ -39,16 +40,16 @@ limits==1.5.1 lockfile==0.12.2 Mako==1.1.5 MarkupSafe==2.0.1 -marshmallow==3.10.0 -marshmallow-sqlalchemy==0.24.1 +marshmallow==3.14.0 +marshmallow-sqlalchemy==0.26.1 msgpack==1.0.2 -mysqlclient==1.4.2.post1 +mysqlclient==2.0.3 ordered-set==4.0.2 # packaging==20.9 passlib==1.7.4 # pep517==0.10.0 progress==1.6 -psycopg2==2.8.2 +psycopg2==2.9.1 pycparser==2.20 Pygments==2.10.0 pyOpenSSL==21.0.0 @@ -60,7 +61,7 @@ requests==2.26.0 retrying==1.3.3 # six==1.15.0 socrate==0.2.0 -SQLAlchemy==1.3.3 +SQLAlchemy==1.4.26 srslib==0.1.4 tabulate==0.8.9 tenacity==8.0.1 From 97e79a973f1ebd1e3d586cb318f0a7484cc4313e Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 4 Nov 2021 08:32:53 +0100 Subject: [PATCH 27/30] fix sso login button spacing again --- core/admin/mailu/sso/templates/form_sso.html | 2 +- core/admin/mailu/sso/views/base.py | 1 + core/admin/mailu/ui/templates/macros.html | 14 ++++++++------ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/core/admin/mailu/sso/templates/form_sso.html b/core/admin/mailu/sso/templates/form_sso.html index b14e7600..d2451597 100644 --- a/core/admin/mailu/sso/templates/form_sso.html +++ b/core/admin/mailu/sso/templates/form_sso.html @@ -5,7 +5,7 @@
{{ macros.form_field(form.email) }} {{ macros.form_field(form.pw) }} - {{ macros.form_fields(fields, label=False, class="btn btn-default", spacing=False) }} + {{ macros.form_fields(fields, label=False, class="btn btn-default") }}
{%- endcall %} {%- endblock %} diff --git a/core/admin/mailu/sso/views/base.py b/core/admin/mailu/sso/views/base.py index fbee52a7..e948aeb7 100644 --- a/core/admin/mailu/sso/views/base.py +++ b/core/admin/mailu/sso/views/base.py @@ -19,6 +19,7 @@ def login(): fields.append(form.submitAdmin) if str(app.config["WEBMAIL"]).upper() != "NONE": fields.append(form.submitWebmail) + fields = [fields] if form.validate_on_submit(): if form.submitAdmin.data: diff --git a/core/admin/mailu/ui/templates/macros.html b/core/admin/mailu/ui/templates/macros.html index 75de4e0e..3b7e4c1d 100644 --- a/core/admin/mailu/ui/templates/macros.html +++ b/core/admin/mailu/ui/templates/macros.html @@ -18,17 +18,19 @@ {%- endif %} {%- endmacro %} -{%- macro form_fields(fields, prepend='', append='', label=True, spacing=True) %} - {%- if spacing %} +{%- macro form_fields(fields, prepend='', append='', label=True) %} {%- set width = (12 / fields|length)|int %} - {%- else %} - {%- set width = 2 %} - {% endif %}
{%- for field in fields %}
- {{ form_individual_field(field, prepend=prepend, append=append, label=label, **kwargs) }} + {%- if field is iterable %} + {%- for subfield in field %} + {{ form_individual_field(subfield, prepend=prepend, append=append, label=label, **kwargs) }} + {%- endfor %} + {%- else %} + {{ form_individual_field(field, prepend=prepend, append=append, label=label, **kwargs) }} + {%- endif %}
{%- endfor %}
From fd5bdc86501562645d540e44358a787a55ebe542 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 11 Nov 2021 12:20:52 +0100 Subject: [PATCH 28/30] added localized date output --- core/admin/mailu/__init__.py | 6 +++++- core/admin/mailu/ui/templates/alias/list.html | 4 ++-- core/admin/mailu/ui/templates/alternative/list.html | 4 +++- core/admin/mailu/ui/templates/fetch/list.html | 6 +++--- core/admin/mailu/ui/templates/relay/list.html | 4 ++-- core/admin/mailu/ui/templates/token/list.html | 4 +++- core/admin/mailu/ui/templates/user/list.html | 4 ++-- 7 files changed, 20 insertions(+), 12 deletions(-) diff --git a/core/admin/mailu/__init__.py b/core/admin/mailu/__init__.py index 2f1b8469..fe1f376c 100644 --- a/core/admin/mailu/__init__.py +++ b/core/admin/mailu/__init__.py @@ -57,11 +57,15 @@ def create_app_from_config(config): config = app.config, ) - # Jinja filter + # Jinja filters @app.template_filter() def format_date(value): return utils.flask_babel.format_date(value) if value else '' + @app.template_filter() + def format_datetime(value): + return utils.flask_babel.format_datetime(value) if value else '' + # Import views from mailu import ui, internal, sso app.register_blueprint(ui.ui, url_prefix=app.config['WEB_ADMIN']) diff --git a/core/admin/mailu/ui/templates/alias/list.html b/core/admin/mailu/ui/templates/alias/list.html index 0b784d52..6b52165e 100644 --- a/core/admin/mailu/ui/templates/alias/list.html +++ b/core/admin/mailu/ui/templates/alias/list.html @@ -34,8 +34,8 @@ {{ alias }} {{ alias.destination|join(', ') or '-' }} {{ alias.comment or '' }} - {{ alias.created_at }} - {{ alias.updated_at or '' }} + {{ alias.created_at | format_date }} + {{ alias.updated_at | format_date }} {%- endfor %} diff --git a/core/admin/mailu/ui/templates/alternative/list.html b/core/admin/mailu/ui/templates/alternative/list.html index b56cd751..4ca9f3c8 100644 --- a/core/admin/mailu/ui/templates/alternative/list.html +++ b/core/admin/mailu/ui/templates/alternative/list.html @@ -19,6 +19,7 @@ {% trans %}Actions{% endtrans %} {% trans %}Name{% endtrans %} {% trans %}Created{% endtrans %} + {% trans %}Last edit{% endtrans %} @@ -28,7 +29,8 @@ {{ alternative }} - {{ alternative.created_at }} + {{ alternative.created_at | format_date }} + {{ alternative.updated_at | format_date }} {%- endfor %} diff --git a/core/admin/mailu/ui/templates/fetch/list.html b/core/admin/mailu/ui/templates/fetch/list.html index d9374fc6..60b214de 100644 --- a/core/admin/mailu/ui/templates/fetch/list.html +++ b/core/admin/mailu/ui/templates/fetch/list.html @@ -36,10 +36,10 @@ {{ fetch.protocol }}{{ 's' if fetch.tls else '' }}://{{ fetch.host }}:{{ fetch.port }} {{ fetch.username }} {% if fetch.keep %}{% trans %}yes{% endtrans %}{% else %}{% trans %}no{% endtrans %}{% endif %} - {{ fetch.last_check or '-' }} + {{ fetch.last_check | format_datetime or '-' }} {{ fetch.error or '-' }} - {{ fetch.created_at }} - {{ fetch.updated_at or '' }} + {{ fetch.created_at | format_date }} + {{ fetch.updated_at | format_date }} {%- endfor %} diff --git a/core/admin/mailu/ui/templates/relay/list.html b/core/admin/mailu/ui/templates/relay/list.html index 07838273..80bc5338 100644 --- a/core/admin/mailu/ui/templates/relay/list.html +++ b/core/admin/mailu/ui/templates/relay/list.html @@ -32,8 +32,8 @@ {{ relay.name }} {{ relay.smtp or '-' }} {{ relay.comment or '' }} - {{ relay.created_at }} - {{ relay.updated_at or '' }} + {{ relay.created_at | format_date }} + {{ relay.updated_at | format_date }} {%- endfor %} diff --git a/core/admin/mailu/ui/templates/token/list.html b/core/admin/mailu/ui/templates/token/list.html index c3cc9b5c..d7c48737 100644 --- a/core/admin/mailu/ui/templates/token/list.html +++ b/core/admin/mailu/ui/templates/token/list.html @@ -20,6 +20,7 @@ {% trans %}Comment{% endtrans %} {% trans %}Authorized IP{% endtrans %} {% trans %}Created{% endtrans %} + {% trans %}Last edit{% endtrans %} @@ -30,7 +31,8 @@ {{ token.comment }} {{ token.ip or "any" }} - {{ token.created_at }} + {{ token.created_at | format_date }} + {{ token.updated_at | format_date }} {%- endfor %} diff --git a/core/admin/mailu/ui/templates/user/list.html b/core/admin/mailu/ui/templates/user/list.html index 59a06ea7..7faddab5 100644 --- a/core/admin/mailu/ui/templates/user/list.html +++ b/core/admin/mailu/ui/templates/user/list.html @@ -45,8 +45,8 @@ {{ user.quota_bytes_used | filesizeformat }} / {{ (user.quota_bytes | filesizeformat) if user.quota_bytes else '∞' }} {{ user.comment or '-' }} - {{ user.created_at }} - {{ user.updated_at or '' }} + {{ user.created_at | format_date }} + {{ user.updated_at | format_date }} {%- endfor %} From cf7914d050687d72606a0157cdf73c7fab785f56 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 11 Nov 2021 16:00:00 +0100 Subject: [PATCH 29/30] fixed field iteration --- core/admin/mailu/ui/templates/macros.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/admin/mailu/ui/templates/macros.html b/core/admin/mailu/ui/templates/macros.html index 3b7e4c1d..0da069a9 100644 --- a/core/admin/mailu/ui/templates/macros.html +++ b/core/admin/mailu/ui/templates/macros.html @@ -24,7 +24,7 @@
{%- for field in fields %}
- {%- if field is iterable %} + {%- if field.__class__.__name__ == 'list' %} {%- for subfield in field %} {{ form_individual_field(subfield, prepend=prepend, append=append, label=label, **kwargs) }} {%- endfor %} From 84a5514a97c564c23faa36714e33750899fdf28a Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Fri, 12 Nov 2021 12:19:45 +0100 Subject: [PATCH 30/30] fixed auto reply form --- core/admin/assets/app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/admin/assets/app.js b/core/admin/assets/app.js index 0926578d..03ea6215 100644 --- a/core/admin/assets/app.js +++ b/core/admin/assets/app.js @@ -28,10 +28,10 @@ $('document').ready(function() { var fieldset = $(this).parents('fieldset'); if (this.checked) { fieldset.removeAttr('disabled'); - fieldset.find('input').not(this).removeAttr('disabled'); + fieldset.find('input,textarea').not(this).removeAttr('disabled'); } else { fieldset.attr('disabled', ''); - fieldset.find('input').not(this).attr('disabled', ''); + fieldset.find('input,textarea').not(this).attr('disabled', ''); } });