aboutsummaryrefslogtreecommitdiffstats
path: root/lib/srtgui
diff options
context:
space:
mode:
Diffstat (limited to 'lib/srtgui')
-rw-r--r--lib/srtgui/api.py146
-rw-r--r--lib/srtgui/reports.py1326
-rw-r--r--lib/srtgui/tables.py861
-rw-r--r--lib/srtgui/templates/base.html32
-rw-r--r--lib/srtgui/templates/cpes-toastertable.html3
-rw-r--r--lib/srtgui/templates/cve.html713
-rw-r--r--lib/srtgui/templates/cves-select-toastertable.html14
-rw-r--r--lib/srtgui/templates/cves-toastertable.html14
-rw-r--r--lib/srtgui/templates/cwes-toastertable.html14
-rw-r--r--lib/srtgui/templates/defect.html86
-rw-r--r--lib/srtgui/templates/defects-toastertable.html14
-rw-r--r--lib/srtgui/templates/guided_tour.html8
-rw-r--r--lib/srtgui/templates/investigation.html439
-rw-r--r--lib/srtgui/templates/investigations-toastertable.html14
-rw-r--r--lib/srtgui/templates/landing.html10
-rw-r--r--lib/srtgui/templates/login.html40
-rw-r--r--lib/srtgui/templates/manage-cpes-toastertable.html14
-rw-r--r--lib/srtgui/templates/management.html14
-rw-r--r--lib/srtgui/templates/product.html84
-rw-r--r--lib/srtgui/templates/products-toastertable.html14
-rw-r--r--lib/srtgui/templates/publish-select-toastertable.html248
-rw-r--r--lib/srtgui/templates/publish.html33
-rw-r--r--lib/srtgui/templates/published-select-toastertable.html247
-rw-r--r--lib/srtgui/templates/report.html73
-rw-r--r--lib/srtgui/templates/sources-toastertable.html72
-rw-r--r--lib/srtgui/templates/triage_cves.html10
-rw-r--r--lib/srtgui/templates/users.html20
-rw-r--r--lib/srtgui/templates/vulnerabilities-toastertable.html17
-rw-r--r--lib/srtgui/templates/vulnerability.html604
-rw-r--r--lib/srtgui/templatetags/projecttags.py6
-rw-r--r--lib/srtgui/urls.py107
-rw-r--r--lib/srtgui/views.py790
-rw-r--r--lib/srtgui/widgets.py16
33 files changed, 5123 insertions, 980 deletions
diff --git a/lib/srtgui/api.py b/lib/srtgui/api.py
index b2c15b97..68aedb5d 100644
--- a/lib/srtgui/api.py
+++ b/lib/srtgui/api.py
@@ -1,7 +1,7 @@
#
# BitBake Toaster Implementation
#
-# Copyright (C) 2016 Intel Corporation
+# Copyright (C) 2016-2018 Intel Corporation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
@@ -24,13 +24,12 @@ import logging
import json
from collections import Counter
-from orm.models import Vulnerability
-
from django.http import HttpResponse, JsonResponse
from django.views.generic import View
from django.core.urlresolvers import reverse
from django.db.models import Q, F
from django.db import Error
+
from srtgui.templatetags.projecttags import filtered_filesizeformat
logger = logging.getLogger("srt")
@@ -40,3 +39,144 @@ def error_response(error):
return JsonResponse({"error": error})
+# quick development/debugging support
+def _log(msg):
+ DBG_LVL = os.environ['SRTDBG_LVL'] if ('SRTDBG_LVL' in os.environ) else 2
+ DBG_LOG = os.environ['SRTDBG_LOG'] if ('SRTDBG_LOG' in os.environ) else '/tmp/toaster.log'
+ if 1 == DBG_LVL:
+ print(msg)
+ elif 2 == DBG_LVL:
+ f1=open(DBG_LOG, 'a')
+ f1.write("|" + msg + "|\n" )
+ f1.close()
+
+
+## add os.makedirs(cache_path) just to be safe?
+def readCveDetails(cve):
+ from orm.models import CveDetail, DataSource
+ cve_name = cve.name
+ cve_datasource = cve.datasource
+
+ # Initialize and populate CveDetail object to return
+ v = CveDetail()
+ v.name = cve_name
+
+ # Fetch cached data, else extract data from datasource file
+ cache_path = os.path.join(os.environ['SRT_BASE_DIR'], "data/cache")
+ cve_path = os.path.join(cache_path, cve_name + ".json")
+
+ #check if in cache, and use if exists. Else fetch from appropriate CVE JSON feed file
+ if (os.path.isfile(cve_path)):
+ try:
+ f = open(cve_path, 'r')
+ CVE_Item = json.load(f)
+ except Exception as e:
+ _log("| error reading json file %s: %s |\n" % (cve_path,e,))
+ return v
+ else:
+ try:
+ SRT_BASE_DIR= os.environ['SRT_BASE_DIR']
+ f = open(os.path.join(SRT_BASE_DIR, cve_datasource.file_path), 'r')
+ source_dct = json.load(f)
+ for item in source_dct["CVE_Items"]:
+ if not 'cve' in item:
+ continue
+ if not 'CVE_data_meta' in item['cve']:
+ continue
+ if not 'ID' in item['cve']['CVE_data_meta']:
+ continue
+ if (item['cve']['CVE_data_meta']['ID'] == cve_name):
+ CVE_Item = item
+ cve_cache_file = open(os.path.join(SRT_BASE_DIR, "data", "cache", cve_name + ".json"), "w+") #write the cve to json file in cache
+ cve_cache_file.write(json.dumps(CVE_Item))
+ break
+ except Exception as e:
+ _log("| error reading json file: %s |\n" % os.path.join(SRT_BASE_DIR, cve_datasource.file_path) )
+ return v
+
+ #initialize and populate CveDetail object to return
+ v = CveDetail()
+ v.name = cve_name
+
+ if ('impact' in CVE_Item) and ('baseMetricV3' in CVE_Item['impact']):
+ baseMetricV3 = CVE_Item['impact']['baseMetricV3']
+ v.cvssV3_baseScore = baseMetricV3['cvssV3']['baseScore']
+ v.cvssV3_baseSeverity = baseMetricV3['cvssV3']['baseSeverity']
+ v.cvssV3_vectorString = baseMetricV3['cvssV3']['vectorString']
+ v.cvssV3_exploitabilityScore = baseMetricV3['exploitabilityScore']
+ v.cvssV3_impactScore = baseMetricV3['impactScore']
+ v.cvssV3_attackVector = baseMetricV3['cvssV3']['attackVector']
+ v.cvssV3_attackComplexity = baseMetricV3['cvssV3']['attackComplexity']
+ v.cvssV3_privilegesRequired = baseMetricV3['cvssV3']['privilegesRequired']
+ v.cvssV3_userInteraction = baseMetricV3['cvssV3']['userInteraction']
+ v.cvssV3_scope = baseMetricV3['cvssV3']['scope']
+ v.cvssV3_confidentialityImpact = baseMetricV3['cvssV3']['confidentialityImpact']
+ v.cvssV3_integrityImpact = baseMetricV3['cvssV3']['integrityImpact']
+ v.cvssV3_availabilityImpact = baseMetricV3['cvssV3']['availabilityImpact']
+ if ('impact' in CVE_Item) and ('baseMetricV2' in CVE_Item['impact']):
+ baseMetricV2 = CVE_Item['impact']['baseMetricV2']
+ v.cvssV2_baseScore = baseMetricV2['cvssV2']['baseScore']
+ v.cvssV2_severity = baseMetricV2['severity']
+ v.cvssV2_vectorString = baseMetricV2['cvssV2']['vectorString']
+ v.cvssV2_exploitabilityScore = baseMetricV2['exploitabilityScore']
+ v.cvssV2_impactScore = baseMetricV2['exploitabilityScore']
+ v.cvssV2_accessVector = baseMetricV2['cvssV2']['accessVector']
+ v.cvssV2_accessComplexity = baseMetricV2['cvssV2']['accessComplexity']
+ v.cvssV2_authentication = baseMetricV2['cvssV2']['authentication']
+ v.cvssV2_confidentialityImpact = baseMetricV2['cvssV2']['confidentialityImpact']
+ v.cvssV2_integrityImpact = baseMetricV2['cvssV2']['integrityImpact']
+
+ configurations = CVE_Item['configurations']
+ is_first_and = True
+ for i, config in enumerate(configurations['nodes']):
+ v.cpe_list += '[config]|'
+ v.cpe_list += '[and]|'
+ if "AND" == config['operator']:
+ # create AND record
+ if not is_first_and:
+ v.cpe_list += '[/and]|'
+ v.cpe_list += '[and]|'
+ #is_first_and = False
+ if 'children' in config:
+ for j, cpe_or_node in enumerate(config['children']):
+ if "OR" == cpe_or_node['operator']:
+ v.cpe_list += nist_scan_configuration_or(v,cpe_or_node, cve_name, j)
+ else:
+ print("ERROR CONFIGURE:OR_OP?:%s" % cpe_or_node['operator'])
+ elif "OR" == config['operator']:
+ v.cpe_list += nist_scan_configuration_or(v,config, cve_name, 0)
+ else:
+ print("ERROR CONFIGURE:OP?:%s" % config_rec['operator'])
+ v.cpe_list += '[/and]|'
+ v.cpe_list += '[/config]|'
+
+ return v
+
+def nist_scan_configuration_or(cve, cpe_or_node, name, and_enum):
+ cpe_list = '[or]|'
+ for cpe in cpe_or_node['cpe']:
+ cpe23Uri = cpe['cpe23Uri']
+ if 'cpeMatchString' in cpe:
+ cpeMatchString = cpe['cpeMatchString']
+ else:
+ cpeMatchString = ''
+ if 'versionEndIncluding' in cpe:
+ versionEndIncluding = cpe['versionEndIncluding']
+ else:
+ versionEndIncluding = ''
+ cpe_list += '%s,%s,%s,%s|' % (cpe['vulnerable'],cpe23Uri,cpeMatchString,versionEndIncluding)
+ cpe_list += '[/or]|'
+ return cpe_list
+
+def saveCveToCache(cve):
+ #Encode cve to json and save into cache
+ path = os.path.join(os.environ['SRT_BASE_DIR'], "data/cache")
+ # Catch the post against this page
+ try:
+ os.makedirs(path)
+ except:
+ pass
+
+ cve_name = cve['CVE_data_meta']['ID']
+ file = open(os.path.join(path, cve_name + ".json" ), 'w+')
+ file.write(json.dumps(cve))
diff --git a/lib/srtgui/reports.py b/lib/srtgui/reports.py
new file mode 100644
index 00000000..f27beb34
--- /dev/null
+++ b/lib/srtgui/reports.py
@@ -0,0 +1,1326 @@
+#
+# Security Response Tool Implementation
+#
+# Copyright (C) 2017-2018 Wind River Systems
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+# Please run flake8 on this file before sending patches
+
+import os
+import re
+import logging
+import json
+from collections import Counter
+from datetime import datetime, date
+
+from orm.models import Cve, Vulnerability, Investigation, Defect, Product
+from orm.models import SrtSetting, Access, Keywords
+
+from django.db.models import Q, F
+from django.db import Error
+from srtgui.templatetags.projecttags import filtered_filesizeformat
+
+logger = logging.getLogger("srt")
+
+SRT_BASE_DIR = os.environ['SRT_BASE_DIR']
+SRT_REPORT_DIR = '%s/reports' % SRT_BASE_DIR
+
+# quick development/debugging support
+from srtgui.api import _log
+
+def _log_args(msg, *args, **kwargs):
+ s = '%s:(' % msg
+ if args:
+ for a in args:
+ s += '%s,' % a
+ s += '),('
+ if kwargs:
+ for key, value in kwargs.items():
+ s += '(%s=%s),' % (key,value)
+ s += ')'
+ _log(s)
+
+class Report():
+ def __init__(self, parent_page, *args, **kwargs):
+ self.parent_page = parent_page
+ self.report_name = '%s%s' % (parent_page[0].upper(),parent_page[1:])
+ self.title = self.report_name
+ self.request = kwargs['request']
+
+ def get_context_data(self, *args, **kwargs):
+ context = {}
+ context['title'] = self.title
+ context['parent_page'] = self.parent_page
+ context['report_name'] = self.report_name
+ context['report_enable_submit'] = '1'
+ # global variables
+ context['access'] = Access(int(self.request.session.get('srt_user_id', '0')))
+
+ return context
+
+ def exec_report(self, *args, **kwargs):
+ return None
+
+
+class ManagementReport(Report):
+ """Report for the Management Page"""
+
+ def __init__(self, parent_page, *args, **kwargs):
+ _log_args("REPORT_MANAGEMENT_INIT(%s)" % parent_page, *args, **kwargs)
+ super(ManagementReport, self).__init__(parent_page, *args, **kwargs)
+
+ def get_context_data(self, *args, **kwargs):
+ _log_args("REPORT_MANAGEMENT_CONTEXT", *args, **kwargs)
+ context = super(ManagementReport, self).get_context_data(*args, **kwargs)
+
+ context['report_type_list'] = '\
+ <option value="status">Overall Status</option> \
+ <option value="vulnerabilities">Open Vulnerabilities</option> \
+ <option value="investigations">Open Investigations</option> \
+ '
+ context['report_get_title'] = '1'
+ context['report_recordrange_list'] = '\
+ <input type="radio" name="records" value="selected" checked> Selected<br> \
+ '
+ context['report_columnrange_list'] = ''
+ context['report_format_list'] = '\
+ <input type="radio" name="format" value="txt" checked> Text<br> \
+ <input type="radio" name="format" value="csv"> CSV<br> \
+ '
+ return context
+
+ def exec_report(self, *args, **kwargs):
+ _log_args("REPORT_MANAGEMENT_EXEC", *args, **kwargs)
+ super(ManagementReport, self).exec_report(*args, **kwargs)
+
+ request_POST = self.request.POST
+
+ records = request_POST.get('records', '')
+ format = request_POST.get('format', '')
+ title = request_POST.get('title', '')
+ report_type = request_POST.get('report_type', '')
+
+ report_name = '%s/management_%s_%s.%s' % (SRT_REPORT_DIR,report_type,datetime.today().strftime('%Y%m%d%H%M'),format)
+ with open(report_name, 'w') as file:
+
+ if 'csv' == format:
+ tab = "\t"
+ else:
+ tab = " = "
+
+ if 'status' == report_type:
+ if 'txt' == format:
+ file.write("Report : Management - Summary\n")
+ file.write("\n")
+ file.write("%s%s%s\n" % ('cve_total',tab,Cve.objects.all().count()))
+ file.write("%s%s%s\n" % ('cve_new',tab,Cve.objects.filter(status=Cve.NEW).count()))
+ file.write("%s%s%s\n" % ('cve_open',tab,Cve.objects.filter( Q(status=Cve.INVESTIGATE) & Q(status=Cve.VULNERABLE) ).count()))
+ file.write("%s%s%s\n" % ('vulnerability_total',tab,Vulnerability.objects.all().count()))
+ file.write("%s%s%s\n" % ('vulnerability_open',tab,Vulnerability.objects.filter(outcome=Vulnerability.OPEN).count()))
+ file.write("%s%s%s\n" % ('vulnerability_high',tab,Vulnerability.objects.filter(severity=Vulnerability.HIGH).count()))
+ file.write("%s%s%s\n" % ('vulnerability_medium',tab,Vulnerability.objects.filter(severity=Vulnerability.MEDIUM).count()))
+ file.write("%s%s%s\n" % ('vulnerability_low',tab,Vulnerability.objects.filter(severity=Vulnerability.HIGH).count()))
+ file.write("%s%s%s\n" % ('investigation_total',tab,Investigation.objects.all().count()))
+ file.write("%s%s%s\n" % ('investigation_open',tab,Investigation.objects.filter(outcome=Investigation.OPEN).count()))
+ file.write("%s%s%s\n" % ('investigation_high',tab,Investigation.objects.filter(severity=Investigation.HIGH).count()))
+ file.write("%s%s%s\n" % ('investigation_medium',tab,Investigation.objects.filter(severity=Investigation.MEDIUM).count()))
+ file.write("%s%s%s\n" % ('investigation_low',tab,Investigation.objects.filter(severity=Investigation.LOW).count()))
+ file.write("%s%s%s\n" % ('defect_total',tab,Defect.objects.all().count()))
+
+ if 'vulnerabilities' == report_type:
+ if 'txt' == format:
+ file.write("Report : Management - Open Vulnerabilities\n")
+ file.write("\n")
+ else:
+ file.write("Name\tStatus\tOutcome\tSeverity\tComments\tCVEs\tInvestigations\n")
+ for v in Vulnerability.objects.filter(outcome=Vulnerability.OPEN):
+ if 'txt' == format:
+ file.write("Name: %s\n" % v.name)
+ file.write(" Status: %s\n" % v.get_status_text)
+ file.write(" Outcome: %s\n" % v.get_outcome_text)
+ file.write(" Severity: %s\n" % v.get_severity_text)
+ file.write(" Comments: %s\n" % v.comments)
+ file.write(" CVEs: ")
+ for i,vc in enumerate(v.vulnerability_to_cve.all()):
+ if i > 0:
+ file.write(",")
+ file.write("%s" % vc.cve.name)
+ file.write("\n")
+ file.write(" Investigations: ")
+ for i,investigation in enumerate(Investigation.objects.filter(vulnerability=v)):
+ if i > 0:
+ file.write(",")
+ file.write("%s" % investigation.name)
+ file.write("\n")
+ file.write("\n")
+ else:
+ file.write("%s\t%s\t%s\t%s\t%s\t" % (v.name,v.get_status_text,v.get_outcome_text,v.get_severity_text,v.comments))
+ for i,vc in enumerate(v.vulnerability_to_cve.all()):
+ if i > 0:
+ file.write(",")
+ file.write("%s" % vc.cve.name)
+ file.write("\t")
+ for i,investigation in enumerate(Investigation.objects.filter(vulnerability=v)):
+ if i > 0:
+ file.write(",")
+ file.write("%s" % investigation.name)
+ file.write("\n")
+
+ if 'investigations' == report_type:
+ if 'txt' == format:
+ file.write("Report : Management - Open Vulnerabilities\n")
+ file.write("\n")
+ else:
+ file.write("Name\tStatus\tOutcome\tSeverity\tComments\tDefects\n")
+ for investigation in Investigation.objects.filter(outcome=Vulnerability.OPEN):
+ if 'txt' == format:
+ file.write("Name: %s\n" % investigation.name)
+ file.write(" Status: %s\n" % investigation.get_status_text)
+ file.write(" Outcome: %s\n" % investigation.get_outcome_text)
+ file.write(" Severity: %s\n" % investigation.get_severity_text)
+ file.write(" Comments: %s\n" % investigation.comments)
+ file.write(" Defects: ")
+ for i,id in enumerate(investigation.investigation_to_defect.filter(investigation=investigation)):
+ if i > 0:
+ file.write(",")
+ file.write("%s" % id.defect.name)
+ file.write("\n")
+ file.write("\n")
+ else:
+ file.write("%s\t%s\t%s\t%s\t%s\t" % (investigation.name,investigation.get_status_text,
+ investigation.get_outcome_text,investigation.get_severity_text,investigation.comments))
+ for i,id in enumerate(investigation.investigation_to_defect.filter(investigation=investigation)):
+ if i > 0:
+ file.write(",")
+ file.write("%s" % id.defect.name)
+ file.write("\n")
+
+ return report_name,os.path.basename(report_name)
+
+class CveReport(Report):
+ """Report for the CVE Page"""
+
+ def __init__(self, parent_page, *args, **kwargs):
+ _log_args("REPORT_CVE_INIT(%s)" % parent_page, *args, **kwargs)
+ super(CveReport, self).__init__(parent_page, *args, **kwargs)
+
+ def get_context_data(self, *args, **kwargs):
+ _log_args("REPORT_CVE_CONTEXT", *args, **kwargs)
+ context = super(CveReport, self).get_context_data(*args, **kwargs)
+
+ context['report_type_list'] = '\
+ <option value="summary">CVE Summary</option> \
+ <option value="audit">CVE Audit</option> \
+ '
+ context['report_get_title'] = '1'
+ context['report_recordrange_list'] = '\
+ <input type="radio" name="records" value="selected" checked> Selected<br> \
+ '
+ context['report_columnrange_list'] = ''
+ context['report_format_list'] = '\
+ <input type="radio" name="format" value="txt" checked> Text<br> \
+ '
+ context['report_custom_list'] = '\
+ <input type="checkbox" class="checkbox-options" name="cvss_v2" value="cvss_v2"> CVSS_v2<br> \
+ <input type="checkbox" class="checkbox-options" name="ref" type="ref"> References<br> \
+ <input type="checkbox" class="checkbox-options" name="cpe" type="cpe"> CPE list<br> \
+ '
+ return context
+
+ def exec_report(self, *args, **kwargs):
+ _log_args("REPORT_CVE_EXEC", *args, **kwargs)
+ super(CveReport, self).exec_report(*args, **kwargs)
+
+ request_POST = self.request.POST
+
+ records = request_POST.get('records', '')
+ format = request_POST.get('format', '')
+ title = request_POST.get('title', '')
+ report_type = request_POST.get('report_type', '')
+ record_list = request_POST.get('record_list', '')
+
+ cvss_v2 = request_POST.get('cvss_v2', '')
+ ref_list = request_POST.get('ref', '')
+ cpe = request_POST.get('cpe', '')
+
+ cve = Cve.objects.get(id=record_list)
+
+ report_name = '%s/cve_%s_%s.%s' % (SRT_REPORT_DIR,report_type,datetime.today().strftime('%Y%m%d%H%M'),format)
+ with open(report_name, 'w') as file:
+
+ if 'csv' == format:
+ tab = "\t"
+ else:
+ tab = " = "
+
+ if ('summary' == report_type) or ('audit' == report_type):
+ if 'txt' == format:
+ file.write("Report : CVE %s - Summary\n" % cve.name)
+ file.write("\n")
+ file.write("%s%s%s\n" % ('source',tab,cve.source))
+ file.write("%s%s%s\n" % ('status',tab,cve.status))
+ file.write("%s%s%s\n" % ('cve_data_type',tab,cve.cve_data_type))
+ file.write("%s%s%s\n" % ('cve_data_format',tab,cve.cve_data_format))
+ file.write("%s%s%s\n" % ('cve_data_version',tab,cve.cve_data_version))
+ file.write("%s%s%s\n" % ('description',tab,cve.description))
+ file.write("\n")
+
+ file.write("CVSS Version 3:\n")
+ file.write(" %s%s%s\n" % ('cvssV3_baseScore',tab,cve.cvssV3_baseScore))
+ file.write(" %s%s%s\n" % ('cvssV3_baseSeverity',tab,cve.cvssV3_baseSeverity))
+ file.write(" %s%s%s\n" % ('cvssV3_vectorString',tab,cve.cvssV3_vectorString))
+ file.write(" %s%s%s\n" % ('cvssV3_exploitabilityScore',tab,cve.cvssV3_exploitabilityScore))
+ file.write(" %s%s%s\n" % ('cvssV3_impactScore',tab,cve.cvssV3_impactScore))
+ file.write(" %s%s%s\n" % ('cvssV3_attackVector',tab,cve.cvssV3_attackVector))
+ file.write(" %s%s%s\n" % ('cvssV3_attackComplexity',tab,cve.cvssV3_attackComplexity))
+ file.write(" %s%s%s\n" % ('cvssV3_privilegesRequired',tab,cve.cvssV3_privilegesRequired))
+ file.write(" %s%s%s\n" % ('cvssV3_userInteraction',tab,cve.cvssV3_userInteraction))
+ file.write(" %s%s%s\n" % ('cvssV3_scope',tab,cve.cvssV3_scope))
+ file.write(" %s%s%s\n" % ('cvssV3_confidentialityImpact',tab,cve.cvssV3_confidentialityImpact))
+ file.write(" %s%s%s\n" % ('cvssV3_integrityImpact',tab,cve.cvssV3_integrityImpact))
+ file.write(" %s%s%s\n" % ('cvssV3_availabilityImpact',tab,cve.cvssV3_availabilityImpact))
+
+ if (cvss_v2):
+ file.write("\n")
+ file.write("CVSS Version 2:\n")
+ file.write(" %s%s%s\n" % ('cvssV2_baseScore',tab,cve.cvssV2_baseScore))
+ file.write(" %s%s%s\n" % ('cvssV2_severity',tab,cve.cvssV2_severity))
+ file.write(" %s%s%s\n" % ('cvssV2_vectorString',tab,cve.cvssV2_vectorString))
+ file.write(" %s%s%s\n" % ('cvssV2_exploitabilityScore',tab,cve.cvssV2_exploitabilityScore))
+ file.write(" %s%s%s\n" % ('cvssV2_impactScore',tab,cve.cvssV2_impactScore))
+ file.write(" %s%s%s\n" % ('cvssV2_accessVector',tab,cve.cvssV2_accessVector))
+ file.write(" %s%s%s\n" % ('cvssV2_accessComplexity',tab,cve.cvssV2_accessComplexity))
+ file.write(" %s%s%s\n" % ('cvssV2_authentication',tab,cve.cvssV2_authentication))
+ file.write(" %s%s%s\n" % ('cvssV2_confidentialityImpact',tab,cve.cvssV2_confidentialityImpact))
+ file.write(" %s%s%s\n" % ('cvssV2_integrityImpact',tab,cve.cvssV2_integrityImpact))
+
+ if (ref_list):
+ file.write("\n")
+ file.write("References:\n")
+ for i,ref in enumerate(cve.references.all()):
+ file.write(" %s\n" % ref.hyperlink)
+
+ if (cpe):
+ file.write("\n")
+ file.write("CPE Table:\n")
+ for cpe in cve.cpe_list.split("|"):
+ if '<config>' == cpe:
+ file.write(" Configation:\n")
+ elif '<and>' == cpe:
+ file.write(" * AND\n")
+ elif '<or>' == cpe:
+ file.write(" * OR\n")
+ else :
+ file.write(" %s\n" % cpe)
+
+ if 'audit' == report_type:
+
+ for cv in cve.cve_to_vulnerability.all():
+ v = cv.vulnerability
+ file.write("\n")
+ file.write("-------------------------------------------\n")
+ file.write("Vulnerability: %s\n" % v.name)
+ file.write(" Status: %s\n" % v.get_status_text)
+ file.write(" Outcome: %s\n" % v.get_outcome_text)
+ file.write(" Severity: %s\n" % v.get_severity_text)
+ file.write(" Comments: %s\n" % v.comments)
+ file.write("\n")
+ file.write(" Investigations:\n")
+ for investigation in Investigation.objects.filter(vulnerability=v):
+ file.write(" Name: %s\n" % investigation.name)
+ file.write(" Status: %s\n" % investigation.get_status_text)
+ file.write(" Outcome: %s\n" % investigation.get_outcome_text)
+ file.write(" Severity: %s\n" % investigation.get_severity_text)
+ file.write(" Defects: ")
+ for i,id in enumerate(investigation.investigation_to_defect.all()):
+ if i > 0:
+ file.write(",")
+ file.write("%s (%s)" % (id.defect.name,id.defect.get_status_text))
+ file.write("\n")
+
+ file.write("\n")
+ file.write(" Comments:\n")
+ for i,vc in enumerate(v.vulnerability_comments.all()):
+ file.write(" %s (%s): %s\n" % (vc.date,vc.author,vc.comment))
+
+ file.write("\n")
+ file.write(" Audit Trail:\n")
+ for i,vh in enumerate(v.vulnerability_history.all()):
+ file.write(" %s (%s): %s\n" % (vh.date,vh.author,vh.comment))
+
+ file.write("\n")
+ else:
+ file.write("Investigations: no attached investigations as this time\n")
+
+ return report_name,os.path.basename(report_name)
+
+class VulnerabilityReport(Report):
+ """Report for the Vulnerability Page"""
+
+ def __init__(self, parent_page, *args, **kwargs):
+ _log_args("REPORT_VULNERABILITY_INIT(%s)" % parent_page, *args, **kwargs)
+ super(VulnerabilityReport, self).__init__(parent_page, *args, **kwargs)
+
+ def get_context_data(self, *args, **kwargs):
+ _log_args("REPORT_VULNERABILITY_CONTEXT", *args, **kwargs)
+ context = super(VulnerabilityReport, self).get_context_data(*args, **kwargs)
+
+ context['report_type_list'] = '\
+ <option value="summary">Vulnerability Summary</option> \
+ <option value="audit">Vulnerability Audit</option> \
+ '
+ context['report_get_title'] = '1'
+ context['report_recordrange_list'] = '\
+ <input type="radio" name="records" value="selected" checked> Selected<br> \
+ '
+ context['report_columnrange_list'] = ''
+ context['report_format_list'] = '\
+ <input type="radio" name="format" value="txt" checked> Text<br> \
+ '
+ return context
+
+ def exec_report(self, *args, **kwargs):
+ _log_args("REPORT_VULNERABILITY_EXEC", *args, **kwargs)
+ super(VulnerabilityReport, self).exec_report(*args, **kwargs)
+
+ request_POST = self.request.POST
+
+ records = request_POST.get('records', '')
+ format = request_POST.get('format', '')
+ title = request_POST.get('title', '')
+ report_type = request_POST.get('report_type', '')
+ record_list = request_POST.get('record_list', '')
+
+ v = Vulnerability.objects.get(id=record_list)
+
+ report_name = '%s/vulnerability_%s_%s.%s' % (SRT_REPORT_DIR,report_type,datetime.today().strftime('%Y%m%d%H%M'),format)
+ with open(report_name, 'w') as file:
+
+ if 'csv' == format:
+ tab = "\t"
+ else:
+ tab = " = "
+
+ if ('summary' == report_type) or ('audit' == report_type):
+ if 'txt' == format:
+ file.write("Report : Vulnerability %s - Summary\n" % v.name)
+ file.write("\n")
+
+ file.write("Vulnerability: %s\n" % v.name)
+ file.write(" Status: %s\n" % v.get_status_text)
+ file.write(" Outcome: %s\n" % v.get_outcome_text)
+ file.write(" Severity: %s\n" % v.get_severity_text)
+ file.write(" Comments: %s\n" % v.comments)
+
+ file.write("\n")
+ file.write("Affected Products:\n")
+ found_p = False
+ for i,p in enumerate(v.get_affected_list):
+ found_p = True
+ file.write("%2d) Product: %s\n" % (i,p.product.long_name))
+ found_i = False
+ for investigation in Investigation.objects.filter(vulnerability=v,product=p.product):
+ found_i = True
+ file.write(" Investigation: %s\n" % investigation.name)
+ file.write(" Status: %s\n" % investigation.get_status_text)
+ file.write(" Outcome: %s\n" % investigation.get_outcome_text)
+ file.write(" Severity: %s\n" % investigation.get_severity_text)
+ file.write(" Defects: ")
+ for j,id in enumerate(investigation.investigation_to_defect.all()):
+ if j > 0:
+ file.write(",")
+ file.write("%s (%s)" % (id.defect.name,id.defect.get_status_text))
+ file.write("\n")
+ if not found_i:
+ file.write(" No investigations found\n")
+ if not found_p:
+ file.write(" No affected products found\n")
+
+ file.write("\n")
+ file.write("Related Products:\n")
+ found_p = False
+ for i,p in enumerate(v.get_related_list):
+ found_p = True
+ file.write("%2d) Product: %s\n" % (i,p.product.long_name))
+ if not found_p:
+ file.write(" No related products found\n")
+
+ file.write("\n")
+ file.write("Comments:\n")
+ found_c = False
+ for i,vc in enumerate(v.vulnerability_comments.all()):
+ found_c = True
+ file.write(" %2d) %s (%s): %s\n" % (i,vc.date,vc.author,vc.comment))
+ if not found_c:
+ file.write(" No comments found\n")
+
+ if 'audit' == report_type:
+ file.write("\n")
+ file.write("Audit Trail:\n")
+ for i,vh in enumerate(v.vulnerability_history.all()):
+ file.write(" %2d) %s (%s): %s\n" % (i,vh.date,vh.author,vh.comment))
+
+ file.write("\n")
+
+ return report_name,os.path.basename(report_name)
+
+class InvestigationReport(Report):
+ """Report for the Investigation Page"""
+
+ def __init__(self, parent_page, *args, **kwargs):
+ _log_args("REPORT_INVESTIGATION_INIT(%s)" % parent_page, *args, **kwargs)
+ super(InvestigationReport, self).__init__(parent_page, *args, **kwargs)
+
+ def get_context_data(self, *args, **kwargs):
+ _log_args("REPORT_INVESTIGATION_CONTEXT", *args, **kwargs)
+ context = super(InvestigationReport, self).get_context_data(*args, **kwargs)
+
+ context['report_type_list'] = '\
+ <option value="summary">Investigation Summary</option> \
+ <option value="audit">Investigation Audit</option> \
+ '
+ context['report_get_title'] = '1'
+ context['report_recordrange_list'] = '\
+ <input type="radio" name="records" value="selected" checked> Selected<br> \
+ '
+ context['report_columnrange_list'] = ''
+ context['report_format_list'] = '\
+ <input type="radio" name="format" value="txt" checked> Text<br> \
+ '
+ return context
+
+ def exec_report(self, *args, **kwargs):
+ _log_args("REPORT_INVESTIGATION_EXEC", *args, **kwargs)
+ super(InvestigationReport, self).exec_report(*args, **kwargs)
+
+ request_POST = self.request.POST
+
+ records = request_POST.get('records', '')
+ format = request_POST.get('format', '')
+ title = request_POST.get('title', '')
+ report_type = request_POST.get('report_type', '')
+ record_list = request_POST.get('record_list', '')
+
+ investigation = Investigation.objects.get(id=record_list)
+
+ report_name = '%s/investigation_%s_%s.%s' % (SRT_REPORT_DIR,report_type,datetime.today().strftime('%Y%m%d%H%M'),format)
+ with open(report_name, 'w') as file:
+
+ if 'csv' == format:
+ tab = "\t"
+ else:
+ tab = " = "
+
+ if ('summary' == report_type) or ('audit' == report_type):
+ if 'txt' == format:
+ file.write("Report : Investigation %s - Summary\n" % investigation.name)
+ file.write("\n")
+
+ file.write("Name: %s\n" % investigation.name)
+ file.write(" Status: %s\n" % investigation.get_status_text)
+ file.write(" Outcome: %s\n" % investigation.get_outcome_text)
+ file.write(" Severity: %s\n" % investigation.get_severity_text)
+ file.write(" Defects: ")
+ for i,id in enumerate(investigation.investigation_to_defect.all()):
+ if i > 0:
+ file.write(",")
+ file.write("%s (%s)" % (id.defect.name,id.defect.get_status_text))
+ file.write("\n")
+
+ file.write("\n")
+ file.write("Comments:\n")
+ found_c = False
+ for i,vc in enumerate(investigation.investigation_comments.all()):
+ found_c = True
+ file.write(" %s (%s): %s\n" % (ic.date,ic.author,ic.comment))
+ if not found_c:
+ file.write(" No comments found\n")
+
+ if 'audit' == report_type:
+ file.write("\n")
+ file.write(" Audit Trail:\n")
+ for i,ih in enumerate(investigation.investigation_history.all()):
+ file.write(" %s (%s): %s\n" % (ih.date,ih.author,ih.comment))
+
+ file.write("\n")
+
+ return report_name,os.path.basename(report_name)
+
+class DefectReport(Report):
+ """Report for the Defect Page"""
+
+ def __init__(self, parent_page, *args, **kwargs):
+ _log_args("REPORT_DEFECT_INIT(%s)" % parent_page, *args, **kwargs)
+ super(DefectReport, self).__init__(parent_page, *args, **kwargs)
+
+ def get_context_data(self, *args, **kwargs):
+ _log_args("REPORT_DEFECT_CONTEXT", *args, **kwargs)
+ context = super(DefectReport, self).get_context_data(*args, **kwargs)
+
+ context['report_type_list'] = '\
+ <option value="summary">Defect Summary</option> \
+ '
+ context['report_get_title'] = '1'
+ context['report_recordrange_list'] = '\
+ <input type="radio" name="records" value="selected" checked> Selected<br> \
+ '
+ context['report_columnrange_list'] = ''
+ context['report_format_list'] = '\
+ <input type="radio" name="format" value="txt" checked> Text<br> \
+ <input type="radio" name="format" value="csv"> CSV<br> \
+ '
+ return context
+
+ def exec_report(self, *args, **kwargs):
+ _log_args("REPORT_DEFECT_EXEC", *args, **kwargs)
+ super(DefectReport, self).exec_report(*args, **kwargs)
+
+ request_POST = self.request.POST
+
+ records = request_POST.get('records', '')
+ format = request_POST.get('format', '')
+ title = request_POST.get('title', '')
+ report_type = request_POST.get('report_type', '')
+ record_list = request_POST.get('record_list', '')
+
+ report_name = '%s/defect_%s_%s.%s' % (SRT_REPORT_DIR,report_type,datetime.today().strftime('%Y%m%d%H%M'),format)
+ with open(report_name, 'w') as file:
+
+ if 'csv' == format:
+ tab = "\t"
+ else:
+ tab = ","
+
+ if ('summary' == report_type):
+ if 'csv' == format:
+ file.write("Name\tSummary\tPriority\tStatus\tResolution\tReleased Version\tURL\tInvestigations\tProduct\n")
+ if 'txt' == format:
+ file.write("Report : Defects Table\n")
+ file.write("\n")
+ file.write("Name,Summary,Priority,Status,Resolution,Released Version,URL,Investigations,Product\n")
+
+ defect = Defect.objects.get(id=record_list)
+ file.write("%s%s" % (defect.name,tab))
+ file.write("%s%s" % (defect.summary,tab))
+ file.write("%s%s" % (defect.get_priority_text,tab))
+ file.write("%s%s" % (defect.get_status_text,tab))
+ file.write("%s%s" % (defect.get_resolution_text,tab))
+ file.write("%s%s" % (defect.release_version,tab))
+ file.write("%s%s" % (defect.publish,tab))
+ file.write("%s%s" % (defect.url,tab))
+ for i,di in enumerate(defect.defect_to_investigation.all()):
+ if i > 0:
+ file.write(" ")
+ file.write("%s" % (di.investigation.name))
+ file.write("%s" % tab)
+ tab='' # EOL
+ file.write("%s%s" % (defect.product.long_name,tab))
+ file.write("\n")
+
+ return report_name,os.path.basename(report_name)
+
+
+class CvesReport(Report):
+ """Report for the CVEs Page"""
+
+ def __init__(self, parent_page, *args, **kwargs):
+ _log_args("REPORT_CVES_INIT(%s)" % parent_page, *args, **kwargs)
+ super(CvesReport, self).__init__(parent_page, *args, **kwargs)
+
+ def get_context_data(self, *args, **kwargs):
+ _log_args("REPORT_CVES_CONTEXT", *args, **kwargs)
+ context = super(CvesReport, self).get_context_data(*args, **kwargs)
+
+ context['report_type_list'] = '\
+ <option value="summary">CVEs Table</option> \
+ '
+ context['report_get_title'] = '1'
+ context['report_recordrange_list'] = '\
+ <input type="radio" name="records" value="selected" checked> Selected<br> \
+ '
+ context['report_columnrange_list'] = ''
+ context['report_format_list'] = '\
+ <input type="radio" name="format" value="txt" checked> Text<br> \
+ <input type="radio" name="format" value="csv"> CSV<br> \
+ '
+ return context
+
+ def exec_report(self, *args, **kwargs):
+ _log_args("REPORT_CVES_EXEC", *args, **kwargs)
+ super(CvesReport, self).exec_report(*args, **kwargs)
+
+ request_POST = self.request.POST
+
+ records = request_POST.get('records', '')
+ format = request_POST.get('format', '')
+ title = request_POST.get('title', '')
+ report_type = request_POST.get('report_type', '')
+ record_list = request_POST.get('record_list', '')
+
+ report_name = '%s/cves_%s_%s.%s' % (SRT_REPORT_DIR,report_type,datetime.today().strftime('%Y%m%d%H%M'),format)
+ with open(report_name, 'w') as file:
+
+ if 'csv' == format:
+ tab = "\t"
+ else:
+ tab = ","
+
+ if ('summary' == report_type):
+ if 'csv' == format:
+ file.write("Name\tStatus\tType\tFormat\tVersion\tVulnerabilities\tDescription\n")
+ if 'txt' == format:
+ file.write("Report : CVEs Table\n")
+ file.write("\n")
+ file.write("Name,Status,Type,Format,Version,Vulnerabilities,Description\n")
+
+ for id in record_list.split(','):
+ if not id:
+ continue
+ cve = Cve.objects.get(id=id)
+ file.write("%s%s" % (cve.name,tab))
+ file.write("%s%s" % (cve.get_status_text,tab))
+ file.write("%s%s" % (cve.cve_data_type,tab))
+ file.write("%s%s" % (cve.cve_data_format,tab))
+ file.write("%s%s" % (cve.cve_data_version,tab))
+
+ for i,cv in enumerate(cve.cve_to_vulnerability.all()):
+ if i > 0:
+ file.write(" ")
+ file.write("%s" % cv.vulnerability.name)
+ file.write("%s" % tab)
+
+ file.write("%s%s" % (cve.description,tab))
+ file.write("\n")
+
+ return report_name,os.path.basename(report_name)
+
+class SelectCvesReport(Report):
+ """Report for the Select CVEs Page"""
+
+ def __init__(self, parent_page, *args, **kwargs):
+ _log_args("REPORT_SELECTCVES_INIT(%s)" % parent_page, *args, **kwargs)
+ super(SelectCvesReport, self).__init__(parent_page, *args, **kwargs)
+
+ def get_context_data(self, *args, **kwargs):
+ _log_args("REPORT_SELECTCVES_CONTEXT", *args, **kwargs)
+ context = super(SelectCvesReport, self).get_context_data(*args, **kwargs)
+
+ context['report_type_list'] = '\
+ <option value="summary">CVEs Table</option> \
+ '
+ context['report_get_title'] = '1'
+ context['report_recordrange_list'] = '\
+ <input type="radio" name="records" value="selected" checked> Selected<br> \
+ '
+ context['report_columnrange_list'] = ''
+ context['report_format_list'] = '\
+ <input type="radio" name="format" value="txt" checked> Text<br> \
+ <input type="radio" name="format" value="csv"> CSV<br> \
+ '
+ return context
+
+ def exec_report(self, *args, **kwargs):
+ _log_args("REPORT_SELECTCVES_EXEC", *args, **kwargs)
+ super(SelectCvesReport, self).exec_report(*args, **kwargs)
+
+ request_POST = self.request.POST
+
+ records = request_POST.get('records', '')
+ format = request_POST.get('format', '')
+ title = request_POST.get('title', '')
+ report_type = request_POST.get('report_type', '')
+ record_list = request_POST.get('record_list', '')
+
+ report_name = '%s/select_cves_%s_%s.%s' % (SRT_REPORT_DIR,report_type,datetime.today().strftime('%Y%m%d%H%M'),format)
+ with open(report_name, 'w') as file:
+
+ if 'csv' == format:
+ tab = "\t"
+ else:
+ tab = ","
+
+ if ('summary' == report_type):
+ if 'csv' == format:
+ file.write("Name\tStatus\tType\tFormat\tVersion\tVulnerabilities\tDescription\n")
+ if 'txt' == format:
+ file.write("Report : CVEs Table\n")
+ file.write("\n")
+ file.write("Name,Status,Type,Format,Version,Vulnerabilities,Description\n")
+
+ for id in record_list.split(','):
+ if not id:
+ continue
+ cve = Cve.objects.get(id=id)
+ file.write("%s%s" % (cve.name,tab))
+ file.write("%s%s" % (cve.get_status_text,tab))
+ file.write("%s%s" % (cve.cve_data_type,tab))
+ file.write("%s%s" % (cve.cve_data_format,tab))
+ file.write("%s%s" % (cve.cve_data_version,tab))
+
+ for i,cv in enumerate(cve.cve_to_vulnerability.all()):
+ if i > 0:
+ file.write(" ")
+ file.write("%s" % cv.vulnerability.name)
+ file.write("%s" % tab)
+
+ file.write("%s%s" % (cve.description,tab))
+ file.write("\n")
+
+ return report_name,os.path.basename(report_name)
+
+class VulnerabilitiesReport(Report):
+ """Report for the Vulnerabilities Page"""
+
+ def __init__(self, parent_page, *args, **kwargs):
+ _log_args("REPORT_VULNERABILITIES_INIT(%s)" % parent_page, *args, **kwargs)
+ super(VulnerabilitiesReport, self).__init__(parent_page, *args, **kwargs)
+
+ def get_context_data(self, *args, **kwargs):
+ _log_args("REPORT_VULNERABILITIES_CONTEXT", *args, **kwargs)
+ context = super(VulnerabilitiesReport, self).get_context_data(*args, **kwargs)
+
+ context['report_type_list'] = '\
+ <option value="summary">Vulnerabilities Table</option> \
+ '
+ context['report_get_title'] = '1'
+ context['report_recordrange_list'] = '\
+ <input type="radio" name="records" value="selected" checked> Selected<br> \
+ '
+ context['report_columnrange_list'] = ''
+ context['report_format_list'] = '\
+ <input type="radio" name="format" value="txt" checked> Text<br> \
+ <input type="radio" name="format" value="csv"> CSV<br> \
+ '
+ return context
+
+ def exec_report(self, *args, **kwargs):
+ _log_args("REPORT_VULNERABILITIES_EXEC", *args, **kwargs)
+ super(VulnerabilitiesReport, self).exec_report(*args, **kwargs)
+
+ request_POST = self.request.POST
+
+ records = request_POST.get('records', '')
+ format = request_POST.get('format', '')
+ title = request_POST.get('title', '')
+ report_type = request_POST.get('report_type', '')
+ record_list = request_POST.get('record_list', '')
+
+ report_name = '%s/vulnerabilities_%s_%s.%s' % (SRT_REPORT_DIR,report_type,datetime.today().strftime('%Y%m%d%H%M'),format)
+ with open(report_name, 'w') as file:
+
+ if 'csv' == format:
+ tab = "\t"
+ else:
+ tab = ","
+
+ if ('summary' == report_type):
+ if 'csv' == format:
+ file.write("Name\tStatus\tOutcome\tSeverity\tCVEs\tInvestigations\n")
+ if 'txt' == format:
+ file.write("Report : Investigations Table\n")
+ file.write("\n")
+ file.write("Name,Status,Outcome,Severity,CVEs,Investigations\n")
+
+ for id in record_list.split(','):
+ if not id:
+ continue
+ v = Vulnerability.objects.get(id=id)
+ file.write("%s%s" % (v.name,tab))
+ file.write("%s%s" % (v.get_status_text,tab))
+ file.write("%s%s" % (v.get_outcome_text,tab))
+ file.write("%s%s" % (v.get_severity_text,tab))
+ for i,vc in enumerate(v.vulnerability_to_cve.all()):
+ if i > 0:
+ file.write(" ")
+ file.write("%s" % vc.cve.name)
+ file.write("%s" % tab)
+ for i,investigation in enumerate(Investigation.objects.filter(vulnerability=v)):
+ if i > 0:
+ file.write(" ")
+ file.write("%s" % investigation.name)
+ #file.write("%s" % tab)
+ file.write("\n")
+
+ return report_name,os.path.basename(report_name)
+
+class InvestigationsReport(Report):
+ """Report for the Investigations Page"""
+
+ def __init__(self, parent_page, *args, **kwargs):
+ _log_args("REPORT_INVESTIGATIONS_INIT(%s)" % parent_page, *args, **kwargs)
+ super(InvestigationsReport, self).__init__(parent_page, *args, **kwargs)
+
+ def get_context_data(self, *args, **kwargs):
+ _log_args("REPORT_INVESTIGATIONS_CONTEXT", *args, **kwargs)
+ context = super(InvestigationsReport, self).get_context_data(*args, **kwargs)
+
+ context['report_type_list'] = '\
+ <option value="summary">Investigations Table</option> \
+ '
+ context['report_get_title'] = '1'
+ context['report_recordrange_list'] = '\
+ <input type="radio" name="records" value="selected" checked> Selected<br> \
+ '
+ context['report_columnrange_list'] = ''
+ context['report_format_list'] = '\
+ <input type="radio" name="format" value="txt" checked> Text<br> \
+ <input type="radio" name="format" value="csv"> CSV<br> \
+ '
+ return context
+
+ def exec_report(self, *args, **kwargs):
+ _log_args("REPORT_INVESTIGATIONS_EXEC", *args, **kwargs)
+ super(InvestigationsReport, self).exec_report(*args, **kwargs)
+
+ request_POST = self.request.POST
+
+ records = request_POST.get('records', '')
+ format = request_POST.get('format', '')
+ title = request_POST.get('title', '')
+ report_type = request_POST.get('report_type', '')
+ record_list = request_POST.get('record_list', '')
+
+ report_name = '%s/investigations_%s_%s.%s' % (SRT_REPORT_DIR,report_type,datetime.today().strftime('%Y%m%d%H%M'),format)
+ with open(report_name, 'w') as file:
+
+ if 'csv' == format:
+ tab = "\t"
+ else:
+ tab = ","
+
+ if ('summary' == report_type):
+ if 'csv' == format:
+ file.write("Name\tStatus\tOutcome\tSeverity\tProduct\tDefects\n")
+ if 'txt' == format:
+ file.write("Report : Investigations Table\n")
+ file.write("\n")
+ file.write("Name,Status,Outcome,Severity,Product,Defects\n")
+
+ for id in record_list.split(','):
+ if not id:
+ continue
+ investigation = Investigation.objects.get(id=id)
+ file.write("%s%s" % (investigation.name,tab))
+ file.write("%s%s" % (investigation.get_status_text,tab))
+ file.write("%s%s" % (investigation.get_outcome_text,tab))
+ file.write("%s%s" % (investigation.get_severity_text,tab))
+ file.write("%s%s" % (investigation.product.long_name,tab))
+ for i,id in enumerate(investigation.investigation_to_defect.all()):
+ if i > 0:
+ file.write(" ")
+ file.write("%s (%s)" % (id.defect.name,id.defect.get_status_text))
+ #file.write("%s" % tab)
+ file.write("\n")
+
+ return report_name,os.path.basename(report_name)
+
+class DefectsReport(Report):
+ """Report for the Defects Page"""
+
+ def __init__(self, parent_page, *args, **kwargs):
+ _log_args("REPORT_DEFECTS_INIT(%s)" % parent_page, *args, **kwargs)
+ super(DefectsReport, self).__init__(parent_page, *args, **kwargs)
+
+ def get_context_data(self, *args, **kwargs):
+ _log_args("REPORT_DEFECTS_CONTEXT", *args, **kwargs)
+ context = super(DefectsReport, self).get_context_data(*args, **kwargs)
+
+ context['report_type_list'] = '\
+ <option value="summary">Defects Table</option> \
+ '
+ context['report_get_title'] = '1'
+ context['report_recordrange_list'] = '\
+ <input type="radio" name="records" value="selected" checked> Selected<br> \
+ '
+ context['report_columnrange_list'] = ''
+ context['report_format_list'] = '\
+ <input type="radio" name="format" value="txt" checked> Text<br> \
+ <input type="radio" name="format" value="csv"> CSV<br> \
+ '
+ return context
+
+ def exec_report(self, *args, **kwargs):
+ _log_args("REPORT_DEFECTS_EXEC", *args, **kwargs)
+ super(DefectsReport, self).exec_report(*args, **kwargs)
+
+ request_POST = self.request.POST
+
+ records = request_POST.get('records', '')
+ format = request_POST.get('format', '')
+ title = request_POST.get('title', '')
+ report_type = request_POST.get('report_type', '')
+ record_list = request_POST.get('record_list', '')
+
+ report_name = '%s/defects_%s_%s.%s' % (SRT_REPORT_DIR,report_type,datetime.today().strftime('%Y%m%d%H%M'),format)
+ with open(report_name, 'w') as file:
+
+ if 'csv' == format:
+ tab = "\t"
+ else:
+ tab = ","
+
+ if ('summary' == report_type):
+ if 'csv' == format:
+ file.write("Name\tSummary\tPriority\tStatus\tResolution\tReleased Version\tURL\tInvestigations\tProduct\n")
+ if 'txt' == format:
+ file.write("Report : Defects Table\n")
+ file.write("\n")
+ file.write("Name,Summary,Priority,Status,Resolution,Released Version,URL,Investigations,Product\n")
+
+ for id in record_list.split(','):
+ if not id:
+ continue
+ defect = Defect.objects.get(id=id)
+ file.write("%s%s" % (defect.name,tab))
+ file.write("%s%s" % (defect.summary,tab))
+ file.write("%s%s" % (defect.get_priority_text,tab))
+ file.write("%s%s" % (defect.get_status_text,tab))
+ file.write("%s%s" % (defect.get_resolution_text,tab))
+ file.write("%s%s" % (defect.release_version,tab))
+ file.write("%s%s" % (defect.publish,tab))
+ file.write("%s%s" % (defect.url,tab))
+ for i,di in enumerate(defect.defect_to_investigation.all()):
+ if i > 0:
+ file.write(" ")
+ file.write("%s" % (di.investigation.name))
+ file.write("%s" % tab)
+ tab='' # EOL
+ file.write("%s%s" % (defect.product.long_name,tab))
+ file.write("\n")
+
+ return report_name,os.path.basename(report_name)
+
+class ProductsReport(Report):
+ """Report for the Products Page"""
+
+ def __init__(self, parent_page, *args, **kwargs):
+ _log_args("REPORT_PRODUCTS_INIT(%s)" % parent_page, *args, **kwargs)
+ super(ProductsReport, self).__init__(parent_page, *args, **kwargs)
+
+ def get_context_data(self, *args, **kwargs):
+ _log_args("REPORT_PRODUCTS_CONTEXT", *args, **kwargs)
+ context = super(ProductsReport, self).get_context_data(*args, **kwargs)
+
+ context['report_type_list'] = '\
+ <option value="summary">Products Table</option> \
+ '
+ context['report_get_title'] = '1'
+ context['report_recordrange_list'] = '\
+ <input type="radio" name="records" value="selected" checked> Selected<br> \
+ '
+ context['report_columnrange_list'] = ''
+ context['report_format_list'] = '\
+ <input type="radio" name="format" value="txt" checked> Text<br> \
+ <input type="radio" name="format" value="csv"> CSV<br> \
+ '
+ return context
+
+ def exec_report(self, *args, **kwargs):
+ _log_args("REPORT_PRODUCTS_EXEC", *args, **kwargs)
+ super(ProductsReport, self).exec_report(*args, **kwargs)
+
+ request_POST = self.request.POST
+
+ records = request_POST.get('records', '')
+ format = request_POST.get('format', '')
+ title = request_POST.get('title', '')
+ report_type = request_POST.get('report_type', '')
+ record_list = request_POST.get('record_list', '')
+
+ report_name = '%s/products_%s_%s.%s' % (SRT_REPORT_DIR,report_type,datetime.today().strftime('%Y%m%d%H%M'),format)
+ with open(report_name, 'w') as file:
+
+ if 'csv' == format:
+ tab = "\t"
+ else:
+ tab = ","
+
+ if ('summary' == report_type):
+ if 'csv' == format:
+ file.write("Name\tVersion\tProfile\tCPE\tSRT SPE\tInvestigations\tDefects\n")
+ if 'txt' == format:
+ file.write("Report : Investigations Table\n")
+ file.write("\n")
+ file.write("Name,Version,Profile,CPE,SRT SPE,Investigations,Defects\n")
+
+ for id in record_list.split(','):
+ if not id:
+ continue
+ product = Product.objects.get(id=id)
+ file.write("%s%s" % (product.name,tab))
+ file.write("%s%s" % (product.version,tab))
+ file.write("%s%s" % (product.profile,tab))
+ file.write("%s%s" % (product.cpe,tab))
+ file.write("%s%s" % (product.srt_cpe,tab))
+ file.write("%s%s" % (product.defect_prefix,tab))
+ for i,pi in enumerate(product.product_investigation.all()):
+ if i > 0:
+ file.write(" ")
+ file.write("%s" % (pi.name))
+ file.write("%s" % tab)
+ for i,pd in enumerate(product.product_defect.all()):
+ if i > 0:
+ file.write(" ")
+ file.write("%s" % (pd.name))
+ #file.write("%s" % tab)
+ file.write("\n")
+
+ return report_name,os.path.basename(report_name)
+
+class PublishCveReport(Report):
+ """Report for the Publish Cve Page"""
+
+ def __init__(self, parent_page, *args, **kwargs):
+ _log_args("REPORT_PUBLISHCVE_INIT(%s)" % parent_page, *args, **kwargs)
+ super(PublishCveReport, self).__init__(parent_page, *args, **kwargs)
+
+ def get_context_data(self, *args, **kwargs):
+ _log_args("REPORT_PUBLISHCVE_CONTEXT", *args, **kwargs)
+ context = super(PublishCveReport, self).get_context_data(*args, **kwargs)
+
+ context['report_type_list'] = '\
+ <option value="summary">CVE Publish Request Table</option> \
+ '
+ context['report_get_title'] = '1'
+ context['report_recordrange_list'] = '\
+ <input type="radio" name="records" value="selected" checked> Selected<br> \
+ '
+ context['report_columnrange_list'] = ''
+ context['report_format_list'] = '\
+ <input type="radio" name="format" value="txt" checked> Text<br> \
+ <input type="radio" name="format" value="csv"> CSV<br> \
+ '
+ return context
+
+ def exec_report(self, *args, **kwargs):
+ _log_args("REPORT_PUBLISHCVE_EXEC", *args, **kwargs)
+ super(PublishCveReport, self).exec_report(*args, **kwargs)
+
+ _log("FOO1")
+ request_POST = self.request.POST
+
+ records = request_POST.get('records', '')
+ format = request_POST.get('format', '')
+ title = request_POST.get('title', '')
+ report_type = request_POST.get('report_type', '')
+ record_list = request_POST.get('record_list', '')
+
+ _log("FOO2 (%s,%s,%s" % (record_list,format,report_type))
+ report_name = '%s/cve_publish_%s_%s.%s' % (SRT_REPORT_DIR,report_type,datetime.today().strftime('%Y%m%d%H%M'),format)
+ with open(report_name, 'w') as file:
+
+ _log("FOO3")
+ if 'csv' == format:
+ tab = "\t"
+ else:
+ tab = ","
+
+ if ('summary' == report_type):
+ if 'csv' == format:
+ file.write("Name\tStatus\tType\tFormat\tVersion\tVulnerabilities\tDescription\n")
+ if 'txt' == format:
+ file.write("Report : CVEs Table\n")
+ file.write("\n")
+ file.write("Name,Status,Type,Format,Version,Vulnerabilities,Description\n")
+
+ _log("FOO4")
+ for id in record_list.split(','):
+ _log("FOO5:%s" % id)
+ if not id:
+ continue
+ try:
+ cve = Cve.objects.get(id=id)
+ file.write("%s%s" % (cve.name,tab))
+ file.write("%s%s" % (cve.get_status_text,tab))
+ file.write("%s%s" % (cve.cve_data_type,tab))
+ file.write("%s%s" % (cve.cve_data_format,tab))
+ file.write("%s%s" % (cve.cve_data_version,tab))
+
+ for i,cv in enumerate(cve.cve_to_vulnerability.all()):
+ if i > 0:
+ file.write(" ")
+ file.write("%s" % cv.vulnerability.name)
+ file.write("%s" % tab)
+
+ file.write("%s" % (cve.description))
+ file.write("\n")
+ except Exception as e:
+ _log("FOOX:%s" % e)
+
+ _log("FOO9:%s" % (report_name))
+ return report_name,os.path.basename(report_name)
+
+class PublishPendingCveReport(Report):
+ """Report for the Publish Cve Page"""
+
+ def __init__(self, parent_page, *args, **kwargs):
+ _log_args("REPORT_PUBLISHPENDINGCVE_INIT(%s)" % parent_page, *args, **kwargs)
+ super(PublishPendingCveReport, self).__init__(parent_page, *args, **kwargs)
+
+ def get_context_data(self, *args, **kwargs):
+ _log_args("REPORT_PUBLISHPENDINGCVE_CONTEXT", *args, **kwargs)
+ context = super(PublishPendingCveReport, self).get_context_data(*args, **kwargs)
+ context['report_type_list'] = '\
+ <option value="summary">CVE Publish Request Table</option> \
+ '
+ context['report_get_title'] = '1'
+ context['report_recordrange_list'] = '\
+ <input type="radio" name="records" value="selected" checked> Selected<br> \
+ '
+ context['report_columnrange_list'] = ''
+ context['report_format_list'] = '\
+ <input type="radio" name="format" value="txt" checked> Text<br> \
+ <input type="radio" name="format" value="csv"> CSV<br> \
+ '
+ return context
+
+ def exec_report(self, *args, **kwargs):
+ _log_args("REPORT_PUBLISHPENDINGCVE_EXEC", *args, **kwargs)
+ super(PublishPendingCveReport, self).exec_report(*args, **kwargs)
+
+ _log("FOO1")
+ request_POST = self.request.POST
+
+ records = request_POST.get('records', '')
+ format = request_POST.get('format', '')
+ title = request_POST.get('title', '')
+ report_type = request_POST.get('report_type', '')
+ record_list = request_POST.get('record_list', '')
+
+ _log("FOO2 (%s,%s,%s" % (record_list,format,report_type))
+ report_name = '%s/cve_publish_%s_%s.%s' % (SRT_REPORT_DIR,report_type,datetime.today().strftime('%Y%m%d%H%M'),format)
+ with open(report_name, 'w') as file:
+
+ _log("FOO3")
+ if 'csv' == format:
+ tab = "\t"
+ else:
+ tab = ","
+
+ if ('summary' == report_type):
+ if 'csv' == format:
+ file.write("Name\tStatus\tType\tFormat\tVersion\tVulnerabilities\tDescription\n")
+ if 'txt' == format:
+ file.write("Report : CVEs Table\n")
+ file.write("\n")
+ file.write("Name,Status,Type,Format,Version,Vulnerabilities,Description\n")
+
+ _log("FOO4")
+ for id in record_list.split(','):
+ if not id:
+ continue
+ _log("FOO5:%s" % id)
+ try:
+ cve = Cve.objects.get(id=id)
+ file.write("%s%s" % (cve.name,tab))
+ file.write("%s%s" % (cve.get_status_text,tab))
+ file.write("%s%s" % (cve.cve_data_type,tab))
+ file.write("%s%s" % (cve.cve_data_format,tab))
+ file.write("%s%s" % (cve.cve_data_version,tab))
+
+ for i,cv in enumerate(cve.cve_to_vulnerability.all()):
+ if i > 0:
+ file.write(" ")
+ file.write("%s" % cv.vulnerability.name)
+ file.write("%s" % tab)
+
+ file.write("%s" % (cve.description))
+ file.write("\n")
+ except Exception as e:
+ _log("FOOX:%s" % e)
+
+ _log("FOO9:%s" % (report_name))
+ return report_name,os.path.basename(report_name)
+
+class DefaultReport(Report):
+ """Report for the Default Page"""
+
+ def __init__(self, parent_page, *args, **kwargs):
+ _log_args("REPORT_GENERIC_INIT(%s)" % parent_page, *args, **kwargs)
+ super(DefaultReport, self).__init__(parent_page, *args, **kwargs)
+ self.default_orderby = "name"
+
+ def get_context_data(self, *args, **kwargs):
+ _log_args("REPORT_GENERIC_CONTEXT", *args, **kwargs)
+ context = super(DefaultReport, self).get_context_data(*args, **kwargs)
+ context['report_enable_submit'] = ''
+
+ #context['report_recordrange_list'] = '\
+ # <input type="radio" name="records" value="selected" checked> Selected<br> \
+ # <input type="radio" name="records" value="all"> all<br> \
+ #context['report_columnrange_list'] = ''
+ # <input type="radio" name="columns" value="selected" checked> Selected<br>
+ # <input type="radio" name="columns" value="all"> All<br>
+ #context['report_format_list'] = '\
+ # <input type="radio" name="format" value="txt" checked> Text<br> \
+ # <input type="radio" name="format" value="csv"> CSV<br> \
+ # <input type="radio" name="format" value="rtf"> RTF<br>
+ # <input type="radio" name="format" value="xml"> XML<br>
+ # <input type="radio" name="format" value="json"> CVE NIST JSON<br>
+
+ return context
+
+ def exec_report(self, *args, **kwargs):
+ _log_args("REPORT_GENERIC_EXEC", *args, **kwargs)
+ super(ManagementReport, self).exec_report(*args, **kwargs)
+ return None
+
+
+class ReportManager():
+ @staticmethod
+ def get_report_class(parent_page, *args, **kwargs):
+ if ('management' == parent_page) or ('manage' == parent_page):
+ return ManagementReport(parent_page, *args, **kwargs)
+
+ elif 'cve' == parent_page:
+ return CveReport(parent_page, *args, **kwargs)
+ elif 'vulnerability' == parent_page:
+ return VulnerabilityReport(parent_page, *args, **kwargs)
+ elif 'investigation' == parent_page:
+ return InvestigationReport(parent_page, *args, **kwargs)
+ elif 'defect' == parent_page:
+ return DefectReport(parent_page, *args, **kwargs)
+
+ elif 'cves' == parent_page:
+ return CvesReport(parent_page, *args, **kwargs)
+ elif 'select-cves' == parent_page:
+ return SelectCvesReport(parent_page, *args, **kwargs)
+ elif 'vulnerabilities' == parent_page:
+ return VulnerabilitiesReport(parent_page, *args, **kwargs)
+ elif 'investigations' == parent_page:
+ return InvestigationsReport(parent_page, *args, **kwargs)
+ elif 'defects' == parent_page:
+ return DefectsReport(parent_page, *args, **kwargs)
+ elif 'products' == parent_page:
+ return ProductsReport(parent_page, *args, **kwargs)
+
+ elif 'select-publish' == parent_page:
+ return PublishCveReport(parent_page, *args, **kwargs)
+ elif 'update-published' == parent_page:
+ return PublishPendingCveReport(parent_page, *args, **kwargs)
+
+
+ else:
+ return DefaultReport(parent_page, *args, **kwargs)
+
+ @staticmethod
+ def get_context_data(parent_page, *args, **kwargs):
+ reporter = ReportManager.get_report_class(parent_page, *args, **kwargs)
+ return reporter.get_context_data(*args, **kwargs)
+
+ @staticmethod
+ def exec_report(parent_page, *args, **kwargs):
+ reporter = ReportManager.get_report_class(parent_page, *args, **kwargs)
+ return reporter.exec_report(*args, **kwargs)
diff --git a/lib/srtgui/tables.py b/lib/srtgui/tables.py
index 798855d6..643dd34d 100644
--- a/lib/srtgui/tables.py
+++ b/lib/srtgui/tables.py
@@ -22,7 +22,8 @@
from srtgui.widgets import ToasterTable
from orm.models import SrtSetting
from orm.models import Cve, Vulnerability, Investigation, CweTable, Product
-from orm.models import CpeTable, Access, CpeFilter, Defect, Keywords
+from orm.models import CpeTable, Access, CpeFilter, Defect, Keywords, DataSource
+from orm.models import PublishPending
from django.db.models import Q, Max, Sum, Count, When, Case, Value, IntegerField
from django.conf.urls import url
@@ -35,47 +36,46 @@ from srtgui.tablefilter import TableFilterActionToggle
from srtgui.tablefilter import TableFilterActionDateRange
from srtgui.tablefilter import TableFilterActionDay
-def _log(msg):
- f1=open('/tmp/srt.log', 'a')
- f1.write("|" + msg + "|\n" )
- f1.close()
+import os
+# quick development/debugging support
+from srtgui.api import _log
-class AllCveTable(ToasterTable):
+class CvesTable(ToasterTable):
"""Table of All CVE's in SRTool"""
def __init__(self, *args, **kwargs):
- super(AllCveTable, self).__init__(*args, **kwargs)
+ super(CvesTable, self).__init__(*args, **kwargs)
self.default_orderby = "name"
def get_context_data(self, **kwargs):
- context = super(AllCveTable, self).get_context_data(**kwargs)
+ context = super(CvesTable, self).get_context_data(**kwargs)
return context
def setup_filters(self, *args, **kwargs):
- # Is Vulnerable filter
+ # Is Status filter
is_status = TableFilter(name="is_status",
title="Filter CVE's by 'Status")
- exec_is_new = TableFilterActionToggle(
+ is_status.add_action(TableFilterActionToggle(
"new",
"New",
Q(status=Cve.NEW))
- exec_is_investigate = TableFilterActionToggle(
+ )
+ is_status.add_action(TableFilterActionToggle(
"investigate",
"Investigate",
Q(status=Cve.INVESTIGATE))
- exec_is_vulnerable = TableFilterActionToggle(
+ )
+ is_status.add_action(TableFilterActionToggle(
"vulnerable",
"Is Vulnerable",
Q(status=Cve.VULNERABLE))
- exec_is_not_vulnerable = TableFilterActionToggle(
+ )
+ is_status.add_action(TableFilterActionToggle(
"not_vulnerable",
"Not Vulnerable",
Q(status=Cve.NOT_VULNERABLE))
- is_status.add_action(exec_is_new)
- is_status.add_action(exec_is_investigate)
- is_status.add_action(exec_is_vulnerable)
- is_status.add_action(exec_is_not_vulnerable)
+ )
self.add_filter(is_status)
# Recommends filter
@@ -123,38 +123,37 @@ class AllCveTable(ToasterTable):
Cve.objects.all()
# filter out hidden records
- userAccess = Access()
+ userAccess = Access(self.request.session.get('srt_user_id', '0'))
if not userAccess.is_admin():
self.queryset = self.queryset.exclude(public = False)
self.queryset = self.queryset.order_by(self.default_orderby)
-# self.static_context_extra['in_prj'] = ProjectLayer.objects.filter(Q(project=kwargs['pid']) & Q(layercommit=kwargs['layerid'])).count()
+
def setup_columns(self, *args, **kwargs):
id_link_template = '''
- <a href="{% url 'cve' data.id %}">
- {{data.name}}
- </a>
+ <a href="{% url 'cve' data.id %}" id="dataid_{{data.id}}">{{data.name}}</a>
'''
- self.add_column(title="ID",
+ self.add_column(title="Name",
hideable=False,
orderable=True,
field_name="name",
static_data_name="name",
- static_data_template=id_link_template)
+ static_data_template=id_link_template,
+ )
self.add_column(title="Status",
field_name="status",
hideable=True,
orderable=True,
- filter_name="is_status",
+# filter_name="is_status",
static_data_name="status",
static_data_template="{{data.get_status_text}}"
)
score_link_template = '''
- {% if 0 == data.recommend %}0{% else %}{{data.recommend}}{% endif %}
+ {% if 0 == data.recommend %}0{% else %}{{data.recommend}}{% endif %}
'''
self.add_column(title="Score",
field_name="recommend",
@@ -189,17 +188,18 @@ class AllCveTable(ToasterTable):
)
severity_v3_template = '''
- {{data.cvssV3_baseScore}} {{data.cvssV3_baseSeverity}}
+ {{data.cvssV3_baseScore}} {{data.cvssV3_baseSeverity}}
'''
self.add_column(title="Severity (V3)",
help_text="Severity of the CVE (v3)",
hideable=False,
orderable=False,
static_data_name='severity_v3',
- static_data_template=severity_v3_template)
+ static_data_template=severity_v3_template,
+ )
severity_v2_template = '''
- {{data.cvssV2_baseScore}} {{data.cvssV2_severity}}
+ {{data.cvssV2_baseScore}} {{data.cvssV2_severity}}
'''
self.add_column(title="Severity (V2)",
help_text="Severity of the CVE (v2)",
@@ -207,19 +207,22 @@ class AllCveTable(ToasterTable):
hidden=True,
orderable=False,
static_data_name='severity_v2',
- static_data_template=severity_v2_template)
+ static_data_template=severity_v2_template,
+ )
self.add_column(title="Published",
help_text="Initial publish date of the CVE",
hideable=False,
orderable=True,
- field_name="publishedDate")
+ field_name="publishedDate",
+ )
self.add_column(title="Modified",
help_text="Last modification date of the CVE",
hideable=True,
orderable=True,
- field_name="lastModifiedDate")
+ field_name="lastModifiedDate",
+ )
self.add_column(title="Comments",
field_name="comments",
@@ -227,7 +230,25 @@ class AllCveTable(ToasterTable):
orderable=True,
)
- userAccess = Access()
+ self.add_column(title="Publish Request",
+ help_text="SRT Publish Request State",
+ hideable=True,
+ hidden=True,
+ orderable=True,
+ field_name="publish_state",
+ static_data_name="publish_state",
+ static_data_template='{{data.get_publish_text}}',
+ )
+
+ self.add_column(title="Publish Date",
+ help_text="SRT Publish date of the CVE",
+ hideable=True,
+ hidden=True,
+ orderable=True,
+ field_name="publish_date"
+ )
+
+ userAccess = Access(self.request.session.get('srt_user_id', '0'))
if userAccess.is_admin():
self.add_column(title="Comments Private",
field_name="comments_private",
@@ -235,27 +256,32 @@ class AllCveTable(ToasterTable):
)
vulnerability_link_template = '''
- {% if data.cve_to_vulnerability.all %}
- {% for cv in data.cve_to_vulnerability.all %}
- {% if not forloop.first %}| {% endif %}<a href="{% url 'vulnerability' cv.vulnerability.pk %}">{{cv.vulnerability.name}}</a>
- {% endfor %}
- {% endif %}
+ {% for cv in data.cve_to_vulnerability.all %}
+ {% if not forloop.first %}| {% endif %}<a href="{% url 'vulnerability' cv.vulnerability.pk %}">{{cv.vulnerability.name}}</a>
+ {% endfor %}
'''
self.add_column(title="Vulnerability",
static_data_name="vulnerability",
static_data_template=vulnerability_link_template,
- hidden=False)
-
- if False:
- defect_template = '''
+# static_data_template='',
+ hidden=False,
+ )
- '''
- self.add_column(title="Defect",
- help_text="Associated Defects",
- hideable=True,
- orderable=True,
- static_data_name='defect',
- static_data_template=defect_template)
+ defect_link_template = '''
+ {% for cv in data.cve_to_vulnerability.all %}
+ {% for investigation in cv.vulnerability.vulnerability_investigation.all %}
+ {% for id in investigation.investigation_to_defect.all %}
+ {% if not forloop.first %}| {% endif %}<a href="{% url 'defect' id.defect.pk %}">{{id.defect.name}}</a>
+ {% endfor %}
+ {% endfor %}
+ {% endfor %}
+ '''
+ self.add_column(title="Defect",
+ static_data_name="defect",
+ static_data_template=defect_link_template,
+# static_data_template='',
+ hidden=False,
+ )
class SelectCveTable(ToasterTable):
@@ -274,27 +300,15 @@ class SelectCveTable(ToasterTable):
data = super(SelectCveTable, self).apply_row_customization(data)
# data:dict_keys(['rows', 'total', 'default_orderby', 'error', 'columns'])
- if False:
- # TEST
- KeywordsFor = SrtSetting.objects.get(name='keywords_for').value.split('|')
- KeywordsAgainst = SrtSetting.objects.get(name='keywords_against').value.split('|')
- qq = 0
- for i in range(len(data['rows'])):
- data['rows'][i]['for'] = 'Y:%s%d' % (KeywordsFor[qq],i)
- data['rows'][i]['against'] = 'N:%s%d' % (KeywordsAgainst[qq],i)
- qq += 1
- if 10<qq:
- qq = 0
-
- if True:
- for i in range(len(data['rows'])):
- data['rows'][i]['for'] = ''
- data['rows'][i]['against'] = ''
- for key in data['rows'][i]['comments_private'].split(','):
- if key.startswith('+'):
- data['rows'][i]['for'] += '%s ' % key[1:]
- elif key.startswith('-'):
- data['rows'][i]['against'] += '%s ' % key[1:]
+ # comments_private -> recommend_list
+ for i in range(len(data['rows'])):
+ data['rows'][i]['for'] = ''
+ data['rows'][i]['against'] = ''
+ for key in data['rows'][i]['recommend_list'].split(','):
+ if key.startswith('+'):
+ data['rows'][i]['for'] += '%s ' % key[1:]
+ elif key.startswith('-'):
+ data['rows'][i]['against'] += '%s ' % key[1:]
return data
@@ -365,14 +379,12 @@ class SelectCveTable(ToasterTable):
Cve.objects.filter(status = Cve.NEW,name__startswith = 'CVE-2018')
# filter out hidden records !!! ALL NEW ONES SHOULD BE PUBLIC
-# userAccess = Access()
+# userAccess = Access(self.request.session.get('srt_user_id', '0'))
# if not userAccess.is_admin():
# self.queryset = self.queryset.exclude(public = False)
self.queryset = self.queryset.order_by(self.default_orderby)
-# self.static_context_extra['in_prj'] = ProjectLayer.objects.filter(Q(project=kwargs['pid']) & Q(layercommit=kwargs['layerid'])).count()
-
def setup_columns(self, *args, **kwargs):
@@ -380,7 +392,7 @@ class SelectCveTable(ToasterTable):
field_name="Select",
hideable=False,
static_data_name="select",
- static_data_template='<input type="checkbox" name="{{data.name}}" />'
+ static_data_template='<input type="checkbox" name="{{data.name}}" />',
)
self.add_column(title="Status",
@@ -389,18 +401,17 @@ class SelectCveTable(ToasterTable):
orderable=True,
filter_name="is_status",
static_data_name="status",
- static_data_template="{{data.get_status_text}}"
+ static_data_template="{{data.get_status_text}}",
)
- self.add_column(title="Comments",
- field_name="comments_private",
+ self.add_column(title="Recommend List",
+ field_name="recommend_list",
hideable=True,
hidden=True,
)
-# {% if 0 == data.recommend %}0{% else %}{{data.recommend}}{% endif %}
recommend_link_template = '''
- {% load projecttags %}{{data.recommend|recommend_display}}
+ {% load projecttags %}{{data.recommend|recommend_display}}
'''
self.add_column(title="Recommendation",
hideable=False,
@@ -412,16 +423,15 @@ class SelectCveTable(ToasterTable):
)
id_link_template = '''
- <a href="{% url 'cve' data.id %}" target="_blank">
- {{data.name}}
- </a>
+ <a href="{% url 'cve' data.id %}" id="dataid_{{data.id}}" target="_blank">{{data.name}}</a>
'''
self.add_column(title="Name",
hideable=False,
orderable=True,
field_name="name",
static_data_name="name",
- static_data_template=id_link_template)
+ static_data_template=id_link_template,
+ )
self.add_column(title="Description",
field_name="description",
@@ -429,17 +439,18 @@ class SelectCveTable(ToasterTable):
)
severity_v3_template = '''
- {{data.cvssV3_baseScore}} {{data.cvssV3_baseSeverity}}
+ {{data.cvssV3_baseScore}} {{data.cvssV3_baseSeverity}}
'''
self.add_column(title="Severity (V3)",
help_text="Severity of the CVE (v3)",
hideable=False,
orderable=False,
static_data_name='severity_v3',
- static_data_template=severity_v3_template)
+ static_data_template=severity_v3_template,
+ )
severity_v2_template = '''
- {{data.cvssV2_baseScore}} {{data.cvssV2_severity}}
+ {{data.cvssV2_baseScore}} {{data.cvssV2_severity}}
'''
self.add_column(title="Severity (V2)",
help_text="Severity of the CVE (v2)",
@@ -447,15 +458,11 @@ class SelectCveTable(ToasterTable):
hidden=True,
orderable=False,
static_data_name='severity_v2',
- static_data_template=severity_v2_template)
-
-
-#{{keyscore|get_dict_value:data.name}}
-#{{keysfor|get_dict_value:data.name}}
-#{{keysagainst|get_dict_value:data.name}}
+ static_data_template=severity_v2_template,
+ )
for_template = '''
- {{keysfor|get_dict_value:data.name}}
+ {{keysfor|get_dict_value:data.name}}
'''
self.add_column(title="Reasons For",
help_text="Keywords for accepting this CVE",
@@ -466,7 +473,7 @@ class SelectCveTable(ToasterTable):
)
against_template = '''
- {{keysagainst|get_dict_value:data.name}}
+ {{keysagainst|get_dict_value:data.name}}
'''
self.add_column(title="Reasons Against",
help_text="Keywords for not accepting this CVE",
@@ -477,15 +484,15 @@ class SelectCveTable(ToasterTable):
)
-class AllDefectTable(ToasterTable):
- """Table of All Defects's in SRTool"""
+class DefectsTable(ToasterTable):
+ """Table of All Defects in SRTool"""
def __init__(self, *args, **kwargs):
- super(AllDefectTable, self).__init__(*args, **kwargs)
+ super(DefectsTable, self).__init__(*args, **kwargs)
self.default_orderby = "name"
def get_context_data(self, **kwargs):
- context = super(AllDefectTable, self).get_context_data(**kwargs)
+ context = super(DefectsTable, self).get_context_data(**kwargs)
return context
@@ -493,102 +500,47 @@ class AllDefectTable(ToasterTable):
# Priority filter
is_priority = TableFilter(name="is_priority",
title="Filter defects by 'Priority'")
- exec_is_low = TableFilterActionToggle(
- "low",
- "Low",
- Q(priority=Defect.LOW))
- exec_is_medium = TableFilterActionToggle(
- "medium",
- "Medium",
- Q(priority=Defect.MEDIUM))
- exec_is_high = TableFilterActionToggle(
- "high",
- "High",
- Q(priority=Defect.HIGH))
- is_priority.add_action(exec_is_low)
- is_priority.add_action(exec_is_medium)
- is_priority.add_action(exec_is_high)
+ for priority in range(len(Defect.Priority)):
+ is_priority.add_action(TableFilterActionToggle(
+ Defect.Priority[priority][1].lower().replace(' ','_'),
+ Defect.Priority[priority][1],
+ Q(resolution=Defect.Priority[priority][0]))
+ )
self.add_filter(is_priority)
# Status filter
is_status = TableFilter(name="is_status",
title="Filter defects by 'Status'")
- exec_is_open = TableFilterActionToggle(
- "open",
- "Open",
- Q(status=Defect.OPEN))
- exec_is_in_progress = TableFilterActionToggle(
- "in_progress",
- "In progress",
- Q(status=Defect.IN_PROGRESS))
- exec_is_on_hold = TableFilterActionToggle(
- "on_hold",
- "On Hold",
- Q(status=Defect.ON_HOLD))
- exec_is_checked_in = TableFilterActionToggle(
- "checked_in",
- "Checked In",
- Q(status=Defect.CHECKED_IN))
- exec_is_resolved = TableFilterActionToggle(
- "resolved",
- "Resolved",
- Q(status=Defect.RESOLVED))
- exec_is_closed = TableFilterActionToggle(
- "closed",
- "Closed",
- Q(status=Defect.CLOSED))
- is_status.add_action(exec_is_open)
- is_status.add_action(exec_is_in_progress)
- is_status.add_action(exec_is_on_hold)
- is_status.add_action(exec_is_checked_in)
- is_status.add_action(exec_is_resolved)
- is_status.add_action(exec_is_closed)
+ for status in range(len(Defect.Status)):
+ is_status.add_action(TableFilterActionToggle(
+ Defect.Status[status][1].lower().replace(' ','_'),
+ Defect.Status[status][1],
+ Q(resolution=Defect.Status[status][0]))
+ )
self.add_filter(is_status)
# Resolution filter
is_resolution = TableFilter(name="is_resolution",
title="Filter defects by 'Resolution'")
- exec_is_unresolved = TableFilterActionToggle(
- "unresolved",
- "Unresolved",
- Q(resolution=Defect.UNRESOLVED))
- exec_is_fixed = TableFilterActionToggle(
- "fixed",
- "Fixed",
- Q(resolution=Defect.FIXED))
- exec_is_will_not_fix = TableFilterActionToggle(
- "will_not_fix",
- "Will Not Fix",
- Q(resolution=Defect.WILL_NOT_FIX))
- exec_is_withdrawn = TableFilterActionToggle(
- "withdrawn",
- "Withdrawn",
- Q(resolution=Defect.WITHDRAWN))
- exec_is_rejected = TableFilterActionToggle(
- "rejected",
- "Rejected",
- Q(resolution=Defect.REJECTED))
- exec_is_duplicate = TableFilterActionToggle(
- "duplicate",
- "Duplicate",
- Q(resolution=Defect.DUPLICATE))
- is_resolution.add_action(exec_is_unresolved)
- is_resolution.add_action(exec_is_fixed)
- is_resolution.add_action(exec_is_will_not_fix)
- is_resolution.add_action(exec_is_withdrawn)
- is_resolution.add_action(exec_is_rejected)
- is_resolution.add_action(exec_is_duplicate)
+ for resolution in range(len(Defect.Resolution)):
+ is_resolution.add_action(TableFilterActionToggle(
+ Defect.Resolution[resolution][1].lower().replace(' ','_'),
+ Defect.Resolution[resolution][1],
+ Q(resolution=Defect.Resolution[resolution][0]))
+ )
self.add_filter(is_resolution)
# Product filter
#(name="Wind River Linux",version="LTS-17")
is_product = TableFilter(name="is_product",
title="Filter defects by 'Product'")
- for p in Product.objects.all():
+ for product in Product.objects.all():
+ _log("PRODUCTS:%s,%s"% (product.defect_prefix,product.long_name))
is_product.add_action( TableFilterActionToggle(
- p.defect_prefix,
- p.long_name(),
- Q(product=p)) )
+ product.defect_prefix,
+ product.long_name,
+ Q(product=product))
+ )
self.add_filter(is_product)
@@ -601,16 +553,15 @@ class AllDefectTable(ToasterTable):
def setup_columns(self, *args, **kwargs):
name_link_template = '''
- <a href="http://defect.wrs.com/browse/{{data.name}}" target="_blank">
- {{data.name}}
- </a>
+ <a href="{% url 'defect' data.id %}" id="dataid_{{data.id}}">{{data.name}}</a>
'''
self.add_column(title="Name",
hideable=False,
orderable=True,
field_name="name",
static_data_name="name",
- static_data_template=name_link_template)
+ static_data_template=name_link_template,
+ )
self.add_column(title="Summary",
field_name="summary",
@@ -622,25 +573,25 @@ class AllDefectTable(ToasterTable):
orderable=True,
filter_name="is_priority",
static_data_name="priority",
- static_data_template='{{data.get_priority_text}}'
+ static_data_template='{{data.get_priority_text}}',
)
-
+
self.add_column(title="Status",
hideable=False,
field_name="status",
orderable=True,
filter_name="is_status",
static_data_name="status",
- static_data_template='{{data.get_status_text}}'
+ static_data_template='{{data.get_status_text}}',
)
-
- self.add_column(title="resolution",
+
+ self.add_column(title="Resolution",
hideable=False,
field_name="resolution",
orderable=True,
filter_name="is_resolution",
static_data_name="resolution",
- static_data_template='{{data.get_resolution_text}}'
+ static_data_template='{{data.get_resolution_text}}',
)
self.add_column(title="Release Version",
@@ -649,53 +600,64 @@ class AllDefectTable(ToasterTable):
field_name="release_version",
)
- self.add_column(title="Publish OLS",
+ self.add_column(title="Publish",
hideable=True,
orderable=True,
- field_name="publishOLS",
+ field_name="publish",
+ )
+
+ url_link_template = '''
+ <a href="{{data.url}}" target="_blank">{{data.url}}</a>
+ '''
+ self.add_column(title="URL",
+ field_name="url",
+ hideable=True,
+ hidden=True,
+ static_data_name="url",
+ static_data_template=url_link_template,
)
#date_created = models.DateField(null=True, blank=True)
#date_updated = models.DateField(null=True, blank=True)
investigations_link_template = '''
- {% for ji in data.defect_to_investigation.all %}
- {% if not forloop.first %}| {% endif %}<a href="{% url 'investigation' ji.investigation.id %}" target="_blank">{{ji.investigation.name}} </a>
- {% endfor %}
+ {% for ji in data.defect_to_investigation.all %}
+ {% if not forloop.first %}| {% endif %}<a href="{% url 'investigation' ji.investigation.id %}" target="_blank">{{ji.investigation.name}} </a>
+ {% endfor %}
'''
self.add_column(title="Investigation",
hideable=True,
# orderable=True, # multiple investigations
static_data_name="investigation",
- static_data_template=investigations_link_template
+ static_data_template=investigations_link_template,
)
# !!! HACK: 'data.product' is returning '%s' when it is supposed to be null !!!
product_link_template = '''
- {% if data.product != '%s' %}
- <a href="{% url 'products'%}">
- {{data.product.long_name}}
- </a>
- {% endif %}
+ {% if data.product != '%s' %}
+ <a href="{% url 'product' data.product.id %}">
+ {{data.product.long_name}}
+ </a>
+ {% endif %}
'''
self.add_column(title="Product",
hideable=True,
orderable=True,
filter_name="is_product",
static_data_name="product",
- static_data_template=product_link_template
+ static_data_template=product_link_template,
)
-class AllCweTable(ToasterTable):
+class CwesTable(ToasterTable):
"""Table of All CWE's in SRTool"""
def __init__(self, *args, **kwargs):
- super(AllCweTable, self).__init__(*args, **kwargs)
+ super(CwesTable, self).__init__(*args, **kwargs)
self.default_orderby = "name_sort"
def get_context_data(self, **kwargs):
- context = super(AllCweTable, self).get_context_data(**kwargs)
+ context = super(CwesTable, self).get_context_data(**kwargs)
return context
@@ -719,28 +681,22 @@ class AllCweTable(ToasterTable):
def setup_columns(self, *args, **kwargs):
- name_link_template = '''
- <a href="cwelink_{{data.name}}"></a>
- {{data.name}}
- '''
self.add_column(title="Name",
+ field_name="name",
hideable=False,
orderable=True,
- field_name="name_sort",
- static_data_name="name_sort",
- static_data_template=name_link_template)
+ )
href_link_template = '''
- <a href="{{data.href}}" target="_blank">
- {{data.href}}
- </a>
+ <a href="{{data.href}}" id="dataid_{{data.id}} target="_blank">{{data.href}}</a>
'''
self.add_column(title="Link",
hideable=False,
orderable=False,
field_name="href",
static_data_name="href",
- static_data_template=href_link_template)
+ static_data_template=href_link_template,
+ )
self.add_column(title="Summary",
field_name="summary",
@@ -758,23 +714,23 @@ class AllCweTable(ToasterTable):
static_data_name="cves",
static_data_template='{{data.vulnerable_count}}',
)
-
+
# self.add_column(title="CVE's",
# hidden=False,
# static_data_name="cves",
# static_data_template='{{data.cwe2cve.all.count}}',
# )
-
-class AllCpeTable(ToasterTable):
+
+class CpesTable(ToasterTable):
"""Table of All CPE's in SRTool"""
def __init__(self, *args, **kwargs):
- super(AllCpeTable, self).__init__(*args, **kwargs)
+ super(CpesTable, self).__init__(*args, **kwargs)
self.default_orderby = "vulnerable"
def get_context_data(self, **kwargs):
- context = super(AllCpeTable, self).get_context_data(**kwargs)
+ context = super(CpesTable, self).get_context_data(**kwargs)
return context
def setup_filters(self, *args, **kwargs):
@@ -808,20 +764,13 @@ class AllCpeTable(ToasterTable):
# cpeMatchString = models.TextField(blank=True)
# cpe23Uri = models.TextField(blank=True)
- vulnerable_link_template = '''
- {% if data.vulnerable %}
- Yes
- {% else %}
- No
- {% endif %}
- '''
self.add_column(title="Vulnerable",
field_name="vulnerable",
hideable=False,
orderable=True,
filter_name="is_vulnerable",
static_data_name="vulnerable",
- static_data_template=vulnerable_link_template
+ static_data_template="{% if data.vulnerable %}Yes{% else %}No{% endif %}",
)
self.add_column(title="CPE 2.3",
@@ -845,16 +794,17 @@ class AllCpeTable(ToasterTable):
)
cve_link_template = '''
- {% for pv in data.cpe2cve.all %}
- {% if not forloop.first %}| {% endif %}<a href="{% url 'cve' pv.cve.id %}">{{pv.cve.name}} </a>
- {% endfor %}
+ {% for pv in data.cpe2cve.all %}
+ {% if not forloop.first %}| {% endif %}<a href="{% url 'cve' pv.cve.id %}">{{pv.cve.name}} </a>
+ {% endfor %}
'''
self.add_column(title="CVE",
hideable=False,
orderable=True,
field_name="cveName",
static_data_name="cveName",
- static_data_template=cve_link_template)
+ static_data_template=cve_link_template,
+ )
class ManageCpeTable(ToasterTable):
@@ -918,7 +868,7 @@ class ManageCpeTable(ToasterTable):
field_name="Select",
hideable=False,
static_data_name="select",
- static_data_template='<input type="checkbox" name="check_{{data.key_prime}}_{{data.key_sub}}" />'
+ static_data_template='<input type="checkbox" name="check_{{data.key_prime}}_{{data.key_sub}}" />',
)
@@ -928,7 +878,7 @@ class ManageCpeTable(ToasterTable):
orderable=True,
filter_name="is_status",
static_data_name="status",
- static_data_template="{{data.get_status_text}}"
+ static_data_template="{{data.get_status_text}}",
)
self.add_column(title="Company",
@@ -943,22 +893,15 @@ class ManageCpeTable(ToasterTable):
hideable=False,
orderable=True,
static_data_name="key_sub",
- static_data_template="{% if data.key_sub %}{{data.key_sub}}{% else %}(company){% endif %}"
+ static_data_template="{% if data.key_sub %}{{data.key_sub}}{% else %}(company){% endif %}",
)
- automatic_link_template = '''
- {% if data.automatic %}
- Yes
- {% else %}
- No
- {% endif %}
- '''
self.add_column(title="Automatic",
field_name="automatic",
hideable=False,
orderable=True,
static_data_name="automatic",
- static_data_template=automatic_link_template
+ static_data_template="{% if data.automatic %}Yes{% else %}No{% endif %}",
)
manage_link_template = '''
@@ -970,7 +913,7 @@ class ManageCpeTable(ToasterTable):
hideable=False,
orderable=True,
static_data_name="manage",
- static_data_template=manage_link_template
+ static_data_template=manage_link_template,
)
@@ -1015,14 +958,15 @@ class ProductsTable(ToasterTable):
def setup_columns(self, *args, **kwargs):
name_link_template = '''
- {{data.name}}
+ <a href="{% url 'product' data.id %}" id="dataid_{{data.id}}">{{data.name}}<a>
'''
self.add_column(title="Name",
hideable=False,
orderable=True,
field_name="name",
static_data_name="name",
- static_data_template=name_link_template)
+ static_data_template=name_link_template,
+ )
self.add_column(title="Version",
field_name="version",
@@ -1042,8 +986,8 @@ class ProductsTable(ToasterTable):
self.add_column(title="SRT CPE",
field_name="srt_cpe",
- hideable=False,
- )
+ hideable=True,
+ )
self.add_column(title="Defect Prefix",
field_name="defect_prefix",
@@ -1052,25 +996,25 @@ class ProductsTable(ToasterTable):
investigations_link_template = '''
- {% if data.product_investigation.all.count %}
- <a href="{% url 'investigations' %}?filter=is_product:{{data.defect_prefix}}&">
- {{data.product_investigation.all.count}}
- </a>
- {% else %}0{% endif %}
+ {% if data.product_investigation.all.count %}
+ <a href="{% url 'investigations' %}?filter=is_product:{{data.defect_prefix}}&">
+ {{data.product_investigation.all.count}}
+ </a>
+ {% else %}0{% endif %}
'''
self.add_column(title="Investigations",
field_name="investigations",
hidden=False,
static_data_name="investigations",
- static_data_template=investigations_link_template
+ static_data_template=investigations_link_template,
)
defects_link_template = '''
- {% if data.product_defect.all.count %}
- <a href="{% url 'all-defects' %}?filter=is_product:{{data.defect_prefix}}&">
- {{data.product_defect.all.count}}
- </a>
- {% else %}0{% endif %}
+ {% if data.product_defect.all.count %}
+ <a href="{% url 'defects' %}?filter=is_product:{{data.defect_prefix}}&">
+ {{data.product_defect.all.count}}
+ </a>
+ {% else %}0{% endif %}
'''
self.add_column(title="Defects",
field_name="defects",
@@ -1080,15 +1024,15 @@ class ProductsTable(ToasterTable):
)
-class AllVulnerabilitiesTable(ToasterTable):
+class VulnerabilitiesTable(ToasterTable):
"""Table of All Vulnerabilities in SRTool"""
def __init__(self, *args, **kwargs):
- super(AllVulnerabilitiesTable, self).__init__(*args, **kwargs)
+ super(VulnerabilitiesTable, self).__init__(*args, **kwargs)
self.default_orderby = "name"
def get_context_data(self, **kwargs):
- context = super(AllVulnerabilitiesTable, self).get_context_data(**kwargs)
+ context = super(VulnerabilitiesTable, self).get_context_data(**kwargs)
return context
@@ -1163,7 +1107,7 @@ class AllVulnerabilitiesTable(ToasterTable):
Vulnerability.objects.all()
# filter out hidden records
- userAccess = Access()
+ userAccess = Access(self.request.session.get('srt_user_id', '0'))
if not userAccess.is_admin():
self.queryset = self.queryset.exclude(public = False)
@@ -1172,37 +1116,37 @@ class AllVulnerabilitiesTable(ToasterTable):
def setup_columns(self, *args, **kwargs):
id_link_template = '''
- <a href="{% url 'vulnerability' data.id %}">
- {{data.name}}
- </a>
+ <a href="{% url 'vulnerability' data.id %}" id="dataid_{{data.id}}">{{data.name}}</a>
'''
self.add_column(title="ID",
hideable=False,
orderable=True,
field_name="name",
static_data_name="name",
- static_data_template=id_link_template)
+ static_data_template=id_link_template,
+ )
cve_link_template = '''
- {% for vc in data.vulnerability_to_cve.all %}
- {% if not forloop.first %}| {% endif %} <a href="{% url 'cve' vc.cve.pk %}">
- {{vc.cve.name}}
- </a>
- {% endfor %}
+ {% for vc in data.vulnerability_to_cve.all %}
+ {% if not forloop.first %}| {% endif %} <a href="{% url 'cve' vc.cve.pk %}">
+ {{vc.cve.name}}
+ </a>
+ {% endfor %}
'''
self.add_column(title="CVE",
hideable=False,
orderable=False,
field_name="cve__name",
static_data_name="cve__name",
- static_data_template=cve_link_template)
+ static_data_template=cve_link_template,
+ )
self.add_column(title="Status",
field_name="status",
hideable=False,
filter_name="is_status",
static_data_name="status",
- static_data_template="{{data.get_status_text}}"
+ static_data_template="{{data.get_status_text}}",
)
self.add_column(title="Outcome",
@@ -1210,7 +1154,7 @@ class AllVulnerabilitiesTable(ToasterTable):
hideable=False,
filter_name="is_outcome",
static_data_name="outcome",
- static_data_template="{{data.get_outcome_text}}"
+ static_data_template="{{data.get_outcome_text}}",
)
self.add_column(title="Severity",
@@ -1218,7 +1162,7 @@ class AllVulnerabilitiesTable(ToasterTable):
hideable=False,
filter_name="is_severity",
static_data_name="severity",
- static_data_template="{{data.get_severity_text}}"
+ static_data_template="{{data.get_severity_text}}",
)
self.add_column(title="Comments",
@@ -1226,62 +1170,82 @@ class AllVulnerabilitiesTable(ToasterTable):
hideable=True,
)
- userAccess = Access()
+ userAccess = Access(self.request.session.get('srt_user_id', '0'))
if userAccess.is_admin():
self.add_column(title="Comments Private",
field_name="comments_private",
hideable=True,
)
+ investigate_link_template = '''
+ {% for investigation in data.vulnerability_investigation.all %}
+ {% if not forloop.first %}| {% endif %}<a href="{% url 'investigation' investigation.id %}" target="_blank">{{investigation.name}}</a>
+ {% endfor %}
+ '''
+ self.add_column(title="Investigations",
+ static_data_name="vulnerability_investigation",
+ static_data_template=investigate_link_template,
+ hidden=False,
+ )
+
+ defect_link_template = '''
+ {% for investigation in data.vulnerability_investigation.all %}
+ {% for id in investigation.investigation_to_defect.all %}
+ {% if forloop.counter == 1 %}| {% endif %}<a href="{% url 'defect' id.defect.id %}" target="_blank">{{id.defect.name}}</a>
+ {% endfor %}
+ {% endfor %}
+ '''
+ self.add_column(title="Defects",
+ static_data_name="investigation_to_defect",
+ static_data_template=defect_link_template,
+ hidden=False,
+ )
+
+ # VulnerabilityProduct.AFFECTED = 0
product_link_template = '''
{% for vp in data.affected_products.all %}
- {% if vp.relation = 0 %}{% if not forloop.first %}| {% endif %}<a href="{% url 'products'%}" target="_blank">{{vp.product.defect_prefix}}</a>{% endif %}
- {% endfor %}
+ {% if vp.product != '%s' %}
+ {% if vp.relation == 0 %}{% if not forloop.first %}| {% endif %}<a href="{% url 'product' vp.product.id %}" target="_blank">{{vp.product.defect_prefix}}</a>{% endif %}
+ {% endfor %}
+ {% endif %}
'''
self.add_column(title="Products",
static_data_name="investigation_products",
static_data_template=product_link_template,
hidden=False,
)
- if False:
- self.add_column(title="Defects",
- static_data_name="investigation_defects",
- static_data_template='\
- 0',
- hidden=False,
- )
-class AllInvestigationsTable(ToasterTable):
+class InvestigationsTable(ToasterTable):
"""Table of All Investigations in SRTool"""
def __init__(self, *args, **kwargs):
- super(AllInvestigationsTable, self).__init__(*args, **kwargs)
+ super(InvestigationsTable, self).__init__(*args, **kwargs)
self.default_orderby = "name"
def get_context_data(self, **kwargs):
- context = super(AllInvestigationsTable, self).get_context_data(**kwargs)
+ context = super(InvestigationsTable, self).get_context_data(**kwargs)
return context
def setup_filters(self, *args, **kwargs):
# Status filter
is_status = TableFilter(name="is_status",
title="Filter Investigations by 'Status'")
- exec_is_investigate = TableFilterActionToggle(
+ is_status.add_action(TableFilterActionToggle(
"investigate",
"Investigate",
Q(status=Investigation.INVESTIGATE))
- exec_is_vulnerable = TableFilterActionToggle(
+ )
+ is_status.add_action(TableFilterActionToggle(
"vulnerable",
"Is Vulnerable",
Q(status=Investigation.VULNERABLE))
- exec_is_not_vulnerable = TableFilterActionToggle(
+ )
+ is_status.add_action(TableFilterActionToggle(
"not_vulnerable",
"Not Vulnerable",
Q(status=Investigation.NOT_VULNERABLE))
- is_status.add_action(exec_is_investigate)
- is_status.add_action(exec_is_vulnerable)
- is_status.add_action(exec_is_not_vulnerable)
+ )
self.add_filter(is_status)
# Outcome filter
@@ -1335,7 +1299,7 @@ class AllInvestigationsTable(ToasterTable):
for p in Product.objects.all():
is_product.add_action( TableFilterActionToggle(
p.defect_prefix,
- p.long_name(),
+ p.long_name,
Q(product=p)) )
self.add_filter(is_product)
@@ -1345,7 +1309,7 @@ class AllInvestigationsTable(ToasterTable):
Investigation.objects.all()
# filter out hidden records
- userAccess = Access()
+ userAccess = Access(self.request.session.get('srt_user_id', '0'))
if not userAccess.is_admin():
self.queryset = self.queryset.exclude(public = False)
@@ -1354,27 +1318,26 @@ class AllInvestigationsTable(ToasterTable):
def setup_columns(self, *args, **kwargs):
id_link_template = '''
- <a href="{% url 'investigation' data.id %}">
- {{data.name}}
- </a>
+ <a href="{% url 'investigation' data.id %}" id="dataid_{{data.id}}">{{data.name}}</a>
'''
self.add_column(title="ID",
hideable=False,
orderable=True,
field_name="name",
static_data_name="name",
- static_data_template=id_link_template)
+ static_data_template=id_link_template,
+ )
defect_link_template = '''
{% for ij in data.investigation_to_defect.all %}
- {% if not forloop.first %}| {% endif %}<a href="http://defect.wrs.com/browse/{{ij.defect.name}}" target="_blank">{{ij.defect.name}} </a>
+ {% if not forloop.first %}| {% endif %}<a href="{% url 'defect' ij.defect.id %}">{{ij.defect.name}} </a>
{% endfor %}
'''
self.add_column(title="Defects",
field_name="defect",
hideable=False,
static_data_name="defect",
- static_data_template=defect_link_template
+ static_data_template=defect_link_template,
)
self.add_column(title="Status",
@@ -1382,7 +1345,7 @@ class AllInvestigationsTable(ToasterTable):
hideable=True,
filter_name="is_status",
static_data_name="status",
- static_data_template="{{data.get_status_text}}"
+ static_data_template="{{data.get_status_text}}",
)
self.add_column(title="Outcome",
@@ -1390,15 +1353,20 @@ class AllInvestigationsTable(ToasterTable):
hideable=False,
filter_name="is_outcome",
static_data_name="outcome",
- static_data_template="{{data.get_outcome_text}}"
+ static_data_template="{{data.get_outcome_text}}",
)
+ release_version_template = '''
+ {% for ij in data.investigation_to_defect.all %}
+ {% if not forloop.first %}| {% endif %}<a href="{{ij.defect.url}}" target="_blank">{{ij.defect.release_version}} </a>
+ {% endfor %}
+ '''
self.add_column(title="Release Version",
# field_name="release_version",
orderable=True,
hideable=False,
- static_data_name="outcome",
- static_data_template="{{data.defect.release_version}}"
+ static_data_name="release_version",
+ static_data_template=release_version_template,
)
self.add_column(title="Severity",
@@ -1406,7 +1374,7 @@ class AllInvestigationsTable(ToasterTable):
filter_name="is_severity",
hideable=False,
static_data_name="severity",
- static_data_template="{{data.get_severity_text}}"
+ static_data_template="{{data.get_severity_text}}",
)
self.add_column(title="Comments",
@@ -1414,7 +1382,7 @@ class AllInvestigationsTable(ToasterTable):
hideable=True,
)
- userAccess = Access()
+ userAccess = Access(self.request.session.get('srt_user_id', '0'))
if userAccess.is_admin():
self.add_column(title="Comments Private",
field_name="comments_private",
@@ -1432,7 +1400,7 @@ class AllInvestigationsTable(ToasterTable):
# orderable=True,
filter_name="is_product",
static_data_name="investigation_products",
- static_data_template="<a href=\"{% url 'products' %}\">{{data.product.long_name}}</a>",
+ static_data_template="<a href=\"{% url 'product' data.product.id %}\">{{data.product.long_name}}</a>",
)
@@ -1468,7 +1436,7 @@ class KeywordsTable(ToasterTable):
Keywords.objects.all()
# # filter out hidden records
-# userAccess = Access()
+# userAccess = Access(self.request.session.get('srt_user_id', '0'))
# if not userAccess.is_admin():
# self.queryset = self.queryset.exclude(public = False)
@@ -1504,5 +1472,278 @@ class KeywordsTable(ToasterTable):
hideable=False,
orderable=False,
static_data_name="manage",
- static_data_template=manage_link_template)
+ static_data_template=manage_link_template,
+ )
+
+
+class SourcesTable(ToasterTable):
+ """Table of All Data Sources in SRTool"""
+
+ def __init__(self, *args, **kwargs):
+ super(SourcesTable, self).__init__(*args, **kwargs)
+ self.default_orderby = "data"
+
+ def get_context_data(self, **kwargs):
+ context = super(SourcesTable, self).get_context_data(**kwargs)
+ return context
+
+ def setup_queryset(self, *args, **kwargs):
+ self.queryset = \
+ DataSource.objects.all()
+
+ self.queryset = self.queryset.order_by(self.default_orderby)
+
+ def setup_columns(self, *args, **kwargs):
+
+ self.add_column(title="Data",
+ hideable=False,
+ orderable=True,
+ field_name="data",
+ static_data_name="data",
+ static_data_template='<span id="dataid_{{data.id}}">{{data.data}}</span>',
+ )
+
+ self.add_column(title="Source",
+ hideable=False,
+ orderable=True,
+ field_name="source",
+ )
+
+ self.add_column(title="Type",
+ hideable=False,
+ orderable=True,
+ field_name="type",
+ )
+
+ self.add_column(title="Description",
+ hideable=False,
+ orderable=False,
+ field_name="description",
+ )
+
+ self.add_column(title="File Path",
+ hideable=True,
+ hidden=True,
+ orderable=False,
+ field_name="file_path",
+ )
+
+ self.add_column(title="URL",
+ hideable=True,
+ hidden=True,
+ orderable=False,
+ field_name="url",
+ )
+
+ self.add_column(title="Meta URL",
+ hideable=True,
+ hidden=True,
+ orderable=False,
+ field_name="meta_url",
+ )
+
+ self.add_column(title="Data Modified",
+ hideable=False,
+ orderable=True,
+ field_name="lastModifiedDate",
+ )
+
+ self.add_column(title="Updates",
+ hideable=False,
+ orderable=True,
+ field_name="update_frequency",
+ static_data_name="update_frequency",
+ static_data_template="{{data.get_frequency_text}}",
+ )
+
+ self.add_column(title="Updated",
+ hideable=False,
+ orderable=True,
+ field_name="update_time",
+ )
+
+ self.add_column(title="Command",
+ hideable=True,
+ orderable=False,
+ field_name="command",
+ )
+
+
+class SelectPublishTable(ToasterTable):
+ """Table of Publishable CVE's in SRTool"""
+
+ def __init__(self, *args, **kwargs):
+ super(SelectPublishTable, self).__init__(*args, **kwargs)
+ self.default_orderby = "name"
+ _log("SelectPublishTable:__init")
+
+ def get_context_data(self,**kwargs):
+ _log("SelectPublishTable:get_context_data")
+ context = super(SelectPublishTable, self).get_context_data(**kwargs)
+ return context
+
+ def setup_filters(self, *args, **kwargs):
+ _log("SelectPublishTable:setup_filters")
+ # Status filter
+ is_status = TableFilter(name="is_status",
+ title="Filter CVE's by 'Status")
+ is_status.add_action(TableFilterActionToggle(
+ "new",
+ "New",
+ Q(status=Cve.NEW))
+ )
+ is_status.add_action(TableFilterActionToggle(
+ "investigate",
+ "Investigate",
+ Q(status=Cve.INVESTIGATE))
+ )
+ is_status.add_action(TableFilterActionToggle(
+ "vulnerable",
+ "Is Vulnerable",
+ Q(status=Cve.VULNERABLE))
+ )
+ is_status.add_action(TableFilterActionToggle(
+ "not_vulnerable",
+ "Not Vulnerable",
+ Q(status=Cve.NOT_VULNERABLE))
+ )
+ self.add_filter(is_status)
+
+ def setup_queryset(self, *args, **kwargs):
+ _log("SelectPublishTable:setup_queryset")
+ self.queryset = \
+ Cve.objects.filter(publish_state = Cve.PUBLISH_REQUEST) | \
+ Cve.objects.filter(publish_state = Cve.PUBLISH_UPDATE)
+
+ _log("SelectPublishTable1:%s" % len(self.queryset))
+
+ # filter out hidden records !!! ALL NEW ONES SHOULD BE PUBLIC
+# userAccess = Access(self.request.session.get('srt_user_id', '0'))
+# if not userAccess.is_admin():
+# self.queryset = self.queryset.exclude(public = False)
+
+ self.queryset = self.queryset.order_by(self.default_orderby)
+
+ def setup_columns(self, *args, **kwargs):
+
+ _log("SelectPublishTable:setup_columns")
+
+ self.add_column(title="Select",
+ field_name="Select",
+ hideable=False,
+ static_data_name="select",
+ static_data_template='<input type="checkbox" name="{{data.name}}" />',
+ )
+
+ self.add_column(title="Status",
+ field_name="status",
+ hideable=False,
+ orderable=True,
+ filter_name="is_status",
+ static_data_name="status",
+ static_data_template="{{data.get_status_text}}",
+ )
+
+ id_link_template = '''
+ <a href="{% url 'cve' data.id %}" id="dataid_{{data.id}}" target="_blank">{{data.name}}</a>
+ '''
+ self.add_column(title="Name",
+ hideable=False,
+ orderable=True,
+ field_name="name",
+ static_data_name="name",
+ static_data_template=id_link_template,
+ )
+
+ self.add_column(title="Publish Request",
+ field_name="publish_state",
+ hideable=False,
+ static_data_name="publish_state",
+ static_data_template="{{data.get_publish_text}}",
+ )
+
+ self.add_column(title="Request Date",
+ field_name="publish_date",
+ hideable=False,
+ static_data_name="publish_date",
+ static_data_template="{% if data.publish_date %}{{data.publish_date}}{% else %}ASAP{% endif %}",
+ )
+
+ severity_v3_template = '''
+ {{data.cvssV3_baseScore}} {{data.cvssV3_baseSeverity}}
+ '''
+ self.add_column(title="Severity (V3)",
+ help_text="Severity of the CVE (v3)",
+ hideable=False,
+ orderable=False,
+ static_data_name='severity_v3',
+ static_data_template=severity_v3_template,
+ )
+
+ self.add_column(title="Description",
+ field_name="description",
+ hideable=False,
+ )
+
+class UpdatePublishedTable(ToasterTable):
+ """Table of Publish requested CVE's in SRTool"""
+
+ def __init__(self, *args, **kwargs):
+ super(UpdatePublishedTable, self).__init__(*args, **kwargs)
+ self.default_orderby = "date"
+
+ def get_context_data(self,**kwargs):
+ context = super(UpdatePublishedTable, self).get_context_data(**kwargs)
+ return context
+
+ def setup_queryset(self, *args, **kwargs):
+ self.queryset = PublishPending.objects.all()
+ self.queryset = self.queryset.order_by(self.default_orderby)
+
+ def setup_columns(self, *args, **kwargs):
+
+ self.add_column(title="Select",
+ field_name="Select",
+ hideable=False,
+ static_data_name="select",
+ static_data_template='<input type="checkbox" name="{{data.cve.name}}" />',
+ )
+
+ self.add_column(title="Status",
+ field_name="status",
+ hideable=False,
+ orderable=True,
+ static_data_name="status",
+ static_data_template="{{data.cve.get_status_text}}",
+ )
+
+ id_link_template = '''
+ <a href="{% url 'cve' data.cve.id %}" id="dataid_{{data.cve.id}}" target="_blank">{{data.cve.name}}</a>
+ '''
+ self.add_column(title="Name",
+ hideable=False,
+ orderable=True,
+ field_name="name",
+ static_data_name="name",
+ static_data_template=id_link_template,
+ )
+
+ self.add_column(title="Publish Request",
+ field_name="publish_state",
+ hideable=False,
+ static_data_name="publish_state",
+ static_data_template="{{data.cve.get_publish_text}}",
+ )
+
+ self.add_column(title="Publish Request Date",
+ field_name="date",
+ hideable=False,
+ orderable=True,
+ )
+
+ if False:
+ self.add_column(title="Note",
+ field_name="note",
+ hideable=False,
+ )
diff --git a/lib/srtgui/templates/base.html b/lib/srtgui/templates/base.html
index 3cc98a49..527d6b9b 100644
--- a/lib/srtgui/templates/base.html
+++ b/lib/srtgui/templates/base.html
@@ -148,9 +148,15 @@ window.onclick = function(event) {
</div>
<div class="collapse navbar-collapse" id="global-nav">
<ul class="nav navbar-nav">
+ <li id="navbar-home" {% if request.resolver_match.url_name == 'landing' %}class="active"{% endif %}>
+ <a href="{% url 'landing' %}">
+ <i class="glyphicon glyphicon-tasks"></i>
+ Home
+ </a>
+ </li>
{% if access.is_guest %}
{% else %}
- <li id="navbar-manage" class="active">
+ <li id="navbar-manage" {% if request.resolver_match.url_name == 'manage' %}class="active"{% endif %}>
<a href="{% url 'manage' %}">
<i class="glyphicon glyphicon-tasks"></i>
Management
@@ -158,18 +164,18 @@ window.onclick = function(event) {
</li>
{% endif %}
{% if request.resolver_match.url_name != 'landing' %}
- <li id="navbar-all-builds"
- {% if request.resolver_match.url_name == 'all-cves' %}
+ <li id="navbar-all-cves"
+ {% if request.resolver_match.url_name == 'cves' %}
class="active"
{% endif %}>
- <a href="{% url 'all-cves' %}">
+ <a href="{% url 'cves' %}">
<i class="glyphicon glyphicon-tasks"></i>
All CVE's
</a>
</li>
{% endif %}
<li id="navbar-docs">
- <a href="{% url 'guided_tour' %}"> <i class="glyphicon glyphicon-book"></i> Documentation </a>
+ <a href="{% url 'guided_tour' %}"> <i class="glyphicon glyphicon-book"></i> Documentation ({{srt_user_id}},{{access.current_user_access}})</a>
<!--
<a target="_blank" href="https://knowledge.windriver.com/en-us/000_Products/000/010/050">
<i class="glyphicon glyphicon-book"></i>
@@ -180,7 +186,7 @@ window.onclick = function(event) {
</ul>
{% if access.is_guest %}
- <a class="btn btn-default navbar-btn navbar-right" id="login-button" href="{% url 'login_admin' %}">Login (Guest)</a>
+ <a class="btn btn-default navbar-btn navbar-right" id="login-button" href="{% url 'login' %}">Login (Guest)</a>
{% else %}
<a class="btn btn-default navbar-btn navbar-right" id="login-button" href="{% url 'login_guest' %}">Logout ({{access.user_name}})</a>
{% endif %}
@@ -189,19 +195,9 @@ window.onclick = function(event) {
<button onclick="myFunction()" class="dropbtn ">Tools</button>
<div id="myDropdown" class="dropdown-content">
{% if request.resolver_match.url_name == 'landing' %}
- {% if access.is_creator %}
- <a href="{% url 'users' %}">Users</a>
- <a href="{% url 'sources' %}">Sources</a>
- <a href="{% url 'manage' %}">Management</a>
- {% endif %}
- <a href="{% url 'export' request.resolver_match.url_name %}">Report ...</a>
- <a href="{% url 'export' request.resolver_match.url_name %}">Export ...</a>
+ <a href="{% url 'report' request.resolver_match.url_name %}">Report/Export ...</a>
{% else %}
- {% if access.is_creator %}
- <a href="">Edit ...</a>
- {% endif %}
- <a href="{% url 'export' request.resolver_match.url_name %}">Report ...</a>
- <a href="{% url 'export' request.resolver_match.url_name %}">Export ...</a>
+ <a id="report_link" href="{% url 'report' request.resolver_match.url_name %}">Report/Export ...</a>
{% endif %}
</div>
</div>
diff --git a/lib/srtgui/templates/cpes-toastertable.html b/lib/srtgui/templates/cpes-toastertable.html
index 58101e2a..8c92c012 100644
--- a/lib/srtgui/templates/cpes-toastertable.html
+++ b/lib/srtgui/templates/cpes-toastertable.html
@@ -29,7 +29,8 @@
<h1 class="top-air" data-role="page-title"></h1>
</div>
- {% url 'cpes' as xhr_table_url %}
+ {# xhr_table_url is just the current url so leave it blank #}
+ {% url '' as xhr_table_url %}
{% include 'toastertable.html' %}
</div>
</div>
diff --git a/lib/srtgui/templates/cve.html b/lib/srtgui/templates/cve.html
index b1df1819..a70448f8 100644
--- a/lib/srtgui/templates/cve.html
+++ b/lib/srtgui/templates/cve.html
@@ -8,357 +8,452 @@
<div class="row">
<!-- Breadcrumbs -->
- <div class="col-md-12">
- <ul class="breadcrumb" id="breadcrumb">
- <li><a href="{% url 'landing' %}">Home</a></li><span class="divider">&rarr;</span>
- <li><a href="{% url 'all-cves' %}">CVE's</a></li><span class="divider">&rarr;</span>
- <li>{{cve_list_table.0.0.name}}</li>
- <li><a class="btn btn-default navbar-btn " id="cve-prev" href="{% url 'cve' cve_prev %}">Prev</a></li>
- <li><a class="btn btn-default navbar-btn " id="cve-next" href="{% url 'cve' cve_next %}">Next</a></li>
- </ul>
- </div>
+ <div class="col-md-12">
+ <ul class="breadcrumb" id="breadcrumb">
+ <li><a href="{% url 'landing' %}">Home</a></li><span class="divider">&rarr;</span>
+ <li><a href="{% url 'cves' %}">CVE's</a></li><span class="divider">&rarr;</span>
+ <li>{{cve_list_table.0.0.name}}</li>
+ <li><a class="btn btn-default navbar-btn " id="cve-prev" href="{% url 'cve' cve_prev %}">Prev</a></li>
+ <li><a class="btn btn-default navbar-btn " id="cve-next" href="{% url 'cve' cve_next %}">Next</a></li>
+ </ul>
+ </div>
</div>
<!-- Begin container -->
+
<div class="row">
<div class="col-md-12">
<div class="page-header build-data">
- <h1>{{cve_list_table.0.0.name}} Detail {% if not cve_list_table.0.0.public %} <font color="red">[PRIVATE]</font> {% endif %}</h1>
+ <h1 style="display:inline-block;vertical-align: middle;">{{cve_list_table.0.0.name}} Detail {% if not cve_list_table.0.0.public %} <font color="red">[PRIVATE]</font> {% endif %}</h1>
+ {% if access.is_creator %}
+ <span style="padding-left:30px;"><button id="select-quickedit" class="btn btn-default" type="button">Edit SRTool Status...</button></span>
+ <!--<span style="padding-left:30px;"><button id="select-quickedit" class="btn btn-default" type="button">Edit CVE Data ...</button></span>-->
+ {% endif %}
</div>
</div>
</div>
+
<div class="row" style="padding-left: 25px;">
<UL>
- <LI>
+ <LI>
+ <i>SRTool Priority:</i> {{cve_list_table.0.0.get_priority_text}}
+ </LI>
+ <LI>
<i>SRTool Status:</i> {{cve_list_table.0.0.get_status_text}}
- </LI>
- <LI>
+ </LI>
+ <LI>
<i>SRTool Notes:</i> '{{cve_list_table.0.0.comments}}'
- {% if access.is_creator %}
- </LI>
- <LI>
- <i>SRTool Private Notes:</i> '{{cve_list_table.0.0.comments_private}}'
- {% endif %}
- </LI>
- <LI>
- {% if access.is_creator %}
- <i>Publish</i> =
- <select name="Publish">
- <option value="Undetermined">Undetermined</option>
- <option value="Automatic Publish Date">Automatic Publish Date</option>
- <option value="Request Publish Date">Request Publish Date</option>
- <option value="Published">Published</option>
- <option value="Do Not Published">Do Not Published</option>
- </select>
- <i>Publish Date</i> = {{cve_list_table.0.0.publish_date}}
- <a class="btn btn-default " id="login-button" href="">Publish Now</a>
- <!--<a class="btn btn-default navbar-btn " id="login-button" href="">Publish Now</a> -->
- {% else %}
- <i>Publish</i> = {{cve_list_table.0.0.get_publish_text}}, <i>Publish Date</i> = {{cve_list_table.0.0.publish_date}}
- {% endif %}
- </LI>
+ {% if access.is_creator %}
+ </LI>
+ <LI>
+ <i>SRTool Private Notes:</i> '{{cve_list_table.0.0.comments_private}}'
+ {% endif %}
+ </LI>
+ <LI>
+ {% if access.is_creator %}
+ <i>Publish = {{cve_list_table.0.0.get_publish_text}}</i>
+ <!--<a class="btn btn-default navbar-btn " id="login-button" href="">Publish Now</a> -->
+ {% else %}
+ <i>Publish</i> = {{cve_list_table.0.0.get_publish_text}}, <i>Publish Date</i> = {{cve_list_table.0.0.publish_date}}
+ {% endif %}
+ </LI>
</UL>
+
+
+</div>
+<!-- Quick Edit -->
+<div id="details-quickedit" style="display:none;">
+ <p><p>
+ <button class="execute" id="submit-quickedit"> Submit Changes </button>
+ <p><i>Priority</i> =
+ <select name="Priority" id="select-priority-state">
+ <option value="0" {% if 0 == cve_list_table.0.0.priority %}selected{% endif %}></option>
+ <option value="1" {% if 1 == cve_list_table.0.0.priority %}selected{% endif %}>Minor</option>
+ <option value="2" {% if 2 == cve_list_table.0.0.priority %}selected{% endif %}>Low</option>
+ <option value="3" {% if 3 == cve_list_table.0.0.priority %}selected{% endif %}>Medium</option>
+ <option value="4" {% if 4 == cve_list_table.0.0.priority %}selected{% endif %}>High</option>
+ </select>
+ <p><input type="text" placeholder="Edit Note" id="text-note" size="40" value="{{cve_list_table.0.0.comments}}"></p>
+ <p><input type="text" placeholder="Edit Private Note" id="text-private-note" size="40" value="{{cve_list_table.0.0.comments_private}}"></p>
+ <i>Publish</i> =
+ <select name="Publish" id="select-publish-state">
+ <option value="0" {% if 0 == cve_list_table.0.0.publish_state %}selected{% endif %}>Unpublished</option>
+ <option value="1" {% if 1 == cve_list_table.0.0.publish_state %}selected{% endif %}>Not to be Published</option>
+ <option value="2" {% if 2 == cve_list_table.0.0.publish_state %}selected{% endif %}>Published</option>
+ <option value="3" {% if 3 == cve_list_table.0.0.publish_state %}selected{% endif %}>Publish Request (New)</option>
+ <option value="4" {% if 4 == cve_list_table.0.0.publish_state %}selected{% endif %}>Publish Request (Update)</option>
+ <option value="5" {% if 5 == cve_list_table.0.0.publish_state %}selected{% endif %}>Publish Submitted</option>
+ </select>
+ <i>Publish Date</i> = <input type="text" placeholder="Auto Publish Date" id="select-publish-date" size="40" value="{{cve_list_table.0.0.publish_date}}"><p>
+ <p><p>
</div>
<div class="row">
<div class="col-md-8 tabbable">
<ul class="nav nav-tabs">
- {% for object,state,id in cve_list_table %}
+ {% for object,details,state,id in cve_list_table %}
<li class="{{state}}">
<a href="#{{id}}" data-toggle="tab">
<span class="glyphicon glyphicon-question-sign get-help" title="{{id}}"></span>
{{id}}
</a>
</li>
- {% endfor %}
+ {% endfor %}
</ul>
<div class="tab-content">
- {% for object,state,id in cve_list_table %}
- <div class="tab-pane {{state}}" id="{{id}}">
+ {% for object,details,state,id in cve_list_table %}
+ <div class="tab-pane {{state}}" id="{{id}}">
<!-- vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -->
- <div class="row">
- <div class="col-md-5">
- <div>
- <h3>Decription</h3>
- {{object.description}}
- </div>
- <p/>
- <div>
- <B>Source:</B> {{object.cve_data_format}} <B>Last Modified:</B> {{object.lastModifiedDate}}
- </div>
- </div>
- <div class="col-md-5">
- <div class="well">
- <h2>Quick Info</h2>
-
-
- <dl class="dl-horizontal">
- <dt>CVE Dictionary Entry:</dt>
- <dd>{{object.name}}</dd>
-
- <dt>Original release date:</dt>
- <dd>{{object.publishedDate}}</dd>
-
- <dt>Last revised:</dt>
- <dd>{{object.lastModifiedDate}}</dd>
-
- <dt>Source:</dt>
- <dd>{{object.cve_data_format}}</dd>
-
- {% if id == "Summary" %}
- <dt>SRTool Vulnerability:</dt>
- <dd>
- {% if object.cve_to_vulnerability.all %}
- {% for cv in object.cve_to_vulnerability.all %}
- {% if not forloop.first %}| {% endif %}<a href="{% url 'vulnerability' cv.vulnerability.pk %}">{{cv.vulnerability.name}}</a>
- {% endfor %}
- {% else %}
- No vulnerability record found
- {% endif %}
- {% endif %}
- </dd>
- </dl>
- </div>
- </div>
- </div>
-
- <div class="row">
- <h3>Impact</h3>
- <div class="col-md-4">
- <h3>CVSS Severity (version 3.0):</h3>
- <dl class="dl-horizontal">
- <dt>CVSS v3 Base Score:</dt>
- <dd>{{object.cvssV3_baseScore}} {{object.cvssV3_baseSeverity}}</dd>
-
- <dt>Vector:</dt>
- <dd>{{object.cvssV3_vectorString}}</dd>
-
- <dt>Impact Score:</dt>
- <dd>{{object.cvssV3_impactScore}}</dd>
-
- <dt>Exploitability Score:</dt>
- <dd>{{object.cvssV3_exploitabilityScore}}</dd>
- </dl>
- <h3>CVSS Version 3 Metrics:</h3>
- <dl class="dl-horizontal">
- <dt>Attack Vector (AV):</dt>
- <dd>{{object.cvssV3_attackVector}}</dd>
-
- <dt>Attack Complexity (AC):</dt>
- <dd>{{object.cvssV3_attackComplexity}}</dd>
-
- <dt>Privileges Required (PR):</dt>
- <dd>{{object.cvssV3_privilegesRequired}}</dd>
-
- <dt>User Interaction (UI):</dt>
- <dd>{{object.cvssV3_userInteraction}}</dd>
-
- <dt>Scope (S):</dt>
- <dd>{{object.cvssV3_scope}}</dd>
-
- <dt>Confidentiality (C):</dt>
- <dd>{{object.cvssV3_confidentialityImpact}}</dd>
-
- <dt>Integrity (I):</dt>
- <dd>{{object.cvssV3_integrityImpact}}</dd>
-
- <dt>Availability (A):</dt>
- <dd>{{object.cvssV3_availabilityImpact}}</dd>
- </dl>
- </div>
- <div class="col-md-4">
- <h3>CVSS Severity (version 2.0):</h3>
- <dl class="dl-horizontal">
- <dt>CVSS v2 Base Score:</dt>
- <dd>{{object.cvssV2_baseScore}} {{object.cvssV2_severity}}</dd>
-
- <dt>Vector:</dt>
- <dd>{{object.cvssV2_vectorString}}</dd>
-
- <dt>Impact Subscore:</dt>
- <dd>{{object.cvssV2_impactScore}}</dd>
-
- <dt>Exploitability Subscore:</dt>
- <dd>{{object.cvssV2_exploitabilityScore}}</dd>
-
- </dl>
- <h3>CVSS Version 2 Metrics:</h3>
- <dl class="dl-horizontal">
- <dt>Access Vector (AV):</dt>
- <dd>{{object.cvssV2_accessVector}}</dd>
-
- <dt>Access Complexity (AC):</dt>
- <dd>{{object.cvssV2_accessComplexity}}</dd>
-
- <dt>Authentication:</dt>
- <dd>{{object.cvssV2_authentication}}</dd>
-
- <dt>Impact Type:</dt>
- <dd>???</dd>
-
- </dl>
- </div>
- </div>
-
- <div class="row">
- <h3>References to Advisories, Solutions, and Tools</h3>
- <p>
- By selecting these links, you will be leaving NIST webspace. We have provided these links to other web sites
- because they may have information that would be of interest to you. No inferences should be drawn on account
- of other sites being referenced, or not, from this page. There may be other web sites that are more appropriate
- for your purpose. NIST does not necessarily endorse the views expressed, or concur with the facts presented on
- these sites. Further, NIST does not endorse any commercial products that may be mentioned on these sites. Please
- address comments about this page to nvd@nist.gov.
- </p>
- <table class="table table-striped table-condensed" data-testid="vuln-hyperlinks-table">
- <thead>
- <tr>
- <th>Hyperlink</th>
- <th>Resource</th>
- <th>Type</th>
- <th>Source</th>
- <th>Name</th>
- </tr>
- </thead>
- {% if object.references.all %}
- {% for ref in object.references.all %}
- <tr>
- <td><a href="{{ref.hyperlink}}" target="_blank">{{ ref.hyperlink }}</a></td>
- <td>{{ ref.resource }}</td>
- <td>{{ ref.type }}</td>
- <td>{{ ref.source }}</td>
- <td>{{ ref.name }}</td>
- </tr>
- {% endfor %}
- {% else %}
- <tr>
- <td>No references</td>
- </tr>
- {% endif %}
- </table>
- </div>
-
- <div class="row">
- <h3>Technical Details</h3>
- <p>
- <h4>Vulnerability Type<a href="{% url 'all-cwes' %}"> (View All)</a></h4>
- <p>
- <table class="table table-striped table-condensed" data-testid="cve2cwe-hyperlinks-table">
- <thead>
- <tr>
- <th>Name</th>
- <th>Summary</th>
- </tr>
- </thead>
- {% if object.cve2cwe.all %}
- {% for ref in object.cve2cwe.all %}
- <tr>
- <td>{{ ref.cwe.name }}</td>
- <td>{{ ref.cwe.summary }}</td>
- </tr>
- {% endfor %}
- {% else %}
- <tr>
- <td>No CWE references</td>
- </tr>
- {% endif %}
- </table>
- </div>
-
- <div class="row">
- <h3>Vulnerable software and versions</h3>
- <div > <!--style="padding-left: 25px;" -->
- {% if object.get_cpe_list %}
- {% for cpe in object.get_cpe_list %}
- {% if not cpe %}
- {% elif not cpe.0 %}
- {% elif '<config' in cpe.0 %}
- <div style="padding-left: 25px;">
- <h4>&bull; Configuration </h3>
- {% elif '<and>' == cpe.0 %}
- <div style="padding-left: 25px;">
- <h4>&bull; AND</h3>
- {% elif '<or>' == cpe.0 %}
- <div style="padding-left: 25px;">
- <h4>&bull; OR</h3>
- <table class="table table-striped table-condensed" data-testid="configs-hyperlinks-table">
- <thead>
- <tr>
- <th>Vulnerable</th>
- <th>CPE 2.3</th>
- <th>CPE 2.2</th>
- <th><!--<span class="glyphicon glyphicon-question-sign get-help" title="Version End Including"></span>-->Version End</th>
- </tr>
- </thead>
- {% elif '</or>' == cpe.0 %}
- </table>
- </div>
- {% elif '</and>' == cpe.0 %}
- </div>
- {% elif '</config>' == cpe.0 %}
- </div>
- {% else %}
- <tr>
- <td>{{ cpe.0 }}</td>
- <td>{{ cpe.1 }}</td>
- <td>{{ cpe.2 }}</td>
- <td>{{ cpe.3 }}</td>
- </tr>
- {% endif %}
- {% endfor %}
- {% else %}
- No CPE configurations
- {% endif %}
- </div>
- <p/>
- </div>
-
-
- <div class="row">
- <h3>History
- </h3>
-
- <table class="table table-striped table-condensed" data-testid="vuln-hyperlinks-table">
- <thead>
- <tr>
- <th>Comment</th>
- <th>Date</th>
- <th>Author</th>
- </tr>
- </thead>
-
- {% if object.cve_history.all %}
- {% for c in object.cve_history.all %}
- <tr>
- <td>{{ c.comment }}</td>
- <td>{{ c.date }}</td>
- <td>{{ c.author }}</td>
- </tr>
- {% endfor %}
- {% else %}
- <tr>
- <td>No history found</td>
- </tr>
- {% endif %}
- </table>
-
- </div>
+ <!-- Row: Description and Quick Info -->
+ <div class="row">
+ <div class="col-md-5">
+ <div>
+ <h3>Decription</h3>
+ {{object.description}}
+ </div>
+ <p/>
+ <div>
+ <B>Source:</B> {{object.cve_data_format}} <B>Last Modified:</B> {{object.lastModifiedDate}}
+ </div>
+ </div>
+ <div class="col-md-5">
+ <div class="well">
+ <h2>Quick Info</h2>
+
+
+ <dl class="dl-horizontal">
+ <dt>CVE Dictionary Entry:</dt>
+ <dd>{{object.name}}</dd>
+
+ <dt>Original release date:</dt>
+ <dd>{{object.publishedDate}}</dd>
+
+ <dt>Last revised:</dt>
+ <dd>{{object.lastModifiedDate}}</dd>
+
+ <dt>Source:</dt>
+ <dd>{{object.cve_data_format}}</dd>
+
+ {% if id == "Summary" %}
+ <dt>SRTool Vulnerability:</dt>
+ <dd>
+ {% if object.cve_to_vulnerability.all %}
+ {% for cv in object.cve_to_vulnerability.all %}
+ {% if not forloop.first %}| {% endif %}<a href="{% url 'vulnerability' cv.vulnerability.pk %}">{{cv.vulnerability.name}}</a>
+ {% endfor %}
+ {% else %}
+ No vulnerability record found
+ {% endif %}
+ {% endif %}
+ </dd>
+
+ <dt>NIST Link:</dt>
+ <dd><a href="https://nvd.nist.gov/vuln/detail/{{object.name}}" target="_blank">{{object.name}}</a></dd>
+
+ </dl>
+ </div>
+ </div>
+ </div> <!-- /Description -->
+
+ <!-- Row: CVSS -->
+ <div class="row" style="padding-left: 25px;">
+ <h3>Impact</h3>
+ <div class="col-md-4">
+ <h3>CVSS Severity (version 3.0):</h3>
+ <dl class="dl-horizontal">
+ <dt>CVSS v3 Base Score:</dt>
+ <dd>{{object.cvssV3_baseScore}} {{object.cvssV3_baseSeverity}}</dd>
+
+ <dt>Vector:</dt>
+ <dd>{{details.cvssV3_vectorString}}</dd>
+
+ <dt>Impact Score:</dt>
+ <dd>{{details.cvssV3_impactScore}}</dd>
+
+ <dt>Exploitability Score:</dt>
+ <dd>{{details.cvssV3_exploitabilityScore}}</dd>
+ </dl>
+ <h3>CVSS Version 3 Metrics:</h3>
+ <dl class="dl-horizontal">
+ <dt>Attack Vector (AV):</dt>
+ <dd>{{details.cvssV3_attackVector}}</dd>
+
+ <dt>Attack Complexity (AC):</dt>
+ <dd>{{details.cvssV3_attackComplexity}}</dd>
+
+ <dt>Privileges Required (PR):</dt>
+ <dd>{{details.cvssV3_privilegesRequired}}</dd>
+
+ <dt>User Interaction (UI):</dt>
+ <dd>{{details.cvssV3_userInteraction}}</dd>
+
+ <dt>Scope (S):</dt>
+ <dd>{{details.cvssV3_scope}}</dd>
+
+ <dt>Confidentiality (C):</dt>
+ <dd>{{details.cvssV3_confidentialityImpact}}</dd>
+
+ <dt>Integrity (I):</dt>
+ <dd>{{details.cvssV3_integrityImpact}}</dd>
+
+ <dt>Availability (A):</dt>
+ <dd>{{details.cvssV3_availabilityImpact}}</dd>
+ </dl>
+ </div>
+ <div class="col-md-4">
+ <h3>CVSS Severity (version 2.0):</h3>
+ <dl class="dl-horizontal">
+ <dt>CVSS v2 Base Score:</dt>
+ <dd>{{object.cvssV2_baseScore}} {{details.cvssV2_severity}}</dd>
+
+ <dt>Vector:</dt>
+ <dd>{{details.cvssV2_vectorString}}</dd>
+
+ <dt>Impact Subscore:</dt>
+ <dd>{{details.cvssV2_impactScore}}</dd>
+
+ <dt>Exploitability Subscore:</dt>
+ <dd>{{details.cvssV2_exploitabilityScore}}</dd>
+
+ </dl>
+ <h3>CVSS Version 2 Metrics:</h3>
+ <dl class="dl-horizontal">
+ <dt>Access Vector (AV):</dt>
+ <dd>{{details.cvssV2_accessVector}}</dd>
+
+ <dt>Access Complexity (AC):</dt>
+ <dd>{{details.cvssV2_accessComplexity}}</dd>
+
+ <dt>Authentication:</dt>
+ <dd>{{details.cvssV2_authentication}}</dd>
+
+ <dt>Impact Type:</dt>
+ <dd>???</dd>
+
+ </dl>
+ </div>
+ </div> <!-- /CVSS -->
+
+ <!-- Row: References -->
+ <div class="row" style="padding-left: 25px;">
+ <h3>References to Advisories, Solutions, and Tools</h3>
+ <p>
+ By selecting these links, you will be leaving NIST webspace. We have provided these links to other web sites
+ because they may have information that would be of interest to you. No inferences should be drawn on account
+ of other sites being referenced, or not, from this page. There may be other web sites that are more appropriate
+ for your purpose. NIST does not necessarily endorse the views expressed, or concur with the facts presented on
+ these sites. Further, NIST does not endorse any commercial products that may be mentioned on these sites. Please
+ address comments about this page to nvd@nist.gov.
+ </p>
+ <table class="table table-striped table-condensed" data-testid="vuln-hyperlinks-table">
+ <thead>
+ <tr>
+ <th>Hyperlink</th>
+ <th>Resource</th>
+ </tr>
+ </thead>
+ {% if object.references.all %}
+ {% for ref in object.references.all %}
+ <tr>
+ <td><a href="{{ref.hyperlink}}" target="_blank">{{ ref.hyperlink }}</a></td>
+ <td>{{ ref.resource }}</td>
+ </tr>
+ {% endfor %}
+ {% else %}
+ <tr>
+ <td>No references</td>
+ </tr>
+ {% endif %}
+ </table>
+ </div> <!-- /References -->
+
+ <!-- Row: CWE -->
+ <div class="row" style="padding-left: 25px;">
+ <h3>Technical Details</h3>
+ <p>
+ <h4>Vulnerability Type<a href="{% url 'cwes' %}"> (View All)</a></h4>
+ <p>
+ <table class="table table-striped table-condensed" data-testid="cve2cwe-hyperlinks-table">
+ <thead>
+ <tr>
+ <th>Name</th>
+ <th>Summary</th>
+ </tr>
+ </thead>
+ {% if object.cve2cwe.all %}
+ {% for ref in object.cve2cwe.all %}
+ <tr>
+ <td>{{ ref.cwe.name }}</td>
+ <td>{{ ref.cwe.summary }}</td>
+ </tr>
+ {% endfor %}
+ {% else %}
+ <tr>
+ <td>No CWE references</td>
+ </tr>
+ {% endif %}
+ </table>
+ </div> <!-- /CWE -->
+
+ <!-- Row: CPE -->
+ <div class="row" style="padding-left: 25px;">
+ <h3>Vulnerable software and versions</h3>
+ <div > <!--style="padding-left: 25px;" -->
+ {% if details.get_cpe_list %}
+ {% for cpe in details.get_cpe_list %}
+ {% if not cpe %}
+ {% elif not cpe.0 %}
+ {% elif '[config' in cpe.0 %}
+ <div style="padding-left: 25px;">
+ <h4>&bull; Configuration </h3>
+ {% elif '[and]' == cpe.0 %}
+ <div style="padding-left: 25px;">
+ <h4>&bull; AND</h3>
+ {% elif '[or]' == cpe.0 %}
+ <div style="padding-left: 25px;">
+ <h4>&bull; OR</h3>
+ <table class="table table-striped table-condensed" data-testid="configs-hyperlinks-table">
+ <thead>
+ <tr>
+ <th>Vulnerable</th>
+ <th>CPE 2.3</th>
+ <th>CPE 2.2</th>
+ <th><!--<span class="glyphicon glyphicon-question-sign get-help" title="Version End Including"></span>-->Version End</th>
+ </tr>
+ </thead>
+ {% elif '[/or]' == cpe.0 %}
+ </table>
+ </div>
+ {% elif '[/and]' == cpe.0 %}
+ </div>
+ {% elif '[/config]' == cpe.0 %}
+ </div>
+ {% else %}
+ <tr>
+ <td>{{ cpe.0 }}</td>
+ <td>{{ cpe.1 }}</td>
+ <td>{{ cpe.2 }}</td>
+ <td>{{ cpe.3 }}</td>
+ </tr>
+ {% endif %}
+ {% endfor %}
+ {% else %}
+ No CPE configurations
+ {% endif %}
+ </div>
+ <p>
+ </div> <!-- /CPE -->
+
<!-- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -->
- </div> <!-- end tab-pane -->
+ </div> <!-- end tab-pane -->
{% endfor %}
</div> <!-- end tab-content -->
</div> <!-- end tabbable -->
</div> <!-- end row -->
+<div class="row" style="padding-left: 25px;">
+ <h3>History</h3>
+
+ <table class="table table-striped table-condensed" data-testid="vuln-hyperlinks-table">
+ <thead>
+ <tr>
+ <th>Comment</th>
+ <th>Date</th>
+ <th>Author</th>
+ </tr>
+ </thead>
+
+ {% if cve_list_table.1.0.cve_history.all %}
+ {% for c in cve_list_table.1.0.cve_history.all %}
+ <tr>
+ <td>{{ c.comment }}</td>
+ <td>{{ c.date }}</td>
+ <td>{{ c.author }}</td>
+ </tr>
+ {% endfor %}
+ {% else %}
+ <tr>
+ <td>No history found</td>
+ </tr>
+ {% endif %}
+ </table>
+</div>
+
<HR ALIGN="center" WIDTH="100%">
+<script>
+ var selected_quickedit=false;
+
+ $(document).ready(function() {
+ function onCommitAjaxSuccess(data, textstatus) {
+ if (window.console && window.console.log) {
+ console.log("XHR returned:", data, "(" + textstatus + ")");
+ } else {
+ alert("NO CONSOLE:\n");
+ return;
+ }
+ if (data.error != "ok") {
+ alert("error on request:\n" + data.error);
+ return;
+ }
+ // reload the page with the updated tables
+ location.reload(true);
+ }
+
+ function onCommitAjaxError(jqXHR, textstatus, error) {
+ console.log("ERROR:"+error+"|"+textstatus);
+ alert("XHR errored1:\n" + error + "\n(" + textstatus + ")");
+ }
+
+ /* ensure cookie exists {% csrf_token %} */
+ function postCommitAjaxRequest(reqdata) {
+ reqdata['cve_id'] = {{ object.id }};
+ var ajax = $.ajax({
+ type:"POST",
+ data: reqdata,
+ url:"{% url 'xhr_cve_commit' %}",
+ headers: { 'X-CSRFToken': $.cookie("csrftoken")},
+ success: onCommitAjaxSuccess,
+ error: onCommitAjaxError,
+ })
+ }
+
+ $('#select-quickedit').click(function(){
+ if (selected_quickedit) {
+ selected_quickedit=false;
+ $("#details-quickedit").slideUp();
+ } else {
+ selected_quickedit=true;
+ $("#details-quickedit").slideDown();
+ }
+ });
+
+ $('#submit-quickedit').click(function(){
+ var note=$('#text-note').val().trim();
+ var private_note=$('#text-private-note').val().trim();
+ var priority=$('#select-priority-state').val();
+ var publish_state=$('#select-publish-state').val();
+ var publish_date=$('#select-publish-date').val();
+ postCommitAjaxRequest({
+ "action" : 'submit-quickedit',
+ "priority" : priority,
+ "note" : note,
+ "private_note" : private_note,
+ "publish_state" : publish_state,
+ "publish_date" : publish_date,
+ });
+ });
+
+ /* Set the report link */
+ $('#report_link').attr('href',"{% url 'report' request.resolver_match.url_name %}?record_list={{cve_list_table.0.0.id}}");
+ });
+</script>
{% endblock %}
-
diff --git a/lib/srtgui/templates/cves-select-toastertable.html b/lib/srtgui/templates/cves-select-toastertable.html
index 8e2445b0..3399332e 100644
--- a/lib/srtgui/templates/cves-select-toastertable.html
+++ b/lib/srtgui/templates/cves-select-toastertable.html
@@ -111,7 +111,8 @@
<h1 class="top-air" data-role="page-title"></h1>
</div>
- {% url 'cpes' as xhr_table_url %}
+ {# xhr_table_url is just the current url so leave it blank #}
+ {% url '' as xhr_table_url %}
{% include 'toastertable.html' %}
</div>
</div>
@@ -338,6 +339,17 @@
titleElt.text(title);
cve_total = total;
update_vulnerable_status();
+
+ /* Set the report link */
+ var record_list=""
+ $(".name > a").each(function(){
+ var this_id=$(this).prop('id');
+ if (this_id.startsWith("dataid_")) {
+ record_list +=this_id.replace(/dataid_/,"") + ",";
+ }
+ });
+ $('#report_link').attr('href',"{% url 'report' request.resolver_match.url_name %}?record_list="+record_list);
+
});
});
</script>
diff --git a/lib/srtgui/templates/cves-toastertable.html b/lib/srtgui/templates/cves-toastertable.html
index fa83e5df..5fc37fdf 100644
--- a/lib/srtgui/templates/cves-toastertable.html
+++ b/lib/srtgui/templates/cves-toastertable.html
@@ -30,7 +30,8 @@
<h1 class="top-air" data-role="page-title"></h1>
</div>
- {% url 'cves' as xhr_table_url %}
+ {# xhr_table_url is just the current url so leave it blank #}
+ {% url '' as xhr_table_url %}
{% include 'toastertable.html' %}
</div>
</div>
@@ -53,6 +54,17 @@
}
titleElt.text(title);
+
+ /* Set the report link */
+ var record_list=""
+ $(".name > a").each(function(){
+ var this_id=$(this).prop('id');
+ if (this_id.startsWith("dataid_")) {
+ record_list +=this_id.replace(/dataid_/,"") + ",";
+ }
+ });
+ $('#report_link').attr('href',"{% url 'report' request.resolver_match.url_name %}?record_list="+record_list);
+
});
});
</script>
diff --git a/lib/srtgui/templates/cwes-toastertable.html b/lib/srtgui/templates/cwes-toastertable.html
index 06369343..cbd62a90 100644
--- a/lib/srtgui/templates/cwes-toastertable.html
+++ b/lib/srtgui/templates/cwes-toastertable.html
@@ -29,7 +29,8 @@
<h1 class="top-air" data-role="page-title"></h1>
</div>
- {% url 'cwes' as xhr_table_url %}
+ {# xhr_table_url is just the current url so leave it blank #}
+ {% url '' as xhr_table_url %}
{% include 'toastertable.html' %}
</div>
</div>
@@ -52,6 +53,17 @@
}
titleElt.text(title);
+
+ /* Set the report link */
+ var record_list=""
+ $(".href > a").each(function(){
+ var this_id=$(this).prop('id');
+ if (this_id.startsWith("dataid_")) {
+ record_list +=this_id.replace(/dataid_/,"") + ",";
+ }
+ });
+ $('#report_link').attr('href',"{% url 'report' request.resolver_match.url_name %}?record_list="+record_list);
+
});
});
</script>
diff --git a/lib/srtgui/templates/defect.html b/lib/srtgui/templates/defect.html
new file mode 100644
index 00000000..aa13b0dd
--- /dev/null
+++ b/lib/srtgui/templates/defect.html
@@ -0,0 +1,86 @@
+{% extends "base.html" %}
+
+{% load projecttags %}
+
+{% block title %} {{object.name}} - SRTool {% endblock %}
+
+{% block pagecontent %}
+
+<div class="row">
+ <!-- Breadcrumbs -->
+ <div class="col-md-12">
+ <ul class="breadcrumb" id="breadcrumb">
+ <li><a href="{% url 'landing' %}">Home</a></li><span class="divider">&rarr;</span>
+ <li><a href="{% url 'defects' %}">Defects</a></li><span class="divider">&rarr;</span>
+ <li>{{object.name}}</li>
+ </ul>
+ </div>
+</div>
+
+<!-- Begin container -->
+
+<div class="row">
+ <div class="col-md-12">
+ <div class="page-header build-data">
+ <h1>Defect {{object.name}} Detail</h1>
+ </div>
+ </div>
+</div>
+
+<div class="row">
+ <div class="col-md-5">
+ <div class="well">
+ <h2>Quick Info</h2>
+ <dl class="dl-horizontal">
+ <dt>Summary:</dt>
+ <dd>{{object.summary}}</dd>
+
+ <dt>URL:</dt>
+ <dd><a href="{{object.url}}" id="dataid_{{object.id}}" target="_blank">{{object.url}}</a></dd>
+
+ <dt>Priority:</dt>
+ <dd>{{object.get_priority_text}}</dd>
+
+ <dt>Status:</dt>
+ <dd>{{object.get_status_text}}</dd>
+
+ <dt>Resolution:</dt>
+ <dd>{{object.get_resolution_text}}</dd>
+
+ <dt>Publish:</dt>
+ <dd>{{object.publish}}</dd>
+
+ <dt>Release Version:</dt>
+ <dd>{{object.release_version}}</dd>
+
+ <dt>Investigations:</dt>
+ <dd>
+ {% for ji in object.defect_to_investigation.all %}
+ {% if not forloop.first %}| {% endif %}<a href="{% url 'investigation' ji.investigation.id %}" target="_blank">{{ji.investigation.name}} </a>
+ {% endfor %}
+ </dd>
+
+ <dt>Product:</dt>
+ <dd><a href="{% url 'product' object.product.id %}">{{object.product.long_name}}</a></dd>
+
+ <dt>date_created:</dt>
+ <dd>{{object.date_created}}</dd>
+
+ <dt>date_updated:</dt>
+ <dd>{{object.date_updated}}</dd>
+
+ </dl>
+ </div>
+ </div>
+</div>
+
+
+<!-- Javascript support -->
+<script>
+ $(document).ready(function() {
+ /* Set the report link */
+ $('#report_link').attr('href',"{% url 'report' request.resolver_match.url_name %}?record_list={{object.id}}");
+ });
+</script>
+
+{% endblock %}
diff --git a/lib/srtgui/templates/defects-toastertable.html b/lib/srtgui/templates/defects-toastertable.html
index 82a6c5ee..1d699909 100644
--- a/lib/srtgui/templates/defects-toastertable.html
+++ b/lib/srtgui/templates/defects-toastertable.html
@@ -29,7 +29,8 @@
<h1 class="top-air" data-role="page-title"></h1>
</div>
- {% url 'cpes' as xhr_table_url %}
+ {# xhr_table_url is just the current url so leave it blank #}
+ {% url '' as xhr_table_url %}
{% include 'toastertable.html' %}
</div>
</div>
@@ -52,6 +53,17 @@
}
titleElt.text(title);
+
+ /* Set the report link */
+ var record_list=""
+ $(".name > a").each(function(){
+ var this_id=$(this).prop('id');
+ if (this_id.startsWith("dataid_")) {
+ record_list +=this_id.replace(/dataid_/,"") + ",";
+ }
+ });
+ $('#report_link').attr('href',"{% url 'report' request.resolver_match.url_name %}?record_list="+record_list);
+
});
});
</script>
diff --git a/lib/srtgui/templates/guided_tour.html b/lib/srtgui/templates/guided_tour.html
index 648bde14..fe5fd60e 100644
--- a/lib/srtgui/templates/guided_tour.html
+++ b/lib/srtgui/templates/guided_tour.html
@@ -74,7 +74,7 @@
<div class="row" style="padding-left: 25px;">
<h3><a id="public"></a>Public View</h3>
<ul>
- <li> <b><a href="{% url 'all-cves' %}">CVE's</a></b> </li>
+ <li> <b><a href="{% url 'cves' %}">CVE's</a></b> </li>
<ul>
<li> The CVE page is based on the NIST public page, and includes the V3 and V2 severities information, download links, and CPE's</li>
<li> There are tabs to see (a) the original source data and (b) the SRTool edits (if any)</li>
@@ -104,7 +104,7 @@
</ul>
</ul>
<ul>
- <li> <b><a href="{% url 'all-defects' %}">Defects</a></b> </li>
+ <li> <b><a href="{% url 'defects' %}">Defects</a></b> </li>
<ul>
<li> This table lists all of the Jira defects being tracked by the Vulnerabilities and Investigations </li>
<li> A quick status overview of the defects is provided </li>
@@ -118,14 +118,14 @@
</ul>
</ul>
<ul>
- <li> <b><a href="{% url 'all-cpes' %}">CPE's</a></b> </li>
+ <li> <b><a href="{% url 'cpes' %}">CPE's</a></b> </li>
<ul>
<li> The 'Common Product Enumerations' (CPE) found in the vulnerable CVE records </li>
<li> This data can help track CPE's that result in vulnerabilities, to help improve triaging CVE's </li>
</ul>
</ul>
<ul>
- <li> <b><a href="{% url 'all-cwes' %}">CWE's</a></b> </li>
+ <li> <b><a href="{% url 'cwes' %}">CWE's</a></b> </li>
<ul>
<li> The 'Common Weakness Enumerations' (CWE) found in the vulnerable CVE records </li>
</ul>
diff --git a/lib/srtgui/templates/investigation.html b/lib/srtgui/templates/investigation.html
index 77cb8fbd..bf0a5672 100644
--- a/lib/srtgui/templates/investigation.html
+++ b/lib/srtgui/templates/investigation.html
@@ -52,7 +52,7 @@
<h2>Quick Info</h2>
<dl class="dl-horizontal">
<dt>Product:</dt>
- <dd>{{object.product.name}} {{ object.product.version }} {{ object.product.profile }}</dd>
+ <dd><a href="{% url 'product' object.product.id %}">{{object.product.long_name}}</a></dd>
<dt>Investigation:</dt>
<dd><a href="{% url 'vulnerability' object.vulnerability.id %}">{{object.vulnerability.get_long_name}}</a></dd>
@@ -60,15 +60,42 @@
<dt>Defect:</dt>
<dd>
{% for ij in object.investigation_to_defect.all %}
- {% if not forloop.first %}| {% endif %}<a href="http://defect.wrs.com/browse/{{ij.defect.name}}" target="_blank">{{ij.defect.name}} </a>
+ {% if not forloop.first %}| {% endif %}<a href="{% url 'defect' ij.defect.id %}" target="_blank">{{ij.defect.name}} </a>
{% endfor %}
<p>
{% if access.is_creator %}
- <a class="btn btn-default navbar-btn " id="new-investigation-attachement" href="">Attach Defect</a>
- <a class="btn btn-default navbar-btn " id="new-investigation-attachement" href="">Create Defect</a>
+ <a class="btn btn-default navbar-btn " id="select-attachdefect">Attach Defect</a>
+ <a class="btn btn-default navbar-btn " id="select-createdefect">Create Defect</a>
+ <a class="btn btn-default navbar-btn " id="select-trashdefect">Detach Defect</a>
{% endif %}
</dd>
+ <div id="details-attachdefect" style="display:none; border: 1px solid; padding:20px; width:400px; margin-bottom:25px; margin-left:150px">
+ <p><b><label>Select Defect by Key:</label></b>
+ <div id="input-attachdefect" style="padding-left: 50px">
+ <p><input type="text" id="text-attachdefect" placeholder="Issue Key (ex. {{defect_example}})" size="20"> <button class="execute" id="submit-attachdefect"> Submit </button></p>
+ </div>
+ </div>
+
+ <div id="details-trashdefect" style="display:none; border: 1px solid; padding:20px; width:400px; margin-bottom:25px; margin-left:150px">
+ <p><b><label>Select Defect(s):</label></b>
+ <div id="select-trashdefectlist" style="padding-left: 50px">
+ <div class="row">
+ <div id="all-investigation-to-defects" class="scrolling" style="width: 300px;">
+ {% for obj in investigation_to_defect %}
+ <div class="checkbox">
+ <label>
+ <input class="checkbox-defects" name="{{obj.defect.pk}}" type="checkbox">{{obj.defect.name}}
+ </label>
+ <p>
+ </div>
+ {% endfor %}
+ </div>
+ <button class="execute" id="submit-trashdefect"> Detach </button>
+ </div>
+ </div>
+ </div>
+
<dt>Status:</dt>
<dd>{{object.get_status_text}}</dd>
@@ -81,7 +108,7 @@
<dt>Release Version:</dt>
<dd>
{% for ij in object.investigation_to_defect.all %}
- {% if not forloop.first %}| {% endif %}<a href="http://defect.wrs.com/browse/{{ij.defect.name}}" target="_blank">{{ij.defect.release_version}} </a>
+ {% if not forloop.first %}| {% endif %}<a href="{{ij.defect.url}}" target="_blank">{{ij.defect.release_version}} </a>
{% endfor %}
</dd>
</dl>
@@ -91,14 +118,18 @@
<hr>
-<div class="row">
+<div class="row" style="padding-left: 25px;">
<h3>Comments
- {% if access.is_creator %}
- <a class="btn btn-default navbar-btn " id="new-investigation-attachement" href="{% url 'login' %}">Add comment</a>
- {% endif %}
+ {% if access.is_creator %}
+ <button id="select-newcomment" class="btn btn-default" type="button">Add comment ...</button>
+ {% endif %}
</h3>
- <table class="table table-striped table-condensed" data-testid="inv-hyperlinks-table">
+ <div id="input-newcomment" style="padding-left: 50px; display:none;">
+ <p><input type="text" id="text-newcomment" size="40"> <button class="execute" id="submit-newcomment"> Submit </button></p>
+ </div>
+
+ <table class="table table-striped table-condensed" data-testid="vuln-hyperlinks-table">
<thead>
<tr>
<th>Comment</th>
@@ -116,11 +147,11 @@
<td>{{ c.comment }}</td>
<td>{{ c.date }}</td>
<td>{{ c.author }}</td>
- {% if access.is_creator %}
+ {% if access.is_creator or c.author == current_user %}
<td>
<span id="config_var_entry_'+configvars_sorted[i][2]+'" class="js-config-var-name"></span>
- <span class="glyphicon glyphicon-edit js-icon-pencil-config_var" id="affected_edit_'+{{c.id}}+'" x-data="'+{{c.id}}+'"></span>
- <span class="glyphicon glyphicon-trash js-icon-trash-config_var" id="comment_trash_'+{{c.id}}+'" x-data="'+{{c.id}}+'"></span>
+ <span class="glyphicon glyphicon-edit edit-comment" id="affected_edit_'+{{c.id}}+'" x-data="{{c.id}}"></span>
+ <span class="glyphicon glyphicon-trash trash-comment" id="comment_trash_'+{{c.id}}+'" x-data="{{c.id}}"></span>
</td>
{% endif %}
</tr>
@@ -134,13 +165,25 @@
</div>
-<div class="row">
+<div class="row" style="padding-left: 25px;">
<h3>Attachments
- {% if access.is_creator %}
- <a class="btn btn-default navbar-btn " id="new-investigation-attachement" href="{% url 'login' %}">Add attachment</a>
- {% endif %}
+ {% if access.is_creator %}
+ <a class="btn btn-default navbar-btn " id="select-addattachment">Add attachment ... </a>
+ {% endif %}
</h3>
+ <div id="details-addattachment" style="padding-left: 50px; display:none;">
+ <p><p>
+ <div class="row">
+ <form id="uploadbanner" enctype="multipart/form-data" method="post">{% csrf_token %}
+ <input id="fileDescription" name="fileDescription" type="text" placeholder="Enter Description" />
+ <input id="fileUpload" name="fileUpload" type="file" />
+ <input type="hidden" id="action" name="action" value="upload">
+ <input type="submit" value="submit file" id="submit-addattachment" />
+ </form>
+ </div>
+ </div>
+
<table class="table table-striped table-condensed" data-testid="vuln-hyperlinks-table">
<thead>
<tr>
@@ -157,17 +200,20 @@
{% for u in object.investigation_uploads.all %}
<tr>
<td>{{ u.description }}</td>
- <td>{{ u.path }}</td>
+ <td>{{ u.path|basename }}</td>
<td>{{ u.size }}</td>
<td>{{ u.date }}</td>
<td>{{ u.author }}</td>
<td>
<span id="attachment_entry_'+{{u.id}}+'" class="js-config-var-name"></span>
- <span class="glyphicon glyphicon-download-alt get-help" title="Download document"></span>
- {% if access.is_creator %}
- <span class="glyphicon glyphicon-edit js-icon-pencil-config_var" id="affected_edit_'+{{u.id}}+'" x-data="'+{{u.id}}+'"></span>
- <span class="glyphicon glyphicon-trash js-icon-trash-config_var" id="attachment_trash_'+{{u.id}}+'" x-data="'+{{u.id}}+'"></span>
- {% endif %}
+ <form id="downloadbanner" enctype="multipart/form-data" method="post" >{% csrf_token %}
+ <input type="hidden" id="action" name="action" value="download">
+ <input type="hidden" id="record_id" name="record_id" value={{u.id}}>
+ <span class="glyphicon glyphicon-download-alt submit-downloadattachment" id="attachment_download_'+{{u.id}}+'" x-data="{{u.id}}"></span>
+ {% if access.is_creator %}
+ <span class="glyphicon glyphicon-trash trash-attachment" id="attachment_trash_'+{{u.id}}+'" x-data="{{u.id}}"></span>
+ {% endif %}
+ </form>
</td>
</tr>
{% endfor %}
@@ -177,18 +223,37 @@
</tr>
{% endif %}
</table>
-
</div>
<br/>
<hr/>
{% if access.is_creator %}
- <div class="row">
+ <div class="row" style="padding-left: 25px;">
<h3>Change Notifications
- <a class="btn btn-default navbar-btn " id="new-investigation-notify" href="{% url 'login' %}">Add user notification</a>
+ {% if access.is_creator %}
+ <button id="select-addusernotify" class="btn btn-default" type="button">Add user notification ...</button>
+ {% endif %}
</h3>
+ <div id="details-addusernotify" style="padding-left: 50px; display:none;">
+ <p><p>
+ <button class="execute" id="submit-addusernotify"> Submit </button>
+ <div class="row">
+ <p>
+ <div id="all-users" class="scrolling" style="width: 300px;">
+ {% for user in users %}
+ <div class="checkbox">
+ <label>
+ <input class="checkbox-users" name="{{user.pk}}" type="checkbox">{{user.name}}
+ </label>
+ <p>
+ </div>
+ {% endfor %}
+ </div>
+ </div>
+ </div>
+
<table class="table table-striped table-condensed" data-testid="vuln-hyperlinks-table">
<thead>
<tr>
@@ -200,16 +265,16 @@
</tr>
</thead>
- {% if object.investigation_users.all %}
- {% for u in object.investigation_users.all %}
+ {% if object.investigation_notification.all %}
+ {% for u in object.investigation_notification.all %}
<tr>
<td>{{ u.user.name }}</td>
<td>{{ u.user.email }}</td>
- {% if access.is_creator %}
+ {% if access.is_creator or u.user.name == current_user %}
<td>
<span id="attachment_entry_'+{{u.id}}+'" class="js-config-var-name"></span>
- <span class="glyphicon glyphicon-edit js-icon-pencil-config_var" id="affected_edit_'+{{u.id}}+'" x-data="'+{{u.id}}+'"></span>
- <span class="glyphicon glyphicon-trash js-icon-trash-config_var" id="attachment_trash_'+{{u.id}}+'" x-data="'+{{u.id}}+'"></span>
+ <span class="glyphicon glyphicon-edit edit-usernotification" id="affected_edit_'+{{u.id}}+'" x-data="{{u.id}}"></span>
+ <span class="glyphicon glyphicon-trash trash-usernotification" id="attachment_trash_'+{{u.id}}+'" x-data="{{u.id}}"></span>
</td>
{% endif %}
</tr>
@@ -223,11 +288,31 @@
</div>
- <div class="row">
+ <div class="row" style="padding-left: 25px;">
<h3>User Access
- <a class="btn btn-default navbar-btn " id="new-investigation-access" href="{% url 'login' %}">Add user access</a>
+ {% if access.is_creator %}
+ <button id="select-adduseraccess" class="btn btn-default" type="button">Add user access ...</button>
+ {% endif %}
</h3>
+ <div id="details-adduseraccess" style="padding-left: 50px; display:none;">
+ <p><p>
+ <button class="execute" id="submit-adduseraccess"> Submit </button>
+ <div class="row">
+ <p>
+ <div id="all-users" class="scrolling" style="width: 300px;">
+ {% for user in users %}
+ <div class="checkbox">
+ <label>
+ <input class="checkbox-users" name="{{user.pk}}" type="checkbox">{{user.name}}
+ </label>
+ <p>
+ </div>
+ {% endfor %}
+ </div>
+ </div>
+ </div>
+
<table class="table table-striped table-condensed" data-testid="vuln-hyperlinks-table">
<thead>
<tr>
@@ -253,8 +338,8 @@
{% if access.is_creator %}
<td>
<span id="attachment_entry_'+{{u.id}}+'" class="js-config-var-name"></span>
- <span class="glyphicon glyphicon-edit js-icon-pencil-config_var" id="affected_edit_'+{{u.id}}+'" x-data="'+{{u.id}}+'"></span>
- <span class="glyphicon glyphicon-trash js-icon-trash-config_var" id="attachment_trash_'+{{u.id}}+'" x-data="'+{{u.id}}+'"></span>
+ <span class="glyphicon glyphicon-edit edit-useraccess" id="affected_edit_'+{{u.id}}+'" x-data="{{u.id}}"></span>
+ <span class="glyphicon glyphicon-trash trash-useraccess" id="attachment_trash_'+{{u.id}}+'" x-data="{{u.id}}"></span>
</td>
{% endif %}
</tr>
@@ -271,7 +356,7 @@
</div>
{% endif %}
-<div class="row">
+<div class="row" style="padding-left: 25px;">
<h3>History</h3>
<table class="table table-striped table-condensed" data-testid="vuln-hyperlinks-table">
<thead>
@@ -297,5 +382,287 @@
</table>
</div>
+<script>
+ var selected_newcomment=false;
+ var selected_addusernotify=false;
+ var selected_adduseraccess=false;
+ var selected_addattachment=false;
+ var selected_attachdefect=false;
+ var selected_trashdefect=false;
+
+ $(document).ready(function() {
+ function onCommitAjaxSuccess(data, textstatus) {
+ if (window.console && window.console.log) {
+ console.log("XHR returned:", data, "(" + textstatus + ")");
+ } else {
+ alert("NO CONSOLE:\n");
+ return;
+ }
+ if (data.error != "ok") {
+ alert("error on request:\n" + data.error);
+ return;
+ }
+ // reload the page with the updated tables
+ location.reload(true);
+ }
+
+ function onCommitAjaxError(jqXHR, textstatus, error) {
+ console.log("ERROR:"+error+"|"+textstatus);
+ alert("XHR errored1:\n" + error + "\n(" + textstatus + ")");
+ }
+
+ /* ensure cookie exists {% csrf_token %} */
+ function postCommitAjaxRequest(reqdata) {
+ reqdata["investigation_id"] = {{ object.id }}
+ var ajax = $.ajax({
+ type:"POST",
+ data: reqdata,
+ url:"{% url 'xhr_investigation_commit' %}",
+ headers: { 'X-CSRFToken': $.cookie("csrftoken")},
+ success: onCommitAjaxSuccess,
+ error: onCommitAjaxError,
+ });
+ }
+
+ /* (De-)Select management */
+
+ $('#select-these').click(function(){
+ $(':checkbox').each(function(){
+ $(this).prop('checked', true);
+ });
+ });
+
+ $('#unselect-these').click(function(){
+ $(':checkbox').each(function(){
+ $(this).prop('checked', false);
+ });
+ });
+
+ /* Defect management */
+
+ $('#select-attachdefect').click(function(){
+ if (selected_attachdefect) {
+ selected_attachdefect=false;
+ $("#details-attachdefect").slideUp();
+ } else {
+ if (selected_trashdefect) {
+ selected_trashdefect = false;
+ }
+ selected_attachdefect=true;
+ $("#details-trashdefect").slideUp();
+ $("#details-attachdefect").slideDown();
+ }
+ })
+
+ $('#select-trashdefect').click(function(){
+ if (selected_trashdefect) {
+ selected_trashdefect=false;
+ $("#details-trashdefect").slideUp();
+ } else {
+ if (selected_attachdefect) {
+ selected_attachdefect = false;
+ }
+ selected_trashdefect=true;
+ $("#details-trashdefect").slideDown();
+ $("#details-attachdefect").slideUp();
+ }
+ })
+
+ $('#submit-attachdefectlist').click(function(){
+ var defect_list=""
+ $(':checkbox').each(function(){
+ if ($(this).is(':checked')) {
+ defect_list += $(this).prop('name') + ",";
+ }
+ });
+ if ("" == defect_list) {
+ alert("No users were selected");
+ return;
+ }
+ postCommitAjaxRequest({
+ "action" : 'submit-attachdefectlist',
+ "defects" : defect_list,
+ });
+ });
+
+ $('#submit-attachdefect').click(function(){
+ var query=$('#text-attachdefect').val().trim()
+ if (query=="") {
+ alert("No query given");
+ return;
+ }
+ postCommitAjaxRequest({
+ "action" : 'submit-attachdefect',
+ "query" : query,
+ })
+ });
+
+ $('#submit-trashdefect').click(function(){
+ var defect_list=""
+ $(':checkbox').each(function(){
+ if ($(this).is(':checked')) {
+ defect_list += $(this).prop('name') + ",";
+ }
+ });
+ if ("" == defect_list) {
+ alert("No users were selected");
+ return;
+ }
+ postCommitAjaxRequest({
+ "action" : 'submit-trashdefect',
+ "defects" : defect_list,
+ });
+ });
+
+ /* Comment management */
+
+ $('#select-newcomment').click(function(){
+ if (selected_newcomment) {
+ selected_newcomment=false;
+ $("#input-newcomment").slideUp();
+ } else {
+ selected_newcomment=true;
+ $("#input-newcomment").slideDown();
+ }
+ });
+
+ $('#submit-newcomment').click(function(){
+ var comment=$('#text-newcomment').val().trim()
+ if (comment=="") {
+ alert("No comment was written");
+ return;
+ }
+ postCommitAjaxRequest({
+ "action" : 'submit-newcomment',
+ "comment" : comment,
+ })
+ });
+
+ $('.trash-comment').click(function(){
+ var result = confirm("Are you sure?");
+ if (result){
+ postCommitAjaxRequest({
+ "action" : 'submit-trashcomment',
+ "record_id" : $(this).attr('x-data'),
+ });
+ }
+ })
+
+ /* Attachement management */
+
+ $('#select-addattachment').click(function() {
+ if (selected_addattachment) {
+ selected_addattachment=false;
+ $("#details-addattachment").slideUp();
+ } else {
+ selected_addattachment=true;
+ $("#details-addattachment").slideDown();
+ }
+ });
+
+ $('.submit-downloadattachment').click(function() {
+ $("#downloadbanner").submit();
+ });
+
+ $('.trash-attachment').click(function() {
+ var result = confirm("Are you sure?");
+ if (result){
+ postCommitAjaxRequest({
+ "action" : 'submit-trashattachment',
+ "record_id" : $(this).attr('x-data'),
+ });
+ }
+ });
+
+ /* User notify management */
+
+ $('#select-addusernotify').click(function(){
+ if (selected_addusernotify) {
+ selected_addusernotify=false;
+ $("#select-these").removeAttr("disabled");
+ $("#unselect-these").removeAttr("disabled");
+ $("#details-addusernotify").slideUp();
+ } else {
+ selected_addusernotify=true;
+ $("#select-these").attr("disabled","disabled");
+ $("#unselect-these").attr("disabled","disabled");
+ $("#details-addusernotify").slideDown();
+ }
+ });
+
+ $('#submit-addusernotify').click(function(){
+ var user_list=""
+ $(':checkbox').each(function(){
+ if ($(this).is(':checked')) {
+ user_list += $(this).prop('name') + ",";
+ }
+ });
+ if ("" == user_list) {
+ alert("No users were selected");
+ return;
+ }
+ postCommitAjaxRequest({
+ "action" : 'submit-addusernotify',
+ "users" : user_list,
+ });
+ });
+
+ $('.trash-usernotification').click(function(){
+ var result = confirm("Are you sure?");
+ if (result){
+ postCommitAjaxRequest({
+ "action" : 'submit-trashusernotification',
+ "record_id" : $(this).attr('x-data'),
+ });
+ }
+ })
+
+ /* User access management */
+
+ $('#select-adduseraccess').click(function(){
+ if (selected_adduseraccess) {
+ selected_adduseraccess=false;
+ $("#select-these").removeAttr("disabled");
+ $("#unselect-these").removeAttr("disabled");
+ $("#details-adduseraccess").slideUp();
+ } else {
+ selected_adduseraccess=true;
+ $("#select-these").attr("disabled","disabled");
+ $("#unselect-these").attr("disabled","disabled");
+ $("#details-adduseraccess").slideDown();
+ }
+ });
+
+ $('#submit-adduseraccess').click(function(){
+ var user_list=""
+ $(':checkbox').each(function(){
+ if ($(this).is(':checked')) {
+ user_list += $(this).prop('name') + ",";
+ }
+ });
+ if ("" == user_list) {
+ alert("No users were selected");
+ return;
+ }
+ postCommitAjaxRequest({
+ "action" : 'submit-adduseraccess',
+ "users" : user_list,
+ });
+ });
+
+ $('.trash-useraccess').click(function(){
+ var result = confirm("Are you sure?");
+ if (result){
+ postCommitAjaxRequest({
+ "action" : 'submit-trashuseraccess',
+ "record_id" : $(this).attr('x-data'),
+ });
+ }
+ })
+
+ /* Set the report link */
+ $('#report_link').attr('href',"{% url 'report' request.resolver_match.url_name %}?record_list={{object.id}}");
+ });
+</script>
{% endblock %}
diff --git a/lib/srtgui/templates/investigations-toastertable.html b/lib/srtgui/templates/investigations-toastertable.html
index 2aee7f7e..384d7141 100644
--- a/lib/srtgui/templates/investigations-toastertable.html
+++ b/lib/srtgui/templates/investigations-toastertable.html
@@ -30,7 +30,8 @@
<h1 class="top-air" data-role="page-title"></h1>
</div>
- {% url 'cves' as xhr_table_url %}
+ {# xhr_table_url is just the current url so leave it blank #}
+ {% url '' as xhr_table_url %}
{% include 'toastertable.html' %}
</div>
</div>
@@ -53,6 +54,17 @@
}
titleElt.text(title);
+
+ /* Set the report link */
+ var record_list=""
+ $(".name > a").each(function(){
+ var this_id=$(this).prop('id');
+ if (this_id.startsWith("dataid_")) {
+ record_list +=this_id.replace(/dataid_/,"") + ",";
+ }
+ });
+ $('#report_link').attr('href',"{% url 'report' request.resolver_match.url_name %}?record_list="+record_list);
+
});
});
</script>
diff --git a/lib/srtgui/templates/landing.html b/lib/srtgui/templates/landing.html
index 52f24482..e0950bd8 100644
--- a/lib/srtgui/templates/landing.html
+++ b/lib/srtgui/templates/landing.html
@@ -25,7 +25,7 @@
</tr>
</thead>
- {% if access.is_admin %}
+ {% if access.is_creator %}
<tr>
<td><a class="btn btn-info btn-lg" href="{% url 'manage' %}">Management</a></td>
<td>Triage CVE's, Create Vulnerabilities, Manage Users</td>
@@ -33,7 +33,7 @@
{% endif %}
<tr>
- <td><a class="btn btn-info btn-lg" href="{% url 'all-cves' %}">CVE's</a></td>
+ <td><a class="btn btn-info btn-lg" href="{% url 'cves' %}">CVE's</a></td>
<td>Common Vulnerblility Enumeration</td>
</tr>
@@ -48,7 +48,7 @@
</tr>
<tr>
- <td><a class="btn btn-info btn-lg" href="{% url 'all-defects' %}">Defects</a></td>
+ <td><a class="btn btn-info btn-lg" href="{% url 'defects' %}">Defects</a></td>
<td>SRTool Defects</td>
</tr>
@@ -58,12 +58,12 @@
</tr>
<tr>
- <td><a class="btn btn-info btn-lg" href="{% url 'all-cpes' %}">CPE's</a></td>
+ <td><a class="btn btn-info btn-lg" href="{% url 'cpes' %}">CPE's</a></td>
<td>Common Platform Enumeration</td>
</tr>
<tr>
- <td><a class="btn btn-info btn-lg" href="{% url 'all-cwes' %}">CWE's</a></td>
+ <td><a class="btn btn-info btn-lg" href="{% url 'cwes' %}">CWE's</a></td>
<td>Common Weakness Enumeration</td>
</tr>
diff --git a/lib/srtgui/templates/login.html b/lib/srtgui/templates/login.html
new file mode 100644
index 00000000..be597992
--- /dev/null
+++ b/lib/srtgui/templates/login.html
@@ -0,0 +1,40 @@
+{% extends "base.html" %}
+
+{% load static %}
+{% load projecttags %}
+{% load humanize %}
+
+{% block title %} Login Page {% endblock %}
+{% block pagecontent %}
+ <div class="row">
+ <div class="col-md-7" style="padding-left: 50px;">
+ <h1>Login Page</h1>
+ </div>
+ </div>
+
+ <form method="POST">{% csrf_token %}
+ <div class="row" style="padding-left: 100px;">
+ <h2>Select User:</h2>
+ {% if object.all %}
+ <select name="username" size="10" required>
+ {% for user in object.all %}
+ <option>{{user.name}} ({{user.get_access_text}})</option>
+ {% endfor %}
+ </select>
+ {% else %}
+ <p>No Users Found</p>
+ {% endif%}
+ </div>
+
+ <div class="row" style="padding-left: 100px;">
+ <h2>Password:</h2>
+ <input type="password" class="form-control" style="width: 150px;" name="password" placeholder="(enter anything)">
+ </div>
+
+ <div class="top-air" style="padding-left: 100px;">
+ <input type="submit" id="login-button" class="btn btn-primary btn-lg" value="Submit"/>
+ <a class="btn btn-info btn-lg" href="{% url 'landing' %}">Cancel</a>
+ </div>
+ </form>
+
+{% endblock %}
diff --git a/lib/srtgui/templates/manage-cpes-toastertable.html b/lib/srtgui/templates/manage-cpes-toastertable.html
index dc4bb800..13fdff80 100644
--- a/lib/srtgui/templates/manage-cpes-toastertable.html
+++ b/lib/srtgui/templates/manage-cpes-toastertable.html
@@ -36,7 +36,8 @@
<h1 class="top-air" data-role="page-title"></h1>
</div>
- {% url 'cpes' as xhr_table_url %}
+ {# xhr_table_url is just the current url so leave it blank #}
+ {% url '' as xhr_table_url %}
{% include 'toastertable.html' %}
</div>
</div>
@@ -60,6 +61,17 @@
}
titleElt.text(title);
+
+ /* Set the report link */
+ var record_list=""
+ $(".name > a").each(function(){
+ var this_id=$(this).prop('id');
+ if (this_id.startsWith("dataid_")) {
+ record_list +=this_id.replace(/dataid_/,"") + ",";
+ }
+ });
+ $('#report_link').attr('href',"{% url 'report' request.resolver_match.url_name %}?record_list="+record_list);
+
});
});
</script>
diff --git a/lib/srtgui/templates/management.html b/lib/srtgui/templates/management.html
index 2e53ee88..cfdd10d4 100644
--- a/lib/srtgui/templates/management.html
+++ b/lib/srtgui/templates/management.html
@@ -35,8 +35,8 @@
</tr>
<tr>
- <td><a class="btn btn-info btn-lg" href="{% url 'publish' %}">Publish Vulnerabilities</a></td>
- <td>Process the items that are ready to be published</td>
+ <td><a class="btn btn-info btn-lg" href="{% url 'publish' %}">Publish Request</a></td>
+ <td>Process the items that are ready to be published from SRTool</td>
</tr>
<tr>
@@ -44,6 +44,7 @@
<td>Report on the over all response system status</td>
</tr>
+ {% if access.is_admin %}
<tr>
<td><a class="btn btn-info btn-lg" href="{% url 'users' %}">Manage Users</a></td>
<td>Add, edit, and remove users</td>
@@ -53,6 +54,7 @@
<td><a class="btn btn-info btn-lg" href="{% url 'sources' %}">Manage Sources</a></td>
<td>Manage source list, perform manual pulls</td>
</tr>
+ {% endif %}
</table>
</div>
@@ -65,16 +67,16 @@
<dl class="dl-horizontal">
<dt>CVE's: Total Count =</dt>
<dd>
- <a href="{% url 'all-cves' %}"> {{cve_total}} </a>
+ <a href="{% url 'cves' %}"> {{cve_total}} </a>
</dd>
<dt>Pending triaged =</dt>
<dd>
- <a href="{% url 'all-cves' %}?limit=25&page=1&orderby=name&filter=is_status:new&default_orderby=name&filter_value=on&"> {{cve_new}} </a>
+ <a href="{% url 'cves' %}?limit=25&page=1&orderby=name&filter=is_status:new&default_orderby=name&filter_value=on&"> {{cve_new}} </a>
</dd>
<!--
<dt>Open =</dt>
<dd>
- <a href="{% url 'all-cves' %}?limit=25&page=1&orderby=name&filter=is_status:open&default_orderby=name&filter_value=on&"> {{cve_open}} </a>
+ <a href="{% url 'cves' %}?limit=25&page=1&orderby=name&filter=is_status:open&default_orderby=name&filter_value=on&"> {{cve_open}} </a>
</dd>
-->
<dt>Vulnerabilities: Total Count =</dt>
@@ -125,7 +127,7 @@
<dt>Defects: Total Count =</dt>
<dd>
- <a href="{% url 'all-defects' %}" %}> {{defect_total}} </a>
+ <a href="{% url 'defects' %}" %}> {{defect_total}} </a>
</dd>
</dl>
diff --git a/lib/srtgui/templates/product.html b/lib/srtgui/templates/product.html
new file mode 100644
index 00000000..e26bb2fe
--- /dev/null
+++ b/lib/srtgui/templates/product.html
@@ -0,0 +1,84 @@
+{% extends "base.html" %}
+
+{% load projecttags %}
+
+{% block title %} {{object.name}} - SRTool {% endblock %}
+
+{% block pagecontent %}
+
+<div class="row">
+ <!-- Breadcrumbs -->
+ <div class="col-md-12">
+ <ul class="breadcrumb" id="breadcrumb">
+ <li><a href="{% url 'landing' %}">Home</a></li><span class="divider">&rarr;</span>
+ <li><a href="{% url 'products' %}">Products</a></li><span class="divider">&rarr;</span>
+ <li>{{object.name}}</li>
+ </ul>
+ </div>
+</div>
+
+<!-- Begin container -->
+
+<div class="row">
+ <div class="col-md-12">
+ <div class="page-header build-data">
+ <h1>Product {{object.long_name}}Detail</h1>
+ </div>
+ </div>
+</div>
+
+<div class="row">
+ <div class="col-md-5">
+ <div class="well">
+ <h2>Quick Info</h2>
+ <dl class="dl-horizontal">
+ <dt>Name:</dt>
+ <dd>{{object.name}}</dd>
+
+ <dt>Version:</dt>
+ <dd>{{object.version}}</dd>
+
+ <dt>Profile:</dt>
+ <dd>{{object.profile}}</dd>
+
+ <dt>Cpe:</dt>
+ <dd>{{object.cpe}}</dd>
+
+ <dt>Srt Cpe:</dt>
+ <dd>{{object.srt_cpe}}</dd>
+
+ <dt>Defect Prefix:</dt>
+ <dd>{{object.defect_prefix }}</dd>
+
+ <dt>Investigations Count/Link:</dt>
+ <dd>
+ {% if object.product_investigation.all.count %}
+ <a href="{% url 'investigations' %}?filter=is_product:{{object.defect_prefix}}&" class="btn btn-info" >
+ {{object.product_investigation.all.count}}
+ </a>
+ {% else %}0{% endif %}
+ </dd>
+
+ <dt>Defects Count/Link:</dt>
+ <dd>
+ {% if object.product_defect.all.count %}
+ <a href="{% url 'defects' %}?filter=is_product:{{object.defect_prefix}}&" class="btn btn-info" >
+ {{object.product_defect.all.count}}
+ </a>
+ {% else %}0{% endif %}
+ </dd>
+
+ </dl>
+ </div>
+ </div>
+</div>
+
+<!-- Javascript support -->
+<script>
+ $(document).ready(function() {
+ /* Set the report link */
+ $('#report_link').attr('href',"{% url 'report' request.resolver_match.url_name %}?record_list={{object.id}}");
+ });
+</script>
+
+{% endblock %}
diff --git a/lib/srtgui/templates/products-toastertable.html b/lib/srtgui/templates/products-toastertable.html
index 65602be7..7e12b96b 100644
--- a/lib/srtgui/templates/products-toastertable.html
+++ b/lib/srtgui/templates/products-toastertable.html
@@ -30,7 +30,8 @@
<h1 class="top-air" data-role="page-title"></h1>
</div>
- {% url 'cves' as xhr_table_url %}
+ {# xhr_table_url is just the current url so leave it blank #}
+ {% url '' as xhr_table_url %}
{% include 'toastertable.html' %}
</div>
</div>
@@ -53,6 +54,17 @@
}
titleElt.text(title);
+
+ /* Set the report link */
+ var record_list=""
+ $(".name > a").each(function(){
+ var this_id=$(this).prop('id');
+ if (this_id.startsWith("dataid_")) {
+ record_list +=this_id.replace(/dataid_/,"") + ",";
+ }
+ });
+ $('#report_link').attr('href',"{% url 'report' request.resolver_match.url_name %}?record_list="+record_list);
+
});
});
</script>
diff --git a/lib/srtgui/templates/publish-select-toastertable.html b/lib/srtgui/templates/publish-select-toastertable.html
new file mode 100644
index 00000000..5a439c63
--- /dev/null
+++ b/lib/srtgui/templates/publish-select-toastertable.html
@@ -0,0 +1,248 @@
+{% extends 'base.html' %}
+{% load static %}
+
+
+{% block extraheadcontent %}
+ <link rel="stylesheet" href="{% static 'css/jquery-ui.min.css' %}" type='text/css'>
+ <link rel="stylesheet" href="{% static 'css/jquery-ui.structure.min.css' %}" type='text/css'>
+ <link rel="stylesheet" href="{% static 'css/jquery-ui.theme.min.css' %}" type='text/css'>
+ <script src="{% static 'js/jquery-ui.min.js' %}">
+ </script>
+ {% if access.is_creator %}{% else %}<meta http-equiv="refresh" content="0; url=/" />{% endif %}
+
+ <style>
+ /* Style the execution buttons */
+ button.execute { height:50px;width:210px;background-color:#4CAF50;text-align:center; border:2px #f69c55;border-radius: 12px; }
+
+ button:disabled {
+ cursor: not-allowed;
+ }
+
+ /* Create two equal columns that floats next to each other */
+ .column {
+ float: left;
+ width: 350px;
+ padding: 10px;
+ }
+
+ /* Clear floats after the columns */
+ .row:after {
+ content: "";
+ display: table;
+ clear: both;
+ }
+ </style>
+
+{% endblock %}
+
+{% block title %} Publish CVE's - SRTool {% endblock %}
+
+{% block pagecontent %}
+
+ <div class="row">
+ <!-- Breadcrumbs -->
+ <div class="col-md-12">
+ <ul class="breadcrumb" id="breadcrumb">
+ <li><a href="{% url 'landing' %}">Home</a></li><span class="divider">&rarr;</span>
+ <li><a href="{% url 'manage' %}">Management</a></li><span class="divider">&rarr;</span>
+ <li><a href="{% url 'publish' %}">Publish</a></li><span class="divider">&rarr;</span>
+ <li>Publish CVE's</li>
+ </ul>
+ </div>
+ </div>
+
+ <div id="change-publish-state" > <!--class="form-inline" -->
+ <b><big>Actions: </big></b>
+ <button id="select-these" class="btn btn-default" type="button">Select these</button>
+ <button id="unselect-these" class="btn btn-default" type="button">Un-select these</button>
+ <button id="select-publish" class="btn btn-default" type="button">Update ...</button>
+ <!--<button id="collect-publish" class="btn btn-default" type="button">Collect Publishable CVEs</button> -->
+ </div>
+
+ <div id="details-publish" style="display:none;">
+ <p><p>
+ <button class="execute" id="submit-publish"> Update Publish CVE State </button>
+ <p><b><big>New Publish State: </big></b>
+ <select name="Publish" id="select-publish-state">
+ <option value="0" >Unpublished</option>
+ <option value="1" >Not to be Published</option>
+ <option value="2" >Published</option>
+ <option value="3" >Publish Request (New)</option>
+ <option value="4" >Publish Request (Update)</option>
+ <option value="5" selected>Publish Submitted</option>
+ </select>
+ </div>
+
+ <div class="row">
+ <div class="col-md-12">
+ <div class="page-header">
+ <h1 class="top-air" data-role="page-title"></h1>
+ </div>
+
+ {% url '' as xhr_table_url %}
+ {% include 'toastertable.html' %}
+ </div>
+ </div>
+
+ <!-- Javascript support -->
+ <script>
+
+ //# sourceURL=somename.js
+
+ // global variables
+ var selected_publish=false;
+ var cve_total=0;
+
+ $(document).ready(function() {
+
+ function onCommitAjaxSuccess(data, textstatus) {
+ if (window.console && window.console.log) {
+ console.log("XHR returned:", data, "(" + textstatus + ")");
+ } else {
+ alert("NO CONSOLE:\n");
+ return;
+ }
+ if (data.error != "ok") {
+ alert("error on request:\n" + data.error);
+ return;
+ }
+ // reload the page with the updated tables
+ location.reload(true);
+ }
+
+ function onCommitAjaxError(jqXHR, textstatus, error) {
+ console.log("ERROR:"+error+"|"+textstatus);
+ alert("XHR errored1:\n" + error + "\n(" + textstatus + ")");
+ }
+
+ /* ensure cookie exists {% csrf_token %} */
+ function postCommitAjaxRequest(reqdata) {
+ var ajax = $.ajax({
+ type:"POST",
+ data: reqdata,
+ url:"{% url 'xhr_cve_publish_commit'%}",
+ headers: { 'X-CSRFToken': $.cookie("csrftoken")},
+ success: onCommitAjaxSuccess,
+ error: onCommitAjaxError,
+ })
+ }
+
+ function update_publish_status() {
+ var cve_count = 0;
+ var cve_checked_count = 0;
+ $('#selectpublishtable input').each(function(){
+ cve_count = cve_count + 1;
+ if ($(this).is(':checked')) {
+ cve_checked_count = cve_checked_count + 1;
+ }
+ });
+ if (cve_total > cve_count) {
+ document.getElementById("select-these").innerText = "Select "+(cve_count-cve_checked_count)+" unchecked ("+(cve_total-cve_count)+" offpage)";
+ } else {
+ document.getElementById("select-these").innerText = "Select "+(cve_count-cve_checked_count)+" unchecked";
+ }
+ document.getElementById("unselect-these").innerText = "Un-select "+cve_checked_count+" checked";
+ if (0 == cve_checked_count) {
+ //$("#submit-publish").attr("disabled","disabled");
+ document.getElementById("submit-publish").disabled = true;
+ } else {
+ //$("#submit-publish").removeAttr("disabled");
+ document.getElementById("submit-publish").disabled = false;
+ }
+ }
+
+ $('#select-these').click(function(){
+ $('#selectpublishtable input').each(function(){
+ $(this).prop('checked', true);
+ });
+ update_publish_status();
+ });
+
+ $('#unselect-these').click(function(){
+ $('#selectpublishtable input').each(function(){
+ $(this).prop('checked', false);
+ });
+ update_publish_status();
+ });
+
+ // Open Publish Action
+ $('#select-publish').click(function(){
+ if (selected_publish) {
+ selected_publish=false;
+ $("#select-these").removeAttr("disabled");
+ $("#unselect-these").removeAttr("disabled");
+ $("#details-publish").slideUp();
+ } else {
+ selected_publish=true;
+ $("#select-these").attr("disabled","disabled");
+ $("#unselect-these").attr("disabled","disabled");
+ update_publish_status();
+ $("#details-publish").slideDown();
+ }
+ });
+
+ $('#submit-publish').click(function(){
+ var cve_list="";
+ $('#selectpublishtable input').each(function(){
+ if ($(this).is(':checked')) {
+ cve_list +=$(this).prop('name') + ",";
+ }
+ });
+ if ("" == cve_list) {
+ alert("No CVE's were selected");
+ return;
+ }
+ publish_state=$('#select-publish-state').val();
+ postCommitAjaxRequest({
+ "publish_state" : publish_state,
+ "cve_list" : cve_list,
+ });
+
+ });
+
+ // When change in product selections, update labels and enables
+ $(document).on("change", "#all-products :checkbox", function() {
+ update_publish_status();
+ });
+
+ // When change in CVE selections, update labels and enables
+ $(document).on("change", "#selectpublishtable :checkbox", function() {
+ update_publish_status();
+ });
+
+
+ // Standard Toaster Table enablement
+
+ var tableElt = $("#{{table_name}}");
+ var titleElt = $("[data-role='page-title']");
+
+ tableElt.on("table-done", function (e, total, tableParams) {
+ var title = "Publish CVE's";
+
+ if (tableParams.search || tableParams.filter) {
+ if (total === 0) {
+ title = "No CVE's found";
+ }
+ else if (total > 0) {
+ title = total + " CVE" + (total > 1 ? "'s" : '') + " found";
+ }
+ }
+
+ titleElt.text(title);
+ cve_total = total;
+ update_publish_status();
+
+ /* Set the report link */
+ var record_list=""
+ $(".name > a").each(function(){
+ var this_id=$(this).prop('id');
+ if (this_id.startsWith("dataid_")) {
+ record_list +=this_id.replace(/dataid_/,"") + ",";
+ }
+ });
+ $('#report_link').attr('href',"{% url 'report' request.resolver_match.url_name %}?record_list="+record_list);
+ });
+
+ });
+ </script>
+{% endblock %}
diff --git a/lib/srtgui/templates/publish.html b/lib/srtgui/templates/publish.html
index 2b65e81b..b1f3d83f 100644
--- a/lib/srtgui/templates/publish.html
+++ b/lib/srtgui/templates/publish.html
@@ -7,25 +7,38 @@
{% block title %} Publish Requests {% endblock %}
{% block pagecontent %}
- <div class="row">
- <div class="col-md-7" style="padding-left: 50px;">
+<div class="row">
+ <!-- Breadcrumbs -->
+ <div class="col-md-12">
+ <ul class="breadcrumb" id="breadcrumb">
<li><a href="{% url 'landing' %}">Home</a></li><span class="divider">&rarr;</span>
<li><a href="{% url 'manage' %}">Management</a></li><span class="divider">&rarr;</span>
- <h1>Publish (Proposals)</h1>
- </div>
- </div>
+ <li>Publish (Proposals)</li>
+ </ul>
+ </div>
+</div>
<h2> Manage Publish Requests</h2>
<ul>
- <li>This interface can review and accept the list of vulnerabilities that have readhed their publication date</li>
- <li>This is preferable over automatic publishing for when the defect and/or official publish date are not very certain</li>
+ <li>The SRTool supports an external publishing tool, for example a business table or the vendor's public website</li>
+ <li>These tools can be used to (a) submit CVEs to that tool, and (b) update the CVEs when they have been published</li>
</ul>
<h2> Publishing Actions</h2>
<ul>
- <li>Format (and hopefully automatically register) the Vulnerability information to the company website</li>
- <li>Format a notice for TechPubs</li>
- <li>Format a notice for the respective product leads</li>
+ <tr>
+ <td><a class="btn btn-info btn-lg" href="{% url 'select-publish' %}">Publish Request</a></td>
+ <td>Process the items that are ready to be published from SRTool</td>
+ </tr>
+
+ <br>
+ <br>
+ <br>
+
+ <tr>
+ <td><a class="btn btn-info btn-lg" href="{% url 'update-published' %}">Published Update</a></td>
+ <td>Process the items that have been published</td>
+ </tr>
</ul>
{% endblock %}
diff --git a/lib/srtgui/templates/published-select-toastertable.html b/lib/srtgui/templates/published-select-toastertable.html
new file mode 100644
index 00000000..df89d142
--- /dev/null
+++ b/lib/srtgui/templates/published-select-toastertable.html
@@ -0,0 +1,247 @@
+{% extends 'base.html' %}
+{% load static %}
+
+
+{% block extraheadcontent %}
+ <link rel="stylesheet" href="{% static 'css/jquery-ui.min.css' %}" type='text/css'>
+ <link rel="stylesheet" href="{% static 'css/jquery-ui.structure.min.css' %}" type='text/css'>
+ <link rel="stylesheet" href="{% static 'css/jquery-ui.theme.min.css' %}" type='text/css'>
+ <script src="{% static 'js/jquery-ui.min.js' %}">
+ </script>
+ {% if access.is_creator %}{% else %}<meta http-equiv="refresh" content="0; url=/" />{% endif %}
+
+ <style>
+ /* Style the execution buttons */
+ button.execute { height:50px;width:210px;background-color:#4CAF50;text-align:center; border:2px #f69c55;border-radius: 12px; }
+
+ button:disabled {
+ cursor: not-allowed;
+ }
+
+ /* Create two equal columns that floats next to each other */
+ .column {
+ float: left;
+ width: 350px;
+ padding: 10px;
+ }
+
+ /* Clear floats after the columns */
+ .row:after {
+ content: "";
+ display: table;
+ clear: both;
+ }
+ </style>
+
+{% endblock %}
+
+{% block title %} Publish Reqested CVE's - SRTool {% endblock %}
+
+{% block pagecontent %}
+
+ <div class="row">
+ <!-- Breadcrumbs -->
+ <div class="col-md-12">
+ <ul class="breadcrumb" id="breadcrumb">
+ <li><a href="{% url 'landing' %}">Home</a></li><span class="divider">&rarr;</span>
+ <li><a href="{% url 'manage' %}">Management</a></li><span class="divider">&rarr;</span>
+ <li><a href="{% url 'publish' %}">Publish</a></li><span class="divider">&rarr;</span>
+ <li>Publish Requested Update CVE's</li>
+ </ul>
+ </div>
+ </div>
+
+ <div id="change-publish-state" > <!--class="form-inline" -->
+ <b><big>Actions: </big></b>
+ <button id="select-these" class="btn btn-default" type="button">Select these</button>
+ <button id="unselect-these" class="btn btn-default" type="button">Un-select these</button>
+ <button id="select-publish" class="btn btn-default" type="button">Update ...</button>
+ <!--<button id="collect-publish" class="btn btn-default" type="button">Collect Publishable CVEs</button> -->
+ </div>
+
+ <div id="details-publish" style="display:none;">
+ <p><p>
+ <button class="execute" id="submit-publish"> Update Publish CVE State </button>
+ <p><b><big>New Publish State: </big></b>
+ <select name="Publish" id="select-publish-state">
+ <option value="0" >Unpublished</option>
+ <option value="1" >Not to be Published</option>
+ <option value="2" selected>Published</option>
+ <option value="3" >Publish Request (New)</option>
+ <option value="4" >Publish Request (Update)</option>
+ <option value="5" >Publish Submitted</option>
+ </select>
+ </div>
+
+ <div class="row">
+ <div class="col-md-12">
+ <div class="page-header">
+ <h1 class="top-air" data-role="page-title"></h1>
+ </div>
+
+ {% url '' as xhr_table_url %}
+ {% include 'toastertable.html' %}
+ </div>
+ </div>
+
+ <!-- Javascript support -->
+ <script>
+
+ //# sourceURL=somename.js
+
+ // global variables
+ var selected_publish=false;
+ var cve_total=0;
+
+ $(document).ready(function() {
+
+ function onCommitAjaxSuccess(data, textstatus) {
+ if (window.console && window.console.log) {
+ console.log("XHR returned:", data, "(" + textstatus + ")");
+ } else {
+ alert("NO CONSOLE:\n");
+ return;
+ }
+ if (data.error != "ok") {
+ alert("error on request:\n" + data.error);
+ return;
+ }
+ // reload the page with the updated tables
+ location.reload(true);
+ }
+
+ function onCommitAjaxError(jqXHR, textstatus, error) {
+ console.log("ERROR:"+error+"|"+textstatus);
+ alert("XHR errored1:\n" + error + "\n(" + textstatus + ")");
+ }
+
+ /* ensure cookie exists {% csrf_token %} */
+ function postCommitAjaxRequest(reqdata) {
+ var ajax = $.ajax({
+ type:"POST",
+ data: reqdata,
+ url:"{% url 'xhr_cve_publish_commit' %}",
+ headers: { 'X-CSRFToken': $.cookie("csrftoken")},
+ success: onCommitAjaxSuccess,
+ error: onCommitAjaxError,
+ })
+ }
+
+ function update_publish_status() {
+ var cve_count = 0;
+ var cve_checked_count = 0;
+ $('#updatepublishedtable input').each(function(){
+ cve_count = cve_count + 1;
+ if ($(this).is(':checked')) {
+ cve_checked_count = cve_checked_count + 1;
+ }
+ });
+ if (cve_total > cve_count) {
+ document.getElementById("select-these").innerText = "Select "+(cve_count-cve_checked_count)+" unchecked ("+(cve_total-cve_count)+" offpage)";
+ } else {
+ document.getElementById("select-these").innerText = "Select "+(cve_count-cve_checked_count)+" unchecked";
+ }
+ document.getElementById("unselect-these").innerText = "Un-select "+cve_checked_count+" checked";
+ if (0 == cve_checked_count) {
+ //$("#submit-publish").attr("disabled","disabled");
+ document.getElementById("submit-publish").disabled = true;
+ } else {
+ //$("#submit-publish").removeAttr("disabled");
+ document.getElementById("submit-publish").disabled = false;
+ }
+ }
+
+ $('#select-these').click(function(){
+ $('#updatepublishedtable input').each(function(){
+ $(this).prop('checked', true);
+ });
+ update_publish_status();
+ });
+
+ $('#unselect-these').click(function(){
+ $('#updatepublishedtable input').each(function(){
+ $(this).prop('checked', false);
+ });
+ update_publish_status();
+ });
+
+ // Open Publish Action
+ $('#select-publish').click(function(){
+ if (selected_publish) {
+ selected_publish=false;
+ $("#select-these").removeAttr("disabled");
+ $("#unselect-these").removeAttr("disabled");
+ $("#details-publish").slideUp();
+ } else {
+ selected_publish=true;
+ $("#select-these").attr("disabled","disabled");
+ $("#unselect-these").attr("disabled","disabled");
+ update_publish_status();
+ $("#details-publish").slideDown();
+ }
+ });
+
+ $('#submit-publish').click(function(){
+ var cve_list="";
+ $('#updatepublishedtable input').each(function(){
+ if ($(this).is(':checked')) {
+ cve_list +=$(this).prop('name') + ",";
+ }
+ });
+ if ("" == cve_list) {
+ alert("No CVE's were selected");
+ return;
+ }
+ publish_state=$('#select-publish-state').val();
+ postCommitAjaxRequest({
+ "publish_state" : publish_state,
+ "cve_list" : cve_list,
+ });
+
+// $.post("/srtgui/export/publish_cve", {parent_page:'publish_cve',cve_list:cve_list,report_type:$('#report_type').val(),report_format:$('#report_format').val(),csrfmiddlewaretoken:'{{ csrf_token }}'}, function(result){
+// alert(result);
+// });
+
+ });
+
+ // When change in CVE selections, update labels and enables
+ $(document).on("change", "#updatepublishedtable :checkbox", function() {
+ update_publish_status();
+ });
+
+
+ // Standard Toaster Table enablement
+
+ var tableElt = $("#{{table_name}}");
+ var titleElt = $("[data-role='page-title']");
+
+ tableElt.on("table-done", function (e, total, tableParams) {
+ var title = "Publish Requested CVE's";
+
+ if (tableParams.search || tableParams.filter) {
+ if (total === 0) {
+ title = "No CVE's found";
+ }
+ else if (total > 0) {
+ title = total + " CVE" + (total > 1 ? "'s" : '') + " found";
+ }
+ }
+
+ titleElt.text(title);
+ cve_total = total;
+ update_publish_status();
+
+ /* Set the report link */
+ var record_list=""
+ $(".name > a").each(function(){
+ var this_id=$(this).prop('id');
+ if (this_id.startsWith("dataid_")) {
+ record_list += this_id.replace(/dataid_/,"") + ",";
+ }
+ });
+ $('#report_link').attr('href',"{% url 'report' request.resolver_match.url_name %}?record_list="+record_list);
+
+ });
+ });
+ </script>
+{% endblock %}
diff --git a/lib/srtgui/templates/report.html b/lib/srtgui/templates/report.html
new file mode 100644
index 00000000..d4d27f76
--- /dev/null
+++ b/lib/srtgui/templates/report.html
@@ -0,0 +1,73 @@
+{% extends "base.html" %}
+
+{% load static %}
+{% load projecttags %}
+{% load humanize %}
+
+{% block title %} Report/Export {% endblock %}
+
+{% block pagecontent %}
+ <div class="row">
+ <div class="col-md-7" style="padding-left: 50px;">
+ <h1>Report/Export: {{title}}</h1>
+ </div>
+ </div>
+
+ <form method="POST">{% csrf_token %}
+ <input type="hidden" name="parent_page" value="{{parent_page}}">
+ <input type="hidden" name="record_list" value="{{record_list}}">
+
+ {% if report_type_list %}
+ <hr>
+ Report Type:<br>
+ <select name="report_type">
+ {{report_type_list|safe}}
+ </select>
+ {% else %}
+ <hr>
+ Note: There is no report defined for this page.<br>
+ {% endif %}
+
+ {% if report_get_title %}
+ <hr>
+ Title:<br>
+ <input type="text" name="title">
+ <br>
+ {% endif %}
+ <hr>
+
+ {% if report_recordrange_list %}
+ Record Range:<br>
+ {{report_recordrange_list|safe}}
+ <br>
+ {% endif %}
+ {% if report_columnrange_list %}
+ Column Range:<br>
+ {{report_columnrange_list|safe}}
+ {% endif %}
+ <hr>
+
+ {% if report_format_list %}
+ Export Format:<br>
+ {{report_format_list|safe}}
+ <hr>
+ {% endif %}
+
+ {% if report_custom_list %}
+ Page Specific Settings:<br>
+ {{report_custom_list|safe}}
+ <hr>
+ {% endif %}
+
+ {% if report_enable_submit %}
+ <input type="submit" id="submit-report-button" class="btn btn-primary btn-lg" value="Generate and Download Report"/>
+ <a class="btn btn-info btn-lg" id="report-done" href="{% url 'landing' %}">Done</a>
+ {% else %}
+ <a class="btn btn-info btn-lg" id="report-cancel" href="{% url 'landing' %}">Cancel</a>
+ {% endif %}
+
+ </form>
+
+<br>
+{% endblock %}
+
diff --git a/lib/srtgui/templates/sources-toastertable.html b/lib/srtgui/templates/sources-toastertable.html
new file mode 100644
index 00000000..1721e3b0
--- /dev/null
+++ b/lib/srtgui/templates/sources-toastertable.html
@@ -0,0 +1,72 @@
+{% extends 'base.html' %}
+{% load static %}
+
+{% block extraheadcontent %}
+ <link rel="stylesheet" href="{% static 'css/jquery-ui.min.css' %}" type='text/css'>
+ <link rel="stylesheet" href="{% static 'css/jquery-ui.structure.min.css' %}" type='text/css'>
+ <link rel="stylesheet" href="{% static 'css/jquery-ui.theme.min.css' %}" type='text/css'>
+ <script src="{% static 'js/jquery-ui.min.js' %}">
+ </script>
+{% endblock %}
+
+{% block title %} Data Sources - SRTool {% endblock %}
+
+{% block pagecontent %}
+
+<div class="row">
+ <!-- Breadcrumbs -->
+ <div class="col-md-12">
+ <ul class="breadcrumb" id="breadcrumb">
+ <li><a href="{% url 'landing' %}">Home</a></li><span class="divider">&rarr;</span>
+ <li><a href="{% url 'manage' %}">Management</a></li><span class="divider">&rarr;</span>
+ <li>Data Sources</li>
+ </ul>
+ </div>
+</div>
+
+
+<div class="row">
+ <div class="col-md-12">
+ <div class="page-header">
+ <h1 class="top-air" data-role="page-title"></h1>
+ </div>
+
+ {# xhr_table_url is just the current url so leave it blank #}
+ {% url '' as xhr_table_url %}
+ {% include 'toastertable.html' %}
+ </div>
+</div>
+
+ <script>
+ $(document).ready(function () {
+ var tableElt = $("#{{table_name}}");
+ var titleElt = $("[data-role='page-title']");
+
+ tableElt.on("table-done", function (e, total, tableParams) {
+ var title = "Data Sources";
+
+ if (tableParams.search || tableParams.filter) {
+ if (total === 0) {
+ title = "No Data Sources found";
+ }
+ else if (total > 0) {
+ title = total + " Data Source" + (total > 1 ? 's' : '') + " found";
+ }
+ }
+
+ titleElt.text(title);
+
+ /* Set the report link */
+ var record_list=""
+ $(".data > span").each(function(){
+ var this_id=$(this).prop('id');
+ if (this_id.startsWith("dataid_")) {
+ record_list +=this_id.replace(/dataid_/,"") + ",";
+ }
+ });
+ $('#report_link').attr('href',"{% url 'report' request.resolver_match.url_name %}?record_list="+record_list);
+
+ });
+ });
+ </script>
+{% endblock %}
diff --git a/lib/srtgui/templates/triage_cves.html b/lib/srtgui/templates/triage_cves.html
index 7325dce8..1df170ab 100644
--- a/lib/srtgui/templates/triage_cves.html
+++ b/lib/srtgui/templates/triage_cves.html
@@ -22,12 +22,18 @@
</ul>
<a class="btn btn-info btn-lg" href="{% url 'keywords' %}">Manage Keyword Filters</a></td>
-<h2> Guided Bulk Triage </h2>
+<h2> New CVEs Triage </h2>
<ul>
- <li>Select a range of similar CVE's via scoring, string matches, and filters</li>
+ <li>Select a range of similar new incoming CVE's via scoring, string matches, and filters</li>
<li>You can then (a) review/sample them, (b) select all or some, and then (c) click a button to bulk assign them</li>
</ul>
<a class="btn btn-info btn-lg" href="{% url 'select-cves' %}">Incoming CVE Triage Page</a>
+
+<h2> Updated CVEs Triage</h2>
+<ul>
+ <li>Select a range of similar updated CVE's via scoring, string matches, and filters</li>
+ <li>You can then (a) review/sample them, (b) select all or some, and then (c) click a button to bulk assign them</li>
+</ul>
<a class="btn btn-info btn-lg" href="{% url 'tbd' %}">Updated CVE Triage Page</a>
<h2> Guided Manual Triage </h2>
diff --git a/lib/srtgui/templates/users.html b/lib/srtgui/templates/users.html
index f934e552..3837b1fb 100644
--- a/lib/srtgui/templates/users.html
+++ b/lib/srtgui/templates/users.html
@@ -42,7 +42,7 @@
</div>
</div>
-<div class="row">
+<div class="row" style="padding-left: 25px;">
<h3>User List
<a class="btn btn-default navbar-btn " id="new-investigation-attachement" href="{% url 'login' %}">Add user</a>
</h3>
@@ -59,17 +59,17 @@
</thead>
{% if object.all %}
- {% for p in object.all %}
+ {% for user in object.all %}
<tr>
- <td>{{ p.name }} </td>
- <td>{{ p.email }} </td>
- <td>{{ p.role }} </td>
- <td>{{ p.get_access_text }} </td>
+ <td>{{ user.name }} </td>
+ <td>{{ user.email }} </td>
+ <td>{{ user.role }} </td>
+ <td>{{ user.get_access_text }} </td>
<td>
- {% if p.name != "Guest" %}
- <span id="user_'+{{p.id}}+'" class="js-user-name"></span>
- <span class="glyphicon glyphicon-edit js-icon-pencil-config_var" id="user_'+{{p.id}}+'" x-data="'+{{p.id}}+'"></span>
- <span class="glyphicon glyphicon-trash js-icon-trash-config_var" id="user_'+{{p.id}}+'" x-data="'+{{p.id}}+'"></span>
+ {% if not user.builtin %}
+ <span id="user_'+{{user.id}}+'" class="js-user-name"></span>
+ <span class="glyphicon glyphicon-edit js-icon-pencil-config_var" id="user_'+{{user.id}}+'" x-data="'+{{user.id}}+'"></span>
+ <span class="glyphicon glyphicon-trash js-icon-trash-config_var" id="user_'+{{user.id}}+'" x-data="'+{{user.id}}+'"></span>
{% endif %}
</td>
diff --git a/lib/srtgui/templates/vulnerabilities-toastertable.html b/lib/srtgui/templates/vulnerabilities-toastertable.html
index 27d8bea4..5a5bae50 100644
--- a/lib/srtgui/templates/vulnerabilities-toastertable.html
+++ b/lib/srtgui/templates/vulnerabilities-toastertable.html
@@ -30,7 +30,8 @@
<h1 class="top-air" data-role="page-title"></h1>
</div>
- {% url 'cves' as xhr_table_url %}
+ {# xhr_table_url is just the current url so leave it blank #}
+ {% url '' as xhr_table_url %}
{% include 'toastertable.html' %}
</div>
</div>
@@ -53,7 +54,21 @@
}
titleElt.text(title);
+
+ /* Set the report link */
+ var record_list=""
+ $(".name > a").each(function(){
+ /* if ('id' in $(this)) { */
+ var this_id=$(this).prop('id');
+ if (this_id.startsWith("dataid_")) {
+ record_list +=this_id.replace(/dataid_/,"") + ",";
+ }
+ /* } */
+ });
+ $('#report_link').attr('href',"{% url 'report' request.resolver_match.url_name %}?record_list="+record_list);
+
});
});
</script>
{% endblock %}
+
diff --git a/lib/srtgui/templates/vulnerability.html b/lib/srtgui/templates/vulnerability.html
index b238f7fc..ec0df78b 100644
--- a/lib/srtgui/templates/vulnerability.html
+++ b/lib/srtgui/templates/vulnerability.html
@@ -1,9 +1,32 @@
{% extends "base.html" %}
-
{% load projecttags %}
-{% block title %} {{object.name}} - SRTool {% endblock %}
+{% block extraheadcontent %}
+ <style>
+ /* Style the execution buttons */
+ /*button.execute { height:50px;width:210px;background-color:#4CAF50;text-align:center; border:2px #f69c55;border-radius: 12px; }*/
+
+ button:disabled {
+ cursor: not-allowed;
+ }
+
+ /* Create two equal columns that floats next to each other */
+ .column {
+ float: left;
+ width: 350px;
+ padding: 10px;
+ }
+
+ /* Clear floats after the columns */
+ .row:after {
+ content: "";
+ display: table;
+ clear: both;
+ }
+ </style>
+{% endblock %}
+{% block title %} {{object.name}} - SRTool {% endblock %}
{% block pagecontent %}
<div class="row">
@@ -56,9 +79,10 @@
</div>
<div class="col-md-5">
<div class="well">
- <h2>Quick Info</h2>
-
-
+ <h2>Quick Info
+ {% if access.is_creator %}
+ <button id="select-quickedit" class="btn btn-default" type="button">Edit ...</button>
+ {% endif %}</h2>
<dl class="dl-horizontal">
<dt>CVE Dictionary Entry:</dt>
<dd>
@@ -98,18 +122,104 @@
<dd>
{{object.get_severity_text}}
</dd>
+ <dt>Note:</dt>
+ <dd>
+ {{object.comments}}
+ </dd>
+ <dt>Private Note:</dt>
+ <dd>
+ {{object.comments_private}}
+ </dd>
+
+ <div id="details-quickedit" style="display:none;">
+ <p><p>
+ <button class="execute" id="submit-quickedit"> Submit Changes </button>
+ <p><input type="text" placeholder="Edit Note" id="text-note" size="40" value="{{object.comments}}"></p>
+ <p><input type="text" placeholder="Edit Private Note" id="text-private-note" size="40" value="{{object.comments_private}}"></p>
+ <p><p>
+ <div class="row">
+ <div class="column">
+ <p><b><label id="set_status">Set Status:</label></b>
+ <div id="status-list" class="scrolling" style="width: 300px;">
+ <div class="checkbox"> <label>
+ <input type="radio" name="status" value="2" type="checkbox" {%if 2 == object.status %}checked="checked"{% endif %}> Vulnerable
+ </label><p></div>
+ <div class="checkbox"> <label>
+ <input type="radio" name="status" value="1" type="checkbox" {%if 1 == object.status %}checked="checked"{% endif %}> Not Vulnerable
+ </label><p></div>
+ <div class="checkbox"> <label>
+ <input type="radio" name="status" value="0" type="checkbox" {%if 0 == object.status %}checked="checked"{% endif %}> Investiage
+ </label><p></div>
+ </div>
+ </div>
+ <div class="column">
+ <p><b><label id="set_outcome">Set Outcome:</label></b>
+ <div id="outcome-list" class="scrolling" style="width: 300px;">
+ <div class="checkbox"> <label>
+ <input type="radio" name="outcome" value="3" type="checkbox" {%if 3 == object.outcome %}checked="checked"{% endif %}> Not Fix
+ </label><p></div>
+ <div class="checkbox"> <label>
+ <input type="radio" name="outcome" value="2" type="checkbox" {%if 2 == object.outcome %}checked="checked"{% endif %}> Closed (Not Vulnerable)
+ </label><p></div>
+ <div class="checkbox"> <label>
+ <input type="radio" name="outcome" value="1" type="checkbox" {%if 1 == object.outcome %}checked="checked"{% endif %}> Closed (Fixed)
+ </label><p></div>
+ <div class="checkbox"> <label>
+ <input type="radio" name="outcome" value="0" type="checkbox" {%if 0 == object.outcome %}checked="checked"{% endif %}> Open
+ </label><p></div>
+ </div>
+ </div>
+ <div class="column">
+ <p><b><label id="set_severity">Set Severity:</label></b>
+ <div id="severity-list" class="scrolling" style="width: 300px;">
+ <div class="checkbox"> <label>
+ <input type="radio" name="severity" value="4" type="checkbox" {%if 4 == object.severity %}checked="checked"{% endif %}> High
+ </label><p></div>
+ <div class="checkbox"> <label>
+ <input type="radio" name="severity" value="3" type="checkbox" {%if 3 == object.severity %}checked="checked"{% endif %}> Medium
+ </label><p></div>
+ <div class="checkbox"> <label>
+ <input type="radio" name="severity" value="2" type="checkbox" {%if 2 == object.severity %}checked="checked"{% endif %}> Low
+ </label><p></div>
+ <div class="checkbox"> <label>
+ <input type="radio" name="severity" value="1" type="checkbox" {%if 0 == object.severity %}checked="checked"{% endif %}> Minor
+ </label><p></div>
+ <div class="checkbox"> <label>
+ <input type="radio" name="severity" value="0" type="checkbox" {%if 0 == object.severity %}checked="checked"{% endif %}> Undefined
+ </label><p></div>
+ </div>
+ </div>
+ </div>
+ </div>
</dl>
</div>
</div>
</div>
-<div class="row">
+<div class="row" style="padding-left: 25px;">
<h3>Affected Products
{% if access.is_creator %}
- <a class="btn btn-default navbar-btn " id="new-investigation-attachement" href="{% url 'login' %}">Add product</a>
+ <button id="select-addaffectedproduct" class="btn btn-default" type="button">Add product ...</button>
{% endif %}
</h3>
+ <div id="details-addaffectedproduct" style="padding-left: 50px; display:none;">
+ <p><p>
+ <button class="execute" id="submit-addaffectedproduct"> Submit </button>
+ <div class="row">
+ <div id="all-affectedproducts" class="scrolling" style="width: 300px;">
+ {% for product in products %}
+ <div class="checkbox">
+ <label>
+ <input class="checkbox-products" name="{{product.pk}}" type="checkbox">{{product.long_name}}
+ </label>
+ <p>
+ </div>
+ {% endfor %}
+ </div>
+ </div>
+ </div>
+
<table class="table table-striped table-condensed" data-testid="vuln-hyperlinks-table">
<thead>
<tr>
@@ -128,19 +238,20 @@
{% if object.get_affected_list.all %}
{% for p in object.get_affected_list.all %}
<tr>
- <td>{{ p.product.name }} {{ p.product.version }} {{ p.product.profile }} </td>
+ {% if p.product != '%s' %} <!-- hack for null records -->
+ <td><a href="{% url 'product' p.product.id %}">{{ p.product.long_name }}<a></td>
{% if p.investigation %}
<td><a href="{% url 'investigation' p.investigation.id %}">{{ p.investigation.name }}<a></td>
<td>{{ p.investigation.get_status_text }}</td>
<td>{{ p.investigation.get_outcome_text }}</td>
<td>
{% for ij in p.investigation.investigation_to_defect.all %}
- {% if not forloop.first %}| {% endif %}<a href="http://defect.wrs.com/browse/{{ij.defect.name}}" target="_blank">{{ij.defect.name}} </a>
+ {% if not forloop.first %}| {% endif %}<a href="{% url 'defect' ij.defect.id %}">{{ij.defect.name}} </a>
{% endfor %}
</td>
<td>
{% for ij in p.investigation.investigation_to_defect.all %}
- {% if not forloop.first %}| {% endif %}<a href="http://defect.wrs.com/browse/{{ij.defect.name}}" target="_blank">{{ij.defect.release_version}} </a>
+ {% if not forloop.first %}| {% endif %}<a href="{% url 'defect' ij.defect.id %}">{{ij.defect.release_version}} </a>
{% endfor %}
</td>
{% else %}
@@ -153,10 +264,10 @@
{% if access.is_creator %}
<td>
<span id="affected_entry_'+{{p.id}}+'" class="js-config-var-name"></span>
- <span class="glyphicon glyphicon-edit js-icon-pencil-config_var" id="affected_edit_'+{{p.id}}+'" x-data="'+{{p.id}}+'"></span>
- <span class="glyphicon glyphicon-trash js-icon-trash-config_var" id="affected_trash_'+{{p.id}}+'" x-data="'+{{p.id}}+'"></span>
+ <span class="glyphicon glyphicon-trash trash-affected" id="affected_trash_'+{{p.id}}+'" x-data="{{p.id}}"></span>
</td>
{% endif %}
+ {% endif %}
</tr>
{% endfor %}
{% else %}
@@ -168,13 +279,30 @@
</div>
-<div class="row">
+<div class="row" style="padding-left: 25px;">
<h3>Related Products
{% if access.is_creator %}
- <a class="btn btn-default navbar-btn " id="new-investigation-attachement" href="{% url 'login' %}">Add product</a>
+ <button id="select-addrelatedproduct" class="btn btn-default" type="button">Add product ...</button>
{% endif %}
</h3>
+ <div id="details-addrelatedproduct" style="padding-left: 50px; display:none;">
+ <p><p>
+ <button class="execute" id="submit-addrelatedproduct"> Submit </button>
+ <div class="row">
+ <div id="all-relatedproducts" class="scrolling" style="width: 300px;">
+ {% for product in products %}
+ <div class="checkbox">
+ <label>
+ <input class="checkbox-products" name="{{product.pk}}" type="checkbox">{{product.long_name}}
+ </label>
+ <p>
+ </div>
+ {% endfor %}
+ </div>
+ </div>
+ </div>
+
<table class="table table-striped table-condensed" data-testid="vuln-hyperlinks-table">
<thead>
<tr>
@@ -188,15 +316,16 @@
{% if object.get_related_list.all %}
{% for p in object.get_related_list.all %}
<tr>
- <td>{{ p.product.name }} {{ p.product.version }} {{ p.product.profile }} </td>
+ {% if p.product != '%s' %} <!-- hack for null records -->
+ <td><a href="{ % url 'product' p.product.id % }">{{p.product.long_name}}</a></td>
<td>Not vulnerable</td>
{% if access.is_creator %}
<td>
<span id="related_var_entry_'+{{p.id}}+'" class="js-config-var-name"></span>
- <span class="glyphicon glyphicon-edit js-icon-pencil-config_var" id="affected_edit_'+{{p.id}}+'" x-data="'+{{p.id}}+'"></span>
- <span class="glyphicon glyphicon-trash js-icon-trash-config_var" id="related_trash_'+{{p.id}}+'" x-data="'+{{p.id}}+'"></span>
+ <span class="glyphicon glyphicon-trash trash-related" id="related_trash_'+{{p.id}}+'" x-data="{{p.id}}"></span>
</td>
{% endif %}
+ {% endif %}
</tr>
{% endfor %}
{% else %}
@@ -209,13 +338,17 @@
</div>
-<div class="row">
+<div class="row" style="padding-left: 25px;">
<h3>Comments
{% if access.is_creator %}
- <a class="btn btn-default navbar-btn " id="new-investigation-comment" href="{% url 'login' %}">Add comment</a>
+ <button id="select-newcomment" class="btn btn-default" type="button">Add comment ...</button>
{% endif %}
</h3>
+<div id="input-newcomment" style="padding-left: 50px; display:none;">
+ <p><input type="text" id="text-newcomment" size="40"> <button class="execute" id="submit-newcomment"> Submit </button></p>
+</div>
+
<table class="table table-striped table-condensed" data-testid="vuln-hyperlinks-table">
<thead>
<tr>
@@ -234,11 +367,10 @@
<td>{{ c.comment }}</td>
<td>{{ c.date }}</td>
<td>{{ c.author }}</td>
- {% if access.is_creator %}
+ {% if access.is_creator or c.author == access.current_user_name %}
<td>
<span id="config_var_entry_'+configvars_sorted[i][2]+'" class="js-config-var-name"></span>
- <span class="glyphicon glyphicon-edit js-icon-pencil-config_var" id="comment_edit_'+{{c.id}}+'" x-data="'+{{c.id}}+'"></span>
- <span class="glyphicon glyphicon-trash js-icon-trash-config_var" id="comment_trash_'+{{c.id}}+'" x-data="'+{{c.id}}+'"></span>
+ <span class="glyphicon glyphicon-trash trash-comment" id="comment_trash_'+{{c.id}}+'" x-data="{{c.id}}"></span>
</td>
{% endif %}
</tr>
@@ -252,13 +384,25 @@
</div>
-<div class="row">
+<div class="row" style="padding-left: 25px;">
<h3>Attachments
{% if access.is_creator %}
- <a class="btn btn-default navbar-btn " id="new-investigation-attachement" href="{% url 'login' %}">Add attachment</a>
+ <a class="btn btn-default navbar-btn " id="select-addattachment">Add attachment ... </a>
{% endif %}
</h3>
+ <div id="details-addattachment" style="padding-left: 50px; display:none;">
+ <p><p>
+ <div class="row">
+ <form id="uploadbanner" enctype="multipart/form-data" method="post">{% csrf_token %}
+ <input id="fileDescription" name="fileDescription" type="text" placeholder="Enter Description" />
+ <input id="fileUpload" name="fileUpload" type="file" />
+ <input type="hidden" id="action" name="action" value="upload">
+ <input type="submit" value="submit file" id="submit-addattachment" />
+ </form>
+ </div>
+ </div>
+
<table class="table table-striped table-condensed" data-testid="vuln-hyperlinks-table">
<thead>
<tr>
@@ -275,17 +419,20 @@
{% for u in object.vulnerability_uploads.all %}
<tr>
<td>{{ u.description }}</td>
- <td>{{ u.path }}</td>
+ <td>{{ u.path|basename }}</td>
<td>{{ u.size }}</td>
<td>{{ u.date }}</td>
<td>{{ u.author }}</td>
<td>
<span id="attachment_entry_'+{{u.id}}+'" class="js-config-var-name"></span>
- <span class="glyphicon glyphicon-download-alt get-help" title="Download document"></span>
- {% if access.is_creator %}
- <span class="glyphicon glyphicon-edit js-icon-pencil-config_var" id="affected_edit_'+{{u.id}}+'" x-data="'+{{u.id}}+'"></span>
- <span class="glyphicon glyphicon-trash js-icon-trash-config_var" id="attachment_trash_'+{{u.id}}+'" x-data="'+{{u.id}}+'"></span>
- {% endif %}
+ <form id="downloadbanner" enctype="multipart/form-data" method="post" >{% csrf_token %}
+ <input type="hidden" id="action" name="action" value="download">
+ <input type="hidden" id="record_id" name="record_id" value={{u.id}}>
+ <span class="glyphicon glyphicon-download-alt submit-downloadattachment" id="attachment_download_'+{{u.id}}+'" x-data="{{u.id}}"></span>
+ {% if access.is_creator %}
+ <span class="glyphicon glyphicon-trash trash-attachment" id="attachment_trash_'+{{u.id}}+'" x-data="{{u.id}}"></span>
+ {% endif %}
+ </form>
</td>
</tr>
{% endfor %}
@@ -295,18 +442,35 @@
</tr>
{% endif %}
</table>
-
</div>
<br/>
-<div class="row">
+<div class="row" style="padding-left: 25px;">
<h3>Change Notifications
{% if access.is_creator %}
- <a class="btn btn-default navbar-btn " id="new-investigation-notify" href="{% url 'login' %}">Add user notification</a>
+ <button id="select-addusernotify" class="btn btn-default" type="button">Add user notification ...</button>
{% endif %}
</h3>
+ <div id="details-addusernotify" style="padding-left: 50px; display:none;">
+ <p><p>
+ <button class="execute" id="submit-addusernotify"> Submit </button>
+ <div class="row">
+ <p>
+ <div id="all-users" class="scrolling" style="width: 300px;">
+ {% for user in users %}
+ <div class="checkbox">
+ <label>
+ <input class="checkbox-users" name="{{user.pk}}" type="checkbox">{{user.name}}
+ </label>
+ <p>
+ </div>
+ {% endfor %}
+ </div>
+ </div>
+ </div>
+
<table class="table table-striped table-condensed" data-testid="vuln-hyperlinks-table">
<thead>
<tr>
@@ -318,16 +482,15 @@
</tr>
</thead>
- {% if object.vulnerability_users.all %}
- {% for u in object.vulnerability_users.all %}
+ {% if object.vulnerability_notification.all %}
+ {% for u in object.vulnerability_notification.all %}
<tr>
<td>{{ u.user.name }}</td>
<td>{{ u.user.email }}</td>
- {% if access.is_creator %}
+ {% if access.is_creator or u.user.name == access.current_user_name %}
<td>
<span id="attachment_entry_'+{{u.id}}+'" class="js-config-var-name"></span>
- <span class="glyphicon glyphicon-edit js-icon-pencil-config_var" id="affected_edit_'+{{u.id}}+'" x-data="'+{{u.id}}+'"></span>
- <span class="glyphicon glyphicon-trash js-icon-trash-config_var" id="attachment_trash_'+{{u.id}}+'" x-data="'+{{u.id}}+'"></span>
+ <span class="glyphicon glyphicon-trash trash-usernotification" id="attachment_trash_'+{{u.id}}+'" x-data="{{u.id}}"></span>
</td>
{% endif %}
</tr>
@@ -341,15 +504,34 @@
</div>
-{% if access.is_creator %}
+{% if not object.public %}
+ {% if access.is_creator %}
- <div class="row">
+ <div class="row" style="padding-left: 25px;">
<h3>User Access
{% if access.is_creator %}
- <a class="btn btn-default navbar-btn " id="new-investigation-access" href="{% url 'login' %}">Add user access</a>
+ <button id="select-adduseraccess" class="btn btn-default" type="button">Add user access ...</button>
{% endif %}
</h3>
+ <div id="details-adduseraccess" style="padding-left: 50px; display:none;">
+ <p><p>
+ <button class="execute" id="submit-adduseraccess"> Submit </button>
+ <div class="row">
+ <p>
+ <div id="all-users" class="scrolling" style="width: 300px;">
+ {% for user in users %}
+ <div class="checkbox">
+ <label>
+ <input class="checkbox-users" name="{{user.pk}}" type="checkbox">{{user.name}}
+ </label>
+ <p>
+ </div>
+ {% endfor %}
+ </div>
+ </div>
+ </div>
+
<table class="table table-striped table-condensed" data-testid="vuln-hyperlinks-table">
<thead>
<tr>
@@ -372,8 +554,7 @@
<td>{{ u.user.name }}</td>
<td>
<span id="attachment_entry_'+{{u.id}}+'" class="js-config-var-name"></span>
- <span class="glyphicon glyphicon-edit js-icon-pencil-config_var" id="affected_edit_'+{{u.id}}+'" x-data="'+{{u.id}}+'"></span>
- <span class="glyphicon glyphicon-trash js-icon-trash-config_var" id="attachment_trash_'+{{u.id}}+'" x-data="'+{{u.id}}+'"></span>
+ <span class="glyphicon glyphicon-trash trash-useraccess" id="attachment_trash_'+{{u.id}}+'" x-data="{{u.id}}"></span>
</td>
</tr>
{% endfor %}
@@ -387,9 +568,10 @@
</table>
</div>
+ {% endif %}
{% endif %}
-<div class="row">
+<div class="row" style="padding-left: 25px;">
<h3>History</h3>
<table class="table table-striped table-condensed" data-testid="vuln-hyperlinks-table">
<thead>
@@ -415,5 +597,339 @@
</table>
</div>
+<!-- Javascript support -->
+<script>
+ var selected_addrelatedproduct=false;
+ var selected_addaffectedproduct=false;
+ var selected_newcomment=false;
+ var selected_addusernotify=false;
+ var selected_adduseraccess=false;
+ var selected_quickedit=false;
+ var selected_addattachment=false;
+
+ window.onload = function() {
+ $("input[name=status][value=" + {{ object.status }} + "]").prop('checked', true);
+ $("input[name=outcome][value=" + {{ object.outcome }} + "]").prop('checked', true);
+ $("input[name=severity][value=" + {{ object.severity }} + "]").prop('checked', true);
+ }
+
+ $(document).ready(function() {
+ function onCommitAjaxSuccess(data, textstatus) {
+ if (window.console && window.console.log) {
+ console.log("XHR returned:", data, "(" + textstatus + ")");
+ } else {
+ alert("NO CONSOLE:\n");
+ return;
+ }
+ if (data.error != "ok") {
+ alert("error on request:\n" + data.error);
+ return;
+ }
+ // reload the page with the updated tables
+ location.reload(true);
+ }
+
+ function onCommitAjaxError(jqXHR, textstatus, error) {
+ console.log("ERROR:"+error+"|"+textstatus);
+ alert("XHR errored1:\n" + error + "\n(" + textstatus + ")");
+ }
+
+ /* ensure cookie exists {% csrf_token %} */
+ function postCommitAjaxRequest(reqdata) {
+ reqdata["vulnerability_id"] = {{ object.id }}
+ var ajax = $.ajax({
+ type:"POST",
+ data: reqdata,
+ url:"{% url 'xhr_vulnerability_commit' %}",
+ headers: { 'X-CSRFToken': $.cookie("csrftoken")},
+ success: onCommitAjaxSuccess,
+ error: onCommitAjaxError,
+ })
+ }
+
+ $('#select-these').click(function(){
+ $(':checkbox').each(function(){
+ $(this).prop('checked', true);
+ });
+ });
+
+ $('#unselect-these').click(function(){
+ $(':checkbox').each(function(){
+ $(this).prop('checked', false);
+ });
+ });
+
+ $('#select-quickedit').click(function(){
+ if (selected_quickedit) {
+ selected_quickedit=false;
+ $("#select-these").removeAttr("disabled");
+ $("#unselect-these").removeAttr("disabled");
+ $("#details-quickedit").slideUp();
+ } else {
+ selected_quickedit=true;
+ $("#select-these").attr("disabled","disabled");
+ $("#unselect-these").attr("disabled","disabled");
+ $("#details-quickedit").slideDown();
+ }
+ });
+
+ $('#submit-quickedit').click(function(){
+ var note=$('#text-note').val().trim()
+ var private_note=$('#text-private-note').val().trim()
+ var status=0
+ $('#status-list input').each(function(){
+ if ($(this).is(':checked')) {
+ status = $(this).prop('value');
+ }
+ });
+ var outcome=0
+ $('#outcome-list input').each(function(){
+ if ($(this).is(':checked')) {
+ outcome = $(this).prop('value');
+ }
+ });
+ var severity=0
+ $('#severity-list input').each(function(){
+ if ($(this).is(':checked')) {
+ severity = $(this).prop('value');
+ }
+ });
+
+ postCommitAjaxRequest({
+ "action" : 'submit-quickedit',
+ "note" : note,
+ "private_note" : private_note,
+ "status" : status,
+ "outcome" : outcome,
+ "severity" : severity,
+ });
+ });
+
+ $('#select-addrelatedproduct').click(function(){
+ if (selected_addrelatedproduct) {
+ selected_addrelatedproduct=false;
+ $("#select-these").removeAttr("disabled");
+ $("#unselect-these").removeAttr("disabled");
+ $("#details-addrelatedproduct").slideUp();
+ } else {
+ selected_addrelatedproduct=true;
+ $("#select-these").attr("disabled","disabled");
+ $("#unselect-these").attr("disabled","disabled");
+ $("#details-addrelatedproduct").slideDown();
+ }
+ });
+
+ $('#submit-addrelatedproduct').click(function(){
+ var product_list=""
+ $(':checkbox').each(function(){
+ if ($(this).is(':checked')) {
+ product_list += $(this).prop('name') + ",";
+ }
+ });
+ if ("" == product_list) {
+ alert("No products were selected");
+ return;
+ }
+ postCommitAjaxRequest({
+ "action" : 'submit-addrelatedproduct',
+ "products" : product_list,
+ });
+ });
+
+ $('.trash-related').click(function() {
+ var result = confirm("Are you sure?");
+ if (result){
+ postCommitAjaxRequest({
+ "action" : 'submit-trashrelated',
+ "record_id" : $(this).attr('x-data'),
+ });
+ }
+ });
+
+ $('#select-addaffectedproduct').click(function(){
+ if (selected_addaffectedproduct) {
+ selected_addaffectedproduct=false;
+ $("#select-these").removeAttr("disabled");
+ $("#unselect-these").removeAttr("disabled");
+ $("#details-addaffectedproduct").slideUp();
+ } else {
+ selected_addaffectedproduct=true;
+ $("#select-these").attr("disabled","disabled");
+ $("#unselect-these").attr("disabled","disabled");
+ $("#details-addaffectedproduct").slideDown();
+ }
+ });
+
+ $('#submit-addaffectedproduct').click(function(){
+ var product_list=""
+ $(':checkbox').each(function(){
+ if ($(this).is(':checked')) {
+ product_list += $(this).prop('name') + ",";
+ }
+ });
+ if ("" == product_list) {
+ alert("No products were selected");
+ return;
+ }
+ postCommitAjaxRequest({
+ "action" : 'submit-addaffectedproduct',
+ "products" : product_list,
+ });
+ });
+
+ $('.trash-affected').click(function() {
+ var result = confirm("Are you sure?");
+ if (result){
+ postCommitAjaxRequest({
+ "action" : 'submit-trashaffected',
+ "record_id" : $(this).attr('x-data'),
+ });
+ }
+ });
+
+ $('#select-newcomment').click(function(){
+ if (selected_newcomment) {
+ selected_newcomment=false;
+ $("#input-newcomment").slideUp();
+ } else {
+ selected_newcomment=true;
+ $("#input-newcomment").slideDown();
+ }
+ });
+
+ $('#submit-newcomment').click(function(){
+ var comment=$('#text-newcomment').val().trim()
+ if (comment=="") {
+ alert("No comment was written");
+ return;
+ }
+ postCommitAjaxRequest({
+ "action" : 'submit-newcomment',
+ "comment" : comment,
+ })
+ });
+
+ $('.trash-comment').click(function(){
+ var result = confirm("Are you sure?");
+ if (result){
+ postCommitAjaxRequest({
+ "action" : 'submit-trashcomment',
+ "record_id" : $(this).attr('x-data'),
+ });
+ }
+ })
+
+ $('#select-addattachment').click(function() {
+ if (selected_addattachment) {
+ selected_addattachment=false;
+ $("#details-addattachment").slideUp();
+ } else {
+ selected_addattachment=true;
+ $("#details-addattachment").slideDown();
+ }
+ });
+
+ $('.submit-downloadattachment').click(function() {
+ $("#downloadbanner").submit();
+ });
+
+ $('.trash-attachment').click(function() {
+ var result = confirm("Are you sure?");
+ if (result){
+ postCommitAjaxRequest({
+ "action" : 'submit-trashattachment',
+ "record_id" : $(this).attr('x-data'),
+ });
+ }
+ });
+
+ // Open AddUserNotify Action
+ $('#select-addusernotify').click(function(){
+ if (selected_addusernotify) {
+ selected_addusernotify=false;
+ $("#select-these").removeAttr("disabled");
+ $("#unselect-these").removeAttr("disabled");
+ $("#details-addusernotify").slideUp();
+ } else {
+ selected_addusernotify=true;
+ $("#select-these").attr("disabled","disabled");
+ $("#unselect-these").attr("disabled","disabled");
+ $("#details-addusernotify").slideDown();
+ }
+ });
+
+ $('#submit-addusernotify').click(function(){
+ var user_list=""
+ $(':checkbox').each(function(){
+ if ($(this).is(':checked')) {
+ user_list += $(this).prop('name') + ",";
+ }
+ });
+ if ("" == user_list) {
+ alert("No users were selected");
+ return;
+ }
+ postCommitAjaxRequest({
+ "action" : 'submit-addusernotify',
+ "users" : user_list,
+ });
+ });
+
+ $('.trash-usernotification').click(function(){
+ var result = confirm("Are you sure?");
+ if (result){
+ postCommitAjaxRequest({
+ "action" : 'submit-trashusernotification',
+ "record_id" : $(this).attr('x-data'),
+ });
+ }
+ })
+
+ $('#select-adduseraccess').click(function(){
+ if (selected_adduseraccess) {
+ selected_adduseraccess=false;
+ $("#select-these").removeAttr("disabled");
+ $("#unselect-these").removeAttr("disabled");
+ $("#details-adduseraccess").slideUp();
+ } else {
+ selected_adduseraccess=true;
+ $("#select-these").attr("disabled","disabled");
+ $("#unselect-these").attr("disabled","disabled");
+ $("#details-adduseraccess").slideDown();
+ }
+ });
+
+ $('#submit-adduseraccess').click(function(){
+ var user_list=""
+ $(':checkbox').each(function(){
+ if ($(this).is(':checked')) {
+ user_list += $(this).prop('name') + ",";
+ }
+ });
+ if ("" == user_list) {
+ alert("No users were selected");
+ return;
+ }
+ postCommitAjaxRequest({
+ "action" : 'submit-adduseraccess',
+ "users" : user_list,
+ });
+ });
+
+ $('.trash-useraccess').click(function(){
+ var result = confirm("Are you sure?");
+ if (result){
+ postCommitAjaxRequest({
+ "action" : 'submit-trashuseraccess',
+ "record_id" : $(this).attr('x-data'),
+ });
+ }
+ })
+
+ /* Set the report link */
+ $('#report_link').attr('href',"{% url 'report' request.resolver_match.url_name %}?record_list={{object.id}}");
+ });
+</script>
+
{% endblock %}
diff --git a/lib/srtgui/templatetags/projecttags.py b/lib/srtgui/templatetags/projecttags.py
index b9afebcd..ac35fa0a 100644
--- a/lib/srtgui/templatetags/projecttags.py
+++ b/lib/srtgui/templatetags/projecttags.py
@@ -27,6 +27,7 @@ from django.utils import timezone
from django.template.defaultfilters import filesizeformat
import json as JsonLib
from django.utils.safestring import mark_safe
+import os
register = template.Library()
@@ -308,3 +309,8 @@ def recommend_display(recommend):
return '>= 3'
else:
return '%s' % recommend
+
+@register.filter(name='basename')
+def basename(value):
+ return os.path.basename(value)
+
diff --git a/lib/srtgui/urls.py b/lib/srtgui/urls.py
index e86acbbc..e13939c9 100644
--- a/lib/srtgui/urls.py
+++ b/lib/srtgui/urls.py
@@ -1,7 +1,7 @@
#
-# BitBake Toaster Implementation
+# Security Response Tool Implementation
#
-# Copyright (C) 2013-2017 Intel Corporation
+# Copyright (C) 2017-2018 Wind River Systems
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
@@ -30,81 +30,100 @@ urlpatterns = [
# landing page
url(r'^landing/$', views.landing, name='landing'),
- url(r'^manage/$', views.management, name='manage'),
- url(r'^manage_cpes/$',
- tables.ManageCpeTable.as_view(template_name="manage-cpes-toastertable.html"),
- name='manage_cpes'),
- url(r'^triage_cves/$', views.triage_cves, name='triage_cves'),
- url(r'^create_vulnerability/$', views.create_vulnerability, name='create_vulnerability'),
- url(r'^publish/$', views.publish, name='publish'),
- url(r'^manage_report/$', views.manage_report, name='manage_report'),
-
url(r'^login/$', views.login, name='login'),
- url(r'^users/$', views.users, name='users'),
-
- # TEST CODE
url(r'^login_guest/$', views.login_guest, name='login_guest'),
- url(r'^login_admin/$', views.login_admin, name='login_admin'),
-
+ url(r'^cve/(?P<cve_pk>\d+)$', views.cve, name="cve"),
+ url(r'^cve/(?P<cve_pk>[^\d].+)$', views.cve),
+ url(r'^cve/(?P<cve_pk>\d+)/active_tab/(?P<active_tab>\d{1})$', views.cve, name="cve"),
url(r'^cves/$',
- tables.AllCveTable.as_view(template_name="cves-toastertable.html"),
- name='all-cves'),
-
- url(r'^start-select-cves/$', views.start_select_cves, name='start-select-cves'),
+ tables.CvesTable.as_view(template_name="cves-toastertable.html"),
+ name='cves'),
url(r'^select-cves/$',
tables.SelectCveTable.as_view(template_name="cves-select-toastertable.html"),
name='select-cves'),
- url(r'^cve/(?P<cve_pk>\d+)/active_tab/(?P<active_tab>\d{1})$', views.cve, name="cve"),
- url(r'^cve/(?P<cve_pk>\d+)$', views.cve, name="cve"),
-
+ url(r'^defect/(?P<defect_pk>\d+)$', views.defect, name="defect"),
+ url(r'^defect/(?P<defect_pk>[^\d].+)$', views.defect),
url(r'^defects/$',
- tables.AllDefectTable.as_view(template_name="defects-toastertable.html"),
- name='all-defects'),
+ tables.DefectsTable.as_view(template_name="defects-toastertable.html"),
+ name='defects'),
url(r'^cpes/$',
- tables.AllCpeTable.as_view(template_name="cpes-toastertable.html"),
- name='all-cpes'),
+ tables.CpesTable.as_view(template_name="cpes-toastertable.html"),
+ name='cpes'),
url(r'^cwes/$',
- tables.AllCweTable.as_view(template_name="cwes-toastertable.html"),
- name='all-cwes'),
+ tables.CwesTable.as_view(template_name="cwes-toastertable.html"),
+ name='cwes'),
+ url(r'^product/(?P<product_pk>\d+)$', views.product, name="product"),
url(r'^products/$',
tables.ProductsTable.as_view(template_name="products-toastertable.html"),
name='products'),
+ url(r'^vulnerability/(?P<vulnerability_pk>\d+)$', views.vulnerability, name="vulnerability"),
+ url(r'^vulnerability/(?P<vulnerability_pk>[^\d].+)$', views.vulnerability),
url(r'^vulnerabilities/$',
- tables.AllVulnerabilitiesTable.as_view(template_name="vulnerabilities-toastertable.html"),
+ tables.VulnerabilitiesTable.as_view(template_name="vulnerabilities-toastertable.html"),
name='vulnerabilities'),
- url(r'^vulnerability/(?P<vulnerability_pk>\d+)$', views.vulnerability, name="vulnerability"),
-
+ url(r'^investigation/(?P<investigation_pk>\d+)$', views.investigation, name="investigation"),
+ url(r'^investigation/(?P<investigation_pk>[^\d].+)$', views.investigation),
url(r'^investigations/$',
- tables.AllInvestigationsTable.as_view(template_name="investigations-toastertable.html"),
+ tables.InvestigationsTable.as_view(template_name="investigations-toastertable.html"),
name='investigations'),
- url(r'^investigation/(?P<investigation_pk>\d+)$', views.investigation, name="investigation"),
-
- url(r'^all-keywords/$',
- tables.KeywordsTable.as_view(template_name="keywords-toastertable.html"),
- name='all-keywords'),
-
url(r'^keywords/$', views.keywords, name='keywords'),
+ url(r'^keywords_table/$',
+ tables.KeywordsTable.as_view(template_name="keywords-toastertable.html"),
+ name='keywords_table'),
- url(r'^sources/$', views.sources, name='sources'),
+ url(r'^select-publish/$',
+ tables.SelectPublishTable.as_view(template_name="publish-select-toastertable.html"),
+ name='select-publish'),
- url(r'^export/(?P<page_name>\D+)$', views.export, name='export'),
-# url(r'^export/$', views.export_null, name='export'),
+ url(r'^update-published/$',
+ tables.UpdatePublishedTable.as_view(template_name="published-select-toastertable.html"),
+ name='update-published'),
- url(r'^guided_tour/$', views.guided_tour, name='guided_tour'),
+ url(r'^report/(?P<page_name>\D+)$', views.report, name='report'),
- url(r'^quicklink/$', views.quicklink, name='quicklink'),
url(r'^xhr_triage_commit/$', views.xhr_triage_commit,
name='xhr_triage_commit'),
+ url(r'^xhr_cve_commit/$', views.xhr_cve_commit,
+ name='xhr_cve_commit'),
+
+ url(r'^xhr_vulnerability_commit/$', views.xhr_vulnerability_commit,
+ name='xhr_vulnerability_commit'),
+
+ url(r'^xhr_investigation_commit/$', views.xhr_investigation_commit,
+ name='xhr_investigation_commit'),
+
+ url(r'^xhr_cve_publish_commit/$', views.xhr_cve_publish_commit,
+ name='xhr_cve_publish_commit'),
+
+
+ url(r'^manage/$', views.management, name='manage'),
+ url(r'^manage_cpes/$',
+ tables.ManageCpeTable.as_view(template_name="manage-cpes-toastertable.html"),
+ name='manage_cpes'),
+ url(r'^triage_cves/$', views.triage_cves, name='triage_cves'),
+ url(r'^create_vulnerability/$', views.create_vulnerability, name='create_vulnerability'),
+ url(r'^publish/$', views.publish, name='publish'),
+ url(r'^manage_report/$', views.manage_report, name='manage_report'),
+ url(r'^sources/$',
+ tables.SourcesTable.as_view(template_name="sources-toastertable.html"),
+ name='sources'),
+ url(r'^users/$', views.users, name='users'),
+
+
+ url(r'^guided_tour/$', views.guided_tour, name='guided_tour'),
+
+ url(r'^quicklink/$', views.quicklink, name='quicklink'),
+
url(r'^tbd/$', views.tbd, name='tbd'),
# default redirection
diff --git a/lib/srtgui/views.py b/lib/srtgui/views.py
index 48556b3b..6e215f33 100644
--- a/lib/srtgui/views.py
+++ b/lib/srtgui/views.py
@@ -2,9 +2,9 @@
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
#
-# BitBake Toaster Implementation
+# Security Response Tool Implementation
#
-# Copyright (C) 2013 Intel Corporation
+# Copyright (C) 2017-2018 Wind River Systems
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
@@ -25,18 +25,24 @@ import re
from django.db.models import F, Q, Sum
from django.db import IntegrityError
from django.shortcuts import render, redirect, get_object_or_404
-from orm.models import Cve, CveHistory
-from orm.models import Vulnerability, VulnerabilityHistory, CveToVulnerablility, VulnerabilityProduct
-from orm.models import Investigation, InvestigationHistory, InvestigationToDefect
+from orm.models import Cve, CveDetail, CveHistory
+from orm.models import Vulnerability, VulnerabilityHistory, CveToVulnerablility, VulnerabilityProduct, VulnerabilityNotification, VulnerabilityAccess, VulnerabilityComments, VulnerabilityUploads
+from orm.models import Investigation, InvestigationHistory, InvestigationToDefect, InvestigationComments, InvestigationNotification, InvestigationAccess, InvestigationUploads
from orm.models import SrtSetting, CweTable, Product
-from orm.models import Investigation, DataSource, User, Access
-from orm.models import Defect
+from orm.models import Investigation, DataSource, User, UserSafe, Access
+from orm.models import Defect, PublishPending
+
+from srtgui.reports import ReportManager
+from srtgui.api import readCveDetails
from django.core.urlresolvers import reverse, resolve
from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
-from django.http import HttpResponse, HttpResponseNotFound, JsonResponse
+from django.core.files.uploadedfile import UploadedFile
+from django.http import HttpResponse, HttpResponseNotFound, JsonResponse, HttpResponseRedirect
from django.utils import timezone
+from django import forms
+
from datetime import timedelta, datetime
from srtgui.templatetags.projecttags import json as jsonfilter
from decimal import Decimal
@@ -44,16 +50,16 @@ import json
import os
from os.path import dirname
import mimetypes
-import datetime
+import subprocess
import logging
+SRT_BASE_DIR = os.environ['SRT_BASE_DIR']
+
logger = logging.getLogger("srt")
-def _log(msg):
- f1=open('/tmp/srt.log', 'a')
- f1.write("|" + msg + "|\n" )
- f1.close()
+# quick development/debugging support
+from srtgui.api import _log
class MimeTypeFinder(object):
# setting this to False enables additional non-standard mimetypes
@@ -72,25 +78,31 @@ class MimeTypeFinder(object):
# single point to add global values into the context before rendering
def toaster_render(request, page, context):
-# context['project_enable'] = project_enable
+ # Share session's user name
+ srt_user_id = int(request.session.get('srt_user_id', '0'))
+ if 0 == srt_user_id:
+ srt_user_id = User.USER_GUEST
+ request.session['srt_user_id'] = srt_user_id
+ request.session.modified = True
+ context['srt_user_id'] = srt_user_id ### REMOVE
+ # Set normal access rights unless pre-empted by page
+ if not 'access' in context:
+ context['access'] = Access(srt_user_id)
return render(request, page, context)
# a context processor which runs on every request; this provides the
# projects and non_cli_projects (i.e. projects created by the user)
# variables referred to in templates, which used to determine the
-# visibility of UI elements like the "New build" button
+# visibility of UI elements like the "Management" button
def managedcontextprocessor(request):
ret = {
# "non_cli_projects": projects.exclude(is_default=True),
# "DEBUG" : srtmain.settings.DEBUG,
# "TOASTER_BRANCH": srtmain.settings.TOASTER_BRANCH,
# "TOASTER_REVISION" : srtmain.settings.TOASTER_REVISION,
- 'access' : Access(),
}
return ret
-
-# all new sessions should come through the landing page;
# determine in which mode we are running in, and redirect appropriately
def landing(request):
@@ -99,9 +111,7 @@ def landing(request):
# user_projects = Project.objects.filter(is_default = False)
# has_user_project = user_projects.count() > 0
- context = {
- 'lvs_nos' : 0,
- }
+ context = {}
return toaster_render(request, 'landing.html', context)
@@ -447,19 +457,18 @@ def _add_daterange_context(queryset_all, request, daterange_list):
def management(request):
# does this user have permission to see this record?
- userAccess = Access()
- if not userAccess.is_admin():
+ userAccess = Access(int(request.session.get('srt_user_id', '0')))
+ if not userAccess.is_creator():
return redirect(landing)
context = {
- 'lvs_nos' : 0,
'cve_total' : Cve.objects.all().count(),
'cve_new' : Cve.objects.filter(status=Cve.NEW).count(),
'cve_open' : Cve.objects.filter( Q(status=Cve.INVESTIGATE) & Q(status=Cve.VULNERABLE) ).count(),
'vulnerability_total' : Vulnerability.objects.all().count(),
-
+
'vulnerability_open' : Vulnerability.objects.filter(outcome=Vulnerability.OPEN).count(),
'vulnerability_high' : Vulnerability.objects.filter(severity=Vulnerability.HIGH).count(),
'vulnerability_medium' : Vulnerability.objects.filter(severity=Vulnerability.MEDIUM).count(),
@@ -479,13 +488,19 @@ def management(request):
import copy
def cve(request, cve_pk, active_tab="1"):
template = "cve.html"
- if Cve.objects.filter(pk=cve_pk).count() == 0 :
- return redirect(landing)
- cve_object = Cve.objects.get(pk=cve_pk)
+ # CVE name or pk
+ try:
+ if cve_pk[0].isdigit():
+ cve_object = Cve.objects.get(pk=cve_pk)
+ else:
+ cve_object = Cve.objects.get(name=cve_pk)
+ cve_pk = cve_object.id
+ except:
+ return redirect(landing)
# does this user have permission to see this record?
- userAccess = Access()
+ userAccess = Access(int(request.session.get('srt_user_id', '0')))
if (not cve_object.public) and (not userAccess.is_admin()):
return redirect(landing)
@@ -500,61 +515,214 @@ def cve(request, cve_pk, active_tab="1"):
else:
response_link = str(investigation_records[0].pk)
+ # fetch CVE's detail information
+ cve_object_detail = readCveDetails(cve_object)
+ _log("FOO:%s" % cve_object_detail)
+
cve_summary = copy.copy(cve_object)
+ cve_summary_detail = copy.copy(cve_object_detail)
cve_summary.source = 'Summary'
-
- cve_local = Cve
+
+ cve_local = Cve()
+ cve_local_detail = CveDetail()
cve_local.source = 'Local'
-
+
context = {
- 'object' : { "name" : "CVE-1234"} ,
- 'cve_list_table' : [
- (cve_summary,tab_states['1'],"Summary"),
- (cve_object,tab_states['2'],"NIST"),
- (cve_local,tab_states['3'],"Local"),
+ 'object' : { "name" : "CVE-1234",
+ "id" : cve_object.id,
+ },
+ 'cve_list_table' : [
+ (cve_summary,cve_summary_detail,tab_states['1'],"Summary"),
+ (cve_object,cve_object_detail,tab_states['2'],"NIST"),
+ (cve_local,cve_local_detail,tab_states['3'],"Local"),
],
'tab_states' : tab_states,
'response_link' : response_link,
'cve_prev' : str(max(1,int(cve_pk)-1)),
'cve_next' : str(min(int(cve_pk)+1,Cve.objects.count()-1)),
}
- return render(request, template, context)
+ return toaster_render(request, template, context)
def vulnerability(request, vulnerability_pk):
- template = "vulnerability.html"
- if Vulnerability.objects.filter(pk=vulnerability_pk).count() == 0 :
- return redirect(landing)
+ if request.method == "GET":
+ template = "vulnerability.html"
- vulnerability_object = Vulnerability.objects.get(pk=vulnerability_pk)
+ # Defect name or pk
+ try:
+ if vulnerability_pk[0].isdigit():
+ vulnerability_object = Vulnerability.objects.get(pk=vulnerability_pk)
+ else:
+ vulnerability_object = Vulnerability.objects.get(name=vulnerability_pk)
+ vulnerability_pk = vulnerability_object.id
+ except:
+ return redirect(landing)
+
+ products = Product.objects.all()
+
+ # does this user have permission to see this record?
+ userAccess = Access(int(request.session.get('srt_user_id', '0')))
+ if (not vulnerability_object.public) and (not userAccess.is_admin()):
+ return redirect(landing)
+
+ context = {
+ 'object' : vulnerability_object,
+ 'users' : UserSafe.get_safe_userlist(True),
+ 'products': products,
+ }
+ return toaster_render(request, template, context)
+ elif request.method == "POST":
+ _log("EXPORT_POST:VULERNABILITY_POST: %s" % request)
+
+ if request.POST["action"] == "upload":
+ if vulnerability_pk[0].isdigit():
+ vulnerability_object = Vulnerability.objects.get(pk=vulnerability_pk)
+ else:
+ vulnerability_object = Vulnerability.objects.get(name=vulnerability_pk)
+ vulnerability_pk = vulnerability_object.id
+ path = os.path.join(SRT_BASE_DIR, "downloads/%s" % vulnerability_object.name)
+ # Catch the post against this page
+ try:
+ os.makedirs(path)
+ except:
+ pass
+
+ try:
+ file = request.FILES['fileUpload']
+ description = request.POST['fileDescription']
+ except Exception as e:
+ _log("EXPORT_POST:'fileupload' does not exist: %s" % e)
+
+ try:
+ with open(path + "/" + file.name, 'xb+') as destination:
+ for line in file:
+ destination.write(line)
+
+ userAccess = Access(int(request.session.get('srt_user_id', '0')))
+ VulnerabilityUploads.objects.get_or_create(vulnerability_id=vulnerability_object.id, description=description, path=path + "/" + file.name, size=file.size, date=datetime.today().strftime('%Y-%m-%d'), author=userAccess.current_user_name)
+ except Exception as e:
+ _log("EXPORT_POST:FILE ALREADY EXISTS: %s" % e)
+ return redirect(vulnerability,vulnerability_pk)
+ elif request.POST["action"] == "download":
+ record_id = request.POST['record_id']
+ upload = VulnerabilityUploads.objects.get(id=record_id)
+ file_path = upload.path
+ if file_path:
+ fsock = open(file_path, "rb")
+ content_type = MimeTypeFinder.get_mimetype(file_path)
+ response = HttpResponse(fsock, content_type = content_type)
+ disposition = 'attachment; filename="{}"'.format(file_path)
+ response['Content-Disposition'] = 'attachment; filename="{}"'.format(file_path)
+ _log("EXPORT_POST_Q{%s} %s || %s " % (response, response['Content-Disposition'], disposition))
+ return response
+ else:
+ return toaster_render(request, "unavailable_artifact.html")
- # does this user have permission to see this record?
- userAccess = Access()
- if (not vulnerability_object.public) and (not userAccess.is_admin()):
+def investigation(request, investigation_pk):
+ if request.method == "GET":
+ template = "investigation.html"
+
+ # Investigation name or pk
+ try:
+ if investigation_pk[0].isdigit():
+ investigation_object = Investigation.objects.get(pk=investigation_pk)
+ else:
+ investigation_object = Investigation.objects.get(name=investigation_pk)
+ investigation_pk = investigation_object.id
+ except:
+ return redirect(landing)
+
+ defects = Defect.objects.all()
+ investigation_to_defect = investigation_object.investigation_to_defect.all()
+ context = {
+ 'object' : investigation_object,
+ 'users' : UserSafe.get_safe_userlist(True),
+ 'defects' : defects,
+ 'investigation_to_defect' : investigation_to_defect,
+ 'defect_example' : SrtSetting.objects.get(name='SRTOOL_DEFECT_SAMPLENAME').value,
+ }
+ return toaster_render(request, template, context)
+ elif request.method == "POST":
+ _log("EXPORT_POST:INVESTIGATION_POST: %s" % request)
+
+ if request.POST["action"] == "upload":
+ if investigation_pk[0].isdigit():
+ investigation_object = Investigation.objects.get(pk=investigation_pk)
+ else:
+ investigation_object = Investigation.objects.get(name=investigation_pk)
+ investigation_pk = investigation_object.id
+ path = os.path.join(SRT_BASE_DIR, "downloads/%s" % investigation_object.name)
+ # Catch the post against this page
+ try:
+ os.makedirs(path)
+ except:
+ pass
+
+ try:
+ file = request.FILES['fileUpload']
+ description = request.POST['fileDescription']
+ except Exception as e:
+ _log("EXPORT_POST:'fileupload' does not exist: %s" % e)
+
+ try:
+ with open(path + "/" + file.name, 'xb+') as destination:
+ for line in file:
+ destination.write(line)
+ userAccess = Access(int(request.session.get('srt_user_id', '0')))
+ InvestigationUploads.objects.get_or_create(investigation_id=investigation_object.id, description=description, path=path + "/" + file.name, size=file.size, date=datetime.today().strftime('%Y-%m-%d'), author=userAccess.current_user_name)
+ except Exception as e:
+ _log("EXPORT_POST:FILE ALREADY EXISTS: %s" % e)
+ return redirect(investigation,investigation_pk)
+ elif request.POST["action"] == "download":
+ record_id = request.POST['record_id']
+ upload = InvestigationUploads.objects.get(id=record_id)
+ file_path = upload.path
+ if file_path:
+ fsock = open(file_path, "rb")
+ content_type = MimeTypeFinder.get_mimetype(file_path)
+ response = HttpResponse(fsock, content_type = content_type)
+ disposition = 'attachment; filename="{}"'.format(file_path)
+ response['Content-Disposition'] = 'attachment; filename="{}"'.format(file_path)
+ _log("EXPORT_POST_Q{%s} %s || %s " % (response, response['Content-Disposition'], disposition))
+ return response
+ else:
+ return toaster_render(request, "unavailable_artifact.html")
+
+
+def defect(request, defect_pk):
+ template = "defect.html"
+
+ # Defect name or pk
+ try:
+ if defect_pk[0].isdigit():
+ defect_object = Defect.objects.get(pk=defect_pk)
+ else:
+ defect_object = Defect.objects.get(name=defect_pk)
+ defect_pk = defect_object.id
+ except:
return redirect(landing)
context = {
- 'object' : vulnerability_object,
-# 'cwe_table' : CweTable.objects.all(),
+ 'object' : defect_object,
+ 'users' : users,
}
- return render(request, template, context)
+ return toaster_render(request, template, context)
-def investigation(request, investigation_pk):
- template = "investigation.html"
- if Investigation.objects.filter(pk=investigation_pk).count() == 0 :
+def product(request, product_pk):
+ template = "product.html"
+ if Product.objects.filter(pk=product_pk).count() == 0 :
return redirect(landing)
- investigation_object = Investigation.objects.get(pk=investigation_pk)
+ product_object = Product.objects.get(pk=product_pk)
context = {
- 'object' : investigation_object,
-# 'cwe_table' : CweTable.objects.all(),
+ 'object' : product_object,
}
- return render(request, template, context)
+ return toaster_render(request, template, context)
def sources(request):
# does this user have permission to see this record?
- userAccess = Access()
+ userAccess = Access(int(request.session.get('srt_user_id', '0')))
if not userAccess.is_admin():
return redirect(landing)
@@ -567,41 +735,46 @@ def sources(request):
context = {
'object' : object,
}
- return render(request, template, context)
+ return toaster_render(request, template, context)
def login(request):
- template = "login.html"
- context = {
- 'object' : object,
- }
- return render(request, template, context)
+ if request.method == "GET":
+ template = "login.html"
+ object = User.objects.all()
+ context = {
+ 'object' : object,
+ 'user_count' : len(object),
+ }
+ return toaster_render(request, template, context)
+ elif request.method == "POST":
+ user_name = request.POST.get('username', '_anonuser')
+ user_name = re.sub(r"\(.*","",user_name).strip()
+ password = request.POST.get('password', 'nopass')
+ _log("LOGIN_POST:%s,%s" % (user_name,password))
-def _log(msg):
- f1=open('/tmp/srt.log', 'a')
- f1.write("|" + msg + "|\n" )
- f1.close()
+ try:
+ ### USER CONTROL
+ user = User.objects.get(name=user_name)
+ request.session['srt_user_id'] = user.id
+ request.session.modified = True
+
+ except Exception as e:
+ _log("LOGIN_ERROR:%s,%s" % (user,e))
+ pass
+ return redirect(landing)
+ #return landing(request)
-# TEMP ACCESS TEST CODE
+ raise Exception("Invalid HTTP method for this page")
+
+# This is effectively the logout command
def login_guest(request):
- current_user = SrtSetting.objects.get_or_create(name='current_user')[0]
- current_user.value = 1
- current_user.save()
- current_user_access = SrtSetting.objects.get_or_create(name='current_user_access')[0]
- current_user_access.value = User.READER
- current_user_access.save()
- return redirect(landing)
-def login_admin(request):
- current_user = SrtSetting.objects.get_or_create(name='current_user')[0]
- current_user.value = 3
- current_user.save()
- current_user_access = SrtSetting.objects.get_or_create(name='current_user_access')[0]
- current_user_access.value = User.ADMIN
- current_user_access.save()
+ request.session['srt_user_id'] = User.USER_GUEST
+ request.session.modified = True
return redirect(landing)
def users(request):
# does this user have permission to see this record?
- userAccess = Access()
+ userAccess = Access(int(request.session.get('srt_user_id', '0')))
if not userAccess.is_admin():
return redirect(landing)
@@ -615,37 +788,55 @@ def users(request):
context = {
'object' : object,
}
- return render(request, template, context)
-
-def export(request,page_name):
- context = {
- 'lvs_nos' : 0,
- 'page' : '%s%s' % (page_name[0:1].upper(),page_name[1:])
- }
- return toaster_render(request, 'export.html', context)
+ return toaster_render(request, template, context)
+
+def report(request,page_name):
+ if request.method == "GET":
+ context = ReportManager.get_context_data(page_name,request=request)
+ record_list = request.GET.get('record_list', '')
+ _log("EXPORT_GET!:%s|%s|" % (request,record_list))
+ context['record_list'] = record_list
+ return toaster_render(request, 'report.html', context)
+ elif request.method == "POST":
+ _log("EXPORT_POST!:%s|%s" % (request,request.FILES))
+ parent_page = request.POST.get('parent_page', '')
+ file_name,response_file_name = ReportManager.exec_report(parent_page,request=request)
+
+ if file_name and response_file_name:
+ fsock = open(file_name, "rb")
+ content_type = MimeTypeFinder.get_mimetype(file_name)
+
+ response = HttpResponse(fsock, content_type = content_type)
+
+ disposition = "attachment; filename=" + response_file_name
+ response["Content-Disposition"] = disposition
+
+ _log("EXPORT_POST_Q{%s|" % (response))
+ return response
+ else:
+ return toaster_render(request, "unavailable_artifact.html", {})
-def export_null(request):
- return export(request,"NuLl")
+ return redirect(landing)
+ raise Exception("Invalid HTTP method for this page")
def triage_cves(request):
# does this user have permission to see this record?
- userAccess = Access()
- if not userAccess.is_admin():
+ userAccess = Access(int(request.session.get('srt_user_id', '0')))
+ if not userAccess.is_creator():
return redirect(landing)
- context = {'lvs_nos' : 0}
+ context = {}
return toaster_render(request, 'triage_cves.html', context)
-
def keywords(request):
# does this user have permission to see this record?
- userAccess = Access()
- if not userAccess.is_admin():
+ userAccess = Access(int(request.session.get('srt_user_id', '0')))
+ if not userAccess.is_creator():
return redirect(landing)
-
+
for_list = SrtSetting.objects.get(name='keywords_for').value.split('|')
against_list = SrtSetting.objects.get(name='keywords_against').value.split('|')
- context = {'lvs_nos' : 0,
+ context = {
'for_list' : for_list,
'for_list_count' : len(for_list),
'against_list' : against_list,
@@ -653,87 +844,36 @@ def keywords(request):
}
return toaster_render(request, 'keywords.html', context)
-
-def start_select_cves(request):
- # pre-calculate the recommend values
- queryset = \
- Cve.objects.filter(status = Cve.NEW,name__startswith = 'CVE-2018-')
-
- KeywordsFor = SrtSetting.objects.get(name='keywords_for').value.split('|')
- KeywordsAgainst = SrtSetting.objects.get(name='keywords_against').value.split('|')
-
- for cve in queryset:
- description = ' '+cve.description.lower()+' '
- total = 0
- list = ''
-
- for keypair in KeywordsFor:
- #print("keypair='%s'" % keypair)
- key,w = keypair.split(',')
- weight = 1
-# if w:
-# weight = int(w)
- #if ' '+key+' ' in description:
- if re.search(r'\b%s\b' % key, description):
- list += ",+%s" % key
- total += weight
-
- for keypair in KeywordsAgainst:
- #print("keypair='%s'" % keypair)
- key,w = keypair.split(',')
- weight = 1
-# if w:
-# weight = int(w)
- # re.search(r'\bis\b', your_string)
- #if ' '+key+' ' in description:
- #if re.search(re.escape(r'\b%s\b' % key), description):
- if re.search(r'\b%s\b' % key, description):
- list += ",-%s" % key
- total -= weight
-
- # set filter maximums
- if total < -3:
- total = -3
- if total > 3:
- total = 3
- cve.recommend = total
- cve.comments_private = list[1:]
- cve.save()
-
- #_log("%s[%d]=%s" % (cve.name,cve.recommend,cve.comments_private))
-
- return redirect("/srtgui/select-cves")
-
def create_vulnerability(request):
# does this user have permission to see this record?
- userAccess = Access()
- if not userAccess.is_admin():
+ userAccess = Access(int(request.session.get('srt_user_id', '0')))
+ if not userAccess.is_creator():
return redirect(landing)
- context = {'lvs_nos' : 0}
+ context = {}
return toaster_render(request, 'create_vulnerability.html', context)
def publish(request):
# does this user have permission to see this record?
- userAccess = Access()
- if not userAccess.is_admin():
+ userAccess = Access(int(request.session.get('srt_user_id', '0')))
+ if not userAccess.is_creator():
return redirect(landing)
- context = {'lvs_nos' : 0}
+ context = {}
return toaster_render(request, 'publish.html', context)
def manage_report(request):
# does this user have permission to see this record?
- userAccess = Access()
- if not userAccess.is_admin():
+ userAccess = Access(int(request.session.get('srt_user_id', '0')))
+ if not userAccess.is_creator():
return redirect(landing)
- return redirect(export,'management')
+ return redirect(report,'management')
def guided_tour(request):
- context = {'lvs_nos' : 0}
+ context = {}
return toaster_render(request, 'guided_tour.html', context)
-
+
def quicklink(request):
current_user = SrtSetting.objects.get_or_create(name='current_user')[0]
current_user.value = 16
@@ -741,7 +881,7 @@ def quicklink(request):
current_user_access = SrtSetting.objects.get_or_create(name='current_user_access')[0]
current_user_access.value = User.ADMIN
current_user_access.save()
- return redirect("/srtgui/start-select-cves")
+ return redirect("/srtgui/select-publish")
def xhr_triage_commit(request):
_log("xhr_triage_commit(%s)" % request.POST)
@@ -752,7 +892,7 @@ def xhr_triage_commit(request):
author_name = User.objects.get(pk=author_id).name
action = request.POST['action']
- today = datetime.datetime.today().strftime("%Y-%m-%d")
+ today = datetime.today().strftime("%Y-%m-%d")
if 'submit-notvulnerable' == action:
reason = request.POST['reason']
cves = request.POST['cves']
@@ -786,10 +926,11 @@ def xhr_triage_commit(request):
first_vulnerability = True
investigation_names = {}
for cve_name in cves[:-1].split(','):
-
+
# update CVE
cve = Cve.objects.get(name=cve_name)
cve.status = Cve.VULNERABLE
+ cve.priority = severity
if cve.comments:
cve.comments += ', ' + reason
else:
@@ -864,7 +1005,322 @@ def xhr_triage_commit(request):
_log("xhr_triage_commit:no(%s)" % e)
return HttpResponse(json.dumps({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json")
+def xhr_cve_commit(request):
+ _log("xhr_cve_commit(%s)" % request.POST)
+ if not 'action' in request.POST:
+ return HttpResponse(json.dumps({"error":"missing action\n"}), content_type = "application/json")
+ try:
+ cve = Cve.objects.get(id=request.POST['cve_id'])
+ action = request.POST['action']
+ history_comment = ''
+ if 'submit-quickedit' == action:
+ note = request.POST['note']
+ priority = int(request.POST['priority'])
+ private_note = request.POST['private_note']
+ publish_state = request.POST['publish_state']
+ publish_date = request.POST['publish_date']
+ if (priority != cve.priority):
+ cve.priority = priority
+ history_comment += "Priority, "
+ if (note != cve.comments):
+ cve.comments = note
+ history_comment += "Note, "
+ if (private_note != cve.comments_private):
+ cve.comments_private = private_note
+ history_comment += "Private Note, "
+ if (publish_state != cve.publish_state):
+ cve.publish_state = publish_state
+ history_comment += "Publish State, "
+ if (publish_date != cve.publish_date):
+ cve.publish_date = publish_date
+ history_comment += "Publish Date, "
+ cve.save()
+ return_data = {
+ "error": "ok",
+ }
+
+ access = Access(int(request.session.get('srt_user_id', '0')))
+ if (history_comment != ''):
+ history_comment = history_comment[:-2]
+ history_comment += " edited"
+ CveHistory.objects.create(cve_id=cve.id, comment=history_comment, date=datetime.now().strftime('%Y-%m-%d'), author=access.current_user_name)
+ _log("xhr_cve_commit:SUCCESS")
+ return HttpResponse(json.dumps( return_data ), content_type = "application/json")
+
+ except Exception as e:
+ _log("xhr_cve_commit:no(%s)" % e)
+ return HttpResponse(json.dumps({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json")
+
+def xhr_cve_publish_commit(request):
+ _log("xhr_cve_publish_commit(%s)" % request.POST)
+ cve_list = request.POST['cve_list']
+ publish_state = int(request.POST['publish_state'])
+ _log("xhr_cve_publish_commit2")
+ try:
+ for name in cve_list.split(','):
+ _log("xhr_cve_publish_commit3:%s" % name)
+ if name:
+ _log("xhr_cve_publish_commit4")
+ cve = Cve.objects.get(name=name)
+ cve.publish_state = publish_state
+ cve.save()
+ _log("xhr_cve_publish_commit5")
+ # Add to publish pending queue?
+ if Cve.PUBLISH_SUBMITTED == publish_state:
+ _log("xhr_cve_publish_commit5a")
+ pub_req,created = PublishPending.objects.get_or_create(cve=cve)
+ pub_req.date=datetime.today().strftime('%Y-%m-%d')
+ pub_req.save()
+ _log("xhr_cve_publish_commit5b")
+ # Remove from publish pending queue?
+ if Cve.PUBLISH_PUBLISHED == publish_state:
+ _log("xhr_cve_publish_commit5c")
+ try:
+ pub_req = PublishPending.objects.get(cve=cve)
+ pub_req.delete()
+ except:
+ pass
+ _log("xhr_cve_publish_commit5d")
+ _log("xhr_cve_publish_commit6")
+ return_data = {
+ "error": "ok",
+ }
+ return HttpResponse(json.dumps( return_data ), content_type = "application/json")
+ except Exception as e:
+ _log("xhr_cve_publish_commit:no(%s)" % e)
+ return HttpResponse(json.dumps({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json")
+
+def xhr_vulnerability_commit(request):
+ _log("xhr_vulnerability_commit(%s)" % request.POST)
+ if not 'action' in request.POST:
+ return HttpResponse(json.dumps({"error":"missing action\n"}), content_type = "application/json")
+
+ action = request.POST['action']
+ v_id = request.POST['vulnerability_id']
+ access = Access(int(request.session.get('srt_user_id', '0')))
+ history_comment = ''
+ try:
+ if 'submit-quickedit' == action:
+ note = request.POST['note']
+ private_note = request.POST['private_note']
+ v = Vulnerability.objects.get(id=v_id)
+ if (v.comments != note):
+ v.comments = note
+ history_comment += "Note, "
+ if (v.comments_private != private_note):
+ v.comments_private = private_note
+ history_comment += "Private Note, "
+ if (v.status != request.POST['status']):
+ v.status = request.POST['status']
+ history_comment += "Status, "
+ if (v.outcome != request.POST['outcome']):
+ v.outcome = request.POST['outcome']
+ history_comment += "Outcome, "
+ if (v.severity != request.POST['severity']):
+ v.severity = request.POST['severity']
+ history_comment += "Severity, "
+ if (history_comment != ''):
+ history_comment = history_comment[:-2]
+ history_comment += " edited"
+ v.save()
+
+ if 'submit-addrelatedproduct' == action:
+ products = request.POST['products']
+ product_names = ''
+ for product_id in products[:-1].split(','):
+ tmp = Product.objects.get(pk=product_id)
+ product_names += tmp.name + ' ' + tmp.version + ', '
+ VulnerabilityProduct.objects.get_or_create(vulnerability_id=v_id, product_id=product_id, relation=1)
+ product_names = product_names[:-2]
+ history_comment = product_names + " added to related products"
+ if 'submit-trashrelated' == action:
+ record_id = request.POST['record_id']
+ record = VulnerabilityProduct.objects.get(id=record_id)
+ product = Product.objects.get(id=record.product_id)
+ history_comment = product.name + ' ' + product.version + " removed from related products"
+ record.delete()
+ if 'submit-addaffectedproduct' == action:
+ products = request.POST['products']
+ product_names = ''
+ for product_id in products[:-1].split(','):
+ tmp = Product.objects.get(pk=product_id)
+ product_names += tmp.name + ' ' + tmp.version + ', '
+ VulnerabilityProduct.objects.get_or_create(vulnerability_id=v_id, product_id=product_id, relation=0)
+ product_names = product_names[:-2]
+ history_comment = product_names + " added to affected products"
+ if 'submit-trashaffected' == action:
+ record_id = request.POST['record_id']
+ record = VulnerabilityProduct.objects.get(id=record_id)
+ product = Product.objects.get(id=record.product_id)
+ history_comment = product.name + ' ' + product.version + " removed from afftected products"
+ record.delete()
+ if 'submit-newcomment' == action:
+ comment = request.POST['comment']
+ VulnerabilityComments.objects.create(vulnerability_id=v_id, comment=comment, date=datetime.today().strftime('%Y-%m-%d'), author=access.current_user_name)
+ history_comment = "New comment submitted"
+ if 'submit-trashcomment' == action:
+ record_id = request.POST['record_id']
+ comment = VulnerabilityComments.objects.get(id=record_id)
+ history_comment = "Comment from " + comment.author + " deleted"
+ comment.delete()
+ if 'submit-trashattachment' == action:
+ record_id = request.POST['record_id']
+ upload = VulnerabilityUploads.objects.get(id=record_id)
+ history_comment = "Upload '" + upload.description + "' from " + upload.author + " deleted"
+ try:
+ os.remove(upload.path)
+ except OSError:
+ pass
+ upload.delete()
+ if 'submit-addusernotify' == action:
+ users = request.POST['users']
+ usernames = ''
+ for user_id in users[:-1].split(','):
+ usernames += User.objects.get(pk=user_id).name + ', '
+ VulnerabilityNotification.objects.get_or_create(vulnerability_id=v_id, user_id=user_id)
+ usernames = usernames[:-2]
+ history_comment = usernames + " added to notifications"
+ if 'submit-trashusernotification' == action:
+ record_id = request.POST['record_id']
+ notification_record = VulnerabilityNotification.objects.get(id=record_id)
+ removed_user = User.objects.get(pk=notification_record.user_id).name
+ history_comment = removed_user + " removed from notifications"
+ notification_record.delete()
+ if 'submit-adduseraccess' == action:
+ users = request.POST['users']
+ usernames = ''
+ for user_id in users[:-1].split(','):
+ usernames += User.objects.get(pk=user_id).name + ', '
+ VulnerabilityAccess.objects.get_or_create(vulnerability_id=v_id, user_id=user_id)
+ usernames = usernames[:-2]
+ history_comment = usernames + " granted access"
+ if 'submit-trashuseraccess' == action:
+ record_id = request.POST['record_id']
+ access_record = VulnerabilityAccess.objects.get(id=record_id)
+ removed_user = User.objects.get(pk=access_record.user_id).name
+ history_comment = removed_user + "'s access removed"
+ access_record.delete()
+ if (history_comment != ''):
+ VulnerabilityHistory.objects.create(vulnerability_id=v_id, comment=history_comment, date=datetime.now().strftime('%Y-%m-%d'), author=access.current_user_name)
+ return_data = {
+ "error": "ok",
+ }
+ return HttpResponse(json.dumps( return_data ), content_type = "application/json")
+ except Exception as e:
+ _log("xhr_vulnerability_commit:no(%s)" % e)
+ return HttpResponse(json.dumps({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json")
+
+def xhr_investigation_commit(request):
+ _log("xhr_investigation_commit(%s)" % request.POST)
+ if not 'action' in request.POST:
+ return HttpResponse(json.dumps({"error":"missing action\n"}), content_type = "application/json")
+
+ action = request.POST['action']
+ invst_id = request.POST['investigation_id']
+ access = Access(int(request.session.get('srt_user_id', '0')))
+ history_comment = "Nothing happened."
+ try:
+ if 'submit-attachdefectlist' == action:
+ defects = request.POST['defects']
+ product_id = Investigation.objects.get(id=invst_id).product_id
+ defect_names = ""
+ for defect_id in defects[:-1].split(','):
+ defect_names += Defect.objects.get(pk=defect_id).name + ", "
+ InvestigationToDefect.objects.get_or_create(investigation_id=invst_id, defect_id=defect_id)
+ defect_names = defect_names[:-2]
+ history_comment = defect_names + " added to defects"
+ if 'submit-attachdefect' == action:
+ query = request.POST['query'].upper()
+ product_id = Investigation.objects.get(id=invst_id).product_id
+ #check if defect already in SRTool data
+ try:
+ defect = Defect.objects.get(name=query)
+ except Defect.DoesNotExist:
+ defect = None
+
+ #If defect not in SRTool, import data from Defect database and create record
+ if defect is None:
+ #try connecting to defect management tool
+ try:
+ cmd_list = SrtSetting.objects.get(name='SRTOOL_DEFECT_ADD').value.split(' ')
+ cmd_list.append(query)
+ result = subprocess.run(cmd_list, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ if 0 == result.returncode:
+ defect = Defect.objects.get(name=query)
+ else:
+ defect = None
+ return HttpResponse(json.dumps({"error":str(e) + "\n"}), content_type = "application/json")
+ except Exception as e:
+ _log("xhr_investigation_commit:Error in defect attach query:(%s)\n" % e)
+ return HttpResponse(json.dumps({"error":str(e) + "\n"}), content_type = "application/json")
+ if defect:
+ InvestigationToDefect.objects.get_or_create(investigation_id=invst_id, defect_id=defect.id, product_id=product_id)
+ history_comment = "Attached " + defect.name
+ if 'submit-trashdefect' == action:
+ defects = request.POST['defects']
+ product_id = Investigation.objects.get(id=invst_id).product_id
+ defect_names = ""
+ for defect_id in defects[:-1].split(','):
+ defect_names += Defect.objects.get(pk=defect_id).name + ", "
+ InvestigationToDefect.objects.get(investigation_id=invst_id, defect_id=defect_id).delete()
+ defect_names = defect_names[:-2]
+ history_comment = defect_names + " deleted from defects"
+ if 'submit-newcomment' == action:
+ comment = request.POST['comment']
+ InvestigationComments.objects.create(investigation_id=invst_id, comment=comment, date=datetime.today().strftime('%Y-%m-%d'), author=access.current_user_name)
+ history_comment = "New comment submitted"
+ if 'submit-trashcomment' == action:
+ record_id = request.POST['record_id']
+ comment = InvestigationComments.objects.get(id=record_id)
+ history_comment = "Comment from " + comment.author + " deleted"
+ comment.delete()
+ if 'submit-trashattachment' == action:
+ record_id = request.POST['record_id']
+ upload = InvestigationUploads.objects.get(id=record_id)
+ history_comment = "Upload '" + upload.description + "' from " + upload.author + " deleted"
+ try:
+ os.remove(upload.path)
+ except OSError:
+ pass
+ upload.delete()
+ if 'submit-addusernotify' == action:
+ users = request.POST['users']
+ usernames = ""
+ for user_id in users[:-1].split(','):
+ usernames += User.objects.get(pk=user_id).name + ", "
+ InvestigationNotification.objects.get_or_create(investigation_id=invst_id, user_id=user_id)
+ usernames = usernames[:-2]
+ history_comment = usernames + " added to notifications"
+ if 'submit-trashusernotification' == action:
+ record_id = request.POST['record_id']
+ notification_record = InvestigationNotification.objects.get(id=record_id)
+ removed_user = User.objects.get(pk=notification_record.user_id).name
+ history_comment = removed_user + " removed from notifications"
+ notification_record.delete()
+ if 'submit-adduseraccess' == action:
+ users = request.POST['users']
+ usernames = ""
+ for user_id in users[:-1].split(','):
+ usernames += User.objects.get(pk=user_id).name + ", "
+ InvestigationAccess.objects.get_or_create(investigation_id=invst_id, user_id=user_id)
+ history_comment = usernames + " granted access"
+ if 'submit-trashuseraccess' == action:
+ record_id = request.POST['record_id']
+ access_record = InvestigationAccess.objects.get(id=record_id)
+ removed_user = User.objects.get(pk=access_record.user_id).name
+ history_comment = removed_user + "'s access removed"
+ access_record.delete()
+ InvestigationHistory.objects.create(investigation_id=invst_id, comment=history_comment, date=datetime.now().strftime('%Y-%m-%d'), author=access.current_user_name)
+ return_data = {
+ "error": "ok",
+ }
+
+ return HttpResponse(json.dumps( return_data ), content_type = "application/json")
+ except Exception as e:
+ _log("xhr_investigation_commit:no(%s)" % e)
+ return HttpResponse(json.dumps({"error":str(e) + "\n"}), content_type = "application/json")
+
+
def tbd(request):
- context = {'lvs_nos' : 0}
+ context = {}
return toaster_render(request, 'tbd.html', context)
-
diff --git a/lib/srtgui/widgets.py b/lib/srtgui/widgets.py
index b43b7619..0c2b56bf 100644
--- a/lib/srtgui/widgets.py
+++ b/lib/srtgui/widgets.py
@@ -34,7 +34,7 @@ from django.utils import timezone
from django.http import JsonResponse
from django.core.urlresolvers import reverse
-from orm.models import Vulnerability, SrtSetting, Access, Keywords
+from orm.models import SrtSetting, Access, Keywords
from srtgui.templatetags.projecttags import sectohms, get_tasks
from srtgui.templatetags.projecttags import json as template_json
@@ -89,8 +89,12 @@ class ToasterTable(TemplateView):
context['empty_state'] = self.empty_state
# global variables
- context['project_enable'] = ('1' == os.environ.get('TOASTER_BUILDSERVER'))
- context['access'] = Access()
+ context['report_id_list'] = ''
+
+ # Number of visits to this view, as counted in the session variable.
+ srt_user_id=int(self.request.session.get('srt_user_id', '0'))
+ context['srt_user_id'] = srt_user_id ### REMOVE
+ context['access'] = Access(srt_user_id)
return context
@@ -113,6 +117,12 @@ class ToasterTable(TemplateView):
return super(ToasterTable, self).get(request, *args, **kwargs)
+ def put(self, *args, **kwargs):
+ """ function to implement in the subclass which sets up
+ the put method """
+ _log("TABLE_PUT_SUPER")
+ pass
+
def get_filter_info(self, request, **kwargs):
self.setup_filters(**kwargs)