def websocket_sign_path(
        hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg):
    """Handle a sign path request."""
    connection.send_message(websocket_api.result_message(msg['id'], {
        'path': async_sign_path(hass, connection.refresh_token_id, msg['path'],
                                timedelta(seconds=msg['expires']))
        }))
Example #2
0
async def ws_delete_person(hass: HomeAssistantType,
                           connection: websocket_api.ActiveConnection,
                           msg):
    """Delete a person."""
    manager = hass.data[DOMAIN]  # type: PersonManager
    await manager.async_delete_person(msg['person_id'])
    connection.send_result(msg['id'])
Example #3
0
def ws_list_person(hass: HomeAssistantType,
                   connection: websocket_api.ActiveConnection, msg):
    """List persons."""
    manager = hass.data[DOMAIN]  # type: PersonManager
    connection.send_result(msg['id'], {
        'storage': manager.storage_persons,
        'config': manager.config_persons,
    })
Example #4
0
def ws_list_person(
    hass: HomeAssistantType, connection: websocket_api.ActiveConnection, msg
):
    """List persons."""
    yaml, storage = hass.data[DOMAIN]
    connection.send_result(
        msg[ATTR_ID], {"storage": storage.async_items(), "config": yaml.async_items()}
    )
Example #5
0
async def ws_get_statistics_metadata(
    hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict
) -> None:
    """Get metadata for a list of statistic_ids."""
    instance = get_instance(hass)
    statistic_ids = await instance.async_add_executor_job(
        list_statistic_ids, hass, msg.get("statistic_ids")
    )
    connection.send_result(msg["id"], statistic_ids)
Example #6
0
async def hacs_repository_info(
    hass: HomeAssistant,
    connection: websocket_api.ActiveConnection,
    msg: dict[str, Any],
) -> None:
    """Return information about HACS."""
    hacs: HacsBase = hass.data.get(DOMAIN)
    repository = hacs.repositories.get_by_id(msg["repository_id"])
    if repository is None:
        connection.send_error(msg["id"], "repository_not_found", "Repository not found")
        return

    if not repository.updated_info:
        await repository.update_repository(ignore_issues=True, force=True)
        repository.updated_info = True

    connection.send_message(
        websocket_api.result_message(
            msg["id"],
            {
                "additional_info": repository.additional_info,
                "authors": repository.data.authors,
                "available_version": repository.display_available_version,
                "beta": repository.data.show_beta,
                "can_download": repository.can_download,
                "category": repository.data.category,
                "config_flow": repository.data.config_flow,
                "country": repository.repository_manifest.country,
                "custom": not hacs.repositories.is_default(str(repository.data.id)),
                "default_branch": repository.data.default_branch,
                "description": repository.data.description,
                "domain": repository.data.domain,
                "downloads": repository.data.downloads,
                "file_name": repository.data.file_name,
                "full_name": repository.data.full_name,
                "hide_default_branch": repository.repository_manifest.hide_default_branch,
                "homeassistant": repository.repository_manifest.homeassistant,
                "id": repository.data.id,
                "installed_version": repository.display_installed_version,
                "installed": repository.data.installed,
                "issues": repository.data.open_issues,
                "last_updated": repository.data.last_updated,
                "local_path": repository.content.path.local,
                "name": repository.display_name,
                "new": repository.data.new,
                "pending_upgrade": repository.pending_update,
                "releases": repository.data.published_tags,
                "ref": repository.ref,
                "selected_tag": repository.data.selected_tag,
                "stars": repository.data.stargazers_count,
                "state": repository.state,
                "status": repository.display_status,
                "topics": repository.data.topics,
                "version_or_commit": repository.display_version_or_commit,
            },
        )
    )
Example #7
0
async def ws_validate_statistics(hass: HomeAssistant,
                                 connection: websocket_api.ActiveConnection,
                                 msg: dict) -> None:
    """Fetch a list of available statistic_id."""
    statistic_ids = await hass.async_add_executor_job(
        validate_statistics,
        hass,
    )
    connection.send_result(msg["id"], statistic_ids)
async def handle_remove(
    hass: HomeAssistant,
    connection: websocket_api.ActiveConnection,
    msg: dict,
) -> None:
    """Remove a backup."""
    manager: BackupManager = hass.data[DOMAIN]
    await manager.remove_backup(msg["slug"])
    connection.send_result(msg["id"])
async def handle_create(
    hass: HomeAssistant,
    connection: websocket_api.ActiveConnection,
    msg: dict,
) -> None:
    """Generate a backup."""
    manager: BackupManager = hass.data[DOMAIN]
    backup = await manager.generate_backup()
    connection.send_result(msg["id"], backup)
Example #10
0
async def ws_validate_statistics(hass: HomeAssistant,
                                 connection: websocket_api.ActiveConnection,
                                 msg: dict) -> None:
    """Fetch a list of available statistic_id."""
    instance: Recorder = hass.data[DATA_INSTANCE]
    statistic_ids = await instance.async_add_executor_job(
        validate_statistics,
        hass,
    )
    connection.send_result(msg["id"], statistic_ids)
Example #11
0
def websocket_get_notifications(hass: HomeAssistant,
                                connection: websocket_api.ActiveConnection,
                                msg):
    """Return a list of persistent_notifications."""
    connection.send_message(
        websocket_api.result_message(msg['id'], [{
            key: data[key]
            for key in (ATTR_NOTIFICATION_ID, ATTR_MESSAGE, ATTR_STATUS,
                        ATTR_TITLE, ATTR_CREATED_AT)
        } for data in hass.data[DOMAIN]['notifications'].values()]))
Example #12
0
def websocket_sign_path(hass: HomeAssistant,
                        connection: websocket_api.ActiveConnection, msg):
    """Handle a sign path request."""
    connection.send_message(
        websocket_api.result_message(
            msg['id'], {
                'path':
                async_sign_path(hass, connection.refresh_token_id, msg['path'],
                                timedelta(seconds=msg['expires']))
            }))
Example #13
0
def ws_clear_statistics(hass: HomeAssistant,
                        connection: websocket_api.ActiveConnection,
                        msg: dict) -> None:
    """Clear statistics for a list of statistic_ids.

    Note: The WS call posts a job to the recorder's queue and then returns, it doesn't
    wait until the job is completed.
    """
    hass.data[DATA_INSTANCE].async_clear_statistics(msg["statistic_ids"])
    connection.send_result(msg["id"])
Example #14
0
async def ws_save_prefs(
    hass: HomeAssistant,
    connection: websocket_api.ActiveConnection,
    msg: dict,
    manager: EnergyManager,
) -> None:
    """Handle get prefs command."""
    msg_id = msg.pop("id")
    msg.pop("type")
    await manager.async_update(cast(EnergyPreferencesUpdate, msg))
    connection.send_result(msg_id, manager.data)
Example #15
0
def ws_list_person(hass: HomeAssistantType,
                   connection: websocket_api.ActiveConnection, msg):
    """List persons."""
    manager = hass.data[DOMAIN]  # type: PersonManager
    connection.send_result(
        msg["id"],
        {
            "storage": manager.storage_persons,
            "config": manager.config_persons
        },
    )
Example #16
0
async def ws_backup_end(hass: HomeAssistant,
                        connection: websocket_api.ActiveConnection,
                        msg: dict) -> None:
    """Backup end notification."""

    instance: Recorder = hass.data[DATA_INSTANCE]
    _LOGGER.info("Backup end notification, releasing write lock")
    if not instance.unlock_database():
        connection.send_error(msg["id"], "database_unlock_failed",
                              "Failed to unlock database.")
    connection.send_result(msg["id"])
Example #17
0
def handle_get(
    hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict
):
    """List all possible diagnostic handlers."""
    domain = msg["domain"]

    if (info := hass.data[DOMAIN].get(domain)) is None:
        connection.send_error(
            msg["id"], websocket_api.ERR_NOT_FOUND, "Domain not supported"
        )
        return
Example #18
0
async def ws_get_list_statistic_ids(hass: HomeAssistant,
                                    connection: websocket_api.ActiveConnection,
                                    msg: dict) -> None:
    """Fetch a list of available statistic_id."""
    statistic_ids = await get_instance(hass).async_add_executor_job(
        list_statistic_ids,
        hass,
        None,
        msg.get("statistic_type"),
    )
    connection.send_result(msg["id"], statistic_ids)
Example #19
0
def handle_info(hass: HomeAssistant,
                connection: websocket_api.ActiveConnection, msg: dict):
    """List all possible diagnostic handlers."""
    connection.send_result(
        msg["id"],
        [{
            "domain": domain,
            "handlers": {key: val is not None
                         for key, val in info.items()},
        } for domain, info in hass.data[DOMAIN].items()],
    )
Example #20
0
async def hacs_repository_ignore(
    hass: HomeAssistant,
    connection: websocket_api.ActiveConnection,
    msg: dict[str, Any],
):
    """Ignore a repository."""
    hacs: HacsBase = hass.data.get(DOMAIN)
    repository = hacs.repositories.get_by_id(msg["repository"])
    hacs.common.ignored_repositories.append(repository.data.full_name)

    await hacs.data.async_write()
    connection.send_message(websocket_api.result_message(msg["id"]))
Example #21
0
async def hacs_critical_list(
    hass: HomeAssistant,
    connection: websocket_api.ActiveConnection,
    msg: dict[str, Any],
):
    """List critical repositories."""
    connection.send_message(
        websocket_api.result_message(
            msg["id"],
            (await async_load_from_store(hass, "critical") or []),
        )
    )
Example #22
0
async def hacs_repositories_removed(
    hass: HomeAssistant,
    connection: websocket_api.ActiveConnection,
    msg: dict[str, Any],
):
    """Get information about removed repositories."""
    hacs: HacsBase = hass.data.get(DOMAIN)
    content = []
    for repo in hacs.repositories.list_removed:
        if repo.repository not in hacs.common.ignored_repositories:
            content.append(repo.to_json())
    connection.send_message(websocket_api.result_message(msg["id"], content))
Example #23
0
def ws_get_prefs(
    hass: HomeAssistant,
    connection: websocket_api.ActiveConnection,
    msg: dict,
    manager: EnergyManager,
) -> None:
    """Handle get prefs command."""
    if manager.data is None:
        connection.send_error(msg["id"], websocket_api.ERR_NOT_FOUND, "No prefs")
        return

    connection.send_result(msg["id"], manager.data)
Example #24
0
def ws_import_statistics(
    hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict
) -> None:
    """Adjust sum statistics."""
    metadata = msg["metadata"]
    stats = msg["stats"]

    if valid_entity_id(metadata["statistic_id"]):
        async_import_statistics(hass, metadata, stats)
    else:
        async_add_external_statistics(hass, metadata, stats)
    connection.send_result(msg["id"])
Example #25
0
async def websocket_delete_refresh_token(
        hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg):
    """Handle a delete refresh token request."""
    refresh_token = connection.user.refresh_tokens.get(msg["refresh_token_id"])

    if refresh_token is None:
        return websocket_api.error_message(msg["id"], "invalid_token_id",
                                           "Received invalid token")

    await hass.auth.async_remove_refresh_token(refresh_token)

    connection.send_message(websocket_api.result_message(msg["id"], {}))
Example #26
0
async def websocket_browse_media(hass: HomeAssistant,
                                 connection: ActiveConnection,
                                 msg: dict) -> None:
    """Browse available media."""
    try:
        media = await async_browse_media(hass, msg.get("media_content_id", ""))
        connection.send_result(
            msg["id"],
            media.as_dict(),
        )
    except BrowseError as err:
        connection.send_error(msg["id"], "browse_media_failed", str(err))
Example #27
0
async def websocket_delete_refresh_token(
        hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg):
    """Handle a delete refresh token request."""
    refresh_token = connection.user.refresh_tokens.get(msg['refresh_token_id'])

    if refresh_token is None:
        return websocket_api.error_message(
            msg['id'], 'invalid_token_id', 'Received invalid token')

    await hass.auth.async_remove_refresh_token(refresh_token)

    connection.send_message(
        websocket_api.result_message(msg['id'], {}))
Example #28
0
async def hacs_repository_refresh(
    hass: HomeAssistant,
    connection: websocket_api.ActiveConnection,
    msg: dict[str, Any],
):
    """Refresh a repository."""
    hacs: HacsBase = hass.data.get(DOMAIN)
    repository = hacs.repositories.get_by_id(msg["repository"])

    await repository.update_repository(ignore_issues=True, force=True)
    await hacs.data.async_write()

    connection.send_message(websocket_api.result_message(msg["id"], {}))
Example #29
0
async def ws_create_person(hass: HomeAssistantType,
                           connection: websocket_api.ActiveConnection, msg):
    """Create a person."""
    manager = hass.data[DOMAIN]  # type: PersonManager
    try:
        person = await manager.async_create_person(
            name=msg['name'],
            user_id=msg.get('user_id'),
            device_trackers=msg['device_trackers'])
        connection.send_result(msg['id'], person)
    except ValueError as err:
        connection.send_error(msg['id'],
                              websocket_api.const.ERR_INVALID_FORMAT, str(err))
Example #30
0
async def ws_backup_start(
    hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict
) -> None:
    """Backup start notification."""

    _LOGGER.info("Backup start notification, locking database for writes")
    instance = get_instance(hass)
    try:
        await instance.lock_database()
    except TimeoutError as err:
        connection.send_error(msg["id"], "timeout_error", str(err))
        return
    connection.send_result(msg["id"])
Example #31
0
def websocket_get_notifications(
        hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg):
    """Return a list of persistent_notifications."""
    connection.send_message(
        websocket_api.result_message(msg['id'], [
            {
                key: data[key] for key in (ATTR_NOTIFICATION_ID,
                                           ATTR_MESSAGE, ATTR_STATUS,
                                           ATTR_TITLE, ATTR_CREATED_AT)
            }
            for data in hass.data[DOMAIN]['notifications'].values()
        ])
    )
Example #32
0
async def hacs_repository_state(
    hass: HomeAssistant,
    connection: websocket_api.ActiveConnection,
    msg: dict[str, Any],
):
    """Set the state of a repository"""
    hacs: HacsBase = hass.data.get(DOMAIN)
    repository = hacs.repositories.get_by_id(msg["repository"])

    repository.state = msg["state"]

    await hacs.data.async_write()
    connection.send_message(websocket_api.result_message(msg["id"], {}))
Example #33
0
async def websocket_update_prefs(hass: HomeAssistant,
                                 connection: ActiveConnection,
                                 msg: dict) -> None:
    """Handle request for account info."""
    prefs = hass.data[DATA_CAMERA_PREFS]

    changes = dict(msg)
    changes.pop("id")
    changes.pop("type")
    entity_id = changes.pop("entity_id")
    await prefs.async_update(entity_id, **changes)

    connection.send_result(msg["id"], prefs.get(entity_id).as_dict())
Example #34
0
    async def ws_delete_item(
        self, hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict
    ) -> None:
        """Delete a item."""
        try:
            await self.storage_collection.async_delete_item(msg[self.item_id_key])
        except ItemNotFound:
            connection.send_error(
                msg["id"],
                websocket_api.const.ERR_NOT_FOUND,
                f"Unable to find {self.item_id_key} {msg[self.item_id_key]}",
            )

        connection.send_result(msg["id"])
Example #35
0
    async def ws_update_item(
        self, hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict
    ) -> None:
        """Update a item."""
        data = dict(msg)
        msg_id = data.pop("id")
        item_id = data.pop(self.item_id_key)
        data.pop("type")

        try:
            item = await self.storage_collection.async_update_item(item_id, data)
            connection.send_result(msg_id, item)
        except ItemNotFound:
            connection.send_error(
                msg["id"],
                websocket_api.const.ERR_NOT_FOUND,
                f"Unable to find {self.item_id_key} {item_id}",
            )
        except vol.Invalid as err:
            connection.send_error(
                msg["id"],
                websocket_api.const.ERR_INVALID_FORMAT,
                humanize_error(data, err),
            )
        except ValueError as err:
            connection.send_error(
                msg_id, websocket_api.const.ERR_INVALID_FORMAT, str(err)
            )
Example #36
0
async def ws_create_person(hass: HomeAssistantType,
                           connection: websocket_api.ActiveConnection, msg):
    """Create a person."""
    manager = hass.data[DOMAIN]  # type: PersonManager
    try:
        person = await manager.async_create_person(
            name=msg['name'],
            user_id=msg.get('user_id'),
            device_trackers=msg['device_trackers']
        )
        connection.send_result(msg['id'], person)
    except ValueError as err:
        connection.send_error(
            msg['id'], websocket_api.const.ERR_INVALID_FORMAT, str(err))
Example #37
0
async def ws_update_person(hass: HomeAssistantType,
                           connection: websocket_api.ActiveConnection, msg):
    """Update a person."""
    manager = hass.data[DOMAIN]  # type: PersonManager
    changes = {}
    for key in ('name', 'user_id', 'device_trackers'):
        if key in msg:
            changes[key] = msg[key]

    try:
        person = await manager.async_update_person(msg['person_id'], **changes)
        connection.send_result(msg['id'], person)
    except ValueError as err:
        connection.send_error(
            msg['id'], websocket_api.const.ERR_INVALID_FORMAT, str(err))
Example #38
0
async def websocket_create_long_lived_access_token(
        hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg):
    """Create or a long-lived access token."""
    refresh_token = await hass.auth.async_create_refresh_token(
        connection.user,
        client_name=msg['client_name'],
        client_icon=msg.get('client_icon'),
        token_type=TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN,
        access_token_expiration=timedelta(days=msg['lifespan']))

    access_token = hass.auth.async_create_access_token(
        refresh_token)

    connection.send_message(
        websocket_api.result_message(msg['id'], access_token))
Example #39
0
def websocket_refresh_tokens(
        hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg):
    """Return metadata of users refresh tokens."""
    current_id = connection.refresh_token_id
    connection.send_message(websocket_api.result_message(msg['id'], [{
        'id': refresh.id,
        'client_id': refresh.client_id,
        'client_name': refresh.client_name,
        'client_icon': refresh.client_icon,
        'type': refresh.token_type,
        'created_at': refresh.created_at,
        'is_current': refresh.id == current_id,
        'last_used_at': refresh.last_used_at,
        'last_used_ip': refresh.last_used_ip,
    } for refresh in connection.user.refresh_tokens.values()]))
Example #40
0
async def handle_info(hass: HomeAssistantType,
                      connection: websocket_api.ActiveConnection,
                      msg: Dict):
    """Handle an info request."""
    info_callbacks = hass.data.get(DOMAIN, {}).get('info', {})
    data = OrderedDict()
    data['homeassistant'] = \
        await hass.helpers.system_info.async_get_system_info()

    if info_callbacks:
        for domain, domain_data in zip(info_callbacks, await asyncio.gather(*[
                _info_wrapper(hass, info_callback) for info_callback
                in info_callbacks.values()
        ])):
            data[domain] = domain_data

    connection.send_message(websocket_api.result_message(msg['id'], data))
Example #41
0
async def websocket_current_user(
        hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg):
    """Return the current user."""
    user = connection.user
    enabled_modules = await hass.auth.async_get_enabled_mfa(user)

    connection.send_message(
        websocket_api.result_message(msg['id'], {
            'id': user.id,
            'name': user.name,
            'is_owner': user.is_owner,
            'is_admin': user.is_admin,
            'credentials': [{'auth_provider_type': c.auth_provider_type,
                             'auth_provider_id': c.auth_provider_id}
                            for c in user.credentials],
            'mfa_modules': [{
                'id': module.id,
                'name': module.name,
                'enabled': module.id in enabled_modules,
            } for module in hass.auth.auth_mfa_modules],
        }))
Example #42
0
async def websocket_get_user_registrations(
        hass: HomeAssistantType, connection: ActiveConnection,
        msg: dict) -> None:
    """Return all registrations or just registrations for given user ID."""
    user_id = msg.get(CONF_USER_ID, connection.user.id)

    if user_id != connection.user.id and not connection.user.is_admin:
        # If user ID is provided and is not current user ID and current user
        # isn't an admin user
        connection.send_error(msg['id'], ERR_UNAUTHORIZED, "Unauthorized")
        return

    user_registrations = []

    for config_entry in hass.config_entries.async_entries(domain=DOMAIN):
        registration = config_entry.data
        if connection.user.is_admin or registration[CONF_USER_ID] is user_id:
            user_registrations.append(safe_registration(registration))

    connection.send_message(
        result_message(msg['id'], user_registrations))
Example #43
0
async def websocket_delete_registration(hass: HomeAssistantType,
                                        connection: ActiveConnection,
                                        msg: dict) -> None:
    """Delete the registration for the given webhook_id."""
    user = connection.user

    webhook_id = msg.get(CONF_WEBHOOK_ID)
    if webhook_id is None:
        connection.send_error(msg['id'], ERR_INVALID_FORMAT,
                              "Webhook ID not provided")
        return

    config_entry = hass.data[DOMAIN][DATA_CONFIG_ENTRIES][webhook_id]

    registration = config_entry.data

    if registration is None:
        connection.send_error(msg['id'], ERR_NOT_FOUND,
                              "Webhook ID not found in storage")
        return

    if registration[CONF_USER_ID] != user.id and not user.is_admin:
        return error_message(
            msg['id'], ERR_UNAUTHORIZED, 'User is not registration owner')

    await hass.config_entries.async_remove(config_entry.entry_id)

    hass.data[DOMAIN][DATA_DELETED_IDS].append(webhook_id)

    store = hass.data[DOMAIN][DATA_STORE]

    try:
        await store.async_save(savable_state(hass))
    except HomeAssistantError:
        return error_message(
            msg['id'], 'internal_error', 'Error deleting registration')

    if (CONF_CLOUDHOOK_URL in registration and
            "cloud" in hass.config.components):
        await async_delete_cloudhook(hass, webhook_id)

    connection.send_message(result_message(msg['id'], 'ok'))