Source code for globus_sdk.local_endpoint.personal.owner_info
from __future__ import annotations
import base64
import shlex
import uuid
class _B32DecodeError(ValueError):
"""custom exception type"""
def _b32decode(v: str) -> str:
# should start with "u_"
if not v.startswith("u_"):
raise _B32DecodeError("should start with 'u_'")
v = v[2:]
# wrong length
if len(v) != 26:
raise _B32DecodeError("wrong length")
# append padding and uppercase so that b32decode will work
v = v.upper() + (6 * "=")
# try to decode
try:
return str(uuid.UUID(bytes=base64.b32decode(v)))
# if it fails, then it can't be a b32-encoded identity
except ValueError as err:
raise _B32DecodeError("decode and load as UUID failed") from err
def _parse_dn_username(s: str) -> tuple[str, bool]:
try:
user, is_id = _b32decode(s), True
except _B32DecodeError:
user, is_id = f"{s}@globusid.org", False
return (user, is_id)
[docs]
class GlobusConnectPersonalOwnerInfo:
"""
Information about the owner of the local Globus Connect Personal endpoint.
Users should never create these objects directly, but instead rely upon
:meth:`LocalGlobusConnectPersonal.get_owner_info()`.
The info object contains ether ``id`` or ``username``.
Parsing an info object from local data cannot guarantee that the ``id`` or
``username`` value will be found. Whichever one is present will be set and the
other attribute will be ``None``.
:ivar id: The Globus Auth ID of the endpoint owner
:vartype id: str or None
:ivar username: The Globus Auth Username of the endpoint owner
:vartype username: str or None
:param config_dn: A DN value from GCP configuration, which will be parsed into
username or ID
"""
_GRIDMAP_DN_START = '"/C=US/O=Globus Consortium/OU=Globus Connect User/CN='
username: str | None
id: str | None
def __init__(self, *, config_dn: str) -> None:
lineinfo = shlex.split(config_dn)
if len(lineinfo) != 2:
raise ValueError("Malformed DN: not right length")
dn, _local_username = lineinfo
username_or_id = dn.split("=", 4)[-1]
user, is_id = _parse_dn_username(username_or_id)
if is_id:
self.username = None
self.id = user
else:
self.username = user
self.id = None
def __str__(self) -> str:
return (
"GlobusConnectPersonalOwnerInfo("
+ (
f"username={self.username}"
if self.username is not None
else f"id={self.id}"
)
+ ")"
)
# private methods for SDK usage only
@classmethod
def _from_file(cls, filename: str) -> GlobusConnectPersonalOwnerInfo:
with open(filename, encoding="utf-8") as fp:
for line in fp:
if line.startswith(cls._GRIDMAP_DN_START):
return cls(config_dn=line.strip())
raise ValueError("Could not find GCP DN in data stream")