Пример #1
0
    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)
Пример #2
0
    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)
Пример #3
0
    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)
Пример #4
0
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')
Пример #5
0
    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/",
            },
        )
Пример #6
0
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
Пример #7
0
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')
Пример #8
0
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
Пример #10
0
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()
Пример #11
0
 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
                                    })
Пример #12
0
 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,
                                    })
Пример #13
0
    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,
        )
Пример #14
0
 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
         }
     )
Пример #15
0
    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
Пример #16
0
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")
Пример #17
0
    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)
Пример #18
0
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())
Пример #19
0
 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,
         },
     )
Пример #20
0
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())
Пример #21
0
    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",
            },
        )
Пример #22
0
    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/'
            }
        )
Пример #23
0
    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/'
            }
        )
Пример #24
0
def async_generate_id():
    """Generate a webhook_id."""
    return generate_secret(entropy=32)
Пример #25
0
def async_generate_id():
    """Generate a webhook_id."""
    return generate_secret(entropy=32)