import json from time import time from traceback import format_exc from functools import partial from sqlor.dbpools import DBPools, get_sor_context from appPublic.Singleton import SingletonDecorator from appPublic.streamhttpclient import StreamHttpClient, liner from appPublic.dictObject import DictObject from appPublic.log import debug, exception, error from appPublic.aes import aes_encode_b64 from ahserver.globalEnv import password_decode from ahserver.serverenv import get_serverenv, ServerEnv from random import randint async def get_deerer(upappid, callerid): db = DBPools() dbname = get_dbname() async with db.sqlorContext(dbname) as sor: ki = await get_userapikey(sor, upappid, callerid) d = deerer(ki.myappid, ki.apikey, ki.secretkey) if not d: return None return d[7:] return None async def sor_get_uapi(sor, upappid, apiname): sql = """select a.*, b.auth_apiname from uapi a, upapp b where a.upappid = b.id and a.name = ${apiname}$ and b.id = ${upappid}$""" recs = await sor.sqlExe(sql, {'upappid': upappid, 'apiname': apiname}) if len(recs) == 0: debug(f'{sql=},{upappid=}, {apiname=} uapi not found') return None return recs[0] def deerer(myappid, apikey, secretkey): t = time() txt = f'{t}:{apikey}' cyber = aes_encode_b64(secretkey, txt) return f'Deerer {myappid}-:-{cyber}' def bearer(apikey): return f'Bearer {apikey}' @SingletonDecorator class UAPIData: def __init__(self): self.apidata = {} self.apikeys = {} self.org_users = {} async def get_userapikey(self, appid, callerid): users = await self.get_apiusers(appid) for u in users: if u.userid == callerid: return DictObject(**{ 'apikey':u.apikey, 'secretkey':u.secretkey, 'baseurl':u.baseurl, 'appownerid': u.ownerid, 'dynamic_func_name': u.dynamic_func, 'myappid': u.myappid }) return None async def get_apiusers(self, appid, orgid=None): key = appid d = self.org_users.get(key) if d: return d env = ServerEnv() async with get_sor_context(env, 'uapi') as sor: sql = """select c.id, c.ownerid, c.myappid, c.baseurl, c.secretkey, c.dynamic_func, a.ownerid as userid, a.orgid as userorgid, a.apikey from upappkey a, users b, upapp c where b.orgid = c.ownerid and a.ownerid = b.id and a.upappid = c.id and a.upappid = ${appid}$ """ ns = {'appid': appid, 'orgid': orgid} if orgid: sql += " and a.orgid = ${orgid}$" else: sql += " and a.orgid = c.ownerid" d = await sor.sqlExe(sql, ns) for r in d: r.apikey = None if r.apikey is None else password_decode(r.apikey) r.secretkey = None if r.secretkey is None else password_decode(r.secretkey) if d is None: e = Exception(f'{appid=} {orgid=} get none user') exception(f'{e}') raise e self.apidata[key] = d return d e = Exception(f'{appid=} {orgid=} get none user') exception(f'{e}') raise e async def get_calluserid(self, appid, orgid=None): users = await self.get_apiusers(appid, orgid=orgid) cnt = len(users) if cnt < 1: e = Exception(f'get_calluserid():{appid=}, {orgid=} return None') exception(f'{e}') raise e i = randint(0, cnt - 1) return users[i].userid async def get_api(self, appid, apiname): key = f'{appid}.{apiname}' api = self.apidata.get(key) if api: return api env = ServerEnv() async with get_sor_context(env, 'uapi') as sor: d = await sor_get_uapi(sor, appid, apiname) if d is None: e = Exception(f'{appid=}, {apiname=} get none api') exception(f'{e}') raise e self.apidata[key] = d return d e = Exception(f'{appid=}, {apiname=} get none api') exception(f'{e}') raise e