From c7e28bf45132a22cf40659ed9ba92b6506bf1717 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89loi=20Rivard?= Date: Mon, 22 Apr 2024 16:53:29 +0200 Subject: [PATCH 01/14] chore: dependencies update --- poetry.lock | 20 ++++++++++---------- pyproject.toml | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/poetry.lock b/poetry.lock index 2a02616..ed8b723 100644 --- a/poetry.lock +++ b/poetry.lock @@ -217,13 +217,13 @@ files = [ [[package]] name = "canaille" -version = "0.0.51" -description = "Lightweight identity and autorization management software" +version = "0.0.52" +description = "Lightweight identity and authorization management software" optional = false -python-versions = "<4.0,>=3.8" +python-versions = "<4.0,>=3.9" files = [ - {file = "canaille-0.0.51-cp312-cp312-manylinux_2_39_x86_64.whl", hash = "sha256:abe9d39e55442e341322fd82bf9d94183530e40563afe2f33d3ac9c0f23e7bc2"}, - {file = "canaille-0.0.51.tar.gz", hash = "sha256:b5598c7ef9325940ebc3b6fbde55d0978d900ea296a34a98d9ce8ff46e08d3c6"}, + {file = "canaille-0.0.52-cp311-cp311-manylinux_2_39_x86_64.whl", hash = "sha256:dc57a70f98d9241d6e976a4a9d0485f1f1c710ffbfa83e5adcb140cc70c3851c"}, + {file = "canaille-0.0.52.tar.gz", hash = "sha256:d03fdc23c49819a2097549052f9ef45694de60f6384593893fc77ae56c3e4f42"}, ] [package.dependencies] @@ -2071,13 +2071,13 @@ python-dotenv = ">=0.9.1" [[package]] name = "pytest-iam" -version = "0.0.9" +version = "0.0.11" description = "A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite" optional = false -python-versions = "<4.0,>=3.8" +python-versions = "<4.0,>=3.9" files = [ - {file = "pytest_iam-0.0.9-py3-none-any.whl", hash = "sha256:ea20832cb51c3be8a8509ad1bf2524db11444186db0ecee94b8418e838fd28c3"}, - {file = "pytest_iam-0.0.9.tar.gz", hash = "sha256:d043f83ebe7aa0ce10ffabf3849e2f42d76fd47ad47ead9c0b4c91ccc108dd8a"}, + {file = "pytest_iam-0.0.11-py3-none-any.whl", hash = "sha256:9af55b04f8857aef8cc52ab89cf37898dbd91086c962ef26f2e104da23d40473"}, + {file = "pytest_iam-0.0.11.tar.gz", hash = "sha256:af3234e5bedd0c3d8ca0e196a35ec20ae1f8bd5af03550045591a33dbc104f02"}, ] [package.dependencies] @@ -2891,4 +2891,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.9,<4.0" -content-hash = "8b4de0bd382a742b2334b748475c9d07d4bd8f22c568c0a1bee1f8eccd0b080b" +content-hash = "57b510e49597171bf8828a7637c46164b3c0af2d3bde05897e0f032f64bb8f9e" diff --git a/pyproject.toml b/pyproject.toml index cc6a93a..7a4adfa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,7 +45,7 @@ pre-commit = "^3.1.1" pytest = "^8.0.0" pytest-cov = "^5.0.0" pytest-dotenv = "^0.5.2" -pytest-iam = "^0.0.9" +pytest-iam = "^0.0.11" pytest-mock = "^3.11.1" wsgidav = "^4.3.1" pytest-smtpd = "^0.1.0" From 6c5b155ed16185d542e718b797b6eaf0c375c353 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89loi=20Rivard?= Date: Mon, 22 Apr 2024 16:55:21 +0200 Subject: [PATCH 02/14] chore: export dependencies --- web/requirements.app.txt | 18 +++++++++--------- web/requirements.dev.txt | 36 +++++++++++++++++------------------- web/requirements.doc.txt | 35 ++++++++++++++++++----------------- 3 files changed, 44 insertions(+), 45 deletions(-) diff --git a/web/requirements.app.txt b/web/requirements.app.txt index f5f57ca..6729e84 100644 --- a/web/requirements.app.txt +++ b/web/requirements.app.txt @@ -6,7 +6,7 @@ babel==2.14.0 ; python_version >= "3.9" and python_version < "4.0" billiard==4.2.0 ; python_version >= "3.9" and python_version < "4.0" blinker==1.7.0 ; python_version >= "3.9" and python_version < "4.0" cachelib==0.9.0 ; python_version >= "3.9" and python_version < "4.0" -celery==5.3.6 ; python_version >= "3.9" and python_version < "4.0" +celery==5.4.0 ; python_version >= "3.9" and python_version < "4.0" certifi==2024.2.2 ; python_version >= "3.9" and python_version < "4.0" cffi==1.16.0 ; python_version >= "3.9" and python_version < "4.0" and platform_python_implementation != "PyPy" charset-normalizer==3.3.2 ; python_version >= "3.9" and python_version < "4.0" @@ -25,18 +25,18 @@ flask-pyoidc==3.14.3 ; python_version >= "3.9" and python_version < "4.0" flask-sqlalchemy==3.0.5 ; python_version >= "3.9" and python_version < "4.0" flask-uploads==0.2.1 ; python_version >= "3.9" and python_version < "4.0" flask-wtf==1.2.1 ; python_version >= "3.9" and python_version < "4.0" -flask==3.0.2 ; python_version >= "3.9" and python_version < "4.0" +flask==3.0.3 ; python_version >= "3.9" and python_version < "4.0" future==1.0.0 ; python_version >= "3.9" and python_version < "4.0" greenlet==3.0.3 ; python_version >= "3.9" and (platform_machine == "aarch64" or platform_machine == "ppc64le" or platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "win32" or platform_machine == "WIN32") and python_version < "4.0" gunicorn==21.2.0 ; python_version >= "3.9" and python_version < "4.0" -idna==3.6 ; python_version >= "3.9" and python_version < "4.0" +idna==3.7 ; python_version >= "3.9" and python_version < "4.0" importlib-metadata==7.1.0 ; python_version >= "3.9" and python_version < "3.10" importlib-resources==6.4.0 ; python_version >= "3.9" and python_version < "4.0" -itsdangerous==2.1.2 ; python_version >= "3.9" and python_version < "4.0" +itsdangerous==2.2.0 ; python_version >= "3.9" and python_version < "4.0" jinja2==3.1.3 ; python_version >= "3.9" and python_version < "4.0" -kombu==5.3.6 ; python_version >= "3.9" and python_version < "4.0" +kombu==5.3.7 ; python_version >= "3.9" and python_version < "4.0" lxml==5.2.1 ; python_version >= "3.9" and python_version < "4.0" -mako==1.3.2 ; python_version >= "3.9" and python_version < "4.0" +mako==1.3.3 ; python_version >= "3.9" and python_version < "4.0" markupsafe==2.1.5 ; python_version >= "3.9" and python_version < "4.0" netaddr==1.2.1 ; python_version >= "3.9" and python_version < "4.0" oic==1.6.1 ; python_version >= "3.9" and python_version < "4.0" @@ -45,9 +45,9 @@ prompt-toolkit==3.0.43 ; python_version >= "3.9" and python_version < "4.0" psycopg2==2.9.9 ; python_version >= "3.9" and python_version < "4.0" pycparser==2.22 ; python_version >= "3.9" and python_version < "4.0" and platform_python_implementation != "PyPy" pycryptodomex==3.20.0 ; python_version >= "3.9" and python_version < "4.0" -pydantic-core==2.16.3 ; python_version >= "3.9" and python_version < "4.0" +pydantic-core==2.18.1 ; python_version >= "3.9" and python_version < "4.0" pydantic-settings==2.2.1 ; python_version >= "3.9" and python_version < "4.0" -pydantic==2.6.4 ; python_version >= "3.9" and python_version < "4.0" +pydantic==2.7.0 ; python_version >= "3.9" and python_version < "4.0" pyjwkest==1.4.2 ; python_version >= "3.9" and python_version < "4.0" python-dateutil==2.9.0.post0 ; python_version >= "3.9" and python_version < "4.0" python-dotenv==1.0.1 ; python_version >= "3.9" and python_version < "4.0" @@ -60,7 +60,7 @@ sqlalchemy-json==0.7.0 ; python_version >= "3.9" and python_version < "4.0" sqlalchemy-utils==0.41.2 ; python_version >= "3.9" and python_version < "4.0" sqlalchemy==1.4.52 ; python_version >= "3.9" and python_version < "4.0" text-unidecode==1.3 ; python_version >= "3.9" and python_version < "4.0" -typing-extensions==4.10.0 ; python_version >= "3.9" and python_version < "4.0" +typing-extensions==4.11.0 ; python_version >= "3.9" and python_version < "4.0" tzdata==2024.1 ; python_version >= "3.9" and python_version < "4.0" urllib3==2.2.1 ; python_version >= "3.9" and python_version < "4.0" vine==5.1.0 ; python_version >= "3.9" and python_version < "4.0" diff --git a/web/requirements.dev.txt b/web/requirements.dev.txt index 67ee123..f341783 100644 --- a/web/requirements.dev.txt +++ b/web/requirements.dev.txt @@ -5,7 +5,7 @@ attrs==23.2.0 ; python_version >= "3.9" and python_version < "4" authlib==1.3.0 ; python_version >= "3.9" and python_version < "4.0" beautifulsoup4==4.12.3 ; python_version >= "3.9" and python_version < "4" blinker==1.7.0 ; python_version >= "3.9" and python_version < "4.0" -canaille[oidc]==0.0.45 ; python_version >= "3.9" and python_version < "4.0" +canaille[oidc]==0.0.52 ; python_version >= "3.9" and python_version < "4.0" cffi==1.16.0 ; python_version >= "3.9" and python_version < "4" and platform_python_implementation != "PyPy" cfgv==3.4.0 ; python_version >= "3.9" and python_version < "4.0" click==8.1.7 ; python_version >= "3.9" and python_version < "4.0" @@ -16,55 +16,53 @@ cryptography==42.0.5 ; python_version >= "3.9" and python_version < "4" cssselect==1.2.0 ; python_version >= "3.9" and python_version < "4.0" defusedxml==0.7.1 ; python_version >= "3.9" and python_version < "4.0" distlib==0.3.8 ; python_version >= "3.9" and python_version < "4.0" -enum-extend==0.1.1 ; python_version >= "3.9" and python_version < "4.0" -exceptiongroup==1.2.0 ; python_version >= "3.9" and python_version < "3.11" -faker==24.4.0 ; python_version >= "3.9" and python_version < "4.0" -filelock==3.13.3 ; python_version >= "3.9" and python_version < "4.0" +exceptiongroup==1.2.1 ; python_version >= "3.9" and python_version < "3.11" +faker==24.11.0 ; python_version >= "3.9" and python_version < "4.0" +filelock==3.13.4 ; python_version >= "3.9" and python_version < "4.0" flake8==7.0.0 ; python_version >= "3.9" and python_version < "4.0" flask-webtest==0.1.4 ; python_version >= "3.9" and python_version < "4.0" flask-wtf==1.2.1 ; python_version >= "3.9" and python_version < "4.0" -flask==3.0.2 ; python_version >= "3.9" and python_version < "4.0" +flask==3.0.3 ; python_version >= "3.9" and python_version < "4.0" freezegun==1.4.0 ; python_version >= "3.9" and python_version < "4.0" -identify==2.5.35 ; python_version >= "3.9" and python_version < "4.0" +identify==2.5.36 ; python_version >= "3.9" and python_version < "4.0" importlib-metadata==7.1.0 ; python_version >= "3.9" and python_version < "3.10" iniconfig==2.0.0 ; python_version >= "3.9" and python_version < "4.0" -itsdangerous==2.1.2 ; python_version >= "3.9" and python_version < "4.0" +itsdangerous==2.2.0 ; python_version >= "3.9" and python_version < "4.0" jinja2==3.1.3 ; python_version >= "3.9" and python_version < "4.0" -json5==0.9.24 ; python_version >= "3.9" and python_version < "4.0" +json5==0.9.25 ; python_version >= "3.9" and python_version < "4.0" lxml==5.2.1 ; python_version >= "3.9" and python_version < "4.0" markupsafe==2.1.5 ; python_version >= "3.9" and python_version < "4.0" mccabe==0.7.0 ; python_version >= "3.9" and python_version < "4.0" nodeenv==1.8.0 ; python_version >= "3.9" and python_version < "4.0" packaging==24.0 ; python_version >= "3.9" and python_version < "4.0" platformdirs==4.2.0 ; python_version >= "3.9" and python_version < "4.0" -pluggy==1.4.0 ; python_version >= "3.9" and python_version < "4.0" +pluggy==1.5.0 ; python_version >= "3.9" and python_version < "4.0" portpicker==1.6.0 ; python_version >= "3.9" and python_version < "4.0" -pre-commit==3.5.0 ; python_version >= "3.9" and python_version < "4.0" +pre-commit==3.7.0 ; python_version >= "3.9" and python_version < "4.0" psutil==5.9.8 ; python_version >= "3.9" and python_version < "4.0" pycodestyle==2.11.1 ; python_version >= "3.9" and python_version < "4.0" pycparser==2.22 ; python_version >= "3.9" and python_version < "4" and platform_python_implementation != "PyPy" -pydantic-core==2.16.3 ; python_version >= "3.9" and python_version < "4.0" +pydantic-core==2.18.1 ; python_version >= "3.9" and python_version < "4.0" pydantic-settings==2.2.1 ; python_version >= "3.9" and python_version < "4.0" -pydantic==2.6.4 ; python_version >= "3.9" and python_version < "4.0" +pydantic==2.7.0 ; python_version >= "3.9" and python_version < "4.0" pyflakes==3.2.0 ; python_version >= "3.9" and python_version < "4.0" pyquery==2.0.0 ; python_version >= "3.9" and python_version < "4.0" pytest-cov==5.0.0 ; python_version >= "3.9" and python_version < "4.0" pytest-dotenv==0.5.2 ; python_version >= "3.9" and python_version < "4.0" -pytest-iam==0.0.9 ; python_version >= "3.9" and python_version < "4.0" +pytest-iam==0.0.11 ; python_version >= "3.9" and python_version < "4.0" pytest-mock==3.14.0 ; python_version >= "3.9" and python_version < "4.0" pytest-smtpd==0.1.0 ; python_version >= "3.9" and python_version < "4" pytest==8.1.1 ; python_version >= "3.9" and python_version < "4.0" python-dateutil==2.9.0.post0 ; python_version >= "3.9" and python_version < "4.0" python-dotenv==1.0.1 ; python_version >= "3.9" and python_version < "4.0" pyyaml==6.0.1 ; python_version >= "3.9" and python_version < "4.0" -setuptools==69.2.0 ; python_version >= "3.9" and python_version < "4.0" +setuptools==69.5.1 ; python_version >= "3.9" and python_version < "4.0" six==1.16.0 ; python_version >= "3.9" and python_version < "4.0" -smtpdfix==0.5.1 ; python_version >= "3.9" and python_version < "4" +smtpdfix==0.5.2 ; python_version >= "3.9" and python_version < "4" soupsieve==2.5 ; python_version >= "3.9" and python_version < "4" -sphinx-enum-extend==0.1.3 ; python_version >= "3.9" and python_version < "4.0" tomli==2.0.1 ; python_version >= "3.9" and python_full_version <= "3.11.0a6" -typing-extensions==4.10.0 ; python_version >= "3.9" and python_version < "4.0" -virtualenv==20.25.1 ; python_version >= "3.9" and python_version < "4.0" +typing-extensions==4.11.0 ; python_version >= "3.9" and python_version < "4.0" +virtualenv==20.25.3 ; python_version >= "3.9" and python_version < "4.0" waitress==3.0.0 ; python_version >= "3.9" and python_version < "4" webob==1.8.7 ; python_version >= "3.9" and python_version < "4" webtest==3.0.0 ; python_version >= "3.9" and python_version < "4" diff --git a/web/requirements.doc.txt b/web/requirements.doc.txt index 968fc6d..b6b109f 100644 --- a/web/requirements.doc.txt +++ b/web/requirements.doc.txt @@ -1,4 +1,4 @@ -alabaster==0.7.13 ; python_version >= "3.9" and python_version < "4.0" +alabaster==0.7.16 ; python_version >= "3.9" and python_version < "4.0" alembic==1.13.1 ; python_version >= "3.9" and python_version < "4.0" amqp==5.2.0 ; python_version >= "3.9" and python_version < "4.0" annotated-types==0.6.0 ; python_version >= "3.9" and python_version < "4.0" @@ -8,7 +8,7 @@ babel==2.14.0 ; python_version >= "3.9" and python_version < "4.0" billiard==4.2.0 ; python_version >= "3.9" and python_version < "4.0" blinker==1.7.0 ; python_version >= "3.9" and python_version < "4.0" cachelib==0.9.0 ; python_version >= "3.9" and python_version < "4.0" -celery==5.3.6 ; python_version >= "3.9" and python_version < "4.0" +celery==5.4.0 ; python_version >= "3.9" and python_version < "4.0" certifi==2024.2.2 ; python_version >= "3.9" and python_version < "4.0" cffi==1.16.0 ; python_version >= "3.9" and python_version < "4.0" and platform_python_implementation != "PyPy" charset-normalizer==3.3.2 ; python_version >= "3.9" and python_version < "4.0" @@ -28,19 +28,19 @@ flask-pyoidc==3.14.3 ; python_version >= "3.9" and python_version < "4.0" flask-sqlalchemy==3.0.5 ; python_version >= "3.9" and python_version < "4.0" flask-uploads==0.2.1 ; python_version >= "3.9" and python_version < "4.0" flask-wtf==1.2.1 ; python_version >= "3.9" and python_version < "4.0" -flask==3.0.2 ; python_version >= "3.9" and python_version < "4.0" +flask==3.0.3 ; python_version >= "3.9" and python_version < "4.0" future==1.0.0 ; python_version >= "3.9" and python_version < "4.0" greenlet==3.0.3 ; python_version >= "3.9" and (platform_machine == "aarch64" or platform_machine == "ppc64le" or platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "win32" or platform_machine == "WIN32") and python_version < "4.0" gunicorn==21.2.0 ; python_version >= "3.9" and python_version < "4.0" -idna==3.6 ; python_version >= "3.9" and python_version < "4.0" +idna==3.7 ; python_version >= "3.9" and python_version < "4.0" imagesize==1.4.1 ; python_version >= "3.9" and python_version < "4.0" importlib-metadata==7.1.0 ; python_version >= "3.9" and python_version < "3.10" importlib-resources==6.4.0 ; python_version >= "3.9" and python_version < "4.0" -itsdangerous==2.1.2 ; python_version >= "3.9" and python_version < "4.0" +itsdangerous==2.2.0 ; python_version >= "3.9" and python_version < "4.0" jinja2==3.1.3 ; python_version >= "3.9" and python_version < "4.0" -kombu==5.3.6 ; python_version >= "3.9" and python_version < "4.0" +kombu==5.3.7 ; python_version >= "3.9" and python_version < "4.0" lxml==5.2.1 ; python_version >= "3.9" and python_version < "4.0" -mako==1.3.2 ; python_version >= "3.9" and python_version < "4.0" +mako==1.3.3 ; python_version >= "3.9" and python_version < "4.0" markdown-it-py==3.0.0 ; python_version >= "3.9" and python_version < "4.0" markupsafe==2.1.5 ; python_version >= "3.9" and python_version < "4.0" mdit-py-plugins==0.4.0 ; python_version >= "3.9" and python_version < "4.0" @@ -53,9 +53,9 @@ prompt-toolkit==3.0.43 ; python_version >= "3.9" and python_version < "4.0" psycopg2==2.9.9 ; python_version >= "3.9" and python_version < "4.0" pycparser==2.22 ; python_version >= "3.9" and python_version < "4.0" and platform_python_implementation != "PyPy" pycryptodomex==3.20.0 ; python_version >= "3.9" and python_version < "4.0" -pydantic-core==2.16.3 ; python_version >= "3.9" and python_version < "4.0" +pydantic-core==2.18.1 ; python_version >= "3.9" and python_version < "4.0" pydantic-settings==2.2.1 ; python_version >= "3.9" and python_version < "4.0" -pydantic==2.6.4 ; python_version >= "3.9" and python_version < "4.0" +pydantic==2.7.0 ; python_version >= "3.9" and python_version < "4.0" pygments==2.17.2 ; python_version >= "3.9" and python_version < "4.0" pyjwkest==1.4.2 ; python_version >= "3.9" and python_version < "4.0" python-dateutil==2.9.0.post0 ; python_version >= "3.9" and python_version < "4.0" @@ -67,21 +67,22 @@ redis==5.0.3 ; python_version >= "3.9" and python_version < "4.0" requests==2.31.0 ; python_version >= "3.9" and python_version < "4.0" six==1.16.0 ; python_version >= "3.9" and python_version < "4.0" snowballstemmer==2.2.0 ; python_version >= "3.9" and python_version < "4.0" -sphinx-issues==4.0.0 ; python_version >= "3.9" and python_version < "4.0" +sphinx-issues==4.1.0 ; python_version >= "3.9" and python_version < "4.0" sphinx-rtd-theme==2.0.0 ; python_version >= "3.9" and python_version < "4.0" -sphinx==7.1.2 ; python_version >= "3.9" and python_version < "4.0" -sphinxcontrib-applehelp==1.0.4 ; python_version >= "3.9" and python_version < "4.0" -sphinxcontrib-devhelp==1.0.2 ; python_version >= "3.9" and python_version < "4.0" -sphinxcontrib-htmlhelp==2.0.1 ; python_version >= "3.9" and python_version < "4.0" +sphinx==7.3.7 ; python_version >= "3.9" and python_version < "4.0" +sphinxcontrib-applehelp==1.0.8 ; python_version >= "3.9" and python_version < "4.0" +sphinxcontrib-devhelp==1.0.6 ; python_version >= "3.9" and python_version < "4.0" +sphinxcontrib-htmlhelp==2.0.5 ; python_version >= "3.9" and python_version < "4.0" sphinxcontrib-jquery==4.1 ; python_version >= "3.9" and python_version < "4.0" sphinxcontrib-jsmath==1.0.1 ; python_version >= "3.9" and python_version < "4.0" -sphinxcontrib-qthelp==1.0.3 ; python_version >= "3.9" and python_version < "4.0" -sphinxcontrib-serializinghtml==1.1.5 ; python_version >= "3.9" and python_version < "4.0" +sphinxcontrib-qthelp==1.0.7 ; python_version >= "3.9" and python_version < "4.0" +sphinxcontrib-serializinghtml==1.1.10 ; python_version >= "3.9" and python_version < "4.0" sqlalchemy-json==0.7.0 ; python_version >= "3.9" and python_version < "4.0" sqlalchemy-utils==0.41.2 ; python_version >= "3.9" and python_version < "4.0" sqlalchemy==1.4.52 ; python_version >= "3.9" and python_version < "4.0" text-unidecode==1.3 ; python_version >= "3.9" and python_version < "4.0" -typing-extensions==4.10.0 ; python_version >= "3.9" and python_version < "4.0" +tomli==2.0.1 ; python_version >= "3.9" and python_version < "3.11" +typing-extensions==4.11.0 ; python_version >= "3.9" and python_version < "4.0" tzdata==2024.1 ; python_version >= "3.9" and python_version < "4.0" urllib3==2.2.1 ; python_version >= "3.9" and python_version < "4.0" vine==5.1.0 ; python_version >= "3.9" and python_version < "4.0" From 576552f9583268e0bd975f24e8a68f5eb665a89a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89loi=20Rivard?= Date: Mon, 22 Apr 2024 17:03:04 +0200 Subject: [PATCH 03/14] tests: fix unit tests --- web/tests/conftest.py | 1 + 1 file changed, 1 insertion(+) diff --git a/web/tests/conftest.py b/web/tests/conftest.py index 26eed23..443f420 100644 --- a/web/tests/conftest.py +++ b/web/tests/conftest.py @@ -47,6 +47,7 @@ def iam_client(iam_server): scope=["openid", "profile", "email"], preconsent=True, ) + iam_client.save() iam_client.audience = [iam_client] iam_client.save() yield iam_client From 3cb31c0ddc78a3c7e05eb166cde487cbe5786c1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89loi=20Rivard?= Date: Mon, 22 Apr 2024 18:31:23 +0200 Subject: [PATCH 04/14] chore: update dependencies --- poetry.lock | 6 +++--- web/requirements.dev.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index ed8b723..7495092 100644 --- a/poetry.lock +++ b/poetry.lock @@ -217,13 +217,13 @@ files = [ [[package]] name = "canaille" -version = "0.0.52" +version = "0.0.53" description = "Lightweight identity and authorization management software" optional = false python-versions = "<4.0,>=3.9" files = [ - {file = "canaille-0.0.52-cp311-cp311-manylinux_2_39_x86_64.whl", hash = "sha256:dc57a70f98d9241d6e976a4a9d0485f1f1c710ffbfa83e5adcb140cc70c3851c"}, - {file = "canaille-0.0.52.tar.gz", hash = "sha256:d03fdc23c49819a2097549052f9ef45694de60f6384593893fc77ae56c3e4f42"}, + {file = "canaille-0.0.53-cp311-cp311-manylinux_2_39_x86_64.whl", hash = "sha256:e3fa454827174fb347bc1aedf1286bbe9b6beedabf3cf82d8fdba7fb7420a8be"}, + {file = "canaille-0.0.53.tar.gz", hash = "sha256:c9b1579d63e9777528dff0f9071c8fe755a5da171f1018b4c41742781a7d73cd"}, ] [package.dependencies] diff --git a/web/requirements.dev.txt b/web/requirements.dev.txt index f341783..08c6f70 100644 --- a/web/requirements.dev.txt +++ b/web/requirements.dev.txt @@ -5,7 +5,7 @@ attrs==23.2.0 ; python_version >= "3.9" and python_version < "4" authlib==1.3.0 ; python_version >= "3.9" and python_version < "4.0" beautifulsoup4==4.12.3 ; python_version >= "3.9" and python_version < "4" blinker==1.7.0 ; python_version >= "3.9" and python_version < "4.0" -canaille[oidc]==0.0.52 ; python_version >= "3.9" and python_version < "4.0" +canaille[oidc]==0.0.53 ; python_version >= "3.9" and python_version < "4.0" cffi==1.16.0 ; python_version >= "3.9" and python_version < "4" and platform_python_implementation != "PyPy" cfgv==3.4.0 ; python_version >= "3.9" and python_version < "4.0" click==8.1.7 ; python_version >= "3.9" and python_version < "4.0" From d749d5def40d2eb8ede80b719f058f9684e37fea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89loi=20Rivard?= Date: Mon, 22 Apr 2024 18:39:28 +0200 Subject: [PATCH 05/14] chore: update dependencies --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- web/requirements.dev.txt | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/poetry.lock b/poetry.lock index 7495092..0587fd0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2071,17 +2071,17 @@ python-dotenv = ">=0.9.1" [[package]] name = "pytest-iam" -version = "0.0.11" +version = "0.0.12" description = "A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite" optional = false python-versions = "<4.0,>=3.9" files = [ - {file = "pytest_iam-0.0.11-py3-none-any.whl", hash = "sha256:9af55b04f8857aef8cc52ab89cf37898dbd91086c962ef26f2e104da23d40473"}, - {file = "pytest_iam-0.0.11.tar.gz", hash = "sha256:af3234e5bedd0c3d8ca0e196a35ec20ae1f8bd5af03550045591a33dbc104f02"}, + {file = "pytest_iam-0.0.12-py3-none-any.whl", hash = "sha256:480a7ff195dae5f3b56cb81a7ca80d0dd8ea0274e79f684390d42fe9c4cc101e"}, + {file = "pytest_iam-0.0.12.tar.gz", hash = "sha256:15b6f343ff3c3649d9355fd8d0fd631553282176104939d4b595048703061b70"}, ] [package.dependencies] -canaille = {version = "<1", extras = ["oidc"]} +canaille = {version = ">=0.0.53,<1", extras = ["oidc"]} faker = ">=21.0.0" portpicker = ">=1.6.0" pytest = ">=7.0.0" @@ -2891,4 +2891,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.9,<4.0" -content-hash = "57b510e49597171bf8828a7637c46164b3c0af2d3bde05897e0f032f64bb8f9e" +content-hash = "40acc55fd255873d306e230e86272caad86500f522e41003352d597dbc52054a" diff --git a/pyproject.toml b/pyproject.toml index 7a4adfa..1190680 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,7 +45,7 @@ pre-commit = "^3.1.1" pytest = "^8.0.0" pytest-cov = "^5.0.0" pytest-dotenv = "^0.5.2" -pytest-iam = "^0.0.11" +pytest-iam = "^0.0.12" pytest-mock = "^3.11.1" wsgidav = "^4.3.1" pytest-smtpd = "^0.1.0" diff --git a/web/requirements.dev.txt b/web/requirements.dev.txt index 08c6f70..9fb11ee 100644 --- a/web/requirements.dev.txt +++ b/web/requirements.dev.txt @@ -49,7 +49,7 @@ pyflakes==3.2.0 ; python_version >= "3.9" and python_version < "4.0" pyquery==2.0.0 ; python_version >= "3.9" and python_version < "4.0" pytest-cov==5.0.0 ; python_version >= "3.9" and python_version < "4.0" pytest-dotenv==0.5.2 ; python_version >= "3.9" and python_version < "4.0" -pytest-iam==0.0.11 ; python_version >= "3.9" and python_version < "4.0" +pytest-iam==0.0.12 ; python_version >= "3.9" and python_version < "4.0" pytest-mock==3.14.0 ; python_version >= "3.9" and python_version < "4.0" pytest-smtpd==0.1.0 ; python_version >= "3.9" and python_version < "4" pytest==8.1.1 ; python_version >= "3.9" and python_version < "4.0" From aa9af4f2b1e350f7a578d758c97a7c83d1f844af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89loi=20Rivard?= Date: Thu, 11 Apr 2024 16:54:04 +0200 Subject: [PATCH 06/14] doc: apps connection draft --- .../keycloak-service-account-roles.png | Bin 0 -> 105264 bytes documentation/maintainers/settings.rst | 51 ++++++++++++++++++ fk.py | 11 ++++ 3 files changed, 62 insertions(+) create mode 100644 documentation/_static/keycloak-service-account-roles.png create mode 100644 fk.py diff --git a/documentation/_static/keycloak-service-account-roles.png b/documentation/_static/keycloak-service-account-roles.png new file mode 100644 index 0000000000000000000000000000000000000000..e4ca02196202a274fff93c9acc8cbff7ba98efb4 GIT binary patch literal 105264 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 literal 0 HcmV?d00001 diff --git a/documentation/maintainers/settings.rst b/documentation/maintainers/settings.rst index af569a7..9ac3a35 100644 --- a/documentation/maintainers/settings.rst +++ b/documentation/maintainers/settings.rst @@ -19,3 +19,54 @@ Pour utiliser ces pages statiques, on peut utiliser le paramètre `error_page `_. + +Il est donc nécessaire de configurer les paramètres de configuration suivants : + +- :attr:`~b3desk.settings.MainSettings.SECRET_KEY` (TODO) +- :attr:`~b3desk.settings.MainSettings.SECRET_KEY` (TODO) +- :attr:`~b3desk.settings.MainSettings.SECRET_KEY` (TODO) + +On peut ensuite tester que la configuration est correcte grâce à la commande suivante: + +.. code-block:: bash + + docker exec -it flask get-apps-id + +En remplaçant ```` par l’identifiant du conteneur `b3desk_web`, et ```` par l’email d’un utilisateur, cette commande tente une connexion à l’API keycloak d’apps, afin de récupérer l’identifiant dont l’email a été passé en paramètre. + +Si la connexion à l’API de keycloak échoue, cette commande indiquera à quelle étape, et quelles sont les pistes de résolution. + +Configuration de Keycloak +------------------------- + +Pour que la connexion de B3Desk à Apps fonctionne correctement, il est nécessaire que keycloak autorise les connexion par `identifiants client `_. + +Vérifier que la configuration de Keycloak est correcte +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Se rendre la console d’administration Keycloak, dans le `realm` ``apps``. + Par exemple https://auth.eole3.dev/auth/admin/master/console/#/apps +- Se rendre dans la section « Clients » et sélectionner « b3desk » +- Sélectionner l’onglet « Service account roles » +- À cet endroit on doit voir deux lignes avec les droits ``real-management view-users`` et ``realm-management query-users``. + +.. image:: ../_static/keycloak-service-account-roles.png + +Configuration de Keycloak est correcte +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Si les droits ``real-management view-users`` et ``realm-management query-users`` ne sont pas présents, il faut les ajouter : + +- Cliquer sur le bouton « Assign roles », une fenêtre modale doit s’ouvrir +- Cliquer sur le menu déroulant des filtres en haut à gauche, et sélectionner « Filter by clients » plutôt que « Filter by realm roles » +- Dans le champ de recherche, entrer « users » et valider +- Cocher « view-users » et « query-users » puis sur le bouton « Assign » diff --git a/fk.py b/fk.py new file mode 100644 index 0000000..2f7f2a1 --- /dev/null +++ b/fk.py @@ -0,0 +1,11 @@ +import subprocess + +from libfaketime import fake_time +from libfaketime import reexec_if_needed + +reexec_if_needed(remove_vars=False) + + +with fake_time("2020-01-01 01:00:00"): + process = subprocess.run("date", capture_output=True) + print(process.stdout.decode()) From 68294785058fb955eb096708e68d0fe324e004d0 Mon Sep 17 00:00:00 2001 From: Loan Robert Date: Tue, 23 Apr 2024 15:05:45 +0200 Subject: [PATCH 07/14] documentation: keycloak configuration to retrieve nextcloud id --- documentation/maintainers/settings.rst | 8 +++++--- web/b3desk/settings.py | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/documentation/maintainers/settings.rst b/documentation/maintainers/settings.rst index 9ac3a35..8dfb399 100644 --- a/documentation/maintainers/settings.rst +++ b/documentation/maintainers/settings.rst @@ -31,9 +31,11 @@ Afin que les utilisateurs de b3desk puissent accéder à leurs fichiers Nextclou Il est donc nécessaire de configurer les paramètres de configuration suivants : -- :attr:`~b3desk.settings.MainSettings.SECRET_KEY` (TODO) -- :attr:`~b3desk.settings.MainSettings.SECRET_KEY` (TODO) -- :attr:`~b3desk.settings.MainSettings.SECRET_KEY` (TODO) +- :attr:`~b3desk.settings.MainSettings.SECONDARY_IDENTITY_PROVIDER_ENABLED` +- :attr:`~b3desk.settings.MainSettings.SECONDARY_IDENTITY_PROVIDER_URI` +- :attr:`~b3desk.settings.MainSettings.SECONDARY_IDENTITY_PROVIDER_REALM` +- :attr:`~b3desk.settings.MainSettings.SECONDARY_IDENTITY_PROVIDER_CLIENT_ID` +- :attr:`~b3desk.settings.MainSettings.SECONDARY_IDENTITY_PROVIDER_CLIENT_SECRET` On peut ensuite tester que la configuration est correcte grâce à la commande suivante: diff --git a/web/b3desk/settings.py b/web/b3desk/settings.py index d61d600..10361d1 100644 --- a/web/b3desk/settings.py +++ b/web/b3desk/settings.py @@ -433,6 +433,28 @@ def get_allowed_mime_types_server_side( Plus d’infos sur https://flask-pyoidc.readthedocs.io/en/latest/api.html#module-flask_pyoidc.provider_configuration """ + SECONDARY_IDENTITY_PROVIDER_ENABLED: Optional[bool] = False + """Indique si un second serveur d'identité pour la connection a un + Nextcloud est activée. + + S'il y a bien besoin de ce second serveur d'identité pour connecter + un utilisateur sur un Nextcloud, l'identifiant Nextcloud de + l'utilisateur sera recherché à partir de son mail. + """ + + SECONDARY_IDENTITY_PROVIDER_URI: Optional[str] = None + """Url du serveur d'identité permettant de retrouver un id utilisateur à + partir de son email.""" + + SECONDARY_IDENTITY_PROVIDER_REALM: Optional[str] = None + """Groupe sous lequel est enregistré l'utilisateur.""" + + SECONDARY_IDENTITY_PROVIDER_CLIENT_ID: Optional[str] = None + """ID du client B3desk dans ce serveur d'identité.""" + + SECONDARY_IDENTITY_PROVIDER_CLIENT_SECRET: Optional[str] = None + """Secret du client B3desk dans ce serveur d'identité.""" + @field_validator("OIDC_ATTENDEE_ISSUER") def get_attendee_issuer(cls, attendee_issuer: str, info: ValidationInfo) -> str: return attendee_issuer or info.data.get("OIDC_ISSUER") From 5f7eb2e652e4cc974c8d4f44af28792069bc01a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89loi=20Rivard?= Date: Tue, 23 Apr 2024 15:51:35 +0200 Subject: [PATCH 08/14] chore: remove debug file --- fk.py | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 fk.py diff --git a/fk.py b/fk.py deleted file mode 100644 index 2f7f2a1..0000000 --- a/fk.py +++ /dev/null @@ -1,11 +0,0 @@ -import subprocess - -from libfaketime import fake_time -from libfaketime import reexec_if_needed - -reexec_if_needed(remove_vars=False) - - -with fake_time("2020-01-01 01:00:00"): - process = subprocess.run("date", capture_output=True) - print(process.stdout.decode()) From 1d93035ad719e543625d8f50d43e932c550d7e7d Mon Sep 17 00:00:00 2001 From: Loan Robert Date: Wed, 24 Apr 2024 19:04:54 +0200 Subject: [PATCH 09/14] documentation: add procedure to have functional cloud sharing files for local environment --- documentation/developers/imitateProduction.md | 118 ++++++++++++++++++ documentation/developers/index.rst | 1 + 2 files changed, 119 insertions(+) create mode 100644 documentation/developers/imitateProduction.md diff --git a/documentation/developers/imitateProduction.md b/documentation/developers/imitateProduction.md new file mode 100644 index 0000000..fe0b908 --- /dev/null +++ b/documentation/developers/imitateProduction.md @@ -0,0 +1,118 @@ +# Reproduire des conditions de production entre les services + +Le `docker-compose.override.yml` permet de reproduire des conditions proches de la production en lançant tous les services requis et en permettant la communication entre chacun. ({doc}`voir ici `). + +Il reste cependant difficile de partager des fichiers depuis un nextcloud local vers une instance BigBlueButton. + +En effet, les différents services communiquent localement entre eux grâce au réseau mis en place par Docker. l'application B3Desk est accessible localement sur localhost:5000 et grâce à la configuration du `etc/host` la machine locale peut accéder avec un navigateur au keycloak sur `keycloak:8080` et au nextcloud sur `nextcloud:80`. + +La problématique que l'on rencontre sur le partage de fichier depuis Nextcloud par exemple pour le partage d'un second fichier qui va nécessairement passer par le worker Celery, est que l'url partagée par B3Desk pointe sur `localhost:5000` qui est son domaine local. Or, lorsque le worker Celery communique cette url à une instance BigBlueButton, ce domaine ne va rien signifier pour lui, et le fichier ne sera pas téléchargé dans la visio. + +Voilà un contournement possible pour le partage de fichiers via Nextcloud : + +## Avoir un vrai domaine pour B3Desk + +### Exposer le local sur un domaine + +NGrok permet de rendre accessible un environnement local depuis un domaine temporaire. + +Il suffit de l'installer, de créer un compte sur le service, de configurer votre authtoken comme précisé dans la [documentation](https://dashboard.ngrok.com/get-started/setup/linux). + +Nous avons besoin de deux domaines, un pour B3Desk et un pour le Nextcloud. + +Trouvez le fichier de configuration avec : +``` +ngrok config check +``` +Cette commande doit vous rendre le chemin de la config que vous pouvez alors éditer pour qu'elle contienne : +``` +version: "xxxx" +authtoken: secret_token +tunnels: + B3Desk: + addr: 5000 + proto: http + B3nc: + addr: 80 + proto: http +``` +Vous pouvez alors lancer la commande suivante pour obtenir deux domaines +``` +ngrok start --all +``` +Vous devriez voir apparaitre : +``` +ngrok (Ctrl+C to quit) + +Session Status online +Account userxyz +[...] +Forwarding https://firsttemporarydomain.ngrok-free.app -> http://localhost:5000 +Forwarding https://secondtemporarydomain.ngrok-free.app -> http://localhost:80 +``` +Ainsi que le trafic sur ces url. + +### Configurer B3Desk pour ce domaine + +Pour que B3Desk soit fonctionnel sur l'url fournie par NGrok, il faut modifier la configuration du `web.env` : +``` +SERVER_NAME=firsttemporarydomain.ngrok-free.app +PREFERRED_URL_SCHEME=https +``` + +Attendez avant de relancer votre service, vous ne pouvez malheureusement pas encore vous authentifier depuis ce domaine. + +## S'authentifier depuis un vrai domaine + +### Avoir un OIDC fonctionnel + +Maintenant que votre site dispose d'un vrai domaine, il faut encore qu'il puisse communiquer avec le Keycloak qui tourne localement et que celui-ci renvoie bien sur ce nouveau domaine. + +Vous devez donc modifier à nouveau votre `web.env` avec : +``` +OIDC_REDIRECT_URI=firsttemporarydomain.ngrok-free.app/oidc_callback +``` + +Vous pouvez maintenant relancer votre service pour que cette configuration soit prise en compte : +``` +docker compose up --build web -d +``` +Si vous vous rendez maintenant sur `https://firsttemporarydomain.ngrok-free.app` vous devriez arriver sur l'accueil du site. + +### Configurer Keycloak + +Il reste encore à configurer le Keycloak. + +Rendez-vous sur `http://keycloak:8080` et connectez-vous en tant qu'admin. + +Dans la partie 'Clients', cliquez sur le 'Client ID' de B3Desk pour pouvoir le modifier. + +Ajoutez l'entrée `https://firsttemporarydomain.ngrok-free.app/*` dans la liste de '* Valid Redirect URIs' et sauvegardez. + +## Pouvoir acceder au Nextcloud depuis le domaine temporaire + +### Accéder au Nextcloud depuis la nouvelle url + +Pour pouvoir accéder au fichiers du Nextcloud depuis la page d'ajout de fichiers dans la visio, avec le bouton 'depuis le Nuage', il faut que la nouvelle url temporaire de Nextcloud `https://secondtemporarydomain.ngrok-free.app` soit dans la liste des `trusted_domains`. + +Vous devez modifier la variable d'environnement `NEXTCLOUD_TRUSTED_DOMAINS` dans le fichier `docker-compose.override.yml` et réinstaller Nextcloud en supprimant la base de données avec `sudo rm -rf nextcloud/html postgres/data` et en relançant les services : +``` +docker compose up --build nextcloud -d +``` + +### Récupérer un token valide + +Il faut modifier le `NC_HOST` du service `tokenmock` pour y indiquer `https://secondtemporarydomain.ngrok-free.app` et non plus `nextcloud` qui n'existe plus. + +Vous devez ensuite relancer ce service : +``` +docker compose up --build tokenmock -d +``` + +### Autoriser le domaine de B3Desk à utiliser WebAppPassword + +Dans les 'Paramètres d'administration' de Nextcloud (avec le compte admin), il faut ajouter le nouveau domaine de B3Desk `https://firsttemporarydomain.ngrok-free.app` dans les 'Allowed origins' de WebAppPassword. + +## Configuration terminée + +Vous êtes maintenant capable de vous authentifier et de partager des fichiers depuis le Nextcloud local sur B3Desk, tout en surveillant les logs ! diff --git a/documentation/developers/index.rst b/documentation/developers/index.rst index 30d019d..317f62f 100644 --- a/documentation/developers/index.rst +++ b/documentation/developers/index.rst @@ -12,3 +12,4 @@ Cette documentation est à destination des développeurs. dockerPersistence translation meetingFiles + imitateProduction From 32bd18329514ecf9b12e86016911175fc8336cf1 Mon Sep 17 00:00:00 2001 From: Loan Robert Date: Wed, 24 Apr 2024 19:36:56 +0200 Subject: [PATCH 10/14] Add info logs about file sharing workflow --- web/b3desk/endpoints/meeting_files.py | 7 +++++++ web/b3desk/models/bbb.py | 4 ++++ web/b3desk/models/users.py | 13 +++++++++++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/web/b3desk/endpoints/meeting_files.py b/web/b3desk/endpoints/meeting_files.py index 17aaa6d..8d87853 100644 --- a/web/b3desk/endpoints/meeting_files.py +++ b/web/b3desk/endpoints/meeting_files.py @@ -169,6 +169,9 @@ def insertDocuments(meeting: Meeting): filehash = hashlib.sha1( f"{secret_key}-1-{id}-{secret_key}".encode() ).hexdigest() + current_app.logger.info( + "Call insert document BigBlueButton API in running room for %s", filename + ) url = url_for( "meeting_files.ncdownload", isexternal=1, @@ -552,6 +555,9 @@ def insertDoc(token): ) xml = f" " + current_app.logger.info( + "Call insert document BigBlueButton API for %s", meeting_file.title + ) requests.post( f"{current_app.config['BIGBLUEBUTTON_ENDPOINT']}/insertDocument", data=xml, @@ -565,6 +571,7 @@ def insertDoc(token): @bp.route("/ncdownload///") @bp.route("/ncdownload////") def ncdownload(isexternal, mfid, mftoken, filename=None): + current_app.logger.info("Service requesting file url %s", filename) secret_key = current_app.config["SECRET_KEY"] # select good file from token # get file through NC credentials - HOW POSSIBLE ? diff --git a/web/b3desk/models/bbb.py b/web/b3desk/models/bbb.py index 00ef4fc..de69c48 100644 --- a/web/b3desk/models/bbb.py +++ b/web/b3desk/models/bbb.py @@ -319,6 +319,10 @@ def meeting_file_addition_xml(self, meeting_files): filehash = hashlib.sha1( f"{current_app.config['SECRET_KEY']}-0-{meeting_file.id}-{current_app.config['SECRET_KEY']}".encode() ).hexdigest() + current_app.logger.info( + "Add document on BigBLueButton room creation for file", + meeting_file.title, + ) url = url_for( "meeting_files.ncdownload", isexternal=0, diff --git a/web/b3desk/models/users.py b/web/b3desk/models/users.py index 6c9d11b..611c49b 100644 --- a/web/b3desk/models/users.py +++ b/web/b3desk/models/users.py @@ -52,7 +52,7 @@ def get_user_nc_credentials(username): or not current_app.config["FILE_SHARING"] or not username ): - current_app.logger.debug( + current_app.logger.info( "File sharing deactivated or unable to perform, no connection to Nextcloud instance" ) return {"nctoken": None, "nclocator": None, "nclogin": None} @@ -87,10 +87,15 @@ def update_user_nc_credentials(user, user_info): and user.nc_locator and user.nc_token and ( - (datetime.now() - user.nc_last_auto_enroll).days + (remaining_time := (datetime.now() - user.nc_last_auto_enroll)).days <= current_app.config["NC_LOGIN_TIMEDELTA_DAYS"] ) ): + current_app.logger.info( + "Nextcloud login for user %s not to be refreshed for %s", + user, + remaining_time, + ) return False preferred_username = ( @@ -104,8 +109,12 @@ def update_user_nc_credentials(user, user_info): or data["nclocator"] is None or data["nctoken"] is None ): + current_app.logger.info( + "No new Nextcloud enroll needed for user %s with those data %s", user, data + ) nc_last_auto_enroll = None else: + current_app.logger.info("New Nextcloud enroll for user %s", data["nclogin"]) nc_last_auto_enroll = datetime.now() user.nc_locator = data["nclocator"] From c53e0d373d394ad82f99bb1e7a87177a69019706 Mon Sep 17 00:00:00 2001 From: Loan Robert Date: Wed, 24 Apr 2024 19:43:00 +0200 Subject: [PATCH 11/14] Update 1.2.3 dev version --- pyproject.toml | 2 +- web/b3desk/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1190680..505f940 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] name = "b3desk" -version = "1.2.2dev" +version = "1.2.3dev" description = "Outil de visioconférence pour les agents de l'Education Nationale et de l'Etat en général." authors = ["Your Name "] readme = "README.md" diff --git a/web/b3desk/__init__.py b/web/b3desk/__init__.py index 2a030c6..63b4867 100644 --- a/web/b3desk/__init__.py +++ b/web/b3desk/__init__.py @@ -29,7 +29,7 @@ from .utils import enum_converter from .utils import model_converter -__version__ = "1.2.2dev" +__version__ = "1.2.3dev" LANGUAGES = ["en", "fr"] From 29e0f92a4d06792c09de3e667dc8f14f6d0483bb Mon Sep 17 00:00:00 2001 From: Loan Robert Date: Wed, 24 Apr 2024 20:07:03 +0200 Subject: [PATCH 12/14] Update to 1.2.4 dev version --- pyproject.toml | 2 +- web/b3desk/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 505f940..5ef7f67 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] name = "b3desk" -version = "1.2.3dev" +version = "1.2.4dev" description = "Outil de visioconférence pour les agents de l'Education Nationale et de l'Etat en général." authors = ["Your Name "] readme = "README.md" diff --git a/web/b3desk/__init__.py b/web/b3desk/__init__.py index 63b4867..2059be4 100644 --- a/web/b3desk/__init__.py +++ b/web/b3desk/__init__.py @@ -29,7 +29,7 @@ from .utils import enum_converter from .utils import model_converter -__version__ = "1.2.3dev" +__version__ = "1.2.4dev" LANGUAGES = ["en", "fr"] From ce7502cd0ef935b262c178f24bc16a33d77a5571 Mon Sep 17 00:00:00 2001 From: Loan Robert Date: Thu, 25 Apr 2024 12:31:47 +0200 Subject: [PATCH 13/14] Fix logging error --- web/b3desk/models/bbb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/b3desk/models/bbb.py b/web/b3desk/models/bbb.py index de69c48..4b7c95f 100644 --- a/web/b3desk/models/bbb.py +++ b/web/b3desk/models/bbb.py @@ -320,7 +320,7 @@ def meeting_file_addition_xml(self, meeting_files): f"{current_app.config['SECRET_KEY']}-0-{meeting_file.id}-{current_app.config['SECRET_KEY']}".encode() ).hexdigest() current_app.logger.info( - "Add document on BigBLueButton room creation for file", + "Add document on BigBLueButton room creation for file %s", meeting_file.title, ) url = url_for( From fa1646f8484e6d25f3f5778d9bf8832be272eb63 Mon Sep 17 00:00:00 2001 From: Loan Robert Date: Thu, 25 Apr 2024 12:33:04 +0200 Subject: [PATCH 14/14] Change gunicorn logging level to info for production --- web/misc/run_webserver.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/misc/run_webserver.sh b/web/misc/run_webserver.sh index 4f2658b..b506e8e 100644 --- a/web/misc/run_webserver.sh +++ b/web/misc/run_webserver.sh @@ -3,4 +3,4 @@ # DB Migration flask db upgrade &>> /var/log/flask-migrate.log -gunicorn --chdir /opt/bbb-visio --bind 0.0.0.0:5000 --log-level warning --access-logfile /var/log/gunicorn-access.log --error-logfile /var/log/gunicorn-error.log wsgi:app +gunicorn --chdir /opt/bbb-visio --bind 0.0.0.0:5000 --log-level info --access-logfile /var/log/gunicorn-access.log --error-logfile /var/log/gunicorn-error.log wsgi:app