Source code for gamesheet_sdk.common.auth.credentials
# Copyright (c) 2026 bdperkin
# SPDX-License-Identifier: MIT
"""Credential resolution for login flows.
Provides helpers that resolve an email address and password from explicit arguments, environment variables
(via :class:`~gamesheet_sdk.common.config.Config`), or interactive prompts. Both
:mod:`~gamesheet_sdk.common.auth.login` (admin) and :mod:`~gamesheet_sdk.teams.login` (teams) delegate to
these functions so the fallback logic lives in one place.
The two resolvers are intentionally kept as separate functions — bundling email and password into a shared
return value trips CodeQL's data-flow analyzer into flagging downstream ``email`` log calls as clear-text
password logging.
"""
from __future__ import annotations
from gamesheet_sdk.common.config import Config
from gamesheet_sdk.common.exceptions import AuthenticationError
[docs]
def resolve_email(cfg: Config, email: str | None) -> str:
"""Resolve the login email from explicit argument or config.
Falls through: explicit ``email`` argument → ``GAMESHEET_USERNAME``
env var → ``Config.username``.
:param cfg: Configuration object containing username from env/defaults.
:type cfg: Config
:param email: Explicit email address, or ``None`` to fall back to config.
:type email: str | None
:returns: The resolved email address.
:rtype: str
:raises AuthenticationError: If no email is available from any source.
"""
if email is None:
email = cfg.username
if not email:
_err_msg = "Login requires an email. Pass it explicitly or set GAMESHEET_USERNAME."
raise AuthenticationError(_err_msg)
return email
[docs]
def resolve_password(cfg: Config, password: str | None) -> str:
"""Resolve the login password from explicit argument or config.
Falls through: explicit ``password`` argument → ``GAMESHEET_PASSWORD``
env var → ``Config.password``.
:param cfg: Configuration object containing password from env/defaults.
:type cfg: Config
:param password: Explicit password, or ``None`` to fall back to config.
:type password: str | None
:returns: The resolved password string.
:rtype: str
:raises AuthenticationError: If no password is available from any source.
"""
if password is None and cfg.password is not None:
password = cfg.password.get_secret_value()
if not password:
_err_msg = "Login requires a password. Pass it explicitly or set GAMESHEET_PASSWORD."
raise AuthenticationError(_err_msg)
return password