flask_more_smorest.perms.models.abstract_user

Abstract User model for Flask-More-Smorest authentication system.

Provides abstract base for User models with email/password auth, roles, settings, and tokens. This is an abstract model - no table is created. Inherit from this to create concrete User models.

Classes

AbstractUser(**kwargs)

Abstract User model with email/password auth, roles, and domain support.

class flask_more_smorest.perms.models.abstract_user.AbstractUser(**kwargs)[source]

Abstract User model with email/password auth, roles, and domain support.

This is an abstract base class - it does NOT create a database table. Subclasses must define concrete fields and table configuration.

Features (all inherited): - Email/password authentication - Roles management via UserRole relationship - Settings management via UserSetting relationship - Token management via Token relationship - Permission checks (_can_read, _can_write, _can_create) - Admin properties (is_admin, is_superadmin) - Role checking (has_role, list_roles)

Subclassing example:

from flask_more_smorest.perms import AbstractUser, init_fms

class CustomUser(AbstractUser):
    # Optional: custom fields only
    bio: Mapped[str | None] = mapped_column(sa.String(500))

    def _can_write(self, user) -> bool:
        return super()._can_write(user)

# Register with the system
init_fms(user=CustomUser)
email: Mapped[str] = <sqlalchemy.orm.properties.MappedColumn object>
password: Mapped[bytes | None] = <sqlalchemy.orm.properties.MappedColumn object>
is_enabled: Mapped[bool] = <sqlalchemy.orm.properties.MappedColumn object>
roles = <_RelationshipDeclared at 0x7a2d7b446710; no key>
settings = <_RelationshipDeclared at 0x7a2d7b446e90; no key>
tokens = <_RelationshipDeclared at 0x7a2d7b444550; no key>
__init__(**kwargs)[source]

Create new user with optional password hashing.

classmethod get_current_user()[source]

Get the current authenticated user of this User subclass.

This provides zero-boilerplate typed access to the current user. Uses the application’s configured authentication (JWT or custom getter).

Return type:

Optional[TypeVar(UserT, bound= AbstractUser)]

Returns:

Current user instance of this User subclass if authenticated, None otherwise

Example

>>> user = AbstractUser.get_current_user()
>>> user = MyCustomUser.get_current_user()
normalize_email(email)[source]

Normalize email to lowercase for case-insensitive lookups.

Emails are automatically converted to lowercase when set, ensuring: - Case-insensitive login (user@example.com == USER@EXAMPLE.COM) - Prevention of duplicate registrations with different cases - Efficient database queries using the email index - Consistent email storage throughout the application

Parameters:

email (str | None) – Email address to normalize

Return type:

str | None

Returns:

Lowercase email address, or None if email is None

set_password(password)[source]

Set password with secure hashing.

Return type:

None

is_password_correct(password)[source]

Check if provided password matches stored hash.

Return type:

bool

update(commit=True, **kwargs)[source]

Update user with password handling.

Return type:

None

property is_admin: bool

Check if user has admin privileges.

property is_superadmin: bool

Check if user has superadmin privileges.

has_role(role, domain_name=None)[source]

Check if user has specified role, optionally scoped to domain.

Parameters:
  • role (Union[Literal['ADMIN', 'SUPERADMIN'], str, Enum]) – Role to check (string or enum value)

  • domain_name (str | None) – Optional domain name to scope the check

Return type:

bool

Returns:

True if user has the role, False otherwise

Example

>>> user.has_role("ADMIN")
True
>>> user.has_role("ADMIN", domain_name="main")
True
list_roles()[source]

List user roles as strings.

Return type:

list[str]

property num_tokens: int

Get number of tokens for this user.

property domain_ids: set[UUID | str]

Return set of domain IDs the user has roles for.

has_domain_access(domain_id)[source]

Check if user has access to a specific domain.

Users have access to a domain if they have any role associated with that domain, or if they have a wildcard role (*). Superadmins automatically have access.

Parameters:

domain_id (UUID | None) – Domain UUID to check access for, or None for global access

Return type:

bool

Returns:

True if user has access to the domain, False otherwise

Example

>>> user.has_domain_access(domain_id)
True
>>> user.has_domain_access(None)  # Global access check
True