Coverage for webapp / decorators.py: 91%
32 statements
« prev ^ index » next coverage.py v7.13.1, created at 2025-12-29 22:06 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2025-12-29 22:06 +0000
1# Core packages
2import functools
3import logging
4from datetime import datetime, timezone
6# Third party packages
7import flask
9from canonicalwebteam.store_api.publishergw import PublisherGW
11from webapp import authentication
12from webapp.helpers import api_publisher_session
14publisher_gateway = PublisherGW(api_publisher_session)
15logger = logging.getLogger(__name__)
18def login_required(func):
19 """
20 Decorator that checks if a user is logged in, and redirects
21 to login page if not.
22 """
24 @functools.wraps(func)
25 def is_user_logged_in(*args, **kwargs):
26 date = datetime.now(timezone.utc)
27 date_str = date.strftime("%Y-%m-%dT%H:%M:%S")
29 if not authentication.is_authenticated(flask.session):
30 authentication.empty_session(flask.session)
32 logger.warning(
33 "User login failed",
34 extra={
35 "datetime": date_str,
36 "appid": "snapcraft-io",
37 "event": "authn_login_fail",
38 },
39 )
41 return flask.redirect(f"/login?next={flask.request.path}")
43 publisher = flask.session.get("publisher")
44 user = publisher["email"]
46 logger.info(
47 f"User {user} login successfully",
48 extra={
49 "datetime": date_str,
50 "appid": "snapcraft-io",
51 "event": f"authn_login_successafterfail:{user}",
52 },
53 )
55 return func(*args, **kwargs)
57 return is_user_logged_in
60def exchange_required(func):
61 @functools.wraps(func)
62 def is_exchanged(*args, **kwargs):
63 if "exchanged_developer_token" not in flask.session:
64 result = publisher_gateway.exchange_dashboard_macaroons(
65 flask.session
66 )
67 flask.session["developer_token"] = result
68 flask.session["exchanged_developer_token"] = True
69 return func(*args, **kwargs)
71 return is_exchanged