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
use_auth = False
token_validity_seconds = 3600 # 1 hour
oauth_validity_days = 15
db = None
mqtt_server = None

View file

@ -62,13 +62,12 @@ class ConfServer:
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("/client/remove/{resource}", self.handle_RemoveClient, name='remove-client'),
web.get("/restart_{service}", self.handle_RestartService, name='restart-service'),
web.post("/lookup.do", self.handle_lookup),
web.post("/newauth.do", self.handle_newauth),
]
)
@ -507,6 +506,26 @@ class ConfServer:
except Exception as 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):
try:

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3
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.storages import MemoryStorage
from datetime import datetime, timedelta
@ -32,6 +32,7 @@ def db_get():
db.table("clients", cache_size=0)
db.table("bots", cache_size=0)
db.table("tokens", cache_size=0)
db.table("oauth", cache_size=0)
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():
clients = db_get().table("clients")
Client = Query()

View file

@ -1,5 +1,9 @@
#!/usr/bin/env python3
import json
import uuid
from datetime import datetime, timedelta
import bumper
class VacBotDevice(object):
@ -83,6 +87,34 @@ class EcoVacsHome_Login(EcoVacs_Login):
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
# https://portal-ww.ecouser.net/api/pim/product/getProductIotMap
EcoVacsHomeProducts = [

View file

@ -17,10 +17,9 @@ class portal_api_appsvr(plugins.ConfServerApp):
self.sub_api = "portal_api"
self.routes = [
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/oauth_callback", self.handle_appsvr_oauth_callback, name="portal_api_appsvr_oauth_callback"),
]
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:
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()

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