forked from home-assistant/core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
models.py
144 lines (105 loc) · 3.98 KB
/
models.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
"""Auth models."""
from __future__ import annotations
from datetime import datetime, timedelta
import secrets
from typing import NamedTuple
import uuid
import attr
from homeassistant.const import __version__
from homeassistant.util import dt as dt_util
from . import permissions as perm_mdl
from .const import GROUP_ID_ADMIN
TOKEN_TYPE_NORMAL = "normal"
TOKEN_TYPE_SYSTEM = "system"
TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN = "long_lived_access_token"
@attr.s(slots=True)
class Group:
"""A group."""
name: str | None = attr.ib()
policy: perm_mdl.PolicyType = attr.ib()
id: str = attr.ib(factory=lambda: uuid.uuid4().hex)
system_generated: bool = attr.ib(default=False)
@attr.s(slots=True)
class User:
"""A user."""
name: str | None = attr.ib()
perm_lookup: perm_mdl.PermissionLookup = attr.ib(eq=False, order=False)
id: str = attr.ib(factory=lambda: uuid.uuid4().hex)
is_owner: bool = attr.ib(default=False)
is_active: bool = attr.ib(default=False)
system_generated: bool = attr.ib(default=False)
local_only: bool = attr.ib(default=False)
groups: list[Group] = attr.ib(factory=list, eq=False, order=False)
# List of credentials of a user.
credentials: list[Credentials] = attr.ib(factory=list, eq=False, order=False)
# Tokens associated with a user.
refresh_tokens: dict[str, RefreshToken] = attr.ib(
factory=dict, eq=False, order=False
)
_permissions: perm_mdl.PolicyPermissions | None = attr.ib(
init=False,
eq=False,
order=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(
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
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
@attr.s(slots=True)
class RefreshToken:
"""RefreshToken for a user to grant new access tokens."""
user: User = attr.ib()
client_id: str | None = attr.ib()
access_token_expiration: timedelta = attr.ib()
client_name: str | None = attr.ib(default=None)
client_icon: str | None = attr.ib(default=None)
token_type: str = attr.ib(
default=TOKEN_TYPE_NORMAL,
validator=attr.validators.in_(
(TOKEN_TYPE_NORMAL, TOKEN_TYPE_SYSTEM, TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN)
),
)
id: str = attr.ib(factory=lambda: uuid.uuid4().hex)
created_at: datetime = attr.ib(factory=dt_util.utcnow)
token: str = attr.ib(factory=lambda: secrets.token_hex(64))
jwt_key: str = attr.ib(factory=lambda: secrets.token_hex(64))
last_used_at: datetime | None = attr.ib(default=None)
last_used_ip: str | None = attr.ib(default=None)
credential: Credentials | None = attr.ib(default=None)
version: str | None = attr.ib(default=__version__)
@attr.s(slots=True)
class Credentials:
"""Credentials for a user on an auth provider."""
auth_provider_type: str = attr.ib()
auth_provider_id: str | None = attr.ib()
# Allow the auth provider to store data to represent their auth.
data: dict = attr.ib()
id: str = attr.ib(factory=lambda: uuid.uuid4().hex)
is_new: bool = attr.ib(default=True)
@attr.s(slots=True)
class Passkey:
"""Passkey for user on an auth provider."""
credential_id: str = attr.ib()
credential_public_key: str = attr.ib()
class UserMeta(NamedTuple):
"""User metadata."""
name: str | None
is_active: bool