Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0.78.0 #16666

Merged
merged 175 commits into from
Sep 17, 2018
Merged

0.78.0 #16666

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
175 commits
Select commit Hold shift + click to select a range
e8775ba
Add multi-factor auth module setup flow (#16141)
awarecan Aug 24, 2018
e91a152
deCONZ - Support device registry (#16115)
Kane610 Aug 24, 2018
84365cd
fix error message for cv.matches_regex (#16175)
heythisisnate Aug 24, 2018
647b3ff
Decouple Konnected entity setup from discovery (#16146)
heythisisnate Aug 24, 2018
69cea60
Add 'moon_phase' to Dark Sky sensor (#16179)
fabaff Aug 24, 2018
24a8d60
Tweak log level for bearer token warning (#16182)
awarecan Aug 25, 2018
97173f4
Device registry store config entry (#16152)
Kane610 Aug 25, 2018
456aa5a
Fix hangouts (#16180)
balloob Aug 25, 2018
26a485d
Default load trusted_network auth provider if configured trusted netw…
awarecan Aug 25, 2018
6178026
Bump frontend to 20180825.0
balloob Aug 25, 2018
f929c38
Zoneminder SSL fix (#16157)
djm300 Aug 25, 2018
2f2bcf0
update python-velbus library version (#16194)
thomasdelaet Aug 25, 2018
a1ce14e
MQTT: Log transmitted as well as received messages (#16195)
smurfix Aug 26, 2018
0a7055d
homematic: Make device avilable again when UNREACH becomes False (#16…
klada Aug 26, 2018
0da3e73
Upgrade sqlalchemy to 1.2.11 (#16192)
fabaff Aug 26, 2018
289b180
Add battery warning, rssi level and check for availability (#16193)
fucm Aug 26, 2018
5341785
Revert changes to platforms using self.device (#16209)
Kane610 Aug 26, 2018
3032de1
Inconsistent entity_id when multiple sensors (#16205)
grea09 Aug 26, 2018
d166f2d
remove hangouts.users state, simplifies hangouts.conversations (#16191)
hobbypunk90 Aug 26, 2018
499bb3f
Handle exception from pillow (#16190)
PhracturedBlue Aug 26, 2018
b043ac0
Update frontend to 20180826.0
balloob Aug 26, 2018
69d104b
Update aiohttp to version 3.4.0. (#16198)
Swamp-Ig Aug 26, 2018
47755fb
Add Time-based Onetime Password Multi-factor Authentication Module (#…
awarecan Aug 26, 2018
bacecb4
Replace pbkdf2 with bcrypt (#16071)
Eriner Aug 26, 2018
4da719f
Update translations
balloob Aug 26, 2018
5d7a2f9
Add temperature sensors to the velbus component (#16203)
cereal2nd Aug 27, 2018
a439690
Rewrite of Trafikverket weather - Multiple sensor types supported (#1…
endor-force Aug 27, 2018
dec2d8d
Add device_tracker.bluetooth_update service (#15252)
kariudo Aug 27, 2018
2e9db1f
Fix geizhals price parsing (#15990)
JulianKahnert Aug 27, 2018
f1e378b
Add new translations
balloob Aug 26, 2018
9466262
Update translations
balloob Aug 27, 2018
9d491f5
Change auth warning (#16216)
balloob Aug 27, 2018
c51170e
Add Volkszaehler sensor (#16188)
fabaff Aug 27, 2018
8435d2f
openalpr flag `WITH_TEST` should be `WITH_TESTS` (#16218)
vrih Aug 27, 2018
24aa580
Fix device telldus (#16224)
balloob Aug 27, 2018
943260f
Upgrade alpha_vantage to 2.1.0 (#16217)
fabaff Aug 27, 2018
6f0c30f
Bump frontend to 20180827.0
balloob Aug 27, 2018
4564982
rewrite hangouts to use intents instead of commands (#16220)
hobbypunk90 Aug 27, 2018
8ab31fe
Store devices as dict instead of list (#16229)
Kane610 Aug 27, 2018
5397c0d
Update trusted networks flow (#16227)
balloob Aug 27, 2018
376d4e4
Warning missed a space (#16233)
balloob Aug 28, 2018
a149807
Package loadable: compare case insensitive (#16234)
balloob Aug 28, 2018
67df162
Change log level to error when auth provider failed loading (#16235)
awarecan Aug 28, 2018
12709ce
Avoid insecure pycryptodome (#16238)
balloob Aug 28, 2018
09dc4d6
Improve package loadable (#16237)
balloob Aug 28, 2018
9a786e4
Fix hangouts (#16232)
balloob Aug 28, 2018
257b8b9
Blow up startup if init auth providers or modules failed (#16240)
awarecan Aug 28, 2018
f891d0f
Update translations
balloob Aug 28, 2018
63614a4
def device shouldnt call it self but self._device (#16255)
Kane610 Aug 29, 2018
5635886
Tweak MFA login flow (#16254)
awarecan Aug 29, 2018
74c0429
Bump frontend to 20180829.0
balloob Aug 29, 2018
e8801ee
Update translations
balloob Aug 29, 2018
630b5df
Merge branch 'master' into dev
balloob Aug 29, 2018
3df8840
Version bump to 0.78.0.dev0
balloob Aug 29, 2018
18ba50b
Switchmate (#15535)
Danielhiversen Aug 29, 2018
aaa1ebe
Add support for discrete states to MyQ cover (#16251)
schmittx Aug 29, 2018
d46a1a2
bump version (#16262)
dgomes Aug 29, 2018
96cf6d5
Replace Authorization by Authentication (#16259)
cgtobi Aug 29, 2018
3934f7b
Add device info to Chromecast (#16261)
balloob Aug 29, 2018
16a8858
Add device info for sonos (#16263)
balloob Aug 29, 2018
7751dd7
Add device info Nest (#16265)
balloob Aug 29, 2018
867d17b
Add Hue device info (#16267)
balloob Aug 29, 2018
5681fa8
Nest Thermostat has software version (#16275)
awarecan Aug 29, 2018
99d4879
Add support for Habitica (#15744)
asmfreak Aug 29, 2018
25ee8e5
Fix data_key override by parent class (#16278)
syssi Aug 29, 2018
87df102
Bump frontend to 20180829.1
balloob Aug 29, 2018
88f72a6
Fix error when vacuum is idling (#16282)
cnrd Aug 29, 2018
645c3a6
Fix so that entities are properly unloaded with config entry (#16281)
Kane610 Aug 29, 2018
7289d5b
Merge branch 'master' into dev
balloob Aug 29, 2018
54c3f4f
Fix spelling mistake in recorder migration [ci skip]
robbiet480 Aug 29, 2018
f20a331
Geo Location component (#15953)
exxamalte Aug 30, 2018
3cbf8e4
Bump songpal dependency (#16297)
rytilahti Aug 30, 2018
67d8db2
Use asterisk_mbox 0.5.0 client (#16296)
PhracturedBlue Aug 30, 2018
b43c47c
Fix LIFX effects (#16309)
amelchio Aug 31, 2018
26d39d3
avoid error in debug log mode and rss entry without title (#16316)
exxamalte Aug 31, 2018
93f4577
Correct wemo static device discovery issue. (#16292)
lamiskin Aug 31, 2018
efa9c82
Update frontend to 20180831.0
balloob Aug 31, 2018
5e8a149
Update translations
balloob Aug 31, 2018
7d852a9
Upgrade Adafruit-DHT to 1.3.4 (#16327)
thomaslian Aug 31, 2018
fa81385
Add unique ID (#16323)
schmittx Aug 31, 2018
d3791fa
Add Cover to the Insteon component (#16215)
teharris1 Aug 31, 2018
2c7d6ee
Fix missing humidity sensor (#16337)
danielperna84 Sep 1, 2018
901cfef
Support Sonos Beam HDMI input (#16340)
Sep 1, 2018
a5d95df
Make last_seen attribute a timezone aware datetime in UTC (#16348)
pnbruckner Sep 1, 2018
b31890c
Handle netatmo exception (#16344)
Danielhiversen Sep 1, 2018
444df5b
Add support for sound_mode for Yamaha rxv media_player (#16352)
Joshi425 Sep 1, 2018
e75a169
Add unique_id to MQTT Light (#16303)
bieniu Sep 1, 2018
2b0b431
Update to EnvoyReader 0.2, support for more hardware (#16212)
jesserizzo Sep 1, 2018
3797b6b
Snips: Added special slot values, session_id and slotname_raw (#16185)
tschmidty69 Sep 1, 2018
87eb6cd
Upgrade hbmqtt to 0.9.4 (#16356)
awarecan Sep 2, 2018
03fb2b3
Upgrade Sphinx to 1.7.7 (#16359)
fabaff Sep 2, 2018
15ad82b
Upgrade qnapstats to 0.2.7 (#16360)
fabaff Sep 2, 2018
1d12c7b
Upgrade mutagen to 1.41.1 (#16361)
fabaff Sep 2, 2018
97695a3
Upgrade shodan to 1.10.0 (#16363)
fabaff Sep 2, 2018
52e9221
Upgrade to youtube_dl to 2018.09.01 (#16365)
fabaff Sep 2, 2018
357e5ea
Added 'nomapnt', 'outcurnt', 'loadapnt' fields (#16176)
MarcSN311 Sep 2, 2018
b29c296
Generic Thermostat: add support for climate.turn_on/climate.turn_off …
aronsky Sep 2, 2018
a5cff98
Add support for Tahoma Lighting Receiver on/off io (#15925)
fucm Sep 2, 2018
03480dc
Update discord.py (#16248)
htotoo Sep 2, 2018
ac3700d
Upgrade python-telegram-bot to 11.0.0 (#16373)
fabaff Sep 2, 2018
78fcea2
Upgrade attrs to 18.2.0 (#16372)
fabaff Sep 2, 2018
4685a2c
Update server.py (#16375)
awarecan Sep 2, 2018
1966597
add_entities for switchmate (#16368)
Danielhiversen Sep 2, 2018
bf29cbd
Update frontend to 20180903.0
balloob Sep 3, 2018
a2a447b
Update translations
balloob Sep 3, 2018
cd47364
Merge branch 'master' into dev
balloob Sep 3, 2018
00cba29
Support for playing radio preset by Onkyo media_player (#16258)
pszafer Sep 3, 2018
2252f4a
Bug fix for Tibber (#16397)
Danielhiversen Sep 3, 2018
ba63a6a
zha: Bump to zigpy 0.2.0/bellows 0.7.0 (#16404)
rcloran Sep 4, 2018
a4aa30f
Fix SystemMonitor IP address sensor (#16394)
ReneNulschDE Sep 4, 2018
7ea482c
add ExpressBus icon key to sensor.mvg (#16387)
9R Sep 4, 2018
7a6facc
Device and entity registry remove config entry on unload (#16247)
Kane610 Sep 4, 2018
f96aee2
Add config flow for OpenUV (#16159)
bachya Sep 4, 2018
8fa9992
Service to load new deCONZ devices without restart (#16308)
Kane610 Sep 4, 2018
e61ac1a
Delegate mqtt topic match validation to the paho mqtt client (#16403)
rohankapoorcom Sep 4, 2018
85658b6
Clean up dlink and some bug fix (#16346)
Danielhiversen Sep 4, 2018
3bd12fc
Implement correct state for RFlink cover (#16304)
nudded Sep 4, 2018
e1501c8
Fix Mi Flora median calculation (#16085)
PaulAnnekov Sep 4, 2018
746f4ac
Add context to scripts and automations (#16415)
balloob Sep 4, 2018
3afc983
Fix openuv.config_flow unit test (#16419)
awarecan Sep 4, 2018
e1084e3
Upgrade sense library to 0.4.2 (#16429)
kbickar Sep 5, 2018
5bd9be6
switchbot (#16396)
Danielhiversen Sep 6, 2018
cf4b72e
Fix camera proxy to not require api_password to function (#16450)
PhracturedBlue Sep 6, 2018
2640db1
Upgrade shodan to 1.10.1 (#16460)
fabaff Sep 6, 2018
db1bda2
Upgrade Sphinx to 1.7.8 (#16459)
fabaff Sep 6, 2018
3acb3a8
update rfxtrx lib (#16463)
Danielhiversen Sep 6, 2018
ce06229
Added Twitch v5 support to the twitch platform (#16428)
miawgogo Sep 6, 2018
cff9b1b
Fix waze_travel_time component startup (#16465)
tsvi Sep 7, 2018
fbaa489
Update license to official GitHub template (#16470)
OverloadUT Sep 7, 2018
1f73840
Add Yale Smart Alarm component (#16377)
domwillcode Sep 7, 2018
80c77b8
Update radiotherm (#15031)
cpw Sep 7, 2018
d0f9d12
Support SNMPv3 and asyncio in snmp switch (#14754)
mtdcr Sep 7, 2018
a5715c4
Fix GitHub change to resolve conflicts (#16477)
fabaff Sep 7, 2018
7ad094b
Add OpenTherm Gateway climate platform (#16299)
mvn23 Sep 7, 2018
50266e9
Support SNMPv3 and asyncio in snmp sensor (#14753)
mtdcr Sep 7, 2018
8a2bc99
Add rate of change to statistics sensor (#15632)
flo-wer Sep 7, 2018
9314338
Restore status attribute for xiaomi_vacuum (#16366)
tamasv Sep 8, 2018
9944c60
Check if API key is valid and users available (#16494)
fabaff Sep 8, 2018
e7b8d2e
Update name legacy api password (#16455)
balloob Sep 8, 2018
e3e3ed4
Fix Netgear LTESensor docstring (#16501)
scop Sep 8, 2018
7d590a6
Update pyHS100 to 0.3.3 (#16502)
amelchio Sep 8, 2018
4291bdc
Move voluptuous-serialize to core requirement (#16507)
awarecan Sep 9, 2018
d6d4ff6
adds listener for OnAVStart and OnAVChange (#16495)
tadly Sep 9, 2018
0d7ee9b
Order imports (#16515)
fabaff Sep 9, 2018
253e787
Upgrade aiohttp to 3.4.4 (#16486)
awarecan Sep 10, 2018
a1578e3
Add a base_url configuration setting to tts. (#16478)
lddubeau Sep 10, 2018
8ed4d73
Upgrade youtube_dl to 2018.09.10 (#16534)
fabaff Sep 10, 2018
c20f147
Upgrade keyring to 15.0.0 (#16536)
fabaff Sep 10, 2018
fb15dbf
Bump frontend to 20180910.0
balloob Sep 10, 2018
1d6609e
Update translations
balloob Sep 10, 2018
3f97944
Bumped version to 0.78.0b0
balloob Sep 10, 2018
00d8907
Update translations
balloob Sep 11, 2018
b9b8bc6
Update frontend to 20180911.0
balloob Sep 11, 2018
968809c
Replace api_password in Camera.Push (#16339)
dgomes Sep 11, 2018
44d2106
Fail fetch auth providers if onboarding required (#16454)
balloob Sep 10, 2018
1ea8c1e
Fix insteon Hub v1 support (#16472)
teharris1 Sep 10, 2018
60b45d4
bugfix - incorrect camera type and missing sensors when multiple neta…
vikramgorla Sep 10, 2018
a4cec0b
Fix arlo intilization when no base station available (#16529)
zellux Sep 11, 2018
20e562b
Long-lived access token (#16453)
awarecan Sep 11, 2018
37c8aac
Fix typo (#16556)
balloob Sep 11, 2018
20f06f4
Fix invalid state (#16558)
balloob Sep 11, 2018
e50fc69
Add websocket commands for refresh tokens (#16559)
balloob Sep 11, 2018
6d33fb2
Bumped version to 0.78.0b1
balloob Sep 11, 2018
68c2153
Update frontend to 20180912.0
balloob Sep 12, 2018
1983361
Return if refresh token is current used one in WS API (#16575)
awarecan Sep 12, 2018
4c1b816
Track refresh token last usage information (#16408)
awarecan Sep 12, 2018
08100a4
Increasing python-websockets' version number (#16578)
zoe1337 Sep 12, 2018
a88cda4
Bumped version to 0.78.0b2
balloob Sep 12, 2018
336289d
Add retry limit for chromecast connection (#16471)
awarecan Sep 12, 2018
b231fa2
Fix broken bluetooth tracker (#16589)
awarecan Sep 13, 2018
abe61c5
Rewrite bluetooth le (#16592)
pvizeli Sep 14, 2018
7f73721
Update translations
balloob Sep 15, 2018
18ce509
Bumped version to 0.78.0b3
balloob Sep 15, 2018
f918d62
version bump to 0.78.0
balloob Sep 17, 2018
366e270
Bump frontend to 20180916.0
balloob Sep 17, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,14 @@ omit =
homeassistant/components/google.py
homeassistant/components/*/google.py

homeassistant/components/habitica/*
homeassistant/components/*/habitica.py

homeassistant/components/hangouts/__init__.py
homeassistant/components/hangouts/const.py
homeassistant/components/hangouts/hangouts_bot.py
homeassistant/components/hangouts/hangups_utils.py
homeassistant/components/*/hangouts.py
homeassistant/components/*/hangouts.py

homeassistant/components/hdmi_cec.py
homeassistant/components/*/hdmi_cec.py
Expand All @@ -142,12 +145,12 @@ omit =

homeassistant/components/ihc/*
homeassistant/components/*/ihc.py

homeassistant/components/insteon/*
homeassistant/components/*/insteon.py

homeassistant/components/insteon_local.py

homeassistant/components/insteon_plm.py

homeassistant/components/ios.py
Expand Down Expand Up @@ -225,7 +228,7 @@ omit =
homeassistant/components/opencv.py
homeassistant/components/*/opencv.py

homeassistant/components/openuv.py
homeassistant/components/openuv/__init__.py
homeassistant/components/*/openuv.py

homeassistant/components/pilight.py
Expand Down Expand Up @@ -374,6 +377,7 @@ omit =
homeassistant/components/alarm_control_panel/nx584.py
homeassistant/components/alarm_control_panel/simplisafe.py
homeassistant/components/alarm_control_panel/totalconnect.py
homeassistant/components/alarm_control_panel/yale_smart_alarm.py
homeassistant/components/apiai.py
homeassistant/components/binary_sensor/arest.py
homeassistant/components/binary_sensor/concord232.py
Expand Down Expand Up @@ -411,6 +415,7 @@ omit =
homeassistant/components/climate/honeywell.py
homeassistant/components/climate/knx.py
homeassistant/components/climate/oem.py
homeassistant/components/climate/opentherm_gw.py
homeassistant/components/climate/proliphix.py
homeassistant/components/climate/radiotherm.py
homeassistant/components/climate/sensibo.py
Expand Down Expand Up @@ -759,6 +764,7 @@ omit =
homeassistant/components/sensor/uscis.py
homeassistant/components/sensor/vasttrafik.py
homeassistant/components/sensor/viaggiatreno.py
homeassistant/components/sensor/volkszaehler.py
homeassistant/components/sensor/waqi.py
homeassistant/components/sensor/waze_travel_time.py
homeassistant/components/sensor/whois.py
Expand Down Expand Up @@ -789,6 +795,8 @@ omit =
homeassistant/components/switch/rest.py
homeassistant/components/switch/rpi_rf.py
homeassistant/components/switch/snmp.py
homeassistant/components/switch/switchbot.py
homeassistant/components/switch/switchmate.py
homeassistant/components/switch/telnet.py
homeassistant/components/switch/tplink.py
homeassistant/components/switch/transmission.py
Expand Down
395 changes: 201 additions & 194 deletions LICENSE.md

Large diffs are not rendered by default.

50 changes: 43 additions & 7 deletions homeassistant/auth/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
import asyncio
import logging
from collections import OrderedDict
from datetime import timedelta
from typing import Any, Dict, List, Optional, Tuple, cast

import jwt

from homeassistant import data_entry_flow
from homeassistant.auth.const import ACCESS_TOKEN_EXPIRATION
from homeassistant.core import callback, HomeAssistant
from homeassistant.util import dt as dt_util

Expand Down Expand Up @@ -242,8 +244,12 @@ async def async_get_enabled_mfa(self, user: models.User) -> Dict[str, str]:
modules[module_id] = module.name
return modules

async def async_create_refresh_token(self, user: models.User,
client_id: Optional[str] = None) \
async def async_create_refresh_token(
self, user: models.User, client_id: Optional[str] = None,
client_name: Optional[str] = None,
client_icon: Optional[str] = None,
token_type: Optional[str] = None,
access_token_expiration: timedelta = ACCESS_TOKEN_EXPIRATION) \
-> models.RefreshToken:
"""Create a new refresh token for a user."""
if not user.is_active:
Expand All @@ -254,10 +260,36 @@ async def async_create_refresh_token(self, user: models.User,
'System generated users cannot have refresh tokens connected '
'to a client.')

if not user.system_generated and client_id is None:
if token_type is None:
if user.system_generated:
token_type = models.TOKEN_TYPE_SYSTEM
else:
token_type = models.TOKEN_TYPE_NORMAL

if user.system_generated != (token_type == models.TOKEN_TYPE_SYSTEM):
raise ValueError(
'System generated users can only have system type '
'refresh tokens')

if token_type == models.TOKEN_TYPE_NORMAL and client_id is None:
raise ValueError('Client is required to generate a refresh token.')

return await self._store.async_create_refresh_token(user, client_id)
if (token_type == models.TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN and
client_name is None):
raise ValueError('Client_name is required for long-lived access '
'token')

if token_type == models.TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN:
for token in user.refresh_tokens.values():
if (token.client_name == client_name and token.token_type ==
models.TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN):
# Each client_name can only have one
# long_lived_access_token type of refresh token
raise ValueError('{} already exists'.format(client_name))

return await self._store.async_create_refresh_token(
user, client_id, client_name, client_icon,
token_type, access_token_expiration)

async def async_get_refresh_token(
self, token_id: str) -> Optional[models.RefreshToken]:
Expand All @@ -277,13 +309,17 @@ async def async_remove_refresh_token(self,

@callback
def async_create_access_token(self,
refresh_token: models.RefreshToken) -> str:
refresh_token: models.RefreshToken,
remote_ip: Optional[str] = None) -> str:
"""Create a new access token."""
self._store.async_log_refresh_token_usage(refresh_token, remote_ip)

# pylint: disable=no-self-use
now = dt_util.utcnow()
return jwt.encode({
'iss': refresh_token.id,
'iat': dt_util.utcnow(),
'exp': dt_util.utcnow() + refresh_token.access_token_expiration,
'iat': now,
'exp': now + refresh_token.access_token_expiration,
}, refresh_token.jwt_key, algorithm='HS256').decode()

async def async_validate_access_token(
Expand Down
60 changes: 57 additions & 3 deletions homeassistant/auth/auth_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from typing import Any, Dict, List, Optional # noqa: F401
import hmac

from homeassistant.auth.const import ACCESS_TOKEN_EXPIRATION
from homeassistant.core import HomeAssistant, callback
from homeassistant.util import dt as dt_util

Expand Down Expand Up @@ -128,11 +129,27 @@ async def async_remove_credentials(
self._async_schedule_save()

async def async_create_refresh_token(
self, user: models.User, client_id: Optional[str] = None) \
self, user: models.User, client_id: Optional[str] = None,
client_name: Optional[str] = None,
client_icon: Optional[str] = None,
token_type: str = models.TOKEN_TYPE_NORMAL,
access_token_expiration: timedelta = ACCESS_TOKEN_EXPIRATION) \
-> models.RefreshToken:
"""Create a new token for a user."""
refresh_token = models.RefreshToken(user=user, client_id=client_id)
kwargs = {
'user': user,
'client_id': client_id,
'token_type': token_type,
'access_token_expiration': access_token_expiration
} # type: Dict[str, Any]
if client_name:
kwargs['client_name'] = client_name
if client_icon:
kwargs['client_icon'] = client_icon

refresh_token = models.RefreshToken(**kwargs)
user.refresh_tokens[refresh_token.id] = refresh_token

self._async_schedule_save()
return refresh_token

Expand Down Expand Up @@ -178,6 +195,15 @@ async def async_get_refresh_token_by_token(

return found

@callback
def async_log_refresh_token_usage(
self, refresh_token: models.RefreshToken,
remote_ip: Optional[str] = None) -> None:
"""Update refresh token last used information."""
refresh_token.last_used_at = dt_util.utcnow()
refresh_token.last_used_ip = remote_ip
self._async_schedule_save()

async def _async_load(self) -> None:
"""Load the users."""
data = await self._store.async_load()
Expand Down Expand Up @@ -216,15 +242,36 @@ async def _async_load(self) -> None:
'Ignoring refresh token %(id)s with invalid created_at '
'%(created_at)s for user_id %(user_id)s', rt_dict)
continue

token_type = rt_dict.get('token_type')
if token_type is None:
if rt_dict['client_id'] is None:
token_type = models.TOKEN_TYPE_SYSTEM
else:
token_type = models.TOKEN_TYPE_NORMAL

# old refresh_token don't have last_used_at (pre-0.78)
last_used_at_str = rt_dict.get('last_used_at')
if last_used_at_str:
last_used_at = dt_util.parse_datetime(last_used_at_str)
else:
last_used_at = None

token = models.RefreshToken(
id=rt_dict['id'],
user=users[rt_dict['user_id']],
client_id=rt_dict['client_id'],
# use dict.get to keep backward compatibility
client_name=rt_dict.get('client_name'),
client_icon=rt_dict.get('client_icon'),
token_type=token_type,
created_at=created_at,
access_token_expiration=timedelta(
seconds=rt_dict['access_token_expiration']),
token=rt_dict['token'],
jwt_key=rt_dict['jwt_key']
jwt_key=rt_dict['jwt_key'],
last_used_at=last_used_at,
last_used_ip=rt_dict.get('last_used_ip'),
)
users[rt_dict['user_id']].refresh_tokens[token.id] = token

Expand Down Expand Up @@ -271,11 +318,18 @@ def _data_to_save(self) -> Dict:
'id': refresh_token.id,
'user_id': user.id,
'client_id': refresh_token.client_id,
'client_name': refresh_token.client_name,
'client_icon': refresh_token.client_icon,
'token_type': refresh_token.token_type,
'created_at': refresh_token.created_at.isoformat(),
'access_token_expiration':
refresh_token.access_token_expiration.total_seconds(),
'token': refresh_token.token,
'jwt_key': refresh_token.jwt_key,
'last_used_at':
refresh_token.last_used_at.isoformat()
if refresh_token.last_used_at else None,
'last_used_ip': refresh_token.last_used_ip,
}
for user in self._users.values()
for refresh_token in user.refresh_tokens.values()
Expand Down
21 changes: 16 additions & 5 deletions homeassistant/auth/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@

from homeassistant.util import dt as dt_util

from .const import ACCESS_TOKEN_EXPIRATION
from .util import generate_secret

TOKEN_TYPE_NORMAL = 'normal'
TOKEN_TYPE_SYSTEM = 'system'
TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN = 'long_lived_access_token'


@attr.s(slots=True)
class User:
Expand Down Expand Up @@ -37,23 +40,31 @@ class RefreshToken:
"""RefreshToken for a user to grant new access tokens."""

user = attr.ib(type=User)
client_id = attr.ib(type=str) # type: Optional[str]
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)
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, default=attr.Factory(lambda: uuid.uuid4().hex))
created_at = attr.ib(type=datetime, default=attr.Factory(dt_util.utcnow))
access_token_expiration = attr.ib(type=timedelta,
default=ACCESS_TOKEN_EXPIRATION)
token = attr.ib(type=str,
default=attr.Factory(lambda: generate_secret(64)))
jwt_key = attr.ib(type=str,
default=attr.Factory(lambda: generate_secret(64)))

last_used_at = attr.ib(type=Optional[datetime], default=None)
last_used_ip = attr.ib(type=Optional[str], default=None)


@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=str) # type: Optional[str]
auth_provider_id = attr.ib(type=Optional[str])

# Allow the auth provider to store data to represent their auth.
data = attr.ib(type=dict)
Expand Down
18 changes: 8 additions & 10 deletions homeassistant/auth/providers/legacy_api_password.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
CONFIG_SCHEMA = AUTH_PROVIDER_SCHEMA.extend({
}, extra=vol.PREVENT_EXTRA)

LEGACY_USER = 'homeassistant'
LEGACY_USER_NAME = 'Legacy API password user'


class InvalidAuthError(HomeAssistantError):
Expand Down Expand Up @@ -52,23 +52,21 @@ def async_validate_login(self, password: str) -> None:

async def async_get_or_create_credentials(
self, flow_result: Dict[str, str]) -> Credentials:
"""Return LEGACY_USER always."""
for credential in await self.async_credentials():
if credential.data['username'] == LEGACY_USER:
return credential
"""Return credentials for this login."""
credentials = await self.async_credentials()
if credentials:
return credentials[0]

return self.async_create_credentials({
'username': LEGACY_USER
})
return self.async_create_credentials({})

async def async_user_meta_for_credentials(
self, credentials: Credentials) -> UserMeta:
"""
Set name as LEGACY_USER always.
Return info for the user.

Will be used to populate info when creating a new user.
"""
return UserMeta(name=LEGACY_USER, is_active=True)
return UserMeta(name=LEGACY_USER_NAME, is_active=True)


class LegacyLoginFlow(LoginFlow):
Expand Down
Loading