role support
This commit is contained in:
@ -15,15 +15,6 @@ import asyncpg
|
||||
|
||||
|
||||
class CallDispatcher:
|
||||
def valid_public_function(self,
|
||||
risotto_context: Context,
|
||||
kwargs: Dict,
|
||||
public_only: bool):
|
||||
if public_only and not self.messages[risotto_context.version][risotto_context.message]['public']:
|
||||
msg = _(f'the message {risotto_context.message} is private')
|
||||
log.error_msg(risotto_context, kwargs, msg)
|
||||
raise NotAllowedError(msg)
|
||||
|
||||
async def valid_call_returns(self,
|
||||
risotto_context: Context,
|
||||
returns: Dict,
|
||||
@ -77,7 +68,7 @@ class CallDispatcher:
|
||||
version: str,
|
||||
message: str,
|
||||
old_risotto_context: Context,
|
||||
public_only: bool=False,
|
||||
check_role: bool=False,
|
||||
**kwargs):
|
||||
""" execute the function associate with specified uri
|
||||
arguments are validate before
|
||||
@ -86,16 +77,14 @@ class CallDispatcher:
|
||||
version,
|
||||
message,
|
||||
'rpc')
|
||||
self.valid_public_function(risotto_context,
|
||||
kwargs,
|
||||
public_only)
|
||||
self.check_message_type(risotto_context,
|
||||
kwargs)
|
||||
try:
|
||||
tiramisu_config = await self.load_kwargs_to_config(risotto_context,
|
||||
kwargs)
|
||||
kw = await self.load_kwargs_to_config(risotto_context,
|
||||
f'{version}.{message}',
|
||||
kwargs,
|
||||
check_role)
|
||||
function_obj = self.messages[version][message]
|
||||
kw = await tiramisu_config.option(message).value.dict()
|
||||
risotto_context.function = function_obj['function']
|
||||
if function_obj['risotto_context']:
|
||||
kw['risotto_context'] = risotto_context
|
||||
@ -150,7 +139,12 @@ class CallDispatcher:
|
||||
|
||||
|
||||
class PublishDispatcher:
|
||||
async def publish(self, version, message, old_risotto_context, public_only=False, **kwargs):
|
||||
async def publish(self,
|
||||
version: str,
|
||||
message: str,
|
||||
old_risotto_context: Context,
|
||||
check_role: bool=False,
|
||||
**kwargs) -> None:
|
||||
risotto_context = self.build_new_context(old_risotto_context,
|
||||
version,
|
||||
message,
|
||||
@ -158,9 +152,8 @@ class PublishDispatcher:
|
||||
self.check_message_type(risotto_context,
|
||||
kwargs)
|
||||
try:
|
||||
config = await self.load_kwargs_to_config(risotto_context,
|
||||
kwargs)
|
||||
config_arguments = await config.option(message).value.dict()
|
||||
config_arguments = await self.load_kwargs_to_config(risotto_context,
|
||||
kwargs)
|
||||
except CallError as err:
|
||||
return
|
||||
except Exception as err:
|
||||
@ -250,7 +243,9 @@ class Dispatcher(register.RegisterDispatcher, CallDispatcher, PublishDispatcher)
|
||||
|
||||
async def load_kwargs_to_config(self,
|
||||
risotto_context: Context,
|
||||
kwargs: Dict):
|
||||
uri: str,
|
||||
kwargs: Dict,
|
||||
check_role: bool):
|
||||
""" create a new Config et set values to it
|
||||
"""
|
||||
# create a new config
|
||||
@ -266,20 +261,73 @@ class Dispatcher(register.RegisterDispatcher, CallDispatcher, PublishDispatcher)
|
||||
except AttributeError:
|
||||
if DEBUG:
|
||||
print_exc()
|
||||
raise ValueError(_(f'unknown parameter "{key}"'))
|
||||
raise ValueError(_(f'unknown parameter in "{uri}": "{key}"'))
|
||||
# check mandatories options
|
||||
if check_role and get_config().get('global').get('check_role'):
|
||||
await self.check_role(subconfig,
|
||||
risotto_context.username,
|
||||
uri)
|
||||
await config.property.read_only()
|
||||
mandatories = await config.value.mandatory()
|
||||
if mandatories:
|
||||
mand = [mand.split('.')[-1] for mand in mandatories]
|
||||
raise ValueError(_(f'missing parameters: {mand}'))
|
||||
# return the config
|
||||
return config
|
||||
raise ValueError(_(f'missing parameters in "{uri}": {mand}'))
|
||||
# return complete an validated kwargs
|
||||
return await subconfig.value.dict()
|
||||
|
||||
def get_service(self,
|
||||
name: str):
|
||||
return self.injected_self[name]
|
||||
|
||||
async def check_role(self,
|
||||
config: Config,
|
||||
user_login: str,
|
||||
uri: str) -> None:
|
||||
db_conf = get_config().get('database')
|
||||
pool = await asyncpg.create_pool(database=db_conf.get('dbname'), user=db_conf.get('user'))
|
||||
async with pool.acquire() as connection:
|
||||
async with connection.transaction():
|
||||
# Verify if user exists and get ID
|
||||
sql = '''
|
||||
SELECT UserId
|
||||
FROM RisottoUser
|
||||
WHERE UserLogin = $1
|
||||
'''
|
||||
user_id = await connection.fetchval(sql,
|
||||
user_login)
|
||||
if user_id is None:
|
||||
raise NotAllowedError(_(f"You ({user_login}) don't have any account in this application"))
|
||||
|
||||
# Get all references for this message
|
||||
refs = {}
|
||||
for option in await config.list('all'):
|
||||
ref = await option.information.get('ref')
|
||||
if ref:
|
||||
refs[ref] = str(await option.value.get())
|
||||
|
||||
# Check role
|
||||
select_role_uri = '''
|
||||
SELECT RoleName
|
||||
FROM URI, RoleURI
|
||||
WHERE URI.URIName = $1 AND RoleURI.URIId = URI.URIId
|
||||
'''
|
||||
select_role_user = '''
|
||||
SELECT RoleAttribute, RoleAttributeValue
|
||||
FROM UserRole
|
||||
WHERE RoleUserId = $1 AND RoleName = $2
|
||||
'''
|
||||
for uri_role in await connection.fetch(select_role_uri,
|
||||
uri):
|
||||
for user_role in await connection.fetch(select_role_user,
|
||||
user_id,
|
||||
uri_role['rolename']):
|
||||
if not user_role['roleattribute']:
|
||||
return
|
||||
if user_role['roleattribute'] in refs and \
|
||||
user_role['roleattributevalue'] == refs[user_role['roleattribute']]:
|
||||
return
|
||||
raise NotAllowedError(_(f'You ({user_login}) don\'t have any authorisation to access to "{uri}"'))
|
||||
|
||||
|
||||
dispatcher = Dispatcher()
|
||||
register.dispatcher = dispatcher
|
||||
|
Reference in New Issue
Block a user