core/homeassistant/auth/models.py

125 lines
3.8 KiB
Python
Raw Normal View History

2018-07-13 09:43:08 +00:00
"""Auth models."""
from datetime import datetime, timedelta
from typing import Dict, List, NamedTuple, Optional # noqa: F401
2018-07-13 09:43:08 +00:00
import uuid
import attr
from homeassistant.util import dt as dt_util
from . import permissions as perm_mdl
from .const import GROUP_ID_ADMIN
2018-07-13 09:43:08 +00:00
from .util import generate_secret
2019-07-31 19:25:30 +00:00
TOKEN_TYPE_NORMAL = "normal"
TOKEN_TYPE_SYSTEM = "system"
TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN = "long_lived_access_token"
2018-07-13 09:43:08 +00:00
@attr.s(slots=True)
class Group:
"""A group."""
name = attr.ib(type=str) # type: Optional[str]
policy = attr.ib(type=perm_mdl.PolicyType)
id = attr.ib(type=str, factory=lambda: uuid.uuid4().hex)
system_generated = attr.ib(type=bool, default=False)
2018-07-13 09:43:08 +00:00
@attr.s(slots=True)
class User:
"""A user."""
name = attr.ib(type=str) # type: Optional[str]
perm_lookup = attr.ib(
2019-07-31 19:25:30 +00:00
type=perm_mdl.PermissionLookup, cmp=False
) # type: perm_mdl.PermissionLookup
id = attr.ib(type=str, factory=lambda: uuid.uuid4().hex)
2018-07-13 09:43:08 +00:00
is_owner = attr.ib(type=bool, default=False)
is_active = attr.ib(type=bool, default=False)
system_generated = attr.ib(type=bool, default=False)
groups = attr.ib(type=List, factory=list, cmp=False) # type: List[Group]
2018-07-13 09:43:08 +00:00
# List of credentials of a user.
2019-07-31 19:25:30 +00:00
credentials = attr.ib(type=list, factory=list, cmp=False) # type: List[Credentials]
2018-07-13 09:43:08 +00:00
# Tokens associated with a user.
refresh_tokens = attr.ib(
type=dict, factory=dict, cmp=False
) # type: Dict[str, RefreshToken]
2018-07-13 09:43:08 +00:00
_permissions = attr.ib(
2019-07-31 19:25:30 +00:00
type=Optional[perm_mdl.PolicyPermissions], init=False, cmp=False, default=None
)
@property
def permissions(self) -> perm_mdl.AbstractPermissions:
"""Return permissions object for user."""
if self.is_owner:
return perm_mdl.OwnerPermissions
if self._permissions is not None:
return self._permissions
self._permissions = perm_mdl.PolicyPermissions(
2019-07-31 19:25:30 +00:00
perm_mdl.merge_policies([group.policy for group in self.groups]),
self.perm_lookup,
)
return self._permissions
@property
def is_admin(self) -> bool:
"""Return if user is part of the admin group."""
if self.is_owner:
return True
2019-07-31 19:25:30 +00:00
return self.is_active and any(gr.id == GROUP_ID_ADMIN for gr in self.groups)
def invalidate_permission_cache(self) -> None:
"""Invalidate permission cache."""
self._permissions = None
2018-07-13 09:43:08 +00:00
@attr.s(slots=True)
class RefreshToken:
"""RefreshToken for a user to grant new access tokens."""
user = attr.ib(type=User)
client_id = attr.ib(type=Optional[str])
access_token_expiration = attr.ib(type=timedelta)
client_name = attr.ib(type=Optional[str], default=None)
client_icon = attr.ib(type=Optional[str], default=None)
2019-07-31 19:25:30 +00:00
token_type = attr.ib(
type=str,
default=TOKEN_TYPE_NORMAL,
validator=attr.validators.in_(
(TOKEN_TYPE_NORMAL, TOKEN_TYPE_SYSTEM, TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN)
),
)
id = attr.ib(type=str, factory=lambda: uuid.uuid4().hex)
created_at = attr.ib(type=datetime, factory=dt_util.utcnow)
token = attr.ib(type=str, factory=lambda: generate_secret(64))
jwt_key = attr.ib(type=str, factory=lambda: generate_secret(64))
2018-07-13 09:43:08 +00:00
last_used_at = attr.ib(type=Optional[datetime], default=None)
last_used_ip = attr.ib(type=Optional[str], default=None)
2018-07-13 09:43:08 +00:00
@attr.s(slots=True)
class Credentials:
"""Credentials for a user on an auth provider."""
auth_provider_type = attr.ib(type=str)
auth_provider_id = attr.ib(type=Optional[str])
2018-07-13 09:43:08 +00:00
# Allow the auth provider to store data to represent their auth.
data = attr.ib(type=dict)
id = attr.ib(type=str, factory=lambda: uuid.uuid4().hex)
2018-07-13 09:43:08 +00:00
is_new = attr.ib(type=bool, default=True)
2019-07-31 19:25:30 +00:00
UserMeta = NamedTuple("UserMeta", [("name", Optional[str]), ("is_active", bool)])