Package: nosorog
NosorogIntrodactionAn assertive security library.Requirements3.5 >= Python <= 3.10Installingpip install nosorogTestingcd/path/to/lib/python3-munittestdiscoverHow to useExceptionsExceptionDefault messageNosorogMangledNameError"Use method`s dunder name instead."NosorogWrongPlaceCallError(1)"Protected method can be called from specified methods only."NosorogWrongPlaceCallError(2)"Protected method can not be called from other object, use self instead."NosorogWentWrongError"Something broken."NosorogTypeErrorchild ofTypeError. No especial message provided.It is possible to use a concatenation of predefined and custom messages:raiseNosorogMangledNameError("Method __get accessible with _MangledName__get() call.")# NosorogMangledNameError: "Use method`s dunder name instead. Method __get accessible with _MangledName__get() call."But it is one exclusion:NosorogWrongPlaceCallErroruses the message"Protected method can be called from specified methods only."by default
and or other instead:fromnosorog.exceptions.mixins.nosorog_exception_messagesimportNosorogExceptionMessagesraiseNosorogWrongPlaceCallError(NosorogExceptionMessages.use_self)# NosorogExceptionMessages: "Protected method can not be called from other object, use self instead."It is not concatenated.Full list of predefined messagesAttributeMessageprotected_from_not_private_call"This method protected from not private call."method_protected"This method protected."wrong_place"Protected method can be called from specified places only."use_self"Protected method can not be called from other object, use self instead."mangled_call_blocked"Use method`s dunder name instead."Class based decoratorsTo import class based decorators use:fromnosorog.decoratorsimportprotect_private,copy_dicts,silentDecoratorDescription@silentintercepts all the exceptions ofNosorogand returnsNoneinstead.@silent.include(exceptions)same as above and list of provided exceptions to.------@protect_private.block_mangled_callprotect of name mangling usage.@protect_private.one_objdecorated method accessible withselfusage only.@protect_private.one_method("method_name")decorated method accessible from one method only.@protect_private.call_from(methods)decorated method accessible from the methods provided in list only.------@copy_dictsmakes shallow copy of all the dicts inargsandkwargs@copy_dicts.deep_argsmakes deep copy of all the dicts inargs@copy_dicts.deep_kwargsmakes deep copy of all the dicts inkwargs@copy_dicts.deep_allmakes deep copy of all the dicts inargsandkwargs@copy_dicts.shallow_argsmakes shallow copy of all the dicts inargs@copy_dicts.shallow_kwargsmakes shallow copy of all the dicts inkwargs@copy_dicts.shallow_allmakes shallow copy of all the dicts inargsandkwargsFunction based decoratorsTo import function based decorators use:fromnosorog.decorators.function_based_decoratorsimportprotect_private,copy_dicts,protect_ids,protected_callDecoratorDescription@protect_private(allowed_list=list)make a call with_Class__private_method()impossible.allowed_listit isstrnames of method which you can call the private method from. also support'self'(str) for calls from same object only.@protected_call(from_method=str, from_file=str)make the attack by the file injection impossible.@copy_dicts(deep_copy=bool)make a copy ofdictsinargsandkwargs.@protect_ids(id_names=[str])trying to convert id tointor throwException.ExamplesThis explanation written for the function based decorators. Class based decorators works the same way with some differences
in the syntax. Read the full documentation onhttps://nosorog.readthedocs.io.Private methodsUsage of dunder methods (__method()) protects the code avoiding direct access to the method.classExample:def__get_data(self):return1>>>Example().__get_data()# AttributeError: 'Example' object has no attribute '__get_data'But it is possible to use the name mangling.>>>Example()._Example__get_data()# 1Nosorogprovides simple and pushy way to protect the dunder method.classExample:@protect_private(allowed_list=['trusted_func'])def__get_data(self):return1classTrusted:@staticmethoddeftrusted_func():returnExample()._Example__get_data()>>>Example().__get_data()# AttributeError: 'Example' object has no attribute '__get_data'>>>Example()._Example__get_data()# Exception: This method protected from not private call.>>>Trusted()._Example__get_data()# 1Also, str'self'can be used as a list item to make impossible to call withoutself.classExample:@protect_private(allowed_list=['trusted_func','self'])def__get_data(self):return1deftrusted_func(self):returnself.__get_data()classTrusted:@staticmethoddeftrusted_func():returnExample()._Example__get_data()>>>Example().trusted_func()# 1>>>Trusted().trusted_func()# Exception: This method can not be called from other object, use self instead.Localization of method callPython does not provide an easy way to limit where the method can be called from. This makes it possible to conduct an
attack by File Injection. With the help of theNosoroglibrary it is possible to specify the places from which the
method can be called.classExample:@protected_call(from_method='safe_method',from_file=os.path.abspath(__file__))def__get_data(self):return1classTrusted:# Place it to the same file as described in the decorator usage.defsafe_method():returnExample()._Example__get_data()# 1This is just a variation of the previous decorator.Protection of the dictsIn the projects where the undefined number of dicts can be passed inargsandkwargs, it is possible to make a deep copy
of each if needed.classExample:@copy_dicts(deep_copy=False)defsome_method(self,*args,**kwargs):# now dicts are shallow copiespassUse@copy_dicts(deep_copy=True)to make deep copies.Protection of idsThis method has been added just for fun.
It is converts all the ids in the list if possible or throws theTypeError.classExample:@protect_ids(id_names=['user_id','pk'])defsome_method(user_id=None,pk=None)passPossibleExceptions@protect_ids(id_names=['user_id',dict()])>>>Example().some_method(user_id='1')# TypeError: Wrong format of id_names in decorator. Must be list of str.@protect_ids(id_names=['user_id','pk'])>>>Example().some_method(user_id=1.234,pk='text_id')# TypeError: Received the ids of wrong type.