Move tokens to new table

Move tokens to new table
- Authcode linked to token
This commit is contained in:
Brian Martin 2019-03-11 10:34:15 -04:00
parent 6994f5ae5e
commit 09e41cbc6e
2 changed files with 169 additions and 176 deletions

View file

@ -7,6 +7,7 @@ from .xmppserver import XMPPServer
import asyncio
import contextvars
import time
from datetime import datetime, timedelta
import platform
import os
import logging
@ -22,6 +23,7 @@ server_cert = "./certs/cert.pem"
server_key = "./certs/key.pem"
use_auth = False
token_validity_seconds = 3600 #1 hour
# Logs
bumperlog = logging.getLogger("bumper")
@ -63,16 +65,12 @@ class BumperUser(object):
def __init__(self, userid=""):
self.userid = userid
self.devices = []
self.tokens = []
self.authcodes = []
self.bots = []
def asdict(self):
return {
"userid": self.userid,
"devices": self.devices,
"tokens": self.tokens,
"authcodes": self.authcodes,
"bots": self.bots,
}
@ -90,6 +88,11 @@ def user_get(userid):
User = Query()
return users.get(User.userid == userid)
def user_by_deviceid(deviceid):
users = db_get().table('users')
User = Query()
return users.get(User.devices.any([deviceid]))
def user_full_upsert(user):
users = db_get().table('users')
User = Query()
@ -135,47 +138,52 @@ def user_remove_bot(userid, did):
users.upsert({'bots': userbots}, User.userid == userid)
def user_get_tokens(userid):
tokens = db_get().table('tokens')
return tokens.search((Query().userid == userid))
def user_get_token(userid, token):
tokens = db_get().table('tokens')
return tokens.get((Query().userid == userid) & (Query().token == token))
def user_add_token(userid, token):
users = db_get().table('users')
User = Query()
user = users.get(User.userid == userid)
usertokens = list(user['tokens'])
if not token in usertokens:
usertokens.append(token)
tokens = db_get().table('tokens')
tmptoken = tokens.get((Query().userid == userid) & (Query().token == token))
if not tmptoken:
tokens.insert({'userid':userid, 'token':token, 'expiration':"{}".format(datetime.now() + timedelta(seconds=token_validity_seconds))})
users.upsert({'tokens': usertokens}, User.userid == userid)
def user_revoke_all_tokens(userid):
tokens = db_get().table('tokens')
tsearch = tokens.search(Query().userid == userid)
for i in tsearch:
tokens.remove(doc_ids=[i.doc_id])
def user_revoke_expired_tokens(userid):
tokens = db_get().table('tokens')
tsearch = tokens.search(Query().userid == userid)
for i in tsearch:
bumperlog.debug("Checking expiration of token {}: Is Current Time: {} >= Expiration: {}".format(i['token'],datetime.fromisoformat(i['expiration']), datetime.now()))
if datetime.now() >= datetime.fromisoformat(i['expiration']):
bumperlog.debug("Removing token {} due to expiration".format(i['token']))
tokens.remove(doc_ids=[i.doc_id])
def user_revoke_token(userid, token):
users = db_get().table('users')
User = Query()
user = users.get(User.userid == userid)
usertokens = list(user['tokens'])
if token in usertokens:
usertokens.remove(token)
tokens = db_get().table('tokens')
tmptoken = tokens.get((Query().userid == userid) & (Query().token == token))
if tmptoken:
tokens.remove(doc_ids=[tmptoken.doc_id])
users.upsert({'tokens': usertokens}, User.userid == userid)
def user_add_authcode(userid, authcode):
users = db_get().table('users')
User = Query()
user = users.get(User.userid == userid)
userauthcodes = list(user['authcodes'])
if not authcode in userauthcodes:
userauthcodes.append(authcode)
users.upsert({'authcodes': userauthcodes}, User.userid == userid)
def user_revoke_authcode(userid, authcode):
users = db_get().table('users')
User = Query()
user = users.get(User.userid == userid)
userauthcodes = list(user['authcodes'])
if authcode in userauthcodes:
userauthcodes.remove(authcode)
users.upsert({'authcodes': userauthcodes}, User.userid == userid)
def user_add_authcode(userid, token, authcode):
tokens = db_get().table('tokens')
tmptoken = tokens.get((Query().userid == userid) & (Query().token == token))
if tmptoken:
tokens.upsert({'authcode': authcode}, ((Query().userid == userid) & (Query().token == token)))
def user_revoke_authcode(userid, token, authcode):
tokens = db_get().table('tokens')
tmptoken = tokens.get((Query().userid == userid) & (Query().token == token))
if tmptoken:
tokens.upsert({'authcode': ''}, ((Query().userid == userid) & (Query().token == token)))
class VacBotDevice(object):
def __init__(
@ -228,9 +236,25 @@ class VacBotClient(object):
def check_authcode(uid, authcode):
users = bumper_users_var.get()
for user in users:
if uid == "fuid_{}".format(user.userid) and authcode in user.authcodes:
bumperlog.debug("Checking for authcode: {}".format(authcode))
tokens = db_get().table('tokens')
tmpauth = tokens.get(
(Query().authcode == authcode) & #Match authcode
((Query().userid == uid.replace("fuid_","")) | (Query().userid == "fuid_{}".format(uid))) #Userid with or without fuid_
)
if tmpauth:
return True
return False
def check_token(uid, token):
bumperlog.debug("Checking for token: {}".format(token))
tokens = db_get().table('tokens')
tmpauth = tokens.get(
(Query().token == token) & #Match token
((Query().userid == uid.replace("fuid_","")) | (Query().userid == "fuid_{}".format(uid))) #Userid with or without fuid_
)
if tmpauth:
return True
return False

View file

@ -185,50 +185,12 @@ class ConfServer:
if (
not user_devid == ""
): # Performing basic "auth" using devid, super insecure
users = bumper.db_get().table('users').all()
for user in users:
if user_devid in user['devices']:
user = bumper.user_by_deviceid(user_devid)
if "checkLogin" in request.path:
if request.query[
"accessToken"
] in user['tokens'] and request.query[
"uid"
] == "fuid_{}".format(
user['userid']
):
body = {
"code": bumper.RETURN_API_SUCCESS,
"data": {
"accessToken": request.query["accessToken"],
"country": countrycode,
"email": "null@null.com",
"uid": "fuid_{}".format(user['userid']),
"username": "fusername_{}".format(
user['userid']
),
},
"msg": "操作成功",
"time": bumper.get_milli_time(time.time()),
}
return web.json_response(body)
self.check_token(countrycode, user, request.query["accessToken"])
else:
body = {
"code": bumper.ERR_TOKEN_INVALID,
"data": None,
"msg": "当前密码错误",
"time": bumper.get_milli_time(time.time()),
}
return web.json_response(body)
else:
#Deactivate old tokens and authcodes
for token in user['tokens']:
bumper.user_revoke_token(user['userid'], token)
for authcode in user['authcodes']:
bumper.user_revoke_authcode(user['userid'], authcode)
bumper.user_revoke_expired_tokens(user['userid'])
body = {
"code": bumper.RETURN_API_SUCCESS,
@ -261,14 +223,44 @@ class ConfServer:
except Exception as e:
confserverlog.exception("{}".format(e))
def check_token(self, countrycode, user, token):
if (
bumper.check_token(user['userid'], token)
):
body = {
"code": bumper.RETURN_API_SUCCESS,
"data": {
"accessToken": token,
"country": countrycode,
"email": "null@null.com",
"uid": "fuid_{}".format(user['userid']),
"username": "fusername_{}".format(
user['userid']
),
},
"msg": "操作成功",
"time": bumper.get_milli_time(time.time()),
}
return web.json_response(body)
else:
body = {
"code": bumper.ERR_TOKEN_INVALID,
"data": None,
"msg": "当前密码错误",
"time": bumper.get_milli_time(time.time()),
}
return web.json_response(body)
def generate_token(self, user):
tmpaccesstoken = uuid.uuid4().hex
bumper.user_add_token(user['userid'],tmpaccesstoken)
return tmpaccesstoken
def generate_authcode(self, countrycode, user):
def generate_authcode(self, user, countrycode, token):
tmpauthcode = "{}_{}".format(countrycode, uuid.uuid4().hex)
bumper.user_add_authcode(user['userid'], tmpauthcode)
bumper.user_add_authcode(user['userid'], token, tmpauthcode)
return tmpauthcode
@ -276,11 +268,11 @@ class ConfServer:
try:
user_devid = devid
countrycode = country
users = bumper.db_get().table('users').all()
user = bumper.user_by_deviceid(user_devid)
bots = bumper.db_get().table('bots').all()
if len(users) > 0: #Default to user 0
tmpuser = users[0]
if user: #Default to user 0
tmpuser = user
bumper.user_add_device(tmpuser['userid'], user_devid)
else:
bumper.user_add("tmpuser") #Add a new user
@ -291,26 +283,13 @@ class ConfServer:
bumper.user_add_bot(tmpuser['userid'], bot['did'])
if "checkLogin" in request.path: #If request was to check a token do so
if request.query["accessToken"] in tmpuser['tokens']:
return {
"code": bumper.RETURN_API_SUCCESS,
"data": {
"accessToken": request.query["accessToken"], # Random chars 32 length
"country": countrycode,
"email": "null@null.com",
"uid": "fuid_{}".format(tmpuser['userid']),
"username": "fusername_{}".format(tmpuser['userid']),
},
"msg": "操作成功",
"time": bumper.get_milli_time(time.time()),
}
checkToken = self.check_token(countrycode, user, request.query["accessToken"])
isGood = json.loads(checkToken.text)
if isGood['code'] == "0000":
return isGood
#Deactivate old tokens and authcodes
for token in tmpuser['tokens']:
bumper.user_revoke_token(tmpuser['userid'], token)
for authcode in tmpuser['authcodes']:
bumper.user_revoke_authcode(tmpuser['userid'], authcode)
bumper.user_revoke_expired_tokens(tmpuser['userid'])
body = {
"code": bumper.RETURN_API_SUCCESS,
@ -334,22 +313,13 @@ class ConfServer:
try:
user_devid = request.match_info.get("devid", "")
if not user_devid == "":
users = bumper.db_get().table('users').all()
for user in users:
if user_devid in user['devices']:
user = bumper.user_by_deviceid(user_devid)
if user:
if (
request.query["uid"] == "fuid_{}".format(user['userid'])
and request.query["accessToken"] in user['tokens']
bumper.check_token(user['userid'], request.query["accessToken"])
):
#Deactivate old tokens and authcodes
for token in user['tokens']:
bumper.user_revoke_token(user['userid'], token)
#bumper.user_revoke_token(user['userid'],request.query["accessToken"])
for authcode in user['authcodes']:
bumper.user_revoke_authcode(user['userid'], authcode)
bumper.user_revoke_token(user['userid'], request.query["accessToken"])
body = {
"code": bumper.RETURN_API_SUCCESS,
@ -368,18 +338,20 @@ class ConfServer:
user_devid = request.match_info.get("devid", "")
if not user_devid == "":
users = bumper.db_get().table('users').all()
if len(users) > 0:
for user in users:
if (
user_devid in user['devices']
and request.query["accessToken"] in user['tokens']
):
user = bumper.user_by_deviceid(user_devid)
if user:
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']
body = {
"code": bumper.RETURN_API_SUCCESS,
"data": {
"authCode": self.generate_authcode(request.match_info.get("country", "us"), user),
"authCode": authcode,
"ecovacsUid": request.query["uid"],
},
"msg": "操作成功",
@ -560,13 +532,10 @@ class ConfServer:
}
elif service == "EcoUpdate":
body = {"result": "ok", "ip": "47.88.66.164", "port": 8005}
elif todo == "loginByItToken":
users = bumper.db_get().table('users').all()
for user in users:
elif todo == "loginByItToken":
if (
postbody["userId"] == "fuid_{}".format(user['userid'])
and postbody["token"] in user['authcodes']
bumper.check_authcode(postbody["userId"], postbody["token"])
):
body = {
"resource": postbody["resource"],