aboutsummaryrefslogtreecommitdiffstats
path: root/lib/cve_checker/tables.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/cve_checker/tables.py')
-rwxr-xr-xlib/cve_checker/tables.py695
1 files changed, 695 insertions, 0 deletions
diff --git a/lib/cve_checker/tables.py b/lib/cve_checker/tables.py
new file mode 100755
index 00000000..252d109f
--- /dev/null
+++ b/lib/cve_checker/tables.py
@@ -0,0 +1,695 @@
+#
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# Security Response Tool Implementation
+#
+# Copyright (C) 2023 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.
+
+#
+# NOTICE: Important ToasterTable implementation concepts and limitations
+#
+# 1) The order of table method execution. This implies that data added
+# to the table object in "get_context_data" is NOT persistent.
+#
+# a) __init__
+# b) get_context_data
+# c) __init__ (second call reason unknown)
+# d) setup_queryset
+# e) setup_filters (if present)
+# f) setup_columns
+# g) apply_row_customization (if present)
+#
+# 2) Named URL path arguments from "urls.py" are accessible via kwargs
+# WARNING: these values not NOT available in "__init__"
+#
+# Example:
+# urls.ps : url(r'^foo/(?P<my_value>\d+)$',
+# tables.py: my_value = int(kwargs['my_value'])
+#
+# 3) Named URL query arguments the table's url are accessible via the request
+#
+# Example:
+# url : http://.../foo/bar/42605?my_value=25
+# tables.py: my_value = self.request.GET.get('my_value','0')
+#
+# 4) The context[] values are NOT present in the individual "setup_columns" context
+# They must be explicitly implemented into the individual column data without Django translation
+#
+# 5) The HTML page's templatetags are NOT present in the "setup_columns" context
+# They must be explicitly added into the template code
+#
+# Example:
+# static_data_template = '''
+# {% load jobtags %}<span onclick="toggle_select(\'box_{{data.id}}\');">{{data.recommend|recommend_display}}</span>
+# '''
+#
+# WARNING: because there is no context (#4), you cannot for example use dictionary lookup filters
+# use apply_row_customization() method instead, and set the self.dict_name in setup_columns()
+#
+
+import os
+import re
+import json
+from datetime import timedelta, datetime, date
+import pytz
+import traceback
+
+from django.db.models import Q, Max, Sum, Count, When, Case, Value, IntegerField
+from django.urls import re_path as url
+from django.urls import reverse, resolve
+from django.http import HttpResponse
+from django.views.generic import TemplateView
+
+from srtgui.widgets import ToasterTable
+from cve_checker.models import Ck_Audit, Ck_Package, Ck_Product, Ck_Layer, CkPackage2CkProduct, CkPackage2Cve, CkUploadManager
+from orm.models import Cve, Product
+from orm.models import Notify, NotifyAccess, NotifyCategories
+from orm.models import DataSource, SrtSetting, Job
+from users.models import SrtUser, UserSafe
+from srtgui.api import execute_process
+
+from srtgui.tablefilter import TableFilter
+from srtgui.tablefilter import TableFilterActionToggle
+from srtgui.tablefilter import TableFilterActionDateRange
+from srtgui.tablefilter import TableFilterActionDay
+
+# quick development/debugging support
+from srtgui.api import _log
+
+class CveCheckerAuditsTable(ToasterTable):
+ """Table of All CvecheckerRecord audits"""
+
+ def __init__(self, *args, **kwargs):
+ super(CveCheckerAuditsTable, self).__init__(*args, **kwargs)
+ self.default_orderby = "-id"
+
+ def get_context_data(self, **kwargs):
+ create_time = datetime.now(pytz.utc)
+ context = super(CveCheckerAuditsTable, self).get_context_data(**kwargs)
+ context['orm_products'] = Product.objects.all().order_by('name')
+ context['ab_sets'] = ("master","nanbield","mickledore","langdale","kirkstone","dunfell")
+ context['new_audit_name'] = 'audit_%s' % (create_time.strftime('%Y%m%d'))
+ context['default_product'] = 'Yocto Project master'
+ context['srt_cvechecker_update'] = SrtSetting.get_setting('SRT_CVECHECKER_UPDATE','')
+ context['mru'] = Job.get_recent()
+ context['mrj_type'] = 'all'
+ # Enforce at least the "Upload" import
+ ck_import_obj,created = CkUploadManager.objects.get_or_create(name='Upload')
+ if created:
+ ck_import_obj.order = 1
+ ck_import_obj.import_mode = 'Upload'
+ ck_import_obj.path = ''
+ ck_import_obj.pem = ''
+ ck_import_obj.repo = ''
+ ck_import_obj.branch = ''
+ ck_import_obj.auto_refresh = False
+ ck_import_obj.select_refresh = datetime.now(pytz.utc)
+ ck_import_obj.select_list = "master|nanbield|mickledore|langdale|kirkstone|dunfell"
+ ck_import_obj.save()
+ ck_import_obj,created = CkUploadManager.objects.get_or_create(name='Import from Auto Builder scan')
+ if created:
+ ck_import_obj.order = 2
+ ck_import_obj.import_mode = 'Repo'
+ ck_import_obj.path = 'yocto-metrics/cve-check'
+ ck_import_obj.pem = ''
+ ck_import_obj.repo = 'git://git.yoctoproject.org/yocto-metrics'
+ ck_import_obj.branch = ''
+ ck_import_obj.auto_refresh = True
+ ck_import_obj.select_refresh = datetime.now(pytz.utc)
+ ck_import_obj.select_list = "master|nanbield|mickledore|langdale|kirkstone|dunfell"
+ ck_import_obj.save()
+ context['ckuploadmanager'] = CkUploadManager.objects.all().order_by('order')
+ # Update the Import select tables
+ cmnd = ["bin/cve_checker/srtool_cvechecker.py","--update-imports","-f"]
+ result_returncode,result_stdout,result_stderr = execute_process(*cmnd)
+ if 0 != result_returncode:
+ _log(f"ERROR:{cmnd}: {result_stderr}:{result_stdout}:")
+ return context
+
+ def setup_queryset(self, *args, **kwargs):
+ self.queryset = Ck_Audit.objects.all()
+ self.queryset = self.queryset.order_by('-id')
+
+ def setup_filters(self, *args, **kwargs):
+ pass
+
+ def setup_columns(self, *args, **kwargs):
+
+ self.add_column(title="Id",
+ field_name="id",
+ hideable=False,
+ orderable=True,
+ )
+
+ name_template = '''
+ <span id="audit_name-disp-{{data.id}}"><td><a href="{% url 'cvechecker_audit' data.id %}">{{data.name}}</a></td></span>
+ <span id="audit_name-edit-{{data.id}}" style="display:none;">
+ <input type="text" id="audit_name-text-{{data.id}}" value="{{data.name}}" size="50">
+ </span>
+ '''
+ self.add_column(title="Name",
+ orderable=True,
+ static_data_name="name",
+ static_data_template=name_template,
+ )
+
+ self.add_column(title="Create Time",
+ field_name="create_time",
+ hideable=True,
+ hidden=True,
+ orderable=True,
+ )
+
+ ck_package_link_template = '''
+ <td><a href="{% url 'cvechecker_audit' data.id %}">{{data.get_package_count}}</a></td>
+ '''
+ self.add_column(title="Package Count",
+ static_data_name="count",
+ static_data_template=ck_package_link_template,
+ )
+
+ self.add_column(title="Unpatched CVE",
+ static_data_name="unpatched_count",
+ static_data_template='<b><label style="color:DarkRed">{{data.get_unpatched_count}}</label></b>',
+ )
+ self.add_column(title="Ignored CVE",
+ static_data_name="ignored_count",
+ static_data_template='<label style="color:green">{{data.get_ignored_count}}</label>',
+ )
+ self.add_column(title="Patched CVE",
+ static_data_name="patched_count",
+ static_data_template='<label style="color:green">{{data.get_patched_count}}</label>',
+ )
+ self.add_column(title="Undefined CVE",
+ static_data_name="undefined_count",
+ static_data_template='<label style="color:DarkRed">{{data.get_undefined_count}}</label>',
+ hideable=True,
+ hidden=True,
+ )
+
+ self.add_column(title="YP Release",
+ static_data_name="orm_product__profile",
+ static_data_template='{{data.orm_product.long_name}}',
+ orderable=True,
+ )
+
+ if UserSafe.is_contributor(self.request.user):
+ manage_link_template = '''
+ <span class="glyphicon glyphicon-edit edit-ck-entry" id="edit-entry-{{data.id}}" x-data="{{data.id}}"></span>
+ <span class="glyphicon glyphicon glyphicon glyphicon-ok save-ck-entry" id="save-entry-{{data.id}}" x-data="{{data.id}}" style="display:none;color: Chartreuse;"></span>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ <span class="glyphicon glyphicon glyphicon glyphicon-remove cancel-ck-entry" id="cancel-entry-{{data.id}}" x-data="{{data.id}}" style="display:none;color: Crimson;"></span>
+ <span class="glyphicon glyphicon-trash trash-audit" x-data="{{data.create_time}}|{{data.id}}"></span>
+ '''
+ self.add_column(title="Manage",
+ hideable=True,
+ static_data_name="manage",
+ static_data_template=manage_link_template,
+ )
+
+
+class CveCheckerAuditTable(ToasterTable):
+ """Table of All entries in CvecheckerRecord"""
+
+ def __init__(self, *args, **kwargs):
+ super(CveCheckerAuditTable, self).__init__(*args, **kwargs)
+ self.default_orderby = "name"
+
+ def get_context_data(self, **kwargs):
+ context = super(CveCheckerAuditTable, self).get_context_data(**kwargs)
+ audit_id = int(kwargs['audit_id'])
+ context['Ck_Audit'] = Ck_Audit.objects.get(id=audit_id)
+ context['mru'] = Job.get_recent()
+ context['mrj_type'] = 'all'
+ return context
+
+ def setup_queryset(self, *args, **kwargs):
+ audit_id = int(kwargs['audit_id'])
+ self.queryset = Ck_Package.objects.filter(ck_audit_id=audit_id)
+ self.queryset = self.queryset.order_by(self.default_orderby)
+
+ def setup_filters(self, *args, **kwargs):
+ # Status filter
+ is_status = TableFilter(name="is_status", title="Status")
+ audit_id = int(kwargs['audit_id'])
+ status_filter = TableFilterActionToggle(
+ "unpatched",
+ "Unpatched",
+ Q(unpatched_cnt__gt=0))
+ is_status.add_action(status_filter)
+ status_filter = TableFilterActionToggle(
+ "patched/ignored",
+ "Patched/Ignored",
+ Q(unpatched_cnt=0))
+ is_status.add_action(status_filter)
+ self.add_filter(is_status)
+
+ def setup_columns(self, *args, **kwargs):
+
+ self.add_column(title="Id",
+ field_name="id",
+ hideable=True,
+ hidden=True,
+ )
+
+ self.add_column(title="Name",
+ field_name="name",
+ hideable=False,
+ orderable=True,
+ )
+
+ self.add_column(title="Version",
+ field_name="version",
+ hideable=False,
+ orderable=True,
+ )
+
+ self.add_column(title="Layer",
+ field_name="ck_layer",
+ hideable=False,
+ orderable=True,
+ static_data_name="ck_layer",
+ static_data_template="{{data.ck_layer.name}}",
+ )
+
+ issue_link_template = '''
+ <a href="{% url 'cvechecker_issue' data.id %}">{{data.get_issue_count}}</a>
+ '''
+ self.add_column(title="Issues",
+ static_data_name="issue_count",
+ static_data_template=issue_link_template,
+ )
+
+ unpatched_link_template = '''
+ <label style="color:{% if data.unpatched_cnt %}DarkRed{% else %}green{% endif %}">{{data.unpatched_cnt}}</label>
+ '''
+ self.add_column(title="Unpatched CVE",
+ filter_name="is_status",
+ static_data_name="unpatched_count",
+ static_data_template=unpatched_link_template,
+ )
+
+ product_link_template = '''
+ <td><a href="{% url 'cvechecker_product' data.id %}">{{data.get_product_names}}</a></td>
+ '''
+ self.add_column(title="Products (cvesInRecord)",
+ static_data_name="product_count",
+ static_data_template=product_link_template,
+ )
+
+
+class CveCheckerAuditCveTable(ToasterTable):
+ """Table of All entries in CvecheckerRecord"""
+
+ def __init__(self, *args, **kwargs):
+ super(CveCheckerAuditCveTable, self).__init__(*args, **kwargs)
+ self.default_orderby = "orm_cve__name"
+
+ def get_context_data(self, **kwargs):
+ context = super(CveCheckerAuditCveTable, self).get_context_data(**kwargs)
+ audit_id = int(kwargs['audit_id'])
+ context['Ck_Audit'] = Ck_Audit.objects.get(id=audit_id)
+ context['mru'] = Job.get_recent()
+ context['mrj_type'] = 'all'
+ return context
+
+ def setup_queryset(self, *args, **kwargs):
+ audit_id = int(kwargs['audit_id'])
+ self.queryset = CkPackage2Cve.objects.filter(ck_audit_id=audit_id)
+ self.queryset = self.queryset.order_by(self.default_orderby)
+
+ def setup_filters(self, *args, **kwargs):
+ # Status filter
+ is_status = TableFilter(name="is_status", title="Status")
+ for status_id in range(CkPackage2Cve.UNPATCHED,CkPackage2Cve.PATCHED+1):
+ status_filter = TableFilterActionToggle(
+ CkPackage2Cve.CK_STATUS[status_id][1],
+ CkPackage2Cve.CK_STATUS[status_id][1],
+ Q(ck_status=status_id))
+ is_status.add_action(status_filter)
+ self.add_filter(is_status)
+
+ def setup_columns(self, *args, **kwargs):
+
+ self.add_column(title="Id",
+ field_name="id",
+ hideable=True,
+ hidden=True,
+ )
+
+ cve_link_template = '''
+ <a href="{% url 'cve' data.orm_cve.name %}" target="_blank">{{data.orm_cve.name}}</a>
+ '''
+ self.add_column(title="Name",
+ static_data_name="orm_cve__name",
+ static_data_template=cve_link_template,
+ hideable=False,
+ orderable=True,
+ )
+
+ self.add_column(title="Status",
+ filter_name="is_status",
+ static_data_name="status",
+ static_data_template="{{data.get_status_text}}",
+ )
+
+ self.add_column(title="V3 Severity",
+ orderable=True,
+ static_data_name="orm_cve__cvssV3_baseSeverity",
+ static_data_template="{{data.orm_cve.cvssV3_baseSeverity}}",
+ )
+
+ self.add_column(title="V3 Score",
+ orderable=True,
+ static_data_name="orm_cve__cvssV3_baseScore",
+ static_data_template="{{data.orm_cve.cvssV3_baseScore}}",
+ )
+
+ self.add_column(title="V2 Severity",
+ orderable=True,
+ static_data_name="data.orm_cve__cvssV2_severity",
+ static_data_template="{{data.orm_cve.cvssV2_severity}}",
+ )
+
+ self.add_column(title="V2 Score",
+ orderable=True,
+ static_data_name="data.orm_cve__cvssV2_baseScore",
+ static_data_template="{{data.orm_cve.cvssV2_baseScore}}",
+ )
+
+ self.add_column(title="Published",
+ static_data_name="data.orm_cve__publishedDate",
+ static_data_template="{{data.orm_cve.publishedDate}}",
+ )
+
+ self.add_column(title="Package",
+ orderable=True,
+ static_data_name="ck_package__name",
+ static_data_template="{{data.ck_package.name}}",
+ )
+
+
+class CveCheckerIssueTable(ToasterTable):
+ """Table of Issues in CvecheckerRecord"""
+
+ def __init__(self, *args, **kwargs):
+ super(CveCheckerIssueTable, self).__init__(*args, **kwargs)
+ self.default_orderby = "orm_cve__name"
+
+ def get_context_data(self, **kwargs):
+ context = super(CveCheckerIssueTable, self).get_context_data(**kwargs)
+ package_id = int(kwargs['package_id'])
+ context['Ck_Package'] = Ck_Package.objects.get(id=package_id)
+ context['mru'] = Job.get_recent()
+ context['mrj_type'] = 'all'
+ return context
+
+ def setup_queryset(self, *args, **kwargs):
+ package_id = int(kwargs['package_id'])
+ self.queryset = CkPackage2Cve.objects.filter(ck_package_id=package_id)
+ self.queryset = self.queryset.order_by(self.default_orderby)
+
+ def setup_filters(self, *args, **kwargs):
+ # Status filter
+ is_status = TableFilter(name="is_status", title="Status")
+ for status_id in range(CkPackage2Cve.UNPATCHED,CkPackage2Cve.PATCHED+1):
+ status_filter = TableFilterActionToggle(
+ CkPackage2Cve.CK_STATUS[status_id][1],
+ CkPackage2Cve.CK_STATUS[status_id][1],
+ Q(ck_status=status_id))
+ is_status.add_action(status_filter)
+ self.add_filter(is_status)
+
+ def setup_columns(self, *args, **kwargs):
+
+ cve_link_template = '''
+ <a href="{% url 'cve' data.orm_cve.name %}" target="_blank">{{data.orm_cve.name}}</a>
+ '''
+ self.add_column(title="Issue",
+ static_data_name="orm_cve__name",
+ static_data_template=cve_link_template,
+ hideable=False,
+ orderable=True,
+ )
+
+ self.add_column(title="CK Status",
+ filter_name="is_status",
+ static_data_name="ck_status",
+ static_data_template="{{data.get_status_text}}",
+ hideable=False,
+ orderable=True,
+ )
+
+ self.add_column(title="description",
+ static_data_name="orm_cve__description",
+ static_data_template="{{data.orm_cve.description}}",
+ hideable=False,
+ orderable=True,
+ )
+
+ self.add_column(title="V3 Score",
+ static_data_name="orm_cve__cvssV3_baseScore",
+ static_data_template="{{data.orm_cve.cvssV3_baseScore}}",
+ hideable=False,
+ orderable=True,
+ )
+
+ self.add_column(title="V3 Severity",
+ static_data_name="orm_cve__cvssV3_baseSeverity",
+ static_data_template="{{data.orm_cve.cvssV3_baseSeverity}}",
+ hideable=False,
+ )
+
+ self.add_column(title="V2 Score",
+ static_data_name="orm_cve__cvssV2_baseScore",
+ static_data_template="{{data.orm_cve.cvssV2_baseScore}}",
+ hideable=True,
+ )
+
+ self.add_column(title="V2 Severity",
+ static_data_name="orm_cve__cvssV2_severity",
+ static_data_template="{{data.orm_cve.cvssV2_severity}}",
+ hideable=True,
+ )
+
+ self.add_column(title="Publish Date",
+ static_data_name="orm_cve__publishedDate",
+ static_data_template="{{data.orm_cve.publishedDate}}",
+ hideable=True,
+ )
+
+ self.add_column(title="Last Modified Date",
+ static_data_name="orm_cve__lastModifiedDate",
+ static_data_template="{{data.orm_cve.lastModifiedDate}}",
+ hideable=True,
+ )
+
+
+class CveCheckerProductTable(ToasterTable):
+ """Table of All entries in CvecheckerRecord"""
+
+ def __init__(self, *args, **kwargs):
+ super(CveCheckerProductTable, self).__init__(*args, **kwargs)
+ self.default_orderby = "ck_product__name"
+
+ def get_context_data(self, **kwargs):
+ context = super(CveCheckerProductTable, self).get_context_data(**kwargs)
+ package_id = int(kwargs['package_id'])
+ context['Ck_Package'] = Ck_Package.objects.get(id=package_id)
+ context['mru'] = Job.get_recent()
+ context['mrj_type'] = 'all'
+ return context
+
+ def setup_queryset(self, *args, **kwargs):
+ package_id = int(kwargs['package_id'])
+ self.queryset = CkPackage2CkProduct.objects.filter(ck_package_id=package_id)
+ self.queryset = self.queryset.order_by(self.default_orderby)
+
+ def setup_filters(self, *args, **kwargs):
+ pass
+
+ def setup_columns(self, *args, **kwargs):
+
+ self.add_column(title="Product",
+ static_data_name="ck_product__name",
+ static_data_template="{{data.ck_product.name}}",
+ hideable=False,
+ orderable=True,
+ )
+
+ self.add_column(title="CvesInRecord",
+ static_data_name="cvesInRecord",
+ static_data_template="{{data.cvesInRecord}}",
+ hideable=False,
+ orderable=True,
+ )
+
+
+class CveCheckerImportManagementTable(ToasterTable):
+ """Table of Audit import meta-management """
+
+ def __init__(self, *args, **kwargs):
+ super(CveCheckerImportManagementTable, self).__init__(*args, **kwargs)
+ self.default_orderby = "order"
+
+ def get_context_data(self, **kwargs):
+ context = super(CveCheckerImportManagementTable, self).get_context_data(**kwargs)
+ return context
+
+ def setup_queryset(self, *args, **kwargs):
+ self.queryset = CkUploadManager.objects.all()
+ self.queryset = self.queryset.order_by(self.default_orderby)
+
+ def setup_filters(self, *args, **kwargs):
+ pass
+
+ def setup_columns(self, *args, **kwargs):
+
+ if UserSafe.is_admin(self.request.user):
+ self.add_column(title="ID",
+ field_name="id",
+ hideable=True,
+ hidden = True,
+ )
+
+ order_template = '''
+ <span id="audit_order-disp-{{data.id}}"><td><a href="{% url 'cvechecker_audit' data.id %}">{{data.order}}</a></td></span>
+ <span id="audit_order-edit-{{data.id}}" style="display:none;">
+ <input type="text" id="audit_order-text-{{data.id}}" value="{{data.order}}" size="10">
+ </span>
+ '''
+ self.add_column(title="Order",
+ static_data_name="order",
+ static_data_template=order_template,
+ orderable=True,
+ )
+
+ name_template = '''
+ <span id="audit_name-disp-{{data.id}}">{{data.name}}</span>
+ <span id="audit_name-edit-{{data.id}}" style="display:none;">
+ <input type="text" id="audit_name-text-{{data.id}}" value="{{data.name}}" size="20">
+ </span>
+ '''
+ self.add_column(title="Title",
+ static_data_name="name",
+ static_data_template=name_template,
+ )
+
+ mode_template = '''
+ <span id="audit_mode-disp-{{data.id}}">{{data.import_mode}}</span>
+ <span id="audit_mode-edit-{{data.id}}" style="display:none;">
+ <select id="audit_mode-text-{{data.id}}" name="audit_mode-text-{{data.id}}">
+ <option value="Repo" {% if "Repo" == data.import_mode %}selected{% endif %} >Repo</option>
+ <option value="SSL" {% if "SSL" == data.import_mode %}selected{% endif %} >SSL</option>
+ <option value="File" {% if "File" == data.import_mode %}selected{% endif %} >File</option>
+ </select>
+ </span>
+ '''
+ self.add_column(title="Mode",
+ static_data_name="import_mode",
+ static_data_template=mode_template,
+ )
+
+ repo_template = '''
+ <span id="audit_repo-disp-{{data.id}}">{{data.repo}}</span>
+ <span id="audit_repo-edit-{{data.id}}" style="display:none;">
+ <input type="text" id="audit_repo-text-{{data.id}}" value="{{data.repo}}" size="30">
+ </span>
+ '''
+ self.add_column(title="Repo URL",
+ static_data_name="repo",
+ static_data_template=repo_template,
+ )
+
+ path_template = '''
+ <span id="audit_path-disp-{{data.id}}">{{data.path}}</span>
+ <span id="audit_path-edit-{{data.id}}" style="display:none;">
+ <input type="text" id="audit_path-text-{{data.id}}" value="{{data.path}}" size="30">
+ </span>
+ '''
+ self.add_column(title="Path",
+ static_data_name="path",
+ static_data_template=path_template,
+ )
+
+ pem_template = '''
+ <span id="audit_pem-disp-{{data.id}}">{{data.pem}}</span>
+ <span id="audit_pem-edit-{{data.id}}" style="display:none;">
+ <input type="text" id="audit_pem-text-{{data.id}}" value="{{data.pem}}" size="20">
+ </span>
+ '''
+ self.add_column(title="Pem File",
+ static_data_name="pem_file",
+ static_data_template=pem_template,
+ )
+
+ branch_template = '''
+ <span id="audit_branch-disp-{{data.id}}">{{data.branch}}</span>
+ <span id="audit_branch-edit-{{data.id}}" style="display:none;">
+ <input type="text" id="audit_branch-text-{{data.id}}" value="{{data.branch}}" size="10">
+ </span>
+ '''
+ self.add_column(title="Branch",
+ static_data_name="branch",
+ static_data_template=branch_template,
+ )
+
+ if False:
+ refresh_template = '''
+ {% if "Upload" == data.name %}{% else %}
+ <span id="audit_refresh-disp-{{data.id}}">{{data.auto_refresh}}</span>
+ <span id="audit_refresh-edit-{{data.id}}" style="display:none;">
+ <select id="audit_refresh-text-{{data.id}}" name="audit_mode-text-{{data.id}}">
+ <option value="False" {% if False == data.auto_refresh %}selected{% endif %} >Absolute choice</option>
+ <option value="True" {% if True == data.auto_refresh %}selected{% endif %} >Automatic refresh choices</option>
+ </select>
+
+ </span>
+ {% endif %}
+ '''
+ self.add_column(title="Auto Refresh",
+ static_data_name="auto_refresh",
+ static_data_template=refresh_template,
+ )
+
+ self.add_column(title="Select Refresh",
+ field_name="select_refresh",
+ hideable=True,
+ hidden = True,
+ )
+ self.add_column(title="Select List",
+ field_name="select_list",
+ hideable=True,
+ hidden = True,
+ )
+
+ if UserSafe.is_contributor(self.request.user):
+ manage_link_template = '''
+ {% if "Upload" == data.name %}Built-in{% else %}
+ <span class="glyphicon glyphicon-edit edit-ck-entry" id="edit-entry-{{data.id}}" x-data="{{data.id}}"></span>
+ <span class="glyphicon glyphicon glyphicon glyphicon-ok save-ck-entry" id="save-entry-{{data.id}}" x-data="{{data.id}}" style="display:none;color: Chartreuse;"></span>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ <span class="glyphicon glyphicon glyphicon glyphicon-remove cancel-ck-entry" id="cancel-entry-{{data.id}}" x-data="{{data.id}}" style="display:none;color: Crimson;"></span>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ <span class="glyphicon glyphicon-trash trash-import" x-data="{{data.name}}|{{data.id}}"></span>
+ {% endif %}
+ '''
+ self.add_column(title="Manage",
+ hideable=True,
+ static_data_name="manage",
+ static_data_template=manage_link_template,
+ )