add new endpoints for app v2 #116
7 changed files with 161 additions and 6 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
37
bumper/db.py
37
bumper/db.py
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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 = [
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
39
bumper/plugins/bumper_confserver_portal_rapp.py
Normal file
39
bumper/plugins/bumper_confserver_portal_rapp.py
Normal 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
14
tests/test_models.py
Normal 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue