from typing import Optional, Tuple from ..logging import log from ..utils import agetpass, ainput from .authenticator import Authenticator, AuthError, AuthSection class SimpleAuthSection(AuthSection): def username(self) -> Optional[str]: return self.s.get("username") def password(self) -> Optional[str]: return self.s.get("password") class SimpleAuthenticator(Authenticator): def __init__(self, name: str, section: SimpleAuthSection) -> None: super().__init__(name) self._username = section.username() self._password = section.password() self._username_fixed = self.username is not None self._password_fixed = self.password is not None async def credentials(self) -> Tuple[str, str]: if self._username is not None and self._password is not None: return self._username, self._password async with log.exclusive_output(): if self._username is None: self._username = await ainput("Username: ") else: print(f"Username: {self._username}") if self._password is None: self._password = await agetpass("Password: ") # Intentionally returned inside the context manager so we know # they're both not None return self._username, self._password def invalidate_credentials(self) -> None: if self._username_fixed and self._password_fixed: raise AuthError("Configured credentials are invalid") if not self._username_fixed: self._username = None if not self._password_fixed: self._password = None def invalidate_username(self) -> None: if self._username_fixed: raise AuthError("Configured username is invalid") else: self._username = None def invalidate_password(self) -> None: if self._password_fixed: raise AuthError("Configured password is invalid") else: self._password = None