fix some pylint findings
This commit is contained in:
parent
c400c87aab
commit
8bfd5c241a
7 changed files with 215 additions and 313 deletions
|
|
@ -1,5 +1,4 @@
|
||||||
"""Models module."""
|
"""Models module."""
|
||||||
import json
|
|
||||||
import uuid
|
import uuid
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
@ -87,28 +86,6 @@ class VacBotClient:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class EcoVacs_Login:
|
|
||||||
"""Ecovacs login."""
|
|
||||||
|
|
||||||
accessToken = ""
|
|
||||||
country = ""
|
|
||||||
email = ""
|
|
||||||
uid = ""
|
|
||||||
username = ""
|
|
||||||
|
|
||||||
def toJSON(self) -> str:
|
|
||||||
"""Convert to json."""
|
|
||||||
return json.dumps(self, default=lambda o: o.__dict__, sort_keys=False)
|
|
||||||
|
|
||||||
|
|
||||||
class EcoVacsHome_Login(EcoVacs_Login):
|
|
||||||
"""Ecovacs home login."""
|
|
||||||
|
|
||||||
loginName = ""
|
|
||||||
mobile: str | None = ""
|
|
||||||
ucUid = ""
|
|
||||||
|
|
||||||
|
|
||||||
class OAuth:
|
class OAuth:
|
||||||
"""Oauth."""
|
"""Oauth."""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ class ProxyClient:
|
||||||
)
|
)
|
||||||
|
|
||||||
bumper.mqtt_helperbot.publish(topic, message.data)
|
bumper.mqtt_helperbot.publish(topic, message.data)
|
||||||
except Exception: # pylint: disable=broad-except
|
except Exception:
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
"An error occurred during handling a message", exc_info=True
|
"An error occurred during handling a message", exc_info=True
|
||||||
)
|
)
|
||||||
|
|
@ -109,6 +109,7 @@ class ProxyClient:
|
||||||
|
|
||||||
|
|
||||||
class _NoCertVerifyClient(MQTTClient): # type:ignore[misc]
|
class _NoCertVerifyClient(MQTTClient): # type:ignore[misc]
|
||||||
|
# pylint: disable=all
|
||||||
"""
|
"""
|
||||||
Mqtt client, which is not verify the certificate.
|
Mqtt client, which is not verify the certificate.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -89,9 +89,10 @@ class MQTTServer:
|
||||||
return self._broker.transitions.state
|
return self._broker.transitions.state
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def broker(self) -> Broker:
|
def sessions(self) -> list[Session]:
|
||||||
"""Get MQTT broker."""
|
"""Get sessions."""
|
||||||
return self._broker
|
# pylint: disable-next=protected-access
|
||||||
|
return [session for (session, _) in self._broker._sessions.values()]
|
||||||
|
|
||||||
async def start(self) -> None:
|
async def start(self) -> None:
|
||||||
"""Start MQTT server."""
|
"""Start MQTT server."""
|
||||||
|
|
@ -151,28 +152,30 @@ class BumperMQTTServerPlugin:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if "@" in client_id:
|
if "@" in client_id:
|
||||||
didsplit = str(client_id).split("@")
|
client_id_split = str(client_id).split("@")
|
||||||
if "ecouser" not in didsplit[1]:
|
client_details_split = client_id_split[1].split("/")
|
||||||
|
if "ecouser" not in client_id_split[1]:
|
||||||
# if ecouser aren't in details it is a bot
|
# if ecouser aren't in details it is a bot
|
||||||
tmpbotdetail = str(didsplit[1]).split("/")
|
|
||||||
bot_add(
|
bot_add(
|
||||||
username,
|
username,
|
||||||
didsplit[0],
|
client_id_split[0],
|
||||||
tmpbotdetail[0],
|
client_details_split[0],
|
||||||
tmpbotdetail[1],
|
client_details_split[1],
|
||||||
"eco-ng",
|
"eco-ng",
|
||||||
)
|
)
|
||||||
_LOGGER.info(
|
_LOGGER.info(
|
||||||
"Bumper Authentication Success - Bot - SN: %s - DID: %s - Class: %s",
|
"Bumper Authentication Success - Bot - SN: %s - DID: %s - Class: %s",
|
||||||
username,
|
username,
|
||||||
didsplit[0],
|
client_id_split[0],
|
||||||
tmpbotdetail[0],
|
client_details_split[0],
|
||||||
)
|
)
|
||||||
|
|
||||||
if bumper.bumper_proxy_mqtt:
|
if bumper.bumper_proxy_mqtt:
|
||||||
mqtt_server = await dns.resolve("mq-ww.ecouser.net")
|
mqtt_server = await dns.resolve("mq-ww.ecouser.net")
|
||||||
_LOGGER_PROXY.info(
|
_LOGGER_PROXY.info(
|
||||||
f"MQTT Proxy Mode - Using server {mqtt_server} for client {client_id}"
|
"MQTT Proxy Mode - Using server %s for client %s",
|
||||||
|
mqtt_server,
|
||||||
|
client_id,
|
||||||
)
|
)
|
||||||
proxy = ProxyClient(
|
proxy = ProxyClient(
|
||||||
client_id, mqtt_server, config={"check_hostname": False}
|
client_id, mqtt_server, config={"check_hostname": False}
|
||||||
|
|
@ -182,13 +185,12 @@ class BumperMQTTServerPlugin:
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
tmpclientdetail = str(didsplit[1]).split("/")
|
if check_authcode(client_id_split[0], password) or not bumper.use_auth:
|
||||||
userid = didsplit[0]
|
client_add(
|
||||||
realm = tmpclientdetail[0]
|
client_id_split[0],
|
||||||
resource = tmpclientdetail[1]
|
client_details_split[0],
|
||||||
|
client_details_split[1],
|
||||||
if check_authcode(didsplit[0], password) or not bumper.use_auth:
|
)
|
||||||
client_add(userid, realm, resource)
|
|
||||||
_LOGGER.info(
|
_LOGGER.info(
|
||||||
"Bumper Authentication Success - Client - Username: %s - ClientID: %s",
|
"Bumper Authentication Success - Client - Username: %s - ClientID: %s",
|
||||||
username,
|
username,
|
||||||
|
|
@ -260,20 +262,22 @@ class BumperMQTTServerPlugin:
|
||||||
if client_id in self._proxy_clients:
|
if client_id in self._proxy_clients:
|
||||||
await self._proxy_clients[client_id].subscribe(topic, qos)
|
await self._proxy_clients[client_id].subscribe(topic, qos)
|
||||||
_LOGGER_PROXY.info(
|
_LOGGER_PROXY.info(
|
||||||
f"MQTT Proxy Mode - New MQTT Topic Subscription - Client: {client_id} - Topic: {topic}"
|
"MQTT Proxy Mode - New MQTT Topic Subscription - Client: %s - Topic: %s",
|
||||||
|
client_id,
|
||||||
|
topic,
|
||||||
)
|
)
|
||||||
elif client_id != HELPER_BOT_CLIENT_ID:
|
elif client_id != HELPER_BOT_CLIENT_ID:
|
||||||
_LOGGER_PROXY.warning(
|
_LOGGER_PROXY.warning(
|
||||||
f"MQTT Proxy Mode - No proxy client found! - Client: {client_id} - Topic: {topic}"
|
"MQTT Proxy Mode - No proxy client found! - Client: %s - Topic: %s",
|
||||||
|
client_id,
|
||||||
|
topic,
|
||||||
)
|
)
|
||||||
|
|
||||||
async def on_broker_client_connected(self, client_id: str) -> None:
|
async def on_broker_client_connected(self, client_id: str) -> None:
|
||||||
"""On client connected."""
|
"""On client connected."""
|
||||||
self._set_client_connected(client_id, True)
|
self._set_client_connected(client_id, True)
|
||||||
|
|
||||||
def _set_client_connected( # pylint: disable=no-self-use
|
def _set_client_connected(self, client_id: str, connected: bool) -> None:
|
||||||
self, client_id: str, connected: bool
|
|
||||||
) -> None:
|
|
||||||
didsplit = str(client_id).split("@")
|
didsplit = str(client_id).split("@")
|
||||||
|
|
||||||
bot = bot_get(didsplit[0])
|
bot = bot_get(didsplit[0])
|
||||||
|
|
@ -286,7 +290,7 @@ class BumperMQTTServerPlugin:
|
||||||
if client:
|
if client:
|
||||||
client_set_mqtt(client["resource"], connected)
|
client_set_mqtt(client["resource"], connected)
|
||||||
|
|
||||||
async def on_broker_message_received( # pylint: disable=no-self-use
|
async def on_broker_message_received(
|
||||||
self, message: IncomingApplicationMessage, client_id: str
|
self, message: IncomingApplicationMessage, client_id: str
|
||||||
) -> None:
|
) -> None:
|
||||||
"""On message received."""
|
"""On message received."""
|
||||||
|
|
@ -316,28 +320,34 @@ class BumperMQTTServerPlugin:
|
||||||
)
|
)
|
||||||
if ttopic[6] == "":
|
if ttopic[6] == "":
|
||||||
_LOGGER_PROXY.warning(
|
_LOGGER_PROXY.warning(
|
||||||
"Request mapper is missing entry, "
|
"Request mapper is missing entry, probably request took to"
|
||||||
f"probably request took to long... Client_id: {client_id}"
|
" long... Client_id: %s - Request_id: %s",
|
||||||
f" - Request_id: {ttopic[10]}"
|
client_id,
|
||||||
|
ttopic[10],
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
ttopic_join = "/".join(ttopic)
|
ttopic_join = "/".join(ttopic)
|
||||||
_LOGGER_PROXY.info(
|
_LOGGER_PROXY.info(
|
||||||
f"Bot Message Converted Topic From {message.topic} TO {ttopic_join} "
|
"Bot Message Converted Topic From %s TO %s with message: %s",
|
||||||
f"with message: {data_decoded}"
|
message.topic,
|
||||||
|
ttopic_join,
|
||||||
|
data_decoded,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
ttopic_join = message.topic
|
ttopic_join = message.topic
|
||||||
_LOGGER_PROXY.info(
|
_LOGGER_PROXY.info(
|
||||||
f"Bot Message From {ttopic_join} with message: {data_decoded}"
|
"Bot Message From %s with message: %s",
|
||||||
|
ttopic_join,
|
||||||
|
data_decoded,
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Send back to ecovacs
|
# Send back to ecovacs
|
||||||
_LOGGER_PROXY.info(
|
_LOGGER_PROXY.info(
|
||||||
"Proxy Forward Message to Ecovacs - Topic:"
|
"Proxy Forward Message to Ecovacs - Topic: %s - Message: %s",
|
||||||
f" {ttopic_join} - Message: {data_decoded}"
|
ttopic_join,
|
||||||
|
data_decoded,
|
||||||
)
|
)
|
||||||
await self._proxy_clients[client_id].publish(
|
await self._proxy_clients[client_id].publish(
|
||||||
ttopic_join, data_decoded.encode(), message.qos
|
ttopic_join, data_decoded.encode(), message.qos
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
"""Auth util module."""
|
"""Auth util module."""
|
||||||
import json
|
|
||||||
import logging
|
import logging
|
||||||
import uuid
|
import uuid
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
@ -27,8 +26,6 @@ from bumper.models import (
|
||||||
ERR_TOKEN_INVALID,
|
ERR_TOKEN_INVALID,
|
||||||
ERR_USER_NOT_ACTIVATED,
|
ERR_USER_NOT_ACTIVATED,
|
||||||
RETURN_API_SUCCESS,
|
RETURN_API_SUCCESS,
|
||||||
EcoVacs_Login,
|
|
||||||
EcoVacsHome_Login,
|
|
||||||
)
|
)
|
||||||
from bumper.util import get_current_time_as_millis
|
from bumper.util import get_current_time_as_millis
|
||||||
from bumper.web.plugins import get_success_response
|
from bumper.web.plugins import get_success_response
|
||||||
|
|
@ -55,78 +52,51 @@ async def login(request: Request) -> Response:
|
||||||
user_devid = request.match_info.get("devid", "")
|
user_devid = request.match_info.get("devid", "")
|
||||||
countrycode = request.match_info.get("country", "us")
|
countrycode = request.match_info.get("country", "us")
|
||||||
apptype = request.match_info.get("apptype", "")
|
apptype = request.match_info.get("apptype", "")
|
||||||
_LOGGER.info(f"client with devid {user_devid} attempting login")
|
_LOGGER.info("Client with devid %s attempting login", user_devid)
|
||||||
if use_auth:
|
if use_auth:
|
||||||
if (
|
if user_devid != "":
|
||||||
not user_devid == ""
|
# Performing basic "auth" using devid, super insecure
|
||||||
): # Performing basic "auth" using devid, super insecure
|
|
||||||
user = user_by_device_id(user_devid)
|
user = user_by_device_id(user_devid)
|
||||||
if user:
|
if user:
|
||||||
if "checkLogin" in request.path:
|
if "checkLogin" in request.path:
|
||||||
_check_token(
|
return web.json_response(
|
||||||
apptype, countrycode, user, request.query["accessToken"]
|
_check_token(
|
||||||
|
apptype, countrycode, user, request.query["accessToken"]
|
||||||
|
)[1]
|
||||||
)
|
)
|
||||||
else:
|
|
||||||
login_details: EcoVacsHome_Login | EcoVacs_Login
|
|
||||||
if "global_" in apptype: # EcoVacs Home
|
|
||||||
login_details = EcoVacsHome_Login()
|
|
||||||
login_details.ucUid = "fuid_{}".format(user["userid"])
|
|
||||||
login_details.loginName = "fusername_{}".format(
|
|
||||||
user["userid"]
|
|
||||||
)
|
|
||||||
login_details.mobile = None
|
|
||||||
|
|
||||||
else:
|
# Deactivate old tokens and authcodes
|
||||||
login_details = EcoVacs_Login()
|
user_revoke_expired_tokens(user["userid"])
|
||||||
|
|
||||||
# Deactivate old tokens and authcodes
|
body = {
|
||||||
user_revoke_expired_tokens(user["userid"])
|
"code": API_ERRORS[RETURN_API_SUCCESS],
|
||||||
|
"data": _get_login_details(
|
||||||
|
apptype, countrycode, user, _generate_token(user)
|
||||||
|
),
|
||||||
|
"msg": "操作成功",
|
||||||
|
"time": get_current_time_as_millis(),
|
||||||
|
}
|
||||||
|
return web.json_response(body)
|
||||||
|
|
||||||
login_details.accessToken = _generate_token(user)
|
|
||||||
login_details.uid = "fuid_{}".format(user["userid"])
|
|
||||||
login_details.username = "fusername_{}".format(user["userid"])
|
|
||||||
login_details.country = countrycode
|
|
||||||
login_details.email = "null@null.com"
|
|
||||||
|
|
||||||
body = {
|
|
||||||
"code": API_ERRORS[RETURN_API_SUCCESS],
|
|
||||||
"data": json.loads(login_details.toJSON()),
|
|
||||||
# {
|
|
||||||
# "accessToken": self.generate_token(tmpuser), # Generate a token
|
|
||||||
# "country": countrycode,
|
|
||||||
# "email": "null@null.com",
|
|
||||||
# "uid": "fuid_{}".format(tmpuser["userid"]),
|
|
||||||
# "username": "fusername_{}".format(tmpuser["userid"]),
|
|
||||||
# },
|
|
||||||
"msg": "操作成功",
|
|
||||||
"time": get_current_time_as_millis(),
|
|
||||||
}
|
|
||||||
|
|
||||||
return web.json_response(body)
|
|
||||||
|
|
||||||
body = {
|
|
||||||
"code": ERR_USER_NOT_ACTIVATED,
|
|
||||||
"data": None,
|
|
||||||
"msg": "当前密码错误",
|
|
||||||
"time": get_current_time_as_millis(),
|
|
||||||
}
|
|
||||||
|
|
||||||
return web.json_response(body)
|
|
||||||
|
|
||||||
else:
|
|
||||||
return web.json_response(
|
return web.json_response(
|
||||||
_auth_any(user_devid, apptype, countrycode, request)
|
{
|
||||||
|
"code": ERR_USER_NOT_ACTIVATED,
|
||||||
|
"data": None,
|
||||||
|
"msg": "当前密码错误",
|
||||||
|
"time": get_current_time_as_millis(),
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
except Exception as e:
|
return web.json_response(_auth_any(user_devid, apptype, countrycode, request))
|
||||||
_LOGGER.exception(f"{e}")
|
except Exception: # pylint: disable=broad-except
|
||||||
|
_LOGGER.exception("An exception occurred", exc_info=True)
|
||||||
|
|
||||||
raise HTTPInternalServerError
|
raise HTTPInternalServerError
|
||||||
|
|
||||||
|
|
||||||
async def get_authcode(request: Request) -> Response:
|
async def get_authcode(request: Request) -> Response:
|
||||||
"""Get auth code."""
|
"""Get auth code."""
|
||||||
try:
|
try: # pylint: disable=too-many-nested-blocks
|
||||||
user_devid = request.match_info.get("devid", None) # Ecovacs
|
user_devid = request.match_info.get("devid", None) # Ecovacs
|
||||||
if not user_devid:
|
if not user_devid:
|
||||||
user_devid = request.query["deviceId"] # Ecovacs Home
|
user_devid = request.query["deviceId"] # Ecovacs Home
|
||||||
|
|
@ -170,134 +140,86 @@ async def get_authcode(request: Request) -> Response:
|
||||||
|
|
||||||
def _check_token(
|
def _check_token(
|
||||||
apptype: str, countrycode: str, user: dict[str, Any], token: str
|
apptype: str, countrycode: str, user: dict[str, Any], token: str
|
||||||
) -> Response:
|
) -> tuple[bool, dict[str, Any]]:
|
||||||
try:
|
if db.check_token(user["userid"], token):
|
||||||
if db.check_token(user["userid"], token):
|
return (
|
||||||
login_details: EcoVacsHome_Login | EcoVacs_Login
|
True,
|
||||||
if "global_" in apptype: # EcoVacs Home
|
{
|
||||||
login_details = EcoVacsHome_Login()
|
|
||||||
login_details.ucUid = "fuid_{}".format(user["userid"])
|
|
||||||
login_details.loginName = "fusername_{}".format(user["userid"])
|
|
||||||
login_details.mobile = None
|
|
||||||
else:
|
|
||||||
login_details = EcoVacs_Login()
|
|
||||||
|
|
||||||
login_details.accessToken = token
|
|
||||||
login_details.uid = "fuid_{}".format(user["userid"])
|
|
||||||
login_details.username = "fusername_{}".format(user["userid"])
|
|
||||||
login_details.country = countrycode
|
|
||||||
login_details.email = "null@null.com"
|
|
||||||
|
|
||||||
body = {
|
|
||||||
"code": RETURN_API_SUCCESS,
|
"code": RETURN_API_SUCCESS,
|
||||||
"data": json.loads(login_details.toJSON()),
|
"data": _get_login_details(apptype, countrycode, user, token),
|
||||||
# {
|
|
||||||
# "accessToken": self.generate_token(tmpuser), # Generate a token
|
|
||||||
# "country": countrycode,
|
|
||||||
# "email": "null@null.com",
|
|
||||||
# "uid": "fuid_{}".format(tmpuser["userid"]),
|
|
||||||
# "username": "fusername_{}".format(tmpuser["userid"]),
|
|
||||||
# },
|
|
||||||
"msg": "操作成功",
|
"msg": "操作成功",
|
||||||
"time": get_current_time_as_millis(),
|
"time": get_current_time_as_millis(),
|
||||||
}
|
},
|
||||||
return web.json_response(body)
|
)
|
||||||
|
|
||||||
else:
|
return (
|
||||||
body = {
|
False,
|
||||||
"code": ERR_TOKEN_INVALID,
|
{
|
||||||
"data": None,
|
"code": ERR_TOKEN_INVALID,
|
||||||
"msg": "当前密码错误",
|
"data": None,
|
||||||
"time": get_current_time_as_millis(),
|
"msg": "当前密码错误",
|
||||||
}
|
"time": get_current_time_as_millis(),
|
||||||
return web.json_response(body)
|
},
|
||||||
|
)
|
||||||
except Exception as e:
|
|
||||||
_LOGGER.exception(f"{e}")
|
|
||||||
|
|
||||||
raise HTTPInternalServerError
|
|
||||||
|
|
||||||
|
|
||||||
def _auth_any(
|
def _auth_any(
|
||||||
devid: str, apptype: str, country: str, request: Request
|
devid: str, apptype: str, country: str, request: Request
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
try:
|
user_devid = devid
|
||||||
user_devid = devid
|
countrycode = country
|
||||||
countrycode = country
|
user = user_by_device_id(user_devid)
|
||||||
user = user_by_device_id(user_devid)
|
bots = _db_get().table("bots").all()
|
||||||
bots = _db_get().table("bots").all()
|
|
||||||
login_details: EcoVacs_Login | EcoVacsHome_Login
|
|
||||||
|
|
||||||
if user: # Default to user 0
|
if not user:
|
||||||
tmpuser = user
|
user_add("tmpuser") # Add a new user
|
||||||
if "global_" in apptype: # EcoVacs Home
|
tmp = user_get("tmpuser")
|
||||||
login_details = EcoVacsHome_Login()
|
assert tmp
|
||||||
login_details.ucUid = "fuid_{}".format(tmpuser["userid"])
|
user = tmp
|
||||||
login_details.loginName = "fusername_{}".format(tmpuser["userid"])
|
|
||||||
login_details.mobile = None
|
|
||||||
else:
|
|
||||||
login_details = EcoVacs_Login()
|
|
||||||
|
|
||||||
login_details.accessToken = _generate_token(tmpuser)
|
token = _generate_token(user)
|
||||||
login_details.uid = "fuid_{}".format(tmpuser["userid"])
|
user_add_device(user["userid"], user_devid)
|
||||||
login_details.username = "fusername_{}".format(tmpuser["userid"])
|
|
||||||
login_details.country = countrycode
|
for bot in bots: # Add all bots to the user
|
||||||
login_details.email = "null@null.com"
|
if "did" in bot:
|
||||||
user_add_device(tmpuser["userid"], user_devid)
|
user_add_bot(user["userid"], bot["did"])
|
||||||
else:
|
else:
|
||||||
user_add("tmpuser") # Add a new user
|
_LOGGER.error("No DID for bot: %s", bot)
|
||||||
tmp = user_get("tmpuser")
|
|
||||||
assert tmp
|
|
||||||
tmpuser = tmp
|
|
||||||
if "global_" in apptype: # EcoVacs Home
|
|
||||||
login_details = EcoVacsHome_Login()
|
|
||||||
login_details.ucUid = "fuid_{}".format(tmpuser["userid"])
|
|
||||||
login_details.loginName = "fusername_{}".format(tmpuser["userid"])
|
|
||||||
login_details.mobile = None
|
|
||||||
else:
|
|
||||||
login_details = EcoVacs_Login()
|
|
||||||
|
|
||||||
login_details.accessToken = _generate_token(tmpuser)
|
if "checkLogin" in request.path: # If request was to check a token do so
|
||||||
login_details.uid = "fuid_{}".format(tmpuser["userid"])
|
(success, body) = _check_token(
|
||||||
login_details.username = "fusername_{}".format(tmpuser["userid"])
|
apptype, countrycode, user, request.query["accessToken"]
|
||||||
login_details.country = countrycode
|
)
|
||||||
login_details.email = "null@null.com"
|
if success:
|
||||||
user_add_device(tmpuser["userid"], user_devid)
|
return body
|
||||||
|
|
||||||
for bot in bots: # Add all bots to the user
|
# Deactivate old tokens and authcodes
|
||||||
if "did" in bot:
|
user_revoke_expired_tokens(user["userid"])
|
||||||
user_add_bot(tmpuser["userid"], bot["did"])
|
|
||||||
else:
|
|
||||||
_LOGGER.error(f"No DID for bot: {bot}")
|
|
||||||
|
|
||||||
if "checkLogin" in request.path: # If request was to check a token do so
|
body = {
|
||||||
checkToken = _check_token(
|
"code": RETURN_API_SUCCESS,
|
||||||
apptype, countrycode, tmpuser, request.query["accessToken"]
|
"data": _get_login_details(apptype, countrycode, user, token),
|
||||||
)
|
"msg": "操作成功",
|
||||||
assert checkToken.text
|
"time": get_current_time_as_millis(),
|
||||||
isGood: dict[str, Any] = json.loads(checkToken.text)
|
}
|
||||||
if isGood["code"] == "0000":
|
|
||||||
return isGood
|
|
||||||
|
|
||||||
# Deactivate old tokens and authcodes
|
return body
|
||||||
user_revoke_expired_tokens(tmpuser["userid"])
|
|
||||||
|
|
||||||
body = {
|
|
||||||
"code": RETURN_API_SUCCESS,
|
|
||||||
"data": json.loads(login_details.toJSON()),
|
|
||||||
# {
|
|
||||||
# "accessToken": self.generate_token(tmpuser), # Generate a token
|
|
||||||
# "country": countrycode,
|
|
||||||
# "email": "null@null.com",
|
|
||||||
# "uid": "fuid_{}".format(tmpuser["userid"]),
|
|
||||||
# "username": "fusername_{}".format(tmpuser["userid"]),
|
|
||||||
# },
|
|
||||||
"msg": "操作成功",
|
|
||||||
"time": get_current_time_as_millis(),
|
|
||||||
}
|
|
||||||
|
|
||||||
return body
|
def _get_login_details(
|
||||||
|
apptype: str, countrycode: str, user: dict[str, Any], token: str
|
||||||
|
) -> dict[str, Any]:
|
||||||
|
details: dict[str, Any] = {
|
||||||
|
"accessToken": token,
|
||||||
|
"uid": f"fuid_{user['userid']}",
|
||||||
|
"username": f"fusername_{user['userid']}",
|
||||||
|
"country": countrycode,
|
||||||
|
"email": "null@null.com",
|
||||||
|
}
|
||||||
|
|
||||||
except Exception as e:
|
if "global_" in apptype:
|
||||||
_LOGGER.exception(f"{e}")
|
details.update(
|
||||||
return {}
|
{"ucUid": details["uid"], "loginName": details["username"], "mobile": None}
|
||||||
|
)
|
||||||
|
|
||||||
|
return details
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,11 @@ _LOGGER = get_logger("webserver_requests")
|
||||||
class CustomEncoder(json.JSONEncoder):
|
class CustomEncoder(json.JSONEncoder):
|
||||||
"""Custom json encoder, which supports set."""
|
"""Custom json encoder, which supports set."""
|
||||||
|
|
||||||
def default(self, obj: Any) -> Any:
|
def default(self, o: Any) -> Any:
|
||||||
"""Convert objects, which are not supported by the default JSONEncoder."""
|
"""Convert objects, which are not supported by the default JSONEncoder."""
|
||||||
if isinstance(obj, set):
|
if isinstance(o, set):
|
||||||
return list(obj)
|
return list(o)
|
||||||
return json.JSONEncoder.default(self, obj)
|
return json.JSONEncoder.default(self, o)
|
||||||
|
|
||||||
|
|
||||||
_EXCLUDE_FROM_LOGGING = [
|
_EXCLUDE_FROM_LOGGING = [
|
||||||
|
|
@ -32,7 +32,9 @@ _EXCLUDE_FROM_LOGGING = [
|
||||||
|
|
||||||
|
|
||||||
@web.middleware
|
@web.middleware
|
||||||
async def log_all_requests(request: Request, handler: Handler) -> StreamResponse:
|
async def log_all_requests( # pylint: disable=too-many-branches
|
||||||
|
request: Request, handler: Handler
|
||||||
|
) -> StreamResponse:
|
||||||
"""Middleware to log all requests."""
|
"""Middleware to log all requests."""
|
||||||
if (
|
if (
|
||||||
not request.match_info.route.resource
|
not request.match_info.route.resource
|
||||||
|
|
@ -45,7 +47,7 @@ async def log_all_requests(request: Request, handler: Handler) -> StreamResponse
|
||||||
"url": str(request.url),
|
"url": str(request.url),
|
||||||
"path": request.path,
|
"path": request.path,
|
||||||
"query_string": request.query_string,
|
"query_string": request.query_string,
|
||||||
"headers": {h for h in request.headers.items()},
|
"headers": set(request.headers.items()),
|
||||||
"route_resource": request.match_info.route.resource.canonical,
|
"route_resource": request.match_info.route.resource.canonical,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -56,7 +58,7 @@ async def log_all_requests(request: Request, handler: Handler) -> StreamResponse
|
||||||
if request.content_type == "application/json":
|
if request.content_type == "application/json":
|
||||||
to_log["request"]["body"] = await request.json()
|
to_log["request"]["body"] = await request.json()
|
||||||
else:
|
else:
|
||||||
to_log["request"]["body"] = {h for h in await request.post()}
|
to_log["request"]["body"] = set(await request.post())
|
||||||
except Exception:
|
except Exception:
|
||||||
_LOGGER.exception(
|
_LOGGER.exception(
|
||||||
"An exception occurred during logging the request.", exc_info=True
|
"An exception occurred during logging the request.", exc_info=True
|
||||||
|
|
@ -75,7 +77,7 @@ async def log_all_requests(request: Request, handler: Handler) -> StreamResponse
|
||||||
|
|
||||||
to_log["response"] = {
|
to_log["response"] = {
|
||||||
"status": f"{response.status}",
|
"status": f"{response.status}",
|
||||||
"headers": {h for h in response.headers.items()},
|
"headers": set(response.headers.items()),
|
||||||
}
|
}
|
||||||
|
|
||||||
if isinstance(response, Response) and response.body:
|
if isinstance(response, Response) and response.body:
|
||||||
|
|
@ -93,7 +95,7 @@ async def log_all_requests(request: Request, handler: Handler) -> StreamResponse
|
||||||
raise
|
raise
|
||||||
|
|
||||||
except web.HTTPNotFound:
|
except web.HTTPNotFound:
|
||||||
_LOGGER.debug(f"Request path {request.raw_path} not found")
|
_LOGGER.debug("Request path %s not found", request.raw_path)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ from aiohttp.web_exceptions import HTTPInternalServerError
|
||||||
from aiohttp.web_request import Request
|
from aiohttp.web_request import Request
|
||||||
from aiohttp.web_response import Response
|
from aiohttp.web_response import Response
|
||||||
from aiohttp.web_routedef import AbstractRouteDef
|
from aiohttp.web_routedef import AbstractRouteDef
|
||||||
from amqtt.session import Session
|
|
||||||
|
|
||||||
import bumper
|
import bumper
|
||||||
from bumper.db import _db_get, token_by_authcode, user_add_oauth
|
from bumper.db import _db_get, token_by_authcode, user_add_oauth
|
||||||
|
|
@ -136,8 +135,7 @@ def _include_product_iot_map_info(bot: dict[str, Any]) -> dict[str, Any]:
|
||||||
)
|
)
|
||||||
|
|
||||||
# mqtt_connection is not always set correctly, therefore workaround until fixed properly
|
# mqtt_connection is not always set correctly, therefore workaround until fixed properly
|
||||||
session: Session
|
for session in bumper.mqtt_server.sessions:
|
||||||
for (session, _) in bumper.mqtt_server.broker._sessions.values():
|
|
||||||
did = session.client_id.split("@")[0]
|
did = session.client_id.split("@")[0]
|
||||||
if did == bot["did"] and session.transitions.state == "connected":
|
if did == bot["did"] and session.transitions.state == "connected":
|
||||||
result["status"] = 1
|
result["status"] = 1
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import ssl
|
import ssl
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
import aiohttp_jinja2
|
import aiohttp_jinja2
|
||||||
|
|
@ -22,22 +23,21 @@ from bumper.web.middlewares import log_all_requests
|
||||||
from bumper.web.plugins import add_plugins
|
from bumper.web.plugins import add_plugins
|
||||||
|
|
||||||
|
|
||||||
class _aiohttp_filter(logging.Filter):
|
class _AiohttpFilter(logging.Filter):
|
||||||
def filter(self, record: logging.LogRecord) -> bool:
|
def filter(self, record: logging.LogRecord) -> bool:
|
||||||
if record.name == "aiohttp.access" and record.levelno == 20:
|
if record.name == "aiohttp.access" and record.levelno == 20:
|
||||||
# Filters aiohttp.access log to switch it from INFO to DEBUG
|
# Filters aiohttp.access log to switch it from INFO to DEBUG
|
||||||
record.levelno = 10
|
record.levelno = 10
|
||||||
record.levelname = "DEBUG"
|
record.levelname = "DEBUG"
|
||||||
|
|
||||||
if record.levelno == 10 and get_logger("confserver").getEffectiveLevel() == 10:
|
return (
|
||||||
return True
|
record.levelno == 10 and get_logger("confserver").getEffectiveLevel() == 10
|
||||||
else:
|
)
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
_LOGGER = get_logger("webserver")
|
_LOGGER = get_logger("webserver")
|
||||||
# Add logging filter above to aiohttp.access
|
# Add logging filter above to aiohttp.access
|
||||||
logging.getLogger("aiohttp.access").addFilter(_aiohttp_filter())
|
logging.getLogger("aiohttp.access").addFilter(_AiohttpFilter())
|
||||||
_LOGGER_PROXY = logging.getLogger("web_proxy")
|
_LOGGER_PROXY = logging.getLogger("web_proxy")
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -129,9 +129,9 @@ class WebServer:
|
||||||
)
|
)
|
||||||
|
|
||||||
await site.start()
|
await site.start()
|
||||||
except Exception as e:
|
except Exception:
|
||||||
_LOGGER.exception(f"{e}")
|
_LOGGER.exception("An exception occurred", exc_info=True)
|
||||||
raise e
|
raise
|
||||||
|
|
||||||
async def shutdown(self) -> None:
|
async def shutdown(self) -> None:
|
||||||
"""Shutdown server."""
|
"""Shutdown server."""
|
||||||
|
|
@ -143,15 +143,16 @@ class WebServer:
|
||||||
self._runners.clear()
|
self._runners.clear()
|
||||||
await self._app.shutdown()
|
await self._app.shutdown()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception:
|
||||||
_LOGGER.exception(f"{e}")
|
_LOGGER.exception("An exception occurred", exc_info=True)
|
||||||
|
raise
|
||||||
|
|
||||||
async def _handle_base(self, request: Request) -> Response:
|
async def _handle_base(self, request: Request) -> Response:
|
||||||
try:
|
try:
|
||||||
bots = _db_get().table("bots").all()
|
bots = _db_get().table("bots").all()
|
||||||
clients = _db_get().table("clients").all()
|
clients = _db_get().table("clients").all()
|
||||||
mq_sessions = []
|
mq_sessions = []
|
||||||
for (session, _) in bumper.mqtt_server.broker._sessions.values():
|
for session in bumper.mqtt_server.sessions:
|
||||||
mq_sessions.append(
|
mq_sessions.append(
|
||||||
{
|
{
|
||||||
"username": session.username,
|
"username": session.username,
|
||||||
|
|
@ -159,7 +160,7 @@ class WebServer:
|
||||||
"state": session.transitions.state,
|
"state": session.transitions.state,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
all = {
|
context = {
|
||||||
"bots": bots,
|
"bots": bots,
|
||||||
"clients": clients,
|
"clients": clients,
|
||||||
"helperbot": {"connected": bumper.mqtt_helperbot.is_connected},
|
"helperbot": {"connected": bumper.mqtt_helperbot.is_connected},
|
||||||
|
|
@ -172,9 +173,11 @@ class WebServer:
|
||||||
},
|
},
|
||||||
"xmpp_server": bumper.xmpp_server,
|
"xmpp_server": bumper.xmpp_server,
|
||||||
}
|
}
|
||||||
return aiohttp_jinja2.render_template("home.jinja2", request, context=all)
|
return aiohttp_jinja2.render_template(
|
||||||
except Exception as e:
|
"home.jinja2", request, context=context
|
||||||
_LOGGER.exception(f"{e}")
|
)
|
||||||
|
except Exception: # pylint: disable=broad-except
|
||||||
|
_LOGGER.exception("An exception occurred", exc_info=True)
|
||||||
|
|
||||||
raise HTTPInternalServerError
|
raise HTTPInternalServerError
|
||||||
|
|
||||||
|
|
@ -208,9 +211,10 @@ class WebServer:
|
||||||
return web.json_response({"status": "complete"})
|
return web.json_response({"status": "complete"})
|
||||||
|
|
||||||
return web.json_response({"status": "invalid service"})
|
return web.json_response({"status": "invalid service"})
|
||||||
except Exception as e:
|
except Exception: # pylint: disable=broad-except
|
||||||
_LOGGER.exception(f"{e}")
|
_LOGGER.exception("An exception occurred", exc_info=True)
|
||||||
raise
|
|
||||||
|
raise HTTPInternalServerError
|
||||||
|
|
||||||
async def _handle_remove_bot(self, request: Request) -> Response:
|
async def _handle_remove_bot(self, request: Request) -> Response:
|
||||||
try:
|
try:
|
||||||
|
|
@ -218,11 +222,11 @@ class WebServer:
|
||||||
bot_remove(did)
|
bot_remove(did)
|
||||||
if bot_get(did):
|
if bot_get(did):
|
||||||
return web.json_response({"status": "failed to remove bot"})
|
return web.json_response({"status": "failed to remove bot"})
|
||||||
else:
|
|
||||||
return web.json_response({"status": "successfully removed bot"})
|
|
||||||
|
|
||||||
except Exception as e:
|
return web.json_response({"status": "successfully removed bot"})
|
||||||
_LOGGER.exception(f"{e}")
|
|
||||||
|
except Exception: # pylint: disable=broad-except
|
||||||
|
_LOGGER.exception("An exception occurred", exc_info=True)
|
||||||
|
|
||||||
raise HTTPInternalServerError
|
raise HTTPInternalServerError
|
||||||
|
|
||||||
|
|
@ -232,11 +236,11 @@ class WebServer:
|
||||||
client_remove(resource)
|
client_remove(resource)
|
||||||
if client_get(resource):
|
if client_get(resource):
|
||||||
return web.json_response({"status": "failed to remove client"})
|
return web.json_response({"status": "failed to remove client"})
|
||||||
else:
|
|
||||||
return web.json_response({"status": "successfully removed client"})
|
|
||||||
|
|
||||||
except Exception as e:
|
return web.json_response({"status": "successfully removed client"})
|
||||||
_LOGGER.exception(f"{e}")
|
|
||||||
|
except Exception: # pylint: disable=broad-except
|
||||||
|
_LOGGER.exception("An exception occurred", exc_info=True)
|
||||||
|
|
||||||
raise HTTPInternalServerError
|
raise HTTPInternalServerError
|
||||||
|
|
||||||
|
|
@ -255,22 +259,18 @@ class WebServer:
|
||||||
srvip = bumper.bumper_announce_ip
|
srvip = bumper.bumper_announce_ip
|
||||||
srvport = 5223
|
srvport = 5223
|
||||||
_LOGGER.info(
|
_LOGGER.info(
|
||||||
"Announcing EcoMsgNew Server to bot as: {}:{}".format(
|
"Announcing EcoMsgNew Server to bot as: %s:%d", srvip, srvport
|
||||||
srvip, srvport
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
server = json.dumps({"ip": srvip, "port": srvport, "result": "ok"})
|
server = json.dumps({"ip": srvip, "port": srvport, "result": "ok"})
|
||||||
# bot seems to be very picky about having no spaces, only way was with text
|
# bot seems to be very picky about having no spaces, only way was with text
|
||||||
server = server.replace(" ", "")
|
server = server.replace(" ", "")
|
||||||
return web.json_response(text=server)
|
return web.json_response(text=server)
|
||||||
|
|
||||||
elif service == "EcoUpdate":
|
if service == "EcoUpdate":
|
||||||
srvip = "47.88.66.164" # EcoVacs Server
|
srvip = "47.88.66.164" # EcoVacs Server
|
||||||
srvport = 8005
|
srvport = 8005
|
||||||
_LOGGER.info(
|
_LOGGER.info(
|
||||||
"Announcing EcoUpdate Server to bot as: {}:{}".format(
|
"Announcing EcoUpdate Server to bot as: %s:%d", srvip, srvport
|
||||||
srvip, srvport
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
return web.json_response(
|
return web.json_response(
|
||||||
{"result": "ok", "ip": srvip, "port": srvport}
|
{"result": "ok", "ip": srvip, "port": srvport}
|
||||||
|
|
@ -278,8 +278,8 @@ class WebServer:
|
||||||
|
|
||||||
return web.json_response({})
|
return web.json_response({})
|
||||||
|
|
||||||
except Exception as e:
|
except Exception: # pylint: disable=broad-except
|
||||||
_LOGGER.exception(f"{e}")
|
_LOGGER.exception("An exception occurred", exc_info=True)
|
||||||
|
|
||||||
raise HTTPInternalServerError
|
raise HTTPInternalServerError
|
||||||
|
|
||||||
|
|
@ -297,8 +297,8 @@ class WebServer:
|
||||||
|
|
||||||
return web.json_response(body)
|
return web.json_response(body)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception: # pylint: disable=broad-except
|
||||||
_LOGGER.exception(f"{e}")
|
_LOGGER.exception("An exception occurred", exc_info=True)
|
||||||
|
|
||||||
raise HTTPInternalServerError
|
raise HTTPInternalServerError
|
||||||
|
|
||||||
|
|
@ -316,62 +316,54 @@ class WebServer:
|
||||||
verify_ssl=False, resolver=get_resolver_with_public_nameserver()
|
verify_ssl=False, resolver=get_resolver_with_public_nameserver()
|
||||||
),
|
),
|
||||||
) as session:
|
) as session:
|
||||||
|
data: Any = None
|
||||||
|
json_data: Any = None
|
||||||
if request.content.total_bytes > 0:
|
if request.content.total_bytes > 0:
|
||||||
read_body = await request.read()
|
read_body = await request.read()
|
||||||
_LOGGER_PROXY.info(
|
_LOGGER_PROXY.info(
|
||||||
f"HTTP Proxy Request to EcoVacs (body=true) (URL:{request.url}) - {read_body.decode('utf-8')}"
|
"HTTP Proxy Request to EcoVacs (body=true) (URL:%s) - %s",
|
||||||
|
request.url,
|
||||||
|
read_body.decode("utf-8"),
|
||||||
)
|
)
|
||||||
if request.content_type == "application/x-www-form-urlencoded":
|
if request.content_type == "application/x-www-form-urlencoded":
|
||||||
# android apps use form
|
# android apps use form
|
||||||
fdata = await request.post()
|
data = await request.post()
|
||||||
async with session.request(
|
|
||||||
request.method, request.url, data=fdata
|
|
||||||
) as resp:
|
|
||||||
response = await resp.text()
|
|
||||||
_LOGGER_PROXY.info(
|
|
||||||
f"HTTP Proxy Response from EcoVacs (URL: {request.url}) - (Status: {resp.status}) - {response}"
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
# handle json
|
# handle json
|
||||||
async with session.request(
|
json_data = await request.json()
|
||||||
request.method, request.url, json=await request.json()
|
|
||||||
) as resp:
|
|
||||||
response = await resp.text()
|
|
||||||
_LOGGER_PROXY.info(
|
|
||||||
f"HTTP Proxy Response from EcoVacs (URL: {request.url}) - (Status: {resp.status}) - {response}"
|
|
||||||
)
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
_LOGGER_PROXY.info(
|
_LOGGER_PROXY.info(
|
||||||
f"HTTP Proxy Request to EcoVacs (body=false) (URL:{request.url})"
|
"HTTP Proxy Request to EcoVacs (body=false) (URL:%s)",
|
||||||
|
request.url,
|
||||||
)
|
)
|
||||||
async with session.request(request.method, request.url) as resp:
|
|
||||||
if resp.content_type == "application/octet-stream":
|
|
||||||
_LOGGER_PROXY.info(
|
|
||||||
f"HTTP Proxy Response from EcoVacs (URL: {request.url}) - (Status: {resp.status}) - <BYTES CONTENT>"
|
|
||||||
)
|
|
||||||
return web.Response(body=await resp.read())
|
|
||||||
else:
|
|
||||||
response = await resp.text()
|
|
||||||
_LOGGER_PROXY.info(
|
|
||||||
f"HTTP Proxy Response from EcoVacs (URL: {request.url}) - (Status: {resp.status}) - {response}"
|
|
||||||
)
|
|
||||||
|
|
||||||
if resp.status == 200:
|
async with session.request(
|
||||||
if resp.content_type == "application/json":
|
request.method, request.url, data=data, json=json_data
|
||||||
response = json.loads(response)
|
) as resp:
|
||||||
return web.json_response(response)
|
|
||||||
if resp.content_type == "application/octet-stream":
|
if resp.content_type == "application/octet-stream":
|
||||||
return web.Response(body=response)
|
_LOGGER_PROXY.info(
|
||||||
|
"HTTP Proxy Response from EcoVacs (URL: %s) - (Status: %d) - <BYTES CONTENT>",
|
||||||
|
request.url,
|
||||||
|
resp.status,
|
||||||
|
)
|
||||||
|
return web.Response(body=await resp.read())
|
||||||
|
|
||||||
return web.Response(text=response)
|
response = await resp.text()
|
||||||
|
_LOGGER_PROXY.info(
|
||||||
|
"HTTP Proxy Response from EcoVacs (URL: %s) - (Status: %d) - %s",
|
||||||
|
request.url,
|
||||||
|
resp.status,
|
||||||
|
response,
|
||||||
|
)
|
||||||
|
return web.Response(text=response)
|
||||||
except asyncio.CancelledError:
|
except asyncio.CancelledError:
|
||||||
_LOGGER_PROXY.exception(
|
_LOGGER_PROXY.exception(
|
||||||
f"Request cancelled or timeout - {request.url}", exc_info=True
|
"Request cancelled or timeout - %s", request.url, exc_info=True
|
||||||
)
|
)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
except Exception:
|
except Exception: # pylint: disable=broad-except
|
||||||
_LOGGER_PROXY.exception("An exception occurred", exc_info=True)
|
_LOGGER_PROXY.exception("An exception occurred", exc_info=True)
|
||||||
|
|
||||||
raise HTTPInternalServerError
|
raise HTTPInternalServerError
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue