Skip to content

Commit 38389b5

Browse files
Improve Google Sheets Sync feature (#1831)
1 parent 7903b7d commit 38389b5

File tree

4 files changed

+73
-6
lines changed

4 files changed

+73
-6
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 2.2.12 on 2020-04-08 16:09
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('dojo', '0035_push_all_issues_help_text_rename_gh_fields'),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name='system_settings',
15+
name='email_address',
16+
field=models.EmailField(blank=True, max_length=100),
17+
),
18+
]

dojo/forms.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2006,6 +2006,10 @@ class GoogleSheetFieldsForm(forms.Form):
20062006
required=True,
20072007
label="Google Drive folder ID",
20082008
help_text="Extract the Drive folder ID from the URL and provide it here")
2009+
email_address = forms.EmailField(
2010+
required=True,
2011+
label="Email Address",
2012+
help_text="Enter the same email Address used to create the Service Account")
20092013
enable_service = forms.BooleanField(
20102014
initial=False,
20112015
required=False,

dojo/google_sheet/views.py

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from django.core.exceptions import PermissionDenied
1717
from django.contrib.auth.decorators import user_passes_test
1818

19-
from dojo.models import Finding, System_Settings, Test, Dojo_User, Note_Type, NoteHistory, Notes
19+
from dojo.models import Finding, System_Settings, Test, Dojo_User, Note_Type, NoteHistory, Notes, Sonarqube_Issue
2020
from dojo.forms import GoogleSheetFieldsForm
2121
from dojo.utils import add_breadcrumb, Product_Tab
2222

@@ -39,6 +39,7 @@ def configure_google_sheets(request):
3939
else:
4040
initial['Protect ' + field.name] = True
4141
initial['drive_folder_ID'] = system_settings.drive_folder_ID
42+
initial['email_address'] = system_settings.email_address
4243
initial['enable_service'] = system_settings.enable_google_sheets
4344
form = GoogleSheetFieldsForm(all_fields=fields, initial=initial, credentials_required=False)
4445
else:
@@ -53,6 +54,7 @@ def configure_google_sheets(request):
5354
system_settings.column_widths = ""
5455
system_settings.credentials = ""
5556
system_settings.drive_folder_ID = ""
57+
system_settings.email_address = ""
5658
system_settings.enable_google_sheets = False
5759
system_settings.save()
5860
messages.add_message(
@@ -92,6 +94,7 @@ def configure_google_sheets(request):
9294
system_settings.column_widths = column_widths
9395
system_settings.credentials = cred_str
9496
system_settings.drive_folder_ID = drive_folder_ID
97+
system_settings.email_address = form.cleaned_data['email_address']
9598
system_settings.enable_google_sheets = form.cleaned_data['enable_service']
9699
system_settings.save()
97100
if initial:
@@ -261,9 +264,15 @@ def export_to_sheet(request, tid):
261264
except googleapiclient.errors.HttpError as error:
262265
error_message = 'There is a problem with the Google Sheets Sync Configuration. Contact your system admin to solve the issue.'
263266
return render(request, 'google_sheet_error.html', {'error_message': error_message})
267+
except Exception as e:
268+
error_message = e
269+
return render(request, 'google_sheet_error.html', {'error_message': error_message})
264270

265271

266272
def create_googlesheet(request, tid):
273+
user_email = request.user.email
274+
if not user_email:
275+
raise Exception('User must have an email address to use this feature.')
267276
test = Test.objects.get(id=tid)
268277
system_settings = get_object_or_404(System_Settings, id=1)
269278
service_account_info = json.loads(system_settings.credentials)
@@ -289,7 +298,7 @@ def create_googlesheet(request, tid):
289298
addParents=folder_id,
290299
removeParents=previous_parents,
291300
fields='id, parents').execute()
292-
user_email = request.user.email
301+
# Share created Spreadsheet with current user
293302
drive_service.permissions().create(body={'type': 'user', 'role': 'writer', 'emailAddress': user_email}, fileId=spreadsheetId).execute()
294303
populate_sheet(tid, spreadsheetId)
295304

@@ -311,7 +320,10 @@ def sync_findings(request, tid, spreadsheetId):
311320
sheet_names.append(date)
312321
except:
313322
pass
314-
sheet_title = str(max(sheet_names))
323+
try:
324+
sheet_title = str(max(sheet_names))
325+
except:
326+
raise Exception('Existing Google Spreadsheet has errors. Delete the speadsheet and export again.')
315327
res['sheet_title'] = sheet_title
316328

317329
result = sheets_service.spreadsheets().values().get(spreadsheetId=spreadsheetId, range=sheet_title).execute()
@@ -443,6 +455,7 @@ def populate_sheet(tid, spreadsheetId):
443455
system_settings = get_object_or_404(System_Settings, id=1)
444456
service_account_info = json.loads(system_settings.credentials)
445457
service_account_email = service_account_info['client_email']
458+
email_address = system_settings.email_address
446459
SCOPES = ['https://www.googleapis.com/auth/spreadsheets']
447460
credentials = service_account.Credentials.from_service_account_info(service_account_info, scopes=SCOPES)
448461
sheets_service = googleapiclient.discovery.build('sheets', 'v4', credentials=credentials, cache_discovery=False)
@@ -548,6 +561,7 @@ def populate_sheet(tid, spreadsheetId):
548561
"editors": {
549562
"users": [
550563
service_account_email,
564+
email_address
551565
]
552566
},
553567
# "description": "Protecting total row",
@@ -618,6 +632,7 @@ def populate_sheet(tid, spreadsheetId):
618632
"editors": {
619633
"users": [
620634
service_account_email,
635+
email_address
621636
]
622637
},
623638
"warningOnly": False
@@ -745,13 +760,14 @@ def populate_sheet(tid, spreadsheetId):
745760
"editors": {
746761
"users": [
747762
service_account_email,
763+
email_address
748764
]
749765
},
750766
"warningOnly": False
751767
}
752768
}
753769
})
754-
elif column_name[:6] == '[note]':
770+
elif column_name[:6] == '[note]' or column_name[:11] == '[duplicate]':
755771
body["requests"].append({
756772
"autoResizeDimensions": {
757773
"dimensions": {
@@ -767,6 +783,7 @@ def populate_sheet(tid, spreadsheetId):
767783

768784
def get_findings_list(tid):
769785
test = Test.objects.get(id=tid)
786+
system_settings = get_object_or_404(System_Settings, id=1)
770787
findings = Finding.objects.filter(test=test).order_by('numerical_severity')
771788
active_note_types = Note_Type.objects.filter(is_active=True).order_by('id')
772789
note_type_activation = active_note_types.count()
@@ -783,11 +800,15 @@ def get_findings_list(tid):
783800
for finding in findings:
784801
finding_details = []
785802
for field in fields:
786-
value = eval("finding." + field.name)
803+
value = getattr(finding, field.name)
787804
if type(value) == datetime.date or type(value) == Test or type(value) == datetime.datetime:
788-
var = str(eval("finding." + field.name))
805+
var = str(value)
789806
elif type(value) == User or type(value) == Dojo_User:
790807
var = value.username
808+
elif type(value) == Finding:
809+
var = value.id
810+
elif type(value) == Sonarqube_Issue:
811+
var = value.key
791812
else:
792813
var = value
793814
finding_details.append(var)
@@ -856,6 +877,29 @@ def get_findings_list(tid):
856877
for i in range(missing_notes_count):
857878
findings_list[f + 1].append('')
858879
findings_list[f + 1].append('')
880+
881+
if system_settings.enable_deduplication:
882+
if note_type_activation:
883+
for note_type in active_note_types:
884+
findings_list[0].append('[duplicate] ' + note_type.name)
885+
for f in range(findings.count()):
886+
original_finding = findings[f].duplicate_finding
887+
for note_type in active_note_types:
888+
try:
889+
note = original_finding.notes.filter(note_type=note_type).latest('date')
890+
findings_list[f + 1].append(note.entry)
891+
except:
892+
findings_list[f + 1].append('')
893+
else:
894+
findings_list[0].append('[duplicate] note')
895+
for f in range(findings.count()):
896+
original_finding = findings[f].duplicate_finding
897+
try:
898+
note = original_finding.notes.latest('date')
899+
findings_list[f + 1].append(note.entry)
900+
except:
901+
findings_list[f + 1].append('')
902+
859903
findings_list[0].append('Last column')
860904
for f in range(findings.count()):
861905
findings_list[f + 1].append('-')

dojo/models.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ class System_Settings(models.Model):
279279
column_widths = models.CharField(max_length=1500, blank=True)
280280
drive_folder_ID = models.CharField(max_length=100, blank=True)
281281
enable_google_sheets = models.BooleanField(default=False, null=True, blank=True)
282+
email_address = models.EmailField(max_length=100, blank=True)
282283

283284
objects = SystemSettingsManager()
284285

0 commit comments

Comments
 (0)