Home Assistant Unofficial Reference 2024.12.1
auth.py
Go to the documentation of this file.
1 """Script to manage users for the Home Assistant auth provider."""
2 
3 import argparse
4 import asyncio
5 from collections.abc import Sequence
6 import logging
7 import os
8 from typing import TYPE_CHECKING
9 
10 from homeassistant import runner
11 from homeassistant.auth import auth_manager_from_config
12 from homeassistant.auth.providers import homeassistant as hass_auth
13 from homeassistant.config import get_default_config_dir
14 from homeassistant.core import HomeAssistant
15 from homeassistant.helpers import device_registry as dr, entity_registry as er
16 
17 # mypy: allow-untyped-calls, allow-untyped-defs
18 
19 
20 def run(args: Sequence[str] | None) -> None:
21  """Handle Home Assistant auth provider script."""
22  parser = argparse.ArgumentParser(description="Manage Home Assistant users")
23  parser.add_argument("--script", choices=["auth"])
24  parser.add_argument(
25  "-c",
26  "--config",
27  default=get_default_config_dir(),
28  help="Directory that contains the Home Assistant configuration",
29  )
30 
31  subparsers = parser.add_subparsers(dest="func")
32  subparsers.required = True
33  parser_list = subparsers.add_parser("list")
34  parser_list.set_defaults(func=list_users)
35 
36  parser_add = subparsers.add_parser("add")
37  parser_add.add_argument("username", type=str)
38  parser_add.add_argument("password", type=str)
39  parser_add.set_defaults(func=add_user)
40 
41  parser_validate_login = subparsers.add_parser("validate")
42  parser_validate_login.add_argument("username", type=str)
43  parser_validate_login.add_argument("password", type=str)
44  parser_validate_login.set_defaults(func=validate_login)
45 
46  parser_change_pw = subparsers.add_parser("change_password")
47  parser_change_pw.add_argument("username", type=str)
48  parser_change_pw.add_argument("new_password", type=str)
49  parser_change_pw.set_defaults(func=change_password)
50 
51  asyncio.set_event_loop_policy(runner.HassEventLoopPolicy(False))
52  asyncio.run(run_command(parser.parse_args(args)))
53 
54 
55 async def run_command(args: argparse.Namespace) -> None:
56  """Run the command."""
57  hass = HomeAssistant(os.path.join(os.getcwd(), args.config))
58  await asyncio.gather(dr.async_load(hass), er.async_load(hass))
59  hass.auth = await auth_manager_from_config(hass, [{"type": "homeassistant"}], [])
60  provider = hass.auth.auth_providers[0]
61  await provider.async_initialize()
62  await args.func(hass, provider, args)
63 
64  # Triggers save on used storage helpers with delay (core auth)
65  logging.getLogger("homeassistant.core").setLevel(logging.WARNING)
66 
67  await hass.async_stop()
68 
69 
70 async def list_users(
71  hass: HomeAssistant, provider: hass_auth.HassAuthProvider, args: argparse.Namespace
72 ) -> None:
73  """List the users."""
74  count = 0
75  if TYPE_CHECKING:
76  assert provider.data
77  for user in provider.data.users:
78  count += 1
79  print(user["username"])
80 
81  print()
82  print("Total users:", count)
83 
84 
85 async def add_user(
86  hass: HomeAssistant, provider: hass_auth.HassAuthProvider, args: argparse.Namespace
87 ) -> None:
88  """Create a user."""
89  if TYPE_CHECKING:
90  assert provider.data
91  try:
92  provider.data.add_auth(args.username, args.password)
93  except hass_auth.InvalidUser:
94  print("Username already exists!")
95  return
96 
97  # Save username/password
98  await provider.data.async_save()
99  print("Auth created")
100 
101 
102 async def validate_login(
103  hass: HomeAssistant, provider: hass_auth.HassAuthProvider, args: argparse.Namespace
104 ) -> None:
105  """Validate a login."""
106  if TYPE_CHECKING:
107  assert provider.data
108  try:
109  provider.data.validate_login(args.username, args.password)
110  print("Auth valid")
111  except hass_auth.InvalidAuth:
112  print("Auth invalid")
113 
114 
115 async def change_password(
116  hass: HomeAssistant, provider: hass_auth.HassAuthProvider, args: argparse.Namespace
117 ) -> None:
118  """Change password."""
119  if TYPE_CHECKING:
120  assert provider.data
121  try:
122  provider.data.change_password(args.username, args.new_password)
123  await provider.data.async_save()
124  print("Password changed")
125  except hass_auth.InvalidUser:
126  print("User not found")
AuthManager auth_manager_from_config(HomeAssistant hass, list[dict[str, Any]] provider_configs, list[dict[str, Any]] module_configs)
Definition: __init__.py:54
str get_default_config_dir()
Definition: config.py:135
None list_users(HomeAssistant hass, hass_auth.HassAuthProvider provider, argparse.Namespace args)
Definition: auth.py:72
None run(Sequence[str]|None args)
Definition: auth.py:20
None add_user(HomeAssistant hass, hass_auth.HassAuthProvider provider, argparse.Namespace args)
Definition: auth.py:87
None run_command(argparse.Namespace args)
Definition: auth.py:55
None validate_login(HomeAssistant hass, hass_auth.HassAuthProvider provider, argparse.Namespace args)
Definition: auth.py:104
None change_password(HomeAssistant hass, hass_auth.HassAuthProvider provider, argparse.Namespace args)
Definition: auth.py:117