Skip to content

Commit f11d6c0

Browse files
Merge pull request #2567 from valentijnscholten/1.6.5-into-master
merge release/1.6.5 into master
2 parents 5c561d7 + 51cadfd commit f11d6c0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+630
-448
lines changed

docker/entrypoint-integration-tests.sh

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,14 @@ else
9191
echo "Error: Ibm AppScan integration test failed"; exit 1
9292
fi
9393

94-
echo "Running Smoke integration test"
95-
if python3 tests/smoke_test.py ; then
96-
echo "Success: Smoke integration tests passed"
97-
else
98-
echo "Error: Smoke integration test failed"; exit 1
99-
fi
94+
# all smoke tests are already covered by other testcases above/below
95+
# test="Smoke integration test"
96+
# echo "Running: $test"
97+
# if python3 tests/smoke_test.py ; then
98+
# success $test
99+
# else
100+
# fail $test
101+
# fi
100102

101103
echo "Running Check Status test"
102104
if python3 tests/check_status.py ; then

dojo/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# Django starts so that shared_task will use this app.
55
from .celery import app as celery_app # noqa
66

7-
__version__ = '1.6.2'
7+
__version__ = '1.6.5'
88
__url__ = 'https://github.com/DefectDojo/django-DefectDojo'
99
__docs__ = 'http://defectdojo.readthedocs.io/'
1010
__demo__ = 'http://defectdojo.pythonanywhere.com/'

dojo/finding/views.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,17 +1031,18 @@ def edit_finding(request, fid):
10311031
form.initial['tags'] = [tag.name for tag in finding.tags]
10321032
form_error = False
10331033
jform = None
1034-
enabled = False
1034+
jira_link_exists = False
1035+
push_all_issues_enabled = False
10351036

10361037
if get_system_setting('enable_jira') and finding.jira_conf_new() is not None:
1037-
enabled = finding.test.engagement.product.jira_pkey_set.first().push_all_issues
1038-
jform = JIRAFindingForm(enabled=enabled, prefix='jiraform')
1038+
push_all_issues_enabled = finding.test.engagement.product.jira_pkey_set.first().push_all_issues
1039+
jform = JIRAFindingForm(enabled=push_all_issues_enabled, prefix='jiraform')
10391040

10401041
try:
10411042
jissue = JIRA_Issue.objects.get(finding=finding)
1042-
enabled = True
1043+
jira_link_exists = True
10431044
except:
1044-
enabled = False
1045+
jira_link_exists = False
10451046

10461047
try:
10471048
gissue = GITHUB_Issue.objects.get(finding=finding)
@@ -1117,12 +1118,19 @@ def edit_finding(request, fid):
11171118

11181119
# Push to Jira?
11191120
push_to_jira = False
1120-
if enabled:
1121+
if push_all_issues_enabled:
11211122
push_to_jira = True
1123+
# elif 'jiraform-push_to_jira' in request.POST:
11221124
elif 'jiraform-push_to_jira' in request.POST:
1123-
jform = JIRAFindingForm(request.POST, prefix='jiraform', enabled=enabled)
1125+
jform = JIRAFindingForm(request.POST, prefix='jiraform', enabled=True)
11241126
if jform.is_valid():
1125-
push_to_jira = jform.cleaned_data.get('push_to_jira')
1127+
# If we get here, this means the box got checked.
1128+
# Currently, the jform is only 1 field, that checkbox.
1129+
# Even though its value is 'on' and therefore should be True, it always returns False.
1130+
# So putting a band-aid here to fix the issue.
1131+
# Someone more knowledgeable can fix it later.
1132+
# push_to_jira = jform.cleaned_data.get('push_to_jira')
1133+
push_to_jira = True
11261134

11271135
if 'githubform-push_to_github' in request.POST:
11281136
gform = GITHUBFindingForm(

dojo/github.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@ def add_external_issue_github(find, prod, eng):
109109
eng = Engagement.objects.get(test=find.test)
110110
prod = Product.objects.get(engagement=eng)
111111
github_product_key = GITHUB_PKey.objects.get(product=prod)
112-
github_conf = github_product_key.git_conf_id
113112
logger.info('Create issue with github profile: ' + str(github_conf) + ' on product: ' + str(github_product_key))
114113

115114
try:

dojo/github_issue_link/urls.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from . import views
33

44
urlpatterns = [
5-
url(r'^webhook', views.webhook, name='web_hook'),
5+
url(r'^github-webhook', views.webhook, name='github_web_hook'),
66
url(r'^github/add', views.new_github, name='add_github'),
77
url(r'^github/(?P<tid>\d+)/delete$', views.delete_github,
88
name='delete_github'),

dojo/jira_link/views.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def webhook(request):
3434

3535
if request.method == 'POST':
3636
parsed = json.loads(request.body.decode('utf-8'))
37-
if 'issue' in list(parsed.keys()):
37+
if parsed.get('webhookEvent') == 'jira:issue_updated':
3838
jid = parsed['issue']['id']
3939
jissue = get_object_or_404(JIRA_Issue, jira_id=jid)
4040
if jissue.finding is not None:
@@ -89,7 +89,7 @@ def webhook(request):
8989
eng.status = 'Completed'
9090
eng.save()
9191
"""
92-
else:
92+
if parsed.get('webhookEvent') == 'comment_created':
9393
comment_text = parsed['comment']['body']
9494
commentor = parsed['comment']['updateAuthor']['displayName']
9595
jid = parsed['comment']['self'].split('/')[7]
@@ -102,6 +102,9 @@ def webhook(request):
102102
finding.notes.add(new_note)
103103
finding.jira_change = timezone.now()
104104
finding.save()
105+
106+
if parsed.get('webhookEvent') not in ['comment_created', 'jira:issue_updated']:
107+
logger.info('Unrecognized JIRA webhook event received: {}'.format(parsed.get('webhookEvent')))
105108
return HttpResponse('')
106109

107110

dojo/models.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1570,7 +1570,11 @@ def remove_from_any_risk_acceptance(self):
15701570

15711571
def duplicate_finding_set(self):
15721572
if self.duplicate:
1573-
return Finding.objects.get(id=self.duplicate_finding.id).original_finding.all().order_by('title')
1573+
if self.duplicate_finding is not None:
1574+
return Finding.objects.get(
1575+
id=self.duplicate_finding.id).original_finding.all().order_by('title')
1576+
else:
1577+
return []
15741578
else:
15751579
return self.original_finding.all().order_by('title')
15761580

@@ -1729,7 +1733,6 @@ def jira_conf_new(self):
17291733
return self.test.engagement.product.jira_pkey_set.all()[0].conf
17301734
except:
17311735
return None
1732-
pass
17331736

17341737
def long_desc(self):
17351738
long_desc = ''
@@ -1747,10 +1750,10 @@ def long_desc(self):
17471750

17481751
for e in self.endpoints.all():
17491752
long_desc += str(e) + '\n\n'
1750-
long_desc += '*Description*: \n' + self.description + '\n\n'
1751-
long_desc += '*Mitigation*: \n' + self.mitigation + '\n\n'
1752-
long_desc += '*Impact*: \n' + self.impact + '\n\n'
1753-
long_desc += '*References*:' + self.references
1753+
long_desc += '*Description*: \n' + str(self.description) + '\n\n'
1754+
long_desc += '*Mitigation*: \n' + str(self.mitigation) + '\n\n'
1755+
long_desc += '*Impact*: \n' + str(self.impact) + '\n\n'
1756+
long_desc += '*References*:' + str(self.references)
17541757
return long_desc
17551758

17561759
def save(self, dedupe_option=True, false_history=False, rules_option=True,
@@ -1763,12 +1766,6 @@ def save(self, dedupe_option=True, false_history=False, rules_option=True,
17631766
self.jira_change = timezone.now()
17641767
if not jira_issue_exists:
17651768
self.jira_creation = timezone.now()
1766-
# If the product has "Push_all_issues" enabled,
1767-
# then we're pushing this to JIRA no matter what
1768-
if not push_to_jira:
1769-
# only if there is a JIRA configuration
1770-
push_to_jira = self.jira_conf_new() and \
1771-
self.jira_conf_new().jira_pkey_set.first().push_all_issues
17721769

17731770
if self.pk is None:
17741771
# We enter here during the first call from serializers.py
@@ -2890,6 +2887,7 @@ def enable_disable_auditlog(enable=True):
28902887
admin.site.register(System_Settings, System_SettingsAdmin)
28912888
admin.site.register(CWE)
28922889
admin.site.register(Regulation)
2890+
admin.site.register(Notifications)
28932891

28942892
# Watson
28952893
watson.register(Product)

dojo/notifications/helper.py

Lines changed: 71 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,28 @@
1010

1111

1212
def create_notification(event=None, *args, **kwargs):
13-
# System notifications
14-
try:
15-
system_notifications = Notifications.objects.get(user=None)
16-
except Exception:
17-
system_notifications = Notifications()
18-
19-
logger.debug('creating system notifications')
20-
process_notifications(event, system_notifications, *args, **kwargs)
2113

2214
if 'recipients' in kwargs:
23-
# mimic existing code so that when recipients is specified, no other personal notifications are sent.
15+
# mimic existing code so that when recipients is specified, no other system or personal notifications are sent.
2416
logger.debug('creating notifications for recipients')
25-
for recipient_notifications in Notifications.objects.filter(user__username__in=kwargs['recipients'], user__is_active=True):
17+
for recipient_notifications in Notifications.objects.filter(user__username__in=kwargs['recipients'], user__is_active=True, product=None):
2618
# kwargs.update({'user': recipient_notifications.user})
2719
process_notifications(event, recipient_notifications, *args, **kwargs)
2820
else:
21+
logger.debug('creating system notifications')
22+
# send system notifications to all admin users
23+
24+
# System notifications
25+
try:
26+
system_notifications = Notifications.objects.get(user=None)
27+
except Exception:
28+
system_notifications = Notifications()
29+
30+
admin_users = Dojo_User.objects.filter(is_staff=True)
31+
for admin_user in admin_users:
32+
system_notifications.user = admin_user
33+
process_notifications(event, system_notifications, *args, **kwargs)
34+
2935
# Personal but global notifications
3036
# only retrieve users which have at least one notification type enabled for this event type.
3137
logger.debug('creating personal notifications')
@@ -71,8 +77,8 @@ def create_notification_message(event, user, notification_type, *args, **kwargs)
7177
try:
7278
notification = render_to_string(template, kwargs)
7379
except Exception as e:
74-
logger.exception(e)
75-
create_description(event)
80+
logger.debug('template not found or not implemented yet: %s', template)
81+
create_description(event, *args, **kwargs)
7682
notification = render_to_string('notifications/other.tpl', kwargs)
7783

7884
return notification
@@ -87,9 +93,9 @@ def process_notifications(event, notifications=None, *args, **kwargs):
8793

8894
sync = 'initiator' in kwargs and hasattr(kwargs['initiator'], 'usercontactinfo') and kwargs['initiator'].usercontactinfo.block_execution
8995

90-
logger.debug('sync: %s', sync)
96+
logger.debug('sync: %s %s', sync, notifications.user)
9197
logger.debug('sending notifications ' + ('synchronously' if sync else 'asynchronously'))
92-
logger.debug(vars(notifications))
98+
# logger.debug(vars(notifications))
9399

94100
slack_enabled = get_system_setting('enable_slack_notifications')
95101
hipchat_enabled = get_system_setting('enable_hipchat_notifications')
@@ -115,7 +121,6 @@ def process_notifications(event, notifications=None, *args, **kwargs):
115121
else:
116122
send_mail_notification(event, notifications.user, *args, **kwargs)
117123

118-
print(getattr(notifications, event, None))
119124
if 'alert' in getattr(notifications, event, None):
120125
if not sync:
121126
send_alert_notification_task.delay(event, notifications.user, *args, **kwargs)
@@ -125,25 +130,25 @@ def process_notifications(event, notifications=None, *args, **kwargs):
125130

126131
def send_slack_notification(event, user=None, *args, **kwargs):
127132
from dojo.utils import get_system_setting, get_slack_user_id
128-
if user is not None:
129-
if hasattr(user, 'usercontactinfo') and user.usercontactinfo.slack_username is not None:
130-
slack_user_id = user.usercontactinfo.slack_user_id
131-
if user.usercontactinfo.slack_user_id is None:
132-
# Lookup the slack userid
133-
slack_user_id = get_slack_user_id(
134-
user.usercontactinfo.slack_username)
135-
slack_user_save = UserContactInfo.objects.get(user_id=user.id)
136-
slack_user_save.slack_user_id = slack_user_id
137-
slack_user_save.save()
138-
139-
channel = '@%s' % slack_user_id
133+
try:
134+
if user is not None:
135+
if hasattr(user, 'usercontactinfo') and user.usercontactinfo.slack_username is not None:
136+
slack_user_id = user.usercontactinfo.slack_user_id
137+
if user.usercontactinfo.slack_user_id is None:
138+
# Lookup the slack userid
139+
slack_user_id = get_slack_user_id(
140+
user.usercontactinfo.slack_username)
141+
slack_user_save = UserContactInfo.objects.get(user_id=user.id)
142+
slack_user_save.slack_user_id = slack_user_id
143+
slack_user_save.save()
144+
145+
channel = '@%s' % slack_user_id
146+
else:
147+
# user has no slack username, skip
148+
return
140149
else:
141-
# user has no slack username, skip
142-
return
143-
else:
144-
channel = get_system_setting('slack_channel')
150+
channel = get_system_setting('slack_channel')
145151

146-
try:
147152
res = requests.request(
148153
method='POST',
149154
url='https://slack.com/api/chat.postMessage',
@@ -161,11 +166,11 @@ def send_slack_notification(event, user=None, *args, **kwargs):
161166

162167
def send_hipchat_notification(event, user=None, *args, **kwargs):
163168
from dojo.utils import get_system_setting
164-
if user:
165-
# HipChat doesn't seem to offer direct message functionality, so no HipChat PM functionality here...
166-
return
167-
168169
try:
170+
if user:
171+
# HipChat doesn't seem to offer direct message functionality, so no HipChat PM functionality here...
172+
return
173+
169174
# We use same template for HipChat as for slack
170175
res = requests.request(
171176
method='POST',
@@ -185,16 +190,17 @@ def send_hipchat_notification(event, user=None, *args, **kwargs):
185190

186191
def send_mail_notification(event, user=None, *args, **kwargs):
187192
from dojo.utils import get_system_setting
193+
try:
188194

189-
if user:
190-
address = user.email
191-
else:
192-
address = get_system_setting('mail_notifications_to')
195+
if user:
196+
address = user.email
197+
else:
198+
address = get_system_setting('mail_notifications_to')
199+
200+
subject = '%s notification' % get_system_setting('team_name')
201+
if 'title' in kwargs:
202+
subject += ': %s' % kwargs['title']
193203

194-
subject = '%s notification' % get_system_setting('team_name')
195-
if 'title' in kwargs:
196-
subject += ': %s' % kwargs['title']
197-
try:
198204
email = EmailMessage(
199205
subject,
200206
create_notification_message(event, user, 'mail', *args, **kwargs),
@@ -214,18 +220,28 @@ def send_mail_notification(event, user=None, *args, **kwargs):
214220

215221

216222
def send_alert_notification(event, user=None, *args, **kwargs):
217-
icon = kwargs.get('icon', 'info-circle')
218-
alert = Alerts(
219-
user_id=user,
220-
title=kwargs.get('title'),
221-
description=create_notification_message(event, user, 'alert', *args, **kwargs),
222-
url=kwargs.get('url', reverse('alerts')),
223-
icon=icon,
224-
source=Notifications._meta.get_field(event).verbose_name.title())
225-
alert.save()
223+
print('sending alert notification')
224+
try:
225+
icon = kwargs.get('icon', 'info-circle')
226+
alert = Alerts(
227+
user_id=user,
228+
title=kwargs.get('title')[:100],
229+
description=create_notification_message(event, user, 'alert', *args, **kwargs),
230+
url=kwargs.get('url', reverse('alerts')),
231+
icon=icon[:25],
232+
source=Notifications._meta.get_field(event).verbose_name.title()[:100]
233+
)
234+
# relative urls will fail validation
235+
alert.clean_fields(exclude=['url'])
236+
alert.save()
237+
except Exception as e:
238+
logger.exception(e)
239+
log_alert(e, *args, **kwargs)
240+
pass
226241

227242

228243
def log_alert(e, *args, **kwargs):
244+
# no try catch here, if this fails we need to show an error
229245
users = Dojo_User.objects.filter(is_superuser=True)
230246
for user in users:
231247
alert = Alerts(
@@ -235,4 +251,6 @@ def log_alert(e, *args, **kwargs):
235251
description="%s" % e,
236252
icon="exclamation-triangle",
237253
source="Notifications")
254+
# relative urls will fail validation
255+
alert.clean_fields(exclude=['url'])
238256
alert.save()

0 commit comments

Comments
 (0)