|
6 | 6 | from django.utils.module_loading import import_string as import_class_from_dotted_path |
7 | 7 | from rest_framework import exceptions |
8 | 8 | from rest_framework.authentication import BasicAuthentication, SessionAuthentication |
| 9 | +from rest_framework.permissions import OperandHolder, SingleOperandHolder |
9 | 10 | from rest_framework.relations import ManyRelatedField |
10 | 11 | from rest_framework.schemas import openapi as drf_openapi |
11 | 12 | from rest_framework.schemas.utils import is_list_view |
|
14 | 15 | from rest_framework_json_api.optional import OAuth2Authentication, TokenMatchesOASRequirements |
15 | 16 | from rest_framework_json_api.views import RelationshipView |
16 | 17 |
|
| 18 | +# DRF 3.9+ has native boolean conditions now |
| 19 | +# But older code may use rest_condition or other packages. |
| 20 | +try: |
| 21 | + from rest_condition import Condition as rest_condition_Condition |
| 22 | +except ImportError: |
| 23 | + rest_condition_Condition = None |
| 24 | + |
| 25 | + |
17 | 26 | #: static OAS 3.0 component definitions that are referenced by AutoSchema. |
18 | 27 | JSONAPI_COMPONENTS = { |
19 | 28 | 'schemas': { |
@@ -566,8 +575,32 @@ def _get_oauth_security(self, path, method): |
566 | 575 | self.openapi_schema['components']['securitySchemes']['oauth']['flows'] = flows |
567 | 576 | # TODO: add JWT and SAML2 bearer |
568 | 577 | content = [] |
569 | | - for perm_class in self.view.permission_classes: |
570 | | - if issubclass(perm_class, TokenMatchesOASRequirements): |
| 578 | + # permission_classes can be a direct list of classes, or instances of Operands, etc. |
| 579 | + # TODO: this is kind of ugly. modularize it. |
| 580 | + for perm_class_or_condition in self.view.permission_classes: |
| 581 | + # check if DRF conditional operands were specified |
| 582 | + if isinstance(perm_class_or_condition, OperandHolder): |
| 583 | + if issubclass(perm_class_or_condition.op1_class, TokenMatchesOASRequirements): |
| 584 | + perm_class_instance = perm_class_or_condition.op1_class() |
| 585 | + elif issubclass(perm_class_or_condition.op2_class, TokenMatchesOASRequirements): |
| 586 | + perm_class_instance = perm_class_or_condition.op2_class() |
| 587 | + else: |
| 588 | + perm_class_instance = None |
| 589 | + elif isinstance(perm_class_or_condition, SingleOperandHolder): |
| 590 | + if issubclass(perm_class_or_condition.op1_class, TokenMatchesOASRequirements): |
| 591 | + perm_class_instance = perm_class_or_condition.op1_class() |
| 592 | + else: |
| 593 | + perm_class_instance = None |
| 594 | + # check for rest_condition.Condition |
| 595 | + elif (rest_condition_Condition and |
| 596 | + isinstance(perm_class_or_condition, rest_condition_Condition)): |
| 597 | + for cond in perm_class_or_condition.perms_or_conds: |
| 598 | + if issubclass(cond, TokenMatchesOASRequirements): |
| 599 | + perm_class_instance = cond() |
| 600 | + break |
| 601 | + else: |
| 602 | + perm_class_instance = perm_class_or_condition() |
| 603 | + if isinstance(perm_class_instance, TokenMatchesOASRequirements): |
571 | 604 | alt_scopes = self.view.required_alternate_scopes |
572 | 605 | if method not in alt_scopes: |
573 | 606 | continue |
|
0 commit comments