Source code for genro_asgi.session.avatar

# Copyright 2025 Softwell S.r.l.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Avatar — the ONE authenticated identity type across the package.

An ``Avatar`` is a plain slotted value object: an identity string, its
authorization tags, and an extensible ``Bag`` of per-user data. ``AuthCore``
returns it and sessions carry it — "nobody" is ``None`` uniformly, never an
anonymous Avatar. The constructor normalizes ``tags=None`` to an empty list
(the identity boundary for e.g. a JWT null tags claim). No framework machinery.
"""

from __future__ import annotations

from genro_bag import Bag

__all__ = ["Avatar"]


[docs] class Avatar: """User identity with authorization tags and extensible Bag data.""" __slots__ = ("_identity", "_tags", "_data")
[docs] def __init__(self, identity: str, tags: list[str] | None = None) -> None: """Build the avatar; ``tags=None`` normalizes to an empty list.""" self._identity = identity self._tags = list(tags) if tags else [] self._data = Bag()
@property def identity(self) -> str: """User identifier (username, email, ...).""" return self._identity @property def tags(self) -> list[str]: """Authorization tags (roles/permissions).""" return self._tags @property def data(self) -> Bag: """Extensible per-user data as a Bag.""" return self._data
if __name__ == "__main__": explicit = Avatar("alice", ["admin"]) assert explicit.identity == "alice" assert explicit.tags == ["admin"] normalized = Avatar("bob", None) assert normalized.tags == []