lepture / authlib

The ultimate Python library in building OAuth, OpenID Connect clients and servers. JWS,JWE,JWK,JWA,JWT included.
https://authlib.org/
BSD 3-Clause "New" or "Revised" License
4.45k stars 445 forks source link

In Django projects ResourceProtector not able to decorate unclude('urls') or class methods. (solution provided) #602

Open danilovmy opened 8 months ago

danilovmy commented 8 months ago

ResourceProtector seems be able to work only with single FB-view, but in django it is Exception than normal situation.

For example: Django offers admin urls - this is a bunch of admin urls or function include('some_app_urls_module')

Currently this snippet not works:

urlpatterns = [
    path('api/', ResourceProtector()(include('api.urls')), name='apis'),  # TODO: realize it
 ]

I can go through every url separately and decorate it with ResourceProtector in loop. But, probably it should happens automatically.

Something like:

class Protector(ResourceProtector):
    def __call__(self, wrapped, *args, **kwargs):
        if isinstance(wrapped, (list, tuple)):
            urlconf_module, app_name, namespace = wrapped
            for urlpattern in (getattr(urlconf_module, 'urlpatterns', None) or []):
                if not hasattr(urlpattern, '_protected_by_resource_protector'):
                    urlpattern.callback = self(urlpattern.callback, *args, **kwargs)
            return (urlconf_module, app_name, namespace)
        wrapped._protected_by_resource_protector = True
        return super().__call__(*args, **kwargs)(wrapped)

We need the _protected_by_resource_protector, because you should not decorate endpoint if it is already decorated.