-
-
Notifications
You must be signed in to change notification settings - Fork 46
Description
Checklist
- I believe the idea is awesome and would benefit the framework
- I have searched in the issue tracker for similar requests, including closed ones
Description
When we want to ensure that a user marked as banned cannot interact, we consider three things:
-
Repeating code at the top of the handler function body to validate whether the user is banned. (It doesn't look nice, but you have control.)
-
Using a decorator that performs the validations for you. (It's not much different from the first option; after all, you still repeat code above the functions, but you still have control.)
-
Defining a handler with a higher group/priority and using
StopPropagation. (It seems much more practical, BUT, if the handler unexpectedly breaks before you callStopPropagation, the banned user will bypass this validation layer; wrapping the entire function in atrywill be necessary.)
I really like the third option, it would be interesting if we could define it as StopPropagation (to ensure that it does not propagate even if an error occurs) before validation, and after using CotinuePropagation, for example:
async def layer_check_user_banned(client: Client, message: Message):
user = ......
if user.banned:
raise StopPropagation
@Client.on_message(group=-1)
async def setup(client: Client, message: Message):
await update.stop_propagation()
layers = (layer_check_user_banned, layer_check_user_has_username, .....)
for layer in layers:
await layer(client, message)
await update.continue_propagation()Alternatively I'm using decorators in these security layers to catch the error and rethrow it as StopPropagation:
def layer(function):
async def _decorator(*args, **kwargs):
try:
return await function(*args, **kwargs)
except StopPropagation:
raise
except Exception as e:
logging.error(
f'Layer {function.__name__!r} traceback:',
exc_info=e
)
raise StopPropagation
return _decorator