tfranzel / drf-spectacular

Sane and flexible OpenAPI 3 schema generation for Django REST framework.
https://drf-spectacular.readthedocs.io
BSD 3-Clause "New" or "Revised" License
2.4k stars 266 forks source link

Scoping documentation based on access level - or - permission classes #325

Closed tiholic closed 3 years ago

tiholic commented 3 years ago

I want to expose docs for handful of APIs (1) to all our users - include in public documentation. And expose docs for complete set of APIs to staff users (2) - these APIs are mostly specific to UI and security related ones like managing auth tokens.

I could achieve (1) using exclude: True using extend_schema. But this suppresses (2)

This could also help us in generating 2 different JS SDKs - one to be open-sourced and another to be consumed in our own UI.

tfranzel commented 3 years ago

currently you can do this by

path('api/internal/schema/', SpectacularAPIView.as_view(urlconf=urlpatterns_public))
path('api/external/schema/', SpectacularAPIView.as_view())  # all

but that means you have to have a splitted urlpatterns in urls.py

tiholic commented 3 years ago

That's a way to go, but we would need to split some views for that!

Can you point me in a direction where we can add a function is_authorized / or list of authentication classes at schema extraction level! I can create a PR for the same.

krzysieqq commented 3 years ago

I tried the same thing recently. IMO the best option could be showing permission_classes items in swagger view, but I didn't know how to reach this out, so I used OAuth scope access (#324 ) which does this thing in another way.

tfranzel commented 3 years ago

Can you point me in a direction where we can add a function is_authorized / or list of authentication classes at schema extraction level! I can create a PR for the sam

@tiholic i don't quite understand what you mean. maybe this is what you are after: we have a settting 'SERVE_PUBLIC': False, (default True) that should filter down the schema based on the permissions of the requesting user. however that will only work with the view and not the CLI obviously. this should work, but i just found that we do not have a test case for this. must have been overlooked

another solution would be scoping via extend_schema, but that does not look like an ideal solution either.

tiholic commented 3 years ago

I'm referring to adding more options to extend_schema. Does that make sense?

So we could write something like

@extend_schema(has_schema_access: lambda req: return req.user.is_staff)
tfranzel commented 3 years ago

i see what you mean. unfortunately would mean you have to apply extend_schema to everything. we could think about this more thoroughly though.

have you tried using 'SERVE_PUBLIC': False this should filter down schema based on the permissions of the requesting user for each and every endpoint? or is that approach to coarse?

tiholic commented 3 years ago

Yes, I'm already using SERVE_PUBLIC: False. Not what solves my need, though.

Anyways I'm extending schema for all my views to have a custom operation IDs for better method names while generating SDK's and don't mind adding an extra argument on few.

tfranzel commented 3 years ago

ok.. bummer. i would prefer to not introduce a change here unless there is more pressure from the users.

generally there is also the option for post- and preprocessing hooks. you can also look into that. enum handling is a postprocessing hook

alxvallejo commented 4 months ago

i see what you mean. unfortunately would mean you have to apply extend_schema to everything

@tfranzel as opposed to what? I thought applying extend_schema was generally the go-to for any view-level specification that goes beyond the auto-schemas generated (in my case it's just about every single view). I'm surprised this isn't more universally supported - documenting permissions for api routes seems like a pretty standard use case.