start refactoring confserver

This commit is contained in:
Robert Resch 2022-03-06 00:03:05 +01:00
parent ba3f28165f
commit 4dce3c262c
32 changed files with 627 additions and 840 deletions

View file

@ -6,7 +6,7 @@ import socket
import sys import sys
from typing import Optional from typing import Optional
from bumper.confserver import ConfServer from bumper.confserver import ConfServer, WebServerBinding
from bumper.db import * from bumper.db import *
from bumper.models import * from bumper.models import *
from bumper.mqttserver import MQTTHelperBot, MQTTServer from bumper.mqttserver import MQTTHelperBot, MQTTServer
@ -53,11 +53,10 @@ token_validity_seconds = 3600 # 1 hour
oauth_validity_days = 15 oauth_validity_days = 15
db = None db = None
mqtt_server: Optional[MQTTServer] = None mqtt_server: MQTTServer
mqtt_helperbot: Optional[MQTTHelperBot] = None mqtt_helperbot: MQTTHelperBot
conf_server: Optional[ConfServer] = None conf_server: ConfServer
conf_server_2: Optional[ConfServer] = None xmpp_server: XMPPServer
xmpp_server: Optional[XMPPServer] = None
# Plugins # Plugins
sys.path.append(os.path.join(bumper_dir, "bumper", "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 logging.getLogger("asyncio").setLevel(logging.CRITICAL + 1) # Ignore this logger
mqtt_listen_port = 8883 mqtt_listen_port = 8883
conf1_listen_port = 443
conf2_listen_port = 8007
xmpp_listen_port = 5223 xmpp_listen_port = 5223
conf_server_bindings = [
WebServerBinding(bumper_listen, 8443, True),
WebServerBinding(bumper_listen, 8007, False),
]
async def start(): async def start():
@ -117,9 +118,7 @@ async def start():
global mqtt_helperbot global mqtt_helperbot
mqtt_helperbot = MQTTHelperBot(bumper_listen, mqtt_listen_port) mqtt_helperbot = MQTTHelperBot(bumper_listen, mqtt_listen_port)
global conf_server global conf_server
conf_server = ConfServer((bumper_listen, conf1_listen_port), usessl=True) conf_server = ConfServer(conf_server_bindings)
global conf_server_2
conf_server_2 = ConfServer((bumper_listen, conf2_listen_port), usessl=False)
global xmpp_server global xmpp_server
xmpp_server = XMPPServer((bumper_listen, xmpp_listen_port)) xmpp_server = XMPPServer((bumper_listen, xmpp_listen_port))
@ -138,17 +137,7 @@ async def start():
await asyncio.sleep(0.1) await asyncio.sleep(0.1)
# Start web servers # Start web servers
conf_server.confserver_app() await conf_server.start()
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
)
)
# Start maintenance # Start maintenance
while not shutting_down: while not shutting_down:
@ -165,8 +154,7 @@ async def shutdown():
try: try:
bumperlog.info("Shutting down") bumperlog.info("Shutting down")
await conf_server.stop_server() await conf_server.shutdown()
await conf_server_2.stop_server()
if mqtt_server.state == "started": if mqtt_server.state == "started":
await mqtt_server.shutdown() await mqtt_server.shutdown()
elif mqtt_server.state == "starting": elif mqtt_server.state == "starting":

View file

@ -1,25 +1,36 @@
#!/usr/bin/env python3 """Web server module."""
import asyncio import asyncio
import dataclasses
import inspect
import json
import logging import logging
import os import os
import ssl import ssl
from typing import Union
import aiohttp_jinja2 import aiohttp_jinja2
import jinja2 import jinja2
from aiohttp import web 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 import bumper
from bumper.models import * from .plugins import ConfServerApp
from .util import get_logger from .util import get_logger
class aiohttp_filter(logging.Filter): class _aiohttp_filter(logging.Filter):
def filter(self, record): def filter(self, record: logging.LogRecord) -> bool:
if ( if record.name == "aiohttp.access" and record.levelno == 20:
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"
@ -30,53 +41,64 @@ class aiohttp_filter(logging.Filter):
confserverlog = get_logger("confserver") confserverlog = get_logger("confserver")
logging.getLogger("aiohttp.access").addFilter( # Add logging filter above to aiohttp.access
aiohttp_filter() logging.getLogger("aiohttp.access").addFilter(_aiohttp_filter())
) # Add logging filter above to aiohttp.access
@dataclasses.dataclass(frozen=True)
class WebServerBinding:
"""Web server binding."""
host: str
port: int
use_ssl: bool
class ConfServer: class ConfServer:
def __init__(self, address, usessl=False): """Web server."""
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"]
def get_milli_time(self, timetoconvert): _EXCLUDE_FROM_LOGGING = ["base", "remove-bot", "remove-client", "restart-service"]
return int(round(timetoconvert * 1000))
def confserver_app(self): def __init__(self, bindings: Union[list[WebServerBinding], WebServerBinding]):
self.app = web.Application( self._runners: list[web.AppRunner] = []
if isinstance(bindings, WebServerBinding):
bindings = [bindings]
self._bindings = bindings
self._app = web.Application(
middlewares=[ middlewares=[
self.log_all_requests, self._log_all_requests,
], ],
) )
aiohttp_jinja2.setup( aiohttp_jinja2.setup(
self.app, self._app,
loader=jinja2.FileSystemLoader( loader=jinja2.FileSystemLoader(
os.path.join(bumper.bumper_dir, "bumper", "web", "templates") 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("", self._handle_base, name="base"),
web.get("/bot/remove/{did}", self.handle_RemoveBot, name="remove-bot"), web.get(
"/bot/remove/{did}", self._handle_remove_bot, name="remove-bot"
),
web.get( web.get(
"/client/remove/{resource}", "/client/remove/{resource}",
self.handle_RemoveClient, self._handle_remove_client,
name="remove-client", name="remove-client",
), ),
web.get( web.get(
"/restart_{service}", "/restart_{service}",
self.handle_RestartService, self._handle_restart_service,
name="restart-service", name="restart-service",
), ),
web.post("/lookup.do", self.handle_lookup), web.post("/lookup.do", self._handle_lookup),
web.post("/newauth.do", self.handle_newauth), web.post("/newauth.do", self._handle_newauth),
] ]
) )
@ -94,11 +116,17 @@ class ConfServer:
} }
# Load plugins # Load plugins
for plug in bumper.discovered_plugins: for module in bumper.discovered_plugins.values():
if isinstance( plugins = [
bumper.discovered_plugins[plug].plugin, bumper.plugins.ConfServerApp m[1]
): for m in inspect.getmembers(module, inspect.isclass)
plugin = bumper.discovered_plugins[plug].plugin 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.plugin_type == "sub_api": # app or sub_api
if plugin.sub_api in apis: if plugin.sub_api in apis:
if plugin.routes: if plugin.routes:
@ -108,73 +136,51 @@ class ConfServer:
elif plugin.plugin_type == "app": elif plugin.plugin_type == "app":
if plugin.path_prefix and plugin.app: if plugin.path_prefix and plugin.app:
logging.debug(f"Adding confserver plugin ({plugin.name})") 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: 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(): async def start(self) -> None:
# print(resource) """Start server."""
async def start_site(self, app, address="localhost", port=8080, usessl=False):
try: try:
runner = web.AppRunner(app) confserverlog.info("Starting ConfServer")
self.runners.append(runner) for binding in self._bindings:
runner = web.AppRunner(self._app)
self._runners.append(runner)
await runner.setup() await runner.setup()
if usessl:
ssl_ctx = None
if binding.use_ssl:
ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
ssl_ctx.load_cert_chain(bumper.server_cert, bumper.server_key) ssl_ctx.load_cert_chain(bumper.server_cert, bumper.server_key)
site = web.TCPSite( site = web.TCPSite(
runner, runner,
host=address, host=binding.host,
port=port, port=binding.port,
ssl_context=ssl_ctx, ssl_context=ssl_ctx,
) )
else:
site = web.TCPSite(runner, host=address, port=port)
await site.start() await site.start()
except Exception as e: except Exception as e:
confserverlog.exception(f"{e}") confserverlog.exception(f"{e}")
raise e raise e
async def start_server(self): async def shutdown(self) -> None:
"""Shutdown server."""
try: try:
confserverlog.info( confserverlog.info("Shutting down")
f"Starting ConfServer at {self.address[0]}:{self.address[1]}" for runner in self._runners:
) await runner.shutdown()
self.runner = web.AppRunner(self.app)
await self.runner.setup()
if self.usessl: self._runners.clear()
ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) await self._app.shutdown()
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()
except Exception as e: except Exception as e:
confserverlog.exception(f"{e}") confserverlog.exception(f"{e}")
async def handle_base(self, request): async def _handle_base(self, request: Request) -> Response:
try: try:
bots = bumper.db_get().table("bots").all() bots = bumper.db_get().table("bots").all()
clients = bumper.db_get().table("clients").all() clients = bumper.db_get().table("clients").all()
@ -196,20 +202,21 @@ class ConfServer:
"sessions": { "sessions": {
"count": len(mq_sessions), "count": len(mq_sessions),
"clients": mq_sessions, "clients": mq_sessions,
} },
}, },
"xmpp_server": bumper.xmpp_server, "xmpp_server": bumper.xmpp_server,
} }
resp = aiohttp_jinja2.render_template("home.jinja2", request, context=all) return aiohttp_jinja2.render_template("home.jinja2", request, context=all)
return resp
except Exception as e: except Exception as e:
confserverlog.exception(f"{e}") confserverlog.exception(f"{e}")
@web.middleware raise HTTPInternalServerError
async def log_all_requests(self, request, handler):
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 = { to_log = {
"request": { "request": {
"route_name": f"{request.match_info.route.name}", "route_name": f"{request.match_info.route.name}",
@ -230,8 +237,8 @@ class ConfServer:
try: try:
postbody = json.loads(await request.text()) postbody = json.loads(await request.text())
except Exception as e: except Exception as e:
confserverlog.error(f"Request body not json: {e} - {e.doc}") confserverlog.error(f"Request body not json: {e}")
postbody = e.doc raise HTTPBadRequest(reason="Body was not json")
else: else:
postbody = await request.post() postbody = await request.post()
@ -242,12 +249,15 @@ class ConfServer:
if response is None: if response is None:
confserverlog.warning("Response was null!") confserverlog.warning("Response was null!")
confserverlog.warning(json.dumps(to_log)) confserverlog.warning(json.dumps(to_log))
return response raise HTTPNoContent
to_log["response"] = { to_log["response"] = {
"status": f"{response.status}", "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)}" to_log["response"]["body"] = f"{json.loads(response.body)}"
confserverlog.debug(json.dumps(to_log)) confserverlog.debug(json.dumps(to_log))
@ -262,16 +272,16 @@ class ConfServer:
except Exception as e: except Exception as e:
confserverlog.exception(f"{e}") confserverlog.exception(f"{e}")
confserverlog.error(json.dumps(to_log)) confserverlog.error(json.dumps(to_log))
return e raise e
else: else:
return await handler(request) return await handler(request)
async def restart_Helper(self): async def _restart_helper_bot(self) -> None:
await bumper.mqtt_helperbot.disconnect() await bumper.mqtt_helperbot.disconnect()
asyncio.create_task(bumper.mqtt_helperbot.start()) asyncio.create_task(bumper.mqtt_helperbot.start())
async def restart_MQTT(self): async def _restart_mqtt_server(self) -> None:
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
if bumper.mqtt_server.state not in ["stopped", "not_started"]: 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())) loop.call_later(1.5, lambda: asyncio.create_task(bumper.mqtt_server.start()))
async def restart_XMPP(self): async def _handle_restart_service(self, request: Request) -> Response:
bumper.xmpp_server.disconnect()
await bumper.xmpp_server.start_async_server()
async def handle_RestartService(self, request):
try: try:
service = request.match_info.get("service", "") service = request.match_info.get("service", "")
if service == "Helperbot": if service == "Helperbot":
await self.restart_Helper() await self._restart_helper_bot()
return web.json_response({"status": "complete"}) return web.json_response({"status": "complete"})
elif service == "MQTTServer": if service == "MQTTServer":
asyncio.create_task(self.restart_MQTT()) asyncio.create_task(self._restart_mqtt_server())
aloop = asyncio.get_event_loop() aloop = asyncio.get_event_loop()
aloop.call_later( 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 ) # In 5 seconds restart Helperbot
return web.json_response({"status": "complete"}) return web.json_response({"status": "complete"})
elif service == "XMPPServer": if service == "XMPPServer":
await self.restart_XMPP() bumper.xmpp_server.disconnect()
await bumper.xmpp_server.start_async_server()
return web.json_response({"status": "complete"}) 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: except Exception as e:
confserverlog.exception(f"{e}") confserverlog.exception(f"{e}")
pass raise
async def handle_RemoveBot(self, request): async def _handle_remove_bot(self, request: Request) -> Response:
try: try:
did = request.match_info.get("did", "") did = request.match_info.get("did", "")
bumper.bot_remove(did) bumper.bot_remove(did)
@ -326,9 +332,10 @@ class ConfServer:
except Exception as e: except Exception as e:
confserverlog.exception(f"{e}") confserverlog.exception(f"{e}")
pass
async def handle_RemoveClient(self, request): raise HTTPInternalServerError
async def _handle_remove_client(self, request: Request) -> Response:
try: try:
resource = request.match_info.get("resource", "") resource = request.match_info.get("resource", "")
bumper.client_remove(resource) bumper.client_remove(resource)
@ -339,93 +346,20 @@ class ConfServer:
except Exception as e: except Exception as e:
confserverlog.exception(f"{e}") confserverlog.exception(f"{e}")
pass
async def handle_login(self, request): raise HTTPInternalServerError
async def _handle_lookup(self, request: Request) -> Response:
try: 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": if request.content_type == "application/x-www-form-urlencoded":
postbody = await request.post() body = await request.post()
else: else:
postbody = json.loads(await request.text()) body = json.loads(await request.text())
confserverlog.debug(postbody) confserverlog.debug(body)
todo = postbody["todo"] if body["todo"] == "FindBest":
if todo == "FindBest": service = body["service"]
service = postbody["service"]
if service == "EcoMsgNew": if service == "EcoMsgNew":
srvip = bumper.bumper_announce_ip srvip = bumper.bumper_announce_ip
srvport = 5223 srvport = 5223
@ -434,13 +368,10 @@ class ConfServer:
srvip, srvport srvip, srvport
) )
) )
msgserver = {"ip": srvip, "port": srvport, "result": "ok"} server = json.dumps({"ip": srvip, "port": srvport, "result": "ok"})
msgserver = json.dumps(msgserver) # bot seems to be very picky about having no spaces, only way was with text
msgserver = msgserver.replace( server = server.replace(" ", "")
" ", "" return web.json_response(text=server)
) # bot seems to be very picky about having no spaces, only way was with text
return web.json_response(text=msgserver)
elif service == "EcoUpdate": elif service == "EcoUpdate":
srvip = "47.88.66.164" # EcoVacs Server srvip = "47.88.66.164" # EcoVacs Server
@ -450,14 +381,18 @@ class ConfServer:
srvip, srvport 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: except Exception as e:
confserverlog.exception(f"{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 # Bumper is only returning the submitted token. No reason yet to create another new token
try: try:
if request.content_type == "application/x-www-form-urlencoded": if request.content_type == "application/x-www-form-urlencoded":
@ -474,401 +409,4 @@ class ConfServer:
except Exception as e: except Exception as e:
confserverlog.exception(f"{e}") confserverlog.exception(f"{e}")
async def disconnect(self): raise HTTPInternalServerError
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}")

View file

@ -31,7 +31,7 @@ def os_db_path(): # createdir=True):
return os.path.join(bumper.data_dir, "bumper.db") 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 # Will create the database if it doesn't exist
db = TinyDB(db_file()) 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()) bot_full_upsert(newbot.asdict())
def bot_remove(did): def bot_remove(did: str):
bots = db_get().table("bots") bots = db_get().table("bots")
bot = bot_get(did) bot = bot_get(did)
if bot: if bot:
@ -392,7 +392,7 @@ def client_add(userid: str, realm: str, resource: str) -> None:
client_full_upsert(newclient.asdict()) client_full_upsert(newclient.asdict())
def client_remove(resource): def client_remove(resource: str):
clients = db_get().table("clients") clients = db_get().table("clients")
client = client_get(resource) client = client_get(resource)
if client: if client:

View file

@ -8,6 +8,7 @@ from typing import Any
from amqtt.session import Session from amqtt.session import Session
import bumper import bumper
from bumper.util import convert_to_millis
class VacBotDevice: class VacBotDevice:
@ -116,9 +117,7 @@ class OAuth:
def toResponse(self): def toResponse(self):
data = self.__dict__ data = self.__dict__
data[ data["expire_at"] = convert_to_millis(
"expire_at"
] = bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time(
datetime.fromisoformat(self.expire_at).timestamp() datetime.fromisoformat(self.expire_at).timestamp()
) )
return data return data

View file

@ -1,13 +1,14 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import json
import logging import logging
from aiohttp import web from aiohttp import web
from bumper import plugins import bumper
from bumper.models import * from bumper.plugins import ConfServerApp
class portal_api_appsvr(plugins.ConfServerApp): class portal_api_appsvr(ConfServerApp):
def __init__(self): def __init__(self):
self.name = "portal_api_appsvr" self.name = "portal_api_appsvr"
self.plugin_type = "sub_api" 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): async def handle_appsvr_app(self, request):
if not request.method == "GET": # Skip GET for now if not request.method == "GET": # Skip GET for now
try: try:
@ -211,6 +208,3 @@ class portal_api_appsvr(plugins.ConfServerApp):
except Exception as e: except Exception as e:
logging.exception(f"{e}") logging.exception(f"{e}")
plugin = portal_api_appsvr()

View file

@ -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 async def handle_dim_devmanager(self, request): # Used in EcoVacs Home App
try: try:
json_body = json.loads(await request.text()) json_body = json.loads(await request.text())
@ -76,6 +72,3 @@ class portal_api_dim(plugins.ConfServerApp):
except Exception as e: except Exception as e:
logging.exception(f"{e}") logging.exception(f"{e}")
plugin = portal_api_dim()

View file

@ -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): async def handle_ad_res(self, request):
try: try:
body = {"code": 0, "data": [], "message": "success", "success": True} body = {"code": 0, "data": [], "message": "success", "success": True}
@ -34,6 +30,3 @@ class portal_api_ecms(plugins.ConfServerApp):
except Exception as e: except Exception as e:
logging.exception(f"{e}") logging.exception(f"{e}")
plugin = portal_api_ecms()

View file

@ -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): async def handle_devmanager_botcommand(self, request):
try: try:
json_body = json.loads(await request.text()) json_body = json.loads(await request.text())
@ -81,6 +77,3 @@ class portal_api_iot(plugins.ConfServerApp):
except Exception as e: except Exception as e:
logging.exception(f"{e}") logging.exception(f"{e}")
plugin = portal_api_iot()

View file

@ -20,10 +20,6 @@ class portal_api_lg(plugins.ConfServerApp):
web.route("*", "/lg/log.do", self.handle_lg_log, name="portal_api_lg_log"), 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 async def handle_lg_log(self, request): # EcoVacs Home
randomid = "".join(random.sample(string.ascii_letters, 6)) 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"} body = {"id": randomid, "errno": bumper.ERR_COMMON, "ret": "fail"}
return web.json_response(body) return web.json_response(body)
plugin = portal_api_lg()

View file

@ -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 async def handle_neng_hasUnreadMessage(self, request): # EcoVacs Home
try: try:
body = {"code": 0, "data": {"hasUnRead": True}} body = {"code": 0, "data": {"hasUnRead": True}}
@ -107,6 +103,3 @@ class portal_api_neng(plugins.ConfServerApp):
except Exception as e: except Exception as e:
logging.exception(f"{e}") logging.exception(f"{e}")
plugin = portal_api_neng()

View file

@ -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): async def handle_getProductIotMap(self, request):
try: try:
body = { body = {
@ -130,8 +126,6 @@ class portal_api_pim(plugins.ConfServerApp):
logging.exception(f"{e}") logging.exception(f"{e}")
plugin = portal_api_pim()
confignetAllResponse = { confignetAllResponse = {
"code": 0, "code": 0,
"data": [ "data": [

View file

@ -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): async def handle_map_get(self, request):
try: try:
body = { body = {
@ -35,6 +31,3 @@ class api_rapp(plugins.ConfServerApp):
except Exception as e: except Exception as e:
logging.exception(f"{e}") logging.exception(f"{e}")
plugin = api_rapp()

View file

@ -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): async def handle_usersapi(self, request):
if not request.method == "GET": # Skip GET for now if not request.method == "GET": # Skip GET for now
try: try:
@ -120,6 +116,3 @@ class portal_api_users(plugins.ConfServerApp):
# Return fail for GET # Return fail for GET
body = {"result": "fail", "todo": "result"} body = {"result": "fail", "todo": "result"}
return web.json_response(body) return web.json_response(body)
plugin = portal_api_users()

View file

@ -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): async def handle_upload_global_file(self, request):
try: try:
fileID = request.match_info.get("id", "") fileID = request.match_info.get("id", "")
@ -42,6 +38,3 @@ class upload_global(plugins.ConfServerApp):
except Exception as e: except Exception as e:
logging.exception(f"{e}") logging.exception(f"{e}")
plugin = upload_global()

View file

@ -8,6 +8,7 @@ from aiohttp import web
import bumper import bumper
from bumper import plugins from bumper import plugins
from bumper.models import * from bumper.models import *
from bumper.rest import auth_util
class v1_global_auth(plugins.ConfServerApp): class v1_global_auth(plugins.ConfServerApp):
@ -16,19 +17,11 @@ class v1_global_auth(plugins.ConfServerApp):
self.plugin_type = "sub_api" self.plugin_type = "sub_api"
self.sub_api = "api_v1" self.sub_api = "api_v1"
authhandler = bumper.ConfServer.ConfServer_AuthHandler()
self.routes = [ self.routes = [
web.route( web.route(
"*", "*",
"/global/auth/getAuthCode", "/global/auth/getAuthCode",
authhandler.get_AuthCode, auth_util.get_authcode,
name="v1_global_auth_getAuthCode", name="v1_global_auth_getAuthCode",
), ),
] ]
self.get_milli_time = (
bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
)
plugin = v1_global_auth()

View file

@ -8,6 +8,7 @@ from aiohttp import web
import bumper import bumper
from bumper import plugins from bumper import plugins
from bumper.models import * from bumper.models import *
from bumper.util import get_current_time_as_millis
class v1_private_ad(plugins.ConfServerApp): 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 async def handle_getAdByPositionType(self, request): # EcoVacs Home
try: try:
body = { body = {
@ -42,7 +39,7 @@ class v1_private_ad(plugins.ConfServerApp):
"data": None, "data": None,
"msg": "操作成功", "msg": "操作成功",
"success": True, "success": True,
"time": self.get_milli_time(datetime.utcnow().timestamp()), "time": get_current_time_as_millis(),
} }
return web.json_response(body) return web.json_response(body)
@ -57,13 +54,10 @@ class v1_private_ad(plugins.ConfServerApp):
"data": None, "data": None,
"msg": "操作成功", "msg": "操作成功",
"success": True, "success": True,
"time": self.get_milli_time(datetime.utcnow().timestamp()), "time": get_current_time_as_millis(),
} }
return web.json_response(body) return web.json_response(body)
except Exception as e: except Exception as e:
logging.exception(f"{e}") logging.exception(f"{e}")
plugin = v1_private_ad()

View file

@ -8,6 +8,7 @@ from aiohttp import web
import bumper import bumper
from bumper import plugins from bumper import plugins
from bumper.models import * from bumper.models import *
from bumper.util import get_current_time_as_millis
class v1_private_campaign(plugins.ConfServerApp): 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): async def handle_homePageAlert(self, request):
try: try:
nextAlert = self.get_milli_time( nextAlert = convert_to_millis(
(datetime.now() + timedelta(hours=12)).timestamp() (datetime.now() + timedelta(hours=12)).timestamp()
) )
@ -43,16 +40,13 @@ class v1_private_campaign(plugins.ConfServerApp):
"hasCampaign": "N", "hasCampaign": "N",
"imageUrl": None, "imageUrl": None,
"nextAlertTime": nextAlert, "nextAlertTime": nextAlert,
"serverTime": self.get_milli_time(datetime.utcnow().timestamp()), "serverTime": get_current_time_as_millis(),
}, },
"msg": "操作成功", "msg": "操作成功",
"time": self.get_milli_time(datetime.utcnow().timestamp()), "time": get_current_time_as_millis(),
} }
return web.json_response(body) return web.json_response(body)
except Exception as e: except Exception as e:
logging.exception(f"{e}") logging.exception(f"{e}")
plugin = v1_private_campaign()

View file

@ -5,6 +5,7 @@ from aiohttp import web
from bumper import plugins from bumper import plugins
from bumper.models import * from bumper.models import *
from bumper.util import get_current_time_as_millis
class v1_private_common(plugins.ConfServerApp): 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): async def handle_checkVersion(self, request):
try: try:
body = { body = {
@ -82,7 +79,7 @@ class v1_private_common(plugins.ConfServerApp):
"v": None, "v": None,
}, },
"msg": "操作成功", "msg": "操作成功",
"time": self.get_milli_time(datetime.utcnow().timestamp()), "time": get_current_time_as_millis(),
} }
return web.json_response(body) return web.json_response(body)
@ -107,7 +104,7 @@ class v1_private_common(plugins.ConfServerApp):
}, },
"msg": "操作成功", "msg": "操作成功",
"success": True, "success": True,
"time": self.get_milli_time(datetime.utcnow().timestamp()), "time": get_current_time_as_millis(),
} }
return web.json_response(body) return web.json_response(body)
@ -122,7 +119,7 @@ class v1_private_common(plugins.ConfServerApp):
"data": None, "data": None,
"msg": "操作成功", "msg": "操作成功",
"success": True, "success": True,
"time": self.get_milli_time(datetime.utcnow().timestamp()), "time": get_current_time_as_millis(),
} }
return web.json_response(body) return web.json_response(body)
@ -144,7 +141,7 @@ class v1_private_common(plugins.ConfServerApp):
}, },
"msg": "操作成功", "msg": "操作成功",
"success": True, "success": True,
"time": self.get_milli_time(datetime.utcnow().timestamp()), "time": get_current_time_as_millis(),
} }
return web.json_response(body) return web.json_response(body)
@ -163,7 +160,7 @@ class v1_private_common(plugins.ConfServerApp):
"data": data, "data": data,
"msg": "操作成功", "msg": "操作成功",
"success": True, "success": True,
"time": self.get_milli_time(datetime.utcnow().timestamp()), "time": get_current_time_as_millis(),
} }
return web.json_response(body) return web.json_response(body)
@ -178,7 +175,7 @@ class v1_private_common(plugins.ConfServerApp):
"data": AREA_LIST, "data": AREA_LIST,
"msg": "操作成功", "msg": "操作成功",
"success": True, "success": True,
"time": self.get_milli_time(datetime.utcnow().timestamp()), "time": get_current_time_as_millis(),
} }
return web.json_response(body) return web.json_response(body)
@ -210,7 +207,7 @@ class v1_private_common(plugins.ConfServerApp):
], ],
"msg": "操作成功", "msg": "操作成功",
"success": True, "success": True,
"time": self.get_milli_time(datetime.utcnow().timestamp()), "time": get_current_time_as_millis(),
} }
return web.json_response(body) return web.json_response(body)
@ -220,7 +217,7 @@ class v1_private_common(plugins.ConfServerApp):
async def handle_getTimestamp(self, request): # EcoVacs Home async def handle_getTimestamp(self, request): # EcoVacs Home
try: try:
time = self.get_milli_time(datetime.utcnow().timestamp()) time = get_current_time_as_millis()
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
"data": {"timestamp": time}, "data": {"timestamp": time},
@ -235,8 +232,6 @@ class v1_private_common(plugins.ConfServerApp):
logging.exception(f"{e}") logging.exception(f"{e}")
plugin = v1_private_common()
AREA_LIST = { AREA_LIST = {
"currentVersion": 231, "currentVersion": 231,
"areaList": [ "areaList": [

View file

@ -8,6 +8,7 @@ from aiohttp import web
import bumper import bumper
from bumper import plugins from bumper import plugins
from bumper.models import * from bumper.models import *
from bumper.util import get_current_time_as_millis
class v1_private_message(plugins.ConfServerApp): 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 async def handle_hasUnreadMessage(self, request): # EcoVacs Home
try: try:
body = { body = {
@ -42,7 +39,7 @@ class v1_private_message(plugins.ConfServerApp):
"data": "N", "data": "N",
"msg": "操作成功", "msg": "操作成功",
"success": True, "success": True,
"time": self.get_milli_time(datetime.utcnow().timestamp()), "time": get_current_time_as_millis(),
} }
return web.json_response(body) return web.json_response(body)
@ -57,13 +54,10 @@ class v1_private_message(plugins.ConfServerApp):
"data": {"hasNextPage": 0, "items": []}, "data": {"hasNextPage": 0, "items": []},
"msg": "操作成功", "msg": "操作成功",
"success": True, "success": True,
"time": self.get_milli_time(datetime.utcnow().timestamp()), "time": get_current_time_as_millis(),
} }
return web.json_response(body) return web.json_response(body)
except Exception as e: except Exception as e:
logging.exception(f"{e}") logging.exception(f"{e}")
plugin = v1_private_message()

View file

@ -8,6 +8,7 @@ from aiohttp import web
import bumper import bumper
from bumper import plugins from bumper import plugins
from bumper.models import * from bumper.models import *
from bumper.util import get_current_time_as_millis
class v1_private_shop(plugins.ConfServerApp): 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 async def handle_getCnWapShopConfig(self, request): # EcoVacs Home
try: try:
body = { body = {
@ -41,13 +38,10 @@ class v1_private_shop(plugins.ConfServerApp):
}, },
"msg": "操作成功", "msg": "操作成功",
"success": True, "success": True,
"time": self.get_milli_time(datetime.utcnow().timestamp()), "time": get_current_time_as_millis(),
} }
return web.json_response(body) return web.json_response(body)
except Exception as e: except Exception as e:
logging.exception(f"{e}") logging.exception(f"{e}")
plugin = v1_private_shop()

View file

@ -8,6 +8,8 @@ from aiohttp import web
import bumper import bumper
from bumper import plugins from bumper import plugins
from bumper.models import * 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): class v1_private_user(plugins.ConfServerApp):
@ -17,30 +19,29 @@ class v1_private_user(plugins.ConfServerApp):
self.plugin_type = "sub_api" self.plugin_type = "sub_api"
self.sub_api = "api_v1" self.sub_api = "api_v1"
authhandler = bumper.ConfServer.ConfServer_AuthHandler()
self.routes = [ self.routes = [
web.route( web.route(
"*", "*",
"/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/login", "/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/login",
authhandler.login, auth_util.login,
name="v1_user_login", name="v1_user_login",
), ),
web.route( web.route(
"*", "*",
"/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkLogin", "/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkLogin",
authhandler.login, auth_util.login,
name="v1_user_checkLogin", name="v1_user_checkLogin",
), ),
web.route( web.route(
"*", "*",
"/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/getAuthCode", "/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/getAuthCode",
authhandler.get_AuthCode, auth_util.get_authcode,
name="v1_user_getAuthCode", name="v1_user_getAuthCode",
), ),
web.route( web.route(
"*", "*",
"/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/logout", "/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/logout",
authhandler.logout, auth_util.logout,
name="v1_user_logout", name="v1_user_logout",
), ),
web.route( web.route(
@ -58,7 +59,7 @@ class v1_private_user(plugins.ConfServerApp):
web.route( web.route(
"*", "*",
"/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/getUserAccountInfo", "/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/getUserAccountInfo",
authhandler.getUserAccountInfo, auth_util.get_user_account_info,
name="v1_user_getUserAccountInfo", name="v1_user_getUserAccountInfo",
), ),
web.route( web.route(
@ -91,10 +92,6 @@ class v1_private_user(plugins.ConfServerApp):
# /registerByEmail # /registerByEmail
] ]
self.get_milli_time = (
bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
)
async def handle_checkAgreement(self, request): async def handle_checkAgreement(self, request):
try: try:
apptype = request.match_info.get("apptype", "") apptype = request.match_info.get("apptype", "")
@ -119,14 +116,14 @@ class v1_private_user(plugins.ConfServerApp):
], ],
"msg": "操作成功", "msg": "操作成功",
"success": True, "success": True,
"time": self.get_milli_time(datetime.utcnow().timestamp()), "time": get_current_time_as_millis(),
} }
else: else:
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
"data": [], "data": [],
"msg": "操作成功", "msg": "操作成功",
"time": self.get_milli_time(datetime.utcnow().timestamp()), "time": get_current_time_as_millis(),
} }
return web.json_response(body) return web.json_response(body)
@ -195,7 +192,7 @@ class v1_private_user(plugins.ConfServerApp):
], ],
"msg": "操作成功", "msg": "操作成功",
"success": True, "success": True,
"time": self.get_milli_time(datetime.utcnow().timestamp()), "time": get_current_time_as_millis(),
} }
return web.json_response(body) return web.json_response(body)
@ -210,7 +207,7 @@ class v1_private_user(plugins.ConfServerApp):
"data": {"isNeedReLogin": "N"}, "data": {"isNeedReLogin": "N"},
"msg": "操作成功", "msg": "操作成功",
"success": True, "success": True,
"time": self.get_milli_time(datetime.utcnow().timestamp()), "time": get_current_time_as_millis(),
} }
return web.json_response(body) return web.json_response(body)
@ -225,13 +222,10 @@ class v1_private_user(plugins.ConfServerApp):
"data": None, "data": None,
"msg": "操作成功", "msg": "操作成功",
"success": True, "success": True,
"time": self.get_milli_time(datetime.utcnow().timestamp()), "time": get_current_time_as_millis(),
} }
return web.json_response(body) return web.json_response(body)
except Exception as e: except Exception as e:
logging.exception(f"{e}") logging.exception(f"{e}")
plugin = v1_private_user()

View file

@ -1,11 +1,11 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import logging import logging
from datetime import datetime
from aiohttp import web from aiohttp import web
import bumper import bumper
from bumper import plugins from bumper import plugins
from bumper.util import get_current_time_as_millis
class v1_private_userSetting(plugins.ConfServerApp): 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): async def handle_getSuggestionSetting(self, request):
try: try:
@ -54,13 +50,10 @@ class v1_private_userSetting(plugins.ConfServerApp):
], ],
}, },
"msg": "操作成功", "msg": "操作成功",
"time": self.get_milli_time(datetime.utcnow().timestamp()), "time": get_current_time_as_millis(),
} }
return web.json_response(body) return web.json_response(body)
except Exception as e: except Exception as e:
logging.exception(f"{e}") logging.exception(f"{e}")
plugin = v1_private_userSetting()

View file

@ -1,13 +1,8 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import asyncio
import logging
from datetime import datetime, timedelta
from aiohttp import web from aiohttp import web
import bumper
from bumper import plugins from bumper import plugins
from bumper.models import * from bumper.rest import auth_util
class v2_private_user(plugins.ConfServerApp): class v2_private_user(plugins.ConfServerApp):
@ -17,19 +12,11 @@ class v2_private_user(plugins.ConfServerApp):
self.plugin_type = "sub_api" self.plugin_type = "sub_api"
self.sub_api = "api_v2" self.sub_api = "api_v2"
authhandler = bumper.ConfServer.ConfServer_AuthHandler()
self.routes = [ self.routes = [
web.route( web.route(
"*", "*",
"/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkLogin", "/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkLogin",
authhandler.login, auth_util.login,
name="v2_user_checkLogin", 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
View file

384
bumper/rest/auth_util.py Normal file
View 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}")

View file

@ -1,8 +1,9 @@
import logging import logging
import os import os
import sys import sys
from datetime import datetime
from logging.handlers import RotatingFileHandler from logging.handlers import RotatingFileHandler
from typing import MutableMapping from typing import MutableMapping, Union
logformat = logging.Formatter( logformat = logging.Formatter(
"[%(asctime)s] :: %(levelname)s :: %(name)s :: %(module)s :: %(funcName)s :: %(lineno)d :: %(message)s" "[%(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) get_logger("amqtt.client", rotate)
return logger 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())

View file

@ -26,7 +26,7 @@ class XMPPServer:
self.address = address self.address = address
self.xmpp_protocol = lambda: XMPPServer_Protocol() self.xmpp_protocol = lambda: XMPPServer_Protocol()
async def start_async_server(self): async def start_async_server(self) -> None:
try: try:
xmppserverlog.info( xmppserverlog.info(
f"Starting XMPP Server at {self.address[0]}:{self.address[1]}" f"Starting XMPP Server at {self.address[0]}:{self.address[1]}"
@ -44,7 +44,7 @@ class XMPPServer:
xmppserverlog.exception(f"{e}") xmppserverlog.exception(f"{e}")
raise e raise e
def disconnect(self): def disconnect(self) -> None:
xmppserverlog.debug("waiting for all clients to disconnect") xmppserverlog.debug("waiting for all clients to disconnect")
for client in self.clients: for client in self.clients:

View file

@ -1,2 +1,3 @@
HOST = "127.0.0.1" HOST = "127.0.0.1"
MQTT_PORT = 8883 MQTT_PORT = 8883
CONF_SERVER_PORT = 11111

View file

@ -4,7 +4,8 @@ import pytest
from amqtt.client import MQTTClient from amqtt.client import MQTTClient
import bumper import bumper
from tests import HOST, MQTT_PORT from bumper import WebServerBinding
from tests import HOST, MQTT_PORT, CONF_SERVER_PORT
@pytest.fixture @pytest.fixture
@ -37,10 +38,8 @@ async def mqtt_client():
@pytest.fixture @pytest.fixture
async def conf_server_client(aiohttp_client): async def conf_server_client(aiohttp_client):
confserver = bumper.ConfServer("127.0.0.1:11111", False) confserver = bumper.ConfServer(WebServerBinding(HOST, CONF_SERVER_PORT, False))
confserver.confserver_app() client = await aiohttp_client(confserver._app)
client = await aiohttp_client(confserver.app)
yield client yield client

View file

@ -9,11 +9,12 @@ from aiohttp import web
from testfixtures import LogCapture from testfixtures import LogCapture
import bumper import bumper
from tests import HOST, MQTT_PORT from bumper import WebServerBinding
from tests import HOST, MQTT_PORT, CONF_SERVER_PORT
def create_confserver(): 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): def async_return(result):
@ -28,27 +29,13 @@ def remove_existing_db():
async def test_confserver_ssl(): async def test_confserver_ssl():
conf_server = bumper.ConfServer((HOST, 11111), usessl=True) conf_server = bumper.ConfServer(WebServerBinding(HOST, CONF_SERVER_PORT, True))
conf_server.confserver_app() await conf_server.start()
await conf_server.start_server()
async def test_confserver_no_ssl(): async def test_confserver_no_ssl():
conf_server = bumper.ConfServer((HOST, 11112), usessl=False) conf_server = bumper.ConfServer(WebServerBinding(HOST, 11112, False))
conf_server.confserver_app() await conf_server.start()
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
)
@pytest.mark.usefixtures("mqtt_server") @pytest.mark.usefixtures("mqtt_server")

View file

@ -26,15 +26,12 @@ async def test_start_stop():
b = bumper b = bumper
b.db = "tests/tmp.db" # Set db location for testing 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()) asyncio.create_task(b.start())
await asyncio.sleep(0.1) await asyncio.sleep(0.1)
l.check_present(("bumper", "INFO", "Starting Bumper")) l.check_present(("bumper", "INFO", "Starting Bumper"))
l.clear() l.clear()
asyncio.create_task(b.shutdown()) await b.shutdown()
await asyncio.sleep(0.1)
l.check_present( l.check_present(
("bumper", "INFO", "Shutting down"), ("bumper", "INFO", "Shutdown complete") ("bumper", "INFO", "Shutting down"), ("bumper", "INFO", "Shutdown complete")
) )

14
tests/test_util.py Normal file
View 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
)