diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 3286e8521f..33f39fd454 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -10,6 +10,7 @@ This is built on the Jupyter Notebook v6.4.12 and IPython 8.5.0 (more notes will - PTV-1810 - address object name display issues in the View Configure tab of app cells. This now saves all app inputs as UPAs in the cell. It also includes an update to input transforms to properly convert from UPAs <-> names or references as appropriate before starting the app. - PTV-1877 - fix app descriptions to replace the documentation link for the upload / download guide - PTV-1878 - fix some failing front end unit tests +- UIP-36 - add support for anonymous user ids sent to Google Analytics ### Dependency Changes diff --git a/kbase-extension/kbase_templates/page.html b/kbase-extension/kbase_templates/page.html index ee7ff78436..dd4a349214 100644 --- a/kbase-extension/kbase_templates/page.html +++ b/kbase-extension/kbase_templates/page.html @@ -44,12 +44,12 @@ function gtag() { dataLayer.push(arguments); } gtag('js', new Date()); gtag('config', '{{google_analytics_id}}', { - 'username': '{{userName}}', + 'username': '{{anon_user_id}}', 'Page_location': document.location, 'page_path': document.location.pathname, 'page_title': document.location.pathname }); - gtag('set', {'user_id': '{{userName}}'}); + gtag('set', {'user_id': '{{anon_user_id}}'}); {% if google_ad_id %} gtag('config', '{{google_ad_id}}'); gtag('event', 'conversion', {'send_to': '{{google_ad_id}}'+'{{google_ad_conversion}}'}); diff --git a/src/biokbase/auth.py b/src/biokbase/auth.py index 5029e86cdc..12a229c0ed 100644 --- a/src/biokbase/auth.py +++ b/src/biokbase/auth.py @@ -101,7 +101,7 @@ def get_token_info(token: str) -> TokenInfo: return token_info -def init_session_env(token_info: TokenInfo, ip: str) -> None: +def init_session_env(token_info: TokenInfo, user_info: UserInfo, ip: str) -> None: """ Initializes the internal session environment. Parameters: @@ -111,6 +111,7 @@ def init_session_env(token_info: TokenInfo, ip: str) -> None: set_environ_token(token_info.token) kbase_env.session = token_info.id kbase_env.user = token_info.user_name + kbase_env.anon_user_id = user_info.anon_user_id kbase_env.client_ip = ip diff --git a/src/biokbase/narrative/common/util.py b/src/biokbase/narrative/common/util.py index 9e09ef29b6..3540a63009 100644 --- a/src/biokbase/narrative/common/util.py +++ b/src/biokbase/narrative/common/util.py @@ -32,6 +32,7 @@ class _KBaseEnv: env_workspace = "KB_WORKSPACE_ID" env_user = "KB_USER_ID" env_env = "KB_ENVIRONMENT" + env_anon_user_id = "KB_ANON_USER_ID" _defaults = { "auth_token": "none", @@ -41,6 +42,7 @@ class _KBaseEnv: "user": "anonymous", "workspace": "none", "env": "none", + "anon_user_id": "none", } def __getattr__(self, name): diff --git a/src/biokbase/narrative/handlers/authhandlers.py b/src/biokbase/narrative/handlers/authhandlers.py index 09eed3f7b4..26ecb92b7f 100644 --- a/src/biokbase/narrative/handlers/authhandlers.py +++ b/src/biokbase/narrative/handlers/authhandlers.py @@ -7,7 +7,12 @@ from notebook.auth.logout import LogoutHandler from traitlets.config import Application -from biokbase.auth import get_token_info, init_session_env, set_environ_token +from biokbase.auth import ( + get_token_info, + get_user_info, + init_session_env, + set_environ_token, +) from biokbase.narrative.common.kblogging import get_logger, log_event from biokbase.narrative.common.util import kbase_env @@ -52,7 +57,8 @@ def get(self): if auth_cookie: token = urllib.parse.unquote(auth_cookie.value) try: - token_info = get_token_info(token) + auth_info = get_token_info(token) + user_info = get_user_info(token) except Exception: app_log.error( "Unable to get user information from authentication token!" @@ -65,7 +71,7 @@ def get(self): # app_log.debug("KBaseLoginHandler.get: user_id={uid} token={tok}" # .format(uid=token_info.get('user', 'none'), # tok=token)) - init_session_env(token_info, client_ip) + init_session_env(auth_info, user_info, client_ip) self.current_user = kbase_env.user log_event( g_log, "session_start", {"user": kbase_env.user, "user_agent": ua} @@ -99,7 +105,10 @@ def password_from_settings(cls, settings): @classmethod def login_available(cls, settings): - """Whether this LoginHandler is needed - and therefore whether the login page should be displayed.""" + """ + Whether this LoginHandler is needed - and therefore whether the login page should be + displayed. + """ return True diff --git a/src/biokbase/narrative/handlers/narrativehandler.py b/src/biokbase/narrative/handlers/narrativehandler.py index 7bd5d82864..c690befd19 100644 --- a/src/biokbase/narrative/handlers/narrativehandler.py +++ b/src/biokbase/narrative/handlers/narrativehandler.py @@ -6,7 +6,7 @@ from tornado import web from traitlets.config import Application -from biokbase.auth import get_token_info, init_session_env +from biokbase.auth import get_token_info, get_user_info, init_session_env from biokbase.narrative.common.kblogging import get_logger, log_event from biokbase.narrative.common.url_config import URLS from biokbase.narrative.common.util import kbase_env @@ -35,7 +35,7 @@ def _init_session(request, cookies): reason="Authorization required for Narrative access", ) if token != kbase_env.auth_token: - init_session_env(get_token_info(token), client_ip) + init_session_env(get_token_info(token), get_user_info(token), client_ip) log_event(g_log, "session_start", {"user": kbase_env.user, "user_agent": ua}) @@ -83,7 +83,7 @@ def get(self, path): kill_kernel=False, mathjax_url=self.mathjax_url, google_analytics_id=URLS.google_analytics_id, - userName=kbase_env.user, + anon_user_id=kbase_env.anon_user_id, google_ad_id=URLS.google_ad_id, google_ad_conversion=URLS.google_ad_conversion, ) diff --git a/src/biokbase/narrative/system.py b/src/biokbase/narrative/system.py index 963e8548d1..039156036f 100644 --- a/src/biokbase/narrative/system.py +++ b/src/biokbase/narrative/system.py @@ -2,8 +2,8 @@ import time from typing import Union -import biokbase.auth import biokbase.narrative.clients as clients +from biokbase.auth import get_auth_token, get_user_info def strict_system_variable(var: str) -> Union[str, int]: @@ -49,12 +49,12 @@ def system_variable(var: str) -> Union[str, int, None]: except Exception: return None elif var == "user_id": - token = biokbase.auth.get_auth_token() + token = get_auth_token() if token is None: return None try: - user_info = biokbase.auth.get_user_info(token) - return user_info.get("user") + user_info = get_user_info(token) + return user_info.user_name except Exception: return None # TODO: make this better with more exception handling. diff --git a/src/biokbase/narrative/tests/test_auth.py b/src/biokbase/narrative/tests/test_auth.py index 23102637de..040c2d4614 100644 --- a/src/biokbase/narrative/tests/test_auth.py +++ b/src/biokbase/narrative/tests/test_auth.py @@ -6,6 +6,7 @@ from biokbase.auth import ( TokenInfo, + UserInfo, get_agent_token, get_auth_token, get_display_names, @@ -144,14 +145,17 @@ def test_init_session_env(): ip = "127.0.0.1" token_id = "some-token-id" user = "kbase_user" + anonymous_id = "some_anon_id" token_info = TokenInfo({"id": token_id, "user": user}, token=token) - init_session_env(token_info, ip) + user_info = UserInfo({"user": user, "anonid": anonymous_id}) + init_session_env(token_info, user_info, ip) assert get_auth_token() == token assert kbase_env.session == token_info.id assert kbase_env.user == token_info.user_name assert kbase_env.client_ip == ip - init_session_env(TokenInfo({}), None) + assert kbase_env.anon_user_id == anonymous_id + init_session_env(TokenInfo({}), UserInfo({}), None) def test_get_agent_token_ok(mock_token_endpoint): diff --git a/src/biokbase/narrative/tests/test_system.py b/src/biokbase/narrative/tests/test_system.py index 5f9ec26f5b..bf71543a90 100644 --- a/src/biokbase/narrative/tests/test_system.py +++ b/src/biokbase/narrative/tests/test_system.py @@ -1,15 +1,15 @@ import os -import biokbase.auth -from unittest import mock -from biokbase.narrative.system import ( - strict_system_variable, - system_variable -) -from .narrative_mock.mockclients import get_mock_client import time -from . import util +from unittest import mock + import pytest +import biokbase.auth +from biokbase.narrative.system import strict_system_variable, system_variable + +from . import util +from .narrative_mock.mockclients import get_mock_client + user_token = "SOME_TOKEN" config = util.ConfigTests() user_id = config.get("users", "test_user") @@ -82,9 +82,11 @@ def test_strict_sys_var_user_ok(): if user_token: biokbase.auth.set_environ_token(user_token) assert strict_system_variable("user_id") == user_id + biokbase.auth.set_environ_token(None) def test_strict_sys_var_user_bad(): biokbase.auth.set_environ_token(bad_fake_token) with pytest.raises(ValueError, match='Unable to retrieve system variable: "user_id"') as e: strict_system_variable("user_id") assert e + biokbase.auth.set_environ_token(None)