add new endpoints for app v2 #116

Merged
edenhaus merged 17 commits from ecovacs-home into master 2021-06-05 15:06:19 +02:00
7 changed files with 161 additions and 6 deletions
Showing only changes of commit 0b9f192ded - Show all commits

View file

@ -57,6 +57,7 @@ bumper_announce_ip = os.environ.get("BUMPER_ANNOUNCE_IP") or bumper_listen
bumper_debug = strtobool(os.environ.get("BUMPER_DEBUG")) or False bumper_debug = strtobool(os.environ.get("BUMPER_DEBUG")) or False
use_auth = False use_auth = False
token_validity_seconds = 3600 # 1 hour token_validity_seconds = 3600 # 1 hour
oauth_validity_days = 15
db = None db = None
mqtt_server = None mqtt_server = None

View file

@ -62,13 +62,12 @@ class ConfServer:
self.app.add_routes( 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_RemoveBot, name='remove-bot'),
web.get("/client/remove/{resource}", self.handle_RemoveClient, name='remove-client'), web.get("/client/remove/{resource}", self.handle_RemoveClient, name='remove-client'),
web.get("/restart_{service}", self.handle_RestartService, name='restart-service'), web.get("/restart_{service}", self.handle_RestartService, name='restart-service'),
web.post("/lookup.do", self.handle_lookup), web.post("/lookup.do", self.handle_lookup),
web.post("/newauth.do", self.handle_newauth),
] ]
) )
@ -507,6 +506,26 @@ class ConfServer:
except Exception as e: except Exception as e:
confserverlog.exception("{}".format(e)) confserverlog.exception("{}".format(e))
async def handle_newauth(self, request):
# 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":
postbody = await request.post()
else:
postbody = json.loads(await request.text())
confserverlog.debug(postbody)
body = {
"authCode": postbody["itToken"],
"result": "ok",
"todo": "result"
}
return web.json_response(body)
except Exception as e:
confserverlog.exception("{}".format(e))
async def disconnect(self): async def disconnect(self):
try: try:

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import bumper import bumper
from bumper.models import VacBotClient, VacBotDevice, BumperUser, EcoVacsHomeProducts from bumper.models import VacBotClient, VacBotDevice, BumperUser, EcoVacsHomeProducts, OAuth
from tinydb import TinyDB, Query from tinydb import TinyDB, Query
from tinydb.storages import MemoryStorage from tinydb.storages import MemoryStorage
from datetime import datetime, timedelta from datetime import datetime, timedelta
@ -32,6 +32,7 @@ def db_get():
db.table("clients", cache_size=0) db.table("clients", cache_size=0)
db.table("bots", cache_size=0) db.table("bots", cache_size=0)
db.table("tokens", cache_size=0) db.table("tokens", cache_size=0)
db.table("oauth", cache_size=0)
return db return db
@ -202,6 +203,40 @@ def user_revoke_authcode(userid, token, authcode):
) )
def user_revoke_expired_oauths(userid):
opendb = db_get()
with opendb:
table = opendb.table("oauth")
search = table.search(Query().userid == userid)
for i in search:
oauth = OAuth(**i)
if datetime.now() >= datetime.fromisoformat(oauth.expire_at):
bumperlog.debug(
"Removing oauth {} due to expiration".format(oauth.access_token)
)
table.remove(doc_ids=[i.doc_id])
def user_add_oauth(userid) -> OAuth:
user_revoke_expired_oauths(userid)
opendb = db_get()
with opendb:
table = opendb.table("oauth")
entry = table.get(Query().userid == userid)
if entry:
return OAuth(**entry)
else:
oauth = OAuth.create_new(userid)
bumperlog.debug("Adding oauth {} for userid {}".format(oauth.access_token, userid))
table.insert(oauth.toDB())
return oauth
def token_by_authcode(authcode):
tokens = db_get().table("tokens")
return tokens.get(Query().authcode == authcode)
def get_disconnected_xmpp_clients(): def get_disconnected_xmpp_clients():
clients = db_get().table("clients") clients = db_get().table("clients")
Client = Query() Client = Query()

View file

@ -1,5 +1,9 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import json import json
import uuid
from datetime import datetime, timedelta
import bumper
class VacBotDevice(object): class VacBotDevice(object):
@ -83,6 +87,34 @@ class EcoVacsHome_Login(EcoVacs_Login):
ucUid = "" ucUid = ""
class OAuth:
access_token = ""
expire_at = ""
refresh_token = ""
userId = ""
def __init__(self, **entries):
self.__dict__.update(entries)
@classmethod
def create_new(cls, userId: str):
oauth = OAuth()
oauth.userId = userId
oauth.access_token = uuid.uuid4().hex
oauth.expire_at = "{}".format(datetime.utcnow() + timedelta(days=bumper.oauth_validity_days))
oauth.refresh_token = uuid.uuid4().hex
return oauth
def toDB(self):
return self.__dict__
def toResponse(self):
data = self.__dict__
data["expire_at"] = bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time(
datetime.fromisoformat(self.expire_at).timestamp())
return data
# EcoVacs Home Product IOT Map - 2020-01-05 # EcoVacs Home Product IOT Map - 2020-01-05
# https://portal-ww.ecouser.net/api/pim/product/getProductIotMap # https://portal-ww.ecouser.net/api/pim/product/getProductIotMap
EcoVacsHomeProducts = [ EcoVacsHomeProducts = [

View file

@ -17,10 +17,9 @@ class portal_api_appsvr(plugins.ConfServerApp):
self.sub_api = "portal_api" self.sub_api = "portal_api"
self.routes = [ self.routes = [
web.route("*", "/appsvr/app.do", self.handle_appsvr_app, name="portal_api_appsvr_app"), web.route("*", "/appsvr/app.do", self.handle_appsvr_app, name="portal_api_appsvr_app"),
web.route("*", "/appsvr/service/list", self.handle_appsvr_service_list, name="portal_api_appsvr_service_list"), web.route("*", "/appsvr/service/list", self.handle_appsvr_service_list, name="portal_api_appsvr_service_list"),
web.route("*", "/appsvr/oauth_callback", self.handle_appsvr_oauth_callback, name="portal_api_appsvr_oauth_callback"),
] ]
self.get_milli_time = bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time self.get_milli_time = bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
@ -180,4 +179,20 @@ class portal_api_appsvr(plugins.ConfServerApp):
except Exception as e: except Exception as e:
logging.exception("{}".format(e)) logging.exception("{}".format(e))
async def handle_appsvr_oauth_callback(self, request):
try:
token = bumper.token_by_authcode(request.query["code"])
oauth = bumper.user_add_oauth(token["userid"])
body = {
"code": 0,
"data": oauth.toResponse(),
"ret": "ok",
"todo": "result"
}
return web.json_response(body)
except Exception as e:
logging.exception("{}".format(e))
plugin = portal_api_appsvr() plugin = portal_api_appsvr()

View file

@ -0,0 +1,39 @@
#!/usr/bin/env python3
from aiohttp import web
import logging
from bumper.models import *
from bumper import plugins
class api_rapp(plugins.ConfServerApp):
def __init__(self):
self.name = "api_rapp"
self.plugin_type = "sub_api"
self.sub_api = "portal_api"
self.routes = [
web.route("*", "/rapp/sds/user/data/map/get", self.handle_map_get, name="api_rapp"),
]
self.get_milli_time = bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
async def handle_map_get(self, request):
try:
body = {
"code": 0,
"data": {
"data": {
"name": "My Home"
},
"tag": None
},
"message": "success"
}
return web.json_response(body)
except Exception as e:
logging.exception("{}".format(e))
plugin = api_rapp()

14
tests/test_models.py Normal file
View file

@ -0,0 +1,14 @@
from bumper import OAuth
def test_oauth():
userId = "test"
o_auth = OAuth.create_new(userId)
assert o_auth is not None
assert o_auth.userId == userId
assert o_auth.access_token is not None
assert o_auth.expire_at is not None
assert o_auth.refresh_token is not None
data = o_auth.toResponse()
assert data is not None