async def post(self, request, data): """Handle the POST request for device registration.""" hass = request.app['hass'] resp = {} webhook_id = generate_secret() data[CONF_WEBHOOK_ID] = resp[CONF_WEBHOOK_ID] = webhook_id if data[ATTR_SUPPORTS_ENCRYPTION] and supports_encryption(): secret = generate_secret(16) data[CONF_SECRET] = resp[CONF_SECRET] = secret data[CONF_USER_ID] = request['hass_user'].id hass.data[DOMAIN][webhook_id] = data try: await self._store.async_save(hass.data[DOMAIN]) except HomeAssistantError: return self.json_message("Error saving device.", HTTP_INTERNAL_SERVER_ERROR) register_device_webhook(hass, self._store, data) return self.json(resp, status_code=HTTP_CREATED)
async def post(self, request: Request, data: Dict) -> Response: """Handle the POST request for registration.""" hass = request.app['hass'] if ATTR_APP_COMPONENT in data: component = get_component(hass, data[ATTR_APP_COMPONENT]) if component is None: fmt_str = "{} is not a valid component." msg = fmt_str.format(data[ATTR_APP_COMPONENT]) return error_response(ERR_INVALID_COMPONENT, msg) if (hasattr(component, 'DEPENDENCIES') is False or (hasattr(component, 'DEPENDENCIES') and DOMAIN not in component.DEPENDENCIES)): fmt_str = "{} is not compatible with mobile_app." msg = fmt_str.format(data[ATTR_APP_COMPONENT]) return error_response(ERR_INVALID_COMPONENT, msg) webhook_id = generate_secret() if hass.components.cloud.async_active_subscription(): data[CONF_CLOUDHOOK_URL] = \ await async_create_cloudhook(hass, webhook_id) data[ATTR_DEVICE_ID] = str(uuid.uuid4()).replace("-", "") data[CONF_WEBHOOK_ID] = webhook_id if data[ATTR_SUPPORTS_ENCRYPTION] and supports_encryption(): from nacl.secret import SecretBox data[CONF_SECRET] = generate_secret(SecretBox.KEY_SIZE) data[CONF_USER_ID] = request['hass_user'].id ctx = {'source': 'registration'} await hass.async_create_task( hass.config_entries.flow.async_init(DOMAIN, context=ctx, data=data)) remote_ui_url = None try: remote_ui_url = async_remote_ui_url(hass) except CloudNotAvailable: pass return self.json( { CONF_CLOUDHOOK_URL: data.get(CONF_CLOUDHOOK_URL), CONF_REMOTE_UI_URL: remote_ui_url, CONF_SECRET: data.get(CONF_SECRET), CONF_WEBHOOK_ID: data[CONF_WEBHOOK_ID], }, status_code=HTTP_CREATED)
def request_stream(hass, stream_source, *, fmt='hls', keepalive=False, options=None): """Set up stream with token.""" if DOMAIN not in hass.config.components: raise HomeAssistantError("Stream component is not set up.") if options is None: options = {} # For RTSP streams, prefer TCP if isinstance(stream_source, str) \ and stream_source[:7] == 'rtsp://' and not options: options['rtsp_flags'] = 'prefer_tcp' try: streams = hass.data[DOMAIN][ATTR_STREAMS] stream = streams.get(stream_source) if not stream: stream = Stream(hass, stream_source, options=options, keepalive=keepalive) streams[stream_source] = stream else: # Update keepalive option on existing stream stream.keepalive = keepalive # Add provider stream.add_provider(fmt) if not stream.access_token: stream.access_token = generate_secret() stream.start() return hass.data[DOMAIN][ATTR_ENDPOINTS][fmt].format( stream.access_token) except Exception: raise HomeAssistantError('Unable to get stream')
async def async_step_user(self, user_input=None): """Handle a user initiated set up flow to create OwnTracks webhook.""" if self._async_current_entries(): return self.async_abort(reason="one_instance_allowed") if user_input is None: return self.async_show_form(step_id="user") webhook_id, webhook_url, cloudhook = await self._get_webhook_id() secret = generate_secret(16) if supports_encryption(): secret_desc = f"The encryption key is {secret} (on Android under preferences -> advanced)" else: secret_desc = "Encryption is not supported because nacl is not installed." return self.async_create_entry( title="OwnTracks", data={ CONF_WEBHOOK_ID: webhook_id, CONF_SECRET: secret, CONF_CLOUDHOOK: cloudhook, }, description_placeholders={ "secret": secret_desc, "webhook_url": webhook_url, "android_url": "https://play.google.com/store/apps/details?id=org.owntracks.android", "ios_url": "https://itunes.apple.com/us/app/owntracks/id692424691?mt=8", "docs_url": "https://www.home-assistant.io/integrations/owntracks/", }, )
def setup(hass, config) -> bool: """Set up the Rachio component.""" from rachiopy import Rachio # Listen for incoming webhook connections hass.http.register_view(RachioWebhookView()) # Configure API api_key = config[DOMAIN].get(CONF_API_KEY) rachio = Rachio(api_key) # Get the URL of this server custom_url = config[DOMAIN].get(CONF_CUSTOM_URL) hass_url = hass.config.api.base_url if custom_url is None else custom_url rachio.webhook_auth = generate_secret() rachio.webhook_url = hass_url + WEBHOOK_PATH # Get the API user try: person = RachioPerson(hass, rachio) except AssertionError as error: _LOGGER.error("Could not reach the Rachio API: %s", error) return False # Check for Rachio controller devices if not person.controllers: _LOGGER.error("No Rachio devices found in account %s", person.username) return False _LOGGER.info("%d Rachio device(s) found", len(person.controllers)) # Enable component hass.data[DOMAIN] = person return True
def request_stream(hass, stream_source, *, fmt='hls', keepalive=False, options=None): """Set up stream with token.""" if DOMAIN not in hass.config.components: raise HomeAssistantError("Stream component is not set up.") if options is None: options = {} try: streams = hass.data[DOMAIN][ATTR_STREAMS] stream = streams.get(stream_source) if not stream: stream = Stream(hass, stream_source, options=options, keepalive=keepalive) streams[stream_source] = stream # Add provider stream.add_provider(fmt) if not stream.access_token: stream.access_token = generate_secret() stream.start() return hass.data[DOMAIN][ATTR_ENDPOINTS][fmt].format( stream.access_token) except Exception: raise HomeAssistantError('Unable to get stream')
def setup(hass, config) -> bool: """Set up the Rachio component.""" from rachiopy import Rachio # Listen for incoming webhook connections hass.http.register_view(RachioWebhookView()) # Configure API api_key = config[DOMAIN].get(CONF_API_KEY) rachio = Rachio(api_key) # Get the URL of this server custom_url = config[DOMAIN].get(CONF_CUSTOM_URL) hass_url = hass.config.api.base_url if custom_url is None else custom_url rachio.webhook_auth = generate_secret() rachio.webhook_url = hass_url + WEBHOOK_PATH # Get the API user try: person = RachioPerson(hass, rachio) except AssertionError as error: _LOGGER.error("Could not reach the Rachio API: %s", error) return False # Check for Rachio controller devices if not person.controllers: _LOGGER.error("No Rachio devices found in account %s", person.username) return False else: _LOGGER.info("%d Rachio device(s) found", len(person.controllers)) # Enable component hass.data[DOMAIN] = person return True
async def async_load(self): """Load stored data.""" data = await self._store.async_load() if data is None: data = {'salt': generate_secret(), 'users': []} self._data = data
def _encode_jwt(hass: HomeAssistant, data: dict) -> str: """JWT encode data.""" secret = hass.data.get(DATA_JWT_SECRET) if secret is None: secret = hass.data[DATA_JWT_SECRET] = generate_secret() return jwt.encode(data, secret, algorithm="HS256").decode()
async def async_step_import(self, user_input): """Import a config flow from configuration.""" webhook_id = self.hass.components.webhook.async_generate_id() secret = generate_secret(16) return self.async_create_entry(title="OwnTracks", data={ CONF_WEBHOOK_ID: webhook_id, CONF_SECRET: secret })
async def async_step_import(self, user_input): """Import a config flow from configuration.""" webhook_id, _webhook_url, cloudhook = await self._get_webhook_id() secret = generate_secret(16) return self.async_create_entry(title="OwnTracks", data={ CONF_WEBHOOK_ID: webhook_id, CONF_SECRET: secret, CONF_CLOUDHOOK: cloudhook, })
async def post(self, request: Request, data: Dict) -> Response: """Handle the POST request for registration.""" hass = request.app["hass"] webhook_id = generate_secret() cloud_loaded = "cloud" in hass.config.components if cloud_loaded and hass.components.cloud.async_active_subscription(): data[ CONF_CLOUDHOOK_URL] = await hass.components.cloud.async_create_cloudhook( webhook_id) data[ATTR_DEVICE_ID] = str(uuid.uuid4()).replace("-", "") data[CONF_WEBHOOK_ID] = webhook_id if data[ATTR_SUPPORTS_ENCRYPTION] and supports_encryption(): data[CONF_SECRET] = generate_secret(SecretBox.KEY_SIZE) data[CONF_USER_ID] = request["hass_user"].id ctx = {"source": "registration"} await hass.async_create_task( hass.config_entries.flow.async_init(DOMAIN, context=ctx, data=data)) remote_ui_url = None if cloud_loaded: try: remote_ui_url = hass.components.cloud.async_remote_ui_url() except hass.components.cloud.CloudNotAvailable: pass return self.json( { CONF_CLOUDHOOK_URL: data.get(CONF_CLOUDHOOK_URL), CONF_REMOTE_UI_URL: remote_ui_url, CONF_SECRET: data.get(CONF_SECRET), CONF_WEBHOOK_ID: data[CONF_WEBHOOK_ID], }, status_code=HTTP_CREATED, )
async def async_step_import(self, user_input): """Import a config flow from configuration.""" webhook_id = self.hass.components.webhook.async_generate_id() secret = generate_secret(16) return self.async_create_entry( title="OwnTracks", data={ CONF_WEBHOOK_ID: webhook_id, CONF_SECRET: secret } )
async def async_load(self): """Load stored data.""" data = await self._store.async_load() if data is None: data = { 'salt': generate_secret(), 'users': [] } self._data = data
def request_stream(hass, stream_source, *, fmt="hls", keepalive=False, options=None): """Set up stream with token.""" if DOMAIN not in hass.config.components: raise HomeAssistantError("Stream integration is not set up.") if DATA_UVLOOP_WARN not in hass.data: hass.data[DATA_UVLOOP_WARN] = True # Warn about https://github.com/home-assistant/home-assistant/issues/22999 if (uvloop is not None and isinstance(hass.loop, uvloop.Loop) and ("shell_command" in hass.config.components or "ffmpeg" in hass.config.components)): _LOGGER.warning( "You are using UVLoop with stream and shell_command. This is known to cause issues. Please uninstall uvloop." ) if options is None: options = {} # For RTSP streams, prefer TCP if (isinstance(stream_source, str) and stream_source[:7] == "rtsp://" and not options): options["rtsp_flags"] = "prefer_tcp" options["stimeout"] = "5000000" try: streams = hass.data[DOMAIN][ATTR_STREAMS] stream = streams.get(stream_source) if not stream: stream = Stream(hass, stream_source, options=options, keepalive=keepalive) streams[stream_source] = stream else: # Update keepalive option on existing stream stream.keepalive = keepalive # Add provider stream.add_provider(fmt) if not stream.access_token: stream.access_token = generate_secret() stream.start() return hass.data[DOMAIN][ATTR_ENDPOINTS][fmt].format( stream.access_token) except Exception: raise HomeAssistantError("Unable to get stream")
async def post(self, request: Request, data: Dict) -> Response: """Handle the POST request for registration.""" hass = request.app['hass'] webhook_id = generate_secret() if hass.components.cloud.async_active_subscription(): data[CONF_CLOUDHOOK_URL] = \ await async_create_cloudhook(hass, webhook_id) data[ATTR_DEVICE_ID] = str(uuid.uuid4()).replace("-", "") data[CONF_WEBHOOK_ID] = webhook_id if data[ATTR_SUPPORTS_ENCRYPTION] and supports_encryption(): from nacl.secret import SecretBox data[CONF_SECRET] = generate_secret(SecretBox.KEY_SIZE) data[CONF_USER_ID] = request['hass_user'].id ctx = {'source': 'registration'} await hass.async_create_task( hass.config_entries.flow.async_init(DOMAIN, context=ctx, data=data)) remote_ui_url = None try: remote_ui_url = async_remote_ui_url(hass) except CloudNotAvailable: pass return self.json({ CONF_CLOUDHOOK_URL: data.get(CONF_CLOUDHOOK_URL), CONF_REMOTE_UI_URL: remote_ui_url, CONF_SECRET: data.get(CONF_SECRET), CONF_WEBHOOK_ID: data[CONF_WEBHOOK_ID], }, status_code=HTTP_CREATED)
def async_sign_path(hass, refresh_token_id, path, expiration): """Sign a path for temporary access without auth header.""" secret = hass.data.get(DATA_SIGN_SECRET) if secret is None: secret = hass.data[DATA_SIGN_SECRET] = generate_secret() now = dt_util.utcnow() return "{}?{}={}".format(path, SIGN_QUERY_PARAM, jwt.encode({ 'iss': refresh_token_id, 'path': path, 'iat': now, 'exp': now + expiration, }, secret, algorithm='HS256').decode())
async def async_step_import(self, user_input): """Import a config flow from configuration.""" if self._async_current_entries(): return self.async_abort(reason="one_instance_allowed") webhook_id, _webhook_url, cloudhook = await self._get_webhook_id() secret = generate_secret(16) return self.async_create_entry( title="OwnTracks", data={ CONF_WEBHOOK_ID: webhook_id, CONF_SECRET: secret, CONF_CLOUDHOOK: cloudhook, }, )
async def async_step_user(self, user_input=None): """Handle a user initiated set up flow to create OwnTracks webhook.""" if self._async_current_entries(): return self.async_abort(reason="one_instance_allowed") if user_input is None: return self.async_show_form(step_id="user") webhook_id, webhook_url, cloudhook = await self._get_webhook_id() # from homeassistant.components.ais_dom import ais_global gate_id = ais_global.get_sercure_android_id_dom() webhook_url = webhook_url.replace("localhost:8180", gate_id + ".paczka.pro") secret = generate_secret(16) if supports_encryption(): secret_desc = ( "The encryption key is {} " "(on Android under preferences -> advanced)".format(secret)) else: secret_desc = ( "Encryption is not supported because libsodium is not " "installed.") return self.async_create_entry( title="OwnTracks", data={ CONF_WEBHOOK_ID: webhook_id, CONF_SECRET: secret, CONF_CLOUDHOOK: cloudhook, }, description_placeholders={ "secret": "", "webhook_url": webhook_url, "android_url": "https://play.google.com/store/apps/details?" "id=org.owntracks.android", "ios_url": "https://itunes.apple.com/us/app/owntracks/id692424691?mt=8", "docs_url": "https://sviete.github.io/AIS-docs/docs/en/next/ais_bramka_presence_detection.html", }, )
async def async_step_user(self, user_input=None): """Handle a user initiated set up flow to create OwnTracks webhook.""" if self._async_current_entries(): return self.async_abort(reason='one_instance_allowed') if user_input is None: return self.async_show_form( step_id='user', ) webhook_id = self.hass.components.webhook.async_generate_id() webhook_url = \ self.hass.components.webhook.async_generate_url(webhook_id) secret = generate_secret(16) if supports_encryption(): secret_desc = ( "The encryption key is {} " "(on Android under preferences -> advanced)".format(secret)) else: secret_desc = ( "Encryption is not supported because libsodium is not " "installed.") return self.async_create_entry( title="OwnTracks", data={ CONF_WEBHOOK_ID: webhook_id, CONF_SECRET: secret }, description_placeholders={ 'secret': secret_desc, 'webhook_url': webhook_url, 'android_url': 'https://play.google.com/store/apps/details?' 'id=org.owntracks.android', 'ios_url': 'https://itunes.apple.com/us/app/owntracks/id692424691?mt=8', 'docs_url': 'https://www.home-assistant.io/components/owntracks/' } )
def async_generate_id(): """Generate a webhook_id.""" return generate_secret(entropy=32)