From 8381ff58ea3449dba388427f7781c63cda5d94d8 Mon Sep 17 00:00:00 2001 From: Pierre Narcisi Date: Thu, 2 Nov 2023 10:09:50 +0100 Subject: [PATCH 01/18] fix warnings --- src/pypnusershub/db/models.py | 2 +- src/pypnusershub/routes.py | 13 ++----------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/pypnusershub/db/models.py b/src/pypnusershub/db/models.py index 080d723..0123e60 100644 --- a/src/pypnusershub/db/models.py +++ b/src/pypnusershub/db/models.py @@ -214,7 +214,7 @@ class Organisme(db.Model): __table_args__ = {"schema": "utilisateurs"} id_organisme = db.Column(db.Integer, primary_key=True) - uuid_organisme = db.Column(UUID(as_uuid=True), default=select([func.uuid_generate_v4()])) + uuid_organisme = db.Column(UUID(as_uuid=True), default=select(func.uuid_generate_v4())) nom_organisme = db.Column(db.Unicode) adresse_organisme = db.Column(db.Unicode) cp_organisme = db.Column(db.Unicode) diff --git a/src/pypnusershub/routes.py b/src/pypnusershub/routes.py index 90c0bfd..57b3c81 100755 --- a/src/pypnusershub/routes.py +++ b/src/pypnusershub/routes.py @@ -12,18 +12,9 @@ import datetime -from flask import ( - Blueprint, - escape, - request, - Response, - current_app, - redirect, - g, - make_response, - jsonify, -) from flask_login import login_user, logout_user, current_user +from flask import Blueprint, request, Response, current_app, redirect, g, make_response, jsonify +from markupsafe import escape from sqlalchemy.orm import exc import sqlalchemy as sa From 8fcd4c4c174a51484961857e5460268021009bc3 Mon Sep 17 00:00:00 2001 From: Pierre Narcisi Date: Mon, 6 Nov 2023 17:06:03 +0100 Subject: [PATCH 02/18] fix add cascade_backref=false --- src/pypnusershub/db/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pypnusershub/db/models.py b/src/pypnusershub/db/models.py index 0123e60..ba8a230 100644 --- a/src/pypnusershub/db/models.py +++ b/src/pypnusershub/db/models.py @@ -137,7 +137,7 @@ class User(db.Model, UserMixin): secondary=cor_roles, primaryjoin="User.id_role == utilisateurs.cor_roles.c.id_role_utilisateur", secondaryjoin="User.id_role == utilisateurs.cor_roles.c.id_role_groupe", - backref=backref("members"), + backref=backref("members", cascade_backrefs=False), ) @property From 9a7e2eb6838f73b591e4f635bad593318f416ecd Mon Sep 17 00:00:00 2001 From: Pierre Narcisi Date: Thu, 2 Nov 2023 10:09:50 +0100 Subject: [PATCH 03/18] fix warnings --- src/pypnusershub/db/models.py | 2 +- src/pypnusershub/routes.py | 13 ++----------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/pypnusershub/db/models.py b/src/pypnusershub/db/models.py index 96f0959..3fd8ebf 100644 --- a/src/pypnusershub/db/models.py +++ b/src/pypnusershub/db/models.py @@ -213,7 +213,7 @@ class Organisme(db.Model): __table_args__ = {"schema": "utilisateurs"} id_organisme = db.Column(db.Integer, primary_key=True) - uuid_organisme = db.Column(UUID(as_uuid=True), default=select([func.uuid_generate_v4()])) + uuid_organisme = db.Column(UUID(as_uuid=True), default=select(func.uuid_generate_v4())) nom_organisme = db.Column(db.Unicode) adresse_organisme = db.Column(db.Unicode) cp_organisme = db.Column(db.Unicode) diff --git a/src/pypnusershub/routes.py b/src/pypnusershub/routes.py index 90c0bfd..57b3c81 100755 --- a/src/pypnusershub/routes.py +++ b/src/pypnusershub/routes.py @@ -12,18 +12,9 @@ import datetime -from flask import ( - Blueprint, - escape, - request, - Response, - current_app, - redirect, - g, - make_response, - jsonify, -) from flask_login import login_user, logout_user, current_user +from flask import Blueprint, request, Response, current_app, redirect, g, make_response, jsonify +from markupsafe import escape from sqlalchemy.orm import exc import sqlalchemy as sa From c51742bdd5f8c792a5ea1e9887b95c023059a713 Mon Sep 17 00:00:00 2001 From: Pierre Narcisi Date: Mon, 6 Nov 2023 17:06:03 +0100 Subject: [PATCH 04/18] fix add cascade_backref=false --- src/pypnusershub/db/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pypnusershub/db/models.py b/src/pypnusershub/db/models.py index 3fd8ebf..4e091d4 100644 --- a/src/pypnusershub/db/models.py +++ b/src/pypnusershub/db/models.py @@ -136,7 +136,7 @@ class User(db.Model, UserMixin): secondary=cor_roles, primaryjoin="User.id_role == utilisateurs.cor_roles.c.id_role_utilisateur", secondaryjoin="User.id_role == utilisateurs.cor_roles.c.id_role_groupe", - backref=backref("members"), + backref=backref("members", cascade_backrefs=False), ) @property From 515d855921db9d8debfeaf20eb73ec5751ce8a69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lie=20Bouttier?= Date: Fri, 10 Nov 2023 19:45:10 +0100 Subject: [PATCH 05/18] require sqlalchemy>=1.4,<2 --- requirements-common.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements-common.in b/requirements-common.in index 1a55a80..fcacd50 100644 --- a/requirements-common.in +++ b/requirements-common.in @@ -6,9 +6,9 @@ flask < 3 flask-login psycopg2 requests -sqlalchemy>=1.3,<2 +sqlalchemy>=1.4,<2 flask-marshmallow marshmallow-sqlalchemy alembic # for flask login -werkzeug<3 \ No newline at end of file +werkzeug<3 From e5a1e5f81163bec3f30904fbd47a32608c113fa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lie=20Bouttier?= Date: Fri, 10 Nov 2023 19:45:20 +0100 Subject: [PATCH 06/18] ci: remove Debian 10, add Debian 12 --- .github/workflows/pytest.yml | 31 +++++++------------------------ 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index c40ee4c..816a9bb 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -18,18 +18,15 @@ jobs: strategy: fail-fast: false matrix: - debian-version: [ '10', '11' ] - sqlalchemy-version: [ '1.3', '1.4' ] + debian-version: [ '11', '12' ] + sqlalchemy-version: [ '1.4' ] include: - - debian-version: '10' - python-version: '3.7' - postgres-version: '11-stretch' - debian-version: '11' python-version: '3.9' postgres-version: '13-bullseye' - exclude: - - debian-version: '10' - sqlalchemy-version: '1.3' + - debian-version: '12' + python-version: '3.11' + postgres-version: '15-bookworm' name: Debian ${{ matrix.debian-version }} - SQLAlchemy ${{ matrix.sqlalchemy-version }} @@ -60,26 +57,12 @@ jobs: with: python-version: ${{ matrix.python-version }} - name: Install dependencies - if: ${{ matrix.sqlalchemy-version == '1.3' }} run: | python -m pip install --upgrade pip python -m pip install \ pytest-cov \ -e .[tests] \ - -e file:dependencies/Utils-Flask-SQLAlchemy#egg=utils-flask-sqlalchemy \ - "sqlalchemy<1.4" \ - "flask-sqlalchemy<3"\ - "flask-marshmallow<0.15" - - name: Install dependencies - if: ${{ matrix.sqlalchemy-version == '1.4' }} - run: | - python -m pip install --upgrade pip - python -m pip install \ - pytest-cov \ - -e .[tests] \ - -e file:dependencies/Utils-Flask-SQLAlchemy#egg=utils-flask-sqlalchemy \ - "sqlalchemy<2,>=1.4" \ - "flask-sqlalchemy>=3" + -e file:dependencies/Utils-Flask-SQLAlchemy#egg=utils-flask-sqlalchemy - name: Install database run: | alembic upgrade utilisateurs@head @@ -91,7 +74,7 @@ jobs: env: USERSHUB_AUTH_MODULE_SETTINGS: test_settings.py - name: Upload coverage to Codecov - if: ${{ matrix.debian-version == '11' }} + if: ${{ matrix.debian-version == '12' }} uses: codecov/codecov-action@v3 with: flags: pytest From 5ec1e2ee453ba86e384b3f58f3edc194152e6bc1 Mon Sep 17 00:00:00 2001 From: Pierre Narcisi Date: Thu, 16 Nov 2023 11:15:06 +0100 Subject: [PATCH 07/18] Bump flask --- requirements-common.in | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/requirements-common.in b/requirements-common.in index fcacd50..425d1a4 100644 --- a/requirements-common.in +++ b/requirements-common.in @@ -1,8 +1,7 @@ authlib bcrypt flask-sqlalchemy -# pytest flask is incompatible with flask 3 -flask < 3 +flask < 4 flask-login psycopg2 requests @@ -11,4 +10,3 @@ flask-marshmallow marshmallow-sqlalchemy alembic # for flask login -werkzeug<3 From 03e99d57c908372988d71d0bb94bc82c2b08fea5 Mon Sep 17 00:00:00 2001 From: Jacobe2169 Date: Thu, 23 Nov 2023 09:49:45 +0100 Subject: [PATCH 08/18] fix required for https://github.com/PnX-SI/UsersHub/pull/191 --- src/pypnusershub/routes_register.py | 168 ++++++++++++++++------------ 1 file changed, 95 insertions(+), 73 deletions(-) diff --git a/src/pypnusershub/routes_register.py b/src/pypnusershub/routes_register.py index 8381ea6..5cec629 100644 --- a/src/pypnusershub/routes_register.py +++ b/src/pypnusershub/routes_register.py @@ -39,15 +39,15 @@ s = requests.Session() -bp = Blueprint('register', __name__) +bp = Blueprint("register", __name__) def get_json_request(r): - ''' - r : retour de la requete requests + """ + r : retour de la requete requests - fonction pour recuperer la reponse json sans lever d'erreur - ''' + fonction pour recuperer la reponse json sans lever d'erreur + """ try: r_json = r.json() except Exception: @@ -57,45 +57,45 @@ def get_json_request(r): def req_json_or_text(r, msg_pypn=""): - ''' - r : retour de la requete requests - msg_pypn : message supplementaire rajouté a la reponse + """ + r : retour de la requete requests + msg_pypn : message supplementaire rajouté a la reponse - revoie un tuple avec la réponse de la requete en json r.json si possible - {'msg': r.text} sinon - et status_code + revoie un tuple avec la réponse de la requete en json r.json si possible + {'msg': r.text} sinon + et status_code - ''' + """ r_json = get_json_request(r) if not r_json and r.text: - r_json = {"msg": r.text} if not r_json and not r.text: - r_json = {"msg": "empty message"} if msg_pypn: - - r_json['msg_pypn'] = msg_pypn + r_json["msg_pypn"] = msg_pypn return json.dumps(r_json), r.status_code def connect_admin(): - ''' - decorateur pour la connexion de l'admin a une appli - ici url config['URL_USERSHUB'] sans / à la fin - ''' + """ + decorateur pour la connexion de l'admin a une appli + ici url config['URL_USERSHUB'] sans / à la fin + """ + def _connect_admin(f): @wraps(f) def __connect_admin(*args, **kwargs): # connexion à usershub - id_app_usershub = db.session.query( - Application.id_application - ).filter(Application.code_application == 'UH').first() + id_app_usershub = ( + db.session.query(Application.id_application) + .filter(Application.code_application == "UH") + .first() + ) if not id_app_usershub: return json.dumps({"msg": "Pas d'id app USERSHUB"}), 500 @@ -104,22 +104,31 @@ def __connect_admin(*args, **kwargs): # test si on est déjà connecté try: - r = s.post(current_app.config['URL_USERSHUB'] + - "/api_register/test_connexion") - b_connexion = (r.status_code == 200) + r = s.post( + current_app.config["URL_USERSHUB"] + "/api_register/test_connexion", + json={}, + ) + b_connexion = r.status_code == 200 except requests.ConnectionError: - return json.dumps({"msg": "Erreur de connexion a l'application USERSHUB (causes possibles : url erronee, application USERSHUB ne fonctionne pas, ..;)"}), 500 + return ( + json.dumps( + { + "msg": "Erreur de connexion a l'application USERSHUB (causes possibles : url erronee, application USERSHUB ne fonctionne pas, ..;)" + } + ), + 500, + ) # si on est pas connecté on se connecte if not b_connexion: # connexion à usershub r = s.post( - current_app.config['URL_USERSHUB'] + "/" + "pypn/auth/login", + current_app.config["URL_USERSHUB"] + "/" + "pypn/auth/login", json={ - 'login': current_app.config['ADMIN_APPLICATION_LOGIN'], - 'password': current_app.config['ADMIN_APPLICATION_PASSWORD'], - 'id_application': id_app_usershub - } + "login": current_app.config["ADMIN_APPLICATION_LOGIN"], + "password": current_app.config["ADMIN_APPLICATION_PASSWORD"], + "id_application": id_app_usershub, + }, ) # si echec de connexion @@ -133,84 +142,97 @@ def __connect_admin(*args, **kwargs): return _connect_admin -@bp.route('test_uh', methods=['GET']) +@bp.route("test_uh", methods=["GET"]) @connect_admin() def test(): - ''' - route pour tester le décorateur connect_admin - ainsi que les paramètres de connexion à USERSHUB: - - config['ADMIN_APPLICATION_LOGIN'] - - config['ADMIN_APPLICATION_PASSWORD'] - ''' + """ + route pour tester le décorateur connect_admin + ainsi que les paramètres de connexion à USERSHUB: + - config['ADMIN_APPLICATION_LOGIN'] + - config['ADMIN_APPLICATION_PASSWORD'] + """ - r = s.post(current_app.config['URL_USERSHUB'] + "/api_register/test_connexion") + r = s.post(current_app.config["URL_USERSHUB"] + "/api_register/test_connexion") return req_json_or_text(r, "Test pypn") -@bp.route("post_usershub/", methods=['POST']) +@bp.route("post_usershub/", methods=["POST"]) @connect_admin() def post_usershub(type_action): - ''' - route generique pour appeler les routes UsersHub en tant qu'administrateur de l'appli en cours - ex : post_usershub/test_connexion appelle la route URL_USERSHUB/api_register/test_connexion - ''' + """ + route generique pour appeler les routes UsersHub en tant qu'administrateur de l'appli en cours + ex : post_usershub/test_connexion appelle la route URL_USERSHUB/api_register/test_connexion + """ # attribution des droits pour les actions dict_type_action_droit = { - 'test_connexion': 0, - 'valid_temp_user': 0, - 'create_temp_user': 0, - 'change_password': 0, - 'create_cor_role_token': 0, - 'add_application_right_to_role': 0, - 'login_recovery': 0, - 'password_recovery': 0, - 'update_user': 1, - 'change_application_right': 4, + "test_connexion": 0, + "valid_temp_user": 0, + "create_temp_user": 0, + "change_password": 0, + "create_cor_role_token": 0, + "add_application_right_to_role": 0, + "login_recovery": 0, + "password_recovery": 0, + "update_user": 1, + "change_application_right": 4, } params = request.args id_droit = 0 - if session.get('current_user', None): - - id_role = session['current_user']['id_role'] + if session.get("current_user", None): + id_role = session["current_user"]["id_role"] - q = (db.session.query(AppUser.id_droit_max) - .filter(AppUser.id_role == id_role) - .filter(AppUser.id_application == get_current_app_id())) + q = ( + db.session.query(AppUser.id_droit_max) + .filter(AppUser.id_role == id_role) + .filter(AppUser.id_application == get_current_app_id()) + ) id_droit = q.one()[0] # si pas de droit definis pour cet action, alors les droits requis sont à 7 => action impossible if id_droit < dict_type_action_droit.get(type_action, 7): - - return json.dumps({"msg": "Droits insuffisant pour la requête UsersHub : " + type_action}), 403 + return ( + json.dumps( + {"msg": "Droits insuffisant pour la requête UsersHub : " + type_action} + ), + 403, + ) # les test de paramètres seront faits dans UsersHub data = request.get_json() - url = current_app.config['URL_USERSHUB'] + "/" + "api_register/" + type_action + url = current_app.config["URL_USERSHUB"] + "/" + "api_register/" + type_action r_usershub = s.post(url, json=data) # after request definir route dans app # par ex. pour l'envoi de mails # lancer uniquement si enable_post_action n'est pas = False dans le body de la requête - if r_usershub.status_code == 200 and data.get('enable_post_action', True): + if r_usershub.status_code == 200 and data.get("enable_post_action", True): out_after = after_request(type_action, get_json_request(r_usershub)) # 0 = pas d'action definie dans current_app.config['after_USERSHUB_request'][type_action] if out_after != 0: - - if out_after['msg'] != "ok": - - return json.dumps({'msg': 'Problème after request pour post_usershub ' + type_action + ':' + out_after['msg']}), 500 + if out_after["msg"] != "ok": + return ( + json.dumps( + { + "msg": "Problème after request pour post_usershub " + + type_action + + ":" + + out_after["msg"] + } + ), + 500, + ) return req_json_or_text(r_usershub) def after_request(type_action, data, *args, **kwargs): - ''' - lorsqu'une fonction est definie dans REGISTER_POST_ACTION_FCT[type_action] - elle est executée avec les données fournies en retour de la requete USERSHUB - ''' + """ + lorsqu'une fonction est definie dans REGISTER_POST_ACTION_FCT[type_action] + elle est executée avec les données fournies en retour de la requete USERSHUB + """ if not REGISTER_POST_ACTION_FCT: return 0 f = REGISTER_POST_ACTION_FCT.get(type_action, None) From 5805681265eff4f1949404d1010fe62692fde14f Mon Sep 17 00:00:00 2001 From: Jacobe2169 Date: Mon, 11 Dec 2023 11:42:55 +0100 Subject: [PATCH 09/18] drop .query --- src/pypnusershub/db/models.py | 67 +++++++++++++++++---- src/pypnusershub/db/models_register.py | 61 ++++++++++--------- src/pypnusershub/db/tools.py | 18 +++--- src/pypnusershub/login_manager.py | 6 +- src/pypnusershub/routes.py | 45 ++++++++++---- src/pypnusershub/routes_register.py | 14 ++--- src/pypnusershub/tests/test_utilisateurs.py | 10 +-- src/pypnusershub/tests/utils.py | 18 ++++-- src/pypnusershub/utils.py | 11 +++- 9 files changed, 168 insertions(+), 82 deletions(-) diff --git a/src/pypnusershub/db/models.py b/src/pypnusershub/db/models.py index 4e091d4..5f945ae 100644 --- a/src/pypnusershub/db/models.py +++ b/src/pypnusershub/db/models.py @@ -2,6 +2,8 @@ from __future__ import unicode_literals, print_function, absolute_import, division +from utils_flask_sqla.models import qfilter + """ mappings applications et utilisateurs """ @@ -125,7 +127,9 @@ class User(db.Model, UserMixin): _password = db.Column("pass", db.Unicode) _password_plus = db.Column("pass_plus", db.Unicode) email = db.Column(db.Unicode) - id_organisme = db.Column(db.Integer, ForeignKey("utilisateurs.bib_organismes.id_organisme")) + id_organisme = db.Column( + db.Integer, ForeignKey("utilisateurs.bib_organismes.id_organisme") + ) remarques = db.Column(db.Unicode) champs_addi = db.Column(JSONB) date_insert = db.Column(db.DateTime) @@ -149,7 +153,9 @@ def max_level_profil(self): UserApplicationRight, or_( UserApplicationRight.id_role == self.id_role, - UserApplicationRight.id_role.in_([role.id_role for role in self.groups]), + UserApplicationRight.id_role.in_( + [role.id_role for role in self.groups] + ), ), ) .join(Profils, UserApplicationRight.id_profil == Profils.id_profil) @@ -206,6 +212,27 @@ def __repr__(self): def __str__(self): return self.identifiant or self.nom_complet + @qfilter + def filter_by_app(cls, code_app=None, **kwargs): + if code_app is None: + code_app = current_app.config["CODE_APPLICATION"] + query = kwargs["query"] + return ( + query.outerjoin(cor_roles, User.id_role == cor_roles.c.id_role_utilisateur) + .outerjoin( + UserApplicationRight, + or_( + UserApplicationRight.id_role == cor_roles.c.id_role_groupe, + UserApplicationRight.id_role == User.id_role, + ), + ) + .join( + Application, + Application.id_application == UserApplicationRight.id_application, + ) + .filter(Application.code_application == code_app) + ).whereclause + @serializable class Organisme(db.Model): @@ -213,7 +240,9 @@ class Organisme(db.Model): __table_args__ = {"schema": "utilisateurs"} id_organisme = db.Column(db.Integer, primary_key=True) - uuid_organisme = db.Column(UUID(as_uuid=True), default=select(func.uuid_generate_v4())) + uuid_organisme = db.Column( + UUID(as_uuid=True), default=select(func.uuid_generate_v4()) + ) nom_organisme = db.Column(db.Unicode) adresse_organisme = db.Column(db.Unicode) cp_organisme = db.Column(db.Unicode) @@ -223,7 +252,9 @@ class Organisme(db.Model): email_organisme = db.Column(db.Unicode) url_organisme = db.Column(db.Unicode) url_logo = db.Column(db.Unicode) - id_parent = db.Column(db.Integer, db.ForeignKey("utilisateurs.bib_organismes.id_organisme")) + id_parent = db.Column( + db.Integer, db.ForeignKey("utilisateurs.bib_organismes.id_organisme") + ) additional_data = db.Column(JSONB, nullable=True, server_default="{}") members = db.relationship(User, backref="organisme") @@ -261,7 +292,9 @@ class Profils(db.Model): nom_profil = db.Column(db.Unicode) desc_profil = db.Column(db.Unicode) - applications = relationship("Application", secondary=profils_for_app, back_populates="profils") + applications = relationship( + "Application", secondary=profils_for_app, back_populates="profils" + ) @serializable @@ -278,7 +311,9 @@ class Application(db.Model): desc_application = db.Column(db.Unicode) id_parent = db.Column(db.Integer) - profils = relationship(Profils, secondary=profils_for_app, back_populates="applications") + profils = relationship( + Profils, secondary=profils_for_app, back_populates="applications" + ) def __repr__(self): return "".format(self.nom_application) @@ -288,7 +323,9 @@ def __str__(self): @staticmethod def get_application(nom_application): - return Application.query.filter(Application.nom_application == nom_application).one() + return db.session.execute( + select(Application).where(Application.nom_application == nom_application) + ).scalar_one() class ApplicationRight(db.Model): @@ -316,12 +353,16 @@ class UserApplicationRight(db.Model): __tablename__ = "cor_role_app_profil" __table_args__ = {"schema": "utilisateurs"} # , 'extend_existing': True} - id_role = db.Column(db.Integer, ForeignKey("utilisateurs.t_roles.id_role"), primary_key=True) + id_role = db.Column( + db.Integer, ForeignKey("utilisateurs.t_roles.id_role"), primary_key=True + ) id_profil = db.Column( db.Integer, ForeignKey("utilisateurs.t_profils.id_profil"), primary_key=True ) id_application = db.Column( - db.Integer, ForeignKey("utilisateurs.t_applications.id_application"), primary_key=True + db.Integer, + ForeignKey("utilisateurs.t_applications.id_application"), + primary_key=True, ) role = relationship("User") @@ -350,7 +391,9 @@ class AppUser(db.Model): nom_role = db.Column(db.Unicode) prenom_role = db.Column(db.Unicode) id_application = db.Column( - db.Integer, db.ForeignKey("utilisateurs.t_applications.id_application"), primary_key=True + db.Integer, + db.ForeignKey("utilisateurs.t_applications.id_application"), + primary_key=True, ) id_organisme = db.Column(db.Integer) application = relationship("Application", backref="app_users") @@ -387,7 +430,9 @@ class AppRole(db.Model): nom_role = db.Column(db.Unicode) prenom_role = db.Column(db.Unicode) id_application = db.Column( - db.Integer, db.ForeignKey("utilisateurs.t_applications.id_application"), primary_key=True + db.Integer, + db.ForeignKey("utilisateurs.t_applications.id_application"), + primary_key=True, ) id_organisme = db.Column(db.Integer) identifiant = db.Column(db.Unicode) diff --git a/src/pypnusershub/db/models_register.py b/src/pypnusershub/db/models_register.py index 6ada9f9..391f13e 100644 --- a/src/pypnusershub/db/models_register.py +++ b/src/pypnusershub/db/models_register.py @@ -3,7 +3,7 @@ from flask import current_app from pypnusershub.db.models import check_and_encrypt_password -from sqlalchemy import or_ +from sqlalchemy import or_, select from sqlalchemy.dialects.postgresql import JSONB from .models import User, db as DB @@ -25,13 +25,13 @@ class TempUser(DB.Model): desc_role = DB.Column(DB.Unicode) password = DB.Column(DB.Unicode) pass_md5 = DB.Column(DB.Unicode) - email = DB.Column(DB.Unicode) + email = DB.Column(DB.Unicode) id_organisme = DB.Column(DB.Integer) remarques = DB.Column(DB.Unicode) champs_addi = DB.Column(JSONB) date_insert = DB.Column(DB.DateTime) date_update = DB.Column(DB.DateTime) - + def set_password(self, password, password_confirmation, md5): self.password, self.pass_md5 = check_and_encrypt_password( password, password_confirmation, md5 @@ -50,51 +50,55 @@ def is_valid(self): is_valid = False msg += "E-mail is not valid. " # check if user or temp user exist with an email or login given - role = ( - DB.session.query(User) - .filter(or_(User.email == self.email, User.identifiant == self.identifiant)) - .first() - ) + role = DB.session.scalars( + select(User).where( + or_(User.email == self.email, User.identifiant == self.identifiant) + ) + ).first() if role: is_valid = False if role.email == self.email: msg += ( - f"Un compte avec l'email {self.email} existe déjà. " + - "S'il s'agit de votre email, vous pouvez faire une demande de renouvellement " + - "de mot de passe via la page de login de GeoNature." + f"Un compte avec l'email {self.email} existe déjà. " + + "S'il s'agit de votre email, vous pouvez faire une demande de renouvellement " + + "de mot de passe via la page de login de GeoNature." ) else: msg += ( - f"Un compte avec l'identifiant {self.identifiant} existe déjà. " + - "Veuillez choisir un identifiant différent." + f"Un compte avec l'identifiant {self.identifiant} existe déjà. " + + "Veuillez choisir un identifiant différent." ) - temp_role = ( - DB.session.query(TempUser) - .filter(or_(TempUser.email == self.email, TempUser.identifiant == self.identifiant)) - .first() - ) + temp_role = DB.session.scalars( + select(TempUser) + .filter( + or_( + TempUser.email == self.email, + TempUser.identifiant == self.identifiant, + ) + ) + .limit(1) + ).first() if temp_role: is_valid = False if temp_role.email == self.email: msg += ( - f"Un compte en attente de validation avec l'email {self.email} existe déjà. "+ - "Merci de patienter le temps que votre demande soit traitée." - + f"Un compte en attente de validation avec l'email {self.email} existe déjà. " + + "Merci de patienter le temps que votre demande soit traitée." ) else: msg += ( - "Un compte en attente de validation avec l'identifiant " + - f"{self.identifiant} existe déjà. " + - "Veuillez choisir un identifiant différent." + "Un compte en attente de validation avec l'identifiant " + + f"{self.identifiant} existe déjà. " + + "Veuillez choisir un identifiant différent." ) return (is_valid, msg) def as_dict(self, recursif=False, columns=(), depth=None): """ - The signature of the function must be the as same the as_dict func - from https://github.com/PnX-SI/Utils-Flask-SQLAlchemy + The signature of the function must be the as same the as_dict func + from https://github.com/PnX-SI/Utils-Flask-SQLAlchemy """ return { "id_temp_user": self.id_temp_user, @@ -117,7 +121,6 @@ def as_dict(self, recursif=False, columns=(), depth=None): class CorRoleToken(DB.Model): - __tablename__ = "cor_role_token" __table_args__ = {"schema": "utilisateurs", "extend_existing": True} @@ -126,7 +129,7 @@ class CorRoleToken(DB.Model): def as_dict(self, recursif=False, columns=(), depth=None): """ - The signature of the function must be the as same the as_dict func - from https://github.com/PnX-SI/Utils-Flask-SQLAlchemy + The signature of the function must be the as same the as_dict func + from https://github.com/PnX-SI/Utils-Flask-SQLAlchemy """ return {"id_role": self.id_role, "token": self.token} diff --git a/src/pypnusershub/db/tools.py b/src/pypnusershub/db/tools.py index 50c8aec..8ad70f5 100644 --- a/src/pypnusershub/db/tools.py +++ b/src/pypnusershub/db/tools.py @@ -18,6 +18,8 @@ from pypnusershub.db import models from pypnusershub.utils import text_resource_stream, get_current_app_id +from geonature.utils.env import db + log = logging.getLogger(__name__) @@ -71,7 +73,6 @@ class DifferentPasswordError(Exception): def load_fixtures(con_uri): with text_resource_stream("fixtures.sql", "pypnusershub.db") as sql_file: - engine = sa.create_engine(con_uri) with engine.connect(): for line in sql_file: @@ -79,20 +80,21 @@ def load_fixtures(con_uri): engine.execute(line) engine.execute("COMMIT") + def encode_token(payload): - expire = datetime.now() + timedelta(seconds=current_app.config['COOKIE_EXPIRATION']) + expire = datetime.now() + timedelta(seconds=current_app.config["COOKIE_EXPIRATION"]) header = { "alg": "HS256", "exp": int(datetime.timestamp(expire)), } jwt = JsonWebToken(["HS256"]) - key = current_app.config['SECRET_KEY'].encode("UTF-8") + key = current_app.config["SECRET_KEY"].encode("UTF-8") return jwt.encode(header, payload, key) def decode_token(payload): jwt = JsonWebToken(["HS256"]) - key = current_app.config['SECRET_KEY'].encode("UTF-8") + key = current_app.config["SECRET_KEY"].encode("UTF-8") claims = jwt.decode(payload, key) claims.validate() return dict(claims) @@ -121,11 +123,11 @@ def user_from_token(token, secret_key=None): if id_app != id_app_from_config: log.info("Invalid token: the token not corespoding to the current app") raise UnreadableAccessRightsError("Token BadSignature", 403) - return ( - models.AppUser.query.filter(models.AppUser.id_role == id_role) + return db.session.execute( + db.select(models.AppUser) + .where(models.AppUser.id_role == id_role) .filter(models.AppUser.id_application == id_app) - .one() - ) + ).scalar_one() except NoResultFound: raise UnreadableAccessRightsError( diff --git a/src/pypnusershub/login_manager.py b/src/pypnusershub/login_manager.py index e2e1b8c..2db5299 100644 --- a/src/pypnusershub/login_manager.py +++ b/src/pypnusershub/login_manager.py @@ -7,12 +7,14 @@ from pypnusershub.db.models import User from pypnusershub.db.tools import decode_token +from geonature.utils.env import db + login_manager = LoginManager() @login_manager.user_loader def load_user(user_id): - return User.query.get(user_id) + return db.session.get(User, user_id) @login_manager.request_loader @@ -24,7 +26,7 @@ def load_user_from_request(request): return None try: user_dict = decode_token(jwt) - user = User.query.get(user_dict["id_role"]) + user = db.session.get(User, user_dict["id_role"]) g.login_via_request = True return user except (ExpiredTokenError, JoseError): diff --git a/src/pypnusershub/routes.py b/src/pypnusershub/routes.py index 57b3c81..fa65f26 100755 --- a/src/pypnusershub/routes.py +++ b/src/pypnusershub/routes.py @@ -13,8 +13,17 @@ import datetime from flask_login import login_user, logout_user, current_user -from flask import Blueprint, request, Response, current_app, redirect, g, make_response, jsonify -from markupsafe import escape +from flask import ( + Blueprint, + request, + Response, + current_app, + redirect, + g, + make_response, + jsonify, +) +from markupsafe import escape from sqlalchemy.orm import exc import sqlalchemy as sa @@ -60,7 +69,9 @@ def register(self, app, *args, **kwargs): # set cookie autorenew app.config["PASS_METHOD"] = app.config.get("PASS_METHOD", "hash") - app.config["REMEMBER_COOKIE_NAME"] = app.config.get("REMEMBER_COOKIE_NAME", "token") + app.config["REMEMBER_COOKIE_NAME"] = app.config.get( + "REMEMBER_COOKIE_NAME", "token" + ) parent = super(ConfigurableBlueprint, self) parent.register(app, *args, **kwargs) @@ -88,10 +99,15 @@ def login(): "One of the following parameter is required ['id_application', 'login', 'password']" ) return Response(msg, status=400) - app = models.Application.query.get(id_app) + app = db.session.get(models.Application, id_app) if not app: raise BadRequest(f"No app for id {id_app}") - user = models.User.query.filter(models.User.identifiant == login).filter_by_app().one() + user = ( + sa.select(models.User) + .where(models.User.identifiant == login) + .where(models.User.filter_by_app()) + .one() + ) user_dict = UserSchema(exclude=["remarques"]).dump(user) except exc.NoResultFound as e: msg = json.dumps( @@ -117,7 +133,9 @@ def login(): token = encode_token(user_dict) token_exp = datetime.datetime.now(datetime.timezone.utc) token_exp += datetime.timedelta(seconds=current_app.config["COOKIE_EXPIRATION"]) - return jsonify({"user": user_dict, "expires": token_exp.isoformat(), "token": token.decode()}) + return jsonify( + {"user": user_dict, "expires": token_exp.isoformat(), "token": token.decode()} + ) @routes.route("/public_login", methods=["POST"]) @@ -125,13 +143,14 @@ def public_login(): if not current_app.config.get("PUBLIC_ACCESS_USERNAME", {}): raise Forbidden - user = ( - models.AppUser.query.filter( - models.AppUser.identifiant == current_app.config.get("PUBLIC_ACCESS_USERNAME") + user = db.session.execute( + sa.select(models.AppUser) + .where( + models.AppUser.identifiant + == current_app.config.get("PUBLIC_ACCESS_USERNAME") ) .filter(models.AppUser.id_application == get_current_app_id()) - .one() - ) + ).scalar_one() user_dict = user.as_dict() login_user(user) # Génération d'un token @@ -139,7 +158,9 @@ def public_login(): token_exp = datetime.datetime.now(datetime.timezone.utc) token_exp += datetime.timedelta(seconds=current_app.config["COOKIE_EXPIRATION"]) - return jsonify({"user": user_dict, "expires": token_exp.isoformat(), "token": token.decode()}) + return jsonify( + {"user": user_dict, "expires": token_exp.isoformat(), "token": token.decode()} + ) @routes.route("/logout", methods=["GET", "POST"]) diff --git a/src/pypnusershub/routes_register.py b/src/pypnusershub/routes_register.py index 5cec629..201e13c 100644 --- a/src/pypnusershub/routes_register.py +++ b/src/pypnusershub/routes_register.py @@ -91,11 +91,11 @@ def _connect_admin(f): @wraps(f) def __connect_admin(*args, **kwargs): # connexion à usershub - id_app_usershub = ( - db.session.query(Application.id_application) - .filter(Application.code_application == "UH") - .first() - ) + id_app_usershub = db.session.scalars( + db.select(Application.id_application) + .where(Application.code_application == "UH") + .limit(1) + ).first() if not id_app_usershub: return json.dumps({"msg": "Pas d'id app USERSHUB"}), 500 @@ -184,11 +184,11 @@ def post_usershub(type_action): id_role = session["current_user"]["id_role"] q = ( - db.session.query(AppUser.id_droit_max) + db.select(AppUser.id_droit_max) .filter(AppUser.id_role == id_role) .filter(AppUser.id_application == get_current_app_id()) ) - id_droit = q.one()[0] + id_droit = db.session.execute(q).scalar_one()[0] # si pas de droit definis pour cet action, alors les droits requis sont à 7 => action impossible if id_droit < dict_type_action_droit.get(type_action, 7): diff --git a/src/pypnusershub/tests/test_utilisateurs.py b/src/pypnusershub/tests/test_utilisateurs.py index 592902a..f7c1c69 100644 --- a/src/pypnusershub/tests/test_utilisateurs.py +++ b/src/pypnusershub/tests/test_utilisateurs.py @@ -29,7 +29,7 @@ def test_insert_user(self, organism, group_and_users): insert_or_update_role(user) user["identifiant"] = "update" insert_or_update_role(user) - created_user = User.query.get(99999) + created_user = db.session.get(User, 99999) user_schema = UserSchema(only=["groups"]) created_user_as_dict = user_schema.dump(created_user) assert created_user_as_dict["identifiant"] == "update" @@ -52,14 +52,16 @@ def test_insert_organisme(self): organism["nom_organisme"] = "update" insert_or_update_organism(organism) - create_organism = Organisme.query.get(99999) + create_organism = db.session.get(Organisme, 99999) organism_schema = OrganismeSchema() organism_as_dict = organism_schema.dump(create_organism) assert organism_as_dict["nom_organisme"] == "update" def test_filter_by_app(self, group_and_users): - roles = User.query.filter_by_app("APPLI_1").all() - assert set([group_and_users["group1"], group_and_users["user1"]]).issubset(roles) + roles = db.select(User).where(User.filter_by_app("APPLI_1")).all() + assert set([group_and_users["group1"], group_and_users["user1"]]).issubset( + roles + ) def test_max_level_profil(self, app, group_and_users): app.config["CODE_APPLICATION"] = "APPLI_1" diff --git a/src/pypnusershub/tests/utils.py b/src/pypnusershub/tests/utils.py index cec92bb..4fb74d4 100644 --- a/src/pypnusershub/tests/utils.py +++ b/src/pypnusershub/tests/utils.py @@ -3,16 +3,20 @@ from werkzeug.datastructures import Headers from flask_login import login_user, logout_user +from sqlalchemy import select from pypnusershub.utils import get_current_app_id from pypnusershub.db.models import User from pypnusershub.db.tools import user_to_token +from geonature.utils.env import db def set_logged_user(client, user): - user = User.query.filter_by( - id_role=user.id_role, - ).one() + user = db.session.execute( + select(User).filter_by( + id_role=user.id_role, + ) + ).scalar_one() login_user(user) client.environ_base["HTTP_AUTHORIZATION"] = "Bearer " + user_to_token(user).decode() @@ -31,9 +35,11 @@ def unset_logged_user(client): def logged_user_headers(user, headers=None): - user = User.query.filter_by( - id_role=user.id_role, - ).one() + user = db.session.execute( + db.select(User).filter_by( + id_role=user.id_role, + ) + ).scalar_one() login_user(user) token = user_to_token(user).decode("latin1") if headers is None: diff --git a/src/pypnusershub/utils.py b/src/pypnusershub/utils.py index 0749306..8703e38 100644 --- a/src/pypnusershub/utils.py +++ b/src/pypnusershub/utils.py @@ -13,6 +13,9 @@ from urllib.parse import urlsplit from flask import current_app, Response +from sqlalchemy import select + +from geonature.utils.env import db class RessourceError(EnvironmentError): @@ -79,10 +82,12 @@ def get_current_app_id(): from pypnusershub.db.models import Application return ( - Application.query.filter_by( - code_application=current_app.config["CODE_APPLICATION"], + db.session.execute( + select(Application).filter_by( + code_application=current_app.config["CODE_APPLICATION"], + ) ) - .one() + .scalar_one() .id_application ) else: From d4154af8541ad2d61fbdcbf1f51f998516939149 Mon Sep 17 00:00:00 2001 From: Jacobe2169 Date: Thu, 14 Dec 2023 17:38:11 +0100 Subject: [PATCH 10/18] remove .query (again) --- src/pypnusershub/db/models.py | 6 +++--- src/pypnusershub/db/models_register.py | 2 +- src/pypnusershub/db/tools.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pypnusershub/db/models.py b/src/pypnusershub/db/models.py index 5f945ae..c3aafbd 100644 --- a/src/pypnusershub/db/models.py +++ b/src/pypnusershub/db/models.py @@ -103,7 +103,7 @@ def filter_by_app(self, code_app=None): Application, Application.id_application == UserApplicationRight.id_application, ) - .filter(Application.code_application == code_app) + .where(Application.code_application == code_app) ) @@ -159,7 +159,7 @@ def max_level_profil(self): ), ) .join(Profils, UserApplicationRight.id_profil == Profils.id_profil) - .filter(UserApplicationRight.id_application == get_current_app_id()) + .where(UserApplicationRight.id_application == get_current_app_id()) ) return q.scalar() or 0 @@ -230,7 +230,7 @@ def filter_by_app(cls, code_app=None, **kwargs): Application, Application.id_application == UserApplicationRight.id_application, ) - .filter(Application.code_application == code_app) + .where(Application.code_application == code_app) ).whereclause diff --git a/src/pypnusershub/db/models_register.py b/src/pypnusershub/db/models_register.py index 391f13e..f515d43 100644 --- a/src/pypnusershub/db/models_register.py +++ b/src/pypnusershub/db/models_register.py @@ -71,7 +71,7 @@ def is_valid(self): temp_role = DB.session.scalars( select(TempUser) - .filter( + .where( or_( TempUser.email == self.email, TempUser.identifiant == self.identifiant, diff --git a/src/pypnusershub/db/tools.py b/src/pypnusershub/db/tools.py index 8ad70f5..978402f 100644 --- a/src/pypnusershub/db/tools.py +++ b/src/pypnusershub/db/tools.py @@ -126,7 +126,7 @@ def user_from_token(token, secret_key=None): return db.session.execute( db.select(models.AppUser) .where(models.AppUser.id_role == id_role) - .filter(models.AppUser.id_application == id_app) + .where(models.AppUser.id_application == id_app) ).scalar_one() except NoResultFound: From 1520467507624c136ba40c1419e941846a43bf2e Mon Sep 17 00:00:00 2001 From: Jacobe2169 Date: Fri, 15 Dec 2023 12:06:24 +0100 Subject: [PATCH 11/18] call select() directly from sqlalchemy instead of flask-sqlalchemy db.select() --- src/pypnusershub/db/tools.py | 2 +- src/pypnusershub/routes_register.py | 3 ++- src/pypnusershub/tests/test_utilisateurs.py | 4 +++- src/pypnusershub/tests/utils.py | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/pypnusershub/db/tools.py b/src/pypnusershub/db/tools.py index 978402f..822e0b9 100644 --- a/src/pypnusershub/db/tools.py +++ b/src/pypnusershub/db/tools.py @@ -124,7 +124,7 @@ def user_from_token(token, secret_key=None): log.info("Invalid token: the token not corespoding to the current app") raise UnreadableAccessRightsError("Token BadSignature", 403) return db.session.execute( - db.select(models.AppUser) + sa.select(models.AppUser) .where(models.AppUser.id_role == id_role) .where(models.AppUser.id_application == id_app) ).scalar_one() diff --git a/src/pypnusershub/routes_register.py b/src/pypnusershub/routes_register.py index 201e13c..c13de38 100644 --- a/src/pypnusershub/routes_register.py +++ b/src/pypnusershub/routes_register.py @@ -30,6 +30,7 @@ from .env import REGISTER_POST_ACTION_FCT from flask import current_app +from sqlalchemy import select from pypnusershub.utils import get_current_app_id @@ -92,7 +93,7 @@ def _connect_admin(f): def __connect_admin(*args, **kwargs): # connexion à usershub id_app_usershub = db.session.scalars( - db.select(Application.id_application) + select(Application.id_application) .where(Application.code_application == "UH") .limit(1) ).first() diff --git a/src/pypnusershub/tests/test_utilisateurs.py b/src/pypnusershub/tests/test_utilisateurs.py index f7c1c69..3af02ea 100644 --- a/src/pypnusershub/tests/test_utilisateurs.py +++ b/src/pypnusershub/tests/test_utilisateurs.py @@ -9,6 +9,8 @@ from pypnusershub.schemas import OrganismeSchema, UserSchema from pypnusershub.tests.fixtures import * +from sqlalchemy import select + @pytest.mark.usefixtures("client_class", "temporary_transaction") class TestUtilisateurs: @@ -58,7 +60,7 @@ def test_insert_organisme(self): assert organism_as_dict["nom_organisme"] == "update" def test_filter_by_app(self, group_and_users): - roles = db.select(User).where(User.filter_by_app("APPLI_1")).all() + roles = select(User).where(User.filter_by_app("APPLI_1")).all() assert set([group_and_users["group1"], group_and_users["user1"]]).issubset( roles ) diff --git a/src/pypnusershub/tests/utils.py b/src/pypnusershub/tests/utils.py index 4fb74d4..0a02517 100644 --- a/src/pypnusershub/tests/utils.py +++ b/src/pypnusershub/tests/utils.py @@ -36,7 +36,7 @@ def unset_logged_user(client): def logged_user_headers(user, headers=None): user = db.session.execute( - db.select(User).filter_by( + select(User).filter_by( id_role=user.id_role, ) ).scalar_one() From fe46bbe51bb7b5837604422b25acaf10e2c3bb54 Mon Sep 17 00:00:00 2001 From: Jacobe2169 Date: Mon, 18 Dec 2023 19:18:29 +0100 Subject: [PATCH 12/18] fix 2.0 sqla translation error --- src/pypnusershub/routes.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/pypnusershub/routes.py b/src/pypnusershub/routes.py index fa65f26..d215c6b 100755 --- a/src/pypnusershub/routes.py +++ b/src/pypnusershub/routes.py @@ -102,12 +102,11 @@ def login(): app = db.session.get(models.Application, id_app) if not app: raise BadRequest(f"No app for id {id_app}") - user = ( + user = db.session.execute( sa.select(models.User) .where(models.User.identifiant == login) .where(models.User.filter_by_app()) - .one() - ) + ).scalar_one() user_dict = UserSchema(exclude=["remarques"]).dump(user) except exc.NoResultFound as e: msg = json.dumps( From 1d1fad892c0fb613dc8b222912caa6f15093a6e8 Mon Sep 17 00:00:00 2001 From: Jacobe2169 Date: Mon, 11 Dec 2023 11:42:55 +0100 Subject: [PATCH 13/18] drop .query --- src/pypnusershub/db/models.py | 67 +++++++++++++++++---- src/pypnusershub/db/models_register.py | 61 ++++++++++--------- src/pypnusershub/db/tools.py | 18 +++--- src/pypnusershub/login_manager.py | 6 +- src/pypnusershub/routes.py | 28 ++++++--- src/pypnusershub/routes_register.py | 14 ++--- src/pypnusershub/tests/test_utilisateurs.py | 10 +-- src/pypnusershub/tests/utils.py | 18 ++++-- src/pypnusershub/utils.py | 11 +++- 9 files changed, 154 insertions(+), 79 deletions(-) diff --git a/src/pypnusershub/db/models.py b/src/pypnusershub/db/models.py index 4e091d4..5f945ae 100644 --- a/src/pypnusershub/db/models.py +++ b/src/pypnusershub/db/models.py @@ -2,6 +2,8 @@ from __future__ import unicode_literals, print_function, absolute_import, division +from utils_flask_sqla.models import qfilter + """ mappings applications et utilisateurs """ @@ -125,7 +127,9 @@ class User(db.Model, UserMixin): _password = db.Column("pass", db.Unicode) _password_plus = db.Column("pass_plus", db.Unicode) email = db.Column(db.Unicode) - id_organisme = db.Column(db.Integer, ForeignKey("utilisateurs.bib_organismes.id_organisme")) + id_organisme = db.Column( + db.Integer, ForeignKey("utilisateurs.bib_organismes.id_organisme") + ) remarques = db.Column(db.Unicode) champs_addi = db.Column(JSONB) date_insert = db.Column(db.DateTime) @@ -149,7 +153,9 @@ def max_level_profil(self): UserApplicationRight, or_( UserApplicationRight.id_role == self.id_role, - UserApplicationRight.id_role.in_([role.id_role for role in self.groups]), + UserApplicationRight.id_role.in_( + [role.id_role for role in self.groups] + ), ), ) .join(Profils, UserApplicationRight.id_profil == Profils.id_profil) @@ -206,6 +212,27 @@ def __repr__(self): def __str__(self): return self.identifiant or self.nom_complet + @qfilter + def filter_by_app(cls, code_app=None, **kwargs): + if code_app is None: + code_app = current_app.config["CODE_APPLICATION"] + query = kwargs["query"] + return ( + query.outerjoin(cor_roles, User.id_role == cor_roles.c.id_role_utilisateur) + .outerjoin( + UserApplicationRight, + or_( + UserApplicationRight.id_role == cor_roles.c.id_role_groupe, + UserApplicationRight.id_role == User.id_role, + ), + ) + .join( + Application, + Application.id_application == UserApplicationRight.id_application, + ) + .filter(Application.code_application == code_app) + ).whereclause + @serializable class Organisme(db.Model): @@ -213,7 +240,9 @@ class Organisme(db.Model): __table_args__ = {"schema": "utilisateurs"} id_organisme = db.Column(db.Integer, primary_key=True) - uuid_organisme = db.Column(UUID(as_uuid=True), default=select(func.uuid_generate_v4())) + uuid_organisme = db.Column( + UUID(as_uuid=True), default=select(func.uuid_generate_v4()) + ) nom_organisme = db.Column(db.Unicode) adresse_organisme = db.Column(db.Unicode) cp_organisme = db.Column(db.Unicode) @@ -223,7 +252,9 @@ class Organisme(db.Model): email_organisme = db.Column(db.Unicode) url_organisme = db.Column(db.Unicode) url_logo = db.Column(db.Unicode) - id_parent = db.Column(db.Integer, db.ForeignKey("utilisateurs.bib_organismes.id_organisme")) + id_parent = db.Column( + db.Integer, db.ForeignKey("utilisateurs.bib_organismes.id_organisme") + ) additional_data = db.Column(JSONB, nullable=True, server_default="{}") members = db.relationship(User, backref="organisme") @@ -261,7 +292,9 @@ class Profils(db.Model): nom_profil = db.Column(db.Unicode) desc_profil = db.Column(db.Unicode) - applications = relationship("Application", secondary=profils_for_app, back_populates="profils") + applications = relationship( + "Application", secondary=profils_for_app, back_populates="profils" + ) @serializable @@ -278,7 +311,9 @@ class Application(db.Model): desc_application = db.Column(db.Unicode) id_parent = db.Column(db.Integer) - profils = relationship(Profils, secondary=profils_for_app, back_populates="applications") + profils = relationship( + Profils, secondary=profils_for_app, back_populates="applications" + ) def __repr__(self): return "".format(self.nom_application) @@ -288,7 +323,9 @@ def __str__(self): @staticmethod def get_application(nom_application): - return Application.query.filter(Application.nom_application == nom_application).one() + return db.session.execute( + select(Application).where(Application.nom_application == nom_application) + ).scalar_one() class ApplicationRight(db.Model): @@ -316,12 +353,16 @@ class UserApplicationRight(db.Model): __tablename__ = "cor_role_app_profil" __table_args__ = {"schema": "utilisateurs"} # , 'extend_existing': True} - id_role = db.Column(db.Integer, ForeignKey("utilisateurs.t_roles.id_role"), primary_key=True) + id_role = db.Column( + db.Integer, ForeignKey("utilisateurs.t_roles.id_role"), primary_key=True + ) id_profil = db.Column( db.Integer, ForeignKey("utilisateurs.t_profils.id_profil"), primary_key=True ) id_application = db.Column( - db.Integer, ForeignKey("utilisateurs.t_applications.id_application"), primary_key=True + db.Integer, + ForeignKey("utilisateurs.t_applications.id_application"), + primary_key=True, ) role = relationship("User") @@ -350,7 +391,9 @@ class AppUser(db.Model): nom_role = db.Column(db.Unicode) prenom_role = db.Column(db.Unicode) id_application = db.Column( - db.Integer, db.ForeignKey("utilisateurs.t_applications.id_application"), primary_key=True + db.Integer, + db.ForeignKey("utilisateurs.t_applications.id_application"), + primary_key=True, ) id_organisme = db.Column(db.Integer) application = relationship("Application", backref="app_users") @@ -387,7 +430,9 @@ class AppRole(db.Model): nom_role = db.Column(db.Unicode) prenom_role = db.Column(db.Unicode) id_application = db.Column( - db.Integer, db.ForeignKey("utilisateurs.t_applications.id_application"), primary_key=True + db.Integer, + db.ForeignKey("utilisateurs.t_applications.id_application"), + primary_key=True, ) id_organisme = db.Column(db.Integer) identifiant = db.Column(db.Unicode) diff --git a/src/pypnusershub/db/models_register.py b/src/pypnusershub/db/models_register.py index 6ada9f9..391f13e 100644 --- a/src/pypnusershub/db/models_register.py +++ b/src/pypnusershub/db/models_register.py @@ -3,7 +3,7 @@ from flask import current_app from pypnusershub.db.models import check_and_encrypt_password -from sqlalchemy import or_ +from sqlalchemy import or_, select from sqlalchemy.dialects.postgresql import JSONB from .models import User, db as DB @@ -25,13 +25,13 @@ class TempUser(DB.Model): desc_role = DB.Column(DB.Unicode) password = DB.Column(DB.Unicode) pass_md5 = DB.Column(DB.Unicode) - email = DB.Column(DB.Unicode) + email = DB.Column(DB.Unicode) id_organisme = DB.Column(DB.Integer) remarques = DB.Column(DB.Unicode) champs_addi = DB.Column(JSONB) date_insert = DB.Column(DB.DateTime) date_update = DB.Column(DB.DateTime) - + def set_password(self, password, password_confirmation, md5): self.password, self.pass_md5 = check_and_encrypt_password( password, password_confirmation, md5 @@ -50,51 +50,55 @@ def is_valid(self): is_valid = False msg += "E-mail is not valid. " # check if user or temp user exist with an email or login given - role = ( - DB.session.query(User) - .filter(or_(User.email == self.email, User.identifiant == self.identifiant)) - .first() - ) + role = DB.session.scalars( + select(User).where( + or_(User.email == self.email, User.identifiant == self.identifiant) + ) + ).first() if role: is_valid = False if role.email == self.email: msg += ( - f"Un compte avec l'email {self.email} existe déjà. " + - "S'il s'agit de votre email, vous pouvez faire une demande de renouvellement " + - "de mot de passe via la page de login de GeoNature." + f"Un compte avec l'email {self.email} existe déjà. " + + "S'il s'agit de votre email, vous pouvez faire une demande de renouvellement " + + "de mot de passe via la page de login de GeoNature." ) else: msg += ( - f"Un compte avec l'identifiant {self.identifiant} existe déjà. " + - "Veuillez choisir un identifiant différent." + f"Un compte avec l'identifiant {self.identifiant} existe déjà. " + + "Veuillez choisir un identifiant différent." ) - temp_role = ( - DB.session.query(TempUser) - .filter(or_(TempUser.email == self.email, TempUser.identifiant == self.identifiant)) - .first() - ) + temp_role = DB.session.scalars( + select(TempUser) + .filter( + or_( + TempUser.email == self.email, + TempUser.identifiant == self.identifiant, + ) + ) + .limit(1) + ).first() if temp_role: is_valid = False if temp_role.email == self.email: msg += ( - f"Un compte en attente de validation avec l'email {self.email} existe déjà. "+ - "Merci de patienter le temps que votre demande soit traitée." - + f"Un compte en attente de validation avec l'email {self.email} existe déjà. " + + "Merci de patienter le temps que votre demande soit traitée." ) else: msg += ( - "Un compte en attente de validation avec l'identifiant " + - f"{self.identifiant} existe déjà. " + - "Veuillez choisir un identifiant différent." + "Un compte en attente de validation avec l'identifiant " + + f"{self.identifiant} existe déjà. " + + "Veuillez choisir un identifiant différent." ) return (is_valid, msg) def as_dict(self, recursif=False, columns=(), depth=None): """ - The signature of the function must be the as same the as_dict func - from https://github.com/PnX-SI/Utils-Flask-SQLAlchemy + The signature of the function must be the as same the as_dict func + from https://github.com/PnX-SI/Utils-Flask-SQLAlchemy """ return { "id_temp_user": self.id_temp_user, @@ -117,7 +121,6 @@ def as_dict(self, recursif=False, columns=(), depth=None): class CorRoleToken(DB.Model): - __tablename__ = "cor_role_token" __table_args__ = {"schema": "utilisateurs", "extend_existing": True} @@ -126,7 +129,7 @@ class CorRoleToken(DB.Model): def as_dict(self, recursif=False, columns=(), depth=None): """ - The signature of the function must be the as same the as_dict func - from https://github.com/PnX-SI/Utils-Flask-SQLAlchemy + The signature of the function must be the as same the as_dict func + from https://github.com/PnX-SI/Utils-Flask-SQLAlchemy """ return {"id_role": self.id_role, "token": self.token} diff --git a/src/pypnusershub/db/tools.py b/src/pypnusershub/db/tools.py index 50c8aec..8ad70f5 100644 --- a/src/pypnusershub/db/tools.py +++ b/src/pypnusershub/db/tools.py @@ -18,6 +18,8 @@ from pypnusershub.db import models from pypnusershub.utils import text_resource_stream, get_current_app_id +from geonature.utils.env import db + log = logging.getLogger(__name__) @@ -71,7 +73,6 @@ class DifferentPasswordError(Exception): def load_fixtures(con_uri): with text_resource_stream("fixtures.sql", "pypnusershub.db") as sql_file: - engine = sa.create_engine(con_uri) with engine.connect(): for line in sql_file: @@ -79,20 +80,21 @@ def load_fixtures(con_uri): engine.execute(line) engine.execute("COMMIT") + def encode_token(payload): - expire = datetime.now() + timedelta(seconds=current_app.config['COOKIE_EXPIRATION']) + expire = datetime.now() + timedelta(seconds=current_app.config["COOKIE_EXPIRATION"]) header = { "alg": "HS256", "exp": int(datetime.timestamp(expire)), } jwt = JsonWebToken(["HS256"]) - key = current_app.config['SECRET_KEY'].encode("UTF-8") + key = current_app.config["SECRET_KEY"].encode("UTF-8") return jwt.encode(header, payload, key) def decode_token(payload): jwt = JsonWebToken(["HS256"]) - key = current_app.config['SECRET_KEY'].encode("UTF-8") + key = current_app.config["SECRET_KEY"].encode("UTF-8") claims = jwt.decode(payload, key) claims.validate() return dict(claims) @@ -121,11 +123,11 @@ def user_from_token(token, secret_key=None): if id_app != id_app_from_config: log.info("Invalid token: the token not corespoding to the current app") raise UnreadableAccessRightsError("Token BadSignature", 403) - return ( - models.AppUser.query.filter(models.AppUser.id_role == id_role) + return db.session.execute( + db.select(models.AppUser) + .where(models.AppUser.id_role == id_role) .filter(models.AppUser.id_application == id_app) - .one() - ) + ).scalar_one() except NoResultFound: raise UnreadableAccessRightsError( diff --git a/src/pypnusershub/login_manager.py b/src/pypnusershub/login_manager.py index e2e1b8c..2db5299 100644 --- a/src/pypnusershub/login_manager.py +++ b/src/pypnusershub/login_manager.py @@ -7,12 +7,14 @@ from pypnusershub.db.models import User from pypnusershub.db.tools import decode_token +from geonature.utils.env import db + login_manager = LoginManager() @login_manager.user_loader def load_user(user_id): - return User.query.get(user_id) + return db.session.get(User, user_id) @login_manager.request_loader @@ -24,7 +26,7 @@ def load_user_from_request(request): return None try: user_dict = decode_token(jwt) - user = User.query.get(user_dict["id_role"]) + user = db.session.get(User, user_dict["id_role"]) g.login_via_request = True return user except (ExpiredTokenError, JoseError): diff --git a/src/pypnusershub/routes.py b/src/pypnusershub/routes.py index 0d3998a..9743e47 100755 --- a/src/pypnusershub/routes.py +++ b/src/pypnusershub/routes.py @@ -12,8 +12,17 @@ import datetime from flask_login import login_user, logout_user, current_user -from flask import Blueprint, request, Response, current_app, redirect, g, make_response, jsonify -from markupsafe import escape +from flask import ( + Blueprint, + request, + Response, + current_app, + redirect, + g, + make_response, + jsonify, +) +from markupsafe import escape from sqlalchemy.orm import exc import sqlalchemy as sa @@ -89,12 +98,13 @@ def login(): "One of the following parameter is required ['id_application', 'login', 'password']" ) return Response(msg, status=400) - app = models.Application.query.get(id_app) + app = db.session.get(models.Application, id_app) if not app: raise BadRequest(f"No app for id {id_app}") user = ( - models.User.query.filter(models.User.identifiant == login) - .filter_by_app() + sa.select(models.User) + .where(models.User.identifiant == login) + .where(models.User.filter_by_app()) .one() ) user_dict = UserSchema(exclude=["remarques"]).dump(user) @@ -132,14 +142,14 @@ def public_login(): if not current_app.config.get("PUBLIC_ACCESS_USERNAME", {}): raise Forbidden - user = ( - models.AppUser.query.filter( + user = db.session.execute( + sa.select(models.AppUser) + .where( models.AppUser.identifiant == current_app.config.get("PUBLIC_ACCESS_USERNAME") ) .filter(models.AppUser.id_application == get_current_app_id()) - .one() - ) + ).scalar_one() user_dict = user.as_dict() login_user(user) # Génération d'un token diff --git a/src/pypnusershub/routes_register.py b/src/pypnusershub/routes_register.py index 8f3335f..7161037 100644 --- a/src/pypnusershub/routes_register.py +++ b/src/pypnusershub/routes_register.py @@ -91,11 +91,11 @@ def _connect_admin(f): @wraps(f) def __connect_admin(*args, **kwargs): # connexion à usershub - id_app_usershub = ( - db.session.query(Application.id_application) - .filter(Application.code_application == "UH") - .first() - ) + id_app_usershub = db.session.scalars( + db.select(Application.id_application) + .where(Application.code_application == "UH") + .limit(1) + ).first() if not id_app_usershub: return json.dumps({"msg": "Pas d'id app USERSHUB"}), 500 @@ -184,11 +184,11 @@ def post_usershub(type_action): id_role = session["current_user"]["id_role"] q = ( - db.session.query(AppUser.id_droit_max) + db.select(AppUser.id_droit_max) .filter(AppUser.id_role == id_role) .filter(AppUser.id_application == get_current_app_id()) ) - id_droit = q.one()[0] + id_droit = db.session.execute(q).scalar_one()[0] # si pas de droit definis pour cet action, alors les droits requis sont à 7 => action impossible if id_droit < dict_type_action_droit.get(type_action, 7): diff --git a/src/pypnusershub/tests/test_utilisateurs.py b/src/pypnusershub/tests/test_utilisateurs.py index 592902a..f7c1c69 100644 --- a/src/pypnusershub/tests/test_utilisateurs.py +++ b/src/pypnusershub/tests/test_utilisateurs.py @@ -29,7 +29,7 @@ def test_insert_user(self, organism, group_and_users): insert_or_update_role(user) user["identifiant"] = "update" insert_or_update_role(user) - created_user = User.query.get(99999) + created_user = db.session.get(User, 99999) user_schema = UserSchema(only=["groups"]) created_user_as_dict = user_schema.dump(created_user) assert created_user_as_dict["identifiant"] == "update" @@ -52,14 +52,16 @@ def test_insert_organisme(self): organism["nom_organisme"] = "update" insert_or_update_organism(organism) - create_organism = Organisme.query.get(99999) + create_organism = db.session.get(Organisme, 99999) organism_schema = OrganismeSchema() organism_as_dict = organism_schema.dump(create_organism) assert organism_as_dict["nom_organisme"] == "update" def test_filter_by_app(self, group_and_users): - roles = User.query.filter_by_app("APPLI_1").all() - assert set([group_and_users["group1"], group_and_users["user1"]]).issubset(roles) + roles = db.select(User).where(User.filter_by_app("APPLI_1")).all() + assert set([group_and_users["group1"], group_and_users["user1"]]).issubset( + roles + ) def test_max_level_profil(self, app, group_and_users): app.config["CODE_APPLICATION"] = "APPLI_1" diff --git a/src/pypnusershub/tests/utils.py b/src/pypnusershub/tests/utils.py index cec92bb..4fb74d4 100644 --- a/src/pypnusershub/tests/utils.py +++ b/src/pypnusershub/tests/utils.py @@ -3,16 +3,20 @@ from werkzeug.datastructures import Headers from flask_login import login_user, logout_user +from sqlalchemy import select from pypnusershub.utils import get_current_app_id from pypnusershub.db.models import User from pypnusershub.db.tools import user_to_token +from geonature.utils.env import db def set_logged_user(client, user): - user = User.query.filter_by( - id_role=user.id_role, - ).one() + user = db.session.execute( + select(User).filter_by( + id_role=user.id_role, + ) + ).scalar_one() login_user(user) client.environ_base["HTTP_AUTHORIZATION"] = "Bearer " + user_to_token(user).decode() @@ -31,9 +35,11 @@ def unset_logged_user(client): def logged_user_headers(user, headers=None): - user = User.query.filter_by( - id_role=user.id_role, - ).one() + user = db.session.execute( + db.select(User).filter_by( + id_role=user.id_role, + ) + ).scalar_one() login_user(user) token = user_to_token(user).decode("latin1") if headers is None: diff --git a/src/pypnusershub/utils.py b/src/pypnusershub/utils.py index 0749306..8703e38 100644 --- a/src/pypnusershub/utils.py +++ b/src/pypnusershub/utils.py @@ -13,6 +13,9 @@ from urllib.parse import urlsplit from flask import current_app, Response +from sqlalchemy import select + +from geonature.utils.env import db class RessourceError(EnvironmentError): @@ -79,10 +82,12 @@ def get_current_app_id(): from pypnusershub.db.models import Application return ( - Application.query.filter_by( - code_application=current_app.config["CODE_APPLICATION"], + db.session.execute( + select(Application).filter_by( + code_application=current_app.config["CODE_APPLICATION"], + ) ) - .one() + .scalar_one() .id_application ) else: From d555f17b7a3c739cc3d893a5e56d6ef6ea336233 Mon Sep 17 00:00:00 2001 From: Jacobe2169 Date: Thu, 14 Dec 2023 17:38:11 +0100 Subject: [PATCH 14/18] remove .query (again) --- src/pypnusershub/db/models.py | 6 +++--- src/pypnusershub/db/models_register.py | 2 +- src/pypnusershub/db/tools.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pypnusershub/db/models.py b/src/pypnusershub/db/models.py index 5f945ae..c3aafbd 100644 --- a/src/pypnusershub/db/models.py +++ b/src/pypnusershub/db/models.py @@ -103,7 +103,7 @@ def filter_by_app(self, code_app=None): Application, Application.id_application == UserApplicationRight.id_application, ) - .filter(Application.code_application == code_app) + .where(Application.code_application == code_app) ) @@ -159,7 +159,7 @@ def max_level_profil(self): ), ) .join(Profils, UserApplicationRight.id_profil == Profils.id_profil) - .filter(UserApplicationRight.id_application == get_current_app_id()) + .where(UserApplicationRight.id_application == get_current_app_id()) ) return q.scalar() or 0 @@ -230,7 +230,7 @@ def filter_by_app(cls, code_app=None, **kwargs): Application, Application.id_application == UserApplicationRight.id_application, ) - .filter(Application.code_application == code_app) + .where(Application.code_application == code_app) ).whereclause diff --git a/src/pypnusershub/db/models_register.py b/src/pypnusershub/db/models_register.py index 391f13e..f515d43 100644 --- a/src/pypnusershub/db/models_register.py +++ b/src/pypnusershub/db/models_register.py @@ -71,7 +71,7 @@ def is_valid(self): temp_role = DB.session.scalars( select(TempUser) - .filter( + .where( or_( TempUser.email == self.email, TempUser.identifiant == self.identifiant, diff --git a/src/pypnusershub/db/tools.py b/src/pypnusershub/db/tools.py index 8ad70f5..978402f 100644 --- a/src/pypnusershub/db/tools.py +++ b/src/pypnusershub/db/tools.py @@ -126,7 +126,7 @@ def user_from_token(token, secret_key=None): return db.session.execute( db.select(models.AppUser) .where(models.AppUser.id_role == id_role) - .filter(models.AppUser.id_application == id_app) + .where(models.AppUser.id_application == id_app) ).scalar_one() except NoResultFound: From d7219e9355db9f20e9f8c0ee8eb8f0c15dcd69b2 Mon Sep 17 00:00:00 2001 From: Jacobe2169 Date: Fri, 15 Dec 2023 12:06:24 +0100 Subject: [PATCH 15/18] call select() directly from sqlalchemy instead of flask-sqlalchemy db.select() --- src/pypnusershub/db/tools.py | 2 +- src/pypnusershub/routes_register.py | 3 ++- src/pypnusershub/tests/test_utilisateurs.py | 4 +++- src/pypnusershub/tests/utils.py | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/pypnusershub/db/tools.py b/src/pypnusershub/db/tools.py index 978402f..822e0b9 100644 --- a/src/pypnusershub/db/tools.py +++ b/src/pypnusershub/db/tools.py @@ -124,7 +124,7 @@ def user_from_token(token, secret_key=None): log.info("Invalid token: the token not corespoding to the current app") raise UnreadableAccessRightsError("Token BadSignature", 403) return db.session.execute( - db.select(models.AppUser) + sa.select(models.AppUser) .where(models.AppUser.id_role == id_role) .where(models.AppUser.id_application == id_app) ).scalar_one() diff --git a/src/pypnusershub/routes_register.py b/src/pypnusershub/routes_register.py index 7161037..1a0ebb6 100644 --- a/src/pypnusershub/routes_register.py +++ b/src/pypnusershub/routes_register.py @@ -30,6 +30,7 @@ from .env import REGISTER_POST_ACTION_FCT from flask import current_app +from sqlalchemy import select from pypnusershub.utils import get_current_app_id @@ -92,7 +93,7 @@ def _connect_admin(f): def __connect_admin(*args, **kwargs): # connexion à usershub id_app_usershub = db.session.scalars( - db.select(Application.id_application) + select(Application.id_application) .where(Application.code_application == "UH") .limit(1) ).first() diff --git a/src/pypnusershub/tests/test_utilisateurs.py b/src/pypnusershub/tests/test_utilisateurs.py index f7c1c69..3af02ea 100644 --- a/src/pypnusershub/tests/test_utilisateurs.py +++ b/src/pypnusershub/tests/test_utilisateurs.py @@ -9,6 +9,8 @@ from pypnusershub.schemas import OrganismeSchema, UserSchema from pypnusershub.tests.fixtures import * +from sqlalchemy import select + @pytest.mark.usefixtures("client_class", "temporary_transaction") class TestUtilisateurs: @@ -58,7 +60,7 @@ def test_insert_organisme(self): assert organism_as_dict["nom_organisme"] == "update" def test_filter_by_app(self, group_and_users): - roles = db.select(User).where(User.filter_by_app("APPLI_1")).all() + roles = select(User).where(User.filter_by_app("APPLI_1")).all() assert set([group_and_users["group1"], group_and_users["user1"]]).issubset( roles ) diff --git a/src/pypnusershub/tests/utils.py b/src/pypnusershub/tests/utils.py index 4fb74d4..0a02517 100644 --- a/src/pypnusershub/tests/utils.py +++ b/src/pypnusershub/tests/utils.py @@ -36,7 +36,7 @@ def unset_logged_user(client): def logged_user_headers(user, headers=None): user = db.session.execute( - db.select(User).filter_by( + select(User).filter_by( id_role=user.id_role, ) ).scalar_one() From 8f2f783182199f8033b9af01143505c26498a988 Mon Sep 17 00:00:00 2001 From: Jacobe2169 Date: Mon, 18 Dec 2023 19:18:29 +0100 Subject: [PATCH 16/18] fix 2.0 sqla translation error --- src/pypnusershub/routes.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/pypnusershub/routes.py b/src/pypnusershub/routes.py index 9743e47..3723cd8 100755 --- a/src/pypnusershub/routes.py +++ b/src/pypnusershub/routes.py @@ -101,12 +101,11 @@ def login(): app = db.session.get(models.Application, id_app) if not app: raise BadRequest(f"No app for id {id_app}") - user = ( + user = db.session.execute( sa.select(models.User) .where(models.User.identifiant == login) .where(models.User.filter_by_app()) - .one() - ) + ).scalar_one() user_dict = UserSchema(exclude=["remarques"]).dump(user) except exc.NoResultFound as e: msg = json.dumps( From b9f8ad0148de4059760e290b4c4598ee3037c2be Mon Sep 17 00:00:00 2001 From: Jacobe2169 Date: Tue, 19 Dec 2023 10:44:20 +0100 Subject: [PATCH 17/18] point UH-authentification-module to hotfix/sqla1.4 --- dependencies/Utils-Flask-SQLAlchemy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/Utils-Flask-SQLAlchemy b/dependencies/Utils-Flask-SQLAlchemy index 6fc91a7..619b3ca 160000 --- a/dependencies/Utils-Flask-SQLAlchemy +++ b/dependencies/Utils-Flask-SQLAlchemy @@ -1 +1 @@ -Subproject commit 6fc91a7314936c50f5b35cf0829abd1fa93f03df +Subproject commit 619b3ca70625316137202fd239c8f2a7ccdd5b91 From 83f4710bf09e24c531ef0e950ccee84b8c8e509f Mon Sep 17 00:00:00 2001 From: Jacobe2169 Date: Tue, 19 Dec 2023 10:51:39 +0100 Subject: [PATCH 18/18] fix bad db import --- src/pypnusershub/db/tools.py | 2 +- src/pypnusershub/login_manager.py | 2 +- src/pypnusershub/routes.py | 4 ---- src/pypnusershub/tests/test_utilisateurs.py | 4 +++- src/pypnusershub/tests/utils.py | 2 +- src/pypnusershub/utils.py | 2 +- 6 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/pypnusershub/db/tools.py b/src/pypnusershub/db/tools.py index 822e0b9..ef469b9 100644 --- a/src/pypnusershub/db/tools.py +++ b/src/pypnusershub/db/tools.py @@ -18,7 +18,7 @@ from pypnusershub.db import models from pypnusershub.utils import text_resource_stream, get_current_app_id -from geonature.utils.env import db +from pypnusershub.env import db log = logging.getLogger(__name__) diff --git a/src/pypnusershub/login_manager.py b/src/pypnusershub/login_manager.py index 2db5299..f872f50 100644 --- a/src/pypnusershub/login_manager.py +++ b/src/pypnusershub/login_manager.py @@ -7,7 +7,7 @@ from pypnusershub.db.models import User from pypnusershub.db.tools import decode_token -from geonature.utils.env import db +from pypnusershub.env import db login_manager = LoginManager() diff --git a/src/pypnusershub/routes.py b/src/pypnusershub/routes.py index dfed5d0..3723cd8 100755 --- a/src/pypnusershub/routes.py +++ b/src/pypnusershub/routes.py @@ -11,10 +11,6 @@ import logging import datetime -<<<<<<< HEAD - -======= ->>>>>>> 8f2f783182199f8033b9af01143505c26498a988 from flask_login import login_user, logout_user, current_user from flask import ( Blueprint, diff --git a/src/pypnusershub/tests/test_utilisateurs.py b/src/pypnusershub/tests/test_utilisateurs.py index 3af02ea..2c71043 100644 --- a/src/pypnusershub/tests/test_utilisateurs.py +++ b/src/pypnusershub/tests/test_utilisateurs.py @@ -60,7 +60,9 @@ def test_insert_organisme(self): assert organism_as_dict["nom_organisme"] == "update" def test_filter_by_app(self, group_and_users): - roles = select(User).where(User.filter_by_app("APPLI_1")).all() + roles = db.session.scalars( + select(User).where(User.filter_by_app("APPLI_1")) + ).all() assert set([group_and_users["group1"], group_and_users["user1"]]).issubset( roles ) diff --git a/src/pypnusershub/tests/utils.py b/src/pypnusershub/tests/utils.py index 0a02517..9c0bfa9 100644 --- a/src/pypnusershub/tests/utils.py +++ b/src/pypnusershub/tests/utils.py @@ -8,7 +8,7 @@ from pypnusershub.utils import get_current_app_id from pypnusershub.db.models import User from pypnusershub.db.tools import user_to_token -from geonature.utils.env import db +from pypnusershub.env import db def set_logged_user(client, user): diff --git a/src/pypnusershub/utils.py b/src/pypnusershub/utils.py index 8703e38..d9a3318 100644 --- a/src/pypnusershub/utils.py +++ b/src/pypnusershub/utils.py @@ -15,7 +15,7 @@ from flask import current_app, Response from sqlalchemy import select -from geonature.utils.env import db +from pypnusershub.env import db class RessourceError(EnvironmentError):