Like any other decorator works -
A decorator is a function which receives a function as an argument, and returns another function.
The returned function will "take the place" from the original function.
Since the desired effect with a decoratos is usually to be able to run some code before and after the original function (the one being decorated) runs, decorators create a new function which takes any number of anonymous and named parameters (the * prefixing "args" and the ** prefixing "kwargs" are responsible to store the parameters in a list and a dictionary, respectively)
Inside this new function, you have a place to write your verification code - and then it calls the original function - which in this context is called "func", and returns its original value.
the "decorator.decorator" call is not strictly needed: it jsut modifies some ttrbitues of the wrapper function so that it appears more closely to be the original funciton (like the 'func_name' attribute) - but the code should work without it.
After definning a decorator, you have to apply it to a function or method you wish to decorate: just put an @allowed_roles in a line prefixing the function definition you want to decorate.