async def websocket_delete(opp, connection, msg):
    """Delete username and related credential."""
    provider = _get_provider(opp)
    await provider.async_initialize()

    credentials = await provider.async_get_or_create_credentials(
        {"username": msg["username"]})

    # if not new, an existing credential exists.
    # Removing the credential will also remove the auth.
    if not credentials.is_new:
        await opp.auth.async_remove_credentials(credentials)

        connection.send_message(websocket_api.result_message(msg["id"]))
        return

    try:
        provider.data.async_remove_auth(msg["username"])
        await provider.data.async_save()
    except auth_ha.InvalidUser:
        connection.send_message(
            websocket_api.error_message(msg["id"], "auth_not_found",
                                        "Given username was not found."))
        return

    connection.send_message(websocket_api.result_message(msg["id"]))
    async def async_setup_flow(msg):
        """Return a setup flow for mfa auth module."""
        flow_manager = opp.data[DATA_SETUP_FLOW_MGR]

        flow_id = msg.get("flow_id")
        if flow_id is not None:
            result = await flow_manager.async_configure(
                flow_id, msg.get("user_input"))
            connection.send_message(
                websocket_api.result_message(msg["id"],
                                             _prepare_result_json(result)))
            return

        mfa_module_id = msg.get("mfa_module_id")
        mfa_module = opp.auth.get_auth_mfa_module(mfa_module_id)
        if mfa_module is None:
            connection.send_message(
                websocket_api.error_message(
                    msg["id"], "no_module",
                    f"MFA module {mfa_module_id} is not found"))
            return

        result = await flow_manager.async_init(
            mfa_module_id, data={"user_id": connection.user.id})

        connection.send_message(
            websocket_api.result_message(msg["id"],
                                         _prepare_result_json(result)))
예제 #3
0
def websocket_get_themes(opp, connection, msg):
    """Handle get themes command."""
    if opp.config.safe_mode:
        connection.send_message(
            websocket_api.result_message(
                msg["id"],
                {
                    "themes": {
                        "safe_mode": {
                            "primary-color": "#db4437",
                            "accent-color": "#ffca28",
                        }
                    },
                    "default_theme": "safe_mode",
                },
            ))
        return

    connection.send_message(
        websocket_api.result_message(
            msg["id"],
            {
                "themes": opp.data[DATA_THEMES],
                "default_theme": opp.data[DATA_DEFAULT_THEME],
                "default_dark_theme": opp.data.get(DATA_DEFAULT_DARK_THEME),
            },
        ))
예제 #4
0
async def websocket_list_devices(opp, connection, msg):
    """Handle list devices command."""
    registry = await async_get_registry(opp)
    connection.send_message(
        websocket_api.result_message(
            msg["id"],
            [_entry_dict(entry) for entry in registry.devices.values()]))
예제 #5
0
async def websocket_current_user(opp: OpenPeerPower,
                                 connection: websocket_api.ActiveConnection,
                                 msg):
    """Return the current user."""
    user = connection.user
    enabled_modules = await opp.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 opp.auth.auth_mfa_modules],
            },
        ))
예제 #6
0
async def websocket_update_prefs(opp, connection, msg):
    """Handle request for account info."""
    cloud = opp.data[DOMAIN]

    changes = dict(msg)
    changes.pop("id")
    changes.pop("type")

    # If we turn alexa linking on, validate that we can fetch access token
    if changes.get(PREF_ALEXA_REPORT_STATE):
        try:
            with async_timeout.timeout(10):
                await cloud.client.alexa_config.async_get_access_token()
        except asyncio.TimeoutError:
            connection.send_error(
                msg["id"], "alexa_timeout", "Timeout validating Alexa access token."
            )
            return
        except (alexa_errors.NoTokenAvailable, RequireRelink):
            connection.send_error(
                msg["id"],
                "alexa_relink",
                "Please go to the Alexa app and re-link the Open Peer Power "
                "skill and then try to enable state reporting.",
            )
            return

    await cloud.client.prefs.async_update(**changes)

    connection.send_message(websocket_api.result_message(msg["id"]))
예제 #7
0
async def websocket_subscription(opp, connection, msg):
    """Handle request for account info."""

    cloud = opp.data[DOMAIN]

    with async_timeout.timeout(REQUEST_TIMEOUT):
        response = await cloud.fetch_subscription_info()

    if response.status != 200:
        connection.send_message(
            websocket_api.error_message(
                msg["id"], "request_failed", "Failed to request subscription"
            )
        )

    data = await response.json()

    # Check if a user is subscribed but local info is outdated
    # In that case, let's refresh and reconnect
    if data.get("provider") and not cloud.is_connected:
        _LOGGER.debug("Found disconnected account with valid subscriotion, connecting")
        await opp.async_add_executor_job(cloud.auth.renew_access_token)

        # Cancel reconnect in progress
        if cloud.iot.state != STATE_DISCONNECTED:
            await cloud.iot.disconnect()

        opp.async_create_task(cloud.iot.connect())

    connection.send_message(websocket_api.result_message(msg["id"], data))
예제 #8
0
def websocket_subscribe_breakpoint_events(opp, connection, msg):
    """Subscribe to breakpoint events."""
    @callback
    def breakpoint_hit(key, run_id, node):
        """Forward events to websocket."""
        connection.send_message(
            websocket_api.event_message(
                msg["id"],
                {
                    "domain": key[0],
                    "item_id": key[1],
                    "run_id": run_id,
                    "node": node,
                },
            ))

    remove_signal = async_dispatcher_connect(opp, SCRIPT_BREAKPOINT_HIT,
                                             breakpoint_hit)

    @callback
    def unsub():
        """Unsubscribe from breakpoint events."""
        remove_signal()
        if (SCRIPT_BREAKPOINT_HIT not in opp.data.get(DATA_DISPATCHER, {})
                or not opp.data[DATA_DISPATCHER][SCRIPT_BREAKPOINT_HIT]):
            breakpoint_clear_all(opp)
            async_dispatcher_send(opp, SCRIPT_DEBUG_CONTINUE_ALL)

    connection.subscriptions[msg["id"]] = unsub

    connection.send_message(websocket_api.result_message(msg["id"]))
예제 #9
0
async def websocket_update(opp, connection, msg):
    """Update a user."""
    user = await opp.auth.async_get_user(msg.pop("user_id"))

    if not user:
        connection.send_message(
            websocket_api.error_message(msg["id"],
                                        websocket_api.const.ERR_NOT_FOUND,
                                        "User not found"))
        return

    if user.system_generated:
        connection.send_message(
            websocket_api.error_message(
                msg["id"],
                "cannot_modify_system_generated",
                "Unable to update system generated users.",
            ))
        return

    msg.pop("type")
    msg_id = msg.pop("id")

    await opp.auth.async_update_user(user, **msg)

    connection.send_message(
        websocket_api.result_message(msg_id, {"user": _user_info(user)}))
예제 #10
0
async def websocket_set_user_data(opp, connection, msg, store, data):
    """Handle set global data command.

    Async friendly.
    """
    data[msg["key"]] = msg["value"]
    await store.async_save(data)
    connection.send_message(websocket_api.result_message(msg["id"]))
예제 #11
0
def websocket_cloud_status(opp, connection, msg):
    """Handle request for account info.

    Async friendly.
    """
    cloud = opp.data[DOMAIN]
    connection.send_message(
        websocket_api.result_message(msg["id"], _account_data(cloud))
    )
예제 #12
0
def websocket_list(opp, connection, msg):
    """Return a list of webhooks."""
    handlers = opp.data.setdefault(DOMAIN, {})
    result = [
        {"webhook_id": webhook_id, "domain": info["domain"], "name": info["name"]}
        for webhook_id, info in handlers.items()
    ]

    connection.send_message(websocket_api.result_message(msg["id"], result))
예제 #13
0
async def websocket_get_translations(opp, connection, msg):
    """Handle get translations command.

    Async friendly.
    """
    resources = await async_get_translations(opp, msg["language"])
    connection.send_message(
        websocket_api.result_message(msg["id"], {"resources": resources})
    )
예제 #14
0
async def websocket_get_user_data(opp, connection, msg, store, data):
    """Handle get global data command.

    Async friendly.
    """
    connection.send_message(
        websocket_api.result_message(
            msg["id"],
            {"value": data.get(msg["key"]) if "key" in msg else data}))
async def websocket_update_device(opp, connection, msg):
    """Handle update area websocket command."""
    registry = await async_get_registry(opp)

    msg.pop("type")
    msg_id = msg.pop("id")

    entry = registry.async_update_device(**msg)

    connection.send_message(websocket_api.result_message(msg_id, _entry_dict(entry)))
예제 #16
0
def websocket_get_panels(opp, connection, msg):
    """Handle get panels command."""
    user_is_admin = connection.user.is_admin
    panels = {
        panel_key: panel.to_response()
        for panel_key, panel in connection.opp.data[DATA_PANELS].items()
        if user_is_admin or not panel.require_admin
    }

    connection.send_message(websocket_api.result_message(msg["id"], panels))
예제 #17
0
async def websocket_subscribe(opp: OpenPeerPower, connection: ActiveConnection,
                              msg: dict):
    """Subscribe to supervisor events."""
    @callback
    def forward_messages(data):
        """Forward events to websocket."""
        connection.send_message(websocket_api.event_message(msg[WS_ID], data))

    connection.subscriptions[msg[WS_ID]] = async_dispatcher_connect(
        opp, EVENT_SUPERVISOR_EVENT, forward_messages)
    connection.send_message(websocket_api.result_message(msg[WS_ID]))
예제 #18
0
async def websocket_list_areas(opp, connection, msg):
    """Handle list areas command."""
    registry = await async_get_registry(opp)
    connection.send_message(
        websocket_api.result_message(
            msg["id"],
            [{
                "name": entry.name,
                "area_id": entry.id
            } for entry in registry.async_list_areas()],
        ))
예제 #19
0
async def websocket_create_area(opp, connection, msg):
    """Create area command."""
    registry = await async_get_registry(opp)
    try:
        entry = registry.async_create(msg["name"])
    except ValueError as err:
        connection.send_message(
            websocket_api.error_message(msg["id"], "invalid_info", str(err)))
    else:
        connection.send_message(
            websocket_api.result_message(msg["id"], _entry_dict(entry)))
예제 #20
0
async def websocket_get_translations(opp, connection, msg):
    """Handle get translations command."""
    resources = await async_get_translations(
        opp,
        msg["language"],
        msg["category"],
        msg.get("integration"),
        msg.get("config_flow"),
    )
    connection.send_message(
        websocket_api.result_message(msg["id"], {"resources": resources}))
예제 #21
0
async def websocket_delete_refresh_token(
        opp: OpenPeerPower, 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 opp.auth.async_remove_refresh_token(refresh_token)

    connection.send_message(websocket_api.result_message(msg["id"], {}))
예제 #22
0
async def websocket_delete_area(opp, connection, msg):
    """Delete area command."""
    registry = await async_get_registry(opp)

    try:
        await registry.async_delete(msg["area_id"])
    except KeyError:
        connection.send_message(
            websocket_api.error_message(msg["id"], "invalid_info",
                                        "Area ID doesn't exist"))
    else:
        connection.send_message(
            websocket_api.result_message(msg["id"], "success"))
예제 #23
0
async def websocket_create_long_lived_access_token(
    opp: OpenPeerPower, connection: websocket_api.ActiveConnection, msg
):
    """Create or a long-lived access token."""
    refresh_token = await opp.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 = opp.auth.async_create_access_token(refresh_token)

    connection.send_message(websocket_api.result_message(msg["id"], access_token))
예제 #24
0
async def websocket_remove_entity(opp, connection, msg):
    """Handle remove entity websocket command.

    Async friendly.
    """
    registry = await async_get_registry(opp)

    if msg["entity_id"] not in registry.entities:
        connection.send_message(
            websocket_api.error_message(msg["id"], ERR_NOT_FOUND,
                                        "Entity not found"))
        return

    registry.async_remove(msg["entity_id"])
    connection.send_message(websocket_api.result_message(msg["id"]))
예제 #25
0
async def websocket_handle_update(opp, connection, msg):
    """Handle update shopping_list item."""
    msg_id = msg.pop("id")
    item_id = msg.pop("item_id")
    msg.pop("type")
    data = msg

    try:
        item = await opp.data[DOMAIN].async_update(item_id, data)
        opp.bus.async_fire(EVENT, {"action": "update", "item": item})
        connection.send_message(websocket_api.result_message(msg_id, item))
    except KeyError:
        connection.send_message(
            websocket_api.error_message(msg_id, "item_not_found", "Item not found")
        )
예제 #26
0
async def websocket_get_entity(opp, connection, msg):
    """Handle get entity registry entry command.

    Async friendly.
    """
    registry = await async_get_registry(opp)
    entry = registry.entities.get(msg["entity_id"])

    if entry is None:
        connection.send_message(
            websocket_api.error_message(msg["id"], ERR_NOT_FOUND,
                                        "Entity not found"))
        return

    connection.send_message(
        websocket_api.result_message(msg["id"], _entry_ext_dict(entry)))
예제 #27
0
def websocket_sign_path(opp: OpenPeerPower,
                        connection: websocket_api.ActiveConnection, msg):
    """Handle a sign path request."""
    connection.send_message(
        websocket_api.result_message(
            msg["id"],
            {
                "path":
                async_sign_path(
                    opp,
                    connection.refresh_token_id,
                    msg["path"],
                    timedelta(seconds=msg["expires"]),
                )
            },
        ))
    async def async_depose(msg):
        """Remove user from mfa auth module."""
        mfa_module_id = msg["mfa_module_id"]
        try:
            await opp.auth.async_disable_user_mfa(connection.user,
                                                  msg["mfa_module_id"])
        except ValueError as err:
            connection.send_message(
                websocket_api.error_message(
                    msg["id"],
                    "disable_failed",
                    f"Cannot disable MFA Module {mfa_module_id}: {err}",
                ))
            return

        connection.send_message(websocket_api.result_message(
            msg["id"], "done"))
예제 #29
0
async def websocket_delete(opp, connection, msg):
    """Delete a user."""
    if msg["user_id"] == connection.user.id:
        connection.send_message(
            websocket_api.error_message(msg["id"], "no_delete_self",
                                        "Unable to delete your own account"))
        return

    user = await opp.auth.async_get_user(msg["user_id"])

    if not user:
        connection.send_message(
            websocket_api.error_message(msg["id"], "not_found",
                                        "User not found"))
        return

    await opp.auth.async_remove_user(user)

    connection.send_message(websocket_api.result_message(msg["id"]))
예제 #30
0
def websocket_refresh_tokens(opp: OpenPeerPower,
                             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()],
        ))