Skip to content

Commit

Permalink
logging: add user information to sentry
Browse files Browse the repository at this point in the history
* Closes: #2734.

Co-Authored-by: Peter Weber <[email protected]>
  • Loading branch information
rerowep committed Nov 13, 2024
1 parent 1fdc0fb commit 0c72f8d
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 32 deletions.
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
# -- General configuration ------------------------------------------------

# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# needs_sphinx = '1.0'

# Do not warn on external images.
suppress_warnings = ['image.nonlocal_uri']
Expand Down
5 changes: 5 additions & 0 deletions rero_ils/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3458,6 +3458,11 @@ def _(x):
LOGGING_SENTRY_LEVEL = "ERROR"
#: Sentry: use celery or not
LOGGING_SENTRY_CELERY = True
# Invenio logging
LOGGING_SENTRY_INIT_KWARGS = {
# instuct sentry to send user data attached to the event
"send_default_pii": True
}

ROLLOVER_LOGGING_CONFIG = {
"version": 1,
Expand Down
9 changes: 2 additions & 7 deletions rero_ils/modules/patrons/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
from rero_ils.modules.providers import Provider
from rero_ils.modules.tasks import process_bulk_queue
from rero_ils.modules.templates.api import TemplatesSearch
from rero_ils.modules.users.api import User
from rero_ils.modules.users.api import User, user_formatted_name
from rero_ils.modules.users.models import UserRole
from rero_ils.modules.utils import (
extracted_data_from_ref,
Expand Down Expand Up @@ -768,12 +768,7 @@ def is_expired(self):
@property
def formatted_name(self):
"""Return the best possible human-readable patron name."""
profile = self.user.user_profile
name_parts = [
profile.get("last_name", "").strip(),
profile.get("first_name", "").strip(),
]
return ", ".join(filter(None, name_parts))
return user_formatted_name(self.user)

@property
def patron_type_pid(self):
Expand Down
6 changes: 3 additions & 3 deletions rero_ils/modules/patrons/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def create_user_from_data(data, send_email=False):
"""Create a user and set the profile fields from a data.
:param data: A dict containing a mix of patron and user data.
:param send_email - send the reset password email to the user
:param send_email: send the reset password email to the user
:returns: The modified dict.
"""
user = User.get_by_username(data.get("username"))
Expand All @@ -94,8 +94,8 @@ def create_user_from_data(data, send_email=False):
def create_patron_from_data(data, dbcommit=True, reindex=True, send_email=False):
"""Create a patron and a user from a data dict.
:param data - dictionary representing a library user
:param send_email - send the reset password email to the user
:param data: dictionary representing a library user
:param send_email: send the reset password email to the user
:returns: - A `Patron` instance
"""
from .api import Patron
Expand Down
23 changes: 23 additions & 0 deletions rero_ils/modules/users/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,20 @@ def password_validator(password):
)


def user_formatted_name(base_user):
"""Formatted name from user profile.
:param user: user to use.
:returns: formatted name.
"""
profile = base_user.user_profile
name_parts = [
profile.get("last_name", "").strip(),
profile.get("first_name", "").strip(),
]
return ", ".join(filter(None, name_parts))


class User(object):
"""User API."""

Expand Down Expand Up @@ -282,3 +296,12 @@ def get_by_username_or_email(cls, username_or_email):
"""
user = cls.get_by_email(username_or_email)
return user or cls.get_by_username(username_or_email)

@property
def formatted_name(self):
"""Formatted name from user profile.
:param user: user to use.
:returns: formatted name.
"""
return user_formatted_name(self.user)
22 changes: 11 additions & 11 deletions rero_ils/modules/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
from flask import current_app, session
from flask_babel import gettext as _
from flask_babel import ngettext
from flask_login import current_user
from invenio_accounts.models import Role
from invenio_cache import current_cache
from invenio_pidstore.models import PersistentIdentifier
Expand Down Expand Up @@ -1087,20 +1086,21 @@ def close(self):

def set_user_name(sender, user):
"""Set the username in the current flask session."""
from .patrons.api import current_librarian, current_patrons
from rero_ils.modules.users.api import user_formatted_name

user_name = None
remove_user_name(sender, user)

if current_librarian:
user_name = current_librarian.formatted_name
elif current_patrons:
user_name = current_patrons[0].formatted_name
user_email = None
with contextlib.suppress(AttributeError):
user_email = user.email

# set session user name
if full_name := user_formatted_name(user):
session["user_name"] = full_name
elif user_email:
session["user_name"] = user_email
else:
with contextlib.suppress(AttributeError):
user_name = current_user.email
if user_name:
session["user_name"] = user_name
session["user_name"] = user.username


def remove_user_name(sender, user):
Expand Down
27 changes: 23 additions & 4 deletions tests/ui/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,38 @@ def user_with_profile(db, default_user_password):


@pytest.fixture(scope="function")
def user_without_email(db, default_user_password):
def user_without_name_email(db, default_user_password):
"""Create a simple invenio user without email."""
with db.session.begin_nested():
profile = dict(
birth_date="1990-01-01",
first_name="User",
last_name="With Profile",
city="Nowhere",
)
user = User(
password=hash_password(default_user_password),
user_profile=profile,
username="user_without_email",
username="user_without_name_email",
active=True,
)
db.session.add(user)
db.session.commit()
user.password_plaintext = default_user_password
return user


@pytest.fixture(scope="function")
def user_without_name(db, default_user_password):
"""Create a simple invenio user without nmae."""
with db.session.begin_nested():
profile = dict(
birth_date="1990-01-01",
city="Nowhere",
)
user = User(
password=hash_password(default_user_password),
user_profile=profile,
username="user_without_name",
email="[email protected]",
active=True,
)
db.session.add(user)
Expand Down
23 changes: 17 additions & 6 deletions tests/ui/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from flask_login import login_user, logout_user
from utils import postdata

from rero_ils.modules.users.api import formatted_name
from rero_ils.theme.views import nl2br


Expand Down Expand Up @@ -135,20 +136,30 @@ def test_language(client, app):


def test_set_user_name(
app, librarian_martigny, patron_martigny, user_with_profile, user_without_email
app,
librarian_martigny,
patron_martigny,
user_with_profile,
user_without_name,
user_without_name_email,
):
"""Test the user_name in the flask session."""
# should be the email address
# should be the formatted name
login_user(user=user_with_profile)
assert "user_name" in session
assert session["user_name"] == user_with_profile.email
assert session["user_name"] == formatted_name(user_with_profile)
# should be removed
logout_user()
assert "user_name" not in session

# should not be set
login_user(user=user_without_email)
assert "user_name" not in session
# should be the email
login_user(user=user_without_name)
assert session["user_name"] == user_without_name.email
logout_user()

# should be the user.username
login_user(user=user_without_name_email)
assert session["user_name"] == user_without_name_email.username
logout_user()

# should be the formatted name
Expand Down

0 comments on commit 0c72f8d

Please sign in to comment.