Skip to content

Commit 7cf1701

Browse files
authored
Read only authorized users in filters and calendar (DefectDojo#6211)
* Read only authorized users for filters * remove is_active in query * performance optimization * flake8 * accessibility * unit test
1 parent 19d6da6 commit 7cf1701

File tree

10 files changed

+205
-44
lines changed

10 files changed

+205
-44
lines changed

dojo/engagement/views.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
from dojo.models import Finding, Product, Engagement, Test, \
3333
Check_List, Test_Import, Notes, \
3434
Risk_Acceptance, Development_Environment, Endpoint, \
35-
Cred_Mapping, Dojo_User, System_Settings, Note_Type, Product_API_Scan_Configuration
35+
Cred_Mapping, System_Settings, Note_Type, Product_API_Scan_Configuration
3636
from dojo.tools.factory import get_scan_types_sorted
3737
from dojo.utils import add_error_message_to_response, add_success_message_to_response, get_page_items, add_breadcrumb, handle_uploaded_threat, \
3838
FileIterWrapper, get_cal_event, Product_Tab, is_scan_file_too_large, \
@@ -50,6 +50,7 @@
5050
from dojo.authorization.roles_permissions import Permissions
5151
from dojo.product.queries import get_authorized_products
5252
from dojo.engagement.queries import get_authorized_engagements
53+
from dojo.user.queries import get_authorized_users
5354
from dojo.authorization.authorization_decorators import user_is_authorized
5455
from dojo.importers.importer.importer import DojoDefaultImporter as Importer
5556
import dojo.notifications.helper as notifications_helper
@@ -83,7 +84,7 @@ def engagement_calendar(request):
8384
'caltype': 'engagements',
8485
'leads': request.GET.getlist('lead', ''),
8586
'engagements': engagements,
86-
'users': Dojo_User.objects.all()
87+
'users': get_authorized_users(Permissions.Engagement_View)
8788
})
8889

8990

dojo/filters.py

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
from dojo.finding.queries import get_authorized_findings
3636
from dojo.endpoint.queries import get_authorized_endpoints
3737
from dojo.finding_group.queries import get_authorized_finding_groups
38+
from dojo.user.queries import get_authorized_users
3839
from django.forms import HiddenInput
3940
from dojo.utils import is_finding_groups_enabled
4041

@@ -592,10 +593,7 @@ def __init__(self, *args, **kwargs):
592593

593594
class EngagementDirectFilter(DojoFilter):
594595
name = CharFilter(lookup_expr='icontains', label='Engagement name contains')
595-
lead = ModelChoiceFilter(
596-
queryset=Dojo_User.objects.filter(
597-
engagement__lead__isnull=False).distinct(),
598-
label="Lead")
596+
lead = ModelChoiceFilter(queryset=Dojo_User.objects.none(), label="Lead")
599597
version = CharFilter(field_name='version', lookup_expr='icontains', label='Engagement version')
600598
test__version = CharFilter(field_name='test__version', lookup_expr='icontains', label='Test version')
601599

@@ -647,6 +645,8 @@ class EngagementDirectFilter(DojoFilter):
647645
def __init__(self, *args, **kwargs):
648646
super(EngagementDirectFilter, self).__init__(*args, **kwargs)
649647
self.form.fields['product__prod_type'].queryset = get_authorized_product_types(Permissions.Product_Type_View)
648+
self.form.fields['lead'].queryset = get_authorized_users(Permissions.Product_Type_View) \
649+
.filter(engagement__lead__isnull=False).distinct()
650650

651651
class Meta:
652652
model = Engagement
@@ -655,10 +655,7 @@ class Meta:
655655

656656
class EngagementFilter(DojoFilter):
657657
engagement__name = CharFilter(lookup_expr='icontains', label='Engagement name contains')
658-
engagement__lead = ModelChoiceFilter(
659-
queryset=Dojo_User.objects.filter(
660-
engagement__lead__isnull=False).distinct(),
661-
label="Lead")
658+
engagement__lead = ModelChoiceFilter(queryset=Dojo_User.objects.none(), label="Lead")
662659
engagement__version = CharFilter(field_name='engagement__version', lookup_expr='icontains', label='Engagement version')
663660
engagement__test__version = CharFilter(field_name='engagement__test__version', lookup_expr='icontains', label='Test version')
664661

@@ -704,17 +701,16 @@ class EngagementFilter(DojoFilter):
704701
def __init__(self, *args, **kwargs):
705702
super(EngagementFilter, self).__init__(*args, **kwargs)
706703
self.form.fields['prod_type'].queryset = get_authorized_product_types(Permissions.Product_Type_View)
704+
self.form.fields['engagement__lead'].queryset = get_authorized_users(Permissions.Product_Type_View) \
705+
.filter(engagement__lead__isnull=False).distinct()
707706

708707
class Meta:
709708
model = Product
710709
fields = ['name', 'prod_type']
711710

712711

713712
class ProductEngagementFilter(DojoFilter):
714-
lead = ModelChoiceFilter(
715-
queryset=Dojo_User.objects.filter(
716-
engagement__lead__isnull=False).distinct(),
717-
label="Lead")
713+
lead = ModelChoiceFilter(queryset=Dojo_User.objects.none(), label="Lead")
718714
version = CharFilter(lookup_expr='icontains', label='Engagement version')
719715
test__version = CharFilter(field_name='test__version', lookup_expr='icontains', label='Test version')
720716

@@ -760,9 +756,14 @@ class ProductEngagementFilter(DojoFilter):
760756

761757
)
762758

759+
def __init__(self, *args, **kwargs):
760+
super(ProductEngagementFilter, self).__init__(*args, **kwargs)
761+
self.form.fields['lead'].queryset = get_authorized_users(Permissions.Product_Type_View) \
762+
.filter(engagement__lead__isnull=False).distinct()
763+
763764
class Meta:
764765
model = Product
765-
fields = ['id', 'name']
766+
fields = ['name']
766767

767768

768769
class ApiEngagementFilter(DojoFilter):
@@ -1156,10 +1157,10 @@ class FindingFilter(FindingFilterWithTags):
11561157
payload = CharFilter(lookup_expr='icontains')
11571158

11581159
reporter = ModelMultipleChoiceFilter(
1159-
queryset=Dojo_User.objects.all())
1160+
queryset=Dojo_User.objects.none())
11601161

11611162
reviewers = ModelMultipleChoiceFilter(
1162-
queryset=Dojo_User.objects.all())
1163+
queryset=Dojo_User.objects.none())
11631164

11641165
test__engagement__product__prod_type = ModelMultipleChoiceFilter(
11651166
queryset=Product_Type.objects.none(),
@@ -1331,6 +1332,8 @@ def __init__(self, *args, **kwargs):
13311332
self.form.fields['finding_group'].queryset = get_authorized_finding_groups(Permissions.Finding_Group_View)
13321333
if self.form.fields.get('endpoints'):
13331334
self.form.fields['endpoints'].queryset = get_authorized_endpoints(Permissions.Endpoint_View).distinct()
1335+
self.form.fields['reporter'].queryset = get_authorized_users(Permissions.Finding_View)
1336+
self.form.fields['reviewers'].queryset = self.form.fields['reporter'].queryset
13341337

13351338

13361339
class AcceptedFindingFilter(FindingFilter):
@@ -1339,11 +1342,12 @@ class AcceptedFindingFilter(FindingFilter):
13391342

13401343
risk_acceptance__owner = \
13411344
ModelMultipleChoiceFilter(
1342-
queryset=Dojo_User.objects.all(),
1345+
queryset=Dojo_User.objects.none(),
13431346
label="Risk Acceptance Owner")
13441347

13451348
def __init__(self, *args, **kwargs):
13461349
super().__init__(*args, **kwargs)
1350+
self.form.fields['risk_acceptance__owner'].queryset = get_authorized_users(Permissions.Finding_View)
13471351

13481352

13491353
class SimilarFindingFilter(FindingFilter):
@@ -1741,10 +1745,7 @@ class Meta:
17411745

17421746

17431747
class EngagementTestFilter(DojoFilter):
1744-
lead = ModelChoiceFilter(
1745-
queryset=Dojo_User.objects.filter(
1746-
engagement__lead__isnull=False).distinct(),
1747-
label="Lead")
1748+
lead = ModelChoiceFilter(queryset=Dojo_User.objects.none(), label="Lead")
17481749
version = CharFilter(lookup_expr='icontains', label='Version')
17491750

17501751
if settings.TRACK_IMPORT_HISTORY:
@@ -1799,6 +1800,8 @@ def __init__(self, *args, **kwargs):
17991800
super(DojoFilter, self).__init__(*args, **kwargs)
18001801
self.form.fields['test_type'].queryset = Test_Type.objects.filter(test__engagement=self.engagement).distinct().order_by('name')
18011802
self.form.fields['api_scan_configuration'].queryset = Product_API_Scan_Configuration.objects.filter(product=self.engagement.product).distinct()
1803+
self.form.fields['lead'].queryset = get_authorized_users(Permissions.Product_Type_View) \
1804+
.filter(test__lead__isnull=False).distinct()
18021805

18031806

18041807
class ApiTestFilter(DojoFilter):
@@ -2080,13 +2083,17 @@ class LogEntryFilter(DojoFilter):
20802083
from auditlog.models import LogEntry
20812084

20822085
action = MultipleChoiceFilter(choices=LogEntry.Action.choices)
2083-
actor = ModelMultipleChoiceFilter(queryset=Dojo_User.objects.all())
2086+
actor = ModelMultipleChoiceFilter(queryset=Dojo_User.objects.none())
20842087
timestamp = DateRangeFilter()
20852088

2089+
def __init__(self, *args, **kwargs):
2090+
super(LogEntryFilter, self).__init__(*args, **kwargs)
2091+
self.form.fields['actor'].queryset = get_authorized_users(Permissions.Product_View)
2092+
20862093
class Meta:
20872094
model = LogEntry
20882095
exclude = ['content_type', 'object_pk', 'object_id', 'object_repr',
2089-
'changes', 'additional_data']
2096+
'changes', 'additional_data', 'remote_addr']
20902097

20912098

20922099
class ProductTypeFilter(DojoFilter):

dojo/forms.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
from dojo.product_type.queries import get_authorized_product_types
4646
from dojo.product.queries import get_authorized_products
4747
from dojo.finding.queries import get_authorized_findings
48-
from dojo.user.queries import get_authorized_users_for_product_and_product_type
48+
from dojo.user.queries import get_authorized_users_for_product_and_product_type, get_authorized_users
4949
from dojo.group.queries import get_authorized_groups, get_group_member_roles
5050

5151
logger = logging.getLogger(__name__)
@@ -761,7 +761,7 @@ def __init__(self, *args, **kwargs):
761761
self.fields['preset'] = forms.ModelChoiceField(help_text="Settings and notes for performing this engagement.", required=False, queryset=Engagement_Presets.objects.filter(product=product))
762762
self.fields['lead'].queryset = get_authorized_users_for_product_and_product_type(None, product, Permissions.Product_View).filter(is_active=True)
763763
else:
764-
self.fields['lead'].queryset = Dojo_User.objects.filter(is_active=True)
764+
self.fields['lead'].queryset = get_authorized_users(Permissions.Engagement_View).filter(is_active=True)
765765

766766
self.fields['product'].queryset = get_authorized_products(Permissions.Engagement_Add)
767767

@@ -812,7 +812,6 @@ class TestForm(forms.ModelForm):
812812
test_type = forms.ModelChoiceField(queryset=Test_Type.objects.all().order_by('name'))
813813
environment = forms.ModelChoiceField(
814814
queryset=Development_Environment.objects.all().order_by('name'))
815-
# credential = forms.ModelChoiceField(Cred_User.objects.all(), required=False)
816815
target_start = forms.DateTimeField(widget=forms.TextInput(
817816
attrs={'class': 'datepicker', 'autocomplete': 'off'}))
818817
target_end = forms.DateTimeField(widget=forms.TextInput(
@@ -838,7 +837,7 @@ def __init__(self, *args, **kwargs):
838837
self.fields['lead'].queryset = get_authorized_users_for_product_and_product_type(None, product, Permissions.Product_View).filter(is_active=True)
839838
self.fields['api_scan_configuration'].queryset = Product_API_Scan_Configuration.objects.filter(product=product)
840839
else:
841-
self.fields['lead'].queryset = User.objects.filter(is_active=True)
840+
self.fields['lead'].queryset = get_authorized_users(Permissions.Test_View).filter(is_active=True)
842841

843842
class Meta:
844843
model = Test
@@ -1129,7 +1128,7 @@ class FindingForm(forms.ModelForm):
11291128
references = forms.CharField(widget=forms.Textarea, required=False)
11301129

11311130
mitigated = SplitDateTimeField(required=False, help_text='Date and time when the flaw has been fixed')
1132-
mitigated_by = forms.ModelChoiceField(required=True, queryset=User.objects.all(), initial=get_current_user)
1131+
mitigated_by = forms.ModelChoiceField(required=True, queryset=get_authorized_users(Permissions.Finding_View), initial=get_current_user)
11331132

11341133
publish_date = forms.DateField(widget=forms.TextInput(attrs={'class': 'datepicker', 'autocomplete': 'off'}), required=False)
11351134

@@ -1580,7 +1579,7 @@ def __init__(self, *args, **kwargs):
15801579
finding = kwargs.pop('finding')
15811580

15821581
super(ReviewFindingForm, self).__init__(*args, **kwargs)
1583-
self.fields['reviewers'].choices = self._get_choices(Dojo_User.objects.filter(is_active=True))
1582+
self.fields['reviewers'].choices = self._get_choices(get_authorized_users(Permissions.Finding_View).filter(is_active=True))
15841583

15851584
if finding is not None:
15861585
queryset = get_authorized_users_for_product_and_product_type(None, finding.test.engagement.product, Permissions.Finding_Edit)
@@ -3167,7 +3166,7 @@ def __init__(self, *args, **kwargs):
31673166
assignee = kwargs.pop('asignees')
31683167
super(AssignUserForm, self).__init__(*args, **kwargs)
31693168
if assignee is None:
3170-
self.fields['assignee'] = forms.ModelChoiceField(queryset=Dojo_User.objects.all(), empty_label='Not Assigned', required=False)
3169+
self.fields['assignee'] = forms.ModelChoiceField(queryset=get_authorized_users(Permissions.Engagement_View), empty_label='Not Assigned', required=False)
31713170
else:
31723171
self.fields['assignee'].initial = assignee
31733172

dojo/static/dojo/css/dojo.css

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,18 @@ div.custom-search-form {
11531153
background-color: #f9f9f9;
11541154
}
11551155

1156+
#the-filters-open {
1157+
background-color: #f9f9f9;
1158+
}
1159+
1160+
#the-filters-paused {
1161+
background-color: #f9f9f9;
1162+
}
1163+
1164+
#the-filters-closed {
1165+
background-color: #f9f9f9;
1166+
}
1167+
11561168
.panel-default {
11571169
border: 1px solid #dddedf;
11581170
}

dojo/templates/dojo/action_history.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,14 @@
88
<div class="panel-heading tight">
99
<h3>
1010
{{ obj }} History
11+
<div class="dropdown pull-right">
12+
<button id="show-filters" data-toggle="collapse" data-target="#the-filters" class="btn btn-primary toggle-filters" aria-label="Filter"> <i class="fa fa-filter"></i> <i class="caret"></i> </button>
13+
</div>
1114
</h3>
1215
</div>
16+
<div id="the-filters" class="is-filters panel-body collapse {% if log_entry_filter.form.has_changed %}in{% endif %}">
17+
{% include "dojo/filter_snippet.html" with form=log_entry_filter.form %}
18+
</div>
1319
</div>
1420
{% if history %}
1521
<div class="clearfix">

dojo/templates/dojo/snippets/engagement_list.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
<div class="panel-heading">
77
<h4> {% if status == "open" %}Active{% elif status == "paused" %}Paused {% else %}Closed{% endif %} Engagements ({{ count }})
88
<div class="dropdown pull-right">
9+
<button id="show-filters-{{status}}" data-toggle="collapse" data-target="#the-filters-{{status}}" class="btn btn-primary toggle-filters" aria-label="Filter"> <i class="fa fa-filter"></i> <i class="caret"></i> </button>
910
<button class="btn btn-primary dropdown-toggle" type="button" id="dropdownMenu1" aria-label="Add Engagement"
1011
data-toggle="dropdown" aria-expanded="true">
1112
<span class="fa fa-bars"></span>

dojo/test/views.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
ReImportScanForm, JIRAFindingForm, JIRAImportScanForm, \
2828
FindingBulkUpdateForm
2929
from dojo.models import IMPORT_UNTOUCHED_FINDING, Finding, Finding_Group, Test, Note_Type, BurpRawRequestResponse, Endpoint, Stub_Finding, \
30-
Finding_Template, Cred_Mapping, Dojo_User, System_Settings, Test_Import, Product_API_Scan_Configuration, Test_Import_Finding_Action
30+
Finding_Template, Cred_Mapping, System_Settings, Test_Import, Product_API_Scan_Configuration, Test_Import_Finding_Action
3131

3232
from dojo.tools.factory import get_choices_sorted, get_scan_types_sorted
3333
from dojo.utils import add_error_message_to_response, add_field_errors_to_response, add_success_message_to_response, get_page_items, get_page_items_and_count, add_breadcrumb, get_cal_event, process_notifications, get_system_setting, \
@@ -43,6 +43,7 @@
4343
from dojo.authorization.authorization import user_has_permission_or_403
4444
from dojo.authorization.roles_permissions import Permissions
4545
from dojo.test.queries import get_authorized_tests
46+
from dojo.user.queries import get_authorized_users
4647
from dojo.importers.reimporter.reimporter import DojoDefaultReImporter as ReImporter
4748

4849

@@ -322,7 +323,7 @@ def test_calendar(request):
322323
'caltype': 'tests',
323324
'leads': request.GET.getlist('lead', ''),
324325
'tests': tests,
325-
'users': Dojo_User.objects.all()})
326+
'users': get_authorized_users(Permissions.Test_View)})
326327

327328

328329
@user_is_authorized(Test, Permissions.Test_View, 'tid')

0 commit comments

Comments
 (0)