mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 21:57:51 +00:00
Add user events (#17328)
This commit is contained in:
parent
44477f3d32
commit
61bf4d8a29
@ -16,6 +16,9 @@ from . import auth_store, models
|
|||||||
from .mfa_modules import auth_mfa_module_from_config, MultiFactorAuthModule
|
from .mfa_modules import auth_mfa_module_from_config, MultiFactorAuthModule
|
||||||
from .providers import auth_provider_from_config, AuthProvider, LoginFlow
|
from .providers import auth_provider_from_config, AuthProvider, LoginFlow
|
||||||
|
|
||||||
|
EVENT_USER_ADDED = 'user_added'
|
||||||
|
EVENT_USER_REMOVED = 'user_removed'
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
_MfaModuleDict = Dict[str, MultiFactorAuthModule]
|
_MfaModuleDict = Dict[str, MultiFactorAuthModule]
|
||||||
_ProviderKey = Tuple[str, Optional[str]]
|
_ProviderKey = Tuple[str, Optional[str]]
|
||||||
@ -126,13 +129,19 @@ class AuthManager:
|
|||||||
|
|
||||||
async def async_create_system_user(self, name: str) -> models.User:
|
async def async_create_system_user(self, name: str) -> models.User:
|
||||||
"""Create a system user."""
|
"""Create a system user."""
|
||||||
return await self._store.async_create_user(
|
user = await self._store.async_create_user(
|
||||||
name=name,
|
name=name,
|
||||||
system_generated=True,
|
system_generated=True,
|
||||||
is_active=True,
|
is_active=True,
|
||||||
groups=[],
|
groups=[],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.hass.bus.async_fire(EVENT_USER_ADDED, {
|
||||||
|
'user_id': user.id
|
||||||
|
})
|
||||||
|
|
||||||
|
return user
|
||||||
|
|
||||||
async def async_create_user(self, name: str) -> models.User:
|
async def async_create_user(self, name: str) -> models.User:
|
||||||
"""Create a user."""
|
"""Create a user."""
|
||||||
group = (await self._store.async_get_groups())[0]
|
group = (await self._store.async_get_groups())[0]
|
||||||
@ -145,7 +154,13 @@ class AuthManager:
|
|||||||
if await self._user_should_be_owner():
|
if await self._user_should_be_owner():
|
||||||
kwargs['is_owner'] = True
|
kwargs['is_owner'] = True
|
||||||
|
|
||||||
return await self._store.async_create_user(**kwargs)
|
user = await self._store.async_create_user(**kwargs)
|
||||||
|
|
||||||
|
self.hass.bus.async_fire(EVENT_USER_ADDED, {
|
||||||
|
'user_id': user.id
|
||||||
|
})
|
||||||
|
|
||||||
|
return user
|
||||||
|
|
||||||
async def async_get_or_create_user(self, credentials: models.Credentials) \
|
async def async_get_or_create_user(self, credentials: models.Credentials) \
|
||||||
-> models.User:
|
-> models.User:
|
||||||
@ -165,12 +180,18 @@ class AuthManager:
|
|||||||
info = await auth_provider.async_user_meta_for_credentials(
|
info = await auth_provider.async_user_meta_for_credentials(
|
||||||
credentials)
|
credentials)
|
||||||
|
|
||||||
return await self._store.async_create_user(
|
user = await self._store.async_create_user(
|
||||||
credentials=credentials,
|
credentials=credentials,
|
||||||
name=info.name,
|
name=info.name,
|
||||||
is_active=info.is_active,
|
is_active=info.is_active,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.hass.bus.async_fire(EVENT_USER_ADDED, {
|
||||||
|
'user_id': user.id
|
||||||
|
})
|
||||||
|
|
||||||
|
return user
|
||||||
|
|
||||||
async def async_link_user(self, user: models.User,
|
async def async_link_user(self, user: models.User,
|
||||||
credentials: models.Credentials) -> None:
|
credentials: models.Credentials) -> None:
|
||||||
"""Link credentials to an existing user."""
|
"""Link credentials to an existing user."""
|
||||||
@ -188,6 +209,10 @@ class AuthManager:
|
|||||||
|
|
||||||
await self._store.async_remove_user(user)
|
await self._store.async_remove_user(user)
|
||||||
|
|
||||||
|
self.hass.bus.async_fire(EVENT_USER_REMOVED, {
|
||||||
|
'user_id': user.id
|
||||||
|
})
|
||||||
|
|
||||||
async def async_activate_user(self, user: models.User) -> None:
|
async def async_activate_user(self, user: models.User) -> None:
|
||||||
"""Activate a user."""
|
"""Activate a user."""
|
||||||
await self._store.async_activate_user(user)
|
await self._store.async_activate_user(user)
|
||||||
|
@ -10,6 +10,7 @@ from homeassistant import auth, data_entry_flow
|
|||||||
from homeassistant.auth import (
|
from homeassistant.auth import (
|
||||||
models as auth_models, auth_store, const as auth_const)
|
models as auth_models, auth_store, const as auth_const)
|
||||||
from homeassistant.auth.const import MFA_SESSION_EXPIRATION
|
from homeassistant.auth.const import MFA_SESSION_EXPIRATION
|
||||||
|
from homeassistant.core import callback
|
||||||
from homeassistant.util import dt as dt_util
|
from homeassistant.util import dt as dt_util
|
||||||
from tests.common import (
|
from tests.common import (
|
||||||
MockUser, ensure_auth_manager_loaded, flush_store, CLIENT_ID)
|
MockUser, ensure_auth_manager_loaded, flush_store, CLIENT_ID)
|
||||||
@ -138,6 +139,14 @@ async def test_auth_manager_from_config_auth_modules(mock_hass):
|
|||||||
|
|
||||||
async def test_create_new_user(hass):
|
async def test_create_new_user(hass):
|
||||||
"""Test creating new user."""
|
"""Test creating new user."""
|
||||||
|
events = []
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def user_added(event):
|
||||||
|
events.append(event)
|
||||||
|
|
||||||
|
hass.bus.async_listen('user_added', user_added)
|
||||||
|
|
||||||
manager = await auth.auth_manager_from_config(hass, [{
|
manager = await auth.auth_manager_from_config(hass, [{
|
||||||
'type': 'insecure_example',
|
'type': 'insecure_example',
|
||||||
'users': [{
|
'users': [{
|
||||||
@ -160,6 +169,10 @@ async def test_create_new_user(hass):
|
|||||||
assert user.is_owner is False
|
assert user.is_owner is False
|
||||||
assert user.name == 'Test Name'
|
assert user.name == 'Test Name'
|
||||||
|
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert len(events) == 1
|
||||||
|
assert events[0].data['user_id'] == user.id
|
||||||
|
|
||||||
|
|
||||||
async def test_login_as_existing_user(mock_hass):
|
async def test_login_as_existing_user(mock_hass):
|
||||||
"""Test login as existing user."""
|
"""Test login as existing user."""
|
||||||
@ -331,6 +344,14 @@ async def test_cannot_retrieve_expired_access_token(hass):
|
|||||||
|
|
||||||
async def test_generating_system_user(hass):
|
async def test_generating_system_user(hass):
|
||||||
"""Test that we can add a system user."""
|
"""Test that we can add a system user."""
|
||||||
|
events = []
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def user_added(event):
|
||||||
|
events.append(event)
|
||||||
|
|
||||||
|
hass.bus.async_listen('user_added', user_added)
|
||||||
|
|
||||||
manager = await auth.auth_manager_from_config(hass, [], [])
|
manager = await auth.auth_manager_from_config(hass, [], [])
|
||||||
user = await manager.async_create_system_user('Hass.io')
|
user = await manager.async_create_system_user('Hass.io')
|
||||||
token = await manager.async_create_refresh_token(user)
|
token = await manager.async_create_refresh_token(user)
|
||||||
@ -338,6 +359,10 @@ async def test_generating_system_user(hass):
|
|||||||
assert token is not None
|
assert token is not None
|
||||||
assert token.client_id is None
|
assert token.client_id is None
|
||||||
|
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert len(events) == 1
|
||||||
|
assert events[0].data['user_id'] == user.id
|
||||||
|
|
||||||
|
|
||||||
async def test_refresh_token_requires_client_for_user(hass):
|
async def test_refresh_token_requires_client_for_user(hass):
|
||||||
"""Test create refresh token for a user with client_id."""
|
"""Test create refresh token for a user with client_id."""
|
||||||
@ -797,3 +822,50 @@ async def test_enable_mfa_for_user(hass, hass_storage):
|
|||||||
|
|
||||||
# disable mfa for user don't enabled just silent fail
|
# disable mfa for user don't enabled just silent fail
|
||||||
await manager.async_disable_user_mfa(user, 'insecure_example')
|
await manager.async_disable_user_mfa(user, 'insecure_example')
|
||||||
|
|
||||||
|
|
||||||
|
async def test_async_remove_user(hass):
|
||||||
|
"""Test removing a user."""
|
||||||
|
events = []
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def user_removed(event):
|
||||||
|
events.append(event)
|
||||||
|
|
||||||
|
hass.bus.async_listen('user_removed', user_removed)
|
||||||
|
|
||||||
|
manager = await auth.auth_manager_from_config(hass, [{
|
||||||
|
'type': 'insecure_example',
|
||||||
|
'users': [{
|
||||||
|
'username': 'test-user',
|
||||||
|
'password': 'test-pass',
|
||||||
|
'name': 'Test Name'
|
||||||
|
}]
|
||||||
|
}], [])
|
||||||
|
hass.auth = manager
|
||||||
|
ensure_auth_manager_loaded(manager)
|
||||||
|
|
||||||
|
# Add fake user with credentials for example auth provider.
|
||||||
|
user = MockUser(
|
||||||
|
id='mock-user',
|
||||||
|
is_owner=False,
|
||||||
|
is_active=False,
|
||||||
|
name='Paulus',
|
||||||
|
).add_to_auth_manager(manager)
|
||||||
|
user.credentials.append(auth_models.Credentials(
|
||||||
|
id='mock-id',
|
||||||
|
auth_provider_type='insecure_example',
|
||||||
|
auth_provider_id=None,
|
||||||
|
data={'username': 'test-user'},
|
||||||
|
is_new=False,
|
||||||
|
))
|
||||||
|
assert len(user.credentials) == 1
|
||||||
|
|
||||||
|
await hass.auth.async_remove_user(user)
|
||||||
|
|
||||||
|
assert len(await manager.async_get_users()) == 0
|
||||||
|
assert len(user.credentials) == 0
|
||||||
|
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert len(events) == 1
|
||||||
|
assert events[0].data['user_id'] == user.id
|
||||||
|
Loading…
x
Reference in New Issue
Block a user