uapi/uapi/appapi.py

177 lines
5.0 KiB
Python

import json
from traceback import format_exc
from functools import partial
from sqlor.dbpools import DBPools
from appPublic.streamhttpclient import StreamHttpClient, liner
from appPublic.dictObject import DictObject
from appPublic.myTE import MyTemplateEngine
from appPublic.log import debug, exception, error
from ahserver.globalEnv import password_decode
from ahserver.serverenv import get_serverenv
def get_dbname():
f = get_serverenv('get_module_dbname')
dbname = f('uapi')
return dbname
def deerer(myappid, apikey, secretkey):
t = time()
txt = f'{t}:{apikey}'
cyber = aes_encrypt_ecb(secretkey, txt)
return f'Deerer {appid}-:-{cyber}'
def bearer(apikey):
return f'Bearer {apikey}'
async def sync_users(request, upappid, userid):
db = DBPools()
dbname = get_dbname()
async with db.sqlorContext(dbname) as sor:
upapp = await get_upapp(sor, upappid)
class UAPI:
def __init__(self, request, env=DictObject()):
self.request = request
self.te = MyTemplateEngine([], env=env)
self.env = env
self.env.request.request = request
self.auth_api = None
self.auth_ret = None
async def rendertmpl(self, tmplstr, params={}):
if tmplstr is None:
return None
ns = self.env.copy()
ns.update(params)
te = MyTemplateEngine([], env=self.env)
return te.renders(tmplstr, ns)
async def get_uapis(self, upappid, apiname, callerid, params={}):
self.env.update(params)
db = DBPools()
dbname = get_dbname()
uapi = None
auth_uapi = None
async with db.sqlorContext(dbname) as sor:
upapps = await sor.R('upapp', {'id': upappid})
if len(upapps) == 0:
e = Exceptions(f'{upappid=}, {apiname=}, {callerid=} upapp not found')
exception(f'{e=}\n{format_exc()}')
raise e
upapp = upapps[0]
apisets = await sor.R('uapiset', {'id': upapp.apisetid})
if len(apisets) == 0:
e = Exceptions(f'{upappid=}, {apiname=}, {callerid=} apiset not found')
exception(f'{e=}\n{format_exc()}')
raise e
return None, None
apiset = apisets[0]
r recs = await sor.R('uapi', {'name':apiname, 'apisetid': upapp.apisetid})
if len(recs)==0:
return None, None
uapi = recs[0]
self.uapi = uapi
kinfo = await self.get_userapikey(sor, upappid, callerid)
self.env.update(kinfo)
auth_uapi = None
if apiset.auth_apiname:
uapis = await sor.R('uapi', {'name': apiset.auth_apiname, 'apisetid': upapp.apisetid})
if len(uapis) == 0:
e = Exceptions(f'{upappid=}, {uapiid=}, {callerid=} {apiset.auth_apinamed=} auth_api not found')
exception(f'{e=}\n{format_exc()}')
raise e
auth_uapi = uapi[0]
self.auth_uapi = auth_uapi
return auth_uapi, uapi
return None, None
async def __call__(self, upappid, apiname, callerid, params={}):
"""
"""
auth_uapi, uapi = await self.get_uapis(upapiid, apiname,
callerid, params=params)
if uapi is None:
return
if auth_uapi:
await self.do_auth(auth_uapi)
async for chunk in self.stream_resp(uapi):
yield chunk
t
async stream_linify(self, upappid, apiname, callerid, params={}):
gen = liner(self.__call__(upappid, apiname, callerid, params=params))
async for line in gen:
yield line
async def request(self, upappid, apiname, callerid, params={}):
b = b''
async for chunk in self__call__(upapiid, apiname, callerid, params=params):
b += chunk
return b
async def do_auth(self, auth_uapi):
b = b''
async for chunk in self.stream_resp(auth_uapi):
b+= chunk
d = json.loads(b.encode('utf-8'))
self.env.update(d)
return
async def stream_resp(self, api):
url = self.env.get('baseurl') + api.path
method = api.httpmethod
headers = await self.rendertmpl(api.headers)
headers = json.loads(headers)
body = await self.rendertmpl(api.data)
if body:
bdy = json.loads(body)
bdy['stream'] = True
body = json.dumps(bdy, ensure_ascii=False)
_params = await self.rendertmpl(api.params)
if _params:
_params = json.loads(_params)
debug(f'{headers=}, {body=}. {method=}, {url=}')
shc = StreamHttpClient()
gen = shc(method, url,
headers=headers,
data=body,
params=_params)
async for chunk in gen:
yield chunk
async def get_userapikey(self, sor, upappid, callerid):
"""
argumemts:
upappid: upappid which will make call to
orgid: owner organization or user which as the caller of the call
return:
None: this orgid has not gotton apikey from upapp
dict if apikey and upapp infos
"""
sql = """select
a.myappid,
a.ownerid as appownerid,
a.baseurl,
b.apikey,
a.secretkey
from upapp a, upappkey b
where a.id = b.upappid
and a.id = ${appid}$
and b.ownerid = ${ownerid}$"""
recs = await sor.sqlExe(sql, {'appid':upappid, 'ownerid': callerid})
if len(recs) < 1:
e = Exception(f'{appid=}, {callerid=} has not apikey')
exception(f'{e}, {format_exc()}')
raise e
r = recs[0]
return DictObject(**{
'apikey':password_decode(r.apikey),
'secretkey':password_decode(r.secretkey),
'baseurl':r.baseurl,
'appownerid': r.appownerid,
'myappid': r.myappid
})
if __name__ == '__main__':
print('test')