diff --git a/pyproject.toml b/pyproject.toml index 442976224e..fe03bcd102 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -319,11 +319,12 @@ vendors = "rero_ils.modules.vendors.jsonschemas" files = "rero_ils.modules.files.jsonschemas" [tool.poetry.plugins."invenio_oauth2server.scopes"] +fullname = "rero_ils.oauth.scopes:fullname" birthdate = "rero_ils.oauth.scopes:birthdate" expiration_date = "rero_ils.oauth.scopes:expiration_date" -fullname = "rero_ils.oauth.scopes:fullname" institution = "rero_ils.oauth.scopes:institution" patron_type = "rero_ils.oauth.scopes:patron_type" +# deprecated scopes patron_types = "rero_ils.oauth.scopes:patron_types" [tool.poetry.plugins."invenio_pidstore.fetchers"] diff --git a/rero_ils/modules/patrons/views.py b/rero_ils/modules/patrons/views.py index 54967e5dad..47f675a034 100644 --- a/rero_ils/modules/patrons/views.py +++ b/rero_ils/modules/patrons/views.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # RERO ILS -# Copyright (C) 2019-2023 RERO +# Copyright (C) 2024 RERO # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by @@ -19,7 +19,6 @@ from __future__ import absolute_import, print_function -import copy import datetime import re @@ -321,78 +320,66 @@ def info(): """Get patron info.""" token_scopes = flask_request.oauth.access_token.scopes - def get_main_patron(patrons): - """Return the main patron. - - :param patrons: List of patrons. - :returns: The main patron. - """ - # TODO: Find a way to determine which is the main patron. - return patrons[0] - - def get_institution_code(institution): - """Get the institution code for a given institution. - - Special transformation for `nj`. - - :param institution: Institution object. - :returns: Code for the institution. - """ - # TODO: make this non rero specific using a configuration - return institution["code"] if institution["code"] != "nj" else "rbnj" - - user = User.get_record(current_user.id).dumps_metadata() - - # Process for all patrons - patrons = copy.deepcopy(current_patrons) - for patron in patrons: - patron["institution"] = patron.organisation - patron["patron"]["type"] = PatronType.get_record_by_pid( - extracted_data_from_ref(patron["patron"]["type"]["$ref"]) - ) - - # Birthdate - data = {} - birthdate = current_user.user_profile.get("birth_date") - if "birthdate" in token_scopes and birthdate: - data["birthdate"] = birthdate + data = {"user_id": current_user.id} # Full name name_parts = [ current_user.user_profile.get("last_name", "").strip(), current_user.user_profile.get("first_name", "").strip(), ] fullname = ", ".join(filter(None, name_parts)) - if "fullname" in token_scopes and fullname: + if fullname and "fullname" in token_scopes: data["fullname"] = fullname + birthdate = current_user.user_profile.get("birth_date") + # Birthdate + if birthdate and "birthdate" in token_scopes: + data["birthdate"] = birthdate - # No patrons found for user - if not patrons: - return jsonify(data) - - # Get the main patron - patron = get_main_patron(patrons) - # Barcode - if patron.get("patron", {}).get("barcode"): - data["barcode"] = patron["patron"]["barcode"][0] - # Patron types - if "patron_types" in token_scopes: - patron_types = [] - for patron in patrons: - info = {} - patron_type_code = patron.get("patron", {}).get("type", {}).get("code") - if patron_type_code: + patrons = current_patrons + if patrons: + patron = patrons[0] + # Barcode + if patron.get("patron", {}).get("barcode"): + data["barcode"] = patron["patron"]["barcode"][0] + # Patron + patron_types = [] + patron_infos = {} + for patron in patrons: + patron_type = PatronType.get_record_by_pid( + extracted_data_from_ref(patron["patron"]["type"]["$ref"]) + ) + patron_type_code = patron_type.get("code") + institution = patron.organisation["code"] + expiration_date = patron.get("patron", {}).get("expiration_date") + + # old list (patron_types) + if "patron_types" in token_scopes: + info = {"patron_pid": patron.pid} + if patron_type_code and "patron_type" in token_scopes: info["patron_type"] = patron_type_code - if patron.get("institution"): - info["institution"] = get_institution_code(patron["institution"]) - if patron.get("patron", {}).get("expiration_date"): + if institution and "institution" in token_scopes: + info["institution"] = institution + if expiration_date and "expiration_date" in token_scopes: info["expiration_date"] = datetime.datetime.strptime( - patron["patron"]["expiration_date"], "%Y-%m-%d" + expiration_date, "%Y-%m-%d" ).isoformat() - if info: - patron_types.append(info) - if patron_types: - data["patron_types"] = patron_types - + patron_types.append(info) + + # new dict (patron_info) + patron_info = {"patron_pid": patron.pid} + if institution and "institution" in token_scopes: + patron_info["institution"] = institution + if patron_type_code and "patron_type" in token_scopes: + patron_info["patron_type"] = patron_type_code + if expiration_date and "expiration_date" in token_scopes: + patron_info["expiration_date"] = datetime.datetime.strptime( + expiration_date, "%Y-%m-%d" + ).isoformat() + patron_infos[institution] = patron_info + + if patron_types: + data["patron_types"] = patron_types + if patron_infos: + data["patron_info"] = patron_infos return jsonify(data) diff --git a/rero_ils/oauth/scopes.py b/rero_ils/oauth/scopes.py index 93922c449c..cf7613245f 100644 --- a/rero_ils/oauth/scopes.py +++ b/rero_ils/oauth/scopes.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # RERO ILS -# Copyright (C) 2021 RERO +# Copyright (C) 2024 RERO # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by @@ -21,7 +21,9 @@ fullname = Scope("fullname", help_text="Full name", group="User") birthdate = Scope("birthdate", help_text="Birthdate", group="User") -institution = Scope("institution", help_text="Institution", group="User") expiration_date = Scope("expiration_date", help_text="Expiration date", group="User") +institution = Scope("institution", help_text="Institution", group="User") patron_type = Scope("patron_type", help_text="Patron type", group="User") -patron_types = Scope("patron_types", help_text="Patron types", group="User") +patron_types = Scope( + "patron_types", help_text="Patron types (deprecated)", group="User" +) diff --git a/setup.py b/setup.py index 0137a76b43..6f230d1983 100644 --- a/setup.py +++ b/setup.py @@ -370,10 +370,12 @@ def run(self): 'invenio_oauth2server.scopes': [ 'fullname = rero_ils.oauth.scopes:fullname', 'birthdate = rero_ils.oauth.scopes:birthdate', - 'institution = rero_ils.oauth.scopes:institution', + 'patron_info = rero_ils.oauth.scopes:patron_info', 'expiration_date = rero_ils.oauth.scopes:expiration_date', + 'institution = rero_ils.oauth.scopes:institution', 'patron_type = rero_ils.oauth.scopes:patron_type', - 'patron_types = rero_ils.oauth.scopes:patron_types' + # deprecated scopes + 'patron_types = rero_ils.oauth.scopes:patron_types', ] }, classifiers=[ diff --git a/tests/api/patrons/test_patrons_rest.py b/tests/api/patrons/test_patrons_rest.py index 855e9de4f5..7e48bbd70c 100644 --- a/tests/api/patrons/test_patrons_rest.py +++ b/tests/api/patrons/test_patrons_rest.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # RERO ILS -# Copyright (C) 2019 RERO +# Copyright (C) 2024 RERO # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by @@ -545,13 +545,19 @@ def test_patron_info(app, client, patron_martigny, librarian_martigny): url_for("api_patrons.info", access_token=no_scope_token.access_token) ) assert res.status_code == 200 - assert res.json == {"barcode": patron_martigny["patron"]["barcode"].pop()} + barcode = patron_martigny["patron"]["barcode"].pop() + assert res.json == { + "barcode": barcode, + "user_id": patron_martigny.user.id, + "patron_info": {"org1": {"patron_pid": patron_martigny.pid}}, + } # full information with all scopes res = client.get(url_for("api_patrons.info", access_token=token.access_token)) assert res.status_code == 200 assert res.json == { - "barcode": "4098124352", + "barcode": barcode, + "user_id": patron_martigny.user.id, "birthdate": "1947-06-07", "fullname": "Roduit, Louis", "patron_types": [ @@ -559,9 +565,19 @@ def test_patron_info(app, client, patron_martigny, librarian_martigny): "expiration_date": patron_martigny["patron"]["expiration_date"] + "T00:00:00", "institution": "org1", + "patron_pid": patron_martigny.pid, "patron_type": "patron-code", } ], + "patron_info": { + "org1": { + "expiration_date": patron_martigny["patron"]["expiration_date"] + + "T00:00:00", + "institution": "org1", + "patron_pid": patron_martigny.pid, + "patron_type": "patron-code", + } + }, } # librarian information with all scopes @@ -569,7 +585,11 @@ def test_patron_info(app, client, patron_martigny, librarian_martigny): url_for("api_patrons.info", access_token=librarian_token.access_token) ) assert res.status_code == 200 - assert res.json == {"birthdate": "1965-02-07", "fullname": "Pedronni, Marie"} + assert res.json == { + "birthdate": "1965-02-07", + "fullname": "Pedronni, Marie", + "user_id": librarian_martigny.user.id, + } def test_patrons_search(client, librarian_martigny):