diff --git a/dojo/admin.py b/dojo/admin.py index a2452ce1e5..c40d39e3c2 100644 --- a/dojo/admin.py +++ b/dojo/admin.py @@ -22,29 +22,25 @@ class QuestionChildAdmin(PolymorphicChildModelAdmin): - """ - Base admin class for all child models of Question - """ + + """Base admin class for all child models of Question""" base_model = Question class TextQuestionAdmin(QuestionChildAdmin): - """ - ModelAdmin for a TextQuestion - """ + + """ModelAdmin for a TextQuestion""" class ChoiceQuestionAdmin(QuestionChildAdmin): - """ - ModelAdmin for a ChoiceQuestion - """ + + """ModelAdmin for a ChoiceQuestion""" class QuestionParentAdmin(PolymorphicParentModelAdmin): - """ - Question parent model admin - """ + + """Question parent model admin""" base_model = Question child_models = ( @@ -60,29 +56,25 @@ class QuestionParentAdmin(PolymorphicParentModelAdmin): class AnswerChildAdmin(PolymorphicChildModelAdmin): - """ - Base admin class for all child Answer models - """ + + """Base admin class for all child Answer models""" base_model = Answer class TextAnswerAdmin(AnswerChildAdmin): - """ - ModelAdmin for TextAnswer - """ + + """ModelAdmin for TextAnswer""" class ChoiceAnswerAdmin(AnswerChildAdmin): - """ - ModelAdmin for ChoiceAnswer - """ + + """ModelAdmin for ChoiceAnswer""" class AnswerParentAdmin(PolymorphicParentModelAdmin): - """ - The parent model admin for answer - """ + + """The parent model admin for answer""" list_display = ( "answered_survey", diff --git a/dojo/api_v2/prefetch/prefetcher.py b/dojo/api_v2/prefetch/prefetcher.py index 3596b3f940..917afd2a04 100644 --- a/dojo/api_v2/prefetch/prefetcher.py +++ b/dojo/api_v2/prefetch/prefetcher.py @@ -18,7 +18,8 @@ class _Prefetcher: @staticmethod def _build_serializers(): - """Returns a map model -> serializer where model is a django model and serializer is the corresponding + """ + Returns a map model -> serializer where model is a django model and serializer is the corresponding serializer used to serialize the model Returns: @@ -52,7 +53,8 @@ def __init__(self): self._prefetch_data = {} def _find_serializer(self, field_type): - """Find the best suited serializer for the given type. + """ + Find the best suited serializer for the given type. Args: field_type (django.db.models.fields): the field type for which we need to find a serializer @@ -72,7 +74,8 @@ def _find_serializer(self, field_type): return self._find_serializer(parent_class) def _prefetch(self, entry, fields_to_fetch): - """Apply prefetching for the given field on the given entry + """ + Apply prefetching for the given field on the given entry Args: entry (ModelInstance): Instance of a model as returned by a django queryset diff --git a/dojo/api_v2/prefetch/schema.py b/dojo/api_v2/prefetch/schema.py index 535e01e4e6..ef5cbbf389 100644 --- a/dojo/api_v2/prefetch/schema.py +++ b/dojo/api_v2/prefetch/schema.py @@ -18,7 +18,8 @@ def _get_path_to_GET_serializer_map(generator): def get_serializer_ref_name(serializer): - """Get serializer's ref_name + """ + Get serializer's ref_name inspired by https://github.com/axnsan12/drf-yasg/blob/78031f0c189585c30fccb5005a6899f2d34289a9/src/drf_yasg/utils.py#L416 :param serializer: Serializer instance @@ -37,14 +38,14 @@ def get_serializer_ref_name(serializer): def prefetch_postprocessing_hook(result, generator, request, public): - """OpenAPI v3 (drf-spectacular) Some endpoints are using the PrefetchListMixin and PrefetchRetrieveMixin. + """ + OpenAPI v3 (drf-spectacular) Some endpoints are using the PrefetchListMixin and PrefetchRetrieveMixin. These have nothing to do with Django prefetch_related. The endpoints have an @extend_schema configured with an extra parameter 'prefetch' This parameter contains an array of relations to prefetch. These prefetched models will be returned in an additional property in the response. The below processor ensures the result schema matches this. """ - serializer_classes = _get_path_to_GET_serializer_map(generator) paths = result.get("paths", {}) diff --git a/dojo/api_v2/prefetch/utils.py b/dojo/api_v2/prefetch/utils.py index de7ea2b383..5e588e03ce 100644 --- a/dojo/api_v2/prefetch/utils.py +++ b/dojo/api_v2/prefetch/utils.py @@ -2,7 +2,8 @@ def _is_many_to_many_relation(field): - """Check if a field specified a many-to-many relationship as defined by django. + """ + Check if a field specified a many-to-many relationship as defined by django. This is the case if the field is an instance of the ManyToManyDescriptor as generated by the django framework @@ -16,7 +17,8 @@ def _is_many_to_many_relation(field): def _is_one_to_one_relation(field): - """Check if a field specified a one-to-one relationship as defined by django. + """ + Check if a field specified a one-to-one relationship as defined by django. This is the case if the field is an instance of the ForwardManyToOne as generated by the django framework @@ -30,7 +32,8 @@ def _is_one_to_one_relation(field): def _get_prefetchable_fields(serializer): - """Get the fields that are prefetchable according to the serializer description. + """ + Get the fields that are prefetchable according to the serializer description. Method mainly used by for automatic schema generation. Args: diff --git a/dojo/api_v2/views.py b/dojo/api_v2/views.py index 9e8368d627..a74442aa96 100644 --- a/dojo/api_v2/views.py +++ b/dojo/api_v2/views.py @@ -2360,6 +2360,7 @@ def get(self, request, format=None): # Authorization: authenticated users, DjangoModelPermissions class ImportScanView(mixins.CreateModelMixin, viewsets.GenericViewSet): + """ Imports a scan report into an engagement or product. @@ -2423,6 +2424,7 @@ def get_queryset(self): class EndpointMetaImporterView( mixins.CreateModelMixin, viewsets.GenericViewSet, ): + """ Imports a CSV file into a product to propagate arbitrary meta and tags on endpoints. @@ -2498,6 +2500,7 @@ def get_queryset(self): # Authorization: object-based class ReImportScanView(mixins.CreateModelMixin, viewsets.GenericViewSet): + """ Reimports a scan report into an existing test. @@ -2898,6 +2901,7 @@ def report_generate(request, obj, options): class SystemSettingsViewSet( mixins.ListModelMixin, mixins.UpdateModelMixin, viewsets.GenericViewSet, ): + """Basic control over System Settings. Use 'id' 1 for PUT, PATCH operations""" permission_classes = (permissions.IsSuperUser, DjangoModelPermissions) diff --git a/dojo/authorization/authorization_decorators.py b/dojo/authorization/authorization_decorators.py index 3063d0821d..1f1bc9dbcb 100644 --- a/dojo/authorization/authorization_decorators.py +++ b/dojo/authorization/authorization_decorators.py @@ -12,7 +12,6 @@ def user_is_authorized(model, permission, arg, lookup="pk", func=None): """Decorator for functions that ensures the user has permission on an object.""" - if func is None: return functools.partial( user_is_authorized, model, permission, arg, lookup, @@ -41,7 +40,6 @@ def _wrapped(request, *args, **kwargs): def user_has_global_permission(permission, func=None): """Decorator for functions that ensures the user has a (global) permission""" - if func is None: return functools.partial(user_has_global_permission, permission) @@ -54,10 +52,7 @@ def _wrapped(request, *args, **kwargs): def user_is_configuration_authorized(permission, func=None): - """ - Decorator for views that checks whether a user has a particular permission enabled. - """ - + """Decorator for views that checks whether a user has a particular permission enabled.""" if func is None: return functools.partial(user_is_configuration_authorized, permission) diff --git a/dojo/authorization/roles_permissions.py b/dojo/authorization/roles_permissions.py index 779463258f..530008a2f7 100644 --- a/dojo/authorization/roles_permissions.py +++ b/dojo/authorization/roles_permissions.py @@ -517,9 +517,7 @@ def get_roles_with_permissions(): def get_global_roles_with_permissions(): - """ - Extra permissions for global roles, on top of the permissions granted to the "normal" roles above. - """ + """Extra permissions for global roles, on top of the permissions granted to the "normal" roles above.""" return { Roles.Maintainer: {Permissions.Product_Type_Add}, Roles.Owner: {Permissions.Product_Type_Add}, diff --git a/dojo/engagement/views.py b/dojo/engagement/views.py index 94e7cec960..ea73bd80c6 100644 --- a/dojo/engagement/views.py +++ b/dojo/engagement/views.py @@ -693,9 +693,7 @@ def add_tests(request, eid): class ImportScanResultsView(View): def get_template(self) -> str: - """ - Returns the template that will be presented to the user - """ + """Returns the template that will be presented to the user""" return "dojo/import_scan_results.html" def get_development_environment( @@ -715,9 +713,7 @@ def get_engagement_or_product( engagement_id: Optional[int] = None, product_id: Optional[int] = None, ) -> Tuple[Engagement, Product, Product | Engagement]: - """ - Using the path parameters, either fetch the product or engagement - """ + """Using the path parameters, either fetch the product or engagement""" engagement = product = engagement_or_product = None # Get the product if supplied # Get the engagement if supplied @@ -740,9 +736,7 @@ def get_form( request: HttpRequest, **kwargs: dict, ) -> ImportScanForm: - """ - Returns the default import form for importing findings - """ + """Returns the default import form for importing findings""" if request.method == "POST": return ImportScanForm(request.POST, request.FILES, **kwargs) return ImportScanForm(**kwargs) @@ -776,9 +770,7 @@ def get_jira_form( request: HttpRequest, engagement_or_product: Engagement | Product, ) -> Tuple[JIRAImportScanForm | None, bool]: - """ - Returns a JiraImportScanForm if jira is enabled - """ + """Returns a JiraImportScanForm if jira is enabled""" jira_form = None push_all_jira_issues = False # Determine if jira issues should be pushed automatically @@ -919,18 +911,14 @@ def get_importer( self, context: dict, ) -> BaseImporter: - """ - Gets the importer to use - """ + """Gets the importer to use""" return DefaultImporter(**context) def import_findings( self, context: dict, ) -> str | None: - """ - Attempt to import with all the supplied information - """ + """Attempt to import with all the supplied information""" try: importer_client = self.get_importer(context) context["test"], _, finding_count, closed_finding_count, _, _, _ = importer_client.process_scan( @@ -952,9 +940,7 @@ def process_form( form: ImportScanForm, context: dict, ) -> str | None: - """ - Process the form and manipulate the input in any way that is appropriate - """ + """Process the form and manipulate the input in any way that is appropriate""" # Update the running context dict with cleaned form input context.update({ "scan": request.FILES.get("file", None), @@ -1024,9 +1010,7 @@ def process_credentials_form( form: CredMappingForm, context: dict, ) -> str | None: - """ - Process the credentials form by creating - """ + """Process the credentials form by creating""" if cred_user := form.cleaned_data["cred_user"]: # Select the credential mapping object from the selected list and only allow if the credential is associated with the product cred_user = Cred_Mapping.objects.filter( @@ -1046,18 +1030,14 @@ def success_redirect( self, context: dict, ) -> HttpResponseRedirect: - """ - Redirect the user to a place that indicates a successful import - """ + """Redirect the user to a place that indicates a successful import""" return HttpResponseRedirect(reverse("view_test", args=(context.get("test").id, ))) def failure_redirect( self, context: dict, ) -> HttpResponseRedirect: - """ - Redirect the user to a place that indicates a failed import - """ + """Redirect the user to a place that indicates a failed import""" return HttpResponseRedirect(reverse( "import_scan_results", args=(context.get("engagement", context.get("product")).id, ), @@ -1069,9 +1049,7 @@ def get( engagement_id: Optional[int] = None, product_id: Optional[int] = None, ) -> HttpResponse: - """ - Process GET requests for the Import View - """ + """Process GET requests for the Import View""" # process the request and path parameters request, context = self.handle_request( request, @@ -1087,9 +1065,7 @@ def post( engagement_id: Optional[int] = None, product_id: Optional[int] = None, ) -> HttpResponse: - """ - Process POST requests for the Import View - """ + """Process POST requests for the Import View""" # process the request and path parameters request, context = self.handle_request( request, diff --git a/dojo/finding/helper.py b/dojo/finding/helper.py index d52857f229..1182cb26d6 100644 --- a/dojo/finding/helper.py +++ b/dojo/finding/helper.py @@ -566,7 +566,7 @@ def engagement_post_delete(sender, instance, **kwargs): def fix_loop_duplicates(): - """ Due to bugs in the past and even currently when under high parallel load, there can be transitive duplicates. """ + """Due to bugs in the past and even currently when under high parallel load, there can be transitive duplicates.""" """ i.e. A -> B -> C. This can lead to problems when deleting findingns, performing deduplication, etc """ candidates = Finding.objects.filter(duplicate_finding__isnull=False, original_finding__isnull=False).order_by("-id") diff --git a/dojo/forms.py b/dojo/forms.py index abd5a40d9c..c398fb21d0 100644 --- a/dojo/forms.py +++ b/dojo/forms.py @@ -140,6 +140,7 @@ def render(self, name, *args, **kwargs): class MonthYearWidget(Widget): + """ A Widget that splits date input into two