start refactoring confserver
This commit is contained in:
parent
ba3f28165f
commit
4dce3c262c
32 changed files with 627 additions and 840 deletions
|
|
@ -6,7 +6,7 @@ import socket
|
|||
import sys
|
||||
from typing import Optional
|
||||
|
||||
from bumper.confserver import ConfServer
|
||||
from bumper.confserver import ConfServer, WebServerBinding
|
||||
from bumper.db import *
|
||||
from bumper.models import *
|
||||
from bumper.mqttserver import MQTTHelperBot, MQTTServer
|
||||
|
|
@ -53,11 +53,10 @@ token_validity_seconds = 3600 # 1 hour
|
|||
oauth_validity_days = 15
|
||||
db = None
|
||||
|
||||
mqtt_server: Optional[MQTTServer] = None
|
||||
mqtt_helperbot: Optional[MQTTHelperBot] = None
|
||||
conf_server: Optional[ConfServer] = None
|
||||
conf_server_2: Optional[ConfServer] = None
|
||||
xmpp_server: Optional[XMPPServer] = None
|
||||
mqtt_server: MQTTServer
|
||||
mqtt_helperbot: MQTTHelperBot
|
||||
conf_server: ConfServer
|
||||
xmpp_server: XMPPServer
|
||||
|
||||
# Plugins
|
||||
sys.path.append(os.path.join(bumper_dir, "bumper", "plugins"))
|
||||
|
|
@ -75,9 +74,11 @@ bumperlog = get_logger("bumper")
|
|||
logging.getLogger("asyncio").setLevel(logging.CRITICAL + 1) # Ignore this logger
|
||||
|
||||
mqtt_listen_port = 8883
|
||||
conf1_listen_port = 443
|
||||
conf2_listen_port = 8007
|
||||
xmpp_listen_port = 5223
|
||||
conf_server_bindings = [
|
||||
WebServerBinding(bumper_listen, 8443, True),
|
||||
WebServerBinding(bumper_listen, 8007, False),
|
||||
]
|
||||
|
||||
|
||||
async def start():
|
||||
|
|
@ -117,9 +118,7 @@ async def start():
|
|||
global mqtt_helperbot
|
||||
mqtt_helperbot = MQTTHelperBot(bumper_listen, mqtt_listen_port)
|
||||
global conf_server
|
||||
conf_server = ConfServer((bumper_listen, conf1_listen_port), usessl=True)
|
||||
global conf_server_2
|
||||
conf_server_2 = ConfServer((bumper_listen, conf2_listen_port), usessl=False)
|
||||
conf_server = ConfServer(conf_server_bindings)
|
||||
global xmpp_server
|
||||
xmpp_server = XMPPServer((bumper_listen, xmpp_listen_port))
|
||||
|
||||
|
|
@ -138,17 +137,7 @@ async def start():
|
|||
await asyncio.sleep(0.1)
|
||||
|
||||
# Start web servers
|
||||
conf_server.confserver_app()
|
||||
asyncio.create_task(
|
||||
conf_server.start_site(
|
||||
conf_server.app, address=bumper_listen, port=conf1_listen_port, usessl=True
|
||||
)
|
||||
)
|
||||
asyncio.create_task(
|
||||
conf_server.start_site(
|
||||
conf_server.app, address=bumper_listen, port=conf2_listen_port, usessl=False
|
||||
)
|
||||
)
|
||||
await conf_server.start()
|
||||
|
||||
# Start maintenance
|
||||
while not shutting_down:
|
||||
|
|
@ -165,8 +154,7 @@ async def shutdown():
|
|||
try:
|
||||
bumperlog.info("Shutting down")
|
||||
|
||||
await conf_server.stop_server()
|
||||
await conf_server_2.stop_server()
|
||||
await conf_server.shutdown()
|
||||
if mqtt_server.state == "started":
|
||||
await mqtt_server.shutdown()
|
||||
elif mqtt_server.state == "starting":
|
||||
|
|
|
|||
|
|
@ -1,25 +1,36 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Web server module."""
|
||||
|
||||
import asyncio
|
||||
import dataclasses
|
||||
import inspect
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import ssl
|
||||
from typing import Union
|
||||
|
||||
import aiohttp_jinja2
|
||||
import jinja2
|
||||
from aiohttp import web
|
||||
from aiohttp.typedefs import Handler
|
||||
from aiohttp.web_exceptions import (
|
||||
HTTPInternalServerError,
|
||||
HTTPNoContent,
|
||||
HTTPBadRequest,
|
||||
)
|
||||
from aiohttp.web_request import Request
|
||||
from aiohttp.web_response import Response, StreamResponse
|
||||
|
||||
from bumper import plugins
|
||||
from bumper.models import *
|
||||
import bumper
|
||||
from .plugins import ConfServerApp
|
||||
|
||||
from .util import get_logger
|
||||
|
||||
|
||||
class aiohttp_filter(logging.Filter):
|
||||
def filter(self, record):
|
||||
if (
|
||||
record.name == "aiohttp.access" and record.levelno == 20
|
||||
): # Filters aiohttp.access log to switch it from INFO to DEBUG
|
||||
class _aiohttp_filter(logging.Filter):
|
||||
def filter(self, record: logging.LogRecord) -> bool:
|
||||
if record.name == "aiohttp.access" and record.levelno == 20:
|
||||
# Filters aiohttp.access log to switch it from INFO to DEBUG
|
||||
record.levelno = 10
|
||||
record.levelname = "DEBUG"
|
||||
|
||||
|
|
@ -30,53 +41,64 @@ class aiohttp_filter(logging.Filter):
|
|||
|
||||
|
||||
confserverlog = get_logger("confserver")
|
||||
logging.getLogger("aiohttp.access").addFilter(
|
||||
aiohttp_filter()
|
||||
) # Add logging filter above to aiohttp.access
|
||||
# Add logging filter above to aiohttp.access
|
||||
logging.getLogger("aiohttp.access").addFilter(_aiohttp_filter())
|
||||
|
||||
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
class WebServerBinding:
|
||||
"""Web server binding."""
|
||||
|
||||
host: str
|
||||
port: int
|
||||
use_ssl: bool
|
||||
|
||||
|
||||
class ConfServer:
|
||||
def __init__(self, address, usessl=False):
|
||||
self.usessl = usessl
|
||||
self.address = address
|
||||
self.app = None
|
||||
self.site = None
|
||||
self.runner = None
|
||||
self.runners = []
|
||||
self.excludelogging = ["base", "remove-bot", "remove-client", "restart-service"]
|
||||
"""Web server."""
|
||||
|
||||
def get_milli_time(self, timetoconvert):
|
||||
return int(round(timetoconvert * 1000))
|
||||
_EXCLUDE_FROM_LOGGING = ["base", "remove-bot", "remove-client", "restart-service"]
|
||||
|
||||
def confserver_app(self):
|
||||
self.app = web.Application(
|
||||
def __init__(self, bindings: Union[list[WebServerBinding], WebServerBinding]):
|
||||
self._runners: list[web.AppRunner] = []
|
||||
|
||||
if isinstance(bindings, WebServerBinding):
|
||||
bindings = [bindings]
|
||||
self._bindings = bindings
|
||||
|
||||
self._app = web.Application(
|
||||
middlewares=[
|
||||
self.log_all_requests,
|
||||
self._log_all_requests,
|
||||
],
|
||||
)
|
||||
aiohttp_jinja2.setup(
|
||||
self.app,
|
||||
self._app,
|
||||
loader=jinja2.FileSystemLoader(
|
||||
os.path.join(bumper.bumper_dir, "bumper", "web", "templates")
|
||||
),
|
||||
)
|
||||
self._add_routes()
|
||||
self._app.freeze() # no modification allowed anymore
|
||||
|
||||
self.app.add_routes(
|
||||
def _add_routes(self) -> None:
|
||||
self._app.add_routes(
|
||||
[
|
||||
web.get("", self.handle_base, name="base"),
|
||||
web.get("/bot/remove/{did}", self.handle_RemoveBot, name="remove-bot"),
|
||||
web.get("", self._handle_base, name="base"),
|
||||
web.get(
|
||||
"/bot/remove/{did}", self._handle_remove_bot, name="remove-bot"
|
||||
),
|
||||
web.get(
|
||||
"/client/remove/{resource}",
|
||||
self.handle_RemoveClient,
|
||||
self._handle_remove_client,
|
||||
name="remove-client",
|
||||
),
|
||||
web.get(
|
||||
"/restart_{service}",
|
||||
self.handle_RestartService,
|
||||
self._handle_restart_service,
|
||||
name="restart-service",
|
||||
),
|
||||
web.post("/lookup.do", self.handle_lookup),
|
||||
web.post("/newauth.do", self.handle_newauth),
|
||||
web.post("/lookup.do", self._handle_lookup),
|
||||
web.post("/newauth.do", self._handle_newauth),
|
||||
]
|
||||
)
|
||||
|
||||
|
|
@ -94,11 +116,17 @@ class ConfServer:
|
|||
}
|
||||
|
||||
# Load plugins
|
||||
for plug in bumper.discovered_plugins:
|
||||
if isinstance(
|
||||
bumper.discovered_plugins[plug].plugin, bumper.plugins.ConfServerApp
|
||||
):
|
||||
plugin = bumper.discovered_plugins[plug].plugin
|
||||
for module in bumper.discovered_plugins.values():
|
||||
plugins = [
|
||||
m[1]
|
||||
for m in inspect.getmembers(module, inspect.isclass)
|
||||
if m[1].__module__ == module.__name__
|
||||
]
|
||||
for plugin_type in plugins:
|
||||
if not issubclass(plugin_type, ConfServerApp):
|
||||
continue
|
||||
|
||||
plugin = plugin_type()
|
||||
if plugin.plugin_type == "sub_api": # app or sub_api
|
||||
if plugin.sub_api in apis:
|
||||
if plugin.routes:
|
||||
|
|
@ -108,73 +136,51 @@ class ConfServer:
|
|||
elif plugin.plugin_type == "app":
|
||||
if plugin.path_prefix and plugin.app:
|
||||
logging.debug(f"Adding confserver plugin ({plugin.name})")
|
||||
self.app.add_subapp(plugin.path_prefix, plugin.app)
|
||||
self._app.add_subapp(plugin.path_prefix, plugin.app)
|
||||
|
||||
for api in apis:
|
||||
self.app.add_subapp(apis[api]["prefix"], apis[api]["app"])
|
||||
self._app.add_subapp(apis[api]["prefix"], apis[api]["app"])
|
||||
|
||||
# for resource in self.app.router.resources():
|
||||
# print(resource)
|
||||
|
||||
async def start_site(self, app, address="localhost", port=8080, usessl=False):
|
||||
async def start(self) -> None:
|
||||
"""Start server."""
|
||||
try:
|
||||
runner = web.AppRunner(app)
|
||||
self.runners.append(runner)
|
||||
confserverlog.info("Starting ConfServer")
|
||||
for binding in self._bindings:
|
||||
runner = web.AppRunner(self._app)
|
||||
self._runners.append(runner)
|
||||
await runner.setup()
|
||||
if usessl:
|
||||
|
||||
ssl_ctx = None
|
||||
if binding.use_ssl:
|
||||
ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
||||
ssl_ctx.load_cert_chain(bumper.server_cert, bumper.server_key)
|
||||
|
||||
site = web.TCPSite(
|
||||
runner,
|
||||
host=address,
|
||||
port=port,
|
||||
host=binding.host,
|
||||
port=binding.port,
|
||||
ssl_context=ssl_ctx,
|
||||
)
|
||||
|
||||
else:
|
||||
site = web.TCPSite(runner, host=address, port=port)
|
||||
|
||||
await site.start()
|
||||
except Exception as e:
|
||||
confserverlog.exception(f"{e}")
|
||||
raise e
|
||||
|
||||
async def start_server(self):
|
||||
async def shutdown(self) -> None:
|
||||
"""Shutdown server."""
|
||||
try:
|
||||
confserverlog.info(
|
||||
f"Starting ConfServer at {self.address[0]}:{self.address[1]}"
|
||||
)
|
||||
self.runner = web.AppRunner(self.app)
|
||||
await self.runner.setup()
|
||||
confserverlog.info("Shutting down")
|
||||
for runner in self._runners:
|
||||
await runner.shutdown()
|
||||
|
||||
if self.usessl:
|
||||
ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
||||
ssl_ctx.load_cert_chain(bumper.server_cert, bumper.server_key)
|
||||
self.site = web.TCPSite(
|
||||
self.runner,
|
||||
host=self.address[0],
|
||||
port=self.address[1],
|
||||
ssl_context=ssl_ctx,
|
||||
)
|
||||
|
||||
else:
|
||||
self.site = web.TCPSite(
|
||||
self.runner, host=self.address[0], port=self.address[1]
|
||||
)
|
||||
|
||||
await self.site.start()
|
||||
except Exception as e:
|
||||
confserverlog.exception(f"{e}")
|
||||
raise e
|
||||
|
||||
async def stop_server(self):
|
||||
try:
|
||||
await self.runner.shutdown()
|
||||
self._runners.clear()
|
||||
await self._app.shutdown()
|
||||
|
||||
except Exception as e:
|
||||
confserverlog.exception(f"{e}")
|
||||
|
||||
async def handle_base(self, request):
|
||||
async def _handle_base(self, request: Request) -> Response:
|
||||
try:
|
||||
bots = bumper.db_get().table("bots").all()
|
||||
clients = bumper.db_get().table("clients").all()
|
||||
|
|
@ -196,20 +202,21 @@ class ConfServer:
|
|||
"sessions": {
|
||||
"count": len(mq_sessions),
|
||||
"clients": mq_sessions,
|
||||
}
|
||||
},
|
||||
},
|
||||
"xmpp_server": bumper.xmpp_server,
|
||||
}
|
||||
resp = aiohttp_jinja2.render_template("home.jinja2", request, context=all)
|
||||
return resp
|
||||
|
||||
return aiohttp_jinja2.render_template("home.jinja2", request, context=all)
|
||||
except Exception as e:
|
||||
confserverlog.exception(f"{e}")
|
||||
|
||||
@web.middleware
|
||||
async def log_all_requests(self, request, handler):
|
||||
raise HTTPInternalServerError
|
||||
|
||||
if request._match_info.route.name not in self.excludelogging:
|
||||
@web.middleware
|
||||
async def _log_all_requests(
|
||||
self, request: Request, handler: Handler
|
||||
) -> StreamResponse:
|
||||
if request._match_info.route.name not in self._EXCLUDE_FROM_LOGGING:
|
||||
to_log = {
|
||||
"request": {
|
||||
"route_name": f"{request.match_info.route.name}",
|
||||
|
|
@ -230,8 +237,8 @@ class ConfServer:
|
|||
try:
|
||||
postbody = json.loads(await request.text())
|
||||
except Exception as e:
|
||||
confserverlog.error(f"Request body not json: {e} - {e.doc}")
|
||||
postbody = e.doc
|
||||
confserverlog.error(f"Request body not json: {e}")
|
||||
raise HTTPBadRequest(reason="Body was not json")
|
||||
|
||||
else:
|
||||
postbody = await request.post()
|
||||
|
|
@ -242,12 +249,15 @@ class ConfServer:
|
|||
if response is None:
|
||||
confserverlog.warning("Response was null!")
|
||||
confserverlog.warning(json.dumps(to_log))
|
||||
return response
|
||||
raise HTTPNoContent
|
||||
|
||||
to_log["response"] = {
|
||||
"status": f"{response.status}",
|
||||
}
|
||||
if not "application/octet-stream" in response.content_type:
|
||||
if (
|
||||
"application/octet-stream" not in response.content_type
|
||||
and isinstance(response, Response)
|
||||
):
|
||||
to_log["response"]["body"] = f"{json.loads(response.body)}"
|
||||
|
||||
confserverlog.debug(json.dumps(to_log))
|
||||
|
|
@ -262,16 +272,16 @@ class ConfServer:
|
|||
except Exception as e:
|
||||
confserverlog.exception(f"{e}")
|
||||
confserverlog.error(json.dumps(to_log))
|
||||
return e
|
||||
raise e
|
||||
|
||||
else:
|
||||
return await handler(request)
|
||||
|
||||
async def restart_Helper(self):
|
||||
async def _restart_helper_bot(self) -> None:
|
||||
await bumper.mqtt_helperbot.disconnect()
|
||||
asyncio.create_task(bumper.mqtt_helperbot.start())
|
||||
|
||||
async def restart_MQTT(self):
|
||||
async def _restart_mqtt_server(self) -> None:
|
||||
loop = asyncio.get_event_loop()
|
||||
|
||||
if bumper.mqtt_server.state not in ["stopped", "not_started"]:
|
||||
|
|
@ -287,35 +297,31 @@ class ConfServer:
|
|||
|
||||
loop.call_later(1.5, lambda: asyncio.create_task(bumper.mqtt_server.start()))
|
||||
|
||||
async def restart_XMPP(self):
|
||||
bumper.xmpp_server.disconnect()
|
||||
await bumper.xmpp_server.start_async_server()
|
||||
|
||||
async def handle_RestartService(self, request):
|
||||
async def _handle_restart_service(self, request: Request) -> Response:
|
||||
try:
|
||||
service = request.match_info.get("service", "")
|
||||
if service == "Helperbot":
|
||||
await self.restart_Helper()
|
||||
await self._restart_helper_bot()
|
||||
return web.json_response({"status": "complete"})
|
||||
elif service == "MQTTServer":
|
||||
asyncio.create_task(self.restart_MQTT())
|
||||
if service == "MQTTServer":
|
||||
asyncio.create_task(self._restart_mqtt_server())
|
||||
aloop = asyncio.get_event_loop()
|
||||
aloop.call_later(
|
||||
5, lambda: asyncio.create_task(self.restart_Helper())
|
||||
5, lambda: asyncio.create_task(self._restart_helper_bot())
|
||||
) # In 5 seconds restart Helperbot
|
||||
|
||||
return web.json_response({"status": "complete"})
|
||||
elif service == "XMPPServer":
|
||||
await self.restart_XMPP()
|
||||
if service == "XMPPServer":
|
||||
bumper.xmpp_server.disconnect()
|
||||
await bumper.xmpp_server.start_async_server()
|
||||
return web.json_response({"status": "complete"})
|
||||
else:
|
||||
return web.json_response({"status": "invalid service"})
|
||||
|
||||
return web.json_response({"status": "invalid service"})
|
||||
except Exception as e:
|
||||
confserverlog.exception(f"{e}")
|
||||
pass
|
||||
raise
|
||||
|
||||
async def handle_RemoveBot(self, request):
|
||||
async def _handle_remove_bot(self, request: Request) -> Response:
|
||||
try:
|
||||
did = request.match_info.get("did", "")
|
||||
bumper.bot_remove(did)
|
||||
|
|
@ -326,9 +332,10 @@ class ConfServer:
|
|||
|
||||
except Exception as e:
|
||||
confserverlog.exception(f"{e}")
|
||||
pass
|
||||
|
||||
async def handle_RemoveClient(self, request):
|
||||
raise HTTPInternalServerError
|
||||
|
||||
async def _handle_remove_client(self, request: Request) -> Response:
|
||||
try:
|
||||
resource = request.match_info.get("resource", "")
|
||||
bumper.client_remove(resource)
|
||||
|
|
@ -339,93 +346,20 @@ class ConfServer:
|
|||
|
||||
except Exception as e:
|
||||
confserverlog.exception(f"{e}")
|
||||
pass
|
||||
|
||||
async def handle_login(self, request):
|
||||
raise HTTPInternalServerError
|
||||
|
||||
async def _handle_lookup(self, request: Request) -> Response:
|
||||
try:
|
||||
user_devid = request.match_info.get("devid", "")
|
||||
countrycode = request.match_info.get("country", "us")
|
||||
apptype = request.match_info.get("apptype", "")
|
||||
confserverlog.info(f"client with devid {user_devid} attempting login")
|
||||
if bumper.use_auth:
|
||||
if (
|
||||
not user_devid == ""
|
||||
): # Performing basic "auth" using devid, super insecure
|
||||
user = bumper.user_by_deviceid(user_devid)
|
||||
if "checkLogin" in request.path:
|
||||
self.check_token(
|
||||
apptype, countrycode, user, request.query["accessToken"]
|
||||
)
|
||||
else:
|
||||
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()
|
||||
|
||||
# Deactivate old tokens and authcodes
|
||||
bumper.user_revoke_expired_tokens(user["userid"])
|
||||
|
||||
login_details.accessToken = self.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": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
||||
body = {
|
||||
"code": bumper.ERR_USER_NOT_ACTIVATED,
|
||||
"data": None,
|
||||
"msg": "当前密码错误",
|
||||
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
||||
else:
|
||||
return web.json_response(
|
||||
self._auth_any(user_devid, apptype, countrycode, request)
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
confserverlog.exception(f"{e}")
|
||||
|
||||
async def handle_lookup(self, request):
|
||||
try:
|
||||
|
||||
body = {}
|
||||
postbody = {}
|
||||
if request.content_type == "application/x-www-form-urlencoded":
|
||||
postbody = await request.post()
|
||||
|
||||
body = await request.post()
|
||||
else:
|
||||
postbody = json.loads(await request.text())
|
||||
body = json.loads(await request.text())
|
||||
|
||||
confserverlog.debug(postbody)
|
||||
confserverlog.debug(body)
|
||||
|
||||
todo = postbody["todo"]
|
||||
if todo == "FindBest":
|
||||
service = postbody["service"]
|
||||
if body["todo"] == "FindBest":
|
||||
service = body["service"]
|
||||
if service == "EcoMsgNew":
|
||||
srvip = bumper.bumper_announce_ip
|
||||
srvport = 5223
|
||||
|
|
@ -434,13 +368,10 @@ class ConfServer:
|
|||
srvip, srvport
|
||||
)
|
||||
)
|
||||
msgserver = {"ip": srvip, "port": srvport, "result": "ok"}
|
||||
msgserver = json.dumps(msgserver)
|
||||
msgserver = msgserver.replace(
|
||||
" ", ""
|
||||
) # bot seems to be very picky about having no spaces, only way was with text
|
||||
|
||||
return web.json_response(text=msgserver)
|
||||
server = json.dumps({"ip": srvip, "port": srvport, "result": "ok"})
|
||||
# bot seems to be very picky about having no spaces, only way was with text
|
||||
server = server.replace(" ", "")
|
||||
return web.json_response(text=server)
|
||||
|
||||
elif service == "EcoUpdate":
|
||||
srvip = "47.88.66.164" # EcoVacs Server
|
||||
|
|
@ -450,14 +381,18 @@ class ConfServer:
|
|||
srvip, srvport
|
||||
)
|
||||
)
|
||||
body = {"result": "ok", "ip": srvip, "port": srvport}
|
||||
return web.json_response(
|
||||
{"result": "ok", "ip": srvip, "port": srvport}
|
||||
)
|
||||
|
||||
return web.json_response(body)
|
||||
return web.json_response({})
|
||||
|
||||
except Exception as e:
|
||||
confserverlog.exception(f"{e}")
|
||||
|
||||
async def handle_newauth(self, request):
|
||||
raise HTTPInternalServerError
|
||||
|
||||
async def _handle_newauth(self, request: Request) -> Response:
|
||||
# Bumper is only returning the submitted token. No reason yet to create another new token
|
||||
try:
|
||||
if request.content_type == "application/x-www-form-urlencoded":
|
||||
|
|
@ -474,401 +409,4 @@ class ConfServer:
|
|||
except Exception as e:
|
||||
confserverlog.exception(f"{e}")
|
||||
|
||||
async def disconnect(self):
|
||||
try:
|
||||
confserverlog.info("shutting down")
|
||||
await self.app.shutdown()
|
||||
|
||||
except Exception as e:
|
||||
confserverlog.exception(f"{e}")
|
||||
|
||||
class ConfServer_GeneralFunctions:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def get_milli_time(self, timetoconvert):
|
||||
return int(round(timetoconvert * 1000))
|
||||
|
||||
class ConfServer_AuthHandler:
|
||||
def __init__(self):
|
||||
self.get_milli_time = (
|
||||
bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
|
||||
)
|
||||
pass
|
||||
|
||||
def generate_token(self, user):
|
||||
try:
|
||||
tmpaccesstoken = uuid.uuid4().hex
|
||||
bumper.user_add_token(user["userid"], tmpaccesstoken)
|
||||
return tmpaccesstoken
|
||||
|
||||
except Exception as e:
|
||||
confserverlog.exception(f"{e}")
|
||||
|
||||
def generate_authcode(self, user, countrycode, token):
|
||||
try:
|
||||
tmpauthcode = f"{countrycode}_{uuid.uuid4().hex}"
|
||||
bumper.user_add_authcode(user["userid"], token, tmpauthcode)
|
||||
return tmpauthcode
|
||||
|
||||
except Exception as e:
|
||||
confserverlog.exception(f"{e}")
|
||||
|
||||
async def login(self, request):
|
||||
try:
|
||||
user_devid = request.match_info.get("devid", "")
|
||||
countrycode = request.match_info.get("country", "us")
|
||||
apptype = request.match_info.get("apptype", "")
|
||||
confserverlog.info(f"client with devid {user_devid} attempting login")
|
||||
if bumper.use_auth:
|
||||
if (
|
||||
not user_devid == ""
|
||||
): # Performing basic "auth" using devid, super insecure
|
||||
user = bumper.user_by_deviceid(user_devid)
|
||||
if "checkLogin" in request.path:
|
||||
self.check_token(
|
||||
apptype, countrycode, user, request.query["accessToken"]
|
||||
)
|
||||
else:
|
||||
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()
|
||||
|
||||
# Deactivate old tokens and authcodes
|
||||
bumper.user_revoke_expired_tokens(user["userid"])
|
||||
|
||||
login_details.accessToken = self.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": self.get_milli_time(
|
||||
datetime.utcnow().timestamp()
|
||||
),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
||||
body = {
|
||||
"code": bumper.ERR_USER_NOT_ACTIVATED,
|
||||
"data": None,
|
||||
"msg": "当前密码错误",
|
||||
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
||||
else:
|
||||
return web.json_response(
|
||||
self._auth_any(user_devid, apptype, countrycode, request)
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
confserverlog.exception(f"{e}")
|
||||
|
||||
async def get_AuthCode(self, request):
|
||||
try:
|
||||
apptype = request.match_info.get("apptype", "")
|
||||
user_devid = request.match_info.get("devid", "") # Ecovacs
|
||||
if user_devid == "":
|
||||
user_devid = request.query["deviceId"] # Ecovacs Home
|
||||
|
||||
if not user_devid == "":
|
||||
user = bumper.user_by_deviceid(user_devid)
|
||||
token = ""
|
||||
if user:
|
||||
if "accessToken" in request.query:
|
||||
token = bumper.user_get_token(
|
||||
user["userid"], request.query["accessToken"]
|
||||
)
|
||||
if token:
|
||||
authcode = ""
|
||||
if not "authcode" in token:
|
||||
authcode = self.generate_authcode(
|
||||
user,
|
||||
request.match_info.get("country", "us"),
|
||||
request.query["accessToken"],
|
||||
)
|
||||
else:
|
||||
authcode = token["authcode"]
|
||||
if "global" in apptype:
|
||||
body = {
|
||||
"code": bumper.RETURN_API_SUCCESS,
|
||||
"data": {
|
||||
"authCode": authcode,
|
||||
"ecovacsUid": request.query["uid"],
|
||||
},
|
||||
"msg": "操作成功",
|
||||
"success": True,
|
||||
"time": self.get_milli_time(
|
||||
datetime.utcnow().timestamp()
|
||||
),
|
||||
}
|
||||
else:
|
||||
body = {
|
||||
"code": bumper.RETURN_API_SUCCESS,
|
||||
"data": {
|
||||
"authCode": authcode,
|
||||
"ecovacsUid": request.query["uid"],
|
||||
},
|
||||
"msg": "操作成功",
|
||||
"time": self.get_milli_time(
|
||||
datetime.utcnow().timestamp()
|
||||
),
|
||||
}
|
||||
return web.json_response(body)
|
||||
|
||||
body = {
|
||||
"code": bumper.ERR_TOKEN_INVALID,
|
||||
"data": None,
|
||||
"msg": "当前密码错误",
|
||||
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
||||
except Exception as e:
|
||||
confserverlog.exception(f"{e}")
|
||||
|
||||
def check_token(self, apptype, countrycode, user, token):
|
||||
try:
|
||||
if bumper.check_token(user["userid"], token):
|
||||
|
||||
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": bumper.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": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
}
|
||||
return web.json_response(body)
|
||||
|
||||
else:
|
||||
body = {
|
||||
"code": bumper.ERR_TOKEN_INVALID,
|
||||
"data": None,
|
||||
"msg": "当前密码错误",
|
||||
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
}
|
||||
return web.json_response(body)
|
||||
|
||||
except Exception as e:
|
||||
confserverlog.exception(f"{e}")
|
||||
|
||||
def _auth_any(self, devid, apptype, country, request):
|
||||
try:
|
||||
user_devid = devid
|
||||
countrycode = country
|
||||
user = bumper.user_by_deviceid(user_devid)
|
||||
bots = bumper.db_get().table("bots").all()
|
||||
|
||||
if user: # Default to user 0
|
||||
tmpuser = user
|
||||
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 = self.generate_token(tmpuser)
|
||||
login_details.uid = "fuid_{}".format(tmpuser["userid"])
|
||||
login_details.username = "fusername_{}".format(tmpuser["userid"])
|
||||
login_details.country = countrycode
|
||||
login_details.email = "null@null.com"
|
||||
bumper.user_add_device(tmpuser["userid"], user_devid)
|
||||
else:
|
||||
bumper.user_add("tmpuser") # Add a new user
|
||||
tmpuser = bumper.user_get("tmpuser")
|
||||
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 = self.generate_token(tmpuser)
|
||||
login_details.uid = "fuid_{}".format(tmpuser["userid"])
|
||||
login_details.username = "fusername_{}".format(tmpuser["userid"])
|
||||
login_details.country = countrycode
|
||||
login_details.email = "null@null.com"
|
||||
bumper.user_add_device(tmpuser["userid"], user_devid)
|
||||
|
||||
for bot in bots: # Add all bots to the user
|
||||
if "did" in bot:
|
||||
bumper.user_add_bot(tmpuser["userid"], bot["did"])
|
||||
else:
|
||||
confserverlog.error(f"No DID for bot: {bot}")
|
||||
|
||||
if (
|
||||
"checkLogin" in request.path
|
||||
): # If request was to check a token do so
|
||||
checkToken = self.check_token(
|
||||
apptype, countrycode, tmpuser, request.query["accessToken"]
|
||||
)
|
||||
isGood = json.loads(checkToken.text)
|
||||
if isGood["code"] == "0000":
|
||||
return isGood
|
||||
|
||||
# Deactivate old tokens and authcodes
|
||||
bumper.user_revoke_expired_tokens(tmpuser["userid"])
|
||||
|
||||
body = {
|
||||
"code": bumper.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": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
}
|
||||
|
||||
return body
|
||||
|
||||
except Exception as e:
|
||||
confserverlog.exception(f"{e}")
|
||||
|
||||
def getUserAccountInfo(self, request):
|
||||
try:
|
||||
user_devid = request.match_info.get("devid", "")
|
||||
countrycode = request.match_info.get("country", "us")
|
||||
apptype = request.match_info.get("apptype", "")
|
||||
user = bumper.user_by_deviceid(user_devid)
|
||||
|
||||
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.uid = "fuid_{}".format(user["userid"])
|
||||
login_details.username = "fusername_{}".format(user["userid"])
|
||||
login_details.country = countrycode
|
||||
login_details.email = "null@null.com"
|
||||
|
||||
body = {
|
||||
"code": bumper.RETURN_API_SUCCESS,
|
||||
"data": {
|
||||
"email": login_details.email,
|
||||
"hasMobile": "N",
|
||||
"hasPassword": "Y",
|
||||
"uid": login_details.uid,
|
||||
"userName": login_details.username,
|
||||
"obfuscatedMobile": None,
|
||||
"mobile": None,
|
||||
"loginName": login_details.loginName,
|
||||
},
|
||||
"msg": "操作成功",
|
||||
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
}
|
||||
|
||||
# Example body
|
||||
# {
|
||||
# "code": "0000",
|
||||
# "data": {
|
||||
# "email": "user@gmail.com",
|
||||
# "hasMobile": "N",
|
||||
# "hasPassword": "Y",
|
||||
# "headIco": "",
|
||||
# "loginName": "user@gmail.com",
|
||||
# "mobile": null,
|
||||
# "mobileAreaNo": null,
|
||||
# "nickname": "",
|
||||
# "obfuscatedMobile": null,
|
||||
# "thirdLoginInfoList": [
|
||||
# {
|
||||
# "accountType": "WeChat",
|
||||
# "hasBind": "N"
|
||||
# }
|
||||
# ],
|
||||
# "uid": "20180719212155_*****",
|
||||
# "userName": "EAY*****"
|
||||
# },
|
||||
# "msg": "操作成功",
|
||||
# "success": true,
|
||||
# "time": 1578203898343
|
||||
# }
|
||||
|
||||
return web.json_response(body)
|
||||
|
||||
except Exception as e:
|
||||
confserverlog.exception(f"{e}")
|
||||
|
||||
async def logout(self, request):
|
||||
try:
|
||||
user_devid = request.match_info.get("devid", "")
|
||||
if not user_devid == "":
|
||||
user = bumper.user_by_deviceid(user_devid)
|
||||
if user:
|
||||
if bumper.check_token(
|
||||
user["userid"], request.query["accessToken"]
|
||||
):
|
||||
# Deactivate old tokens and authcodes
|
||||
bumper.user_revoke_token(
|
||||
user["userid"], request.query["accessToken"]
|
||||
)
|
||||
|
||||
body = {
|
||||
"code": bumper.RETURN_API_SUCCESS,
|
||||
"data": None,
|
||||
"msg": "操作成功",
|
||||
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
||||
except Exception as e:
|
||||
confserverlog.exception(f"{e}")
|
||||
raise HTTPInternalServerError
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ def os_db_path(): # createdir=True):
|
|||
return os.path.join(bumper.data_dir, "bumper.db")
|
||||
|
||||
|
||||
def db_get():
|
||||
def db_get() -> TinyDB:
|
||||
# Will create the database if it doesn't exist
|
||||
db = TinyDB(db_file())
|
||||
|
||||
|
|
@ -340,7 +340,7 @@ def bot_add(sn: str, did: str, devclass: str, resource: str, company: str) -> No
|
|||
bot_full_upsert(newbot.asdict())
|
||||
|
||||
|
||||
def bot_remove(did):
|
||||
def bot_remove(did: str):
|
||||
bots = db_get().table("bots")
|
||||
bot = bot_get(did)
|
||||
if bot:
|
||||
|
|
@ -392,7 +392,7 @@ def client_add(userid: str, realm: str, resource: str) -> None:
|
|||
client_full_upsert(newclient.asdict())
|
||||
|
||||
|
||||
def client_remove(resource):
|
||||
def client_remove(resource: str):
|
||||
clients = db_get().table("clients")
|
||||
client = client_get(resource)
|
||||
if client:
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ from typing import Any
|
|||
from amqtt.session import Session
|
||||
|
||||
import bumper
|
||||
from bumper.util import convert_to_millis
|
||||
|
||||
|
||||
class VacBotDevice:
|
||||
|
|
@ -116,9 +117,7 @@ class OAuth:
|
|||
|
||||
def toResponse(self):
|
||||
data = self.__dict__
|
||||
data[
|
||||
"expire_at"
|
||||
] = bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time(
|
||||
data["expire_at"] = convert_to_millis(
|
||||
datetime.fromisoformat(self.expire_at).timestamp()
|
||||
)
|
||||
return data
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
#!/usr/bin/env python3
|
||||
import json
|
||||
import logging
|
||||
|
||||
from aiohttp import web
|
||||
|
||||
from bumper import plugins
|
||||
from bumper.models import *
|
||||
import bumper
|
||||
from bumper.plugins import ConfServerApp
|
||||
|
||||
|
||||
class portal_api_appsvr(plugins.ConfServerApp):
|
||||
class portal_api_appsvr(ConfServerApp):
|
||||
def __init__(self):
|
||||
self.name = "portal_api_appsvr"
|
||||
self.plugin_type = "sub_api"
|
||||
|
|
@ -34,10 +35,6 @@ class portal_api_appsvr(plugins.ConfServerApp):
|
|||
),
|
||||
]
|
||||
|
||||
self.get_milli_time = (
|
||||
bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
|
||||
)
|
||||
|
||||
async def handle_appsvr_app(self, request):
|
||||
if not request.method == "GET": # Skip GET for now
|
||||
try:
|
||||
|
|
@ -211,6 +208,3 @@ class portal_api_appsvr(plugins.ConfServerApp):
|
|||
|
||||
except Exception as e:
|
||||
logging.exception(f"{e}")
|
||||
|
||||
|
||||
plugin = portal_api_appsvr()
|
||||
|
|
|
|||
|
|
@ -27,10 +27,6 @@ class portal_api_dim(plugins.ConfServerApp):
|
|||
),
|
||||
]
|
||||
|
||||
self.get_milli_time = (
|
||||
bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
|
||||
)
|
||||
|
||||
async def handle_dim_devmanager(self, request): # Used in EcoVacs Home App
|
||||
try:
|
||||
json_body = json.loads(await request.text())
|
||||
|
|
@ -76,6 +72,3 @@ class portal_api_dim(plugins.ConfServerApp):
|
|||
|
||||
except Exception as e:
|
||||
logging.exception(f"{e}")
|
||||
|
||||
|
||||
plugin = portal_api_dim()
|
||||
|
|
|
|||
|
|
@ -22,10 +22,6 @@ class portal_api_ecms(plugins.ConfServerApp):
|
|||
),
|
||||
]
|
||||
|
||||
self.get_milli_time = (
|
||||
bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
|
||||
)
|
||||
|
||||
async def handle_ad_res(self, request):
|
||||
try:
|
||||
body = {"code": 0, "data": [], "message": "success", "success": True}
|
||||
|
|
@ -34,6 +30,3 @@ class portal_api_ecms(plugins.ConfServerApp):
|
|||
|
||||
except Exception as e:
|
||||
logging.exception(f"{e}")
|
||||
|
||||
|
||||
plugin = portal_api_ecms()
|
||||
|
|
|
|||
|
|
@ -27,10 +27,6 @@ class portal_api_iot(plugins.ConfServerApp):
|
|||
),
|
||||
]
|
||||
|
||||
self.get_milli_time = (
|
||||
bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
|
||||
)
|
||||
|
||||
async def handle_devmanager_botcommand(self, request):
|
||||
try:
|
||||
json_body = json.loads(await request.text())
|
||||
|
|
@ -81,6 +77,3 @@ class portal_api_iot(plugins.ConfServerApp):
|
|||
|
||||
except Exception as e:
|
||||
logging.exception(f"{e}")
|
||||
|
||||
|
||||
plugin = portal_api_iot()
|
||||
|
|
|
|||
|
|
@ -20,10 +20,6 @@ class portal_api_lg(plugins.ConfServerApp):
|
|||
web.route("*", "/lg/log.do", self.handle_lg_log, name="portal_api_lg_log"),
|
||||
]
|
||||
|
||||
self.get_milli_time = (
|
||||
bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
|
||||
)
|
||||
|
||||
async def handle_lg_log(self, request): # EcoVacs Home
|
||||
randomid = "".join(random.sample(string.ascii_letters, 6))
|
||||
|
||||
|
|
@ -101,6 +97,3 @@ class portal_api_lg(plugins.ConfServerApp):
|
|||
|
||||
body = {"id": randomid, "errno": bumper.ERR_COMMON, "ret": "fail"}
|
||||
return web.json_response(body)
|
||||
|
||||
|
||||
plugin = portal_api_lg()
|
||||
|
|
|
|||
|
|
@ -37,10 +37,6 @@ class portal_api_neng(plugins.ConfServerApp):
|
|||
),
|
||||
]
|
||||
|
||||
self.get_milli_time = (
|
||||
bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
|
||||
)
|
||||
|
||||
async def handle_neng_hasUnreadMessage(self, request): # EcoVacs Home
|
||||
try:
|
||||
body = {"code": 0, "data": {"hasUnRead": True}}
|
||||
|
|
@ -107,6 +103,3 @@ class portal_api_neng(plugins.ConfServerApp):
|
|||
|
||||
except Exception as e:
|
||||
logging.exception(f"{e}")
|
||||
|
||||
|
||||
plugin = portal_api_neng()
|
||||
|
|
|
|||
|
|
@ -53,10 +53,6 @@ class portal_api_pim(plugins.ConfServerApp):
|
|||
),
|
||||
]
|
||||
|
||||
self.get_milli_time = (
|
||||
bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
|
||||
)
|
||||
|
||||
async def handle_getProductIotMap(self, request):
|
||||
try:
|
||||
body = {
|
||||
|
|
@ -130,8 +126,6 @@ class portal_api_pim(plugins.ConfServerApp):
|
|||
logging.exception(f"{e}")
|
||||
|
||||
|
||||
plugin = portal_api_pim()
|
||||
|
||||
confignetAllResponse = {
|
||||
"code": 0,
|
||||
"data": [
|
||||
|
|
|
|||
|
|
@ -19,10 +19,6 @@ class api_rapp(plugins.ConfServerApp):
|
|||
),
|
||||
]
|
||||
|
||||
self.get_milli_time = (
|
||||
bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
|
||||
)
|
||||
|
||||
async def handle_map_get(self, request):
|
||||
try:
|
||||
body = {
|
||||
|
|
@ -35,6 +31,3 @@ class api_rapp(plugins.ConfServerApp):
|
|||
|
||||
except Exception as e:
|
||||
logging.exception(f"{e}")
|
||||
|
||||
|
||||
plugin = api_rapp()
|
||||
|
|
|
|||
|
|
@ -25,10 +25,6 @@ class portal_api_users(plugins.ConfServerApp):
|
|||
),
|
||||
]
|
||||
|
||||
self.get_milli_time = (
|
||||
bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
|
||||
)
|
||||
|
||||
async def handle_usersapi(self, request):
|
||||
if not request.method == "GET": # Skip GET for now
|
||||
try:
|
||||
|
|
@ -120,6 +116,3 @@ class portal_api_users(plugins.ConfServerApp):
|
|||
# Return fail for GET
|
||||
body = {"result": "fail", "todo": "result"}
|
||||
return web.json_response(body)
|
||||
|
||||
|
||||
plugin = portal_api_users()
|
||||
|
|
|
|||
|
|
@ -26,10 +26,6 @@ class upload_global(plugins.ConfServerApp):
|
|||
),
|
||||
]
|
||||
|
||||
self.get_milli_time = (
|
||||
bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
|
||||
)
|
||||
|
||||
async def handle_upload_global_file(self, request):
|
||||
try:
|
||||
fileID = request.match_info.get("id", "")
|
||||
|
|
@ -42,6 +38,3 @@ class upload_global(plugins.ConfServerApp):
|
|||
|
||||
except Exception as e:
|
||||
logging.exception(f"{e}")
|
||||
|
||||
|
||||
plugin = upload_global()
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ from aiohttp import web
|
|||
import bumper
|
||||
from bumper import plugins
|
||||
from bumper.models import *
|
||||
from bumper.rest import auth_util
|
||||
|
||||
|
||||
class v1_global_auth(plugins.ConfServerApp):
|
||||
|
|
@ -16,19 +17,11 @@ class v1_global_auth(plugins.ConfServerApp):
|
|||
self.plugin_type = "sub_api"
|
||||
self.sub_api = "api_v1"
|
||||
|
||||
authhandler = bumper.ConfServer.ConfServer_AuthHandler()
|
||||
self.routes = [
|
||||
web.route(
|
||||
"*",
|
||||
"/global/auth/getAuthCode",
|
||||
authhandler.get_AuthCode,
|
||||
auth_util.get_authcode,
|
||||
name="v1_global_auth_getAuthCode",
|
||||
),
|
||||
]
|
||||
|
||||
self.get_milli_time = (
|
||||
bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
|
||||
)
|
||||
|
||||
|
||||
plugin = v1_global_auth()
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ from aiohttp import web
|
|||
import bumper
|
||||
from bumper import plugins
|
||||
from bumper.models import *
|
||||
from bumper.util import get_current_time_as_millis
|
||||
|
||||
|
||||
class v1_private_ad(plugins.ConfServerApp):
|
||||
|
|
@ -31,10 +32,6 @@ class v1_private_ad(plugins.ConfServerApp):
|
|||
),
|
||||
]
|
||||
|
||||
self.get_milli_time = (
|
||||
bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
|
||||
)
|
||||
|
||||
async def handle_getAdByPositionType(self, request): # EcoVacs Home
|
||||
try:
|
||||
body = {
|
||||
|
|
@ -42,7 +39,7 @@ class v1_private_ad(plugins.ConfServerApp):
|
|||
"data": None,
|
||||
"msg": "操作成功",
|
||||
"success": True,
|
||||
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
|
@ -57,13 +54,10 @@ class v1_private_ad(plugins.ConfServerApp):
|
|||
"data": None,
|
||||
"msg": "操作成功",
|
||||
"success": True,
|
||||
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
||||
except Exception as e:
|
||||
logging.exception(f"{e}")
|
||||
|
||||
|
||||
plugin = v1_private_ad()
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ from aiohttp import web
|
|||
import bumper
|
||||
from bumper import plugins
|
||||
from bumper.models import *
|
||||
from bumper.util import get_current_time_as_millis
|
||||
|
||||
|
||||
class v1_private_campaign(plugins.ConfServerApp):
|
||||
|
|
@ -25,13 +26,9 @@ class v1_private_campaign(plugins.ConfServerApp):
|
|||
),
|
||||
]
|
||||
|
||||
self.get_milli_time = (
|
||||
bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
|
||||
)
|
||||
|
||||
async def handle_homePageAlert(self, request):
|
||||
try:
|
||||
nextAlert = self.get_milli_time(
|
||||
nextAlert = convert_to_millis(
|
||||
(datetime.now() + timedelta(hours=12)).timestamp()
|
||||
)
|
||||
|
||||
|
|
@ -43,16 +40,13 @@ class v1_private_campaign(plugins.ConfServerApp):
|
|||
"hasCampaign": "N",
|
||||
"imageUrl": None,
|
||||
"nextAlertTime": nextAlert,
|
||||
"serverTime": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
"serverTime": get_current_time_as_millis(),
|
||||
},
|
||||
"msg": "操作成功",
|
||||
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
||||
except Exception as e:
|
||||
logging.exception(f"{e}")
|
||||
|
||||
|
||||
plugin = v1_private_campaign()
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ from aiohttp import web
|
|||
|
||||
from bumper import plugins
|
||||
from bumper.models import *
|
||||
from bumper.util import get_current_time_as_millis
|
||||
|
||||
|
||||
class v1_private_common(plugins.ConfServerApp):
|
||||
|
|
@ -64,10 +65,6 @@ class v1_private_common(plugins.ConfServerApp):
|
|||
),
|
||||
]
|
||||
|
||||
self.get_milli_time = (
|
||||
bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
|
||||
)
|
||||
|
||||
async def handle_checkVersion(self, request):
|
||||
try:
|
||||
body = {
|
||||
|
|
@ -82,7 +79,7 @@ class v1_private_common(plugins.ConfServerApp):
|
|||
"v": None,
|
||||
},
|
||||
"msg": "操作成功",
|
||||
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
|
@ -107,7 +104,7 @@ class v1_private_common(plugins.ConfServerApp):
|
|||
},
|
||||
"msg": "操作成功",
|
||||
"success": True,
|
||||
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
|
@ -122,7 +119,7 @@ class v1_private_common(plugins.ConfServerApp):
|
|||
"data": None,
|
||||
"msg": "操作成功",
|
||||
"success": True,
|
||||
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
|
@ -144,7 +141,7 @@ class v1_private_common(plugins.ConfServerApp):
|
|||
},
|
||||
"msg": "操作成功",
|
||||
"success": True,
|
||||
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
|
@ -163,7 +160,7 @@ class v1_private_common(plugins.ConfServerApp):
|
|||
"data": data,
|
||||
"msg": "操作成功",
|
||||
"success": True,
|
||||
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
|
@ -178,7 +175,7 @@ class v1_private_common(plugins.ConfServerApp):
|
|||
"data": AREA_LIST,
|
||||
"msg": "操作成功",
|
||||
"success": True,
|
||||
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
|
@ -210,7 +207,7 @@ class v1_private_common(plugins.ConfServerApp):
|
|||
],
|
||||
"msg": "操作成功",
|
||||
"success": True,
|
||||
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
|
@ -220,7 +217,7 @@ class v1_private_common(plugins.ConfServerApp):
|
|||
|
||||
async def handle_getTimestamp(self, request): # EcoVacs Home
|
||||
try:
|
||||
time = self.get_milli_time(datetime.utcnow().timestamp())
|
||||
time = get_current_time_as_millis()
|
||||
body = {
|
||||
"code": bumper.RETURN_API_SUCCESS,
|
||||
"data": {"timestamp": time},
|
||||
|
|
@ -235,8 +232,6 @@ class v1_private_common(plugins.ConfServerApp):
|
|||
logging.exception(f"{e}")
|
||||
|
||||
|
||||
plugin = v1_private_common()
|
||||
|
||||
AREA_LIST = {
|
||||
"currentVersion": 231,
|
||||
"areaList": [
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ from aiohttp import web
|
|||
import bumper
|
||||
from bumper import plugins
|
||||
from bumper.models import *
|
||||
from bumper.util import get_current_time_as_millis
|
||||
|
||||
|
||||
class v1_private_message(plugins.ConfServerApp):
|
||||
|
|
@ -31,10 +32,6 @@ class v1_private_message(plugins.ConfServerApp):
|
|||
),
|
||||
]
|
||||
|
||||
self.get_milli_time = (
|
||||
bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
|
||||
)
|
||||
|
||||
async def handle_hasUnreadMessage(self, request): # EcoVacs Home
|
||||
try:
|
||||
body = {
|
||||
|
|
@ -42,7 +39,7 @@ class v1_private_message(plugins.ConfServerApp):
|
|||
"data": "N",
|
||||
"msg": "操作成功",
|
||||
"success": True,
|
||||
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
|
@ -57,13 +54,10 @@ class v1_private_message(plugins.ConfServerApp):
|
|||
"data": {"hasNextPage": 0, "items": []},
|
||||
"msg": "操作成功",
|
||||
"success": True,
|
||||
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
||||
except Exception as e:
|
||||
logging.exception(f"{e}")
|
||||
|
||||
|
||||
plugin = v1_private_message()
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ from aiohttp import web
|
|||
import bumper
|
||||
from bumper import plugins
|
||||
from bumper.models import *
|
||||
from bumper.util import get_current_time_as_millis
|
||||
|
||||
|
||||
class v1_private_shop(plugins.ConfServerApp):
|
||||
|
|
@ -25,10 +26,6 @@ class v1_private_shop(plugins.ConfServerApp):
|
|||
),
|
||||
]
|
||||
|
||||
self.get_milli_time = (
|
||||
bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
|
||||
)
|
||||
|
||||
async def handle_getCnWapShopConfig(self, request): # EcoVacs Home
|
||||
try:
|
||||
body = {
|
||||
|
|
@ -41,13 +38,10 @@ class v1_private_shop(plugins.ConfServerApp):
|
|||
},
|
||||
"msg": "操作成功",
|
||||
"success": True,
|
||||
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
||||
except Exception as e:
|
||||
logging.exception(f"{e}")
|
||||
|
||||
|
||||
plugin = v1_private_shop()
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ from aiohttp import web
|
|||
import bumper
|
||||
from bumper import plugins
|
||||
from bumper.models import *
|
||||
from bumper.rest import auth_util
|
||||
from bumper.util import get_current_time_as_millis
|
||||
|
||||
|
||||
class v1_private_user(plugins.ConfServerApp):
|
||||
|
|
@ -17,30 +19,29 @@ class v1_private_user(plugins.ConfServerApp):
|
|||
self.plugin_type = "sub_api"
|
||||
self.sub_api = "api_v1"
|
||||
|
||||
authhandler = bumper.ConfServer.ConfServer_AuthHandler()
|
||||
self.routes = [
|
||||
web.route(
|
||||
"*",
|
||||
"/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/login",
|
||||
authhandler.login,
|
||||
auth_util.login,
|
||||
name="v1_user_login",
|
||||
),
|
||||
web.route(
|
||||
"*",
|
||||
"/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkLogin",
|
||||
authhandler.login,
|
||||
auth_util.login,
|
||||
name="v1_user_checkLogin",
|
||||
),
|
||||
web.route(
|
||||
"*",
|
||||
"/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/getAuthCode",
|
||||
authhandler.get_AuthCode,
|
||||
auth_util.get_authcode,
|
||||
name="v1_user_getAuthCode",
|
||||
),
|
||||
web.route(
|
||||
"*",
|
||||
"/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/logout",
|
||||
authhandler.logout,
|
||||
auth_util.logout,
|
||||
name="v1_user_logout",
|
||||
),
|
||||
web.route(
|
||||
|
|
@ -58,7 +59,7 @@ class v1_private_user(plugins.ConfServerApp):
|
|||
web.route(
|
||||
"*",
|
||||
"/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/getUserAccountInfo",
|
||||
authhandler.getUserAccountInfo,
|
||||
auth_util.get_user_account_info,
|
||||
name="v1_user_getUserAccountInfo",
|
||||
),
|
||||
web.route(
|
||||
|
|
@ -91,10 +92,6 @@ class v1_private_user(plugins.ConfServerApp):
|
|||
# /registerByEmail
|
||||
]
|
||||
|
||||
self.get_milli_time = (
|
||||
bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
|
||||
)
|
||||
|
||||
async def handle_checkAgreement(self, request):
|
||||
try:
|
||||
apptype = request.match_info.get("apptype", "")
|
||||
|
|
@ -119,14 +116,14 @@ class v1_private_user(plugins.ConfServerApp):
|
|||
],
|
||||
"msg": "操作成功",
|
||||
"success": True,
|
||||
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
else:
|
||||
body = {
|
||||
"code": bumper.RETURN_API_SUCCESS,
|
||||
"data": [],
|
||||
"msg": "操作成功",
|
||||
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
|
@ -195,7 +192,7 @@ class v1_private_user(plugins.ConfServerApp):
|
|||
],
|
||||
"msg": "操作成功",
|
||||
"success": True,
|
||||
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
|
@ -210,7 +207,7 @@ class v1_private_user(plugins.ConfServerApp):
|
|||
"data": {"isNeedReLogin": "N"},
|
||||
"msg": "操作成功",
|
||||
"success": True,
|
||||
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
|
@ -225,13 +222,10 @@ class v1_private_user(plugins.ConfServerApp):
|
|||
"data": None,
|
||||
"msg": "操作成功",
|
||||
"success": True,
|
||||
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
||||
except Exception as e:
|
||||
logging.exception(f"{e}")
|
||||
|
||||
|
||||
plugin = v1_private_user()
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
#!/usr/bin/env python3
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
from aiohttp import web
|
||||
|
||||
import bumper
|
||||
from bumper import plugins
|
||||
from bumper.util import get_current_time_as_millis
|
||||
|
||||
|
||||
class v1_private_userSetting(plugins.ConfServerApp):
|
||||
|
|
@ -24,10 +24,6 @@ class v1_private_userSetting(plugins.ConfServerApp):
|
|||
),
|
||||
]
|
||||
|
||||
self.get_milli_time = (
|
||||
bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
|
||||
)
|
||||
|
||||
async def handle_getSuggestionSetting(self, request):
|
||||
try:
|
||||
|
||||
|
|
@ -54,13 +50,10 @@ class v1_private_userSetting(plugins.ConfServerApp):
|
|||
],
|
||||
},
|
||||
"msg": "操作成功",
|
||||
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
||||
except Exception as e:
|
||||
logging.exception(f"{e}")
|
||||
|
||||
|
||||
plugin = v1_private_userSetting()
|
||||
|
|
|
|||
|
|
@ -1,13 +1,8 @@
|
|||
#!/usr/bin/env python3
|
||||
import asyncio
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from aiohttp import web
|
||||
|
||||
import bumper
|
||||
from bumper import plugins
|
||||
from bumper.models import *
|
||||
from bumper.rest import auth_util
|
||||
|
||||
|
||||
class v2_private_user(plugins.ConfServerApp):
|
||||
|
|
@ -17,19 +12,11 @@ class v2_private_user(plugins.ConfServerApp):
|
|||
self.plugin_type = "sub_api"
|
||||
self.sub_api = "api_v2"
|
||||
|
||||
authhandler = bumper.ConfServer.ConfServer_AuthHandler()
|
||||
self.routes = [
|
||||
web.route(
|
||||
"*",
|
||||
"/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkLogin",
|
||||
authhandler.login,
|
||||
auth_util.login,
|
||||
name="v2_user_checkLogin",
|
||||
),
|
||||
]
|
||||
|
||||
self.get_milli_time = (
|
||||
bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
|
||||
)
|
||||
|
||||
|
||||
plugin = v2_private_user()
|
||||
|
|
|
|||
0
bumper/rest/__init__.py
Normal file
0
bumper/rest/__init__.py
Normal file
384
bumper/rest/auth_util.py
Normal file
384
bumper/rest/auth_util.py
Normal file
|
|
@ -0,0 +1,384 @@
|
|||
"""Auth util module."""
|
||||
import json
|
||||
import uuid
|
||||
|
||||
from aiohttp import web
|
||||
|
||||
import bumper
|
||||
from bumper import (
|
||||
get_logger,
|
||||
EcoVacsHome_Login,
|
||||
EcoVacs_Login,
|
||||
API_ERRORS,
|
||||
RETURN_API_SUCCESS,
|
||||
)
|
||||
from bumper.util import get_current_time_as_millis
|
||||
|
||||
_logger = get_logger("confserver")
|
||||
|
||||
|
||||
def generate_token(user):
|
||||
try:
|
||||
tmpaccesstoken = uuid.uuid4().hex
|
||||
bumper.user_add_token(user["userid"], tmpaccesstoken)
|
||||
return tmpaccesstoken
|
||||
|
||||
except Exception as e:
|
||||
_logger.exception(f"{e}")
|
||||
|
||||
|
||||
def generate_authcode(user, countrycode, token):
|
||||
try:
|
||||
tmpauthcode = f"{countrycode}_{uuid.uuid4().hex}"
|
||||
bumper.user_add_authcode(user["userid"], token, tmpauthcode)
|
||||
return tmpauthcode
|
||||
|
||||
except Exception as e:
|
||||
_logger.exception(f"{e}")
|
||||
|
||||
|
||||
async def login(request):
|
||||
try:
|
||||
user_devid = request.match_info.get("devid", "")
|
||||
countrycode = request.match_info.get("country", "us")
|
||||
apptype = request.match_info.get("apptype", "")
|
||||
_logger.info(f"client with devid {user_devid} attempting login")
|
||||
if bumper.use_auth:
|
||||
if (
|
||||
not user_devid == ""
|
||||
): # Performing basic "auth" using devid, super insecure
|
||||
user = bumper.user_by_deviceid(user_devid)
|
||||
if "checkLogin" in request.path:
|
||||
check_token(
|
||||
apptype, countrycode, user, request.query["accessToken"]
|
||||
)
|
||||
else:
|
||||
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()
|
||||
|
||||
# Deactivate old tokens and authcodes
|
||||
bumper.user_revoke_expired_tokens(user["userid"])
|
||||
|
||||
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": bumper.ERR_USER_NOT_ACTIVATED,
|
||||
"data": None,
|
||||
"msg": "当前密码错误",
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
||||
else:
|
||||
return web.json_response(
|
||||
_auth_any(user_devid, apptype, countrycode, request)
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
_logger.exception(f"{e}")
|
||||
|
||||
|
||||
async def get_authcode(request):
|
||||
try:
|
||||
apptype = request.match_info.get("apptype", "")
|
||||
user_devid = request.match_info.get("devid", "") # Ecovacs
|
||||
if user_devid == "":
|
||||
user_devid = request.query["deviceId"] # Ecovacs Home
|
||||
|
||||
if not user_devid == "":
|
||||
user = bumper.user_by_deviceid(user_devid)
|
||||
token = ""
|
||||
if user:
|
||||
if "accessToken" in request.query:
|
||||
token = bumper.user_get_token(
|
||||
user["userid"], request.query["accessToken"]
|
||||
)
|
||||
if token:
|
||||
authcode = ""
|
||||
if not "authcode" in token:
|
||||
authcode = generate_authcode(
|
||||
user,
|
||||
request.match_info.get("country", "us"),
|
||||
request.query["accessToken"],
|
||||
)
|
||||
else:
|
||||
authcode = token["authcode"]
|
||||
if "global" in apptype:
|
||||
body = {
|
||||
"code": bumper.RETURN_API_SUCCESS,
|
||||
"data": {
|
||||
"authCode": authcode,
|
||||
"ecovacsUid": request.query["uid"],
|
||||
},
|
||||
"msg": "操作成功",
|
||||
"success": True,
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
else:
|
||||
body = {
|
||||
"code": bumper.RETURN_API_SUCCESS,
|
||||
"data": {
|
||||
"authCode": authcode,
|
||||
"ecovacsUid": request.query["uid"],
|
||||
},
|
||||
"msg": "操作成功",
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
return web.json_response(body)
|
||||
|
||||
body = {
|
||||
"code": bumper.ERR_TOKEN_INVALID,
|
||||
"data": None,
|
||||
"msg": "当前密码错误",
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
||||
except Exception as e:
|
||||
_logger.exception(f"{e}")
|
||||
|
||||
|
||||
def check_token(apptype, countrycode, user, token):
|
||||
try:
|
||||
if bumper.check_token(user["userid"], token):
|
||||
|
||||
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": bumper.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)
|
||||
|
||||
else:
|
||||
body = {
|
||||
"code": bumper.ERR_TOKEN_INVALID,
|
||||
"data": None,
|
||||
"msg": "当前密码错误",
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
return web.json_response(body)
|
||||
|
||||
except Exception as e:
|
||||
_logger.exception(f"{e}")
|
||||
|
||||
|
||||
def _auth_any(devid, apptype, country, request):
|
||||
try:
|
||||
user_devid = devid
|
||||
countrycode = country
|
||||
user = bumper.user_by_deviceid(user_devid)
|
||||
bots = bumper.db_get().table("bots").all()
|
||||
|
||||
if user: # Default to user 0
|
||||
tmpuser = user
|
||||
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)
|
||||
login_details.uid = "fuid_{}".format(tmpuser["userid"])
|
||||
login_details.username = "fusername_{}".format(tmpuser["userid"])
|
||||
login_details.country = countrycode
|
||||
login_details.email = "null@null.com"
|
||||
bumper.user_add_device(tmpuser["userid"], user_devid)
|
||||
else:
|
||||
bumper.user_add("tmpuser") # Add a new user
|
||||
tmpuser = bumper.user_get("tmpuser")
|
||||
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)
|
||||
login_details.uid = "fuid_{}".format(tmpuser["userid"])
|
||||
login_details.username = "fusername_{}".format(tmpuser["userid"])
|
||||
login_details.country = countrycode
|
||||
login_details.email = "null@null.com"
|
||||
bumper.user_add_device(tmpuser["userid"], user_devid)
|
||||
|
||||
for bot in bots: # Add all bots to the user
|
||||
if "did" in bot:
|
||||
bumper.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
|
||||
checkToken = check_token(
|
||||
apptype, countrycode, tmpuser, request.query["accessToken"]
|
||||
)
|
||||
isGood = json.loads(checkToken.text)
|
||||
if isGood["code"] == "0000":
|
||||
return isGood
|
||||
|
||||
# Deactivate old tokens and authcodes
|
||||
bumper.user_revoke_expired_tokens(tmpuser["userid"])
|
||||
|
||||
body = {
|
||||
"code": bumper.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
|
||||
|
||||
except Exception as e:
|
||||
_logger.exception(f"{e}")
|
||||
|
||||
|
||||
def get_user_account_info(request):
|
||||
try:
|
||||
user_devid = request.match_info.get("devid", "")
|
||||
countrycode = request.match_info.get("country", "us")
|
||||
apptype = request.match_info.get("apptype", "")
|
||||
user = bumper.user_by_deviceid(user_devid)
|
||||
|
||||
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.uid = "fuid_{}".format(user["userid"])
|
||||
login_details.username = "fusername_{}".format(user["userid"])
|
||||
login_details.country = countrycode
|
||||
login_details.email = "null@null.com"
|
||||
|
||||
body = {
|
||||
"code": bumper.RETURN_API_SUCCESS,
|
||||
"data": {
|
||||
"email": login_details.email,
|
||||
"hasMobile": "N",
|
||||
"hasPassword": "Y",
|
||||
"uid": login_details.uid,
|
||||
"userName": login_details.username,
|
||||
"obfuscatedMobile": None,
|
||||
"mobile": None,
|
||||
"loginName": login_details.loginName,
|
||||
},
|
||||
"msg": "操作成功",
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
|
||||
# Example body
|
||||
# {
|
||||
# "code": "0000",
|
||||
# "data": {
|
||||
# "email": "user@gmail.com",
|
||||
# "hasMobile": "N",
|
||||
# "hasPassword": "Y",
|
||||
# "headIco": "",
|
||||
# "loginName": "user@gmail.com",
|
||||
# "mobile": null,
|
||||
# "mobileAreaNo": null,
|
||||
# "nickname": "",
|
||||
# "obfuscatedMobile": null,
|
||||
# "thirdLoginInfoList": [
|
||||
# {
|
||||
# "accountType": "WeChat",
|
||||
# "hasBind": "N"
|
||||
# }
|
||||
# ],
|
||||
# "uid": "20180719212155_*****",
|
||||
# "userName": "EAY*****"
|
||||
# },
|
||||
# "msg": "操作成功",
|
||||
# "success": true,
|
||||
# "time": 1578203898343
|
||||
# }
|
||||
|
||||
return web.json_response(body)
|
||||
|
||||
except Exception as e:
|
||||
_logger.exception(f"{e}")
|
||||
|
||||
|
||||
async def logout(request):
|
||||
try:
|
||||
user_devid = request.match_info.get("devid", "")
|
||||
if not user_devid == "":
|
||||
user = bumper.user_by_deviceid(user_devid)
|
||||
if user:
|
||||
if bumper.check_token(user["userid"], request.query["accessToken"]):
|
||||
# Deactivate old tokens and authcodes
|
||||
bumper.user_revoke_token(
|
||||
user["userid"], request.query["accessToken"]
|
||||
)
|
||||
|
||||
body = {
|
||||
"code": bumper.RETURN_API_SUCCESS,
|
||||
"data": None,
|
||||
"msg": "操作成功",
|
||||
"time": get_current_time_as_millis(),
|
||||
}
|
||||
|
||||
return web.json_response(body)
|
||||
|
||||
except Exception as e:
|
||||
_logger.exception(f"{e}")
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
import logging
|
||||
import os
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from logging.handlers import RotatingFileHandler
|
||||
from typing import MutableMapping
|
||||
from typing import MutableMapping, Union
|
||||
|
||||
logformat = logging.Formatter(
|
||||
"[%(asctime)s] :: %(levelname)s :: %(name)s :: %(module)s :: %(funcName)s :: %(lineno)d :: %(message)s"
|
||||
|
|
@ -43,3 +44,12 @@ def get_logger(name: str, rotate: RotatingFileHandler = None) -> logging.Logger:
|
|||
get_logger("amqtt.client", rotate)
|
||||
|
||||
return logger
|
||||
|
||||
|
||||
def convert_to_millis(seconds: Union[int, float]) -> int:
|
||||
"""Convert seconds to milliseconds."""
|
||||
return int(round(seconds * 1000))
|
||||
|
||||
|
||||
def get_current_time_as_millis() -> int:
|
||||
return convert_to_millis(datetime.utcnow().timestamp())
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class XMPPServer:
|
|||
self.address = address
|
||||
self.xmpp_protocol = lambda: XMPPServer_Protocol()
|
||||
|
||||
async def start_async_server(self):
|
||||
async def start_async_server(self) -> None:
|
||||
try:
|
||||
xmppserverlog.info(
|
||||
f"Starting XMPP Server at {self.address[0]}:{self.address[1]}"
|
||||
|
|
@ -44,7 +44,7 @@ class XMPPServer:
|
|||
xmppserverlog.exception(f"{e}")
|
||||
raise e
|
||||
|
||||
def disconnect(self):
|
||||
def disconnect(self) -> None:
|
||||
|
||||
xmppserverlog.debug("waiting for all clients to disconnect")
|
||||
for client in self.clients:
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
HOST = "127.0.0.1"
|
||||
MQTT_PORT = 8883
|
||||
CONF_SERVER_PORT = 11111
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ import pytest
|
|||
from amqtt.client import MQTTClient
|
||||
|
||||
import bumper
|
||||
from tests import HOST, MQTT_PORT
|
||||
from bumper import WebServerBinding
|
||||
from tests import HOST, MQTT_PORT, CONF_SERVER_PORT
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
|
@ -37,10 +38,8 @@ async def mqtt_client():
|
|||
|
||||
@pytest.fixture
|
||||
async def conf_server_client(aiohttp_client):
|
||||
confserver = bumper.ConfServer("127.0.0.1:11111", False)
|
||||
confserver.confserver_app()
|
||||
|
||||
client = await aiohttp_client(confserver.app)
|
||||
confserver = bumper.ConfServer(WebServerBinding(HOST, CONF_SERVER_PORT, False))
|
||||
client = await aiohttp_client(confserver._app)
|
||||
|
||||
yield client
|
||||
|
||||
|
|
|
|||
|
|
@ -9,11 +9,12 @@ from aiohttp import web
|
|||
from testfixtures import LogCapture
|
||||
|
||||
import bumper
|
||||
from tests import HOST, MQTT_PORT
|
||||
from bumper import WebServerBinding
|
||||
from tests import HOST, MQTT_PORT, CONF_SERVER_PORT
|
||||
|
||||
|
||||
def create_confserver():
|
||||
return bumper.ConfServer("127.0.0.1:11111", False)
|
||||
return bumper.ConfServer(WebServerBinding(HOST, CONF_SERVER_PORT, False))
|
||||
|
||||
|
||||
def async_return(result):
|
||||
|
|
@ -28,27 +29,13 @@ def remove_existing_db():
|
|||
|
||||
|
||||
async def test_confserver_ssl():
|
||||
conf_server = bumper.ConfServer((HOST, 11111), usessl=True)
|
||||
conf_server.confserver_app()
|
||||
await conf_server.start_server()
|
||||
conf_server = bumper.ConfServer(WebServerBinding(HOST, CONF_SERVER_PORT, True))
|
||||
await conf_server.start()
|
||||
|
||||
|
||||
async def test_confserver_no_ssl():
|
||||
conf_server = bumper.ConfServer((HOST, 11112), usessl=False)
|
||||
conf_server.confserver_app()
|
||||
await conf_server.start_server()
|
||||
|
||||
|
||||
def test_get_milli_time():
|
||||
cserv = create_confserver()
|
||||
assert (
|
||||
cserv.get_milli_time(
|
||||
datetime.datetime(
|
||||
2018, 1, 1, 1, 0, 0, 0, tzinfo=datetime.timezone.utc
|
||||
).timestamp()
|
||||
)
|
||||
== 1514768400000
|
||||
)
|
||||
conf_server = bumper.ConfServer(WebServerBinding(HOST, 11112, False))
|
||||
await conf_server.start()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mqtt_server")
|
||||
|
|
|
|||
|
|
@ -26,15 +26,12 @@ async def test_start_stop():
|
|||
|
||||
b = bumper
|
||||
b.db = "tests/tmp.db" # Set db location for testing
|
||||
b.conf1_listen_address = "127.0.0.1"
|
||||
b.conf1_listen_port = 444
|
||||
asyncio.create_task(b.start())
|
||||
await asyncio.sleep(0.1)
|
||||
l.check_present(("bumper", "INFO", "Starting Bumper"))
|
||||
l.clear()
|
||||
|
||||
asyncio.create_task(b.shutdown())
|
||||
await asyncio.sleep(0.1)
|
||||
await b.shutdown()
|
||||
l.check_present(
|
||||
("bumper", "INFO", "Shutting down"), ("bumper", "INFO", "Shutdown complete")
|
||||
)
|
||||
|
|
|
|||
14
tests/test_util.py
Normal file
14
tests/test_util.py
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import datetime
|
||||
|
||||
from bumper.util import convert_to_millis
|
||||
|
||||
|
||||
def test_get_milli_time():
|
||||
assert (
|
||||
convert_to_millis(
|
||||
datetime.datetime(
|
||||
2018, 1, 1, 1, 0, 0, 0, tzinfo=datetime.timezone.utc
|
||||
).timestamp()
|
||||
)
|
||||
== 1514768400000
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue