Source code for qcportal.auth.models

from enum import Enum

from pydantic import BaseModel, Field, field_validator, ConfigDict

from ..common_types import Max128Str
from ..exceptions import InvalidPasswordError, InvalidUsernameError, InvalidGroupnameError


[docs] class AuthTypeEnum(str, Enum): password = "password"
[docs] def is_valid_password(password: str) -> None: # Null character not allowed if "\x00" in password: raise InvalidPasswordError("Password contains a NUL character") # Password should be somewhat long if len(password) == 0: raise InvalidPasswordError("Password is empty") if len(password) < 6: raise InvalidPasswordError("Password must contain at least 6 characters")
[docs] def is_valid_username(username: str) -> None: if len(username) == 0: raise InvalidUsernameError("Username is empty") # Null character not allowed if "\x00" in username: raise InvalidUsernameError("Username contains a NUL character") # Spaces are not allowed if " " in username: raise InvalidUsernameError("Username contains spaces") # Username cannot be all numbers if username.isdecimal(): raise InvalidUsernameError("Username cannot be all numbers")
[docs] def is_valid_groupname(groupname: str) -> None: if len(groupname) == 0: raise InvalidGroupnameError("Groupname is empty") # Null character not allowed if "\x00" in groupname: raise InvalidGroupnameError("Groupname contains a NUL character") # Spaces are not allowed if " " in groupname: raise InvalidGroupnameError("Groupname contains spaces") # Groupname cannot be all numbers if groupname.isdecimal(): raise InvalidGroupnameError("Groupname cannot be all numbers")
[docs] class GroupInfo(BaseModel): """ Information about a group """ id: int | None = None """ID of the group""" groupname: str """The name of the group""" description: str = "" """Text description of the group""" model_config = ConfigDict(extra="forbid", use_attribute_docstrings=True) @field_validator("groupname", mode="before") @classmethod def _valid_groupname(cls, v): """Makes sure the groupname is a valid string""" try: is_valid_groupname(v) return v except Exception as e: raise ValueError(str(e))
[docs] class UserInfo(BaseModel): """ Information about a user """ # id may be None when used for initial creation id: int | None = Field(None, frozen=True) """The id of the user""" auth_type: AuthTypeEnum = Field(AuthTypeEnum.password, frozen=True) """Type of authentication the user uses""" username: str = Field(..., frozen=True) """The username of this user""" role: str """The role this user belongs to""" groups: list[str] = [] """Groups this user belongs to""" enabled: bool """Whether this user is enabled or not""" fullname: Max128Str = "" """The full name or description of the user""" organization: Max128Str = "" """The organization the user belongs to""" email: Max128Str = "" """The email address for the user""" model_config = ConfigDict(extra="forbid", use_attribute_docstrings=True) @field_validator("username", mode="before") @classmethod def _valid_username(cls, v): """Makes sure the username is a valid string""" try: is_valid_username(v) return v except Exception as e: raise ValueError(str(e)) @field_validator("groups", mode="after") @classmethod def _valid_groupnames(cls, v): """Makes sure the groupnames are valid strings""" try: for x in v: is_valid_groupname(x) return v except Exception as e: raise ValueError(str(e))