Source code for dapla_metadata.dapla.user_info
from __future__ import annotations
import contextlib
import logging
from typing import Protocol
import jwt
from dapla_metadata._shared import config
from dapla_metadata._shared.enums import DaplaRegion
logger = logging.getLogger(__name__)
[docs]
class UserInfo(Protocol):
"""Information about the current user.
Implementations may be provided for different platforms or testing.
"""
@property
def short_email(self) -> str | None:
"""Get the short email address."""
...
@property
def current_group(self) -> str:
"""Get the group which the user is currently representing."""
...
@property
def current_team(self) -> str:
"""Get the team which the user is currently representing."""
...
[docs]
class UnknownUserInfo:
"""Fallback when no implementation is found."""
@property
def short_email(self) -> str | None:
"""Unknown email address."""
return None
@property
def current_group(self) -> str:
"""Get the group which the user is currently representing."""
return ""
@property
def current_team(self) -> str:
"""Get the team which the user is currently representing."""
return ""
[docs]
class TestUserInfo:
"""Information about the current user for local development and testing."""
PLACEHOLDER_EMAIL_ADDRESS = "default_user@ssb.no"
PLACEHOLDER_GROUP = "default-team-developers"
PLACEHOLDER_TEAM = "default-team"
@property
def short_email(self) -> str | None:
"""Get the short email address."""
return TestUserInfo.PLACEHOLDER_EMAIL_ADDRESS
@property
def current_group(self) -> str | None:
"""Get the group which the user is currently representing."""
return TestUserInfo.PLACEHOLDER_GROUP
@property
def current_team(self) -> str | None:
"""Get the team which the user is currently representing."""
return TestUserInfo.PLACEHOLDER_TEAM
[docs]
class DaplaLabUserInfo:
"""Information about the current user when running on Dapla Lab."""
@property
def short_email(self) -> str | None:
"""Get the short email address."""
encoded_jwt = config.get_oidc_token()
if encoded_jwt:
# The JWT has been verified by the platform prior to injection, no need to verify.
decoded_jwt = jwt.decode(encoded_jwt, options={"verify_signature": False})
with contextlib.suppress(KeyError):
# If email can't be found in the JWT, fall through and return None
return decoded_jwt["email"]
logger.warning(
"Could not access JWT from environment. Could not get short email address.",
)
return None
@property
def current_group(self) -> str:
"""Get the group which the user is currently representing."""
if group := config.get_dapla_group_context():
return group
msg = "DAPLA_GROUP_CONTEXT environment variable not found"
raise OSError(msg)
@property
def current_team(self) -> str:
"""Get the team which the user is currently representing."""
return parse_team_name(self.current_group)
[docs]
def parse_team_name(group: str) -> str:
"""Parses the group to get the current team.
>>> parse_team_name("dapla-metadata-developers")
'dapla-metadata'
>>> parse_team_name("dapla-metadata-data-admins")
'dapla-metadata'
>>> parse_team_name("dapla-metadata")
'dapla'
>>> parse_team_name("dapla-metadata-not-real-name")
'dapla-metadata-not-real'
"""
parts = group.split("-")
return "-".join(parts[:-2] if group.endswith("data-admins") else parts[:-1])